WebRTC RTP Transport

Unofficial Proposal Draft,

More details about this document
This version:
https://github.com/w3c/webrtc-rtptransport
Latest published version:
https://www.w3.org/TR/webrtc-rtptransport/
Feedback:
public-webrtc@w3.org with subject line “[webrtc-rtptransport] … message topic …” (archives)
GitHub
Editors:
(Microsoft Corporation)
(Google)
(Microsoft Corporation)
Participate:
Git Repository.
File an issue.
Version History:
https://github.com/w3c/webrtc-rtptransport/commits

Abstract

The WebRTC-RtpTransport API allows web applications to send and receive RTP/RTCP packets using the protocol defined in [RFC3550].

Status of this document

1. Introduction

This section is non-normative.

This specification uses [RFC3550] to send and receive RTP and RTCP packets.

Note: The API presented in this specification represents a preliminary proposal based on work-in-progress within the W3C WEBRTC WG. As a result, the API is likely to change significantly going forward.

2. Conformance

As well as sections marked as non-normative, all authoring guidelines, diagrams, examples, and notes in this specification are non-normative. Everything else in this specification is normative.

The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "NOT RECOMMENDED", "MAY", and "OPTIONAL" are to be interpreted as described in [RFC2119] and [RFC8174] when, and only when, they appear in all capitals, as shown here.

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.

3. Terminology

Terminology definitions go here.

4. RTCRtpTransport Interface

[Exposed=(Window)]
interface RTCRtpTransport {
  attribute EventHandler onpacketizedrtpavailable;
  sequence<RTCRtpPacket> readPacketizedRtp(unsigned long maxNumberOfPackets);

  attribute EventHandler onsentrtp;
  // Batch interface to read RTCRtpSent notifications.
  sequence<RTCRtpSent> readSentRtp(long maxCount);

  attribute EventHandler onreceivedrtpacks;  // No payload. Use readReceivedRtpAcks
  // Batch interface to read RTCRtpAcks as an alternative to onrtpacksreceived.
  sequence<RTCRtpAcks> readReceivedRtpAcks(long maxCount);

  readonly attribute unsigned long bandwidthEstimate;  // bps
  readonly attribute unsigned long allocatedBandwidth;  // bps
  attribute unsigned long customAllocatedBandwidth;  // writable
  // Means "when doing bitrate allocation and rate control, don’t use more than this"
  attribute unsigned long customMaxBandwidth;
  // Means "make each packet smaller by this much so I can put custom stuff in each packet"
  attribute unsigned long customPerPacketOverhead;
};

4.1. Attributes

onpacketizedrtpavailable, of type EventHandler
onsentrtp, of type EventHandler
onreceivedrtpacks, of type EventHandler
bandwidthEstimate, of type unsigned long, readonly
allocatedBandwidth, of type unsigned long, readonly
customAllocatedBandwidth, of type unsigned long
customMaxBandwidth, of type unsigned long
customPerPacketOverhead, of type unsigned long

4.2. Methods

readPacketizedRtp(maxNumberOfPackets)
readSentRtp(long maxCount)
readReceivedRtpAcks(long maxCount)

5. Objects

5.1. RTCRtpPacket Interface

[Exposed=(Window)]
interface RTCRtpPacket {
  constructor(RTCRtpPacketInit init);
  readonly attribute boolean marker;
  readonly attribute octet payloadType;
  readonly attribute unsigned short sequenceNumber;
  readonly attribute unsigned long timestamp;
  readonly attribute unsigned long ssrc;
  sequence<unsigned long> getCsrcs();
  sequence<RTCRtpHeaderExtension> getHeaderExtensions();
  readonly attribute unsigned long paddingBytes;

  // Write payload to the specified (Shared-)ArrayBuffer/ArrayBufferView,
  // allowing for BYOB. Throws a TypeError if |destination| is smaller than
  // |payloadByteLength|.
  undefined copyPayloadTo(AllowSharedBufferSource destination);
  readonly attribute unsigned long payloadByteLength;

  // OPTIONAL: Extra information that may be useful to know
  readonly attribute DOMHighResTimeStamp receivedTime;
  readonly attribute unsigned long sequenceNumberRolloverCount;

