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 bytes []byte
) )
for _, c := range s { for i, c := range s {
switch c { switch c {
case ' ': case ' ':
continue continue
@ -33,7 +33,7 @@ func binToSlice(s string) ([]byte, error) {
} }
a >>= 1 a >>= 1
if a == 0 { if a == 0 || i == (len(s)-1) {
bytes = append(bytes, cur) bytes = append(bytes, cur)
cur = 0 cur = 0
a = 0x80 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 package h264dec
import ( import (
@ -30,6 +39,8 @@ type VideoStream struct {
SPS *SPS SPS *SPS
PPS *PPS PPS *PPS
Slices []*SliceContext Slices []*SliceContext
ChromaArrayType int
} }
type SliceContext struct { type SliceContext struct {
*NALUnit *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 7.3.3.1 of specifications) and a ref_pic_list_mvc_modification
// (defined in H.7.3.3.1.1 of specifications). // (defined in H.7.3.3.1.1 of specifications).
type RefPicListModification struct { type RefPicListModification struct {
RefPicListModificationFlagL0 bool RefPicListModificationFlag [2]bool
ModificationOfPicNums int ModificationOfPicNums [2][]int
AbsDiffPicNumMinus1 int AbsDiffPicNumMinus1 [2][]int
LongTermPicNum int LongTermPicNum [2][]int
RefPicListModificationFlagL1 bool
} }
// TODO: need to complete this. // 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 // NewRefPicListModification parses elements of a ref_pic_list_modification
// following the syntax structure defined in section 7.3.3.1, and returns as // following the syntax structure defined in section 7.3.3.1, and returns as
// a new RefPicListModification. // a new RefPicListModification.
func NewRefPicListModification(br *bits.BitReader, h *SliceHeader) (*RefPicListModification, error) { func NewRefPicListModification(br *bits.BitReader, p *PPS, s *SliceHeader) (*RefPicListModification, error) {
ref := &RefPicListModification{} r := &RefPicListModification{}
r := newFieldReader(br) 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 // 7.3.3.1
if h.SliceType%5 != 2 && h.SliceType%5 != 4 { if s.SliceType%5 != 2 && s.SliceType%5 != 4 {
ref.RefPicListModificationFlagL0 = r.readBits(1) == 1 r.RefPicListModificationFlag[0] = fr.readBits(1) == 1
if ref.RefPicListModificationFlagL0 { if r.RefPicListModificationFlag[0] {
for ref.ModificationOfPicNums != 3 { for i := 0; ; i++ {
ref.ModificationOfPicNums = int(r.readUe()) r.ModificationOfPicNums[0][i] = int(fr.readUe())
if ref.ModificationOfPicNums == 0 || ref.ModificationOfPicNums == 1 { if r.ModificationOfPicNums[0][i] == 0 || r.ModificationOfPicNums[0][i] == 1 {
ref.AbsDiffPicNumMinus1 = int(r.readUe()) r.AbsDiffPicNumMinus1[0][i] = int(fr.readUe())
} else if ref.ModificationOfPicNums == 2 { } else if r.ModificationOfPicNums[0][i] == 2 {
ref.LongTermPicNum = int(r.readUe()) r.LongTermPicNum[0][i] = int(fr.readUe())
} }
}
}
} if r.ModificationOfPicNums[0][i] == 3 {
if h.SliceType%5 == 1 { break
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())
} }
} }
} }
} }
// 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 // 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 { type PredWeightTable struct {
LumaLog2WeightDenom int LumaLog2WeightDenom int
ChromaLog2WeightDenom int ChromaLog2WeightDenom int
ChromaArrayType int
LumaWeightL0Flag bool LumaWeightL0Flag bool
LumaWeightL0 []int LumaWeightL0 []int
LumaOffsetL0 []int LumaOffsetL0 []int
@ -126,13 +149,13 @@ type PredWeightTable struct {
// NewPredWeightTable parses elements of a pred_weight_table following the // NewPredWeightTable parses elements of a pred_weight_table following the
// syntax structure defined in section 7.3.3.2, and returns as a new // syntax structure defined in section 7.3.3.2, and returns as a new
// PredWeightTable. // PredWeightTable.
func NewPredWeightTable(br *bits.BitReader, h *SliceHeader) (*PredWeightTable, error) { func NewPredWeightTable(br *bits.BitReader, h *SliceHeader, chromaArrayType int) (*PredWeightTable, error) {
p := &PredWeightTable{} p := &PredWeightTable{}
r := newFieldReader(br) r := newFieldReader(br)
p.LumaLog2WeightDenom = int(r.readUe()) p.LumaLog2WeightDenom = int(r.readUe())
if p.ChromaArrayType != 0 { if chromaArrayType != 0 {
p.ChromaLog2WeightDenom = int(r.readUe()) p.ChromaLog2WeightDenom = int(r.readUe())
} }
for i := 0; i <= h.NumRefIdxL0ActiveMinus1; i++ { 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) p.LumaOffsetL0 = append(p.LumaOffsetL0, se)
} }
if p.ChromaArrayType != 0 { if chromaArrayType != 0 {
b, err := br.ReadBits(1) b, err := br.ReadBits(1)
if err != nil { if err != nil {
return nil, errors.Wrap(err, "could not read ChromaWeightL0Flag") 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) p.LumaOffsetL1 = append(p.LumaOffsetL1, se)
} }
if p.ChromaArrayType != 0 { if chromaArrayType != 0 {
b, err := br.ReadBits(1) b, err := br.ReadBits(1)
if err != nil { if err != nil {
return nil, errors.Wrap(err, "could not read ChromaWeightL1Flag") 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 // DecRefPicMarking provides elements of a dec_ref_pic_marking syntax structure
// as defined in section 7.3.3.3 of the specifications. // as defined in section 7.3.3.3 of the specifications.
type DecRefPicMarking struct { type DecRefPicMarking struct {
NoOutputOfPriorPicsFlag bool NoOutputOfPriorPicsFlag bool
LongTermReferenceFlag bool LongTermReferenceFlag bool
AdaptiveRefPicMarkingModeFlag bool AdaptiveRefPicMarkingModeFlag bool
elements []drpmElement
}
type drpmElement struct {
MemoryManagementControlOperation int MemoryManagementControlOperation int
DifferenceOfPicNumsMinus1 int DifferenceOfPicNumsMinus1 int
LongTermPicNum int
LongTermFrameIdx int LongTermFrameIdx int
MaxLongTermFrameIdxPlus1 int MaxLongTermFrameIdxPlus1 int
} }
@ -243,7 +271,7 @@ type DecRefPicMarking struct {
// NewDecRefPicMarking parses elements of a dec_ref_pic_marking following the // 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 // syntax structure defined in section 7.3.3.3, and returns as a new
// DecRefPicMarking. // DecRefPicMarking.
func NewDecRefPicMarking(br *bits.BitReader, idrPic bool, h *SliceHeader) (*DecRefPicMarking, error) { func NewDecRefPicMarking(br *bits.BitReader, idrPic bool) (*DecRefPicMarking, error) {
d := &DecRefPicMarking{} d := &DecRefPicMarking{}
r := newFieldReader(br) r := newFieldReader(br)
if idrPic { if idrPic {
@ -266,19 +294,26 @@ func NewDecRefPicMarking(br *bits.BitReader, idrPic bool, h *SliceHeader) (*DecR
d.AdaptiveRefPicMarkingModeFlag = b == 1 d.AdaptiveRefPicMarkingModeFlag = b == 1
if d.AdaptiveRefPicMarkingModeFlag { if d.AdaptiveRefPicMarkingModeFlag {
d.MemoryManagementControlOperation = int(r.readUe()) for i := 0; ; i++ {
for d.MemoryManagementControlOperation != 0 { d.elements = append(d.elements, drpmElement{})
if d.MemoryManagementControlOperation == 1 || d.MemoryManagementControlOperation == 3 {
d.DifferenceOfPicNumsMinus1 = int(r.readUe()) 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 { if d.elements[i].MemoryManagementControlOperation == 2 {
h.RefPicListModification.LongTermPicNum = int(r.readUe()) d.elements[i].LongTermPicNum = int(r.readUe())
} }
if d.MemoryManagementControlOperation == 3 || d.MemoryManagementControlOperation == 6 { if d.elements[i].MemoryManagementControlOperation == 3 || d.elements[i].MemoryManagementControlOperation == 6 {
d.LongTermFrameIdx = int(r.readUe()) d.elements[i].LongTermFrameIdx = int(r.readUe())
} }
if d.MemoryManagementControlOperation == 4 { if d.elements[i].MemoryManagementControlOperation == 4 {
d.MaxLongTermFrameIdxPlus1 = int(r.readUe()) 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 return numMbPart
} }
func MbPred(sliceContext *SliceContext, br *bits.BitReader, rbsp []byte) error { func MbPred(chromaArrayType int, sliceContext *SliceContext, br *bits.BitReader, rbsp []byte) error {
r := newFieldReader(br)
var cabac *CABAC var cabac *CABAC
r := newFieldReader(br)
sliceType := sliceTypeMap[sliceContext.Slice.Header.SliceType] sliceType := sliceTypeMap[sliceContext.Slice.Header.SliceType]
mbPartPredMode, err := MbPartPredMode(sliceContext.Slice.Data, sliceType, sliceContext.Slice.Data.MbType, 0) mbPartPredMode, err := MbPartPredMode(sliceContext.Slice.Data, sliceType, sliceContext.Slice.Data.MbType, 0)
if err != nil { 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 { if sliceContext.PPS.EntropyCodingMode == 1 {
// TODO: ue(v) or ae(v) // TODO: ue(v) or ae(v)
binarization := NewBinarization( binarization := NewBinarization(
@ -837,7 +873,7 @@ func MbaffFrameFlag(sps *SPS, header *SliceHeader) int {
return 0 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) r := newFieldReader(br)
var cabac *CABAC var cabac *CABAC
sliceContext.Slice.Data = &SliceData{BitReader: br} sliceContext.Slice.Data = &SliceData{BitReader: br}
@ -1066,7 +1102,7 @@ func NewSliceData(sliceContext *SliceContext, br *bits.BitReader) (*SliceData, e
} }
} }
// TODO: fix nil argument for. // 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) m, err = MbPartPredMode(sliceContext.Slice.Data, sliceContext.Slice.Data.SliceTypeName, sliceContext.Slice.Data.MbType, 0)
if err != nil { if err != nil {
@ -1085,7 +1121,7 @@ func NewSliceData(sliceContext *SliceContext, br *bits.BitReader) (*SliceData, e
} else { } else {
me, _ := readMe( me, _ := readMe(
br, br,
uint(sliceContext.Slice.Header.ChromaArrayType), uint(chromaArrayType),
// TODO: fix this // TODO: fix this
//MbPartPredMode(sliceContext.Slice.Data, sliceContext.Slice.Data.SliceTypeName, sliceContext.Slice.Data.MbType, 0))) //MbPartPredMode(sliceContext.Slice.Data, sliceContext.Slice.Data.SliceTypeName, sliceContext.Slice.Data.MbType, 0)))
0) 0)
@ -1162,10 +1198,10 @@ func NewSliceData(sliceContext *SliceContext, br *bits.BitReader) (*SliceData, e
func (c *SliceContext) Update(header *SliceHeader, data *SliceData) { func (c *SliceContext) Update(header *SliceHeader, data *SliceData) {
c.Slice = &Slice{Header: header, Data: data} 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 var err error
sps := videoStream.SPS sps := vid.SPS
pps := videoStream.PPS 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: %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]) logger.Printf("debug: \t%#v\n", rbsp[0:8])
var idrPic bool var idrPic bool
@ -1174,9 +1210,9 @@ func NewSliceContext(videoStream *VideoStream, nalUnit *NALUnit, rbsp []byte, sh
} }
header := SliceHeader{} header := SliceHeader{}
if sps.SeparateColorPlaneFlag { if sps.SeparateColorPlaneFlag {
header.ChromaArrayType = 0 vid.ChromaArrayType = 0
} else { } else {
header.ChromaArrayType = int(sps.ChromaFormatIDC) vid.ChromaArrayType = int(sps.ChromaFormatIDC)
} }
br := bits.NewBitReader(bytes.NewReader(rbsp)) br := bits.NewBitReader(bytes.NewReader(rbsp))
r := newFieldReader(br) r := newFieldReader(br)
@ -1270,21 +1306,21 @@ func NewSliceContext(videoStream *VideoStream, nalUnit *NALUnit, rbsp []byte, sh
// H.7.3.3.1.1 // H.7.3.3.1.1
// refPicListMvcModifications() // refPicListMvcModifications()
} else { } else {
header.RefPicListModification, err = NewRefPicListModification(br, &header) header.RefPicListModification, err = NewRefPicListModification(br, pps, &header)
if err != nil { if err != nil {
return nil, errors.Wrap(err, "could not parse RefPicListModification") return nil, errors.Wrap(err, "could not parse RefPicListModification")
} }
} }
if (pps.WeightedPred && (sliceType == "P" || sliceType == "SP")) || (pps.WeightedBipred == 1 && sliceType == "B") { 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 { if err != nil {
return nil, errors.Wrap(err, "could not parse PredWeightTable") return nil, errors.Wrap(err, "could not parse PredWeightTable")
} }
} }
if nalUnit.RefIdc != 0 { if nalUnit.RefIdc != 0 {
// devRefPicMarking() // devRefPicMarking()
header.DecRefPicMarking, err = NewDecRefPicMarking(br, idrPic, &header) header.DecRefPicMarking, err = NewDecRefPicMarking(br, idrPic)
if err != nil { if err != nil {
return nil, errors.Wrap(err, "could not parse DecRefPicMarking") return nil, errors.Wrap(err, "could not parse DecRefPicMarking")
} }
@ -1330,7 +1366,7 @@ func NewSliceContext(videoStream *VideoStream, nalUnit *NALUnit, rbsp []byte, sh
Header: &header, Header: &header,
}, },
} }
sliceContext.Slice.Data, err = NewSliceData(sliceContext, br) sliceContext.Slice.Data, err = NewSliceData(vid.ChromaArrayType, sliceContext, br)
if err != nil { if err != nil {
return nil, errors.Wrap(err, "could not create slice data") 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 package h264dec
import "testing" import (
"bytes"
"reflect"
"testing"
"bitbucket.org/ausocean/av/codec/h264/h264dec/bits"
)
var subWidthCTests = []struct { var subWidthCTests = []struct {
in SPS 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)
}
}
}