codec/h264/h264dec: separated VUI and HRD from SPS struct

Took out all VUI and HRD parameters from the SPS struct and gave them their own structs - VUIParameters and HRDParameters, along with 'contructors'
NewVUIParameters and NewHRDParameters to parse from a bits.BitReader and populate the fields of the struct.
This commit is contained in:
Saxon 2019-07-21 22:11:24 +09:30
parent 269b607606
commit a755ccfc58
5 changed files with 451 additions and 446 deletions

View File

@ -35,14 +35,14 @@ func YOffset(yRefMin16, refMbH int) int {
} }
func MbWidthC(sps *SPS) int { func MbWidthC(sps *SPS) int {
mbWidthC := 16 / SubWidthC(sps) mbWidthC := 16 / SubWidthC(sps)
if sps.ChromaFormat == chromaMonochrome || sps.UseSeparateColorPlane { if sps.ChromaFormatIDC == chromaMonochrome || sps.SeparateColorPlaneFlag {
mbWidthC = 0 mbWidthC = 0
} }
return mbWidthC return mbWidthC
} }
func MbHeightC(sps *SPS) int { func MbHeightC(sps *SPS) int {
mbHeightC := 16 / SubHeightC(sps) mbHeightC := 16 / SubHeightC(sps)
if sps.ChromaFormat == chromaMonochrome || sps.UseSeparateColorPlane { if sps.ChromaFormatIDC == chromaMonochrome || sps.SeparateColorPlaneFlag {
mbHeightC = 0 mbHeightC = 0
} }
return mbHeightC return mbHeightC

View File

@ -195,7 +195,7 @@ func NewPPS(sps *SPS, rbsp []byte, showPacket bool) (*PPS, error) {
if pps.PicScalingMatrixPresent { if pps.PicScalingMatrixPresent {
v := 6 v := 6
if sps.ChromaFormat != chroma444 { if sps.ChromaFormatIDC != chroma444 {
v = 2 v = 2
} }
for i := 0; i < 6+(v*pps.Transform8x8Mode); i++ { for i := 0; i < 6+(v*pps.Transform8x8Mode); i++ {
@ -231,9 +231,6 @@ func NewPPS(sps *SPS, rbsp []byte, showPacket bool) (*PPS, error) {
// rbspTrailingBits() // rbspTrailingBits()
} }
if showPacket {
debugPacket("PPS", pps)
}
return &pps, nil return &pps, nil
} }

View File

@ -145,13 +145,13 @@ func (d SliceData) ae(v int) int {
// 8.2.2 // 8.2.2
func MbToSliceGroupMap(sps *SPS, pps *PPS, header *SliceHeader) []int { func MbToSliceGroupMap(sps *SPS, pps *PPS, header *SliceHeader) []int {
mbaffFrameFlag := 0 mbaffFrameFlag := 0
if sps.MBAdaptiveFrameField && !header.FieldPic { if sps.MBAdaptiveFrameFieldFlag && !header.FieldPic {
mbaffFrameFlag = 1 mbaffFrameFlag = 1
} }
mapUnitToSliceGroupMap := MapUnitToSliceGroupMap(sps, pps, header) mapUnitToSliceGroupMap := MapUnitToSliceGroupMap(sps, pps, header)
mbToSliceGroupMap := []int{} mbToSliceGroupMap := []int{}
for i := 0; i <= PicSizeInMbs(sps, header)-1; i++ { for i := 0; i <= PicSizeInMbs(sps, header)-1; i++ {
if sps.FrameMbsOnly || header.FieldPic { if sps.FrameMBSOnlyFlag || header.FieldPic {
mbToSliceGroupMap = append(mbToSliceGroupMap, mapUnitToSliceGroupMap[i]) mbToSliceGroupMap = append(mbToSliceGroupMap, mapUnitToSliceGroupMap[i])
continue continue
} }
@ -159,7 +159,7 @@ func MbToSliceGroupMap(sps *SPS, pps *PPS, header *SliceHeader) []int {
mbToSliceGroupMap = append(mbToSliceGroupMap, mapUnitToSliceGroupMap[i/2]) mbToSliceGroupMap = append(mbToSliceGroupMap, mapUnitToSliceGroupMap[i/2])
continue continue
} }
if !sps.FrameMbsOnly && !sps.MBAdaptiveFrameField && !header.FieldPic { if !sps.FrameMBSOnlyFlag && !sps.MBAdaptiveFrameFieldFlag && !header.FieldPic {
mbToSliceGroupMap = append( mbToSliceGroupMap = append(
mbToSliceGroupMap, mbToSliceGroupMap,
mapUnitToSliceGroupMap[(i/(2*PicWidthInMbs(sps)))*PicWidthInMbs(sps)+(i%PicWidthInMbs(sps))]) mapUnitToSliceGroupMap[(i/(2*PicWidthInMbs(sps)))*PicWidthInMbs(sps)+(i%PicWidthInMbs(sps))])
@ -169,7 +169,7 @@ func MbToSliceGroupMap(sps *SPS, pps *PPS, header *SliceHeader) []int {
} }
func PicWidthInMbs(sps *SPS) int { func PicWidthInMbs(sps *SPS) int {
return sps.PicWidthInMbsMinus1 + 1 return sps.PicWidthInMBSMinus1 + 1
} }
func PicHeightInMapUnits(sps *SPS) int { func PicHeightInMapUnits(sps *SPS) int {
return sps.PicHeightInMapUnitsMinus1 + 1 return sps.PicHeightInMapUnitsMinus1 + 1
@ -178,7 +178,7 @@ func PicSizeInMapUnits(sps *SPS) int {
return PicWidthInMbs(sps) * PicHeightInMapUnits(sps) return PicWidthInMbs(sps) * PicHeightInMapUnits(sps)
} }
func FrameHeightInMbs(sps *SPS) int { func FrameHeightInMbs(sps *SPS) int {
return (2 - flagVal(sps.FrameMbsOnly)) * PicHeightInMapUnits(sps) return (2 - flagVal(sps.FrameMBSOnlyFlag)) * PicHeightInMapUnits(sps)
} }
func PicHeightInMbs(sps *SPS, header *SliceHeader) int { func PicHeightInMbs(sps *SPS, header *SliceHeader) int {
return FrameHeightInMbs(sps) / (1 + flagVal(header.FieldPic)) return FrameHeightInMbs(sps) / (1 + flagVal(header.FieldPic))
@ -190,13 +190,13 @@ func PicSizeInMbs(sps *SPS, header *SliceHeader) int {
// table 6-1 // table 6-1
func SubWidthC(sps *SPS) int { func SubWidthC(sps *SPS) int {
n := 17 n := 17
if sps.UseSeparateColorPlane { if sps.SeparateColorPlaneFlag {
if sps.ChromaFormat == chroma444 { if sps.ChromaFormatIDC == chroma444 {
return n return n
} }
} }
switch sps.ChromaFormat { switch sps.ChromaFormatIDC {
case chromaMonochrome: case chromaMonochrome:
return n return n
case chroma420: case chroma420:
@ -211,12 +211,12 @@ func SubWidthC(sps *SPS) int {
} }
func SubHeightC(sps *SPS) int { func SubHeightC(sps *SPS) int {
n := 17 n := 17
if sps.UseSeparateColorPlane { if sps.SeparateColorPlaneFlag {
if sps.ChromaFormat == chroma444 { if sps.ChromaFormatIDC == chroma444 {
return n return n
} }
} }
switch sps.ChromaFormat { switch sps.ChromaFormatIDC {
case chromaMonochrome: case chromaMonochrome:
return n return n
case chroma420: case chroma420:
@ -578,17 +578,17 @@ func nextMbAddress(n int, sps *SPS, pps *PPS, header *SliceHeader) int {
i := n + 1 i := n + 1
// picSizeInMbs is the number of macroblocks in picture 0 // picSizeInMbs is the number of macroblocks in picture 0
// 7-13 // 7-13
// PicWidthInMbs = sps.PicWidthInMbsMinus1 + 1 // PicWidthInMbs = sps.PicWidthInMBSMinus1 + 1
// PicHeightInMapUnits = sps.PicHeightInMapUnitsMinus1 + 1 // PicHeightInMapUnits = sps.PicHeightInMapUnitsMinus1 + 1
// 7-29 // 7-29
// picSizeInMbs = PicWidthInMbs * PicHeightInMbs // picSizeInMbs = PicWidthInMbs * PicHeightInMbs
// 7-26 // 7-26
// PicHeightInMbs = FrameHeightInMbs / (1 + header.fieldPicFlag) // PicHeightInMbs = FrameHeightInMbs / (1 + header.fieldPicFlag)
// 7-18 // 7-18
// FrameHeightInMbs = (2 - ps.FrameMbsOnly) * PicHeightInMapUnits // FrameHeightInMbs = (2 - ps.FrameMBSOnlyFlag) * PicHeightInMapUnits
picWidthInMbs := sps.PicWidthInMbsMinus1 + 1 picWidthInMbs := sps.PicWidthInMBSMinus1 + 1
picHeightInMapUnits := sps.PicHeightInMapUnitsMinus1 + 1 picHeightInMapUnits := sps.PicHeightInMapUnitsMinus1 + 1
frameHeightInMbs := (2 - flagVal(sps.FrameMbsOnly)) * picHeightInMapUnits frameHeightInMbs := (2 - flagVal(sps.FrameMBSOnlyFlag)) * picHeightInMapUnits
picHeightInMbs := frameHeightInMbs / (1 + flagVal(header.FieldPic)) picHeightInMbs := frameHeightInMbs / (1 + flagVal(header.FieldPic))
picSizeInMbs := picWidthInMbs * picHeightInMbs picSizeInMbs := picWidthInMbs * picHeightInMbs
mbToSliceGroupMap := MbToSliceGroupMap(sps, pps, header) mbToSliceGroupMap := MbToSliceGroupMap(sps, pps, header)
@ -600,7 +600,7 @@ func nextMbAddress(n int, sps *SPS, pps *PPS, header *SliceHeader) int {
func CurrMbAddr(sps *SPS, header *SliceHeader) int { func CurrMbAddr(sps *SPS, header *SliceHeader) int {
mbaffFrameFlag := 0 mbaffFrameFlag := 0
if sps.MBAdaptiveFrameField && !header.FieldPic { if sps.MBAdaptiveFrameFieldFlag && !header.FieldPic {
mbaffFrameFlag = 1 mbaffFrameFlag = 1
} }
@ -608,7 +608,7 @@ func CurrMbAddr(sps *SPS, header *SliceHeader) int {
} }
func MbaffFrameFlag(sps *SPS, header *SliceHeader) int { func MbaffFrameFlag(sps *SPS, header *SliceHeader) int {
if sps.MBAdaptiveFrameField && !header.FieldPic { if sps.MBAdaptiveFrameFieldFlag && !header.FieldPic {
return 1 return 1
} }
return 0 return 0
@ -630,7 +630,7 @@ func NewSliceData(sliceContext *SliceContext, br *bits.BitReader) (*SliceData, e
} }
} }
mbaffFrameFlag := 0 mbaffFrameFlag := 0
if sliceContext.SPS.MBAdaptiveFrameField && !sliceContext.Slice.Header.FieldPic { if sliceContext.SPS.MBAdaptiveFrameFieldFlag && !sliceContext.Slice.Header.FieldPic {
mbaffFrameFlag = 1 mbaffFrameFlag = 1
} }
currMbAddr := sliceContext.Slice.Header.FirstMbInSlice * (1 * mbaffFrameFlag) currMbAddr := sliceContext.Slice.Header.FirstMbInSlice * (1 * mbaffFrameFlag)
@ -791,7 +791,7 @@ func NewSliceData(sliceContext *SliceContext, br *bits.BitReader) (*SliceData, e
mbWidthC := 16 / SubWidthC(sliceContext.SPS) mbWidthC := 16 / SubWidthC(sliceContext.SPS)
mbHeightC := 16 / SubHeightC(sliceContext.SPS) mbHeightC := 16 / SubHeightC(sliceContext.SPS)
// if monochrome // if monochrome
if sliceContext.SPS.ChromaFormat == chromaMonochrome || sliceContext.SPS.UseSeparateColorPlane { if sliceContext.SPS.ChromaFormatIDC == chromaMonochrome || sliceContext.SPS.SeparateColorPlaneFlag {
mbWidthC = 0 mbWidthC = 0
mbHeightC = 0 mbHeightC = 0
} }
@ -824,7 +824,7 @@ func NewSliceData(sliceContext *SliceContext, br *bits.BitReader) (*SliceData, e
if NumbSubMbPart(subMbType[mbPartIdx]) > 1 { if NumbSubMbPart(subMbType[mbPartIdx]) > 1 {
noSubMbPartSizeLessThan8x8Flag = 0 noSubMbPartSizeLessThan8x8Flag = 0
} }
} else if !sliceContext.SPS.Direct8x8Inference { } else if !sliceContext.SPS.Direct8x8InferenceFlag {
noSubMbPartSizeLessThan8x8Flag = 0 noSubMbPartSizeLessThan8x8Flag = 0
} }
} }
@ -876,7 +876,7 @@ func NewSliceData(sliceContext *SliceContext, br *bits.BitReader) (*SliceData, e
} }
// sliceContext.Slice.Data.CodedBlockPattern = me(v) | ae(v) // 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) { 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.Direct8x8InferenceFlag) {
// TODO: 1 bit or ae(v) // TODO: 1 bit or ae(v)
if sliceContext.PPS.EntropyCodingMode == 1 { if sliceContext.PPS.EntropyCodingMode == 1 {
binarization := NewBinarization("Transform8x8Flag", sliceContext.Slice.Data) binarization := NewBinarization("Transform8x8Flag", sliceContext.Slice.Data)
@ -956,10 +956,10 @@ func NewSliceContext(videoStream *VideoStream, nalUnit *NalUnit, rbsp []byte, sh
idrPic = true idrPic = true
} }
header := SliceHeader{} header := SliceHeader{}
if sps.UseSeparateColorPlane { if sps.SeparateColorPlaneFlag {
header.ChromaArrayType = 0 header.ChromaArrayType = 0
} else { } else {
header.ChromaArrayType = sps.ChromaFormat header.ChromaArrayType = sps.ChromaFormatIDC
} }
br := bits.NewBitReader(bytes.NewReader(rbsp)) br := bits.NewBitReader(bytes.NewReader(rbsp))
@ -980,7 +980,7 @@ func NewSliceContext(videoStream *VideoStream, nalUnit *NalUnit, rbsp []byte, sh
return nil, errors.Wrap(err, "could not parse PPSID") return nil, errors.Wrap(err, "could not parse PPSID")
} }
if sps.UseSeparateColorPlane { if sps.SeparateColorPlaneFlag {
b, err := br.ReadBits(2) b, err := br.ReadBits(2)
if err != nil { if err != nil {
return nil, errors.Wrap(err, "could not read ColorPlaneID") return nil, errors.Wrap(err, "could not read ColorPlaneID")
@ -989,7 +989,7 @@ func NewSliceContext(videoStream *VideoStream, nalUnit *NalUnit, rbsp []byte, sh
} }
// TODO: See 7.4.3 // TODO: See 7.4.3
// header.FrameNum = b.NextField("FrameNum", 0) // header.FrameNum = b.NextField("FrameNum", 0)
if !sps.FrameMbsOnly { if !sps.FrameMBSOnlyFlag {
b, err := br.ReadBits(1) b, err := br.ReadBits(1)
if err != nil { if err != nil {
return nil, errors.Wrap(err, "could not read FieldPic") return nil, errors.Wrap(err, "could not read FieldPic")
@ -1023,7 +1023,7 @@ func NewSliceContext(videoStream *VideoStream, nalUnit *NalUnit, rbsp []byte, sh
} }
} }
} }
if sps.PicOrderCountType == 1 && !sps.DeltaPicOrderAlwaysZero { if sps.PicOrderCountType == 1 && !sps.DeltaPicOrderAlwaysZeroFlag {
header.DeltaPicOrderCnt[0], err = readSe(br) header.DeltaPicOrderCnt[0], err = readSe(br)
if err != nil { if err != nil {
return nil, errors.Wrap(err, "could not parse DeltaPicOrderCnt") return nil, errors.Wrap(err, "could not parse DeltaPicOrderCnt")
@ -1361,9 +1361,6 @@ func NewSliceContext(videoStream *VideoStream, nalUnit *NalUnit, rbsp []byte, sh
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")
} }
if showPacket {
debugPacket("debug: Header", sliceContext.Slice.Header)
debugPacket("debug: Data", sliceContext.Slice.Data)
}
return sliceContext, nil return sliceContext, nil
} }

View File

@ -7,12 +7,12 @@ var subWidthCTests = []struct {
want int want int
}{ }{
{SPS{}, 17}, {SPS{}, 17},
{SPS{ChromaFormat: 0}, 17}, {SPS{ChromaFormatIDC: 0}, 17},
{SPS{ChromaFormat: 1}, 2}, {SPS{ChromaFormatIDC: 1}, 2},
{SPS{ChromaFormat: 2}, 2}, {SPS{ChromaFormatIDC: 2}, 2},
{SPS{ChromaFormat: 3}, 1}, {SPS{ChromaFormatIDC: 3}, 1},
{SPS{ChromaFormat: 3, UseSeparateColorPlane: true}, 17}, {SPS{ChromaFormatIDC: 3, SeparateColorPlaneFlag: true}, 17},
{SPS{ChromaFormat: 999}, 17}, {SPS{ChromaFormatIDC: 999}, 17},
} }
// TestSubWidthC tests that the correct SubWidthC is returned given // TestSubWidthC tests that the correct SubWidthC is returned given
@ -30,12 +30,12 @@ var subHeightCTests = []struct {
want int want int
}{ }{
{SPS{}, 17}, {SPS{}, 17},
{SPS{ChromaFormat: 0}, 17}, {SPS{ChromaFormatIDC: 0}, 17},
{SPS{ChromaFormat: 1}, 2}, {SPS{ChromaFormatIDC: 1}, 2},
{SPS{ChromaFormat: 2}, 1}, {SPS{ChromaFormatIDC: 2}, 1},
{SPS{ChromaFormat: 3}, 1}, {SPS{ChromaFormatIDC: 3}, 1},
{SPS{ChromaFormat: 3, UseSeparateColorPlane: true}, 17}, {SPS{ChromaFormatIDC: 3, SeparateColorPlaneFlag: true}, 17},
{SPS{ChromaFormat: 999}, 17}, {SPS{ChromaFormatIDC: 999}, 17},
} }
// TestSubHeightC tests that the correct SubHeightC is returned given // TestSubHeightC tests that the correct SubHeightC is returned given

View File

@ -2,112 +2,11 @@ package h264dec
import ( import (
"bytes" "bytes"
"fmt"
"strings"
"bitbucket.org/ausocean/av/codec/h264/h264dec/bits" "bitbucket.org/ausocean/av/codec/h264/h264dec/bits"
"github.com/pkg/errors" "github.com/pkg/errors"
) )
// Specification Page 43 7.3.2.1.1
// Range is always inclusive
// XRange is always exclusive
type SPS struct {
// 8 bits
Profile int
// 6 bits
Constraint0, Constraint1 int
Constraint2, Constraint3 int
Constraint4, Constraint5 int
// 2 bit reserved 0 bits
// 8 bits
Level int
// Range 0 - 31 ; 6 bits
ID int
ChromaFormat int
UseSeparateColorPlane bool
BitDepthLumaMinus8 int
BitDepthChromaMinus8 int
QPrimeYZeroTransformBypass bool
SeqScalingMatrixPresent bool
// Delta is (0-12)-1 ; 4 bits
SeqScalingList []bool // se
// Range 0 - 12; 4 bits
Log2MaxFrameNumMinus4 int
// Range 0 - 2; 2 bits
PicOrderCountType int
// Range 0 - 12; 4 bits
Log2MaxPicOrderCntLSBMin4 int
DeltaPicOrderAlwaysZero bool
// Range (-2^31)+1 to (2^31)-1 ; 31 bits
OffsetForNonRefPic int // Value - 1 (se)
// Range (-2^31)+1 to (2^31)-1 ; 31 bits
OffsetForTopToBottomField int // Value - 1 (se)
// Range 0 - 255 ; 8 bits
NumRefFramesInPicOrderCntCycle int
// Range (-2^31)+1 to (2^31)-1 ; 31 bits
OffsetForRefFrameList []int // Value - 1 ([]se)
// Range 0 - MaxDpbFrames
MaxNumRefFrames int
GapsInFrameNumValueAllowed bool
// Page 77
PicWidthInMbsMinus1 int
// Page 77
PicHeightInMapUnitsMinus1 int
FrameMbsOnly bool
MBAdaptiveFrameField bool
Direct8x8Inference bool
FrameCropping bool
FrameCropLeftOffset int
FrameCropRightOffset int
FrameCropTopOffset int
FrameCropBottomOffset int
VuiParametersPresent bool
VuiParameters []int
AspectRatioInfoPresent bool
AspectRatio int
SarWidth int
SarHeight int
OverscanInfoPresent bool
OverscanAppropriate bool
VideoSignalTypePresent bool
VideoFormat int
VideoFullRange bool
ColorDescriptionPresent bool
ColorPrimaries int
TransferCharacteristics int
MatrixCoefficients int
ChromaLocInfoPresent bool
ChromaSampleLocTypeTopField int
ChromaSampleLocTypeBottomField int
CpbCntMinus1 int
BitRateScale int
CpbSizeScale int
BitRateValueMinus1 []int
Cbr []bool
InitialCpbRemovalDelayLengthMinus1 int
CpbRemovalDelayLengthMinus1 int
CpbSizeValueMinus1 []int
DpbOutputDelayLengthMinus1 int
TimeOffsetLength int
TimingInfoPresent bool
NumUnitsInTick int
TimeScale int
NalHrdParametersPresent bool
FixedFrameRate bool
VclHrdParametersPresent bool
LowHrdDelay bool
PicStructPresent bool
BitstreamRestriction bool
MotionVectorsOverPicBoundaries bool
MaxBytesPerPicDenom int
MaxBitsPerMbDenom int
Log2MaxMvLengthHorizontal int
Log2MaxMvLengthVertical int
MaxDecFrameBuffering int
MaxNumReorderFrames int
}
var ( var (
DefaultScalingMatrix4x4 = [][]int{ DefaultScalingMatrix4x4 = [][]int{
{6, 13, 20, 28, 13, 20, 28, 32, 20, 28, 32, 37, 28, 32, 37, 42}, {6, 13, 20, 28, 13, 20, 28, 32, 20, 28, 32, 37, 28, 32, 37, 42},
@ -161,98 +60,62 @@ var (
ScalingList8x8 = ScalingList4x4 ScalingList8x8 = ScalingList4x4
) )
func isInList(l []int, term int) bool { // SPS describes a sequence parameter set as defined by section 7.3.2.1.1 in
for _, m := range l { // the Specifications.
if m == term { type SPS struct {
return true Profile int
} Constraint0 int
} Constraint1 int
return false Constraint2 int
} Constraint3 int
func debugPacket(name string, packet interface{}) { Constraint4 int
logger.Printf("debug: %s packet\n", name) Constraint5 int
for _, line := range strings.Split(fmt.Sprintf("%+v", packet), " ") { LevelIDC int
logger.Printf("debug: \t%#v\n", line) SPSID int
} ChromaFormatIDC int
} SeparateColorPlaneFlag bool
func scalingList(br *bits.BitReader, scalingList []int, sizeOfScalingList int, defaultScalingMatrix []int) error { BitDepthLumaMinus8 int
lastScale := 8 BitDepthChromaMinus8 int
nextScale := 8 QPPrimeYZeroTransformBypassFlag bool
for i := 0; i < sizeOfScalingList; i++ { SeqScalingMatrixPresentFlag bool
if nextScale != 0 { SeqScalingListPresentFlag []bool
deltaScale, err := readSe(br) ScalingList4x4 [][]int
if err != nil { UseDefaultScalingMatrix4x4Flag []bool
return errors.Wrap(err, "could not parse deltaScale") ScalingList8x8 [][]int
} UseDefaultScalingMatrix8x8Flag []bool
nextScale = (lastScale + deltaScale + 256) % 256 Log2MaxFrameNumMinus4 int
if i == 0 && nextScale == 0 { PicOrderCountType int
// Scaling list should use the default list for this point in the matrix Log2MaxPicOrderCntLSBMin4 int
_ = defaultScalingMatrix DeltaPicOrderAlwaysZeroFlag bool
} OffsetForNonRefPic int
} OffsetForTopToBottomField int
if nextScale == 0 { NumRefFramesInPicOrderCntCycle int
scalingList[i] = lastScale OffsetForRefFrameList []int
} else { MaxNumRefFrames int
scalingList[i] = nextScale GapsInFrameNumValueAllowed bool
} PicWidthInMBSMinus1 int
lastScale = scalingList[i] PicHeightInMapUnitsMinus1 int
} FrameMBSOnlyFlag bool
return nil MBAdaptiveFrameFieldFlag bool
Direct8x8InferenceFlag bool
FrameCroppingFlag bool
FrameCropLeftOffset int
FrameCropRightOffset int
FrameCropTopOffset int
FrameCropBottomOffset int
VUIParametersPresentFlag bool
VUIParameters *VUIParameters
} }
// NewSPS parses a sequence parameter set raw byte sequence from br following
// the syntax structure specified in section 7.3.2.1.1, and returns as a new
// SPS.
func NewSPS(rbsp []byte, showPacket bool) (*SPS, error) { func NewSPS(rbsp []byte, showPacket bool) (*SPS, error) {
logger.Printf("debug: SPS RBSP %d bytes %d bits\n", len(rbsp), len(rbsp)*8) logger.Printf("debug: SPS RBSP %d bytes %d bits\n", len(rbsp), len(rbsp)*8)
logger.Printf("debug: \t%#v\n", rbsp[0:8]) logger.Printf("debug: \t%#v\n", rbsp[0:8])
sps := SPS{} sps := SPS{}
br := bits.NewBitReader(bytes.NewReader(rbsp)) br := bits.NewBitReader(bytes.NewReader(rbsp))
var err error var err error
hrdParameters := func() error {
sps.CpbCntMinus1, err = readUe(br)
if err != nil {
return errors.Wrap(err, "could not parse CpbCntMinus1")
}
err := readFields(br, []field{
{&sps.BitRateScale, "BitRateScale", 4},
{&sps.CpbSizeScale, "CpbSizeScale", 4},
})
if err != nil {
return err
}
// SchedSelIdx E1.2
for sseli := 0; sseli <= sps.CpbCntMinus1; sseli++ {
ue, err := readUe(br)
if err != nil {
return errors.Wrap(err, "could not parse BitRateValueMinus1")
}
sps.BitRateValueMinus1 = append(sps.BitRateValueMinus1, ue)
ue, err = readUe(br)
if err != nil {
return errors.Wrap(err, "could not parse CpbSizeValueMinus1")
}
sps.CpbSizeValueMinus1 = append(sps.CpbSizeValueMinus1, ue)
if v, _ := br.ReadBits(1); v == 1 {
sps.Cbr = append(sps.Cbr, true)
} else {
sps.Cbr = append(sps.Cbr, false)
}
err = readFields(br,
[]field{
{&sps.InitialCpbRemovalDelayLengthMinus1, "InitialCpbRemovalDelayLengthMinus1", 5},
{&sps.CpbRemovalDelayLengthMinus1, "CpbRemovalDelayLengthMinus1", 5},
{&sps.DpbOutputDelayLengthMinus1, "DpbOutputDelayLengthMinus1", 5},
{&sps.TimeOffsetLength, "TimeOffsetLength", 5},
},
)
if err != nil {
return err
}
}
return nil
}
err = readFields(br, err = readFields(br,
[]field{ []field{
@ -275,30 +138,30 @@ func NewSPS(rbsp []byte, showPacket bool) (*SPS, error) {
if err != nil { if err != nil {
return nil, errors.Wrap(err, "could not read Level") return nil, errors.Wrap(err, "could not read Level")
} }
sps.Level = int(b) sps.LevelIDC = int(b)
// sps.ID = b.NextField("SPSID", 6) // proper // sps.ID = b.NextField("SPSID", 6) // proper
sps.ID, err = readUe(br) sps.SPSID, err = readUe(br)
if err != nil { if err != nil {
return nil, errors.Wrap(err, "could not parse ID") return nil, errors.Wrap(err, "could not parse ID")
} }
sps.ChromaFormat, err = readUe(br) sps.ChromaFormatIDC, err = readUe(br)
if err != nil { if err != nil {
return nil, errors.Wrap(err, "could not parse ChromaFormat") return nil, errors.Wrap(err, "could not parse ChromaFormatIDC")
} }
// This should be done only for certain ProfileIDC: // This should be done only for certain ProfileIDC:
isProfileIDC := []int{100, 110, 122, 244, 44, 83, 86, 118, 128, 138, 139, 134, 135} isProfileIDC := []int{100, 110, 122, 244, 44, 83, 86, 118, 128, 138, 139, 134, 135}
// SpecialProfileCase1 // SpecialProfileCase1
if isInList(isProfileIDC, sps.Profile) { if isInList(isProfileIDC, sps.Profile) {
if sps.ChromaFormat == chroma444 { if sps.ChromaFormatIDC == chroma444 {
// TODO: should probably deal with error here. // TODO: should probably deal with error here.
b, err := br.ReadBits(1) b, err := br.ReadBits(1)
if err != nil { if err != nil {
return nil, errors.Wrap(err, "could not read UseSeparateColorPlaneFlag") return nil, errors.Wrap(err, "could not read UseSeparateColorPlaneFlag")
} }
sps.UseSeparateColorPlane = b == 1 sps.SeparateColorPlaneFlag = b == 1
} }
sps.BitDepthLumaMinus8, err = readUe(br) sps.BitDepthLumaMinus8, err = readUe(br)
@ -315,17 +178,17 @@ func NewSPS(rbsp []byte, showPacket bool) (*SPS, error) {
if err != nil { if err != nil {
return nil, errors.Wrap(err, "could not read QPrimeYZeroTransformBypass") return nil, errors.Wrap(err, "could not read QPrimeYZeroTransformBypass")
} }
sps.QPrimeYZeroTransformBypass = b == 1 sps.QPPrimeYZeroTransformBypassFlag = b == 1
b, err = br.ReadBits(1) b, err = br.ReadBits(1)
if err != nil { if err != nil {
return nil, errors.Wrap(err, "could not read SeqScalingMatrixPresent") return nil, errors.Wrap(err, "could not read SeqScalingMatrixPresent")
} }
sps.SeqScalingMatrixPresent = b == 1 sps.SeqScalingMatrixPresentFlag = b == 1
if sps.SeqScalingMatrixPresent { if sps.SeqScalingMatrixPresentFlag {
max := 12 max := 12
if sps.ChromaFormat != chroma444 { if sps.ChromaFormatIDC != chroma444 {
max = 8 max = 8
} }
logger.Printf("debug: \tbuilding Scaling matrix for %d elements\n", max) logger.Printf("debug: \tbuilding Scaling matrix for %d elements\n", max)
@ -334,9 +197,9 @@ func NewSPS(rbsp []byte, showPacket bool) (*SPS, error) {
if err != nil { if err != nil {
return nil, errors.Wrap(err, "could not read SeqScalingList") return nil, errors.Wrap(err, "could not read SeqScalingList")
} }
sps.SeqScalingList = append(sps.SeqScalingList, b == 1) sps.SeqScalingListPresentFlag = append(sps.SeqScalingListPresentFlag, b == 1)
if sps.SeqScalingList[i] { if sps.SeqScalingListPresentFlag[i] {
if i < 6 { if i < 6 {
scalingList( scalingList(
br, br,
@ -380,7 +243,7 @@ func NewSPS(rbsp []byte, showPacket bool) (*SPS, error) {
if err != nil { if err != nil {
return nil, errors.Wrap(err, "could not read DeltaPicOrderAlwaysZero") return nil, errors.Wrap(err, "could not read DeltaPicOrderAlwaysZero")
} }
sps.DeltaPicOrderAlwaysZero = b == 1 sps.DeltaPicOrderAlwaysZeroFlag = b == 1
sps.OffsetForNonRefPic, err = readSe(br) sps.OffsetForNonRefPic, err = readSe(br)
if err != nil { if err != nil {
@ -420,7 +283,7 @@ func NewSPS(rbsp []byte, showPacket bool) (*SPS, error) {
} }
sps.GapsInFrameNumValueAllowed = b == 1 sps.GapsInFrameNumValueAllowed = b == 1
sps.PicWidthInMbsMinus1, err = readUe(br) sps.PicWidthInMBSMinus1, err = readUe(br)
if err != nil { if err != nil {
return nil, errors.Wrap(err, "could not parse PicWidthInMbsMinus1") return nil, errors.Wrap(err, "could not parse PicWidthInMbsMinus1")
} }
@ -434,25 +297,25 @@ func NewSPS(rbsp []byte, showPacket bool) (*SPS, error) {
if err != nil { if err != nil {
return nil, errors.Wrap(err, "could not read FrameMbsOnly") return nil, errors.Wrap(err, "could not read FrameMbsOnly")
} }
sps.FrameMbsOnly = b == 1 sps.FrameMBSOnlyFlag = b == 1
if !sps.FrameMbsOnly { if !sps.FrameMBSOnlyFlag {
b, err = br.ReadBits(1) b, err = br.ReadBits(1)
if err != nil { if err != nil {
return nil, errors.Wrap(err, "could not read MBAdaptiveFrameField") return nil, errors.Wrap(err, "could not read MBAdaptiveFrameField")
} }
sps.MBAdaptiveFrameField = b == 1 sps.MBAdaptiveFrameFieldFlag = b == 1
} }
err = readFlags(br, []flag{ err = readFlags(br, []flag{
{&sps.Direct8x8Inference, "Direct8x8Inference"}, {&sps.Direct8x8InferenceFlag, "Direct8x8Inference"},
{&sps.FrameCropping, "FrameCropping"}, {&sps.FrameCroppingFlag, "FrameCropping"},
}) })
if err != nil { if err != nil {
return nil, err return nil, err
} }
if sps.FrameCropping { if sps.FrameCroppingFlag {
sps.FrameCropLeftOffset, err = readUe(br) sps.FrameCropLeftOffset, err = readUe(br)
if err != nil { if err != nil {
return nil, errors.Wrap(err, "could not parse FrameCropLeftOffset") return nil, errors.Wrap(err, "could not parse FrameCropLeftOffset")
@ -478,36 +341,86 @@ func NewSPS(rbsp []byte, showPacket bool) (*SPS, error) {
if err != nil { if err != nil {
return nil, errors.Wrap(err, "could not read VuiParametersPresent") return nil, errors.Wrap(err, "could not read VuiParametersPresent")
} }
sps.VuiParametersPresent = b == 1 sps.VUIParametersPresentFlag = b == 1
if sps.VuiParametersPresent { if sps.VUIParametersPresentFlag {
// vui_parameters
b, err = br.ReadBits(1) } // End VuiParameters Annex E.1.1
return &sps, nil
}
// SPS describes a sequence parameter set as defined by section E.1.1 in the
// Specifications.
type VUIParameters struct {
AspectRatioInfoPresentFlag bool
AspectRatioIDC int
SARWidth int
SARHeight int
OverscanInfoPresentFlag bool
OverscanAppropriateFlag bool
VideoSignalTypePresentFlag bool
VideoFormat int
VideoFullRangeFlag bool
ColorDescriptionPresentFlag bool
ColorPrimaries int
TransferCharacteristics int
MatrixCoefficients int
ChromaLocInfoPresentFlag bool
ChromaSampleLocTypeTopField int
ChromaSampleLocTypeBottomField int
TimingInfoPresentFlag bool
NumUnitsInTick int
TimeScale int
FixedFrameRateFlag bool
NALHRDParametersPresentFlag bool
NALHRDParameters *HRDParameters
VCLHRDParametersPresentFlag bool
VCLHRDParameters *HRDParameters
LowDelayHRDFlag bool
PicStructPresentFlag bool
BitstreamRestrictionFlag bool
MotionVectorsOverPicBoundariesFlag bool
MaxBytesPerPicDenom int
MaxBitsPerMBDenom int
Log2MaxMVLengthHorizontal int
Log2MaxMVLengthVertical int
MaxNumReorderFrames int
MaxDecFrameBuffering int
}
// NewVUIParameters parses video usability information parameters from br
// following the syntax structure specified in section E.1.1, and returns as a
// new VUIParameters.
func NewVUIParameters(br *bits.BitReader) (*VUIParameters, error) {
p := &VUIParameters{}
b, err := br.ReadBits(1)
if err != nil { if err != nil {
return nil, errors.Wrap(err, "could not read AspectRatioInfoPresent") return nil, errors.Wrap(err, "could not read AspectRatioInfoPresent")
} }
sps.AspectRatioInfoPresent = b == 1 p.AspectRatioInfoPresentFlag = b == 1
if sps.AspectRatioInfoPresent { if p.AspectRatioInfoPresentFlag {
b, err = br.ReadBits(8) b, err = br.ReadBits(8)
if err != nil { if err != nil {
return nil, errors.Wrap(err, "could not read AspectRatio") return nil, errors.Wrap(err, "could not read AspectRatio")
} }
sps.AspectRatio = int(b) p.AspectRatioIDC = int(b)
EXTENDED_SAR := 999 EXTENDED_SAR := 999
if sps.AspectRatio == EXTENDED_SAR { if p.AspectRatioIDC == EXTENDED_SAR {
b, err = br.ReadBits(16) b, err = br.ReadBits(16)
if err != nil { if err != nil {
return nil, errors.Wrap(err, "could not read SarWidth") return nil, errors.Wrap(err, "could not read SarWidth")
} }
sps.SarWidth = int(b) p.SARWidth = int(b)
b, err = br.ReadBits(16) b, err = br.ReadBits(16)
if err != nil { if err != nil {
return nil, errors.Wrap(err, "could not read SarHeight") return nil, errors.Wrap(err, "could not read SarHeight")
} }
sps.SarHeight = int(b) p.SARHeight = int(b)
} }
} }
@ -515,49 +428,49 @@ func NewSPS(rbsp []byte, showPacket bool) (*SPS, error) {
if err != nil { if err != nil {
return nil, errors.Wrap(err, "could not read OverscanInfoPresent") return nil, errors.Wrap(err, "could not read OverscanInfoPresent")
} }
sps.OverscanInfoPresent = b == 1 p.OverscanInfoPresentFlag = b == 1
if sps.OverscanInfoPresent { if p.OverscanInfoPresentFlag {
b, err = br.ReadBits(1) b, err = br.ReadBits(1)
if err != nil { if err != nil {
return nil, errors.Wrap(err, "could not read OverscanAppropriate") return nil, errors.Wrap(err, "could not read OverscanAppropriate")
} }
sps.OverscanAppropriate = b == 1 p.OverscanAppropriateFlag = b == 1
} }
b, err = br.ReadBits(1) b, err = br.ReadBits(1)
if err != nil { if err != nil {
return nil, errors.Wrap(err, "could not read VideoSignalTypePresent") return nil, errors.Wrap(err, "could not read VideoSignalTypePresent")
} }
sps.VideoSignalTypePresent = b == 1 p.VideoSignalTypePresentFlag = b == 1
if sps.VideoSignalTypePresent { if p.VideoSignalTypePresentFlag {
b, err = br.ReadBits(3) b, err = br.ReadBits(3)
if err != nil { if err != nil {
return nil, errors.Wrap(err, "could not read VideoFormat") return nil, errors.Wrap(err, "could not read VideoFormat")
} }
sps.VideoFormat = int(b) p.VideoFormat = int(b)
} }
if sps.VideoSignalTypePresent { if p.VideoSignalTypePresentFlag {
b, err = br.ReadBits(1) b, err = br.ReadBits(1)
if err != nil { if err != nil {
return nil, errors.Wrap(err, "could not read VideoFullRange") return nil, errors.Wrap(err, "could not read VideoFullRange")
} }
sps.VideoFullRange = b == 1 p.VideoFullRangeFlag = b == 1
b, err = br.ReadBits(1) b, err = br.ReadBits(1)
if err != nil { if err != nil {
return nil, errors.Wrap(err, "could not read ColorDescriptionPresent") return nil, errors.Wrap(err, "could not read ColorDescriptionPresent")
} }
sps.ColorDescriptionPresent = b == 1 p.ColorDescriptionPresentFlag = b == 1
if sps.ColorDescriptionPresent { if p.ColorDescriptionPresentFlag {
err = readFields(br, err = readFields(br,
[]field{ []field{
{&sps.ColorPrimaries, "ColorPrimaries", 8}, {&p.ColorPrimaries, "ColorPrimaries", 8},
{&sps.TransferCharacteristics, "TransferCharacteristics", 8}, {&p.TransferCharacteristics, "TransferCharacteristics", 8},
{&sps.MatrixCoefficients, "MatrixCoefficients", 8}, {&p.MatrixCoefficients, "MatrixCoefficients", 8},
}, },
) )
if err != nil { if err != nil {
@ -570,15 +483,15 @@ func NewSPS(rbsp []byte, showPacket bool) (*SPS, error) {
if err != nil { if err != nil {
return nil, errors.Wrap(err, "could not read ChromaLocInfoPresent") return nil, errors.Wrap(err, "could not read ChromaLocInfoPresent")
} }
sps.ChromaLocInfoPresent = b == 1 p.ChromaLocInfoPresentFlag = b == 1
if sps.ChromaLocInfoPresent { if p.ChromaLocInfoPresentFlag {
sps.ChromaSampleLocTypeTopField, err = readUe(br) p.ChromaSampleLocTypeTopField, err = readUe(br)
if err != nil { if err != nil {
return nil, errors.Wrap(err, "could not parse ChromaSampleLocTypeTopField") return nil, errors.Wrap(err, "could not parse ChromaSampleLocTypeTopField")
} }
sps.ChromaSampleLocTypeBottomField, err = readUe(br) p.ChromaSampleLocTypeBottomField, err = readUe(br)
if err != nil { if err != nil {
return nil, errors.Wrap(err, "could not parse ChromaSampleLocTypeBottomField") return nil, errors.Wrap(err, "could not parse ChromaSampleLocTypeBottomField")
} }
@ -588,12 +501,12 @@ func NewSPS(rbsp []byte, showPacket bool) (*SPS, error) {
if err != nil { if err != nil {
return nil, errors.Wrap(err, "could not read TimingInfoPresent") return nil, errors.Wrap(err, "could not read TimingInfoPresent")
} }
sps.TimingInfoPresent = b == 1 p.TimingInfoPresentFlag = b == 1
if sps.TimingInfoPresent { if p.TimingInfoPresentFlag {
err := readFields(br, []field{ err := readFields(br, []field{
{&sps.NumUnitsInTick, "NumUnitsInTick", 32}, {&p.NumUnitsInTick, "NumUnitsInTick", 32},
{&sps.TimeScale, "TimeScale", 32}, {&p.TimeScale, "TimeScale", 32},
}) })
if err != nil { if err != nil {
return nil, err return nil, err
@ -603,17 +516,17 @@ func NewSPS(rbsp []byte, showPacket bool) (*SPS, error) {
if err != nil { if err != nil {
return nil, errors.Wrap(err, "could not read FixedFrameRate") return nil, errors.Wrap(err, "could not read FixedFrameRate")
} }
sps.FixedFrameRate = b == 1 p.FixedFrameRateFlag = b == 1
} }
b, err = br.ReadBits(1) b, err = br.ReadBits(1)
if err != nil { if err != nil {
return nil, errors.Wrap(err, "could not read NalHrdParametersPresent") return nil, errors.Wrap(err, "could not read NalHrdParametersPresent")
} }
sps.NalHrdParametersPresent = b == 1 p.NALHRDParametersPresentFlag = b == 1
if sps.NalHrdParametersPresent { if p.NALHRDParametersPresentFlag {
err = hrdParameters() p.NALHRDParameters, err = NewHRDParameters(br)
if err != nil { if err != nil {
return nil, errors.Wrap(err, "could not get hrdParameters") return nil, errors.Wrap(err, "could not get hrdParameters")
} }
@ -623,68 +536,166 @@ func NewSPS(rbsp []byte, showPacket bool) (*SPS, error) {
if err != nil { if err != nil {
return nil, errors.Wrap(err, "could not read VclHrdParametersPresent") return nil, errors.Wrap(err, "could not read VclHrdParametersPresent")
} }
sps.VclHrdParametersPresent = b == 1 p.VCLHRDParametersPresentFlag = b == 1
if sps.VclHrdParametersPresent { if p.VCLHRDParametersPresentFlag {
err = hrdParameters() p.VCLHRDParameters, err = NewHRDParameters(br)
if err != nil { if err != nil {
return nil, errors.Wrap(err, "could not get hrdParameters") return nil, errors.Wrap(err, "could not get hrdParameters")
} }
} }
if sps.NalHrdParametersPresent || sps.VclHrdParametersPresent { if p.NALHRDParametersPresentFlag || p.VCLHRDParametersPresentFlag {
b, err = br.ReadBits(1) b, err = br.ReadBits(1)
if err != nil { if err != nil {
return nil, errors.Wrap(err, "could not read LowHrdDelay") return nil, errors.Wrap(err, "could not read LowHrdDelay")
} }
sps.LowHrdDelay = b == 1 p.LowDelayHRDFlag = b == 1
} }
err := readFlags(br, []flag{ err = readFlags(br, []flag{
{&sps.PicStructPresent, "PicStructPresent"}, {&p.PicStructPresentFlag, "PicStructPresent"},
{&sps.BitstreamRestriction, "BitStreamRestriction"}, {&p.BitstreamRestrictionFlag, "BitStreamRestriction"},
}) })
if sps.BitstreamRestriction { if p.BitstreamRestrictionFlag {
b, err = br.ReadBits(1) b, err = br.ReadBits(1)
if err != nil { if err != nil {
return nil, errors.Wrap(err, "could not read MotionVectorsOverPicBoundaries") return nil, errors.Wrap(err, "could not read MotionVectorsOverPicBoundaries")
} }
sps.MotionVectorsOverPicBoundaries = b == 1 p.MotionVectorsOverPicBoundariesFlag = b == 1
sps.MaxBytesPerPicDenom, err = readUe(br) p.MaxBytesPerPicDenom, err = readUe(br)
if err != nil { if err != nil {
return nil, errors.Wrap(err, "could not parse MaxBytesPerPicDenom") return nil, errors.Wrap(err, "could not parse MaxBytesPerPicDenom")
} }
sps.MaxBitsPerMbDenom, err = readUe(br) p.MaxBitsPerMBDenom, err = readUe(br)
if err != nil { if err != nil {
return nil, errors.Wrap(err, "could not parse MaxBitsPerMbDenom") return nil, errors.Wrap(err, "could not parse MaxBitsPerMbDenom")
} }
sps.Log2MaxMvLengthHorizontal, err = readUe(br) p.Log2MaxMVLengthHorizontal, err = readUe(br)
if err != nil { if err != nil {
return nil, errors.Wrap(err, "could not parse Log2MaxMvLengthHorizontal") return nil, errors.Wrap(err, "could not parse Log2MaxMvLengthHorizontal")
} }
sps.Log2MaxMvLengthVertical, err = readUe(br) p.Log2MaxMVLengthVertical, err = readUe(br)
if err != nil { if err != nil {
return nil, errors.Wrap(err, "could not parse Log2MaxMvLengthVertical") return nil, errors.Wrap(err, "could not parse Log2MaxMvLengthVertical")
} }
sps.MaxNumReorderFrames, err = readUe(br) p.MaxNumReorderFrames, err = readUe(br)
if err != nil { if err != nil {
return nil, errors.Wrap(err, "could not parse MaxNumReorderFrames") return nil, errors.Wrap(err, "could not parse MaxNumReorderFrames")
} }
sps.MaxDecFrameBuffering, err = readUe(br) p.MaxDecFrameBuffering, err = readUe(br)
if err != nil { if err != nil {
return nil, errors.Wrap(err, "could not parse MaxDecFrameBuffering") return nil, errors.Wrap(err, "could not parse MaxDecFrameBuffering")
} }
} }
return p, nil
}
} // End VuiParameters Annex E.1.1 // HRDParameters describes hypothetical reference decoder parameters as defined
if showPacket { // by section E.1.2 in the specifications.
debugPacket("SPS", sps) type HRDParameters struct {
CPBCntMinus1 int
BitRateScale int
CPBSizeScale int
BitRateValueMinus1 []int
CPBSizeValueMinus1 []int
CBRFlag []bool
InitialCPBRemovalDelayLenMinus1 int
CPBRemovalDelayLenMinus1 int
DPBOutputDelayLenMinus1 int
TimeOffsetLen int
} }
return &sps, nil
// NewHRDParameters parses hypothetical reference decoder parameter from br
// following the syntax structure specified in section E.1.2, and returns as a
// new HRDParameters.
func NewHRDParameters(br *bits.BitReader) (*HRDParameters, error) {
h := &HRDParameters{}
var err error
h.CPBCntMinus1, err = readUe(br)
if err != nil {
return nil, errors.Wrap(err, "could not parse CPBCntMinus1")
}
err = readFields(br, []field{
{&h.BitRateScale, "BitRateScale", 4},
{&h.CPBSizeScale, "CPBSizeScale", 4},
})
if err != nil {
return nil, err
}
// SchedSelIdx E1.2
for sseli := 0; sseli <= h.CPBCntMinus1; sseli++ {
ue, err := readUe(br)
if err != nil {
return nil, errors.Wrap(err, "could not parse BitRateValueMinus1")
}
h.BitRateValueMinus1 = append(h.BitRateValueMinus1, ue)
ue, err = readUe(br)
if err != nil {
return nil, errors.Wrap(err, "could not parse CPBSizeValueMinus1")
}
h.CPBSizeValueMinus1 = append(h.CPBSizeValueMinus1, ue)
if v, _ := br.ReadBits(1); v == 1 {
h.CBRFlag = append(h.CBRFlag, true)
} else {
h.CBRFlag = append(h.CBRFlag, false)
}
err = readFields(br,
[]field{
{&h.InitialCPBRemovalDelayLenMinus1, "InitialCPBRemovalDelayLenMinus1", 5},
{&h.CPBRemovalDelayLenMinus1, "CPBRemovalDelayLenMinus1", 5},
{&h.DPBOutputDelayLenMinus1, "DpbOutputDelayLenMinus1", 5},
{&h.TimeOffsetLen, "TimeOffsetLen", 5},
},
)
if err != nil {
return nil, err
}
}
return h, nil
}
func isInList(l []int, term int) bool {
for _, m := range l {
if m == term {
return true
}
}
return false
}
func scalingList(br *bits.BitReader, scalingList []int, sizeOfScalingList int, defaultScalingMatrix []int) error {
lastScale := 8
nextScale := 8
for i := 0; i < sizeOfScalingList; i++ {
if nextScale != 0 {
deltaScale, err := readSe(br)
if err != nil {
return errors.Wrap(err, "could not parse deltaScale")
}
nextScale = (lastScale + deltaScale + 256) % 256
if i == 0 && nextScale == 0 {
// Scaling list should use the default list for this point in the matrix
_ = defaultScalingMatrix
}
}
if nextScale == 0 {
scalingList[i] = lastScale
} else {
scalingList[i] = nextScale
}
lastScale = scalingList[i]
}
return nil
} }