mirror of https://bitbucket.org/ausocean/av.git
codec/h264/h264dec: merged in master and fixed conflict
This commit is contained in:
commit
84dfbfa2fd
|
@ -262,7 +262,7 @@ func run(cfg revid.Config) {
|
|||
|
||||
ns, err := netsender.New(log, nil, readPin, nil)
|
||||
if err != nil {
|
||||
log.Log(logger.Fatal, pkg+"could not initialise netsender client")
|
||||
log.Log(logger.Fatal, pkg+"could not initialise netsender client: "+err.Error())
|
||||
}
|
||||
|
||||
var vs int
|
||||
|
|
|
@ -19,6 +19,8 @@ const (
|
|||
naluTypePrefixNALU
|
||||
naluTypeSubsetSPS
|
||||
naluTypeDepthParamSet
|
||||
naluTypeSliceLayerExtRBSP = 20
|
||||
naluTypeSliceLayerExtRBSP2 = 21
|
||||
)
|
||||
|
||||
var (
|
||||
|
|
|
@ -1,161 +1,291 @@
|
|||
/*
|
||||
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 (
|
||||
"bitbucket.org/ausocean/av/codec/h264/h264dec/bits"
|
||||
"fmt"
|
||||
"io"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
|
||||
"bitbucket.org/ausocean/av/codec/h264/h264dec/bits"
|
||||
)
|
||||
|
||||
type NalUnit struct {
|
||||
NumBytes int
|
||||
ForbiddenZeroBit int
|
||||
RefIdc int
|
||||
Type int
|
||||
SvcExtensionFlag int
|
||||
Avc3dExtensionFlag int
|
||||
IdrFlag int
|
||||
PriorityId int
|
||||
NoInterLayerPredFlag int
|
||||
DependencyId int
|
||||
QualityId int
|
||||
TemporalId int
|
||||
UseRefBasePicFlag int
|
||||
DiscardableFlag int
|
||||
OutputFlag int
|
||||
ReservedThree2Bits int
|
||||
HeaderBytes int
|
||||
NonIdrFlag int
|
||||
ViewId int
|
||||
AnchorPicFlag int
|
||||
InterViewFlag int
|
||||
ReservedOneBit int
|
||||
ViewIdx int
|
||||
DepthFlag int
|
||||
// MVCExtension describes a NAL unit header multiview video coding extension, as
|
||||
// defined in section H.7.3.1.1 of the specifications.
|
||||
// Semantics of fields are specified in section H.7.4.1.1.
|
||||
type MVCExtension struct {
|
||||
// non_idr_flag, if true indicates that access unit is not IDR.
|
||||
NonIdrFlag bool
|
||||
|
||||
// priority_id, indicates priority of NAL unit. A lower value => higher priority.
|
||||
PriorityID uint8
|
||||
|
||||
// view_id, specifies a view identifier for the unit. Units with identical
|
||||
// view_id are in the same view.
|
||||
ViewID uint32
|
||||
|
||||
// temporal_id, temporal identifier for the unit.
|
||||
TemporalID uint8
|
||||
|
||||
// anchor_pic_flag, if true access unit is an anchor access unit.
|
||||
AnchorPicFlag bool
|
||||
|
||||
// inter_view_flag, if false current view component not used for inter-view
|
||||
// prediction elsewhere in access unit.
|
||||
InterViewFlag bool
|
||||
|
||||
// reserved_one_bit, always 1 (ignored by decoders)
|
||||
ReservedOneBit uint8
|
||||
}
|
||||
|
||||
// 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{}
|
||||
r := newFieldReader(br)
|
||||
|
||||
e.NonIdrFlag = r.readBits(1) == 1
|
||||
e.PriorityID = uint8(r.readBits(6))
|
||||
e.ViewID = uint32(r.readBits(10))
|
||||
e.TemporalID = uint8(r.readBits(3))
|
||||
e.AnchorPicFlag = r.readBits(1) == 1
|
||||
e.InterViewFlag = r.readBits(1) == 1
|
||||
e.ReservedOneBit = uint8(r.readBits(1))
|
||||
|
||||
if r.err() != nil {
|
||||
return nil, fmt.Errorf("error from fieldReader: %v", r.err())
|
||||
}
|
||||
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.
|
||||
// For field semantics see section J.7.4.1.1.
|
||||
type ThreeDAVCExtension struct {
|
||||
// view_idx, specifies the order index for the NAL i.e. view_id = view_id[view_idx].
|
||||
ViewIdx uint8
|
||||
|
||||
// dpeth_flag, if true indicates NAL part of a depth view component, otherwise
|
||||
// a texture view component.
|
||||
DepthFlag bool
|
||||
|
||||
// non_idr_flag, if true indicates that access unit is not IDR.
|
||||
NonIdrFlag bool
|
||||
|
||||
// temporal_id, temporal identifier for the unit.
|
||||
TemporalID uint8
|
||||
|
||||
// anchor_pic_flag, if true access unit is an anchor access unit.
|
||||
AnchorPicFlag bool
|
||||
|
||||
// inter_view_flag, if false current view component not used for inter-view
|
||||
// prediction elsewhere in access unit.
|
||||
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{}
|
||||
r := newFieldReader(br)
|
||||
|
||||
e.ViewIdx = uint8(r.readBits(8))
|
||||
e.DepthFlag = r.readBits(1) == 1
|
||||
e.NonIdrFlag = r.readBits(1) == 1
|
||||
e.TemporalID = uint8(r.readBits(3))
|
||||
e.AnchorPicFlag = r.readBits(1) == 1
|
||||
e.InterViewFlag = r.readBits(1) == 1
|
||||
|
||||
if r.err() != nil {
|
||||
return nil, fmt.Errorf("error from fieldReader: %v", r.err())
|
||||
}
|
||||
|
||||
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.
|
||||
// For field semantics see section G.7.4.1.1.
|
||||
type SVCExtension struct {
|
||||
// idr_flag, if true the current coded picture is an IDR picture when
|
||||
// dependency_id == max(dependency_id) in the coded picture.
|
||||
IdrFlag bool
|
||||
|
||||
// priority_id, specifies priority identifier for unit.
|
||||
PriorityID uint8
|
||||
|
||||
// no_inter_layer_pred_flag, if true inter-layer prediction can't be used for
|
||||
// decoding slice.
|
||||
NoInterLayerPredFlag bool
|
||||
|
||||
// dependency_id, specifies a dependency identifier for the NAL.
|
||||
DependencyID uint8
|
||||
|
||||
// quality_id, specifies a quality identifier for the NAL.
|
||||
QualityID uint8
|
||||
|
||||
// temporal_id, specifiesa temporal identifier for the NAL.
|
||||
TemporalID uint8
|
||||
|
||||
// use_ref_base_pic_flag, if true indicates reference base pictures and
|
||||
// decoded pictures are used as references for inter prediction.
|
||||
UseRefBasePicFlag bool
|
||||
|
||||
// discardable_flag, if true, indicates current NAL is not used for decoding
|
||||
// dependency representations that are part of the current coded picture or
|
||||
// any subsequent coded picture in decoding order and have a greater
|
||||
// dependency_id value than current NAL.
|
||||
DiscardableFlag bool
|
||||
|
||||
// output_flag, affects the decoded picture output and removal processes as
|
||||
// specified in Annex C.
|
||||
OutputFlag bool
|
||||
|
||||
// reserved_three_2bits, equal to 3. Decoders ignore.
|
||||
ReservedThree2Bits uint8
|
||||
}
|
||||
|
||||
// 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{}
|
||||
r := newFieldReader(br)
|
||||
|
||||
e.IdrFlag = r.readBits(1) == 1
|
||||
e.PriorityID = uint8(r.readBits(6))
|
||||
e.NoInterLayerPredFlag = r.readBits(1) == 1
|
||||
e.DependencyID = uint8(r.readBits(3))
|
||||
e.QualityID = uint8(r.readBits(4))
|
||||
e.TemporalID = uint8(r.readBits(3))
|
||||
e.UseRefBasePicFlag = r.readBits(1) == 1
|
||||
e.DiscardableFlag = r.readBits(1) == 1
|
||||
e.OutputFlag = r.readBits(1) == 1
|
||||
e.ReservedThree2Bits = uint8(r.readBits(2))
|
||||
|
||||
if r.err() != nil {
|
||||
return nil, fmt.Errorf("error from fieldReader: %v", r.err())
|
||||
}
|
||||
return e, nil
|
||||
}
|
||||
|
||||
// NALUnit describes a network abstraction layer unit, as defined in section
|
||||
// 7.3.1 of the specifications.
|
||||
// Field semantics are defined in section 7.4.1.
|
||||
type NALUnit struct {
|
||||
// forbidden_zero_bit, always 0.
|
||||
ForbiddenZeroBit uint8
|
||||
|
||||
// nal_ref_idc, if not 0 indicates content of NAL contains a sequence parameter
|
||||
// set, a sequence parameter set extension, a subset sequence parameter set,
|
||||
// a picture parameter set, a slice of a reference picture, a slice data
|
||||
// partition of a reference picture, or a prefix NAL preceding a slice of
|
||||
// a reference picture.
|
||||
RefIdc uint8
|
||||
|
||||
// nal_unit_type, specifies the type of RBSP data contained in the NAL as
|
||||
// defined in Table 7-1.
|
||||
Type uint8
|
||||
|
||||
// svc_extension_flag, indicates whether a nal_unit_header_svc_extension()
|
||||
// (G.7.3.1.1) or nal_unit_header_mvc_extension() (H.7.3.1.1) will follow next
|
||||
// in the syntax structure.
|
||||
SVCExtensionFlag bool
|
||||
|
||||
// avc_3d_extension_flag, for nal_unit_type = 21, indicates that a
|
||||
// nal_unit_header_mvc_extension() (H.7.3.1.1) or
|
||||
// nal_unit_header_3davc_extension() (J.7.3.1.1) will follow next in syntax
|
||||
// structure.
|
||||
AVC3DExtensionFlag bool
|
||||
|
||||
// nal_unit_header_svc_extension() as defined in section G.7.3.1.1.
|
||||
SVCExtension *SVCExtension
|
||||
|
||||
// nal_unit_header_3davc_extension() as defined in section J.7.3.1.1
|
||||
ThreeDAVCExtension *ThreeDAVCExtension
|
||||
|
||||
// nal_unit_header_mvc_extension() as defined in section H.7.3.1.1).
|
||||
MVCExtension *MVCExtension
|
||||
|
||||
// emulation_prevention_three_byte, equal to 0x03 and is discarded by decoder.
|
||||
EmulationPreventionThreeByte byte
|
||||
rbsp []byte
|
||||
|
||||
// rbsp_byte, the raw byte sequence payload data for the NAL.
|
||||
RBSP []byte
|
||||
}
|
||||
|
||||
func NalUnitHeaderSvcExtension(nalUnit *NalUnit, br *bits.BitReader) error {
|
||||
return readFields(br, []field{
|
||||
{&nalUnit.IdrFlag, "IdrFlag", 1},
|
||||
{&nalUnit.PriorityId, "PriorityId", 6},
|
||||
{&nalUnit.NoInterLayerPredFlag, "NoInterLayerPredFlag", 1},
|
||||
{&nalUnit.DependencyId, "DependencyId", 3},
|
||||
{&nalUnit.QualityId, "QualityId", 4},
|
||||
{&nalUnit.TemporalId, "TemporalId", 3},
|
||||
{&nalUnit.UseRefBasePicFlag, "UseRefBasePicFlag", 1},
|
||||
{&nalUnit.DiscardableFlag, "DiscardableFlag", 1},
|
||||
{&nalUnit.OutputFlag, "OutputFlag", 1},
|
||||
{&nalUnit.ReservedThree2Bits, "ReservedThree2Bits", 2},
|
||||
})
|
||||
}
|
||||
// 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{}
|
||||
r := newFieldReader(br)
|
||||
|
||||
func NalUnitHeader3davcExtension(nalUnit *NalUnit, br *bits.BitReader) error {
|
||||
return readFields(br, []field{
|
||||
{&nalUnit.ViewIdx, "ViewIdx", 8},
|
||||
{&nalUnit.DepthFlag, "DepthFlag", 1},
|
||||
{&nalUnit.NonIdrFlag, "NonIdrFlag", 1},
|
||||
{&nalUnit.TemporalId, "TemporalId", 3},
|
||||
{&nalUnit.AnchorPicFlag, "AnchorPicFlag", 1},
|
||||
{&nalUnit.InterViewFlag, "InterViewFlag", 1},
|
||||
})
|
||||
}
|
||||
n.ForbiddenZeroBit = uint8(r.readBits(1))
|
||||
n.RefIdc = uint8(r.readBits(2))
|
||||
n.Type = uint8(r.readBits(5))
|
||||
|
||||
func NalUnitHeaderMvcExtension(nalUnit *NalUnit, br *bits.BitReader) error {
|
||||
return readFields(br, []field{
|
||||
{&nalUnit.NonIdrFlag, "NonIdrFlag", 1},
|
||||
{&nalUnit.PriorityId, "PriorityId", 6},
|
||||
{&nalUnit.ViewId, "ViewId", 10},
|
||||
{&nalUnit.TemporalId, "TemporalId", 3},
|
||||
{&nalUnit.AnchorPicFlag, "AnchorPicFlag", 1},
|
||||
{&nalUnit.InterViewFlag, "InterViewFlag", 1},
|
||||
{&nalUnit.ReservedOneBit, "ReservedOneBit", 1},
|
||||
})
|
||||
}
|
||||
|
||||
func (n *NalUnit) RBSP() []byte {
|
||||
return n.rbsp
|
||||
}
|
||||
|
||||
func NewNalUnit(frame []byte, numBytesInNal int) (*NalUnit, error) {
|
||||
logger.Printf("debug: reading %d byte NAL\n", numBytesInNal)
|
||||
nalUnit := NalUnit{
|
||||
NumBytes: numBytesInNal,
|
||||
HeaderBytes: 1,
|
||||
}
|
||||
// TODO: pass in actual io.Reader to NewBitReader
|
||||
br := bits.NewBitReader(nil)
|
||||
|
||||
err := readFields(br, []field{
|
||||
{&nalUnit.ForbiddenZeroBit, "ForbiddenZeroBit", 1},
|
||||
{&nalUnit.RefIdc, "NalRefIdc", 2},
|
||||
{&nalUnit.Type, "NalUnitType", 5},
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if nalUnit.Type == 14 || nalUnit.Type == 20 || nalUnit.Type == 21 {
|
||||
if nalUnit.Type != 21 {
|
||||
b, err := br.ReadBits(1)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "could not read SvcExtensionFlag")
|
||||
}
|
||||
nalUnit.SvcExtensionFlag = int(b)
|
||||
var err error
|
||||
if n.Type == naluTypePrefixNALU || n.Type == naluTypeSliceLayerExtRBSP || n.Type == naluTypeSliceLayerExtRBSP2 {
|
||||
if n.Type != naluTypeSliceLayerExtRBSP2 {
|
||||
n.SVCExtensionFlag = r.readBits(1) == 1
|
||||
} else {
|
||||
b, err := br.ReadBits(1)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "could not read Avc3dExtensionFlag")
|
||||
}
|
||||
nalUnit.Avc3dExtensionFlag = int(b)
|
||||
n.AVC3DExtensionFlag = r.readBits(1) == 1
|
||||
}
|
||||
if nalUnit.SvcExtensionFlag == 1 {
|
||||
NalUnitHeaderSvcExtension(&nalUnit, br)
|
||||
nalUnit.HeaderBytes += 3
|
||||
} else if nalUnit.Avc3dExtensionFlag == 1 {
|
||||
NalUnitHeader3davcExtension(&nalUnit, br)
|
||||
nalUnit.HeaderBytes += 2
|
||||
if n.SVCExtensionFlag {
|
||||
n.SVCExtension, err = NewSVCExtension(br)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "could not parse SVCExtension")
|
||||
}
|
||||
} else if n.AVC3DExtensionFlag {
|
||||
n.ThreeDAVCExtension, err = NewThreeDAVCExtension(br)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "could not parse ThreeDAVCExtension")
|
||||
}
|
||||
} else {
|
||||
NalUnitHeaderMvcExtension(&nalUnit, br)
|
||||
nalUnit.HeaderBytes += 3
|
||||
|
||||
n.MVCExtension, err = NewMVCExtension(br)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "could not parse MVCExtension")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
logger.Printf("debug: found %d byte header. Reading body\n", nalUnit.HeaderBytes)
|
||||
for i := nalUnit.HeaderBytes; i < nalUnit.NumBytes; i++ {
|
||||
for moreRBSPData(br) {
|
||||
next3Bytes, err := br.PeekBits(24)
|
||||
if err != nil {
|
||||
logger.Printf("error: while reading next 3 NAL bytes: %v\n", err)
|
||||
break
|
||||
|
||||
// If PeekBits cannot get 3 bytes, but there still might be 2 bytes left in
|
||||
// the source, we will get an io.EOF; we wish to ignore this and continue.
|
||||
// The call to moreRBSPData will determine when we have reached the end of
|
||||
// the NAL unit.
|
||||
if err != nil && errors.Cause(err) != io.EOF {
|
||||
return nil, errors.Wrap(err, "could not Peek next 3 bytes")
|
||||
}
|
||||
// Little odd, the err above and the i+2 check might be synonyms
|
||||
if i+2 < nalUnit.NumBytes && next3Bytes == 0x000003 {
|
||||
|
||||
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")
|
||||
}
|
||||
nalUnit.rbsp = append(nalUnit.rbsp, byte(rbspByte))
|
||||
rbspByte := byte(r.readBits(8))
|
||||
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")
|
||||
}
|
||||
nalUnit.EmulationPreventionThreeByte = byte(eptByte)
|
||||
n.EmulationPreventionThreeByte = byte(r.readBits(8))
|
||||
} else {
|
||||
if b, err := br.ReadBits(8); err == nil {
|
||||
nalUnit.rbsp = append(nalUnit.rbsp, byte(b))
|
||||
} else {
|
||||
logger.Printf("error: while reading byte %d of %d nal bytes: %v\n", i, nalUnit.NumBytes, err)
|
||||
break
|
||||
}
|
||||
n.RBSP = append(n.RBSP, byte(r.readBits(8)))
|
||||
}
|
||||
}
|
||||
|
||||
// nalUnit.rbsp = frame[nalUnit.HeaderBytes:]
|
||||
logger.Printf("info: decoded %s NAL with %d RBSP bytes\n", NALUnitType[nalUnit.Type], len(nalUnit.rbsp))
|
||||
return &nalUnit, nil
|
||||
if r.err() != nil {
|
||||
return nil, fmt.Errorf("fieldReader error: %v", r.err())
|
||||
}
|
||||
|
||||
return n, nil
|
||||
}
|
||||
|
|
|
@ -36,6 +36,87 @@ const (
|
|||
naMbPartPredMode
|
||||
)
|
||||
|
||||
// fieldReader provides methods for reading bool and int fields from a
|
||||
// bits.BitReader with a sticky error that may be checked after a series of
|
||||
// parsing read calls.
|
||||
type fieldReader struct {
|
||||
e error
|
||||
br *bits.BitReader
|
||||
}
|
||||
|
||||
// newFieldReader returns a new fieldReader.
|
||||
func newFieldReader(br *bits.BitReader) fieldReader {
|
||||
return fieldReader{br: br}
|
||||
}
|
||||
|
||||
// readBitsInt returns an int from reading n bits from br. If we have an error
|
||||
// already, we do not continue with the read.
|
||||
func (r fieldReader) readBits(n int) uint64 {
|
||||
if r.e != nil {
|
||||
return 0
|
||||
}
|
||||
var b uint64
|
||||
b, r.e = r.br.ReadBits(n)
|
||||
return b
|
||||
}
|
||||
|
||||
// readUe parses a syntax element of ue(v) descriptor, i.e. an unsigned integer
|
||||
// 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
|
||||
// has a non-nil error.
|
||||
func (r fieldReader) readUe() int {
|
||||
if r.e != nil {
|
||||
return 0
|
||||
}
|
||||
var i int
|
||||
i, r.e = readUe(r.br)
|
||||
return i
|
||||
}
|
||||
|
||||
// readTe parses a syntax element of te(v) descriptor i.e, truncated
|
||||
// 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
|
||||
// has a non-nil error.
|
||||
func (r fieldReader) readTe(x uint) int {
|
||||
if r.e != nil {
|
||||
return 0
|
||||
}
|
||||
var i int
|
||||
i, r.e = readTe(r.br, x)
|
||||
return i
|
||||
}
|
||||
|
||||
// readSe parses a syntax element with descriptor se(v), i.e. a signed integer
|
||||
// Exp-Golomb-coded syntax element, using the method described in sections
|
||||
// 9.1 and 9.1.1 and returns as int. The read does not happen if the fieldReader
|
||||
// has a non-nil error.
|
||||
func (r fieldReader) readSe() int {
|
||||
if r.e != nil {
|
||||
return 0
|
||||
}
|
||||
var i int
|
||||
i, r.e = readSe(r.br)
|
||||
return i
|
||||
}
|
||||
|
||||
// readMe parses a syntax element of me(v) descriptor, i.e. mapped
|
||||
// Exp-Golomb-coded element, using methods described in sections 9.1 and 9.1.2
|
||||
// and returns as int. The read does not happen if the fieldReader has a
|
||||
// non-nil error.
|
||||
func (r fieldReader) readMe(chromaArrayType uint, mpm mbPartPredMode) int {
|
||||
if r.e != nil {
|
||||
return 0
|
||||
}
|
||||
var i uint
|
||||
i, r.e = readMe(r.br, chromaArrayType, mpm)
|
||||
return int(i)
|
||||
}
|
||||
|
||||
// err returns the fieldReader's error e.
|
||||
func (r fieldReader) err() error {
|
||||
return r.e
|
||||
}
|
||||
|
||||
// readUe parses a syntax element of ue(v) descriptor, i.e. an unsigned integer
|
||||
// Exp-Golomb-coded element using method as specified in section 9.1 of ITU-T H.264.
|
||||
//
|
||||
|
|
|
@ -63,7 +63,7 @@ func (h *H264Reader) Start() {
|
|||
switch nalUnit.Type {
|
||||
case naluTypeSPS:
|
||||
// TODO: handle this error
|
||||
sps, _ := NewSPS(nalUnit.rbsp, false)
|
||||
sps, _ := NewSPS(nalUnit.RBSP, false)
|
||||
h.VideoStreams = append(
|
||||
h.VideoStreams,
|
||||
&VideoStream{SPS: sps},
|
||||
|
@ -78,13 +78,13 @@ func (h *H264Reader) Start() {
|
|||
videoStream := h.VideoStreams[len(h.VideoStreams)-1]
|
||||
logger.Printf("info: frame number %d\n", len(videoStream.Slices))
|
||||
// TODO: handle this error
|
||||
sliceContext, _ := NewSliceContext(videoStream, nalUnit, nalUnit.RBSP(), true)
|
||||
sliceContext, _ := NewSliceContext(videoStream, nalUnit, nalUnit.RBSP, true)
|
||||
videoStream.Slices = append(videoStream.Slices, sliceContext)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (r *H264Reader) readNalUnit() (*NalUnit, *bits.BitReader, error) {
|
||||
func (r *H264Reader) readNalUnit() (*NALUnit, *bits.BitReader, error) {
|
||||
// Read to start of NAL
|
||||
logger.Printf("debug: Seeking NAL %d start\n", len(r.NalUnits))
|
||||
|
||||
|
@ -131,7 +131,7 @@ func (r *H264Reader) readNalUnit() (*NalUnit, *bits.BitReader, error) {
|
|||
r.NalUnits = append(r.NalUnits, nalUnitReader)
|
||||
// TODO: this should really take an io.Reader rather than []byte. Need to fix nil
|
||||
// once this is fixed.
|
||||
nalUnit, err := NewNalUnit(nil, 0)
|
||||
nalUnit, err := NewNALUnit(nil)
|
||||
if err != nil {
|
||||
return nil, nil, errors.Wrap(err, "cannot create new nal unit")
|
||||
}
|
||||
|
|
|
@ -23,7 +23,7 @@ type VideoStream struct {
|
|||
Slices []*SliceContext
|
||||
}
|
||||
type SliceContext struct {
|
||||
*NalUnit
|
||||
*NALUnit
|
||||
*SPS
|
||||
*PPS
|
||||
*Slice
|
||||
|
@ -240,12 +240,12 @@ func CodedBlockPatternChroma(data *SliceData) int {
|
|||
|
||||
// dependencyId see Annex G.8.8.1
|
||||
// Also G7.3.1.1 nal_unit_header_svc_extension
|
||||
func DQId(nalUnit *NalUnit) int {
|
||||
return (nalUnit.DependencyId << 4) + nalUnit.QualityId
|
||||
func DQId(nalUnit *NALUnit) int {
|
||||
return int((nalUnit.SVCExtension.DependencyID << 4)) + int(nalUnit.SVCExtension.QualityID)
|
||||
}
|
||||
|
||||
// Annex G p527
|
||||
func NumMbPart(nalUnit *NalUnit, sps *SPS, header *SliceHeader, data *SliceData) int {
|
||||
func NumMbPart(nalUnit *NALUnit, sps *SPS, header *SliceHeader, data *SliceData) int {
|
||||
sliceType := sliceTypeMap[header.SliceType]
|
||||
numMbPart := 0
|
||||
if MbTypeName(sliceType, CurrMbAddr(sps, header)) == "B_SKIP" || MbTypeName(sliceType, CurrMbAddr(sps, header)) == "B_Direct_16x16" {
|
||||
|
@ -381,7 +381,7 @@ func MbPred(sliceContext *SliceContext, br *bits.BitReader, rbsp []byte) error {
|
|||
}
|
||||
|
||||
} else if mbPartPredMode != direct {
|
||||
for mbPartIdx := 0; mbPartIdx < NumMbPart(sliceContext.NalUnit, sliceContext.SPS, sliceContext.Slice.Header, sliceContext.Slice.Data); mbPartIdx++ {
|
||||
for mbPartIdx := 0; mbPartIdx < NumMbPart(sliceContext.NALUnit, sliceContext.SPS, sliceContext.Slice.Header, sliceContext.Slice.Data); mbPartIdx++ {
|
||||
sliceContext.Update(sliceContext.Slice.Header, sliceContext.Slice.Data)
|
||||
m, err := MbPartPredMode(sliceContext.Slice.Data, sliceType, sliceContext.Slice.Data.MbType, mbPartIdx)
|
||||
if err != nil {
|
||||
|
@ -417,7 +417,7 @@ func MbPred(sliceContext *SliceContext, br *bits.BitReader, rbsp []byte) error {
|
|||
}
|
||||
}
|
||||
}
|
||||
for mbPartIdx := 0; mbPartIdx < NumMbPart(sliceContext.NalUnit, sliceContext.SPS, sliceContext.Slice.Header, sliceContext.Slice.Data); mbPartIdx++ {
|
||||
for mbPartIdx := 0; mbPartIdx < NumMbPart(sliceContext.NALUnit, sliceContext.SPS, sliceContext.Slice.Header, sliceContext.Slice.Data); mbPartIdx++ {
|
||||
m, err := MbPartPredMode(sliceContext.Slice.Data, sliceType, sliceContext.Slice.Data.MbType, mbPartIdx)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, fmt.Sprintf("could not get mbPartPredMode for loop 2 mbPartIdx: %d", mbPartIdx))
|
||||
|
@ -456,7 +456,7 @@ func MbPred(sliceContext *SliceContext, br *bits.BitReader, rbsp []byte) error {
|
|||
}
|
||||
}
|
||||
}
|
||||
for mbPartIdx := 0; mbPartIdx < NumMbPart(sliceContext.NalUnit, sliceContext.SPS, sliceContext.Slice.Header, sliceContext.Slice.Data); mbPartIdx++ {
|
||||
for mbPartIdx := 0; mbPartIdx < NumMbPart(sliceContext.NALUnit, sliceContext.SPS, sliceContext.Slice.Header, sliceContext.Slice.Data); mbPartIdx++ {
|
||||
sliceContext.Update(sliceContext.Slice.Header, sliceContext.Slice.Data)
|
||||
m, err := MbPartPredMode(sliceContext.Slice.Data, sliceType, sliceContext.Slice.Data.MbType, mbPartIdx)
|
||||
if err != nil {
|
||||
|
@ -815,7 +815,7 @@ func NewSliceData(sliceContext *SliceContext, br *bits.BitReader) (*SliceData, e
|
|||
if err != nil {
|
||||
return nil, errors.Wrap(err, "could not get mbPartPredMode")
|
||||
}
|
||||
if sliceContext.Slice.Data.MbTypeName == "I_NxN" && m != intra16x16 && NumMbPart(sliceContext.NalUnit, sliceContext.SPS, sliceContext.Slice.Header, sliceContext.Slice.Data) == 4 {
|
||||
if sliceContext.Slice.Data.MbTypeName == "I_NxN" && m != intra16x16 && NumMbPart(sliceContext.NALUnit, sliceContext.SPS, sliceContext.Slice.Header, sliceContext.Slice.Data) == 4 {
|
||||
logger.Printf("\tTODO: subMbPred\n")
|
||||
/*
|
||||
subMbType := SubMbPred(sliceContext.Slice.Data.MbType)
|
||||
|
@ -945,11 +945,11 @@ func NewSliceData(sliceContext *SliceContext, br *bits.BitReader) (*SliceData, e
|
|||
func (c *SliceContext) Update(header *SliceHeader, data *SliceData) {
|
||||
c.Slice = &Slice{Header: header, Data: data}
|
||||
}
|
||||
func NewSliceContext(videoStream *VideoStream, nalUnit *NalUnit, rbsp []byte, showPacket bool) (*SliceContext, error) {
|
||||
func NewSliceContext(videoStream *VideoStream, nalUnit *NALUnit, rbsp []byte, showPacket bool) (*SliceContext, error) {
|
||||
var err error
|
||||
sps := videoStream.SPS
|
||||
pps := videoStream.PPS
|
||||
logger.Printf("debug: %s RBSP %d bytes %d bits == \n", NALUnitType[nalUnit.Type], len(rbsp), len(rbsp)*8)
|
||||
logger.Printf("debug: %s RBSP %d bytes %d bits == \n", NALUnitType[int(nalUnit.Type)], len(rbsp), len(rbsp)*8)
|
||||
logger.Printf("debug: \t%#v\n", rbsp[0:8])
|
||||
var idrPic bool
|
||||
if nalUnit.Type == 5 {
|
||||
|
@ -974,7 +974,7 @@ func NewSliceContext(videoStream *VideoStream, nalUnit *NalUnit, rbsp []byte, sh
|
|||
}
|
||||
|
||||
sliceType := sliceTypeMap[header.SliceType]
|
||||
logger.Printf("debug: %s (%s) slice of %d bytes\n", NALUnitType[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)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "could not parse PPSID")
|
||||
|
@ -1350,7 +1350,7 @@ func NewSliceContext(videoStream *VideoStream, nalUnit *NalUnit, rbsp []byte, sh
|
|||
}
|
||||
|
||||
sliceContext := &SliceContext{
|
||||
NalUnit: nalUnit,
|
||||
NALUnit: nalUnit,
|
||||
SPS: sps,
|
||||
PPS: pps,
|
||||
Slice: &Slice{
|
||||
|
|
9
go.mod
9
go.mod
|
@ -3,17 +3,12 @@ module bitbucket.org/ausocean/av
|
|||
go 1.12
|
||||
|
||||
require (
|
||||
bitbucket.org/ausocean/iot v1.2.4
|
||||
bitbucket.org/ausocean/iot v1.2.5
|
||||
bitbucket.org/ausocean/utils v1.2.6
|
||||
github.com/BurntSushi/toml v0.3.1 // indirect
|
||||
github.com/Comcast/gots v0.0.0-20190305015453-8d56e473f0f7
|
||||
github.com/Shopify/toxiproxy v2.1.4+incompatible // indirect
|
||||
github.com/andreyvit/diff v0.0.0-20170406064948-c7f18ee00883 // indirect
|
||||
github.com/go-audio/audio v0.0.0-20181013203223-7b2a6ca21480
|
||||
github.com/go-audio/wav v0.0.0-20181013172942-de841e69b884
|
||||
github.com/mewkiz/flac v1.0.5
|
||||
github.com/sergi/go-diff v1.0.0 // indirect
|
||||
github.com/pkg/errors v0.8.1
|
||||
github.com/yobert/alsa v0.0.0-20180630182551-d38d89fa843e
|
||||
gopkg.in/natefinch/lumberjack.v2 v2.0.0 // indirect
|
||||
gopkg.in/yaml.v2 v2.2.2 // indirect
|
||||
)
|
||||
|
|
11
go.sum
11
go.sum
|
@ -1,5 +1,8 @@
|
|||
bitbucket.org/ausocean/iot v1.2.4 h1:M/473iQ0d4q+76heerjAQuqXzQyc5dZ3F7Bfuq6X7q4=
|
||||
bitbucket.org/ausocean/iot v1.2.4/go.mod h1:5HVLgPHccW2PxS7WDUQO6sKWMgk3Vfze/7d5bHs8EWU=
|
||||
bitbucket.org/ausocean/iot v1.2.5 h1:udD5X4oXUuKwdjO7bcq4StcDdjP8fJa2L0FnJJwF+6Q=
|
||||
bitbucket.org/ausocean/iot v1.2.5/go.mod h1:dOclxXkdxAQGWO7Y5KcP1wpNfxg9oKUA2VqjJ3Le4RA=
|
||||
bitbucket.org/ausocean/utils v1.2.4/go.mod h1:5JIXFTAMMNl5Ob79tpZfDCJ+gOO8rj7v4ORj56tHZpw=
|
||||
bitbucket.org/ausocean/utils v1.2.6 h1:JN66APCV+hu6GebIHSu2KSywhLym4vigjSz5+fB0zXc=
|
||||
bitbucket.org/ausocean/utils v1.2.6/go.mod h1:uXzX9z3PLemyURTMWRhVI8uLhPX4uuvaaO85v2hcob8=
|
||||
github.com/BurntSushi/toml v0.3.1 h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ=
|
||||
|
@ -8,16 +11,21 @@ github.com/Comcast/gots v0.0.0-20190305015453-8d56e473f0f7 h1:LdOc9B9Bj6LEsKiXSh
|
|||
github.com/Comcast/gots v0.0.0-20190305015453-8d56e473f0f7/go.mod h1:O5HA0jgDXkBp+jw0770QNBT8fsRJCbH7JXmM7wxLUBU=
|
||||
github.com/Shopify/toxiproxy v2.1.4+incompatible h1:TKdv8HiTLgE5wdJuEML90aBgNWsokNbMijUGhmcoBJc=
|
||||
github.com/Shopify/toxiproxy v2.1.4+incompatible/go.mod h1:OXgGpZ6Cli1/URJOF1DMxUHB2q5Ap20/P/eIdh4G0pI=
|
||||
github.com/adrianmo/go-nmea v1.1.1-0.20190109062325-c448653979f7/go.mod h1:HHPxPAm2kmev+61qmkZh7xgZF/7qHtSpsWppip2Ipv8=
|
||||
github.com/andreyvit/diff v0.0.0-20170406064948-c7f18ee00883 h1:bvNMNQO63//z+xNgfBlViaCIJKLlCJ6/fmUseuG0wVQ=
|
||||
github.com/andreyvit/diff v0.0.0-20170406064948-c7f18ee00883/go.mod h1:rCTlJbsFo29Kk6CurOXKm700vrz8f0KW0JNfpkRJY/8=
|
||||
github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8=
|
||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/go-audio/aiff v0.0.0-20180403003018-6c3a8a6aff12/go.mod h1:AMSAp6W1zd0koOdX6QDgGIuBDTUvLa2SLQtm7d9eM3c=
|
||||
github.com/go-audio/audio v0.0.0-20180206231410-b697a35b5608/go.mod h1:6uAu0+H2lHkwdGsAY+j2wHPNPpPoeg5AaEFh9FlA+Zs=
|
||||
github.com/go-audio/audio v0.0.0-20181013203223-7b2a6ca21480 h1:4sGU+UABMMsRJyD+Y2yzMYxq0GJFUsRRESI0P1gZ2ig=
|
||||
github.com/go-audio/audio v0.0.0-20181013203223-7b2a6ca21480/go.mod h1:6uAu0+H2lHkwdGsAY+j2wHPNPpPoeg5AaEFh9FlA+Zs=
|
||||
github.com/go-audio/wav v0.0.0-20181013172942-de841e69b884 h1:2TaXIaVA4ff/MHHezOj83tCypALTFAcXOImcFWNa3jw=
|
||||
github.com/go-audio/wav v0.0.0-20181013172942-de841e69b884/go.mod h1:UiqzUyfX0zs3pJ/DPyvS5v8sN6s5bXPUDDIVA5v8dks=
|
||||
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
|
||||
github.com/jacobsa/go-serial v0.0.0-20180131005756-15cf729a72d4/go.mod h1:2RvX5ZjVtsznNZPEt4xwJXNJrM3VTZoQf7V6gk0ysvs=
|
||||
github.com/kidoman/embd v0.0.0-20170508013040-d3d8c0c5c68d/go.mod h1:ACKj9jnzOzj1lw2ETilpFGK7L9dtJhAzT7T1OhAGtRQ=
|
||||
github.com/mattetti/audio v0.0.0-20180912171649-01576cde1f21 h1:Hc1iKlyxNHp3CV59G2E/qabUkHvEwOIJxDK0CJ7CRjA=
|
||||
github.com/mattetti/audio v0.0.0-20180912171649-01576cde1f21/go.mod h1:LlQmBGkOuV/SKzEDXBPKauvN2UqCgzXO2XjecTGj40s=
|
||||
github.com/mewkiz/flac v1.0.5 h1:dHGW/2kf+/KZ2GGqSVayNEhL9pluKn/rr/h/QqD9Ogc=
|
||||
|
@ -29,16 +37,19 @@ github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZN
|
|||
github.com/sergi/go-diff v1.0.0 h1:Kpca3qRNrduNnOQeazBd0ysaKrUJiIuISHxogkT9RPQ=
|
||||
github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo=
|
||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
github.com/stretchr/testify v1.2.1/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
|
||||
github.com/stretchr/testify v1.3.0 h1:TivCn/peBQ7UY8ooIcPgZFpTNSz0Q2U6UrFlUfqbe0Q=
|
||||
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
|
||||
github.com/yobert/alsa v0.0.0-20180630182551-d38d89fa843e h1:3NIzz7weXhh3NToPgbtlQtKiVgerEaG4/nY2skGoGG0=
|
||||
github.com/yobert/alsa v0.0.0-20180630182551-d38d89fa843e/go.mod h1:CaowXBWOiSGWEpBBV8LoVnQTVPV4ycyviC9IBLj8dRw=
|
||||
github.com/yryz/ds18b20 v0.0.0-20180211073435-3cf383a40624/go.mod h1:MqFju5qeLDFh+S9PqxYT7TEla8xeW7bgGr/69q3oki0=
|
||||
go.uber.org/atomic v1.3.2 h1:2Oa65PReHzfn29GpvgsYwloV9AVFHPDk8tYxt2c2tr4=
|
||||
go.uber.org/atomic v1.3.2/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE=
|
||||
go.uber.org/multierr v1.1.0 h1:HoEmRHQPVSqub6w2z2d2EOVs2fjyFRGyofhKuyDq0QI=
|
||||
go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0=
|
||||
go.uber.org/zap v1.9.1 h1:XCJQEf3W6eZaVwhRBof6ImoYGJSITeKWsyeh3HFu/5o=
|
||||
go.uber.org/zap v1.9.1/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q=
|
||||
golang.org/x/sys v0.0.0-20190305064518-30e92a19ae4a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/natefinch/lumberjack.v2 v2.0.0 h1:1Lc07Kr7qY4U2YPouBjpCLxpiyxIVoxqXgkXLknAOE8=
|
||||
|
|
Loading…
Reference in New Issue