mirror of https://bitbucket.org/ausocean/av.git
Merged in mb-type-binarization (pull request #234)
Mb type binarization Approved-by: Alan Noble <anoble@gmail.com>
This commit is contained in:
commit
89386ceb2d
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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 (
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue