mirror of https://bitbucket.org/ausocean/av.git
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:
parent
269b607606
commit
a755ccfc58
|
@ -35,14 +35,14 @@ func YOffset(yRefMin16, refMbH int) int {
|
|||
}
|
||||
func MbWidthC(sps *SPS) int {
|
||||
mbWidthC := 16 / SubWidthC(sps)
|
||||
if sps.ChromaFormat == chromaMonochrome || sps.UseSeparateColorPlane {
|
||||
if sps.ChromaFormatIDC == chromaMonochrome || sps.SeparateColorPlaneFlag {
|
||||
mbWidthC = 0
|
||||
}
|
||||
return mbWidthC
|
||||
}
|
||||
func MbHeightC(sps *SPS) int {
|
||||
mbHeightC := 16 / SubHeightC(sps)
|
||||
if sps.ChromaFormat == chromaMonochrome || sps.UseSeparateColorPlane {
|
||||
if sps.ChromaFormatIDC == chromaMonochrome || sps.SeparateColorPlaneFlag {
|
||||
mbHeightC = 0
|
||||
}
|
||||
return mbHeightC
|
||||
|
|
|
@ -195,7 +195,7 @@ func NewPPS(sps *SPS, rbsp []byte, showPacket bool) (*PPS, error) {
|
|||
|
||||
if pps.PicScalingMatrixPresent {
|
||||
v := 6
|
||||
if sps.ChromaFormat != chroma444 {
|
||||
if sps.ChromaFormatIDC != chroma444 {
|
||||
v = 2
|
||||
}
|
||||
for i := 0; i < 6+(v*pps.Transform8x8Mode); i++ {
|
||||
|
@ -231,9 +231,6 @@ func NewPPS(sps *SPS, rbsp []byte, showPacket bool) (*PPS, error) {
|
|||
// rbspTrailingBits()
|
||||
}
|
||||
|
||||
if showPacket {
|
||||
debugPacket("PPS", pps)
|
||||
}
|
||||
return &pps, nil
|
||||
|
||||
}
|
||||
|
|
|
@ -145,13 +145,13 @@ func (d SliceData) ae(v int) int {
|
|||
// 8.2.2
|
||||
func MbToSliceGroupMap(sps *SPS, pps *PPS, header *SliceHeader) []int {
|
||||
mbaffFrameFlag := 0
|
||||
if sps.MBAdaptiveFrameField && !header.FieldPic {
|
||||
if sps.MBAdaptiveFrameFieldFlag && !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 {
|
||||
if sps.FrameMBSOnlyFlag || header.FieldPic {
|
||||
mbToSliceGroupMap = append(mbToSliceGroupMap, mapUnitToSliceGroupMap[i])
|
||||
continue
|
||||
}
|
||||
|
@ -159,7 +159,7 @@ func MbToSliceGroupMap(sps *SPS, pps *PPS, header *SliceHeader) []int {
|
|||
mbToSliceGroupMap = append(mbToSliceGroupMap, mapUnitToSliceGroupMap[i/2])
|
||||
continue
|
||||
}
|
||||
if !sps.FrameMbsOnly && !sps.MBAdaptiveFrameField && !header.FieldPic {
|
||||
if !sps.FrameMBSOnlyFlag && !sps.MBAdaptiveFrameFieldFlag && !header.FieldPic {
|
||||
mbToSliceGroupMap = append(
|
||||
mbToSliceGroupMap,
|
||||
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 {
|
||||
return sps.PicWidthInMbsMinus1 + 1
|
||||
return sps.PicWidthInMBSMinus1 + 1
|
||||
}
|
||||
func PicHeightInMapUnits(sps *SPS) int {
|
||||
return sps.PicHeightInMapUnitsMinus1 + 1
|
||||
|
@ -178,7 +178,7 @@ func PicSizeInMapUnits(sps *SPS) int {
|
|||
return PicWidthInMbs(sps) * PicHeightInMapUnits(sps)
|
||||
}
|
||||
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 {
|
||||
return FrameHeightInMbs(sps) / (1 + flagVal(header.FieldPic))
|
||||
|
@ -190,13 +190,13 @@ func PicSizeInMbs(sps *SPS, header *SliceHeader) int {
|
|||
// table 6-1
|
||||
func SubWidthC(sps *SPS) int {
|
||||
n := 17
|
||||
if sps.UseSeparateColorPlane {
|
||||
if sps.ChromaFormat == chroma444 {
|
||||
if sps.SeparateColorPlaneFlag {
|
||||
if sps.ChromaFormatIDC == chroma444 {
|
||||
return n
|
||||
}
|
||||
}
|
||||
|
||||
switch sps.ChromaFormat {
|
||||
switch sps.ChromaFormatIDC {
|
||||
case chromaMonochrome:
|
||||
return n
|
||||
case chroma420:
|
||||
|
@ -211,12 +211,12 @@ func SubWidthC(sps *SPS) int {
|
|||
}
|
||||
func SubHeightC(sps *SPS) int {
|
||||
n := 17
|
||||
if sps.UseSeparateColorPlane {
|
||||
if sps.ChromaFormat == chroma444 {
|
||||
if sps.SeparateColorPlaneFlag {
|
||||
if sps.ChromaFormatIDC == chroma444 {
|
||||
return n
|
||||
}
|
||||
}
|
||||
switch sps.ChromaFormat {
|
||||
switch sps.ChromaFormatIDC {
|
||||
case chromaMonochrome:
|
||||
return n
|
||||
case chroma420:
|
||||
|
@ -578,17 +578,17 @@ 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
|
||||
// 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
|
||||
// FrameHeightInMbs = (2 - ps.FrameMBSOnlyFlag) * PicHeightInMapUnits
|
||||
picWidthInMbs := sps.PicWidthInMBSMinus1 + 1
|
||||
picHeightInMapUnits := sps.PicHeightInMapUnitsMinus1 + 1
|
||||
frameHeightInMbs := (2 - flagVal(sps.FrameMbsOnly)) * picHeightInMapUnits
|
||||
frameHeightInMbs := (2 - flagVal(sps.FrameMBSOnlyFlag)) * picHeightInMapUnits
|
||||
picHeightInMbs := frameHeightInMbs / (1 + flagVal(header.FieldPic))
|
||||
picSizeInMbs := picWidthInMbs * picHeightInMbs
|
||||
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 {
|
||||
mbaffFrameFlag := 0
|
||||
if sps.MBAdaptiveFrameField && !header.FieldPic {
|
||||
if sps.MBAdaptiveFrameFieldFlag && !header.FieldPic {
|
||||
mbaffFrameFlag = 1
|
||||
}
|
||||
|
||||
|
@ -608,7 +608,7 @@ func CurrMbAddr(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 0
|
||||
|
@ -630,7 +630,7 @@ func NewSliceData(sliceContext *SliceContext, br *bits.BitReader) (*SliceData, e
|
|||
}
|
||||
}
|
||||
mbaffFrameFlag := 0
|
||||
if sliceContext.SPS.MBAdaptiveFrameField && !sliceContext.Slice.Header.FieldPic {
|
||||
if sliceContext.SPS.MBAdaptiveFrameFieldFlag && !sliceContext.Slice.Header.FieldPic {
|
||||
mbaffFrameFlag = 1
|
||||
}
|
||||
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)
|
||||
mbHeightC := 16 / SubHeightC(sliceContext.SPS)
|
||||
// if monochrome
|
||||
if sliceContext.SPS.ChromaFormat == chromaMonochrome || sliceContext.SPS.UseSeparateColorPlane {
|
||||
if sliceContext.SPS.ChromaFormatIDC == chromaMonochrome || sliceContext.SPS.SeparateColorPlaneFlag {
|
||||
mbWidthC = 0
|
||||
mbHeightC = 0
|
||||
}
|
||||
|
@ -824,7 +824,7 @@ func NewSliceData(sliceContext *SliceContext, br *bits.BitReader) (*SliceData, e
|
|||
if NumbSubMbPart(subMbType[mbPartIdx]) > 1 {
|
||||
noSubMbPartSizeLessThan8x8Flag = 0
|
||||
}
|
||||
} else if !sliceContext.SPS.Direct8x8Inference {
|
||||
} else if !sliceContext.SPS.Direct8x8InferenceFlag {
|
||||
noSubMbPartSizeLessThan8x8Flag = 0
|
||||
}
|
||||
}
|
||||
|
@ -876,7 +876,7 @@ func NewSliceData(sliceContext *SliceContext, br *bits.BitReader) (*SliceData, e
|
|||
}
|
||||
|
||||
// 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)
|
||||
if sliceContext.PPS.EntropyCodingMode == 1 {
|
||||
binarization := NewBinarization("Transform8x8Flag", sliceContext.Slice.Data)
|
||||
|
@ -956,10 +956,10 @@ func NewSliceContext(videoStream *VideoStream, nalUnit *NalUnit, rbsp []byte, sh
|
|||
idrPic = true
|
||||
}
|
||||
header := SliceHeader{}
|
||||
if sps.UseSeparateColorPlane {
|
||||
if sps.SeparateColorPlaneFlag {
|
||||
header.ChromaArrayType = 0
|
||||
} else {
|
||||
header.ChromaArrayType = sps.ChromaFormat
|
||||
header.ChromaArrayType = sps.ChromaFormatIDC
|
||||
}
|
||||
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")
|
||||
}
|
||||
|
||||
if sps.UseSeparateColorPlane {
|
||||
if sps.SeparateColorPlaneFlag {
|
||||
b, err := br.ReadBits(2)
|
||||
if err != nil {
|
||||
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
|
||||
// header.FrameNum = b.NextField("FrameNum", 0)
|
||||
if !sps.FrameMbsOnly {
|
||||
if !sps.FrameMBSOnlyFlag {
|
||||
b, err := br.ReadBits(1)
|
||||
if err != nil {
|
||||
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)
|
||||
if err != nil {
|
||||
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 {
|
||||
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
|
||||
}
|
||||
|
|
|
@ -7,12 +7,12 @@ var subWidthCTests = []struct {
|
|||
want int
|
||||
}{
|
||||
{SPS{}, 17},
|
||||
{SPS{ChromaFormat: 0}, 17},
|
||||
{SPS{ChromaFormat: 1}, 2},
|
||||
{SPS{ChromaFormat: 2}, 2},
|
||||
{SPS{ChromaFormat: 3}, 1},
|
||||
{SPS{ChromaFormat: 3, UseSeparateColorPlane: true}, 17},
|
||||
{SPS{ChromaFormat: 999}, 17},
|
||||
{SPS{ChromaFormatIDC: 0}, 17},
|
||||
{SPS{ChromaFormatIDC: 1}, 2},
|
||||
{SPS{ChromaFormatIDC: 2}, 2},
|
||||
{SPS{ChromaFormatIDC: 3}, 1},
|
||||
{SPS{ChromaFormatIDC: 3, SeparateColorPlaneFlag: true}, 17},
|
||||
{SPS{ChromaFormatIDC: 999}, 17},
|
||||
}
|
||||
|
||||
// TestSubWidthC tests that the correct SubWidthC is returned given
|
||||
|
@ -30,12 +30,12 @@ var subHeightCTests = []struct {
|
|||
want int
|
||||
}{
|
||||
{SPS{}, 17},
|
||||
{SPS{ChromaFormat: 0}, 17},
|
||||
{SPS{ChromaFormat: 1}, 2},
|
||||
{SPS{ChromaFormat: 2}, 1},
|
||||
{SPS{ChromaFormat: 3}, 1},
|
||||
{SPS{ChromaFormat: 3, UseSeparateColorPlane: true}, 17},
|
||||
{SPS{ChromaFormat: 999}, 17},
|
||||
{SPS{ChromaFormatIDC: 0}, 17},
|
||||
{SPS{ChromaFormatIDC: 1}, 2},
|
||||
{SPS{ChromaFormatIDC: 2}, 1},
|
||||
{SPS{ChromaFormatIDC: 3}, 1},
|
||||
{SPS{ChromaFormatIDC: 3, SeparateColorPlaneFlag: true}, 17},
|
||||
{SPS{ChromaFormatIDC: 999}, 17},
|
||||
}
|
||||
|
||||
// TestSubHeightC tests that the correct SubHeightC is returned given
|
||||
|
|
|
@ -2,112 +2,11 @@ package h264dec
|
|||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"bitbucket.org/ausocean/av/codec/h264/h264dec/bits"
|
||||
"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 (
|
||||
DefaultScalingMatrix4x4 = [][]int{
|
||||
{6, 13, 20, 28, 13, 20, 28, 32, 20, 28, 32, 37, 28, 32, 37, 42},
|
||||
|
@ -161,98 +60,62 @@ var (
|
|||
ScalingList8x8 = ScalingList4x4
|
||||
)
|
||||
|
||||
func isInList(l []int, term int) bool {
|
||||
for _, m := range l {
|
||||
if m == term {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
func debugPacket(name string, packet interface{}) {
|
||||
logger.Printf("debug: %s packet\n", name)
|
||||
for _, line := range strings.Split(fmt.Sprintf("%+v", packet), " ") {
|
||||
logger.Printf("debug: \t%#v\n", line)
|
||||
}
|
||||
}
|
||||
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
|
||||
// SPS describes a sequence parameter set as defined by section 7.3.2.1.1 in
|
||||
// the Specifications.
|
||||
type SPS struct {
|
||||
Profile int
|
||||
Constraint0 int
|
||||
Constraint1 int
|
||||
Constraint2 int
|
||||
Constraint3 int
|
||||
Constraint4 int
|
||||
Constraint5 int
|
||||
LevelIDC int
|
||||
SPSID int
|
||||
ChromaFormatIDC int
|
||||
SeparateColorPlaneFlag bool
|
||||
BitDepthLumaMinus8 int
|
||||
BitDepthChromaMinus8 int
|
||||
QPPrimeYZeroTransformBypassFlag bool
|
||||
SeqScalingMatrixPresentFlag bool
|
||||
SeqScalingListPresentFlag []bool
|
||||
ScalingList4x4 [][]int
|
||||
UseDefaultScalingMatrix4x4Flag []bool
|
||||
ScalingList8x8 [][]int
|
||||
UseDefaultScalingMatrix8x8Flag []bool
|
||||
Log2MaxFrameNumMinus4 int
|
||||
PicOrderCountType int
|
||||
Log2MaxPicOrderCntLSBMin4 int
|
||||
DeltaPicOrderAlwaysZeroFlag bool
|
||||
OffsetForNonRefPic int
|
||||
OffsetForTopToBottomField int
|
||||
NumRefFramesInPicOrderCntCycle int
|
||||
OffsetForRefFrameList []int
|
||||
MaxNumRefFrames int
|
||||
GapsInFrameNumValueAllowed bool
|
||||
PicWidthInMBSMinus1 int
|
||||
PicHeightInMapUnitsMinus1 int
|
||||
FrameMBSOnlyFlag bool
|
||||
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) {
|
||||
logger.Printf("debug: SPS RBSP %d bytes %d bits\n", len(rbsp), len(rbsp)*8)
|
||||
logger.Printf("debug: \t%#v\n", rbsp[0:8])
|
||||
sps := SPS{}
|
||||
br := bits.NewBitReader(bytes.NewReader(rbsp))
|
||||
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,
|
||||
[]field{
|
||||
|
@ -275,30 +138,30 @@ func NewSPS(rbsp []byte, showPacket bool) (*SPS, error) {
|
|||
if err != nil {
|
||||
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, err = readUe(br)
|
||||
sps.SPSID, err = readUe(br)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "could not parse ID")
|
||||
}
|
||||
|
||||
sps.ChromaFormat, err = readUe(br)
|
||||
sps.ChromaFormatIDC, err = readUe(br)
|
||||
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:
|
||||
isProfileIDC := []int{100, 110, 122, 244, 44, 83, 86, 118, 128, 138, 139, 134, 135}
|
||||
// SpecialProfileCase1
|
||||
if isInList(isProfileIDC, sps.Profile) {
|
||||
if sps.ChromaFormat == chroma444 {
|
||||
if sps.ChromaFormatIDC == chroma444 {
|
||||
// TODO: should probably deal with error here.
|
||||
b, err := br.ReadBits(1)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "could not read UseSeparateColorPlaneFlag")
|
||||
}
|
||||
sps.UseSeparateColorPlane = b == 1
|
||||
sps.SeparateColorPlaneFlag = b == 1
|
||||
}
|
||||
|
||||
sps.BitDepthLumaMinus8, err = readUe(br)
|
||||
|
@ -315,17 +178,17 @@ func NewSPS(rbsp []byte, showPacket bool) (*SPS, error) {
|
|||
if err != nil {
|
||||
return nil, errors.Wrap(err, "could not read QPrimeYZeroTransformBypass")
|
||||
}
|
||||
sps.QPrimeYZeroTransformBypass = b == 1
|
||||
sps.QPPrimeYZeroTransformBypassFlag = b == 1
|
||||
|
||||
b, err = br.ReadBits(1)
|
||||
if err != nil {
|
||||
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
|
||||
if sps.ChromaFormat != chroma444 {
|
||||
if sps.ChromaFormatIDC != chroma444 {
|
||||
max = 8
|
||||
}
|
||||
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 {
|
||||
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 {
|
||||
scalingList(
|
||||
br,
|
||||
|
@ -380,7 +243,7 @@ func NewSPS(rbsp []byte, showPacket bool) (*SPS, error) {
|
|||
if err != nil {
|
||||
return nil, errors.Wrap(err, "could not read DeltaPicOrderAlwaysZero")
|
||||
}
|
||||
sps.DeltaPicOrderAlwaysZero = b == 1
|
||||
sps.DeltaPicOrderAlwaysZeroFlag = b == 1
|
||||
|
||||
sps.OffsetForNonRefPic, err = readSe(br)
|
||||
if err != nil {
|
||||
|
@ -420,7 +283,7 @@ func NewSPS(rbsp []byte, showPacket bool) (*SPS, error) {
|
|||
}
|
||||
sps.GapsInFrameNumValueAllowed = b == 1
|
||||
|
||||
sps.PicWidthInMbsMinus1, err = readUe(br)
|
||||
sps.PicWidthInMBSMinus1, err = readUe(br)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "could not parse PicWidthInMbsMinus1")
|
||||
}
|
||||
|
@ -434,25 +297,25 @@ func NewSPS(rbsp []byte, showPacket bool) (*SPS, error) {
|
|||
if err != nil {
|
||||
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)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "could not read MBAdaptiveFrameField")
|
||||
}
|
||||
sps.MBAdaptiveFrameField = b == 1
|
||||
sps.MBAdaptiveFrameFieldFlag = b == 1
|
||||
}
|
||||
|
||||
err = readFlags(br, []flag{
|
||||
{&sps.Direct8x8Inference, "Direct8x8Inference"},
|
||||
{&sps.FrameCropping, "FrameCropping"},
|
||||
{&sps.Direct8x8InferenceFlag, "Direct8x8Inference"},
|
||||
{&sps.FrameCroppingFlag, "FrameCropping"},
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if sps.FrameCropping {
|
||||
if sps.FrameCroppingFlag {
|
||||
sps.FrameCropLeftOffset, err = readUe(br)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "could not parse FrameCropLeftOffset")
|
||||
|
@ -478,213 +341,361 @@ func NewSPS(rbsp []byte, showPacket bool) (*SPS, error) {
|
|||
if err != nil {
|
||||
return nil, errors.Wrap(err, "could not read VuiParametersPresent")
|
||||
}
|
||||
sps.VuiParametersPresent = b == 1
|
||||
sps.VUIParametersPresentFlag = b == 1
|
||||
|
||||
if sps.VuiParametersPresent {
|
||||
// vui_parameters
|
||||
if sps.VUIParametersPresentFlag {
|
||||
|
||||
} // 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 {
|
||||
return nil, errors.Wrap(err, "could not read AspectRatioInfoPresent")
|
||||
}
|
||||
p.AspectRatioInfoPresentFlag = b == 1
|
||||
|
||||
if p.AspectRatioInfoPresentFlag {
|
||||
b, err = br.ReadBits(8)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "could not read AspectRatio")
|
||||
}
|
||||
p.AspectRatioIDC = int(b)
|
||||
|
||||
EXTENDED_SAR := 999
|
||||
if p.AspectRatioIDC == EXTENDED_SAR {
|
||||
b, err = br.ReadBits(16)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "could not read SarWidth")
|
||||
}
|
||||
p.SARWidth = int(b)
|
||||
|
||||
b, err = br.ReadBits(16)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "could not read SarHeight")
|
||||
}
|
||||
p.SARHeight = int(b)
|
||||
}
|
||||
}
|
||||
|
||||
b, err = br.ReadBits(1)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "could not read OverscanInfoPresent")
|
||||
}
|
||||
p.OverscanInfoPresentFlag = b == 1
|
||||
|
||||
if p.OverscanInfoPresentFlag {
|
||||
b, err = br.ReadBits(1)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "could not read AspectRatioInfoPresent")
|
||||
return nil, errors.Wrap(err, "could not read OverscanAppropriate")
|
||||
}
|
||||
sps.AspectRatioInfoPresent = b == 1
|
||||
p.OverscanAppropriateFlag = b == 1
|
||||
}
|
||||
|
||||
if sps.AspectRatioInfoPresent {
|
||||
b, err = br.ReadBits(8)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "could not read AspectRatio")
|
||||
}
|
||||
sps.AspectRatio = int(b)
|
||||
b, err = br.ReadBits(1)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "could not read VideoSignalTypePresent")
|
||||
}
|
||||
p.VideoSignalTypePresentFlag = b == 1
|
||||
|
||||
EXTENDED_SAR := 999
|
||||
if sps.AspectRatio == EXTENDED_SAR {
|
||||
b, err = br.ReadBits(16)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "could not read SarWidth")
|
||||
}
|
||||
sps.SarWidth = int(b)
|
||||
|
||||
b, err = br.ReadBits(16)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "could not read SarHeight")
|
||||
}
|
||||
sps.SarHeight = int(b)
|
||||
}
|
||||
if p.VideoSignalTypePresentFlag {
|
||||
b, err = br.ReadBits(3)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "could not read VideoFormat")
|
||||
}
|
||||
p.VideoFormat = int(b)
|
||||
}
|
||||
|
||||
if p.VideoSignalTypePresentFlag {
|
||||
b, err = br.ReadBits(1)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "could not read VideoFullRange")
|
||||
}
|
||||
p.VideoFullRangeFlag = b == 1
|
||||
|
||||
b, err = br.ReadBits(1)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "could not read OverscanInfoPresent")
|
||||
return nil, errors.Wrap(err, "could not read ColorDescriptionPresent")
|
||||
}
|
||||
sps.OverscanInfoPresent = b == 1
|
||||
p.ColorDescriptionPresentFlag = b == 1
|
||||
|
||||
if sps.OverscanInfoPresent {
|
||||
b, err = br.ReadBits(1)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "could not read OverscanAppropriate")
|
||||
}
|
||||
sps.OverscanAppropriate = b == 1
|
||||
}
|
||||
|
||||
b, err = br.ReadBits(1)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "could not read VideoSignalTypePresent")
|
||||
}
|
||||
sps.VideoSignalTypePresent = b == 1
|
||||
|
||||
if sps.VideoSignalTypePresent {
|
||||
b, err = br.ReadBits(3)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "could not read VideoFormat")
|
||||
}
|
||||
sps.VideoFormat = int(b)
|
||||
}
|
||||
|
||||
if sps.VideoSignalTypePresent {
|
||||
b, err = br.ReadBits(1)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "could not read VideoFullRange")
|
||||
}
|
||||
sps.VideoFullRange = b == 1
|
||||
|
||||
b, err = br.ReadBits(1)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "could not read ColorDescriptionPresent")
|
||||
}
|
||||
sps.ColorDescriptionPresent = b == 1
|
||||
|
||||
if sps.ColorDescriptionPresent {
|
||||
err = readFields(br,
|
||||
[]field{
|
||||
{&sps.ColorPrimaries, "ColorPrimaries", 8},
|
||||
{&sps.TransferCharacteristics, "TransferCharacteristics", 8},
|
||||
{&sps.MatrixCoefficients, "MatrixCoefficients", 8},
|
||||
},
|
||||
)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
b, err = br.ReadBits(1)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "could not read ChromaLocInfoPresent")
|
||||
}
|
||||
sps.ChromaLocInfoPresent = b == 1
|
||||
|
||||
if sps.ChromaLocInfoPresent {
|
||||
sps.ChromaSampleLocTypeTopField, err = readUe(br)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "could not parse ChromaSampleLocTypeTopField")
|
||||
}
|
||||
|
||||
sps.ChromaSampleLocTypeBottomField, err = readUe(br)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "could not parse ChromaSampleLocTypeBottomField")
|
||||
}
|
||||
}
|
||||
|
||||
b, err = br.ReadBits(1)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "could not read TimingInfoPresent")
|
||||
}
|
||||
sps.TimingInfoPresent = b == 1
|
||||
|
||||
if sps.TimingInfoPresent {
|
||||
err := readFields(br, []field{
|
||||
{&sps.NumUnitsInTick, "NumUnitsInTick", 32},
|
||||
{&sps.TimeScale, "TimeScale", 32},
|
||||
})
|
||||
if p.ColorDescriptionPresentFlag {
|
||||
err = readFields(br,
|
||||
[]field{
|
||||
{&p.ColorPrimaries, "ColorPrimaries", 8},
|
||||
{&p.TransferCharacteristics, "TransferCharacteristics", 8},
|
||||
{&p.MatrixCoefficients, "MatrixCoefficients", 8},
|
||||
},
|
||||
)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
b, err = br.ReadBits(1)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "could not read FixedFrameRate")
|
||||
}
|
||||
sps.FixedFrameRate = b == 1
|
||||
}
|
||||
|
||||
b, err = br.ReadBits(1)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "could not read NalHrdParametersPresent")
|
||||
}
|
||||
sps.NalHrdParametersPresent = b == 1
|
||||
|
||||
if sps.NalHrdParametersPresent {
|
||||
err = hrdParameters()
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "could not get hrdParameters")
|
||||
}
|
||||
}
|
||||
|
||||
b, err = br.ReadBits(1)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "could not read VclHrdParametersPresent")
|
||||
}
|
||||
sps.VclHrdParametersPresent = b == 1
|
||||
|
||||
if sps.VclHrdParametersPresent {
|
||||
err = hrdParameters()
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "could not get hrdParameters")
|
||||
}
|
||||
}
|
||||
if sps.NalHrdParametersPresent || sps.VclHrdParametersPresent {
|
||||
b, err = br.ReadBits(1)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "could not read LowHrdDelay")
|
||||
}
|
||||
sps.LowHrdDelay = b == 1
|
||||
}
|
||||
|
||||
err := readFlags(br, []flag{
|
||||
{&sps.PicStructPresent, "PicStructPresent"},
|
||||
{&sps.BitstreamRestriction, "BitStreamRestriction"},
|
||||
})
|
||||
|
||||
if sps.BitstreamRestriction {
|
||||
b, err = br.ReadBits(1)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "could not read MotionVectorsOverPicBoundaries")
|
||||
}
|
||||
sps.MotionVectorsOverPicBoundaries = b == 1
|
||||
|
||||
sps.MaxBytesPerPicDenom, err = readUe(br)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "could not parse MaxBytesPerPicDenom")
|
||||
}
|
||||
|
||||
sps.MaxBitsPerMbDenom, err = readUe(br)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "could not parse MaxBitsPerMbDenom")
|
||||
}
|
||||
|
||||
sps.Log2MaxMvLengthHorizontal, err = readUe(br)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "could not parse Log2MaxMvLengthHorizontal")
|
||||
}
|
||||
|
||||
sps.Log2MaxMvLengthVertical, err = readUe(br)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "could not parse Log2MaxMvLengthVertical")
|
||||
}
|
||||
|
||||
sps.MaxNumReorderFrames, err = readUe(br)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "could not parse MaxNumReorderFrames")
|
||||
}
|
||||
|
||||
sps.MaxDecFrameBuffering, err = readUe(br)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "could not parse MaxDecFrameBuffering")
|
||||
}
|
||||
}
|
||||
|
||||
} // End VuiParameters Annex E.1.1
|
||||
if showPacket {
|
||||
debugPacket("SPS", sps)
|
||||
}
|
||||
return &sps, nil
|
||||
|
||||
b, err = br.ReadBits(1)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "could not read ChromaLocInfoPresent")
|
||||
}
|
||||
p.ChromaLocInfoPresentFlag = b == 1
|
||||
|
||||
if p.ChromaLocInfoPresentFlag {
|
||||
p.ChromaSampleLocTypeTopField, err = readUe(br)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "could not parse ChromaSampleLocTypeTopField")
|
||||
}
|
||||
|
||||
p.ChromaSampleLocTypeBottomField, err = readUe(br)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "could not parse ChromaSampleLocTypeBottomField")
|
||||
}
|
||||
}
|
||||
|
||||
b, err = br.ReadBits(1)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "could not read TimingInfoPresent")
|
||||
}
|
||||
p.TimingInfoPresentFlag = b == 1
|
||||
|
||||
if p.TimingInfoPresentFlag {
|
||||
err := readFields(br, []field{
|
||||
{&p.NumUnitsInTick, "NumUnitsInTick", 32},
|
||||
{&p.TimeScale, "TimeScale", 32},
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
b, err = br.ReadBits(1)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "could not read FixedFrameRate")
|
||||
}
|
||||
p.FixedFrameRateFlag = b == 1
|
||||
}
|
||||
|
||||
b, err = br.ReadBits(1)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "could not read NalHrdParametersPresent")
|
||||
}
|
||||
p.NALHRDParametersPresentFlag = b == 1
|
||||
|
||||
if p.NALHRDParametersPresentFlag {
|
||||
p.NALHRDParameters, err = NewHRDParameters(br)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "could not get hrdParameters")
|
||||
}
|
||||
}
|
||||
|
||||
b, err = br.ReadBits(1)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "could not read VclHrdParametersPresent")
|
||||
}
|
||||
p.VCLHRDParametersPresentFlag = b == 1
|
||||
|
||||
if p.VCLHRDParametersPresentFlag {
|
||||
p.VCLHRDParameters, err = NewHRDParameters(br)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "could not get hrdParameters")
|
||||
}
|
||||
}
|
||||
if p.NALHRDParametersPresentFlag || p.VCLHRDParametersPresentFlag {
|
||||
b, err = br.ReadBits(1)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "could not read LowHrdDelay")
|
||||
}
|
||||
p.LowDelayHRDFlag = b == 1
|
||||
}
|
||||
|
||||
err = readFlags(br, []flag{
|
||||
{&p.PicStructPresentFlag, "PicStructPresent"},
|
||||
{&p.BitstreamRestrictionFlag, "BitStreamRestriction"},
|
||||
})
|
||||
|
||||
if p.BitstreamRestrictionFlag {
|
||||
b, err = br.ReadBits(1)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "could not read MotionVectorsOverPicBoundaries")
|
||||
}
|
||||
p.MotionVectorsOverPicBoundariesFlag = b == 1
|
||||
|
||||
p.MaxBytesPerPicDenom, err = readUe(br)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "could not parse MaxBytesPerPicDenom")
|
||||
}
|
||||
|
||||
p.MaxBitsPerMBDenom, err = readUe(br)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "could not parse MaxBitsPerMbDenom")
|
||||
}
|
||||
|
||||
p.Log2MaxMVLengthHorizontal, err = readUe(br)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "could not parse Log2MaxMvLengthHorizontal")
|
||||
}
|
||||
|
||||
p.Log2MaxMVLengthVertical, err = readUe(br)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "could not parse Log2MaxMvLengthVertical")
|
||||
}
|
||||
|
||||
p.MaxNumReorderFrames, err = readUe(br)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "could not parse MaxNumReorderFrames")
|
||||
}
|
||||
|
||||
p.MaxDecFrameBuffering, err = readUe(br)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "could not parse MaxDecFrameBuffering")
|
||||
}
|
||||
}
|
||||
return p, nil
|
||||
}
|
||||
|
||||
// HRDParameters describes hypothetical reference decoder parameters as defined
|
||||
// by section E.1.2 in the specifications.
|
||||
type HRDParameters struct {
|
||||
CPBCntMinus1 int
|
||||
BitRateScale int
|
||||
CPBSizeScale int
|
||||
BitRateValueMinus1 []int
|
||||
CPBSizeValueMinus1 []int
|
||||
CBRFlag []bool
|
||||
InitialCPBRemovalDelayLenMinus1 int
|
||||
CPBRemovalDelayLenMinus1 int
|
||||
DPBOutputDelayLenMinus1 int
|
||||
TimeOffsetLen int
|
||||
}
|
||||
|
||||
// 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
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue