From 6efed19b7fd772904639a36ea2234d8604b8c234 Mon Sep 17 00:00:00 2001 From: scruzin Date: Mon, 15 Jul 2019 08:50:45 +0930 Subject: [PATCH 01/24] Use ausocean/iot v1.2.5. --- go.mod | 9 ++------- go.sum | 11 +++++++++++ 2 files changed, 13 insertions(+), 7 deletions(-) diff --git a/go.mod b/go.mod index c3d766c5..37a7a31f 100644 --- a/go.mod +++ b/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 ) diff --git a/go.sum b/go.sum index cd09945f..5ee9f294 100644 --- a/go.sum +++ b/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= From 16b4d570b6a3c6343ca6e5bcbb5f2acf24be2a8d Mon Sep 17 00:00:00 2001 From: Saxon Date: Fri, 19 Jul 2019 17:25:57 +0930 Subject: [PATCH 02/24] codec/h264/h264dec/bits/bitreader.go: added ReadBool and ReadBitsInt methods --- codec/h264/decode/bits/bitreader.go | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/codec/h264/decode/bits/bitreader.go b/codec/h264/decode/bits/bitreader.go index 7e17f407..08cc5d41 100644 --- a/codec/h264/decode/bits/bitreader.go +++ b/codec/h264/decode/bits/bitreader.go @@ -128,6 +128,24 @@ func (br *BitReader) ReadBits(n int) (uint64, error) { return r, nil } +// ReadBitsInt reads n bits from the source, and returns as an int. +func (br *BitReader) ReadBitsInt(n int) (int, error) { + b, err := br.ReadBits(n) + if err != nil { + return 0, err + } + return int(b), nil +} + +// ReadBool reads a single bit from the source, converts to a bool and returns. +func (br *BitReader) ReadBool() (bool, error) { + b, err := br.ReadBits(1) + if err != nil { + return false, err + } + return b == 1, nil +} + // PeekBits provides the next n bits returning them in the least-significant // part of a uint64, without advancing through the source. // For example, with a source as []byte{0x8f,0xe3} (1000 1111, 1110 0011), we From 0d9861c49eddf506fec0c9f84b7c5c78160ecd63 Mon Sep 17 00:00:00 2001 From: Saxon Date: Fri, 19 Jul 2019 17:37:54 +0930 Subject: [PATCH 03/24] codec/h264/decode: added SVCExtension struct with NewSVCExtension function --- codec/h264/decode/nalunit.go | 94 +++++++++++++++++++++++++++--------- 1 file changed, 70 insertions(+), 24 deletions(-) diff --git a/codec/h264/decode/nalunit.go b/codec/h264/decode/nalunit.go index 35eeab76..0101f750 100644 --- a/codec/h264/decode/nalunit.go +++ b/codec/h264/decode/nalunit.go @@ -1,7 +1,7 @@ package h264 import ( - "github.com/ausocean/h264decode/h264/bits" + "bitbucket.org/ausocean/av/codec/h264/decode/bits" "github.com/pkg/errors" ) @@ -12,16 +12,7 @@ type NalUnit struct { 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 + SVCExtension *SVCExtension HeaderBytes int NonIdrFlag int ViewId int @@ -34,19 +25,74 @@ type NalUnit struct { 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}, - }) +type SVCExtension struct { + IdrFlag bool + PriorityId int + NoInterLayerPredFlag bool + DependencyId int + QualityId int + TemporalId int + UseRefBasePicFlag bool + DiscardableFlag bool + OutputFlag bool + ReservedThree2Bits int +} + +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 } func NalUnitHeader3davcExtension(nalUnit *NalUnit, br *bits.BitReader) error { From e54bc234c87881f1df90049731adb6a647e9060e Mon Sep 17 00:00:00 2001 From: Saxon Date: Fri, 19 Jul 2019 17:50:45 +0930 Subject: [PATCH 04/24] codec/h264/decode: added ThreeDAVCExtenstion type and NewThreeDAVCExtension function --- codec/h264/decode/nalunit.go | 66 +++++++++++++++++++++++++----------- 1 file changed, 47 insertions(+), 19 deletions(-) diff --git a/codec/h264/decode/nalunit.go b/codec/h264/decode/nalunit.go index 0101f750..db983909 100644 --- a/codec/h264/decode/nalunit.go +++ b/codec/h264/decode/nalunit.go @@ -13,18 +13,57 @@ type NalUnit struct { SvcExtensionFlag int Avc3dExtensionFlag int SVCExtension *SVCExtension - HeaderBytes int - NonIdrFlag int - ViewId int - AnchorPicFlag int - InterViewFlag int - ReservedOneBit int - ViewIdx int - DepthFlag int + ThreeDAVCExtension *ThreeDAVCExtension EmulationPreventionThreeByte byte rbsp []byte } +type ThreeDAVCExtension struct { + ViewIdx int + DepthFlag bool + NonIdrFlag bool + TemporalID int + AnchorPicFlag bool + InterViewFlag bool +} + +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 +} + type SVCExtension struct { IdrFlag bool PriorityId int @@ -95,17 +134,6 @@ func NewSVCExtension(br *bits.BitReader) (*SVCExtension, error) { return e, nil } -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}, - }) -} - func NalUnitHeaderMvcExtension(nalUnit *NalUnit, br *bits.BitReader) error { return readFields(br, []field{ {&nalUnit.NonIdrFlag, "NonIdrFlag", 1}, From 24f6b2d12f27d7ee0df2b8577908a05532c49686 Mon Sep 17 00:00:00 2001 From: Saxon Date: Fri, 19 Jul 2019 18:04:51 +0930 Subject: [PATCH 05/24] codec/h264/decode: added MVCExtension type and NewMVCExtension func --- codec/h264/decode/nalunit.go | 65 +++++++++++++++++++++++++++++------- 1 file changed, 53 insertions(+), 12 deletions(-) diff --git a/codec/h264/decode/nalunit.go b/codec/h264/decode/nalunit.go index db983909..9969cf91 100644 --- a/codec/h264/decode/nalunit.go +++ b/codec/h264/decode/nalunit.go @@ -14,10 +14,63 @@ type NalUnit struct { Avc3dExtensionFlag int SVCExtension *SVCExtension ThreeDAVCExtension *ThreeDAVCExtension + MVCExtension *MVCExtension EmulationPreventionThreeByte byte rbsp []byte } +type MVCExtension struct { + NonIdrFlag bool + PriorityID int + ViewID int + TemporalID int + AnchorPicFlag bool + InterViewFlag bool + ReservedOneBit int +} + +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 +} + type ThreeDAVCExtension struct { ViewIdx int DepthFlag bool @@ -134,18 +187,6 @@ func NewSVCExtension(br *bits.BitReader) (*SVCExtension, error) { return e, nil } -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 } From f11ba2b43375b9e0250bc415dbc1df847eb6e469 Mon Sep 17 00:00:00 2001 From: Saxon Date: Fri, 19 Jul 2019 20:20:33 +0930 Subject: [PATCH 06/24] codec/h264/h264dec: renamed NalUnit function to NewNALUnit and cleaned it up --- codec/h264/decode/nalunit.go | 134 +++++++++++++++++------------------ 1 file changed, 65 insertions(+), 69 deletions(-) diff --git a/codec/h264/decode/nalunit.go b/codec/h264/decode/nalunit.go index 9969cf91..2adf3165 100644 --- a/codec/h264/decode/nalunit.go +++ b/codec/h264/decode/nalunit.go @@ -1,23 +1,12 @@ package h264 import ( - "bitbucket.org/ausocean/av/codec/h264/decode/bits" - "github.com/pkg/errors" -) + "io" -type NalUnit struct { - NumBytes int - ForbiddenZeroBit int - RefIdc int - Type int - SvcExtensionFlag int - Avc3dExtensionFlag int - SVCExtension *SVCExtension - ThreeDAVCExtension *ThreeDAVCExtension - MVCExtension *MVCExtension - EmulationPreventionThreeByte byte - rbsp []byte -} + "github.com/pkg/errors" + + "bitbucket.org/ausocean/av/codec/h264/decode/bits" +) type MVCExtension struct { NonIdrFlag bool @@ -187,70 +176,80 @@ func NewSVCExtension(br *bits.BitReader) (*SVCExtension, error) { return e, nil } -func (n *NalUnit) RBSP() []byte { - return n.rbsp +type NALUnit struct { + ForbiddenZeroBit int + RefIdc int + Type int + SVCExtensionFlag int + AVC3dExtensionFlag int + SVCExtension *SVCExtension + ThreeDAVCExtension *ThreeDAVCExtension + MVCExtension *MVCExtension + EmulationPreventionThreeByte byte + RBSP []byte } -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) +func NewNALUnit(br *bits.BitReader) (*NALUnit, error) { + n := &NALUnit{} err := readFields(br, []field{ - {&nalUnit.ForbiddenZeroBit, "ForbiddenZeroBit", 1}, - {&nalUnit.RefIdc, "NalRefIdc", 2}, - {&nalUnit.Type, "NalUnitType", 5}, + {&n.ForbiddenZeroBit, "ForbiddenZeroBit", 1}, + {&n.RefIdc, "NalRefIdc", 2}, + {&n.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) - } else { - b, err := br.ReadBits(1) - if err != nil { - return nil, errors.Wrap(err, "could not read Avc3dExtensionFlag") - } - nalUnit.Avc3dExtensionFlag = int(b) - } - if nalUnit.SvcExtensionFlag == 1 { - NalUnitHeaderSvcExtension(&nalUnit, br) - nalUnit.HeaderBytes += 3 - } else if nalUnit.Avc3dExtensionFlag == 1 { - NalUnitHeader3davcExtension(&nalUnit, br) - nalUnit.HeaderBytes += 2 - } else { - NalUnitHeaderMvcExtension(&nalUnit, br) - nalUnit.HeaderBytes += 3 + 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 } } - 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 err != nil && errors.Cause(err) != io.EOF { + return nil, errors.Wrap("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)) + n.rbsp = append(n.rbsp, byte(rbspByte)) } i += 2 @@ -259,18 +258,15 @@ func NewNalUnit(frame []byte, numBytesInNal int) (*NalUnit, error) { if err != nil { return nil, errors.Wrap(err, "could not read eptByte") } - nalUnit.EmulationPreventionThreeByte = byte(eptByte) + n.EmulationPreventionThreeByte = byte(eptByte) } 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 + 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)) } } - // 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 + return n, nil } From bdf3b37fef494ac86f9dcd3f7e79983baa6e836c Mon Sep 17 00:00:00 2001 From: Saxon Date: Fri, 19 Jul 2019 20:23:30 +0930 Subject: [PATCH 07/24] codec/h264/h264dec: fixed import path for bits package --- codec/h264/h264dec/nalunit.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/codec/h264/h264dec/nalunit.go b/codec/h264/h264dec/nalunit.go index 4ecf8e99..592d747f 100644 --- a/codec/h264/h264dec/nalunit.go +++ b/codec/h264/h264dec/nalunit.go @@ -5,7 +5,7 @@ import ( "github.com/pkg/errors" - "bitbucket.org/ausocean/av/codec/h264/decode/bits" + "bitbucket.org/ausocean/av/codec/h264/h264dec/bits" ) type MVCExtension struct { From 278c6f2ef17b1d809c7f6040b82685fa1fc4eace Mon Sep 17 00:00:00 2001 From: Saxon Date: Fri, 19 Jul 2019 20:51:48 +0930 Subject: [PATCH 08/24] codec/h264/h264dec/nalunit.go: added commenting --- codec/h264/h264dec/nalunit.go | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/codec/h264/h264dec/nalunit.go b/codec/h264/h264dec/nalunit.go index 592d747f..dc76fb43 100644 --- a/codec/h264/h264dec/nalunit.go +++ b/codec/h264/h264dec/nalunit.go @@ -1,3 +1,12 @@ +/* +DESCRIPTION + nalunit.go provides structures for a NAL unit as well as it's extensions. + +AUTHORS + Saxon Nelson-Milton , The Australian Ocean Laboratory (AusOcean) + mrmod +*/ + package h264dec import ( @@ -8,6 +17,8 @@ import ( "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 @@ -18,6 +29,9 @@ type MVCExtension struct { 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 @@ -60,6 +74,8 @@ func NewMVCExtension(br *bits.BitReader) (*MVCExtension, error) { 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 @@ -69,6 +85,9 @@ type ThreeDAVCExtension struct { 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 @@ -106,6 +125,8 @@ func NewThreeDAVCExtension(br *bits.BitReader) (*ThreeDAVCExtension, error) { 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 @@ -119,6 +140,9 @@ type SVCExtension struct { 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 @@ -176,6 +200,8 @@ func NewSVCExtension(br *bits.BitReader) (*SVCExtension, error) { 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 @@ -189,6 +215,8 @@ type NALUnit struct { 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{} From 4d65d0d433bb735bb3f6c42b857f409b2286973e Mon Sep 17 00:00:00 2001 From: Saxon Date: Fri, 19 Jul 2019 20:58:01 +0930 Subject: [PATCH 09/24] codec/h264/h264dec: fixed random build errors --- codec/h264/h264dec/nalunit.go | 32 +++++++++++++------------------- codec/h264/h264dec/read.go | 10 +++++----- codec/h264/h264dec/slice.go | 20 ++++++++++---------- 3 files changed, 28 insertions(+), 34 deletions(-) diff --git a/codec/h264/h264dec/nalunit.go b/codec/h264/h264dec/nalunit.go index dc76fb43..9f4ecab3 100644 --- a/codec/h264/h264dec/nalunit.go +++ b/codec/h264/h264dec/nalunit.go @@ -129,11 +129,11 @@ func NewThreeDAVCExtension(br *bits.BitReader) (*ThreeDAVCExtension, error) { // defined in section G.7.3.1.1 of the specifications. type SVCExtension struct { IdrFlag bool - PriorityId int + PriorityID int NoInterLayerPredFlag bool - DependencyId int - QualityId int - TemporalId int + DependencyID int + QualityID int + TemporalID int UseRefBasePicFlag bool DiscardableFlag bool OutputFlag bool @@ -152,7 +152,7 @@ func NewSVCExtension(br *bits.BitReader) (*SVCExtension, error) { return nil, errors.Wrap(err, "could not read IdrFlag") } - e.PriorityId, err = br.ReadBitsInt(6) + e.PriorityID, err = br.ReadBitsInt(6) if err != nil { return nil, errors.Wrap(err, "could not read PriorityId") } @@ -162,17 +162,17 @@ func NewSVCExtension(br *bits.BitReader) (*SVCExtension, error) { return nil, errors.Wrap(err, "could not read NoInterLayerPredFlag") } - e.DependencyId, err = br.ReadBitsInt(3) + e.DependencyID, err = br.ReadBitsInt(3) if err != nil { return nil, errors.Wrap(err, "could not read DependencyId") } - e.QualityId, err = br.ReadBitsInt(4) + e.QualityID, err = br.ReadBitsInt(4) if err != nil { return nil, errors.Wrap(err, "could not read QualityId") } - e.TemporalId, err = br.ReadBitsInt(3) + e.TemporalID, err = br.ReadBitsInt(3) if err != nil { return nil, errors.Wrap(err, "could not read TemporalId") } @@ -206,8 +206,8 @@ type NALUnit struct { ForbiddenZeroBit int RefIdc int Type int - SVCExtensionFlag int - AVC3dExtensionFlag int + SVCExtensionFlag bool + AVC3DExtensionFlag bool SVCExtension *SVCExtension ThreeDAVCExtension *ThreeDAVCExtension MVCExtension *MVCExtension @@ -229,8 +229,6 @@ func NewNALUnit(br *bits.BitReader) (*NALUnit, error) { 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 { @@ -249,26 +247,23 @@ func NewNALUnit(br *bits.BitReader) (*NALUnit, error) { 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") + return nil, errors.Wrap(err, "could not Peek next 3 bytes") } if next3Bytes == 0x000003 { @@ -277,9 +272,8 @@ func NewNALUnit(br *bits.BitReader) (*NALUnit, error) { if err != nil { return nil, errors.Wrap(err, "could not read rbspByte") } - n.rbsp = append(n.rbsp, byte(rbspByte)) + n.RBSP = append(n.RBSP, byte(rbspByte)) } - i += 2 // Read Emulation prevention three byte. eptByte, err := br.ReadBits(8) @@ -292,7 +286,7 @@ func NewNALUnit(br *bits.BitReader) (*NALUnit, error) { if err != nil { return nil, errors.Wrap(err, "could not read RBSP byte") } - n.rbsp = append(n.rbsp, byte(b)) + n.RBSP = append(n.RBSP, byte(b)) } } diff --git a/codec/h264/h264dec/read.go b/codec/h264/h264dec/read.go index 92a12ed9..bf45bd1b 100644 --- a/codec/h264/h264dec/read.go +++ b/codec/h264/h264dec/read.go @@ -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}, @@ -71,20 +71,20 @@ func (h *H264Reader) Start() { case naluTypePPS: videoStream := h.VideoStreams[len(h.VideoStreams)-1] // TODO: handle this error - videoStream.PPS, _ = NewPPS(videoStream.SPS, nalUnit.RBSP(), false) + videoStream.PPS, _ = NewPPS(videoStream.SPS, nalUnit.RBSP, false) case naluTypeSliceIDRPicture: fallthrough case naluTypeSliceNonIDRPicture: 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") } diff --git a/codec/h264/h264dec/slice.go b/codec/h264/h264dec/slice.go index b25b4502..360282a6 100644 --- a/codec/h264/h264dec/slice.go +++ b/codec/h264/h264dec/slice.go @@ -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 (nalUnit.SVCExtension.DependencyID << 4) + 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,7 +945,7 @@ 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 @@ -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{ From 865c1676da44e6a8e63a2eda4cb014a02a6a6b10 Mon Sep 17 00:00:00 2001 From: Saxon Date: Sun, 21 Jul 2019 21:22:55 +0930 Subject: [PATCH 10/24] codec/h264/h264dec: wrote explantory comment for neglectance of io.EOF error when peeking in RBSP parsing process --- codec/h264/h264dec/nalunit.go | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/codec/h264/h264dec/nalunit.go b/codec/h264/h264dec/nalunit.go index 9f4ecab3..4f5725cc 100644 --- a/codec/h264/h264dec/nalunit.go +++ b/codec/h264/h264dec/nalunit.go @@ -262,6 +262,11 @@ func NewNALUnit(br *bits.BitReader) (*NALUnit, error) { for moreRBSPData(br) { next3Bytes, err := br.PeekBits(24) + + // 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") } From bdc3b4cfc5c7e402a1c8148f2e4a27a9bbcdd264 Mon Sep 17 00:00:00 2001 From: Saxon Date: Wed, 24 Jul 2019 00:04:10 +0930 Subject: [PATCH 11/24] container/mts/mpegts.go: added Programs, Streams and MediaStreams functions --- container/mts/mpegts.go | 85 +++++++++++++++++++++++++++++++++++++++-- 1 file changed, 82 insertions(+), 3 deletions(-) diff --git a/container/mts/mpegts.go b/container/mts/mpegts.go index 0b356770..f2a9ae0b 100644 --- a/container/mts/mpegts.go +++ b/container/mts/mpegts.go @@ -33,6 +33,7 @@ import ( "fmt" "github.com/Comcast/gots/packet" + gotspsi "github.com/Comcast/gots/psi" "github.com/pkg/errors" "bitbucket.org/ausocean/av/container/mts/meta" @@ -420,9 +421,9 @@ func GetPTSRange(clip []byte, pid uint16) (pts [2]uint64, err error) { } var ( - errNoPesPayload = errors.New("no PES payload") - errNoPesPTS = errors.New("no PES PTS") - errInvalidPesHeader = errors.New("invalid PES header") + errNoPesPayload = errors.New("no PES payload") + errNoPesPTS = errors.New("no PES PTS") + errInvalidPesHeader = errors.New("invalid PES header") errInvalidPesPayload = errors.New("invalid PES payload") ) @@ -592,3 +593,81 @@ func SegmentForMeta(d []byte, key, val string) ([][]byte, error) { return res, nil } + +// pid returns the packet identifier for the given packet. +func pid(p []byte) uint16 { + return uint16(p[1]&0x1f)<<8 | uint16(p[2]) +} + +// Programs returns a map of program numbers and corresponding PMT PIDs for a +// given MPEG-TS PAT packet. +func Programs(p []byte) (map[uint16]uint16, error) { + pat, err := gotspsi.NewPAT(p) + if err != nil { + return nil, err + } + return pat.ProgramMap(), nil +} + +// Streams returns elementary streams defined in a given MPEG-TS PMT packet. +// A gotspsi.PmtElementaryStream will give stream type from +// gotspsi.PmtElementaryStream.StreamType() and PID from +// gotspsi.PmtElementaryStream.ElementaryPid(). +// +// PmtStreamTypes from gots/psi are defined as follows: +// PmtStreamTypeMpeg2VideoH262 uint8 = 2 // H262 +// PmtStreamTypeMpeg4Video uint8 = 27 // H264 +// PmtStreamTypeMpeg4VideoH264 uint8 = 27 // H264 +// PmtStreamTypeMpeg4VideoH265 uint8 = 36 // H265 +// PmtStreamTypeAac uint8 = 15 // AAC +// PmtStreamTypeAc3 uint8 = 129 // DD +// PmtStreamTypeEc3 uint8 = 135 // DD+ +// PmtStreamTypeScte35 uint8 = 134 // SCTE-35 +func Streams(p []byte) ([]gotspsi.PmtElementaryStream, error) { + pmt, err := gotspsi.NewPMT(p) + if err != nil { + return nil, err + } + return pmt.ElementaryStreams(), nil +} + +// MediaStreams retrieves the PmtElementaryStreams from the given PSI. This +// function currently assumes that PSI contain a PAT followed by a PMT directly +// after. We also assume that this MPEG-TS stream contains just one program, +// but this program may contain different streams, i.e. a video stream + audio +// stream. +func MediaStreams(p []byte) ([]gotspsi.PmtElementaryStream, error) { + pat := p[:PacketSize] + pmt := p[PacketSize : 2*PacketSize] + + if pid(pat) != PatPid { + return nil, errors.New("first packet is not a PAT") + } + + m, err := Programs(pat) + if err != nil { + return nil, errors.Wrap(err, "could not get programs from PAT") + } + + if len(m) == 0 { + return nil, errors.New("no programs contained in PAT") + } + + if len(m) > 1 { + return nil, errors.New("more than one program not yet supported") + } + + var v uint16 + for _, v = range m { + } + + if pid(pmt) != v { + return nil, errors.New("second packet is not desired PMT") + } + + s, err := Streams(pmt) + if err != nil { + return nil, errors.Wrap(err, "could not get streams from PMT") + } + return s, nil +} From 3c1965d93826b8ba77c4715cbd96ed6dc5e86877 Mon Sep 17 00:00:00 2001 From: scruzin Date: Fri, 26 Jul 2019 18:55:56 +0930 Subject: [PATCH 12/24] Propagate netsender client error. --- cmd/revid-cli/main.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmd/revid-cli/main.go b/cmd/revid-cli/main.go index 46f39905..cf2ee174 100644 --- a/cmd/revid-cli/main.go +++ b/cmd/revid-cli/main.go @@ -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 From 6779fa3cb64e7c1e3984e4eafb36e365597e8c99 Mon Sep 17 00:00:00 2001 From: Saxon Date: Sat, 27 Jul 2019 12:26:30 +0930 Subject: [PATCH 13/24] codec/h264/h264dec: commenting for NAL uni syntax structure fields --- codec/h264/h264dec/nalunit.go | 143 +++++++++++++++++++++++++++------- 1 file changed, 115 insertions(+), 28 deletions(-) diff --git a/codec/h264/h264dec/nalunit.go b/codec/h264/h264dec/nalunit.go index 4f5725cc..2e076567 100644 --- a/codec/h264/h264dec/nalunit.go +++ b/codec/h264/h264dec/nalunit.go @@ -19,13 +19,29 @@ import ( // 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 { - NonIdrFlag bool - PriorityID int - ViewID int - TemporalID int - AnchorPicFlag bool - InterViewFlag bool + // 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 int + + // view_id, specifies a view identifier for the unit. Units with identical + // view_id are in the same view. + ViewID int + + // temporal_id, temporal identifier for the unit. + TemporalID int + + // 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 int } @@ -76,12 +92,26 @@ func NewMVCExtension(br *bits.BitReader) (*MVCExtension, error) { // 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 { - ViewIdx int - DepthFlag bool - NonIdrFlag bool - TemporalID int + // view_idx, specifies the order index for the NAL i.e. view_id = view_id[view_idx]. + ViewIdx int + + // 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 int + + // 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 } @@ -127,17 +157,44 @@ func NewThreeDAVCExtension(br *bits.BitReader) (*ThreeDAVCExtension, error) { // 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 { - IdrFlag bool - PriorityID int + // 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 int + + // no_inter_layer_pred_flag, if true inter-layer prediction can't be used for + // decoding slice. NoInterLayerPredFlag bool - DependencyID int - QualityID int - TemporalID int - UseRefBasePicFlag bool - DiscardableFlag bool - OutputFlag bool - ReservedThree2Bits int + + // dependency_id, specifies a dependency identifier for the NAL. + DependencyID int + + // quality_id, specifies a quality identifier for the NAL. + QualityID int + + // temporal_id, specifiesa temporal identifier for the NAL. + TemporalID int + + // 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 int } // NewSVCExtension parses a NAL unit header scalable video coding extension from @@ -202,17 +259,47 @@ func NewSVCExtension(br *bits.BitReader) (*SVCExtension, error) { // 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 { - ForbiddenZeroBit int - RefIdc int - Type int - SVCExtensionFlag bool - AVC3DExtensionFlag bool - SVCExtension *SVCExtension - ThreeDAVCExtension *ThreeDAVCExtension - MVCExtension *MVCExtension + // forbidden_zero_bit, always 0. + ForbiddenZeroBit int + + // 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 int + + // nal_unit_type, specifies the type of RBSP data contained in the NAL as + // defined in Table 7-1. + Type int + + // 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 } // NewNALUnit parses a network abstraction layer unit from br following the From 23c53d78f5900f0f8d44148dc7bb6d546f2b0d3e Mon Sep 17 00:00:00 2001 From: scruzin Date: Mon, 15 Jul 2019 08:50:45 +0930 Subject: [PATCH 14/24] Use ausocean/iot v1.2.5. --- go.mod | 9 ++------- go.sum | 11 +++++++++++ 2 files changed, 13 insertions(+), 7 deletions(-) diff --git a/go.mod b/go.mod index c3d766c5..37a7a31f 100644 --- a/go.mod +++ b/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 ) diff --git a/go.sum b/go.sum index cd09945f..5ee9f294 100644 --- a/go.sum +++ b/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= From 46c709404f7213499eb1672d55bc900f94d28e14 Mon Sep 17 00:00:00 2001 From: scruzin Date: Fri, 26 Jul 2019 18:55:56 +0930 Subject: [PATCH 15/24] Propagate netsender client error. --- cmd/revid-cli/main.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmd/revid-cli/main.go b/cmd/revid-cli/main.go index 46f39905..cf2ee174 100644 --- a/cmd/revid-cli/main.go +++ b/cmd/revid-cli/main.go @@ -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 From 404e6493b609d533e3583c8b300563b65554074f Mon Sep 17 00:00:00 2001 From: Saxon Date: Sat, 27 Jul 2019 13:35:05 +0930 Subject: [PATCH 16/24] codec/h264/h26dec/read.go: added fieldReader type to provide sticky error and specific methods for bool and int reading --- codec/h264/h264dec/read.go | 40 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 40 insertions(+) diff --git a/codec/h264/h264dec/read.go b/codec/h264/h264dec/read.go index 92a12ed9..f0a65500 100644 --- a/codec/h264/h264dec/read.go +++ b/codec/h264/h264dec/read.go @@ -228,3 +228,43 @@ func readFlags(br *bits.BitReader, flags []flag) error { } return nil } + +// 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} +} + +// readBool returns a bool from reading one bit from br. If we have an error +// already, we do not continue with the read. +func (r fieldReader) readBool() bool { + if r.e != nil { + return false + } + var b uint64 + b, r.e = r.br.ReadBits(1) + return b == 1 +} + +// 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) readBitsInt(n int) int { + if r.e != nil { + return 0 + } + var b uint64 + b, r.e = r.br.ReadBits(n) + return int(b) +} + +// err returns the fieldReader's error e. +func (r fieldReader) err() error { + return r.e +} From 9f47b22a84b82dc09579852238d45a14f5815b81 Mon Sep 17 00:00:00 2001 From: Saxon Date: Sat, 27 Jul 2019 13:59:12 +0930 Subject: [PATCH 17/24] codec/h264/h264dec: moved fieldReader to parse.go and wrote methods for reading other descriptor types like ue and te. --- codec/h264/h264dec/parse.go | 92 +++++++++++++++++++++++++++++++++++++ codec/h264/h264dec/read.go | 40 ---------------- 2 files changed, 92 insertions(+), 40 deletions(-) diff --git a/codec/h264/h264dec/parse.go b/codec/h264/h264dec/parse.go index 86baaece..e6fba287 100644 --- a/codec/h264/h264dec/parse.go +++ b/codec/h264/h264dec/parse.go @@ -36,6 +36,98 @@ 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} +} + +// readBool returns a bool from reading one bit from br. If we have an error +// already, we do not continue with the read. +func (r fieldReader) readBool() bool { + if r.e != nil { + return false + } + var b uint64 + b, r.e = r.br.ReadBits(1) + return b == 1 +} + +// 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) readBitsInt(n int) int { + if r.e != nil { + return 0 + } + var b uint64 + b, r.e = r.br.ReadBits(n) + return int(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. // diff --git a/codec/h264/h264dec/read.go b/codec/h264/h264dec/read.go index f0a65500..92a12ed9 100644 --- a/codec/h264/h264dec/read.go +++ b/codec/h264/h264dec/read.go @@ -228,43 +228,3 @@ func readFlags(br *bits.BitReader, flags []flag) error { } return nil } - -// 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} -} - -// readBool returns a bool from reading one bit from br. If we have an error -// already, we do not continue with the read. -func (r fieldReader) readBool() bool { - if r.e != nil { - return false - } - var b uint64 - b, r.e = r.br.ReadBits(1) - return b == 1 -} - -// 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) readBitsInt(n int) int { - if r.e != nil { - return 0 - } - var b uint64 - b, r.e = r.br.ReadBits(n) - return int(b) -} - -// err returns the fieldReader's error e. -func (r fieldReader) err() error { - return r.e -} From 75a6df5da5a15426c7a9c3d9e0ae3b477e920560 Mon Sep 17 00:00:00 2001 From: Saxon Date: Mon, 29 Jul 2019 12:33:14 +0930 Subject: [PATCH 18/24] codec/h264/h264dec: removed readBitsInt and readBool --- codec/h264/h264dec/parse.go | 13 +------------ 1 file changed, 1 insertion(+), 12 deletions(-) diff --git a/codec/h264/h264dec/parse.go b/codec/h264/h264dec/parse.go index e6fba287..68abe8c6 100644 --- a/codec/h264/h264dec/parse.go +++ b/codec/h264/h264dec/parse.go @@ -49,20 +49,9 @@ func newFieldReader(br *bits.BitReader) fieldReader { return fieldReader{br: br} } -// readBool returns a bool from reading one bit from br. If we have an error -// already, we do not continue with the read. -func (r fieldReader) readBool() bool { - if r.e != nil { - return false - } - var b uint64 - b, r.e = r.br.ReadBits(1) - return b == 1 -} - // 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) readBitsInt(n int) int { +func (r fieldReader) readBits(n int) int { if r.e != nil { return 0 } From 430e56e22bd477be5954223d1092a48bf721e870 Mon Sep 17 00:00:00 2001 From: Saxon Date: Mon, 29 Jul 2019 12:35:01 +0930 Subject: [PATCH 19/24] codec/h264/h264dec: fixed readBits return type --- codec/h264/h264dec/parse.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/codec/h264/h264dec/parse.go b/codec/h264/h264dec/parse.go index 68abe8c6..0763be27 100644 --- a/codec/h264/h264dec/parse.go +++ b/codec/h264/h264dec/parse.go @@ -51,13 +51,13 @@ func newFieldReader(br *bits.BitReader) fieldReader { // 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) int { +func (r fieldReader) readBits(n int) uint64 { if r.e != nil { return 0 } var b uint64 b, r.e = r.br.ReadBits(n) - return int(b) + return b } // readUe parses a syntax element of ue(v) descriptor, i.e. an unsigned integer From 23d9f289dd8638604ebe6a7a24adf7d420f98708 Mon Sep 17 00:00:00 2001 From: Saxon Date: Mon, 29 Jul 2019 13:04:59 +0930 Subject: [PATCH 20/24] codec/h264/h264dec: fixed field types for NalUnit and now using fieldReader in NewNALUnit --- codec/h264/h264dec/nalunit.go | 51 +++++++++++++---------------------- codec/h264/h264dec/slice.go | 4 +-- 2 files changed, 20 insertions(+), 35 deletions(-) diff --git a/codec/h264/h264dec/nalunit.go b/codec/h264/h264dec/nalunit.go index 2e076567..2e754f12 100644 --- a/codec/h264/h264dec/nalunit.go +++ b/codec/h264/h264dec/nalunit.go @@ -10,6 +10,7 @@ AUTHORS package h264dec import ( + "fmt" "io" "github.com/pkg/errors" @@ -262,18 +263,18 @@ func NewSVCExtension(br *bits.BitReader) (*SVCExtension, error) { // Field semantics are defined in section 7.4.1. type NALUnit struct { // forbidden_zero_bit, always 0. - ForbiddenZeroBit int + 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 int + RefIdc uint8 // nal_unit_type, specifies the type of RBSP data contained in the NAL as // defined in Table 7-1. - Type int + 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 @@ -306,28 +307,19 @@ type NALUnit struct { // 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) - err := readFields(br, []field{ - {&n.ForbiddenZeroBit, "ForbiddenZeroBit", 1}, - {&n.RefIdc, "NalRefIdc", 2}, - {&n.Type, "NalUnitType", 5}, - }) - if err != nil { - return nil, err - } + n.ForbiddenZeroBit = uint8(r.readBits(1)) + n.RefIdc = uint8(r.readBits(2)) + n.Type = uint8(r.readBits(5)) // TODO: use consts for the NAL types here + var err error 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") - } + n.SVCExtensionFlag = r.readBits(1) == 1 } else { - n.AVC3DExtensionFlag, err = br.ReadBool() - if err != nil { - return nil, errors.Wrap(err, "could not read AVC3DExtensionFlag") - } + n.AVC3DExtensionFlag = r.readBits(1) == 1 } if n.SVCExtensionFlag { n.SVCExtension, err = NewSVCExtension(br) @@ -360,27 +352,20 @@ func NewNALUnit(br *bits.BitReader) (*NALUnit, error) { 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") - } + rbspByte := byte(r.readBits(8)) n.RBSP = append(n.RBSP, byte(rbspByte)) } // 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) + n.EmulationPreventionThreeByte = byte(r.readBits(8)) } 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)) + n.RBSP = append(n.RBSP, byte(r.readBits(8))) } } + if r.err() != nil { + return nil, fmt.Errorf("fieldReader error: %v", r.err()) + } + return n, nil } diff --git a/codec/h264/h264dec/slice.go b/codec/h264/h264dec/slice.go index 360282a6..77e369d9 100644 --- a/codec/h264/h264dec/slice.go +++ b/codec/h264/h264dec/slice.go @@ -949,7 +949,7 @@ func NewSliceContext(videoStream *VideoStream, nalUnit *NALUnit, rbsp []byte, sh 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") From 6c691743033cf84638b55cd0b831ffcd36acc731 Mon Sep 17 00:00:00 2001 From: Saxon Date: Mon, 29 Jul 2019 13:41:40 +0930 Subject: [PATCH 21/24] codec/h264/h264dec: change field types to types more consistent with specs and now using fieldReader to read fields of syntax structures --- codec/h264/h264dec/nalunit.go | 169 +++++++++------------------------- codec/h264/h264dec/slice.go | 2 +- 2 files changed, 46 insertions(+), 125 deletions(-) diff --git a/codec/h264/h264dec/nalunit.go b/codec/h264/h264dec/nalunit.go index 2e754f12..656fa166 100644 --- a/codec/h264/h264dec/nalunit.go +++ b/codec/h264/h264dec/nalunit.go @@ -26,14 +26,14 @@ type MVCExtension struct { NonIdrFlag bool // priority_id, indicates priority of NAL unit. A lower value => higher priority. - PriorityID int + PriorityID uint8 // view_id, specifies a view identifier for the unit. Units with identical // view_id are in the same view. - ViewID int + ViewID uint32 // temporal_id, temporal identifier for the unit. - TemporalID int + TemporalID uint8 // anchor_pic_flag, if true access unit is an anchor access unit. AnchorPicFlag bool @@ -43,7 +43,7 @@ type MVCExtension struct { InterViewFlag bool // reserved_one_bit, always 1 (ignored by decoders) - ReservedOneBit int + ReservedOneBit uint8 } // NewMVCExtension parses a NAL unit header multiview video coding extension @@ -51,43 +51,19 @@ type MVCExtension struct { // returns as a new MVCExtension. func NewMVCExtension(br *bits.BitReader) (*MVCExtension, error) { e := &MVCExtension{} - var err error + r := newFieldReader(br) - e.NonIdrFlag, err = br.ReadBool() - if err != nil { - return nil, errors.Wrap(err, "could not read NonIdrFlag") + 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()) } - - 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 } @@ -96,7 +72,7 @@ func NewMVCExtension(br *bits.BitReader) (*MVCExtension, error) { // 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 int + ViewIdx uint8 // dpeth_flag, if true indicates NAL part of a depth view component, otherwise // a texture view component. @@ -106,7 +82,7 @@ type ThreeDAVCExtension struct { NonIdrFlag bool // temporal_id, temporal identifier for the unit. - TemporalID int + TemporalID uint8 // anchor_pic_flag, if true access unit is an anchor access unit. AnchorPicFlag bool @@ -121,36 +97,17 @@ type ThreeDAVCExtension struct { // J.7.3.1.1, and returns as a new ThreeDAVCExtension. func NewThreeDAVCExtension(br *bits.BitReader) (*ThreeDAVCExtension, error) { e := &ThreeDAVCExtension{} - var err error + r := newFieldReader(br) - e.ViewIdx, err = br.ReadBitsInt(8) - if err != nil { - return nil, errors.Wrap(err, "could not read ViewIdx") - } + 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 - 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") + if r.err() != nil { + return nil, fmt.Errorf("error from fieldReader: %v", r.err()) } return e, nil @@ -165,20 +122,20 @@ type SVCExtension struct { IdrFlag bool // priority_id, specifies priority identifier for unit. - PriorityID int + 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 int + DependencyID uint8 // quality_id, specifies a quality identifier for the NAL. - QualityID int + QualityID uint8 // temporal_id, specifiesa temporal identifier for the NAL. - TemporalID int + TemporalID uint8 // use_ref_base_pic_flag, if true indicates reference base pictures and // decoded pictures are used as references for inter prediction. @@ -195,7 +152,7 @@ type SVCExtension struct { OutputFlag bool // reserved_three_2bits, equal to 3. Decoders ignore. - ReservedThree2Bits int + ReservedThree2Bits uint8 } // NewSVCExtension parses a NAL unit header scalable video coding extension from @@ -203,58 +160,22 @@ type SVCExtension struct { // as a new SVCExtension. func NewSVCExtension(br *bits.BitReader) (*SVCExtension, error) { e := &SVCExtension{} - var err error + r := newFieldReader(br) - e.IdrFlag, err = br.ReadBool() - if err != nil { - return nil, errors.Wrap(err, "could not read IdrFlag") + 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()) } - - 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 } diff --git a/codec/h264/h264dec/slice.go b/codec/h264/h264dec/slice.go index 77e369d9..93e2a6e4 100644 --- a/codec/h264/h264dec/slice.go +++ b/codec/h264/h264dec/slice.go @@ -241,7 +241,7 @@ 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.SVCExtension.DependencyID << 4) + nalUnit.SVCExtension.QualityID + return int((nalUnit.SVCExtension.DependencyID << 4)) + int(nalUnit.SVCExtension.QualityID) } // Annex G p527 From 8e1e84d311069067b45f2841f2dbb4142a944b17 Mon Sep 17 00:00:00 2001 From: Saxon Date: Mon, 29 Jul 2019 13:43:03 +0930 Subject: [PATCH 22/24] codec/h264/h264dec/bits: removed ReadBitsInt and ReadBool as not required anymore --- codec/h264/h264dec/bits/bitreader.go | 18 ------------------ 1 file changed, 18 deletions(-) diff --git a/codec/h264/h264dec/bits/bitreader.go b/codec/h264/h264dec/bits/bitreader.go index 08cc5d41..7e17f407 100644 --- a/codec/h264/h264dec/bits/bitreader.go +++ b/codec/h264/h264dec/bits/bitreader.go @@ -128,24 +128,6 @@ func (br *BitReader) ReadBits(n int) (uint64, error) { return r, nil } -// ReadBitsInt reads n bits from the source, and returns as an int. -func (br *BitReader) ReadBitsInt(n int) (int, error) { - b, err := br.ReadBits(n) - if err != nil { - return 0, err - } - return int(b), nil -} - -// ReadBool reads a single bit from the source, converts to a bool and returns. -func (br *BitReader) ReadBool() (bool, error) { - b, err := br.ReadBits(1) - if err != nil { - return false, err - } - return b == 1, nil -} - // PeekBits provides the next n bits returning them in the least-significant // part of a uint64, without advancing through the source. // For example, with a source as []byte{0x8f,0xe3} (1000 1111, 1110 0011), we From b71d8fdd8b7e15ffd6523fc325aebaa208f54a7e Mon Sep 17 00:00:00 2001 From: Saxon Date: Mon, 29 Jul 2019 13:49:57 +0930 Subject: [PATCH 23/24] container/mts/mpegts.go: undoing changes to mpegts.go that shouldn't be there --- container/mts/mpegts.go | 85 ++--------------------------------------- 1 file changed, 3 insertions(+), 82 deletions(-) diff --git a/container/mts/mpegts.go b/container/mts/mpegts.go index f2a9ae0b..0b356770 100644 --- a/container/mts/mpegts.go +++ b/container/mts/mpegts.go @@ -33,7 +33,6 @@ import ( "fmt" "github.com/Comcast/gots/packet" - gotspsi "github.com/Comcast/gots/psi" "github.com/pkg/errors" "bitbucket.org/ausocean/av/container/mts/meta" @@ -421,9 +420,9 @@ func GetPTSRange(clip []byte, pid uint16) (pts [2]uint64, err error) { } var ( - errNoPesPayload = errors.New("no PES payload") - errNoPesPTS = errors.New("no PES PTS") - errInvalidPesHeader = errors.New("invalid PES header") + errNoPesPayload = errors.New("no PES payload") + errNoPesPTS = errors.New("no PES PTS") + errInvalidPesHeader = errors.New("invalid PES header") errInvalidPesPayload = errors.New("invalid PES payload") ) @@ -593,81 +592,3 @@ func SegmentForMeta(d []byte, key, val string) ([][]byte, error) { return res, nil } - -// pid returns the packet identifier for the given packet. -func pid(p []byte) uint16 { - return uint16(p[1]&0x1f)<<8 | uint16(p[2]) -} - -// Programs returns a map of program numbers and corresponding PMT PIDs for a -// given MPEG-TS PAT packet. -func Programs(p []byte) (map[uint16]uint16, error) { - pat, err := gotspsi.NewPAT(p) - if err != nil { - return nil, err - } - return pat.ProgramMap(), nil -} - -// Streams returns elementary streams defined in a given MPEG-TS PMT packet. -// A gotspsi.PmtElementaryStream will give stream type from -// gotspsi.PmtElementaryStream.StreamType() and PID from -// gotspsi.PmtElementaryStream.ElementaryPid(). -// -// PmtStreamTypes from gots/psi are defined as follows: -// PmtStreamTypeMpeg2VideoH262 uint8 = 2 // H262 -// PmtStreamTypeMpeg4Video uint8 = 27 // H264 -// PmtStreamTypeMpeg4VideoH264 uint8 = 27 // H264 -// PmtStreamTypeMpeg4VideoH265 uint8 = 36 // H265 -// PmtStreamTypeAac uint8 = 15 // AAC -// PmtStreamTypeAc3 uint8 = 129 // DD -// PmtStreamTypeEc3 uint8 = 135 // DD+ -// PmtStreamTypeScte35 uint8 = 134 // SCTE-35 -func Streams(p []byte) ([]gotspsi.PmtElementaryStream, error) { - pmt, err := gotspsi.NewPMT(p) - if err != nil { - return nil, err - } - return pmt.ElementaryStreams(), nil -} - -// MediaStreams retrieves the PmtElementaryStreams from the given PSI. This -// function currently assumes that PSI contain a PAT followed by a PMT directly -// after. We also assume that this MPEG-TS stream contains just one program, -// but this program may contain different streams, i.e. a video stream + audio -// stream. -func MediaStreams(p []byte) ([]gotspsi.PmtElementaryStream, error) { - pat := p[:PacketSize] - pmt := p[PacketSize : 2*PacketSize] - - if pid(pat) != PatPid { - return nil, errors.New("first packet is not a PAT") - } - - m, err := Programs(pat) - if err != nil { - return nil, errors.Wrap(err, "could not get programs from PAT") - } - - if len(m) == 0 { - return nil, errors.New("no programs contained in PAT") - } - - if len(m) > 1 { - return nil, errors.New("more than one program not yet supported") - } - - var v uint16 - for _, v = range m { - } - - if pid(pmt) != v { - return nil, errors.New("second packet is not desired PMT") - } - - s, err := Streams(pmt) - if err != nil { - return nil, errors.Wrap(err, "could not get streams from PMT") - } - return s, nil -} From 520ead0c6c5c0e32ae30936520ea529831da672b Mon Sep 17 00:00:00 2001 From: Saxon Date: Mon, 29 Jul 2019 14:08:59 +0930 Subject: [PATCH 24/24] codec/h264/h264dec/nalunit.go: using consts for NAL unit types check in newNALUnit --- codec/h264/h264dec/frame.go | 2 ++ codec/h264/h264dec/nalunit.go | 5 ++--- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/codec/h264/h264dec/frame.go b/codec/h264/h264dec/frame.go index 9e240a45..82b32ae5 100644 --- a/codec/h264/h264dec/frame.go +++ b/codec/h264/h264dec/frame.go @@ -19,6 +19,8 @@ const ( naluTypePrefixNALU naluTypeSubsetSPS naluTypeDepthParamSet + naluTypeSliceLayerExtRBSP = 20 + naluTypeSliceLayerExtRBSP2 = 21 ) var ( diff --git a/codec/h264/h264dec/nalunit.go b/codec/h264/h264dec/nalunit.go index 656fa166..f1535855 100644 --- a/codec/h264/h264dec/nalunit.go +++ b/codec/h264/h264dec/nalunit.go @@ -234,10 +234,9 @@ func NewNALUnit(br *bits.BitReader) (*NALUnit, error) { n.RefIdc = uint8(r.readBits(2)) n.Type = uint8(r.readBits(5)) - // TODO: use consts for the NAL types here var err error - if n.Type == 14 || n.Type == 20 || n.Type == 21 { - if n.Type != 21 { + if n.Type == naluTypePrefixNALU || n.Type == naluTypeSliceLayerExtRBSP || n.Type == naluTypeSliceLayerExtRBSP2 { + if n.Type != naluTypeSliceLayerExtRBSP2 { n.SVCExtensionFlag = r.readBits(1) == 1 } else { n.AVC3DExtensionFlag = r.readBits(1) == 1