  undefined setHeaderExtension(RTCRtpHeaderExtension headerExtension);
};
marker, of type boolean, readonly
payloadType, of type octet, readonly
sequenceNumber, of type unsigned short, readonly
timestamp, of type unsigned long, readonly
ssrc, of type unsigned long, readonly
paddingBytes, of type unsigned long, readonly
payloadByteLength, of type unsigned long, readonly
receivedTime, of type DOMHighResTimeStamp, readonly
sequenceNumberRolloverCount, of type unsigned long, readonly
getCsrcs()
getHeaderExtensions()
copyValueTo(AllowSharedBufferSource destination)
setHeaderExtension(RTCRtpHeaderExtension headerExtension)

5.2. RTCRtpHeaderExtension Interface

[Exposed=(Window)]
interface RTCRtpHeaderExtension {
  constructor(RTCRtpHeaderExtensionInit init);
  readonly attribute DOMString uri;
  readonly attribute unsigned long valueByteLength;

  // Write the extension’s value to the specified (Shared-)ArrayBuffer/ArrayBufferView,
  // allowing for BYOB. Throws a TypeError if |destination| is smaller than
  // |valueByteLength|.
  undefined copyValueTo(AllowSharedBufferSource destination);
};
uri, of type DOMString, readonly
valueByteLength, of type unsigned long, readonly
copyValueTo(AllowSharedBufferSource destination)

5.3. RTCRtpHeaderExtensionInit Dictionary

dictionary RTCRtpHeaderExtensionInit {
  required DOMString uri;
  required AllowSharedBufferSource value;
};
uri, of type DOMString
value, of type AllowSharedBufferSource

5.4. RTCRtpPacketInit Dictionary

dictionary RTCRtpPacketInit {
  boolean marker = false;
  required octet payloadType;
  required unsigned long timestamp;
  sequence<unsigned long> csrcs = [];
  // Cannot be MID, RID, or congestion control sequence number
  sequence<RTCRtpHeaderExtensionInit> headerExtensions = [];
  required AllowSharedBufferSource payload;
  // Causes padding bit to be set and padding added when serializing if > 0.
  unsigned long paddingBytes = 0;
};
marker, of type boolean, defaulting to false
payloadType, of type octet
timestamp, of type unsigned long
csrcs, of type sequence<unsigned long>, defaulting to []
headerExtensions, of type sequence<RTCRtpHeaderExtensionInit>, defaulting to []
payload, of type AllowSharedBufferSource
paddingBytes, of type unsigned long, defaulting to 0

5.5. RTCRtpAcks Interface

[Exposed=(Window)]
interface RTCRtpAcks {
  sequence<RTCRtpAck> getAcks();
  readonly attribute unsigned long long remoteSendTimestamp;
  readonly attribute DOMHighResTimeStamp receivedTime;
  readonly attribute RTCExplicitCongestionNotification explicitCongestionNotification;  // AKA "ECN"
};
getAcks()
remoteSendTimestamp, of type unsigned long long, readonly
receivedTime, of type DOMHighResTimeStamp, readonly
explicitCongestionNotification, of type RTCExplicitCongestionNotification, readonly

5.6. RTCRtpAck

[Exposed=(Window)]
interface RTCRtpAck {
  // Correlated with RtpSent.ackId
  readonly attribute unsigned long long ackId; 
  readonly attribute unsigned long long remoteReceiveTimestamp;
};
ackId, of type unsigned long long, readonly
remoteReceiveTimestamp, of type unsigned long long, readonly

5.7. RTCExplicitCongestionNotification

enum RTCExplicitCongestionNotification {
  // ECT = ECN-Capable Transport
  "unset",  // AKA "Not-ECT";  Bits: 00
  "scalable-congestion-not-experienced",  // AKA "ECT(1)" or "Scalable" or "L4S" ; Bits: 01
  "classic-congestion-not-experienced", // AKA "ECT(0)" or "Classic" or "not L4S"; Bits: 10
  "congestion-experienced" // AKA "CE" or "ECN-marked" or "marked"; Bits: 11
};

6. RTCRtpPacketSender Interface

[Exposed=(Window,Worker), Transferable]
interface RTCRtpPacketSender {
  readonly attribute DOMString? mid;
  readonly attribute DOMString? rid;
  readonly attribute unsigned long ssrc;
  readonly attribute unsigned long rtxSsrc;

  attribute EventHandler onpacketizedrtp;
  sequence<RTCRtpPacket> readPacketizedRtp(long maxNumberOfPackets);

