mediamtx/internal/recorder/recorder.go
Alessandro Ros b77df43536
fix crash when recording a stream with unsupported tracks (#3978) (#3996)
* normalize variable names

* fix file name

* fix crash when recording a stream with unsupported tracks (#3978)
2024-11-30 11:23:41 +01:00

99 lines
2.1 KiB
Go

// Package recorder contains the recorder.
package recorder
import (
"time"
"github.com/bluenviron/mediamtx/internal/conf"
"github.com/bluenviron/mediamtx/internal/logger"
"github.com/bluenviron/mediamtx/internal/stream"
)
// OnSegmentCreateFunc is the prototype of the function passed as OnSegmentCreate
type OnSegmentCreateFunc = func(path string)
// OnSegmentCompleteFunc is the prototype of the function passed as OnSegmentComplete
type OnSegmentCompleteFunc = func(path string, duration time.Duration)
// Recorder writes recordings to disk.
type Recorder struct {
PathFormat string
Format conf.RecordFormat
PartDuration time.Duration
SegmentDuration time.Duration
PathName string
Stream *stream.Stream
OnSegmentCreate OnSegmentCreateFunc
OnSegmentComplete OnSegmentCompleteFunc
Parent logger.Writer
restartPause time.Duration
currentInstance *recorderInstance
terminate chan struct{}
done chan struct{}
}
// Initialize initializes Recorder.
func (r *Recorder) Initialize() {
if r.OnSegmentCreate == nil {
r.OnSegmentCreate = func(string) {
}
}
if r.OnSegmentComplete == nil {
r.OnSegmentComplete = func(string, time.Duration) {
}
}
if r.restartPause == 0 {
r.restartPause = 2 * time.Second
}
r.terminate = make(chan struct{})
r.done = make(chan struct{})
r.currentInstance = &recorderInstance{
rec: r,
}
r.currentInstance.initialize()
go r.run()
}
// Log implements logger.Writer.
func (r *Recorder) Log(level logger.Level, format string, args ...interface{}) {
r.Parent.Log(level, "[recorder] "+format, args...)
}
// Close closes the agent.
func (r *Recorder) Close() {
r.Log(logger.Info, "recording stopped")
close(r.terminate)
<-r.done
}
func (r *Recorder) run() {
defer close(r.done)
for {
select {
case <-r.currentInstance.done:
r.currentInstance.close()
case <-r.terminate:
r.currentInstance.close()
return
}
select {
case <-time.After(r.restartPause):
case <-r.terminate:
return
}
r.currentInstance = &recorderInstance{
rec: r,
}
r.currentInstance.initialize()
}
}