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

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

Introduction

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

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

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

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

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

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

Terminology

The following terms are defined in RTP Header Extension for Absolute Capture Time:

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

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

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

Filtering ICE candidates with Content-Security-Policy

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

Modifications to existing procedures

Append the following paragraph to the administratively prohibited algorithm:

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

RTP header extension control

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

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

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

{{RTCRtpTransceiver}} interface extensions

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

partial dictionary RTCRtpHeaderExtensionCapability {
  required RTCRtpTransceiverDirection direction;
};

partial interface RTCRtpTransceiver {
  sequence<RTCRtpHeaderExtensionCapability> getHeaderExtensionsToNegotiate();
  undefined setHeaderExtensionsToNegotiate(
      sequence<RTCRtpHeaderExtensionCapability> extensions);
  sequence<RTCRtpHeaderExtensionCapability> getNegotiatedHeaderExtensions();
};
      

Let {{RTCRtpTransceiver/[[HeaderExtensionsToNegotiate]]}} and {{RTCRtpTransceiver/[[NegotiatedHeaderExtensions]]}} be internal slots of the {{RTCRtpTransceiver}}, initialized as follows:

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

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

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

Modifications to existing procedures

Make the following modifications to the set a session description algorithm:

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

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

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

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

Methods

getHeaderExtensionsToNegotiate

Execute the following steps:

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

  2. Return transceiver.{{RTCRtpTransceiver/[[HeaderExtensionsToNegotiate]]}}.

setHeaderExtensionsToNegotiate

Execute the following steps:

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

  2. Let extensions be the first argument of this method.

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

  4. For each index i of extensions, run the following steps:

    1. Let extension be the i-th element of extensions.

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

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

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

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

  5. Set transceiver.{{RTCRtpTransceiver/[[HeaderExtensionsToNegotiate]]}} to extensions.

getNegotiatedHeaderExtensions

Execute the following steps:

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

  2. Return transceiver.{{RTCRtpTransceiver/[[NegotiatedHeaderExtensions]]}}.

RTCRtpEncodingParameters extensions

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

partial dictionary RTCRtpEncodingParameters {
  unsigned long ptime;
  boolean adaptivePtime = false;
  RTCRtpCodec codec;
};

Dictionary {{RTCRtpEncodingParameters}} Members

ptime of type unsigned long

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

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

adaptivePtime of type boolean, defaulting to false.

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

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

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

codec of type RTCRtpCodec

Optional value selecting which codec is used for this encoding's RTP stream. The {{RTCRtpCodec}} dictionary is defined in [[WEBRTC]]. If [=map/exists|absent=], the user agent can chose to use any negotiated codec.

Modifications to existing procedures

setParameters()

Add the following steps to the [=RTCRtpSender/setParameters validation steps=]:

  1. Let choosableCodecs be parameters.{{RTCRtpParameters/codecs}}.

  2. If choosableCodecs is an empty list, set choosableCodecs to transceiver.{{RTCRtpTransceiver/[[PreferredCodecs]]}}.

  3. If choosableCodecs is still an empty list, set choosableCodecs to the [=RTCRtpSender/list of implemented send codecs=] for transceiver's kind.

  4. If any encoding in encodings [=map/exists|contains=] a codec [= codec match | not found =] in choosableCodecs, return a promise [= rejected =] with a newly [= exception/created =] {{InvalidModificationError}}.

  5. If the user agent does not support setting the codec for any encoding or mixing different codec values on the different encodings, return a promise [= rejected =] with a newly [= exception/created =] {{OperationError}}.

addTransceiver()

Add the following steps to the [=RTCPeerConnection/addTransceiver sendEncodings validation steps=]:

  1. If any codec parameter in sendEncodings does [= codec match | not match =] any codec in {{RTCRtpSender.getCapabilities(kind)}}.codecs, [= exception/throw =] an {{OperationError}}.

  2. If the user agent does not support changing codecs without negotiation or does not support setting codecs for individual encodings, return a promise [= rejected =] with a newly [= exception/created =] {{OperationError}}.

Set the session description

Append the following steps to the set the session description algorithm:

  1. For each transceiver in connection's [= set of transceivers =]:

    1. Let codecs be transceiver.{{RTCRtpTransceiver/[[Sender]]}}.{{RTCRtpSender/[[SendCodecs]]}}.

    2. If codecs is not an empty list:

      1. Remove any codec value in transceiver.{{RTCRtpTransceiver/[[Sender]]}}.{{RTCRtpSender/[[SendEncodings]]}} that does not [= codec match | match =] any entry in codecs.

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

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

partial dictionary RTCSetParameterOptions {
  sequence<RTCEncodingOptions> encodingOptions = [];
};

dictionary RTCEncodingOptions {
  boolean keyFrame = false;
};

Dictionary {{RTCSetParameterOptions}} Members

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

encodingOptions of type sequence<{{RTCEncodingOptions}}>, defaulting to [].

A sequence containing encoding options for each RTP encoding.

Dictionary {{RTCEncodingOptions}} Members

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

keyFrame of type boolean, defaulting to false.

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

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

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

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

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

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

{{RTCIceTransport}} extensions

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

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

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

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

  2. If connection.{{RTCPeerConnection/[[IsClosed]]}} is true, abort these steps.

  3. Let |candidatePair:RTCIceCandidatePair| be a new {{RTCIceCandidatePair}} dictionary with its {{RTCIceCandidatePair/local}} and {{RTCIceCandidatePair/remote}} members initialized to new {{RTCIceCandidate}}s representing the local and remote part of the [= formed =] pair respectively.

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

  5. [=Assert=]: |candidatePair| does not [= candidate pair match | match =] any item in |transport|.{{RTCIceTransport/[[CandidatePairs]]}}

  6. [= list/Append =] |candidatePair| to {{RTCIceTransport/[[CandidatePairs]]}}.

  7. [= Fire an event =] named {{RTCIceTransport/icecandidatepairadd}} at |transport|, using {{RTCIceCandidatePairEvent}}, with the {{RTCIceCandidatePairEvent/local}} and {{RTCIceCandidatePairEvent/remote}} attributes initialized to the local and remote candidates, respectively, of |candidatePair|.

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

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

  2. If connection.{{RTCPeerConnection/[[IsClosed]]}} is true, abort these steps.

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

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

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

  6. Let |accepted:boolean| be the result of [= fire an event | firing an event =] named {{RTCIceTransport/icecandidatepairnominate}} at |transport|, using {{RTCIceCandidatePairEvent}}, with the {{Event/cancelable}} attribute initialized to true, and the {{RTCIceCandidatePairEvent/local}} and {{RTCIceCandidatePairEvent/remote}} attributes initialized to the local and remote candidates, respectively, of |candidatePair|.

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

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

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

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

When the [= ICE agent =] has picked a candidate pair to remove, the [= user agent =] MUST [= queue a task =] to remove a candidate pair:

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

  2. If connection.{{RTCPeerConnection/[[IsClosed]]}} is true, abort these steps.

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

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

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

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

  7. Let |accepted:boolean| be the result of [= fire an event | firing an event =] named {{RTCIceTransport/icecandidatepairremove}} at |transport|, using {{RTCIceCandidatePairEvent}}, with the {{Event/cancelable}} attribute initialized to cancelable, and the {{RTCIceCandidatePairEvent/local}} and {{RTCIceCandidatePairEvent/remote}} attributes initialized to the local and remote candidates, respectively, of |candidatePair|.

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

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

  10. Otherwise (if |accepted| is true), run the following steps:

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

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

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

        partial interface RTCIceTransport {
          attribute EventHandler onicecandidatepairadd;
          attribute EventHandler onicecandidatepairremove;
          attribute EventHandler onicecandidatepairnominate;
          Promise<undefined> selectCandidatePair(RTCIceCandidatePair candidatePair);
          Promise<undefined> removeCandidatePair(RTCIceCandidatePair candidatePair);
        };

