Subject: [rtcweb] Clarification on simulcast and RID and RepairedRtpStreamId

From: Iñaki Baz Castillo <[email-masked]>
Date: Sat, 1 Dec 2018 13:04:06 +0100

Hi,

We are almost in 2019 and, personally, I don't know yet which the
proper/standard way for simulcast + RTX is.

Clearly, RID must be used to send simulcast so, instead of signaling
a=ssrc lines in the offer, the offerer signals a=rid values for all
the simulcast streams. The remote learns the associated SSRC upon
receipt of the first RTP packet by matching its RTP RID extension
value. This is clearly specified in
https://tools.ietf.org/html/draft-ietf-avtext-rid-09 and Firefox does
properly implement it.

Now, the issue is when adding RTX to simulcast streams. Theoretically
(if I'm not wrong) the sender should signal both the a=rid of media
streams and the a=rrid of their associated RTX streams, and then send
RTP RID in media RTP packets and RTP RepairedRtpStreamId in RTX RTP
packets.

NOTE: Not sure about a=rrid, I can't find it in any draft. So:

Q1: Is there any spec defining the SDP syntax to indicate
RepairedRtpStreamId values in the SDP?

Q2: Is THIS (RID + RepairedRtpStreamId) the proper way to go for
simulcast + RTX?

Also, when it comes to receive media with RTX it's clear that WebRTC
does not define how to receive simulcast streams for WebRTC clients
(browsers), so browsers must receive a single stream plus an optional
RTX stream.

In this case, as far as a=mid plus RTP MID extension is used (or
a=ssrc) signaled, there is zero need for RID. However, how is RTX
supposed to be signaled in this case? Chrome expects ""a=ssrc-group:
FID MEDIA_SSRC RTX_SSRC" in the remote SDP to be able to receive an
additional RTX stream.

Q3: Is this the way to go for receiving a single stream with RTX?

-- 
Iñaki Baz Castillo
<[email-masked]>

---

From: Sergio Garcia Murillo <[email-masked]>
Date: Sun, 2 Dec 2018 16:29:23 +0100

The value for the RepairedRtpStreamId is the same as the RtpStreamId 
which is negotiated in the a=rid value, so there is no further need for 
an a=rrid negotiation.

However, I have the doubt about the usage of the RepairedRtpStreamId as 
I have heard some opinions that the rtx could use also the RtpStreamId 
header and demultiplex media and rtx ssrcs via payload type. This would 
make sense as the rtx rfc states that the rtx packet should contain the 
same extensions as the original packet, so the RtpStreamId is copied by 
default by firefox in the rtx packet.

So I would like to get a clarification about what is the preferred way 
of implementing.

Also, when rid is not used I assume that the mid header extension should 
also be included in the rtx packet to be able to avoid ssrc negotiation. 
Should also mid have to be included when using simulcast (my assumption 
is that it is needed in order to differentiate between same rids in 
different mids).

Best regards
Sergio

---

From: Magnus Westerlund <[email-masked]>
Date: Mon, 3 Dec 2018 10:02:05 +0000

Hi,

I think what should really be done is to update RFC 4588 to recommend
that one uses RepairedStreamID to indicate the retransmission stream's
relation to the source stream for the same RTP session multiplexing
case. I also think there is a point to discuss the separate RTP session
multiplexing case and its SSRC usage.  This will however require one to
have a legacy discussion section for both these cases.

> RepairedRtpStreamId values in the SDP?

As Sergio stated, no needed for that as the ID value referenced are the
RID ID for the source stream.

> Q2: Is THIS (RID + RepairedRtpStreamId) the proper way to go for

Yes, if you would use the RFC 4588 format.

However, for FLEXFEC one doesn't need that at all as the repair packets
are self-describing. I have raised an question in PAYLOAD WG if flexfec
should be explicit about its non usage of RepairedStreamId. 

> Q3: Is this the way to go for receiving a single stream with RTX?
To attempt to restate your question. For RTP sessions, where there are a
single source media stream per Media Description in SDP (m= block) and
where there is explicit MID signalling and SSRC signalling, then one
will not need RepairedStreamId and can instead rely on explicit MID
signalling for the RTX stream?

I think no. I think using RepairedStreamId independent if there is
multiple source RTP streams or not per media description provides a more
consistent experience.

However, as noted at the start. The use of RepairedStreamId for RFC4588
RTX format is not well defined and how to handle and detect legacy. So,
I think an update should be done.

Cheers

Magnus Westerlund 

----------------------------------------------------------------------
Network Architecture & Protocols, Ericsson Research
----------------------------------------------------------------------
Ericsson AB                 | Phone  +46 10 7148287
Torshamnsgatan 23           | Mobile +46 73 0949079
SE-164 80 Stockholm, Sweden | mailto: [email-masked]
----------------------------------------------------------------------

---

From: Sergio Garcia Murillo <[email-masked]>
Date: Mon, 3 Dec 2018 11:11:55 +0100

On 03/12/2018 11:02, Magnus Westerlund wrote:
> consistent experience

How would that work, if we are not using simulcast, no rid will 
negotiated in the SDP (AFAIK) so we can't use RepairedStreamId and we 
will have to rely on mid header extension and pt multiplexing, right?

Best regards

Sergio

---

From: Magnus Westerlund <[email-masked]>
Date: Mon, 3 Dec 2018 12:44:38 +0000

On 2018-12-03 11:11, Sergio Garcia Murillo wrote:

How would that work, if we are not using simulcast, no rid will negotiated in the SDP (AFAIK) so we can't use RepairedStreamId and we will have to rely on mid header extension and pt multiplexing, right?

That is my point, that we should define that when using RFC 4588 RTX one should include RID and use the RepairedStreamID for dynamic bindings of the SSRCs even if one doesn't use Simulcast. That would be a stable and commonly operational solution.

The solution that Iñaki suggested still only works in a sub-set of conditions and you will still need to implement the dynamic late binding solution that is described in RFC4588. That will be the ultimate fallback.

Cheers

Magnus Westerlund

SE-164 80 Stockholm, Sweden | mailto: [email-masked]<mailto:[email-masked]>

---

From: Sergio Garcia Murillo <[email-masked]>
Date: Mon, 3 Dec 2018 14:36:32 +0100

On 03/12/2018 13:44, Magnus Westerlund wrote:
> That is my point, that we should define that when using RFC 4588 RTX 
> one should include RID and use the RepairedStreamID for dynamic 
> bindings of the SSRCs even if one doesn't use Simulcast. That would be 
> a stable and commonly operational solution.
>
>
Given than rid is not globally unique but unique per mid, the rtx packet 
would need to include the mid anyway, wouldn't rid be redundant for 
non-simulcast use case?

Best regards

Sergio

---

From: Iñaki Baz Castillo <[email-masked]>
Date: Mon, 3 Dec 2018 22:05:27 +0100

> would need to include the mid anyway, wouldn't rid be redundant for

All the streams (ssrcs) belonging to the same "source" and
"transceiver" should have the same MID.
MID should be used as the first demux mechanism to identify the
"source" or "transceiver".
Then inspect RID, ssrc and PT to match the exact media/RTX/FLEXFEC stream.

-- 
Iñaki Baz Castillo
<[email-masked]>

---

From: Sergio Garcia Murillo <[email-masked]>
Date: Mon, 3 Dec 2018 22:26:22 +0100

> Then inspect RID, ssrc and PT to match the exact media/RTX/FLEXFEC stream.
My point is that there is a single source in the transceiver/MID why 
should we add default RID and waste 2 more bytes in each media and rtx 
packet?

Best regards

Sergio

---

From: Iñaki Baz Castillo <[email-masked]>
Date: Mon, 3 Dec 2018 22:26:17 +0100

> should we add default RID and waste 2 more bytes in each media and rtx

Regardless what browsers do today, both MID and RID headers should be
just included in the first packets. The receiver is supposed to update
its ssrc table for faster matching.

NOTE: The sender should also resend MID and RID if the SSRC changed
because some RFCs state that SSRCs may conflict and things that
absolutely never happen.

-- 
Iñaki Baz Castillo
<[email-masked]>

---

From: Iñaki Baz Castillo <[email-masked]>
Date: Mon, 3 Dec 2018 22:30:33 +0100

> multiple source RTP streams or not per media description provides a more

So, you say that the receiver would receive both media and RTX streams
with same RID values, and then the receiver would decide whether it's
a media or a rtx packet based on PT, right?

> I think an update should be done.

Is that issue related to the fact that RTX packets are supposed to
also carry original packet header extensions?

Why is there any problem with 4588? This is just about the browser
adding RID to RTX packets. That breaks nothing in RFC 4588 (IMHO).

-- 
Iñaki Baz Castillo
<[email-masked]>

---

From: Magnus Westerlund <[email-masked]>
Date: Tue, 4 Dec 2018 09:04:18 +0000

> a media or a rtx packet based on PT, right?

Yes, but for the Repair stream I think the right thing would be to
replace the RtpStreamID with a RepairedStreamId SDES Item and header
extension as appropriate but with the same RID ID.

> also carry original packet header extensions?

That implications I actually hadn't thought about. But you are right
there is an issue here. 

So RFC 4588 says this:

   If the original RTP header carried an RTP header extension, the
   retransmission packet SHOULD carry the same header extension.  This
   header extension MUST be placed right after the fixed RTP header, as
   specified in RTP [3].  In this case, the retransmission payload
   header MUST be placed after the header extension.

So following that an implementation SHOULD include the RtpStreamID
header extension and the RFC is silent about adding additional ones. So
the reconstructed original packet needs to have the RtpStreamId header
extensio. However, some text on the use of RepairedRtpStreamId appears
required. Like that it should be added at certain cases, like first
sendings of an repair RTP stream (until know it be delivered) as well as
when endpoints join the session. The receiver also needs to know to
strip this particular header and not include it in those that are
attached to the reconstructed packet.

> adding RID to RTX packets. That breaks nothing in RFC 4588 (IMHO).

With the exception for the issue with the header extension related to
RepairedRTPStreamID above I agree nothing breaks. However, the late
binding mechanism in RFC4588 is actually problematic in some cases.
Where the RepairedRTPStreamId pointing to the relevant RID actually
supports dynamic in session rebinding and have no issues with multiple
outstanding NACK requests prior to learnt the binding. So this is a
superior mechanism that should be recommended for usage with RFC4588 RTX
in all new applications and possibly some old ones.

The legacy fallback story appears reasonably clear as there are several
signalling attributes one can key on that wouldn't be there unless one
supports this mechanism.

Cheers

Magnus Westerlund

---

From: Sergio Garcia Murillo <[email-masked]>
Date: Tue, 4 Dec 2018 10:30:21 +0100

> attached to the reconstructed packet.

Given that RFC 4588 already covers the inclusion of the original 
RTPStreamID header into the RTX packet and that FlexFEC will not use 
RapairedStreamId mechanism (as a single flex fec stream will be used for 
all protected media), I see no use at all for the RepairedStreamId 
header extension and related mechanisms at all.

Best regards

Sergio

---

From: Sergio Garcia Murillo <[email-masked]>
Date: Tue, 4 Dec 2018 10:39:04 +0100

> because some RFCs state that SSRCs may conflict and things that
Kind of agree, but from a theoretical point of view remember that we 
introduced MIDs/RIDs to cover rtp proxing/switching scenarios in which 
ssrc conflicts may happen, so in order to cover those scenarios the 
MIDs/RIDs values must be included in every packet. If we ignore that, 
then could just go back to ssrc signaling and avoid mids/rids 
completely, which I would be in favor of.

Best regards

Sergio

---

From: Magnus Westerlund <[email-masked]>
Date: Tue, 4 Dec 2018 09:57:50 +0000

> completely, which I would be in favor of.
However, an RTP middlebox has the freedom to introduce those header
extensions when switching. They do not need to be sent end-to-end all
the time. So after the initial establishment of them, I see it as the
central middlebox responsibility to ensure that they are included in the
down stream legs towards the conference participants. Also at least for
video introducing them only on reception of a FIR also makes sense.

Cheers 

Magnus Westerlund

---

From: Sergio Garcia Murillo <[email-masked]>
Date: Tue, 4 Dec 2018 11:05:01 +0100

> video introducing them only on reception of a FIR also makes sense.

Same could be said about changing the ssrc to avoid collisions and we 
would have avoided our selves to introduced all this new ids.

Best regards

Sergio

---

From: Magnus Westerlund <[email-masked]>
Date: Tue, 4 Dec 2018 10:51:56 +0000

> would have avoided our selves to introduced all this new ids.

I think you are significantly misrepresenting the reasons why RID's are
needed. The fact that we have multiple models for how RTP middleboxes
works is a significant contributing factor. The next is in RTP ancestry
as a non-centralized multi-party protocol, i.e. intended to work over
any source multicast. And as simulcast do implies a selection by the
middlebox that aspect do needs to be handled. A clean-slate approach
could possibly select another set of constraints and maybe be somewhat
simpler but not a lot.

I do note that also the MIDs and RIDs only have per signalling context
and may require translation between the various legs of the conference
in a multi-party one.

Cheers 

Magnus Westerlund

---

From: Sergio Garcia Murillo <[email-masked]>
Date: Tue, 4 Dec 2018 12:26:23 +0100

> and may require translation between the various legs of the conference

I disagree with several of those statements, but my intention was not to 
start a new discussion about the need of mids/rids, but the usage in RTX 
which I have not yet got a good answer.

Trying to get back to the discussion:

  * What headers should contain a RTX packet from a track added via
    addTrack or addTransceiver without encodings
  * What headers should contain an RTX packet from a track added via
    addTransceiver with several encoding+rids

Best regards

Sergio

---

From: Iñaki Baz Castillo <[email-masked]>
Date: Tue, 4 Dec 2018 12:34:15 +0100

On Tue, 4 Dec 2018 at 10:35, Sergio Garcia Murillo
<[email-masked]> wrote:
> MIDs/RIDs values must be included in every packet.

I don't think that rationale is correct. No need for MID/RID in
*every* packet, but just in the first ones (despite what browsers do).
Once magic SSRC conflict happens (AM I READY TALKING ABOUT SSRC
CONFLICT??) the sender should just choose a new SSRC and add MID/RID
in the next packets.

> If we ignore that,

Definitely signaling ssrcs instead of MID/RID is *much* easier for
anyone who has implemented this stuff. I'm still waiting for any good
reason to not signal ssrcs (NOTE: I do not believe in SSRC conflicts
and will not believe in it no matter which "RTP middlebox stuff"
rationale is given to me).

Said that, if we go that way (signal MID and RID instead of ssrcs)
it's ok as far as we can also properly signal simulcast + RTX, which
is not clear given the length of this thread.

-- 
Iñaki Baz Castillo
<[email-masked]>

---

From: Sergio Garcia Murillo <[email-masked]>
Date: Tue, 4 Dec 2018 12:48:57 +0100

> CONFLICT??) the sender should just choose a new SSRC and add MID/RID

Yes, they could be sent in all packets until the first received RTCP RR 
for that ssrc (to ensure binding on the received side) and then only on 
first packet of an intra frame for video.

> rationale is given to me).

+1

btw, I use an alternative approach for signaling back rids/ssrc 
association for chrome sdp mangling in order to havea single processing 
algo on the SFU (note the ssrc attribute on the rid which is completely 
valid accoding to the rid ABNF ;)

a=ssrc-group:FID 3267388881 2718767991
a=ssrc:3267388881 cname:jwLMsXS4a6eBfofC
a=ssrc:3267388881 msid:GSRze2SaLY9enVp5h3LslsdM0kD7cydbdFk3 
21715433-7804-4c4d-a269-dfc6a06470cd
a=ssrc:3267388881 mslabel:GSRze2SaLY9enVp5h3LslsdM0kD7cydbdFk3
a=ssrc:3267388881 label:21715433-7804-4c4d-a269-dfc6a06470cd
a=ssrc:2718767991 cname:jwLMsXS4a6eBfofC
a=ssrc:2718767991 msid:GSRze2SaLY9enVp5h3LslsdM0kD7cydbdFk3 
21715433-7804-4c4d-a269-dfc6a06470cd
a=ssrc:2718767991 mslabel:GSRze2SaLY9enVp5h3LslsdM0kD7cydbdFk3
a=ssrc:2718767991 label:21715433-7804-4c4d-a269-dfc6a06470cd
a=ssrc-group:FID 100 101
a=ssrc:100 cname:jwLMsXS4a6eBfofC
a=ssrc:100 msid:GSRze2SaLY9enVp5h3LslsdM0kD7cydbdFk3 
21715433-7804-4c4d-a269-dfc6a06470cd
a=ssrc:100 mslabel:GSRze2SaLY9enVp5h3LslsdM0kD7cydbdFk3
a=ssrc:100 label:21715433-7804-4c4d-a269-dfc6a06470cd
a=ssrc:101 cname:jwLMsXS4a6eBfofC
a=ssrc:101 msid:GSRze2SaLY9enVp5h3LslsdM0kD7cydbdFk3 
21715433-7804-4c4d-a269-dfc6a06470cd
a=ssrc:101 mslabel:GSRze2SaLY9enVp5h3LslsdM0kD7cydbdFk3
a=ssrc:101 label:21715433-7804-4c4d-a269-dfc6a06470cd
a=ssrc-group:FID 102 103
a=ssrc:102 cname:jwLMsXS4a6eBfofC
a=ssrc:102 msid:GSRze2SaLY9enVp5h3LslsdM0kD7cydbdFk3 
21715433-7804-4c4d-a269-dfc6a06470cd
a=ssrc:102 mslabel:GSRze2SaLY9enVp5h3LslsdM0kD7cydbdFk3
a=ssrc:102 label:21715433-7804-4c4d-a269-dfc6a06470cd
a=ssrc:103 cname:jwLMsXS4a6eBfofC
a=ssrc:103 msid:GSRze2SaLY9enVp5h3LslsdM0kD7cydbdFk3 
21715433-7804-4c4d-a269-dfc6a06470cd
a=ssrc:103 mslabel:GSRze2SaLY9enVp5h3LslsdM0kD7cydbdFk3
a=ssrc:103 label:21715433-7804-4c4d-a269-dfc6a06470cd
a=ssrc-group:SIM 3267388881 100 102
a=simulcast:send a;b;c
a=rid:a send ssrc=102
a=rid:b send ssrc=100
a=rid:c send ssrc=3267388881

> is not clear given the length of this thread.

Neither for non-simulcast scenarios

Best regards

Sergio

---

From: Iñaki Baz Castillo <[email-masked]>
Date: Tue, 4 Dec 2018 12:45:05 +0100

> video introducing them only on reception of a FIR also makes sense.

The problem here is well known and happens often in this WG: the lack
of proper layer separation in SDP / RTP. The thing is:

1) MID/RID is valid within the context of a transport, nothing else.
And a transport is hop by hop. The receiver (an endpoint, a SFU, a
MCU, whatever) checks packet MID and then packet RID/RRID to figure
out the corresponding "transceiver" or m section and the corresponding
stream (media, simulcast, RTX).

2) If the receiver is a SFU which is gonna multiplex such a "track"
with many others to send them to a receiver over a single transport
(Bundle) then MID/RID does not make any sense because MID is typically
"0" or "1" etc. So the SFU would need to rewrite MID for each receiver
or just not announce MID support at all in the other leg.

3) In the case of RTX this is much more easier: RTX is just hop by
hop. If there is a SFU in the middle, you don't send a RTX packet
directly to the endpoint. You send it to the SFU (assuming the SFU
sent you a NACK). The SFU "decodes" and stores it. If the receiver in
the other leg sends a NACK, the SFU encapsulates such a stored packet
into a new RTX packet and sends it to the receiver. So RTX is hop by
hop, and hence it does not make any sense to talk about reusing
MID/RID headers for same reasons given in 2).

-- 
Iñaki Baz Castillo
<[email-masked]>