fix crash when H264 or H265 parameters are nil (#1155)

in H264 and H264, parameters (VPS, SPS and PPS) are automatically
prepended to random access units. When parameters were nil, they were
prepended anyway, leading to a crash. Parameters are not prepended only
if they are valid.
This commit is contained in:
aler9 2023-01-05 13:10:28 +01:00
parent e3fff72b7c
commit 59c0ef520f
4 changed files with 66 additions and 15 deletions

View File

@ -138,6 +138,8 @@ func (t *formatProcessorH264) updateTrackParametersFromNALUs(nalus [][]byte) {
}
func (t *formatProcessorH264) remuxAccessUnit(nalus [][]byte) [][]byte {
var sps []byte
var pps []byte
addParameters := false
n := 0
@ -154,7 +156,12 @@ func (t *formatProcessorH264) remuxAccessUnit(nalus [][]byte) [][]byte {
case h264.NALUTypeIDR: // prepend parameters if there's at least an IDR
if !addParameters {
addParameters = true
n += 2
sps = t.format.SafeSPS()
pps = t.format.SafePPS()
if sps != nil && pps != nil {
n += 2
}
}
}
n++
@ -167,9 +174,9 @@ func (t *formatProcessorH264) remuxAccessUnit(nalus [][]byte) [][]byte {
filteredNALUs := make([][]byte, n)
i := 0
if addParameters {
filteredNALUs[0] = t.format.SafeSPS()
filteredNALUs[1] = t.format.SafePPS()
if addParameters && sps != nil && pps != nil {
filteredNALUs[0] = sps
filteredNALUs[1] = pps
i = 2
}

View File

@ -4,6 +4,7 @@ import (
"bytes"
"testing"
"github.com/aler9/gortsplib/v2/pkg/codecs/h264"
"github.com/aler9/gortsplib/v2/pkg/format"
"github.com/pion/rtp"
"github.com/stretchr/testify/require"
@ -20,13 +21,14 @@ func TestH264DynamicParams(t *testing.T) {
enc := forma.CreateEncoder()
pkts, err := enc.Encode([][]byte{{7, 1, 2, 3}}, 0) // SPS
pkts, err := enc.Encode([][]byte{{byte(h264.NALUTypeIDR)}}, 0)
require.NoError(t, err)
p.Process(&DataH264{RTPPackets: []*rtp.Packet{pkts[0]}}, false)
data := &DataH264{RTPPackets: []*rtp.Packet{pkts[0]}}
p.Process(data, true)
pkts, err = enc.Encode([][]byte{{8}}, 0) // PPS
require.NoError(t, err)
p.Process(&DataH264{RTPPackets: []*rtp.Packet{pkts[0]}}, false)
require.Equal(t, [][]byte{
{byte(h264.NALUTypeIDR)},
}, data.AU)
pkts, err = enc.Encode([][]byte{{7, 4, 5, 6}}, 0) // SPS
require.NoError(t, err)
@ -38,6 +40,17 @@ func TestH264DynamicParams(t *testing.T) {
require.Equal(t, []byte{7, 4, 5, 6}, forma.SPS)
require.Equal(t, []byte{8, 1}, forma.PPS)
pkts, err = enc.Encode([][]byte{{byte(h264.NALUTypeIDR)}}, 0)
require.NoError(t, err)
data = &DataH264{RTPPackets: []*rtp.Packet{pkts[0]}}
p.Process(data, true)
require.Equal(t, [][]byte{
{0x07, 4, 5, 6},
{0x08, 1},
{byte(h264.NALUTypeIDR)},
}, data.AU)
}
func TestH264OversizedPackets(t *testing.T) {

View File

@ -154,6 +154,9 @@ func (t *formatProcessorH265) updateTrackParametersFromNALUs(nalus [][]byte) {
}
func (t *formatProcessorH265) remuxAccessUnit(nalus [][]byte) [][]byte {
var vps []byte
var sps []byte
var pps []byte
addParameters := false
n := 0
@ -171,7 +174,14 @@ func (t *formatProcessorH265) remuxAccessUnit(nalus [][]byte) [][]byte {
case h265.NALUType_IDR_W_RADL, h265.NALUType_IDR_N_LP, h265.NALUType_CRA_NUT:
if !addParameters {
addParameters = true
n += 3
vps = t.format.SafeVPS()
sps = t.format.SafeSPS()
pps = t.format.SafePPS()
if vps != nil && sps != nil && pps != nil {
n += 3
}
}
}
n++
@ -184,10 +194,10 @@ func (t *formatProcessorH265) remuxAccessUnit(nalus [][]byte) [][]byte {
filteredNALUs := make([][]byte, n)
i := 0
if addParameters {
filteredNALUs[0] = t.format.SafeVPS()
filteredNALUs[1] = t.format.SafeSPS()
filteredNALUs[2] = t.format.SafePPS()
if addParameters && vps != nil && sps != nil && pps != nil {
filteredNALUs[0] = vps
filteredNALUs[1] = sps
filteredNALUs[2] = pps
i = 3
}

View File

@ -20,7 +20,16 @@ func TestH265DynamicParams(t *testing.T) {
enc := forma.CreateEncoder()
pkts, err := enc.Encode([][]byte{{byte(h265.NALUType_VPS_NUT) << 1, 1, 2, 3}}, 0)
pkts, err := enc.Encode([][]byte{{byte(h265.NALUType_CRA_NUT) << 1, 0}}, 0)
require.NoError(t, err)
data := &DataH265{RTPPackets: []*rtp.Packet{pkts[0]}}
p.Process(data, true)
require.Equal(t, [][]byte{
{byte(h265.NALUType_CRA_NUT) << 1, 0},
}, data.AU)
pkts, err = enc.Encode([][]byte{{byte(h265.NALUType_VPS_NUT) << 1, 1, 2, 3}}, 0)
require.NoError(t, err)
p.Process(&DataH265{RTPPackets: []*rtp.Packet{pkts[0]}}, false)
@ -35,6 +44,18 @@ func TestH265DynamicParams(t *testing.T) {
require.Equal(t, []byte{byte(h265.NALUType_VPS_NUT) << 1, 1, 2, 3}, forma.VPS)
require.Equal(t, []byte{byte(h265.NALUType_SPS_NUT) << 1, 4, 5, 6}, forma.SPS)
require.Equal(t, []byte{byte(h265.NALUType_PPS_NUT) << 1, 7, 8, 9}, forma.PPS)
pkts, err = enc.Encode([][]byte{{byte(h265.NALUType_CRA_NUT) << 1, 0}}, 0)
require.NoError(t, err)
data = &DataH265{RTPPackets: []*rtp.Packet{pkts[0]}}
p.Process(data, true)
require.Equal(t, [][]byte{
{byte(h265.NALUType_VPS_NUT) << 1, 1, 2, 3},
{byte(h265.NALUType_SPS_NUT) << 1, 4, 5, 6},
{byte(h265.NALUType_PPS_NUT) << 1, 7, 8, 9},
{byte(h265.NALUType_CRA_NUT) << 1, 0},
}, data.AU)
}
func TestH265OversizedPackets(t *testing.T) {