package mpegts import ( "bytes" "context" "fmt" "testing" "github.com/asticode/go-astits" "github.com/bluenviron/gortsplib/v5/pkg/description" "github.com/bluenviron/gortsplib/v5/pkg/format" "github.com/bluenviron/mediacommon/v2/pkg/codecs/mpeg4audio" "github.com/bluenviron/mediamtx/internal/logger" "github.com/bluenviron/mediamtx/internal/test" "github.com/stretchr/testify/require" ) func TestToStream(t *testing.T) { for _, ca := range []string{ "h265", "h264", "mpeg-4 audio latm", } { t.Run(ca, func(t *testing.T) { var buf bytes.Buffer mux := astits.NewMuxer(context.Background(), &buf) switch ca { case "h265": err := mux.AddElementaryStream(astits.PMTElementaryStream{ ElementaryPID: 122, StreamType: astits.StreamTypeH265Video, }) require.NoError(t, err) mux.SetPCRPID(122) _, err = mux.WriteTables() require.NoError(t, err) case "h264": err := mux.AddElementaryStream(astits.PMTElementaryStream{ ElementaryPID: 122, StreamType: astits.StreamTypeH264Video, }) require.NoError(t, err) mux.SetPCRPID(122) _, err = mux.WriteTables() require.NoError(t, err) case "mpeg-4 audio latm": err := mux.AddElementaryStream(astits.PMTElementaryStream{ ElementaryPID: 122, StreamType: astits.StreamTypeAACLATMAudio, }) require.NoError(t, err) mux.SetPCRPID(122) enc1, err := mpeg4audio.AudioMuxElement{ MuxConfigPresent: true, StreamMuxConfig: &mpeg4audio.StreamMuxConfig{ Programs: []*mpeg4audio.StreamMuxConfigProgram{{ Layers: []*mpeg4audio.StreamMuxConfigLayer{{ AudioSpecificConfig: &mpeg4audio.AudioSpecificConfig{ Type: 2, SampleRate: 48000, ChannelCount: 2, }, LatmBufferFullness: 255, }}, }}, }, Payloads: [][][][]byte{{{{1, 2, 3, 4}}}}, }.Marshal() require.NoError(t, err) enc2, err := mpeg4audio.AudioSyncStream{ AudioMuxElements: [][]byte{enc1}, }.Marshal() require.NoError(t, err) _, err = mux.WriteData(&astits.MuxerData{ PID: 122, PES: &astits.PESData{ Header: &astits.PESHeader{ OptionalHeader: &astits.PESOptionalHeader{ MarkerBits: 2, PTSDTSIndicator: astits.PTSDTSIndicatorOnlyPTS, PTS: &astits.ClockReference{Base: 90000}, }, StreamID: 192, }, Data: enc2, }, }) require.NoError(t, err) } r := &EnhancedReader{R: &buf} err := r.Initialize() require.NoError(t, err) desc, err := ToStream(r, nil, nil) require.NoError(t, err) switch ca { case "h265": require.Equal(t, []*description.Media{{ Type: description.MediaTypeVideo, Formats: []format.Format{&format.H265{ PayloadTyp: 96, }}, }}, desc) case "h264": require.Equal(t, []*description.Media{{ Type: description.MediaTypeVideo, Formats: []format.Format{&format.H264{ PayloadTyp: 96, PacketizationMode: 1, }}, }}, desc) case "mpeg-4 audio latm": require.Equal(t, []*description.Media{{ Type: description.MediaTypeAudio, Formats: []format.Format{&format.MPEG4AudioLATM{ PayloadTyp: 96, ProfileLevelID: 30, StreamMuxConfig: &mpeg4audio.StreamMuxConfig{ Programs: []*mpeg4audio.StreamMuxConfigProgram{{ Layers: []*mpeg4audio.StreamMuxConfigLayer{{ AudioSpecificConfig: &mpeg4audio.AudioSpecificConfig{ Type: 2, SampleRate: 48000, ChannelCount: 2, }, LatmBufferFullness: 255, }}, }}, }, }}, }}, desc) } }) } } func TestToStreamNoSupportedCodecs(t *testing.T) { var buf bytes.Buffer mux := astits.NewMuxer(context.Background(), &buf) err := mux.AddElementaryStream(astits.PMTElementaryStream{ ElementaryPID: 122, StreamType: astits.StreamTypeDTSAudio, }) require.NoError(t, err) mux.SetPCRPID(122) _, err = mux.WriteTables() require.NoError(t, err) r := &EnhancedReader{R: &buf} err = r.Initialize() require.NoError(t, err) l := test.Logger(func(logger.Level, string, ...interface{}) { t.Error("should not happen") }) _, err = ToStream(r, nil, l) require.Equal(t, errNoSupportedCodecs, err) } func TestToStreamSkipUnsupportedTracks(t *testing.T) { var buf bytes.Buffer mux := astits.NewMuxer(context.Background(), &buf) err := mux.AddElementaryStream(astits.PMTElementaryStream{ ElementaryPID: 122, StreamType: astits.StreamTypeDTSAudio, }) require.NoError(t, err) err = mux.AddElementaryStream(astits.PMTElementaryStream{ ElementaryPID: 123, StreamType: astits.StreamTypeH264Video, }) require.NoError(t, err) mux.SetPCRPID(122) _, err = mux.WriteTables() require.NoError(t, err) r := &EnhancedReader{R: &buf} err = r.Initialize() require.NoError(t, err) n := 0 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 (unsupported codec)", fmt.Sprintf(format, args...)) } n++ }) _, err = ToStream(r, nil, l) require.NoError(t, err) }