Browse Source

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
pull/1395/head
Alessandro Ros 3 years ago committed by GitHub
parent
commit
fb06f6db72
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 27
      internal/hls/muxer_test.go
  2. 24
      internal/hls/muxer_variant_fmp4_segmenter.go

27
internal/hls/muxer_test.go

@ -566,3 +566,30 @@ func TestMuxerDoubleRead(t *testing.T) {
require.NoError(t, err) require.NoError(t, err)
require.Equal(t, byts1, byts2) 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)
}

24
internal/hls/muxer_variant_fmp4_segmenter.go

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

Loading…
Cancel
Save