mirror of
https://github.com/bluenviron/mediamtx.git
synced 2026-01-26 21:39:16 -08:00
rtsp: add random value to timestamp of tracks from other protocols (#3071)
This commit is contained in:
parent
da7c5744b1
commit
b6db3121b5
26 changed files with 203 additions and 49 deletions
4
go.mod
4
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
|
||||
|
|
|
|||
8
go.sum
8
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=
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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")
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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() ||
|
||||
|
|
|
|||
|
|
@ -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),
|
||||
|
|
|
|||
|
|
@ -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
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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},
|
||||
|
|
|
|||
|
|
@ -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
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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},
|
||||
|
|
|
|||
|
|
@ -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
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
|
|
|||
|
|
@ -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
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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")
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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{},
|
||||
},
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue