Webrtc-pc: Missing CNAME in RID based simulcast offer

Created on 5 Mar 2019  路  29Comments  路  Source: w3c/webrtc-pc

Just wondering if the simulcast video SDP m= section should signal the CNAME into it or not.

Firefox

This is a video m= section with simulcast produced by Firefox:

m=video 51480 UDP/TLS/RTP/SAVPF 120 121 126 97
c=IN IP4 88.21.227.155
a=bundle-only
a=sendonly
a=extmap:3 urn:ietf:params:rtp-hdrext:sdes:mid
a=extmap:4 http://www.webrtc.org/experiments/rtp-hdrext/abs-send-time
a=extmap:5 urn:ietf:params:rtp-hdrext:toffset
a=extmap:6/sendonly urn:ietf:params:rtp-hdrext:sdes:rtp-stream-id
a=fmtp:126 profile-level-id=42e01f;level-asymmetry-allowed=1;packetization-mode=1
a=fmtp:97 profile-level-id=42e01f;level-asymmetry-allowed=1
a=fmtp:120 max-fs=12288;max-fr=60
a=fmtp:121 max-fs=12288;max-fr=60
a=ice-pwd:6542d3c9d4f263a124f4754980c4cdb6
a=ice-ufrag:b5b7831a
a=mid:1
a=msid:- {edaf93d8-5f50-0a49-9cf6-9dbf7e1c7caf}
a=rid:high1 send
a=rid:medium1 send
a=rid:low1 send
a=rtcp-fb:120 nack
a=rtcp-fb:120 nack pli
a=rtcp-fb:120 ccm fir
a=rtcp-fb:120 goog-remb
a=rtcp-fb:121 nack
a=rtcp-fb:121 nack pli
a=rtcp-fb:121 ccm fir
a=rtcp-fb:121 goog-remb
a=rtcp-fb:126 nack
a=rtcp-fb:126 nack pli
a=rtcp-fb:126 ccm fir
a=rtcp-fb:126 goog-remb
a=rtcp-fb:97 nack
a=rtcp-fb:97 nack pli
a=rtcp-fb:97 ccm fir
a=rtcp-fb:97 goog-remb
a=rtcp-mux
a=rtpmap:120 VP8/90000
a=rtpmap:121 VP9/90000
a=rtpmap:126 H264/90000
a=rtpmap:97 H264/90000
a=setup:actpass
a=simulcast: send rid=high1;medium1;low1
a=ssrc:3444738190 cname:{a35cb30a-6d20-3147-b3aa-b156114b1552}
a=ssrc:1693134513 cname:{a35cb30a-6d20-3147-b3aa-b156114b1552}
a=ssrc:3248117645 cname:{a35cb30a-6d20-3147-b3aa-b156114b1552}

It signals the CNAME value in a=ssrc lines:

a=ssrc:3444738190 cname:{a35cb30a-6d20-3147-b3aa-b156114b1552}
a=ssrc:1693134513 cname:{a35cb30a-6d20-3147-b3aa-b156114b1552}
a=ssrc:3248117645 cname:{a35cb30a-6d20-3147-b3aa-b156114b1552}

Chrome M74

However, since in Chrome M74 with rid based simulcast there is no a=ssrc lines (ok not needed since mid and rid do the work) we get no CNAME at all:

