Possible to disable RTCP-XR in producer?

Continuing with the Kurento integration, with this pipeline:

Browser >--(WebRTC)--> mediasoup >--(RTP)--> Kurento (applies a filter)
                                             |
Browser <--(WebRTC)--< mediasoup <--(RTP)--<--

In the lower branch, mediasoup receives RTP from Kurento. On the Kurento side, we sent our SDP Offer and Kurento replied with this Answer:

v=0
o=- 3784038970 3784038970 IN IP4 192.168.1.19
s=Kurento Media Server
c=IN IP4 192.168.1.19
t=0 0
m=video 2200 RTP/AVPF 96
a=sendonly
a=rtpmap:96 VP8/90000
a=rtcp-fb:96 goog-remb
a=rtcp-fb:96 ccm fir
a=rtcp-fb:96 nack
a=rtcp-fb:96 nack pli
a=ssrc:2868176879 cname:user3008311439@host-6710c6df
a=rtcp:2201

All these fields are parsed and used to build an RtpSendParameters.

On the mediasoup side, a PlainRtpTransport is set up and produce() is called with those rtpParameters:

kmsRtpSendParameters: {
  "mid": null,
  "codecs": [
    {
      "mimeType": "video/VP8",
      "clockRate": 90000,
      "payloadType": 96,
      "rtcpFeedback": [
        {
          "type": "goog-remb"
        },
        {
          "type": "ccm",
          "parameter": "fir"
        },
        {
          "type": "nack"
        },
        {
          "type": "nack",
          "parameter": "pli"
        }
      ],
      "parameters": {}
    }
  ],
  "headerExtensions": [],
  "encodings": [
    {
      "ssrc": 2868176879
    }
  ],
  "rtcp": {
    "cname": "user3008311439@host-6710c6df",
    "reducedSize": false
  }
}

There is no mention of RTCP Extended Report support on the producer’s RtpSendParameters, but still some RTCP-XR are finding their way to Kurento (which from the underlying GStreamer library, prints a warning each and every time).

They appear in Wireshark as Receiver Report - Extended report (RFC 3611), and don’t seem to come from the browser, as I can only see them going from mediasoup to Kurento.

Is it possible to enforce that the producer does not send these RTCP-XR packets?

Just realized that I was testing with mediasoup 3.2; will check the latest version and see what happens.

EDIT - Upgraded to 3.3.8, didn’t change.

Those packets are generated by mediasoup in order to calculate the RTT of a producer. RTCP packets not implemented by an endpoint should be simply discarded, hence I would like to think that those GStreamer logs are configurable and can be filtered.

There is no official way to signal them in WebRTC.

Isn’t the presence of a=rtcp-xr attribute in the SDP Offer/Answer the official way to signal it in WebRTC?

Sadly the implementation in GStreamer has a hardcoded log message whenever an unknown RTCP message type is found. Not ideal, but that’s what it is right now. I think only later versions lowered the message level, but it is still hardcoded anyhow.

On a bit of a tangent: is reducedSize: false honored? The documentation seems to imply it isn’t, but I still put it in the params in hopes it’s just a confusing wording in the docs.

The problem here is that WebRTC endpoints do not announce support for RTCP Extended Reports (XR), defined in RFC 3611. But somehow WebRTC set of specs mandate support for it. So we cannot “just” enable it based on endpoint parameters because, if so, we wouldn’t enable it for Chrome or Firefox.

Anyway, RFC 3611 was written in in 2003, this is 16 years ago. mediasoup does not try to support super old RTP implementations. We assume and mandate some features even if they are not announced (such as RTCP XR, symmetric RTP and RTCP, and RTCP reduced-size).

For instance, RTCP reduced-size is defined in RFC 5506, which was written in 2009 (more than 10 years ago) and updates the RTP/AVPF profile (“Extended RTP Profile for Real-time Transport Control Protocol (RTCP)-Based Feedback”) defined in RFC 4585 written in 2006 (13 years ago) and mandatory to implement for any decent RTP stack.

If there was something producing real problems or issues in certain well known RTP endpoints or tools, we may do something to make them happy. But just adding optional support for enabling/disabling RTP/RTCP features defined more than 10 years ago is not in our goals (due to lack of time). Does is make sense?

BTW RTCP reduced-size is required for RTCP NACK to work:

https://tools.ietf.org/html/rfc5506#section-3.2

So we assume RTCP reduced-size regardless a=rtcp-rsize is not negotiated in the RTP parameters.

All I can see there is how RTCP reduced-size would help reduce bandwidth used by RTCP, they only mention one of the typical use cases where this reduction is a benefit, with NACK because if RTCP packets are smaller it means you can fit more NACK feedback per second in cases of high packet loss.

rtcp-rsize is definitely not required for NACK, indeed Kurento does not support rsize but NACKs are perfectly supported. Same for GStreamer implementation of webrtc, where the rtcp-rsize is supported, but is orthogonal to using reduced size. So I think it shouldn’t be forced in mediasoup.

Going back to the original point:

Just to add some more info, these rtcp-xr packets seem to be used, only experimentally, by Chrome starting from version 72, in screen sharing mode only, in a field test that they reckon is only temporary while a new standard message format is created for this purpose:

https://bugs.chromium.org/p/webrtc/issues/detail?id=9969

