// 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// This file implements decoding DCT/WHT residual coefficients and// reconstructing YCbCr data equal to predicted values plus residuals.//// There are 1*16*16 + 2*8*8 + 1*4*4 coefficients per macroblock:// - 1*16*16 luma DCT coefficients,// - 2*8*8 chroma DCT coefficients, and// - 1*4*4 luma WHT coefficients.// Coefficients are read in lots of 16, and the later coefficients in each lot// are often zero.//// The YCbCr data consists of 1*16*16 luma values and 2*8*8 chroma values,// plus previously decoded values along the top and left borders. The combined// values are laid out as a [1+16+1+8][32]uint8 so that vertically adjacent// samples are 32 bytes apart. In detail, the layout is://// 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1// . . . . . . . a b b b b b b b b b b b b b b b b c c c c . . . . 0// . . . . . . . d Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y . . . . . . . . 1// . . . . . . . d Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y . . . . . . . . 2// . . . . . . . d Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y . . . . . . . . 3// . . . . . . . d Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y c c c c . . . . 4// . . . . . . . d Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y . . . . . . . . 5// . . . . . . . d Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y . . . . . . . . 6// . . . . . . . d Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y . . . . . . . . 7// . . . . . . . d Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y c c c c . . . . 8// . . . . . . . d Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y . . . . . . . . 9// . . . . . . . d Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y . . . . . . . . 10// . . . . . . . d Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y . . . . . . . . 11// . . . . . . . d Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y c c c c . . . . 12// . . . . . . . d Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y . . . . . . . . 13// . . . . . . . d Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y . . . . . . . . 14// . . . . . . . d Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y . . . . . . . . 15// . . . . . . . d Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y . . . . . . . . 16// . . . . . . . e f f f f f f f f . . . . . . . g h h h h h h h h 17// . . . . . . . i B B B B B B B B . . . . . . . j R R R R R R R R 18// . . . . . . . i B B B B B B B B . . . . . . . j R R R R R R R R 19// . . . . . . . i B B B B B B B B . . . . . . . j R R R R R R R R 20// . . . . . . . i B B B B B B B B . . . . . . . j R R R R R R R R 21// . . . . . . . i B B B B B B B B . . . . . . . j R R R R R R R R 22// . . . . . . . i B B B B B B B B . . . . . . . j R R R R R R R R 23// . . . . . . . i B B B B B B B B . . . . . . . j R R R R R R R R 24// . . . . . . . i B B B B B B B B . . . . . . . j R R R R R R R R 25//// Y, B and R are the reconstructed luma (Y) and chroma (B, R) values.// The Y values are predicted (either as one 16x16 region or 16 4x4 regions)// based on the row above's Y values (some combination of {abc} or {dYC}) and// the column left's Y values (either {ad} or {bY}). Similarly, B and R values// are predicted on the row above and column left of their respective 8x8// region: {efi} for B, {ghj} for R.//// For uppermost macroblocks (i.e. those with mby == 0), the {abcefgh} values// are initialized to 0x81. Otherwise, they are copied from the bottom row of// the macroblock above. The {c} values are then duplicated from row 0 to rows// 4, 8 and 12 of the ybr workspace.// Similarly, for leftmost macroblocks (i.e. those with mbx == 0), the {adeigj}// values are initialized to 0x7f. Otherwise, they are copied from the right// column of the macroblock to the left.// For the top-left macroblock (with mby == 0 && mbx == 0), {aeg} is 0x81.//// When moving from one macroblock to the next horizontally, the {adeigj}// values can simply be copied from the workspace to itself, shifted by 8 or// 16 columns. When moving from one macroblock to the next vertically,// filtering can occur and hence the row values have to be copied from the// post-filtered image instead of the pre-filtered workspace.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)// prepareYBR prepares the {abcdefghij} elements of ybr.func ( *Decoder) (, int) {if == 0 {for := 0; < 17; ++ { .ybr[][7] = 0x81 }for := 17; < 26; ++ { .ybr[][7] = 0x81 .ybr[][23] = 0x81 } } else {for := 0; < 17; ++ { .ybr[][7] = .ybr[][7+16] }for := 17; < 26; ++ { .ybr[][7] = .ybr[][15] .ybr[][23] = .ybr[][31] } }if == 0 {for := 7; < 28; ++ { .ybr[0][] = 0x7f }for := 7; < 16; ++ { .ybr[17][] = 0x7f }for := 23; < 32; ++ { .ybr[17][] = 0x7f } } else {for := 0; < 16; ++ { .ybr[0][8+] = .img.Y[(16*-1)*.img.YStride+16*+] }for := 0; < 8; ++ { .ybr[17][8+] = .img.Cb[(8*-1)*.img.CStride+8*+] }for := 0; < 8; ++ { .ybr[17][24+] = .img.Cr[(8*-1)*.img.CStride+8*+] }if == .mbw-1 {for := 16; < 20; ++ { .ybr[0][8+] = .img.Y[(16*-1)*.img.YStride+16*+15] } } else {for := 16; < 20; ++ { .ybr[0][8+] = .img.Y[(16*-1)*.img.YStride+16*+] } } }for := 4; < 16; += 4 { .ybr[][24] = .ybr[0][24] .ybr[][25] = .ybr[0][25] .ybr[][26] = .ybr[0][26] .ybr[][27] = .ybr[0][27] }}// btou converts a bool to a 0/1 value.func btou( bool) uint8 {if {return1 }return0}// pack packs four 0/1 values into four bits of a uint32.func pack( [4]uint8, int) uint32 { := uint32([0])<<0 | uint32([1])<<1 | uint32([2])<<2 | uint32([3])<<3return << uint()}// unpack unpacks four 0/1 values from a four-bit value.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 (// The mapping from 4x4 region position to band is specified in section 13.3. bands = [17]uint8{0, 1, 2, 3, 6, 4, 5, 6, 6, 6, 6, 6, 6, 6, 6, 7, 0}// Category probabilities are specified in section 13.2. // Decoding categories 1 and 2 are done inline. 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}, }// The zigzag order is: // 0 1 5 6 // 2 4 7 12 // 3 8 11 13 // 9 10 14 15 zigzag = [16]uint8{0, 1, 4, 8, 5, 2, 3, 6, 9, 12, 13, 10, 7, 11, 14, 15})// parseResiduals4 parses a 4x4 region of residual coefficients, as specified// in section 13.3, and returns a 0/1 value indicating whether there was at// least one non-zero coefficient.// r is the partition to read bits from.// plane and context describe which token probability table to use. context is// either 0, 1 or 2, and equals how many of the macroblock left and macroblock// above have non-zero coefficients.// quant are the DC/AC quantization factors.// skipFirstCoeff is whether the DC coefficient has already been parsed.// coeffBase is the base index of d.coeff to write to.func ( *Decoder) ( *partition, int, uint8, [2]uint16, bool, int) uint8 { , := &.tokenProb[], 0if { = 1 } := [bands[]][]if !.readBit([0]) {return0 }for != 16 { ++if !.readBit([1]) { = [bands[]][0]continue }varuint32if !.readBit([2]) { = 1 = [bands[]][1] } else {if !.readBit([3]) {if !.readBit([4]) { = 2 } else { = 3 + .readUint([5], 1) } } elseif !.readBit([6]) {if !.readBit([7]) {// Category 1. = 5 + .readUint(159, 1) } else {// Category 2. = 7 + 2*.readUint(165, 1) + .readUint(145, 1) } } else {// Categories 3, 4, 5 or 6. := .readUint([8], 1) := .readUint([9+], 1) := 2* + := &cat3456[] = 0for := 0; [] != 0; ++ { *= 2 += .readUint([], 1) } += 3 + (8 << ) } = [bands[]][2] } := zigzag[-1] := int32() * int32([btou( > 0)])if .readBit(uniformProb) { = - } .coeff[+int()] = int16()if == 16 || !.readBit([0]) {return1 } }return1}// parseResiduals parses the residuals and returns whether inner loop filtering// should be skipped for this macroblock.func ( *Decoder) (, int) ( bool) { := &.op[&(.nOP-1)] := planeY1SansY2 := &.quant[.segment]// Parse the DC coefficient of each 4x4 luma region.if .usePredY16 { := .parseResiduals4(, planeY2, .leftMB.nzY16+.upMB[].nzY16, .y2, false, whtCoeffBase) .leftMB.nzY16 = .upMB[].nzY16 = .inverseWHT16() = planeY1WithY2 }var ( , [4]uint8 , uint32int )// Parse the luma coefficients. := unpack[.leftMB.nzMask&0x0f] := unpack[.upMB[].nzMask&0x0f]for := 0; < 4; ++ { := []for := 0; < 4; ++ { = .parseResiduals4(, , +[], .y1, .usePredY16, ) [] = [] = [] = btou(.coeff[] != 0) += 16 } [] = |= pack(, *4) |= pack(, *4) } := pack(, 0) := pack(, 0)// Parse the chroma coefficients. = unpack[.leftMB.nzMask>>4] = unpack[.upMB[].nzMask>>4]for := 0; < 4; += 2 {for := 0; < 2; ++ { := [+]for := 0; < 2; ++ { = .parseResiduals4(, planeUV, +[+], .uv, false, ) [+] = [*2+] = [*2+] = btou(.coeff[] != 0) += 16 } [+] = } |= pack(, 16+*2) |= pack(, 16+*2) } |= pack(, 4) |= pack(, 4)// Save decoder state. .leftMB.nzMask = uint8() .upMB[].nzMask = uint8() .nzDCMask = .nzACMask = // Section 15.1 of the spec says that "Steps 2 and 4 [of the loop filter] // are skipped... [if] there is no DCT coefficient coded for the whole // macroblock."return == 0 && == 0}// reconstructMacroblock applies the predictor functions and adds the inverse-// DCT transformed residuals to recover the YCbCr data.func ( *Decoder) (, int) {if .usePredY16 { := checkTopLeftPred(, , .predY16)predFunc16[](, 1, 8)for := 0; < 4; ++ {for := 0; < 4; ++ { := 4* + := 4* + 1 := 4* + 8 := uint32(1) << uint()if .nzACMask& != 0 { .inverseDCT4(, , 16*) } elseif .nzDCMask& != 0 { .inverseDCT4DCOnly(, , 16*) } } } } else {for := 0; < 4; ++ {for := 0; < 4; ++ { := 4* + := 4* + 1 := 4* + 8predFunc4[.predY4[][]](, , ) := uint32(1) << uint()if .nzACMask& != 0 { .inverseDCT4(, , 16*) } elseif .nzDCMask& != 0 { .inverseDCT4DCOnly(, , 16*) } } } } := checkTopLeftPred(, , .predC8)predFunc8[](, ybrBY, ybrBX)if .nzACMask&0x0f0000 != 0 { .inverseDCT8(ybrBY, ybrBX, bCoeffBase) } elseif .nzDCMask&0x0f0000 != 0 { .inverseDCT8DCOnly(ybrBY, ybrBX, bCoeffBase) }predFunc8[](, ybrRY, ybrRX)if .nzACMask&0xf00000 != 0 { .inverseDCT8(ybrRY, ybrRX, rCoeffBase) } elseif .nzDCMask&0xf00000 != 0 { .inverseDCT8DCOnly(ybrRY, ybrRX, rCoeffBase) }}// reconstruct reconstructs one macroblock and returns whether inner loop// filtering should be skipped for it.func ( *Decoder) (, int) ( bool) {if .segmentHeader.updateMap {if !.fp.readBit(.segmentHeader.prob[0]) { .segment = int(.fp.readUint(.segmentHeader.prob[1], 1)) } else { .segment = int(.fp.readUint(.segmentHeader.prob[2], 1)) + 2 } }if .useSkipProb { = .fp.readBit(.skipProb) }// Prepare the workspace.for := range .coeff { .coeff[] = 0 } .prepareYBR(, )// Parse the predictor modes. .usePredY16 = .fp.readBit(145)if .usePredY16 { .parsePredModeY16() } else { .parsePredModeY4() } .parsePredModeC8()// Parse the residuals.if ! { = .parseResiduals(, ) } else {if .usePredY16 { .leftMB.nzY16 = 0 .upMB[].nzY16 = 0 } .leftMB.nzMask = 0 .upMB[].nzMask = 0 .nzDCMask = 0 .nzACMask = 0 }// Reconstruct the YCbCr data and copy it to the image. .reconstructMacroblock(, )for , := (*.img.YStride+)*16, 0; < 16; , = +.img.YStride, +1 {copy(.img.Y[:+16], .ybr[ybrYY+][ybrYX:ybrYX+16]) }for , := (*.img.CStride+)*8, 0; < 8; , = +.img.CStride, +1 {copy(.img.Cb[:+8], .ybr[ybrBY+][ybrBX:ybrBX+8])copy(.img.Cr[:+8], .ybr[ybrRY+][ybrRX:ybrRX+8]) }return}
The pages are generated with Goldsv0.8.7. (GOOS=linux GOARCH=amd64)
Golds is a Go 101 project developed by Tapir Liu.
PR and bug reports are welcome and can be submitted to the issue list.
Please follow @zigo_101 (reachable from the left QR code) to get the latest news of Golds.