mirror of
https://github.com/aler9/rtsp-simple-server
synced 2025-09-27 03:56:15 +08:00
103 lines
1.9 KiB
Go
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()
|
|
}
|