package h264dec import ( "bytes" "fmt" "math" "bitbucket.org/ausocean/av/codec/h264/h264dec/bits" "github.com/pkg/errors" ) // Chroma formats as defined in section 6.2, tab 6-1. const ( chromaMonochrome = iota chroma420 chroma422 chroma444 ) type VideoStream struct { SPS *SPS PPS *PPS Slices []*SliceContext } type SliceContext struct { *NALUnit *SPS *PPS *Slice } type Slice struct { Header *SliceHeader Data *SliceData } // 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 MemoryManagementControlOperation int DifferenceOfPicNumsMinus1 int LongTermFrameIdx 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 { BitReader *bits.BitReader CabacAlignmentOneBit int MbSkipRun int MbSkipFlag bool MbFieldDecodingFlag bool EndOfSliceFlag bool MbType int MbTypeName string SliceTypeName string PcmAlignmentZeroBit int PcmSampleLuma []int PcmSampleChroma []int TransformSize8x8Flag bool CodedBlockPattern int MbQpDelta int PrevIntra4x4PredModeFlag []int RemIntra4x4PredMode []int PrevIntra8x8PredModeFlag []int RemIntra8x8PredMode []int IntraChromaPredMode int RefIdxL0 []int RefIdxL1 []int MvdL0 [][][]int MvdL1 [][][]int } // Table 7-6 var sliceTypeMap = map[int]string{ 0: "P", 1: "B", 2: "I", 3: "SP", 4: "SI", 5: "P", 6: "B", 7: "I", 8: "SP", 9: "SI", } func flagVal(b bool) int { if b { return 1 } return 0 } // context-adaptive arithmetic entropy-coded element (CABAC) // 9.3 // When parsing the slice date of a slice (7.3.4) the initialization is 9.3.1 func (d SliceData) ae(v int) int { // 9.3.1.1 : CABAC context initialization ctxIdx return 0 } // 8.2.2 func MbToSliceGroupMap(sps *SPS, pps *PPS, header *SliceHeader) []int { mbaffFrameFlag := 0 if sps.MBAdaptiveFrameField && !header.FieldPic { mbaffFrameFlag = 1 } mapUnitToSliceGroupMap := MapUnitToSliceGroupMap(sps, pps, header) mbToSliceGroupMap := []int{} for i := 0; i <= PicSizeInMbs(sps, header)-1; i++ { if sps.FrameMbsOnly || header.FieldPic { mbToSliceGroupMap = append(mbToSliceGroupMap, mapUnitToSliceGroupMap[i]) continue } if mbaffFrameFlag == 1 { mbToSliceGroupMap = append(mbToSliceGroupMap, mapUnitToSliceGroupMap[i/2]) continue } if !sps.FrameMbsOnly && !sps.MBAdaptiveFrameField && !header.FieldPic { mbToSliceGroupMap = append( mbToSliceGroupMap, mapUnitToSliceGroupMap[(i/(2*PicWidthInMbs(sps)))*PicWidthInMbs(sps)+(i%PicWidthInMbs(sps))]) } } return mbToSliceGroupMap } func PicWidthInMbs(sps *SPS) int { return sps.PicWidthInMbsMinus1 + 1 } func PicHeightInMapUnits(sps *SPS) int { return sps.PicHeightInMapUnitsMinus1 + 1 } func PicSizeInMapUnits(sps *SPS) int { return PicWidthInMbs(sps) * PicHeightInMapUnits(sps) } func FrameHeightInMbs(sps *SPS) int { return (2 - flagVal(sps.FrameMbsOnly)) * PicHeightInMapUnits(sps) } func PicHeightInMbs(sps *SPS, header *SliceHeader) int { return FrameHeightInMbs(sps) / (1 + flagVal(header.FieldPic)) } func PicSizeInMbs(sps *SPS, header *SliceHeader) int { return PicWidthInMbs(sps) * PicHeightInMbs(sps, header) } // table 6-1 func SubWidthC(sps *SPS) int { n := 17 if sps.UseSeparateColorPlane { if sps.ChromaFormat == chroma444 { return n } } switch sps.ChromaFormat { case chromaMonochrome: return n case chroma420: n = 2 case chroma422: n = 2 case chroma444: n = 1 } return n } func SubHeightC(sps *SPS) int { n := 17 if sps.UseSeparateColorPlane { if sps.ChromaFormat == chroma444 { return n } } switch sps.ChromaFormat { case chromaMonochrome: return n case chroma420: n = 2 case chroma422: n = 1 case chroma444: n = 1 } return n } // 7-36 func CodedBlockPatternLuma(data *SliceData) int { return data.CodedBlockPattern % 16 } func CodedBlockPatternChroma(data *SliceData) int { return data.CodedBlockPattern / 16 } // dependencyId see Annex G.8.8.1 // Also G7.3.1.1 nal_unit_header_svc_extension func DQId(nalUnit *NALUnit) int { return int((nalUnit.SVCExtension.DependencyID << 4)) + int(nalUnit.SVCExtension.QualityID) } // Annex G p527 func NumMbPart(nalUnit *NALUnit, sps *SPS, header *SliceHeader, data *SliceData) int { sliceType := sliceTypeMap[header.SliceType] numMbPart := 0 if MbTypeName(sliceType, CurrMbAddr(sps, header)) == "B_SKIP" || MbTypeName(sliceType, CurrMbAddr(sps, header)) == "B_Direct_16x16" { if DQId(nalUnit) == 0 && nalUnit.Type != 20 { numMbPart = 4 } else if DQId(nalUnit) > 0 && nalUnit.Type == 20 { numMbPart = 1 } } else if MbTypeName(sliceType, CurrMbAddr(sps, header)) != "B_SKIP" && MbTypeName(sliceType, CurrMbAddr(sps, header)) != "B_Direct_16x16" { numMbPart = CurrMbAddr(sps, header) } return numMbPart } func MbPred(sliceContext *SliceContext, br *bits.BitReader, rbsp []byte) error { var cabac *CABAC sliceType := sliceTypeMap[sliceContext.Slice.Header.SliceType] mbPartPredMode, err := MbPartPredMode(sliceContext.Slice.Data, sliceType, sliceContext.Slice.Data.MbType, 0) if err != nil { return errors.Wrap(err, "could not get mbPartPredMode") } if mbPartPredMode == intra4x4 || mbPartPredMode == intra8x8 || mbPartPredMode == intra16x16 { if mbPartPredMode == intra4x4 { for luma4x4BlkIdx := 0; luma4x4BlkIdx < 16; luma4x4BlkIdx++ { var v int if sliceContext.PPS.EntropyCodingMode == 1 { // TODO: 1 bit or ae(v) binarization := NewBinarization( "PrevIntra4x4PredModeFlag", sliceContext.Slice.Data) binarization.Decode(sliceContext, br, rbsp) cabac = initCabac(binarization, sliceContext) _ = cabac logger.Printf("TODO: ae for PevIntra4x4PredModeFlag[%d]\n", luma4x4BlkIdx) } else { b, err := br.ReadBits(1) if err != nil { return errors.Wrap(err, "could not read PrevIntra4x4PredModeFlag") } v = int(b) } sliceContext.Slice.Data.PrevIntra4x4PredModeFlag = append( sliceContext.Slice.Data.PrevIntra4x4PredModeFlag, v) if sliceContext.Slice.Data.PrevIntra4x4PredModeFlag[luma4x4BlkIdx] == 0 { if sliceContext.PPS.EntropyCodingMode == 1 { // TODO: 3 bits or ae(v) binarization := NewBinarization( "RemIntra4x4PredMode", sliceContext.Slice.Data) binarization.Decode(sliceContext, br, rbsp) logger.Printf("TODO: ae for RemIntra4x4PredMode[%d]\n", luma4x4BlkIdx) } else { b, err := br.ReadBits(3) if err != nil { return errors.Wrap(err, "could not read RemIntra4x4PredMode") } v = int(b) } if len(sliceContext.Slice.Data.RemIntra4x4PredMode) < luma4x4BlkIdx { sliceContext.Slice.Data.RemIntra4x4PredMode = append( sliceContext.Slice.Data.RemIntra4x4PredMode, make([]int, luma4x4BlkIdx-len(sliceContext.Slice.Data.RemIntra4x4PredMode)+1)...) } sliceContext.Slice.Data.RemIntra4x4PredMode[luma4x4BlkIdx] = v } } } if mbPartPredMode == intra8x8 { for luma8x8BlkIdx := 0; luma8x8BlkIdx < 4; luma8x8BlkIdx++ { sliceContext.Update(sliceContext.Slice.Header, sliceContext.Slice.Data) var v int if sliceContext.PPS.EntropyCodingMode == 1 { // TODO: 1 bit or ae(v) binarization := NewBinarization("PrevIntra8x8PredModeFlag", sliceContext.Slice.Data) binarization.Decode(sliceContext, br, rbsp) logger.Printf("TODO: ae for PrevIntra8x8PredModeFlag[%d]\n", luma8x8BlkIdx) } else { b, err := br.ReadBits(1) if err != nil { return errors.Wrap(err, "could not read PrevIntra8x8PredModeFlag") } v = int(b) } sliceContext.Slice.Data.PrevIntra8x8PredModeFlag = append( sliceContext.Slice.Data.PrevIntra8x8PredModeFlag, v) if sliceContext.Slice.Data.PrevIntra8x8PredModeFlag[luma8x8BlkIdx] == 0 { if sliceContext.PPS.EntropyCodingMode == 1 { // TODO: 3 bits or ae(v) binarization := NewBinarization( "RemIntra8x8PredMode", sliceContext.Slice.Data) binarization.Decode(sliceContext, br, rbsp) logger.Printf("TODO: ae for RemIntra8x8PredMode[%d]\n", luma8x8BlkIdx) } else { b, err := br.ReadBits(3) if err != nil { return errors.Wrap(err, "could not read RemIntra8x8PredMode") } v = int(b) } if len(sliceContext.Slice.Data.RemIntra8x8PredMode) < luma8x8BlkIdx { sliceContext.Slice.Data.RemIntra8x8PredMode = append( sliceContext.Slice.Data.RemIntra8x8PredMode, make([]int, luma8x8BlkIdx-len(sliceContext.Slice.Data.RemIntra8x8PredMode)+1)...) } sliceContext.Slice.Data.RemIntra8x8PredMode[luma8x8BlkIdx] = v } } } if sliceContext.Slice.Header.ChromaArrayType == 1 || sliceContext.Slice.Header.ChromaArrayType == 2 { if sliceContext.PPS.EntropyCodingMode == 1 { // TODO: ue(v) or ae(v) binarization := NewBinarization( "IntraChromaPredMode", sliceContext.Slice.Data) binarization.Decode(sliceContext, br, rbsp) logger.Printf("TODO: ae for IntraChromaPredMode\n") } else { var err error sliceContext.Slice.Data.IntraChromaPredMode, err = readUe(br) if err != nil { return errors.Wrap(err, "could not parse IntraChromaPredMode") } } } } else if mbPartPredMode != direct { for mbPartIdx := 0; mbPartIdx < NumMbPart(sliceContext.NALUnit, sliceContext.SPS, sliceContext.Slice.Header, sliceContext.Slice.Data); mbPartIdx++ { sliceContext.Update(sliceContext.Slice.Header, sliceContext.Slice.Data) m, err := MbPartPredMode(sliceContext.Slice.Data, sliceType, sliceContext.Slice.Data.MbType, mbPartIdx) if err != nil { return errors.Wrap(err, fmt.Sprintf("could not get mbPartPredMode for loop 1 mbPartIdx: %d", mbPartIdx)) } if (sliceContext.Slice.Header.NumRefIdxL0ActiveMinus1 > 0 || sliceContext.Slice.Data.MbFieldDecodingFlag != sliceContext.Slice.Header.FieldPic) && m != predL1 { logger.Printf("\tTODO: refIdxL0[%d] te or ae(v)\n", mbPartIdx) if len(sliceContext.Slice.Data.RefIdxL0) < mbPartIdx { sliceContext.Slice.Data.RefIdxL0 = append( sliceContext.Slice.Data.RefIdxL0, make([]int, mbPartIdx-len(sliceContext.Slice.Data.RefIdxL0)+1)...) } if sliceContext.PPS.EntropyCodingMode == 1 { // TODO: te(v) or ae(v) binarization := NewBinarization( "RefIdxL0", sliceContext.Slice.Data) binarization.Decode(sliceContext, br, rbsp) logger.Printf("TODO: ae for RefIdxL0[%d]\n", mbPartIdx) } else { // TODO: Only one reference picture is used for inter-prediction, // then the value should be 0 if MbaffFrameFlag(sliceContext.SPS, sliceContext.Slice.Header) == 0 || !sliceContext.Slice.Data.MbFieldDecodingFlag { sliceContext.Slice.Data.RefIdxL0[mbPartIdx], _ = readTe( br, uint(sliceContext.Slice.Header.NumRefIdxL0ActiveMinus1)) } else { rangeMax := 2*sliceContext.Slice.Header.NumRefIdxL0ActiveMinus1 + 1 sliceContext.Slice.Data.RefIdxL0[mbPartIdx], _ = readTe( br, uint(rangeMax)) } } } } for mbPartIdx := 0; mbPartIdx < NumMbPart(sliceContext.NALUnit, sliceContext.SPS, sliceContext.Slice.Header, sliceContext.Slice.Data); mbPartIdx++ { m, err := MbPartPredMode(sliceContext.Slice.Data, sliceType, sliceContext.Slice.Data.MbType, mbPartIdx) if err != nil { return errors.Wrap(err, fmt.Sprintf("could not get mbPartPredMode for loop 2 mbPartIdx: %d", mbPartIdx)) } if m != predL1 { for compIdx := 0; compIdx < 2; compIdx++ { if len(sliceContext.Slice.Data.MvdL0) < mbPartIdx { sliceContext.Slice.Data.MvdL0 = append( sliceContext.Slice.Data.MvdL0, make([][][]int, mbPartIdx-len(sliceContext.Slice.Data.MvdL0)+1)...) } if len(sliceContext.Slice.Data.MvdL0[mbPartIdx][0]) < compIdx { sliceContext.Slice.Data.MvdL0[mbPartIdx][0] = append( sliceContext.Slice.Data.MvdL0[mbPartIdx][0], make([]int, compIdx-len(sliceContext.Slice.Data.MvdL0[mbPartIdx][0])+1)...) } if sliceContext.PPS.EntropyCodingMode == 1 { // TODO: se(v) or ae(v) if compIdx == 0 { binarization := NewBinarization( "MvdLnEnd0", sliceContext.Slice.Data) binarization.Decode(sliceContext, br, rbsp) } else if compIdx == 1 { binarization := NewBinarization( "MvdLnEnd1", sliceContext.Slice.Data) binarization.Decode(sliceContext, br, rbsp) } logger.Printf("TODO: ae for MvdL0[%d][0][%d]\n", mbPartIdx, compIdx) } else { sliceContext.Slice.Data.MvdL0[mbPartIdx][0][compIdx], _ = readSe(br) } } } } for mbPartIdx := 0; mbPartIdx < NumMbPart(sliceContext.NALUnit, sliceContext.SPS, sliceContext.Slice.Header, sliceContext.Slice.Data); mbPartIdx++ { sliceContext.Update(sliceContext.Slice.Header, sliceContext.Slice.Data) m, err := MbPartPredMode(sliceContext.Slice.Data, sliceType, sliceContext.Slice.Data.MbType, mbPartIdx) if err != nil { return errors.Wrap(err, fmt.Sprintf("could not get mbPartPredMode for loop 3 mbPartIdx: %d", mbPartIdx)) } if m != predL0 { for compIdx := 0; compIdx < 2; compIdx++ { if len(sliceContext.Slice.Data.MvdL1) < mbPartIdx { sliceContext.Slice.Data.MvdL1 = append( sliceContext.Slice.Data.MvdL1, make([][][]int, mbPartIdx-len(sliceContext.Slice.Data.MvdL1)+1)...) } if len(sliceContext.Slice.Data.MvdL1[mbPartIdx][0]) < compIdx { sliceContext.Slice.Data.MvdL1[mbPartIdx][0] = append( sliceContext.Slice.Data.MvdL0[mbPartIdx][0], make([]int, compIdx-len(sliceContext.Slice.Data.MvdL1[mbPartIdx][0])+1)...) } if sliceContext.PPS.EntropyCodingMode == 1 { if compIdx == 0 { binarization := NewBinarization( "MvdLnEnd0", sliceContext.Slice.Data) binarization.Decode(sliceContext, br, rbsp) } else if compIdx == 1 { binarization := NewBinarization( "MvdLnEnd1", sliceContext.Slice.Data) binarization.Decode(sliceContext, br, rbsp) } // TODO: se(v) or ae(v) logger.Printf("TODO: ae for MvdL1[%d][0][%d]\n", mbPartIdx, compIdx) } else { sliceContext.Slice.Data.MvdL1[mbPartIdx][0][compIdx], _ = readSe(br) } } } } } return nil } // 8.2.2.1 func MapUnitToSliceGroupMap(sps *SPS, pps *PPS, header *SliceHeader) []int { mapUnitToSliceGroupMap := []int{} picSizeInMapUnits := PicSizeInMapUnits(sps) if pps.NumSliceGroupsMinus1 == 0 { // 0 to PicSizeInMapUnits -1 inclusive for i := 0; i <= picSizeInMapUnits-1; i++ { mapUnitToSliceGroupMap = append(mapUnitToSliceGroupMap, 0) } } else { switch pps.SliceGroupMapType { case 0: // 8.2.2.1 i := 0 for i < picSizeInMapUnits { // iGroup should be incremented in the pps.RunLengthMinus1 index operation. There may be a bug here for iGroup := 0; iGroup <= pps.NumSliceGroupsMinus1 && i < picSizeInMapUnits; i += pps.RunLengthMinus1[iGroup+1] + 1 { for j := 0; j < pps.RunLengthMinus1[iGroup] && i+j < picSizeInMapUnits; j++ { if len(mapUnitToSliceGroupMap) < i+j { mapUnitToSliceGroupMap = append( mapUnitToSliceGroupMap, make([]int, (i+j)-len(mapUnitToSliceGroupMap)+1)...) } mapUnitToSliceGroupMap[i+j] = iGroup } } } case 1: // 8.2.2.2 for i := 0; i < picSizeInMapUnits; i++ { v := ((i % PicWidthInMbs(sps)) + (((i / PicWidthInMbs(sps)) * (pps.NumSliceGroupsMinus1 + 1)) / 2)) % (pps.NumSliceGroupsMinus1 + 1) mapUnitToSliceGroupMap = append(mapUnitToSliceGroupMap, v) } case 2: // 8.2.2.3 for i := 0; i < picSizeInMapUnits; i++ { mapUnitToSliceGroupMap = append(mapUnitToSliceGroupMap, pps.NumSliceGroupsMinus1) } for iGroup := pps.NumSliceGroupsMinus1 - 1; iGroup >= 0; iGroup-- { yTopLeft := pps.TopLeft[iGroup] / PicWidthInMbs(sps) xTopLeft := pps.TopLeft[iGroup] % PicWidthInMbs(sps) yBottomRight := pps.BottomRight[iGroup] / PicWidthInMbs(sps) xBottomRight := pps.BottomRight[iGroup] % PicWidthInMbs(sps) for y := yTopLeft; y <= yBottomRight; y++ { for x := xTopLeft; x <= xBottomRight; x++ { idx := y*PicWidthInMbs(sps) + x if len(mapUnitToSliceGroupMap) < idx { mapUnitToSliceGroupMap = append( mapUnitToSliceGroupMap, make([]int, idx-len(mapUnitToSliceGroupMap)+1)...) mapUnitToSliceGroupMap[idx] = iGroup } } } } case 3: // 8.2.2.4 // TODO case 4: // 8.2.2.5 // TODO case 5: // 8.2.2.6 // TODO case 6: // 8.2.2.7 // TODO } } // 8.2.2.8 // Convert mapUnitToSliceGroupMap to MbToSliceGroupMap return mapUnitToSliceGroupMap } func nextMbAddress(n int, sps *SPS, pps *PPS, header *SliceHeader) int { i := n + 1 // picSizeInMbs is the number of macroblocks in picture 0 // 7-13 // PicWidthInMbs = sps.PicWidthInMbsMinus1 + 1 // PicHeightInMapUnits = sps.PicHeightInMapUnitsMinus1 + 1 // 7-29 // picSizeInMbs = PicWidthInMbs * PicHeightInMbs // 7-26 // PicHeightInMbs = FrameHeightInMbs / (1 + header.fieldPicFlag) // 7-18 // FrameHeightInMbs = (2 - ps.FrameMbsOnly) * PicHeightInMapUnits picWidthInMbs := sps.PicWidthInMbsMinus1 + 1 picHeightInMapUnits := sps.PicHeightInMapUnitsMinus1 + 1 frameHeightInMbs := (2 - flagVal(sps.FrameMbsOnly)) * picHeightInMapUnits picHeightInMbs := frameHeightInMbs / (1 + flagVal(header.FieldPic)) picSizeInMbs := picWidthInMbs * picHeightInMbs mbToSliceGroupMap := MbToSliceGroupMap(sps, pps, header) for i < picSizeInMbs && mbToSliceGroupMap[i] != mbToSliceGroupMap[i] { i++ } return i } func CurrMbAddr(sps *SPS, header *SliceHeader) int { mbaffFrameFlag := 0 if sps.MBAdaptiveFrameField && !header.FieldPic { mbaffFrameFlag = 1 } return header.FirstMbInSlice * (1 * mbaffFrameFlag) } func MbaffFrameFlag(sps *SPS, header *SliceHeader) int { if sps.MBAdaptiveFrameField && !header.FieldPic { return 1 } return 0 } func NewSliceData(sliceContext *SliceContext, br *bits.BitReader) (*SliceData, error) { var cabac *CABAC var err error sliceContext.Slice.Data = &SliceData{BitReader: br} // TODO: Why is this being initialized here? // initCabac(sliceContext) if sliceContext.PPS.EntropyCodingMode == 1 { for !br.ByteAligned() { b, err := br.ReadBits(1) if err != nil { return nil, errors.Wrap(err, "could not read CabacAlignmentOneBit") } sliceContext.Slice.Data.CabacAlignmentOneBit = int(b) } } mbaffFrameFlag := 0 if sliceContext.SPS.MBAdaptiveFrameField && !sliceContext.Slice.Header.FieldPic { mbaffFrameFlag = 1 } currMbAddr := sliceContext.Slice.Header.FirstMbInSlice * (1 * mbaffFrameFlag) moreDataFlag := true prevMbSkipped := 0 sliceContext.Slice.Data.SliceTypeName = sliceTypeMap[sliceContext.Slice.Header.SliceType] sliceContext.Slice.Data.MbTypeName = MbTypeName(sliceContext.Slice.Data.SliceTypeName, sliceContext.Slice.Data.MbType) logger.Printf("debug: \tSliceData: Processing moreData: %v\n", moreDataFlag) for moreDataFlag { logger.Printf("debug: \tLooking for more sliceContext.Slice.Data in slice type %s\n", sliceContext.Slice.Data.SliceTypeName) if sliceContext.Slice.Data.SliceTypeName != "I" && sliceContext.Slice.Data.SliceTypeName != "SI" { logger.Printf("debug: \tNonI/SI slice, processing moreData\n") if sliceContext.PPS.EntropyCodingMode == 0 { sliceContext.Slice.Data.MbSkipRun, err = readUe(br) if err != nil { return nil, errors.Wrap(err, "could not parse MbSkipRun") } if sliceContext.Slice.Data.MbSkipRun > 0 { prevMbSkipped = 1 } for i := 0; i < sliceContext.Slice.Data.MbSkipRun; i++ { // nextMbAddress(currMbAdd currMbAddr = nextMbAddress(currMbAddr, sliceContext.SPS, sliceContext.PPS, sliceContext.Slice.Header) } if sliceContext.Slice.Data.MbSkipRun > 0 { moreDataFlag = moreRBSPData(br) } } else { b, err := br.ReadBits(1) if err != nil { return nil, errors.Wrap(err, "could not read MbSkipFlag") } sliceContext.Slice.Data.MbSkipFlag = b == 1 moreDataFlag = !sliceContext.Slice.Data.MbSkipFlag } } if moreDataFlag { if mbaffFrameFlag == 1 && (currMbAddr%2 == 0 || (currMbAddr%2 == 1 && prevMbSkipped == 1)) { if sliceContext.PPS.EntropyCodingMode == 1 { // TODO: ae implementation binarization := NewBinarization("MbFieldDecodingFlag", sliceContext.Slice.Data) // TODO: this should take a BitReader where the nil is. binarization.Decode(sliceContext, br, nil) logger.Printf("TODO: ae for MbFieldDecodingFlag\n") } else { b, err := br.ReadBits(1) if err != nil { return nil, errors.Wrap(err, "could not read MbFieldDecodingFlag") } sliceContext.Slice.Data.MbFieldDecodingFlag = b == 1 } } // BEGIN: macroblockLayer() if sliceContext.PPS.EntropyCodingMode == 1 { // TODO: ae implementation binarization := NewBinarization("MbType", sliceContext.Slice.Data) cabac = initCabac(binarization, sliceContext) _ = cabac // TODO: remove bytes parameter from this function. binarization.Decode(sliceContext, br, nil) if binarization.PrefixSuffix { logger.Printf("debug: MBType binarization has prefix and suffix\n") } bits := []int{} for binIdx := 0; binarization.IsBinStringMatch(bits); binIdx++ { newBit, err := br.ReadBits(1) if err != nil { return nil, errors.Wrap(err, "could not read bit") } if binarization.UseDecodeBypass == 1 { // DecodeBypass logger.Printf("TODO: decodeBypass is set: 9.3.3.2.3") codIRange, codIOffset, err := initDecodingEngine(sliceContext.Slice.Data.BitReader) if err != nil { return nil, errors.Wrap(err, "could not initialise decoding engine") } // Initialize the decoder // TODO: When should the suffix of MaxBinIdxCtx be used and when just the prefix? // TODO: When should the suffix of CtxIdxOffset be used? arithmeticDecoder, err := NewArithmeticDecoding( sliceContext, binarization, CtxIdx( binarization.binIdx, binarization.MaxBinIdxCtx.Prefix, binarization.CtxIdxOffset.Prefix, ), codIRange, codIOffset, ) if err != nil { return nil, errors.Wrap(err, "error from NewArithmeticDecoding") } // Bypass decoding codIOffset, _, err = arithmeticDecoder.DecodeBypass( sliceContext.Slice.Data, codIRange, codIOffset, ) if err != nil { return nil, errors.Wrap(err, "could not DecodeBypass") } // End DecodeBypass } else { // DO 9.3.3.1 ctxIdx := CtxIdx( binIdx, binarization.MaxBinIdxCtx.Prefix, binarization.CtxIdxOffset.Prefix) if binarization.MaxBinIdxCtx.IsPrefixSuffix { logger.Printf("TODO: Handle PrefixSuffix binarization\n") } logger.Printf("debug: MBType ctxIdx for %d is %d\n", binIdx, ctxIdx) // Then 9.3.3.2 codIRange, codIOffset, err := initDecodingEngine(br) if err != nil { return nil, errors.Wrap(err, "error from initDecodingEngine") } logger.Printf("debug: coding engine initialized: %d/%d\n", codIRange, codIOffset) } bits = append(bits, int(newBit)) } logger.Printf("TODO: ae for MBType\n") } else { sliceContext.Slice.Data.MbType, err = readUe(br) if err != nil { return nil, errors.Wrap(err, "could not parse MbType") } } if sliceContext.Slice.Data.MbTypeName == "I_PCM" { for !br.ByteAligned() { _, err := br.ReadBits(1) if err != nil { return nil, errors.Wrap(err, "could not read PCMAlignmentZeroBit") } } // 7-3 p95 bitDepthY := 8 + sliceContext.SPS.BitDepthLumaMinus8 for i := 0; i < 256; i++ { s, err := br.ReadBits(bitDepthY) if err != nil { return nil, errors.Wrap(err, fmt.Sprintf("could not read PcmSampleLuma[%d]", i)) } sliceContext.Slice.Data.PcmSampleLuma = append( sliceContext.Slice.Data.PcmSampleLuma, int(s)) } // 9.3.1 p 246 // cabac = initCabac(binarization, sliceContext) // 6-1 p 47 mbWidthC := 16 / SubWidthC(sliceContext.SPS) mbHeightC := 16 / SubHeightC(sliceContext.SPS) // if monochrome if sliceContext.SPS.ChromaFormat == chromaMonochrome || sliceContext.SPS.UseSeparateColorPlane { mbWidthC = 0 mbHeightC = 0 } bitDepthC := 8 + sliceContext.SPS.BitDepthChromaMinus8 for i := 0; i < 2*mbWidthC*mbHeightC; i++ { s, err := br.ReadBits(bitDepthC) if err != nil { return nil, errors.Wrap(err, fmt.Sprintf("could not read PcmSampleChroma[%d]", i)) } sliceContext.Slice.Data.PcmSampleChroma = append( sliceContext.Slice.Data.PcmSampleChroma, int(s)) } // 9.3.1 p 246 // cabac = initCabac(binarization, sliceContext) } else { noSubMbPartSizeLessThan8x8Flag := 1 m, err := MbPartPredMode(sliceContext.Slice.Data, sliceContext.Slice.Data.SliceTypeName, sliceContext.Slice.Data.MbType, 0) if err != nil { return nil, errors.Wrap(err, "could not get mbPartPredMode") } if sliceContext.Slice.Data.MbTypeName == "I_NxN" && m != intra16x16 && NumMbPart(sliceContext.NALUnit, sliceContext.SPS, sliceContext.Slice.Header, sliceContext.Slice.Data) == 4 { logger.Printf("\tTODO: subMbPred\n") /* subMbType := SubMbPred(sliceContext.Slice.Data.MbType) for mbPartIdx := 0; mbPartIdx < 4; mbPartIdx++ { if subMbType[mbPartIdx] != "B_Direct_8x8" { if NumbSubMbPart(subMbType[mbPartIdx]) > 1 { noSubMbPartSizeLessThan8x8Flag = 0 } } else if !sliceContext.SPS.Direct8x8Inference { noSubMbPartSizeLessThan8x8Flag = 0 } } */ } else { if sliceContext.PPS.Transform8x8Mode == 1 && sliceContext.Slice.Data.MbTypeName == "I_NxN" { // TODO // 1 bit or ae(v) // If sliceContext.PPS.EntropyCodingMode == 1, use ae(v) if sliceContext.PPS.EntropyCodingMode == 1 { binarization := NewBinarization("TransformSize8x8Flag", sliceContext.Slice.Data) cabac = initCabac(binarization, sliceContext) binarization.Decode(sliceContext, br, nil) logger.Println("TODO: ae(v) for TransformSize8x8Flag") } else { b, err := br.ReadBits(1) if err != nil { return nil, errors.Wrap(err, "could not read TransformSize8x8Flag") } sliceContext.Slice.Data.TransformSize8x8Flag = b == 1 } } // TODO: fix nil argument for. MbPred(sliceContext, br, nil) } m, err = MbPartPredMode(sliceContext.Slice.Data, sliceContext.Slice.Data.SliceTypeName, sliceContext.Slice.Data.MbType, 0) if err != nil { return nil, errors.Wrap(err, "could not get mbPartPredMode") } if m != intra16x16 { // TODO: me, ae logger.Printf("TODO: CodedBlockPattern pending me/ae implementation\n") if sliceContext.PPS.EntropyCodingMode == 1 { binarization := NewBinarization("CodedBlockPattern", sliceContext.Slice.Data) cabac = initCabac(binarization, sliceContext) // TODO: fix nil argument. binarization.Decode(sliceContext, br, nil) logger.Printf("TODO: ae for CodedBlockPattern\n") } else { me, _ := readMe( br, uint(sliceContext.Slice.Header.ChromaArrayType), // TODO: fix this //MbPartPredMode(sliceContext.Slice.Data, sliceContext.Slice.Data.SliceTypeName, sliceContext.Slice.Data.MbType, 0))) 0) sliceContext.Slice.Data.CodedBlockPattern = int(me) } // sliceContext.Slice.Data.CodedBlockPattern = me(v) | ae(v) if CodedBlockPatternLuma(sliceContext.Slice.Data) > 0 && sliceContext.PPS.Transform8x8Mode == 1 && sliceContext.Slice.Data.MbTypeName != "I_NxN" && noSubMbPartSizeLessThan8x8Flag == 1 && (sliceContext.Slice.Data.MbTypeName != "B_Direct_16x16" || sliceContext.SPS.Direct8x8Inference) { // TODO: 1 bit or ae(v) if sliceContext.PPS.EntropyCodingMode == 1 { binarization := NewBinarization("Transform8x8Flag", sliceContext.Slice.Data) cabac = initCabac(binarization, sliceContext) // TODO: fix nil argument. binarization.Decode(sliceContext, br, nil) logger.Printf("TODO: ae for TranformSize8x8Flag\n") } else { b, err := br.ReadBits(1) if err != nil { return nil, errors.Wrap(err, "coult not read TransformSize8x8Flag") } sliceContext.Slice.Data.TransformSize8x8Flag = b == 1 } } } m, err = MbPartPredMode(sliceContext.Slice.Data, sliceContext.Slice.Data.SliceTypeName, sliceContext.Slice.Data.MbType, 0) if err != nil { return nil, errors.Wrap(err, "could not get mbPartPredMode") } if CodedBlockPatternLuma(sliceContext.Slice.Data) > 0 || CodedBlockPatternChroma(sliceContext.Slice.Data) > 0 || m == intra16x16 { // TODO: se or ae(v) if sliceContext.PPS.EntropyCodingMode == 1 { binarization := NewBinarization("MbQpDelta", sliceContext.Slice.Data) cabac = initCabac(binarization, sliceContext) // TODO; fix nil argument binarization.Decode(sliceContext, br, nil) logger.Printf("TODO: ae for MbQpDelta\n") } else { sliceContext.Slice.Data.MbQpDelta, _ = readSe(br) } } } } // END MacroblockLayer if sliceContext.PPS.EntropyCodingMode == 0 { moreDataFlag = moreRBSPData(br) } else { if sliceContext.Slice.Data.SliceTypeName != "I" && sliceContext.Slice.Data.SliceTypeName != "SI" { if sliceContext.Slice.Data.MbSkipFlag { prevMbSkipped = 1 } else { prevMbSkipped = 0 } } if mbaffFrameFlag == 1 && currMbAddr%2 == 0 { moreDataFlag = true } else { // TODO: ae implementation b, err := br.ReadBits(1) if err != nil { return nil, errors.Wrap(err, "could not read EndOfSliceFlag") } sliceContext.Slice.Data.EndOfSliceFlag = b == 1 moreDataFlag = !sliceContext.Slice.Data.EndOfSliceFlag } } currMbAddr = nextMbAddress(currMbAddr, sliceContext.SPS, sliceContext.PPS, sliceContext.Slice.Header) } // END while moreDataFlag return sliceContext.Slice.Data, nil } func (c *SliceContext) Update(header *SliceHeader, data *SliceData) { c.Slice = &Slice{Header: header, Data: data} } func NewSliceContext(videoStream *VideoStream, nalUnit *NALUnit, rbsp []byte, showPacket bool) (*SliceContext, error) { var err error sps := videoStream.SPS pps := videoStream.PPS 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]) var idrPic bool if nalUnit.Type == 5 { idrPic = true } header := SliceHeader{} if sps.UseSeparateColorPlane { header.ChromaArrayType = 0 } else { header.ChromaArrayType = sps.ChromaFormat } br := bits.NewBitReader(bytes.NewReader(rbsp)) header.FirstMbInSlice, err = readUe(br) if err != nil { return nil, errors.Wrap(err, "could not parse FirstMbInSlice") } header.SliceType, err = readUe(br) if err != nil { return nil, errors.Wrap(err, "could not parse SliceType") } sliceType := sliceTypeMap[header.SliceType] logger.Printf("debug: %s (%s) slice of %d bytes\n", NALUnitType[int(nalUnit.Type)], sliceType, len(rbsp)) header.PPSID, err = readUe(br) if err != nil { return nil, errors.Wrap(err, "could not parse PPSID") } if sps.UseSeparateColorPlane { b, err := br.ReadBits(2) if err != nil { return nil, errors.Wrap(err, "could not read ColorPlaneID") } header.ColorPlaneID = int(b) } // TODO: See 7.4.3 // header.FrameNum = b.NextField("FrameNum", 0) if !sps.FrameMbsOnly { b, err := br.ReadBits(1) if err != nil { return nil, errors.Wrap(err, "could not read FieldPic") } header.FieldPic = b == 1 if header.FieldPic { b, err := br.ReadBits(1) if err != nil { return nil, errors.Wrap(err, "could not read BottomField") } header.BottomField = b == 1 } } if idrPic { header.IDRPicID, err = readUe(br) if err != nil { return nil, errors.Wrap(err, "could not parse IDRPicID") } } if sps.PicOrderCountType == 0 { b, err := br.ReadBits(sps.Log2MaxPicOrderCntLSBMin4 + 4) if err != nil { return nil, errors.Wrap(err, "could not read PicOrderCntLsb") } header.PicOrderCntLsb = int(b) if pps.BottomFieldPicOrderInFramePresent && !header.FieldPic { header.DeltaPicOrderCntBottom, err = readSe(br) if err != nil { return nil, errors.Wrap(err, "could not parse DeltaPicOrderCntBottom") } } } if sps.PicOrderCountType == 1 && !sps.DeltaPicOrderAlwaysZero { header.DeltaPicOrderCnt[0], err = readSe(br) if err != nil { return nil, errors.Wrap(err, "could not parse DeltaPicOrderCnt") } if pps.BottomFieldPicOrderInFramePresent && !header.FieldPic { header.DeltaPicOrderCnt[1], err = readSe(br) if err != nil { return nil, errors.Wrap(err, "could not parse DeltaPicOrderCnt") } } } if pps.RedundantPicCntPresent { header.RedundantPicCnt, err = readUe(br) if err != nil { return nil, errors.Wrap(err, "could not parse RedundantPicCnt") } } if sliceType == "B" { b, err := br.ReadBits(1) if err != nil { return nil, errors.Wrap(err, "could not read DirectSpatialMvPred") } header.DirectSpatialMvPred = b == 1 } if sliceType == "B" || sliceType == "SP" { b, err := br.ReadBits(1) if err != nil { return nil, errors.Wrap(err, "could not read NumRefIdxActiveOverride") } header.NumRefIdxActiveOverride = b == 1 if header.NumRefIdxActiveOverride { header.NumRefIdxL0ActiveMinus1, err = readUe(br) if err != nil { return nil, errors.Wrap(err, "could not parse NumRefIdxL0ActiveMinus1") } if sliceType == "B" { header.NumRefIdxL1ActiveMinus1, err = readUe(br) if err != nil { return nil, errors.Wrap(err, "could not parse NumRefIdxL1ActiveMinus1") } } } } if nalUnit.Type == 20 || nalUnit.Type == 21 { // Annex H // H.7.3.3.1.1 // refPicListMvcModifications() } else { header.RefPicListModification, err = NewRefPicListModification(br, &header) if err != nil { return nil, errors.Wrap(err, "could not parse RefPicListModification") } } if (pps.WeightedPred && (sliceType == "P" || sliceType == "SP")) || (pps.WeightedBipred == 1 && sliceType == "B") { header.PredWeightTable, err = NewPredWeightTable(br, &header) if err != nil { return nil, errors.Wrap(err, "could not parse PredWeightTable") } } if nalUnit.RefIdc != 0 { // devRefPicMarking() 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) if err != nil { return nil, errors.Wrap(err, "could not parse CabacInit") } } header.SliceQpDelta, err = readSe(br) if err != nil { return nil, errors.Wrap(err, "could not parse SliceQpDelta") } if sliceType == "SP" || sliceType == "SI" { if sliceType == "SP" { b, err := br.ReadBits(1) if err != nil { return nil, errors.Wrap(err, "could not read SpForSwitch") } header.SpForSwitch = b == 1 } header.SliceQsDelta, err = readSe(br) if err != nil { return nil, errors.Wrap(err, "could not parse SliceQsDelta") } } if pps.DeblockingFilterControlPresent { header.DisableDeblockingFilter, err = readUe(br) if err != nil { return nil, errors.Wrap(err, "could not parse DisableDeblockingFilter") } if header.DisableDeblockingFilter != 1 { header.SliceAlphaC0OffsetDiv2, err = readSe(br) if err != nil { return nil, errors.Wrap(err, "could not parse SliceAlphaC0OffsetDiv2") } header.SliceBetaOffsetDiv2, err = readSe(br) if err != nil { return nil, errors.Wrap(err, "could not parse SliceBetaOffsetDiv2") } } } if pps.NumSliceGroupsMinus1 > 0 && pps.SliceGroupMapType >= 3 && pps.SliceGroupMapType <= 5 { b, err := br.ReadBits(int(math.Ceil(math.Log2(float64(pps.PicSizeInMapUnitsMinus1/pps.SliceGroupChangeRateMinus1 + 1))))) if err != nil { return nil, errors.Wrap(err, "could not read SliceGruopChangeCycle") } header.SliceGroupChangeCycle = int(b) } sliceContext := &SliceContext{ NALUnit: nalUnit, SPS: sps, PPS: pps, Slice: &Slice{ Header: &header, }, } sliceContext.Slice.Data, err = NewSliceData(sliceContext, br) if err != nil { return nil, errors.Wrap(err, "could not create slice data") } if showPacket { debugPacket("debug: Header", sliceContext.Slice.Header) debugPacket("debug: Data", sliceContext.Slice.Data) } return sliceContext, nil }