codec/h264/h264dec: fixed field types in sps.go and corrected code after merge of master into branch

This commit is contained in:
Saxon 2019-07-30 10:16:08 +09:30
parent 8e8dbbaec6
commit 1d6c501bb8
4 changed files with 230 additions and 691 deletions

View File

@ -64,11 +64,11 @@ func (r fieldReader) readBits(n int) uint64 {
// Exp-Golomb-coded element using method as specified in section 9.1 of ITU-T // Exp-Golomb-coded element using method as specified in section 9.1 of ITU-T
// H.264 and return as an int. The read does not happen if the fieldReader // H.264 and return as an int. The read does not happen if the fieldReader
// has a non-nil error. // has a non-nil error.
func (r fieldReader) readUe() int { func (r fieldReader) readUe() uint64 {
if r.e != nil { if r.e != nil {
return 0 return 0
} }
var i int var i uint64
i, r.e = readUe(r.br) i, r.e = readUe(r.br)
return i return i
} }
@ -77,11 +77,11 @@ func (r fieldReader) readUe() int {
// Exp-Golomb-coded syntax element using method as specified in section 9.1 // Exp-Golomb-coded syntax element using method as specified in section 9.1
// and returns as an int. The read does not happen if the fieldReader // and returns as an int. The read does not happen if the fieldReader
// has a non-nil error. // has a non-nil error.
func (r fieldReader) readTe(x uint) int { func (r fieldReader) readTe(x uint) int64 {
if r.e != nil { if r.e != nil {
return 0 return 0
} }
var i int var i int64
i, r.e = readTe(r.br, x) i, r.e = readTe(r.br, x)
return i return i
} }
@ -122,7 +122,7 @@ func (r fieldReader) err() error {
// //
// TODO: this should return uint, but rest of code needs to be changed for this // TODO: this should return uint, but rest of code needs to be changed for this
// to happen. // to happen.
func readUe(r *bits.BitReader) (int, error) { func readUe(r *bits.BitReader) (uint64, error) {
nZeros := -1 nZeros := -1
var err error var err error
for b := uint64(0); b == 0; nZeros++ { for b := uint64(0); b == 0; nZeros++ {
@ -135,7 +135,7 @@ func readUe(r *bits.BitReader) (int, error) {
if err != nil { if err != nil {
return 0, err return 0, err
} }
return int(math.Pow(float64(2), float64(nZeros)) - 1 + float64(rem)), nil return uint64(math.Pow(float64(2), float64(nZeros)) - 1 + float64(rem)), nil
} }
// readTe parses a syntax element of te(v) descriptor i.e, truncated // readTe parses a syntax element of te(v) descriptor i.e, truncated
@ -143,9 +143,10 @@ func readUe(r *bits.BitReader) (int, error) {
// Rec. ITU-T H.264 (04/2017). // Rec. ITU-T H.264 (04/2017).
// //
// TODO: this should also return uint. // TODO: this should also return uint.
func readTe(r *bits.BitReader, x uint) (int, error) { func readTe(r *bits.BitReader, x uint) (int64, error) {
if x > 1 { if x > 1 {
return readUe(r) ue, err := readUe(r)
return int64(ue), err
} }
if x == 1 { if x == 1 {
@ -181,7 +182,7 @@ func readSe(r *bits.BitReader) (int, error) {
// in Rec. ITU-T H.264 (04/2017). // in Rec. ITU-T H.264 (04/2017).
func readMe(r *bits.BitReader, chromaArrayType uint, mpm mbPartPredMode) (uint, error) { func readMe(r *bits.BitReader, chromaArrayType uint, mpm mbPartPredMode) (uint, error) {
// Indexes to codedBlockPattern map. // Indexes to codedBlockPattern map.
var i1, i2, i3 int var i1, i2, i3 uint64
// ChromaArrayType selects first index. // ChromaArrayType selects first index.
switch chromaArrayType { switch chromaArrayType {
@ -200,7 +201,7 @@ func readMe(r *bits.BitReader, chromaArrayType uint, mpm mbPartPredMode) (uint,
} }
// Need to check that we won't go out of bounds with this index. // Need to check that we won't go out of bounds with this index.
if i2 >= len(codedBlockPattern[i1]) { if int(i2) >= len(codedBlockPattern[i1]) {
return 0, errInvalidCodeNum return 0, errInvalidCodeNum
} }

View File

@ -4,7 +4,6 @@ import (
"math" "math"
"bitbucket.org/ausocean/av/codec/h264/h264dec/bits" "bitbucket.org/ausocean/av/codec/h264/h264dec/bits"
"github.com/pkg/errors"
) )
// import "strings" // import "strings"
@ -47,151 +46,54 @@ func NewPPS(sps *SPS, rbsp []byte, showPacket bool) (*PPS, error) {
pps := PPS{} pps := PPS{}
// TODO: give this io.Reader // TODO: give this io.Reader
br := bits.NewBitReader(nil) br := bits.NewBitReader(nil)
r := newFieldReader(br)
var err error pps.ID = int(r.readUe())
pps.ID, err = readUe(br) pps.SPSID = int(r.readUe())
if err != nil { pps.EntropyCodingMode = int(r.readBits(1))
return nil, errors.Wrap(err, "could not parse ID") pps.BottomFieldPicOrderInFramePresent = r.readBits(1) == 1
} pps.NumSliceGroupsMinus1 = int(r.readUe())
pps.SPSID, err = readUe(br)
if err != nil {
return nil, errors.Wrap(err, "could not parse SPS ID")
}
b, err := br.ReadBits(1)
if err != nil {
return nil, errors.Wrap(err, "could not read EntropyCodingMode")
}
pps.EntropyCodingMode = int(b)
b, err = br.ReadBits(1)
if err != nil {
return nil, errors.Wrap(err, "could not read BottomFieldPicOrderInFramePresent")
}
pps.BottomFieldPicOrderInFramePresent = b == 1
pps.NumSliceGroupsMinus1, err = readUe(br)
if err != nil {
return nil, errors.Wrap(err, "could not parse NumSliceGroupsMinus1")
}
if pps.NumSliceGroupsMinus1 > 0 { if pps.NumSliceGroupsMinus1 > 0 {
pps.SliceGroupMapType, err = readUe(br) pps.SliceGroupMapType = int(r.readUe())
if err != nil {
return nil, errors.Wrap(err, "could not parse SliceGroupMapType")
}
if pps.SliceGroupMapType == 0 { if pps.SliceGroupMapType == 0 {
for iGroup := 0; iGroup <= pps.NumSliceGroupsMinus1; iGroup++ { for iGroup := 0; iGroup <= pps.NumSliceGroupsMinus1; iGroup++ {
pps.RunLengthMinus1[iGroup], err = readUe(br) pps.RunLengthMinus1[iGroup] = int(r.readUe())
if err != nil {
return nil, errors.Wrap(err, "could not parse RunLengthMinus1")
}
} }
} else if pps.SliceGroupMapType == 2 { } else if pps.SliceGroupMapType == 2 {
for iGroup := 0; iGroup < pps.NumSliceGroupsMinus1; iGroup++ { for iGroup := 0; iGroup < pps.NumSliceGroupsMinus1; iGroup++ {
pps.TopLeft[iGroup], err = readUe(br) pps.TopLeft[iGroup] = int(r.readUe())
if err != nil { pps.BottomRight[iGroup] = int(r.readUe())
return nil, errors.Wrap(err, "could not parse TopLeft[iGroup]")
}
if err != nil {
return nil, errors.Wrap(err, "could not parse TopLeft[iGroup]")
}
pps.BottomRight[iGroup], err = readUe(br)
if err != nil {
return nil, errors.Wrap(err, "could not parse BottomRight[iGroup]")
}
} }
} else if pps.SliceGroupMapType > 2 && pps.SliceGroupMapType < 6 { } else if pps.SliceGroupMapType > 2 && pps.SliceGroupMapType < 6 {
b, err = br.ReadBits(1) pps.SliceGroupChangeDirection = r.readBits(1) == 1
if err != nil { pps.SliceGroupChangeRateMinus1 = int(r.readUe())
return nil, errors.Wrap(err, "could not read SliceGroupChangeDirection")
}
pps.SliceGroupChangeDirection = b == 1
pps.SliceGroupChangeRateMinus1, err = readUe(br)
if err != nil {
return nil, errors.Wrap(err, "could not parse SliceGroupChangeRateMinus1")
}
} else if pps.SliceGroupMapType == 6 { } else if pps.SliceGroupMapType == 6 {
pps.PicSizeInMapUnitsMinus1, err = readUe(br) pps.PicSizeInMapUnitsMinus1 = int(r.readUe())
if err != nil {
return nil, errors.Wrap(err, "could not parse PicSizeInMapUnitsMinus1")
}
for i := 0; i <= pps.PicSizeInMapUnitsMinus1; i++ { for i := 0; i <= pps.PicSizeInMapUnitsMinus1; i++ {
b, err = br.ReadBits(int(math.Ceil(math.Log2(float64(pps.NumSliceGroupsMinus1 + 1))))) pps.SliceGroupId[i] = int(r.readBits(int(math.Ceil(math.Log2(float64(pps.NumSliceGroupsMinus1 + 1))))))
if err != nil {
return nil, errors.Wrap(err, "coult not read SliceGroupId")
}
pps.SliceGroupId[i] = int(b)
} }
} }
} }
pps.NumRefIdxL0DefaultActiveMinus1, err = readUe(br) pps.NumRefIdxL0DefaultActiveMinus1 = int(r.readUe())
if err != nil { pps.NumRefIdxL1DefaultActiveMinus1 = int(r.readUe())
return nil, errors.New("could not parse NumRefIdxL0DefaultActiveMinus1") pps.WeightedPred = r.readBits(1) == 1
} pps.WeightedBipred = int(r.readBits(2))
pps.PicInitQpMinus26 = int(r.readSe())
pps.NumRefIdxL1DefaultActiveMinus1, err = readUe(br) pps.PicInitQsMinus26 = int(r.readSe())
if err != nil { pps.ChromaQpIndexOffset = int(r.readSe())
return nil, errors.New("could not parse NumRefIdxL1DefaultActiveMinus1") pps.DeblockingFilterControlPresent = r.readBits(1) == 1
} pps.ConstrainedIntraPred = r.readBits(1) == 1
pps.RedundantPicCntPresent = r.readBits(1) == 1
b, err = br.ReadBits(1)
if err != nil {
return nil, errors.Wrap(err, "could not read WeightedPred")
}
pps.WeightedPred = b == 1
b, err = br.ReadBits(2)
if err != nil {
return nil, errors.Wrap(err, "could not read WeightedBipred")
}
pps.WeightedBipred = int(b)
pps.PicInitQpMinus26, err = readSe(br)
if err != nil {
return nil, errors.New("could not parse PicInitQpMinus26")
}
pps.PicInitQsMinus26, err = readSe(br)
if err != nil {
return nil, errors.New("could not parse PicInitQsMinus26")
}
pps.ChromaQpIndexOffset, err = readSe(br)
if err != nil {
return nil, errors.New("could not parse ChromaQpIndexOffset")
}
err = readFlags(br, []flag{
{&pps.DeblockingFilterControlPresent, "DeblockingFilterControlPresent"},
{&pps.ConstrainedIntraPred, "ConstrainedIntraPred"},
{&pps.RedundantPicCntPresent, "RedundantPicCntPresent"},
})
if err != nil {
return nil, err
}
logger.Printf("debug: \tChecking for more PPS data") logger.Printf("debug: \tChecking for more PPS data")
if moreRBSPData(br) { if moreRBSPData(br) {
logger.Printf("debug: \tProcessing additional PPS data") logger.Printf("debug: \tProcessing additional PPS data")
pps.Transform8x8Mode = int(r.readBits(1))
b, err = br.ReadBits(1) pps.PicScalingMatrixPresent = r.readBits(1) == 1
if err != nil {
return nil, errors.Wrap(err, "could not read Transform8x8Mode")
}
pps.Transform8x8Mode = int(b)
b, err = br.ReadBits(1)
if err != nil {
return nil, errors.Wrap(err, "could not read PicScalingMatrixPresent")
}
pps.PicScalingMatrixPresent = b == 1
if pps.PicScalingMatrixPresent { if pps.PicScalingMatrixPresent {
v := 6 v := 6
@ -199,11 +101,7 @@ func NewPPS(sps *SPS, rbsp []byte, showPacket bool) (*PPS, error) {
v = 2 v = 2
} }
for i := 0; i < 6+(v*pps.Transform8x8Mode); i++ { for i := 0; i < 6+(v*pps.Transform8x8Mode); i++ {
b, err = br.ReadBits(1) pps.PicScalingListPresent[i] = r.readBits(1) == 1
if err != nil {
return nil, errors.Wrap(err, "could not read PicScalingListPresent")
}
pps.PicScalingListPresent[i] = b == 1
if pps.PicScalingListPresent[i] { if pps.PicScalingListPresent[i] {
if i < 6 { if i < 6 {
scalingList( scalingList(
@ -222,10 +120,7 @@ func NewPPS(sps *SPS, rbsp []byte, showPacket bool) (*PPS, error) {
} }
} }
} }
pps.SecondChromaQpIndexOffset, err = readSe(br) pps.SecondChromaQpIndexOffset = r.readSe()
if err != nil {
return nil, errors.New("could not parse SecondChromaQpIndexOffset")
}
} }
moreRBSPData(br) moreRBSPData(br)
// rbspTrailingBits() // rbspTrailingBits()

View File

@ -169,22 +169,22 @@ func MbToSliceGroupMap(sps *SPS, pps *PPS, header *SliceHeader) []int {
} }
func PicWidthInMbs(sps *SPS) int { func PicWidthInMbs(sps *SPS) int {
return sps.PicWidthInMBSMinus1 + 1 return int(sps.PicWidthInMBSMinus1 + 1)
} }
func PicHeightInMapUnits(sps *SPS) int { func PicHeightInMapUnits(sps *SPS) int {
return sps.PicHeightInMapUnitsMinus1 + 1 return int(sps.PicHeightInMapUnitsMinus1 + 1)
} }
func PicSizeInMapUnits(sps *SPS) int { func PicSizeInMapUnits(sps *SPS) int {
return PicWidthInMbs(sps) * PicHeightInMapUnits(sps) return int(PicWidthInMbs(sps) * PicHeightInMapUnits(sps))
} }
func FrameHeightInMbs(sps *SPS) int { func FrameHeightInMbs(sps *SPS) int {
return (2 - flagVal(sps.FrameMBSOnlyFlag)) * PicHeightInMapUnits(sps) return int((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 int(FrameHeightInMbs(sps) / (1 + flagVal(header.FieldPic)))
} }
func PicSizeInMbs(sps *SPS, header *SliceHeader) int { func PicSizeInMbs(sps *SPS, header *SliceHeader) int {
return PicWidthInMbs(sps) * PicHeightInMbs(sps, header) return int(PicWidthInMbs(sps) * PicHeightInMbs(sps, header))
} }
// table 6-1 // table 6-1
@ -262,6 +262,7 @@ func NumMbPart(nalUnit *NALUnit, sps *SPS, header *SliceHeader, data *SliceData)
} }
func MbPred(sliceContext *SliceContext, br *bits.BitReader, rbsp []byte) error { func MbPred(sliceContext *SliceContext, br *bits.BitReader, rbsp []byte) error {
r := newFieldReader(br)
var cabac *CABAC var cabac *CABAC
sliceType := sliceTypeMap[sliceContext.Slice.Header.SliceType] sliceType := sliceTypeMap[sliceContext.Slice.Header.SliceType]
mbPartPredMode, err := MbPartPredMode(sliceContext.Slice.Data, sliceType, sliceContext.Slice.Data.MbType, 0) mbPartPredMode, err := MbPartPredMode(sliceContext.Slice.Data, sliceType, sliceContext.Slice.Data.MbType, 0)
@ -372,11 +373,7 @@ func MbPred(sliceContext *SliceContext, br *bits.BitReader, rbsp []byte) error {
logger.Printf("TODO: ae for IntraChromaPredMode\n") logger.Printf("TODO: ae for IntraChromaPredMode\n")
} else { } else {
var err error sliceContext.Slice.Data.IntraChromaPredMode = int(r.readUe())
sliceContext.Slice.Data.IntraChromaPredMode, err = readUe(br)
if err != nil {
return errors.Wrap(err, "could not parse IntraChromaPredMode")
}
} }
} }
@ -405,14 +402,10 @@ func MbPred(sliceContext *SliceContext, br *bits.BitReader, rbsp []byte) error {
// TODO: Only one reference picture is used for inter-prediction, // TODO: Only one reference picture is used for inter-prediction,
// then the value should be 0 // then the value should be 0
if MbaffFrameFlag(sliceContext.SPS, sliceContext.Slice.Header) == 0 || !sliceContext.Slice.Data.MbFieldDecodingFlag { if MbaffFrameFlag(sliceContext.SPS, sliceContext.Slice.Header) == 0 || !sliceContext.Slice.Data.MbFieldDecodingFlag {
sliceContext.Slice.Data.RefIdxL0[mbPartIdx], _ = readTe( sliceContext.Slice.Data.RefIdxL0[mbPartIdx] = int(r.readTe(uint(sliceContext.Slice.Header.NumRefIdxL0ActiveMinus1)))
br,
uint(sliceContext.Slice.Header.NumRefIdxL0ActiveMinus1))
} else { } else {
rangeMax := 2*sliceContext.Slice.Header.NumRefIdxL0ActiveMinus1 + 1 rangeMax := 2*sliceContext.Slice.Header.NumRefIdxL0ActiveMinus1 + 1
sliceContext.Slice.Data.RefIdxL0[mbPartIdx], _ = readTe( sliceContext.Slice.Data.RefIdxL0[mbPartIdx] = int(r.readTe(uint(rangeMax)))
br,
uint(rangeMax))
} }
} }
} }
@ -588,9 +581,9 @@ func nextMbAddress(n int, sps *SPS, pps *PPS, header *SliceHeader) int {
// FrameHeightInMbs = (2 - ps.FrameMBSOnlyFlag) * 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.FrameMBSOnlyFlag)) * picHeightInMapUnits frameHeightInMbs := (2 - flagVal(sps.FrameMBSOnlyFlag)) * int(picHeightInMapUnits)
picHeightInMbs := frameHeightInMbs / (1 + flagVal(header.FieldPic)) picHeightInMbs := frameHeightInMbs / (1 + flagVal(header.FieldPic))
picSizeInMbs := picWidthInMbs * picHeightInMbs picSizeInMbs := int(picWidthInMbs) * picHeightInMbs
mbToSliceGroupMap := MbToSliceGroupMap(sps, pps, header) mbToSliceGroupMap := MbToSliceGroupMap(sps, pps, header)
for i < picSizeInMbs && mbToSliceGroupMap[i] != mbToSliceGroupMap[i] { for i < picSizeInMbs && mbToSliceGroupMap[i] != mbToSliceGroupMap[i] {
i++ i++
@ -615,8 +608,8 @@ func MbaffFrameFlag(sps *SPS, header *SliceHeader) int {
} }
func NewSliceData(sliceContext *SliceContext, br *bits.BitReader) (*SliceData, error) { func NewSliceData(sliceContext *SliceContext, br *bits.BitReader) (*SliceData, error) {
r := newFieldReader(br)
var cabac *CABAC var cabac *CABAC
var err error
sliceContext.Slice.Data = &SliceData{BitReader: br} sliceContext.Slice.Data = &SliceData{BitReader: br}
// TODO: Why is this being initialized here? // TODO: Why is this being initialized here?
// initCabac(sliceContext) // initCabac(sliceContext)
@ -645,10 +638,7 @@ func NewSliceData(sliceContext *SliceContext, br *bits.BitReader) (*SliceData, e
if sliceContext.Slice.Data.SliceTypeName != "I" && sliceContext.Slice.Data.SliceTypeName != "SI" { if sliceContext.Slice.Data.SliceTypeName != "I" && sliceContext.Slice.Data.SliceTypeName != "SI" {
logger.Printf("debug: \tNonI/SI slice, processing moreData\n") logger.Printf("debug: \tNonI/SI slice, processing moreData\n")
if sliceContext.PPS.EntropyCodingMode == 0 { if sliceContext.PPS.EntropyCodingMode == 0 {
sliceContext.Slice.Data.MbSkipRun, err = readUe(br) sliceContext.Slice.Data.MbSkipRun = int(r.readUe())
if err != nil {
return nil, errors.Wrap(err, "could not parse MbSkipRun")
}
if sliceContext.Slice.Data.MbSkipRun > 0 { if sliceContext.Slice.Data.MbSkipRun > 0 {
prevMbSkipped = 1 prevMbSkipped = 1
@ -762,10 +752,7 @@ func NewSliceData(sliceContext *SliceContext, br *bits.BitReader) (*SliceData, e
logger.Printf("TODO: ae for MBType\n") logger.Printf("TODO: ae for MBType\n")
} else { } else {
sliceContext.Slice.Data.MbType, err = readUe(br) sliceContext.Slice.Data.MbType = int(r.readUe())
if err != nil {
return nil, errors.Wrap(err, "could not parse MbType")
}
} }
if sliceContext.Slice.Data.MbTypeName == "I_PCM" { if sliceContext.Slice.Data.MbTypeName == "I_PCM" {
for !br.ByteAligned() { for !br.ByteAligned() {
@ -777,7 +764,7 @@ func NewSliceData(sliceContext *SliceContext, br *bits.BitReader) (*SliceData, e
// 7-3 p95 // 7-3 p95
bitDepthY := 8 + sliceContext.SPS.BitDepthLumaMinus8 bitDepthY := 8 + sliceContext.SPS.BitDepthLumaMinus8
for i := 0; i < 256; i++ { for i := 0; i < 256; i++ {
s, err := br.ReadBits(bitDepthY) s, err := br.ReadBits(int(bitDepthY))
if err != nil { if err != nil {
return nil, errors.Wrap(err, fmt.Sprintf("could not read PcmSampleLuma[%d]", i)) return nil, errors.Wrap(err, fmt.Sprintf("could not read PcmSampleLuma[%d]", i))
} }
@ -798,7 +785,7 @@ func NewSliceData(sliceContext *SliceContext, br *bits.BitReader) (*SliceData, e
bitDepthC := 8 + sliceContext.SPS.BitDepthChromaMinus8 bitDepthC := 8 + sliceContext.SPS.BitDepthChromaMinus8
for i := 0; i < 2*mbWidthC*mbHeightC; i++ { for i := 0; i < 2*mbWidthC*mbHeightC; i++ {
s, err := br.ReadBits(bitDepthC) s, err := br.ReadBits(int(bitDepthC))
if err != nil { if err != nil {
return nil, errors.Wrap(err, fmt.Sprintf("could not read PcmSampleChroma[%d]", i)) return nil, errors.Wrap(err, fmt.Sprintf("could not read PcmSampleChroma[%d]", i))
} }
@ -959,27 +946,17 @@ func NewSliceContext(videoStream *VideoStream, nalUnit *NALUnit, rbsp []byte, sh
if sps.SeparateColorPlaneFlag { if sps.SeparateColorPlaneFlag {
header.ChromaArrayType = 0 header.ChromaArrayType = 0
} else { } else {
header.ChromaArrayType = sps.ChromaFormatIDC header.ChromaArrayType = int(sps.ChromaFormatIDC)
} }
br := bits.NewBitReader(bytes.NewReader(rbsp)) br := bits.NewBitReader(bytes.NewReader(rbsp))
r := newFieldReader(br)
header.FirstMbInSlice, err = readUe(br) header.FirstMbInSlice = int(r.readUe())
if err != nil { header.SliceType = int(r.readUe())
return nil, errors.Wrap(err, "could not parse FirstMbInSlice")
}
header.SliceType, err = readUe(br)
if err != nil {
return nil, errors.Wrap(err, "could not parse SliceType")
}
sliceType := sliceTypeMap[header.SliceType] sliceType := sliceTypeMap[header.SliceType]
logger.Printf("debug: %s (%s) slice of %d bytes\n", NALUnitType[int(nalUnit.Type)], sliceType, len(rbsp)) logger.Printf("debug: %s (%s) slice of %d bytes\n", NALUnitType[int(nalUnit.Type)], sliceType, len(rbsp))
header.PPSID, err = readUe(br) header.PPSID = int(r.readUe())
if err != nil {
return nil, errors.Wrap(err, "could not parse PPSID")
}
if sps.SeparateColorPlaneFlag { if sps.SeparateColorPlaneFlag {
b, err := br.ReadBits(2) b, err := br.ReadBits(2)
if err != nil { if err != nil {
@ -1004,13 +981,10 @@ func NewSliceContext(videoStream *VideoStream, nalUnit *NALUnit, rbsp []byte, sh
} }
} }
if idrPic { if idrPic {
header.IDRPicID, err = readUe(br) header.IDRPicID = int(r.readUe())
if err != nil {
return nil, errors.Wrap(err, "could not parse IDRPicID")
}
} }
if sps.PicOrderCountType == 0 { if sps.PicOrderCountType == 0 {
b, err := br.ReadBits(sps.Log2MaxPicOrderCntLSBMin4 + 4) b, err := br.ReadBits(int(sps.Log2MaxPicOrderCntLSBMin4 + 4))
if err != nil { if err != nil {
return nil, errors.Wrap(err, "could not read PicOrderCntLsb") return nil, errors.Wrap(err, "could not read PicOrderCntLsb")
} }
@ -1037,10 +1011,7 @@ func NewSliceContext(videoStream *VideoStream, nalUnit *NALUnit, rbsp []byte, sh
} }
} }
if pps.RedundantPicCntPresent { if pps.RedundantPicCntPresent {
header.RedundantPicCnt, err = readUe(br) header.RedundantPicCnt = int(r.readUe())
if err != nil {
return nil, errors.Wrap(err, "could not parse RedundantPicCnt")
}
} }
if sliceType == "B" { if sliceType == "B" {
b, err := br.ReadBits(1) b, err := br.ReadBits(1)
@ -1057,15 +1028,9 @@ func NewSliceContext(videoStream *VideoStream, nalUnit *NALUnit, rbsp []byte, sh
header.NumRefIdxActiveOverride = b == 1 header.NumRefIdxActiveOverride = b == 1
if header.NumRefIdxActiveOverride { if header.NumRefIdxActiveOverride {
header.NumRefIdxL0ActiveMinus1, err = readUe(br) header.NumRefIdxL0ActiveMinus1 = int(r.readUe())
if err != nil {
return nil, errors.Wrap(err, "could not parse NumRefIdxL0ActiveMinus1")
}
if sliceType == "B" { if sliceType == "B" {
header.NumRefIdxL1ActiveMinus1, err = readUe(br) header.NumRefIdxL1ActiveMinus1 = int(r.readUe())
if err != nil {
return nil, errors.Wrap(err, "could not parse NumRefIdxL1ActiveMinus1")
}
} }
} }
} }
@ -1085,21 +1050,12 @@ func NewSliceContext(videoStream *VideoStream, nalUnit *NALUnit, rbsp []byte, sh
if header.RefPicListModificationFlagL0 { if header.RefPicListModificationFlagL0 {
for header.ModificationOfPicNums != 3 { for header.ModificationOfPicNums != 3 {
header.ModificationOfPicNums, err = readUe(br) header.ModificationOfPicNums = int(r.readUe())
if err != nil {
return nil, errors.Wrap(err, "could not parse ModificationOfPicNums")
}
if header.ModificationOfPicNums == 0 || header.ModificationOfPicNums == 1 { if header.ModificationOfPicNums == 0 || header.ModificationOfPicNums == 1 {
header.AbsDiffPicNumMinus1, err = readUe(br) header.AbsDiffPicNumMinus1 = int(r.readUe())
if err != nil {
return nil, errors.Wrap(err, "could not parse AbsDiffPicNumMinus1")
}
} else if header.ModificationOfPicNums == 2 { } else if header.ModificationOfPicNums == 2 {
header.LongTermPicNum, err = readUe(br) header.LongTermPicNum = int(r.readUe())
if err != nil {
return nil, errors.Wrap(err, "could not parse LongTermPicNum")
}
} }
} }
} }
@ -1114,21 +1070,12 @@ func NewSliceContext(videoStream *VideoStream, nalUnit *NALUnit, rbsp []byte, sh
if header.RefPicListModificationFlagL1 { if header.RefPicListModificationFlagL1 {
for header.ModificationOfPicNums != 3 { for header.ModificationOfPicNums != 3 {
header.ModificationOfPicNums, err = readUe(br) header.ModificationOfPicNums = int(r.readUe())
if err != nil {
return nil, errors.Wrap(err, "could not parse ModificationOfPicNums")
}
if header.ModificationOfPicNums == 0 || header.ModificationOfPicNums == 1 { if header.ModificationOfPicNums == 0 || header.ModificationOfPicNums == 1 {
header.AbsDiffPicNumMinus1, err = readUe(br) header.AbsDiffPicNumMinus1 = int(r.readUe())
if err != nil {
return nil, errors.Wrap(err, "could not parse AbsDiffPicNumMinus1")
}
} else if header.ModificationOfPicNums == 2 { } else if header.ModificationOfPicNums == 2 {
header.LongTermPicNum, err = readUe(br) header.LongTermPicNum = int(r.readUe())
if err != nil {
return nil, errors.Wrap(err, "could not parse LongTermPicNum")
}
} }
} }
} }
@ -1138,23 +1085,13 @@ func NewSliceContext(videoStream *VideoStream, nalUnit *NALUnit, rbsp []byte, sh
if (pps.WeightedPred && (sliceType == "P" || sliceType == "SP")) || (pps.WeightedBipred == 1 && sliceType == "B") { if (pps.WeightedPred && (sliceType == "P" || sliceType == "SP")) || (pps.WeightedBipred == 1 && sliceType == "B") {
// predWeightTable() // predWeightTable()
header.LumaLog2WeightDenom, err = readUe(br) header.LumaLog2WeightDenom = int(r.readUe())
if err != nil {
return nil, errors.Wrap(err, "could not parse LumaLog2WeightDenom")
}
if header.ChromaArrayType != 0 { if header.ChromaArrayType != 0 {
header.ChromaLog2WeightDenom, err = readUe(br) header.ChromaLog2WeightDenom = int(r.readUe())
if err != nil {
return nil, errors.Wrap(err, "could not parse ChromaLog2WeightDenom")
}
} }
for i := 0; i <= header.NumRefIdxL0ActiveMinus1; i++ { for i := 0; i <= header.NumRefIdxL0ActiveMinus1; i++ {
b, err := br.ReadBits(1) header.LumaWeightL0Flag = r.readBits(1) == 1
if err != nil {
return nil, errors.Wrap(err, "could not read LumaWeightL0Flag")
}
header.LumaWeightL0Flag = b == 1
if header.LumaWeightL0Flag { if header.LumaWeightL0Flag {
se, err := readSe(br) se, err := readSe(br)
@ -1266,69 +1203,37 @@ func NewSliceContext(videoStream *VideoStream, nalUnit *NALUnit, rbsp []byte, sh
header.AdaptiveRefPicMarkingModeFlag = b == 1 header.AdaptiveRefPicMarkingModeFlag = b == 1
if header.AdaptiveRefPicMarkingModeFlag { if header.AdaptiveRefPicMarkingModeFlag {
header.MemoryManagementControlOperation, err = readUe(br) header.MemoryManagementControlOperation = int(r.readUe())
if err != nil {
return nil, errors.Wrap(err, "could not parse MemoryManagementControlOperation")
}
for header.MemoryManagementControlOperation != 0 { for header.MemoryManagementControlOperation != 0 {
if header.MemoryManagementControlOperation == 1 || header.MemoryManagementControlOperation == 3 { if header.MemoryManagementControlOperation == 1 || header.MemoryManagementControlOperation == 3 {
header.DifferenceOfPicNumsMinus1, err = readUe(br) header.DifferenceOfPicNumsMinus1 = int(r.readUe())
if err != nil {
return nil, errors.Wrap(err, "could not parse MemoryManagementControlOperation")
}
} }
if header.MemoryManagementControlOperation == 2 { if header.MemoryManagementControlOperation == 2 {
header.LongTermPicNum, err = readUe(br) header.LongTermPicNum = int(r.readUe())
if err != nil {
return nil, errors.Wrap(err, "could not parse LongTermPicNum")
}
} }
if header.MemoryManagementControlOperation == 3 || header.MemoryManagementControlOperation == 6 { if header.MemoryManagementControlOperation == 3 || header.MemoryManagementControlOperation == 6 {
header.LongTermFrameIdx, err = readUe(br) header.LongTermFrameIdx = int(r.readUe())
if err != nil {
return nil, errors.Wrap(err, "could not parse LongTermFrameIdx")
}
} }
if header.MemoryManagementControlOperation == 4 { if header.MemoryManagementControlOperation == 4 {
header.MaxLongTermFrameIdxPlus1, err = readUe(br) header.MaxLongTermFrameIdxPlus1 = int(r.readUe())
if err != nil {
return nil, errors.Wrap(err, "could not parse MaxLongTermFrameIdxPlus1")
}
} }
} }
} }
} // end decRefPicMarking } // end decRefPicMarking
} }
if pps.EntropyCodingMode == 1 && sliceType != "I" && sliceType != "SI" { if pps.EntropyCodingMode == 1 && sliceType != "I" && sliceType != "SI" {
header.CabacInit, err = readUe(br) header.CabacInit = int(r.readUe())
if err != nil {
return nil, errors.Wrap(err, "could not parse CabacInit")
}
}
header.SliceQpDelta, err = readSe(br)
if err != nil {
return nil, errors.Wrap(err, "could not parse SliceQpDelta")
} }
header.SliceQpDelta = int(r.readSe())
if sliceType == "SP" || sliceType == "SI" { if sliceType == "SP" || sliceType == "SI" {
if sliceType == "SP" { if sliceType == "SP" {
b, err := br.ReadBits(1) header.SpForSwitch = r.readBits(1) == 1
if err != nil {
return nil, errors.Wrap(err, "could not read SpForSwitch")
}
header.SpForSwitch = b == 1
}
header.SliceQsDelta, err = readSe(br)
if err != nil {
return nil, errors.Wrap(err, "could not parse SliceQsDelta")
} }
header.SliceQsDelta = int(r.readSe())
} }
if pps.DeblockingFilterControlPresent { if pps.DeblockingFilterControlPresent {
header.DisableDeblockingFilter, err = readUe(br) header.DisableDeblockingFilter = int(r.readUe())
if err != nil {
return nil, errors.Wrap(err, "could not parse DisableDeblockingFilter")
}
if header.DisableDeblockingFilter != 1 { if header.DisableDeblockingFilter != 1 {
header.SliceAlphaC0OffsetDiv2, err = readSe(br) header.SliceAlphaC0OffsetDiv2, err = readSe(br)
if err != nil { if err != nil {

View File

@ -2,6 +2,7 @@ package h264dec
import ( import (
"bytes" "bytes"
"fmt"
"bitbucket.org/ausocean/av/codec/h264/h264dec/bits" "bitbucket.org/ausocean/av/codec/h264/h264dec/bits"
"github.com/pkg/errors" "github.com/pkg/errors"
@ -63,46 +64,46 @@ var (
// SPS describes a sequence parameter set as defined by section 7.3.2.1.1 in // SPS describes a sequence parameter set as defined by section 7.3.2.1.1 in
// the Specifications. // the Specifications.
type SPS struct { type SPS struct {
Profile int Profile uint8
Constraint0 int Constraint0 bool
Constraint1 int Constraint1 bool
Constraint2 int Constraint2 bool
Constraint3 int Constraint3 bool
Constraint4 int Constraint4 bool
Constraint5 int Constraint5 bool
LevelIDC int LevelIDC uint8
SPSID int SPSID uint64
ChromaFormatIDC int ChromaFormatIDC uint64
SeparateColorPlaneFlag bool SeparateColorPlaneFlag bool
BitDepthLumaMinus8 int BitDepthLumaMinus8 uint64
BitDepthChromaMinus8 int BitDepthChromaMinus8 uint64
QPPrimeYZeroTransformBypassFlag bool QPPrimeYZeroTransformBypassFlag bool
SeqScalingMatrixPresentFlag bool SeqScalingMatrixPresentFlag bool
SeqScalingListPresentFlag []bool SeqScalingListPresentFlag []bool
ScalingList4x4 [][]int ScalingList4x4 [][]uint64
UseDefaultScalingMatrix4x4Flag []bool UseDefaultScalingMatrix4x4Flag []bool
ScalingList8x8 [][]int ScalingList8x8 [][]uint64
UseDefaultScalingMatrix8x8Flag []bool UseDefaultScalingMatrix8x8Flag []bool
Log2MaxFrameNumMinus4 int Log2MaxFrameNumMinus4 uint64
PicOrderCountType int PicOrderCountType uint64
Log2MaxPicOrderCntLSBMin4 int Log2MaxPicOrderCntLSBMin4 uint64
DeltaPicOrderAlwaysZeroFlag bool DeltaPicOrderAlwaysZeroFlag bool
OffsetForNonRefPic int OffsetForNonRefPic int64
OffsetForTopToBottomField int OffsetForTopToBottomField int64
NumRefFramesInPicOrderCntCycle int NumRefFramesInPicOrderCntCycle uint64
OffsetForRefFrameList []int OffsetForRefFrameList []int
MaxNumRefFrames int MaxNumRefFrames uint64
GapsInFrameNumValueAllowed bool GapsInFrameNumValueAllowed bool
PicWidthInMBSMinus1 int PicWidthInMBSMinus1 uint64
PicHeightInMapUnitsMinus1 int PicHeightInMapUnitsMinus1 uint64
FrameMBSOnlyFlag bool FrameMBSOnlyFlag bool
MBAdaptiveFrameFieldFlag bool MBAdaptiveFrameFieldFlag bool
Direct8x8InferenceFlag bool Direct8x8InferenceFlag bool
FrameCroppingFlag bool FrameCroppingFlag bool
FrameCropLeftOffset int FrameCropLeftOffset uint64
FrameCropRightOffset int FrameCropRightOffset uint64
FrameCropTopOffset int FrameCropTopOffset uint64
FrameCropBottomOffset int FrameCropBottomOffset uint64
VUIParametersPresentFlag bool VUIParametersPresentFlag bool
VUIParameters *VUIParameters VUIParameters *VUIParameters
} }
@ -115,76 +116,33 @@ func NewSPS(rbsp []byte, showPacket bool) (*SPS, error) {
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 r := newFieldReader(br)
err = readFields(br, sps.Profile = uint8(r.readBits(8))
[]field{ sps.Constraint0 = r.readBits(1) == 1
{&sps.Profile, "ProfileIDC", 8}, sps.Constraint1 = r.readBits(1) == 1
{&sps.Constraint0, "Constraint0", 1}, sps.Constraint2 = r.readBits(1) == 1
{&sps.Constraint1, "Constraint1", 1}, sps.Constraint3 = r.readBits(1) == 1
{&sps.Constraint2, "Constraint2", 1}, sps.Constraint4 = r.readBits(1) == 1
{&sps.Constraint3, "Constraint3", 1}, sps.Constraint5 = r.readBits(1) == 1
{&sps.Constraint4, "Constraint4", 1}, r.readBits(2) // 2 reserved bits.
{&sps.Constraint5, "Constraint5", 1}, sps.LevelIDC = uint8(r.readBits(8))
}, sps.SPSID = r.readUe()
) sps.ChromaFormatIDC = r.readUe()
_, err = br.ReadBits(2)
if err != nil {
return nil, errors.Wrap(err, "could not read ReservedZeroBits")
}
b, err := br.ReadBits(8)
if err != nil {
return nil, errors.Wrap(err, "could not read Level")
}
sps.LevelIDC = int(b)
// sps.ID = b.NextField("SPSID", 6) // proper
sps.SPSID, err = readUe(br)
if err != nil {
return nil, errors.Wrap(err, "could not parse ID")
}
sps.ChromaFormatIDC, err = readUe(br)
if err != nil {
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, int(sps.Profile)) {
if sps.ChromaFormatIDC == chroma444 { if sps.ChromaFormatIDC == chroma444 {
// TODO: should probably deal with error here. // TODO: should probably deal with error here.
b, err := br.ReadBits(1) sps.SeparateColorPlaneFlag = r.readBits(1) == 1
if err != nil {
return nil, errors.Wrap(err, "could not read UseSeparateColorPlaneFlag")
}
sps.SeparateColorPlaneFlag = b == 1
} }
sps.BitDepthLumaMinus8, err = readUe(br) sps.BitDepthLumaMinus8 = r.readUe()
if err != nil { sps.BitDepthChromaMinus8 = r.readUe()
return nil, errors.Wrap(err, "could not parse BitDepthLumaMinus8") sps.QPPrimeYZeroTransformBypassFlag = r.readBits(1) == 1
} sps.SeqScalingMatrixPresentFlag = r.readBits(1) == 1
sps.BitDepthChromaMinus8, err = readUe(br)
if err != nil {
return nil, errors.Wrap(err, "could not parse BitDepthChromaMinus8")
}
b, err := br.ReadBits(1)
if err != nil {
return nil, errors.Wrap(err, "could not read QPrimeYZeroTransformBypass")
}
sps.QPPrimeYZeroTransformBypassFlag = b == 1
b, err = br.ReadBits(1)
if err != nil {
return nil, errors.Wrap(err, "could not read SeqScalingMatrixPresent")
}
sps.SeqScalingMatrixPresentFlag = b == 1
if sps.SeqScalingMatrixPresentFlag { if sps.SeqScalingMatrixPresentFlag {
max := 12 max := 12
@ -193,11 +151,7 @@ func NewSPS(rbsp []byte, showPacket bool) (*SPS, error) {
} }
logger.Printf("debug: \tbuilding Scaling matrix for %d elements\n", max) logger.Printf("debug: \tbuilding Scaling matrix for %d elements\n", max)
for i := 0; i < max; i++ { for i := 0; i < max; i++ {
b, err := br.ReadBits(1) sps.SeqScalingListPresentFlag = append(sps.SeqScalingListPresentFlag, r.readBits(1) == 1)
if err != nil {
return nil, errors.Wrap(err, "could not read SeqScalingList")
}
sps.SeqScalingListPresentFlag = append(sps.SeqScalingListPresentFlag, b == 1)
if sps.SeqScalingListPresentFlag[i] { if sps.SeqScalingListPresentFlag[i] {
if i < 6 { if i < 6 {
@ -223,125 +177,44 @@ func NewSPS(rbsp []byte, showPacket bool) (*SPS, error) {
// showSPS() // showSPS()
// return sps // return sps
// Possibly wrong due to no scaling list being built // Possibly wrong due to no scaling list being built
sps.Log2MaxFrameNumMinus4, err = readUe(br) sps.Log2MaxFrameNumMinus4 = r.readUe()
if err != nil { sps.PicOrderCountType = r.readUe()
return nil, errors.Wrap(err, "could not parse Log2MaxFrameNumMinus4")
}
sps.PicOrderCountType, err = readUe(br)
if err != nil {
return nil, errors.Wrap(err, "could not parse PicOrderCountType")
}
if sps.PicOrderCountType == 0 { if sps.PicOrderCountType == 0 {
sps.Log2MaxPicOrderCntLSBMin4, err = readUe(br) sps.Log2MaxPicOrderCntLSBMin4 = r.readUe()
if err != nil {
return nil, errors.Wrap(err, "could not parse Log2MaxPicOrderCntLSBMin4")
}
} else if sps.PicOrderCountType == 1 { } else if sps.PicOrderCountType == 1 {
b, err = br.ReadBits(1) sps.DeltaPicOrderAlwaysZeroFlag = r.readBits(1) == 1
if err != nil { sps.OffsetForNonRefPic = int64(r.readSe())
return nil, errors.Wrap(err, "could not read DeltaPicOrderAlwaysZero") sps.OffsetForTopToBottomField = int64(r.readSe())
} sps.NumRefFramesInPicOrderCntCycle = r.readUe()
sps.DeltaPicOrderAlwaysZeroFlag = b == 1
sps.OffsetForNonRefPic, err = readSe(br) for i := 0; i < int(sps.NumRefFramesInPicOrderCntCycle); i++ {
if err != nil { sps.OffsetForRefFrameList = append(sps.OffsetForRefFrameList, r.readSe())
return nil, errors.Wrap(err, "could not parse OffsetForNonRefPic")
}
sps.OffsetForTopToBottomField, err = readSe(br)
if err != nil {
return nil, errors.Wrap(err, "could not parse OffsetForTopToBottomField")
}
sps.NumRefFramesInPicOrderCntCycle, err = readUe(br)
if err != nil {
return nil, errors.Wrap(err, "could not parse NumRefFramesInPicOrderCntCycle")
}
for i := 0; i < sps.NumRefFramesInPicOrderCntCycle; i++ {
se, err := readSe(br)
if err != nil {
return nil, errors.Wrap(err, "could not parse OffsetForRefFrameList")
}
sps.OffsetForRefFrameList = append(
sps.OffsetForRefFrameList,
se)
} }
} }
sps.MaxNumRefFrames, err = readUe(br) sps.MaxNumRefFrames = r.readUe()
if err != nil { sps.GapsInFrameNumValueAllowed = r.readBits(1) == 1
return nil, errors.Wrap(err, "could not parse MaxNumRefFrames") sps.PicWidthInMBSMinus1 = r.readUe()
} sps.PicHeightInMapUnitsMinus1 = r.readUe()
sps.FrameMBSOnlyFlag = r.readBits(1) == 1
b, err = br.ReadBits(1)
if err != nil {
return nil, errors.Wrap(err, "could not read GapsInFrameNumValueAllowed")
}
sps.GapsInFrameNumValueAllowed = b == 1
sps.PicWidthInMBSMinus1, err = readUe(br)
if err != nil {
return nil, errors.Wrap(err, "could not parse PicWidthInMbsMinus1")
}
sps.PicHeightInMapUnitsMinus1, err = readUe(br)
if err != nil {
return nil, errors.Wrap(err, "could not parse PicHeightInMapUnitsMinus1")
}
b, err = br.ReadBits(1)
if err != nil {
return nil, errors.Wrap(err, "could not read FrameMbsOnly")
}
sps.FrameMBSOnlyFlag = b == 1
if !sps.FrameMBSOnlyFlag { if !sps.FrameMBSOnlyFlag {
b, err = br.ReadBits(1) sps.MBAdaptiveFrameFieldFlag = r.readBits(1) == 1
if err != nil {
return nil, errors.Wrap(err, "could not read MBAdaptiveFrameField")
}
sps.MBAdaptiveFrameFieldFlag = b == 1
} }
err = readFlags(br, []flag{ sps.Direct8x8InferenceFlag = r.readBits(1) == 1
{&sps.Direct8x8InferenceFlag, "Direct8x8Inference"}, sps.FrameCroppingFlag = r.readBits(1) == 1
{&sps.FrameCroppingFlag, "FrameCropping"},
})
if err != nil {
return nil, err
}
if sps.FrameCroppingFlag { if sps.FrameCroppingFlag {
sps.FrameCropLeftOffset, err = readUe(br) sps.FrameCropLeftOffset = r.readUe()
if err != nil { sps.FrameCropRightOffset = r.readUe()
return nil, errors.Wrap(err, "could not parse FrameCropLeftOffset") sps.FrameCropTopOffset = r.readUe()
} sps.FrameCropBottomOffset = r.readUe()
sps.FrameCropRightOffset, err = readUe(br)
if err != nil {
return nil, errors.Wrap(err, "could not parse FrameCropRightOffset")
}
sps.FrameCropTopOffset, err = readUe(br)
if err != nil {
return nil, errors.Wrap(err, "could not parse FrameCropTopOffset")
}
sps.FrameCropBottomOffset, err = readUe(br)
if err != nil {
return nil, errors.Wrap(err, "could not parse FrameCropBottomOffset")
}
} }
b, err = br.ReadBits(1) sps.VUIParametersPresentFlag = r.readBits(1) == 1
if err != nil {
return nil, errors.Wrap(err, "could not read VuiParametersPresent")
}
sps.VUIParametersPresentFlag = b == 1
if sps.VUIParametersPresentFlag { if sps.VUIParametersPresentFlag {
@ -354,24 +227,24 @@ func NewSPS(rbsp []byte, showPacket bool) (*SPS, error) {
// Specifications. // Specifications.
type VUIParameters struct { type VUIParameters struct {
AspectRatioInfoPresentFlag bool AspectRatioInfoPresentFlag bool
AspectRatioIDC int AspectRatioIDC uint8
SARWidth int SARWidth uint32
SARHeight int SARHeight uint32
OverscanInfoPresentFlag bool OverscanInfoPresentFlag bool
OverscanAppropriateFlag bool OverscanAppropriateFlag bool
VideoSignalTypePresentFlag bool VideoSignalTypePresentFlag bool
VideoFormat int VideoFormat uint8
VideoFullRangeFlag bool VideoFullRangeFlag bool
ColorDescriptionPresentFlag bool ColorDescriptionPresentFlag bool
ColorPrimaries int ColorPrimaries uint8
TransferCharacteristics int TransferCharacteristics uint8
MatrixCoefficients int MatrixCoefficients uint8
ChromaLocInfoPresentFlag bool ChromaLocInfoPresentFlag bool
ChromaSampleLocTypeTopField int ChromaSampleLocTypeTopField uint64
ChromaSampleLocTypeBottomField int ChromaSampleLocTypeBottomField uint64
TimingInfoPresentFlag bool TimingInfoPresentFlag bool
NumUnitsInTick int NumUnitsInTick uint32
TimeScale int TimeScale uint32
FixedFrameRateFlag bool FixedFrameRateFlag bool
NALHRDParametersPresentFlag bool NALHRDParametersPresentFlag bool
NALHRDParameters *HRDParameters NALHRDParameters *HRDParameters
@ -381,12 +254,12 @@ type VUIParameters struct {
PicStructPresentFlag bool PicStructPresentFlag bool
BitstreamRestrictionFlag bool BitstreamRestrictionFlag bool
MotionVectorsOverPicBoundariesFlag bool MotionVectorsOverPicBoundariesFlag bool
MaxBytesPerPicDenom int MaxBytesPerPicDenom uint64
MaxBitsPerMBDenom int MaxBitsPerMBDenom uint64
Log2MaxMVLengthHorizontal int Log2MaxMVLengthHorizontal uint64
Log2MaxMVLengthVertical int Log2MaxMVLengthVertical uint64
MaxNumReorderFrames int MaxNumReorderFrames uint64
MaxDecFrameBuffering int MaxDecFrameBuffering uint64
} }
// NewVUIParameters parses video usability information parameters from br // NewVUIParameters parses video usability information parameters from br
@ -394,137 +267,60 @@ type VUIParameters struct {
// new VUIParameters. // new VUIParameters.
func NewVUIParameters(br *bits.BitReader) (*VUIParameters, error) { func NewVUIParameters(br *bits.BitReader) (*VUIParameters, error) {
p := &VUIParameters{} p := &VUIParameters{}
r := newFieldReader(br)
b, err := br.ReadBits(1) p.AspectRatioInfoPresentFlag = r.readBits(1) == 1
if err != nil {
return nil, errors.Wrap(err, "could not read AspectRatioInfoPresent")
}
p.AspectRatioInfoPresentFlag = b == 1
if p.AspectRatioInfoPresentFlag { if p.AspectRatioInfoPresentFlag {
b, err = br.ReadBits(8) p.AspectRatioIDC = uint8(r.readBits(8))
if err != nil {
return nil, errors.Wrap(err, "could not read AspectRatio")
}
p.AspectRatioIDC = int(b)
EXTENDED_SAR := 999 EXTENDED_SAR := 999
if p.AspectRatioIDC == EXTENDED_SAR { if int(p.AspectRatioIDC) == EXTENDED_SAR {
b, err = br.ReadBits(16) p.SARWidth = uint32(r.readBits(16))
if err != nil { p.SARHeight = uint32(r.readBits(16))
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) p.OverscanInfoPresentFlag = r.readBits(1) == 1
if err != nil {
return nil, errors.Wrap(err, "could not read OverscanInfoPresent")
}
p.OverscanInfoPresentFlag = b == 1
if p.OverscanInfoPresentFlag { if p.OverscanInfoPresentFlag {
b, err = br.ReadBits(1) p.OverscanAppropriateFlag = r.readBits(1) == 1
if err != nil {
return nil, errors.Wrap(err, "could not read OverscanAppropriate")
}
p.OverscanAppropriateFlag = b == 1
} }
b, err = br.ReadBits(1) p.VideoSignalTypePresentFlag = r.readBits(1) == 1
if err != nil {
return nil, errors.Wrap(err, "could not read VideoSignalTypePresent")
}
p.VideoSignalTypePresentFlag = b == 1
if p.VideoSignalTypePresentFlag { if p.VideoSignalTypePresentFlag {
b, err = br.ReadBits(3) p.VideoFormat = uint8(r.readBits(3))
if err != nil {
return nil, errors.Wrap(err, "could not read VideoFormat")
}
p.VideoFormat = int(b)
} }
if p.VideoSignalTypePresentFlag { if p.VideoSignalTypePresentFlag {
b, err = br.ReadBits(1) p.VideoFullRangeFlag = r.readBits(1) == 1
if err != nil { p.ColorDescriptionPresentFlag = r.readBits(1) == 1
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 ColorDescriptionPresent")
}
p.ColorDescriptionPresentFlag = b == 1
if p.ColorDescriptionPresentFlag { if p.ColorDescriptionPresentFlag {
err = readFields(br, p.ColorPrimaries = uint8(r.readBits(8))
[]field{ p.TransferCharacteristics = uint8(r.readBits(8))
{&p.ColorPrimaries, "ColorPrimaries", 8}, p.MatrixCoefficients = uint8(r.readBits(8))
{&p.TransferCharacteristics, "TransferCharacteristics", 8},
{&p.MatrixCoefficients, "MatrixCoefficients", 8},
},
)
if err != nil {
return nil, err
}
} }
} }
p.ChromaLocInfoPresentFlag = r.readBits(1) == 1
b, err = br.ReadBits(1)
if err != nil {
return nil, errors.Wrap(err, "could not read ChromaLocInfoPresent")
}
p.ChromaLocInfoPresentFlag = b == 1
if p.ChromaLocInfoPresentFlag { if p.ChromaLocInfoPresentFlag {
p.ChromaSampleLocTypeTopField, err = readUe(br) p.ChromaSampleLocTypeTopField = uint64(r.readUe())
if err != nil { p.ChromaSampleLocTypeBottomField = uint64(r.readUe())
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) p.TimingInfoPresentFlag = r.readBits(1) == 1
if err != nil {
return nil, errors.Wrap(err, "could not read TimingInfoPresent")
}
p.TimingInfoPresentFlag = b == 1
if p.TimingInfoPresentFlag { if p.TimingInfoPresentFlag {
err := readFields(br, []field{ p.NumUnitsInTick = uint32(r.readBits(32))
{&p.NumUnitsInTick, "NumUnitsInTick", 32}, p.TimeScale = uint32(r.readBits(32))
{&p.TimeScale, "TimeScale", 32}, p.FixedFrameRateFlag = r.readBits(1) == 1
})
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) p.NALHRDParametersPresentFlag = r.readBits(1) == 1
if err != nil {
return nil, errors.Wrap(err, "could not read NalHrdParametersPresent")
}
p.NALHRDParametersPresentFlag = b == 1
var err error
if p.NALHRDParametersPresentFlag { if p.NALHRDParametersPresentFlag {
p.NALHRDParameters, err = NewHRDParameters(br) p.NALHRDParameters, err = NewHRDParameters(br)
if err != nil { if err != nil {
@ -532,11 +328,7 @@ func NewVUIParameters(br *bits.BitReader) (*VUIParameters, error) {
} }
} }
b, err = br.ReadBits(1) p.VCLHRDParametersPresentFlag = r.readBits(1) == 1
if err != nil {
return nil, errors.Wrap(err, "could not read VclHrdParametersPresent")
}
p.VCLHRDParametersPresentFlag = b == 1
if p.VCLHRDParametersPresentFlag { if p.VCLHRDParametersPresentFlag {
p.VCLHRDParameters, err = NewHRDParameters(br) p.VCLHRDParameters, err = NewHRDParameters(br)
@ -545,54 +337,20 @@ func NewVUIParameters(br *bits.BitReader) (*VUIParameters, error) {
} }
} }
if p.NALHRDParametersPresentFlag || p.VCLHRDParametersPresentFlag { if p.NALHRDParametersPresentFlag || p.VCLHRDParametersPresentFlag {
b, err = br.ReadBits(1) p.LowDelayHRDFlag = r.readBits(1) == 1
if err != nil {
return nil, errors.Wrap(err, "could not read LowHrdDelay")
}
p.LowDelayHRDFlag = b == 1
} }
err = readFlags(br, []flag{ p.PicStructPresentFlag = r.readBits(1) == 1
{&p.PicStructPresentFlag, "PicStructPresent"}, p.BitstreamRestrictionFlag = r.readBits(1) == 1
{&p.BitstreamRestrictionFlag, "BitStreamRestriction"},
})
if p.BitstreamRestrictionFlag { if p.BitstreamRestrictionFlag {
b, err = br.ReadBits(1) p.MotionVectorsOverPicBoundariesFlag = r.readBits(1) == 1
if err != nil { p.MaxBytesPerPicDenom = r.readUe()
return nil, errors.Wrap(err, "could not read MotionVectorsOverPicBoundaries") p.MaxBitsPerMBDenom = r.readUe()
} p.Log2MaxMVLengthHorizontal = r.readUe()
p.MotionVectorsOverPicBoundariesFlag = b == 1 p.Log2MaxMVLengthVertical = r.readUe()
p.MaxNumReorderFrames = r.readUe()
p.MaxBytesPerPicDenom, err = readUe(br) p.MaxDecFrameBuffering = r.readUe()
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 return p, nil
} }
@ -600,16 +358,16 @@ func NewVUIParameters(br *bits.BitReader) (*VUIParameters, error) {
// HRDParameters describes hypothetical reference decoder parameters as defined // HRDParameters describes hypothetical reference decoder parameters as defined
// by section E.1.2 in the specifications. // by section E.1.2 in the specifications.
type HRDParameters struct { type HRDParameters struct {
CPBCntMinus1 int CPBCntMinus1 uint64
BitRateScale int BitRateScale uint8
CPBSizeScale int CPBSizeScale uint8
BitRateValueMinus1 []int BitRateValueMinus1 []uint64
CPBSizeValueMinus1 []int CPBSizeValueMinus1 []uint64
CBRFlag []bool CBRFlag []bool
InitialCPBRemovalDelayLenMinus1 int InitialCPBRemovalDelayLenMinus1 uint8
CPBRemovalDelayLenMinus1 int CPBRemovalDelayLenMinus1 uint8
DPBOutputDelayLenMinus1 int DPBOutputDelayLenMinus1 uint8
TimeOffsetLen int TimeOffsetLen uint8
} }
// NewHRDParameters parses hypothetical reference decoder parameter from br // NewHRDParameters parses hypothetical reference decoder parameter from br
@ -617,33 +375,16 @@ type HRDParameters struct {
// new HRDParameters. // new HRDParameters.
func NewHRDParameters(br *bits.BitReader) (*HRDParameters, error) { func NewHRDParameters(br *bits.BitReader) (*HRDParameters, error) {
h := &HRDParameters{} h := &HRDParameters{}
var err error r := newFieldReader(br)
h.CPBCntMinus1, err = readUe(br)
if err != nil {
return nil, errors.Wrap(err, "could not parse CPBCntMinus1")
}
err = readFields(br, []field{ h.CPBCntMinus1 = r.readUe()
{&h.BitRateScale, "BitRateScale", 4}, h.BitRateScale = uint8(r.readBits(4))
{&h.CPBSizeScale, "CPBSizeScale", 4}, h.CPBSizeScale = uint8(r.readBits(4))
})
if err != nil {
return nil, err
}
// SchedSelIdx E1.2 // SchedSelIdx E1.2
for sseli := 0; sseli <= h.CPBCntMinus1; sseli++ { for sseli := 0; sseli <= int(h.CPBCntMinus1); sseli++ {
ue, err := readUe(br) h.BitRateValueMinus1 = append(h.BitRateValueMinus1, r.readUe())
if err != nil { h.CPBSizeValueMinus1 = append(h.CPBSizeValueMinus1, r.readUe())
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 { if v, _ := br.ReadBits(1); v == 1 {
h.CBRFlag = append(h.CBRFlag, true) h.CBRFlag = append(h.CBRFlag, true)
@ -651,17 +392,14 @@ func NewHRDParameters(br *bits.BitReader) (*HRDParameters, error) {
h.CBRFlag = append(h.CBRFlag, false) h.CBRFlag = append(h.CBRFlag, false)
} }
err = readFields(br, h.InitialCPBRemovalDelayLenMinus1 = uint8(r.readBits(5))
[]field{ h.CPBRemovalDelayLenMinus1 = uint8(r.readBits(5))
{&h.InitialCPBRemovalDelayLenMinus1, "InitialCPBRemovalDelayLenMinus1", 5}, h.DPBOutputDelayLenMinus1 = uint8(r.readBits(5))
{&h.CPBRemovalDelayLenMinus1, "CPBRemovalDelayLenMinus1", 5}, h.TimeOffsetLen = uint8(r.readBits(5))
{&h.DPBOutputDelayLenMinus1, "DpbOutputDelayLenMinus1", 5}, }
{&h.TimeOffsetLen, "TimeOffsetLen", 5},
}, if r.err() != nil {
) return nil, fmt.Errorf("error from fieldReader: %v", r.err())
if err != nil {
return nil, err
}
} }
return h, nil return h, nil
} }