Closed fayfive closed 1 year ago
Hello, the problem is more clear now, you're claiming that in some RTP/H264 streams there are multiple NALUs inside a single RTP Fragmentation Unit (FU-A), and therefore rtph264.Decoder
is unable to parse them.
The question is that theoretically a FU-A RTP packet can't hold more than one NALU at a time, therefore, how is it possible that multiple NALUs are packed inside a single FU-A? how are you able to split the SPS, PPS and IDR NALUs from the packet dump you posted?
oh now i see, Annex-B is used to pack SPS, PPS and IDR inside a single FU-A, you can see the [0 0 0 1]
delimiter inside your packet:
124 135 77 192 31 141 141 112 120 8 175 112 128 0 0 3 0 128 0 0 30 71 132 66 55
0 0 0 1 104 206 60 128
0 0 0 1 101 184 0 1 0 0 15 196 139 141...
I've investigated, and the decoder already supports decoding Annex-B inside FU-A packets. This is a working example that uses the packet dump you provided:
https://go.dev/play/p/dGqbXP59Z4k
Why are you having problem decoding such streams?
I found that if I push the first frame that is Pframe and the next frame is sps+pps+Iframe to the decoder, and the sps+pps+Iframe can not decode. If the first frame is sps+pps+Iframe, it works well.
I found that if I push the first frame that is Pframe and the next frame is sps+pps+Iframe to the decoder, and the sps+pps+Iframe can not decode. If the first frame is sps+pps+Iframe, it works well.
Everything is clear now, the reason is that rtph264.Decoder decodes Annex-B if and only if the first received RTP packet contains an Annex-B delimiter:
The decoder will be improved in order to parse Annex-B even if the first received RTP packet doesn't contain an Annex-B delimiter.
That means the first frame must be Iframe to the decoder? I modify the gortsplib/pkg/formatdecenc/rtph264/decoder.go
func (d *Decoder) removeAnnexB(nalus [][]byte) ([][]byte, error) {
if !d.firstNALUParsed {
d.firstNALUParsed = true
if len(nalus) == 1 {
nalu := nalus[0]
i := bytes.Index(nalu, []byte{0x00, 0x00, 0x00, 0x01})
if i >= 0 {
d.annexBMode = true
if !bytes.HasPrefix(nalu, []byte{0x00, 0x00, 0x00, 0x01}) {
nalu = append([]byte{0x00, 0x00, 0x00, 0x01}, nalu...)
}
return h264.AnnexBUnmarshal(nalu)
} else {
d.firstNALUParsed = false // I add here to avoid the first frame is Pframe or else
}
}
} else if d.annexBMode {
if len(nalus) != 1 {
return nil, fmt.Errorf("multiple NALUs in Annex-B mode are not supported")
}
nalu := nalus[0]
if !bytes.HasPrefix(nalu, []byte{0x00, 0x00, 0x00, 0x01}) {
nalu = append([]byte{0x00, 0x00, 0x00, 0x01}, nalu...)
}
return h264.AnnexBUnmarshal(nalu)
}
return nalus, nil
}
I have created a PR to you
This issue is being locked automatically because it has been closed for more than 6 months. Please open a new issue in case you encounter a similar problem.
Some h264 stream contain sps+pps+Iframe together in a FU-A, not sps+pps Iframe, sps+pps+Iframe just has one Mark. Here is the first udp package contain sps+pps+Iframe