Merged in fix-merge (pull request #213)

codec/h264/decode: did not copy over most up to date version from old repo, so fixing that
This commit is contained in:
Saxon Milton 2019-07-19 04:03:25 +00:00
commit 8a7a89d5a3
5 changed files with 138 additions and 18 deletions

View File

@ -1,3 +0,0 @@
.*.swp
*.mp4
*.h264

View File

@ -93,6 +93,7 @@ func MbTypeName(sliceType string, mbType int) string {
var ( var (
errNaMode = errors.New("no mode for given slice and mb type") errNaMode = errors.New("no mode for given slice and mb type")
errPartition = errors.New("partition must be 0") errPartition = errors.New("partition must be 0")
errSliceType = errors.New("bad sliceType")
) )
// MbPartPredMode returns a macroblock partition prediction mode for the given // MbPartPredMode returns a macroblock partition prediction mode for the given
@ -111,8 +112,11 @@ func MbPartPredMode(data *SliceData, sliceType string, mbType, partition int) (m
if mbType > 0 && mbType < 25 { if mbType > 0 && mbType < 25 {
return intra16x16, nil return intra16x16, nil
} }
return -1, errNaMode return naMbPartPredMode, errNaMode
case "SI": case "SI":
if mbType != 0 {
return naMbPartPredMode, errNaMode
}
return intra4x4, nil return intra4x4, nil
case "P": case "P":
fallthrough fallthrough
@ -120,7 +124,7 @@ func MbPartPredMode(data *SliceData, sliceType string, mbType, partition int) (m
if mbType >= 0 && mbType < 3 { if mbType >= 0 && mbType < 3 {
return predL0, nil return predL0, nil
} else if mbType == 3 || mbType == 4 { } else if mbType == 3 || mbType == 4 {
return -1, errNaMode return naMbPartPredMode, errNaMode
} else { } else {
return predL0, nil return predL0, nil
} }
@ -128,6 +132,8 @@ func MbPartPredMode(data *SliceData, sliceType string, mbType, partition int) (m
switch mbType { switch mbType {
case 0: case 0:
return direct, nil return direct, nil
case 3:
return biPred, nil
case 1: case 1:
fallthrough fallthrough
case 4: case 4:
@ -157,14 +163,16 @@ func MbPartPredMode(data *SliceData, sliceType string, mbType, partition int) (m
case 15: case 15:
return predL1, nil return predL1, nil
case 22: case 22:
return -1, errNaMode return naMbPartPredMode, errNaMode
default: default:
if mbType > 15 && mbType < 22 { if mbType > 15 && mbType < 22 {
return biPred, nil return biPred, nil
} }
return direct, nil return direct, nil
} }
default:
return naMbPartPredMode, errSliceType
} }
} }
return -1, errPartition return naMbPartPredMode, errPartition
} }

View File

@ -0,0 +1,112 @@
/*
NAME
parse.go
DESCRIPTION
mbtype_test.go provides testing for functions provided in mbtype.go.
AUTHORS
Saxon Nelson-Milton <saxon@ausocean.org>, The Australian Ocean Laboratory (AusOcean)
*/
package h264
import (
"testing"
)
func TestMbPartPredMode(t *testing.T) {
tests := []struct {
sliceType string
mbType int
data *SliceData
want mbPartPredMode
err error
}{
// Table 7-11 (I-slices).
0: {"I", 0, &SliceData{TransformSize8x8Flag: false}, intra4x4, nil},
1: {"I", 0, &SliceData{TransformSize8x8Flag: true}, intra8x8, nil},
2: {"I", 1, nil, intra16x16, nil},
3: {"I", 2, nil, intra16x16, nil},
4: {"I", 3, nil, intra16x16, nil},
5: {"I", 4, nil, intra16x16, nil},
6: {"I", 5, nil, intra16x16, nil},
7: {"I", 6, nil, intra16x16, nil},
8: {"I", 7, nil, intra16x16, nil},
9: {"I", 8, nil, intra16x16, nil},
10: {"I", 9, nil, intra16x16, nil},
11: {"I", 10, nil, intra16x16, nil},
12: {"I", 11, nil, intra16x16, nil},
13: {"I", 12, nil, intra16x16, nil},
14: {"I", 13, nil, intra16x16, nil},
15: {"I", 14, nil, intra16x16, nil},
16: {"I", 15, nil, intra16x16, nil},
17: {"I", 16, nil, intra16x16, nil},
18: {"I", 17, nil, intra16x16, nil},
19: {"I", 18, nil, intra16x16, nil},
20: {"I", 19, nil, intra16x16, nil},
21: {"I", 20, nil, intra16x16, nil},
22: {"I", 21, nil, intra16x16, nil},
23: {"I", 22, nil, intra16x16, nil},
24: {"I", 23, nil, intra16x16, nil},
25: {"I", 24, nil, intra16x16, nil},
26: {"I", 25, nil, naMbPartPredMode, errNaMode},
// Table 7-12 (SI-slices).
27: {"SI", 0, nil, intra4x4, nil},
// Table 7-13 (SP-slices).
28: {"SP", 0, nil, predL0, nil},
29: {"SP", 1, nil, predL0, nil},
30: {"SP", 2, nil, predL0, nil},
31: {"SP", 3, nil, naMbPartPredMode, errNaMode},
32: {"SP", 4, nil, naMbPartPredMode, errNaMode},
// Table 7-14 (B-slices).
33: {"B", 0, nil, direct, nil},
34: {"B", 1, nil, predL0, nil},
35: {"B", 2, nil, predL1, nil},
36: {"B", 3, nil, biPred, nil},
37: {"B", 4, nil, predL0, nil},
38: {"B", 5, nil, predL0, nil},
39: {"B", 6, nil, predL1, nil},
40: {"B", 7, nil, predL1, nil},
41: {"B", 8, nil, predL0, nil},
42: {"B", 9, nil, predL0, nil},
43: {"B", 10, nil, predL1, nil},
44: {"B", 11, nil, predL1, nil},
45: {"B", 12, nil, predL0, nil},
46: {"B", 13, nil, predL0, nil},
47: {"B", 14, nil, predL1, nil},
48: {"B", 15, nil, predL1, nil},
49: {"B", 16, nil, biPred, nil},
50: {"B", 17, nil, biPred, nil},
51: {"B", 18, nil, biPred, nil},
52: {"B", 19, nil, biPred, nil},
53: {"B", 20, nil, biPred, nil},
54: {"B", 21, nil, biPred, nil},
55: {"B", 22, nil, naMbPartPredMode, errNaMode},
// Test some weird cases where we expect error.
56: {"O", 0, nil, naMbPartPredMode, errSliceType},
57: {"I", 26, nil, naMbPartPredMode, errNaMode},
58: {"I", -1, nil, naMbPartPredMode, errNaMode},
59: {"SI", 1, nil, naMbPartPredMode, errNaMode},
// Cases for inferred mbtype.
60: {"SP", 5, nil, predL0, nil},
61: {"SP", -1, nil, predL0, nil},
62: {"B", -1, nil, direct, nil},
63: {"B", 23, nil, direct, nil},
}
for i, test := range tests {
m, err := MbPartPredMode(test.data, test.sliceType, test.mbType, 0)
if err != test.err {
t.Errorf("unexpected error from test %d.\nGot: %v\nWant: %v\n", i, err, test.err)
}
if m != test.want {
t.Errorf("did not get expected result for test %d.\nGot: %v\nWant: %v\n", i, m, test.want)
}
}
}

View File

@ -16,10 +16,12 @@ package h264
import ( import (
"math" "math"
"github.com/icza/bitio" "github.com/ausocean/h264decode/h264/bits"
"github.com/pkg/errors" "github.com/pkg/errors"
) )
// mbPartPredMode represents a macroblock partition prediction mode.
// Modes are defined as consts below. These modes are in section 7.4.5.
type mbPartPredMode int8 type mbPartPredMode int8
const ( const (
@ -31,6 +33,7 @@ const (
direct direct
biPred biPred
inter inter
naMbPartPredMode
) )
// readUe parses a syntax element of ue(v) descriptor, i.e. an unsigned integer // readUe parses a syntax element of ue(v) descriptor, i.e. an unsigned integer
@ -38,7 +41,7 @@ const (
// //
// TODO: this should return uint, but rest of code needs to be changed for this // TODO: this should return uint, but rest of code needs to be changed for this
// to happen. // to happen.
func readUe(r bitio.Reader) (int, error) { func readUe(r *bits.BitReader) (int, error) {
nZeros := -1 nZeros := -1
var err error var err error
for b := uint64(0); b == 0; nZeros++ { for b := uint64(0); b == 0; nZeros++ {
@ -47,7 +50,7 @@ func readUe(r bitio.Reader) (int, error) {
return 0, err return 0, err
} }
} }
rem, err := r.ReadBits(byte(nZeros)) rem, err := r.ReadBits(int(nZeros))
if err != nil { if err != nil {
return 0, err return 0, err
} }
@ -59,7 +62,7 @@ func readUe(r bitio.Reader) (int, error) {
// Rec. ITU-T H.264 (04/2017). // Rec. ITU-T H.264 (04/2017).
// //
// TODO: this should also return uint. // TODO: this should also return uint.
func readTe(r bitio.Reader, x uint) (int, error) { func readTe(r *bits.BitReader, x uint) (int, error) {
if x > 1 { if x > 1 {
return readUe(r) return readUe(r)
} }
@ -83,7 +86,7 @@ var errReadTeBadX = errors.New("x must be more than or equal to 1")
// readSe parses a syntax element with descriptor se(v), i.e. a signed integer // readSe parses a syntax element with descriptor se(v), i.e. a signed integer
// Exp-Golomb-coded syntax element, using the method described in sections // Exp-Golomb-coded syntax element, using the method described in sections
// 9.1 and 9.1.1 in Rec. ITU-T H.264 (04/2017). // 9.1 and 9.1.1 in Rec. ITU-T H.264 (04/2017).
func readSe(r bitio.Reader) (int, error) { func readSe(r *bits.BitReader) (int, error) {
codeNum, err := readUe(r) codeNum, err := readUe(r)
if err != nil { if err != nil {
return 0, errors.Wrap(err, "error reading ue(v)") return 0, errors.Wrap(err, "error reading ue(v)")
@ -95,7 +98,7 @@ func readSe(r bitio.Reader) (int, error) {
// readMe parses a syntax element of me(v) descriptor, i.e. mapped // readMe parses a syntax element of me(v) descriptor, i.e. mapped
// Exp-Golomb-coded element, using methods described in sections 9.1 and 9.1.2 // Exp-Golomb-coded element, using methods described in sections 9.1 and 9.1.2
// in Rec. ITU-T H.264 (04/2017). // in Rec. ITU-T H.264 (04/2017).
func readMe(r bitio.Reader, chromaArrayType uint, mpm mbPartPredMode) (uint, error) { func readMe(r *bits.BitReader, chromaArrayType uint, mpm mbPartPredMode) (uint, error) {
// Indexes to codedBlockPattern map. // Indexes to codedBlockPattern map.
var i1, i2, i3 int var i1, i2, i3 int

View File

@ -15,7 +15,7 @@ import (
"bytes" "bytes"
"testing" "testing"
"github.com/icza/bitio" "github.com/ausocean/h264decode/h264/bits"
) )
// TestReadUe checks that readUe correctly parses an Exp-Golomb-coded element // TestReadUe checks that readUe correctly parses an Exp-Golomb-coded element
@ -41,7 +41,7 @@ func TestReadUe(t *testing.T) {
} }
for i, test := range tests { for i, test := range tests {
got, err := readUe(bitio.NewReader(bytes.NewReader(test.in))) got, err := readUe(bits.NewBitReader(bytes.NewReader(test.in)))
if err != nil { if err != nil {
t.Fatalf("did not expect error: %v from readUe", err) t.Fatalf("did not expect error: %v from readUe", err)
} }
@ -69,7 +69,7 @@ func TestReadTe(t *testing.T) {
} }
for i, test := range tests { for i, test := range tests {
got, err := readTe(bitio.NewReader(bytes.NewReader(test.in)), test.x) got, err := readTe(bits.NewBitReader(bytes.NewReader(test.in)), test.x)
if err != test.err { if err != test.err {
t.Fatalf("did not get expected error for test: %v\nGot: %v\nWant: %v\n", i, err, test.err) t.Fatalf("did not get expected error for test: %v\nGot: %v\nWant: %v\n", i, err, test.err)
} }
@ -99,7 +99,7 @@ func TestReadSe(t *testing.T) {
} }
for i, test := range tests { for i, test := range tests {
got, err := readSe(bitio.NewReader(bytes.NewReader(test.in))) got, err := readSe(bits.NewBitReader(bytes.NewReader(test.in)))
if err != nil { if err != nil {
t.Fatalf("did not expect error: %v from readSe", err) t.Fatalf("did not expect error: %v from readSe", err)
} }
@ -142,7 +142,7 @@ func TestReadMe(t *testing.T) {
} }
for i, test := range tests { for i, test := range tests {
got, err := readMe(bitio.NewReader(bytes.NewReader(test.in)), test.cat, test.mpm) got, err := readMe(bits.NewBitReader(bytes.NewReader(test.in)), test.cat, test.mpm)
if err != test.err { if err != test.err {
t.Fatalf("did not expect to get error: %v for test: %v", err, i) t.Fatalf("did not expect to get error: %v for test: %v", err, i)
} }