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
Data *SliceData
}
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
CabacInit int
SliceQpDelta int
SpForSwitch bool
SliceQsDelta int
DisableDeblockingFilter int
SliceAlphaC0OffsetDiv2 int
SliceBetaOffsetDiv2 int
SliceGroupChangeCycle int
RefPicListModificationFlagL0 bool
ModificationOfPicNums int
AbsDiffPicNumMinus1 int
LongTermPicNum int
RefPicListModificationFlagL1 bool
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
// RefPicListModification provides elements of a ref_pic_list_modification syntax
// (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
}
// TODO: need to complete this.
// NewRefPicListMVCModification parses elements of a ref_pic_list_mvc_modification
// following the syntax structure defined in section H.7.3.3.1.1, and returns as
// a new RefPicListModification.
func NewRefPicListMVCModifiation(br *bits.BitReader) (*RefPicListModification, error) {
return nil, nil
}
// 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) {
r := &RefPicListModification{}
// 7.3.3.1
if h.SliceType%5 != 2 && h.SliceType%5 != 4 {
b, err := br.ReadBits(1)
if err != nil {
return nil, errors.Wrap(err, "could not read RefPicListModificationFlagL0")
}
r.RefPicListModificationFlagL0 = b == 1
if r.RefPicListModificationFlagL0 {
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")
}
}
}
}
}
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
LongTermReferenceFlag bool
AdaptiveRefPicMarkingModeFlag bool
@ -86,6 +266,96 @@ type SliceHeader struct {
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 {
BitReader *bits.BitReader
CabacAlignmentOneBit int
@ -1075,229 +1345,24 @@ func NewSliceContext(videoStream *VideoStream, nalUnit *NALUnit, rbsp []byte, sh
// H.7.3.3.1.1
// refPicListMvcModifications()
} else {
// 7.3.3.1
if header.SliceType%5 != 2 && header.SliceType%5 != 4 {
b, err := br.ReadBits(1)
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")
}
}
}
}
header.RefPicListModification, err = NewRefPicListModification(br, &header)
if err != nil {
return nil, errors.Wrap(err, "could not parse RefPicListModification")
}
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") {
// predWeightTable()
header.LumaLog2WeightDenom, err = readUe(br)
header.PredWeightTable, err = NewPredWeightTable(br, &header)
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 {
// devRefPicMarking()
if idrPic {
b, err := br.ReadBits(1)
if err != nil {
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
header.DecRefPicMarking, err = NewDecRefPicMarking(br, idrPic, &header)
if err != nil {
return nil, errors.Wrap(err, "could not parse DecRefPicMarking")
}
}
if pps.EntropyCodingMode == 1 && sliceType != "I" && sliceType != "SI" {
header.CabacInit, err = readUe(br)