hls muxer: fix crash (#1394)

this happened when variant is lowLatency and two AUs have adjacent
DTSs, resulting in a sample duration equal to zero.

discovered while investigating #1156
This commit is contained in:
Alessandro Ros 2023-01-18 16:41:35 +01:00 committed by GitHub
parent 0bce6c6ec9
commit fb06f6db72
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 42 additions and 9 deletions

View file

@ -566,3 +566,30 @@ func TestMuxerDoubleRead(t *testing.T) {
require.NoError(t, err)
require.Equal(t, byts1, byts2)
}
func TestMuxerFMP4ZeroDuration(t *testing.T) {
videoTrack := &format.H264{
PayloadTyp: 96,
SPS: testSPS,
PPS: []byte{0x08},
PacketizationMode: 1,
}
m, err := NewMuxer(MuxerVariantLowLatency, 3, 1*time.Second, 0, 50*1024*1024, videoTrack, nil)
require.NoError(t, err)
defer m.Close()
err = m.WriteH26x(time.Now(), 0, [][]byte{
testSPS, // SPS
{8}, // PPS
{5}, // IDR
})
require.NoError(t, err)
err = m.WriteH26x(time.Now(), 1*time.Nanosecond, [][]byte{
testSPS, // SPS
{8}, // PPS
{5}, // IDR
})
require.NoError(t, err)
}

View file

@ -25,21 +25,22 @@ func partDurationIsCompatible(partDuration time.Duration, sampleDuration time.Du
return partDuration > ((f * 85) / 100)
}
func partDurationIsCompatibleWithAll(partDuration time.Duration, sampleDurations map[time.Duration]struct{}) bool {
for sd := range sampleDurations {
if !partDurationIsCompatible(partDuration, sd) {
return false
}
}
return true
}
func findCompatiblePartDuration(
minPartDuration time.Duration,
sampleDurations map[time.Duration]struct{},
) time.Duration {
i := minPartDuration
for ; i < 5*time.Second; i += 5 * time.Millisecond {
isCompatible := func() bool {
for sd := range sampleDurations {
if !partDurationIsCompatible(i, sd) {
return false
}
}
return true
}()
if isCompatible {
if partDurationIsCompatibleWithAll(i, sampleDurations) {
break
}
}
@ -147,6 +148,11 @@ func (m *muxerVariantFMP4Segmenter) adjustPartDuration(du time.Duration) {
return
}
// avoid a crash by skipping invalid durations
if du == 0 {
return
}
if _, ok := m.sampleDurations[du]; !ok {
m.sampleDurations[du] = struct{}{}
m.adjustedPartDuration = findCompatiblePartDuration(