NOTE
Looks like a regression in libwebrtc. See https://issues.webrtc.org/issues/503013383.
Bug
Starting with Chrome 148, producing a video simulcast track and then producing (or replacing) an audio track on the same send transport throws at setLocalDescription and permanently breaks the PeerConnection:
Failed to set local offer sdp: RTP extension ID reassignment not supported (video-layers-allocation00 → ssrc-audio-level)
VP8 hits a slightly different variant, typically when the mic is swapped after video is already published:
RTP extension ID reassignment not supported (dependency-descriptor → ssrc-audio-level)
Once either one fires, the send transport is toast — no further producers can be created on it.
Steps to reproduce
NOTE: See also these STR that are easier to test.
- Create a send transport and produce a video simulcast track (VP8 or H264).
- Produce an audio track on the same transport.
- Close the audio producer and produce again with a different
deviceId.
Step 3 throws the reassignment error.
Reproducible in mediasoup-demo with a small tweak: split the combined enable/disable flow into separate per-device buttons for webcam, mic, and mic selection.
Expected behaviour
Renegotiation goes through regardless of the order in which audio and video producers are created or replaced.
Environment
mediasoup-client: 3.18.8
- Browser: Chrome 148+ (confirmed on 148.0.7778.5 Beta; Chrome 147 stable is fine)
- Codec: VP8 and H264 simulcast
- OS: any
Root cause
Chrome 148 picked up libwebrtc commit 5788235 ("Consolidate RTP header extension validation in BaseChannel"), which adds a historical_rtp_header_extensions_ map on BaseChannel. Every extmap ID seen in a local offer is recorded there permanently, and any later setLocalDescription that binds the same ID to a different URI gets rejected.
AnswerMediaSection builds the synthetic answer only from extensions the server confirmed (answerRtpParameters.headerExtensions). Extensions Chrome offered but the server doesn't support — video-layers-allocation00 for simulcast, dependency-descriptor for VP8/VP9 — are dropped from the answer. Chrome still records their IDs in its history but treats them as "unconfirmed", so when a later m-section comes along it may hand those IDs to other extensions (e.g. ssrc-audio-level). The new strict check then rejects the whole renegotiation.
Fix
#367
NOTE
Looks like a regression in libwebrtc. See https://issues.webrtc.org/issues/503013383.
Bug
Starting with Chrome 148, producing a video simulcast track and then producing (or replacing) an audio track on the same send transport throws at
setLocalDescriptionand permanently breaks thePeerConnection:VP8 hits a slightly different variant, typically when the mic is swapped after video is already published:
Once either one fires, the send transport is toast — no further producers can be created on it.
Steps to reproduce
NOTE: See also these STR that are easier to test.
deviceId.Step 3 throws the reassignment error.
Reproducible in
mediasoup-demowith a small tweak: split the combined enable/disable flow into separate per-device buttons for webcam, mic, and mic selection.Expected behaviour
Renegotiation goes through regardless of the order in which audio and video producers are created or replaced.
Environment
mediasoup-client: 3.18.8Root cause
Chrome 148 picked up libwebrtc commit 5788235 ("Consolidate RTP header extension validation in BaseChannel"), which adds a
historical_rtp_header_extensions_map onBaseChannel. Every extmap ID seen in a local offer is recorded there permanently, and any latersetLocalDescriptionthat binds the same ID to a different URI gets rejected.AnswerMediaSectionbuilds the synthetic answer only from extensions the server confirmed (answerRtpParameters.headerExtensions). Extensions Chrome offered but the server doesn't support —video-layers-allocation00for simulcast,dependency-descriptorfor VP8/VP9 — are dropped from the answer. Chrome still records their IDs in its history but treats them as "unconfirmed", so when a later m-section comes along it may hand those IDs to other extensions (e.g.ssrc-audio-level). The new strict check then rejects the whole renegotiation.Fix
#367