codec/h264/h2646dec: fixed up binarization tables and added mbTypeBinarization function along with test TestMbTypeBinarization.

This commit is contained in:
Saxon 2019-08-14 14:08:24 +09:30
parent b41ae4bcd3
commit cd83cf9e8e
4 changed files with 230 additions and 130 deletions

View File

@ -100,13 +100,7 @@ func CondTermFlag(mbAddr, mbSkipFlag int) int {
} }
// s9.3.3 p 278: Returns the value of the syntax element // s9.3.3 p 278: Returns the value of the syntax element
func (bin *Binarization) Decode(sliceContext *SliceContext, b *bits.BitReader, rbsp []byte) { func (bin *Binarization) Decode(sliceContext *SliceContext, b *bits.BitReader, rbsp []byte) {}
if bin.SyntaxElement == "MbType" {
bin.binString = binIdxMbMap[sliceContext.Slice.Data.SliceTypeName][sliceContext.Slice.Data.MbType]
} else {
logger.Printf("TODO: no means to find binString for %s\n", bin.SyntaxElement)
}
}
// 9.3.3.1.1 : returns ctxIdxInc // 9.3.3.1.1 : returns ctxIdxInc
func Decoder9_3_3_1_1_1(condTermFlagA, condTermFlagB int) int { func Decoder9_3_3_1_1_1(condTermFlagA, condTermFlagB int) int {
@ -178,13 +172,11 @@ func initCabac(binarization *Binarization, context *SliceContext) *CABAC {
} }
} }
// Table 9-36, 9-37 // Binarizations for macroblock types in slice types.
// func BinIdx(mbType int, sliceTypeName string) []int {
// Map of SliceTypeName[MbType][]int{binString}
// {"SliceTypeName": {MbTypeCode: []BinString}}
var ( var (
binIdxMbMap = map[string]map[int][]int{ // binOfIMBTypes provides binarization strings for values of macroblock
"I": { // type in I slices as defined in table 9-36 of the specifications.
binOfIMBTypes = [numOfIMBTypes][]int{
0: {0}, 0: {0},
1: {1, 0, 0, 0, 0, 0}, 1: {1, 0, 0, 0, 0, 0},
2: {1, 0, 0, 0, 0, 1}, 2: {1, 0, 0, 0, 0, 1},
@ -211,102 +203,129 @@ var (
23: {1, 0, 1, 1, 1, 1, 0}, 23: {1, 0, 1, 1, 1, 1, 0},
24: {1, 0, 1, 1, 1, 1, 1}, 24: {1, 0, 1, 1, 1, 1, 1},
25: {1, 1}, 25: {1, 1},
}, }
// Table 9-37
"P": { // binOfPOrSPMBTypes provides binarization strings for values of macroblock
// type in P or SP slices as defined in table 9-37 of the specifications.
// NB: binarization of macroblock types 5 to 30 is 1 and not included here.
binOfPOrSPMBTypes = [5][]int{
0: {0, 0, 0}, 0: {0, 0, 0},
1: {0, 1, 1}, 1: {0, 1, 1},
2: {0, 1, 0}, 2: {0, 1, 0},
3: {0, 0, 1}, 3: {0, 0, 1},
4: {}, 4: {},
5: {1},
6: {1},
7: {1},
8: {1},
9: {1},
10: {1},
11: {1},
12: {1},
13: {1},
14: {1},
15: {1},
16: {1},
17: {1},
18: {1},
19: {1},
20: {1},
21: {1},
22: {1},
23: {1},
24: {1},
25: {1},
26: {1},
27: {1},
28: {1},
29: {1},
30: {1},
},
// Table 9-37
"SP": {
0: {0, 0, 0},
1: {0, 1, 1},
2: {0, 1, 0},
3: {0, 0, 1},
4: {},
5: {1},
6: {1},
7: {1},
8: {1},
9: {1},
10: {1},
11: {1},
12: {1},
13: {1},
14: {1},
15: {1},
16: {1},
17: {1},
18: {1},
19: {1},
20: {1},
21: {1},
22: {1},
23: {1},
24: {1},
25: {1},
26: {1},
27: {1},
28: {1},
29: {1},
30: {1},
},
// TODO: B Slice table 9-37
} }
// Map of SliceTypeName[SubMbType][]int{binString} // binOfBMBTypes provides binarization strings for values of macroblock
binIdxSubMbMap = map[string]map[int][]int{ // type in B slice as defined in table 9-37 of the specifications.
"P": { // NB: binarization of macroblock types 23 to 48 is 111101 and is not
0: {1}, // included here.
1: {0, 0}, binOfBMBTypes = [23][]int{
2: {0, 1, 1}, 0: {0},
3: {0, 1, 0}, 1: {1, 0, 0},
}, 2: {1, 0, 1},
"SP": { 3: {1, 1, 0, 0, 0, 0},
0: {1}, 4: {1, 1, 0, 0, 0, 1},
1: {0, 0}, 5: {1, 1, 0, 0, 1, 0},
2: {0, 1, 1}, 6: {1, 1, 0, 0, 1, 1},
3: {0, 1, 0}, 7: {1, 1, 0, 1, 0, 0},
}, 8: {1, 1, 0, 1, 0, 1},
// TODO: B slice table 9-38 9: {1, 1, 0, 1, 1, 0},
10: {1, 1, 0, 1, 1, 1},
11: {1, 1, 1, 1, 1, 0},
12: {1, 1, 1, 0, 0, 0, 0},
13: {1, 1, 1, 0, 0, 0, 1},
14: {1, 1, 1, 0, 0, 1, 0},
15: {1, 1, 1, 0, 0, 1, 1},
16: {1, 1, 1, 0, 1, 0, 0},
17: {1, 1, 1, 0, 1, 0, 1},
18: {1, 1, 1, 0, 1, 1, 0},
19: {1, 1, 1, 0, 1, 1, 1},
20: {1, 1, 1, 1, 0, 0, 0},
21: {1, 1, 1, 1, 0, 0, 1},
22: {1, 1, 1, 1, 1, 1},
} }
// Table 9-36, 9-37
MbBinIdx = []int{1, 2, 3, 4, 5, 6}
// Table 9-38
SubMbBinIdx = []int{0, 1, 2, 3, 4, 5}
) )
// Binarizations for sub-macroblock types in slice types.
var (
// binOfPorSPSubMBTypes provides binarization strings for values of sub-macroblock
// type in P or SP slices as defined in table 9-38 of the specifications.
binOfPOrSPSubMBTypes = [4][]int{
0: {1},
1: {0, 0},
2: {0, 1, 1},
3: {0, 1, 0},
}
// binOfBSubMBTypes provides binarization strings for values of sub-macroblock
// type in B slices as defined in table 9-38 of the specifications.
binOfBSubMBTypes = [numOfBSubMBTypes][]int{
0: {1},
1: {1, 0, 0},
2: {1, 0, 1},
3: {1, 1, 0, 0, 0},
4: {1, 1, 0, 0, 1},
5: {1, 1, 0, 1, 0},
6: {1, 1, 0, 1, 1},
7: {1, 1, 1, 0, 0, 0},
8: {1, 1, 1, 0, 0, 1},
9: {1, 1, 1, 0, 1, 0},
10: {1, 1, 1, 0, 1, 1},
11: {1, 1, 1, 1, 0},
12: {1, 1, 1, 1, 1},
}
)
// Errors used by mbTypeBinarization.
var (
errBadMbType = errors.New("macroblock type outside of valid range")
errInvalidSliceType = errors.New("slice type does not exist")
)
// mbTypeBinarization returns the macroblock type binarization for the given
// macroblock type value and slice type using the process defined in section
// 9.3.2.5 of the specifications.
func mbTypeBinarization(v, slice int) ([]int, error) {
switch slice {
case sliceTypeI:
if v < minIMbType || v > maxIMbType {
return nil, errBadMbType
}
return binOfIMBTypes[v], nil
case sliceTypeSI:
if v < minSIMbType || v > maxSIMbType {
return nil, errBadMbType
}
if v == sliceTypeSI {
return []int{0}, nil
}
return append([]int{1}, binOfIMBTypes[v-1]...), nil
case sliceTypeP, sliceTypeSP:
if v < minPOrSPMbType || v > maxPOrSPMbType || v == P8x8ref0 {
return nil, errBadMbType
}
if v < 5 {
return binOfPOrSPMBTypes[v], nil
}
return append([]int{1}, binOfIMBTypes[v-5]...), nil
case sliceTypeB:
if v < minBMbType || v > maxBMbType {
return nil, errBadMbType
}
if v < 23 {
return binOfBMBTypes[v], nil
}
return append([]int{1, 1, 1, 1, 0, 1}, binOfIMBTypes[v-23]...), nil
default:
return nil, errInvalidSliceType
}
}
// Table 9-34 // Table 9-34
type MaxBinIdxCtx struct { type MaxBinIdxCtx struct {
// When false, Prefix is the MaxBinIdxCtx // When false, Prefix is the MaxBinIdxCtx

View File

@ -1,6 +1,46 @@
package h264dec package h264dec
import "testing" import (
"reflect"
"testing"
)
func TestMbTypeBinarization(t *testing.T) {
tests := []struct {
v, slice int
want []int
err error
}{
{v: 6, slice: sliceTypeI, want: []int{1, 0, 0, 1, 0, 0, 1}},
{v: 26, slice: sliceTypeI, err: errBadMbType},
{v: -1, slice: sliceTypeI, err: errBadMbType},
{v: 4, slice: sliceTypeSI, want: []int{0}},
{v: 6, slice: sliceTypeSI, want: []int{1, 1, 0, 0, 1, 0, 0, 0}},
{v: 0, slice: sliceTypeSI, err: errBadMbType},
{v: 27, slice: sliceTypeSI, err: errBadMbType},
{v: 2, slice: sliceTypeP, want: []int{0, 1, 0}},
{v: 3, slice: sliceTypeSP, want: []int{0, 0, 1}},
{v: 7, slice: sliceTypeP, want: []int{1, 1, 0, 0, 0, 0, 1}},
{v: 7, slice: sliceTypeSP, want: []int{1, 1, 0, 0, 0, 0, 1}},
{v: -1, slice: sliceTypeP, err: errBadMbType},
{v: 31, slice: sliceTypeP, err: errBadMbType},
{v: 8, slice: sliceTypeB, want: []int{1, 1, 0, 1, 0, 1}},
{v: 30, slice: sliceTypeB, want: []int{1, 1, 1, 1, 0, 1, 1, 0, 0, 1, 0, 1, 0}},
{v: -1, slice: sliceTypeB, err: errBadMbType},
{v: 49, slice: sliceTypeB, err: errBadMbType},
}
for i, test := range tests {
got, err := mbTypeBinarization(test.v, test.slice)
if err != test.err {
t.Errorf("did not get expected error for test %d\nGot: %v\nWant: %v", i, err, test.err)
}
if !reflect.DeepEqual(got, test.want) {
t.Errorf("did not get expected result for test %d\nGot: %v\nWant: %v", i, got, test.want)
}
}
}
var ctxIdxTests = []struct { var ctxIdxTests = []struct {
binIdx int binIdx int

View File

@ -4,6 +4,38 @@ import (
"errors" "errors"
) )
// P slice macroblock types.
const (
P8x8ref0 = 4
)
// Number of macroblock types for each slice type.
const (
numOfIMBTypes = 26
numOfPMBTypes = 31
numOfSPMBTypes = 31
numOfBMBTypes = 49
)
// Number of sub macroblock types for each slice type.
const (
numOfPSubMBTypes = 4
numOfSPSubMBTypes = 4
numOfBSubMBTypes = 13
)
// Min and max macroblock types for slice types.
const (
minIMbType = 0
maxIMbType = 25
minPOrSPMbType = 0
maxPOrSPMbType = 30
minBMbType = 0
maxBMbType = 48
minSIMbType = 1
maxSIMbType = 26
)
const MB_TYPE_INFERRED = 1000 const MB_TYPE_INFERRED = 1000
var ( var (

View File

@ -9,6 +9,15 @@ import (
"github.com/pkg/errors" "github.com/pkg/errors"
) )
// Slice types.
const (
sliceTypeP = 0
sliceTypeB = 1
sliceTypeI = 2
sliceTypeSP = 3
sliceTypeSI = 4
)
// Chroma formats as defined in section 6.2, tab 6-1. // Chroma formats as defined in section 6.2, tab 6-1.
const ( const (
chromaMonochrome = iota chromaMonochrome = iota