fix: VP8/H264 simulcast producer fails on mic change in Chrome 148+ (…#367
Closed
panov-va wants to merge 1 commit into
Closed
fix: VP8/H264 simulcast producer fails on mic change in Chrome 148+ (…#367panov-va wants to merge 1 commit into
panov-va wants to merge 1 commit into
Conversation
…RTP extension ID reassignment)
Author
|
Hi @ibc! Could you take a look at this PR, please? The new Chrome 148 behaviour breaks every mediasoup app I know of that has a similar flow, and the 148 beta is about to start rolling out to users. |
| // URI is rejected with "RTP extension ID reassignment not supported". | ||
| // | ||
| // Previously, extensions unsupported by the server were simply omitted | ||
| // from the synthetic answer. Chrome then considered their IDs "free" |
There was a problem hiding this comment.
If this is true, is it really the correct libwebrtc behaviour? Does it make sense to record the ID as assigned and at the same time consider it as free if the remote did not support it (i.e. excluded it from the answer).
Member
|
As per discussion and research in the issue ticket #368, let's mark this PR as draft since it's almost guaranteed that this is a bug/regression in libwebrtc. |
Member
|
Closing because thhe issue has been fixed in Chrome: |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Background
Chrome 148 ships libwebrtc commit 5788235 ("Consolidate RTP header extension validation in BaseChannel"), which enforces global uniqueness of extmap IDs for the lifetime of an
RTCPeerConnection. Once an ID is bound to a URI in any bundled m-section, it's recorded inhistorical_rtp_header_extensions_and cannot be reused for a different URI — not in later offer/answer exchanges, not in new m-sections. The violation surfaces as:…thrown from
setLocalDescription.Root cause
AnswerMediaSectionbuilds the synthetic SDP answer fromanswerRtpParameters.headerExtensions, i.e. the intersection of Chrome's offer and the server'srouterRtpCapabilities. Anything Chrome offered that the server doesn't support (video-layers-allocation00for simulcast,dependency-descriptorfor VP8/VP9) is dropped from the answer.That used to be fine. Under the new rules, those dropped extensions still get registered in Chrome's internal ID history when the offer is set as local description. When a later m-section needs to allocate IDs for audio extensions like
ssrc-audio-level, Chrome may pick an ID previously occupied by one of the dropped video extensions, and the strict check kills the renegotiation.For VP8/VP9 the problem was worse:
RemoteSdp.send()explicitly strippeddependency-descriptorfrom the answer afterAnswerMediaSectionhad already built it. Correct before, actively harmful now.Fix
src/handlers/sdp/MediaSection.ts— afterAnswerMediaSectionemits the confirmed (server-supported) extensions, a second pass writes back every remaining offer extension with no direction attribute (sendrecvper RFC 5285). Chrome registers the ID against its original URI and won't hand it out to anything else.src/handlers/sdp/RemoteSdp.ts— removed the post-processing step that strippeddependency-descriptorfor non-AV1/H264 codecs. It ran afterAnswerMediaSectionand silently undid the pinning on VP8/VP9.Why this is safe
dependency-descriptoris inrouterRtpCapabilitiesfor these codecs, so it already shows up inanswerRtpParameters.headerExtensionsand the first loop emits it as active. The deletedRemoteSdpfilter was a no-op here anyway: it only triggered whenddCodecwas missing (i.e. VP8/VP9).dependency-descriptornow appears in the answer as a pin-only entry. The server doesn't activate it (not inrouterRtpCapabilitiesfor these codecs) and ignores it. Chrome won't put the extension on VP8/VP9 packets either, since there's no SVC layer structure to describe. Net effect: the extmap ID is locked to the URI and nothing else changes.AnswerMediaSectionis shared withChrome111,Chrome74,Firefox120,Safari12,ReactNative106. Either they confirmed the extension (second loop skips it) or they dropped it themselves, in which case a pin entry in the synthetic answer is harmless.Reproduction (mediasoup-demo)
The stock demo UI doesn't let you pick devices individually, so:
enableWebcam()/enableMic().disableMic()thenenableMic()with a differentdeviceId.Without the patch,
setLocalDescriptionthrowsRTP extension ID reassignment not supported (dependency-descriptor → ssrc-audio-level). With it, the sequence goes through cleanly on both VP8 and H264.