webrtc: fix error "Failed to setup RTCP mux" on some readers (#3381) (#3449)

This commit is contained in:
Alessandro Ros 2024-06-10 15:43:52 +02:00 committed by GitHub
parent 095921dc26
commit 427249877c
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 98 additions and 0 deletions

View File

@ -128,6 +128,9 @@ func (co *PeerConnection) Start() error {
mediaEngine := &webrtc.MediaEngine{}
if co.Publish {
videoSetupped := false
audioSetupped := false
for _, tr := range co.OutgoingTracks {
params, err := tr.codecParameters()
if err != nil {
@ -137,8 +140,10 @@ func (co *PeerConnection) Start() error {
var codecType webrtc.RTPCodecType
if tr.isVideo() {
codecType = webrtc.RTPCodecTypeVideo
videoSetupped = true
} else {
codecType = webrtc.RTPCodecTypeAudio
audioSetupped = true
}
err = mediaEngine.RegisterCodec(params, codecType)
@ -146,6 +151,33 @@ func (co *PeerConnection) Start() error {
return err
}
}
// always register at least a video and a audio codec
// otherwise handshake will fail or audio will be muted on some clients (like Firefox)
if !videoSetupped {
err := mediaEngine.RegisterCodec(webrtc.RTPCodecParameters{
RTPCodecCapability: webrtc.RTPCodecCapability{
MimeType: webrtc.MimeTypeVP8,
ClockRate: 90000,
},
PayloadType: 96,
}, webrtc.RTPCodecTypeVideo)
if err != nil {
return err
}
}
if !audioSetupped {
err := mediaEngine.RegisterCodec(webrtc.RTPCodecParameters{
RTPCodecCapability: webrtc.RTPCodecCapability{
MimeType: webrtc.MimeTypePCMU,
ClockRate: 8000,
},
PayloadType: 0,
}, webrtc.RTPCodecTypeAudio)
if err != nil {
return err
}
}
} else {
for _, codec := range incomingVideoCodecs {
err := mediaEngine.RegisterCodec(codec, webrtc.RTPCodecTypeVideo)

View File

@ -9,6 +9,7 @@ import (
"github.com/bluenviron/mediamtx/internal/conf"
"github.com/bluenviron/mediamtx/internal/test"
"github.com/pion/rtp"
"github.com/pion/sdp/v3"
"github.com/pion/webrtc/v3"
"github.com/stretchr/testify/require"
)
@ -409,3 +410,68 @@ func TestPeerConnectionPublishRead(t *testing.T) {
})
}
}
// test that an audio codec is present regardless of the fact that an audio track is not.
func TestPeerConnectionFallbackCodecs(t *testing.T) {
pc1 := &PeerConnection{
HandshakeTimeout: conf.StringDuration(10 * time.Second),
TrackGatherTimeout: conf.StringDuration(2 * time.Second),
LocalRandomUDP: true,
IPsFromInterfaces: true,
Publish: false,
Log: test.NilLogger,
}
err := pc1.Start()
require.NoError(t, err)
defer pc1.Close()
pc2 := &PeerConnection{
HandshakeTimeout: conf.StringDuration(10 * time.Second),
TrackGatherTimeout: conf.StringDuration(2 * time.Second),
LocalRandomUDP: true,
IPsFromInterfaces: true,
Publish: true,
OutgoingTracks: []*OutgoingTrack{{
Format: &format.AV1{
PayloadTyp: 96,
},
}},
Log: test.NilLogger,
}
err = pc2.Start()
require.NoError(t, err)
defer pc2.Close()
offer, err := pc1.CreatePartialOffer()
require.NoError(t, err)
answer, err := pc2.CreateFullAnswer(context.Background(), offer)
require.NoError(t, err)
var s sdp.SessionDescription
err = s.Unmarshal([]byte(answer.SDP))
require.NoError(t, err)
require.Equal(t, []*sdp.MediaDescription{
{
MediaName: sdp.MediaName{
Media: "video",
Port: sdp.RangedPort{Value: 9},
Protos: []string{"UDP", "TLS", "RTP", "SAVPF"},
Formats: []string{"97"},
},
ConnectionInformation: s.MediaDescriptions[0].ConnectionInformation,
Attributes: s.MediaDescriptions[0].Attributes,
},
{
MediaName: sdp.MediaName{
Media: "audio",
Port: sdp.RangedPort{Value: 9},
Protos: []string{"UDP", "TLS", "RTP", "SAVPF"},
Formats: []string{"0"},
},
ConnectionInformation: s.MediaDescriptions[1].ConnectionInformation,
Attributes: s.MediaDescriptions[1].Attributes,
},
}, s.MediaDescriptions)
}