prepend SPS and PPS once when remuxing H264 streams

This avoids missing frames when reading with RTSP and the original
stream has NALU groups with multiple IDRs in it.
This commit is contained in:
aler9
2022-10-09 23:39:08 +02:00
parent 31d9429c18
commit 8aa719eda5
2 changed files with 27 additions and 19 deletions

View File

@@ -116,7 +116,10 @@ func TestRTMPServerPublishRead(t *testing.T) {
MessageStreamID: 0x1000000,
IsKeyFrame: true,
H264Type: flvio.AVC_NALU,
Payload: []byte{0x00, 0x00, 0x00, 0x04, 0x05, 0x02, 0x03, 0x04},
Payload: []byte{
0x00, 0x00, 0x00, 0x04, 0x05, 0x02, 0x03, 0x04, // IDR 1
0x00, 0x00, 0x00, 0x04, 0x05, 0x02, 0x03, 0x04, // IDR 2
},
})
require.NoError(t, err)
@@ -128,12 +131,14 @@ func TestRTMPServerPublishRead(t *testing.T) {
IsKeyFrame: true,
H264Type: flvio.AVC_NALU,
Payload: []byte{
0x00, 0x00, 0x00, 0x19, 0x67, 0x42, 0xc0, 0x28,
0xd9, 0x00, 0x78, 0x02, 0x27, 0xe5, 0x84, 0x00,
0x00, 0x03, 0x00, 0x04, 0x00, 0x00, 0x03, 0x00,
0xf0, 0x3c, 0x60, 0xc9, 0x20, 0x00, 0x00, 0x00,
0x04, 0x08, 0x06, 0x07, 0x08, 0x00, 0x00, 0x00,
0x04, 0x05, 0x02, 0x03, 0x04,
0x00, 0x00, 0x00, 0x19, // SPS
0x67, 0x42, 0xc0, 0x28, 0xd9, 0x00, 0x78, 0x02,
0x27, 0xe5, 0x84, 0x00, 0x00, 0x03, 0x00, 0x04,
0x00, 0x00, 0x03, 0x00, 0xf0, 0x3c, 0x60, 0xc9,
0x20,
0x00, 0x00, 0x00, 0x04, 0x08, 0x06, 0x07, 0x08, // PPS
0x00, 0x00, 0x00, 0x04, 0x05, 0x02, 0x03, 0x04, // IDR 1
0x00, 0x00, 0x00, 0x04, 0x05, 0x02, 0x03, 0x04, // IDR 2
},
}, msg1)
})

View File

@@ -51,10 +51,10 @@ func (t *streamTrackH264) updateTrackParameters(nalus [][]byte) {
}
}
// remux is needed to
// - fix corrupted streams
// - make streams compatible with all protocols
// remux is needed to fix corrupted streams and make streams
// compatible with all protocols.
func (t *streamTrackH264) remuxNALUs(nalus [][]byte) [][]byte {
addSPSPPS := false
n := 0
for _, nalu := range nalus {
typ := h264.NALUType(nalu[0] & 0x1F)
@@ -64,8 +64,12 @@ func (t *streamTrackH264) remuxNALUs(nalus [][]byte) [][]byte {
case h264.NALUTypeAccessUnitDelimiter:
continue
case h264.NALUTypeIDR:
// prepend SPS and PPS to the group if there's at least an IDR
if !addSPSPPS {
addSPSPPS = true
n += 2
}
}
n++
}
@@ -76,23 +80,22 @@ func (t *streamTrackH264) remuxNALUs(nalus [][]byte) [][]byte {
filteredNALUs := make([][]byte, n)
i := 0
if addSPSPPS {
filteredNALUs[0] = t.track.SafeSPS()
filteredNALUs[1] = t.track.SafePPS()
i = 2
}
for _, nalu := range nalus {
typ := h264.NALUType(nalu[0] & 0x1F)
switch typ {
case h264.NALUTypeSPS, h264.NALUTypePPS:
// remove since they're automatically added before every IDR
// remove since they're automatically added
continue
case h264.NALUTypeAccessUnitDelimiter:
// remove since it is not needed
continue
case h264.NALUTypeIDR:
// add SPS and PPS before every IDR
filteredNALUs[i] = t.track.SafeSPS()
i++
filteredNALUs[i] = t.track.SafePPS()
i++
}
filteredNALUs[i] = nalu