├── .github └── workflows │ └── auto-publish.yml ├── .pr-preview.json ├── CODE_OF_CONDUCT.md ├── CONTRIBUTING.md ├── LICENSE.md ├── README.md ├── explainer.md ├── index.html ├── section13 ├── w3c.json ├── webrtc-extensions.js └── webrtc.css /.github/workflows/auto-publish.yml: -------------------------------------------------------------------------------- 1 | name: Validate and Auto Publish 2 | 3 | on: 4 | push: 5 | paths: 6 | - index.html 7 | branches: 8 | - main 9 | pull_request: {} 10 | 11 | jobs: 12 | validate-and-publish: 13 | name: Validate and Publish 14 | runs-on: ubuntu-latest # only linux supported at present 15 | steps: 16 | - uses: actions/checkout@v2 17 | - uses: w3c/spec-prod@v2 # use the action 18 | with: 19 | TOOLCHAIN: respec 20 | W3C_NOTIFICATIONS_CC: "dom@w3.org" 21 | VALIDATE_LINKS: false 22 | -------------------------------------------------------------------------------- /.pr-preview.json: -------------------------------------------------------------------------------- 1 | { 2 | "src_file": "index.html", 3 | "type": "respec" 4 | } 5 | -------------------------------------------------------------------------------- /CODE_OF_CONDUCT.md: -------------------------------------------------------------------------------- 1 | # Code of Conduct 2 | 3 | All documentation, code and communication under this repository are covered by the [W3C Code of Ethics and Professional Conduct](https://www.w3.org/Consortium/cepc/). 4 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | Contributions to this repository are intended to become part of Recommendation-track documents governed by the 2 | [W3C Patent Policy](https://www.w3.org/Consortium/Patent-Policy/) and 3 | [Software and Document License](https://www.w3.org/Consortium/Legal/copyright-software). To make substantive contributions to specifications, you must either participate 4 | in the relevant W3C Working Group or make a non-member patent licensing commitment. 5 | 6 | If you are not the sole contributor to a contribution (pull request), please identify all 7 | contributors in the pull request comment. 8 | 9 | To add a contributor (other than yourself, that's automatic), mark them one per line as follows: 10 | 11 | ``` 12 | +@github_username 13 | ``` 14 | 15 | If you added a contributor by mistake, you can remove them in a comment with: 16 | 17 | ``` 18 | -@github_username 19 | ``` 20 | 21 | If you are making a pull request on behalf of someone else but you had no part in designing the 22 | feature, you can remove yourself with the above syntax. 23 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | All documents in this Repository are licensed by contributors 2 | under the 3 | [W3C Software and Document License](https://www.w3.org/Consortium/Legal/copyright-software). 4 | 5 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # webrtc-extensions 2 | A repository for "WebRTC 1.1+" features. 3 | 4 | Latest version: https://w3c.github.io/webrtc-extensions/ 5 | 6 | This is the repository for webrtc-extensions. You're welcome to 7 | [contribute](CONTRIBUTING.md)! 8 | -------------------------------------------------------------------------------- /explainer.md: -------------------------------------------------------------------------------- 1 | ## Explainer 2 | 3 | ### Introduction 4 | 5 | This document explains [extensions to the WEBRTC specification](https://w3c.github.io/webrtc-extensions). This document contains a number of sections, each of which contains design details to one specific extension. 6 | 7 | ### RTCRtpContributingSource extensions on captureTimestamp and senderCaptureTimeOffset 8 | 9 | Authors: 10 | minyue@chromium.org 11 | hbos@chromium.org 12 | chxg@google.com 13 | 14 | Participate 15 | https://www.chromestatus.com/feature/5728533701722112 16 | 17 | #### Abstract 18 | 19 | This section explains the two new data fields in RTCRtpContributingSource, namely captureTimestamp and senderCaptureTimeOffset, see [here](https://w3c.github.io/webrtc-extensions/#rtcrtpcontributingsource-dictionary). They are introduced for audio-video synchronization and end-to-end delay measurements. These measurements are quality indices of a real-time communication system, and they can be well used for monitoring the performance of such a system and A/B testing of new features. The audio-video synchronization measurement may also be used for achieving audio-video synchronization by adjusting the playout delay of the audio or the video stream accordingly. 20 | 21 | The solution to audio-video synchronization and end-to-end delay measurements described here is particularly desired by systems, where an intermediate stream regenerator that terminates the streams originating from senders is involved. One example of this is an audio mixer. 22 | 23 | #### Introduction 24 | 25 | In simple real-time communication systems, which involves only a sender and a receiver, the RTCP scheme [RFC3550] allows estimation of round-trip time and thus end-to-end delay. 26 | However, in a more sophisticated system, where an intermediate stream regenerator is involved, the estimation of end-to-end delay becomes more difficult. For example, if audio mixing is performed on the server side, the server terminates inbound media streams, processes the media data, and then generates new outbound media streams with fresh synchronization information. 27 | 28 | The solution proposed in this document is based on a new RTP header extension, absolute capture time, which contains two data fields: 29 | * an absolute capture timestamp, which is stamped by the original capturer, and is supposed to be received untouched by the end receivers. 30 | * an estimated clock offset with respect to the capturer's clock, which is supposed to be read and updated by every intermediate sender. 31 | 32 | With the absolute capture timestamps, end receivers can accurately measure how synchronized the audio and video tracks are. With the `estimated clock offset`, which gets updated at each intermediate hop, end receivers can estimate their clock offset with respect to the capturer's clock, and then, together with the absolute capture timestamp, measure the end-to-end delay. 33 | 34 | The absolute capture time RTP header extension is defined [here](https://webrtc.org/experiments/rtp-hdrext/abs-capture-time). 35 | 36 | The two new data fields in RTCRtpContributingSource are to surface the two data fields in the absolute capture time RTP header extension. 37 | 38 | #### Goals 39 | 40 | * Facilitate calculation of audio video synchronization performance in real-time communication systems. 41 | * Facilitate calculation of end-to-end delay in real-time communication systems, particularly those that involve intermediate stream regenerators. 42 | 43 | ##### Non-goals 44 | 45 | This proposal does not aim for improving the accuracy of end-to-end delay measurement in real-time communication systems that can already measure it based on RTCP based schemes. 46 | 47 | #### [API 1]: captureTimestamp 48 | 49 | This specification adds captureTimestamp, type of DOMHighResTimeStamp, to the RTCRtpContributingSource dictionary. This surfaces the absolute capture timestamp in the absolute capture time RTP header extension, when it is present or can be extrapolated from previously received data, for the last rendered audio or video frame. It can be used for measuring audio video synchronization performance as illustrated in the following example code: 50 | 51 | [receiverAudio, receiverVideo] = peerconnection.getReceivers(); 52 | 53 | latestCaptureTimestampAudio = receiverAudio.getSynchronizationSources()[0].captureTimestamp; 54 | latestCaptureTimestampVideo = receiverVideo.getSynchronizationSources()[0].captureTimestamp; 55 | 56 | synchronizationError = latestCaptureTimestampAudio - latestCaptureTimestampVideo; 57 | 58 | #### [API 2]: senderCaptureTimeOffset 59 | 60 | This specification also adds senderCaptureTimeOffset, type of DOMHighResTimeStamp, to the RTCRtpContributingSource dictionary. In this context, the sender refers to the system that directly sends RTP and RTCP packets to the receiver, and thus the sender-receiver path only represents the "last hop" in a system that involves intermediate stream regenerators. 61 | 62 | An example code to use captureTimestamp and senderCaptureTimeOffset to calculate end-to-end delay: 63 | 64 | receiver = peerconnection.getReceivers()[0]; 65 | csrc = receiver.getSynchronizationSources()[0]; 66 | latestCaptureTimestamp = csrc.captureTimestamp; 67 | latestSenderCaptureTimeOffset = csrc.senderCaptureTimeOffset; 68 | receiverTimestamp = csrc.timestamp; 69 | 70 | // Calculates sender-receiver clock offset from stats. 71 | stats = peerconnection.getStats(); 72 | remoteOutboundRtpStats = getRequiredStats(stats, "remote-outbound-rtp"); 73 | remoteInboundRtpStats = getRequiredStats(stats, "remote-inbound-rtp") 74 | senderReceiverTimeOffset = remoteOutboundRtpStats.timestamp - (remoteOutboundRtpStats.remoteTimestamp + remoteInboundRtpStats.roundTripTime / 2); 75 | 76 | // Calcuates sender-capturer clock offset. 77 | captureReceiverTimeOffset = senderReceiverTimeOffset + latestSenderCaptureTimeOffset; 78 | 79 | receiverCaptureTimestamp = latestCaptureTimestamp + captureReceiverTimeOffset; 80 | endToEndDelay = receiverTimestamp - receiverCaptureTimestamp; 81 | 82 | #### Detailed design discussion 83 | 84 | ##### [Tricky design choice 1]: multiple ways to surface end-to-end delay 85 | 86 | The proposed solution is, as [API 2], to surface the sender-capture time offset as the raw data existing the absolute capture time RTP header extension. Then the calculation of end-to-end delay requires other data, as depicted in the code example in [API 2]. Alternatively, we can surface another derived quality, even just the end-to-end delay. However, for the sake of clarity and testability in the specification, it would be best to report the raw data. 87 | 88 | #### Considered alternatives 89 | 90 | We believe that given the choice of signaling protocol, the API suggested here is obvious. This section will sketch some of the other proposals for signaling protocols that have been considered and rejected over the development of this proposal. 91 | 92 | ##### [Alternative 1] Intermediate servers bake round-trip-time from capturer in its RTCP. 93 | 94 | If an intermediate server includes the one-way delay from the original capturer in the NTP timestamps in its RTCP packets, the end receiver does not have to care if there was a server in-between or not. The proposed way of updating the `estimated clock offset` with respect to the capturer's clock, as the second data in the absolute capture time RTP header extension, is based on the same principle. 95 | 96 | However, without the original capture timestamp, this method may fail if the intermediate server regenerates the stream and applies RTP timestamping that does not strictly follow the capturer's clock rate. A discussion of this scheme can be found [here](https://github.com/w3c/webrtc-stats/issues/537). 97 | 98 | ##### [Alternative 2] Audio Timing Header Extension 99 | 100 | In WebRTC, [video-timing](https://webrtc.org/experiments/rtp-hdrext/video-timing/) has been proposed as an experimental RTP header extension. We rejected the idea of reusing it for audio or adding an audio version of it, since it has a duration-based design that requires its header extension to be sent with every frame, hence consuming significantly more bandwidth than our timestamp-based design. 101 | 102 | ##### [Alternative 3] [RFC5484]: SMPTE Time-Code 103 | 104 | We rejected the proposal in [RFC5484] to use SMPTE time-codes. It seems needlessly complex for our use cases. It would also only help us solve the desynchronization metric problem, and not provide us with a solution for a one-way delay metric. 105 | 106 | ##### [Alternative 4] [RFC6051]: Rapid Synchronisation of RTP Flows 107 | 108 | We rejected the proposals in [RFC6051] since they cannot overcome the problem of synchronizing beyond mixers. The extended version of abs-capture-time does however borrow design elements from the RFC’s In-Band Delivery of Synchronisation Metadata section. 109 | 110 | #### Stakeholder Feedback / Opposition 111 | 112 | The proposal has been presented to W3C WG and browser implementers. While there is no signal from other implementers to implement this yet, the proposal has been reviewed without concerns raised. 113 | 114 | Real applications, Google Hangouts and Meet, for example, have been asking for reliable audio video synchronization and end-to-end delay measurements for several years, which we can back up with [discussions](https://github.com/w3c/webrtc-stats/issues/158) from 2017. 115 | 116 | #### References & acknowledgements 117 | 118 | * [RFC3550] Schulzrinne, H., Casner, S., Frederick, R. and V. Jacobson, "RTP: A 119 | Transport Protocl for Real-Time Applications", RFC 3550, July 2003. 120 | * [RFC5484] D. Singer, "Associating Time-Codes with RTP Streams", RFC 5484, March 2009. 121 | * [RFC6051] Perkins, C. and T. Schierl, "Rapid Synchronisation of RTP Flows", RFC 6051, November 2010. 122 | 123 | Many thanks for valuable feedback and advice from: 124 | Harald Alvestrand 125 | 126 | ### A new flag in RTCRtpEncodingParameters for adaptive packet rate 127 | 128 | Authors: 129 | minyue@chromium.org 130 | eladalon@chromium.org 131 | jakobi@google.com 132 | hbos@chromium.org 133 | 134 | Participate 135 | https://www.chromestatus.com/feature/5752004691361792 136 | https://github.com/w3c/webrtc-pc/issues/2300 137 | https://github.com/w3c/webrtc-pc/issues/2309 138 | 139 | #### Abstract 140 | This document provides an API for enabling/disabling a sender in a real-time audio-video call to adapt its audio packet rate to better utilize the network connection between the sender and other participants. 141 | 142 | #### Introduction 143 | Congestion control is a common way for real-time audio-video conferencing to achieve a good performance [1], because, without it, the senders in a call may send too much data and congest the network, thus degrading call quality. 144 | 145 | A common congestion control is to adapt the bitrate of the audio and/or the video streams according to an estimate of the link capacity of the network. This proposal is focused on the audio bitrate adaptation. The total bitrate of an audio stream equals 146 | 147 | total_birate = codec_bitrate + header_size * packet_rate, 148 | 149 | An audio codec compresses audio into a sequence of packets, each representing a frame of the audio, and the duration of a trunk is referred to as the packet time. The average bitrate of these packets is the codec bitrate. Then, depending on the protocols used for transmission, various layers of headers can be added to the packets, as an example, RTP [RFC3550], TURN [RFC5766], UDP [RFC768] and IP. These headers account for a significant portion of the total bitrate. With a packet rate of 50 (packets per second), the header rate can be as high as 37.6 kbps, which is equivalent to a codec rate for delivering a high quality full-band audio. 150 | 151 | Obviously, it is not ideal to only have a control on the codec bitrate. An efficient bitrate adaptation should also change the packet rate. The audio packet rate is analogous to the video frame rate, which also plays an important role in the video bitrate adaptation. 152 | 153 | Despite the great value of adapting packet rate, it can be difficult to ship the feature as default, since it may introduce interoperability problems. Although there seems to be no specifications to force a fixed packet rate, some implementations may have taken it as an assumption and may fail or perform suboptimally. Therefore the proposal is to add a new flag, [adaptivePTime](https://w3c.github.io/webrtc-extensions/#dom-rtcrtpencodingparameters-adaptiveptime), in RTCRtpEncodingParameters, so that RTC applications can enable adaptive packet rate. 154 | 155 | #### Goals 156 | Allow a sender in a real-time audio-video call to choose whether or not to enable adaptive packet rate. 157 | 158 | ##### Non-goals 159 | This document does not specify the algorithm for packet rate adaptation. The way to probe the link capacity and decide the packet rate is up to implementations. 160 | 161 | #### [API]: adaptivePTime 162 | Add adaptivePTime, type of boolean, to the RTCRtpEncodingParameters dictionary. It can be used for enabling adaptive packet rate. The choice of the name is due to the fact that ptime is a commonly used word for the audio packet interval, in the context of RTC, see, e.g., [RFC3264]. An example code of the usage of this flag follows: 163 | 164 | const pc = new RTCPeerConnection(); 165 | const { sender } = pc.addTransceiver('audio', { 166 | sendEncodings: [{ 167 | adaptivePTime: true 168 | }] 169 | }); 170 | 171 | #### Detailed design discussion 172 | ##### [Tricky design choice 1]: where to put the flag 173 | As an alternative to RTCRtpEncodingParameters, RTCConfiguration was considered to be the host of the adaptivePTime flag, see discussions [1](https://github.com/w3c/webrtc-pc/issues/2300) and [2](https://github.com/w3c/webrtc-pc/issues/2309). Consensus was reached that RTCRtpEncodingParameters is a better place since the flag can be set on a per RTCRtpSender basis. 174 | 175 | ##### [Tricky design choice 2]: the format of the API 176 | Another discussion was arround wether to expose the full control of packet rate, see [this](https://github.com/w3c/webrtc-pc/issues/2309), which was basically suggesting to use ptime, which had been proposed as a member in RTCRtpEncodingParameters, instead of adding a flag. This leaves the implementation of packet rate adaptation algorithm to the application developers, which gives them more flexibility but also brings difficulties to non-experts. Eventually, we decided to adopt the adaptivePTime, and also abondened the ptime, see [this](https://github.com/w3c/webrtc-pc/issues/2311), which means the implementation of packet rate adaptation algorithm is up to browsers. 177 | 178 | #### Considered alternatives 179 | ##### [Alternative 1] SDP parameter ptime 180 | We have considered using the parameter ptime as defined in Session Description Protocol (SDP)[RFC4566], and interpret the absence of it as allowing packet rate adaptation. But there are two problems 181 | 182 | * This will not guarantee interoperability, as the absence of ptime can be interpreted as a fixed default packet time by some implementations, e.g., Opus interpretes as a default packet time of 20 milliseconds [RFC7587]. 183 | 184 | * The parameter ptime is a receiver preference, and therefore, we need to munge the SDP, if we want to control the sender. SDP munging is discouraged. 185 | 186 | ##### [Alternative 2] New SDP parameter 187 | The effort of standardizing a new SDP parameter is large. Another drawback is that the SDP negotiation lacks dynamic nature, as it is difficult to re-configure during a call. 188 | 189 | #### Stakeholder Feedback / Opposition 190 | The need for an adaptive packet rate has been raised in a public discussion, and the concern on interoperability was also mentioned there. Mozilla has been involved in the discussions and seemed fine with the proposal. 191 | 192 | #### References & acknowledgements 193 | 194 | * [1] G. Carlucci, L. De Cicco, S. Holmer and S. Mascolo, "Congestion Control for Web Real-Time Communication," in IEEE/ACM Transactions on Networking, vol. 25, no. 5, pp. 2629-2642, Oct. 2017. 195 | * [RFC3550] Schulzrinne, H., Casner, S., Frederick, R., and V. Jacobson, "RTP: A Transport Protocol for Real-Time Applications", STD 64, RFC 3550, July 2003. 196 | * [RFC768] Postel, J., "User Datagram Protocol", STD 6, RFC 768, August 1980. 197 | * [RFC5766] Mahy, R., Matthews, P., and J. Rosenberg, "Traversal Using Relays around NAT (TURN): Relay Extensions to Session Traversal Utilities for NAT (STUN)", RFC 5766, April 2010. 198 | * [RFC3264] Rosenberg, J. and H. Schulzrinne, "An Offer/Answer Model with Session Description Protocol (SDP)", RFC 3264, June 2002. 199 | * [RFC4566] Handley, M., Jacobson, V., and C. Perkins, "SDP: Session Description Protocol", RFC 4566, July 2006. 200 | * [RFC7587] Spittka, J., Vos, K., and JM. Valin, "RTP Payload Format for the Opus Speech and Audio Codec", RFC 7587, June 2015. 201 | 202 | Many thanks for valuable feedback and advice from: 203 | Harald Alvestrand, Jan-Ivar Bruaroey, Philipp Hancke, Roman Shpount and Justin Uberti (in alphabetical order). 204 | -------------------------------------------------------------------------------- /index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | WebRTC Extensions 7 | 8 | 9 | 10 | 11 |
12 |

13 | This document defines a set of ECMAScript APIs in WebIDL to extend the WebRTC 1.0 API. 14 |

15 |
16 |
17 |

The API is based on preliminary work done in the W3C WEBRTC Working Group.

18 |
19 |
20 |

Introduction

21 |

22 | This document contains proposed extensions to the [[WEBRTC]] specification. 23 | Some of these extensions were originally included within the [[WEBRTC]] specification, 24 | but needed to be removed due to lack of implementation experience. Others were not 25 | sufficiently mature to be incorporated into that specification when they were developed, 26 | but were too small to warrant creation of a separate document. 27 |

28 |

29 | This document contains some sections extending one specific interface or dictionary in 30 | the base specification; in this case the extension is only described in an individual 31 | section. Where an extension affects multiple interfaces or dictionaries, a subsection 32 | in the "Overviews" section describes the extension as a whole, while normative text 33 | is provided in sections relating to the individual interfaces. 34 |

35 |

36 | As extensions mature and gain implementation experience, they may move from this document 37 | to the base specification if WG consensus emerges to do so. 38 |

39 |
40 |
41 |

This specification defines conformance criteria that apply to a single 42 | product: the user agent that implements the interfaces that it 43 | contains.

44 |

Conformance requirements phrased as algorithms or specific steps may be 45 | implemented in any manner, so long as the end result is equivalent. (In 46 | particular, the algorithms defined in this specification are intended to be 47 | easy to follow, and not intended to be performant.)

48 |

Implementations that use ECMAScript to implement the APIs defined in 49 | this specification MUST implement them in a manner consistent with the 50 | ECMAScript Bindings defined in the Web IDL specification [[WEBIDL]], as 51 | this specification uses that specification and terminology.

52 |
53 |
54 |

Terminology

55 |

56 | The following terms are defined in 57 | Absolute Capture Timestamp RTP header extension 58 | [[RTP-EXT-CAPTURE-TIME]]: 59 |

60 | 65 |

66 | The process of forming a candidate pair is defined in 67 | [[RFC8445]] Section 6.1.2.2. 68 |

69 |

70 | The process of nominating a candidate pair is defined in 71 | [[RFC8445]] Section 8.1.1. 72 |

73 |

74 | The process of freeing a candidate is defined in [[RFC8445]] Section 8.3. 75 |

76 | 77 |

78 | 80 | The following terms are defined in mediacapture-extensions 81 | video timestamp concepts 82 |

83 | 88 |
89 |
90 |

91 | Filtering ICE candidates with Content-Security-Policy 92 |

93 |

94 | The {{RTCPeerConnection}} interface is defined in [[WEBRTC]]. This document 95 | extends that interface by using Content-Security-Policy for ICE candidate 96 | filtering. 97 |

98 |
99 |

Modifications to existing procedures

100 | 101 |

Append the following paragraph to the 102 | administratively prohibited 103 | algorithm:

104 | 105 |

If 106 | should RTC connections be blocked for global? with the 107 | [=relevant global object=] of the {{RTCPeerConnection}} object in question 108 | returns `"Blocked"`, then all candidates MUST be 110 | administratively prohibited.

111 |
112 |
113 |
114 |

RTP header extension control

115 |

116 | RTP header extension control is an extension to {{RTCRtpTransceiver}} that allows 117 | to set and query the RTP header extensions supported and negotiated in SDP. 118 |

119 | The RTP header extension mechanism is defined in [[RFC8285]], with 120 | the SDP negotiation mechanism defined in section 5. It goes into some 121 | detail on the meaning of "direction" with regard to RTP header 122 | extensions, and gives a detailed procedure for negotiating RTP header 123 | extension IDs. 124 |

125 |

126 | This API extension gives the means to control the use and direction of 127 | RTP header extensions as documented in [[RFC8285]]. It does not 128 | influence the ID negotiation mechanism, except for being able to 129 | control the number of extensions offered. 130 |

131 |
132 |

133 | {{RTCRtpTransceiver}} interface extensions 134 |

135 |

136 | The {{RTCRtpTransceiver}} 137 | interface is defined in [[WEBRTC]]. This document extends that interface 138 | by adding an additional method and attribute in order to control negotiation of 139 | RTP header extensions. 140 |