Attributes

onicecandidatepairadd of type {{EventHandler}}

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

onicecandidatepairremove of type {{EventHandler}}

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

onicecandidatepairnominate of type {{EventHandler}}

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

Methods

selectCandidatePair

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

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

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

  2. If connection.{{RTCPeerConnection/[[IsClosed]]}} is true, [= exception/throw =] an {{InvalidStateError}}.

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

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

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

  6. If |candidatePair| does not [= candidate pair match | match =] any item in [=this=]. {{RTCIceTransport/[[CandidatePairs]]}}, [= exception/throw =] a {{NotFoundError}}.

  7. Let |p:Promise| be a new promise.

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

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

      1. 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.

      2. Resolve p.

  9. Return p.

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

removeCandidatePair

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

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

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

  2. If connection.{{RTCPeerConnection/[[IsClosed]]}} is true, [= exception/throw =] an {{InvalidStateError}}.

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

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

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

  6. If |candidatePair| does not [= candidate pair match | match =] any item in [=this=]. {{RTCIceTransport/[[CandidatePairs]]}}, [= exception/throw =] a {{NotFoundError}}.

  7. [= list/Remove =] the item in [=this=].{{RTCIceTransport/[[CandidatePairs]]}} that [= candidate pair match | matches =] |candidatePair|.

  8. Let |p:Promise| be a new promise.

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

    1. When the [= ICE agent =] has completed the removal, [= queue a task =] to run the following steps:

      1. [= Fire an event =] named {{RTCIceTransport/icecandidatepairremove}} at |transport|, using {{RTCIceCandidatePairEvent}}, with the {{Event/cancelable}} attribute initialized to false, and the {{RTCIceCandidatePairEvent/local}} and {{RTCIceCandidatePairEvent/remote}} attributes initialized to the {{RTCIceCandidatePair/local}} and {{RTCIceCandidatePair/remote}} candidates, respectively, of candidatePair.

      2. Resolve p.

  10. Return p.

RTCIceCandidatePairEvent

The {{RTCIceTransport/icecandidatepairadd}} and {{RTCIceTransport/icecandidatepairremove}} events use the {{RTCIceCandidatePairEvent}} interface.

[Exposed=Window]
  interface RTCIceCandidatePairEvent : Event {
    constructor(DOMString type, RTCIceCandidatePairEventInit eventInitDict);
    readonly attribute RTCIceCandidate local;
    readonly attribute RTCIceCandidate remote;
  };

Constructors

RTCIceCandidatePairEvent.constructor()

Attributes

local of type {{RTCIceCandidate}}, readonly

The {{local}} attribute represents the local {{RTCIceCandidate}} of the candidate pair associated with the event.

remote of type {{RTCIceCandidate}}, readonly

The {{remote}} attribute represents the remote {{RTCIceCandidate}} of the candidate pair associated with the event.

  dictionary RTCIceCandidatePairEventInit : EventInit {
    required RTCIceCandidate local;
    required RTCIceCandidate remote;
  };

Dictionary RTCIceCandidatePairEventInit Members

local of type {{RTCIceCandidate}}, required

The local {{RTCIceCandidate}} of the candidate pair announced by the event.

remote of type {{RTCIceCandidate}}, required

The remote {{RTCIceCandidate}} of the candidate pair announced by the event.

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

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

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

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

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

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

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

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

  8. Return true.

The candidate pair match algorithm given two {{RTCIceCandidatePair}} |first:RTCIceCandidatePair| and |second:RTCIceCandidatePair| is as follows:

  1. If |first|.{{RTCIceCandidatePair/local}} does not [= candidate match | match =] |second|.{{RTCIceCandidatePair/local}}, return false.

  2. If |first|.{{RTCIceCandidatePair/remote}} does not [= candidate match | match =] |second|.{{RTCIceCandidatePair/remote}}, return false.

  3. Return true.

{{RTCRtpContributingSource}} extensions

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

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

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

Despite {{RTCRemoteInboundRtpStreamStats.roundTripTime}} measurements only accounting for the "last hop", one-way delay from the [=capture system=]'s time of capture to the [=receiver system=]'s time of playout can be estimated if the [=RTP Header Extension for Absolute Capture Time=] is used all hops of the way, where each RTCP-terminating intermediate system appropriately updates the [=estimated capture clock offset=].

partial dictionary RTCRtpContributingSource {
  DOMHighResTimeStamp captureTimestamp;
  DOMHighResTimeStamp senderCaptureTimeOffset;
};

Dictionary {{RTCRtpContributingSource}} Members

captureTimestamp of type {{DOMHighResTimeStamp}}.

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

On populating this member, the user agent MUST run the following steps:

  1. If the relevant RTP packet contains the RTP Header Extension for Absolute Capture Time, return the value of the absolute capture timestamp field and abort these steps.

  2. Otherwise, if the relevant RTP packet does not contain the RTP Header Extension for Absolute Capture Time but a previous RTP packet did, return the result of calculating the absolute capture timestamp according to timestamp interpolation and abort these steps.

  3. Otherwise, return undefined.

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

senderCaptureTimeOffset of type {{DOMHighResTimeStamp}}.

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

On populating this member, the user agent MUST run the following steps:

  1. If the relevant RTP packet contains the RTP Header Extension for Absolute Capture Time and the estimated capture clock offset field is present, return the value of the estimated capture clock offset field and abort these steps.

  2. Otherwise, if the relevant RTP packet does not contain the RTP Header Extension for Absolute Capture Time's estimated capture clock offset field, but a previous RTP packet did, return the most recent value that was present and abort these steps.

  3. Otherwise, return undefined.

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

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

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

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

Data Channel Extensions

Transferable Data Channels

This section extends {{RTCDataChannel}} by making it transferable.

This allows sending and receiving messages outside the context the connection was created, for instance in workers or third-party iframes.

The WebIDL changes are the following:

  [Exposed=(Window,Worker), Transferable]
  partial interface RTCDataChannel {
};

The create an RTCDataChannel algorithm is updated by adding the following steps after step 4 of the original algorithm:

  1. Initialize channel.`[[IsTransferable]]` to true.

  2. Queue a task to run the following step:

    1. Set channel.`[[IsTransferable]]` to false.

This task needs to run before any task enqueued by the receiving messages on a data channel algorithm for channel. This ensures that no message is lost during the transfer of a {{RTCDataChannel}}.

The send() algorithm is modified by adding the following step after step 1 of the original algorithm:
  1. Set channel.`[[IsTransferable]]` to false.

The {{RTCDataChannel}} transfer steps, given value and dataHolder, are:

  1. If value.`[[IsTransferable]]` is false, throw a "DataCloneError" DOMException.

  2. Set dataHolder.`[[ReadyState]]` to value.`[[ReadyState]]`.

  3. Set dataHolder.`[[DataChannelLabel]]` to value.`[[DataChannelLabel]]`.

  4. Set dataHolder.`[[Ordered]]` to value.`[[Ordered]]`.

  5. Set dataHolder.`[[MaxPacketLifeTime]]` to value..`[[MaxPacketLifeTime]]`

  6. Set dataHolder.`[[MaxRetransmits]]` to value.`[[MaxRetransmits]]`.

  7. Set dataHolder.`[[DataChannelProtocol]]` to value.`[[DataChannelProtocol]]`.

  8. Set dataHolder.`[[Negotiated]]` to value.`[[Negotiated]]`.

  9. Set dataHolder.`[[DataChannelId]]` to value.`[[DataChannelId]]`.

  10. Set dataHolder.`[[underlyingDataTransport]]` to value underlying data transport.

  11. Set value.`[[IsTransferable]]` to false.

  12. Set value.`[[ReadyState]]` to "closed".

