mirror of
https://github.com/aler9/gortsplib
synced 2025-10-06 23:52:46 +08:00
h264: fix Annex-B decoding
Some Annex-B streams use both [0 0 1] and [0 0 0 1] as delimiters. These streams are now parsed correctly.
This commit is contained in:
@@ -1,20 +1,19 @@
|
||||
package h264
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
)
|
||||
|
||||
// AnnexBUnmarshal decodes NALUs from the Annex-B stream format.
|
||||
func AnnexBUnmarshal(byts []byte) ([][]byte, error) {
|
||||
bl := len(byts)
|
||||
zeroCount := 0
|
||||
initZeroCount := 0
|
||||
|
||||
outer:
|
||||
for i := 0; i < bl; i++ {
|
||||
switch byts[i] {
|
||||
case 0:
|
||||
zeroCount++
|
||||
initZeroCount++
|
||||
|
||||
case 1:
|
||||
break outer
|
||||
@@ -23,35 +22,46 @@ outer:
|
||||
return nil, fmt.Errorf("unexpected byte: %d", byts[i])
|
||||
}
|
||||
}
|
||||
if zeroCount != 2 && zeroCount != 3 {
|
||||
if initZeroCount != 2 && initZeroCount != 3 {
|
||||
return nil, fmt.Errorf("initial delimiter not found")
|
||||
}
|
||||
|
||||
start := zeroCount + 1
|
||||
start := initZeroCount + 1
|
||||
zeroCount := 0
|
||||
n := 0
|
||||
|
||||
var n int
|
||||
if zeroCount == 2 {
|
||||
n = bytes.Count(byts[start:], []byte{0x00, 0x00, 0x01})
|
||||
} else {
|
||||
n = bytes.Count(byts[start:], []byte{0x00, 0x00, 0x00, 0x01})
|
||||
for i := start; i < bl; i++ {
|
||||
switch byts[i] {
|
||||
case 0:
|
||||
zeroCount++
|
||||
|
||||
case 1:
|
||||
if zeroCount == 2 || zeroCount == 3 {
|
||||
n++
|
||||
}
|
||||
zeroCount = 0
|
||||
|
||||
default:
|
||||
zeroCount = 0
|
||||
}
|
||||
}
|
||||
|
||||
ret := make([][]byte, n+1)
|
||||
pos := 0
|
||||
|
||||
curZeroCount := 0
|
||||
start = initZeroCount + 1
|
||||
zeroCount = 0
|
||||
delimStart := 0
|
||||
|
||||
for i := start; i < bl; i++ {
|
||||
switch byts[i] {
|
||||
case 0:
|
||||
if curZeroCount == 0 {
|
||||
if zeroCount == 0 {
|
||||
delimStart = i
|
||||
}
|
||||
curZeroCount++
|
||||
zeroCount++
|
||||
|
||||
case 1:
|
||||
if curZeroCount == zeroCount {
|
||||
if zeroCount == 2 || zeroCount == 3 {
|
||||
if (delimStart - start) > MaxNALUSize {
|
||||
return nil, fmt.Errorf("NALU size (%d) is too big (maximum is %d)", delimStart-start, MaxNALUSize)
|
||||
}
|
||||
@@ -65,10 +75,10 @@ outer:
|
||||
pos++
|
||||
start = i + 1
|
||||
}
|
||||
curZeroCount = 0
|
||||
zeroCount = 0
|
||||
|
||||
default:
|
||||
curZeroCount = 0
|
||||
zeroCount = 0
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -13,23 +13,15 @@ var casesAnnexB = []struct {
|
||||
dec [][]byte
|
||||
}{
|
||||
{
|
||||
"2 zeros, single",
|
||||
[]byte{0x00, 0x00, 0x01, 0xaa, 0xbb},
|
||||
[]byte{0x00, 0x00, 0x00, 0x01, 0xaa, 0xbb},
|
||||
[][]byte{
|
||||
{0xaa, 0xbb},
|
||||
},
|
||||
},
|
||||
{
|
||||
"2 zeros, multiple",
|
||||
"2 zeros",
|
||||
[]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,
|
||||
0x00, 0x00, 0x00, 0x01, 0xaa, 0xbb,
|
||||
0x00, 0x00, 0x00, 0x01, 0xcc, 0xdd,
|
||||
0x00, 0x00, 0x00, 0x01, 0xee, 0xff,
|
||||
},
|
||||
[][]byte{
|
||||
{0xaa, 0xbb},
|
||||
@@ -38,24 +30,16 @@ var casesAnnexB = []struct {
|
||||
},
|
||||
},
|
||||
{
|
||||
"3 zeros, single",
|
||||
[]byte{0x00, 0x00, 0x00, 0x01, 0xaa, 0xbb},
|
||||
[]byte{0x00, 0x00, 0x00, 0x01, 0xaa, 0xbb},
|
||||
[][]byte{
|
||||
{0xaa, 0xbb},
|
||||
},
|
||||
},
|
||||
{
|
||||
"3 zeros, multiple",
|
||||
"3 zeros",
|
||||
[]byte{
|
||||
0x00, 0x00, 0x00, 0x01, 0xaa, 0xbb, 0x00, 0x00,
|
||||
0x00, 0x01, 0xcc, 0xdd, 0x00, 0x00, 0x00, 0x01,
|
||||
0xee, 0xff,
|
||||
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,
|
||||
0x00, 0x00, 0x00, 0x01, 0xaa, 0xbb,
|
||||
0x00, 0x00, 0x00, 0x01, 0xcc, 0xdd,
|
||||
0x00, 0x00, 0x00, 0x01, 0xee, 0xff,
|
||||
},
|
||||
[][]byte{
|
||||
{0xaa, 0xbb},
|
||||
@@ -63,6 +47,31 @@ var casesAnnexB = []struct {
|
||||
{0xee, 0xff},
|
||||
},
|
||||
},
|
||||
{
|
||||
// used by Apple inside HLS test streams
|
||||
"2 or 3 zeros",
|
||||
[]byte{
|
||||
0, 0, 0, 1, 9, 240,
|
||||
0, 0, 0, 1, 39, 66, 224, 21, 169, 24, 60, 23, 252, 184, 3, 80, 96, 16, 107, 108, 43, 94, 247, 192, 64,
|
||||
0, 0, 0, 1, 40, 222, 9, 200,
|
||||
0, 0, 1, 6, 0, 7, 131, 236, 119, 0, 0, 0, 0, 1, 3, 0, 64, 128,
|
||||
0, 0, 1, 6, 5, 17, 3, 135, 244, 78, 205, 10, 75, 220, 161, 148, 58, 195, 212, 155, 23, 31, 0, 128,
|
||||
},
|
||||
[]byte{
|
||||
0, 0, 0, 1, 9, 240,
|
||||
0, 0, 0, 1, 39, 66, 224, 21, 169, 24, 60, 23, 252, 184, 3, 80, 96, 16, 107, 108, 43, 94, 247, 192, 64,
|
||||
0, 0, 0, 1, 40, 222, 9, 200,
|
||||
0, 0, 0, 1, 6, 0, 7, 131, 236, 119, 0, 0, 0, 0, 1, 3, 0, 64, 128,
|
||||
0, 0, 0, 1, 6, 5, 17, 3, 135, 244, 78, 205, 10, 75, 220, 161, 148, 58, 195, 212, 155, 23, 31, 0, 128,
|
||||
},
|
||||
[][]byte{
|
||||
{9, 240},
|
||||
{39, 66, 224, 21, 169, 24, 60, 23, 252, 184, 3, 80, 96, 16, 107, 108, 43, 94, 247, 192, 64},
|
||||
{40, 222, 9, 200},
|
||||
{6, 0, 7, 131, 236, 119, 0, 0, 0, 0, 1, 3, 0, 64, 128},
|
||||
{6, 5, 17, 3, 135, 244, 78, 205, 10, 75, 220, 161, 148, 58, 195, 212, 155, 23, 31, 0, 128},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
func TestAnnexBUnmarshal(t *testing.T) {
|
||||
|
Reference in New Issue
Block a user