141 |
 142 | partial dictionary RTCRtpHeaderExtensionCapability {
 143 |   required RTCRtpTransceiverDirection direction;
 144 | };
 145 | 
 146 | partial interface RTCRtpTransceiver {
 147 |   sequence<RTCRtpHeaderExtensionCapability> getHeaderExtensionsToNegotiate();
 148 |   undefined setHeaderExtensionsToNegotiate(
 149 |       sequence<RTCRtpHeaderExtensionCapability> extensions);
 150 |   sequence<RTCRtpHeaderExtensionCapability> getNegotiatedHeaderExtensions();
 151 | };
 152 |       
153 |

154 | Let 155 | {{RTCRtpTransceiver/[[HeaderExtensionsToNegotiate]]}} 156 | and 157 | {{RTCRtpTransceiver/[[NegotiatedHeaderExtensions]]}} 158 | be internal slots of the {{RTCRtpTransceiver}}, initialized as follows: 159 |

160 |
    161 |
  1. 162 |

    Set {{RTCRtpTransceiver/[[HeaderExtensionsToNegotiate]]}} to the 163 | platform-specific list of implemented RTP header extensions. The 164 | {{RTCRtpHeaderExtensionCapability/direction}} attribute for all 165 | extensions that are mandatory to use MUST be initialized to an 166 | appropriate value other than {{RTCRtpTransceiverDirection/"stopped"}}. 167 | The {{RTCRtpHeaderExtensionCapability/direction}} attribute for 168 | extensions that will not be offered by default in an initial offer MUST 169 | be initialized to {{RTCRtpTransceiverDirection/"stopped"}}.

    170 |

    The list of header extensions that MUST/SHOULD be 171 | supported is listed in [[RTCWEB-RTP]], section 5.2. The "mid" extension 172 | is mandatory to use when BUNDLE is in use, per [[BUNDLE]] section 173 | 9.1.

    174 |
  2. 175 |
  3. 176 |

    Set {{RTCRtpTransceiver/[[NegotiatedHeaderExtensions]]}} to an empty 177 | list.

    178 |
  4. 179 |
180 |
181 |
182 |

Modifications to existing procedures

183 |

184 | Make the following modifications to the 185 | set a session description 186 | algorithm: 187 |

188 | 232 |

233 | In the algorithms for generating initial offers in [[RTCWEB-JSEP]] section 5.2.1, 234 | replace "for each supported RTP header extension, an "a=extmap" line, as specified in 235 | [[RFC5285]], section 5" " with "For each RTP header extension "e" 236 | listed in {{RTCRtpTransceiver/[[HeaderExtensionsToNegotiate]]}} where {{RTCRtpHeaderExtensionCapability/direction}} is not {{RTCRtpTransceiverDirection/"stopped"}}, an "a=extmap" 237 | line, as specified in [[RFC5285]], section 5, with direction taken from "e"'s {{RTCRtpHeaderExtensionCapability/direction}} 238 | attribute." 239 |

240 |

241 | In the algorithm for generating subsequent offers in [[RTCWEB-JSEP]] section 5.2.2, replace "The 242 | RTP header extensions MUST only include those that are present in the most recent answer" 243 | with "For each RTP header extension listed in {{RTCRtpTransceiver/[[HeaderExtensionsToNegotiate]]}}, 244 | and where {{RTCRtpHeaderExtensionCapability/direction}} is not {{RTCRtpTransceiverDirection/"stopped"}}, generate 245 | an appropriate "a=extmap" line with "direction" set according to the rules of [[RFC5285]] 246 | section 6, considering the {{RTCRtpHeaderExtensionCapability/direction}} in {{RTCRtpTransceiver/[[HeaderExtensionsToNegotiate]]}} to indicate the 247 | answerer's desired usage". 248 |

249 |

250 | In the algorithm for generating initial answers in [[RTCWEB-JSEP]] section 5.3.1, replace "For 251 | each supported RTP header extension that is present in the offer" with "For each 252 | supported RTP header extension that is present in the offer and is also present in 253 | {{RTCRtpTransceiver/[[HeaderExtensionsToNegotiate]]}} with a {{RTCRtpHeaderExtensionCapability/direction}} different from {{RTCRtpTransceiverDirection/"stopped"}}, 254 | set the appropriate direction based on {{RTCRtpHeaderExtensionCapability/direction}} that does not exceed the direction in the offer". 255 |

256 |

257 | Since JSEP does not know about WebRTC internal slots, merging this change requires 258 | more work on a JSEP revision. 259 |

260 |
261 |
262 |

Methods

263 |
264 |
getHeaderExtensionsToNegotiate
265 |
266 |

Execute the following steps:

267 |
    268 |
  1. 269 |

    Let transceiver be the {{RTCRtpTransceiver}} that 270 | this method was invoked on.

    271 |
  2. 272 |
  3. 273 |

    Return 274 | transceiver.{{RTCRtpTransceiver/[[HeaderExtensionsToNegotiate]]}}.

    275 |
  4. 276 |
277 |
278 |
279 |
280 |
setHeaderExtensionsToNegotiate
281 |
282 |

Execute the following steps:

283 |
    284 |
  1. 285 |

    Let transceiver be the {{RTCRtpTransceiver}} that 286 | this method was invoked on.

    287 |
  2. 288 |
  3. 289 |

    Let extensions be the first argument of this 290 | method.

    291 |
  4. 292 |
  5. 293 |

    If the size of extensions does not match the size of 294 | transceiver.{{RTCRtpTransceiver/[[HeaderExtensionsToNegotiate]]}} 295 | [=exception/throw=] an {{InvalidModificationError}}. 296 |

    297 |
  6. 298 |
  7. 299 |

    For each index i of extensions, run the 300 | following steps:

    301 |
      302 |
    1. 303 |

      Let extension be the i-th element of 304 | extensions.

      305 |
    2. 306 |
    3. 307 |

      If 308 | extension.{{RTCRtpHeaderExtensionCapability/uri}} 309 | is not equal to the {{RTCRtpHeaderExtensionCapability/uri}} of 310 | the i-th element of 311 | transceiver.{{RTCRtpTransceiver/[[HeaderExtensionsToNegotiate]]}}, 312 | [=exception/throw=] an {{InvalidModificationError}}.

      313 |
    4. 314 |
    5. 315 |

      If 316 | extension.{{RTCRtpHeaderExtensionCapability/direction}} 317 | is not {{RTCRtpTransceiverDirection/"sendrecv"}} and 318 | {{RTCRtpHeaderExtensionParameters/uri}} indicates a 319 | mandatory-to-use attribute that is required to be both sent 320 | and received, [=exception/throw=] an 321 | {{InvalidModificationError}}.

      322 |
    6. 323 |
    7. 324 |

      If 325 | extension.{{RTCRtpHeaderExtensionCapability/direction}} 326 | is {{RTCRtpTransceiverDirection/"stopped"}} and 327 | {{RTCRtpHeaderExtensionCapability/uri}} indicates a 328 | mandatory-to-implement extension, [=exception/throw=] an 329 | {{InvalidModificationError}}.

      330 |
    8. 331 |
    9. 332 |

      If necessary, restrict 333 | extension.{{RTCRtpHeaderExtensionCapability/direction}} 334 | as to not exceed the user agent's capabilities for this 335 | extension.

      336 |
    10. 337 |
    338 |
  8. 339 |
  9. 340 |

    Set 341 | transceiver.{{RTCRtpTransceiver/[[HeaderExtensionsToNegotiate]]}} 342 | to extensions.

    343 |
  10. 344 |
345 |
346 |
347 |
348 |
getNegotiatedHeaderExtensions
349 |
350 |

Execute the following steps:

351 |
    352 |
  1. 353 |

    Let transceiver be the {{RTCRtpTransceiver}} that 354 | this method was invoked on.

    355 |
  2. 356 |
  3. 357 |

    Return 358 | transceiver.{{RTCRtpTransceiver/[[NegotiatedHeaderExtensions]]}}.

    359 |
  4. 360 |
361 |
362 |
363 |
364 |
365 |
366 |

367 | RTCRtpEncodingParameters extensions 368 |

369 |

370 | The {{RTCRtpEncodingParameters}} dictionary is defined in 371 | [[WEBRTC]]. This document extends that dictionary with 372 | additional members to control audio packetization. 373 |

374 |
partial dictionary RTCRtpEncodingParameters {
 375 |     RTCResolutionRestriction scaleResolutionDownTo;
 376 |     unsigned long            ptime;
 377 |     boolean                  adaptivePtime = false;
 378 | };
379 |
380 |

Dictionary {{RTCRtpEncodingParameters}} Members

381 |
382 |
383 | scaleResolutionDownTo of type {{RTCResolutionRestriction}} 384 |
385 |
386 |

The maximum dimensions at which to restrict this encoding.

387 |

When {{scaleResolutionDownTo}} is specified, the 388 | {{RTCRtpEncodingParameters/scaleResolutionDownBy}} value MUST be 389 | ignored. Instead, frames are sent according to the specified 390 | resolution restrictions: frames MUST NOT be upscaled.

391 |

When configuring parameters, the following validation MUST be 392 | performed if {{scaleResolutionDownTo}} is specified on any encoding or 393 | else {{RTCPeerConnection/addTransceiver()}} [= exception/throws =] a 394 | newly [= exception/created =] {{OperationError}} and 395 | {{RTCRtpSender/setParameters()}} [= reject|rejects =] with a newly 396 | [= exception/created =] {{InvalidModificationError}}:

397 |
    398 |
  • 399 |

    {{scaleResolutionDownTo}} is specified on all 400 | {{RTCRtpEncodingParameters/active}} encodings.

    401 |
  • 402 |
  • 403 |

    For each {{scaleResolutionDownTo}} value, both dimensions have 404 | a value greater than 0.

    405 |
  • 406 |
407 |
408 |
409 | ptime of type unsigned long 410 |
411 |
412 |

The preferred duration of media represented by a packet in milliseconds.

413 |
414 |

415 | {{RTCRtpEncodingParameters/ptime}} was moved from [[WEBRTC]] to 416 | this specification due to lack of support from implementers. It is 417 | therefore marked as a feature at risk. 418 |

419 |
420 |
421 |
422 | adaptivePtime of type boolean, 423 | defaulting to false. 424 |
425 |
426 |

Indicates whether this encoding MAY dynamically change 427 | the frame length. If the value is true, the 428 | user agent MAY use any valid frame length for any of its 429 | frames, and MAY change this at any time. Valid values are 430 | multiples of 10ms. If the maxptime attribute 431 | (defined in [[RFC4566]] Section 6) is specified, that maximum 432 | applies. If the value is false, the user agent 433 | MUST use a fixed frame length.

434 |

If {{adaptivePtime}} is set to true, 435 | {{ptime}} MUST NOT be set; otherwise, 436 | {{InvalidModificationError}} MUST be [=exception/throw|thrown=].

437 |

Using a longer frame length reduces the 438 | bandwidth consumption due to overhead, but does so at the cost 439 | of increased latency. Changing the frame length dynamically 440 | allows the user agent to adapt its bandwidth allocation strategy 441 | based on the current network conditions.

442 |
443 |
444 |
445 |
446 |
447 |

448 | The {{RTCResolutionRestriction}} dictionary. 449 |

450 |
dictionary RTCResolutionRestriction {
 451 |     unsigned long maxWidth;
 452 |     unsigned long maxHeight;
 453 | };
454 |
455 |

Dictionary {{RTCResolutionRestriction}} Members

456 |
457 |
458 | maxWidth of type unsigned long 459 |
460 |
461 |

The maximum width that frames will be encoded with. The 462 | restrictions are orientation agnostic, see note below. When scaling is 463 | applied, both dimensions of the frame MUST be downscaled using the 464 | same factor.

465 |
466 |
467 | maxHeight of type unsigned long 468 |
469 |
470 |

The maximum height that frames will be encoded with. The 471 | restrictions are orientation agnostic, see note below. When scaling is 472 | applied, both dimensions of the frame MUST be downscaled using the 473 | same factor.

474 |

475 | The restrictions being orientation agnostic means that they will 476 | automatically be adjusted to the orientation of the frame being 477 | restricted (portrait mode or landscape mode) by swapping width and 478 | height if necessary. This means that it does not matter if 1280x720 or 479 | 720x1280 is specified, both always result in the exact same scaling 480 | factor regardless of the orientation of the frame. 481 |