v=0
o=- 4475402510119283512 2 IN IP4 127.0.0.1
s=-
t=0 0
a=group:BUNDLE 0
a=msid-semantic: WMS ux6BnSURfcW7X6XyQIQGzpTQC9EIz7ZUCVXv
m=video 9 UDP/TLS/RTP/SAVPF 96 97 98 99 100 101 102 122 127 121 125 107 108 109 124 120 123 119 114 115 116
c=IN IP4 0.0.0.0
a=rtcp:9 IN IP4 0.0.0.0
a=ice-ufrag:SDCL
a=ice-pwd:/QejtpsepgzkUiGHdCj49NcL
a=ice-options:trickle
a=fingerprint:sha-256 05:18:EE:03:06:36:C5:E1:1F:BB:FA:1C:29:8A:5E:24:63:3D:0E:E4:EF:00:53:2B:6A:B0:D7:30:92:9E:24:13
a=setup:actpass
a=mid:0
a=extmap:14 urn:ietf:params:rtp-hdrext:toffset
a=extmap:13 http://www.webrtc.org/experiments/rtp-hdrext/abs-send-time
a=extmap:12 urn:3gpp:video-orientation
a=extmap:2 http://www.ietf.org/id/draft-holmer-rmcat-transport-wide-cc-extensions-01
a=extmap:11 http://www.webrtc.org/experiments/rtp-hdrext/playout-delay
a=extmap:6 http://www.webrtc.org/experiments/rtp-hdrext/video-content-type
a=extmap:7 http://www.webrtc.org/experiments/rtp-hdrext/video-timing
a=extmap:8 http://tools.ietf.org/html/draft-ietf-avtext-framemarking-07
a=extmap:9 http://www.webrtc.org/experiments/rtp-hdrext/color-space
a=extmap:3 urn:ietf:params:rtp-hdrext:sdes:mid
a=extmap:4 urn:ietf:params:rtp-hdrext:sdes:rtp-stream-id
a=extmap:5 urn:ietf:params:rtp-hdrext:sdes:repaired-rtp-stream-id
a=sendrecv
a=msid:ux6BnSURfcW7X6XyQIQGzpTQC9EIz7ZUCVXv 0a9aeb9a-f7bd-457a-a4ab-ac06e4b21f86
a=rtcp-mux
a=rtcp-rsize
a=rtpmap:96 VP8/90000
a=rtcp-fb:96 goog-remb
a=rtcp-fb:96 transport-cc
a=rtcp-fb:96 ccm fir
a=rtcp-fb:96 nack
a=rtcp-fb:96 nack pli
a=rtpmap:97 rtx/90000
a=fmtp:97 apt=96
a=rtpmap:98 VP9/90000
a=rtcp-fb:98 goog-remb
a=rtcp-fb:98 transport-cc
a=rtcp-fb:98 ccm fir
a=rtcp-fb:98 nack
a=rtcp-fb:98 nack pli
a=fmtp:98 profile-id=0
a=rtpmap:99 rtx/90000
a=fmtp:99 apt=98
a=rtpmap:100 VP9/90000
a=rtcp-fb:100 goog-remb
a=rtcp-fb:100 transport-cc
a=rtcp-fb:100 ccm fir
a=rtcp-fb:100 nack
a=rtcp-fb:100 nack pli
a=fmtp:100 profile-id=2
a=rtpmap:101 rtx/90000
a=fmtp:101 apt=100
a=rtpmap:102 H264/90000
a=rtcp-fb:102 goog-remb
a=rtcp-fb:102 transport-cc
a=rtcp-fb:102 ccm fir
a=rtcp-fb:102 nack
a=rtcp-fb:102 nack pli
a=fmtp:102 level-asymmetry-allowed=1;packetization-mode=1;profile-level-id=42001f
a=rtpmap:122 rtx/90000
a=fmtp:122 apt=102
a=rtpmap:127 H264/90000
a=rtcp-fb:127 goog-remb
a=rtcp-fb:127 transport-cc
a=rtcp-fb:127 ccm fir
a=rtcp-fb:127 nack
a=rtcp-fb:127 nack pli
a=fmtp:127 level-asymmetry-allowed=1;packetization-mode=0;profile-level-id=42001f
a=rtpmap:121 rtx/90000
a=fmtp:121 apt=127
a=rtpmap:125 H264/90000
a=rtcp-fb:125 goog-remb
a=rtcp-fb:125 transport-cc
a=rtcp-fb:125 ccm fir
a=rtcp-fb:125 nack
a=rtcp-fb:125 nack pli
a=fmtp:125 level-asymmetry-allowed=1;packetization-mode=1;profile-level-id=42e01f
a=rtpmap:107 rtx/90000
a=fmtp:107 apt=125
a=rtpmap:108 H264/90000
a=rtcp-fb:108 goog-remb
a=rtcp-fb:108 transport-cc
a=rtcp-fb:108 ccm fir
a=rtcp-fb:108 nack
a=rtcp-fb:108 nack pli
a=fmtp:108 level-asymmetry-allowed=1;packetization-mode=0;profile-level-id=42e01f
a=rtpmap:109 rtx/90000
a=fmtp:109 apt=108
a=rtpmap:124 H264/90000
a=rtcp-fb:124 goog-remb
a=rtcp-fb:124 transport-cc
a=rtcp-fb:124 ccm fir
a=rtcp-fb:124 nack
a=rtcp-fb:124 nack pli
a=fmtp:124 level-asymmetry-allowed=1;packetization-mode=1;profile-level-id=4d0032
a=rtpmap:120 rtx/90000
a=fmtp:120 apt=124
a=rtpmap:123 H264/90000
a=rtcp-fb:123 goog-remb
a=rtcp-fb:123 transport-cc
a=rtcp-fb:123 ccm fir
a=rtcp-fb:123 nack
a=rtcp-fb:123 nack pli
a=fmtp:123 level-asymmetry-allowed=1;packetization-mode=1;profile-level-id=640032
a=rtpmap:119 rtx/90000
a=fmtp:119 apt=123
a=rtpmap:114 red/90000
a=rtpmap:115 rtx/90000
a=fmtp:115 apt=114
a=rtpmap:116 ulpfec/90000
a=rid:0 send
a=rid:1 send
a=rid:2 send
a=simulcast:send 0;1;2

One may think that we can get the CNAME later by inspecting rtpSender.getParameters(), but it does not "work" (this may be a bug in libwebrtc M74, reported here):

videoRtpSender.getParameters().rtcp

// => {cname: "", reducedSize: true}

Spec and CNAME

JSEP does not mention CNAME at all. The only it says is:

Changes in draft-11:

o Clarified handling of RTP CNAMEs.

(well, it's not "clarified" at all, it's just that the word "CNAME" no longer appears in the draft...).

How is this supposed to work? Must the SDP offer include the used CNAME somewhere? If so, do we need some kind of new a=cname:xxxxxxx? Or is it just that signaling the CNAME is just optional and the remote is supposed to learn it by inspecting RTCP SDES packets and matching the media ssrc into them (which should have be learnt before via rid matching)?

question

All 29 comments

Why is a cname needed?
my understanding is that it helps associate and uniquely identify an rtp stream in case the ssrc changes, but that is exactly what rids + mids do.
specs do not indicate the use of cname in simulcast (or at all, according to op).
I would say that this is closely related to #1174 should we have "conflicting" or dual identifiers for streams.

Isn't CNAME used by receiving endpoints to synchronize different tracks (audio and video)? I assume the CNAME is unique per "participant" for a reason. A PeerConnection may receive multiple audio and video tracks with different ssrcs and MIDs, but the only way to know which ones of those tracks must be synchronized is by looking at the CNAME of them.

https://tools.ietf.org/html/draft-ietf-rtcweb-rtp-usage-26#section-4.9

Each RTP endpoint MUST have at least one RTCP CNAME, and that RTCP
CNAME MUST be unique within the RTCPeerConnection. RTCP CNAMEs
identify a particular synchronisation context, i.e., all SSRCs
associated with a single RTCP CNAME share a common reference clock.
If an endpoint has SSRCs that are associated with several
unsynchronised reference clocks, and hence different synchronisation
contexts, it will need to use multiple RTCP CNAMEs, one for each
synchronisation context.

Looks like it's mandated here: https://tools.ietf.org/html/draft-ietf-rtcweb-rtp-usage-26#section-4.9

The previous section mentions how ssrc should be mandated as well, incidentally.

Looks like it's mandated here: https://tools.ietf.org/html/draft-ietf-rtcweb-rtp-usage-26#section-4.9

The previous section mentions how ssrc should be mandated as well, incidentally.

"While support for signalled SSRC identifiers is mandated, their use
in an RTP session is OPTIONAL. Implementations MUST be prepared to
accept RTP and RTCP packets using SSRCs that have not been explicitly
signalled ahead of time."

I read that as "you need to be able to receive SDP with SSRC in it", but every implementation also needs to be prepared to receive SDP without SSRC.

Good catch, sorry for the noise!

@alvestrand said in blink-dev:

The CNAME is supposed to be the same for all sources, so picking any CNAME from any RTCP packet would do the trick.

Is this from the receiver perspective? I mean: if a PeerConnection is receiving ssrc 1 with audio and ssrc 2 with video, without CNAME in the remote SDP, and eventually it receives a RTCP compound packet with CNAME=AAA associated to ssrc 1 and CNAME=AAA associated to ssrc 2, is that enough for it to sync both tracks?

Hi @amithilbuch, just in case you are assuming that a=ssrc line with CNAME is useless, just try to send two video streams to Chrome M72 without signaling the CNAME in the remote SDP (but just a=ssrc lines with ssrc and msid information). And you will see that second video is never rendered even if the remote endpoint is sending proper RTCP SenderReports with SDES items containing the CNAME value.

This is:

  • Chrome M72
  • Unified-Plan
  • Just receiving media from a SFU.
  • Remote SDP with various m= sections.
  • a=ssrc lines in each m= section with just msid related info (cname not present).
  • Chrome renders first audio and first video.
  • Chrome DOES NOT render next audios/videos.

It seems to me that libwebrtc does depend on knowing CNAME value sin advance (this is, during SDP negotiation). Now, not sure what the spec(s) say about this.

And here more fun regarding Chrome and CNAME.

@ibc i am not assuming it is useless, i am trying to understand it's uses. i read that it uniquely identifies an rtp stream, and hence might be replaceable by rid + mid. i did not read about it being used to synchronize to different rtp streams to sync audio and video. if that is the use case for it, and there is no alternative (ex. as what @alvestrand suggested in blink-dev), then we will need it.
We will also need to understand if it can be signaled without ssrc, otherwise we need more spec work as well.
regarding capabilities of clients, i think this is where contributors (me included) need to work to have implementations fully spec-compliant. and if cname is optional, we should work to support that.

The CNAME has been reasonably controversial for a long time. It's been suggested (among other things) that it represent a MediaStream, because a MediaStream also tries to impose the requirement to synchronize. But it got rejected because the WebRTC client is free to move tracks between MediaStreams - so we ended up with the current language saying "all tracks from a WebRTC client must have the same CNAME" - indicating to anyone who cares about CNAME as a source of sync info that the WebRTC client has taken responsibility for all the synchronization that needs to be done.

The discussions also indicated that the actual use of CNAME to indicate synchronization contexts was not very widespread - it was in the spec, but people didn't care much.

When receiving an RTCP packet with a CNAME in it, I think you are in one of two situations:

  • You're able to assign it to a media section. In that case, all tracks are supposed to represent the same source, which means they're either synchronized, or you have a problem on your hands.

  • You're not able to assign it to a media section, in which case you've lost anyway.

Short version: CNAME is a feature mentioned in the specs, but a) sending the same CNAME on all RTP streams solves the problem for outgoing, and b) ignoring the CNAME entirely on incoming does no harm.

So I don't see a problem that needs solving here.

@alvestrand I'll properly read your comment later but, for now, just let me tell you a real problem:

  • Chrome (at least M72) requires a=ssrc lines with cname in order to match those SSRCs.
  • Using a=ssrc lines with any other "attribute" (such as msid, mslabel or label) does not work.

Use case:

  • PeerConnection receiving one video track (Unifien-Plan).
  • MID RTP header extension not negotiated by the remote party.
  • The remote media section has a=ssrc with msid "attribute" but there is no a=ssrc with cname "attribute".
  • The video is rendered.
  • Then the sender switches off the video.
  • We, the receiver, mark the remote m section with a=inactive.
  • The remote sends a new video track.
  • We get a new m= video section as before.
  • The new video is NOT rendered.
  • I think that the receiver is matching the stream by codec payloadType, so it finds the first m= video section which is "a=inactive" and just drops the RTP packets.

In the very same scenario, if I add a=ssrc lines with cname "attribute" instead of msid, then second video is properly rendered.

What I mean is that Chrome (libwebrtc) does use the a=ssrc with cname for matching SSRC in received packets, so the remote SDP MUST have that cname lines. And here we are discussing about not signaling them in the remote offer so the problem described above would happen.

@alvestrand here the issue report.

@alvestrand said:

Short version: CNAME is a feature mentioned in the specs, but a) sending the same CNAME on all RTP streams solves the problem for outgoing, and b) ignoring the CNAME entirely on incoming does no harm.

Once the bug has been (mostly) identified, can we please focus on whether knowing the CNAME (in advance via SDP or in runtime upon reception of RTCP SDES) is useful or not for synchronizing incoming tracks from the same source?

  • AFAIU RTP timestamp are the same for SSRC streams originated by the same source, so for example the mic and webcam tracks share both CNAME and RTP timestamps (more or less).
  • The receiver can then synchronize both audio and video tracks by "waiting" a bit for rendering audio if the video stream is being received with some delay.

That's the only CNAME use-case coming to my mind, and that can not be achieved via MID because MID values do not tell anything about who the source is. Said that, what I said above regarding "RTP timestamp are the same for SSRC streams originated by the same source" may be completely wrong and, if so, the rest of this comment does not make any sense.

In summary: Does libwebrtc use CNAME value for something in the receiver side?

NOTE: I've tested setting CNAME="foo" in the a=ssrc line of the remote SDP offer and then sending RTCP SDES chunks with CNAME=bar". Chrome does not mind at all.

