2019-07-19 08:50:39 +03:00
|
|
|
package h264dec
|
2019-07-18 07:32:42 +03:00
|
|
|
|
|
|
|
import (
|
|
|
|
"bytes"
|
2019-07-30 03:46:08 +03:00
|
|
|
"fmt"
|
2019-07-18 07:32:42 +03:00
|
|
|
|
2019-07-19 09:14:45 +03:00
|
|
|
"bitbucket.org/ausocean/av/codec/h264/h264dec/bits"
|
2019-07-18 07:32:42 +03:00
|
|
|
"github.com/pkg/errors"
|
|
|
|
)
|
|
|
|
|
|
|
|
var (
|
|
|
|
DefaultScalingMatrix4x4 = [][]int{
|
|
|
|
{6, 13, 20, 28, 13, 20, 28, 32, 20, 28, 32, 37, 28, 32, 37, 42},
|
|
|
|
{10, 14, 20, 24, 14, 20, 24, 27, 20, 24, 27, 30, 24, 27, 30, 34},
|
|
|
|
}
|
|
|
|
|
|
|
|
DefaultScalingMatrix8x8 = [][]int{
|
|
|
|
{6, 10, 13, 16, 18, 23, 25, 27,
|
|
|
|
10, 11, 16, 18, 23, 25, 27, 29,
|
|
|
|
13, 16, 18, 23, 25, 27, 29, 31,
|
|
|
|
16, 18, 23, 25, 27, 29, 31, 33,
|
|
|
|
18, 23, 25, 27, 29, 31, 33, 36,
|
|
|
|
23, 25, 27, 29, 31, 33, 36, 38,
|
|
|
|
25, 27, 29, 31, 33, 36, 38, 40,
|
|
|
|
27, 29, 31, 33, 36, 38, 40, 42},
|
|
|
|
{9, 13, 15, 17, 19, 21, 22, 24,
|
|
|
|
13, 13, 17, 19, 21, 22, 24, 25,
|
|
|
|
15, 17, 19, 21, 22, 24, 25, 27,
|
|
|
|
17, 19, 21, 22, 24, 25, 27, 28,
|
|
|
|
19, 21, 22, 24, 25, 27, 28, 30,
|
|
|
|
21, 22, 24, 25, 27, 28, 30, 32,
|
|
|
|
22, 24, 25, 27, 28, 30, 32, 33,
|
|
|
|
24, 25, 27, 28, 30, 32, 33, 35},
|
|
|
|
}
|
|
|
|
Default4x4IntraList = []int{6, 13, 13, 20, 20, 20, 38, 38, 38, 38, 32, 32, 32, 37, 37, 42}
|
|
|
|
Default4x4InterList = []int{10, 14, 14, 20, 20, 20, 24, 24, 24, 24, 27, 27, 27, 30, 30, 34}
|
|
|
|
Default8x8IntraList = []int{
|
|
|
|
6, 10, 10, 13, 11, 13, 16, 16, 16, 16, 18, 18, 18, 18, 18, 23,
|
|
|
|
23, 23, 23, 23, 23, 25, 25, 25, 25, 25, 25, 25, 27, 27, 27, 27,
|
|
|
|
27, 27, 27, 27, 29, 29, 29, 29, 29, 29, 29, 31, 31, 31, 31, 31,
|
|
|
|
31, 33, 33, 33, 33, 33, 36, 36, 36, 36, 38, 38, 38, 40, 40, 42}
|
|
|
|
Default8x8InterList = []int{
|
|
|
|
9, 13, 13, 15, 13, 15, 17, 17, 17, 17, 19, 19, 19, 19, 19, 21,
|
|
|
|
21, 21, 21, 21, 21, 22, 22, 22, 22, 22, 22, 22, 24, 24, 24, 24,
|
|
|
|
24, 24, 24, 24, 25, 25, 25, 25, 25, 25, 25, 27, 27, 27, 27, 27,
|
|
|
|
27, 28, 28, 28, 28, 28, 30, 30, 30, 30, 32, 32, 32, 33, 33, 35}
|
|
|
|
ScalingList4x4 = map[int][]int{
|
|
|
|
0: Default4x4IntraList,
|
|
|
|
1: Default4x4IntraList,
|
|
|
|
2: Default4x4IntraList,
|
|
|
|
3: Default4x4InterList,
|
|
|
|
4: Default4x4InterList,
|
|
|
|
5: Default4x4InterList,
|
|
|
|
6: Default8x8IntraList,
|
|
|
|
7: Default8x8InterList,
|
|
|
|
8: Default8x8IntraList,
|
|
|
|
9: Default8x8InterList,
|
|
|
|
10: Default8x8IntraList,
|
|
|
|
11: Default8x8InterList,
|
|
|
|
}
|
|
|
|
ScalingList8x8 = ScalingList4x4
|
|
|
|
)
|
|
|
|
|
2019-07-21 15:41:24 +03:00
|
|
|
// SPS describes a sequence parameter set as defined by section 7.3.2.1.1 in
|
|
|
|
// the Specifications.
|
|
|
|
type SPS struct {
|
2019-07-30 03:46:08 +03:00
|
|
|
Profile uint8
|
|
|
|
Constraint0 bool
|
|
|
|
Constraint1 bool
|
|
|
|
Constraint2 bool
|
|
|
|
Constraint3 bool
|
|
|
|
Constraint4 bool
|
|
|
|
Constraint5 bool
|
|
|
|
LevelIDC uint8
|
|
|
|
SPSID uint64
|
|
|
|
ChromaFormatIDC uint64
|
2019-07-21 15:41:24 +03:00
|
|
|
SeparateColorPlaneFlag bool
|
2019-07-30 03:46:08 +03:00
|
|
|
BitDepthLumaMinus8 uint64
|
|
|
|
BitDepthChromaMinus8 uint64
|
2019-07-21 15:41:24 +03:00
|
|
|
QPPrimeYZeroTransformBypassFlag bool
|
|
|
|
SeqScalingMatrixPresentFlag bool
|
|
|
|
SeqScalingListPresentFlag []bool
|
2019-07-30 03:46:08 +03:00
|
|
|
ScalingList4x4 [][]uint64
|
2019-07-21 15:41:24 +03:00
|
|
|
UseDefaultScalingMatrix4x4Flag []bool
|
2019-07-30 03:46:08 +03:00
|
|
|
ScalingList8x8 [][]uint64
|
2019-07-21 15:41:24 +03:00
|
|
|
UseDefaultScalingMatrix8x8Flag []bool
|
2019-07-30 03:46:08 +03:00
|
|
|
Log2MaxFrameNumMinus4 uint64
|
|
|
|
PicOrderCountType uint64
|
|
|
|
Log2MaxPicOrderCntLSBMin4 uint64
|
2019-07-21 15:41:24 +03:00
|
|
|
DeltaPicOrderAlwaysZeroFlag bool
|
2019-07-30 03:46:08 +03:00
|
|
|
OffsetForNonRefPic int64
|
|
|
|
OffsetForTopToBottomField int64
|
|
|
|
NumRefFramesInPicOrderCntCycle uint64
|
2019-07-21 15:41:24 +03:00
|
|
|
OffsetForRefFrameList []int
|
2019-07-30 03:46:08 +03:00
|
|
|
MaxNumRefFrames uint64
|
2019-07-21 15:41:24 +03:00
|
|
|
GapsInFrameNumValueAllowed bool
|
2019-07-30 03:46:08 +03:00
|
|
|
PicWidthInMBSMinus1 uint64
|
|
|
|
PicHeightInMapUnitsMinus1 uint64
|
2019-07-21 15:41:24 +03:00
|
|
|
FrameMBSOnlyFlag bool
|
|
|
|
MBAdaptiveFrameFieldFlag bool
|
|
|
|
Direct8x8InferenceFlag bool
|
|
|
|
FrameCroppingFlag bool
|
2019-07-30 03:46:08 +03:00
|
|
|
FrameCropLeftOffset uint64
|
|
|
|
FrameCropRightOffset uint64
|
|
|
|
FrameCropTopOffset uint64
|
|
|
|
FrameCropBottomOffset uint64
|
2019-07-21 15:41:24 +03:00
|
|
|
VUIParametersPresentFlag bool
|
|
|
|
VUIParameters *VUIParameters
|
2019-07-18 07:32:42 +03:00
|
|
|
}
|
2019-07-21 15:41:24 +03:00
|
|
|
|
|
|
|
// 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.
|
2019-07-18 07:32:42 +03:00
|
|
|
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))
|
2019-07-30 03:46:08 +03:00
|
|
|
r := newFieldReader(br)
|
|
|
|
|
|
|
|
sps.Profile = uint8(r.readBits(8))
|
|
|
|
sps.Constraint0 = r.readBits(1) == 1
|
|
|
|
sps.Constraint1 = r.readBits(1) == 1
|
|
|
|
sps.Constraint2 = r.readBits(1) == 1
|
|
|
|
sps.Constraint3 = r.readBits(1) == 1
|
|
|
|
sps.Constraint4 = r.readBits(1) == 1
|
|
|
|
sps.Constraint5 = r.readBits(1) == 1
|
|
|
|
r.readBits(2) // 2 reserved bits.
|
|
|
|
sps.LevelIDC = uint8(r.readBits(8))
|
|
|
|
sps.SPSID = r.readUe()
|
|
|
|
sps.ChromaFormatIDC = r.readUe()
|
2019-07-18 07:32:42 +03:00
|
|
|
|
|
|
|
// This should be done only for certain ProfileIDC:
|
|
|
|
isProfileIDC := []int{100, 110, 122, 244, 44, 83, 86, 118, 128, 138, 139, 134, 135}
|
|
|
|
// SpecialProfileCase1
|
2019-07-30 03:46:08 +03:00
|
|
|
if isInList(isProfileIDC, int(sps.Profile)) {
|
2019-07-21 15:41:24 +03:00
|
|
|
if sps.ChromaFormatIDC == chroma444 {
|
2019-07-18 07:32:42 +03:00
|
|
|
// TODO: should probably deal with error here.
|
2019-07-30 03:46:08 +03:00
|
|
|
sps.SeparateColorPlaneFlag = r.readBits(1) == 1
|
2019-07-18 07:32:42 +03:00
|
|
|
}
|
|
|
|
|
2019-07-30 03:46:08 +03:00
|
|
|
sps.BitDepthLumaMinus8 = r.readUe()
|
|
|
|
sps.BitDepthChromaMinus8 = r.readUe()
|
|
|
|
sps.QPPrimeYZeroTransformBypassFlag = r.readBits(1) == 1
|
|
|
|
sps.SeqScalingMatrixPresentFlag = r.readBits(1) == 1
|
2019-07-18 07:32:42 +03:00
|
|
|
|
2019-07-21 15:41:24 +03:00
|
|
|
if sps.SeqScalingMatrixPresentFlag {
|
2019-07-18 07:32:42 +03:00
|
|
|
max := 12
|
2019-07-21 15:41:24 +03:00
|
|
|
if sps.ChromaFormatIDC != chroma444 {
|
2019-07-18 07:32:42 +03:00
|
|
|
max = 8
|
|
|
|
}
|
|
|
|
logger.Printf("debug: \tbuilding Scaling matrix for %d elements\n", max)
|
|
|
|
for i := 0; i < max; i++ {
|
2019-07-30 03:46:08 +03:00
|
|
|
sps.SeqScalingListPresentFlag = append(sps.SeqScalingListPresentFlag, r.readBits(1) == 1)
|
2019-07-18 07:32:42 +03:00
|
|
|
|
2019-07-21 15:41:24 +03:00
|
|
|
if sps.SeqScalingListPresentFlag[i] {
|
2019-07-18 07:32:42 +03:00
|
|
|
if i < 6 {
|
|
|
|
scalingList(
|
|
|
|
br,
|
|
|
|
ScalingList4x4[i],
|
|
|
|
16,
|
|
|
|
DefaultScalingMatrix4x4[i])
|
|
|
|
// 4x4: Page 75 bottom
|
|
|
|
} else {
|
|
|
|
// 8x8 Page 76 top
|
|
|
|
scalingList(
|
|
|
|
br,
|
|
|
|
ScalingList8x8[i],
|
|
|
|
64,
|
|
|
|
DefaultScalingMatrix8x8[i-6])
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} // End SpecialProfileCase1
|
|
|
|
|
|
|
|
// showSPS()
|
|
|
|
// return sps
|
|
|
|
// Possibly wrong due to no scaling list being built
|
2019-07-30 03:46:08 +03:00
|
|
|
sps.Log2MaxFrameNumMinus4 = r.readUe()
|
|
|
|
sps.PicOrderCountType = r.readUe()
|
2019-07-18 07:32:42 +03:00
|
|
|
|
|
|
|
if sps.PicOrderCountType == 0 {
|
2019-07-30 03:46:08 +03:00
|
|
|
sps.Log2MaxPicOrderCntLSBMin4 = r.readUe()
|
2019-07-18 07:32:42 +03:00
|
|
|
} else if sps.PicOrderCountType == 1 {
|
2019-07-30 03:46:08 +03:00
|
|
|
sps.DeltaPicOrderAlwaysZeroFlag = r.readBits(1) == 1
|
|
|
|
sps.OffsetForNonRefPic = int64(r.readSe())
|
|
|
|
sps.OffsetForTopToBottomField = int64(r.readSe())
|
|
|
|
sps.NumRefFramesInPicOrderCntCycle = r.readUe()
|
2019-07-18 07:32:42 +03:00
|
|
|
|
2019-07-30 03:46:08 +03:00
|
|
|
for i := 0; i < int(sps.NumRefFramesInPicOrderCntCycle); i++ {
|
|
|
|
sps.OffsetForRefFrameList = append(sps.OffsetForRefFrameList, r.readSe())
|
2019-07-18 07:32:42 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
2019-07-30 03:46:08 +03:00
|
|
|
sps.MaxNumRefFrames = r.readUe()
|
|
|
|
sps.GapsInFrameNumValueAllowed = r.readBits(1) == 1
|
|
|
|
sps.PicWidthInMBSMinus1 = r.readUe()
|
|
|
|
sps.PicHeightInMapUnitsMinus1 = r.readUe()
|
|
|
|
sps.FrameMBSOnlyFlag = r.readBits(1) == 1
|
2019-07-18 07:32:42 +03:00
|
|
|
|
2019-07-21 15:41:24 +03:00
|
|
|
if !sps.FrameMBSOnlyFlag {
|
2019-07-30 03:46:08 +03:00
|
|
|
sps.MBAdaptiveFrameFieldFlag = r.readBits(1) == 1
|
2019-07-18 07:32:42 +03:00
|
|
|
}
|
|
|
|
|
2019-07-30 03:46:08 +03:00
|
|
|
sps.Direct8x8InferenceFlag = r.readBits(1) == 1
|
|
|
|
sps.FrameCroppingFlag = r.readBits(1) == 1
|
2019-07-18 07:32:42 +03:00
|
|
|
|
2019-07-21 15:41:24 +03:00
|
|
|
if sps.FrameCroppingFlag {
|
2019-07-30 03:46:08 +03:00
|
|
|
sps.FrameCropLeftOffset = r.readUe()
|
|
|
|
sps.FrameCropRightOffset = r.readUe()
|
|
|
|
sps.FrameCropTopOffset = r.readUe()
|
|
|
|
sps.FrameCropBottomOffset = r.readUe()
|
2019-07-18 07:32:42 +03:00
|
|
|
}
|
|
|
|
|
2019-07-30 03:46:08 +03:00
|
|
|
sps.VUIParametersPresentFlag = r.readBits(1) == 1
|
2019-07-18 07:32:42 +03:00
|
|
|
|
2019-07-21 15:41:24 +03:00
|
|
|
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
|
2019-07-30 03:46:08 +03:00
|
|
|
AspectRatioIDC uint8
|
|
|
|
SARWidth uint32
|
|
|
|
SARHeight uint32
|
2019-07-21 15:41:24 +03:00
|
|
|
OverscanInfoPresentFlag bool
|
|
|
|
OverscanAppropriateFlag bool
|
|
|
|
VideoSignalTypePresentFlag bool
|
2019-07-30 03:46:08 +03:00
|
|
|
VideoFormat uint8
|
2019-07-21 15:41:24 +03:00
|
|
|
VideoFullRangeFlag bool
|
|
|
|
ColorDescriptionPresentFlag bool
|
2019-07-30 03:46:08 +03:00
|
|
|
ColorPrimaries uint8
|
|
|
|
TransferCharacteristics uint8
|
|
|
|
MatrixCoefficients uint8
|
2019-07-21 15:41:24 +03:00
|
|
|
ChromaLocInfoPresentFlag bool
|
2019-07-30 03:46:08 +03:00
|
|
|
ChromaSampleLocTypeTopField uint64
|
|
|
|
ChromaSampleLocTypeBottomField uint64
|
2019-07-21 15:41:24 +03:00
|
|
|
TimingInfoPresentFlag bool
|
2019-07-30 03:46:08 +03:00
|
|
|
NumUnitsInTick uint32
|
|
|
|
TimeScale uint32
|
2019-07-21 15:41:24 +03:00
|
|
|
FixedFrameRateFlag bool
|
|
|
|
NALHRDParametersPresentFlag bool
|
|
|
|
NALHRDParameters *HRDParameters
|
|
|
|
VCLHRDParametersPresentFlag bool
|
|
|
|
VCLHRDParameters *HRDParameters
|
|
|
|
LowDelayHRDFlag bool
|
|
|
|
PicStructPresentFlag bool
|
|
|
|
BitstreamRestrictionFlag bool
|
|
|
|
MotionVectorsOverPicBoundariesFlag bool
|
2019-07-30 03:46:08 +03:00
|
|
|
MaxBytesPerPicDenom uint64
|
|
|
|
MaxBitsPerMBDenom uint64
|
|
|
|
Log2MaxMVLengthHorizontal uint64
|
|
|
|
Log2MaxMVLengthVertical uint64
|
|
|
|
MaxNumReorderFrames uint64
|
|
|
|
MaxDecFrameBuffering uint64
|
2019-07-21 15:41:24 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
// 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{}
|
2019-07-30 03:46:08 +03:00
|
|
|
r := newFieldReader(br)
|
2019-07-21 15:41:24 +03:00
|
|
|
|
2019-07-30 03:46:08 +03:00
|
|
|
p.AspectRatioInfoPresentFlag = r.readBits(1) == 1
|
2019-07-21 15:41:24 +03:00
|
|
|
|
|
|
|
if p.AspectRatioInfoPresentFlag {
|
2019-07-30 03:46:08 +03:00
|
|
|
p.AspectRatioIDC = uint8(r.readBits(8))
|
2019-07-18 07:32:42 +03:00
|
|
|
|
2019-07-21 15:41:24 +03:00
|
|
|
EXTENDED_SAR := 999
|
2019-07-30 03:46:08 +03:00
|
|
|
if int(p.AspectRatioIDC) == EXTENDED_SAR {
|
|
|
|
p.SARWidth = uint32(r.readBits(16))
|
|
|
|
p.SARHeight = uint32(r.readBits(16))
|
2019-07-18 07:32:42 +03:00
|
|
|
}
|
2019-07-21 15:41:24 +03:00
|
|
|
}
|
|
|
|
|
2019-07-30 03:46:08 +03:00
|
|
|
p.OverscanInfoPresentFlag = r.readBits(1) == 1
|
2019-07-18 07:32:42 +03:00
|
|
|
|
2019-07-21 15:41:24 +03:00
|
|
|
if p.OverscanInfoPresentFlag {
|
2019-07-30 03:46:08 +03:00
|
|
|
p.OverscanAppropriateFlag = r.readBits(1) == 1
|
2019-07-21 15:41:24 +03:00
|
|
|
}
|
2019-07-18 07:32:42 +03:00
|
|
|
|
2019-07-30 03:46:08 +03:00
|
|
|
p.VideoSignalTypePresentFlag = r.readBits(1) == 1
|
2019-07-21 15:41:24 +03:00
|
|
|
|
|
|
|
if p.VideoSignalTypePresentFlag {
|
2019-07-30 03:46:08 +03:00
|
|
|
p.VideoFormat = uint8(r.readBits(3))
|
2019-07-21 15:41:24 +03:00
|
|
|
}
|
2019-07-18 07:32:42 +03:00
|
|
|
|
2019-07-21 15:41:24 +03:00
|
|
|
if p.VideoSignalTypePresentFlag {
|
2019-07-30 03:46:08 +03:00
|
|
|
p.VideoFullRangeFlag = r.readBits(1) == 1
|
|
|
|
p.ColorDescriptionPresentFlag = r.readBits(1) == 1
|
2019-07-18 07:32:42 +03:00
|
|
|
|
2019-07-21 15:41:24 +03:00
|
|
|
if p.ColorDescriptionPresentFlag {
|
2019-07-30 03:46:08 +03:00
|
|
|
p.ColorPrimaries = uint8(r.readBits(8))
|
|
|
|
p.TransferCharacteristics = uint8(r.readBits(8))
|
|
|
|
p.MatrixCoefficients = uint8(r.readBits(8))
|
2019-07-21 15:41:24 +03:00
|
|
|
}
|
|
|
|
}
|
2019-07-30 03:46:08 +03:00
|
|
|
p.ChromaLocInfoPresentFlag = r.readBits(1) == 1
|
2019-07-21 15:41:24 +03:00
|
|
|
|
|
|
|
if p.ChromaLocInfoPresentFlag {
|
2019-07-30 03:46:08 +03:00
|
|
|
p.ChromaSampleLocTypeTopField = uint64(r.readUe())
|
|
|
|
p.ChromaSampleLocTypeBottomField = uint64(r.readUe())
|
2019-07-21 15:41:24 +03:00
|
|
|
}
|
2019-07-18 07:32:42 +03:00
|
|
|
|
2019-07-30 03:46:08 +03:00
|
|
|
p.TimingInfoPresentFlag = r.readBits(1) == 1
|
2019-07-18 07:32:42 +03:00
|
|
|
|
2019-07-21 15:41:24 +03:00
|
|
|
if p.TimingInfoPresentFlag {
|
2019-07-30 03:46:08 +03:00
|
|
|
p.NumUnitsInTick = uint32(r.readBits(32))
|
|
|
|
p.TimeScale = uint32(r.readBits(32))
|
|
|
|
p.FixedFrameRateFlag = r.readBits(1) == 1
|
2019-07-21 15:41:24 +03:00
|
|
|
}
|
2019-07-18 07:32:42 +03:00
|
|
|
|
2019-07-30 03:46:08 +03:00
|
|
|
p.NALHRDParametersPresentFlag = r.readBits(1) == 1
|
2019-07-18 07:32:42 +03:00
|
|
|
|
2019-07-30 03:46:08 +03:00
|
|
|
var err error
|
2019-07-21 15:41:24 +03:00
|
|
|
if p.NALHRDParametersPresentFlag {
|
|
|
|
p.NALHRDParameters, err = NewHRDParameters(br)
|
|
|
|
if err != nil {
|
|
|
|
return nil, errors.Wrap(err, "could not get hrdParameters")
|
2019-07-18 07:32:42 +03:00
|
|
|
}
|
2019-07-21 15:41:24 +03:00
|
|
|
}
|
2019-07-18 07:32:42 +03:00
|
|
|
|
2019-07-30 03:46:08 +03:00
|
|
|
p.VCLHRDParametersPresentFlag = r.readBits(1) == 1
|
2019-07-21 15:41:24 +03:00
|
|
|
|
|
|
|
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 {
|
2019-07-30 03:46:08 +03:00
|
|
|
p.LowDelayHRDFlag = r.readBits(1) == 1
|
2019-07-21 15:41:24 +03:00
|
|
|
}
|
2019-07-18 07:32:42 +03:00
|
|
|
|
2019-07-30 03:46:08 +03:00
|
|
|
p.PicStructPresentFlag = r.readBits(1) == 1
|
|
|
|
p.BitstreamRestrictionFlag = r.readBits(1) == 1
|
2019-07-18 07:32:42 +03:00
|
|
|
|
2019-07-21 15:41:24 +03:00
|
|
|
if p.BitstreamRestrictionFlag {
|
2019-07-30 03:46:08 +03:00
|
|
|
p.MotionVectorsOverPicBoundariesFlag = r.readBits(1) == 1
|
|
|
|
p.MaxBytesPerPicDenom = r.readUe()
|
|
|
|
p.MaxBitsPerMBDenom = r.readUe()
|
|
|
|
p.Log2MaxMVLengthHorizontal = r.readUe()
|
|
|
|
p.Log2MaxMVLengthVertical = r.readUe()
|
|
|
|
p.MaxNumReorderFrames = r.readUe()
|
|
|
|
p.MaxDecFrameBuffering = r.readUe()
|
2019-07-21 15:41:24 +03:00
|
|
|
}
|
|
|
|
return p, nil
|
|
|
|
}
|
2019-07-18 07:32:42 +03:00
|
|
|
|
2019-07-21 15:41:24 +03:00
|
|
|
// HRDParameters describes hypothetical reference decoder parameters as defined
|
|
|
|
// by section E.1.2 in the specifications.
|
|
|
|
type HRDParameters struct {
|
2019-07-30 03:46:08 +03:00
|
|
|
CPBCntMinus1 uint64
|
|
|
|
BitRateScale uint8
|
|
|
|
CPBSizeScale uint8
|
|
|
|
BitRateValueMinus1 []uint64
|
|
|
|
CPBSizeValueMinus1 []uint64
|
2019-07-21 15:41:24 +03:00
|
|
|
CBRFlag []bool
|
2019-07-30 03:46:08 +03:00
|
|
|
InitialCPBRemovalDelayLenMinus1 uint8
|
|
|
|
CPBRemovalDelayLenMinus1 uint8
|
|
|
|
DPBOutputDelayLenMinus1 uint8
|
|
|
|
TimeOffsetLen uint8
|
2019-07-21 15:41:24 +03:00
|
|
|
}
|
2019-07-18 07:32:42 +03:00
|
|
|
|
2019-07-21 15:41:24 +03:00
|
|
|
// 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{}
|
2019-07-30 03:46:08 +03:00
|
|
|
r := newFieldReader(br)
|
2019-07-18 07:32:42 +03:00
|
|
|
|
2019-07-30 03:46:08 +03:00
|
|
|
h.CPBCntMinus1 = r.readUe()
|
|
|
|
h.BitRateScale = uint8(r.readBits(4))
|
|
|
|
h.CPBSizeScale = uint8(r.readBits(4))
|
2019-07-21 15:41:24 +03:00
|
|
|
|
|
|
|
// SchedSelIdx E1.2
|
2019-07-30 03:46:08 +03:00
|
|
|
for sseli := 0; sseli <= int(h.CPBCntMinus1); sseli++ {
|
|
|
|
h.BitRateValueMinus1 = append(h.BitRateValueMinus1, r.readUe())
|
|
|
|
h.CPBSizeValueMinus1 = append(h.CPBSizeValueMinus1, r.readUe())
|
2019-07-21 15:41:24 +03:00
|
|
|
|
|
|
|
if v, _ := br.ReadBits(1); v == 1 {
|
|
|
|
h.CBRFlag = append(h.CBRFlag, true)
|
|
|
|
} else {
|
|
|
|
h.CBRFlag = append(h.CBRFlag, false)
|
|
|
|
}
|
|
|
|
|
2019-07-30 03:46:08 +03:00
|
|
|
h.InitialCPBRemovalDelayLenMinus1 = uint8(r.readBits(5))
|
|
|
|
h.CPBRemovalDelayLenMinus1 = uint8(r.readBits(5))
|
|
|
|
h.DPBOutputDelayLenMinus1 = uint8(r.readBits(5))
|
|
|
|
h.TimeOffsetLen = uint8(r.readBits(5))
|
|
|
|
}
|
|
|
|
|
|
|
|
if r.err() != nil {
|
|
|
|
return nil, fmt.Errorf("error from fieldReader: %v", r.err())
|
2019-07-21 15:41:24 +03:00
|
|
|
}
|
|
|
|
return h, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func isInList(l []int, term int) bool {
|
|
|
|
for _, m := range l {
|
|
|
|
if m == term {
|
|
|
|
return true
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return false
|
|
|
|
}
|
2019-07-18 07:32:42 +03:00
|
|
|
|
2019-07-21 15:41:24 +03:00
|
|
|
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)
|
2019-07-18 07:32:42 +03:00
|
|
|
if err != nil {
|
2019-07-21 15:41:24 +03:00
|
|
|
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
|
2019-07-18 07:32:42 +03:00
|
|
|
}
|
|
|
|
}
|
2019-07-21 15:41:24 +03:00
|
|
|
if nextScale == 0 {
|
|
|
|
scalingList[i] = lastScale
|
|
|
|
} else {
|
|
|
|
scalingList[i] = nextScale
|
|
|
|
}
|
|
|
|
lastScale = scalingList[i]
|
2019-07-18 07:32:42 +03:00
|
|
|
}
|
2019-07-21 15:41:24 +03:00
|
|
|
return nil
|
2019-07-18 07:32:42 +03:00
|
|
|
}
|