mirror of
https://github.com/bluenviron/mediamtx.git
synced 2025-12-20 02:00:05 -08:00
recorder: prevent FMP4 durations from overflowing (#4711) (#5126)
Some checks are pending
code_lint / go (push) Waiting to run
code_lint / go_mod (push) Waiting to run
code_lint / docs (push) Waiting to run
code_lint / api_docs (push) Waiting to run
code_test / test_64 (push) Waiting to run
code_test / test_32 (push) Waiting to run
code_test / test_e2e (push) Waiting to run
Some checks are pending
code_lint / go (push) Waiting to run
code_lint / go_mod (push) Waiting to run
code_lint / docs (push) Waiting to run
code_lint / api_docs (push) Waiting to run
code_test / test_64 (push) Waiting to run
code_test / test_32 (push) Waiting to run
code_test / test_e2e (push) Waiting to run
The timestamp difference between two samples was put inside an unsigned integer, and, when negative, caused an overflow.
This commit is contained in:
parent
4ff80d773b
commit
c42642ac3c
2 changed files with 108 additions and 3 deletions
|
|
@ -58,7 +58,14 @@ func (t *formatFMP4Track) write(sample *sample) error {
|
|||
if sample == nil {
|
||||
return nil
|
||||
}
|
||||
sample.Duration = uint32(t.nextSample.dts - sample.dts)
|
||||
|
||||
duration := t.nextSample.dts - sample.dts
|
||||
if duration < 0 {
|
||||
t.nextSample.dts = sample.dts
|
||||
duration = 0
|
||||
}
|
||||
|
||||
sample.Duration = uint32(duration)
|
||||
|
||||
dts := timestampToDuration(sample.dts, int(t.initTrack.TimeScale))
|
||||
|
||||
|
|
|
|||
|
|
@ -311,7 +311,7 @@ func TestRecorder(t *testing.T) {
|
|||
}
|
||||
}
|
||||
|
||||
func TestRecorderFMP4NegativeDTS(t *testing.T) {
|
||||
func TestRecorderFMP4NegativeInitialDTS(t *testing.T) {
|
||||
desc := &description.Session{Medias: []*description.Media{
|
||||
{
|
||||
Type: description.MediaTypeVideo,
|
||||
|
|
@ -398,7 +398,7 @@ func TestRecorderFMP4NegativeDTS(t *testing.T) {
|
|||
for _, part := range parts {
|
||||
for _, track := range part.Tracks {
|
||||
if track.ID == 2 {
|
||||
require.Less(t, track.BaseTime, uint64(1*90000))
|
||||
require.Equal(t, uint64(6615), track.BaseTime)
|
||||
found = true
|
||||
}
|
||||
}
|
||||
|
|
@ -407,6 +407,104 @@ func TestRecorderFMP4NegativeDTS(t *testing.T) {
|
|||
require.True(t, found)
|
||||
}
|
||||
|
||||
func TestRecorderFMP4NegativeDTSDiff(t *testing.T) {
|
||||
desc := &description.Session{Medias: []*description.Media{
|
||||
{
|
||||
Type: description.MediaTypeVideo,
|
||||
Formats: []rtspformat.Format{&rtspformat.MPEG4Audio{
|
||||
PayloadTyp: 96,
|
||||
Config: &mpeg4audio.AudioSpecificConfig{
|
||||
Type: 2,
|
||||
SampleRate: 44100,
|
||||
ChannelCount: 2,
|
||||
},
|
||||
SizeLength: 13,
|
||||
IndexLength: 3,
|
||||
IndexDeltaLength: 3,
|
||||
}},
|
||||
},
|
||||
}}
|
||||
|
||||
strm := &stream.Stream{
|
||||
WriteQueueSize: 512,
|
||||
RTPMaxPayloadSize: 1450,
|
||||
Desc: desc,
|
||||
GenerateRTPPackets: true,
|
||||
Parent: test.NilLogger,
|
||||
}
|
||||
err := strm.Initialize()
|
||||
require.NoError(t, err)
|
||||
defer strm.Close()
|
||||
|
||||
dir, err := os.MkdirTemp("", "mediamtx-agent")
|
||||
require.NoError(t, err)
|
||||
defer os.RemoveAll(dir)
|
||||
|
||||
recordPath := filepath.Join(dir, "%path/%Y-%m-%d_%H-%M-%S-%f")
|
||||
|
||||
w := &Recorder{
|
||||
PathFormat: recordPath,
|
||||
Format: conf.RecordFormatFMP4,
|
||||
PartDuration: 100 * time.Millisecond,
|
||||
MaxPartSize: 50 * 1024 * 1024,
|
||||
SegmentDuration: 2 * time.Second,
|
||||
PathName: "mypath",
|
||||
Stream: strm,
|
||||
Parent: test.NilLogger,
|
||||
}
|
||||
w.Initialize()
|
||||
|
||||
strm.WriteUnit(desc.Medias[0], desc.Medias[0].Formats[0], &unit.Unit{
|
||||
PTS: 44100,
|
||||
NTP: time.Date(2008, 5, 20, 22, 15, 25, 0, time.UTC),
|
||||
Payload: unit.PayloadMPEG4Audio{{1, 2}},
|
||||
})
|
||||
|
||||
strm.WriteUnit(desc.Medias[0], desc.Medias[0].Formats[0], &unit.Unit{
|
||||
PTS: 3 * 44100,
|
||||
NTP: time.Date(2008, 5, 20, 22, 15, 25, 0, time.UTC),
|
||||
Payload: unit.PayloadMPEG4Audio{{1, 2}},
|
||||
})
|
||||
|
||||
strm.WriteUnit(desc.Medias[0], desc.Medias[0].Formats[0], &unit.Unit{
|
||||
PTS: 2 * 44100,
|
||||
NTP: time.Date(2008, 5, 20, 22, 15, 25, 0, time.UTC),
|
||||
Payload: unit.PayloadMPEG4Audio{{1, 2}},
|
||||
})
|
||||
|
||||
strm.WriteUnit(desc.Medias[0], desc.Medias[0].Formats[0], &unit.Unit{
|
||||
PTS: 4 * 44100,
|
||||
NTP: time.Date(2008, 5, 20, 22, 15, 25, 0, time.UTC),
|
||||
Payload: unit.PayloadMPEG4Audio{{1, 2}},
|
||||
})
|
||||
|
||||
time.Sleep(50 * time.Millisecond)
|
||||
|
||||
w.Close()
|
||||
|
||||
byts, err := os.ReadFile(filepath.Join(dir, "mypath", "2008-05-20_22-15-25-000000.mp4"))
|
||||
require.NoError(t, err)
|
||||
|
||||
var parts fmp4.Parts
|
||||
err = parts.Unmarshal(byts)
|
||||
require.NoError(t, err)
|
||||
|
||||
require.Equal(t, fmp4.Parts{{
|
||||
Tracks: []*fmp4.PartTrack{{
|
||||
ID: 1,
|
||||
Samples: []*fmp4.Sample{
|
||||
{
|
||||
Payload: []byte{1, 2},
|
||||
},
|
||||
{
|
||||
Duration: 44100,
|
||||
Payload: []byte{1, 2},
|
||||
},
|
||||
},
|
||||
}},
|
||||
}}, parts)
|
||||
}
|
||||
|
||||
func TestRecorderSkipTracksPartial(t *testing.T) {
|
||||
for _, ca := range []string{"fmp4", "mpegts"} {
|
||||
t.Run(ca, func(t *testing.T) {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue