build(deps): bump github.com/bluenviron/gortmplib from 0.1.2 to 0.2.0 (#5300)
Some checks failed
code_lint / go (push) Has been cancelled
code_lint / go_mod (push) Has been cancelled
code_lint / docs (push) Has been cancelled
code_lint / api_docs (push) Has been cancelled
code_test / test_64 (push) Has been cancelled
code_test / test_32 (push) Has been cancelled
code_test / test_e2e (push) Has been cancelled

Bumps [github.com/bluenviron/gortmplib](https://github.com/bluenviron/gortmplib) from 0.1.2 to 0.2.0.
- [Commits](https://github.com/bluenviron/gortmplib/compare/v0.1.2...v0.2.0)

---
updated-dependencies:
- dependency-name: github.com/bluenviron/gortmplib
  dependency-version: 0.2.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
This commit is contained in:
dependabot[bot] 2025-12-28 17:29:27 +01:00 committed by GitHub
parent 174618f3f3
commit 62effa79ef
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
10 changed files with 646 additions and 532 deletions

2
go.mod
View file

@ -11,7 +11,7 @@ require (
github.com/alecthomas/kong v1.13.0
github.com/asticode/go-astits v1.14.0
github.com/bluenviron/gohlslib/v2 v2.2.4
github.com/bluenviron/gortmplib v0.1.2
github.com/bluenviron/gortmplib v0.2.0
github.com/bluenviron/gortsplib/v5 v5.2.2
github.com/bluenviron/mediacommon/v2 v2.6.0
github.com/datarhei/gosrt v0.9.0

4
go.sum
View file

@ -37,8 +37,8 @@ github.com/benburkert/openpgp v0.0.0-20160410205803-c2471f86866c h1:8XZeJrs4+ZYh
github.com/benburkert/openpgp v0.0.0-20160410205803-c2471f86866c/go.mod h1:x1vxHcL/9AVzuk5HOloOEPrtJY0MaalYr78afXZ+pWI=
github.com/bluenviron/gohlslib/v2 v2.2.4 h1:5F/Ud2VuJrrLYCDV0Ham947UIIrd801/GyoCsPYMqiw=
github.com/bluenviron/gohlslib/v2 v2.2.4/go.mod h1:5J8Ry4xraLs6W0B2gVS0IqhCzcq+CDDJIisfkpoHyxM=
github.com/bluenviron/gortmplib v0.1.2 h1:bJ+5pUxKnHjEoKPbNs7lDLyYy5R9Z1lISJ1n54DsjWE=
github.com/bluenviron/gortmplib v0.1.2/go.mod h1:oVOWgfs7wsZNoKYLttyqLar7a71ZTohO1JOVXkNxtHg=
github.com/bluenviron/gortmplib v0.2.0 h1:j15eeHrgVh6Avg9oAx+r4w0HugTqrIqLBsYnhs3D1dE=
github.com/bluenviron/gortmplib v0.2.0/go.mod h1:yzobxBF8zusF2nKbEOF69zIIL429j0kaCWc/euNdvO4=
github.com/bluenviron/gortsplib/v5 v5.2.2 h1:5q2viB8PGxWOSXNhVvj8buyr1wighLbHqRZ0U7MLM3o=
github.com/bluenviron/gortsplib/v5 v5.2.2/go.mod h1:xkVBOAnR4fzaerPN650CBb7N+zUUsj7PI2HiY1TP7Co=
github.com/bluenviron/mediacommon/v2 v2.6.0 h1:wZAPXwv7V78Cx2x7cToYIHOLToHl6APcvHbdQT+gOkg=

View file

@ -15,9 +15,9 @@ import (
"time"
"github.com/bluenviron/gortmplib"
rtmpcodecs "github.com/bluenviron/gortmplib/pkg/codecs"
"github.com/bluenviron/gortsplib/v5"
"github.com/bluenviron/gortsplib/v5/pkg/description"
"github.com/bluenviron/gortsplib/v5/pkg/format"
"github.com/bluenviron/mediacommon/v2/pkg/formats/mpegts"
tscodecs "github.com/bluenviron/mediacommon/v2/pkg/formats/mpegts/codecs"
srt "github.com/datarhei/gosrt"
@ -441,14 +441,21 @@ func TestAPIProtocolListGet(t *testing.T) {
require.NoError(t, err)
defer conn.Close()
track := &gortmplib.Track{
Codec: &rtmpcodecs.H264{
SPS: test.FormatH264.SPS,
PPS: test.FormatH264.PPS,
},
}
w := &gortmplib.Writer{
Conn: conn,
Tracks: []format.Format{test.FormatH264},
Tracks: []*gortmplib.Track{track},
}
err = w.Initialize()
require.NoError(t, err)
err = w.WriteH264(test.FormatH264, 2*time.Second, 2*time.Second, [][]byte{{5, 2, 3, 4}})
err = w.WriteH264(track, 2*time.Second, 2*time.Second, [][]byte{{5, 2, 3, 4}})
require.NoError(t, err)
time.Sleep(500 * time.Millisecond)
@ -1038,14 +1045,21 @@ func TestAPIProtocolKick(t *testing.T) {
require.NoError(t, err)
defer conn.Close()
track := &gortmplib.Track{
Codec: &rtmpcodecs.H264{
SPS: test.FormatH264.SPS,
PPS: test.FormatH264.PPS,
},
}
w := &gortmplib.Writer{
Conn: conn,
Tracks: []format.Format{test.FormatH264},
Tracks: []*gortmplib.Track{track},
}
err = w.Initialize()
require.NoError(t, err)
err = w.WriteH264(test.FormatH264, 2*time.Second, 2*time.Second, [][]byte{{5, 2, 3, 4}})
err = w.WriteH264(track, 2*time.Second, 2*time.Second, [][]byte{{5, 2, 3, 4}})
require.NoError(t, err)
case "webrtc":

View file

@ -13,9 +13,9 @@ import (
"time"
"github.com/bluenviron/gortmplib"
rtmpcodecs "github.com/bluenviron/gortmplib/pkg/codecs"
"github.com/bluenviron/gortsplib/v5"
"github.com/bluenviron/gortsplib/v5/pkg/description"
"github.com/bluenviron/gortsplib/v5/pkg/format"
"github.com/bluenviron/mediacommon/v2/pkg/formats/mpegts"
tscodecs "github.com/bluenviron/mediacommon/v2/pkg/formats/mpegts/codecs"
srt "github.com/datarhei/gosrt"
@ -218,14 +218,21 @@ webrtc_sessions_rtcp_packets_sent 0
require.NoError(t, err2)
defer conn.Close()
track := &gortmplib.Track{
Codec: &rtmpcodecs.H264{
SPS: test.FormatH264.SPS,
PPS: test.FormatH264.PPS,
},
}
w := &gortmplib.Writer{
Conn: conn,
Tracks: []format.Format{test.FormatH264},
Tracks: []*gortmplib.Track{track},
}
err2 = w.Initialize()
require.NoError(t, err2)
err2 = w.WriteH264(test.FormatH264, 2*time.Second, 2*time.Second, [][]byte{{5, 2, 3, 4}})
err2 = w.WriteH264(track, 2*time.Second, 2*time.Second, [][]byte{{5, 2, 3, 4}})
require.NoError(t, err2)
<-terminate
@ -246,14 +253,21 @@ webrtc_sessions_rtcp_packets_sent 0
require.NoError(t, err2)
defer conn.Close()
track := &gortmplib.Track{
Codec: &rtmpcodecs.H264{
SPS: test.FormatH264.SPS,
PPS: test.FormatH264.PPS,
},
}
w := &gortmplib.Writer{
Conn: conn,
Tracks: []format.Format{test.FormatH264},
Tracks: []*gortmplib.Track{track},
}
err2 = w.Initialize()
require.NoError(t, err2)
err2 = w.WriteH264(test.FormatH264, 2*time.Second, 2*time.Second, [][]byte{{5, 2, 3, 4}})
err2 = w.WriteH264(track, 2*time.Second, 2*time.Second, [][]byte{{5, 2, 3, 4}})
require.NoError(t, err2)
<-terminate

View file

@ -8,6 +8,7 @@ import (
"time"
"github.com/bluenviron/gortmplib"
"github.com/bluenviron/gortmplib/pkg/codecs"
"github.com/bluenviron/gortmplib/pkg/message"
"github.com/bluenviron/gortsplib/v5/pkg/description"
"github.com/bluenviron/gortsplib/v5/pkg/format"
@ -44,7 +45,7 @@ func FromStream(
nconn net.Conn,
writeTimeout time.Duration,
) error {
var tracks []format.Format
var tracks []*gortmplib.Track
var w *gortmplib.Writer
for _, media := range desc.Medias {
@ -52,6 +53,11 @@ func FromStream(
switch forma := forma.(type) {
case *format.AV1:
if slices.Contains(conn.FourCcList, any(fourCCToString(message.FourCCAV1))) {
track := &gortmplib.Track{
Codec: &codecs.AV1{},
}
tracks = append(tracks, track)
r.OnData(
media,
forma,
@ -62,16 +68,19 @@ func FromStream(
nconn.SetWriteDeadline(time.Now().Add(writeTimeout))
return (*w).WriteAV1(
forma,
track,
timestampToDuration(u.PTS, forma.ClockRate()),
u.Payload.(unit.PayloadAV1))
})
tracks = append(tracks, forma)
}
case *format.VP9:
if slices.Contains(conn.FourCcList, any(fourCCToString(message.FourCCVP9))) {
track := &gortmplib.Track{
Codec: &codecs.VP9{},
}
tracks = append(tracks, track)
r.OnData(
media,
forma,
@ -82,16 +91,24 @@ func FromStream(
nconn.SetWriteDeadline(time.Now().Add(writeTimeout))
return (*w).WriteVP9(
forma,
track,
timestampToDuration(u.PTS, forma.ClockRate()),
u.Payload.(unit.PayloadVP9))
})
tracks = append(tracks, forma)
}
case *format.H265:
if slices.Contains(conn.FourCcList, any(fourCCToString(message.FourCCHEVC))) {
vps, sps, pps := forma.SafeParams()
track := &gortmplib.Track{
Codec: &codecs.H265{
VPS: vps,
SPS: sps,
PPS: pps,
},
}
tracks = append(tracks, track)
var videoDTSExtractor *h265.DTSExtractor
r.OnData(
@ -117,16 +134,23 @@ func FromStream(
nconn.SetWriteDeadline(time.Now().Add(writeTimeout))
return (*w).WriteH265(
forma,
track,
timestampToDuration(u.PTS, forma.ClockRate()),
timestampToDuration(dts, forma.ClockRate()),
u.Payload.(unit.PayloadH265))
})
tracks = append(tracks, forma)
}
case *format.H264:
sps, pps := forma.SafeParams()
track := &gortmplib.Track{
Codec: &codecs.H264{
SPS: sps,
PPS: pps,
},
}
tracks = append(tracks, track)
var videoDTSExtractor *h264.DTSExtractor
r.OnData(
@ -170,16 +194,21 @@ func FromStream(
nconn.SetWriteDeadline(time.Now().Add(writeTimeout))
return (*w).WriteH264(
forma,
track,
timestampToDuration(u.PTS, forma.ClockRate()),
timestampToDuration(dts, forma.ClockRate()),
u.Payload.(unit.PayloadH264))
})
tracks = append(tracks, forma)
case *format.Opus:
if slices.Contains(conn.FourCcList, any(fourCCToString(message.FourCCOpus))) {
track := &gortmplib.Track{
Codec: &codecs.Opus{
ChannelCount: forma.ChannelCount,
},
}
tracks = append(tracks, track)
r.OnData(
media,
forma,
@ -193,7 +222,7 @@ func FromStream(
for _, pkt := range u.Payload.(unit.PayloadOpus) {
nconn.SetWriteDeadline(time.Now().Add(writeTimeout))
err := (*w).WriteOpus(
forma,
track,
timestampToDuration(pts, forma.ClockRate()),
pkt,
)
@ -206,11 +235,16 @@ func FromStream(
return nil
})
tracks = append(tracks, forma)
}
case *format.MPEG4Audio:
track := &gortmplib.Track{
Codec: &codecs.MPEG4Audio{
Config: forma.Config,
},
}
tracks = append(tracks, track)
r.OnData(
media,
forma,
@ -224,7 +258,7 @@ func FromStream(
nconn.SetWriteDeadline(time.Now().Add(writeTimeout))
err := (*w).WriteMPEG4Audio(
forma,
track,
timestampToDuration(pts, forma.ClockRate()),
au,
)
@ -236,10 +270,15 @@ func FromStream(
return nil
})
tracks = append(tracks, forma)
case *format.MPEG4AudioLATM:
if !forma.CPresent {
track := &gortmplib.Track{
Codec: &codecs.MPEG4Audio{
Config: forma.StreamMuxConfig.Programs[0].Layers[0].AudioSpecificConfig,
},
}
tracks = append(tracks, track)
r.OnData(
media,
forma,
@ -257,16 +296,19 @@ func FromStream(
nconn.SetWriteDeadline(time.Now().Add(writeTimeout))
return (*w).WriteMPEG4Audio(
forma,
track,
timestampToDuration(u.PTS, forma.ClockRate()),
ame.Payloads[0][0][0],
)
})
tracks = append(tracks, forma)
}
case *format.MPEG1Audio:
track := &gortmplib.Track{
Codec: &codecs.MPEG1Audio{},
}
tracks = append(tracks, track)
r.OnData(
media,
forma,
@ -286,7 +328,7 @@ func FromStream(
nconn.SetWriteDeadline(time.Now().Add(writeTimeout))
err = (*w).WriteMPEG1Audio(
forma,
track,
timestampToDuration(pts, forma.ClockRate()),
frame)
if err != nil {
@ -300,10 +342,16 @@ func FromStream(
return nil
})
tracks = append(tracks, forma)
case *format.AC3:
if slices.Contains(conn.FourCcList, any(fourCCToString(message.FourCCAC3))) {
track := &gortmplib.Track{
Codec: &codecs.AC3{
SampleRate: forma.SampleRate,
ChannelCount: forma.ChannelCount,
},
}
tracks = append(tracks, track)
r.OnData(
media,
forma,
@ -317,7 +365,7 @@ func FromStream(
nconn.SetWriteDeadline(time.Now().Add(writeTimeout))
err := (*w).WriteAC3(
forma,
track,
timestampToDuration(pts, forma.ClockRate()),
frame)
if err != nil {
@ -327,12 +375,19 @@ func FromStream(
return nil
})
tracks = append(tracks, forma)
}
case *format.G711:
if forma.SampleRate == 8000 {
track := &gortmplib.Track{
Codec: &codecs.G711{
MULaw: forma.MULaw,
SampleRate: forma.SampleRate,
ChannelCount: forma.ChannelCount,
},
}
tracks = append(tracks, track)
r.OnData(
media,
forma,
@ -343,13 +398,11 @@ func FromStream(
nconn.SetWriteDeadline(time.Now().Add(writeTimeout))
return (*w).WriteG711(
forma,
track,
timestampToDuration(u.PTS, forma.ClockRate()),
u.Payload.(unit.PayloadG711),
)
})
tracks = append(tracks, forma)
}
case *format.LPCM:
@ -358,6 +411,15 @@ func FromStream(
forma.SampleRate == 11025 ||
forma.SampleRate == 22050 ||
forma.SampleRate == 44100) {
track := &gortmplib.Track{
Codec: &codecs.LPCM{
BitDepth: forma.BitDepth,
SampleRate: forma.SampleRate,
ChannelCount: forma.ChannelCount,
},
}
tracks = append(tracks, track)
r.OnData(
media,
forma,
@ -368,13 +430,11 @@ func FromStream(
nconn.SetWriteDeadline(time.Now().Add(writeTimeout))
return (*w).WriteLPCM(
forma,
track,
timestampToDuration(u.PTS, forma.ClockRate()),
u.Payload.(unit.PayloadLPCM),
)
})
tracks = append(tracks, forma)
}
}
}
@ -393,10 +453,12 @@ func FromStream(
return err
}
setuppedFormats := r.Formats()
n := 1
for _, media := range desc.Medias {
for _, forma := range media.Formats {
if !slices.Contains(tracks, forma) {
if !slices.Contains(setuppedFormats, forma) {
r.Parent.Log(logger.Warn, "skipping track %d (%s)", n, forma.Codec())
}
n++

View file

@ -9,6 +9,7 @@ import (
"time"
"github.com/bluenviron/gortmplib"
"github.com/bluenviron/gortmplib/pkg/codecs"
"github.com/bluenviron/gortsplib/v5/pkg/description"
"github.com/bluenviron/gortsplib/v5/pkg/format"
"github.com/bluenviron/mediamtx/internal/codecprocessor"
@ -20,405 +21,49 @@ import (
)
func TestFromStream(t *testing.T) {
for _, ca := range []string{
"h264 + aac",
"av1",
"vp9",
"h265",
"h264",
"opus",
"aac",
"mp3",
"ac-3",
"pcma",
"pcmu",
"lpcm",
"h265 + h264 + vp9 + av1 + opus + aac",
} {
t.Run(ca, func(t *testing.T) {
var medias []*description.Media
h265VPS := []byte{
0x40, 0x01, 0x0c, 0x01, 0xff, 0xff, 0x01, 0x60,
0x00, 0x00, 0x03, 0x00, 0x90, 0x00, 0x00, 0x03,
0x00, 0x00, 0x03, 0x00, 0x78, 0xba, 0x02, 0x40,
}
h265SPS := []byte{
0x42, 0x01, 0x01, 0x01, 0x60, 0x00, 0x00, 0x03,
0x00, 0x90, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03,
0x00, 0x78, 0xa0, 0x03, 0xc0, 0x80, 0x11, 0x07,
0xcb, 0x96, 0xe9, 0x29, 0x30, 0xbc, 0x05, 0xa0,
0x20, 0x00, 0x00, 0x03, 0x00, 0x20, 0x00, 0x00,
0x03, 0x03, 0xc1,
}
h265PPS := []byte{
0x44, 0x01, 0xc0, 0x73, 0xc1, 0x89,
}
switch ca {
case "h264 + aac":
medias = []*description.Media{
{
Formats: []format.Format{test.FormatH264},
},
{
Formats: []format.Format{test.FormatMPEG4Audio},
},
}
case "av1":
medias = []*description.Media{
{
Formats: []format.Format{&format.AV1{
PayloadTyp: 96,
}},
},
}
case "vp9":
medias = []*description.Media{
{
Formats: []format.Format{&format.VP9{
PayloadTyp: 96,
}},
},
}
case "h265":
medias = []*description.Media{
{
Formats: []format.Format{
&format.H265{
PayloadTyp: 96,
VPS: []byte{
0x40, 0x01, 0x0c, 0x01, 0xff, 0xff, 0x01, 0x60,
0x00, 0x00, 0x03, 0x00, 0x90, 0x00, 0x00, 0x03,
0x00, 0x00, 0x03, 0x00, 0x78, 0xba, 0x02, 0x40,
},
SPS: []byte{
0x42, 0x01, 0x01, 0x01, 0x60, 0x00, 0x00, 0x03,
0x00, 0x90, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03,
0x00, 0x78, 0xa0, 0x03, 0xc0, 0x80, 0x11, 0x07,
0xcb, 0x96, 0xe9, 0x29, 0x30, 0xbc, 0x05, 0xa0,
0x20, 0x00, 0x00, 0x03, 0x00, 0x20, 0x00, 0x00,
0x03, 0x03, 0xc1,
},
PPS: []byte{
0x44, 0x01, 0xc0, 0x73, 0xc1, 0x89,
},
},
},
},
}
case "h264":
medias = []*description.Media{
{
Formats: []format.Format{test.FormatH264},
},
}
case "opus":
medias = []*description.Media{
{
Formats: []format.Format{&format.Opus{
PayloadTyp: 96,
ChannelCount: 2,
}},
},
}
case "aac":
medias = []*description.Media{
{
Formats: []format.Format{test.FormatMPEG4Audio},
},
}
case "mp3":
medias = []*description.Media{
{
Formats: []format.Format{&format.MPEG1Audio{}},
},
}
case "ac-3":
medias = []*description.Media{
{
Formats: []format.Format{&format.AC3{
SampleRate: 44100,
ChannelCount: 2,
}},
},
}
case "pcma":
medias = []*description.Media{
{
Formats: []format.Format{&format.G711{
MULaw: false,
SampleRate: 8000,
ChannelCount: 1,
}},
},
}
case "pcmu":
medias = []*description.Media{
{
Formats: []format.Format{&format.G711{
MULaw: true,
SampleRate: 8000,
ChannelCount: 1,
}},
},
}
case "lpcm":
medias = []*description.Media{
{
Formats: []format.Format{&format.LPCM{
BitDepth: 16,
SampleRate: 44100,
ChannelCount: 2,
}},
},
}
case "h265 + h264 + vp9 + av1 + opus + aac":
medias = []*description.Media{
{
Formats: []format.Format{&format.H265{}},
},
{
Formats: []format.Format{&format.H264{}},
},
{
Formats: []format.Format{&format.VP9{}},
},
{
Formats: []format.Format{&format.AV1{}},
},
{
Formats: []format.Format{&format.Opus{
PayloadTyp: 96,
ChannelCount: 2,
}},
},
{
Formats: []format.Format{&format.MPEG4Audio{
PayloadTyp: 96,
Config: test.FormatMPEG4Audio.Config,
SizeLength: 13,
IndexLength: 3,
IndexDeltaLength: 3,
}},
},
}
}
strm := &stream.Stream{
WriteQueueSize: 512,
RTPMaxPayloadSize: 1450,
Desc: &description.Session{Medias: medias},
GenerateRTPPackets: true,
Parent: test.NilLogger,
}
err := strm.Initialize()
require.NoError(t, err)
ln, err := net.Listen("tcp", "127.0.0.1:9121")
require.NoError(t, err)
defer ln.Close()
done := make(chan struct{})
go func() {
u, err2 := url.Parse("rtmp://127.0.0.1:9121/stream")
require.NoError(t, err2)
c := &gortmplib.Client{
URL: u,
}
err2 = c.Initialize(context.Background())
require.NoError(t, err2)
r := &gortmplib.Reader{
Conn: c,
}
err2 = r.Initialize()
require.NoError(t, err2)
switch ca {
case "h264 + aac":
require.Equal(t, []format.Format{
&format.H264{
SPS: test.FormatH264.SPS,
PPS: test.FormatH264.PPS,
PacketizationMode: 1,
PayloadTyp: 96,
},
&format.MPEG4Audio{
PayloadTyp: 96,
Config: test.FormatMPEG4Audio.Config,
SizeLength: 13,
IndexLength: 3,
IndexDeltaLength: 3,
},
}, r.Tracks())
case "av1":
require.Equal(t, []format.Format{
&format.AV1{
PayloadTyp: 96,
},
}, r.Tracks())
case "vp9":
require.Equal(t, []format.Format{
&format.VP9{
PayloadTyp: 96,
},
}, r.Tracks())
case "h265":
require.Equal(t, []format.Format{
&format.H265{
VPS: []byte{
0x40, 0x01, 0x0c, 0x01, 0xff, 0xff, 0x01, 0x60,
0x00, 0x00, 0x03, 0x00, 0x90, 0x00, 0x00, 0x03,
0x00, 0x00, 0x03, 0x00, 0x78, 0xba, 0x02, 0x40,
},
SPS: []byte{
0x42, 0x01, 0x01, 0x01, 0x60, 0x00, 0x00, 0x03,
0x00, 0x90, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03,
0x00, 0x78, 0xa0, 0x03, 0xc0, 0x80, 0x11, 0x07,
0xcb, 0x96, 0xe9, 0x29, 0x30, 0xbc, 0x05, 0xa0,
0x20, 0x00, 0x00, 0x03, 0x00, 0x20, 0x00, 0x00,
0x03, 0x03, 0xc1,
},
PPS: []byte{
0x44, 0x01, 0xc0, 0x73, 0xc1, 0x89,
},
PayloadTyp: 96,
},
}, r.Tracks())
case "h264":
require.Equal(t, []format.Format{
&format.H264{
SPS: test.FormatH264.SPS,
PPS: test.FormatH264.PPS,
PacketizationMode: 1,
PayloadTyp: 96,
},
}, r.Tracks())
case "opus":
require.Equal(t, []format.Format{
&format.Opus{
PayloadTyp: 96,
ChannelCount: 2,
},
}, r.Tracks())
case "aac":
require.Equal(t, []format.Format{
&format.MPEG4Audio{
PayloadTyp: 96,
Config: test.FormatMPEG4Audio.Config,
SizeLength: 13,
IndexLength: 3,
IndexDeltaLength: 3,
},
}, r.Tracks())
case "mp3":
require.Equal(t, []format.Format{
&format.MPEG1Audio{},
}, r.Tracks())
case "ac-3":
require.Equal(t, []format.Format{
&format.AC3{
PayloadTyp: 96,
SampleRate: 48000,
ChannelCount: 1,
},
}, r.Tracks())
case "pcma":
require.Equal(t, []format.Format{
&format.G711{
PayloadTyp: 8,
MULaw: false,
ChannelCount: 1,
SampleRate: 8000,
},
}, r.Tracks())
case "pcmu":
require.Equal(t, []format.Format{
&format.G711{
MULaw: true,
ChannelCount: 1,
SampleRate: 8000,
},
}, r.Tracks())
case "lpcm":
require.Equal(t, []format.Format{
&format.LPCM{
PayloadTyp: 96,
BitDepth: 16,
SampleRate: 44100,
ChannelCount: 2,
},
}, r.Tracks())
case "h265 + h264 + vp9 + av1 + opus + aac":
require.Equal(t, []format.Format{
&format.H265{
PayloadTyp: 96,
VPS: codecprocessor.H265DefaultVPS,
SPS: codecprocessor.H265DefaultSPS,
PPS: codecprocessor.H265DefaultPPS,
},
&format.H264{
PayloadTyp: 96,
PacketizationMode: 1,
SPS: codecprocessor.H264DefaultSPS,
PPS: codecprocessor.H264DefaultPPS,
},
&format.VP9{
PayloadTyp: 96,
},
&format.AV1{
PayloadTyp: 96,
},
&format.Opus{
PayloadTyp: 96,
ChannelCount: 2,
},
&format.MPEG4Audio{
PayloadTyp: 96,
Config: test.FormatMPEG4Audio.Config,
SizeLength: 13,
IndexLength: 3,
IndexDeltaLength: 3,
},
}, r.Tracks())
}
close(done)
}()
nconn, err := ln.Accept()
require.NoError(t, err)
defer nconn.Close()
conn := &gortmplib.ServerConn{
RW: nconn,
}
err = conn.Initialize()
require.NoError(t, err)
err = conn.Accept()
require.NoError(t, err)
r := &stream.Reader{Parent: test.NilLogger}
err = FromStream(strm.Desc, r, conn, nconn, 10*time.Second)
require.NoError(t, err)
strm.AddReader(r)
defer strm.RemoveReader(r)
switch ca {
case "h264 + aac":
cases := []struct {
name string
medias []*description.Media
expectedTracks []*gortmplib.Track
writeUnits func([]*description.Media, *stream.Stream)
}{
{
name: "h264 + aac",
medias: []*description.Media{
{
Formats: []format.Format{test.FormatH264},
},
{
Formats: []format.Format{test.FormatMPEG4Audio},
},
},
expectedTracks: []*gortmplib.Track{
{Codec: &codecs.H264{
SPS: test.FormatH264.SPS,
PPS: test.FormatH264.PPS,
}},
{Codec: &codecs.MPEG4Audio{
Config: test.FormatMPEG4Audio.Config,
}},
},
writeUnits: func(medias []*description.Media, strm *stream.Stream) {
strm.WriteUnit(medias[0], medias[0].Formats[0], &unit.Unit{
PTS: 0,
Payload: unit.PayloadH264{
@ -432,8 +77,21 @@ func TestFromStream(t *testing.T) {
{3, 4},
},
})
case "av1":
},
},
{
name: "av1",
medias: []*description.Media{
{
Formats: []format.Format{&format.AV1{
PayloadTyp: 96,
}},
},
},
expectedTracks: []*gortmplib.Track{
{Codec: &codecs.AV1{}},
},
writeUnits: func(medias []*description.Media, strm *stream.Stream) {
for i := range 2 {
strm.WriteUnit(medias[0], medias[0].Formats[0], &unit.Unit{
PTS: 90000 * 2 * int64(i),
@ -443,16 +101,51 @@ func TestFromStream(t *testing.T) {
}},
})
}
case "vp9":
},
},
{
name: "vp9",
medias: []*description.Media{
{
Formats: []format.Format{&format.VP9{
PayloadTyp: 96,
}},
},
},
expectedTracks: []*gortmplib.Track{
{Codec: &codecs.VP9{}},
},
writeUnits: func(medias []*description.Media, strm *stream.Stream) {
for i := range 2 {
strm.WriteUnit(medias[0], medias[0].Formats[0], &unit.Unit{
PTS: 90000 * 2 * int64(i),
Payload: unit.PayloadVP9{1, 2},
})
}
case "h265":
},
},
{
name: "h265",
medias: []*description.Media{
{
Formats: []format.Format{
&format.H265{
PayloadTyp: 96,
VPS: h265VPS,
SPS: h265SPS,
PPS: h265PPS,
},
},
},
},
expectedTracks: []*gortmplib.Track{
{Codec: &codecs.H265{
VPS: h265VPS,
SPS: h265SPS,
PPS: h265PPS,
}},
},
writeUnits: func(medias []*description.Media, strm *stream.Stream) {
for i := range 2 {
strm.WriteUnit(medias[0], medias[0].Formats[0], &unit.Unit{
PTS: 90000 * 2 * int64(i),
@ -462,8 +155,22 @@ func TestFromStream(t *testing.T) {
}},
})
}
case "h264":
},
},
{
name: "h264",
medias: []*description.Media{
{
Formats: []format.Format{test.FormatH264},
},
},
expectedTracks: []*gortmplib.Track{
{Codec: &codecs.H264{
SPS: test.FormatH264.SPS,
PPS: test.FormatH264.PPS,
}},
},
writeUnits: func(medias []*description.Media, strm *stream.Stream) {
for i := range 2 {
strm.WriteUnit(medias[0], medias[0].Formats[0], &unit.Unit{
PTS: 90000 * 2 * int64(i),
@ -472,8 +179,24 @@ func TestFromStream(t *testing.T) {
},
})
}
case "opus":
},
},
{
name: "opus",
medias: []*description.Media{
{
Formats: []format.Format{&format.Opus{
PayloadTyp: 96,
ChannelCount: 2,
}},
},
},
expectedTracks: []*gortmplib.Track{
{Codec: &codecs.Opus{
ChannelCount: 2,
}},
},
writeUnits: func(medias []*description.Media, strm *stream.Stream) {
for i := range 2 {
strm.WriteUnit(medias[0], medias[0].Formats[0], &unit.Unit{
PTS: 90000 * 5 * int64(i),
@ -482,8 +205,21 @@ func TestFromStream(t *testing.T) {
},
})
}
case "aac":
},
},
{
name: "aac",
medias: []*description.Media{
{
Formats: []format.Format{test.FormatMPEG4Audio},
},
},
expectedTracks: []*gortmplib.Track{
{Codec: &codecs.MPEG4Audio{
Config: test.FormatMPEG4Audio.Config,
}},
},
writeUnits: func(medias []*description.Media, strm *stream.Stream) {
for i := range 2 {
strm.WriteUnit(medias[0], medias[0].Formats[0], &unit.Unit{
PTS: 90000 * 5 * int64(i),
@ -492,8 +228,19 @@ func TestFromStream(t *testing.T) {
},
})
}
case "mp3":
},
},
{
name: "mp3",
medias: []*description.Media{
{
Formats: []format.Format{&format.MPEG1Audio{}},
},
},
expectedTracks: []*gortmplib.Track{
{Codec: &codecs.MPEG1Audio{}},
},
writeUnits: func(medias []*description.Media, strm *stream.Stream) {
for i := range 2 {
strm.WriteUnit(medias[0], medias[0].Formats[0], &unit.Unit{
PTS: 90000 * 5 * int64(i),
@ -504,8 +251,25 @@ func TestFromStream(t *testing.T) {
},
})
}
case "ac-3":
},
},
{
name: "ac-3",
medias: []*description.Media{
{
Formats: []format.Format{&format.AC3{
SampleRate: 44100,
ChannelCount: 2,
}},
},
},
expectedTracks: []*gortmplib.Track{
{Codec: &codecs.AC3{
SampleRate: 48000,
ChannelCount: 1,
}},
},
writeUnits: func(medias []*description.Media, strm *stream.Stream) {
for i := range 2 {
strm.WriteUnit(medias[0], medias[0].Formats[0], &unit.Unit{
PTS: 90000 * 5 * int64(i),
@ -563,8 +327,27 @@ func TestFromStream(t *testing.T) {
},
})
}
case "pcma", "pcmu":
},
},
{
name: "pcma",
medias: []*description.Media{
{
Formats: []format.Format{&format.G711{
MULaw: false,
SampleRate: 8000,
ChannelCount: 1,
}},
},
},
expectedTracks: []*gortmplib.Track{
{Codec: &codecs.G711{
MULaw: false,
ChannelCount: 1,
SampleRate: 8000,
}},
},
writeUnits: func(medias []*description.Media, strm *stream.Stream) {
for i := range 2 {
strm.WriteUnit(medias[0], medias[0].Formats[0], &unit.Unit{
PTS: 90000 * 5 * int64(i),
@ -573,8 +356,56 @@ func TestFromStream(t *testing.T) {
},
})
}
case "lpcm":
},
},
{
name: "pcmu",
medias: []*description.Media{
{
Formats: []format.Format{&format.G711{
MULaw: true,
SampleRate: 8000,
ChannelCount: 1,
}},
},
},
expectedTracks: []*gortmplib.Track{
{Codec: &codecs.G711{
MULaw: true,
ChannelCount: 1,
SampleRate: 8000,
}},
},
writeUnits: func(medias []*description.Media, strm *stream.Stream) {
for i := range 2 {
strm.WriteUnit(medias[0], medias[0].Formats[0], &unit.Unit{
PTS: 90000 * 5 * int64(i),
Payload: unit.PayloadG711{
3, 4,
},
})
}
},
},
{
name: "lpcm",
medias: []*description.Media{
{
Formats: []format.Format{&format.LPCM{
BitDepth: 16,
SampleRate: 44100,
ChannelCount: 2,
}},
},
},
expectedTracks: []*gortmplib.Track{
{Codec: &codecs.LPCM{
BitDepth: 16,
SampleRate: 44100,
ChannelCount: 2,
}},
},
writeUnits: func(medias []*description.Media, strm *stream.Stream) {
for i := range 2 {
strm.WriteUnit(medias[0], medias[0].Formats[0], &unit.Unit{
PTS: 90000 * 5 * int64(i),
@ -583,8 +414,59 @@ func TestFromStream(t *testing.T) {
},
})
}
case "h265 + h264 + vp9 + av1 + opus + aac":
},
},
{
name: "h265 + h264 + vp9 + av1 + opus + aac",
medias: []*description.Media{
{
Formats: []format.Format{&format.H265{}},
},
{
Formats: []format.Format{&format.H264{}},
},
{
Formats: []format.Format{&format.VP9{}},
},
{
Formats: []format.Format{&format.AV1{}},
},
{
Formats: []format.Format{&format.Opus{
PayloadTyp: 96,
ChannelCount: 2,
}},
},
{
Formats: []format.Format{&format.MPEG4Audio{
PayloadTyp: 96,
Config: test.FormatMPEG4Audio.Config,
SizeLength: 13,
IndexLength: 3,
IndexDeltaLength: 3,
}},
},
},
expectedTracks: []*gortmplib.Track{
{Codec: &codecs.H265{
VPS: codecprocessor.H265DefaultVPS,
SPS: codecprocessor.H265DefaultSPS,
PPS: codecprocessor.H265DefaultPPS,
}},
{Codec: &codecs.H264{
SPS: codecprocessor.H264DefaultSPS,
PPS: codecprocessor.H264DefaultPPS,
}},
{Codec: &codecs.VP9{}},
{Codec: &codecs.AV1{}},
{Codec: &codecs.Opus{
ChannelCount: 2,
}},
{Codec: &codecs.MPEG4Audio{
Config: test.FormatMPEG4Audio.Config,
}},
},
writeUnits: func(medias []*description.Media, strm *stream.Stream) {
strm.WriteUnit(medias[0], medias[0].Formats[0], &unit.Unit{
Payload: unit.PayloadH265{
{
@ -641,7 +523,73 @@ func TestFromStream(t *testing.T) {
{3, 4},
},
})
},
},
}
for _, tc := range cases {
t.Run(tc.name, func(t *testing.T) {
medias := tc.medias
strm := &stream.Stream{
WriteQueueSize: 512,
RTPMaxPayloadSize: 1450,
Desc: &description.Session{Medias: medias},
GenerateRTPPackets: true,
Parent: test.NilLogger,
}
err := strm.Initialize()
require.NoError(t, err)
ln, err := net.Listen("tcp", "127.0.0.1:9121")
require.NoError(t, err)
defer ln.Close()
done := make(chan struct{})
go func() {
u, err2 := url.Parse("rtmp://127.0.0.1:9121/stream")
require.NoError(t, err2)
c := &gortmplib.Client{
URL: u,
}
err2 = c.Initialize(context.Background())
require.NoError(t, err2)
r := &gortmplib.Reader{
Conn: c,
}
err2 = r.Initialize()
require.NoError(t, err2)
require.Equal(t, tc.expectedTracks, r.Tracks())
close(done)
}()
nconn, err := ln.Accept()
require.NoError(t, err)
defer nconn.Close()
conn := &gortmplib.ServerConn{
RW: nconn,
}
err = conn.Initialize()
require.NoError(t, err)
err = conn.Accept()
require.NoError(t, err)
r := &stream.Reader{Parent: test.NilLogger}
err = FromStream(strm.Desc, r, conn, nconn, 10*time.Second)
require.NoError(t, err)
strm.AddReader(r)
defer strm.RemoveReader(r)
tc.writeUnits(medias, strm)
<-done
})

View file

@ -5,6 +5,7 @@ import (
"time"
"github.com/bluenviron/gortmplib"
"github.com/bluenviron/gortmplib/pkg/codecs"
"github.com/bluenviron/gortmplib/pkg/message"
"github.com/bluenviron/gortsplib/v5/pkg/description"
"github.com/bluenviron/gortsplib/v5/pkg/format"
@ -38,145 +39,199 @@ func ToStream(
var medias []*description.Media
for _, track := range r.Tracks() {
ctrack := track
switch ttrack := track.(type) {
case *format.AV1:
switch codec := track.Codec.(type) {
case *codecs.AV1:
forma := &format.AV1{
PayloadTyp: 96,
}
medi := &description.Media{
Type: description.MediaTypeVideo,
Formats: []format.Format{ctrack},
Formats: []format.Format{forma},
}
medias = append(medias, medi)
r.OnDataAV1(ttrack, func(pts time.Duration, tu [][]byte) {
(*strm).WriteUnit(medi, ctrack, &unit.Unit{
PTS: durationToTimestamp(pts, ctrack.ClockRate()),
r.OnDataAV1(track, func(pts time.Duration, tu [][]byte) {
(*strm).WriteUnit(medi, forma, &unit.Unit{
PTS: durationToTimestamp(pts, forma.ClockRate()),
Payload: unit.PayloadAV1(tu),
})
})
case *format.VP9:
case *codecs.VP9:
forma := &format.VP9{
PayloadTyp: 96,
}
medi := &description.Media{
Type: description.MediaTypeVideo,
Formats: []format.Format{ctrack},
Formats: []format.Format{forma},
}
medias = append(medias, medi)
r.OnDataVP9(ttrack, func(pts time.Duration, frame []byte) {
(*strm).WriteUnit(medi, ctrack, &unit.Unit{
PTS: durationToTimestamp(pts, ctrack.ClockRate()),
r.OnDataVP9(track, func(pts time.Duration, frame []byte) {
(*strm).WriteUnit(medi, forma, &unit.Unit{
PTS: durationToTimestamp(pts, forma.ClockRate()),
Payload: unit.PayloadVP9(frame),
})
})
case *format.H265:
case *codecs.H265:
forma := &format.H265{
PayloadTyp: 96,
VPS: codec.VPS,
SPS: codec.SPS,
PPS: codec.PPS,
}
medi := &description.Media{
Type: description.MediaTypeVideo,
Formats: []format.Format{ctrack},
Formats: []format.Format{forma},
}
medias = append(medias, medi)
r.OnDataH265(ttrack, func(pts time.Duration, _ time.Duration, au [][]byte) {
(*strm).WriteUnit(medi, ctrack, &unit.Unit{
PTS: durationToTimestamp(pts, ctrack.ClockRate()),
r.OnDataH265(track, func(pts time.Duration, _ time.Duration, au [][]byte) {
(*strm).WriteUnit(medi, forma, &unit.Unit{
PTS: durationToTimestamp(pts, forma.ClockRate()),
Payload: unit.PayloadH265(au),
})
})
case *format.H264:
case *codecs.H264:
forma := &format.H264{
PayloadTyp: 96,
SPS: codec.SPS,
PPS: codec.PPS,
PacketizationMode: 1,
}
medi := &description.Media{
Type: description.MediaTypeVideo,
Formats: []format.Format{ctrack},
Formats: []format.Format{forma},
}
medias = append(medias, medi)
r.OnDataH264(ttrack, func(pts time.Duration, _ time.Duration, au [][]byte) {
(*strm).WriteUnit(medi, ctrack, &unit.Unit{
PTS: durationToTimestamp(pts, ctrack.ClockRate()),
r.OnDataH264(track, func(pts time.Duration, _ time.Duration, au [][]byte) {
(*strm).WriteUnit(medi, forma, &unit.Unit{
PTS: durationToTimestamp(pts, forma.ClockRate()),
Payload: unit.PayloadH264(au),
})
})
case *format.Opus:
case *codecs.Opus:
forma := &format.Opus{
PayloadTyp: 96,
ChannelCount: codec.ChannelCount,
}
medi := &description.Media{
Type: description.MediaTypeAudio,
Formats: []format.Format{ctrack},
Formats: []format.Format{forma},
}
medias = append(medias, medi)
r.OnDataOpus(ttrack, func(pts time.Duration, packet []byte) {
(*strm).WriteUnit(medi, ctrack, &unit.Unit{
PTS: durationToTimestamp(pts, ctrack.ClockRate()),
r.OnDataOpus(track, func(pts time.Duration, packet []byte) {
(*strm).WriteUnit(medi, forma, &unit.Unit{
PTS: durationToTimestamp(pts, forma.ClockRate()),
Payload: unit.PayloadOpus{packet},
})
})
case *format.MPEG4Audio:
case *codecs.MPEG4Audio:
forma := &format.MPEG4Audio{
PayloadTyp: 96,
Config: codec.Config,
SizeLength: 13,
IndexLength: 3,
IndexDeltaLength: 3,
}
medi := &description.Media{
Type: description.MediaTypeAudio,
Formats: []format.Format{ctrack},
Formats: []format.Format{forma},
}
medias = append(medias, medi)
r.OnDataMPEG4Audio(ttrack, func(pts time.Duration, au []byte) {
(*strm).WriteUnit(medi, ctrack, &unit.Unit{
PTS: durationToTimestamp(pts, ctrack.ClockRate()),
r.OnDataMPEG4Audio(track, func(pts time.Duration, au []byte) {
(*strm).WriteUnit(medi, forma, &unit.Unit{
PTS: durationToTimestamp(pts, forma.ClockRate()),
Payload: unit.PayloadMPEG4Audio{au},
})
})
case *format.MPEG1Audio:
case *codecs.MPEG1Audio:
forma := &format.MPEG1Audio{}
medi := &description.Media{
Type: description.MediaTypeAudio,
Formats: []format.Format{ctrack},
Formats: []format.Format{forma},
}
medias = append(medias, medi)
r.OnDataMPEG1Audio(ttrack, func(pts time.Duration, frame []byte) {
(*strm).WriteUnit(medi, ctrack, &unit.Unit{
PTS: durationToTimestamp(pts, ctrack.ClockRate()),
r.OnDataMPEG1Audio(track, func(pts time.Duration, frame []byte) {
(*strm).WriteUnit(medi, forma, &unit.Unit{
PTS: durationToTimestamp(pts, forma.ClockRate()),
Payload: unit.PayloadMPEG1Audio{frame},
})
})
case *format.AC3:
case *codecs.AC3:
forma := &format.AC3{
PayloadTyp: 96,
SampleRate: codec.SampleRate,
ChannelCount: codec.ChannelCount,
}
medi := &description.Media{
Type: description.MediaTypeAudio,
Formats: []format.Format{ctrack},
Formats: []format.Format{forma},
}
medias = append(medias, medi)
r.OnDataAC3(ttrack, func(pts time.Duration, frame []byte) {
(*strm).WriteUnit(medi, ctrack, &unit.Unit{
PTS: durationToTimestamp(pts, ctrack.ClockRate()),
r.OnDataAC3(track, func(pts time.Duration, frame []byte) {
(*strm).WriteUnit(medi, forma, &unit.Unit{
PTS: durationToTimestamp(pts, forma.ClockRate()),
Payload: unit.PayloadAC3{frame},
})
})
case *format.G711:
case *codecs.G711:
forma := &format.G711{
PayloadTyp: func() uint8 {
switch {
case codec.ChannelCount == 1 && codec.MULaw:
return 0
case codec.ChannelCount == 1 && !codec.MULaw:
return 8
default:
return 96
}
}(),
MULaw: codec.MULaw,
SampleRate: codec.SampleRate,
ChannelCount: codec.ChannelCount,
}
medi := &description.Media{
Type: description.MediaTypeAudio,
Formats: []format.Format{ctrack},
Formats: []format.Format{forma},
}
medias = append(medias, medi)
r.OnDataG711(ttrack, func(pts time.Duration, samples []byte) {
(*strm).WriteUnit(medi, ctrack, &unit.Unit{
PTS: durationToTimestamp(pts, ctrack.ClockRate()),
r.OnDataG711(track, func(pts time.Duration, samples []byte) {
(*strm).WriteUnit(medi, forma, &unit.Unit{
PTS: durationToTimestamp(pts, forma.ClockRate()),
Payload: unit.PayloadG711(samples),
})
})
case *format.LPCM:
case *codecs.LPCM:
forma := &format.LPCM{
PayloadTyp: 96,
BitDepth: codec.BitDepth,
SampleRate: codec.SampleRate,
ChannelCount: codec.ChannelCount,
}
medi := &description.Media{
Type: description.MediaTypeAudio,
Formats: []format.Format{ctrack},
Formats: []format.Format{forma},
}
medias = append(medias, medi)
r.OnDataLPCM(ttrack, func(pts time.Duration, samples []byte) {
(*strm).WriteUnit(medi, ctrack, &unit.Unit{
PTS: durationToTimestamp(pts, ctrack.ClockRate()),
r.OnDataLPCM(track, func(pts time.Duration, samples []byte) {
(*strm).WriteUnit(medi, forma, &unit.Unit{
PTS: durationToTimestamp(pts, forma.ClockRate()),
Payload: unit.PayloadLPCM(samples),
})
})

View file

@ -4,6 +4,7 @@ import (
"crypto/rand"
"errors"
"fmt"
"slices"
"time"
"github.com/bluenviron/gortsplib/v5/pkg/description"
@ -666,10 +667,12 @@ func FromStream(
return errNoSupportedCodecsFrom
}
setuppedFormats := r.Formats()
n := 1
for _, media := range desc.Medias {
for _, forma := range media.Formats {
if forma != videoFormat && forma != audioFormat {
if !slices.Contains(setuppedFormats, forma) {
r.Parent.Log(logger.Warn, "skipping track %d (%s)", n, forma.Codec())
}
n++

View file

@ -9,8 +9,8 @@ import (
"time"
"github.com/bluenviron/gortmplib"
"github.com/bluenviron/gortmplib/pkg/codecs"
"github.com/bluenviron/gortsplib/v5/pkg/description"
"github.com/bluenviron/gortsplib/v5/pkg/format"
"github.com/bluenviron/mediamtx/internal/conf"
"github.com/bluenviron/mediamtx/internal/defs"
"github.com/bluenviron/mediamtx/internal/externalcmd"
@ -158,14 +158,22 @@ func TestServerPublish(t *testing.T) {
defer conn.Close()
w := &gortmplib.Writer{
Conn: conn,
Tracks: []format.Format{test.FormatH264, test.FormatMPEG4Audio},
Conn: conn,
Tracks: []*gortmplib.Track{
{Codec: &codecs.H264{
SPS: test.FormatH264.SPS,
PPS: test.FormatH264.PPS,
}},
{Codec: &codecs.MPEG4Audio{
Config: test.FormatMPEG4Audio.Config,
}},
},
}
err = w.Initialize()
require.NoError(t, err)
err = w.WriteH264(
test.FormatH264,
w.Tracks[0],
2*time.Second, 2*time.Second, [][]byte{
{5, 2, 3, 4},
})
@ -292,9 +300,11 @@ func TestServerRead(t *testing.T) {
require.NoError(t, err)
tracks := r.Tracks()
require.Equal(t, []format.Format{test.FormatH264}, tracks)
require.Len(t, tracks, 1)
_, ok := tracks[0].Codec.(*codecs.H264)
require.True(t, ok)
r.OnDataH264(tracks[0].(*format.H264), func(_ time.Duration, _ time.Duration, au [][]byte) {
r.OnDataH264(tracks[0], func(_ time.Duration, _ time.Duration, au [][]byte) {
require.Equal(t, [][]byte{
test.FormatH264.SPS,
test.FormatH264.PPS,

View file

@ -11,7 +11,7 @@ import (
"github.com/stretchr/testify/require"
"github.com/bluenviron/gortmplib"
"github.com/bluenviron/gortsplib/v5/pkg/format"
"github.com/bluenviron/gortmplib/pkg/codecs"
"github.com/bluenviron/mediamtx/internal/conf"
"github.com/bluenviron/mediamtx/internal/defs"
"github.com/bluenviron/mediamtx/internal/test"
@ -118,13 +118,21 @@ func TestSource(t *testing.T) {
require.NoError(t, err)
w := &gortmplib.Writer{
Conn: conn,
Tracks: []format.Format{test.FormatH264, test.FormatMPEG4Audio},
Conn: conn,
Tracks: []*gortmplib.Track{
{Codec: &codecs.H264{
SPS: test.FormatH264.SPS,
PPS: test.FormatH264.PPS,
}},
{Codec: &codecs.MPEG4Audio{
Config: test.FormatMPEG4Audio.Config,
}},
},
}
err = w.Initialize()
require.NoError(t, err)
err = w.WriteMPEG4Audio(test.FormatMPEG4Audio, 2*time.Second, []byte{5, 2, 3, 4})
err = w.WriteMPEG4Audio(w.Tracks[1], 2*time.Second, []byte{5, 2, 3, 4})
require.NoError(t, err)
break