record: rename segmentPath into path (#2777)
This commit is contained in:
@@ -40,9 +40,9 @@ func gatherCleanerEntries(paths map[string]*conf.Path) []record.CleanerEntry {
|
||||
for _, pa := range paths {
|
||||
if pa.Record && pa.RecordDeleteAfter != 0 {
|
||||
entry := record.CleanerEntry{
|
||||
SegmentPathFormat: pa.RecordPath,
|
||||
Format: pa.RecordFormat,
|
||||
DeleteAfter: time.Duration(pa.RecordDeleteAfter),
|
||||
PathFormat: pa.RecordPath,
|
||||
Format: pa.RecordFormat,
|
||||
DeleteAfter: time.Duration(pa.RecordDeleteAfter),
|
||||
}
|
||||
out[entry] = struct{}{}
|
||||
}
|
||||
@@ -57,8 +57,8 @@ func gatherCleanerEntries(paths map[string]*conf.Path) []record.CleanerEntry {
|
||||
}
|
||||
|
||||
sort.Slice(out2, func(i, j int) bool {
|
||||
if out2[i].SegmentPathFormat != out2[j].SegmentPathFormat {
|
||||
return out2[i].SegmentPathFormat < out2[j].SegmentPathFormat
|
||||
if out2[i].PathFormat != out2[j].PathFormat {
|
||||
return out2[i].PathFormat < out2[j].PathFormat
|
||||
}
|
||||
return out2[i].DeleteAfter < out2[j].DeleteAfter
|
||||
})
|
||||
|
||||
+11
-11
@@ -897,17 +897,17 @@ func (pa *path) setNotReady() {
|
||||
|
||||
func (pa *path) startRecording() {
|
||||
pa.recordAgent = &record.Agent{
|
||||
WriteQueueSize: pa.writeQueueSize,
|
||||
SegmentPathFormat: pa.conf.RecordPath,
|
||||
Format: pa.conf.RecordFormat,
|
||||
PartDuration: time.Duration(pa.conf.RecordPartDuration),
|
||||
SegmentDuration: time.Duration(pa.conf.RecordSegmentDuration),
|
||||
PathName: pa.name,
|
||||
Stream: pa.stream,
|
||||
OnSegmentCreate: func(segmentPath string) {
|
||||
WriteQueueSize: pa.writeQueueSize,
|
||||
PathFormat: pa.conf.RecordPath,
|
||||
Format: pa.conf.RecordFormat,
|
||||
PartDuration: time.Duration(pa.conf.RecordPartDuration),
|
||||
SegmentDuration: time.Duration(pa.conf.RecordSegmentDuration),
|
||||
PathName: pa.name,
|
||||
Stream: pa.stream,
|
||||
OnSegmentCreate: func(path string) {
|
||||
if pa.conf.RunOnRecordSegmentCreate != "" {
|
||||
env := pa.externalCmdEnv()
|
||||
env["MTX_SEGMENT_PATH"] = segmentPath
|
||||
env["MTX_SEGMENT_PATH"] = path
|
||||
|
||||
pa.Log(logger.Info, "runOnRecordSegmentCreate command launched")
|
||||
externalcmd.NewCmd(
|
||||
@@ -918,10 +918,10 @@ func (pa *path) startRecording() {
|
||||
nil)
|
||||
}
|
||||
},
|
||||
OnSegmentComplete: func(segmentPath string) {
|
||||
OnSegmentComplete: func(path string) {
|
||||
if pa.conf.RunOnRecordSegmentComplete != "" {
|
||||
env := pa.externalCmdEnv()
|
||||
env["MTX_SEGMENT_PATH"] = segmentPath
|
||||
env["MTX_SEGMENT_PATH"] = path
|
||||
|
||||
pa.Log(logger.Info, "runOnRecordSegmentComplete command launched")
|
||||
externalcmd.NewCmd(
|
||||
|
||||
@@ -11,7 +11,7 @@ import (
|
||||
// Agent writes recordings to disk.
|
||||
type Agent struct {
|
||||
WriteQueueSize int
|
||||
SegmentPathFormat string
|
||||
PathFormat string
|
||||
Format conf.RecordFormat
|
||||
PartDuration time.Duration
|
||||
SegmentDuration time.Duration
|
||||
|
||||
@@ -22,25 +22,25 @@ type sample struct {
|
||||
type agentInstance struct {
|
||||
agent *Agent
|
||||
|
||||
segmentPathFormat string
|
||||
writer *asyncwriter.Writer
|
||||
format format
|
||||
pathFormat string
|
||||
writer *asyncwriter.Writer
|
||||
format format
|
||||
|
||||
terminate chan struct{}
|
||||
done chan struct{}
|
||||
}
|
||||
|
||||
func (a *agentInstance) initialize() {
|
||||
a.segmentPathFormat = a.agent.SegmentPathFormat
|
||||
a.pathFormat = a.agent.PathFormat
|
||||
|
||||
a.segmentPathFormat = strings.ReplaceAll(a.segmentPathFormat, "%path", a.agent.PathName)
|
||||
a.pathFormat = strings.ReplaceAll(a.pathFormat, "%path", a.agent.PathName)
|
||||
|
||||
switch a.agent.Format {
|
||||
case conf.RecordFormatMPEGTS:
|
||||
a.segmentPathFormat += ".ts"
|
||||
a.pathFormat += ".ts"
|
||||
|
||||
default:
|
||||
a.segmentPathFormat += ".mp4"
|
||||
a.pathFormat += ".mp4"
|
||||
}
|
||||
|
||||
a.terminate = make(chan struct{})
|
||||
|
||||
@@ -156,13 +156,13 @@ func TestAgent(t *testing.T) {
|
||||
}
|
||||
|
||||
w := &Agent{
|
||||
WriteQueueSize: 1024,
|
||||
SegmentPathFormat: recordPath,
|
||||
Format: f,
|
||||
PartDuration: 100 * time.Millisecond,
|
||||
SegmentDuration: 1 * time.Second,
|
||||
PathName: "mypath",
|
||||
Stream: stream,
|
||||
WriteQueueSize: 1024,
|
||||
PathFormat: recordPath,
|
||||
Format: f,
|
||||
PartDuration: 100 * time.Millisecond,
|
||||
SegmentDuration: 1 * time.Second,
|
||||
PathName: "mypath",
|
||||
Stream: stream,
|
||||
OnSegmentCreate: func(fpath string) {
|
||||
segCreated <- struct{}{}
|
||||
},
|
||||
@@ -266,14 +266,14 @@ func TestAgentFMP4NegativeDTS(t *testing.T) {
|
||||
recordPath := filepath.Join(dir, "%path/%Y-%m-%d_%H-%M-%S-%f")
|
||||
|
||||
w := &Agent{
|
||||
WriteQueueSize: 1024,
|
||||
SegmentPathFormat: recordPath,
|
||||
Format: conf.RecordFormatFMP4,
|
||||
PartDuration: 100 * time.Millisecond,
|
||||
SegmentDuration: 1 * time.Second,
|
||||
PathName: "mypath",
|
||||
Stream: stream,
|
||||
Parent: &nilLogger{},
|
||||
WriteQueueSize: 1024,
|
||||
PathFormat: recordPath,
|
||||
Format: conf.RecordFormatFMP4,
|
||||
PartDuration: 100 * time.Millisecond,
|
||||
SegmentDuration: 1 * time.Second,
|
||||
PathName: "mypath",
|
||||
Stream: stream,
|
||||
Parent: &nilLogger{},
|
||||
}
|
||||
w.Initialize()
|
||||
|
||||
|
||||
+11
-11
@@ -41,9 +41,9 @@ func commonPath(v string) string {
|
||||
|
||||
// CleanerEntry is a cleaner entry.
|
||||
type CleanerEntry struct {
|
||||
SegmentPathFormat string
|
||||
Format conf.RecordFormat
|
||||
DeleteAfter time.Duration
|
||||
PathFormat string
|
||||
Format conf.RecordFormat
|
||||
DeleteAfter time.Duration
|
||||
}
|
||||
|
||||
// Cleaner removes expired recording segments from disk.
|
||||
@@ -106,21 +106,21 @@ func (c *Cleaner) doRun() {
|
||||
}
|
||||
|
||||
func (c *Cleaner) doRunEntry(e *CleanerEntry) error {
|
||||
segmentPathFormat := e.SegmentPathFormat
|
||||
pathFormat := e.PathFormat
|
||||
|
||||
switch e.Format {
|
||||
case conf.RecordFormatMPEGTS:
|
||||
segmentPathFormat += ".ts"
|
||||
pathFormat += ".ts"
|
||||
|
||||
default:
|
||||
segmentPathFormat += ".mp4"
|
||||
pathFormat += ".mp4"
|
||||
}
|
||||
|
||||
// we have to convert to absolute paths
|
||||
// otherwise, commonPath and fpath inside Walk() won't have common elements
|
||||
segmentPathFormat, _ = filepath.Abs(segmentPathFormat)
|
||||
pathFormat, _ = filepath.Abs(pathFormat)
|
||||
|
||||
commonPath := commonPath(segmentPathFormat)
|
||||
commonPath := commonPath(pathFormat)
|
||||
now := timeNow()
|
||||
|
||||
filepath.Walk(commonPath, func(fpath string, info fs.FileInfo, err error) error { //nolint:errcheck
|
||||
@@ -129,10 +129,10 @@ func (c *Cleaner) doRunEntry(e *CleanerEntry) error {
|
||||
}
|
||||
|
||||
if !info.IsDir() {
|
||||
var pa segmentPath
|
||||
ok := pa.decode(segmentPathFormat, fpath)
|
||||
var pa path
|
||||
ok := pa.decode(pathFormat, fpath)
|
||||
if ok {
|
||||
if now.Sub(pa.time) > e.DeleteAfter {
|
||||
if now.Sub(time.Time(pa)) > e.DeleteAfter {
|
||||
c.Log(logger.Debug, "removing %s", fpath)
|
||||
os.Remove(fpath)
|
||||
}
|
||||
|
||||
@@ -33,9 +33,9 @@ func TestCleaner(t *testing.T) {
|
||||
|
||||
c := &Cleaner{
|
||||
Entries: []CleanerEntry{{
|
||||
SegmentPathFormat: recordPath,
|
||||
Format: conf.RecordFormatFMP4,
|
||||
DeleteAfter: 10 * time.Second,
|
||||
PathFormat: recordPath,
|
||||
Format: conf.RecordFormatFMP4,
|
||||
DeleteAfter: 10 * time.Second,
|
||||
}},
|
||||
Parent: nilLogger{},
|
||||
}
|
||||
|
||||
@@ -65,7 +65,7 @@ func newFormatFMP4Part(
|
||||
|
||||
func (p *formatFMP4Part) close() error {
|
||||
if p.s.fi == nil {
|
||||
p.s.path = segmentPath{time: p.created}.encode(p.s.f.a.segmentPathFormat)
|
||||
p.s.path = path(p.created).encode(p.s.f.a.pathFormat)
|
||||
p.s.f.a.agent.Log(logger.Debug, "creating segment %s", p.s.path)
|
||||
|
||||
err := os.MkdirAll(filepath.Dir(p.s.path), 0o755)
|
||||
|
||||
@@ -51,7 +51,7 @@ func (s *formatMPEGTSSegment) close() error {
|
||||
|
||||
func (s *formatMPEGTSSegment) Write(p []byte) (int, error) {
|
||||
if s.fi == nil {
|
||||
s.path = segmentPath{time: s.created}.encode(s.f.a.segmentPathFormat)
|
||||
s.path = path(s.created).encode(s.f.a.pathFormat)
|
||||
s.f.a.agent.Log(logger.Debug, "creating segment %s", s.path)
|
||||
|
||||
err := os.MkdirAll(filepath.Dir(s.path), 0o755)
|
||||
|
||||
@@ -21,11 +21,9 @@ func leadingZeros(v int, size int) string {
|
||||
return out2 + out
|
||||
}
|
||||
|
||||
type segmentPath struct {
|
||||
time time.Time
|
||||
}
|
||||
type path time.Time
|
||||
|
||||
func (p *segmentPath) decode(format string, v string) bool {
|
||||
func (p *path) decode(format string, v string) bool {
|
||||
re := format
|
||||
|
||||
for _, ch := range []uint8{
|
||||
@@ -143,22 +141,22 @@ func (p *segmentPath) decode(format string, v string) bool {
|
||||
}
|
||||
|
||||
if unixSec > 0 {
|
||||
p.time = time.Unix(unixSec, 0)
|
||||
*p = path(time.Unix(unixSec, 0))
|
||||
} else {
|
||||
p.time = time.Date(year, month, day, hour, minute, second, micros*1000, time.Local)
|
||||
*p = path(time.Date(year, month, day, hour, minute, second, micros*1000, time.Local))
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
func (p segmentPath) encode(format string) string {
|
||||
format = strings.ReplaceAll(format, "%Y", strconv.FormatInt(int64(p.time.Year()), 10))
|
||||
format = strings.ReplaceAll(format, "%m", leadingZeros(int(p.time.Month()), 2))
|
||||
format = strings.ReplaceAll(format, "%d", leadingZeros(p.time.Day(), 2))
|
||||
format = strings.ReplaceAll(format, "%H", leadingZeros(p.time.Hour(), 2))
|
||||
format = strings.ReplaceAll(format, "%M", leadingZeros(p.time.Minute(), 2))
|
||||
format = strings.ReplaceAll(format, "%S", leadingZeros(p.time.Second(), 2))
|
||||
format = strings.ReplaceAll(format, "%f", leadingZeros(p.time.Nanosecond()/1000, 6))
|
||||
format = strings.ReplaceAll(format, "%s", strconv.FormatInt(p.time.Unix(), 10))
|
||||
func (p path) encode(format string) string {
|
||||
format = strings.ReplaceAll(format, "%Y", strconv.FormatInt(int64(time.Time(p).Year()), 10))
|
||||
format = strings.ReplaceAll(format, "%m", leadingZeros(int(time.Time(p).Month()), 2))
|
||||
format = strings.ReplaceAll(format, "%d", leadingZeros(time.Time(p).Day(), 2))
|
||||
format = strings.ReplaceAll(format, "%H", leadingZeros(time.Time(p).Hour(), 2))
|
||||
format = strings.ReplaceAll(format, "%M", leadingZeros(time.Time(p).Minute(), 2))
|
||||
format = strings.ReplaceAll(format, "%S", leadingZeros(time.Time(p).Second(), 2))
|
||||
format = strings.ReplaceAll(format, "%f", leadingZeros(time.Time(p).Nanosecond()/1000, 6))
|
||||
format = strings.ReplaceAll(format, "%s", strconv.FormatInt(time.Time(p).Unix(), 10))
|
||||
return format
|
||||
}
|
||||
@@ -7,34 +7,30 @@ import (
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
var segmentPathCases = []struct {
|
||||
var pathCases = []struct {
|
||||
name string
|
||||
format string
|
||||
dec segmentPath
|
||||
dec path
|
||||
enc string
|
||||
}{
|
||||
{
|
||||
"standard",
|
||||
"%path/%Y-%m-%d_%H-%M-%S-%f.mp4",
|
||||
segmentPath{
|
||||
time: time.Date(2008, 11, 0o7, 11, 22, 4, 123456000, time.Local),
|
||||
},
|
||||
path(time.Date(2008, 11, 0o7, 11, 22, 4, 123456000, time.Local)),
|
||||
"%path/2008-11-07_11-22-04-123456.mp4",
|
||||
},
|
||||
{
|
||||
"unix seconds",
|
||||
"%path/%s.mp4",
|
||||
segmentPath{
|
||||
time: time.Date(2021, 12, 2, 12, 15, 23, 0, time.UTC).Local(),
|
||||
},
|
||||
path(time.Date(2021, 12, 2, 12, 15, 23, 0, time.UTC).Local()),
|
||||
"%path/1638447323.mp4",
|
||||
},
|
||||
}
|
||||
|
||||
func TestSegmentPathDecode(t *testing.T) {
|
||||
for _, ca := range segmentPathCases {
|
||||
func TestPathDecode(t *testing.T) {
|
||||
for _, ca := range pathCases {
|
||||
t.Run(ca.name, func(t *testing.T) {
|
||||
var dec segmentPath
|
||||
var dec path
|
||||
ok := dec.decode(ca.format, ca.enc)
|
||||
require.Equal(t, true, ok)
|
||||
require.Equal(t, ca.dec, dec)
|
||||
@@ -42,8 +38,8 @@ func TestSegmentPathDecode(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestSegmentPathEncode(t *testing.T) {
|
||||
for _, ca := range segmentPathCases {
|
||||
func TestPathEncode(t *testing.T) {
|
||||
for _, ca := range pathCases {
|
||||
t.Run(ca.name, func(t *testing.T) {
|
||||
require.Equal(t, ca.enc, ca.dec.encode(ca.format))
|
||||
})
|
||||
Reference in New Issue
Block a user