Skip to content

Commit f1bdde7

Browse files
rainliuyngrtc
andauthored
Add support for multi codec negotiation (#741)
* Add support for multi codec negotiation * Implemented alternative proposal via SettingEngine --------- Co-authored-by: yngrtc <[email protected]>
1 parent a1f8f19 commit f1bdde7

File tree

5 files changed

+120
-5
lines changed

5 files changed

+120
-5
lines changed

webrtc/src/api/media_engine/media_engine_test.rs

Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -801,3 +801,77 @@ a=rtpmap:111 opus/48000/2
801801

802802
Ok(())
803803
}
804+
805+
#[tokio::test]
806+
async fn test_multi_codec_negotiation() -> Result<()> {
807+
const OFFER_SDP: &str = "v=0
808+
o=- 781500112831855234 6 IN IP4 127.0.0.1
809+
s=-
810+
t=0 0
811+
a=group:BUNDLE 0 1 2 3
812+
a=extmap-allow-mixed
813+
a=msid-semantic: WMS be0216be-f3d8-40ca-a624-379edf70f1c9
814+
m=application 53555 UDP/DTLS/SCTP webrtc-datachannel
815+
a=mid:0
816+
a=sctp-port:5000
817+
a=max-message-size:262144
818+
m=video 9 UDP/TLS/RTP/SAVPF 98
819+
a=mid:1
820+
a=sendonly
821+
a=msid:be0216be-f3d8-40ca-a624-379edf70f1c9 3d032b3b-ffe5-48ec-b783-21375668d1c3
822+
a=rtcp-mux
823+
a=rtcp-rsize
824+
a=rtpmap:98 VP9/90000
825+
a=rtcp-fb:98 goog-remb
826+
a=rtcp-fb:98 transport-cc
827+
a=rtcp-fb:98 ccm fir
828+
a=rtcp-fb:98 nack
829+
a=rtcp-fb:98 nack pli
830+
a=fmtp:98 profile-id=0
831+
a=rid:q send
832+
a=rid:h send
833+
a=simulcast:send q;h
834+
m=video 9 UDP/TLS/RTP/SAVPF 96
835+
a=mid:2
836+
a=sendonly
837+
a=msid:6ff05509-be96-4ef1-a74f-425e14720983 16d5d7fe-d076-4718-9ca9-ec62b4543727
838+
a=rtcp-mux
839+
a=rtcp-rsize
840+
a=rtpmap:96 VP8/90000
841+
a=rtcp-fb:96 goog-remb
842+
a=rtcp-fb:96 transport-cc
843+
a=rtcp-fb:96 ccm fir
844+
a=rtcp-fb:96 nack
845+
a=rtcp-fb:96 nack pli
846+
a=ssrc:4281768245 cname:JDM9GNMEg+9To6K7
847+
a=ssrc:4281768245 msid:6ff05509-be96-4ef1-a74f-425e14720983 16d5d7fe-d076-4718-9ca9-ec62b4543727
848+
";
849+
let must_parse = |raw: &str| -> Result<SessionDescription> {
850+
let mut reader = Cursor::new(raw.as_bytes());
851+
Ok(SessionDescription::unmarshal(&mut reader)?)
852+
};
853+
854+
// "Multi codec negotiation disabled"
855+
{
856+
let mut m = MediaEngine::default();
857+
m.register_default_codecs()?;
858+
m.update_from_remote_description(&must_parse(OFFER_SDP)?)
859+
.await?;
860+
let negotiated_video_codecs = m.negotiated_video_codecs.lock();
861+
assert_eq!(negotiated_video_codecs.len(), 1)
862+
}
863+
864+
// "Multi codec negotiation enabled"
865+
{
866+
let mut m = MediaEngine::default();
867+
m.set_multi_codec_negotiation(true);
868+
assert!(m.multi_codec_negotiation());
869+
m.register_default_codecs()?;
870+
m.update_from_remote_description(&must_parse(OFFER_SDP)?)
871+
.await?;
872+
let negotiated_video_codecs = m.negotiated_video_codecs.lock();
873+
assert_eq!(negotiated_video_codecs.len(), 2)
874+
}
875+
876+
Ok(())
877+
}

webrtc/src/api/media_engine/mod.rs

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,7 @@ pub struct MediaEngine {
8888
// If we have attempted to negotiate a codec type yet.
8989
pub(crate) negotiated_video: AtomicBool,
9090
pub(crate) negotiated_audio: AtomicBool,
91+
pub(crate) negotiate_multi_codecs: AtomicBool,
9192

9293
pub(crate) video_codecs: Vec<RTCRtpCodecParameters>,
9394
pub(crate) audio_codecs: Vec<RTCRtpCodecParameters>,
@@ -461,6 +462,17 @@ impl MediaEngine {
461462
}
462463
}
463464

