Files
rtsp-simple-server/internal/recorder/recorder_instance.go
Alessandro Ros 9ddcbf5c97 recorder: limit maximum part size (#4674) (#4760)
this prevents RAM exhaustion.
2025-07-20 19:16:33 +02:00

103 lines
1.9 KiB
Go

package recorder
import (
"strings"
"time"
"github.com/bluenviron/mediacommon/v2/pkg/formats/fmp4"
"github.com/bluenviron/mediamtx/internal/conf"
"github.com/bluenviron/mediamtx/internal/logger"
"github.com/bluenviron/mediamtx/internal/recordstore"
"github.com/bluenviron/mediamtx/internal/stream"
)
type sample struct {
*fmp4.Sample
dts int64
ntp time.Time
}
type recorderInstance struct {
pathFormat string
format conf.RecordFormat
partDuration time.Duration
maxPartSize conf.StringSize
segmentDuration time.Duration
pathName string
stream *stream.Stream
onSegmentCreate OnSegmentCreateFunc
onSegmentComplete OnSegmentCompleteFunc
parent logger.Writer
pathFormat2 string
format2 format
skip bool
terminate chan struct{}
done chan struct{}
}
// Log implements logger.Writer.
func (ri *recorderInstance) Log(level logger.Level, format string, args ...interface{}) {
ri.parent.Log(level, format, args...)
}
func (ri *recorderInstance) initialize() {
ri.pathFormat2 = ri.pathFormat
ri.pathFormat2 = recordstore.PathAddExtension(
strings.ReplaceAll(ri.pathFormat2, "%path", ri.pathName),
ri.format,
)
ri.terminate = make(chan struct{})
ri.done = make(chan struct{})
switch ri.format {
case conf.RecordFormatMPEGTS:
ri.format2 = &formatMPEGTS{
ri: ri,
}
ok := ri.format2.initialize()
ri.skip = !ok
default:
ri.format2 = &formatFMP4{
ri: ri,
}
ok := ri.format2.initialize()
ri.skip = !ok
}
if !ri.skip {
ri.stream.StartReader(ri)
}
go ri.run()
}
func (ri *recorderInstance) close() {
close(ri.terminate)
<-ri.done
}
func (ri *recorderInstance) run() {
defer close(ri.done)
if !ri.skip {
select {
case err := <-ri.stream.ReaderError(ri):
ri.Log(logger.Error, err.Error())
case <-ri.terminate:
}
ri.stream.RemoveReader(ri)
} else {
<-ri.terminate
}
ri.format2.close()
}