482 |
483 |
484 |
485 |
486 |
487 |

488 | {{RTCRtpSender}} {{RTCRtpSender/setParameters()}} extensions for requesting the generation of a key frame. 489 |

490 |

491 | The {{RTCRtpSender}}'s {{RTCRtpSender/setParameters()}} method is defined in 492 | [[WEBRTC]]. This document extends the optional second argument to request 493 | generation of a key frame by the encoder. 494 |

495 |
partial dictionary RTCSetParameterOptions {
 496 |   sequence<RTCEncodingOptions> encodingOptions = [];
 497 | };
 498 | 
 499 | dictionary RTCEncodingOptions {
 500 |   boolean keyFrame = false;
 501 | };
502 |
503 |

Dictionary {{RTCSetParameterOptions}} Members

504 |

505 | The {{RTCSetParameterOptions}} are extended by a sequence of {{RTCEncodingOptions}}, one for each encoding. 506 |

507 |
508 |
509 | encodingOptions of type sequence<{{RTCEncodingOptions}}>, defaulting to []. 510 |
511 |
512 |

513 | A sequence containing encoding options for each RTP encoding. 514 |

515 |
516 |
517 |
518 |
519 |

Dictionary {{RTCEncodingOptions}} Members

520 |

521 | {{RTCEncodingOptions}} is the WebRTC equivalent of {{VideoEncoderEncodeOptions}} in [[WebCodecs]]. 522 |

523 |
524 |
525 | keyFrame of type boolean, defaulting to false. 526 |
527 |
528 |

529 | When set to true, request that RTCRtpSender's encoder generates a keyframe for the encoding. 530 | The semantic of this boolean is similar to the RTCP FIR message described in [RFC5104], section 3.5.1. 531 |

532 |
533 |
534 |
535 |
536 |

{{RTCRtpSender}} {{RTCRtpSender/setParameters()}} modifications to existing procedures

537 |

538 | In the steps to call the {{RTCRtpSender/setParameters()}} method, 539 | let parameters be the method's first argument and let 540 | setParameterOptions be the method's second argument. 541 |

542 |

Append the following steps after the steps to validate the parameters:

543 | 555 |

In the steps to configure the media stack to use parameters, append the following step:

556 | 563 |

564 | {{RTCRtpSender/setParameters()}} does not wait for a key frame to be produced by the encoder. 565 |

566 |
567 |
568 |
569 |

570 | {{RTCIceTransport}} extensions 571 |

572 |

573 | The {{RTCIceTransport}} interface is defined in [[WEBRTC]]. This document extends that interface to allow an 574 | application to observe and affect certain actions that an ICE agent [[RFC5245]] performs. 575 |

576 |

577 | The [= ICE agent =] performs connectivity checks to identify valid candidate pairs on which it is possible to send 578 | and receive media and data. In order to conclude ICE processing, the [= ICE agent =] {{nominates}} a valid candidate 579 | pair as the selected candidate pair. Prior to nomination, any valid candidate pair may be used to send and receive data. 580 | Once 581 | a candidate pair is nominated successfully, only the selected candidate pair will be used to send and receive data. 582 | Changing 583 | the selected candidate pair after a successful nomination requires an ICE restart. 584 |

585 |

586 | When the [= ICE agent =] has [= formed =] a candidate pair, the [= user agent =] MUST [= queue a task =] to add a candidate pair: 588 |

589 |
    590 |
  1. 591 |

    592 | Let |connection:RTCPeerConnection| be the {{RTCPeerConnection}} object associated with this [= ICE agent =]. 593 |

    594 |
  2. 595 |
  3. 596 |

    597 | If connection.{{RTCPeerConnection/[[IsClosed]]}} is 598 | true, abort these steps. 599 |

    600 |
  4. 601 |
  5. 602 |

    603 | Let |candidatePair:RTCIceCandidatePair| be the result of [= creating an RTCIceCandidatePair =] with 604 | |local:RTCIceCandidate| and |remote:RTCIceCandidate|, representing the local and remote candidates of the [= formed =] 605 | pair respectively. 606 |

    607 |
  6. 608 |
  7. 609 |

    610 | Let |transport:RTCIceTransport| be the {{RTCIceTransport}} object associated with |candidatePair|. 611 |

    612 |
  8. 613 |
  9. 614 |

    615 | [=Assert=]: |transport|.{{RTCIceTransport/[[CandidatePairs]]}} does not [= list/contain =] |candidatePair|. 616 |

    617 |
  10. 618 |
  11. 619 |

    620 | [= list/Append =] |candidatePair| to |transport|.{{RTCIceTransport/[[CandidatePairs]]}}. 621 |

    622 |
  12. 623 |
  13. 624 |

    625 | [= Fire an event =] named 626 | {{RTCIceTransport/icecandidatepairadd}} at |transport|, using {{RTCIceCandidatePairEvent}}, 627 | with the {{RTCIceCandidatePairEvent/candidatePair}} attribute 628 | initialized to |candidatePair|. 629 |

    630 |
  14. 631 |
632 |

633 | When the [= ICE agent =] has picked a candidate pair to {{nominate}} as the selected candidate pair, the [= user 634 | agent =] 635 | MUST [= queue a task =] to nominate a 636 | candidate pair: 637 |

638 |
    639 |
  1. 640 |

    641 | Let |connection:RTCPeerConnection| be the {{RTCPeerConnection}} object associated with this [= ICE agent =]. 642 |

    643 |
  2. 644 |
  3. 645 |

    646 | If connection.{{RTCPeerConnection/[[IsClosed]]}} is 647 | true, abort these steps. 648 |

    649 |
  4. 650 |
  5. 651 |

    652 | Let |transport:RTCIceTransport| be the {{RTCIceTransport}} object associated with this candidate pair. 653 |

    654 |
  6. 655 |
  7. 656 |

    657 | Let |candidatePair:RTCIceCandidatePair| be the candidate pair which is being {{nominated}}. 658 |

    659 |
  8. 660 |
  9. 661 |

    662 | Set |transport|.{{RTCIceTransport/[[ProposalPending]]}} to true. 663 |

    664 |
  10. 665 |
  11. 666 |

    667 | Let |accepted:boolean| be the result of [= fire an event | firing an event =] named 668 | {{RTCIceTransport/icecandidatepairnominate}} at |transport|, using {{RTCIceCandidatePairEvent}}, with the 669 | {{Event/cancelable}} attribute initialized to true, and the {{RTCIceCandidatePairEvent/candidatePair}} attribute 670 | initialized to |candidatePair|. 671 |

    672 |
  12. 673 |
  13. 674 |

    675 | Set |transport|.{{RTCIceTransport/[[ProposalPending]]}} to false. 676 |

    677 |
  14. 678 |
  15. 679 |

    680 | If |accepted| is false, abort these steps and instruct the [= ICE agent =] to continue to perform connectivity checks. 681 |

    682 |
  16. 683 |
  17. 684 |

    685 | Otherwise, instruct the [= ICE agent =] to {{nominate}} the candidate pair indicated by |candidatePair|. 686 |

    687 |
  18. 688 |
689 |

690 | The [= ICE agent =] will continue to send data using |candidatePair| until instructed to use another candidate pair with {{RTCIceTransport/selectCandidatePair}}. 691 |

692 |
693 | The [= ICE agent =] can decide to remove a candidate pair for several reasons. Examples include: 694 | 705 |
706 |

707 | When the [= ICE agent =] has decided to remove a candidate pair, the [= user agent =] MUST [= queue a task =] to remove a candidate pair: 709 |

710 |
    711 |
  1. 712 |

    713 | Let |connection:RTCPeerConnection| be the {{RTCPeerConnection}} object associated with this [= ICE agent =]. 714 |

    715 |
  2. 716 |
  3. 717 |

    718 | If connection.{{RTCPeerConnection/[[IsClosed]]}} is 719 | true, abort these steps. 720 |

    721 |
  4. 722 |
  5. 723 |

    724 | Let |candidatePair:RTCIceCandidatePair| be the candidate pair which is being removed. 725 |

    726 |
  6. 727 |
  7. 728 |

    729 | Let |transport:RTCIceTransport| be the {{RTCIceTransport}} object associated with |candidatePair|. 730 |

    731 |
  8. 732 |
  9. 733 |

    734 | Let |cancelable:boolean| be true if the candidate pair is being removed in order to [= free =] an unused 735 | candidate, and 736 | false otherwise. 737 |

    738 |
  10. 739 |
  11. 740 |

    741 | Set |transport|.{{RTCIceTransport/[[ProposalPending]]}} to true. 742 |

    743 |
  12. 744 |
  13. 745 |

    746 | Let |accepted:boolean| be the result of [= fire an event | firing an event =] named 747 | {{RTCIceTransport/icecandidatepairremove}} at |transport|, using {{RTCIceCandidatePairEvent}}, with the 748 | {{Event/cancelable}} attribute initialized to cancelable, and the {{RTCIceCandidatePairEvent/candidatePair}} attribute 749 | initialized to |candidatePair|. 750 |

    751 |
  14. 752 |
  15. 753 |

    754 | Set |transport|.{{RTCIceTransport/[[ProposalPending]]}} to false. 755 |

    756 |
  16. 757 |
  17. 758 |

    759 | If |accepted| is false, instruct the [= ICE agent =] to not remove the candidate pair indicated by 760 | |candidatePair|, and instead continue to send and respond to ICE connectivity checks on the candidate pair as 761 | before. 762 |

    763 |
  18. 764 |
  19. 765 |

    766 | Otherwise (if |accepted| is true), run the following steps: 767 |

    768 |
      769 |
    1. 770 |

      771 | [= list/Remove =] |candidatePair| from |transport|.{{RTCIceTransport/[[CandidatePairs]]}}. 772 |

      773 |
    2. 774 |
    3. 775 |

      776 | Instruct the [= ICE agent =] to remove the candidate pair indicated by |candidatePair|. 777 |

      778 |
    4. 779 |
    780 |
  20. 781 |
782 |

783 | The {{RTCIceTransport}} object is extended by adding the following internal slots: 784 |

785 | 793 |
 794 |         partial interface RTCIceTransport {
 795 |           attribute EventHandler onicecandidatepairadd;
 796 |           attribute EventHandler onicecandidatepairremove;
 797 |           attribute EventHandler onicecandidatepairnominate;
 798 |           Promise<undefined> selectCandidatePair(RTCIceCandidatePair candidatePair);
 799 |           Promise<undefined> removeCandidatePair(RTCIceCandidatePair candidatePair);
 800 |         };
801 |
802 |

Attributes

803 |
804 |
805 | onicecandidatepairadd of type {{EventHandler}} 806 |
807 |
808 |

809 | The event type of this event handler is {{icecandidatepairadd}}, and is fired as part of 810 | the [= add a candidate pair =] algorithm. 811 |

812 |
813 |
814 | onicecandidatepairremove of type {{EventHandler}} 815 |
816 |
817 |

818 | The event type of this event handler is {{icecandidatepairremove}}, and is fired as part of 819 | the [= remove a candidate pair =] algorithm. 820 |

821 |
822 |
823 | onicecandidatepairnominate of type {{EventHandler}} 824 |
825 |
826 |

827 | The event type of this event handler is {{icecandidatepairnominate}}, and is fired as part 828 | of the [= nominate a candidate pair =] algorithm. 829 |

830 |
831 |
832 |
833 |
834 |

Methods

835 |
836 |
837 | selectCandidatePair 838 |
839 |
840 |

841 | The {{selectCandidatePair}} method attempts to select a different candidate pair to send data 842 | over. If successful, data will be sent on the provided candidate pair. 843 | It is meant to be called after the application defers the {{nomination}} of a candidate pair 844 | by cancelling the {{RTCIceTransport/icecandidatepairnominate}} event. 845 |

846 |

847 | When this method is invoked, the [= user agent =] MUST run the following steps: 848 |

849 |
    850 |
  1. 851 |

    852 | Let |connection:RTCPeerConnection| be the {{RTCPeerConnection}} object associated with [=this=]. 853 |

    854 |
  2. 855 |
  3. 856 |

    857 | If connection.{{RTCPeerConnection/[[IsClosed]]}} is 858 | true, [= exception/throw =] an {{InvalidStateError}}. 859 |

    860 |
  4. 861 |
  5. 862 |

    863 | If [=this=].{{RTCIceTransport/[[ProposalPending]]}} is true, [= exception/throw =] an {{InvalidStateError}}. 864 |

    865 |
  6. 866 |
  7. 867 |

    868 | If [=this=].{{RTCIceTransport/[[IceTransportState]]}} is either of 869 | {{RTCIceTransportState/"new"}}, {{RTCIceTransportState/"failed"}} or {{RTCIceTransportState/"closed"}}, [= 870 | exception/throw =] 871 | an {{InvalidStateError}}. 872 |

    873 |
  8. 874 |
  9. 875 |

    876 | Let |candidatePair:RTCIceCandidatePair| be the method's first argument. 877 |

    878 |
  10. 879 |
  11. 880 |

    881 | If [=this=].{{RTCIceTransport/[[CandidatePairs]]}} does not [= list/contain =] |candidatePair|, [= exception/throw =] a {{NotFoundError}}. 882 |

    883 |
  12. 884 |
  13. 885 |

    886 | Let |p:Promise| be a new promise. 887 |

    888 |
  14. 889 |
  15. 890 |

    891 | In parallel, instruct the [= ICE agent =] to use |candidatePair| to send data. 892 |

    893 |
      894 |
    1. 895 |

      896 | When the [= ICE agent =] has completed selecting |candidatePair|, [= queue a task =] to run the following steps: 897 |

      898 |
        899 |
      1. 900 |

        901 | Run the [=RTCIceTransport/change the selected candidate pair and state=] steps to update [=this=].{{RTCIceTransport/[[SelectedCandidatePair]]}} and [=this=].{{RTCIceTransport/[[IceTransportState]]}} as necessary and fire any associated events. 902 |

        903 |
      2. 904 |
      3. 905 |

        906 | Resolve p. 907 |

        908 |
      4. 909 |
      910 |
    2. 911 |
    912 |
  16. 913 |
  17. 914 |

    915 | Return p. 916 |

    917 |
  18. 918 |
919 |

920 | After changing the selected candidate pair, the controlling [= ICE agent =] may attempt to [= nominate the candidate 921 | pair =] as 922 | well to conclude ICE processing. The application may cancel the nomination to allow further changes to the selected 923 | candidate pair. 924 |

925 |
926 |
927 | removeCandidatePair 928 |
929 |
930 |

931 | The {{removeCandidatePair}} method removes the provided candidate pair. The [= ICE agent =] will stop sending and 932 | responding to ICE connectivity checks on the removed candidate pair, and it can no longer be used to send data for this 933 | transport. This method is meant to be called when the application wants to allow the [= ICE agent =] to [= free =] 934 | candidates that it no longer needs. 935 |

936 |

937 | When this method is invoked, the [= user agent =] MUST run the following steps: 938 |

939 |
    940 |
  1. 941 |

    942 | Let |connection:RTCPeerConnection| be the {{RTCPeerConnection}} object associated with [= this =]. 943 |

    944 |
  2. 945 |
  3. 946 |

    947 | If connection.{{RTCPeerConnection/[[IsClosed]]}} is 948 | true, [= exception/throw =] an 949 | {{InvalidStateError}}. 950 |

    951 |
  4. 952 |
  5. 953 |

    954 | If [= this =].{{RTCIceTransport/[[ProposalPending]]}} is true, [= exception/throw =] an 955 | {{InvalidStateError}}. 956 |

    957 |
  6. 958 |
  7. 959 |

    960 | If [= this =].{{RTCIceTransport/[[IceTransportState]]}} is either of {{RTCIceTransportState/"new"}}, {{RTCIceTransportState/"failed"}} or {{RTCIceTransportState/"closed"}}, [= exception/throw =] an {{InvalidStateError}}. 961 |

    962 |
  8. 963 |
  9. 964 |

    965 | Let |candidatePair:RTCIceCandidatePair| be the method's first argument. 966 |

    967 |
  10. 968 |
  11. 969 |

    970 | If [=this=].{{RTCIceTransport/[[CandidatePairs]]}} does not [= list/contain =] |candidatePair|, [= exception/throw =] a {{NotFoundError}}. 971 |

    972 |
  12. 973 |
  13. 974 |

    975 | [= list/Remove =] |candidatePair| from 976 | [=this=].{{RTCIceTransport/[[CandidatePairs]]}}. 977 |

    978 |
  14. 979 |
  15. 980 |

    981 | Let |p:Promise| be a new promise. 982 |

    983 |
  16. 984 |
  17. 985 |

    986 | In parallel, instruct the [= ICE agent =] to remove the candidate pair indicated by candidatePair. 987 |

    988 |
      989 |
    1. 990 |

      991 | When the [= ICE agent =] has completed the removal, [= queue a task =] to run the following steps: 992 |

      993 |
        994 |
      1. 995 |

        996 | [= Fire an event =] named {{RTCIceTransport/icecandidatepairremove}} at |transport|, using {{RTCIceCandidatePairEvent}}, with the {{Event/cancelable}} attribute initialized to false, and the {{RTCIceCandidatePairEvent/candidatePair}} attribute initialized to |candidatePair|. 997 |

        998 |
      2. 999 |
      3. 1000 |

        1001 | Resolve p. 1002 |

        1003 |
      4. 1004 |
      1005 |
    2. 1006 |
    1007 |
  18. 1008 |
  19. 1009 |

    1010 | Return p. 1011 |

    1012 |
  20. 1013 |
1014 |
1015 |
1016 |
1017 |
1018 |

1019 | RTCIceCandidatePairEvent 1020 |

1021 |

1022 | The {{RTCIceTransport/icecandidatepairadd}}, {{RTCIceTransport/icecandidatepairnominate}} and 1023 | {{RTCIceTransport/icecandidatepairremove}} events use the 1024 | {{RTCIceCandidatePairEvent}} interface. 1025 |

1026 |
1027 |
[Exposed=Window]
1028 |   interface RTCIceCandidatePairEvent : Event {
1029 |     constructor(DOMString type, RTCIceCandidatePairEventInit eventInitDict);
1030 |     readonly attribute RTCIceCandidatePair candidatePair;
1031 |   };
1032 |
1033 |

Constructors

1034 |
1035 |
RTCIceCandidatePairEvent.constructor()
1036 |
1037 |
1038 |
1039 |
1040 |

Attributes

1041 |
1042 |
1043 | candidatePair of type {{RTCIceCandidatePair}}, readonly 1044 |
1045 |
1046 |

1047 | The {{candidatePair}} attribute represents the candidate pair associated with the event. 1048 |

1049 |
1050 |
1051 |
1052 |
1053 |
1054 |
1055 |   dictionary RTCIceCandidatePairEventInit : EventInit {
1056 |     required RTCIceCandidatePair candidatePair;
1057 |   };
1058 |
1059 |

Dictionary RTCIceCandidatePairEventInit Members

1060 |
1062 |
1063 | candidatePair of type {{RTCIceCandidatePair}}, required 1064 |
1065 |
1066 |

1067 | The candidate pair announced by the event. 1068 |

1069 |
1070 |
1071 |
1072 |
1073 |
1074 |
1075 |

Modifications to existing procedures

1076 |

1077 | In the steps to [=RTCIceTransport/change the selected candidate pair and state=], if the selected candidate pair was changed, modify the first step to the following: 1078 |

1079 |
    1080 |
  1. 1081 | Let newCandidatePair be the [= list/item =] [= list/contained =] in |this|.{{RTCIceTransport/[[CandidatePairs]]}} whose {{RTCIceCandidatePair/local}} and {{RTCIceCandidatePair/remote}} attributes respectively [= candidate match | match =] the local and remote candidates of the indicated pair if one is selected, and null otherwise. 1082 |
  2. 1083 |
1084 |

1085 | The candidate match algorithm given two {{RTCIceCandidate}} |first:RTCIceCandidate| and 1086 | |second:RTCIceCandidate| is as follows: 1087 |

1088 |
    1089 |
  1. 1090 |

    1091 | If |first|.{{RTCIceCandidate/candidate}} is not [= string/identical to =] |second|.{{RTCIceCandidate/candidate}}, return false. 1092 |

    1093 |
  2. 1094 |
  3. 1095 |

    1096 | If either (but not both) of |first|.{{RTCIceCandidate/sdpMid}} and |second|.{{RTCIceCandidate/sdpMid}} is 1097 | null, return false. 1098 |

    1099 |
  4. 1100 |
  5. 1101 |

    1102 | If neither of |first|.{{RTCIceCandidate/sdpMid}} and |second|.{{RTCIceCandidate/sdpMid}} is null, and |first|.{{RTCIceCandidate/sdpMid}} is not [= string/identical to =] 1103 | |second|.{{RTCIceCandidate/sdpMid}}, return false. 1104 |

    1105 |
  6. 1106 |
  7. 1107 |

    1108 | If either (but not both) of |first|.{{RTCIceCandidate/sdpMLineIndex}} and |second|.{{RTCIceCandidate/sdpMLineIndex}} is 1109 | null, return false. 1110 |

    1111 |
  8. 1112 |
  9. 1113 |

    1114 | If neither of |first|.{{RTCIceCandidate/sdpMLineIndex}} and |second|.{{RTCIceCandidate/sdpMLineIndex}} is null and |first|.{{RTCIceCandidate/sdpMLineIndex}} is not equal to 1115 | |second|.{{RTCIceCandidate/sdpMLineIndex}}, return false. 1116 |

    1117 |
  10. 1118 |
  11. 1119 |

    1120 | If either (but not both) of |first|.{{RTCIceCandidate/usernameFragment}} and |second|.{{RTCIceCandidate/usernameFragment}} is 1121 | null, return false. 1122 |

    1123 |
  12. 1124 |
  13. 1125 |

    1126 | If neither of |first|.{{RTCIceCandidate/usernameFragment}} and |second|.{{RTCIceCandidate/usernameFragment}} is null and |first|.{{RTCIceCandidate/usernameFragment}} is not [= string/identical to =] 1127 | |second|.{{RTCIceCandidate/usernameFragment}}, return false. 1128 |

    1129 |
  14. 1130 |
  15. 1131 |

    1132 | Return true. 1133 |

    1134 |
  16. 1135 |
1136 |
1137 |
1138 |
1139 |

1140 | {{RTCRtpContributingSource}} extensions 1141 |

1142 |

1143 | The {{RTCRtpContributingSource}} dictionary is defined in [[WEBRTC]]. This 1144 | document extends that dictionary by adding two additional members. 1145 |

1146 |

1147 | In this section, the capture system refers to the system where 1148 | media is sourced from and the sender system refers to the 1149 | system that is sending RTP and RTCP packets to the 1150 | receiver system where {{RTCRtpContributingSource}} data is 1151 | populated. 1152 |

1153 |

1154 | In a direct connection, the capture system is the same as the 1155 | sender system. But when one or more RTCP-terminating intermediate 1156 | systems (e.g. mixers) are involved this is not the case. In such cases, 1157 | media is sourced from the capture system, may be relayed through a 1158 | number of intermediate systems and is then finally sent from the 1159 | sender system to the receiver system. The 1160 | sender system-receiver system path only represents the 1161 | "last hop". 1162 |

1163 |

1164 | Despite {{RTCRemoteInboundRtpStreamStats.roundTripTime}} 1165 | measurements only accounting for the "last hop", one-way delay from the 1166 | [=capture system=]'s time of capture to the [=receiver system=]'s 1167 | time of playout can be estimated if the 1168 | [=Absolute Capture Timestamp RTP header extension=] is used all hops of 1169 | the way, where each RTCP-terminating intermediate system appropriately 1170 | updates the [=estimated capture clock offset=]. 1171 |