Do you think it would be better to use a Lip Sync group (https://tools.ietf.org/html/rfc5888#section-7) instead for CNAME for stream synchronization?

This way CNAME can be completely ignored. JSEP already requires using LS groups exactly for that purpose.

Here is the problem:
https://cs.chromium.org/chromium/src/third_party/webrtc/pc/webrtc_sdp.cc?type=cs&sq=package:chromium&g=0&l=690
tracks are not created if there is no incoming cname.
that doesn't mean that if there is a cname, something is done with it... so this might be an easy fix.

Definitely using something like "a=group:LS 1 2" would help here. Now my question is: what are current WebRTC implementations use to synchronize tracks from the same source? Or is it just that they do not try to sync them at all?

My mistake, it gets fed into the RTCP cname property, so we would need to understand what happens when RTCP does not contain cname before fixing this.

My mistake, it gets fed into the RTCP cname property, so we would need to understand what happens when RTCP does not contain cname before fixing this.

I think we should split the issue into two items:

  1. Whether CNAME is required in the SDP. Obviously libwebrtc depends on it as you found here.
  2. Whether libwebrtc uses CNAME for something. Here I want to clarify that CNAME can be told in two ways:

    1. By signaling it in the SDP.

    2. By sending RTCP SDES items with CNAME to the receiver. Such a SDES also includes the media SSRC so the receiver can learn the stream CNAME in runtime. Said that, no idea if libwebrtc also "learns" the CNAME that way or just via SDP. And, anyway, no idea whether libwebrtc needs CNAME for something (other than matching SSRCs in the SDP) or not.

From a rather old comment by @alvestrand it uses msid:
https://bugs.chromium.org/p/webrtc/issues/detail?id=4667#c18

But that would mean msid and LS are redundant?

wow... I can't believe that. msid is just a WebRTC artifact to "associate" tracks within a MediaStream. It's just crazy that the RTP receptor depends on that to do sync stuff. What about if the source is not using MediaStream at all?

Does this also affect the sender? I mean, if I call twice to gUM (one for audio and one for video) and I don't "mix" them into the same MediaStream and I do not pass any MediaStream to addTransceiver, will libwebrtc not care much about sending both tracks in sync?

suppose you have a LS group and two msids which contradict each other...

ok, so I will use the CNAME as streamId to generate a=msid and a=ssrc:xxx msid lines with the same "media stream id".

From what I can see, libwebrtc is using msid to synchronize the RTP streams. CNAME is used for statistics only. "LS" groups are not supported. Based on the source code (https://cs.chromium.org/chromium/src/third_party/webrtc/call/audio_receive_stream.h?type=cs&q=sync_group&sq=package:chromium&g=0&l=123), there was an issue (https://bugs.chromium.org/p/webrtc/issues/detail?id=4762) to fix how synchronization works but this was since closed.

@fippo "LS" group should allow to specify synchronization context across multiple MediaStreams. Tracks withing MediaStream are always synchronized and LS group is redundant (unless remote does not support msid).

JSEP requires adding LS group to SDP and adding individual tracks to the appropriate LS group, including tracks in the same MediaStream. (https://tools.ietf.org/html/draft-ietf-rtcweb-jsep-26#section-5.2.1). As far as I can see current implementations are not compliant with JSEP draft.

I agree that LS is the way to go here. At least it does not depend on pure "Web" concepts (such as MediaStream).

@inaki Can we separate W3C and IETF specification issues from implementation bugs?

From a WebRTC 1.0 API perspective, the specification supports CNAME in the object model. Assuming that were to be provided, is it sufficient?

Hi @aboba, I assume you meant @ibc :)

In my case it's ok with just having CNAME in the object model. Whether it must be in the SDP or not is indeed another subject. Note that CNAME is (theoretically) also sent in RTCP Sender Reports (within a SDES item) so the receiver can correlate it with the media SSRC (already known via SDP or RID).

In the other side, libwebrtc fails to match incoming SSRCs if the remote SDP doe snot contain a=ssrc lines with "cname" attribute, but that's another story.

I'm not sure what change is being asked for here.
We've got cname as part of RTCRtcpParameters, which is a member of RTCRtpParameters, whch is the base dictionary for RTCRtpSendParameters and RTCRtpReceiveParameters, which can be read by getParameters() on their respective sender/receiver objects.

So you can figure out what CNAMEs are in use once the browser has started using them (and lack of support for this field is a browser bug).

As commented above, CNAMEs are not required to be signalled in SDP. If there exists a need to have them in SDP, draft-alvestrand-mmusic-simulcast-ssrc seems like a possible avenue, but this is a spec entirely outside the webrtc-pc specification, so shouldn't be tracked in this bugtracker.

Can we close this as "no change needed"?

@alvestrand, the current status is:

This is: right now if Chrome generates a SDP without a=ssrc:AAAAA cname:BBBBB, such a SDP cannot be consumed by other Chrome.

One may argue: _SDP m= sections without a=ssrc lines just happen in RID based simulcast, which is not browser-to-browser._

Well, in theory and even without any kind of simulcast, the browser should be able to generate a SDP offer without any a=ssrc line in any m= audio or video section. In fact, a=mid is good enough (having both parties RTP MID support). But Chrome will fail to match incoming RTP due to lack of a=ssrc:aaaaa cname:bbbb lines.

Said that, IMHO this should be discussed in Issue 10385: PeerConnection fails to match RTP streams if there is no a=ssrc line with CNAME attribute rather than here.

Was this page helpful?
0 / 5 - 0 ratings