mirror of
https://github.com/bluenviron/mediamtx
synced 2025-01-21 06:31:00 +00:00
log track ID when skipping tracks (#3798)
This commit is contained in:
parent
077040a234
commit
658848f8c8
@ -141,7 +141,6 @@ func setupAudioTrack(
|
||||
stream *stream.Stream,
|
||||
writer *asyncwriter.Writer,
|
||||
muxer *gohlslib.Muxer,
|
||||
l logger.Writer,
|
||||
) format.Format {
|
||||
var audioFormatOpus *format.Opus
|
||||
audioMedia := stream.Desc().FindFormat(&audioFormatOpus)
|
||||
@ -174,9 +173,7 @@ func setupAudioTrack(
|
||||
|
||||
if audioFormatMPEG4Audio != nil {
|
||||
co := audioFormatMPEG4Audio.GetConfig()
|
||||
if co == nil {
|
||||
l.Log(logger.Warn, "skipping MPEG-4 audio track: tracks without explicit configuration are not supported")
|
||||
} else {
|
||||
if co != nil {
|
||||
stream.AddReader(writer, audioMedia, audioFormatMPEG4Audio, func(u unit.Unit) error {
|
||||
tunit := u.(*unit.MPEG4Audio)
|
||||
|
||||
@ -224,18 +221,19 @@ func FromStream(
|
||||
stream,
|
||||
writer,
|
||||
muxer,
|
||||
l,
|
||||
)
|
||||
|
||||
if videoFormat == nil && audioFormat == nil {
|
||||
return ErrNoSupportedCodecs
|
||||
}
|
||||
|
||||
n := 1
|
||||
for _, media := range stream.Desc().Medias {
|
||||
for _, forma := range media.Formats {
|
||||
if forma != videoFormat && forma != audioFormat {
|
||||
l.Log(logger.Warn, "skipping track with codec %s", forma.Codec())
|
||||
l.Log(logger.Warn, "skipping track %d (%s)", n, forma.Codec())
|
||||
}
|
||||
n++
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -68,9 +68,9 @@ func TestFromStreamSkipUnsupportedTracks(t *testing.T) {
|
||||
require.Equal(t, logger.Warn, l)
|
||||
switch n {
|
||||
case 0:
|
||||
require.Equal(t, "skipping track with codec VP8", fmt.Sprintf(format, args...))
|
||||
require.Equal(t, "skipping track 2 (VP8)", fmt.Sprintf(format, args...))
|
||||
case 1:
|
||||
require.Equal(t, "skipping track with codec MPEG-1/2 Audio", fmt.Sprintf(format, args...))
|
||||
require.Equal(t, "skipping track 3 (MPEG-1/2 Audio)", fmt.Sprintf(format, args...))
|
||||
}
|
||||
n++
|
||||
})
|
||||
|
@ -33,13 +33,14 @@ func FromStream(
|
||||
) error {
|
||||
var w *mcmpegts.Writer
|
||||
var tracks []*mcmpegts.Track
|
||||
var skippedFormats []format.Format
|
||||
setuppedFormats := make(map[format.Format]struct{})
|
||||
|
||||
addTrack := func(codec mcmpegts.Codec) *mcmpegts.Track {
|
||||
addTrack := func(forma format.Format, codec mcmpegts.Codec) *mcmpegts.Track {
|
||||
track := &mcmpegts.Track{
|
||||
Codec: codec,
|
||||
}
|
||||
tracks = append(tracks, track)
|
||||
setuppedFormats[forma] = struct{}{}
|
||||
return track
|
||||
}
|
||||
|
||||
@ -47,7 +48,7 @@ func FromStream(
|
||||
for _, forma := range medi.Formats {
|
||||
switch forma := forma.(type) {
|
||||
case *format.H265: //nolint:dupl
|
||||
track := addTrack(&mcmpegts.CodecH265{})
|
||||
track := addTrack(forma, &mcmpegts.CodecH265{})
|
||||
|
||||
var dtsExtractor *h265.DTSExtractor
|
||||
|
||||
@ -80,7 +81,7 @@ func FromStream(
|
||||
})
|
||||
|
||||
case *format.H264: //nolint:dupl
|
||||
track := addTrack(&mcmpegts.CodecH264{})
|
||||
track := addTrack(forma, &mcmpegts.CodecH264{})
|
||||
|
||||
var dtsExtractor *h264.DTSExtractor
|
||||
|
||||
@ -113,7 +114,7 @@ func FromStream(
|
||||
})
|
||||
|
||||
case *format.MPEG4Video:
|
||||
track := addTrack(&mcmpegts.CodecMPEG4Video{})
|
||||
track := addTrack(forma, &mcmpegts.CodecMPEG4Video{})
|
||||
|
||||
firstReceived := false
|
||||
var lastPTS time.Duration
|
||||
@ -140,7 +141,7 @@ func FromStream(
|
||||
})
|
||||
|
||||
case *format.MPEG1Video:
|
||||
track := addTrack(&mcmpegts.CodecMPEG1Video{})
|
||||
track := addTrack(forma, &mcmpegts.CodecMPEG1Video{})
|
||||
|
||||
firstReceived := false
|
||||
var lastPTS time.Duration
|
||||
@ -167,7 +168,7 @@ func FromStream(
|
||||
})
|
||||
|
||||
case *format.Opus:
|
||||
track := addTrack(&mcmpegts.CodecOpus{
|
||||
track := addTrack(forma, &mcmpegts.CodecOpus{
|
||||
ChannelCount: forma.ChannelCount,
|
||||
})
|
||||
|
||||
@ -191,7 +192,7 @@ func FromStream(
|
||||
return fmt.Errorf("MPEG-4 audio tracks without explicit configuration are not supported")
|
||||
}
|
||||
|
||||
track := addTrack(&mcmpegts.CodecMPEG4Audio{
|
||||
track := addTrack(forma, &mcmpegts.CodecMPEG4Audio{
|
||||
Config: *co,
|
||||
})
|
||||
|
||||
@ -210,7 +211,7 @@ func FromStream(
|
||||
})
|
||||
|
||||
case *format.MPEG1Audio:
|
||||
track := addTrack(&mcmpegts.CodecMPEG1Audio{})
|
||||
track := addTrack(forma, &mcmpegts.CodecMPEG1Audio{})
|
||||
|
||||
stream.AddReader(writer, medi, forma, func(u unit.Unit) error {
|
||||
tunit := u.(*unit.MPEG1Audio)
|
||||
@ -227,7 +228,7 @@ func FromStream(
|
||||
})
|
||||
|
||||
case *format.AC3:
|
||||
track := addTrack(&mcmpegts.CodecAC3{})
|
||||
track := addTrack(forma, &mcmpegts.CodecAC3{})
|
||||
|
||||
sampleRate := time.Duration(forma.SampleRate)
|
||||
|
||||
@ -249,9 +250,6 @@ func FromStream(
|
||||
}
|
||||
return bw.Flush()
|
||||
})
|
||||
|
||||
default:
|
||||
skippedFormats = append(skippedFormats, forma)
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -260,8 +258,14 @@ func FromStream(
|
||||
return errNoSupportedCodecs
|
||||
}
|
||||
|
||||
for _, forma := range skippedFormats {
|
||||
l.Log(logger.Warn, "skipping track with codec %s", forma.Codec())
|
||||
n := 1
|
||||
for _, medi := range stream.Desc().Medias {
|
||||
for _, forma := range medi.Formats {
|
||||
if _, ok := setuppedFormats[forma]; !ok {
|
||||
l.Log(logger.Warn, "skipping track %d (%s)", n, forma.Codec())
|
||||
}
|
||||
n++
|
||||
}
|
||||
}
|
||||
|
||||
w = mcmpegts.NewWriter(bw, tracks)
|
||||
|
@ -60,7 +60,7 @@ func TestFromStreamSkipUnsupportedTracks(t *testing.T) {
|
||||
l := test.Logger(func(l logger.Level, format string, args ...interface{}) {
|
||||
require.Equal(t, logger.Warn, l)
|
||||
if n == 0 {
|
||||
require.Equal(t, "skipping track with codec VP8", fmt.Sprintf(format, args...))
|
||||
require.Equal(t, "skipping track 2 (VP8)", fmt.Sprintf(format, args...))
|
||||
}
|
||||
n++
|
||||
})
|
||||
|
@ -208,7 +208,7 @@ func ToStream(
|
||||
}
|
||||
|
||||
for _, id := range unsupportedTracks {
|
||||
l.Log(logger.Warn, "skipping track %d due to unsupported codec", id)
|
||||
l.Log(logger.Warn, "skipping track %d (unsupported codec)", id)
|
||||
}
|
||||
|
||||
return medias, nil
|
||||
|
@ -67,7 +67,7 @@ func TestToStreamSkipUnsupportedTracks(t *testing.T) {
|
||||
l := test.Logger(func(l logger.Level, format string, args ...interface{}) {
|
||||
require.Equal(t, logger.Warn, l)
|
||||
if n == 0 {
|
||||
require.Equal(t, "skipping track 1 due to unsupported codec", fmt.Sprintf(format, args...))
|
||||
require.Equal(t, "skipping track 1 (unsupported codec)", fmt.Sprintf(format, args...))
|
||||
}
|
||||
n++
|
||||
})
|
||||
|
@ -202,11 +202,13 @@ func FromStream(
|
||||
return err
|
||||
}
|
||||
|
||||
n := 1
|
||||
for _, media := range stream.Desc().Medias {
|
||||
for _, forma := range media.Formats {
|
||||
if forma != videoFormat && forma != audioFormat {
|
||||
l.Log(logger.Warn, "skipping track with codec %s", forma.Codec())
|
||||
l.Log(logger.Warn, "skipping track %d (%s)", n, forma.Codec())
|
||||
}
|
||||
n++
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -68,9 +68,9 @@ func TestFromStreamSkipUnsupportedTracks(t *testing.T) {
|
||||
require.Equal(t, logger.Warn, l)
|
||||
switch n {
|
||||
case 0:
|
||||
require.Equal(t, "skipping track with codec VP8", fmt.Sprintf(format, args...))
|
||||
require.Equal(t, "skipping track 1 (VP8)", fmt.Sprintf(format, args...))
|
||||
case 1:
|
||||
require.Equal(t, "skipping track with codec H264", fmt.Sprintf(format, args...))
|
||||
require.Equal(t, "skipping track 3 (H264)", fmt.Sprintf(format, args...))
|
||||
}
|
||||
n++
|
||||
})
|
||||
|
@ -537,11 +537,13 @@ func FromStream(
|
||||
return errNoSupportedCodecsFrom
|
||||
}
|
||||
|
||||
n := 1
|
||||
for _, media := range stream.Desc().Medias {
|
||||
for _, forma := range media.Formats {
|
||||
if forma != videoFormat && forma != audioFormat {
|
||||
l.Log(logger.Warn, "skipping track with codec %s", forma.Codec())
|
||||
l.Log(logger.Warn, "skipping track %d (%s)", n, forma.Codec())
|
||||
}
|
||||
n++
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -60,7 +60,7 @@ func TestFromStreamSkipUnsupportedTracks(t *testing.T) {
|
||||
l := test.Logger(func(l logger.Level, format string, args ...interface{}) {
|
||||
require.Equal(t, logger.Warn, l)
|
||||
if n == 0 {
|
||||
require.Equal(t, "skipping track with codec H265", fmt.Sprintf(format, args...))
|
||||
require.Equal(t, "skipping track 2 (H265)", fmt.Sprintf(format, args...))
|
||||
}
|
||||
n++
|
||||
})
|
||||
|
@ -110,8 +110,8 @@ type formatFMP4 struct {
|
||||
|
||||
func (f *formatFMP4) initialize() {
|
||||
nextID := 1
|
||||
var formats []rtspformat.Format
|
||||
var skippedFormats []rtspformat.Format
|
||||
var setuppedFormats []rtspformat.Format
|
||||
setuppedFormatsMap := make(map[rtspformat.Format]struct{})
|
||||
|
||||
addTrack := func(format rtspformat.Format, codec fmp4.Codec) *formatFMP4Track {
|
||||
initTrack := &fmp4.InitTrack{
|
||||
@ -127,7 +127,8 @@ func (f *formatFMP4) initialize() {
|
||||
}
|
||||
|
||||
f.tracks = append(f.tracks, track)
|
||||
formats = append(formats, format)
|
||||
setuppedFormats = append(setuppedFormats, format)
|
||||
setuppedFormatsMap[format] = struct{}{}
|
||||
return track
|
||||
}
|
||||
|
||||
@ -597,9 +598,7 @@ func (f *formatFMP4) initialize() {
|
||||
|
||||
case *rtspformat.MPEG4Audio:
|
||||
co := forma.GetConfig()
|
||||
if co == nil {
|
||||
f.ai.Log(logger.Warn, "skipping MPEG-4 audio track: tracks without explicit configuration are not supported")
|
||||
} else {
|
||||
if co != nil {
|
||||
codec := &fmp4.CodecMPEG4Audio{
|
||||
Config: *co,
|
||||
}
|
||||
@ -804,24 +803,27 @@ func (f *formatFMP4) initialize() {
|
||||
ntp: tunit.NTP,
|
||||
})
|
||||
})
|
||||
|
||||
default:
|
||||
skippedFormats = append(skippedFormats, forma)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if len(formats) == 0 {
|
||||
if len(setuppedFormats) == 0 {
|
||||
f.ai.Log(logger.Warn, "no supported tracks found, skipping recording")
|
||||
return
|
||||
}
|
||||
|
||||
for _, forma := range skippedFormats {
|
||||
f.ai.Log(logger.Warn, "skipping track with codec %s", forma.Codec())
|
||||
n := 1
|
||||
for _, medi := range f.ai.agent.Stream.Desc().Medias {
|
||||
for _, forma := range medi.Formats {
|
||||
if _, ok := setuppedFormatsMap[forma]; !ok {
|
||||
f.ai.Log(logger.Warn, "skipping track %d (%s)", n, forma.Codec())
|
||||
}
|
||||
n++
|
||||
}
|
||||
}
|
||||
|
||||
f.ai.Log(logger.Info, "recording %s",
|
||||
defs.FormatsInfo(formats))
|
||||
defs.FormatsInfo(setuppedFormats))
|
||||
}
|
||||
|
||||
func (f *formatFMP4) close() {
|
||||
|
@ -51,8 +51,8 @@ type formatMPEGTS struct {
|
||||
|
||||
func (f *formatMPEGTS) initialize() {
|
||||
var tracks []*mpegts.Track
|
||||
var formats []rtspformat.Format
|
||||
var skippedFormats []rtspformat.Format
|
||||
var setuppedFormats []rtspformat.Format
|
||||
setuppedFormatsMap := make(map[rtspformat.Format]struct{})
|
||||
|
||||
addTrack := func(format rtspformat.Format, codec mpegts.Codec) *mpegts.Track {
|
||||
track := &mpegts.Track{
|
||||
@ -60,7 +60,8 @@ func (f *formatMPEGTS) initialize() {
|
||||
}
|
||||
|
||||
tracks = append(tracks, track)
|
||||
formats = append(formats, format)
|
||||
setuppedFormats = append(setuppedFormats, format)
|
||||
setuppedFormatsMap[format] = struct{}{}
|
||||
return track
|
||||
}
|
||||
|
||||
@ -303,20 +304,23 @@ func (f *formatMPEGTS) initialize() {
|
||||
},
|
||||
)
|
||||
})
|
||||
|
||||
default:
|
||||
skippedFormats = append(skippedFormats, forma)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if len(tracks) == 0 {
|
||||
if len(setuppedFormats) == 0 {
|
||||
f.ai.Log(logger.Warn, "no supported tracks found, skipping recording")
|
||||
return
|
||||
}
|
||||
|
||||
for _, forma := range skippedFormats {
|
||||
f.ai.Log(logger.Warn, "skipping track with codec %s", forma.Codec())
|
||||
n := 1
|
||||
for _, medi := range f.ai.agent.Stream.Desc().Medias {
|
||||
for _, forma := range medi.Formats {
|
||||
if _, ok := setuppedFormatsMap[forma]; !ok {
|
||||
f.ai.Log(logger.Warn, "skipping track %d (%s)", n, forma.Codec())
|
||||
}
|
||||
n++
|
||||
}
|
||||
}
|
||||
|
||||
f.dw = &dynamicWriter{}
|
||||
@ -324,7 +328,7 @@ func (f *formatMPEGTS) initialize() {
|
||||
f.mw = mpegts.NewWriter(f.bw, tracks)
|
||||
|
||||
f.ai.Log(logger.Info, "recording %s",
|
||||
defs.FormatsInfo(formats))
|
||||
defs.FormatsInfo(setuppedFormats))
|
||||
}
|
||||
|
||||
func (f *formatMPEGTS) close() {
|
||||
|
@ -1,6 +1,7 @@
|
||||
package recorder
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"testing"
|
||||
@ -14,6 +15,7 @@ import (
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
"github.com/bluenviron/mediamtx/internal/conf"
|
||||
"github.com/bluenviron/mediamtx/internal/logger"
|
||||
"github.com/bluenviron/mediamtx/internal/stream"
|
||||
"github.com/bluenviron/mediamtx/internal/test"
|
||||
"github.com/bluenviron/mediamtx/internal/unit"
|
||||
@ -407,3 +409,67 @@ func TestRecorderFMP4NegativeDTS(t *testing.T) {
|
||||
|
||||
require.Equal(t, true, found)
|
||||
}
|
||||
|
||||
func TestRecorderSkipTracks(t *testing.T) {
|
||||
for _, ca := range []string{"fmp4", "mpegts"} {
|
||||
t.Run(ca, func(t *testing.T) {
|
||||
desc := &description.Session{Medias: []*description.Media{
|
||||
{
|
||||
Type: description.MediaTypeVideo,
|
||||
Formats: []rtspformat.Format{&rtspformat.H264{}},
|
||||
},
|
||||
{
|
||||
Type: description.MediaTypeVideo,
|
||||
Formats: []rtspformat.Format{&rtspformat.VP8{}},
|
||||
},
|
||||
}}
|
||||
|
||||
stream, err := stream.New(
|
||||
1460,
|
||||
desc,
|
||||
true,
|
||||
test.NilLogger,
|
||||
)
|
||||
require.NoError(t, err)
|
||||
defer stream.Close()
|
||||
|
||||
dir, err := os.MkdirTemp("", "mediamtx-agent")
|
||||
require.NoError(t, err)
|
||||
defer os.RemoveAll(dir)
|
||||
|
||||
recordPath := filepath.Join(dir, "%path/%Y-%m-%d_%H-%M-%S-%f")
|
||||
|
||||
n := 0
|
||||
|
||||
l := test.Logger(func(l logger.Level, format string, args ...interface{}) {
|
||||
if n == 0 {
|
||||
require.Equal(t, logger.Warn, l)
|
||||
require.Equal(t, "[recorder] skipping track 2 (VP8)", fmt.Sprintf(format, args...))
|
||||
}
|
||||
n++
|
||||
})
|
||||
|
||||
var fo conf.RecordFormat
|
||||
if ca == "fmp4" {
|
||||
fo = conf.RecordFormatFMP4
|
||||
} else {
|
||||
fo = conf.RecordFormatMPEGTS
|
||||
}
|
||||
|
||||
w := &Recorder{
|
||||
WriteQueueSize: 1024,
|
||||
PathFormat: recordPath,
|
||||
Format: fo,
|
||||
PartDuration: 100 * time.Millisecond,
|
||||
SegmentDuration: 1 * time.Second,
|
||||
PathName: "mypath",
|
||||
Stream: stream,
|
||||
Parent: l,
|
||||
}
|
||||
w.Initialize()
|
||||
defer w.Close()
|
||||
|
||||
require.Equal(t, 2, n)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user