1172 |
partial dictionary RTCRtpContributingSource {
1173 |   DOMHighResTimeStamp captureTimestamp;
1174 |   DOMHighResTimeStamp senderCaptureTimeOffset;
1175 | };
1176 |
1177 |

Dictionary {{RTCRtpContributingSource}} Members

1178 |
1179 |
captureTimestamp of type {{DOMHighResTimeStamp}}.
1180 |
1181 |

1182 | The {{captureTimestamp}} is the timestamp that, the most recent frame 1183 | (from an RTP packet originating from this source) delivered to the 1184 | {{RTCRtpReceiver}}'s {{MediaStreamTrack}}, was originally captured. 1185 | Its reference clock is the capture system's NTP clock (same 1186 | clock used to generate NTP timestamps for RTCP sender reports on that 1187 | system). 1188 |

1189 |

1190 | On populating this member, the user agent MUST run the following 1191 | steps: 1192 |

1193 |
    1194 |
  1. 1195 |

    If the relevant RTP packet contains the 1196 | Absolute Capture Timestamp RTP header extension, return the 1197 | value of the absolute capture timestamp field and abort 1198 | these steps.

    1199 |
  2. 1200 |
  3. 1201 |

    Otherwise, if the relevant RTP packet does not contain the 1202 | Absolute Capture Timestamp RTP header extension but a 1203 | previous RTP packet did, return the result of calculating the 1204 | absolute capture timestamp according to 1205 | timestamp interpolation and abort these steps.

    1206 |
  4. 1207 |
  5. 1208 | Otherwise, return undefined. 1209 |
  6. 1210 |
1211 |

1212 | If multiple receiving tracks are sourced from the same 1213 | capture system, two {{captureTimestamp}}s can be used to 1214 | accurately measure audio-video synchronization since both timestamps 1215 | are based on the same system's clock. 1216 |

1217 |
1218 |
senderCaptureTimeOffset of type {{DOMHighResTimeStamp}}.
1219 |
1220 |

1221 | The {{senderCaptureTimeOffset}} is the sender system's 1222 | estimate of the offset between its own NTP clock and the 1223 | capture system's NTP clock, for the same frame that the 1224 | {{captureTimestamp}} was originated from. 1225 |

1226 |

1227 | On populating this member, the user agent MUST run the following 1228 | steps: 1229 |

1230 |
    1231 |
  1. 1232 |

    If the relevant RTP packet contains the 1233 | Absolute Capture Timestamp RTP header extension and the 1234 | estimated capture clock offset field is present, return the 1235 | value of the estimated capture clock offset field and abort 1236 | these steps.

    1237 |
  2. 1238 |
  3. 1239 |

    Otherwise, if the relevant RTP packet does not contain the 1240 | Absolute Capture Timestamp RTP header extension's 1241 | estimated capture clock offset field, but a 1242 | previous RTP packet did, return the most recent value that was 1243 | present and abort these steps.

    1244 |
  4. 1245 |
  5. 1246 | Otherwise, return undefined. 1247 |
  6. 1248 |
1249 |

1250 | The time of capture can estimatedly be expressed in the 1251 | sender system's clock as follows: 1252 | senderCaptureTimestamp = {{captureTimestamp}} + 1253 | {{senderCaptureTimeOffset}}. 1254 |

1255 |

1256 | The offset between the sender system's clock and the 1257 | receiver system's clock can be estimated as follows: 1258 | senderReceiverTimeOffset = 1259 | {{RTCRemoteOutboundRtpStreamStats}}.timestamp}} - 1260 | ({{RTCRemoteOutboundRtpStreamStats.remoteTimestamp}} + 1261 | {{RTCRemoteInboundRtpStreamStats.roundTripTime}} / 2). 1262 |

1263 |

1264 | The time of capture can estimatedly be expressed in the 1265 | receiver system's clock as follows: 1266 | receiverCaptureTimestamp = senderCaptureTimestamp + 1267 | senderReceiverTimeOffset. 1268 |

1269 |

1270 | The one-way delay between the capture system's time of capture 1271 | and the receiver system's time of playout can be estimated as 1272 | follows: 1273 | {{RTCRtpContributingSource.timestamp}} - 1274 | receiverCaptureTimestamp. 1275 |

1276 |
1277 |
1278 |
1279 |
1280 |
1281 |

1282 | Data Channel Extensions 1283 |

1284 |
1285 |

1286 | Transferable Data Channels 1287 |

1288 |

This section extends {{RTCDataChannel}} by exposing it to any type of {{Worker}} (not just DedicatedWorker).

1289 |
1290 |

The WebIDL changes are the following: 1291 |

1292 |   [Exposed=(Window,Worker), Transferable]
1293 |   partial interface RTCDataChannel {
1294 | };
1295 |
1296 |
1297 |
1298 |
1299 |

RTP Header Extension Encryption

1300 |
1301 |

1302 | RTCRtpHeaderEncryptionPolicy Enum 1303 |

1304 |

1305 | RTP header extension encryption policy affects whether RTP header extension 1306 | encryption is negotiated if the remote endpoint does not support [[RFC9335]]. 1307 | If the remote endpoint supports [[RFC9335]], all media streams are sent 1308 | utilizing [[RFC9335]]. 1309 |

1310 |
1311 |
enum RTCRtpHeaderEncryptionPolicy {
1312 |   "negotiate",
1313 |   "require"
1314 | };
1315 | 1317 | 1318 | 1319 | 1320 | 1321 | 1322 | 1323 | 1330 | 1331 | 1332 | 1333 | 1343 | 1344 | 1345 |
Enumeration description (non-normative)
negotiate 1324 |

1325 | Negotiate RTP header extension encryption as defined in [[RFC9335]]. 1326 | If encryption cannot be negotiated, RTP header extensions are sent in 1327 | the clear. 1328 |

1329 |

require 1334 |

1335 | Require RTP header extension encryption. In [[WEBRTC]] Section 4.4.1.5, add the 1336 | following check after Step 4.4.4: 1337 | If remote is true, the connection's 1338 | {{RTCRtpHeaderEncryptionPolicy}} is {{RTCRtpHeaderEncryptionPolicy/require}} 1339 | and the description does not support [[RFC9335]], then [= reject =] p 1340 | with a newly [= exception/created =] {{InvalidAccessError}} and abort these steps. 1341 |

1342 |
1346 |
1347 |
1348 |
1349 |

1350 | {{RTCRtpTransceiver}} interface extensions 1351 |

1352 |

1353 | {{RTCRtpTransceiver/rtpHeaderEncryptionNegotiated}} defines whether 1354 | the transceiver is sending enrypted RTP header extensions as defined in 1355 | [[RFC9335]]. 1356 |

1357 |
1358 | partial interface RTCRtpTransceiver {
1359 |   readonly attribute boolean rtpHeaderEncryptionNegotiated;
1360 | };
1361 |
1362 |

1363 | Attributes 1364 |

1365 |
1367 |
1368 | rtpHeaderEncryptionNegotiated of type Boolean, readonly, nullable 1370 |
1371 |
1372 |

1373 | The {{rtpHeaderEncryptionNegotiated}} attribute indicates whether [[RFC9335]] has been 1374 | negotiated. On getting, the attribute MUST 1375 | return the value of the {{RTCRtpTransceiver/[[RtpHeaderEncryptionNegotiated]]}} slot. 1376 | In [[WEBRTC]] Section 5.4, add the following step to "create an {{RTCRtpTransceiver}}": 1377 | Let transceiver have a [[\RtpHeaderEncryptionNegotiated]] 1378 | internal slot, initialized to false. 1379 |

1380 |
1381 |
1382 |
1383 |
1384 |
1385 |

1386 | {{RTCConfiguration}} extensions 1387 |

1388 |

1389 | {{RTCConfiguration/rtpHeaderEncryptionPolicy}} defines the 1390 | policy for negotiation of RTP header encryption using 1391 | [[RFC9335]]. 1392 |

1393 |
partial dictionary RTCConfiguration {
1394 |   RTCRtpHeaderEncryptionPolicy rtpHeaderEncryptionPolicy = "negotiate";
1395 | };
1396 |
1397 |

1398 | Dictionary {{RTCConfiguration}} Members 1399 |

1400 |
1402 |
1403 | rtpHeaderEncryptionPolicy of type RTCRtpHeaderEncryptionPolicy 1405 |
1406 |
1407 |

1408 |

1409 |
1410 |

1411 | {{RTCConfiguration/rtpHeaderEncryptionPolicy}} is marked 1412 | as a feature at risk, since there is no clear commitment 1413 | from implementers. 1414 |

1415 |
1416 |
1417 |
1418 |
1419 |
1420 |
1421 |
1422 |

Disabling hardware acceleration

1423 |

1424 | While hardware acceleration of video encoding and decoding is generally desirable, it has proven to be 1425 | operationally challenging to achieve in the environment of a browser with no detailed information about 1426 | the underlying hardware. In some cases, falling back to software encoding yields better results. 1427 |

1428 |

1429 | The methods specified in this section should be used sparingly and not for extended amounts of time. 1430 |

1431 |

1432 | In privacy-sensitive contexts, browsers may disable hardware acceleration by default to 1433 | reduce the fingerprinting surface. 1434 |

1435 |
1436 |

1437 | {{RTCRtpReceiver}} extensions 1438 |

1439 |

1440 | The {{RTCRtpReceiver}} interface is defined in [[WEBRTC]]. This document extends this interface 1441 | by adding a static method and internal slot 1442 | {{RTCRtpReceiver/[[HardwareDisabled]]}} initialized to false. 1443 |

1444 |
partial interface RTCRtpReceiver {
1445 |   static undefined disableHardwareDecoding();
1446 | };
1447 |

When the {{RTCRtpReceiver}}'s disableHardwareDecoding method is called, the user agent MUST run the following steps:

1448 |
    1449 |
  1. 1450 |

    When the RTCPeerConnection.constructor() has been invoked abort these steps.

    1451 |
  2. 1452 |
  3. 1453 |

    Set the RTCRtpReceiver's {{RTCRtpReceiver/[[HardwareDisabled]]}} slot to true.

    1454 |
  4. 1455 |
1456 |
1457 |
1458 |

1459 | {{RTCRtpSender}} extensions 1460 |

1461 |

1462 | The {{RTCRtpSender}} interface is defined in [[WEBRTC]]. This document extends this interface 1463 | by adding a static method and internal slot 1464 | {{RTCRtpSender/[[HardwareDisabled]]}} initialized to false. 1465 |

1466 |
partial interface RTCRtpSender {
1467 |   static undefined disableHardwareEncoding();
1468 | };
1469 |

When the {{RTCRtpSender}}'s disableHardwareEncoding method is called, the user agent MUST run the following steps:

1470 |
    1471 |
  1. 1472 |

    When the RTCPeerConnection.constructor() has been invoked abort these steps.

    1473 |
  2. 1474 |
  3. 1475 |

    Set the RTCRtpSender's {{RTCRtpSender/[[HardwareDisabled]]}} slot to true.

    1476 |
  4. 1477 |
1478 |
1479 |
1480 |

Modifications to existing procedures

1481 |

1482 | In the set a session description algorithm, add a step 1483 | right after the step that sets transceiver.[[\Receiver]].[[\ReceiveCodecs]], 1484 | saying "If the RTCRtpReceiver's {{RTCRtpReceiver/[[HardwareDisabled]]}} slot is true, 1485 | remove any codec from transceiver.[[\Receiver]].[[\ReceiveCodecs]] for which the underlying decoder 1486 | is hardware-accelerated". 1487 |

1488 |

1489 | In the set a session description algorithm, add a step 1490 | right after the step that sets transceiver.[[\Sender]].[[\SendCodecs]], 1491 | saying "If the RTCRtpSender's {{RTCRtpSender/[[HardwareDisabled]]}} slot is true, 1492 | remove any codec from transceiver.[[\Sender]].[[\SendCodecs]] for which the underlying encoder 1493 | is hardware-accelerated". 1494 |

