Skip to content

Commit 033dd61

Browse files
authored
muxer: prevent FMP4 durations from overflowing (bluenviron/mediamtx#5126) (#290)
1 parent aa26735 commit 033dd61

File tree

2 files changed

+88
-2
lines changed

2 files changed

+88
-2
lines changed

muxer_segmenter.go

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -538,7 +538,13 @@ func (s *muxerSegmenter) fmp4WriteSample(
538538
if sample == nil {
539539
return nil
540540
}
541+
541542
duration := track.fmp4NextSample.dts - sample.dts
543+
if duration < 0 {
544+
track.fmp4NextSample.dts = sample.dts
545+
duration = 0
546+
}
547+
542548
sample.Duration = uint32(duration)
543549

544550
if track.isLeading {
@@ -557,7 +563,7 @@ func (s *muxerSegmenter) fmp4WriteSample(
557563
}
558564

559565
if track.isLeading {
560-
s.fmp4AdjustPartDuration(timestampToDuration(duration, track.ClockRate))
566+
s.fmp4AdjustPartDuration(timestampToDuration(int64(sample.Duration), track.ClockRate))
561567
}
562568

563569
err := track.stream.nextPart.writeSample(

muxer_test.go

Lines changed: 81 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1187,7 +1187,7 @@ func TestMuxerFMP4ZeroDuration(t *testing.T) {
11871187
require.NoError(t, err)
11881188
}
11891189

1190-
func TestMuxerFMP4NegativeTimestamp(t *testing.T) {
1190+
func TestMuxerFMP4NegativeInitialDTS(t *testing.T) {
11911191
m := &Muxer{
11921192
Variant: MuxerVariantFMP4,
11931193
SegmentCount: 3,
@@ -1217,6 +1217,86 @@ func TestMuxerFMP4NegativeTimestamp(t *testing.T) {
12171217
require.Error(t, err, "sample timestamp is impossible to handle")
12181218
}
12191219

1220+
func TestMuxerFMP4NegativeDTSDiff(t *testing.T) {
1221+
m := &Muxer{
1222+
Variant: MuxerVariantFMP4,
1223+
SegmentCount: 3,
1224+
SegmentMinDuration: 2 * time.Second,
1225+
Tracks: []*Track{testAudioTrack},
1226+
}
1227+
1228+
err := m.Start()
1229+
require.NoError(t, err)
1230+
defer m.Close()
1231+
1232+
err = m.WriteMPEG4Audio(testAudioTrack, testTime,
1233+
1*44100,
1234+
[][]byte{{1, 2}})
1235+
require.NoError(t, err)
1236+
1237+
err = m.WriteMPEG4Audio(testAudioTrack, testTime,
1238+
3*44100,
1239+
[][]byte{{1, 2}})
1240+
require.NoError(t, err)
1241+
1242+
err = m.WriteMPEG4Audio(testAudioTrack, testTime,
1243+
2*44100,
1244+
[][]byte{{1, 2}})
1245+
require.NoError(t, err)
1246+
1247+
for i := 4; i < 10; i++ {
1248+
err = m.WriteMPEG4Audio(testAudioTrack, testTime,
1249+
int64(i)*44100,
1250+
[][]byte{{1, 2}})
1251+
require.NoError(t, err)
1252+
}
1253+
1254+
byts, _, err := doRequest(m, "audio1_stream.m3u8")
1255+
require.NoError(t, err)
1256+
require.Equal(t, `#EXTM3U`+"\n"+
1257+
`#EXT-X-VERSION:10`+"\n"+
1258+
`#EXT-X-TARGETDURATION:2`+"\n"+
1259+
`#EXT-X-MEDIA-SEQUENCE:1`+"\n"+
1260+
`#EXT-X-MAP:URI="`+m.prefix+`_audio1_init.mp4"`+"\n"+
1261+
`#EXTINF:2.00000,`+"\n"+
1262+
``+m.prefix+`_audio1_seg1.mp4`+"\n"+
1263+
`#EXT-X-PROGRAM-DATE-TIME:2010-01-01T01:01:01Z`+"\n"+
1264+
`#EXTINF:2.00000,`+"\n"+
1265+
``+m.prefix+`_audio1_seg2.mp4`+"\n"+
1266+
`#EXT-X-PROGRAM-DATE-TIME:2010-01-01T01:01:01Z`+"\n"+
1267+
`#EXTINF:2.00000,`+"\n"+
1268+
``+m.prefix+`_audio1_seg3.mp4`+"\n",
1269+
string(byts))
1270+
1271+
byts, _, err = doRequest(m, m.prefix+"_audio1_seg1.mp4")
1272+
require.NoError(t, err)
1273+
1274+
var parts fmp4.Parts
1275+
err = parts.Unmarshal(byts)
1276+
require.NoError(t, err)
1277+
1278+
require.Equal(t, fmp4.Parts{{
1279+
SequenceNumber: 1,
1280+
Tracks: []*fmp4.PartTrack{{
1281+
ID: 1,
1282+
BaseTime: 573300,
1283+
Samples: []*fmp4.Sample{
1284+
{
1285+
Payload: []byte{1, 2},
1286+
},
1287+
{
1288+
Duration: 44100,
1289+
Payload: []byte{1, 2},
1290+
},
1291+
{
1292+
Duration: 44100,
1293+
Payload: []byte{1, 2},
1294+
},
1295+
},
1296+
}},
1297+
}}, parts)
1298+
}
1299+
12201300
func TestMuxerFMP4SequenceNumber(t *testing.T) {
12211301
m := &Muxer{
12221302
Variant: MuxerVariantLowLatency,

0 commit comments

Comments
 (0)