Skip to content

webrtc/v4: renegotiation can generate invalid answer extmap when earlier m-sections use different extmap IDs than later ones #3417

@shushenghong

Description

@shushenghong

I think pion/webrtc v4.2.11 may generate an invalid answer during renegotiation when the same PeerConnection goes through this sequence:

  1. publish video track (mid 1, 0 is a data channel)
  2. unpublish video (remove track and stop tranceiver)
  3. publish audio (new sdp will remove mid 1 and add mid 2)
  4. publish video again (mid will be 0 2 3)

In my case, the browser's offer is valid, but the answer generated by Pion reassigns RTP header extension IDs in the new video m-section, and Chrome rejects the answer in
setRemoteDescription().

The browser error is:

InvalidAccessError: Failed to execute 'setRemoteDescription' on 'RTCPeerConnection':
Failed to set remote answer sdp:
Failed to update RTP header extensions for m-section with mid='3'.
RTP extension ID reassignment from urn:ietf:params:rtp-hdrext:sdes:mid
to http://www.ietf.org/id/draft-holmer-rmcat-transport-wide-cc-extensions-01 for ID 4.

### Environment

- github.com/pion/webrtc/v4 v4.2.11
- Browser: Chrome 147
- Scenario: browser publisher -> Pion

### Repro sequence

This happens on the same publish PeerConnection:

1. publish video
2. renegotiate to unpublish that video
3. renegotiate to publish audio
4. renegotiate again to publish video

The important detail is that after step 1 and step 2, the old video m-section still exists historically in the same PC, and later audio/video m-sections use different extmap ID
assignments.

### Offer/answer snippets

Earlier video offer/answer used extmaps like:

a=extmap:4 http://www.ietf.org/id/draft-holmer-rmcat-transport-wide-cc-extensions-01
a=extmap:9 urn:ietf:params:rtp-hdrext:sdes:mid
a=extmap:10 urn:ietf:params:rtp-hdrext:sdes:rtp-stream-id
a=extmap:11 urn:ietf:params:rtp-hdrext:sdes:repaired-rtp-stream-id

Later audio and new video offer use:

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

That offer is accepted by browsers.

However, the answer generated by Pion for the new video m-section becomes:

a=extmap:4 http://www.ietf.org/id/draft-holmer-rmcat-transport-wide-cc-extensions-01
a=extmap:9 urn:ietf:params:rtp-hdrext:sdes:mid
a=extmap:10 urn:ietf:params:rtp-hdrext:sdes:rtp-stream-id
a=extmap:11 urn:ietf:params:rtp-hdrext:sdes:repaired-rtp-stream-id
a=extmap:3 http://www.ietf.org/id/draft-holmer-rmcat-transport-wide-cc-extensions-01

So in the same answered m-section:

- id=4 is reassigned from offered sdes:mid to transport-cc
- transport-cc appears twice (id=4 and id=3)

Chrome rejects this answer immediately.

### Why I think this is a Pion issue

My understanding is that this is legal on the offer side, because extmap IDs are scoped per m-section, and different m-sections in the same PC can use different ID->URI mappings.

From reading the v4.2.11 source, my hypothesis is:

- negotiated header extensions are being merged into a PC-global map keyed only by extension ID
- an older video m-section's mapping (for example 4 -> transport-cc, 9 -> sdes:mid) leaks into later audio/video m-sections
- when Pion generates the answer for the later video m-section, it reuses stale extmap assignments from the earlier m-section

So this looks like extmap negotiation state is effectively tracked too globally, instead of per m-section / transceiver.

### Expected behavior

For the new video m-section, the answer should preserve the offer's extmap semantics, for example:

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=extmap:10 urn:ietf:params:rtp-hdrext:sdes:rtp-stream-id
a=extmap:11 urn:ietf:params:rtp-hdrext:sdes:repaired-rtp-stream-id

### Actual behavior

Pion generates an answer where extmap IDs are reassigned using stale mappings from an earlier m-section, and the browser rejects the answer.

Metadata

Metadata

Assignees

Labels

No labels
No labels

Type

No type
No fields configured for issues without a type.

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions