19 changed files with 13 additions and 667 deletions
@ -1,79 +0,0 @@ |
|||||||
package h264 |
|
||||||
|
|
||||||
import ( |
|
||||||
"fmt" |
|
||||||
) |
|
||||||
|
|
||||||
// DecodeAnnexB decodes NALUs from the Annex-B code stream format.
|
|
||||||
func DecodeAnnexB(byts []byte) ([][]byte, error) { |
|
||||||
bl := len(byts) |
|
||||||
|
|
||||||
// check initial delimiter
|
|
||||||
n := func() int { |
|
||||||
if bl < 3 || byts[0] != 0x00 || byts[1] != 0x00 { |
|
||||||
return -1 |
|
||||||
} |
|
||||||
|
|
||||||
if byts[2] == 0x01 { |
|
||||||
return 3 |
|
||||||
} |
|
||||||
|
|
||||||
if bl < 4 || byts[2] != 0x00 || byts[3] != 0x01 { |
|
||||||
return -1 |
|
||||||
} |
|
||||||
|
|
||||||
return 4 |
|
||||||
}() |
|
||||||
if n < 0 { |
|
||||||
return nil, fmt.Errorf("input doesn't start with a delimiter") |
|
||||||
} |
|
||||||
|
|
||||||
var ret [][]byte |
|
||||||
zeros := 0 |
|
||||||
start := n |
|
||||||
delimStart := 0 |
|
||||||
|
|
||||||
for i := n; i < bl; i++ { |
|
||||||
switch byts[i] { |
|
||||||
case 0: |
|
||||||
if zeros == 0 { |
|
||||||
delimStart = i |
|
||||||
} |
|
||||||
zeros++ |
|
||||||
|
|
||||||
case 1: |
|
||||||
if zeros == 2 || zeros == 3 { |
|
||||||
nalu := byts[start:delimStart] |
|
||||||
if len(nalu) == 0 { |
|
||||||
return nil, fmt.Errorf("empty NALU") |
|
||||||
} |
|
||||||
ret = append(ret, nalu) |
|
||||||
start = i + 1 |
|
||||||
} |
|
||||||
zeros = 0 |
|
||||||
|
|
||||||
default: |
|
||||||
zeros = 0 |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
nalu := byts[start:bl] |
|
||||||
if len(nalu) == 0 { |
|
||||||
return nil, fmt.Errorf("empty NALU") |
|
||||||
} |
|
||||||
ret = append(ret, nalu) |
|
||||||
|
|
||||||
return ret, nil |
|
||||||
} |
|
||||||
|
|
||||||
// EncodeAnnexB encodes NALUs into the Annex-B code stream format.
|
|
||||||
func EncodeAnnexB(nalus [][]byte) ([]byte, error) { |
|
||||||
var ret []byte |
|
||||||
|
|
||||||
for _, nalu := range nalus { |
|
||||||
ret = append(ret, []byte{0x00, 0x00, 0x00, 0x01}...) |
|
||||||
ret = append(ret, nalu...) |
|
||||||
} |
|
||||||
|
|
||||||
return ret, nil |
|
||||||
} |
|
@ -1,115 +0,0 @@ |
|||||||
package h264 |
|
||||||
|
|
||||||
import ( |
|
||||||
"testing" |
|
||||||
|
|
||||||
"github.com/stretchr/testify/require" |
|
||||||
) |
|
||||||
|
|
||||||
var casesAnnexB = []struct { |
|
||||||
name string |
|
||||||
encin []byte |
|
||||||
encout []byte |
|
||||||
dec [][]byte |
|
||||||
}{ |
|
||||||
{ |
|
||||||
"2 zeros, single", |
|
||||||
[]byte{0x00, 0x00, 0x01, 0xaa, 0xbb}, |
|
||||||
[]byte{0x00, 0x00, 0x00, 0x01, 0xaa, 0xbb}, |
|
||||||
[][]byte{ |
|
||||||
{0xaa, 0xbb}, |
|
||||||
}, |
|
||||||
}, |
|
||||||
{ |
|
||||||
"2 zeros, multiple", |
|
||||||
[]byte{ |
|
||||||
0x00, 0x00, 0x01, 0xaa, 0xbb, 0x00, 0x00, 0x01, |
|
||||||
0xcc, 0xdd, 0x00, 0x00, 0x01, 0xee, 0xff, |
|
||||||
}, |
|
||||||
[]byte{ |
|
||||||
0x00, 0x00, 0x00, 0x01, 0xaa, 0xbb, 0x00, 0x00, |
|
||||||
0x00, 0x01, 0xcc, 0xdd, 0x00, 0x00, 0x00, 0x01, |
|
||||||
0xee, 0xff, |
|
||||||
}, |
|
||||||
[][]byte{ |
|
||||||
{0xaa, 0xbb}, |
|
||||||
{0xcc, 0xdd}, |
|
||||||
{0xee, 0xff}, |
|
||||||
}, |
|
||||||
}, |
|
||||||
{ |
|
||||||
"3 zeros, single", |
|
||||||
[]byte{0x00, 0x00, 0x00, 0x01, 0xaa, 0xbb}, |
|
||||||
[]byte{0x00, 0x00, 0x00, 0x01, 0xaa, 0xbb}, |
|
||||||
[][]byte{ |
|
||||||
{0xaa, 0xbb}, |
|
||||||
}, |
|
||||||
}, |
|
||||||
{ |
|
||||||
"3 zeros, multiple", |
|
||||||
[]byte{ |
|
||||||
0x00, 0x00, 0x00, 0x01, 0xaa, 0xbb, 0x00, 0x00, |
|
||||||
0x00, 0x01, 0xcc, 0xdd, 0x00, 0x00, 0x00, 0x01, |
|
||||||
0xee, 0xff, |
|
||||||
}, |
|
||||||
[]byte{ |
|
||||||
0x00, 0x00, 0x00, 0x01, 0xaa, 0xbb, 0x00, 0x00, |
|
||||||
0x00, 0x01, 0xcc, 0xdd, 0x00, 0x00, 0x00, 0x01, |
|
||||||
0xee, 0xff, |
|
||||||
}, |
|
||||||
[][]byte{ |
|
||||||
{0xaa, 0xbb}, |
|
||||||
{0xcc, 0xdd}, |
|
||||||
{0xee, 0xff}, |
|
||||||
}, |
|
||||||
}, |
|
||||||
} |
|
||||||
|
|
||||||
func TestAnnexBDecode(t *testing.T) { |
|
||||||
for _, ca := range casesAnnexB { |
|
||||||
t.Run(ca.name, func(t *testing.T) { |
|
||||||
dec, err := DecodeAnnexB(ca.encin) |
|
||||||
require.NoError(t, err) |
|
||||||
require.Equal(t, ca.dec, dec) |
|
||||||
}) |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
func TestAnnexBEncode(t *testing.T) { |
|
||||||
for _, ca := range casesAnnexB { |
|
||||||
t.Run(ca.name, func(t *testing.T) { |
|
||||||
enc, err := EncodeAnnexB(ca.dec) |
|
||||||
require.NoError(t, err) |
|
||||||
require.Equal(t, ca.encout, enc) |
|
||||||
}) |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
func TestAnnexBDecodeError(t *testing.T) { |
|
||||||
for _, ca := range []struct { |
|
||||||
name string |
|
||||||
enc []byte |
|
||||||
}{ |
|
||||||
{ |
|
||||||
"empty", |
|
||||||
[]byte{}, |
|
||||||
}, |
|
||||||
{ |
|
||||||
"missing initial delimiter", |
|
||||||
[]byte{0xaa, 0xbb}, |
|
||||||
}, |
|
||||||
{ |
|
||||||
"empty initial", |
|
||||||
[]byte{0x00, 0x00, 0x01}, |
|
||||||
}, |
|
||||||
{ |
|
||||||
"empty 2nd", |
|
||||||
[]byte{0x00, 0x00, 0x01, 0xaa, 0x00, 0x00, 0x01}, |
|
||||||
}, |
|
||||||
} { |
|
||||||
t.Run(ca.name, func(t *testing.T) { |
|
||||||
_, err := DecodeAnnexB(ca.enc) |
|
||||||
require.Error(t, err) |
|
||||||
}) |
|
||||||
} |
|
||||||
} |
|
@ -1,90 +0,0 @@ |
|||||||
package h264 |
|
||||||
|
|
||||||
// AntiCompetitionAdd adds the anti-competition bytes to a NALU.
|
|
||||||
func AntiCompetitionAdd(nalu []byte) []byte { |
|
||||||
var ret []byte |
|
||||||
step := 0 |
|
||||||
start := 0 |
|
||||||
|
|
||||||
for i, b := range nalu { |
|
||||||
switch step { |
|
||||||
case 0: |
|
||||||
if b == 0 { |
|
||||||
step++ |
|
||||||
} |
|
||||||
|
|
||||||
case 1: |
|
||||||
if b == 0 { |
|
||||||
step++ |
|
||||||
} else { |
|
||||||
step = 0 |
|
||||||
} |
|
||||||
|
|
||||||
case 2: |
|
||||||
switch b { |
|
||||||
case 3, 2, 1, 0: |
|
||||||
ret = append(ret, nalu[start:i-2]...) |
|
||||||
ret = append(ret, []byte{0x00, 0x00, 0x03, b}...) |
|
||||||
step = 0 |
|
||||||
start = i + 1 |
|
||||||
|
|
||||||
default: |
|
||||||
step = 0 |
|
||||||
} |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
ret = append(ret, nalu[start:]...) |
|
||||||
return ret |
|
||||||
} |
|
||||||
|
|
||||||
// AntiCompetitionRemove removes the anti-competition bytes from a NALU.
|
|
||||||
func AntiCompetitionRemove(nalu []byte) []byte { |
|
||||||
// 0x00 0x00 0x03 0x00 -> 0x00 0x00 0x00
|
|
||||||
// 0x00 0x00 0x03 0x01 -> 0x00 0x00 0x01
|
|
||||||
// 0x00 0x00 0x03 0x02 -> 0x00 0x00 0x02
|
|
||||||
// 0x00 0x00 0x03 0x03 -> 0x00 0x00 0x03
|
|
||||||
|
|
||||||
var ret []byte |
|
||||||
step := 0 |
|
||||||
start := 0 |
|
||||||
|
|
||||||
for i, b := range nalu { |
|
||||||
switch step { |
|
||||||
case 0: |
|
||||||
if b == 0 { |
|
||||||
step++ |
|
||||||
} |
|
||||||
|
|
||||||
case 1: |
|
||||||
if b == 0 { |
|
||||||
step++ |
|
||||||
} else { |
|
||||||
step = 0 |
|
||||||
} |
|
||||||
|
|
||||||
case 2: |
|
||||||
if b == 3 { |
|
||||||
step++ |
|
||||||
} else { |
|
||||||
step = 0 |
|
||||||
} |
|
||||||
|
|
||||||
case 3: |
|
||||||
switch b { |
|
||||||
case 3, 2, 1, 0: |
|
||||||
ret = append(ret, nalu[start:i-3]...) |
|
||||||
ret = append(ret, []byte{0x00, 0x00, b}...) |
|
||||||
step = 0 |
|
||||||
start = i + 1 |
|
||||||
|
|
||||||
default: |
|
||||||
step = 0 |
|
||||||
} |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
ret = append(ret, nalu[start:]...) |
|
||||||
|
|
||||||
return ret |
|
||||||
} |
|
@ -1,47 +0,0 @@ |
|||||||
package h264 |
|
||||||
|
|
||||||
import ( |
|
||||||
"testing" |
|
||||||
|
|
||||||
"github.com/stretchr/testify/require" |
|
||||||
) |
|
||||||
|
|
||||||
var casesAntiCompetition = []struct { |
|
||||||
name string |
|
||||||
unproc []byte |
|
||||||
proc []byte |
|
||||||
}{ |
|
||||||
{ |
|
||||||
"base", |
|
||||||
[]byte{ |
|
||||||
0x00, 0x00, 0x00, |
|
||||||
0x00, 0x00, 0x01, |
|
||||||
0x00, 0x00, 0x02, |
|
||||||
0x00, 0x00, 0x03, |
|
||||||
}, |
|
||||||
[]byte{ |
|
||||||
0x00, 0x00, 0x03, 0x00, |
|
||||||
0x00, 0x00, 0x03, 0x01, |
|
||||||
0x00, 0x00, 0x03, 0x02, |
|
||||||
0x00, 0x00, 0x03, 0x03, |
|
||||||
}, |
|
||||||
}, |
|
||||||
} |
|
||||||
|
|
||||||
func TestAntiCompetitionAdd(t *testing.T) { |
|
||||||
for _, ca := range casesAntiCompetition { |
|
||||||
t.Run(ca.name, func(t *testing.T) { |
|
||||||
proc := AntiCompetitionAdd(ca.unproc) |
|
||||||
require.Equal(t, ca.proc, proc) |
|
||||||
}) |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
func TestAntiCompetitionRemove(t *testing.T) { |
|
||||||
for _, ca := range casesAntiCompetition { |
|
||||||
t.Run(ca.name, func(t *testing.T) { |
|
||||||
unproc := AntiCompetitionRemove(ca.proc) |
|
||||||
require.Equal(t, ca.unproc, unproc) |
|
||||||
}) |
|
||||||
} |
|
||||||
} |
|
@ -1,55 +0,0 @@ |
|||||||
package h264 |
|
||||||
|
|
||||||
import ( |
|
||||||
"encoding/binary" |
|
||||||
"fmt" |
|
||||||
) |
|
||||||
|
|
||||||
// DecodeAVCC encodes NALUs from the AVCC code stream format.
|
|
||||||
func DecodeAVCC(byts []byte) ([][]byte, error) { |
|
||||||
var ret [][]byte |
|
||||||
|
|
||||||
for len(byts) > 0 { |
|
||||||
if len(byts) < 4 { |
|
||||||
return nil, fmt.Errorf("invalid length") |
|
||||||
} |
|
||||||
|
|
||||||
le := binary.BigEndian.Uint32(byts) |
|
||||||
byts = byts[4:] |
|
||||||
|
|
||||||
if len(byts) < int(le) { |
|
||||||
return nil, fmt.Errorf("invalid length") |
|
||||||
} |
|
||||||
|
|
||||||
ret = append(ret, byts[:le]) |
|
||||||
byts = byts[le:] |
|
||||||
} |
|
||||||
|
|
||||||
if len(ret) == 0 { |
|
||||||
return nil, fmt.Errorf("no NALUs decoded") |
|
||||||
} |
|
||||||
|
|
||||||
return ret, nil |
|
||||||
} |
|
||||||
|
|
||||||
// EncodeAVCC encodes NALUs into the AVCC code stream format.
|
|
||||||
func EncodeAVCC(nalus [][]byte) ([]byte, error) { |
|
||||||
le := 0 |
|
||||||
for _, nalu := range nalus { |
|
||||||
le += 4 + len(nalu) |
|
||||||
} |
|
||||||
|
|
||||||
ret := make([]byte, le) |
|
||||||
pos := 0 |
|
||||||
|
|
||||||
for _, nalu := range nalus { |
|
||||||
ln := len(nalu) |
|
||||||
binary.BigEndian.PutUint32(ret[pos:], uint32(ln)) |
|
||||||
pos += 4 |
|
||||||
|
|
||||||
copy(ret[pos:], nalu) |
|
||||||
pos += ln |
|
||||||
} |
|
||||||
|
|
||||||
return ret, nil |
|
||||||
} |
|
@ -1,85 +0,0 @@ |
|||||||
package h264 |
|
||||||
|
|
||||||
import ( |
|
||||||
"testing" |
|
||||||
|
|
||||||
"github.com/stretchr/testify/require" |
|
||||||
) |
|
||||||
|
|
||||||
var casesAVCC = []struct { |
|
||||||
name string |
|
||||||
enc []byte |
|
||||||
dec [][]byte |
|
||||||
}{ |
|
||||||
{ |
|
||||||
"single", |
|
||||||
[]byte{ |
|
||||||
0x00, 0x00, 0x00, 0x03, |
|
||||||
0xaa, 0xbb, 0xcc, |
|
||||||
}, |
|
||||||
[][]byte{ |
|
||||||
{0xaa, 0xbb, 0xcc}, |
|
||||||
}, |
|
||||||
}, |
|
||||||
{ |
|
||||||
"multiple", |
|
||||||
[]byte{ |
|
||||||
0x00, 0x00, 0x00, 0x02, |
|
||||||
0xaa, 0xbb, |
|
||||||
0x00, 0x00, 0x00, 0x02, |
|
||||||
0xcc, 0xdd, |
|
||||||
0x00, 0x00, 0x00, 0x02, |
|
||||||
0xee, 0xff, |
|
||||||
}, |
|
||||||
[][]byte{ |
|
||||||
{0xaa, 0xbb}, |
|
||||||
{0xcc, 0xdd}, |
|
||||||
{0xee, 0xff}, |
|
||||||
}, |
|
||||||
}, |
|
||||||
} |
|
||||||
|
|
||||||
func TestAVCCDecode(t *testing.T) { |
|
||||||
for _, ca := range casesAVCC { |
|
||||||
t.Run(ca.name, func(t *testing.T) { |
|
||||||
dec, err := DecodeAVCC(ca.enc) |
|
||||||
require.NoError(t, err) |
|
||||||
require.Equal(t, ca.dec, dec) |
|
||||||
}) |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
func TestAVCCEncode(t *testing.T) { |
|
||||||
for _, ca := range casesAVCC { |
|
||||||
t.Run(ca.name, func(t *testing.T) { |
|
||||||
enc, err := EncodeAVCC(ca.dec) |
|
||||||
require.NoError(t, err) |
|
||||||
require.Equal(t, ca.enc, enc) |
|
||||||
}) |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
func TestAVCCDecodeError(t *testing.T) { |
|
||||||
for _, ca := range []struct { |
|
||||||
name string |
|
||||||
enc []byte |
|
||||||
}{ |
|
||||||
{ |
|
||||||
"empty", |
|
||||||
[]byte{}, |
|
||||||
}, |
|
||||||
{ |
|
||||||
"invalid length", |
|
||||||
[]byte{0x01}, |
|
||||||
}, |
|
||||||
{ |
|
||||||
"invalid length", |
|
||||||
[]byte{0x00, 0x00, 0x00, 0x03}, |
|
||||||
}, |
|
||||||
} { |
|
||||||
t.Run(ca.name, func(t *testing.T) { |
|
||||||
_, err := DecodeAVCC(ca.enc) |
|
||||||
require.Error(t, err) |
|
||||||
}) |
|
||||||
} |
|
||||||
} |
|
@ -1,61 +0,0 @@ |
|||||||
package h264 |
|
||||||
|
|
||||||
import ( |
|
||||||
"time" |
|
||||||
) |
|
||||||
|
|
||||||
// DTSEstimator is a DTS estimator.
|
|
||||||
type DTSEstimator struct { |
|
||||||
initializing int |
|
||||||
prevDTS time.Duration |
|
||||||
prevPTS time.Duration |
|
||||||
prevPrevPTS time.Duration |
|
||||||
} |
|
||||||
|
|
||||||
// NewDTSEstimator allocates a DTSEstimator.
|
|
||||||
func NewDTSEstimator() *DTSEstimator { |
|
||||||
return &DTSEstimator{ |
|
||||||
initializing: 2, |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
// Feed provides PTS to the estimator, and returns the estimated DTS.
|
|
||||||
func (d *DTSEstimator) Feed(pts time.Duration) time.Duration { |
|
||||||
switch d.initializing { |
|
||||||
case 2: |
|
||||||
d.initializing-- |
|
||||||
return 0 |
|
||||||
|
|
||||||
case 1: |
|
||||||
d.initializing-- |
|
||||||
d.prevPTS = pts |
|
||||||
d.prevDTS = time.Millisecond |
|
||||||
return time.Millisecond |
|
||||||
} |
|
||||||
|
|
||||||
dts := func() time.Duration { |
|
||||||
// P or I frame
|
|
||||||
if pts > d.prevPTS { |
|
||||||
// previous frame was B
|
|
||||||
// use the DTS of the previous frame
|
|
||||||
if d.prevPTS < d.prevPrevPTS { |
|
||||||
return d.prevPTS |
|
||||||
} |
|
||||||
|
|
||||||
// previous frame was P or I
|
|
||||||
// use two frames ago plus a small quantity
|
|
||||||
// to avoid non-monotonous DTS with B-frames
|
|
||||||
return d.prevPrevPTS + time.Millisecond |
|
||||||
} |
|
||||||
|
|
||||||
// B Frame
|
|
||||||
// increase by a small quantity
|
|
||||||
return d.prevDTS + time.Millisecond |
|
||||||
}() |
|
||||||
|
|
||||||
d.prevPrevPTS = d.prevPTS |
|
||||||
d.prevPTS = pts |
|
||||||
d.prevDTS = dts |
|
||||||
|
|
||||||
return dts |
|
||||||
} |
|
@ -1,32 +0,0 @@ |
|||||||
package h264 |
|
||||||
|
|
||||||
import ( |
|
||||||
"testing" |
|
||||||
"time" |
|
||||||
|
|
||||||
"github.com/stretchr/testify/require" |
|
||||||
) |
|
||||||
|
|
||||||
func TestDTSEstimator(t *testing.T) { |
|
||||||
est := NewDTSEstimator() |
|
||||||
|
|
||||||
// initial state
|
|
||||||
dts := est.Feed(0) |
|
||||||
require.Equal(t, time.Duration(0), dts) |
|
||||||
|
|
||||||
// b-frame
|
|
||||||
dts = est.Feed(1*time.Second - 200*time.Millisecond) |
|
||||||
require.Equal(t, time.Millisecond, dts) |
|
||||||
|
|
||||||
// b-frame
|
|
||||||
dts = est.Feed(1*time.Second - 400*time.Millisecond) |
|
||||||
require.Equal(t, 2*time.Millisecond, dts) |
|
||||||
|
|
||||||
// p-frame
|
|
||||||
dts = est.Feed(1 * time.Second) |
|
||||||
require.Equal(t, 1*time.Second-400*time.Millisecond, dts) |
|
||||||
|
|
||||||
// p-frame
|
|
||||||
dts = est.Feed(1*time.Second + 200*time.Millisecond) |
|
||||||
require.Equal(t, 1*time.Second-399*time.Millisecond, dts) |
|
||||||
} |
|
@ -1,88 +0,0 @@ |
|||||||
package h264 |
|
||||||
|
|
||||||
import ( |
|
||||||
"fmt" |
|
||||||
) |
|
||||||
|
|
||||||
// NALUType is the type of a NALU.
|
|
||||||
type NALUType uint8 |
|
||||||
|
|
||||||
// standard NALU types.
|
|
||||||
const ( |
|
||||||
NALUTypeNonIDR NALUType = 1 |
|
||||||
NALUTypeDataPartitionA NALUType = 2 |
|
||||||
NALUTypeDataPartitionB NALUType = 3 |
|
||||||
NALUTypeDataPartitionC NALUType = 4 |
|
||||||
NALUTypeIDR NALUType = 5 |
|
||||||
NALUTypeSEI NALUType = 6 |
|
||||||
NALUTypeSPS NALUType = 7 |
|
||||||
NALUTypePPS NALUType = 8 |
|
||||||
NALUTypeAccessUnitDelimiter NALUType = 9 |
|
||||||
NALUTypeEndOfSequence NALUType = 10 |
|
||||||
NALUTypeEndOfStream NALUType = 11 |
|
||||||
NALUTypeFillerData NALUType = 12 |
|
||||||
NALUTypeSPSExtension NALUType = 13 |
|
||||||
NALUTypePrefix NALUType = 14 |
|
||||||
NALUTypeSubsetSPS NALUType = 15 |
|
||||||
NALUTypeReserved16 NALUType = 16 |
|
||||||
NALUTypeReserved17 NALUType = 17 |
|
||||||
NALUTypeReserved18 NALUType = 18 |
|
||||||
NALUTypeSliceLayerWithoutPartitioning NALUType = 19 |
|
||||||
NALUTypeSliceExtension NALUType = 20 |
|
||||||
NALUTypeSliceExtensionDepth NALUType = 21 |
|
||||||
NALUTypeReserved22 NALUType = 22 |
|
||||||
NALUTypeReserved23 NALUType = 23 |
|
||||||
) |
|
||||||
|
|
||||||
// String implements fmt.Stringer.
|
|
||||||
func (nt NALUType) String() string { |
|
||||||
switch nt { |
|
||||||
case NALUTypeNonIDR: |
|
||||||
return "NonIDR" |
|
||||||
case NALUTypeDataPartitionA: |
|
||||||
return "DataPartitionA" |
|
||||||
case NALUTypeDataPartitionB: |
|
||||||
return "DataPartitionB" |
|
||||||
case NALUTypeDataPartitionC: |
|
||||||
return "DataPartitionC" |
|
||||||
case NALUTypeIDR: |
|
||||||
return "IDR" |
|
||||||
case NALUTypeSEI: |
|
||||||
return "SEI" |
|
||||||
case NALUTypeSPS: |
|
||||||
return "SPS" |
|
||||||
case NALUTypePPS: |
|
||||||
return "PPS" |
|
||||||
case NALUTypeAccessUnitDelimiter: |
|
||||||
return "AccessUnitDelimiter" |
|
||||||
case NALUTypeEndOfSequence: |
|
||||||
return "EndOfSequence" |
|
||||||
case NALUTypeEndOfStream: |
|
||||||
return "EndOfStream" |
|
||||||
case NALUTypeFillerData: |
|
||||||
return "FillerData" |
|
||||||
case NALUTypeSPSExtension: |
|
||||||
return "SPSExtension" |
|
||||||
case NALUTypePrefix: |
|
||||||
return "Prefix" |
|
||||||
case NALUTypeSubsetSPS: |
|
||||||
return "SubsetSPS" |
|
||||||
case NALUTypeReserved16: |
|
||||||
return "Reserved16" |
|
||||||
case NALUTypeReserved17: |
|
||||||
return "Reserved17" |
|
||||||
case NALUTypeReserved18: |
|
||||||
return "Reserved18" |
|
||||||
case NALUTypeSliceLayerWithoutPartitioning: |
|
||||||
return "SliceLayerWithoutPartitioning" |
|
||||||
case NALUTypeSliceExtension: |
|
||||||
return "SliceExtension" |
|
||||||
case NALUTypeSliceExtensionDepth: |
|
||||||
return "SliceExtensionDepth" |
|
||||||
case NALUTypeReserved22: |
|
||||||
return "Reserved22" |
|
||||||
case NALUTypeReserved23: |
|
||||||
return "Reserved23" |
|
||||||
} |
|
||||||
return fmt.Sprintf("unknown (%d)", nt) |
|
||||||
} |
|
Loading…
Reference in new issue