mirror of https://bitbucket.org/ausocean/av.git
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:
commit
13490e0145
|
@ -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
|
||||||
|
|
|
@ -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 {
|
||||||
|
break
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
if s.SliceType%5 == 1 {
|
||||||
if h.SliceType%5 == 1 {
|
r.RefPicListModificationFlag[1] = fr.readBits(1) == 1
|
||||||
ref.RefPicListModificationFlagL1 = r.readBits(1) == 1
|
|
||||||
|
|
||||||
if ref.RefPicListModificationFlagL1 {
|
if r.RefPicListModificationFlag[1] {
|
||||||
for ref.ModificationOfPicNums != 3 {
|
for i := 0; ; i++ {
|
||||||
ref.ModificationOfPicNums = int(r.readUe())
|
r.ModificationOfPicNums[1][i] = int(fr.readUe())
|
||||||
|
|
||||||
if ref.ModificationOfPicNums == 0 || ref.ModificationOfPicNums == 1 {
|
if r.ModificationOfPicNums[1][i] == 0 || r.ModificationOfPicNums[1][i] == 1 {
|
||||||
ref.AbsDiffPicNumMinus1 = int(r.readUe())
|
r.AbsDiffPicNumMinus1[1][i] = int(fr.readUe())
|
||||||
} else if ref.ModificationOfPicNums == 2 {
|
} else if r.ModificationOfPicNums[1][i] == 2 {
|
||||||
ref.LongTermPicNum = int(r.readUe())
|
r.LongTermPicNum[1][i] = int(fr.readUe())
|
||||||
|
}
|
||||||
|
|
||||||
|
if r.ModificationOfPicNums[1][i] == 3 {
|
||||||
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// refPicListModification()
|
return r, nil
|
||||||
return nil, 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")
|
||||||
|
@ -234,8 +257,13 @@ 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")
|
||||||
}
|
}
|
||||||
|
|
|
@ -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)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue