Merged in mb-type-binarization (pull request #234)

Mb type binarization

Approved-by: Alan Noble <anoble@gmail.com>
This commit is contained in:
Saxon Milton 2019-08-19 22:11:49 +00:00
commit 89386ceb2d
4 changed files with 286 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
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)
}
}
func (bin *Binarization) Decode(sliceContext *SliceContext, b *bits.BitReader, rbsp []byte) {}
// 9.3.3.1.1 : returns ctxIdxInc
func Decoder9_3_3_1_1_1(condTermFlagA, condTermFlagB int) int {
@ -178,135 +172,185 @@ func initCabac(binarization *Binarization, context *SliceContext) *CABAC {
}
}
// Table 9-36, 9-37
// func BinIdx(mbType int, sliceTypeName string) []int {
// Map of SliceTypeName[MbType][]int{binString}
// {"SliceTypeName": {MbTypeCode: []BinString}}
// Binarizations for macroblock types in slice types.
var (
binIdxMbMap = map[string]map[int][]int{
"I": {
0: {0},
1: {1, 0, 0, 0, 0, 0},
2: {1, 0, 0, 0, 0, 1},
3: {1, 0, 0, 0, 1, 0},
4: {1, 0, 0, 0, 1, 1},
5: {1, 0, 0, 1, 0, 0, 0},
6: {1, 0, 0, 1, 0, 0, 1},
7: {1, 0, 0, 1, 0, 1, 0},
8: {1, 0, 0, 1, 0, 1, 1},
9: {1, 0, 0, 1, 1, 0, 0},
10: {1, 0, 0, 1, 1, 0, 1},
11: {1, 0, 0, 1, 1, 1, 0},
12: {1, 0, 0, 1, 1, 1, 1},
13: {1, 0, 1, 0, 0, 0},
14: {1, 0, 1, 0, 0, 1},
15: {1, 0, 1, 0, 1, 0},
16: {1, 0, 1, 0, 1, 1},
17: {1, 0, 1, 1, 0, 0, 0},
18: {1, 0, 1, 1, 0, 0, 1},
19: {1, 0, 1, 1, 0, 1, 0},
20: {1, 0, 1, 1, 0, 1, 1},
21: {1, 0, 1, 1, 1, 0, 0},
22: {1, 0, 1, 1, 1, 0, 1},
23: {1, 0, 1, 1, 1, 1, 0},
24: {1, 0, 1, 1, 1, 1, 1},
25: {1, 1},
},
// Table 9-37
"P": {
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},
},
// 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
// binOfIMBTypes provides binarization strings for values of macroblock
// type in I slices as defined in table 9-36 of the specifications.
binOfIMBTypes = [numOfIMBTypes][]int{
0: {0},
1: {1, 0, 0, 0, 0, 0},
2: {1, 0, 0, 0, 0, 1},
3: {1, 0, 0, 0, 1, 0},
4: {1, 0, 0, 0, 1, 1},
5: {1, 0, 0, 1, 0, 0, 0},
6: {1, 0, 0, 1, 0, 0, 1},
7: {1, 0, 0, 1, 0, 1, 0},
8: {1, 0, 0, 1, 0, 1, 1},
9: {1, 0, 0, 1, 1, 0, 0},
10: {1, 0, 0, 1, 1, 0, 1},
11: {1, 0, 0, 1, 1, 1, 0},
12: {1, 0, 0, 1, 1, 1, 1},
13: {1, 0, 1, 0, 0, 0},
14: {1, 0, 1, 0, 0, 1},
15: {1, 0, 1, 0, 1, 0},
16: {1, 0, 1, 0, 1, 1},
17: {1, 0, 1, 1, 0, 0, 0},
18: {1, 0, 1, 1, 0, 0, 1},
19: {1, 0, 1, 1, 0, 1, 0},
20: {1, 0, 1, 1, 0, 1, 1},
21: {1, 0, 1, 1, 1, 0, 0},
22: {1, 0, 1, 1, 1, 0, 1},
23: {1, 0, 1, 1, 1, 1, 0},
24: {1, 0, 1, 1, 1, 1, 1},
25: {1, 1},
}
// Map of SliceTypeName[SubMbType][]int{binString}
binIdxSubMbMap = map[string]map[int][]int{
"P": {
0: {1},
1: {0, 0},
2: {0, 1, 1},
3: {0, 1, 0},
},
"SP": {
0: {1},
1: {0, 0},
2: {0, 1, 1},
3: {0, 1, 0},
},
// TODO: B slice table 9-38
// 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},
1: {0, 1, 1},
2: {0, 1, 0},
3: {0, 0, 1},
4: {},
}
// Table 9-36, 9-37
MbBinIdx = []int{1, 2, 3, 4, 5, 6}
// Table 9-38
SubMbBinIdx = []int{0, 1, 2, 3, 4, 5}
// binOfBMBTypes provides binarization strings for values of macroblock
// type in B slice as defined in table 9-37 of the specifications.
// NB: binarization of macroblock types 23 to 48 is 111101 and is not
// included here.
binOfBMBTypes = [23][]int{
0: {0},
1: {1, 0, 0},
2: {1, 0, 1},
3: {1, 1, 0, 0, 0, 0},
4: {1, 1, 0, 0, 0, 1},
5: {1, 1, 0, 0, 1, 0},
6: {1, 1, 0, 0, 1, 1},
7: {1, 1, 0, 1, 0, 0},
8: {1, 1, 0, 1, 0, 1},
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},
}
)
// 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")
errBadMbSliceType = errors.New("bad slice type for macroblock")
)
// 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, errBadMbSliceType
}
}
// Error used by subMbTypeBinarization.
var errBadSubMbSliceType = errors.New("bad slice type for sub-macroblock")
// subMbTypeBinarization returns the binarization of a sub-macroblock type
// given the slice in which it is in using the process defined in section
// 9.3.2.5 of the specifications.
func subMbTypeBinarization(v, slice int) ([]int, error) {
switch slice {
case sliceTypeP, sliceTypeSP:
if v < minPOrSPSubMbType || v > maxPOrSPSubMbType {
return nil, errBadMbType
}
return binOfPOrSPSubMBTypes[v], nil
case sliceTypeB:
if v < minBSubMbType || v > maxBSubMbType {
return nil, errBadMbType
}
return binOfBSubMBTypes[v], nil
default:
return nil, errBadSubMbSliceType
}
}
// Table 9-34
type MaxBinIdxCtx struct {
// When false, Prefix is the MaxBinIdxCtx

View File

@ -1,6 +1,73 @@
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},
{v: 6, slice: 20, err: errBadMbSliceType},
}
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)
}
}
}
func TestSubMbTypeBinarization(t *testing.T) {
tests := []struct {
v, slice int
want []int
err error
}{
{v: 2, slice: sliceTypeP, want: []int{0, 1, 1}},
{v: 2, slice: sliceTypeSP, want: []int{0, 1, 1}},
{v: -1, slice: sliceTypeSP, err: errBadMbType},
{v: 4, slice: sliceTypeSP, err: errBadMbType},
{v: 9, slice: sliceTypeB, want: []int{1, 1, 1, 0, 1, 0}},
{v: 9, slice: 40, err: errBadSubMbSliceType},
}
for i, test := range tests {
got, err := subMbTypeBinarization(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 {
binIdx int

View File

@ -4,6 +4,42 @@ import (
"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
minPOrSPSubMbType = 0
maxPOrSPSubMbType = 3
minBSubMbType = 0
maxBSubMbType = 12
)
const MB_TYPE_INFERRED = 1000
var (

View File

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