Merged in slice-modularisation (pull request #218)

codec/h264/h264dec: SliceHeader modularisation
This commit is contained in:
Saxon Milton 2019-08-01 11:25:14 +00:00
commit 3f1c09a671
1 changed files with 325 additions and 260 deletions

View File

@ -32,51 +32,231 @@ type Slice struct {
Header *SliceHeader Header *SliceHeader
Data *SliceData Data *SliceData
} }
type SliceHeader struct {
FirstMbInSlice int // RefPicListModification provides elements of a ref_pic_list_modification syntax
SliceType int // (defined in 7.3.3.1 of specifications) and a ref_pic_list_mvc_modification
PPSID int // (defined in H.7.3.3.1.1 of specifications).
ColorPlaneID int type RefPicListModification struct {
FrameNum int RefPicListModificationFlagL0 bool
FieldPic bool ModificationOfPicNums int
BottomField bool AbsDiffPicNumMinus1 int
IDRPicID int LongTermPicNum int
PicOrderCntLsb int RefPicListModificationFlagL1 bool
DeltaPicOrderCntBottom int }
DeltaPicOrderCnt []int
RedundantPicCnt int // TODO: need to complete this.
DirectSpatialMvPred bool // NewRefPicListMVCModification parses elements of a ref_pic_list_mvc_modification
NumRefIdxActiveOverride bool // following the syntax structure defined in section H.7.3.3.1.1, and returns as
NumRefIdxL0ActiveMinus1 int // a new RefPicListModification.
NumRefIdxL1ActiveMinus1 int func NewRefPicListMVCModifiation(br *bits.BitReader) (*RefPicListModification, error) {
CabacInit int return nil, nil
SliceQpDelta int }
SpForSwitch bool
SliceQsDelta int // NewRefPicListModification parses elements of a ref_pic_list_modification
DisableDeblockingFilter int // following the syntax structure defined in section 7.3.3.1, and returns as
SliceAlphaC0OffsetDiv2 int // a new RefPicListModification.
SliceBetaOffsetDiv2 int func NewRefPicListModification(br *bits.BitReader, h *SliceHeader) (*RefPicListModification, error) {
SliceGroupChangeCycle int r := &RefPicListModification{}
RefPicListModificationFlagL0 bool // 7.3.3.1
ModificationOfPicNums int if h.SliceType%5 != 2 && h.SliceType%5 != 4 {
AbsDiffPicNumMinus1 int b, err := br.ReadBits(1)
LongTermPicNum int if err != nil {
RefPicListModificationFlagL1 bool return nil, errors.Wrap(err, "could not read RefPicListModificationFlagL0")
LumaLog2WeightDenom int }
ChromaLog2WeightDenom int r.RefPicListModificationFlagL0 = b == 1
ChromaArrayType int
LumaWeightL0Flag bool if r.RefPicListModificationFlagL0 {
LumaWeightL0 []int for r.ModificationOfPicNums != 3 {
LumaOffsetL0 []int r.ModificationOfPicNums, err = readUe(br)
ChromaWeightL0Flag bool if err != nil {
ChromaWeightL0 [][]int return nil, errors.Wrap(err, "could not parse ModificationOfPicNums")
ChromaOffsetL0 [][]int }
LumaWeightL1Flag bool
LumaWeightL1 []int if r.ModificationOfPicNums == 0 || r.ModificationOfPicNums == 1 {
LumaOffsetL1 []int r.AbsDiffPicNumMinus1, err = readUe(br)
ChromaWeightL1Flag bool if err != nil {
ChromaWeightL1 [][]int return nil, errors.Wrap(err, "could not parse AbsDiffPicNumMinus1")
ChromaOffsetL1 [][]int }
} else if r.ModificationOfPicNums == 2 {
r.LongTermPicNum, err = readUe(br)
if err != nil {
return nil, errors.Wrap(err, "could not parse LongTermPicNum")
}
}
}
}
}
if h.SliceType%5 == 1 {
b, err := br.ReadBits(1)
if err != nil {
return nil, errors.Wrap(err, "could not read RefPicListModificationFlagL1")
}
r.RefPicListModificationFlagL1 = b == 1
if r.RefPicListModificationFlagL1 {
for r.ModificationOfPicNums != 3 {
r.ModificationOfPicNums, err = readUe(br)
if err != nil {
return nil, errors.Wrap(err, "could not parse ModificationOfPicNums")
}
if r.ModificationOfPicNums == 0 || r.ModificationOfPicNums == 1 {
r.AbsDiffPicNumMinus1, err = readUe(br)
if err != nil {
return nil, errors.Wrap(err, "could not parse AbsDiffPicNumMinus1")
}
} else if r.ModificationOfPicNums == 2 {
r.LongTermPicNum, err = readUe(br)
if err != nil {
return nil, errors.Wrap(err, "could not parse LongTermPicNum")
}
}
}
}
}
// refPicListModification()
return nil, nil
}
// PredWeightTable provides elements of a pred_weight_table syntax structure
// as defined in section 7.3.3.2 of the specifications.
type PredWeightTable struct {
LumaLog2WeightDenom int
ChromaLog2WeightDenom int
ChromaArrayType int
LumaWeightL0Flag bool
LumaWeightL0 []int
LumaOffsetL0 []int
ChromaWeightL0Flag bool
ChromaWeightL0 [][]int
ChromaOffsetL0 [][]int
LumaWeightL1Flag bool
LumaWeightL1 []int
LumaOffsetL1 []int
ChromaWeightL1Flag bool
ChromaWeightL1 [][]int
ChromaOffsetL1 [][]int
}
// 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) {
p := &PredWeightTable{}
var err error
p.LumaLog2WeightDenom, err = readUe(br)
if err != nil {
return nil, errors.Wrap(err, "could not parse LumaLog2WeightDenom")
}
if p.ChromaArrayType != 0 {
p.ChromaLog2WeightDenom, err = readUe(br)
if err != nil {
return nil, errors.Wrap(err, "could not parse ChromaLog2WeightDenom")
}
}
for i := 0; i <= h.NumRefIdxL0ActiveMinus1; i++ {
b, err := br.ReadBits(1)
if err != nil {
return nil, errors.Wrap(err, "could not read LumaWeightL0Flag")
}
p.LumaWeightL0Flag = b == 1
if p.LumaWeightL0Flag {
se, err := readSe(br)
if err != nil {
return nil, errors.Wrap(err, "could not parse LumaWeightL0")
}
p.LumaWeightL0 = append(p.LumaWeightL0, se)
se, err = readSe(br)
if err != nil {
return nil, errors.Wrap(err, "could not parse LumaOffsetL0")
}
p.LumaOffsetL0 = append(p.LumaOffsetL0, se)
}
if p.ChromaArrayType != 0 {
b, err := br.ReadBits(1)
if err != nil {
return nil, errors.Wrap(err, "could not read ChromaWeightL0Flag")
}
p.ChromaWeightL0Flag = b == 1
if p.ChromaWeightL0Flag {
p.ChromaWeightL0 = append(p.ChromaWeightL0, []int{})
p.ChromaOffsetL0 = append(p.ChromaOffsetL0, []int{})
for j := 0; j < 2; j++ {
se, err := readSe(br)
if err != nil {
return nil, errors.Wrap(err, "could not parse ChromaWeightL0")
}
p.ChromaWeightL0[i] = append(p.ChromaWeightL0[i], se)
se, err = readSe(br)
if err != nil {
return nil, errors.Wrap(err, "could not parse ChromaOffsetL0")
}
p.ChromaOffsetL0[i] = append(p.ChromaOffsetL0[i], se)
}
}
}
}
if h.SliceType%5 == 1 {
for i := 0; i <= h.NumRefIdxL1ActiveMinus1; i++ {
b, err := br.ReadBits(1)
if err != nil {
return nil, errors.Wrap(err, "could not read LumaWeightL1Flag")
}
p.LumaWeightL1Flag = b == 1
if p.LumaWeightL1Flag {
se, err := readSe(br)
if err != nil {
return nil, errors.Wrap(err, "could not parse LumaWeightL1")
}
p.LumaWeightL1 = append(p.LumaWeightL1, se)
se, err = readSe(br)
if err != nil {
return nil, errors.Wrap(err, "could not parse LumaOffsetL1")
}
p.LumaOffsetL1 = append(p.LumaOffsetL1, se)
}
if p.ChromaArrayType != 0 {
b, err := br.ReadBits(1)
if err != nil {
return nil, errors.Wrap(err, "could not read ChromaWeightL1Flag")
}
p.ChromaWeightL1Flag = b == 1
if p.ChromaWeightL1Flag {
p.ChromaWeightL1 = append(p.ChromaWeightL1, []int{})
p.ChromaOffsetL1 = append(p.ChromaOffsetL1, []int{})
for j := 0; j < 2; j++ {
se, err := readSe(br)
if err != nil {
return nil, errors.Wrap(err, "could not parse ChromaWeightL1")
}
p.ChromaWeightL1[i] = append(p.ChromaWeightL1[i], se)
se, err = readSe(br)
if err != nil {
return nil, errors.Wrap(err, "could not parse ChromaOffsetL1")
}
p.ChromaOffsetL1[i] = append(p.ChromaOffsetL1[i], se)
}
}
}
}
}
return p, nil
}
// 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 NoOutputOfPriorPicsFlag bool
LongTermReferenceFlag bool LongTermReferenceFlag bool
AdaptiveRefPicMarkingModeFlag bool AdaptiveRefPicMarkingModeFlag bool
@ -86,6 +266,96 @@ type SliceHeader struct {
MaxLongTermFrameIdxPlus1 int MaxLongTermFrameIdxPlus1 int
} }
// 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) {
d := &DecRefPicMarking{}
if idrPic {
b, err := br.ReadBits(1)
if err != nil {
return nil, errors.Wrap(err, "could not read NoOutputOfPriorPicsFlag")
}
d.NoOutputOfPriorPicsFlag = b == 1
b, err = br.ReadBits(1)
if err != nil {
return nil, errors.Wrap(err, "could not read LongTermReferenceFlag")
}
d.LongTermReferenceFlag = b == 1
} else {
b, err := br.ReadBits(1)
if err != nil {
return nil, errors.Wrap(err, "could not read AdaptiveRefPicMarkingModeFlag")
}
d.AdaptiveRefPicMarkingModeFlag = b == 1
if d.AdaptiveRefPicMarkingModeFlag {
d.MemoryManagementControlOperation, err = readUe(br)
if err != nil {
return nil, errors.Wrap(err, "could not parse MemoryManagementControlOperation")
}
for d.MemoryManagementControlOperation != 0 {
if d.MemoryManagementControlOperation == 1 || d.MemoryManagementControlOperation == 3 {
d.DifferenceOfPicNumsMinus1, err = readUe(br)
if err != nil {
return nil, errors.Wrap(err, "could not parse MemoryManagementControlOperation")
}
}
if d.MemoryManagementControlOperation == 2 {
h.RefPicListModification.LongTermPicNum, err = readUe(br)
if err != nil {
return nil, errors.Wrap(err, "could not parse LongTermPicNum")
}
}
if d.MemoryManagementControlOperation == 3 || d.MemoryManagementControlOperation == 6 {
d.LongTermFrameIdx, err = readUe(br)
if err != nil {
return nil, errors.Wrap(err, "could not parse LongTermFrameIdx")
}
}
if d.MemoryManagementControlOperation == 4 {
d.MaxLongTermFrameIdxPlus1, err = readUe(br)
if err != nil {
return nil, errors.Wrap(err, "could not parse MaxLongTermFrameIdxPlus1")
}
}
}
}
}
return d, nil
}
type SliceHeader struct {
FirstMbInSlice int
SliceType int
PPSID int
ColorPlaneID int
FrameNum int
FieldPic bool
BottomField bool
IDRPicID int
PicOrderCntLsb int
DeltaPicOrderCntBottom int
DeltaPicOrderCnt []int
RedundantPicCnt int
DirectSpatialMvPred bool
NumRefIdxActiveOverride bool
NumRefIdxL0ActiveMinus1 int
NumRefIdxL1ActiveMinus1 int
*RefPicListModification
*PredWeightTable
*DecRefPicMarking
CabacInit int
SliceQpDelta int
SpForSwitch bool
SliceQsDelta int
DisableDeblockingFilter int
SliceAlphaC0OffsetDiv2 int
SliceBetaOffsetDiv2 int
SliceGroupChangeCycle int
}
type SliceData struct { type SliceData struct {
BitReader *bits.BitReader BitReader *bits.BitReader
CabacAlignmentOneBit int CabacAlignmentOneBit int
@ -1075,229 +1345,24 @@ 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 {
// 7.3.3.1 header.RefPicListModification, err = NewRefPicListModification(br, &header)
if header.SliceType%5 != 2 && header.SliceType%5 != 4 { if err != nil {
b, err := br.ReadBits(1) return nil, errors.Wrap(err, "could not parse RefPicListModification")
if err != nil {
return nil, errors.Wrap(err, "could not read RefPicListModificationFlagL0")
}
header.RefPicListModificationFlagL0 = b == 1
if header.RefPicListModificationFlagL0 {
for header.ModificationOfPicNums != 3 {
header.ModificationOfPicNums, err = readUe(br)
if err != nil {
return nil, errors.Wrap(err, "could not parse ModificationOfPicNums")
}
if header.ModificationOfPicNums == 0 || header.ModificationOfPicNums == 1 {
header.AbsDiffPicNumMinus1, err = readUe(br)
if err != nil {
return nil, errors.Wrap(err, "could not parse AbsDiffPicNumMinus1")
}
} else if header.ModificationOfPicNums == 2 {
header.LongTermPicNum, err = readUe(br)
if err != nil {
return nil, errors.Wrap(err, "could not parse LongTermPicNum")
}
}
}
}
} }
if header.SliceType%5 == 1 {
b, err := br.ReadBits(1)
if err != nil {
return nil, errors.Wrap(err, "could not read RefPicListModificationFlagL1")
}
header.RefPicListModificationFlagL1 = b == 1
if header.RefPicListModificationFlagL1 {
for header.ModificationOfPicNums != 3 {
header.ModificationOfPicNums, err = readUe(br)
if err != nil {
return nil, errors.Wrap(err, "could not parse ModificationOfPicNums")
}
if header.ModificationOfPicNums == 0 || header.ModificationOfPicNums == 1 {
header.AbsDiffPicNumMinus1, err = readUe(br)
if err != nil {
return nil, errors.Wrap(err, "could not parse AbsDiffPicNumMinus1")
}
} else if header.ModificationOfPicNums == 2 {
header.LongTermPicNum, err = readUe(br)
if err != nil {
return nil, errors.Wrap(err, "could not parse LongTermPicNum")
}
}
}
}
}
// 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") {
// predWeightTable() header.PredWeightTable, err = NewPredWeightTable(br, &header)
header.LumaLog2WeightDenom, err = readUe(br)
if err != nil { if err != nil {
return nil, errors.Wrap(err, "could not parse LumaLog2WeightDenom") return nil, errors.Wrap(err, "could not parse PredWeightTable")
} }
}
if header.ChromaArrayType != 0 {
header.ChromaLog2WeightDenom, err = readUe(br)
if err != nil {
return nil, errors.Wrap(err, "could not parse ChromaLog2WeightDenom")
}
}
for i := 0; i <= header.NumRefIdxL0ActiveMinus1; i++ {
b, err := br.ReadBits(1)
if err != nil {
return nil, errors.Wrap(err, "could not read LumaWeightL0Flag")
}
header.LumaWeightL0Flag = b == 1
if header.LumaWeightL0Flag {
se, err := readSe(br)
if err != nil {
return nil, errors.Wrap(err, "could not parse LumaWeightL0")
}
header.LumaWeightL0 = append(header.LumaWeightL0, se)
se, err = readSe(br)
if err != nil {
return nil, errors.Wrap(err, "could not parse LumaOffsetL0")
}
header.LumaOffsetL0 = append(header.LumaOffsetL0, se)
}
if header.ChromaArrayType != 0 {
b, err := br.ReadBits(1)
if err != nil {
return nil, errors.Wrap(err, "could not read ChromaWeightL0Flag")
}
header.ChromaWeightL0Flag = b == 1
if header.ChromaWeightL0Flag {
header.ChromaWeightL0 = append(header.ChromaWeightL0, []int{})
header.ChromaOffsetL0 = append(header.ChromaOffsetL0, []int{})
for j := 0; j < 2; j++ {
se, err := readSe(br)
if err != nil {
return nil, errors.Wrap(err, "could not parse ChromaWeightL0")
}
header.ChromaWeightL0[i] = append(header.ChromaWeightL0[i], se)
se, err = readSe(br)
if err != nil {
return nil, errors.Wrap(err, "could not parse ChromaOffsetL0")
}
header.ChromaOffsetL0[i] = append(header.ChromaOffsetL0[i], se)
}
}
}
}
if header.SliceType%5 == 1 {
for i := 0; i <= header.NumRefIdxL1ActiveMinus1; i++ {
b, err := br.ReadBits(1)
if err != nil {
return nil, errors.Wrap(err, "could not read LumaWeightL1Flag")
}
header.LumaWeightL1Flag = b == 1
if header.LumaWeightL1Flag {
se, err := readSe(br)
if err != nil {
return nil, errors.Wrap(err, "could not parse LumaWeightL1")
}
header.LumaWeightL1 = append(header.LumaWeightL1, se)
se, err = readSe(br)
if err != nil {
return nil, errors.Wrap(err, "could not parse LumaOffsetL1")
}
header.LumaOffsetL1 = append(header.LumaOffsetL1, se)
}
if header.ChromaArrayType != 0 {
b, err := br.ReadBits(1)
if err != nil {
return nil, errors.Wrap(err, "could not read ChromaWeightL1Flag")
}
header.ChromaWeightL1Flag = b == 1
if header.ChromaWeightL1Flag {
header.ChromaWeightL1 = append(header.ChromaWeightL1, []int{})
header.ChromaOffsetL1 = append(header.ChromaOffsetL1, []int{})
for j := 0; j < 2; j++ {
se, err := readSe(br)
if err != nil {
return nil, errors.Wrap(err, "could not parse ChromaWeightL1")
}
header.ChromaWeightL1[i] = append(header.ChromaWeightL1[i], se)
se, err = readSe(br)
if err != nil {
return nil, errors.Wrap(err, "could not parse ChromaOffsetL1")
}
header.ChromaOffsetL1[i] = append(header.ChromaOffsetL1[i], se)
}
}
}
}
}
} // end predWeightTable
if nalUnit.RefIdc != 0 { if nalUnit.RefIdc != 0 {
// devRefPicMarking() // devRefPicMarking()
if idrPic { header.DecRefPicMarking, err = NewDecRefPicMarking(br, idrPic, &header)
b, err := br.ReadBits(1) if err != nil {
if err != nil { return nil, errors.Wrap(err, "could not parse DecRefPicMarking")
return nil, errors.Wrap(err, "could not read NoOutputOfPriorPicsFlag") }
}
header.NoOutputOfPriorPicsFlag = b == 1
b, err = br.ReadBits(1)
if err != nil {
return nil, errors.Wrap(err, "could not read LongTermReferenceFlag")
}
header.LongTermReferenceFlag = b == 1
} else {
b, err := br.ReadBits(1)
if err != nil {
return nil, errors.Wrap(err, "could not read AdaptiveRefPicMarkingModeFlag")
}
header.AdaptiveRefPicMarkingModeFlag = b == 1
if header.AdaptiveRefPicMarkingModeFlag {
header.MemoryManagementControlOperation, err = readUe(br)
if err != nil {
return nil, errors.Wrap(err, "could not parse MemoryManagementControlOperation")
}
for header.MemoryManagementControlOperation != 0 {
if header.MemoryManagementControlOperation == 1 || header.MemoryManagementControlOperation == 3 {
header.DifferenceOfPicNumsMinus1, err = readUe(br)
if err != nil {
return nil, errors.Wrap(err, "could not parse MemoryManagementControlOperation")
}
}
if header.MemoryManagementControlOperation == 2 {
header.LongTermPicNum, err = readUe(br)
if err != nil {
return nil, errors.Wrap(err, "could not parse LongTermPicNum")
}
}
if header.MemoryManagementControlOperation == 3 || header.MemoryManagementControlOperation == 6 {
header.LongTermFrameIdx, err = readUe(br)
if err != nil {
return nil, errors.Wrap(err, "could not parse LongTermFrameIdx")
}
}
if header.MemoryManagementControlOperation == 4 {
header.MaxLongTermFrameIdxPlus1, err = readUe(br)
if err != nil {
return nil, errors.Wrap(err, "could not parse MaxLongTermFrameIdxPlus1")
}
}
}
}
} // end decRefPicMarking
} }
if pps.EntropyCodingMode == 1 && sliceType != "I" && sliceType != "SI" { if pps.EntropyCodingMode == 1 && sliceType != "I" && sliceType != "SI" {
header.CabacInit, err = readUe(br) header.CabacInit, err = readUe(br)