webrtc
webrtc copied to clipboard
Add/remove track triggers endless on_negotiation_needed loop
If I use Chrome with the following steps:
- Add microphone track
- Remove microphone track
I get an endless loop of on_negotiation_needed.
Here are the relevant SDPs.
- (add track) Chrome -> webrtc-rs (OFFER)
m=audio 9 UDP/TLS/RTP/SAVPF 111 63 103 104 9 0 8 106 105 13 110 112 113 126
c=IN IP4 0.0.0.0
a=rtcp:9 IN IP4 0.0.0.0
a=ice-ufrag:ZBso
a=ice-pwd:ugprC0ILgibKFU7TutTPS+qe
a=ice-options:trickle
a=fingerprint:sha-256 B7:D5:86:B0:92:C6:A6:03:80:C8:59:47:25:EC:FF:3F:57:F5:97:EF:76:B9:AA:14:B7:8C:C9:B3:4D:CA:1B:0A
a=setup:actpass
a=mid:1
a=extmap:1 urn:ietf:params:rtp-hdrext:ssrc-audio-level
a=extmap:2 http://www.webrtc.org/experiments/rtp-hdrext/abs-send-time
a=extmap:3 http://www.ietf.org/id/draft-holmer-rmcat-transport-wide-cc-extensions-01
a=extmap:4 urn:ietf:params:rtp-hdrext:sdes:mid
a=sendonly
a=msid:9aeb7f33-5936-40e6-b8a2-efe256e7b7d6 e19a2e98-520c-4da1-a30f-2e00dd8ad70c
a=rtcp-mux
a=rtpmap:111 opus/48000/2
a=rtcp-fb:111 transport-cc
a=fmtp:111 minptime=10;useinbandfec=1
a=rtpmap:63 red/48000/2
a=fmtp:63 111/111
a=rtpmap:103 ISAC/16000
a=rtpmap:104 ISAC/32000
a=rtpmap:9 G722/8000
a=rtpmap:0 PCMU/8000
a=rtpmap:8 PCMA/8000
a=rtpmap:106 CN/32000
a=rtpmap:105 CN/16000
a=rtpmap:13 CN/8000
a=rtpmap:110 telephone-event/48000
a=rtpmap:112 telephone-event/32000
a=rtpmap:113 telephone-event/16000
a=rtpmap:126 telephone-event/8000
a=ssrc:142606332 cname:cM8EbrdiR9FwX+tt
a=ssrc:142606332 msid:9aeb7f33-5936-40e6-b8a2-efe256e7b7d6 e19a2e98-520c-4da1-a30f-2e00dd8ad70c
a=ssrc:142606332 mslabel:9aeb7f33-5936-40e6-b8a2-efe256e7b7d6
a=ssrc:142606332 label:e19a2e98-520c-4da1-a30f-2e00dd8ad70c
- webrtc-rs -> Chrome (ANSWER)
m=audio 9 UDP/TLS/RTP/SAVPF 111
c=IN IP4 0.0.0.0
a=setup:passive
a=mid:1
a=ice-ufrag:VvfSgSRxteUdZhzy
a=ice-pwd:mBuvzThvtcrjYjLCxsVDiKhIPGBbXjgD
a=rtcp-mux
a=rtcp-rsize
a=rtpmap:111 opus/48000/2
a=fmtp:111 minptime=10;useinbandfec=1
a=rtcp-fb:111 transport-cc
a=extmap:3 http://www.ietf.org/id/draft-holmer-rmcat-transport-wide-cc-extensions-01
a=recvonly
- (remove track) Chrome -> webrtc-rs (OFFER)
m=audio 9 UDP/TLS/RTP/SAVPF 111 63 103 104 9 0 8 106 105 13 110 112 113 126
c=IN IP4 0.0.0.0
a=rtcp:9 IN IP4 0.0.0.0
a=ice-ufrag:ZBso
a=ice-pwd:ugprC0ILgibKFU7TutTPS+qe
a=ice-options:trickle
a=fingerprint:sha-256 B7:D5:86:B0:92:C6:A6:03:80:C8:59:47:25:EC:FF:3F:57:F5:97:EF:76:B9:AA:14:B7:8C:C9:B3:4D:CA:1B:0A
a=setup:actpass
a=mid:1
a=extmap:1 urn:ietf:params:rtp-hdrext:ssrc-audio-level
a=extmap:2 http://www.webrtc.org/experiments/rtp-hdrext/abs-send-time
a=extmap:3 http://www.ietf.org/id/draft-holmer-rmcat-transport-wide-cc-extensions-01
a=extmap:4 urn:ietf:params:rtp-hdrext:sdes:mid
a=inactive
a=msid:9aeb7f33-5936-40e6-b8a2-efe256e7b7d6 e19a2e98-520c-4da1-a30f-2e00dd8ad70c
a=rtcp-mux
a=rtpmap:111 opus/48000/2
a=rtcp-fb:111 transport-cc
a=fmtp:111 minptime=10;useinbandfec=1
a=rtpmap:63 red/48000/2
a=fmtp:63 111/111
a=rtpmap:103 ISAC/16000
a=rtpmap:104 ISAC/32000
a=rtpmap:9 G722/8000
a=rtpmap:0 PCMU/8000
a=rtpmap:8 PCMA/8000
a=rtpmap:106 CN/32000
a=rtpmap:105 CN/16000
a=rtpmap:13 CN/8000
a=rtpmap:110 telephone-event/48000
a=rtpmap:112 telephone-event/32000
a=rtpmap:113 telephone-event/16000
a=rtpmap:126 telephone-event/8000
a=ssrc:142606332 cname:cM8EbrdiR9FwX+tt
a=ssrc:142606332 msid:9aeb7f33-5936-40e6-b8a2-efe256e7b7d6 e19a2e98-520c-4da1-a30f-2e00dd8ad70c
a=ssrc:142606332 mslabel:9aeb7f33-5936-40e6-b8a2-efe256e7b7d6
a=ssrc:142606332 label:e19a2e98-520c-4da1-a30f-2e00dd8ad70c
- webrtc-rs -> Chrome (ANSWER)
m=audio 9 UDP/TLS/RTP/SAVPF 111
c=IN IP4 0.0.0.0
a=setup:passive
a=mid:1
a=ice-ufrag:VvfSgSRxteUdZhzy
a=ice-pwd:mBuvzThvtcrjYjLCxsVDiKhIPGBbXjgD
a=rtcp-mux
a=rtcp-rsize
a=rtpmap:111 opus/48000/2
a=fmtp:111 minptime=10;useinbandfec=1
a=rtcp-fb:111 transport-cc
a=extmap:3 http://www.ietf.org/id/draft-holmer-rmcat-transport-wide-cc-extensions-01
a=inactive
In SDP 3 and 4 notice the a=inactive attribute in both offer and answer.
The problem is here
The transceiver flag is "stopped", the media sections still exist (mid=1), but are inactive. I'm unclear what the solution should be.
As a test to confirm, I tried to make this wrapper for get_by_mid, which fixes the problem – but is that correct?
fn get_active_by_mid<'a, 'b>(
search_mid: &'a str,
desc: &'b session_description::RTCSessionDescription,
) -> Option<&'b MediaDescription> {
if let Some(m) = get_by_mid(search_mid, desc) {
if m.attribute("inactive").is_some() {
return None;
}
return Some(m);
}
None
}