Browse Source

record: rename segmentPath into path (#2777)

pull/2782/head
Alessandro Ros 1 year ago committed by GitHub
parent
commit
20123fd5b9
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 10
      internal/core/core.go
  2. 22
      internal/core/path.go
  3. 2
      internal/record/agent.go
  4. 14
      internal/record/agent_instance.go
  5. 30
      internal/record/agent_test.go
  6. 22
      internal/record/cleaner.go
  7. 6
      internal/record/cleaner_test.go
  8. 2
      internal/record/format_fmp4_part.go
  9. 2
      internal/record/format_mpegts_segment.go
  10. 28
      internal/record/path.go
  11. 22
      internal/record/path_test.go

10
internal/core/core.go

@ -40,9 +40,9 @@ func gatherCleanerEntries(paths map[string]*conf.Path) []record.CleanerEntry { @@ -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 { @@ -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
})

22
internal/core/path.go

@ -897,17 +897,17 @@ func (pa *path) setNotReady() { @@ -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() { @@ -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(

2
internal/record/agent.go

@ -11,7 +11,7 @@ import ( @@ -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

14
internal/record/agent_instance.go

@ -22,25 +22,25 @@ type sample struct { @@ -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{})

30
internal/record/agent_test.go

@ -156,13 +156,13 @@ func TestAgent(t *testing.T) { @@ -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) { @@ -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()

22
internal/record/cleaner.go

@ -41,9 +41,9 @@ func commonPath(v string) string { @@ -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() { @@ -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 { @@ -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)
}

6
internal/record/cleaner_test.go

@ -33,9 +33,9 @@ func TestCleaner(t *testing.T) { @@ -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{},
}

2
internal/record/format_fmp4_part.go

@ -65,7 +65,7 @@ func newFormatFMP4Part( @@ -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)

2
internal/record/format_mpegts_segment.go

@ -51,7 +51,7 @@ func (s *formatMPEGTSSegment) close() error { @@ -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)

28
internal/record/segment_path.go → internal/record/path.go

@ -21,11 +21,9 @@ func leadingZeros(v int, size int) string { @@ -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 { @@ -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
}

22
internal/record/segment_path_test.go → internal/record/path_test.go

@ -7,34 +7,30 @@ import ( @@ -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) { @@ -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))
})
Loading…
Cancel
Save