At this point I don’t want to discuss with you how mediasoup should be implemented; I can (and “SHOULD” as the RFC says) simply ignore these packets. But I’d appreciate some insights of why these are generated by mediasoup itself even when none of the peers are actually using them (eg. I observed these with Wireshark as part of a normal webcam-based Webrtc call, where rtcp xr is not being generated by Chrome at all, so why inject these packets from ms.)

Hi! So two subjects here:

Regarding rtcp-size and NACK:

Correct me if I’m wrong but AFAIU, if rtcp-rsize is not supported by the endpoint then mediasoup cannot send separate separate NACK feedbacks but just full RTCP compound packets that also contain NACK feedbacks (in addition to the mandatory Sender Report and Receiver Report entries), am I right?

If so, I’m pretty sure that having to generate a full compound packet when sending a NACK feedback cannot be good. From RFC 5506 section 3.3:

3.3. Benefits of Reduced-Size RTCP

As mentioned in the introduction, most advantages of using Reduced- Size RTCP packets exist in cases when the available RTCP bitrate is limited. This is because they can become substantially smaller than compound packets. A compound packet is forced to contain both an RR or an SR and the CNAME SDES item. The RR containing a report block for a single source is 32 bytes, an SR is 52 bytes. Both may be larger if they contain report blocks for multiple sources. The SDES packet containing a CNAME item will be 10 bytes plus the CNAME string length. Here, it is reasonable that the CNAME string is at least 10 bytes to get a decent collision resistance. If the recommended form of user@host is used, then most strings will be longer than 20 characters. Thus, a Reduced-Size RTCP can become at least 70-80 bytes smaller than the compound packet.

Being completely honest we don’t want to send NACK feedbacks within RTCP compound packets. IMHO it’s a complete no-sense (it would be a CPU and network killer) and any RTP endpoint supporting NACK is supposed to also support reduced-size.

Regarding RTCP XR:

I don’t know what those “XR reports with a type=42” are. In mediasoup we just implement the super standard TRR and DLRR XR types:

Those types are needed to calculate the RTT in a Producer (so mediasoup can calculate the RTT of a RTP stream received from an endpoint) and include an roundTripTime field in Producer stats. Note that for Consumer stats we don’t need any XR to calculate its RTT.

The type=42 RTCP XR you mention is, indeed, a hack or custom stuff used by Chromium to signal “the encoder target bitrate via RTCP”:

We are not doing that at all and we ignore RTCP XR packets with types different than 4 (RTT) and 5 (DLRR).

NOTE: mediasoup does just send separate NACKs to endpoints, but it does allow receiving full RTCP compound packets including NACKs.

Cool, also thanks for the links. I’ll study them.

Just out of curiosity then, I assume these TRR/DLRR packets that are sent out via RTCP-XR, require that the other peer understands them and replies with some answer? If that is the case, then Chrome does respond with an answer when it receives those packets?

I’m asking because I had never seen Chrome spontaneously send RTCP-XR by itself, so I’m wondering under what circumstances these packets are “enabled” inside Chrome.

Also this seems to make most sense in the WebrtcTransport; do you think it will have any negative effect if the other peer (i.e. Kurento) doesn’t support RTCP-XR in the case of PlainRtpTransport? (Kurento sending RTP to mediasoup in a potential scenario where both mediasoup and Kurento are not in the same host or local network) – (anyway I am pretty sure no other pure RTP implementation including FFmpeg or GStreamer have any support for rtcp-xr whatsoever)

AFAIU, mediasoup sends regular RTCP Receiver Report (related to a RTP stream in a Producer) to Chrome, and Chrome eventually sends a RTCP XR of type DLRR to mediasoup. By correlating some values in both packets, mediasoup can calculate the RTT of such a RTP stream.

However I’ll let this question to @jmillan because he knows more than me about this.

AFAIU Chrome just includes some field in its RTCP Receiver Report which depends on the RTCP XR type DLRR previously sent be mediasoup to Chrome.

As @jmillan said above, some RFC out there states that:

RTCP packets not implemented by an endpoint should be simply discarded

And yes, we could be more strict and just send those XR packets if the endpoint announces support for such a specific RTCP XR type in its RTP parameters/capabilities. However, WebRTC browsers do not account it in their SDPs.

Yes, we add a RTCP-XR RRT packet on each RTCP compound packet sent from the Producer (Along with the RR reports). Chrome sends us back a RTCP-XR DLRR in response of the previous one. That’s how you can calculate the RTT for non sending streams.

Than you very much for all the info; I take some things from this conversation:

  • I’ll look to add rtcp-rsize to Kurento ASAP

  • I’ll also backport the change in GStreamer that lowered the log level of the “unknown RTCP message” when an XR message arrives from the remote peer. It’s not a full solution because it’s still a hardcoded message, but at least it won’t appear as a worrying warning.

  • From this response by Iñaki:

it wasn’t explicit but I understood that mediasoup will indeed ignore the RtpSendParameters.rtcp.reducedSize: false param given to PlainRtpTransport.produce().

If that’s correct, I’d suggest clarifying it better in the documentation both that mediasoup will ignore it (in the param’s doc) and that rtcp-rsize is always enabled in mediasoup (in the param’s doc and also somewhere in the global mediasoup RTP doc)

oh, actually it’s already there:

:slight_smile: