mirror of
https://github.com/aler9/rtsp-simple-server
synced 2025-10-28 18:01:54 +08:00
update gortsplib (#2390)
Some checks reported warnings
lint / code (push) Has been cancelled
lint / mod-tidy (push) Has been cancelled
lint / apidocs (push) Has been cancelled
test / test64 (push) Has been cancelled
test / test32 (push) Has been cancelled
test / test_highlevel (push) Has been cancelled
Some checks reported warnings
lint / code (push) Has been cancelled
lint / mod-tidy (push) Has been cancelled
lint / apidocs (push) Has been cancelled
test / test64 (push) Has been cancelled
test / test32 (push) Has been cancelled
test / test_highlevel (push) Has been cancelled
This commit is contained in:
2
go.mod
2
go.mod
@@ -8,7 +8,7 @@ require (
|
|||||||
github.com/alecthomas/kong v0.8.0
|
github.com/alecthomas/kong v0.8.0
|
||||||
github.com/aler9/writerseeker v1.1.0
|
github.com/aler9/writerseeker v1.1.0
|
||||||
github.com/bluenviron/gohlslib v1.0.3
|
github.com/bluenviron/gohlslib v1.0.3
|
||||||
github.com/bluenviron/gortsplib/v4 v4.1.1-0.20230919201539-fc2a10a4999a
|
github.com/bluenviron/gortsplib/v4 v4.1.1-0.20230921145131-44da79f72d5e
|
||||||
github.com/bluenviron/mediacommon v1.3.1-0.20230919191723-607668055ebe
|
github.com/bluenviron/mediacommon v1.3.1-0.20230919191723-607668055ebe
|
||||||
github.com/datarhei/gosrt v0.5.4
|
github.com/datarhei/gosrt v0.5.4
|
||||||
github.com/fsnotify/fsnotify v1.6.0
|
github.com/fsnotify/fsnotify v1.6.0
|
||||||
|
|||||||
4
go.sum
4
go.sum
@@ -14,8 +14,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/benburkert/openpgp v0.0.0-20160410205803-c2471f86866c/go.mod h1:x1vxHcL/9AVzuk5HOloOEPrtJY0MaalYr78afXZ+pWI=
|
||||||
github.com/bluenviron/gohlslib v1.0.3 h1:FMHevlIrrZ67uzCXmlTSGflsfYREEtHb8L9BDyf7lJc=
|
github.com/bluenviron/gohlslib v1.0.3 h1:FMHevlIrrZ67uzCXmlTSGflsfYREEtHb8L9BDyf7lJc=
|
||||||
github.com/bluenviron/gohlslib v1.0.3/go.mod h1:R/aIsSxLI61N0CVMjtcHqJouK6+Ddd5YIihcCr7IFIw=
|
github.com/bluenviron/gohlslib v1.0.3/go.mod h1:R/aIsSxLI61N0CVMjtcHqJouK6+Ddd5YIihcCr7IFIw=
|
||||||
github.com/bluenviron/gortsplib/v4 v4.1.1-0.20230919201539-fc2a10a4999a h1:2zaPnmdTRJyfySBbRF8mCQDfOFOL2qQHfQFrLpKeyS0=
|
github.com/bluenviron/gortsplib/v4 v4.1.1-0.20230921145131-44da79f72d5e h1:Y8b0vKPQLerALedmNNBmxrJR6sBcnge+fQeCH+Kfh3A=
|
||||||
github.com/bluenviron/gortsplib/v4 v4.1.1-0.20230919201539-fc2a10a4999a/go.mod h1:0rVtKDafUA14isZuaBTm5+X9NPqLYs/lY8JIww6+doM=
|
github.com/bluenviron/gortsplib/v4 v4.1.1-0.20230921145131-44da79f72d5e/go.mod h1:0rVtKDafUA14isZuaBTm5+X9NPqLYs/lY8JIww6+doM=
|
||||||
github.com/bluenviron/mediacommon v1.3.1-0.20230919191723-607668055ebe h1:8kvIJfRXvv1Za1hdArKjvd/l8WCHJF+d+oLtANdFbr8=
|
github.com/bluenviron/mediacommon v1.3.1-0.20230919191723-607668055ebe h1:8kvIJfRXvv1Za1hdArKjvd/l8WCHJF+d+oLtANdFbr8=
|
||||||
github.com/bluenviron/mediacommon v1.3.1-0.20230919191723-607668055ebe/go.mod h1:/vlOVSebDwzdRtQONOKLua0fOSJg1tUDHpP+h9a0uqM=
|
github.com/bluenviron/mediacommon v1.3.1-0.20230919191723-607668055ebe/go.mod h1:/vlOVSebDwzdRtQONOKLua0fOSJg1tUDHpP+h9a0uqM=
|
||||||
github.com/bytedance/sonic v1.5.0/go.mod h1:ED5hyg4y6t3/9Ku1R6dU/4KyJ48DZ4jPhfY1O2AihPM=
|
github.com/bytedance/sonic v1.5.0/go.mod h1:ED5hyg4y6t3/9Ku1R6dU/4KyJ48DZ4jPhfY1O2AihPM=
|
||||||
|
|||||||
@@ -472,12 +472,12 @@ func (m *hlsMuxer) createAudioTrack(stream *stream.Stream) (*description.Media,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var audioFormatMPEG4AudioGeneric *format.MPEG4AudioGeneric
|
var audioFormatMPEG4Audio *format.MPEG4Audio
|
||||||
audioMedia = stream.Desc().FindFormat(&audioFormatMPEG4AudioGeneric)
|
audioMedia = stream.Desc().FindFormat(&audioFormatMPEG4Audio)
|
||||||
|
|
||||||
if audioMedia != nil {
|
if audioMedia != nil {
|
||||||
stream.AddReader(m.writer, audioMedia, audioFormatMPEG4AudioGeneric, func(u unit.Unit) error {
|
stream.AddReader(m.writer, audioMedia, audioFormatMPEG4Audio, func(u unit.Unit) error {
|
||||||
tunit := u.(*unit.MPEG4AudioGeneric)
|
tunit := u.(*unit.MPEG4Audio)
|
||||||
|
|
||||||
if tunit.AUs == nil {
|
if tunit.AUs == nil {
|
||||||
return nil
|
return nil
|
||||||
@@ -496,39 +496,7 @@ func (m *hlsMuxer) createAudioTrack(stream *stream.Stream) (*description.Media,
|
|||||||
|
|
||||||
return audioMedia, &gohlslib.Track{
|
return audioMedia, &gohlslib.Track{
|
||||||
Codec: &codecs.MPEG4Audio{
|
Codec: &codecs.MPEG4Audio{
|
||||||
Config: *audioFormatMPEG4AudioGeneric.Config,
|
Config: *audioFormatMPEG4Audio.GetConfig(),
|
||||||
},
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
var audioFormatMPEG4AudioLATM *format.MPEG4AudioLATM
|
|
||||||
audioMedia = stream.Desc().FindFormat(&audioFormatMPEG4AudioLATM)
|
|
||||||
|
|
||||||
if audioMedia != nil &&
|
|
||||||
audioFormatMPEG4AudioLATM.Config != nil &&
|
|
||||||
len(audioFormatMPEG4AudioLATM.Config.Programs) == 1 &&
|
|
||||||
len(audioFormatMPEG4AudioLATM.Config.Programs[0].Layers) == 1 {
|
|
||||||
stream.AddReader(m.writer, audioMedia, audioFormatMPEG4AudioLATM, func(u unit.Unit) error {
|
|
||||||
tunit := u.(*unit.MPEG4AudioLATM)
|
|
||||||
|
|
||||||
if tunit.AU == nil {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
err := m.muxer.WriteMPEG4Audio(
|
|
||||||
tunit.NTP,
|
|
||||||
tunit.PTS,
|
|
||||||
[][]byte{tunit.AU})
|
|
||||||
if err != nil {
|
|
||||||
return fmt.Errorf("muxer error: %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
})
|
|
||||||
|
|
||||||
return audioMedia, &gohlslib.Track{
|
|
||||||
Codec: &codecs.MPEG4Audio{
|
|
||||||
Config: *audioFormatMPEG4AudioLATM.Config.Programs[0].Layers[0].AudioSpecificConfig,
|
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -168,7 +168,7 @@ func (s *hlsSource) run(ctx context.Context, cnf *conf.PathConf, reloadConf chan
|
|||||||
}
|
}
|
||||||
|
|
||||||
c.OnDataMPEG4Audio(track, func(pts time.Duration, aus [][]byte) {
|
c.OnDataMPEG4Audio(track, func(pts time.Duration, aus [][]byte) {
|
||||||
stream.WriteUnit(medi, medi.Formats[0], &unit.MPEG4AudioGeneric{
|
stream.WriteUnit(medi, medi.Formats[0], &unit.MPEG4Audio{
|
||||||
Base: unit.Base{
|
Base: unit.Base{
|
||||||
NTP: time.Now(),
|
NTP: time.Now(),
|
||||||
PTS: pts,
|
PTS: pts,
|
||||||
|
|||||||
@@ -135,7 +135,7 @@ func mpegtsSetupTracks(r *mpegts.Reader, stream **stream.Stream) ([]*description
|
|||||||
}
|
}
|
||||||
|
|
||||||
r.OnDataMPEG4Audio(track, func(pts int64, aus [][]byte) error {
|
r.OnDataMPEG4Audio(track, func(pts int64, aus [][]byte) error {
|
||||||
(*stream).WriteUnit(medi, medi.Formats[0], &unit.MPEG4AudioGeneric{
|
(*stream).WriteUnit(medi, medi.Formats[0], &unit.MPEG4Audio{
|
||||||
Base: unit.Base{
|
Base: unit.Base{
|
||||||
NTP: time.Now(),
|
NTP: time.Now(),
|
||||||
PTS: decodeTime(pts),
|
PTS: decodeTime(pts),
|
||||||
|
|||||||
@@ -395,12 +395,12 @@ func (c *rtmpConn) setupAudio(
|
|||||||
stream *stream.Stream,
|
stream *stream.Stream,
|
||||||
writer *asyncwriter.Writer,
|
writer *asyncwriter.Writer,
|
||||||
) (*description.Media, format.Format) {
|
) (*description.Media, format.Format) {
|
||||||
var audioFormatMPEG4Generic *format.MPEG4AudioGeneric
|
var audioFormatMPEG4Audio *format.MPEG4Audio
|
||||||
audioMedia := stream.Desc().FindFormat(&audioFormatMPEG4Generic)
|
audioMedia := stream.Desc().FindFormat(&audioFormatMPEG4Audio)
|
||||||
|
|
||||||
if audioMedia != nil {
|
if audioMedia != nil {
|
||||||
stream.AddReader(writer, audioMedia, audioFormatMPEG4Generic, func(u unit.Unit) error {
|
stream.AddReader(writer, audioMedia, audioFormatMPEG4Audio, func(u unit.Unit) error {
|
||||||
tunit := u.(*unit.MPEG4AudioGeneric)
|
tunit := u.(*unit.MPEG4Audio)
|
||||||
|
|
||||||
if tunit.AUs == nil {
|
if tunit.AUs == nil {
|
||||||
return nil
|
return nil
|
||||||
@@ -410,7 +410,7 @@ func (c *rtmpConn) setupAudio(
|
|||||||
c.nconn.SetWriteDeadline(time.Now().Add(time.Duration(c.writeTimeout)))
|
c.nconn.SetWriteDeadline(time.Now().Add(time.Duration(c.writeTimeout)))
|
||||||
err := (*w).WriteMPEG4Audio(
|
err := (*w).WriteMPEG4Audio(
|
||||||
tunit.PTS+time.Duration(i)*mpeg4audio.SamplesPerAccessUnit*
|
tunit.PTS+time.Duration(i)*mpeg4audio.SamplesPerAccessUnit*
|
||||||
time.Second/time.Duration(audioFormatMPEG4Generic.ClockRate()),
|
time.Second/time.Duration(audioFormatMPEG4Audio.ClockRate()),
|
||||||
au,
|
au,
|
||||||
)
|
)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -421,28 +421,7 @@ func (c *rtmpConn) setupAudio(
|
|||||||
return nil
|
return nil
|
||||||
})
|
})
|
||||||
|
|
||||||
return audioMedia, audioFormatMPEG4Generic
|
return audioMedia, audioFormatMPEG4Audio
|
||||||
}
|
|
||||||
|
|
||||||
var audioFormatMPEG4AudioLATM *format.MPEG4AudioLATM
|
|
||||||
audioMedia = stream.Desc().FindFormat(&audioFormatMPEG4AudioLATM)
|
|
||||||
|
|
||||||
if audioMedia != nil &&
|
|
||||||
audioFormatMPEG4AudioLATM.Config != nil &&
|
|
||||||
len(audioFormatMPEG4AudioLATM.Config.Programs) == 1 &&
|
|
||||||
len(audioFormatMPEG4AudioLATM.Config.Programs[0].Layers) == 1 {
|
|
||||||
stream.AddReader(writer, audioMedia, audioFormatMPEG4AudioLATM, func(u unit.Unit) error {
|
|
||||||
tunit := u.(*unit.MPEG4AudioLATM)
|
|
||||||
|
|
||||||
if tunit.AU == nil {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
c.nconn.SetWriteDeadline(time.Now().Add(time.Duration(c.writeTimeout)))
|
|
||||||
return (*w).WriteMPEG4Audio(tunit.PTS, tunit.AU)
|
|
||||||
})
|
|
||||||
|
|
||||||
return audioMedia, audioFormatMPEG4AudioLATM
|
|
||||||
}
|
}
|
||||||
|
|
||||||
var audioFormatMPEG1 *format.MPEG1Audio
|
var audioFormatMPEG1 *format.MPEG1Audio
|
||||||
@@ -590,9 +569,9 @@ func (c *rtmpConn) runPublish(conn *rtmp.Conn, u *url.URL) error {
|
|||||||
medias = append(medias, audioMedia)
|
medias = append(medias, audioMedia)
|
||||||
|
|
||||||
switch audioFormat.(type) {
|
switch audioFormat.(type) {
|
||||||
case *format.MPEG4AudioGeneric:
|
case *format.MPEG4Audio:
|
||||||
r.OnDataMPEG4Audio(func(pts time.Duration, au []byte) {
|
r.OnDataMPEG4Audio(func(pts time.Duration, au []byte) {
|
||||||
stream.WriteUnit(audioMedia, audioFormat, &unit.MPEG4AudioGeneric{
|
stream.WriteUnit(audioMedia, audioFormat, &unit.MPEG4Audio{
|
||||||
Base: unit.Base{
|
Base: unit.Base{
|
||||||
NTP: time.Now(),
|
NTP: time.Now(),
|
||||||
PTS: pts,
|
PTS: pts,
|
||||||
|
|||||||
@@ -148,9 +148,9 @@ func (s *rtmpSource) runReader(u *url.URL, nconn net.Conn) error {
|
|||||||
medias = append(medias, audioMedia)
|
medias = append(medias, audioMedia)
|
||||||
|
|
||||||
switch audioFormat.(type) {
|
switch audioFormat.(type) {
|
||||||
case *format.MPEG4AudioGeneric:
|
case *format.MPEG4Audio:
|
||||||
mc.OnDataMPEG4Audio(func(pts time.Duration, au []byte) {
|
mc.OnDataMPEG4Audio(func(pts time.Duration, au []byte) {
|
||||||
stream.WriteUnit(audioMedia, audioFormat, &unit.MPEG4AudioGeneric{
|
stream.WriteUnit(audioMedia, audioFormat, &unit.MPEG4Audio{
|
||||||
Base: unit.Base{
|
Base: unit.Base{
|
||||||
NTP: time.Now(),
|
NTP: time.Now(),
|
||||||
PTS: pts,
|
PTS: pts,
|
||||||
|
|||||||
@@ -467,13 +467,13 @@ func (c *srtConn) runRead(req srtNewConnReq, pathName string, user string, pass
|
|||||||
return bw.Flush()
|
return bw.Flush()
|
||||||
})
|
})
|
||||||
|
|
||||||
case *format.MPEG4AudioGeneric:
|
case *format.MPEG4Audio:
|
||||||
track := addTrack(medi, &mpegts.CodecMPEG4Audio{
|
track := addTrack(medi, &mpegts.CodecMPEG4Audio{
|
||||||
Config: *forma.Config,
|
Config: *forma.GetConfig(),
|
||||||
})
|
})
|
||||||
|
|
||||||
res.stream.AddReader(writer, medi, forma, func(u unit.Unit) error {
|
res.stream.AddReader(writer, medi, forma, func(u unit.Unit) error {
|
||||||
tunit := u.(*unit.MPEG4AudioGeneric)
|
tunit := u.(*unit.MPEG4Audio)
|
||||||
if tunit.AUs == nil {
|
if tunit.AUs == nil {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
@@ -486,29 +486,6 @@ func (c *srtConn) runRead(req srtNewConnReq, pathName string, user string, pass
|
|||||||
return bw.Flush()
|
return bw.Flush()
|
||||||
})
|
})
|
||||||
|
|
||||||
case *format.MPEG4AudioLATM:
|
|
||||||
if forma.Config != nil &&
|
|
||||||
len(forma.Config.Programs) == 1 &&
|
|
||||||
len(forma.Config.Programs[0].Layers) == 1 {
|
|
||||||
track := addTrack(medi, &mpegts.CodecMPEG4Audio{
|
|
||||||
Config: *forma.Config.Programs[0].Layers[0].AudioSpecificConfig,
|
|
||||||
})
|
|
||||||
|
|
||||||
res.stream.AddReader(writer, medi, forma, func(u unit.Unit) error {
|
|
||||||
tunit := u.(*unit.MPEG4AudioLATM)
|
|
||||||
if tunit.AU == nil {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
sconn.SetWriteDeadline(time.Now().Add(time.Duration(c.writeTimeout)))
|
|
||||||
err = w.WriteMPEG4Audio(track, durationGoToMPEGTS(tunit.PTS), [][]byte{tunit.AU})
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
return bw.Flush()
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
case *format.Opus:
|
case *format.Opus:
|
||||||
track := addTrack(medi, &mpegts.CodecOpus{
|
track := addTrack(medi, &mpegts.CodecOpus{
|
||||||
ChannelCount: func() int {
|
ChannelCount: func() int {
|
||||||
|
|||||||
@@ -11,19 +11,19 @@ import (
|
|||||||
"github.com/bluenviron/mediamtx/internal/unit"
|
"github.com/bluenviron/mediamtx/internal/unit"
|
||||||
)
|
)
|
||||||
|
|
||||||
type formatProcessorMPEG4AudioGeneric struct {
|
type formatProcessorMPEG4Audio struct {
|
||||||
udpMaxPayloadSize int
|
udpMaxPayloadSize int
|
||||||
format *format.MPEG4Audio
|
format *format.MPEG4Audio
|
||||||
encoder *rtpmpeg4audio.Encoder
|
encoder *rtpmpeg4audio.Encoder
|
||||||
decoder *rtpmpeg4audio.Decoder
|
decoder *rtpmpeg4audio.Decoder
|
||||||
}
|
}
|
||||||
|
|
||||||
func newMPEG4AudioGeneric(
|
func newMPEG4Audio(
|
||||||
udpMaxPayloadSize int,
|
udpMaxPayloadSize int,
|
||||||
forma *format.MPEG4Audio,
|
forma *format.MPEG4Audio,
|
||||||
generateRTPPackets bool,
|
generateRTPPackets bool,
|
||||||
) (*formatProcessorMPEG4AudioGeneric, error) {
|
) (*formatProcessorMPEG4Audio, error) {
|
||||||
t := &formatProcessorMPEG4AudioGeneric{
|
t := &formatProcessorMPEG4Audio{
|
||||||
udpMaxPayloadSize: udpMaxPayloadSize,
|
udpMaxPayloadSize: udpMaxPayloadSize,
|
||||||
format: forma,
|
format: forma,
|
||||||
}
|
}
|
||||||
@@ -38,7 +38,7 @@ func newMPEG4AudioGeneric(
|
|||||||
return t, nil
|
return t, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *formatProcessorMPEG4AudioGeneric) createEncoder() error {
|
func (t *formatProcessorMPEG4Audio) createEncoder() error {
|
||||||
t.encoder = &rtpmpeg4audio.Encoder{
|
t.encoder = &rtpmpeg4audio.Encoder{
|
||||||
PayloadMaxSize: t.udpMaxPayloadSize - 12,
|
PayloadMaxSize: t.udpMaxPayloadSize - 12,
|
||||||
PayloadType: t.format.PayloadTyp,
|
PayloadType: t.format.PayloadTyp,
|
||||||
@@ -49,8 +49,8 @@ func (t *formatProcessorMPEG4AudioGeneric) createEncoder() error {
|
|||||||
return t.encoder.Init()
|
return t.encoder.Init()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *formatProcessorMPEG4AudioGeneric) ProcessUnit(uu unit.Unit) error { //nolint:dupl
|
func (t *formatProcessorMPEG4Audio) ProcessUnit(uu unit.Unit) error { //nolint:dupl
|
||||||
u := uu.(*unit.MPEG4AudioGeneric)
|
u := uu.(*unit.MPEG4Audio)
|
||||||
|
|
||||||
pkts, err := t.encoder.Encode(u.AUs)
|
pkts, err := t.encoder.Encode(u.AUs)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -67,13 +67,13 @@ func (t *formatProcessorMPEG4AudioGeneric) ProcessUnit(uu unit.Unit) error { //n
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *formatProcessorMPEG4AudioGeneric) ProcessRTPPacket( //nolint:dupl
|
func (t *formatProcessorMPEG4Audio) ProcessRTPPacket( //nolint:dupl
|
||||||
pkt *rtp.Packet,
|
pkt *rtp.Packet,
|
||||||
ntp time.Time,
|
ntp time.Time,
|
||||||
pts time.Duration,
|
pts time.Duration,
|
||||||
hasNonRTSPReaders bool,
|
hasNonRTSPReaders bool,
|
||||||
) (Unit, error) {
|
) (Unit, error) {
|
||||||
u := &unit.MPEG4AudioGeneric{
|
u := &unit.MPEG4Audio{
|
||||||
Base: unit.Base{
|
Base: unit.Base{
|
||||||
RTPPackets: []*rtp.Packet{pkt},
|
RTPPackets: []*rtp.Packet{pkt},
|
||||||
NTP: ntp,
|
NTP: ntp,
|
||||||
@@ -1,112 +0,0 @@
|
|||||||
package formatprocessor
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"time"
|
|
||||||
|
|
||||||
"github.com/bluenviron/gortsplib/v4/pkg/format"
|
|
||||||
"github.com/bluenviron/gortsplib/v4/pkg/format/rtpmpeg4audiolatm"
|
|
||||||
"github.com/pion/rtp"
|
|
||||||
|
|
||||||
"github.com/bluenviron/mediamtx/internal/unit"
|
|
||||||
)
|
|
||||||
|
|
||||||
type formatProcessorMPEG4AudioLATM struct {
|
|
||||||
udpMaxPayloadSize int
|
|
||||||
format *format.MPEG4AudioLATM
|
|
||||||
encoder *rtpmpeg4audiolatm.Encoder
|
|
||||||
decoder *rtpmpeg4audiolatm.Decoder
|
|
||||||
}
|
|
||||||
|
|
||||||
func newMPEG4AudioLATM(
|
|
||||||
udpMaxPayloadSize int,
|
|
||||||
forma *format.MPEG4AudioLATM,
|
|
||||||
generateRTPPackets bool,
|
|
||||||
) (*formatProcessorMPEG4AudioLATM, error) {
|
|
||||||
t := &formatProcessorMPEG4AudioLATM{
|
|
||||||
udpMaxPayloadSize: udpMaxPayloadSize,
|
|
||||||
format: forma,
|
|
||||||
}
|
|
||||||
|
|
||||||
if generateRTPPackets {
|
|
||||||
err := t.createEncoder()
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return t, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (t *formatProcessorMPEG4AudioLATM) createEncoder() error {
|
|
||||||
t.encoder = &rtpmpeg4audiolatm.Encoder{
|
|
||||||
PayloadType: t.format.PayloadTyp,
|
|
||||||
}
|
|
||||||
return t.encoder.Init()
|
|
||||||
}
|
|
||||||
|
|
||||||
func (t *formatProcessorMPEG4AudioLATM) ProcessUnit(uu unit.Unit) error { //nolint:dupl
|
|
||||||
u := uu.(*unit.MPEG4AudioLATM)
|
|
||||||
|
|
||||||
pkts, err := t.encoder.Encode(u.AU)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
ts := uint32(multiplyAndDivide(u.PTS, time.Duration(t.format.ClockRate()), time.Second))
|
|
||||||
for _, pkt := range pkts {
|
|
||||||
pkt.Timestamp += ts
|
|
||||||
}
|
|
||||||
|
|
||||||
u.RTPPackets = pkts
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (t *formatProcessorMPEG4AudioLATM) ProcessRTPPacket( //nolint:dupl
|
|
||||||
pkt *rtp.Packet,
|
|
||||||
ntp time.Time,
|
|
||||||
pts time.Duration,
|
|
||||||
hasNonRTSPReaders bool,
|
|
||||||
) (Unit, error) {
|
|
||||||
u := &unit.MPEG4AudioLATM{
|
|
||||||
Base: unit.Base{
|
|
||||||
RTPPackets: []*rtp.Packet{pkt},
|
|
||||||
NTP: ntp,
|
|
||||||
PTS: pts,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
// remove padding
|
|
||||||
pkt.Header.Padding = false
|
|
||||||
pkt.PaddingSize = 0
|
|
||||||
|
|
||||||
if pkt.MarshalSize() > t.udpMaxPayloadSize {
|
|
||||||
return nil, fmt.Errorf("payload size (%d) is greater than maximum allowed (%d)",
|
|
||||||
pkt.MarshalSize(), t.udpMaxPayloadSize)
|
|
||||||
}
|
|
||||||
|
|
||||||
// decode from RTP
|
|
||||||
if hasNonRTSPReaders || t.decoder != nil {
|
|
||||||
if t.decoder == nil {
|
|
||||||
var err error
|
|
||||||
t.decoder, err = t.format.CreateDecoder()
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
au, err := t.decoder.Decode(pkt)
|
|
||||||
if err != nil {
|
|
||||||
if err == rtpmpeg4audiolatm.ErrMorePacketsNeeded {
|
|
||||||
return u, nil
|
|
||||||
}
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
u.AU = au
|
|
||||||
}
|
|
||||||
|
|
||||||
// route packet as is
|
|
||||||
return u, nil
|
|
||||||
}
|
|
||||||
@@ -63,11 +63,8 @@ func New(
|
|||||||
case *format.Opus:
|
case *format.Opus:
|
||||||
return newOpus(udpMaxPayloadSize, forma, generateRTPPackets)
|
return newOpus(udpMaxPayloadSize, forma, generateRTPPackets)
|
||||||
|
|
||||||
case *format.MPEG4AudioGeneric:
|
case *format.MPEG4Audio:
|
||||||
return newMPEG4AudioGeneric(udpMaxPayloadSize, forma, generateRTPPackets)
|
return newMPEG4Audio(udpMaxPayloadSize, forma, generateRTPPackets)
|
||||||
|
|
||||||
case *format.MPEG4AudioLATM:
|
|
||||||
return newMPEG4AudioLATM(udpMaxPayloadSize, forma, generateRTPPackets)
|
|
||||||
|
|
||||||
case *format.MPEG1Audio:
|
case *format.MPEG1Audio:
|
||||||
return newMPEG1Audio(udpMaxPayloadSize, forma, generateRTPPackets)
|
return newMPEG1Audio(udpMaxPayloadSize, forma, generateRTPPackets)
|
||||||
|
|||||||
@@ -571,16 +571,16 @@ func NewAgent(
|
|||||||
return nil
|
return nil
|
||||||
})
|
})
|
||||||
|
|
||||||
case *format.MPEG4AudioGeneric:
|
case *format.MPEG4Audio:
|
||||||
codec := &fmp4.CodecMPEG4Audio{
|
codec := &fmp4.CodecMPEG4Audio{
|
||||||
Config: *forma.Config,
|
Config: *forma.GetConfig(),
|
||||||
}
|
}
|
||||||
track := addTrack(codec)
|
track := addTrack(codec)
|
||||||
|
|
||||||
sampleRate := time.Duration(forma.Config.SampleRate)
|
sampleRate := time.Duration(forma.ClockRate())
|
||||||
|
|
||||||
stream.AddReader(r.writer, media, forma, func(u unit.Unit) error {
|
stream.AddReader(r.writer, media, forma, func(u unit.Unit) error {
|
||||||
tunit := u.(*unit.MPEG4AudioGeneric)
|
tunit := u.(*unit.MPEG4Audio)
|
||||||
if tunit.AUs == nil {
|
if tunit.AUs == nil {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
@@ -603,26 +603,6 @@ func NewAgent(
|
|||||||
return nil
|
return nil
|
||||||
})
|
})
|
||||||
|
|
||||||
case *format.MPEG4AudioLATM:
|
|
||||||
codec := &fmp4.CodecMPEG4Audio{
|
|
||||||
Config: *forma.Config.Programs[0].Layers[0].AudioSpecificConfig,
|
|
||||||
}
|
|
||||||
track := addTrack(codec)
|
|
||||||
|
|
||||||
stream.AddReader(r.writer, media, forma, func(u unit.Unit) error {
|
|
||||||
tunit := u.(*unit.MPEG4AudioLATM)
|
|
||||||
if tunit.AU == nil {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
return track.record(&sample{
|
|
||||||
PartSample: &fmp4.PartSample{
|
|
||||||
Payload: tunit.AU,
|
|
||||||
},
|
|
||||||
dts: tunit.PTS,
|
|
||||||
})
|
|
||||||
})
|
|
||||||
|
|
||||||
case *format.MPEG1Audio:
|
case *format.MPEG1Audio:
|
||||||
codec := &fmp4.CodecMPEG1Audio{
|
codec := &fmp4.CodecMPEG1Audio{
|
||||||
SampleRate: 32000,
|
SampleRate: 32000,
|
||||||
|
|||||||
@@ -132,7 +132,7 @@ func TestAgent(t *testing.T) {
|
|||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
|
||||||
stream.WriteUnit(desc.Medias[2], desc.Medias[2].Formats[0], &unit.MPEG4AudioGeneric{
|
stream.WriteUnit(desc.Medias[2], desc.Medias[2].Formats[0], &unit.MPEG4Audio{
|
||||||
Base: unit.Base{
|
Base: unit.Base{
|
||||||
PTS: (50 + time.Duration(i)) * time.Second,
|
PTS: (50 + time.Duration(i)) * time.Second,
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -87,7 +87,7 @@ func (w *Writer) writeTracks(videoTrack format.Format, audioTrack format.Format)
|
|||||||
case *format.MPEG1Audio:
|
case *format.MPEG1Audio:
|
||||||
return message.CodecMPEG1Audio
|
return message.CodecMPEG1Audio
|
||||||
|
|
||||||
case *format.MPEG4AudioGeneric, *format.MPEG4AudioLATM:
|
case *format.MPEG4Audio:
|
||||||
return message.CodecMPEG4Audio
|
return message.CodecMPEG4Audio
|
||||||
|
|
||||||
default:
|
default:
|
||||||
@@ -127,12 +127,8 @@ func (w *Writer) writeTracks(videoTrack format.Format, audioTrack format.Format)
|
|||||||
|
|
||||||
var audioConfig *mpeg4audio.AudioSpecificConfig
|
var audioConfig *mpeg4audio.AudioSpecificConfig
|
||||||
|
|
||||||
switch track := audioTrack.(type) {
|
if track, ok := audioTrack.(*format.MPEG4Audio); ok {
|
||||||
case *format.MPEG4Audio:
|
audioConfig = track.GetConfig()
|
||||||
audioConfig = track.Config
|
|
||||||
|
|
||||||
case *format.MPEG4AudioLATM:
|
|
||||||
audioConfig = track.Config.Programs[0].Layers[0].AudioSpecificConfig
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if audioConfig != nil {
|
if audioConfig != nil {
|
||||||
|
|||||||
7
internal/unit/mpeg4_audio.go
Normal file
7
internal/unit/mpeg4_audio.go
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
package unit
|
||||||
|
|
||||||
|
// MPEG4Audio is a MPEG-4 Audio data unit.
|
||||||
|
type MPEG4Audio struct {
|
||||||
|
Base
|
||||||
|
AUs [][]byte
|
||||||
|
}
|
||||||
@@ -1,7 +0,0 @@
|
|||||||
package unit
|
|
||||||
|
|
||||||
// MPEG4AudioGeneric is a MPEG-4 Audio data unit.
|
|
||||||
type MPEG4AudioGeneric struct {
|
|
||||||
Base
|
|
||||||
AUs [][]byte
|
|
||||||
}
|
|
||||||
@@ -1,7 +0,0 @@
|
|||||||
package unit
|
|
||||||
|
|
||||||
// MPEG4AudioLATM is a MPEG-4 Audio data unit.
|
|
||||||
type MPEG4AudioLATM struct {
|
|
||||||
Base
|
|
||||||
AU []byte
|
|
||||||
}
|
|
||||||
Reference in New Issue
Block a user