  // https://github.com/w3c/webrtc-rtptransport/issues/32
  undefined sendRtp(RTCRtpPacket packet);
  Promise<RTCRtpSendResult> sendRtp(RTCRtpPacketInit packetInit, optional RTCRtpSendOptions options = {});

  // Amount allocated by the browser
  readonly attribute unsigned long allocatedBandwidth;
};
mid, of type DOMString, readonly, nullable
rid, of type DOMString, readonly, nullable
ssrc, of type unsigned long, readonly
rtxSsrc, of type unsigned long, readonly
onpacketizedrtp, of type EventHandler
readPacketizedRtp(long maxNumberOfPackets)
sendRtp(RTCRtpPacket packet)
sendRtp(RTCRtpPacketInit packetInit, optional RTCRtpSendOptions options = {})

6.1. RTCRtpSendResult Interface

[Exposed=(Window)]
interface RTCRtpSendResult {
  readonly attribute RTCRtpSent? sent;
  readonly attribute RTCRtpUnsentReason? unsent;
};
sent, of type RTCRtpSent, readonly, nullable
unsent, of type RTCRtpUnsentReason, readonly, nullable

6.2. RTCRtpSent Interface

[Exposed=(Window)]
interface RTCRtpSent {
  readonly attribute DOMHighResTimeStamp time;

  // Can be correlated with acks
  readonly attribute unsigned long long? ackId;
  readonly attribute unsigned long long size;
};
time, of type DOMHighResTimeStamp, readonly
ackId, of type unsigned long long, readonly, nullable
size, of type unsigned long long, readonly

6.3. RTCRtpUnsentReason Enum

enum RTCRtpUnsentReason {
  "overuse",
  "transport-unavailable",
};

6.4. RTCRtpSendOptions Dictionary

dictionary RTCRtpSendOptions {
  DOMHighResTimeStamp sendTime;
};
sendTime, of type DOMHighResTimeStamp

7. RTCRtpPacketReceiver Interface

[Exposed=(Window,Worker), Transferable]
interface RTCRtpPacketReceiver {
  readonly attribute DOMString? mid;
  readonly attribute DOMString? rid;  // Unique to RTCRtpPacketReceiver (scoped to MID)
  sequence<unsigned long> getSsrcs();
  sequence<unsigned long> getRtxSsrcs();

  attribute EventHandler onreceivedrtp;
  sequence<RTCRtpPacket> readReceivedRtp(long maxNumberOfPackets);

  undefined receiveRtp(RTCRtpPacket packet);
};
mid, of type DOMString, readonly, nullable
rid, of type DOMString, readonly, nullable
onreceivedrtp, of type EventHandler
readReceivedRtp(long maxNumberOfPackets)
receiveRtp(RTCRtpPacket packet)
getSsrcs()
getRtxSsrcs()

8. Interface Extensions

8.1. RTCPeerConnection Interface Extensions

partial interface RTCPeerConnection {
  // There may be an RtpTransport with no RtpSenders and no RtpReceivers.
  readonly attribute RTCRtpTransport? rtpTransport;
};
rtpTransport, of type RTCRtpTransport, readonly, nullable

8.2. RTCRtpSender Interface Extensions

partial interface RTCRtpSender {
  // shared between RTCRtpSenders in the same BUNDLE group
  readonly attribute RTCRtpTransport? rtpTransport;
  Promise<RTCRtpPacketSender> replacePacketSender();
};
rtpTransport, of type RTCRtpTransport, readonly, nullable
replacePacketSender()

8.3. RTCConfiguration Dictionary Extensions

partial dictionary RTCConfiguration {
  // Means "continue to encode and packetize packets, but don’t send them.
  // Instead give them to me via onpacketizedrtpavailable/readPacketizedRtp
  // and I will send them."
  // TODO: Think of a better name
  boolean customPacer;
};
customPacer, of type boolean

8.4. RTCRtpReceiver Interface Extensions

partial interface RTCRtpReceiver {
  // shared between RTCRtpSenders in the same BUNDLE group
  readonly attribute RTCRtpTransport? rtpTransport;
  Promise<RTCRtpPacketReceiver> replacePacketReciever();
};
rtpTransport, of type RTCRtpTransport, readonly, nullable
replacePacketReciever()

9. Privacy and security considerations

9.1. Confidentiality of Communications

9.2. State Persistence

9.3. Protocol Security

