mirror of
https://github.com/bluenviron/mediamtx.git
synced 2026-01-09 11:52:02 -08:00
This commit is contained in:
parent
e6f861ee95
commit
dc453620fe
3 changed files with 123 additions and 9 deletions
|
|
@ -31,6 +31,14 @@ type Agent struct {
|
|||
|
||||
// Initialize initializes Agent.
|
||||
func (w *Agent) Initialize() {
|
||||
if w.OnSegmentCreate == nil {
|
||||
w.OnSegmentCreate = func(string) {
|
||||
}
|
||||
}
|
||||
if w.OnSegmentComplete == nil {
|
||||
w.OnSegmentComplete = func(string) {
|
||||
}
|
||||
}
|
||||
if w.restartPause == 0 {
|
||||
w.restartPause = 2 * time.Second
|
||||
}
|
||||
|
|
|
|||
|
|
@ -10,6 +10,7 @@ import (
|
|||
"github.com/bluenviron/gortsplib/v4/pkg/format"
|
||||
"github.com/bluenviron/mediacommon/pkg/codecs/h265"
|
||||
"github.com/bluenviron/mediacommon/pkg/codecs/mpeg4audio"
|
||||
"github.com/bluenviron/mediacommon/pkg/formats/fmp4"
|
||||
"github.com/bluenviron/mediamtx/internal/logger"
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
|
|
@ -211,11 +212,6 @@ func TestAgent(t *testing.T) {
|
|||
|
||||
w.Close()
|
||||
|
||||
for i := 0; i < 2; i++ {
|
||||
<-segCreated
|
||||
<-segDone
|
||||
}
|
||||
|
||||
_, err = os.Stat(filepath.Join(dir, "mypath", "2010-05-20_22-15-25-000000."+ext))
|
||||
require.NoError(t, err)
|
||||
|
||||
|
|
@ -224,3 +220,110 @@ func TestAgent(t *testing.T) {
|
|||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestAgentFMP4NegativeDTS(t *testing.T) {
|
||||
desc := &description.Session{Medias: []*description.Media{
|
||||
{
|
||||
Type: description.MediaTypeVideo,
|
||||
Formats: []format.Format{&format.H264{
|
||||
PayloadTyp: 96,
|
||||
PacketizationMode: 1,
|
||||
}},
|
||||
},
|
||||
{
|
||||
Type: description.MediaTypeAudio,
|
||||
Formats: []format.Format{&format.MPEG4Audio{
|
||||
PayloadTyp: 96,
|
||||
Config: &mpeg4audio.Config{
|
||||
Type: 2,
|
||||
SampleRate: 44100,
|
||||
ChannelCount: 2,
|
||||
},
|
||||
SizeLength: 13,
|
||||
IndexLength: 3,
|
||||
IndexDeltaLength: 3,
|
||||
}},
|
||||
},
|
||||
}}
|
||||
|
||||
timeNow = func() time.Time {
|
||||
return time.Date(2008, 0o5, 20, 22, 15, 25, 0, time.UTC)
|
||||
}
|
||||
|
||||
stream, err := stream.New(
|
||||
1460,
|
||||
desc,
|
||||
true,
|
||||
&nilLogger{},
|
||||
)
|
||||
require.NoError(t, err)
|
||||
defer stream.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 := &Agent{
|
||||
WriteQueueSize: 1024,
|
||||
RecordPath: recordPath,
|
||||
Format: conf.RecordFormatFMP4,
|
||||
PartDuration: 100 * time.Millisecond,
|
||||
SegmentDuration: 1 * time.Second,
|
||||
PathName: "mypath",
|
||||
Stream: stream,
|
||||
Parent: &nilLogger{},
|
||||
}
|
||||
w.Initialize()
|
||||
|
||||
for i := 0; i < 3; i++ {
|
||||
stream.WriteUnit(desc.Medias[0], desc.Medias[0].Formats[0], &unit.H264{
|
||||
Base: unit.Base{
|
||||
PTS: -50*time.Millisecond + (time.Duration(i) * 200 * time.Millisecond),
|
||||
},
|
||||
AU: [][]byte{
|
||||
{ // SPS
|
||||
0x67, 0x42, 0xc0, 0x28, 0xd9, 0x00, 0x78, 0x02,
|
||||
0x27, 0xe5, 0x84, 0x00, 0x00, 0x03, 0x00, 0x04,
|
||||
0x00, 0x00, 0x03, 0x00, 0xf0, 0x3c, 0x60, 0xc9, 0x20,
|
||||
},
|
||||
{ // PPS
|
||||
0x08, 0x06, 0x07, 0x08,
|
||||
},
|
||||
{5}, // IDR
|
||||
},
|
||||
})
|
||||
|
||||
stream.WriteUnit(desc.Medias[1], desc.Medias[1].Formats[0], &unit.MPEG4Audio{
|
||||
Base: unit.Base{
|
||||
PTS: -100*time.Millisecond + (time.Duration(i) * 200 * time.Millisecond),
|
||||
},
|
||||
AUs: [][]byte{{1, 2, 3, 4}},
|
||||
})
|
||||
}
|
||||
|
||||
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)
|
||||
|
||||
found := false
|
||||
|
||||
for _, part := range parts {
|
||||
for _, track := range part.Tracks {
|
||||
if track.ID == 2 {
|
||||
require.Less(t, track.BaseTime, uint64(1*90000))
|
||||
found = true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
require.Equal(t, true, found)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -27,16 +27,19 @@ func (t *recFormatFMP4Track) record(sample *sample) error {
|
|||
t.f.hasVideo = true
|
||||
}
|
||||
|
||||
if t.f.currentSegment == nil {
|
||||
t.f.currentSegment = newRecFormatFMP4Segment(t.f, sample.dts)
|
||||
}
|
||||
|
||||
sample, t.nextSample = t.nextSample, sample
|
||||
if sample == nil {
|
||||
return nil
|
||||
}
|
||||
sample.Duration = uint32(durationGoToMp4(t.nextSample.dts-sample.dts, t.initTrack.TimeScale))
|
||||
|
||||
if t.f.currentSegment == nil {
|
||||
t.f.currentSegment = newRecFormatFMP4Segment(t.f, sample.dts)
|
||||
// BaseTime is negative, this is not supported by fMP4. Reject the sample silently.
|
||||
} else if (sample.dts - t.f.currentSegment.startDTS) < 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
err := t.f.currentSegment.record(t, sample)
|
||||
if err != nil {
|
||||
return err
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue