Merged in slice-testing (pull request #225)

codec/h264/h264dec: added some testing for parsing found in slice.go

Approved-by: Alan Noble <anoble@gmail.com>
This commit is contained in:
Saxon Milton 2019-08-20 02:53:00 +00:00
commit 13490e0145
3 changed files with 391 additions and 70 deletions

View File

@ -21,7 +21,7 @@ func binToSlice(s string) ([]byte, error) {
bytes []byte
)
for _, c := range s {
for i, c := range s {
switch c {
case ' ':
continue
@ -33,7 +33,7 @@ func binToSlice(s string) ([]byte, error) {
}
a >>= 1
if a == 0 {
if a == 0 || i == (len(s)-1) {
bytes = append(bytes, cur)
cur = 0
a = 0x80

View File

@ -1,3 +1,12 @@
/*
DESCRIPTION
slice.go provides parsing functionality for slice raw byte sequence data.
AUTHORS
Saxon Nelson-Milton <saxon@ausocean.org>, The Australian Ocean Laboratory (AusOcean)
Bruce McMoran <mcmoranbjr@gmail.com>
*/
package h264dec
import (
@ -30,6 +39,8 @@ type VideoStream struct {
SPS *SPS
PPS *PPS
Slices []*SliceContext
ChromaArrayType int
}
type SliceContext struct {
*NALUnit
@ -46,11 +57,10 @@ type Slice struct {
// (defined in 7.3.3.1 of specifications) and a ref_pic_list_mvc_modification
// (defined in H.7.3.3.1.1 of specifications).
type RefPicListModification struct {
RefPicListModificationFlagL0 bool
ModificationOfPicNums int
AbsDiffPicNumMinus1 int
LongTermPicNum int
RefPicListModificationFlagL1 bool
RefPicListModificationFlag [2]bool
ModificationOfPicNums [2][]int
AbsDiffPicNumMinus1 [2][]int
LongTermPicNum [2][]int
}
// TODO: need to complete this.
@ -64,43 +74,57 @@ func NewRefPicListMVCModifiation(br *bits.BitReader) (*RefPicListModification, e
// NewRefPicListModification parses elements of a ref_pic_list_modification
// following the syntax structure defined in section 7.3.3.1, and returns as
// a new RefPicListModification.
func NewRefPicListModification(br *bits.BitReader, h *SliceHeader) (*RefPicListModification, error) {
ref := &RefPicListModification{}
r := newFieldReader(br)
func NewRefPicListModification(br *bits.BitReader, p *PPS, s *SliceHeader) (*RefPicListModification, error) {
r := &RefPicListModification{}
r.ModificationOfPicNums[0] = make([]int, p.NumRefIdxL0DefaultActiveMinus1+2)
r.ModificationOfPicNums[1] = make([]int, p.NumRefIdxL1DefaultActiveMinus1+2)
r.AbsDiffPicNumMinus1[0] = make([]int, p.NumRefIdxL0DefaultActiveMinus1+2)
r.AbsDiffPicNumMinus1[1] = make([]int, p.NumRefIdxL1DefaultActiveMinus1+2)
r.LongTermPicNum[0] = make([]int, p.NumRefIdxL0DefaultActiveMinus1+2)
r.LongTermPicNum[1] = make([]int, p.NumRefIdxL1DefaultActiveMinus1+2)
fr := newFieldReader(br)
// 7.3.3.1
if h.SliceType%5 != 2 && h.SliceType%5 != 4 {
ref.RefPicListModificationFlagL0 = r.readBits(1) == 1
if s.SliceType%5 != 2 && s.SliceType%5 != 4 {
r.RefPicListModificationFlag[0] = fr.readBits(1) == 1
if ref.RefPicListModificationFlagL0 {
for ref.ModificationOfPicNums != 3 {
ref.ModificationOfPicNums = int(r.readUe())
if r.RefPicListModificationFlag[0] {
for i := 0; ; i++ {
r.ModificationOfPicNums[0][i] = int(fr.readUe())
if ref.ModificationOfPicNums == 0 || ref.ModificationOfPicNums == 1 {
ref.AbsDiffPicNumMinus1 = int(r.readUe())
} else if ref.ModificationOfPicNums == 2 {
ref.LongTermPicNum = int(r.readUe())
if r.ModificationOfPicNums[0][i] == 0 || r.ModificationOfPicNums[0][i] == 1 {
r.AbsDiffPicNumMinus1[0][i] = int(fr.readUe())
} else if r.ModificationOfPicNums[0][i] == 2 {
r.LongTermPicNum[0][i] = int(fr.readUe())
}
}
}
}
if h.SliceType%5 == 1 {
ref.RefPicListModificationFlagL1 = r.readBits(1) == 1
if ref.RefPicListModificationFlagL1 {
for ref.ModificationOfPicNums != 3 {
ref.ModificationOfPicNums = int(r.readUe())
if ref.ModificationOfPicNums == 0 || ref.ModificationOfPicNums == 1 {
ref.AbsDiffPicNumMinus1 = int(r.readUe())
} else if ref.ModificationOfPicNums == 2 {
ref.LongTermPicNum = int(r.readUe())
if r.ModificationOfPicNums[0][i] == 3 {
break
}
}
}
}
// refPicListModification()
return nil, nil
if s.SliceType%5 == 1 {
r.RefPicListModificationFlag[1] = fr.readBits(1) == 1
if r.RefPicListModificationFlag[1] {
for i := 0; ; i++ {
r.ModificationOfPicNums[1][i] = int(fr.readUe())
if r.ModificationOfPicNums[1][i] == 0 || r.ModificationOfPicNums[1][i] == 1 {
r.AbsDiffPicNumMinus1[1][i] = int(fr.readUe())
} else if r.ModificationOfPicNums[1][i] == 2 {
r.LongTermPicNum[1][i] = int(fr.readUe())
}
if r.ModificationOfPicNums[1][i] == 3 {
break
}
}
}
}
return r, nil
}
// PredWeightTable provides elements of a pred_weight_table syntax structure
@ -108,7 +132,6 @@ func NewRefPicListModification(br *bits.BitReader, h *SliceHeader) (*RefPicListM
type PredWeightTable struct {
LumaLog2WeightDenom int
ChromaLog2WeightDenom int
ChromaArrayType int
LumaWeightL0Flag bool
LumaWeightL0 []int
LumaOffsetL0 []int
@ -126,13 +149,13 @@ type PredWeightTable struct {
// NewPredWeightTable parses elements of a pred_weight_table following the
// syntax structure defined in section 7.3.3.2, and returns as a new
// PredWeightTable.
func NewPredWeightTable(br *bits.BitReader, h *SliceHeader) (*PredWeightTable, error) {
func NewPredWeightTable(br *bits.BitReader, h *SliceHeader, chromaArrayType int) (*PredWeightTable, error) {
p := &PredWeightTable{}
r := newFieldReader(br)
p.LumaLog2WeightDenom = int(r.readUe())
if p.ChromaArrayType != 0 {
if chromaArrayType != 0 {
p.ChromaLog2WeightDenom = int(r.readUe())
}
for i := 0; i <= h.NumRefIdxL0ActiveMinus1; i++ {
@ -151,7 +174,7 @@ func NewPredWeightTable(br *bits.BitReader, h *SliceHeader) (*PredWeightTable, e
}
p.LumaOffsetL0 = append(p.LumaOffsetL0, se)
}
if p.ChromaArrayType != 0 {
if chromaArrayType != 0 {
b, err := br.ReadBits(1)
if err != nil {
return nil, errors.Wrap(err, "could not read ChromaWeightL0Flag")
@ -198,7 +221,7 @@ func NewPredWeightTable(br *bits.BitReader, h *SliceHeader) (*PredWeightTable, e
}
p.LumaOffsetL1 = append(p.LumaOffsetL1, se)
}
if p.ChromaArrayType != 0 {
if chromaArrayType != 0 {
b, err := br.ReadBits(1)
if err != nil {
return nil, errors.Wrap(err, "could not read ChromaWeightL1Flag")
@ -231,11 +254,16 @@ func NewPredWeightTable(br *bits.BitReader, h *SliceHeader) (*PredWeightTable, e
// DecRefPicMarking provides elements of a dec_ref_pic_marking syntax structure
// as defined in section 7.3.3.3 of the specifications.
type DecRefPicMarking struct {
NoOutputOfPriorPicsFlag bool
LongTermReferenceFlag bool
AdaptiveRefPicMarkingModeFlag bool
NoOutputOfPriorPicsFlag bool
LongTermReferenceFlag bool
AdaptiveRefPicMarkingModeFlag bool
elements []drpmElement
}
type drpmElement struct {
MemoryManagementControlOperation int
DifferenceOfPicNumsMinus1 int
LongTermPicNum int
LongTermFrameIdx int
MaxLongTermFrameIdxPlus1 int
}
@ -243,7 +271,7 @@ type DecRefPicMarking struct {
// NewDecRefPicMarking parses elements of a dec_ref_pic_marking following the
// syntax structure defined in section 7.3.3.3, and returns as a new
// DecRefPicMarking.
func NewDecRefPicMarking(br *bits.BitReader, idrPic bool, h *SliceHeader) (*DecRefPicMarking, error) {
func NewDecRefPicMarking(br *bits.BitReader, idrPic bool) (*DecRefPicMarking, error) {
d := &DecRefPicMarking{}
r := newFieldReader(br)
if idrPic {
@ -266,19 +294,26 @@ func NewDecRefPicMarking(br *bits.BitReader, idrPic bool, h *SliceHeader) (*DecR
d.AdaptiveRefPicMarkingModeFlag = b == 1
if d.AdaptiveRefPicMarkingModeFlag {
d.MemoryManagementControlOperation = int(r.readUe())
for d.MemoryManagementControlOperation != 0 {
if d.MemoryManagementControlOperation == 1 || d.MemoryManagementControlOperation == 3 {
d.DifferenceOfPicNumsMinus1 = int(r.readUe())
for i := 0; ; i++ {
d.elements = append(d.elements, drpmElement{})
d.elements[i].MemoryManagementControlOperation = int(r.readUe())
if d.elements[i].MemoryManagementControlOperation == 1 || d.elements[i].MemoryManagementControlOperation == 3 {
d.elements[i].DifferenceOfPicNumsMinus1 = int(r.readUe())
}
if d.MemoryManagementControlOperation == 2 {
h.RefPicListModification.LongTermPicNum = int(r.readUe())
if d.elements[i].MemoryManagementControlOperation == 2 {
d.elements[i].LongTermPicNum = int(r.readUe())
}
if d.MemoryManagementControlOperation == 3 || d.MemoryManagementControlOperation == 6 {
d.LongTermFrameIdx = int(r.readUe())
if d.elements[i].MemoryManagementControlOperation == 3 || d.elements[i].MemoryManagementControlOperation == 6 {
d.elements[i].LongTermFrameIdx = int(r.readUe())
}
if d.MemoryManagementControlOperation == 4 {
d.MaxLongTermFrameIdxPlus1 = int(r.readUe())
if d.elements[i].MemoryManagementControlOperation == 4 {
d.elements[i].MaxLongTermFrameIdxPlus1 = int(r.readUe())
}
if d.elements[i].MemoryManagementControlOperation == 0 {
break
}
}
}
@ -491,9 +526,10 @@ func NumMbPart(nalUnit *NALUnit, sps *SPS, header *SliceHeader, data *SliceData)
return numMbPart
}
func MbPred(sliceContext *SliceContext, br *bits.BitReader, rbsp []byte) error {
r := newFieldReader(br)
func MbPred(chromaArrayType int, sliceContext *SliceContext, br *bits.BitReader, rbsp []byte) error {
var cabac *CABAC
r := newFieldReader(br)
sliceType := sliceTypeMap[sliceContext.Slice.Header.SliceType]
mbPartPredMode, err := MbPartPredMode(sliceContext.Slice.Data, sliceType, sliceContext.Slice.Data.MbType, 0)
if err != nil {
@ -593,7 +629,7 @@ func MbPred(sliceContext *SliceContext, br *bits.BitReader, rbsp []byte) error {
}
}
if sliceContext.Slice.Header.ChromaArrayType == 1 || sliceContext.Slice.Header.ChromaArrayType == 2 {
if chromaArrayType == 1 || chromaArrayType == 2 {
if sliceContext.PPS.EntropyCodingMode == 1 {
// TODO: ue(v) or ae(v)
binarization := NewBinarization(
@ -837,7 +873,7 @@ func MbaffFrameFlag(sps *SPS, header *SliceHeader) int {
return 0
}
func NewSliceData(sliceContext *SliceContext, br *bits.BitReader) (*SliceData, error) {
func NewSliceData(chromaArrayType int, sliceContext *SliceContext, br *bits.BitReader) (*SliceData, error) {
r := newFieldReader(br)
var cabac *CABAC
sliceContext.Slice.Data = &SliceData{BitReader: br}
@ -1066,7 +1102,7 @@ func NewSliceData(sliceContext *SliceContext, br *bits.BitReader) (*SliceData, e
}
}
// TODO: fix nil argument for.
MbPred(sliceContext, br, nil)
MbPred(chromaArrayType, sliceContext, br, nil)
}
m, err = MbPartPredMode(sliceContext.Slice.Data, sliceContext.Slice.Data.SliceTypeName, sliceContext.Slice.Data.MbType, 0)
if err != nil {
@ -1085,7 +1121,7 @@ func NewSliceData(sliceContext *SliceContext, br *bits.BitReader) (*SliceData, e
} else {
me, _ := readMe(
br,
uint(sliceContext.Slice.Header.ChromaArrayType),
uint(chromaArrayType),
// TODO: fix this
//MbPartPredMode(sliceContext.Slice.Data, sliceContext.Slice.Data.SliceTypeName, sliceContext.Slice.Data.MbType, 0)))
0)
@ -1162,10 +1198,10 @@ func NewSliceData(sliceContext *SliceContext, br *bits.BitReader) (*SliceData, e
func (c *SliceContext) Update(header *SliceHeader, data *SliceData) {
c.Slice = &Slice{Header: header, Data: data}
}
func NewSliceContext(videoStream *VideoStream, nalUnit *NALUnit, rbsp []byte, showPacket bool) (*SliceContext, error) {
func NewSliceContext(vid *VideoStream, nalUnit *NALUnit, rbsp []byte, showPacket bool) (*SliceContext, error) {
var err error
sps := videoStream.SPS
pps := videoStream.PPS
sps := vid.SPS
pps := vid.PPS
logger.Printf("debug: %s RBSP %d bytes %d bits == \n", NALUnitType[int(nalUnit.Type)], len(rbsp), len(rbsp)*8)
logger.Printf("debug: \t%#v\n", rbsp[0:8])
var idrPic bool
@ -1174,9 +1210,9 @@ func NewSliceContext(videoStream *VideoStream, nalUnit *NALUnit, rbsp []byte, sh
}
header := SliceHeader{}
if sps.SeparateColorPlaneFlag {
header.ChromaArrayType = 0
vid.ChromaArrayType = 0
} else {
header.ChromaArrayType = int(sps.ChromaFormatIDC)
vid.ChromaArrayType = int(sps.ChromaFormatIDC)
}
br := bits.NewBitReader(bytes.NewReader(rbsp))
r := newFieldReader(br)
@ -1270,21 +1306,21 @@ func NewSliceContext(videoStream *VideoStream, nalUnit *NALUnit, rbsp []byte, sh
// H.7.3.3.1.1
// refPicListMvcModifications()
} else {
header.RefPicListModification, err = NewRefPicListModification(br, &header)
header.RefPicListModification, err = NewRefPicListModification(br, pps, &header)
if err != nil {
return nil, errors.Wrap(err, "could not parse RefPicListModification")
}
}
if (pps.WeightedPred && (sliceType == "P" || sliceType == "SP")) || (pps.WeightedBipred == 1 && sliceType == "B") {
header.PredWeightTable, err = NewPredWeightTable(br, &header)
header.PredWeightTable, err = NewPredWeightTable(br, &header, vid.ChromaArrayType)
if err != nil {
return nil, errors.Wrap(err, "could not parse PredWeightTable")
}
}
if nalUnit.RefIdc != 0 {
// devRefPicMarking()
header.DecRefPicMarking, err = NewDecRefPicMarking(br, idrPic, &header)
header.DecRefPicMarking, err = NewDecRefPicMarking(br, idrPic)
if err != nil {
return nil, errors.Wrap(err, "could not parse DecRefPicMarking")
}
@ -1330,7 +1366,7 @@ func NewSliceContext(videoStream *VideoStream, nalUnit *NALUnit, rbsp []byte, sh
Header: &header,
},
}
sliceContext.Slice.Data, err = NewSliceData(sliceContext, br)
sliceContext.Slice.Data, err = NewSliceData(vid.ChromaArrayType, sliceContext, br)
if err != nil {
return nil, errors.Wrap(err, "could not create slice data")
}

View File

@ -1,6 +1,37 @@
/*
DESCRIPTION
slice_test.go provides testing for parsing functionality found in slice.go.
AUTHORS
Saxon Nelson-Milton <saxon@ausocean.org>
Shawn Smith <shawn@ausocean.org>
LICENSE
Copyright (C) 2019 the Australian Ocean Lab (AusOcean).
It is free software: you can redistribute it and/or modify them
under the terms of the GNU General Public License as published by the
Free Software Foundation, either version 3 of the License, or (at your
option) any later version.
It is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
for more details.
You should have received a copy of the GNU General Public License
in gpl.txt. If not, see http://www.gnu.org/licenses.
*/
package h264dec
import "testing"
import (
"bytes"
"reflect"
"testing"
"bitbucket.org/ausocean/av/codec/h264/h264dec/bits"
)
var subWidthCTests = []struct {
in SPS
@ -47,3 +78,257 @@ func TestSubHeightC(t *testing.T) {
}
}
}
func TestNewRefPicListModification(t *testing.T) {
tests := []struct {
in string
s SliceHeader
p PPS
want RefPicListModification
}{
{
in: "1" + // u(1) ref_pic_list_modification_flag_l0=true
// First modification for list0
"1" + // ue(v) modification_of_pic_nums_idc[0][0] = 0
"010" + // ue(v) abs_diff_pic_num_minus1[0][0] = 1
// Second modification for list0
"010" + // ue(v) modification_of_pic_nums_idc[0][1] = 1
"011" + // ue(v) abs_diff_pic_num_minus1[0][1] = 2
// Third modification for list0
"011" + // ue(v) modification_of_pic_nums_idc[0][2] = 2
"010" + // ue(v) long_term_pic_num = 1
// Fourth modification does not exist
"00100", // ue(v) modification_of_pic_nums_idc[0][3] = 3
s: SliceHeader{
SliceType: 3,
},
p: PPS{
NumRefIdxL0DefaultActiveMinus1: 2,
},
want: RefPicListModification{
RefPicListModificationFlag: [2]bool{true, false},
ModificationOfPicNums: [2][]int{{0, 1, 2, 3}, {0, 0}},
AbsDiffPicNumMinus1: [2][]int{{1, 2, 0, 0}, {0, 0}},
LongTermPicNum: [2][]int{{0, 0, 1, 0}, {0, 0}},
},
},
}
for i, test := range tests {
inBytes, err := binToSlice(test.in)
if err != nil {
t.Fatalf("unexpected error %v for binToSlice in test %d", err, i)
}
got, err := NewRefPicListModification(bits.NewBitReader(bytes.NewReader(inBytes)), &test.p, &test.s)
if err != nil {
t.Fatalf("unexpected error %v for NewRefPicListModification in test %d", err, i)
}
if !reflect.DeepEqual(*got, test.want) {
t.Errorf("did not get expected result for test %d\nGot: %v\nWant: %v\n", i, got, test.want)
}
}
}
func TestNewPredWeightTable(t *testing.T) {
tests := []struct {
in string
sliceHeader SliceHeader
chromaArrayType int
want PredWeightTable
}{
{
in: "011" + // ue(v) luma_log2_weight_denom = 2
"00100" + // ue(v) chroma_log2_weigght_denom = 3
// list0
// i = 0
"1" + // u(1) luma_weight_l0_flag = true
"011" + // se(v) luma_weight_l0[0] = -1
"010" + // se(v) luma_offset_l0[0] = 1
"1" + // u(1) chroma_weight_l0_flag = true
// i = 0, j = 0
"010" + // se(v) chroma_weight_l0[0][0] = 1
"010" + // se(v) chroma_offset_l0[0][0] = 1
// i = 0, j = 1
"010" + // se(v) chroma_weight_l0[0][1] = 1
"010" + // se(v) chroma_offset_l0[0][1] = 1
// i = 1
"1" + // u(1) luma_weight_l0_flag = true
"011" + // se(v) luma_weight_l0[1] = -1
"00100" + // se(v) luma_offset_l0[1] = 2
"1" + // u(1) chroma_weight_l0_flag = true
// i = 1, j = 0
"011" + // se(v) chroma_weight_l0[1][0] = -1
"00101" + // se(v) chroma_offset_l0[1][0] = -2
// i = 1, j = 1
"011" + // se(v) chroma_weight_l0[1][1] = -1
"011" + // se(v) chroma_offset_l0[1][1] = -1
// list1
// i = 0
"1" + // u(1) luma_weight_l1_flag = true
"011" + // se(v) luma_weight_l1[0] = -1
"010" + // se(v) luma_offset_l1[0] = 1
"1" + // u(1) chroma_weight_l1_flag = true
// i = 0, j = 0
"010" + // se(v) chroma_weight_l1[0][0] = 1
"010" + // se(v) chroma_offset_l1[0][0] = 1
// i = 0, j = 1
"010" + // se(v) chroma_weight_l1[0][1] = 1
"010" + // se(v) chroma_offset_l1[0][1] = 1
// i = 1
"1" + // u(1) luma_weight_l1_flag = true
"011" + // se(v) luma_weight_l1[1] = -1
"00100" + // se(v) luma_offset_l1[1] = 2
"1" + // u(1) chroma_weight_l1_flag = true
// i = 1, j = 0
"011" + // se(v) chroma_weight_l0[1][0] = -1
"00101" + // se(v) chroma_offset_l0[1][0] = -2
// i = 1, j = 1
"011" + // se(v) chroma_weight_l0[1][1] = -1
"011", // se(v) chroma_offset_l0[1][1] = -1
sliceHeader: SliceHeader{
NumRefIdxL0ActiveMinus1: 1,
NumRefIdxL1ActiveMinus1: 1,
SliceType: 1,
},
chromaArrayType: 1,
want: PredWeightTable{
LumaLog2WeightDenom: 2,
ChromaLog2WeightDenom: 3,
LumaWeightL0Flag: true,
LumaWeightL0: []int{-1, -1},
LumaOffsetL0: []int{1, 2},
ChromaWeightL0Flag: true,
ChromaWeightL0: [][]int{{1, 1}, {-1, -1}},
ChromaOffsetL0: [][]int{{1, 1}, {-2, -1}},
LumaWeightL1Flag: true,
LumaWeightL1: []int{-1, -1},
LumaOffsetL1: []int{1, 2},
ChromaWeightL1Flag: true,
ChromaWeightL1: [][]int{{1, 1}, {-1, -1}},
ChromaOffsetL1: [][]int{{1, 1}, {-2, -1}},
},
},
}
for i, test := range tests {
inBytes, err := binToSlice(test.in)
if err != nil {
t.Fatalf("unexpected error %v for binToSlice in test %d", err, i)
}
got, err := NewPredWeightTable(bits.NewBitReader(bytes.NewReader(inBytes)),
&test.sliceHeader, test.chromaArrayType)
if err != nil {
t.Fatalf("unexpected error %v for NewPredWeightTable in test %d", err, i)
}
if !reflect.DeepEqual(*got, test.want) {
t.Errorf("did not get expected result for test %d\nGot: %v\nWant: %v\n", i, got, test.want)
}
}
}
func TestDecRefPicMarking(t *testing.T) {
tests := []struct {
in string
idrPic bool
want DecRefPicMarking
}{
{
in: "0" + // u(1) no_output_of_prior_pics_flag = false
"1", // u(1) long_term_reference_flag = true
idrPic: true,
want: DecRefPicMarking{
NoOutputOfPriorPicsFlag: false,
LongTermReferenceFlag: true,
},
},
{
in: "1" + // u(1) adaptive_ref_pic_marking_mode_flag = true
"010" + // ue(v) memory_management_control_operation = 1
"011" + // ue(v) difference_of_pic_nums_minus1 = 2
"00100" + // ue(v) memory_management_control_operation = 3
"1" + // ue(v) difference_of_pic_nums_minus1 = 0
"011" + // ue(v) long_term_frame_idx = 2
"011" + // ue(v) memory_management_control_operation = 2
"00100" + // ue(v) long_term_pic_num = 3
"00101" + // ue(v) memory_management_control_operation = 4
"010" + // ue(v) max_long_term_frame_idx_plus1 = 1
"1", // ue(v) memory_management_control_operation = 0
idrPic: false,
want: DecRefPicMarking{
AdaptiveRefPicMarkingModeFlag: true,
elements: []drpmElement{
{
MemoryManagementControlOperation: 1,
DifferenceOfPicNumsMinus1: 2,
},
{
MemoryManagementControlOperation: 3,
DifferenceOfPicNumsMinus1: 0,
LongTermFrameIdx: 2,
},
{
MemoryManagementControlOperation: 2,
LongTermPicNum: 3,
},
{
MemoryManagementControlOperation: 4,
MaxLongTermFrameIdxPlus1: 1,
},
{
MemoryManagementControlOperation: 0,
},
},
},
},
}
for i, test := range tests {
inBytes, err := binToSlice(test.in)
if err != nil {
t.Fatalf("unexpected error %v for binToSlice in test %d", err, i)
}
got, err := NewDecRefPicMarking(bits.NewBitReader(bytes.NewReader(inBytes)), test.idrPic)
if err != nil {
t.Fatalf("unexpected error %v for NewPredWeightTable in test %d", err, i)
}
if !reflect.DeepEqual(*got, test.want) {
t.Errorf("did not get expected result for test %d\nGot: %v\nWant: %v\n", i, got, test.want)
}
}
}