func (d *Decoder) reconstructMacroblock(mbx, mby int) {
	if d.usePredY16 {
		p := checkTopLeftPred(mbx, mby, d.predY16)
		predFunc16[p](d, 1, 8)
		for j := 0; j < 4; j++ {
			for i := 0; i < 4; i++ {
				n := 4*j + i
				y := 4*j + 1
				x := 4*i + 8
				mask := uint32(1) << uint(n)
				if d.nzACMask&mask != 0 {
					d.inverseDCT4(y, x, 16*n)
				} else if d.nzDCMask&mask != 0 {
					d.inverseDCT4DCOnly(y, x, 16*n)
				}
			}
		}
	} else {
		for j := 0; j < 4; j++ {
			for i := 0; i < 4; i++ {
				n := 4*j + i
				y := 4*j + 1
				x := 4*i + 8
				predFunc4[d.predY4[j][i]](d, y, x)
				mask := uint32(1) << uint(n)
				if d.nzACMask&mask != 0 {
					d.inverseDCT4(y, x, 16*n)
				} else if d.nzDCMask&mask != 0 {
					d.inverseDCT4DCOnly(y, x, 16*n)
				}
			}
		}
	}
	p := checkTopLeftPred(mbx, mby, d.predC8)
	predFunc8[p](d, ybrBY, ybrBX)
	if d.nzACMask&0x0f0000 != 0 {
		d.inverseDCT8(ybrBY, ybrBX, bCoeffBase)
	} else if d.nzDCMask&0x0f0000 != 0 {
		d.inverseDCT8DCOnly(ybrBY, ybrBX, bCoeffBase)
	}
	predFunc8[p](d, ybrRY, ybrRX)
	if d.nzACMask&0xf00000 != 0 {
		d.inverseDCT8(ybrRY, ybrRX, rCoeffBase)
	} else if d.nzDCMask&0xf00000 != 0 {
		d.inverseDCT8DCOnly(ybrRY, ybrRX, rCoeffBase)
	}
}
reconstructMacroblock applies the predictor functions and adds the inverse-
DCT transformed residuals to recover the YCbCr data.
package vp8
const (
	bCoeffBase   = 1*16*16 + 0*8*8
	rCoeffBase   = 1*16*16 + 1*8*8
	whtCoeffBase = 1*16*16 + 2*8*8
)
const (
	ybrYX = 8
	ybrYY = 1
	ybrBX = 8
	ybrBY = 18
	ybrRX = 24
	ybrRY = 18
)
func (d *Decoder) prepareYBR(mbx, mby int) {
	if mbx == 0 {
		for y := 0; y < 17; y++ {
			d.ybr[y][7] = 0x81
		}
		for y := 17; y < 26; y++ {
			d.ybr[y][7] = 0x81
			d.ybr[y][23] = 0x81
		}
	} else {
		for y := 0; y < 17; y++ {
			d.ybr[y][7] = d.ybr[y][7+16]
		}
		for y := 17; y < 26; y++ {
			d.ybr[y][7] = d.ybr[y][15]
			d.ybr[y][23] = d.ybr[y][31]
		}
	}
	if mby == 0 {
		for x := 7; x < 28; x++ {
			d.ybr[0][x] = 0x7f
		}
		for x := 7; x < 16; x++ {
			d.ybr[17][x] = 0x7f
		}
		for x := 23; x < 32; x++ {
			d.ybr[17][x] = 0x7f
		}
	} else {
		for i := 0; i < 16; i++ {
			d.ybr[0][8+i] = d.img.Y[(16*mby-1)*d.img.YStride+16*mbx+i]
		}
		for i := 0; i < 8; i++ {
			d.ybr[17][8+i] = d.img.Cb[(8*mby-1)*d.img.CStride+8*mbx+i]
		}
		for i := 0; i < 8; i++ {
			d.ybr[17][24+i] = d.img.Cr[(8*mby-1)*d.img.CStride+8*mbx+i]
		}
		if mbx == d.mbw-1 {
			for i := 16; i < 20; i++ {
				d.ybr[0][8+i] = d.img.Y[(16*mby-1)*d.img.YStride+16*mbx+15]
			}
		} else {
			for i := 16; i < 20; i++ {
				d.ybr[0][8+i] = d.img.Y[(16*mby-1)*d.img.YStride+16*mbx+i]
			}
		}
	}
	for y := 4; y < 16; y += 4 {
		d.ybr[y][24] = d.ybr[0][24]
		d.ybr[y][25] = d.ybr[0][25]
		d.ybr[y][26] = d.ybr[0][26]
		d.ybr[y][27] = d.ybr[0][27]
	}
}
func btou(b bool) uint8 {
	if b {
		return 1
	}
	return 0
}
func pack(x [4]uint8, shift int) uint32 {
	u := uint32(x[0])<<0 | uint32(x[1])<<1 | uint32(x[2])<<2 | uint32(x[3])<<3
	return u << uint(shift)
}
var unpack = [16][4]uint8{
	{0, 0, 0, 0},
	{1, 0, 0, 0},
	{0, 1, 0, 0},
	{1, 1, 0, 0},
	{0, 0, 1, 0},
	{1, 0, 1, 0},
	{0, 1, 1, 0},
	{1, 1, 1, 0},
	{0, 0, 0, 1},
	{1, 0, 0, 1},
	{0, 1, 0, 1},
	{1, 1, 0, 1},
	{0, 0, 1, 1},
	{1, 0, 1, 1},
	{0, 1, 1, 1},
	{1, 1, 1, 1},
}
var (
	bands = [17]uint8{0, 1, 2, 3, 6, 4, 5, 6, 6, 6, 6, 6, 6, 6, 6, 7, 0}
	cat3456 = [4][12]uint8{
		{173, 148, 140, 0, 0, 0, 0, 0, 0, 0, 0, 0},
		{176, 155, 140, 135, 0, 0, 0, 0, 0, 0, 0, 0},
		{180, 157, 141, 134, 130, 0, 0, 0, 0, 0, 0, 0},
		{254, 254, 243, 230, 196, 177, 153, 140, 133, 130, 129, 0},
	}
	zigzag = [16]uint8{0, 1, 4, 8, 5, 2, 3, 6, 9, 12, 13, 10, 7, 11, 14, 15}
)
func (d *Decoder) parseResiduals4(r *partition, plane int, context uint8, quant [2]uint16, skipFirstCoeff bool, coeffBase int) uint8 {
	prob, n := &d.tokenProb[plane], 0
	if skipFirstCoeff {
		n = 1
	}
	p := prob[bands[n]][context]
	if !r.readBit(p[0]) {
		return 0
	}
	for n != 16 {
		n++
		if !r.readBit(p[1]) {
			p = prob[bands[n]][0]
			continue
		}
		var v uint32
		if !r.readBit(p[2]) {
			v = 1
			p = prob[bands[n]][1]
		} else {
			if !r.readBit(p[3]) {
				if !r.readBit(p[4]) {
					v = 2
				} else {
					v = 3 + r.readUint(p[5], 1)
				}
			} else if !r.readBit(p[6]) {
				if !r.readBit(p[7]) {
					v = 5 + r.readUint(159, 1)
				} else {
					v = 7 + 2*r.readUint(165, 1) + r.readUint(145, 1)
				}
			} else {
				b1 := r.readUint(p[8], 1)
				b0 := r.readUint(p[9+b1], 1)
				cat := 2*b1 + b0
				tab := &cat3456[cat]
				v = 0
				for i := 0; tab[i] != 0; i++ {
					v *= 2
					v += r.readUint(tab[i], 1)
				}
				v += 3 + (8 << cat)
			}
			p = prob[bands[n]][2]
		}
		z := zigzag[n-1]
		c := int32(v) * int32(quant[btou(z > 0)])
		if r.readBit(uniformProb) {
			c = -c
		}
		d.coeff[coeffBase+int(z)] = int16(c)
		if n == 16 || !r.readBit(p[0]) {
			return 1
		}
	}
	return 1
}
func (d *Decoder) parseResiduals(mbx, mby int) (skip bool) {
	partition := &d.op[mby&(d.nOP-1)]
	plane := planeY1SansY2
	quant := &d.quant[d.segment]
	if d.usePredY16 {
		nz := d.parseResiduals4(partition, planeY2, d.leftMB.nzY16+d.upMB[mbx].nzY16, quant.y2, false, whtCoeffBase)
		d.leftMB.nzY16 = nz
		d.upMB[mbx].nzY16 = nz
		d.inverseWHT16()
		plane = planeY1WithY2
	}
	var (
		nzDC, nzAC         [4]uint8
		nzDCMask, nzACMask uint32
		coeffBase          int
	)
	lnz := unpack[d.leftMB.nzMask&0x0f]
	unz := unpack[d.upMB[mbx].nzMask&0x0f]
	for y := 0; y < 4; y++ {
		nz := lnz[y]
		for x := 0; x < 4; x++ {
			nz = d.parseResiduals4(partition, plane, nz+unz[x], quant.y1, d.usePredY16, coeffBase)
			unz[x] = nz
			nzAC[x] = nz
			nzDC[x] = btou(d.coeff[coeffBase] != 0)
			coeffBase += 16
		}
		lnz[y] = nz
		nzDCMask |= pack(nzDC, y*4)
		nzACMask |= pack(nzAC, y*4)
	}
	lnzMask := pack(lnz, 0)
	unzMask := pack(unz, 0)
	lnz = unpack[d.leftMB.nzMask>>4]
	unz = unpack[d.upMB[mbx].nzMask>>4]
	for c := 0; c < 4; c += 2 {
		for y := 0; y < 2; y++ {
			nz := lnz[y+c]
			for x := 0; x < 2; x++ {
				nz = d.parseResiduals4(partition, planeUV, nz+unz[x+c], quant.uv, false, coeffBase)
				unz[x+c] = nz
				nzAC[y*2+x] = nz
				nzDC[y*2+x] = btou(d.coeff[coeffBase] != 0)
				coeffBase += 16
			}
			lnz[y+c] = nz
		}
		nzDCMask |= pack(nzDC, 16+c*2)
		nzACMask |= pack(nzAC, 16+c*2)
	}
	lnzMask |= pack(lnz, 4)
	unzMask |= pack(unz, 4)
	d.leftMB.nzMask = uint8(lnzMask)
	d.upMB[mbx].nzMask = uint8(unzMask)
	d.nzDCMask = nzDCMask
	d.nzACMask = nzACMask
	return nzDCMask == 0 && nzACMask == 0
}