diff --git a/codec/h264/h264dec/slice.go b/codec/h264/h264dec/slice.go index eaf0be79..5fa12c82 100644 --- a/codec/h264/h264dec/slice.go +++ b/codec/h264/h264dec/slice.go @@ -119,6 +119,141 @@ func NewRefPicListModification(br *bits.BitReader, h *SliceHeader) (*RefPicListM 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 +} + type SliceHeader struct { FirstMbInSlice int SliceType int @@ -136,24 +271,9 @@ type SliceHeader struct { NumRefIdxActiveOverride bool NumRefIdxL0ActiveMinus1 int NumRefIdxL1ActiveMinus1 int - RefPicListModification *RefPicListModification - // pred_weight_table - 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 + *PredWeightTable // dec_ref_pic_marking NoOutputOfPriorPicsFlag bool @@ -1170,113 +1290,11 @@ func NewSliceContext(videoStream *VideoStream, nalUnit *NalUnit, rbsp []byte, sh } 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 {