rtph264: accept non-compliant single FU-A frames (#649)

Some IP cameras (e.g. CostarHD) have been observed to emit single
fragment RTP FU-A packets, with start and end bit both set, for
sufficiently small H.264 P-frames. Rather than emit an error,
workaround such non-compliant frames.
This commit is contained in:
Chris Hiszpanski
2024-12-04 14:21:09 -08:00
committed by GitHub
parent d7efbd0a48
commit 44aaa0977a
2 changed files with 46 additions and 4 deletions

View File

@@ -90,10 +90,6 @@ func (d *Decoder) decodeNALUs(pkt *rtp.Packet) ([][]byte, error) {
if start == 1 {
d.resetFragments()
if end != 0 {
return nil, fmt.Errorf("invalid FU-A packet (can't contain both a start and end bit)")
}
nri := (pkt.Payload[0] >> 5) & 0x03
typ := pkt.Payload[1] & 0x1F
d.fragmentsSize = len(pkt.Payload[1:])
@@ -101,6 +97,20 @@ func (d *Decoder) decodeNALUs(pkt *rtp.Packet) ([][]byte, error) {
d.fragmentNextSeqNum = pkt.SequenceNumber + 1
d.firstPacketReceived = true
// RFC 6184 clearly states:
//
// A fragmented NAL unit MUST NOT be transmitted in one FU; that is, the
// Start bit and End bit MUST NOT both be set to one in the same FU
// header.
//
// However, some vendors camera (e.g. CostarHD) have been observed to nevertheless
// emit one fragmented NAL unit for sufficiently small P-frames.
if end != 0 {
nalus = [][]byte{joinFragments(d.fragments, d.fragmentsSize)}
d.resetFragments()
break
}
return nil, ErrMorePacketsNeeded
}