av/codec/h264/h264dec/pps.go

132 lines
3.8 KiB
Go

package h264dec
import (
"math"
"bitbucket.org/ausocean/av/codec/h264/h264dec/bits"
)
// import "strings"
// Specification Page 46 7.3.2.2
type PPS struct {
ID, SPSID int
EntropyCodingMode int
NumSliceGroupsMinus1 int
BottomFieldPicOrderInFramePresent bool
NumSlicGroupsMinus1 int
SliceGroupMapType int
RunLengthMinus1 []int
TopLeft []int
BottomRight []int
SliceGroupChangeDirection bool
SliceGroupChangeRateMinus1 int
PicSizeInMapUnitsMinus1 int
SliceGroupId []int
NumRefIdxL0DefaultActiveMinus1 int
NumRefIdxL1DefaultActiveMinus1 int
WeightedPred bool
WeightedBipred int
PicInitQpMinus26 int
PicInitQsMinus26 int
ChromaQpIndexOffset int
DeblockingFilterControlPresent bool
ConstrainedIntraPred bool
RedundantPicCntPresent bool
Transform8x8Mode int
PicScalingMatrixPresent bool
PicScalingListPresent []bool
SecondChromaQpIndexOffset int
}
func NewPPS(sps *SPS, rbsp []byte, showPacket bool) (*PPS, error) {
logger.Printf("debug: PPS RBSP %d bytes %d bits == \n", len(rbsp), len(rbsp)*8)
logger.Printf("debug: \t%#v\n", rbsp[0:8])
pps := PPS{}
// TODO: give this io.Reader
br := bits.NewBitReader(nil)
r := newFieldReader(br)
pps.ID = int(r.readUe())
pps.SPSID = int(r.readUe())
pps.EntropyCodingMode = int(r.readBits(1))
pps.BottomFieldPicOrderInFramePresent = r.readBits(1) == 1
pps.NumSliceGroupsMinus1 = int(r.readUe())
if pps.NumSliceGroupsMinus1 > 0 {
pps.SliceGroupMapType = int(r.readUe())
if pps.SliceGroupMapType == 0 {
for iGroup := 0; iGroup <= pps.NumSliceGroupsMinus1; iGroup++ {
pps.RunLengthMinus1[iGroup] = int(r.readUe())
}
} else if pps.SliceGroupMapType == 2 {
for iGroup := 0; iGroup < pps.NumSliceGroupsMinus1; iGroup++ {
pps.TopLeft[iGroup] = int(r.readUe())
pps.BottomRight[iGroup] = int(r.readUe())
}
} else if pps.SliceGroupMapType > 2 && pps.SliceGroupMapType < 6 {
pps.SliceGroupChangeDirection = r.readBits(1) == 1
pps.SliceGroupChangeRateMinus1 = int(r.readUe())
} else if pps.SliceGroupMapType == 6 {
pps.PicSizeInMapUnitsMinus1 = int(r.readUe())
for i := 0; i <= pps.PicSizeInMapUnitsMinus1; i++ {
pps.SliceGroupId[i] = int(r.readBits(int(math.Ceil(math.Log2(float64(pps.NumSliceGroupsMinus1 + 1))))))
}
}
}
pps.NumRefIdxL0DefaultActiveMinus1 = int(r.readUe())
pps.NumRefIdxL1DefaultActiveMinus1 = int(r.readUe())
pps.WeightedPred = r.readBits(1) == 1
pps.WeightedBipred = int(r.readBits(2))
pps.PicInitQpMinus26 = int(r.readSe())
pps.PicInitQsMinus26 = int(r.readSe())
pps.ChromaQpIndexOffset = int(r.readSe())
pps.DeblockingFilterControlPresent = r.readBits(1) == 1
pps.ConstrainedIntraPred = r.readBits(1) == 1
pps.RedundantPicCntPresent = r.readBits(1) == 1
logger.Printf("debug: \tChecking for more PPS data")
if moreRBSPData(br) {
logger.Printf("debug: \tProcessing additional PPS data")
pps.Transform8x8Mode = int(r.readBits(1))
pps.PicScalingMatrixPresent = r.readBits(1) == 1
if pps.PicScalingMatrixPresent {
v := 6
if sps.ChromaFormatIDC != chroma444 {
v = 2
}
for i := 0; i < 6+(v*pps.Transform8x8Mode); i++ {
pps.PicScalingListPresent[i] = r.readBits(1) == 1
if pps.PicScalingListPresent[i] {
if i < 6 {
scalingList(
br,
ScalingList4x4[i],
16,
DefaultScalingMatrix4x4[i])
} else {
scalingList(
br,
ScalingList8x8[i],
64,
DefaultScalingMatrix8x8[i-6])
}
}
}
pps.SecondChromaQpIndexOffset = r.readSe()
}
moreRBSPData(br)
// rbspTrailingBits()
}
return &pps, nil
}