mirror of
https://github.com/aler9/gortsplib
synced 2025-10-05 23:26:54 +08:00
rtph264: add error in case we decoded a non-starting fragmented packets and we didn't received anything before
This commit is contained in:
@@ -14,6 +14,10 @@ import (
|
|||||||
// ErrMorePacketsNeeded is returned when more packets are needed.
|
// ErrMorePacketsNeeded is returned when more packets are needed.
|
||||||
var ErrMorePacketsNeeded = errors.New("need more packets")
|
var ErrMorePacketsNeeded = errors.New("need more packets")
|
||||||
|
|
||||||
|
// ErrNonStartingPacketAndNoPrevious is returned when we decoded a non-starting
|
||||||
|
// fragmented packet and we didn't received anything before.
|
||||||
|
var ErrNonStartingPacketAndNoPrevious = errors.New("decoded a non-starting fragmented packet without any previous starting packets")
|
||||||
|
|
||||||
// PacketConnReader creates a io.Reader around a net.PacketConn.
|
// PacketConnReader creates a io.Reader around a net.PacketConn.
|
||||||
type PacketConnReader struct {
|
type PacketConnReader struct {
|
||||||
net.PacketConn
|
net.PacketConn
|
||||||
@@ -38,8 +42,9 @@ type Decoder struct {
|
|||||||
initialTsSet bool
|
initialTsSet bool
|
||||||
|
|
||||||
// for Decode()
|
// for Decode()
|
||||||
state decoderState
|
startingPacketReceived bool
|
||||||
fragmentedBuf []byte
|
state decoderState
|
||||||
|
fragmentedBuf []byte
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewDecoder allocates a Decoder.
|
// NewDecoder allocates a Decoder.
|
||||||
@@ -87,7 +92,7 @@ func (d *Decoder) DecodeRTP(pkt *rtp.Packet) ([][]byte, time.Duration, error) {
|
|||||||
|
|
||||||
for len(pkt.Payload) > 0 {
|
for len(pkt.Payload) > 0 {
|
||||||
if len(pkt.Payload) < 2 {
|
if len(pkt.Payload) < 2 {
|
||||||
return nil, 0, fmt.Errorf("Invalid STAP-A packet")
|
return nil, 0, fmt.Errorf("invalid STAP-A packet (invalid size)")
|
||||||
}
|
}
|
||||||
|
|
||||||
size := binary.BigEndian.Uint16(pkt.Payload)
|
size := binary.BigEndian.Uint16(pkt.Payload)
|
||||||
@@ -99,7 +104,7 @@ func (d *Decoder) DecodeRTP(pkt *rtp.Packet) ([][]byte, time.Duration, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if int(size) > len(pkt.Payload) {
|
if int(size) > len(pkt.Payload) {
|
||||||
return nil, 0, fmt.Errorf("Invalid STAP-A packet")
|
return nil, 0, fmt.Errorf("invalid STAP-A packet (invalid size)")
|
||||||
}
|
}
|
||||||
|
|
||||||
nalus = append(nalus, pkt.Payload[:size])
|
nalus = append(nalus, pkt.Payload[:size])
|
||||||
@@ -110,16 +115,20 @@ func (d *Decoder) DecodeRTP(pkt *rtp.Packet) ([][]byte, time.Duration, error) {
|
|||||||
return nil, 0, fmt.Errorf("STAP-A packet doesn't contain any NALU")
|
return nil, 0, fmt.Errorf("STAP-A packet doesn't contain any NALU")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
d.startingPacketReceived = true
|
||||||
return nalus, d.decodeTimestamp(pkt.Timestamp), nil
|
return nalus, d.decodeTimestamp(pkt.Timestamp), nil
|
||||||
|
|
||||||
case naluTypeFUA: // first packet of a fragmented NALU
|
case naluTypeFUA: // first packet of a fragmented NALU
|
||||||
if len(pkt.Payload) < 2 {
|
if len(pkt.Payload) < 2 {
|
||||||
return nil, 0, fmt.Errorf("Invalid FU-A packet")
|
return nil, 0, fmt.Errorf("invalid FU-A packet (invalid size)")
|
||||||
}
|
}
|
||||||
|
|
||||||
start := pkt.Payload[1] >> 7
|
start := pkt.Payload[1] >> 7
|
||||||
if start != 1 {
|
if start != 1 {
|
||||||
return nil, 0, fmt.Errorf("first NALU does not contain the start bit")
|
if !d.startingPacketReceived {
|
||||||
|
return nil, 0, ErrNonStartingPacketAndNoPrevious
|
||||||
|
}
|
||||||
|
return nil, 0, fmt.Errorf("invalid FU-A packet (non-starting)")
|
||||||
}
|
}
|
||||||
|
|
||||||
nri := (pkt.Payload[0] >> 5) & 0x03
|
nri := (pkt.Payload[0] >> 5) & 0x03
|
||||||
@@ -127,25 +136,27 @@ func (d *Decoder) DecodeRTP(pkt *rtp.Packet) ([][]byte, time.Duration, error) {
|
|||||||
d.fragmentedBuf = append([]byte{(nri << 5) | typ}, pkt.Payload[2:]...)
|
d.fragmentedBuf = append([]byte{(nri << 5) | typ}, pkt.Payload[2:]...)
|
||||||
|
|
||||||
d.state = decoderStateReadingFragmented
|
d.state = decoderStateReadingFragmented
|
||||||
|
d.startingPacketReceived = true
|
||||||
return nil, 0, ErrMorePacketsNeeded
|
return nil, 0, ErrMorePacketsNeeded
|
||||||
|
|
||||||
case naluTypeSTAPB, naluTypeMTAP16,
|
case naluTypeSTAPB, naluTypeMTAP16,
|
||||||
naluTypeMTAP24, naluTypeFUB:
|
naluTypeMTAP24, naluTypeFUB:
|
||||||
return nil, 0, fmt.Errorf("NALU type not supported (%v)", typ)
|
return nil, 0, fmt.Errorf("packet type not supported (%v)", typ)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
d.startingPacketReceived = true
|
||||||
return [][]byte{pkt.Payload}, d.decodeTimestamp(pkt.Timestamp), nil
|
return [][]byte{pkt.Payload}, d.decodeTimestamp(pkt.Timestamp), nil
|
||||||
|
|
||||||
default: // decoderStateReadingFragmented
|
default: // decoderStateReadingFragmented
|
||||||
if len(pkt.Payload) < 2 {
|
if len(pkt.Payload) < 2 {
|
||||||
d.state = decoderStateInitial
|
d.state = decoderStateInitial
|
||||||
return nil, 0, fmt.Errorf("Invalid non-starting FU-A packet")
|
return nil, 0, fmt.Errorf("invalid FU-A packet (invalid size)")
|
||||||
}
|
}
|
||||||
|
|
||||||
typ := naluType(pkt.Payload[0] & 0x1F)
|
typ := naluType(pkt.Payload[0] & 0x1F)
|
||||||
if typ != naluTypeFUA {
|
if typ != naluTypeFUA {
|
||||||
d.state = decoderStateInitial
|
d.state = decoderStateInitial
|
||||||
return nil, 0, fmt.Errorf("Packet is not FU-A")
|
return nil, 0, fmt.Errorf("expected FU-A packet, got another type")
|
||||||
}
|
}
|
||||||
|
|
||||||
end := (pkt.Payload[1] >> 6) & 0x01
|
end := (pkt.Payload[1] >> 6) & 0x01
|
||||||
@@ -157,6 +168,7 @@ func (d *Decoder) DecodeRTP(pkt *rtp.Packet) ([][]byte, time.Duration, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
d.state = decoderStateInitial
|
d.state = decoderStateInitial
|
||||||
|
d.startingPacketReceived = true
|
||||||
return [][]byte{d.fragmentedBuf}, d.decodeTimestamp(pkt.Timestamp), nil
|
return [][]byte{d.fragmentedBuf}, d.decodeTimestamp(pkt.Timestamp), nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -265,6 +265,29 @@ func TestDecode(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestDecodePartOfFragmentedBeforeSingle(t *testing.T) {
|
||||||
|
d := NewDecoder()
|
||||||
|
|
||||||
|
_, _, err := d.Decode(mergeBytes(
|
||||||
|
[]byte{
|
||||||
|
0x80, 0xe0, 0x44, 0xef, 0x88, 0x77, 0x79, 0xab,
|
||||||
|
0x9d, 0xbb, 0x78, 0x12, 0x1c, 0x45,
|
||||||
|
},
|
||||||
|
[]byte{0x04, 0x05, 0x06, 0x07},
|
||||||
|
bytes.Repeat([]byte{0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07}, 147),
|
||||||
|
))
|
||||||
|
require.Equal(t, ErrNonStartingPacketAndNoPrevious, err)
|
||||||
|
|
||||||
|
_, _, err = d.Decode(mergeBytes(
|
||||||
|
[]byte{
|
||||||
|
0x80, 0xe0, 0x44, 0xed, 0x88, 0x77, 0x6f, 0x1f,
|
||||||
|
0x9d, 0xbb, 0x78, 0x12, 0x05,
|
||||||
|
},
|
||||||
|
bytes.Repeat([]byte{0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07}, 8),
|
||||||
|
))
|
||||||
|
require.NoError(t, err)
|
||||||
|
}
|
||||||
|
|
||||||
func TestDecodeSTAPAWithPadding(t *testing.T) {
|
func TestDecodeSTAPAWithPadding(t *testing.T) {
|
||||||
d := NewDecoder()
|
d := NewDecoder()
|
||||||
nalus, _, err := d.Decode([]byte{
|
nalus, _, err := d.Decode([]byte{
|
||||||
@@ -318,7 +341,7 @@ func TestDecodeErrors(t *testing.T) {
|
|||||||
0x80, 0xe0, 0x44, 0xed, 0x88, 0x77, 0x6a, 0x15,
|
0x80, 0xe0, 0x44, 0xed, 0x88, 0x77, 0x6a, 0x15,
|
||||||
0x9d, 0xbb, 0x78, 0x12, byte(naluTypeSTAPA), 0x01,
|
0x9d, 0xbb, 0x78, 0x12, byte(naluTypeSTAPA), 0x01,
|
||||||
}},
|
}},
|
||||||
"Invalid STAP-A packet",
|
"invalid STAP-A packet (invalid size)",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"STAP-A with invalid size",
|
"STAP-A with invalid size",
|
||||||
@@ -326,7 +349,7 @@ func TestDecodeErrors(t *testing.T) {
|
|||||||
0x80, 0xe0, 0x44, 0xed, 0x88, 0x77, 0x6a, 0x15,
|
0x80, 0xe0, 0x44, 0xed, 0x88, 0x77, 0x6a, 0x15,
|
||||||
0x9d, 0xbb, 0x78, 0x12, byte(naluTypeSTAPA), 0x00, 0x15,
|
0x9d, 0xbb, 0x78, 0x12, byte(naluTypeSTAPA), 0x00, 0x15,
|
||||||
}},
|
}},
|
||||||
"Invalid STAP-A packet",
|
"invalid STAP-A packet (invalid size)",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"FU-A without payload",
|
"FU-A without payload",
|
||||||
@@ -334,15 +357,24 @@ func TestDecodeErrors(t *testing.T) {
|
|||||||
0x80, 0xe0, 0x44, 0xed, 0x88, 0x77, 0x6a, 0x15,
|
0x80, 0xe0, 0x44, 0xed, 0x88, 0x77, 0x6a, 0x15,
|
||||||
0x9d, 0xbb, 0x78, 0x12, byte(naluTypeFUA),
|
0x9d, 0xbb, 0x78, 0x12, byte(naluTypeFUA),
|
||||||
}},
|
}},
|
||||||
"Invalid FU-A packet",
|
"invalid FU-A packet (invalid size)",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"FU-A without start bit",
|
"FU-A without start bit",
|
||||||
[][]byte{{
|
[][]byte{
|
||||||
0x80, 0xe0, 0x44, 0xed, 0x88, 0x77, 0x6a, 0x15,
|
mergeBytes(
|
||||||
0x9d, 0xbb, 0x78, 0x12, byte(naluTypeFUA), 0x00,
|
[]byte{
|
||||||
}},
|
0x80, 0xe0, 0x44, 0xed, 0x88, 0x77, 0x6f, 0x1f,
|
||||||
"first NALU does not contain the start bit",
|
0x9d, 0xbb, 0x78, 0x12, 0x05,
|
||||||
|
},
|
||||||
|
bytes.Repeat([]byte{0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07}, 8),
|
||||||
|
),
|
||||||
|
{
|
||||||
|
0x80, 0xe0, 0x44, 0xed, 0x88, 0x77, 0x6a, 0x15,
|
||||||
|
0x9d, 0xbb, 0x78, 0x12, byte(naluTypeFUA), 0x00,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
"invalid FU-A packet (non-starting)",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"FU-A with 2nd packet empty",
|
"FU-A with 2nd packet empty",
|
||||||
@@ -362,7 +394,7 @@ func TestDecodeErrors(t *testing.T) {
|
|||||||
},
|
},
|
||||||
),
|
),
|
||||||
},
|
},
|
||||||
"Invalid non-starting FU-A packet",
|
"invalid FU-A packet (invalid size)",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"FU-A with 2nd packet invalid",
|
"FU-A with 2nd packet invalid",
|
||||||
@@ -382,7 +414,7 @@ func TestDecodeErrors(t *testing.T) {
|
|||||||
},
|
},
|
||||||
),
|
),
|
||||||
},
|
},
|
||||||
"Packet is not FU-A",
|
"expected FU-A packet, got another type",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"MTAP",
|
"MTAP",
|
||||||
@@ -390,7 +422,7 @@ func TestDecodeErrors(t *testing.T) {
|
|||||||
0x80, 0xe0, 0x44, 0xed, 0x88, 0x77, 0x6a, 0x15,
|
0x80, 0xe0, 0x44, 0xed, 0x88, 0x77, 0x6a, 0x15,
|
||||||
0x9d, 0xbb, 0x78, 0x12, byte(naluTypeMTAP16),
|
0x9d, 0xbb, 0x78, 0x12, byte(naluTypeMTAP16),
|
||||||
}},
|
}},
|
||||||
"NALU type not supported (MTAP16)",
|
"packet type not supported (MTAP16)",
|
||||||
},
|
},
|
||||||
} {
|
} {
|
||||||
t.Run(ca.name, func(t *testing.T) {
|
t.Run(ca.name, func(t *testing.T) {
|
||||||
|
Reference in New Issue
Block a user