1495 |
1496 |
1497 |
1498 |

Event summary

1499 |

1500 | The following events fire on {{RTCIceTransport}} objects:

1501 | 1502 | 1503 | 1504 | 1505 | 1506 | 1507 | 1508 | 1509 | 1510 | 1511 | 1512 | 1513 | 1516 | 1517 | 1518 | 1519 | 1520 | 1523 | 1524 | 1525 | 1526 | 1527 | 1531 | 1532 | 1533 |
Event nameInterfaceFired when...
icecandidatepairadd{{RTCIceCandidatePairEvent}} 1514 | The [= ICE agent =] has formed a candidate pair and is making it available to the script. 1515 |
icecandidatepairremove{{RTCIceCandidatePairEvent}} 1521 | The [= ICE agent =] has picked a candidate pair to remove, and unless the operation is canceled by invoking the preventDefault() method on the event, it will be removed. 1522 |
icecandidatepairnominate{{RTCIceCandidatePairEvent}} 1528 | The [= ICE agent =] has picked a valid candidate pair to {{nominate}}, and unless the operation is canceled by 1529 | invoking the preventDefault() method on the event, it will be {{nominated}}. 1530 |
1534 |
1535 |
1536 |

Timestamp behavior

1537 |

RTCRtpReceiver timestamps

1538 |

Remote capture timestamp

1539 |

1540 | For a frame produced in a {{RTCRtpReceiver}} track, it is possible for the user agent to compute a 1541 | remote capture timestamp. It is a best-effort estimate of the capture 1542 | time of the frame translated to the receiver clock, and can use methods like using RTCP SR 1543 | as specified in [[?RFC3550]] Section 6.4.1, or by other alternative means if use by RTCP SR 1544 | isn't feasible. 1545 | The capture time of an incoming frame is available if its constituent RTP packets contain the 1546 | [=Absolute Capture Timestamp RTP header extension=]. 1547 |

1548 |

1549 | Each frame's [=capture timestamp=] MUST be set to the [=remote capture timestamp=], if the information 1550 | required to compute it is available. 1551 |

1552 |

Received RTP timestamp

1553 |

1554 | For a video frame produced in a {{RTCRtpReceiver}} track, the frame's [=RTP timestamp=] MUST be set 1555 | from the RTP timestamp of constituent packets of the corresponding received encoded frame. 1556 |

1557 |

Receive timestamp

1558 |

1559 | For a frame produced in a {{RTCRtpReceiver}} track, the [=receive timestamp=] MUST be set 1560 | as the time the corresponding encoded frame was received by the platform, i.e. the time at which the 1561 | last packet belonging to this frame was received over the network. 1562 |

1563 |
1564 |
1565 |

1566 | Security Considerations 1567 |

1568 |

1569 | This section is non-normative; it specifies no new behaviour. 1570 | The overall security considerations of the general set 1571 | of APIs and protocols used in WebRTC are described in 1572 | [[?RFC8827]]. 1573 |

1574 |
1575 |

1576 | Impact on local network 1577 |

1578 |

1579 | The extensions defined in this document do not provide 1580 | additional impact on the local network beyond what is described in 1581 | [[WEBRTC]] Section 13.3. 1582 |

1583 |
1584 |
1585 |

1586 | Confidentiality of Communications 1587 |

1588 |

1589 | This document defines extensions for encryption of RTP Header Extensions which 1590 | improve the confidentiality of communications by encrypting header extension 1591 | IDs, as well as CSRCs. 1592 |

1593 |
1594 |
1595 |
1596 |

1597 | Privacy Considerations 1598 |

1599 |

1600 | This section is non-normative; it specifies no new behaviour. 1601 |

1602 |
1603 |

1604 | Revealing IP addresses 1605 |

1606 |

1607 | The extensions defined in this document do not reveal additional 1608 | information on IP addresses beyond that already described in 1609 | [[WEBRTC]] Section 13.2. 1610 |

1611 |
1612 |
1613 |

1614 | Persistent information exposed by WebRTC 1615 |

1616 |

1617 | The extensions defined in this document do not provide additional 1618 | persistent information beyond that which is discussed in [[WEBRTC]] 1619 | Section 13.5. 1620 |

1621 |
1622 |
1623 |
1624 |

1625 | Accessibility Considerations 1626 |

1627 |

1628 | The WebRTC 1.0 specification exposes an API to control protocols 1629 | (defined within the IETF) necessary to establish real-time audio, video 1630 | and data exchange. Real-Time Text, defined in [[RFC4103]], is supported 1631 | via the data channel API as described in [[WEBRTC]] Section 14. The 1632 | extensions defined in this document do not affect support for Real-Time 1633 | Text. 1634 |

1635 |
1636 |
1637 |

Acknowledgements

1638 |

1639 | The editors wish to thank the Working Group chairs and Team Contact, 1640 | Dominique Hazaël-Massieux, for their support. Substantial text in this 1641 | specification was provided by many people including 1642 | Harald Alvestrand, Justin Uberti and Peter Thatcher. 1643 |

1644 |

1645 | The {{RTCRtpSender}} and {{RTCRtpReceiver}} objects were initially 1646 | described in the W3C ORTC 1647 | CG, and have been adapted for use in this specification. 1648 |

1649 |
1650 | 1651 | 1652 | -------------------------------------------------------------------------------- /section13: -------------------------------------------------------------------------------- 1 |
2 |

Removed features

3 |

4 | This section documents features that were moved from [[WEBRTC]] to this extension 5 | specification due to lack of support from implementers. 6 |

7 |
8 |

9 | {{RTCPeerConnection}} extensions 10 |

11 |

12 | The {{RTCPeerConnection}} 13 | interface is defined in [[WEBRTC]]. This document extends that interface 14 | by adding an additional static method. 15 |

16 |
partial interface RTCPeerConnection {
 17 |   static sequence<RTCIceServer> getDefaultIceServers();
 18 | };
19 |
20 |

Methods

21 |
23 |
getDefaultIceServers
24 |
25 |

Returns a list of ICE servers that are configured into the 26 | browser. A browser might be configured to use local or private 27 | STUN or TURN servers. This method allows an application to learn 28 | about these servers and optionally use them.

29 |

This list is likely to be persistent and 30 | is the same across origins. It thus increases the 31 | fingerprinting surface of the browser. In privacy-sensitive 32 | contexts, browsers can consider mitigations such as only 33 | providing this data to whitelisted origins (or not providing it 34 | at all.)

35 |

Since the use of this information is left to 36 | the discretion of application developers, configuring a user 37 | agent with these defaults does not per se increase a user's 38 | ability to limit the exposure of their IP addresses.

39 |

If set, the configured default ICE servers exposed by 40 | {{RTCPeerConnection/getDefaultIceServers}} on 41 | {{RTCPeerConnection}} instances provides persistent 42 | information across time and origins which increases the fingerprinting 43 | surface of a given browser.

44 |
45 |

46 | {{RTCPeerConnection/getDefaultIceServers()}} was moved from [[WEBRTC]] to 47 | this specification due to lack of support from implementers and concerns 48 | discussed in webrtc-pc#2023. 49 |

50 |
51 |
52 |
53 |
54 |
55 |
56 |

57 | {{RTCIceCredentialType}} extensions 58 |

59 |

The following enum values are added to the 60 | {{RTCIceCredentialType}} 61 | enum defined in [[WEBRTC]].

62 |
63 |
// This is a partial enum, but this is not yet expressable in WebIDL.
 65 | enum RTCIceCredentialType {
 66 |     "oauth"
 67 | };
68 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 136 | 137 | 138 |
Enumeration description
oauth

An OAuth 2.0 based authentication method, as described 77 | in [[RFC7635]]. 78 |

79 |

For OAuth Authentication, the ICE Agent requires three 80 | pieces of credential information. The credential is composed of 81 | a kid, which the {{RTCIceServer.username}} member is used for, and 82 | macKey and accessToken, which are 83 | placed in the {{RTCOAuthCredential}} dictionary. 84 |

85 |

86 | This specification does not define how an application (acting 87 | as the [=OAuth Client=]) obtains the 88 | accessToken, kid and 89 | macKey from the [=Authorization Server=], as 90 | WebRTC only handles the interaction between the ICE 91 | Agent and TURN server. For example, the application may use 92 | the OAuth 2.0 Implicit Grant type, with PoP (Proof-of-Possession) 93 | Token type, as described in [[RFC6749]] and 94 | [[OAUTH-POP-KEY-DISTRIBUTION]]; an example of this is provided 95 | in [[RFC7635]], Appendix B.

96 |

97 | The application, acting as the OAuth Client, is responsible for 98 | refreshing the credential information and updating the ICE 99 | Agent with fresh new credentials before the 100 | accessToken expires. The OAuth Client can use the 101 | {{RTCPeerConnection.setConfiguration()}} 102 | method to periodically refresh the TURN credentials.

103 |

The length of the HMAC key 104 | ({{RTCOAuthCredential.macKey}}) MAY be any integer 105 | number of bytes greater than 20 (160 bits).

106 |

According to [[RFC7635]] Section 4.1, the 107 | HMAC key MUST be a symmetric key, as asymmetric keys would 108 | result in large access tokens which may not fit in a single 109 | STUN message.

110 |

Currently the STUN/TURN protocols use only SHA-1 and SHA-2 111 | family hash algorithms for Message Integrity Protection, as 112 | defined in [[RFC5389]] Section 15.4, and [[STUN-BIS]] 113 | Section 14.6.

114 |

When setting a 116 | configuration and evaluating urls, also run the following step: 117 |

    118 |
  1. 119 |

    If scheme name is turn or 120 | turns, and 121 | server.{{RTCIceServer/credentialType}} is 122 | "oauth", and 123 | server.{{RTCIceServer/credential}} is not an 124 | {{RTCOAuthCredential}}, then [=exception/throw=] an 125 | {{InvalidAccessError}}.

    126 |
  2. 127 |
128 |
129 |

130 | The {{RTCIceCredentialType/"oauth"}} value of {{RTCIceCredentialType}} 131 | was moved from [[WEBRTC]] to this specification due to lack of support 132 | from implementers. It is therefore marked as a feature at risk. 133 |

134 |
135 |
139 |
140 |
141 |
142 |

143 | RTCOAuthCredential Dictionary 144 |

145 |

The {{RTCOAuthCredential}} dictionary is used to describe 146 | the OAuth auth credential information which is used by the STUN/TURN 147 | client (inside the ICE Agent) to authenticate against a STUN/TURN 148 | server, as described in [[RFC7635]]. Note that the kid 149 | parameter is not located in this dictionary, but in 150 | {{RTCIceServer.username}} member.

151 |
152 |

153 | The {{RTCOAuthCredential}} dictionary was moved from [[WEBRTC]] to 154 | this specification due to lack of support from implementers. It is 155 | therefore marked as a feature at risk. 156 |

157 |
158 |
159 |
dictionary RTCOAuthCredential {
161 |     required DOMString macKey;
162 |     required DOMString accessToken;
163 | };
164 |
165 |

Dictionary {{RTCOAuthCredential}} Members 166 |

167 |
169 |
macKey of type DOMString, required
171 |
172 |

The "mac_key", as described in [[RFC7635]], Section 6.2, in 173 | a base64-url encoded format. It is used in STUN message 174 | integrity hash calculation (as the password is used in password 175 | based authentication). Note that the OAuth response "key" 176 | parameter is a JSON Web Key (JWK) or a JWK encrypted with a JWE 177 | format. Also note that this is the only OAuth parameter whose 178 | value is not used directly, but must be extracted from the "k" 179 | parameter value from the JWK, which contains the needed 180 | base64-encoded "mac_key".

181 |
182 |
accessToken of type DOMString, required
184 |
185 |

