mirror of
				https://github.com/superseriousbusiness/gotosocial.git
				synced 2025-11-02 16:52:25 -06:00 
			
		
		
		
	
		
			
	
	
		
			404 lines
		
	
	
	
		
			12 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
		
		
			
		
	
	
			404 lines
		
	
	
	
		
			12 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
| 
								 | 
							
								// Copyright 2011 The Go Authors. All rights reserved.
							 | 
						||
| 
								 | 
							
								// Use of this source code is governed by a BSD-style
							 | 
						||
| 
								 | 
							
								// license that can be found in the LICENSE file.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								// Package vp8 implements a decoder for the VP8 lossy image format.
							 | 
						||
| 
								 | 
							
								//
							 | 
						||
| 
								 | 
							
								// The VP8 specification is RFC 6386.
							 | 
						||
| 
								 | 
							
								package vp8 // import "golang.org/x/image/vp8"
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								// This file implements the top-level decoding algorithm.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								import (
							 | 
						||
| 
								 | 
							
									"errors"
							 | 
						||
| 
								 | 
							
									"image"
							 | 
						||
| 
								 | 
							
									"io"
							 | 
						||
| 
								 | 
							
								)
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								// limitReader wraps an io.Reader to read at most n bytes from it.
							 | 
						||
| 
								 | 
							
								type limitReader struct {
							 | 
						||
| 
								 | 
							
									r io.Reader
							 | 
						||
| 
								 | 
							
									n int
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								// ReadFull reads exactly len(p) bytes into p.
							 | 
						||
| 
								 | 
							
								func (r *limitReader) ReadFull(p []byte) error {
							 | 
						||
| 
								 | 
							
									if len(p) > r.n {
							 | 
						||
| 
								 | 
							
										return io.ErrUnexpectedEOF
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
									n, err := io.ReadFull(r.r, p)
							 | 
						||
| 
								 | 
							
									r.n -= n
							 | 
						||
| 
								 | 
							
									return err
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								// FrameHeader is a frame header, as specified in section 9.1.
							 | 
						||
| 
								 | 
							
								type FrameHeader struct {
							 | 
						||
| 
								 | 
							
									KeyFrame          bool
							 | 
						||
| 
								 | 
							
									VersionNumber     uint8
							 | 
						||
| 
								 | 
							
									ShowFrame         bool
							 | 
						||
| 
								 | 
							
									FirstPartitionLen uint32
							 | 
						||
| 
								 | 
							
									Width             int
							 | 
						||
| 
								 | 
							
									Height            int
							 | 
						||
| 
								 | 
							
									XScale            uint8
							 | 
						||
| 
								 | 
							
									YScale            uint8
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								const (
							 | 
						||
| 
								 | 
							
									nSegment     = 4
							 | 
						||
| 
								 | 
							
									nSegmentProb = 3
							 | 
						||
| 
								 | 
							
								)
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								// segmentHeader holds segment-related header information.
							 | 
						||
| 
								 | 
							
								type segmentHeader struct {
							 | 
						||
| 
								 | 
							
									useSegment     bool
							 | 
						||
| 
								 | 
							
									updateMap      bool
							 | 
						||
| 
								 | 
							
									relativeDelta  bool
							 | 
						||
| 
								 | 
							
									quantizer      [nSegment]int8
							 | 
						||
| 
								 | 
							
									filterStrength [nSegment]int8
							 | 
						||
| 
								 | 
							
									prob           [nSegmentProb]uint8
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								const (
							 | 
						||
| 
								 | 
							
									nRefLFDelta  = 4
							 | 
						||
| 
								 | 
							
									nModeLFDelta = 4
							 | 
						||
| 
								 | 
							
								)
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								// filterHeader holds filter-related header information.
							 | 
						||
| 
								 | 
							
								type filterHeader struct {
							 | 
						||
| 
								 | 
							
									simple          bool
							 | 
						||
| 
								 | 
							
									level           int8
							 | 
						||
| 
								 | 
							
									sharpness       uint8
							 | 
						||
| 
								 | 
							
									useLFDelta      bool
							 | 
						||
| 
								 | 
							
									refLFDelta      [nRefLFDelta]int8
							 | 
						||
| 
								 | 
							
									modeLFDelta     [nModeLFDelta]int8
							 | 
						||
| 
								 | 
							
									perSegmentLevel [nSegment]int8
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								// mb is the per-macroblock decode state. A decoder maintains mbw+1 of these
							 | 
						||
| 
								 | 
							
								// as it is decoding macroblocks left-to-right and top-to-bottom: mbw for the
							 | 
						||
| 
								 | 
							
								// macroblocks in the row above, and one for the macroblock to the left.
							 | 
						||
| 
								 | 
							
								type mb struct {
							 | 
						||
| 
								 | 
							
									// pred is the predictor mode for the 4 bottom or right 4x4 luma regions.
							 | 
						||
| 
								 | 
							
									pred [4]uint8
							 | 
						||
| 
								 | 
							
									// nzMask is a mask of 8 bits: 4 for the bottom or right 4x4 luma regions,
							 | 
						||
| 
								 | 
							
									// and 2 + 2 for the bottom or right 4x4 chroma regions. A 1 bit indicates
							 | 
						||
| 
								 | 
							
									// that region has non-zero coefficients.
							 | 
						||
| 
								 | 
							
									nzMask uint8
							 | 
						||
| 
								 | 
							
									// nzY16 is a 0/1 value that is 1 if the macroblock used Y16 prediction and
							 | 
						||
| 
								 | 
							
									// had non-zero coefficients.
							 | 
						||
| 
								 | 
							
									nzY16 uint8
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								// Decoder decodes VP8 bitstreams into frames. Decoding one frame consists of
							 | 
						||
| 
								 | 
							
								// calling Init, DecodeFrameHeader and then DecodeFrame in that order.
							 | 
						||
| 
								 | 
							
								// A Decoder can be re-used to decode multiple frames.
							 | 
						||
| 
								 | 
							
								type Decoder struct {
							 | 
						||
| 
								 | 
							
									// r is the input bitsream.
							 | 
						||
| 
								 | 
							
									r limitReader
							 | 
						||
| 
								 | 
							
									// scratch is a scratch buffer.
							 | 
						||
| 
								 | 
							
									scratch [8]byte
							 | 
						||
| 
								 | 
							
									// img is the YCbCr image to decode into.
							 | 
						||
| 
								 | 
							
									img *image.YCbCr
							 | 
						||
| 
								 | 
							
									// mbw and mbh are the number of 16x16 macroblocks wide and high the image is.
							 | 
						||
| 
								 | 
							
									mbw, mbh int
							 | 
						||
| 
								 | 
							
									// frameHeader is the frame header. When decoding multiple frames,
							 | 
						||
| 
								 | 
							
									// frames that aren't key frames will inherit the Width, Height,
							 | 
						||
| 
								 | 
							
									// XScale and YScale of the most recent key frame.
							 | 
						||
| 
								 | 
							
									frameHeader FrameHeader
							 | 
						||
| 
								 | 
							
									// Other headers.
							 | 
						||
| 
								 | 
							
									segmentHeader segmentHeader
							 | 
						||
| 
								 | 
							
									filterHeader  filterHeader
							 | 
						||
| 
								 | 
							
									// The image data is divided into a number of independent partitions.
							 | 
						||
| 
								 | 
							
									// There is 1 "first partition" and between 1 and 8 "other partitions"
							 | 
						||
| 
								 | 
							
									// for coefficient data.
							 | 
						||
| 
								 | 
							
									fp  partition
							 | 
						||
| 
								 | 
							
									op  [8]partition
							 | 
						||
| 
								 | 
							
									nOP int
							 | 
						||
| 
								 | 
							
									// Quantization factors.
							 | 
						||
| 
								 | 
							
									quant [nSegment]quant
							 | 
						||
| 
								 | 
							
									// DCT/WHT coefficient decoding probabilities.
							 | 
						||
| 
								 | 
							
									tokenProb   [nPlane][nBand][nContext][nProb]uint8
							 | 
						||
| 
								 | 
							
									useSkipProb bool
							 | 
						||
| 
								 | 
							
									skipProb    uint8
							 | 
						||
| 
								 | 
							
									// Loop filter parameters.
							 | 
						||
| 
								 | 
							
									filterParams      [nSegment][2]filterParam
							 | 
						||
| 
								 | 
							
									perMBFilterParams []filterParam
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									// The eight fields below relate to the current macroblock being decoded.
							 | 
						||
| 
								 | 
							
									//
							 | 
						||
| 
								 | 
							
									// Segment-based adjustments.
							 | 
						||
| 
								 | 
							
									segment int
							 | 
						||
| 
								 | 
							
									// Per-macroblock state for the macroblock immediately left of and those
							 | 
						||
| 
								 | 
							
									// macroblocks immediately above the current macroblock.
							 | 
						||
| 
								 | 
							
									leftMB mb
							 | 
						||
| 
								 | 
							
									upMB   []mb
							 | 
						||
| 
								 | 
							
									// Bitmasks for which 4x4 regions of coeff contain non-zero coefficients.
							 | 
						||
| 
								 | 
							
									nzDCMask, nzACMask uint32
							 | 
						||
| 
								 | 
							
									// Predictor modes.
							 | 
						||
| 
								 | 
							
									usePredY16 bool // The libwebp C code calls this !is_i4x4_.
							 | 
						||
| 
								 | 
							
									predY16    uint8
							 | 
						||
| 
								 | 
							
									predC8     uint8
							 | 
						||
| 
								 | 
							
									predY4     [4][4]uint8
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									// The two fields below form a workspace for reconstructing a macroblock.
							 | 
						||
| 
								 | 
							
									// Their specific sizes are documented in reconstruct.go.
							 | 
						||
| 
								 | 
							
									coeff [1*16*16 + 2*8*8 + 1*4*4]int16
							 | 
						||
| 
								 | 
							
									ybr   [1 + 16 + 1 + 8][32]uint8
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								// NewDecoder returns a new Decoder.
							 | 
						||
| 
								 | 
							
								func NewDecoder() *Decoder {
							 | 
						||
| 
								 | 
							
									return &Decoder{}
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								// Init initializes the decoder to read at most n bytes from r.
							 | 
						||
| 
								 | 
							
								func (d *Decoder) Init(r io.Reader, n int) {
							 | 
						||
| 
								 | 
							
									d.r = limitReader{r, n}
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								// DecodeFrameHeader decodes the frame header.
							 | 
						||
| 
								 | 
							
								func (d *Decoder) DecodeFrameHeader() (fh FrameHeader, err error) {
							 | 
						||
| 
								 | 
							
									// All frame headers are at least 3 bytes long.
							 | 
						||
| 
								 | 
							
									b := d.scratch[:3]
							 | 
						||
| 
								 | 
							
									if err = d.r.ReadFull(b); err != nil {
							 | 
						||
| 
								 | 
							
										return
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
									d.frameHeader.KeyFrame = (b[0] & 1) == 0
							 | 
						||
| 
								 | 
							
									d.frameHeader.VersionNumber = (b[0] >> 1) & 7
							 | 
						||
| 
								 | 
							
									d.frameHeader.ShowFrame = (b[0]>>4)&1 == 1
							 | 
						||
| 
								 | 
							
									d.frameHeader.FirstPartitionLen = uint32(b[0])>>5 | uint32(b[1])<<3 | uint32(b[2])<<11
							 | 
						||
| 
								 | 
							
									if !d.frameHeader.KeyFrame {
							 | 
						||
| 
								 | 
							
										return d.frameHeader, nil
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
									// Frame headers for key frames are an additional 7 bytes long.
							 | 
						||
| 
								 | 
							
									b = d.scratch[:7]
							 | 
						||
| 
								 | 
							
									if err = d.r.ReadFull(b); err != nil {
							 | 
						||
| 
								 | 
							
										return
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
									// Check the magic sync code.
							 | 
						||
| 
								 | 
							
									if b[0] != 0x9d || b[1] != 0x01 || b[2] != 0x2a {
							 | 
						||
| 
								 | 
							
										err = errors.New("vp8: invalid format")
							 | 
						||
| 
								 | 
							
										return
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
									d.frameHeader.Width = int(b[4]&0x3f)<<8 | int(b[3])
							 | 
						||
| 
								 | 
							
									d.frameHeader.Height = int(b[6]&0x3f)<<8 | int(b[5])
							 | 
						||
| 
								 | 
							
									d.frameHeader.XScale = b[4] >> 6
							 | 
						||
| 
								 | 
							
									d.frameHeader.YScale = b[6] >> 6
							 | 
						||
| 
								 | 
							
									d.mbw = (d.frameHeader.Width + 0x0f) >> 4
							 | 
						||
| 
								 | 
							
									d.mbh = (d.frameHeader.Height + 0x0f) >> 4
							 | 
						||
| 
								 | 
							
									d.segmentHeader = segmentHeader{
							 | 
						||
| 
								 | 
							
										prob: [3]uint8{0xff, 0xff, 0xff},
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
									d.tokenProb = defaultTokenProb
							 | 
						||
| 
								 | 
							
									d.segment = 0
							 | 
						||
| 
								 | 
							
									return d.frameHeader, nil
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								// ensureImg ensures that d.img is large enough to hold the decoded frame.
							 | 
						||
| 
								 | 
							
								func (d *Decoder) ensureImg() {
							 | 
						||
| 
								 | 
							
									if d.img != nil {
							 | 
						||
| 
								 | 
							
										p0, p1 := d.img.Rect.Min, d.img.Rect.Max
							 | 
						||
| 
								 | 
							
										if p0.X == 0 && p0.Y == 0 && p1.X >= 16*d.mbw && p1.Y >= 16*d.mbh {
							 | 
						||
| 
								 | 
							
											return
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
									m := image.NewYCbCr(image.Rect(0, 0, 16*d.mbw, 16*d.mbh), image.YCbCrSubsampleRatio420)
							 | 
						||
| 
								 | 
							
									d.img = m.SubImage(image.Rect(0, 0, d.frameHeader.Width, d.frameHeader.Height)).(*image.YCbCr)
							 | 
						||
| 
								 | 
							
									d.perMBFilterParams = make([]filterParam, d.mbw*d.mbh)
							 | 
						||
| 
								 | 
							
									d.upMB = make([]mb, d.mbw)
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								// parseSegmentHeader parses the segment header, as specified in section 9.3.
							 | 
						||
| 
								 | 
							
								func (d *Decoder) parseSegmentHeader() {
							 | 
						||
| 
								 | 
							
									d.segmentHeader.useSegment = d.fp.readBit(uniformProb)
							 | 
						||
| 
								 | 
							
									if !d.segmentHeader.useSegment {
							 | 
						||
| 
								 | 
							
										d.segmentHeader.updateMap = false
							 | 
						||
| 
								 | 
							
										return
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
									d.segmentHeader.updateMap = d.fp.readBit(uniformProb)
							 | 
						||
| 
								 | 
							
									if d.fp.readBit(uniformProb) {
							 | 
						||
| 
								 | 
							
										d.segmentHeader.relativeDelta = !d.fp.readBit(uniformProb)
							 | 
						||
| 
								 | 
							
										for i := range d.segmentHeader.quantizer {
							 | 
						||
| 
								 | 
							
											d.segmentHeader.quantizer[i] = int8(d.fp.readOptionalInt(uniformProb, 7))
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
										for i := range d.segmentHeader.filterStrength {
							 | 
						||
| 
								 | 
							
											d.segmentHeader.filterStrength[i] = int8(d.fp.readOptionalInt(uniformProb, 6))
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
									if !d.segmentHeader.updateMap {
							 | 
						||
| 
								 | 
							
										return
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
									for i := range d.segmentHeader.prob {
							 | 
						||
| 
								 | 
							
										if d.fp.readBit(uniformProb) {
							 | 
						||
| 
								 | 
							
											d.segmentHeader.prob[i] = uint8(d.fp.readUint(uniformProb, 8))
							 | 
						||
| 
								 | 
							
										} else {
							 | 
						||
| 
								 | 
							
											d.segmentHeader.prob[i] = 0xff
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								// parseFilterHeader parses the filter header, as specified in section 9.4.
							 | 
						||
| 
								 | 
							
								func (d *Decoder) parseFilterHeader() {
							 | 
						||
| 
								 | 
							
									d.filterHeader.simple = d.fp.readBit(uniformProb)
							 | 
						||
| 
								 | 
							
									d.filterHeader.level = int8(d.fp.readUint(uniformProb, 6))
							 | 
						||
| 
								 | 
							
									d.filterHeader.sharpness = uint8(d.fp.readUint(uniformProb, 3))
							 | 
						||
| 
								 | 
							
									d.filterHeader.useLFDelta = d.fp.readBit(uniformProb)
							 | 
						||
| 
								 | 
							
									if d.filterHeader.useLFDelta && d.fp.readBit(uniformProb) {
							 | 
						||
| 
								 | 
							
										for i := range d.filterHeader.refLFDelta {
							 | 
						||
| 
								 | 
							
											d.filterHeader.refLFDelta[i] = int8(d.fp.readOptionalInt(uniformProb, 6))
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
										for i := range d.filterHeader.modeLFDelta {
							 | 
						||
| 
								 | 
							
											d.filterHeader.modeLFDelta[i] = int8(d.fp.readOptionalInt(uniformProb, 6))
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
									if d.filterHeader.level == 0 {
							 | 
						||
| 
								 | 
							
										return
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
									if d.segmentHeader.useSegment {
							 | 
						||
| 
								 | 
							
										for i := range d.filterHeader.perSegmentLevel {
							 | 
						||
| 
								 | 
							
											strength := d.segmentHeader.filterStrength[i]
							 | 
						||
| 
								 | 
							
											if d.segmentHeader.relativeDelta {
							 | 
						||
| 
								 | 
							
												strength += d.filterHeader.level
							 | 
						||
| 
								 | 
							
											}
							 | 
						||
| 
								 | 
							
											d.filterHeader.perSegmentLevel[i] = strength
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
									} else {
							 | 
						||
| 
								 | 
							
										d.filterHeader.perSegmentLevel[0] = d.filterHeader.level
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
									d.computeFilterParams()
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								// parseOtherPartitions parses the other partitions, as specified in section 9.5.
							 | 
						||
| 
								 | 
							
								func (d *Decoder) parseOtherPartitions() error {
							 | 
						||
| 
								 | 
							
									const maxNOP = 1 << 3
							 | 
						||
| 
								 | 
							
									var partLens [maxNOP]int
							 | 
						||
| 
								 | 
							
									d.nOP = 1 << d.fp.readUint(uniformProb, 2)
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									// The final partition length is implied by the remaining chunk data
							 | 
						||
| 
								 | 
							
									// (d.r.n) and the other d.nOP-1 partition lengths. Those d.nOP-1 partition
							 | 
						||
| 
								 | 
							
									// lengths are stored as 24-bit uints, i.e. up to 16 MiB per partition.
							 | 
						||
| 
								 | 
							
									n := 3 * (d.nOP - 1)
							 | 
						||
| 
								 | 
							
									partLens[d.nOP-1] = d.r.n - n
							 | 
						||
| 
								 | 
							
									if partLens[d.nOP-1] < 0 {
							 | 
						||
| 
								 | 
							
										return io.ErrUnexpectedEOF
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
									if n > 0 {
							 | 
						||
| 
								 | 
							
										buf := make([]byte, n)
							 | 
						||
| 
								 | 
							
										if err := d.r.ReadFull(buf); err != nil {
							 | 
						||
| 
								 | 
							
											return err
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
										for i := 0; i < d.nOP-1; i++ {
							 | 
						||
| 
								 | 
							
											pl := int(buf[3*i+0]) | int(buf[3*i+1])<<8 | int(buf[3*i+2])<<16
							 | 
						||
| 
								 | 
							
											if pl > partLens[d.nOP-1] {
							 | 
						||
| 
								 | 
							
												return io.ErrUnexpectedEOF
							 | 
						||
| 
								 | 
							
											}
							 | 
						||
| 
								 | 
							
											partLens[i] = pl
							 | 
						||
| 
								 | 
							
											partLens[d.nOP-1] -= pl
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									// We check if the final partition length can also fit into a 24-bit uint.
							 | 
						||
| 
								 | 
							
									// Strictly speaking, this isn't part of the spec, but it guards against a
							 | 
						||
| 
								 | 
							
									// malicious WEBP image that is too large to ReadFull the encoded DCT
							 | 
						||
| 
								 | 
							
									// coefficients into memory, whether that's because the actual WEBP file is
							 | 
						||
| 
								 | 
							
									// too large, or whether its RIFF metadata lists too large a chunk.
							 | 
						||
| 
								 | 
							
									if 1<<24 <= partLens[d.nOP-1] {
							 | 
						||
| 
								 | 
							
										return errors.New("vp8: too much data to decode")
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									buf := make([]byte, d.r.n)
							 | 
						||
| 
								 | 
							
									if err := d.r.ReadFull(buf); err != nil {
							 | 
						||
| 
								 | 
							
										return err
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
									for i, pl := range partLens {
							 | 
						||
| 
								 | 
							
										if i == d.nOP {
							 | 
						||
| 
								 | 
							
											break
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
										d.op[i].init(buf[:pl])
							 | 
						||
| 
								 | 
							
										buf = buf[pl:]
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
									return nil
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								// parseOtherHeaders parses header information other than the frame header.
							 | 
						||
| 
								 | 
							
								func (d *Decoder) parseOtherHeaders() error {
							 | 
						||
| 
								 | 
							
									// Initialize and parse the first partition.
							 | 
						||
| 
								 | 
							
									firstPartition := make([]byte, d.frameHeader.FirstPartitionLen)
							 | 
						||
| 
								 | 
							
									if err := d.r.ReadFull(firstPartition); err != nil {
							 | 
						||
| 
								 | 
							
										return err
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
									d.fp.init(firstPartition)
							 | 
						||
| 
								 | 
							
									if d.frameHeader.KeyFrame {
							 | 
						||
| 
								 | 
							
										// Read and ignore the color space and pixel clamp values. They are
							 | 
						||
| 
								 | 
							
										// specified in section 9.2, but are unimplemented.
							 | 
						||
| 
								 | 
							
										d.fp.readBit(uniformProb)
							 | 
						||
| 
								 | 
							
										d.fp.readBit(uniformProb)
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
									d.parseSegmentHeader()
							 | 
						||
| 
								 | 
							
									d.parseFilterHeader()
							 | 
						||
| 
								 | 
							
									if err := d.parseOtherPartitions(); err != nil {
							 | 
						||
| 
								 | 
							
										return err
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
									d.parseQuant()
							 | 
						||
| 
								 | 
							
									if !d.frameHeader.KeyFrame {
							 | 
						||
| 
								 | 
							
										// Golden and AltRef frames are specified in section 9.7.
							 | 
						||
| 
								 | 
							
										// TODO(nigeltao): implement. Note that they are only used for video, not still images.
							 | 
						||
| 
								 | 
							
										return errors.New("vp8: Golden / AltRef frames are not implemented")
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
									// Read and ignore the refreshLastFrameBuffer bit, specified in section 9.8.
							 | 
						||
| 
								 | 
							
									// It applies only to video, and not still images.
							 | 
						||
| 
								 | 
							
									d.fp.readBit(uniformProb)
							 | 
						||
| 
								 | 
							
									d.parseTokenProb()
							 | 
						||
| 
								 | 
							
									d.useSkipProb = d.fp.readBit(uniformProb)
							 | 
						||
| 
								 | 
							
									if d.useSkipProb {
							 | 
						||
| 
								 | 
							
										d.skipProb = uint8(d.fp.readUint(uniformProb, 8))
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
									if d.fp.unexpectedEOF {
							 | 
						||
| 
								 | 
							
										return io.ErrUnexpectedEOF
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
									return nil
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								// DecodeFrame decodes the frame and returns it as an YCbCr image.
							 | 
						||
| 
								 | 
							
								// The image's contents are valid up until the next call to Decoder.Init.
							 | 
						||
| 
								 | 
							
								func (d *Decoder) DecodeFrame() (*image.YCbCr, error) {
							 | 
						||
| 
								 | 
							
									d.ensureImg()
							 | 
						||
| 
								 | 
							
									if err := d.parseOtherHeaders(); err != nil {
							 | 
						||
| 
								 | 
							
										return nil, err
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
									// Reconstruct the rows.
							 | 
						||
| 
								 | 
							
									for mbx := 0; mbx < d.mbw; mbx++ {
							 | 
						||
| 
								 | 
							
										d.upMB[mbx] = mb{}
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
									for mby := 0; mby < d.mbh; mby++ {
							 | 
						||
| 
								 | 
							
										d.leftMB = mb{}
							 | 
						||
| 
								 | 
							
										for mbx := 0; mbx < d.mbw; mbx++ {
							 | 
						||
| 
								 | 
							
											skip := d.reconstruct(mbx, mby)
							 | 
						||
| 
								 | 
							
											fs := d.filterParams[d.segment][btou(!d.usePredY16)]
							 | 
						||
| 
								 | 
							
											fs.inner = fs.inner || !skip
							 | 
						||
| 
								 | 
							
											d.perMBFilterParams[d.mbw*mby+mbx] = fs
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
									if d.fp.unexpectedEOF {
							 | 
						||
| 
								 | 
							
										return nil, io.ErrUnexpectedEOF
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
									for i := 0; i < d.nOP; i++ {
							 | 
						||
| 
								 | 
							
										if d.op[i].unexpectedEOF {
							 | 
						||
| 
								 | 
							
											return nil, io.ErrUnexpectedEOF
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
									// Apply the loop filter.
							 | 
						||
| 
								 | 
							
									//
							 | 
						||
| 
								 | 
							
									// Even if we are using per-segment levels, section 15 says that "loop
							 | 
						||
| 
								 | 
							
									// filtering must be skipped entirely if loop_filter_level at either the
							 | 
						||
| 
								 | 
							
									// frame header level or macroblock override level is 0".
							 | 
						||
| 
								 | 
							
									if d.filterHeader.level != 0 {
							 | 
						||
| 
								 | 
							
										if d.filterHeader.simple {
							 | 
						||
| 
								 | 
							
											d.simpleFilter()
							 | 
						||
| 
								 | 
							
										} else {
							 | 
						||
| 
								 | 
							
											d.normalFilter()
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
									return d.img, nil
							 | 
						||
| 
								 | 
							
								}
							 |