From b6db3121b5cc61f0dc62a2c753ada5b185271768 Mon Sep 17 00:00:00 2001 From: Alessandro Ros Date: Mon, 26 Feb 2024 00:41:05 +0100 Subject: [PATCH] rtsp: add random value to timestamp of tracks from other protocols (#3071) --- go.mod | 4 ++-- go.sum | 8 ++++---- internal/conf/auth_method.go | 4 ++-- internal/conf/conf.go | 2 +- internal/conf/path.go | 2 +- internal/core/auth.go | 2 +- internal/formatprocessor/ac3.go | 12 +++++++++++- internal/formatprocessor/av1.go | 17 +++++++++++++---- internal/formatprocessor/g711.go | 12 +++++++++++- internal/formatprocessor/g711_test.go | 2 ++ internal/formatprocessor/h264.go | 17 +++++++++++++---- internal/formatprocessor/h265.go | 17 +++++++++++++---- internal/formatprocessor/lpcm.go | 12 +++++++++++- internal/formatprocessor/lpcm_test.go | 2 ++ internal/formatprocessor/mjpeg.go | 12 +++++++++++- internal/formatprocessor/mpeg1_audio.go | 12 +++++++++++- internal/formatprocessor/mpeg1_video.go | 12 +++++++++++- internal/formatprocessor/mpeg4_audio.go | 12 +++++++++++- internal/formatprocessor/mpeg4_video.go | 12 +++++++++++- internal/formatprocessor/opus.go | 12 +++++++++++- internal/formatprocessor/processor.go | 8 -------- internal/formatprocessor/vp8.go | 12 +++++++++++- internal/formatprocessor/vp9.go | 12 +++++++++++- internal/protocols/rtmp/conn.go | 22 ++++++++++++++++++---- internal/protocols/rtmp/reader.go | 11 +++++++++-- internal/servers/rtsp/server_test.go | 2 +- 26 files changed, 203 insertions(+), 49 deletions(-) diff --git a/go.mod b/go.mod index 14ed28ae442..21b6c3f32a4 100644 --- a/go.mod +++ b/go.mod @@ -7,7 +7,7 @@ require ( github.com/abema/go-mp4 v1.2.0 github.com/alecthomas/kong v0.8.1 github.com/bluenviron/gohlslib v1.2.2 - github.com/bluenviron/gortsplib/v4 v4.7.2 + github.com/bluenviron/gortsplib/v4 v4.7.3-0.20240225222544-ce46aee084cc github.com/bluenviron/mediacommon v1.9.2 github.com/datarhei/gosrt v0.5.7 github.com/fsnotify/fsnotify v1.7.0 @@ -64,7 +64,7 @@ require ( github.com/ugorji/go/codec v1.2.11 // indirect github.com/xo/terminfo v0.0.0-20210125001918-ca9a967f8778 // indirect golang.org/x/arch v0.3.0 // indirect - golang.org/x/net v0.20.0 // indirect + golang.org/x/net v0.21.0 // indirect golang.org/x/sys v0.17.0 // indirect golang.org/x/text v0.14.0 // indirect google.golang.org/protobuf v1.30.0 // indirect diff --git a/go.sum b/go.sum index 9cd104152bc..a2051c00adc 100644 --- a/go.sum +++ b/go.sum @@ -18,8 +18,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 v1.2.2 h1:ivtv5XPX5XgXDUUZYBBIF5T8ilRsO5OvTOQdObqG/OI= github.com/bluenviron/gohlslib v1.2.2/go.mod h1:TEVMn5iOPrS//mB/H9e08QkTvR6uS5c4LVeXFrfqSE4= -github.com/bluenviron/gortsplib/v4 v4.7.2 h1:Nu8m89q07tiwnXIcNsdLjtkjLZDdOs2+/GJpoPk2IWk= -github.com/bluenviron/gortsplib/v4 v4.7.2/go.mod h1:8nWeCJhIZzGofBnHFLBeRm6hbyPlkyGTzzdT+MBUxmc= +github.com/bluenviron/gortsplib/v4 v4.7.3-0.20240225222544-ce46aee084cc h1:P+XOzo6/bSghx7YiZ1KaiWeab0KTGih8hg4jAcwqvS0= +github.com/bluenviron/gortsplib/v4 v4.7.3-0.20240225222544-ce46aee084cc/go.mod h1:uJYwJ+MhikHFswvOtNWv9Guaq7XnRPc/B8qY6KJSlQs= github.com/bluenviron/mediacommon v1.9.2 h1:EHcvoC5YMXRcFE010bTNf07ZiSlB/e/AdZyG7GsEYN0= github.com/bluenviron/mediacommon v1.9.2/go.mod h1:lt8V+wMyPw8C69HAqDWV5tsAwzN9u2Z+ca8B6C//+n0= github.com/bytedance/sonic v1.5.0/go.mod h1:ED5hyg4y6t3/9Ku1R6dU/4KyJ48DZ4jPhfY1O2AihPM= @@ -224,8 +224,8 @@ golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg= golang.org/x/net v0.11.0/go.mod h1:2L/ixqYpgIVXmeoSA/4Lu7BzTG4KIyPIryS4IsOd1oQ= golang.org/x/net v0.14.0/go.mod h1:PpSgVXXLK0OxS0F31C1/tv6XNguvCrnXIDrFMspZIUI= golang.org/x/net v0.15.0/go.mod h1:idbUs1IY1+zTqbi8yxTbhexhEEk5ur9LInksu6HrEpk= -golang.org/x/net v0.20.0 h1:aCL9BSgETF1k+blQaYUBx9hJ9LOGP3gAVemcZlf1Kpo= -golang.org/x/net v0.20.0/go.mod h1:z8BVo6PvndSri0LbOE3hAn0apkU+1YvI6E70E9jsnvY= +golang.org/x/net v0.21.0 h1:AQyQV4dYCvJ7vGmJyKki9+PBdyvhkSd8EIx/qb0AYv4= +golang.org/x/net v0.21.0/go.mod h1:bIjVDfnllIU7BJ2DNgfnXvpSvtn8VRwhlsaeUTyUS44= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= diff --git a/internal/conf/auth_method.go b/internal/conf/auth_method.go index e759fc4d7f8..9c35c5eb3f7 100644 --- a/internal/conf/auth_method.go +++ b/internal/conf/auth_method.go @@ -21,7 +21,7 @@ func (d AuthMethods) MarshalJSON() ([]byte, error) { case headers.AuthBasic: out[i] = "basic" - case headers.AuthDigest: + case headers.AuthDigestMD5: out[i] = "digest" default: @@ -49,7 +49,7 @@ func (d *AuthMethods) UnmarshalJSON(b []byte) error { *d = append(*d, headers.AuthBasic) case "digest": - *d = append(*d, headers.AuthDigest) + *d = append(*d, headers.AuthDigestMD5) default: return fmt.Errorf("invalid authentication method: '%s'", v) diff --git a/internal/conf/conf.go b/internal/conf/conf.go index 30e3df54fab..54b4d715788 100644 --- a/internal/conf/conf.go +++ b/internal/conf/conf.go @@ -367,7 +367,7 @@ func (conf *Conf) Validate() error { return fmt.Errorf("'externalAuthenticationURL' must be a HTTP URL") } - if contains(conf.AuthMethods, headers.AuthDigest) { + if contains(conf.AuthMethods, headers.AuthDigestMD5) { return fmt.Errorf("'externalAuthenticationURL' can't be used when 'digest' is in authMethods") } } diff --git a/internal/conf/path.go b/internal/conf/path.go index 2420db12f39..a37b99ff536 100644 --- a/internal/conf/path.go +++ b/internal/conf/path.go @@ -393,7 +393,7 @@ func (pconf *Path) validate(conf *Conf, name string) error { (pconf.ReadUser == "" && pconf.ReadPass != "") { return fmt.Errorf("read username and password must be both filled") } - if contains(conf.AuthMethods, headers.AuthDigest) { + if contains(conf.AuthMethods, headers.AuthDigestMD5) { if pconf.PublishUser.IsHashed() || pconf.PublishPass.IsHashed() || pconf.ReadUser.IsHashed() || diff --git a/internal/core/auth.go b/internal/core/auth.go index 32126a95867..16c99b1b385 100644 --- a/internal/core/auth.go +++ b/internal/core/auth.go @@ -105,7 +105,7 @@ func doAuthentication( } if pathUser != "" { - if accessRequest.RTSPRequest != nil && rtspAuth.Method == headers.AuthDigest { + if accessRequest.RTSPRequest != nil && rtspAuth.Method == headers.AuthDigestMD5 { err := auth.Validate( accessRequest.RTSPRequest, string(pathUser), diff --git a/internal/formatprocessor/ac3.go b/internal/formatprocessor/ac3.go index 20badf04e7a..da1d3eb761a 100644 --- a/internal/formatprocessor/ac3.go +++ b/internal/formatprocessor/ac3.go @@ -7,6 +7,7 @@ import ( "github.com/bluenviron/gortsplib/v4/pkg/format" "github.com/bluenviron/gortsplib/v4/pkg/format/rtpac3" + "github.com/bluenviron/gortsplib/v4/pkg/rtptime" "github.com/pion/rtp" "github.com/bluenviron/mediamtx/internal/unit" @@ -15,6 +16,7 @@ import ( type formatProcessorAC3 struct { udpMaxPayloadSize int format *format.AC3 + timeEncoder *rtptime.Encoder encoder *rtpac3.Encoder decoder *rtpac3.Decoder } @@ -34,6 +36,14 @@ func newAC3( if err != nil { return nil, err } + + t.timeEncoder = &rtptime.Encoder{ + ClockRate: forma.ClockRate(), + } + err = t.timeEncoder.Initialize() + if err != nil { + return nil, err + } } return t, nil @@ -55,7 +65,7 @@ func (t *formatProcessorAC3) ProcessUnit(uu unit.Unit) error { //nolint:dupl } u.RTPPackets = pkts - ts := uint32(multiplyAndDivide(u.PTS, time.Duration(t.format.ClockRate()), time.Second)) + ts := t.timeEncoder.Encode(u.PTS) for _, pkt := range u.RTPPackets { pkt.Timestamp += ts } diff --git a/internal/formatprocessor/av1.go b/internal/formatprocessor/av1.go index 2bc8bae66f7..05e96b97b1a 100644 --- a/internal/formatprocessor/av1.go +++ b/internal/formatprocessor/av1.go @@ -7,6 +7,7 @@ import ( "github.com/bluenviron/gortsplib/v4/pkg/format" "github.com/bluenviron/gortsplib/v4/pkg/format/rtpav1" + "github.com/bluenviron/gortsplib/v4/pkg/rtptime" "github.com/pion/rtp" "github.com/bluenviron/mediamtx/internal/unit" @@ -15,9 +16,9 @@ import ( type formatProcessorAV1 struct { udpMaxPayloadSize int format *format.AV1 - - encoder *rtpav1.Encoder - decoder *rtpav1.Decoder + timeEncoder *rtptime.Encoder + encoder *rtpav1.Encoder + decoder *rtpav1.Decoder } func newAV1( @@ -35,6 +36,14 @@ func newAV1( if err != nil { return nil, err } + + t.timeEncoder = &rtptime.Encoder{ + ClockRate: forma.ClockRate(), + } + err = t.timeEncoder.Initialize() + if err != nil { + return nil, err + } } return t, nil @@ -57,7 +66,7 @@ func (t *formatProcessorAV1) ProcessUnit(uu unit.Unit) error { //nolint:dupl } u.RTPPackets = pkts - ts := uint32(multiplyAndDivide(u.PTS, time.Duration(t.format.ClockRate()), time.Second)) + ts := t.timeEncoder.Encode(u.PTS) for _, pkt := range u.RTPPackets { pkt.Timestamp += ts } diff --git a/internal/formatprocessor/g711.go b/internal/formatprocessor/g711.go index 38b3bb0e66e..fe26db55578 100644 --- a/internal/formatprocessor/g711.go +++ b/internal/formatprocessor/g711.go @@ -6,6 +6,7 @@ import ( "github.com/bluenviron/gortsplib/v4/pkg/format" "github.com/bluenviron/gortsplib/v4/pkg/format/rtplpcm" + "github.com/bluenviron/gortsplib/v4/pkg/rtptime" "github.com/pion/rtp" "github.com/bluenviron/mediamtx/internal/unit" @@ -14,6 +15,7 @@ import ( type formatProcessorG711 struct { udpMaxPayloadSize int format *format.G711 + timeEncoder *rtptime.Encoder encoder *rtplpcm.Encoder decoder *rtplpcm.Decoder } @@ -33,6 +35,14 @@ func newG711( if err != nil { return nil, err } + + t.timeEncoder = &rtptime.Encoder{ + ClockRate: forma.ClockRate(), + } + err = t.timeEncoder.Initialize() + if err != nil { + return nil, err + } } return t, nil @@ -57,7 +67,7 @@ func (t *formatProcessorG711) ProcessUnit(uu unit.Unit) error { //nolint:dupl } u.RTPPackets = pkts - ts := uint32(multiplyAndDivide(u.PTS, time.Duration(t.format.ClockRate()), time.Second)) + ts := t.timeEncoder.Encode(u.PTS) for _, pkt := range u.RTPPackets { pkt.Timestamp += ts } diff --git a/internal/formatprocessor/g711_test.go b/internal/formatprocessor/g711_test.go index d907442f4db..37852d56a0c 100644 --- a/internal/formatprocessor/g711_test.go +++ b/internal/formatprocessor/g711_test.go @@ -32,6 +32,7 @@ func TestG611Encode(t *testing.T) { Version: 2, PayloadType: 8, SequenceNumber: unit.RTPPackets[0].SequenceNumber, + Timestamp: unit.RTPPackets[0].Timestamp, SSRC: unit.RTPPackets[0].SSRC, }, Payload: []byte{1, 2, 3, 4}, @@ -60,6 +61,7 @@ func TestG611Encode(t *testing.T) { Version: 2, PayloadType: 0, SequenceNumber: unit.RTPPackets[0].SequenceNumber, + Timestamp: unit.RTPPackets[0].Timestamp, SSRC: unit.RTPPackets[0].SSRC, }, Payload: []byte{1, 2, 3, 4}, diff --git a/internal/formatprocessor/h264.go b/internal/formatprocessor/h264.go index e34aef530d6..7f0f11aff0b 100644 --- a/internal/formatprocessor/h264.go +++ b/internal/formatprocessor/h264.go @@ -7,6 +7,7 @@ import ( "github.com/bluenviron/gortsplib/v4/pkg/format" "github.com/bluenviron/gortsplib/v4/pkg/format/rtph264" + "github.com/bluenviron/gortsplib/v4/pkg/rtptime" "github.com/bluenviron/mediacommon/pkg/codecs/h264" "github.com/pion/rtp" @@ -73,9 +74,9 @@ func rtpH264ExtractParams(payload []byte) ([]byte, []byte) { type formatProcessorH264 struct { udpMaxPayloadSize int format *format.H264 - - encoder *rtph264.Encoder - decoder *rtph264.Decoder + timeEncoder *rtptime.Encoder + encoder *rtph264.Encoder + decoder *rtph264.Decoder } func newH264( @@ -93,6 +94,14 @@ func newH264( if err != nil { return nil, err } + + t.timeEncoder = &rtptime.Encoder{ + ClockRate: forma.ClockRate(), + } + err = t.timeEncoder.Initialize() + if err != nil { + return nil, err + } } return t, nil @@ -226,7 +235,7 @@ func (t *formatProcessorH264) ProcessUnit(uu unit.Unit) error { } u.RTPPackets = pkts - ts := uint32(multiplyAndDivide(u.PTS, time.Duration(t.format.ClockRate()), time.Second)) + ts := t.timeEncoder.Encode(u.PTS) for _, pkt := range u.RTPPackets { pkt.Timestamp += ts } diff --git a/internal/formatprocessor/h265.go b/internal/formatprocessor/h265.go index 74b8b80b5f5..e04cafe4e64 100644 --- a/internal/formatprocessor/h265.go +++ b/internal/formatprocessor/h265.go @@ -7,6 +7,7 @@ import ( "github.com/bluenviron/gortsplib/v4/pkg/format" "github.com/bluenviron/gortsplib/v4/pkg/format/rtph265" + "github.com/bluenviron/gortsplib/v4/pkg/rtptime" "github.com/bluenviron/mediacommon/pkg/codecs/h265" "github.com/pion/rtp" @@ -80,9 +81,9 @@ func rtpH265ExtractParams(payload []byte) ([]byte, []byte, []byte) { type formatProcessorH265 struct { udpMaxPayloadSize int format *format.H265 - - encoder *rtph265.Encoder - decoder *rtph265.Decoder + timeEncoder *rtptime.Encoder + encoder *rtph265.Encoder + decoder *rtph265.Decoder } func newH265( @@ -100,6 +101,14 @@ func newH265( if err != nil { return nil, err } + + t.timeEncoder = &rtptime.Encoder{ + ClockRate: forma.ClockRate(), + } + err = t.timeEncoder.Initialize() + if err != nil { + return nil, err + } } return t, nil @@ -245,7 +254,7 @@ func (t *formatProcessorH265) ProcessUnit(uu unit.Unit) error { //nolint:dupl } u.RTPPackets = pkts - ts := uint32(multiplyAndDivide(u.PTS, time.Duration(t.format.ClockRate()), time.Second)) + ts := t.timeEncoder.Encode(u.PTS) for _, pkt := range u.RTPPackets { pkt.Timestamp += ts } diff --git a/internal/formatprocessor/lpcm.go b/internal/formatprocessor/lpcm.go index c26d03bd716..73cc8c59087 100644 --- a/internal/formatprocessor/lpcm.go +++ b/internal/formatprocessor/lpcm.go @@ -6,6 +6,7 @@ import ( "github.com/bluenviron/gortsplib/v4/pkg/format" "github.com/bluenviron/gortsplib/v4/pkg/format/rtplpcm" + "github.com/bluenviron/gortsplib/v4/pkg/rtptime" "github.com/pion/rtp" "github.com/bluenviron/mediamtx/internal/unit" @@ -14,6 +15,7 @@ import ( type formatProcessorLPCM struct { udpMaxPayloadSize int format *format.LPCM + timeEncoder *rtptime.Encoder encoder *rtplpcm.Encoder decoder *rtplpcm.Decoder } @@ -33,6 +35,14 @@ func newLPCM( if err != nil { return nil, err } + + t.timeEncoder = &rtptime.Encoder{ + ClockRate: forma.ClockRate(), + } + err = t.timeEncoder.Initialize() + if err != nil { + return nil, err + } } return t, nil @@ -57,7 +67,7 @@ func (t *formatProcessorLPCM) ProcessUnit(uu unit.Unit) error { //nolint:dupl } u.RTPPackets = pkts - ts := uint32(multiplyAndDivide(u.PTS, time.Duration(t.format.ClockRate()), time.Second)) + ts := t.timeEncoder.Encode(u.PTS) for _, pkt := range u.RTPPackets { pkt.Timestamp += ts } diff --git a/internal/formatprocessor/lpcm_test.go b/internal/formatprocessor/lpcm_test.go index a217a38f35d..1aa6f629f84 100644 --- a/internal/formatprocessor/lpcm_test.go +++ b/internal/formatprocessor/lpcm_test.go @@ -13,6 +13,7 @@ func TestLPCMEncode(t *testing.T) { forma := &format.LPCM{ PayloadTyp: 96, BitDepth: 16, + SampleRate: 44100, ChannelCount: 2, } @@ -30,6 +31,7 @@ func TestLPCMEncode(t *testing.T) { Version: 2, PayloadType: 96, SequenceNumber: unit.RTPPackets[0].SequenceNumber, + Timestamp: unit.RTPPackets[0].Timestamp, SSRC: unit.RTPPackets[0].SSRC, }, Payload: []byte{1, 2, 3, 4}, diff --git a/internal/formatprocessor/mjpeg.go b/internal/formatprocessor/mjpeg.go index 90c5cce25d5..8acb71217db 100644 --- a/internal/formatprocessor/mjpeg.go +++ b/internal/formatprocessor/mjpeg.go @@ -7,6 +7,7 @@ import ( "github.com/bluenviron/gortsplib/v4/pkg/format" "github.com/bluenviron/gortsplib/v4/pkg/format/rtpmjpeg" + "github.com/bluenviron/gortsplib/v4/pkg/rtptime" "github.com/pion/rtp" "github.com/bluenviron/mediamtx/internal/unit" @@ -15,6 +16,7 @@ import ( type formatProcessorMJPEG struct { udpMaxPayloadSize int format *format.MJPEG + timeEncoder *rtptime.Encoder encoder *rtpmjpeg.Encoder decoder *rtpmjpeg.Decoder } @@ -34,6 +36,14 @@ func newMJPEG( if err != nil { return nil, err } + + t.timeEncoder = &rtptime.Encoder{ + ClockRate: forma.ClockRate(), + } + err = t.timeEncoder.Initialize() + if err != nil { + return nil, err + } } return t, nil @@ -56,7 +66,7 @@ func (t *formatProcessorMJPEG) ProcessUnit(uu unit.Unit) error { //nolint:dupl } u.RTPPackets = pkts - ts := uint32(multiplyAndDivide(u.PTS, time.Duration(t.format.ClockRate()), time.Second)) + ts := t.timeEncoder.Encode(u.PTS) for _, pkt := range u.RTPPackets { pkt.Timestamp += ts } diff --git a/internal/formatprocessor/mpeg1_audio.go b/internal/formatprocessor/mpeg1_audio.go index 6a02f62bd8d..41a42f4cb75 100644 --- a/internal/formatprocessor/mpeg1_audio.go +++ b/internal/formatprocessor/mpeg1_audio.go @@ -7,6 +7,7 @@ import ( "github.com/bluenviron/gortsplib/v4/pkg/format" "github.com/bluenviron/gortsplib/v4/pkg/format/rtpmpeg1audio" + "github.com/bluenviron/gortsplib/v4/pkg/rtptime" "github.com/pion/rtp" "github.com/bluenviron/mediamtx/internal/unit" @@ -15,6 +16,7 @@ import ( type formatProcessorMPEG1Audio struct { udpMaxPayloadSize int format *format.MPEG1Audio + timeEncoder *rtptime.Encoder encoder *rtpmpeg1audio.Encoder decoder *rtpmpeg1audio.Decoder } @@ -34,6 +36,14 @@ func newMPEG1Audio( if err != nil { return nil, err } + + t.timeEncoder = &rtptime.Encoder{ + ClockRate: forma.ClockRate(), + } + err = t.timeEncoder.Initialize() + if err != nil { + return nil, err + } } return t, nil @@ -55,7 +65,7 @@ func (t *formatProcessorMPEG1Audio) ProcessUnit(uu unit.Unit) error { //nolint:d } u.RTPPackets = pkts - ts := uint32(multiplyAndDivide(u.PTS, time.Duration(t.format.ClockRate()), time.Second)) + ts := t.timeEncoder.Encode(u.PTS) for _, pkt := range u.RTPPackets { pkt.Timestamp += ts } diff --git a/internal/formatprocessor/mpeg1_video.go b/internal/formatprocessor/mpeg1_video.go index 2ce207f8f9c..8083aeffd91 100644 --- a/internal/formatprocessor/mpeg1_video.go +++ b/internal/formatprocessor/mpeg1_video.go @@ -7,6 +7,7 @@ import ( "github.com/bluenviron/gortsplib/v4/pkg/format" "github.com/bluenviron/gortsplib/v4/pkg/format/rtpmpeg1video" + "github.com/bluenviron/gortsplib/v4/pkg/rtptime" "github.com/pion/rtp" "github.com/bluenviron/mediamtx/internal/unit" @@ -15,6 +16,7 @@ import ( type formatProcessorMPEG1Video struct { udpMaxPayloadSize int format *format.MPEG1Video + timeEncoder *rtptime.Encoder encoder *rtpmpeg1video.Encoder decoder *rtpmpeg1video.Decoder } @@ -34,6 +36,14 @@ func newMPEG1Video( if err != nil { return nil, err } + + t.timeEncoder = &rtptime.Encoder{ + ClockRate: forma.ClockRate(), + } + err = t.timeEncoder.Initialize() + if err != nil { + return nil, err + } } return t, nil @@ -56,7 +66,7 @@ func (t *formatProcessorMPEG1Video) ProcessUnit(uu unit.Unit) error { //nolint:d } u.RTPPackets = pkts - ts := uint32(multiplyAndDivide(u.PTS, time.Duration(t.format.ClockRate()), time.Second)) + ts := t.timeEncoder.Encode(u.PTS) for _, pkt := range u.RTPPackets { pkt.Timestamp += ts } diff --git a/internal/formatprocessor/mpeg4_audio.go b/internal/formatprocessor/mpeg4_audio.go index 6ca41deaf36..267644195cd 100644 --- a/internal/formatprocessor/mpeg4_audio.go +++ b/internal/formatprocessor/mpeg4_audio.go @@ -7,6 +7,7 @@ import ( "github.com/bluenviron/gortsplib/v4/pkg/format" "github.com/bluenviron/gortsplib/v4/pkg/format/rtpmpeg4audio" + "github.com/bluenviron/gortsplib/v4/pkg/rtptime" "github.com/pion/rtp" "github.com/bluenviron/mediamtx/internal/unit" @@ -15,6 +16,7 @@ import ( type formatProcessorMPEG4Audio struct { udpMaxPayloadSize int format *format.MPEG4Audio + timeEncoder *rtptime.Encoder encoder *rtpmpeg4audio.Encoder decoder *rtpmpeg4audio.Decoder } @@ -34,6 +36,14 @@ func newMPEG4Audio( if err != nil { return nil, err } + + t.timeEncoder = &rtptime.Encoder{ + ClockRate: forma.ClockRate(), + } + err = t.timeEncoder.Initialize() + if err != nil { + return nil, err + } } return t, nil @@ -59,7 +69,7 @@ func (t *formatProcessorMPEG4Audio) ProcessUnit(uu unit.Unit) error { //nolint:d } u.RTPPackets = pkts - ts := uint32(multiplyAndDivide(u.PTS, time.Duration(t.format.ClockRate()), time.Second)) + ts := t.timeEncoder.Encode(u.PTS) for _, pkt := range u.RTPPackets { pkt.Timestamp += ts } diff --git a/internal/formatprocessor/mpeg4_video.go b/internal/formatprocessor/mpeg4_video.go index 56786761acc..eac47fc1425 100644 --- a/internal/formatprocessor/mpeg4_video.go +++ b/internal/formatprocessor/mpeg4_video.go @@ -8,6 +8,7 @@ import ( "github.com/bluenviron/gortsplib/v4/pkg/format" "github.com/bluenviron/gortsplib/v4/pkg/format/rtpmpeg4video" + "github.com/bluenviron/gortsplib/v4/pkg/rtptime" "github.com/bluenviron/mediacommon/pkg/codecs/mpeg4video" "github.com/pion/rtp" @@ -17,6 +18,7 @@ import ( type formatProcessorMPEG4Video struct { udpMaxPayloadSize int format *format.MPEG4Video + timeEncoder *rtptime.Encoder encoder *rtpmpeg4video.Encoder decoder *rtpmpeg4video.Decoder } @@ -36,6 +38,14 @@ func newMPEG4Video( if err != nil { return nil, err } + + t.timeEncoder = &rtptime.Encoder{ + ClockRate: forma.ClockRate(), + } + err = t.timeEncoder.Initialize() + if err != nil { + return nil, err + } } return t, nil @@ -93,7 +103,7 @@ func (t *formatProcessorMPEG4Video) ProcessUnit(uu unit.Unit) error { //nolint:d return err } - ts := uint32(multiplyAndDivide(u.PTS, time.Duration(t.format.ClockRate()), time.Second)) + ts := t.timeEncoder.Encode(u.PTS) for _, pkt := range u.RTPPackets { pkt.Timestamp += ts } diff --git a/internal/formatprocessor/opus.go b/internal/formatprocessor/opus.go index 80aa953688c..ab4595431b2 100644 --- a/internal/formatprocessor/opus.go +++ b/internal/formatprocessor/opus.go @@ -6,6 +6,7 @@ import ( "github.com/bluenviron/gortsplib/v4/pkg/format" "github.com/bluenviron/gortsplib/v4/pkg/format/rtpsimpleaudio" + "github.com/bluenviron/gortsplib/v4/pkg/rtptime" "github.com/bluenviron/mediacommon/pkg/codecs/opus" "github.com/pion/rtp" @@ -15,6 +16,7 @@ import ( type formatProcessorOpus struct { udpMaxPayloadSize int format *format.Opus + timeEncoder *rtptime.Encoder encoder *rtpsimpleaudio.Encoder decoder *rtpsimpleaudio.Decoder } @@ -34,6 +36,14 @@ func newOpus( if err != nil { return nil, err } + + t.timeEncoder = &rtptime.Encoder{ + ClockRate: forma.ClockRate(), + } + err = t.timeEncoder.Initialize() + if err != nil { + return nil, err + } } return t, nil @@ -59,7 +69,7 @@ func (t *formatProcessorOpus) ProcessUnit(uu unit.Unit) error { //nolint:dupl return err } - ts := uint32(multiplyAndDivide(pts, time.Duration(t.format.ClockRate()), time.Second)) + ts := t.timeEncoder.Encode(u.PTS) pkt.Timestamp += ts rtpPackets = append(rtpPackets, pkt) diff --git a/internal/formatprocessor/processor.go b/internal/formatprocessor/processor.go index 76713a3ffa1..530ff8c83b1 100644 --- a/internal/formatprocessor/processor.go +++ b/internal/formatprocessor/processor.go @@ -10,14 +10,6 @@ import ( "github.com/bluenviron/mediamtx/internal/unit" ) -// avoid an int64 overflow and preserve resolution by splitting division into two parts: -// first add the integer part, then the decimal part. -func multiplyAndDivide(v, m, d time.Duration) time.Duration { - secs := v / d - dec := v % d - return (secs*m + dec*m/d) -} - // Processor cleans and normalizes streams. type Processor interface { // process a Unit. diff --git a/internal/formatprocessor/vp8.go b/internal/formatprocessor/vp8.go index 3b18397fb0f..61ea9730f73 100644 --- a/internal/formatprocessor/vp8.go +++ b/internal/formatprocessor/vp8.go @@ -7,6 +7,7 @@ import ( "github.com/bluenviron/gortsplib/v4/pkg/format" "github.com/bluenviron/gortsplib/v4/pkg/format/rtpvp8" + "github.com/bluenviron/gortsplib/v4/pkg/rtptime" "github.com/pion/rtp" "github.com/bluenviron/mediamtx/internal/unit" @@ -15,6 +16,7 @@ import ( type formatProcessorVP8 struct { udpMaxPayloadSize int format *format.VP8 + timeEncoder *rtptime.Encoder encoder *rtpvp8.Encoder decoder *rtpvp8.Decoder } @@ -34,6 +36,14 @@ func newVP8( if err != nil { return nil, err } + + t.timeEncoder = &rtptime.Encoder{ + ClockRate: forma.ClockRate(), + } + err = t.timeEncoder.Initialize() + if err != nil { + return nil, err + } } return t, nil @@ -56,7 +66,7 @@ func (t *formatProcessorVP8) ProcessUnit(uu unit.Unit) error { //nolint:dupl } u.RTPPackets = pkts - ts := uint32(multiplyAndDivide(u.PTS, time.Duration(t.format.ClockRate()), time.Second)) + ts := t.timeEncoder.Encode(u.PTS) for _, pkt := range u.RTPPackets { pkt.Timestamp += ts } diff --git a/internal/formatprocessor/vp9.go b/internal/formatprocessor/vp9.go index a6af1cd6ff4..db7ccb7604c 100644 --- a/internal/formatprocessor/vp9.go +++ b/internal/formatprocessor/vp9.go @@ -7,6 +7,7 @@ import ( "github.com/bluenviron/gortsplib/v4/pkg/format" "github.com/bluenviron/gortsplib/v4/pkg/format/rtpvp9" + "github.com/bluenviron/gortsplib/v4/pkg/rtptime" "github.com/pion/rtp" "github.com/bluenviron/mediamtx/internal/unit" @@ -15,6 +16,7 @@ import ( type formatProcessorVP9 struct { udpMaxPayloadSize int format *format.VP9 + timeEncoder *rtptime.Encoder encoder *rtpvp9.Encoder decoder *rtpvp9.Decoder } @@ -34,6 +36,14 @@ func newVP9( if err != nil { return nil, err } + + t.timeEncoder = &rtptime.Encoder{ + ClockRate: forma.ClockRate(), + } + err = t.timeEncoder.Initialize() + if err != nil { + return nil, err + } } return t, nil @@ -56,7 +66,7 @@ func (t *formatProcessorVP9) ProcessUnit(uu unit.Unit) error { //nolint:dupl } u.RTPPackets = pkts - ts := uint32(multiplyAndDivide(u.PTS, time.Duration(t.format.ClockRate()), time.Second)) + ts := t.timeEncoder.Encode(u.PTS) for _, pkt := range u.RTPPackets { pkt.Timestamp += ts } diff --git a/internal/protocols/rtmp/conn.go b/internal/protocols/rtmp/conn.go index 22bb3606d6c..c9c25f65064 100644 --- a/internal/protocols/rtmp/conn.go +++ b/internal/protocols/rtmp/conn.go @@ -18,8 +18,15 @@ func resultIsOK1(res *message.CommandAMF0) bool { return false } - ma, ok := res.Arguments[1].(amf0.Object) - if !ok { + var ma amf0.Object + switch pl := res.Arguments[1].(type) { + case amf0.Object: + ma = pl + + case amf0.ECMAArray: + ma = amf0.Object(pl) + + default: return false } @@ -359,8 +366,15 @@ func (c *Conn) initializeServer() (*url.URL, bool, error) { return nil, false, fmt.Errorf("invalid connect command: %+v", cmd) } - ma, ok := cmd.Arguments[0].(amf0.Object) - if !ok { + var ma amf0.Object + switch pl := cmd.Arguments[0].(type) { + case amf0.Object: + ma = pl + + case amf0.ECMAArray: + ma = amf0.Object(pl) + + default: return nil, false, fmt.Errorf("invalid connect command: %+v", cmd) } diff --git a/internal/protocols/rtmp/reader.go b/internal/protocols/rtmp/reader.go index 376242e99f8..99bc79ba282 100644 --- a/internal/protocols/rtmp/reader.go +++ b/internal/protocols/rtmp/reader.go @@ -156,8 +156,15 @@ func tracksFromMetadata(conn *Conn, payload []interface{}) (format.Format, forma return nil, nil, fmt.Errorf("invalid metadata") } - md, ok := payload[0].(amf0.Object) - if !ok { + var md amf0.Object + switch pl := payload[0].(type) { + case amf0.Object: + md = pl + + case amf0.ECMAArray: + md = amf0.Object(pl) + + default: return nil, nil, fmt.Errorf("invalid metadata") } diff --git a/internal/servers/rtsp/server_test.go b/internal/servers/rtsp/server_test.go index 74e51b66619..618d1ba8072 100644 --- a/internal/servers/rtsp/server_test.go +++ b/internal/servers/rtsp/server_test.go @@ -233,7 +233,7 @@ func TestServerRead(t *testing.T) { Marker: true, PayloadType: 96, SequenceNumber: p.SequenceNumber, - Timestamp: 0, + Timestamp: p.Timestamp, SSRC: p.SSRC, CSRC: []uint32{}, },