The {{RTCDataChannel}} [=transfer-receiving steps=], given dataHolder and channel, are:

  1. Initialize channel.`[[ReadyState]]` to dataHolder.`[[ReadyState]]`.

  2. Initialize channel.`[[DataChannelLabel]]` to dataHolder.`[[\DataChannelLabel]]`.

  3. Initialize channel.`[[Ordered]]` to dataHolder.`[[Ordered]]`.

  4. Initialize channel.`[[MaxPacketLifeTime]]` to dataHolder.`[[MaxPacketLifeTime]]`.

  5. Initialize channel.`[[MaxRetransmits]]` to dataHolder.`[[MaxRetransmits]]`.

  6. Initialize channel.`[[DataChannelProtocol]]` to dataHolder.`[[DataChannelProtocol]]`.

  7. Initialize channel.`[[Negotiated]]` to dataHolder.`[[Negotiated]]`.

  8. Initialize channel.`[[DataChannelId]]` to dataHolder.`[[DataChannelId]]`.

  9. Initialize channel underlying data transport to dataHolder.`[[underlyingDataTransport]]`.

The above steps do not need to transfer `[[BufferedAmount]]` as its value will always be equal to 0. The reason is an {{RTCDataChannel}} can be transferred only if its send() algorithm was not called prior the transfer.

If the underlying data transport is closed at the time of the [=transfer-receiving steps=], the {{RTCDataChannel}} object will be closed by running the announcing a data channel as closed algorithm immediately after the [=transfer-receiving steps=].

RTP Header Extension Encryption

RTCRtpHeaderEncryptionPolicy Enum

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

enum RTCRtpHeaderEncryptionPolicy {
  "negotiate",
  "require"
};
Enumeration description (non-normative)
negotiate

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

require

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

{{RTCRtpTransceiver}} interface extensions

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

partial interface RTCRtpTransceiver {
  readonly attribute boolean rtpHeaderEncryptionNegotiated;
};

Attributes

rtpHeaderEncryptionNegotiated of type Boolean, readonly, nullable

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

{{RTCConfiguration}} extensions

{{RTCConfiguration/rtpHeaderEncryptionPolicy}} defines the policy for negotiation of RTP header encryption using [[RFC9335]].

partial dictionary RTCConfiguration {
  RTCRtpHeaderEncryptionPolicy rtpHeaderEncryptionPolicy = "negotiate";
};

Dictionary {{RTCConfiguration}} Members

rtpHeaderEncryptionPolicy of type RTCRtpHeaderEncryptionPolicy

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

Disabling hardware acceleration

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

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

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

{{RTCRtpReceiver}} extensions

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

partial interface RTCRtpReceiver {
  static undefined disableHardwareDecoding();
};

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

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

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

{{RTCRtpSender}} extensions

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

partial interface RTCRtpSender {
  static undefined disableHardwareEncoding();
};

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

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

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

Modifications to existing procedures

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

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

Event summary

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

Event name Interface Fired when...
icecandidatepairadd {{RTCIceCandidatePairEvent}} The [= ICE agent =] has formed a candidate pair and is making it available to the script.
icecandidatepairremove {{RTCIceCandidatePairEvent}} 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.
icecandidatepairnominate {{RTCIceCandidatePairEvent}} The [= ICE agent =] has picked a valid candidate pair to {{nominate}}, and unless the operation is canceled by invoking the preventDefault() method on the event, it will be {{nominated}}.

Security Considerations

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

Impact on local network

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

Confidentiality of Communications

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

Privacy Considerations

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

Revealing IP addresses

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

Persistent information exposed by WebRTC

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

Accessibility Considerations

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

Acknowledgements

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

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