The "access_token", as described in [[RFC7635]], Section 186 | 6.2, in a base64-encoded format. This is an encrypted 187 | self-contained token that is opaque to the application. 188 | Authenticated encryption is used for message encryption and 189 | integrity protection. The access token contains a non-encrypted 190 | nonce value, which is used by the Authorization Server for unique 191 | mac_key generation. The second part of the token is protected 192 | by Authenticated Encryption. It contains the mac_key, a 193 | timestamp and a lifetime. The timestamp combined with lifetime 194 | provides expiry information; this information describes the 195 | time window during which the token credential is valid and 196 | accepted by the TURN server. 197 |

198 |
199 |
200 |
201 |
202 |

An example of an RTCOAuthCredential dictionary is:

203 |
204 | {
205 |   macKey: 'WmtzanB3ZW9peFhtdm42NzUzNG0=',
206 |   accessToken: 'AAwg3kPHWPfvk9bDFL936wYvkoctMADzQ5VhNDgeMR3+ZlZ35byg972fW8QjpEl7bx91YLBPFsIhsxloWcXPhA=='
207 | }
208 |
209 |
210 |

211 | {{RTCIceServer}} extensions 212 |

213 |

214 | The {{RTCIceServer}} 215 | dictionary is defined in [[WEBRTC]]. This document extends that 216 | dictionary by adding the {{RTCIceServer/credential}} attribute, and adds a 217 | paragraph to how to interpret the existing {{RTCIceServer/username}} 218 | attribute. 219 |

220 |
partial dictionary RTCIceServer {
222 |     // This attribute is not new in this extension spec, but how to interpret it
223 |     // in the case of credentialType being "oauth" is described here.
224 |     DOMString username;
225 |     (DOMString or RTCOAuthCredential) credential;
226 | };
227 |

Dictionary {{RTCIceServer}} Members

228 |
230 |
username of type {{DOMString}}
231 |
232 |

How to interpret the {{username}} when this 233 | {{RTCIceServer}} object represents a TURN server, and 234 | {{RTCIceServer/credentialType}} is {{RTCIceCredentialType/"password"}} is specified 235 | in {{RTCIceServer}} of [[WEBRTC]].

236 |

If this {{RTCIceServer}} object represents a 237 | TURN server, and {{RTCIceServer/credentialType}} is 238 | {{RTCIceCredentialType/"oauth"}}, then this attribute specifies the Key ID 239 | (kid) of the shared symmetric key, which is shared 240 | between the TURN server and the Authorization Server, as described 241 | in [[RFC7635]]. It is an ephemeral and unique key identifier. 242 | The kid allows the TURN server to select the 243 | appropriate keying material for decryption of the Access-Token, 244 | so the key identified by this kid is used in the 245 | Authenticated Encryption of the "access_token". The 246 | kid value is equal with the OAuth response "kid" 247 | parameter, as defined in [[RFC7515]] Section 4.1.4.

248 |
249 |
credential of type (DOMString or {{RTCOAuthCredential}}) 251 |
252 |
253 |

If this {{RTCIceServer}} object represents a 254 | TURN server, then this attribute specifies the credential to 255 | use with that TURN server.

256 |

If {{RTCIceServer/credentialType}} is {{RTCIceCredentialType/"password"}}, 257 | {{credential}} is a DOMString, and represents a 258 | long-term authentication password, as described in 259 | [[RFC5389]], Section 10.2.

260 |

If {{RTCIceServer/credentialType}} is {{RTCIceCredentialType/"oauth"}}, 261 | {{credential}} is an {{RTCOAuthCredential}}, which 262 | contains the OAuth access token and MAC key.

263 |

If this {{RTCIceServer}} object represents a 264 | TURN server, and {{RTCIceServer/credentialType}} is 265 | {{RTCIceCredentialType/"oauth"}}, then this attribute specifies the Key ID 266 | (kid) of the shared symmetric key, which is shared 267 | between the TURN server and the Authorization Server, as described 268 | in [[RFC7635]]. It is an ephemeral and unique key identifier. 269 | The kid allows the TURN server to select the 270 | appropriate keying material for decryption of the Access-Token, 271 | so the key identified by this kid is used in the 272 | Authenticated Encryption of the "access_token". The 273 | kid value is equal with the OAuth response "kid" 274 | parameter, as defined in [[RFC7515]] Section 4.1.4.

275 |
276 |

277 | The {{RTCIceServer/credential}} attribute was moved from [[WEBRTC]] to 278 | this specification due to lack of support from implementers. It is 279 | therefore marked as a feature at risk. 280 |

281 |
282 |
283 |
284 |

An example array of {{RTCIceServer}} objects is:

285 |
286 | {
287 |   urls: 'turns:turn2.example.net',
288 |   username: '22BIjxU93h/IgwEb',
289 |   credential: {
290 |     macKey: 'WmtzanB3ZW9peFhtdm42NzUzNG0=',
291 |     accessToken: 'AAwg3kPHWPfvk9bDFL936wYvkoctMADzQ5VhNDgeMR3+ZlZ35byg972fW8QjpEl7bx91YLBPFsIhsxloWcXPhA=='
292 |   },
293 |   credentialType: 'oauth'
294 | }
295 |
296 |
297 |

298 | {{RTCRtpSynchronizationSource}} extensions 299 |

300 |

This document extends {{RTCRtpSynchronizationSource}} with a {{RTCRtpSynchronizationSource/voiceActivityFlag}} member (initially defined in the WebRTC 1.0 specification but later dropped due to lack of implementation).

301 |
302 |     partial dictionary RTCRtpSynchronizationSource {
303 |     boolean voiceActivityFlag;
304 |     };
305 |
307 |
308 | voiceActivityFlag of type boolean 310 |
311 |
312 |

313 | Only present for audio receivers. Whether the last RTP 314 | packet, delivered from this source, contains voice activity 315 | (true) or not (false). If the RFC 6464 extension header was 316 | not present, or if the peer has signaled that it is not using 317 | the V bit by setting the "vad" extension attribute to "off", 318 | as described in [[!RFC6464]], Section 4, 319 | {{voiceActivityFlag}} will be absent. 320 |

321 |
322 |

323 | {{RTCRtpSynchronizationSource/voiceActivityFlag}} was moved from [[WEBRTC]] to 324 | this specification due to lack of support from implementers. It is therefore 325 | marked as a feature at risk. 326 |

327 |
328 |
329 |
330 |
331 |
332 | -------------------------------------------------------------------------------- /w3c.json: -------------------------------------------------------------------------------- 1 | { 2 | "group": [47318] 3 | , "contacts": ["dontcallmeDom","caribouW3"] 4 | , "repo-type": "rec-track" 5 | } 6 | -------------------------------------------------------------------------------- /webrtc-extensions.js: -------------------------------------------------------------------------------- 1 | var respecConfig = { 2 | "group": "webrtc", 3 | github: { 4 | repoURL: "https://github.com/w3c/webrtc-extensions/", 5 | branch: "main" 6 | }, 7 | latestVersion: null, 8 | "xref": ["html", "webidl", "webrtc", "hr-time", "mediacapture-streams", "webrtc-stats", "infra", "dom"], 9 | "specStatus": "ED", 10 | editors: [ 11 | // { name: "Your Name", url: "http://example.org/", 12 | // company: "Your Company", companyURL: "http://example.com/" }, 13 | { name: "Bernard Aboba", company: "Microsoft Corporation", 14 | w3cid: "65611" 15 | } 16 | ], 17 | formerEditors: [ 18 | { name: "Henrik Boström", company: "Google", w3cid: "96936", retiredDate: "2021-02-01" } 19 | ], 20 | authors: [ 21 | ], 22 | wgPublicList: "public-webrtc", 23 | otherLinks: [ 24 | { 25 | key: "Participate", 26 | data: [ 27 | { 28 | value: "Mailing list", 29 | href: "https://lists.w3.org/Archives/Public/public-webrtc/" 30 | } 31 | ] 32 | } 33 | ], 34 | localBiblio: { 35 | "IANA-STUN-6": { 36 | "title": "STUN Error Codes", 37 | "href": "https://www.iana.org/assignments/stun-parameters/stun-parameters.xhtml#stun-parameters-6", 38 | "publisher": "IANA" 39 | }, 40 | "CRYPTEX": { 41 | "aliasOf": "RFC9335" 42 | }, 43 | "RTP-EXT-CAPTURE-TIME": { 44 | "title": "Absolute Capture Timestamp RTP header extension", 45 | "href": "https://www.ietf.org/archive/id/draft-ietf-avtcore-abs-capture-time-00.html", 46 | "authors": [ 47 | "H. Alvestrand" 48 | ], 49 | "status": "6 February 2025. Internet Draft (work in progress)", 50 | "publisher": "IETF" 51 | } 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /webrtc.css: -------------------------------------------------------------------------------- 1 | @media screen { 2 | html { background: #eeeeee; } 3 | body { margin-bottom: 30%; border-bottom: thin solid #3c790a; } 4 | } 5 | 6 | pre { margin-left: 2em; white-space: pre-wrap; } 7 | dt, dfn { font-weight: bold; font-style: normal; } 8 | i, em, dt dfn { font-style: italic; } 9 | pre, code { font-size: inherit; font-family: monospace, Droid Sans Fallback, sans-serif; font-variant: normal; } 10 | pre strong { color: black; font: inherit; font-weight: bold; background: yellow; } 11 | pre em { font-weight: bolder; font-style: normal; } 12 | var sub { vertical-align: bottom; font-size: smaller; position: relative; top: 0.1em; } 13 | table { border-collapse: collapse; border-style: hidden hidden none hidden; } 14 | table thead, table tbody { border-bottom: solid; } 15 | table tbody th { text-align: left; } 16 | table tbody th:first-child { border-left: solid; } 17 | table td, table th { border-left: solid; border-right: solid; border-bottom: solid thin; vertical-align: top; padding: 0.2em; } 18 | 19 | ins { background: green; color: white; /* color: green; border: solid thin lime; padding: 0.3em; line-height: 1.6em; */ text-decoration: none; } 20 | del { background: maroon; color: white; /* color: maroon; border: solid thin red; padding: 0.3em; line-height: 1.6em; */ text-decoration: line-through; } 21 | body ins, body del { display: block; } 22 | body * ins, body * del { display: inline; } 23 | 24 | 25 | li > span:not([title=""]):not([class="XXX"]):not([class="impl"]):not([class="note"]) { border-bottom: solid #99CC99; } 26 | 27 | .note { color: green; background: transparent; font-family: sans-serif, Droid Sans Fallback; } 28 | .warning { color: red; background: transparent; } 29 | .note, .warning { font-weight: bolder; font-style: italic; } 30 | .note em, .warning em, .note i, .warning i { font-style: normal; } 31 | p.note, div.note { padding: 0.5em 2em; } 32 | span.note { padding: 0 2em; } 33 | .note p:first-child, .warning p:first-child { margin-top: 0; } 34 | .note p:last-child, .warning p:last-child { margin-bottom: 0; } 35 | .warning:before { font-style: normal; } 36 | p.note:before { content: 'Note: '; } 37 | p.warning:before { content: '\26A0 Warning! '; } 38 | 39 | .bookkeeping:before { display: block; content: 'Bookkeeping details'; font-weight: bolder; font-style: italic; } 40 | .bookkeeping { font-size: 0.8em; margin: 2em 0; } 41 | .bookkeeping p { margin: 0.5em 2em; display: list-item; list-style: square; } 42 | .bookkeeping dt { margin: 0.5em 2em 0; } 43 | .bookkeeping dd { margin: 0 3em 0.5em; } 44 | 45 | .critical { margin: 1em; border: double thick red; padding: 1em; background: #FFFFCC; } 46 | .critical > :first-child { margin-top: 0; } 47 | 48 | .example { display: block; color: #222222; background: #FCFCFC; border-left: double; margin-left: 2em; padding-left: 1em; } 49 | td > .example:only-child { margin: 0 0 0 0.1em; } 50 | .rfc2119 { font-variant: small-caps;} 51 | 52 | --------------------------------------------------------------------------------