mirror of https://bitbucket.org/ausocean/av.git
301 lines
7.7 KiB
Go
301 lines
7.7 KiB
Go
/*
|
|
DESCRIPTION
|
|
nalunit.go provides structures for a NAL unit as well as it's extensions.
|
|
|
|
AUTHORS
|
|
Saxon Nelson-Milton <saxon@ausocean.org>, The Australian Ocean Laboratory (AusOcean)
|
|
mrmod <mcmoranbjr@gmail.com>
|
|
*/
|
|
|
|
package h264dec
|
|
|
|
import (
|
|
"io"
|
|
|
|
"github.com/pkg/errors"
|
|
|
|
"bitbucket.org/ausocean/av/codec/h264/h264dec/bits"
|
|
)
|
|
|
|
// MVCExtension describes a NAL unit header multiview video coding extension, as
|
|
// defined in section H.7.3.1.1 of the specifications.
|
|
type MVCExtension struct {
|
|
NonIdrFlag bool
|
|
PriorityID int
|
|
ViewID int
|
|
TemporalID int
|
|
AnchorPicFlag bool
|
|
InterViewFlag bool
|
|
ReservedOneBit int
|
|
}
|
|
|
|
// NewMVCExtension parses a NAL unit header multiview video coding extension
|
|
// from br following the syntax structure specified in section H.7.3.1.1, and
|
|
// returns as a new MVCExtension.
|
|
func NewMVCExtension(br *bits.BitReader) (*MVCExtension, error) {
|
|
e := &MVCExtension{}
|
|
var err error
|
|
|
|
e.NonIdrFlag, err = br.ReadBool()
|
|
if err != nil {
|
|
return nil, errors.Wrap(err, "could not read NonIdrFlag")
|
|
}
|
|
|
|
e.PriorityID, err = br.ReadBitsInt(6)
|
|
if err != nil {
|
|
return nil, errors.Wrap(err, "could not read PriorityId")
|
|
}
|
|
|
|
e.ViewID, err = br.ReadBitsInt(10)
|
|
if err != nil {
|
|
return nil, errors.Wrap(err, "could not read ViewId")
|
|
}
|
|
|
|
e.TemporalID, err = br.ReadBitsInt(3)
|
|
if err != nil {
|
|
return nil, errors.Wrap(err, "could not read TemporalId")
|
|
}
|
|
|
|
e.AnchorPicFlag, err = br.ReadBool()
|
|
if err != nil {
|
|
return nil, errors.Wrap(err, "could not read AnchorPicFlag")
|
|
}
|
|
|
|
e.InterViewFlag, err = br.ReadBool()
|
|
if err != nil {
|
|
return nil, errors.Wrap(err, "could not read InterViewFlag")
|
|
}
|
|
|
|
e.ReservedOneBit, err = br.ReadBitsInt(1)
|
|
if err != nil {
|
|
return nil, errors.Wrap(err, "could not read ReservedOneBit")
|
|
}
|
|
|
|
return e, nil
|
|
}
|
|
|
|
// ThreeDAVCExtension describes a NAL unit header 3D advanced video coding
|
|
// extension, as defined in section J.7.3.1.1 of the specifications.
|
|
type ThreeDAVCExtension struct {
|
|
ViewIdx int
|
|
DepthFlag bool
|
|
NonIdrFlag bool
|
|
TemporalID int
|
|
AnchorPicFlag bool
|
|
InterViewFlag bool
|
|
}
|
|
|
|
// NewThreeDAVCExtension parses a NAL unit header 3D advanced video coding
|
|
// extension from br following the syntax structure specified in section
|
|
// J.7.3.1.1, and returns as a new ThreeDAVCExtension.
|
|
func NewThreeDAVCExtension(br *bits.BitReader) (*ThreeDAVCExtension, error) {
|
|
e := &ThreeDAVCExtension{}
|
|
var err error
|
|
|
|
e.ViewIdx, err = br.ReadBitsInt(8)
|
|
if err != nil {
|
|
return nil, errors.Wrap(err, "could not read ViewIdx")
|
|
}
|
|
|
|
e.DepthFlag, err = br.ReadBool()
|
|
if err != nil {
|
|
return nil, errors.Wrap(err, "could not read DepthFlag")
|
|
}
|
|
|
|
e.NonIdrFlag, err = br.ReadBool()
|
|
if err != nil {
|
|
return nil, errors.Wrap(err, "could not read NonIdrFlag")
|
|
}
|
|
|
|
e.TemporalID, err = br.ReadBitsInt(3)
|
|
if err != nil {
|
|
return nil, errors.Wrap(err, "could not read TemporalId")
|
|
}
|
|
|
|
e.AnchorPicFlag, err = br.ReadBool()
|
|
if err != nil {
|
|
return nil, errors.Wrap(err, "could not read AnchorPicFlag")
|
|
}
|
|
|
|
e.InterViewFlag, err = br.ReadBool()
|
|
if err != nil {
|
|
return nil, errors.Wrap(err, "could not read InterViewFlag")
|
|
}
|
|
|
|
return e, nil
|
|
}
|
|
|
|
// SVCExtension describes a NAL unit header scalable video coding extension, as
|
|
// defined in section G.7.3.1.1 of the specifications.
|
|
type SVCExtension struct {
|
|
IdrFlag bool
|
|
PriorityId int
|
|
NoInterLayerPredFlag bool
|
|
DependencyId int
|
|
QualityId int
|
|
TemporalId int
|
|
UseRefBasePicFlag bool
|
|
DiscardableFlag bool
|
|
OutputFlag bool
|
|
ReservedThree2Bits int
|
|
}
|
|
|
|
// NewSVCExtension parses a NAL unit header scalable video coding extension from
|
|
// br following the syntax structure specified in section G.7.3.1.1, and returns
|
|
// as a new SVCExtension.
|
|
func NewSVCExtension(br *bits.BitReader) (*SVCExtension, error) {
|
|
e := &SVCExtension{}
|
|
var err error
|
|
|
|
e.IdrFlag, err = br.ReadBool()
|
|
if err != nil {
|
|
return nil, errors.Wrap(err, "could not read IdrFlag")
|
|
}
|
|
|
|
e.PriorityId, err = br.ReadBitsInt(6)
|
|
if err != nil {
|
|
return nil, errors.Wrap(err, "could not read PriorityId")
|
|
}
|
|
|
|
e.NoInterLayerPredFlag, err = br.ReadBool()
|
|
if err != nil {
|
|
return nil, errors.Wrap(err, "could not read NoInterLayerPredFlag")
|
|
}
|
|
|
|
e.DependencyId, err = br.ReadBitsInt(3)
|
|
if err != nil {
|
|
return nil, errors.Wrap(err, "could not read DependencyId")
|
|
}
|
|
|
|
e.QualityId, err = br.ReadBitsInt(4)
|
|
if err != nil {
|
|
return nil, errors.Wrap(err, "could not read QualityId")
|
|
}
|
|
|
|
e.TemporalId, err = br.ReadBitsInt(3)
|
|
if err != nil {
|
|
return nil, errors.Wrap(err, "could not read TemporalId")
|
|
}
|
|
|
|
e.UseRefBasePicFlag, err = br.ReadBool()
|
|
if err != nil {
|
|
return nil, errors.Wrap(err, "could not read UseRefBasePicFlag")
|
|
}
|
|
|
|
e.DiscardableFlag, err = br.ReadBool()
|
|
if err != nil {
|
|
return nil, errors.Wrap(err, "could not read DiscardableFlag")
|
|
}
|
|
|
|
e.OutputFlag, err = br.ReadBool()
|
|
if err != nil {
|
|
return nil, errors.Wrap(err, "could not read OutputFlag")
|
|
}
|
|
|
|
e.ReservedThree2Bits, err = br.ReadBitsInt(2)
|
|
if err != nil {
|
|
return nil, errors.Wrap(err, "could not read ReservedThree2Bits")
|
|
}
|
|
|
|
return e, nil
|
|
}
|
|
|
|
// NALUnit describes a network abstraction layer unit, as defined in section
|
|
// 7.3.1 of the specifications.
|
|
type NALUnit struct {
|
|
ForbiddenZeroBit int
|
|
RefIdc int
|
|
Type int
|
|
SVCExtensionFlag int
|
|
AVC3dExtensionFlag int
|
|
SVCExtension *SVCExtension
|
|
ThreeDAVCExtension *ThreeDAVCExtension
|
|
MVCExtension *MVCExtension
|
|
EmulationPreventionThreeByte byte
|
|
RBSP []byte
|
|
}
|
|
|
|
// NewNALUnit parses a network abstraction layer unit from br following the
|
|
// syntax structure specified in section 7.3.1, and returns as a new NALUnit.
|
|
func NewNALUnit(br *bits.BitReader) (*NALUnit, error) {
|
|
n := &NALUnit{}
|
|
|
|
err := readFields(br, []field{
|
|
{&n.ForbiddenZeroBit, "ForbiddenZeroBit", 1},
|
|
{&n.RefIdc, "NalRefIdc", 2},
|
|
{&n.Type, "NalUnitType", 5},
|
|
})
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
var headBytes, rbspBytes = 1, 0
|
|
|
|
// TODO: use consts for the NAL types here
|
|
if n.Type == 14 || n.Type == 20 || n.Type == 21 {
|
|
if n.Type != 21 {
|
|
n.SVCExtensionFlag, err = br.ReadBool()
|
|
if err != nil {
|
|
return nil, errors.Wrap(err, "could not read SVCExtensionFlag")
|
|
}
|
|
} else {
|
|
n.AVC3DExtensionFlag, err = br.ReadBool()
|
|
if err != nil {
|
|
return nil, errors.Wrap(err, "could not read AVC3DExtensionFlag")
|
|
}
|
|
}
|
|
if n.SVCExtensionFlag {
|
|
n.SVCExtension, err = NewSVCExtension(br)
|
|
if err != nil {
|
|
return nil, errors.Wrap(err, "could not parse SVCExtension")
|
|
}
|
|
n.HeaderBytes += 3
|
|
} else if n.AVC3DExtensionFlag {
|
|
n.ThreeDAVCExtension, err = NewThreeDAVCExtension(br)
|
|
if err != nil {
|
|
return nil, errors.Wrap(err, "could not parse ThreeDAVCExtension")
|
|
}
|
|
n.HeaderBytes += 2
|
|
} else {
|
|
n.MVCExtension, err = NewMVCExtension(br)
|
|
if err != nil {
|
|
return nil, errors.Wrap(err, "could not parse MVCExtension")
|
|
}
|
|
n.HeaderBytes += 3
|
|
}
|
|
}
|
|
|
|
for moreRBSPData(br) {
|
|
next3Bytes, err := br.PeekBits(24)
|
|
if err != nil && errors.Cause(err) != io.EOF {
|
|
return nil, errors.Wrap("could not Peek next 3 bytes")
|
|
}
|
|
|
|
if next3Bytes == 0x000003 {
|
|
for j := 0; j < 2; j++ {
|
|
rbspByte, err := br.ReadBits(8)
|
|
if err != nil {
|
|
return nil, errors.Wrap(err, "could not read rbspByte")
|
|
}
|
|
n.rbsp = append(n.rbsp, byte(rbspByte))
|
|
}
|
|
i += 2
|
|
|
|
// Read Emulation prevention three byte.
|
|
eptByte, err := br.ReadBits(8)
|
|
if err != nil {
|
|
return nil, errors.Wrap(err, "could not read eptByte")
|
|
}
|
|
n.EmulationPreventionThreeByte = byte(eptByte)
|
|
} else {
|
|
b, err := br.ReadBits(8)
|
|
if err != nil {
|
|
return nil, errors.Wrap(err, "could not read RBSP byte")
|
|
}
|
|
n.rbsp = append(n.rbsp, byte(b))
|
|
}
|
|
}
|
|
|
|
return n, nil
|
|
}
|