465+
/// set_multi_codec_negotiation enables or disables the negotiation of multiple codecs.
466+
pub(crate) fn set_multi_codec_negotiation(&self, negotiate_multi_codecs: bool) {
467+
self.negotiate_multi_codecs
468+
.store(negotiate_multi_codecs, Ordering::SeqCst);
469+
}
470+
471+
/// multi_codec_negotiation returns the current state of the negotiation of multiple codecs.
472+
pub(crate) fn multi_codec_negotiation(&self) -> bool {
473+
self.negotiate_multi_codecs.load(Ordering::SeqCst)
474+
}
475+
464476
pub(crate) async fn get_codec_by_payload(
465477
&self,
466478
payload_type: PayloadType,
@@ -653,12 +665,14 @@ impl MediaEngine {
653665
desc: &SessionDescription,
654666
) -> Result<()> {
655667
for media in &desc.media_descriptions {
656-
let typ = if !self.negotiated_audio.load(Ordering::SeqCst)
668+
let typ = if (!self.negotiated_audio.load(Ordering::SeqCst)
669+
|| self.negotiate_multi_codecs.load(Ordering::SeqCst))
657670
&& media.media_name.media.to_lowercase() == "audio"
658671
{
659672
self.negotiated_audio.store(true, Ordering::SeqCst);
660673
RTPCodecType::Audio
661-
} else if !self.negotiated_video.load(Ordering::SeqCst)
674+
} else if (!self.negotiated_video.load(Ordering::SeqCst)
675+
|| self.negotiate_multi_codecs.load(Ordering::SeqCst))
662676
&& media.media_name.media.to_lowercase() == "video"
663677
{
664678
self.negotiated_video.store(true, Ordering::SeqCst);

webrtc/src/api/setting_engine/mod.rs

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,7 @@ pub struct SettingEngine {
9999
//iceProxyDialer :proxy.Dialer,?
100100
pub(crate) udp_network: UDPNetwork,
101101
pub(crate) disable_media_engine_copy: bool,
102+
pub(crate) disable_media_engine_multiple_codecs: bool,
102103
pub(crate) srtp_protection_profiles: Vec<SrtpProtectionProfile>,
103104
pub(crate) receive_mtu: usize,
104105
pub(crate) mid_generator: Option<Arc<dyn Fn(isize) -> String + Send + Sync>>,
@@ -342,6 +343,16 @@ impl SettingEngine {
342343
self.disable_media_engine_copy = is_disabled;
343344
}
344345

346+
/// disable_media_engine_multiple_codecs disables the MediaEngine negotiating different codecs.
347+
/// With the default value multiple media sections in the SDP can each negotiate different
348+
/// codecs. This is the new default behvior, because it makes Pion more spec compliant.
349+
/// The value of this setting will get copied to every copy of the MediaEngine generated
350+
/// for new PeerConnections (assuming DisableMediaEngineCopy is set to false).
351+
/// Note: this setting is targeted to be removed in release 4.2.0 (or later).
352+
pub fn disable_media_engine_multiple_codecs(&mut self, is_disabled: bool) {
353+
self.disable_media_engine_multiple_codecs = is_disabled;
354+
}
355+
345356
/// set_receive_mtu sets the size of read buffer that copies incoming packets. This is optional.
346357
/// Leave this 0 for the default receive_mtu
347358
pub fn set_receive_mtu(&mut self, receive_mtu: usize) {

webrtc/src/api/setting_engine/setting_engine_test.rs

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -269,3 +269,15 @@ async fn test_setting_engine_set_disable_media_engine_copy() -> Result<()> {
269269

270270
Ok(())
271271
}
272+
273+
#[test]
274+
fn test_setting_engine_media_engine_and_mtu_flags() -> Result<()> {
275+
let mut s = SettingEngine::default();
276+
277+
s.disable_media_engine_multiple_codecs(true);
278+
assert!(s.disable_media_engine_multiple_codecs);
279+
280+
s.set_receive_mtu(1337);
281+
assert_eq!(1337, s.receive_mtu);
282+
Ok(())
283+
}

webrtc/src/peer_connection/peer_connection_internal.rs

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -121,10 +121,14 @@ impl PeerConnectionInternal {
121121
peer_connection_state: Arc::new(AtomicU8::new(RTCPeerConnectionState::New as u8)),
122122

123123
setting_engine: Arc::clone(&api.setting_engine),
124-
media_engine: if !api.setting_engine.disable_media_engine_copy {
125-
Arc::new(api.media_engine.clone_to())
126-
} else {
124+
media_engine: if api.setting_engine.disable_media_engine_copy {
127125
Arc::clone(&api.media_engine)
126+
} else {
127+
let cloned_media_engine = Arc::new(api.media_engine.clone_to());
128+
cloned_media_engine.set_multi_codec_negotiation(
129+
!api.setting_engine.disable_media_engine_multiple_codecs,
130+
);
131+
cloned_media_engine
128132
},
129133
interceptor,
130134
stats_interceptor,

0 commit comments

Comments
 (0)