9.4. Fingerprinting and Tracking

10. Examples

See the explainer document.

11. Acknowledgements

The editors wish to thank the WEBRTC Working Group chairs and Team Contact for their support.

Index

Terms defined by this specification

Terms defined by reference

References

Normative References

[HR-TIME-3]
Yoav Weiss. High Resolution Time. URL: https://w3c.github.io/hr-time/
[HTML]
Anne van Kesteren; et al. HTML Standard. Living Standard. URL: https://html.spec.whatwg.org/multipage/
[RFC2119]
S. Bradner. Key words for use in RFCs to Indicate Requirement Levels. March 1997. Best Current Practice. URL: https://datatracker.ietf.org/doc/html/rfc2119
[RFC3550]
H. Schulzrinne; et al. RTP: A Transport Protocol for Real-Time Applications. July 2003. RFC. URL: https://datatracker.ietf.org/doc/html/rfc3550
[RFC8174]
B. Leiba. Ambiguity of Uppercase vs Lowercase in RFC 2119 Key Words. May 2017. Best Current Practice. URL: https://www.rfc-editor.org/rfc/rfc8174
[WEBIDL]
Edgar Chen; Timothy Gu. Web IDL Standard. Living Standard. URL: https://webidl.spec.whatwg.org/
[WEBRTC]
Cullen Jennings; et al. WebRTC: Real-Time Communication in Browsers. URL: https://w3c.github.io/webrtc-pc/

IDL Index

[Exposed=(Window)]
interface RTCRtpTransport {
  attribute EventHandler onpacketizedrtpavailable;
  sequence<RTCRtpPacket> readPacketizedRtp(unsigned long maxNumberOfPackets);

  attribute EventHandler onsentrtp;
  // Batch interface to read RTCRtpSent notifications.
  sequence<RTCRtpSent> readSentRtp(long maxCount);

  attribute EventHandler onreceivedrtpacks;  // No payload. Use readReceivedRtpAcks
  // Batch interface to read RTCRtpAcks as an alternative to onrtpacksreceived.
  sequence<RTCRtpAcks> readReceivedRtpAcks(long maxCount);

  readonly attribute unsigned long bandwidthEstimate;  // bps
  readonly attribute unsigned long allocatedBandwidth;  // bps
  attribute unsigned long customAllocatedBandwidth;  // writable
  // Means "when doing bitrate allocation and rate control, don’t use more than this"
  attribute unsigned long customMaxBandwidth;
  // Means "make each packet smaller by this much so I can put custom stuff in each packet"
  attribute unsigned long customPerPacketOverhead;
};


[Exposed=(Window)]
interface RTCRtpPacket {
  constructor(RTCRtpPacketInit init);
  readonly attribute boolean marker;
  readonly attribute octet payloadType;
  readonly attribute unsigned short sequenceNumber;
  readonly attribute unsigned long timestamp;
  readonly attribute unsigned long ssrc;
  sequence<unsigned long> getCsrcs();
  sequence<RTCRtpHeaderExtension> getHeaderExtensions();
  readonly attribute unsigned long paddingBytes;

  // Write payload to the specified (Shared-)ArrayBuffer/ArrayBufferView,
  // allowing for BYOB. Throws a TypeError if |destination| is smaller than
  // |payloadByteLength|.
  undefined copyPayloadTo(AllowSharedBufferSource destination);
  readonly attribute unsigned long payloadByteLength;

  // OPTIONAL: Extra information that may be useful to know
  readonly attribute DOMHighResTimeStamp receivedTime;
  readonly attribute unsigned long sequenceNumberRolloverCount;

  undefined setHeaderExtension(RTCRtpHeaderExtension headerExtension);
};

[Exposed=(Window)]
interface RTCRtpHeaderExtension {
  constructor(RTCRtpHeaderExtensionInit init);
  readonly attribute DOMString uri;
  readonly attribute unsigned long valueByteLength;

  // Write the extension’s value to the specified (Shared-)ArrayBuffer/ArrayBufferView,
  // allowing for BYOB. Throws a TypeError if |destination| is smaller than
  // |valueByteLength|.
  undefined copyValueTo(AllowSharedBufferSource destination);
};

dictionary RTCRtpHeaderExtensionInit {
  required DOMString uri;
  required AllowSharedBufferSource value;
};

dictionary RTCRtpPacketInit {
  boolean marker = false;
  required octet payloadType;
  required unsigned long timestamp;
  sequence<unsigned long> csrcs = [];
  // Cannot be MID, RID, or congestion control sequence number
  sequence<RTCRtpHeaderExtensionInit> headerExtensions = [];
  required AllowSharedBufferSource payload;
  // Causes padding bit to be set and padding added when serializing if > 0.
  unsigned long paddingBytes = 0;
};

[Exposed=(Window)]
interface RTCRtpAcks {
  sequence<RTCRtpAck> getAcks();
  readonly attribute unsigned long long remoteSendTimestamp;
  readonly attribute DOMHighResTimeStamp receivedTime;
  readonly attribute RTCExplicitCongestionNotification explicitCongestionNotification;  // AKA "ECN"
};

[Exposed=(Window)]
interface RTCRtpAck {
  // Correlated with RtpSent.ackId
  readonly attribute unsigned long long ackId; 
  readonly attribute unsigned long long remoteReceiveTimestamp;
};

enum RTCExplicitCongestionNotification {
  // ECT = ECN-Capable Transport
  "unset",  // AKA "Not-ECT";  Bits: 00
  "scalable-congestion-not-experienced",  // AKA "ECT(1)" or "Scalable" or "L4S" ; Bits: 01
  "classic-congestion-not-experienced", // AKA "ECT(0)" or "Classic" or "not L4S"; Bits: 10
  "congestion-experienced" // AKA "CE" or "ECN-marked" or "marked"; Bits: 11
};

[Exposed=(Window,Worker), Transferable]
interface RTCRtpPacketSender {
  readonly attribute DOMString? mid;
  readonly attribute DOMString? rid;
  readonly attribute unsigned long ssrc;
  readonly attribute unsigned long rtxSsrc;

  attribute EventHandler onpacketizedrtp;
  sequence<RTCRtpPacket> readPacketizedRtp(long maxNumberOfPackets);

  // https://github.com/w3c/webrtc-rtptransport/issues/32
  undefined sendRtp(RTCRtpPacket packet);
  Promise<RTCRtpSendResult> sendRtp(RTCRtpPacketInit packetInit, optional RTCRtpSendOptions options = {});

  // Amount allocated by the browser
  readonly attribute unsigned long allocatedBandwidth;
};

[Exposed=(Window)]
interface RTCRtpSendResult {
  readonly attribute RTCRtpSent? sent;
  readonly attribute RTCRtpUnsentReason? unsent;
};

[Exposed=(Window)]
interface RTCRtpSent {
  readonly attribute DOMHighResTimeStamp time;

  // Can be correlated with acks
  readonly attribute unsigned long long? ackId;
  readonly attribute unsigned long long size;
};

enum RTCRtpUnsentReason {
  "overuse",
  "transport-unavailable",
};

dictionary RTCRtpSendOptions {
  DOMHighResTimeStamp sendTime;
};

[Exposed=(Window,Worker), Transferable]
interface RTCRtpPacketReceiver {
  readonly attribute DOMString? mid;
  readonly attribute DOMString? rid;  // Unique to RTCRtpPacketReceiver (scoped to MID)
  sequence<unsigned long> getSsrcs();
  sequence<unsigned long> getRtxSsrcs();

  attribute EventHandler onreceivedrtp;
  sequence<RTCRtpPacket> readReceivedRtp(long maxNumberOfPackets);

  undefined receiveRtp(RTCRtpPacket packet);
};

partial interface RTCPeerConnection {
  // There may be an RtpTransport with no RtpSenders and no RtpReceivers.
  readonly attribute RTCRtpTransport? rtpTransport;
};

partial interface RTCRtpSender {
  // shared between RTCRtpSenders in the same BUNDLE group
  readonly attribute RTCRtpTransport? rtpTransport;
  Promise<RTCRtpPacketSender> replacePacketSender();
};

partial dictionary RTCConfiguration {
  // Means "continue to encode and packetize packets, but don’t send them.
  // Instead give them to me via onpacketizedrtpavailable/readPacketizedRtp
  // and I will send them."
  // TODO: Think of a better name
  boolean customPacer;
};

partial interface RTCRtpReceiver {
  // shared between RTCRtpSenders in the same BUNDLE group
  readonly attribute RTCRtpTransport? rtpTransport;
  Promise<RTCRtpPacketReceiver> replacePacketReciever();
};