Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Bring Your Own Packets #84

Open
wants to merge 2 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
42 changes: 40 additions & 2 deletions explainer-use-case-1.md
Original file line number Diff line number Diff line change
Expand Up @@ -268,7 +268,7 @@ rtpPacketReceiver.onrtpreceived = () => {
const videoRtpPackets = rtpPacketReceiver.readReceivedRtp(10);
for (const videoRtpPacket of videoRtpPackets) {
const destArrayBufferView = allocateFromBufferPool(videoRtpPacket.payloadByteLength); // Custom memory management
videoRtpPacket.copyPayloadTo(destArrayBufferView);
destArrayBufferView.set(videoRtpPacket.payload);
depacketizeIntoJitterBuffer(videoRtpPacket.sequenceNumber, videoRtpPacket.marker, destArrayBufferView); // Custom
}
};
Expand All @@ -288,8 +288,46 @@ function packetizeEncodedFrame(frameArrayBuffer) {
rtpPacketSender.sendRtp({payload: packetPayloadView, makePacketMetadata().../* Custom */});
}
}
```


## Example 15: Receive with BYOP (Bring Your Own Packets)
```javascript
const dstPackets = [];
for (let i = 0; i < kBatchNumPackets; ++i) {
dstPackets.push(new RTCRtpPacket()); // Dummy until written to.
}

const [pc, videoRtpReceiver] = await setupPeerConnectionWithRtpReceiver(); // Custom
const rtpPacketReceiver = await videoRtpReceiver.replacePacketReceiver(); // Custom
rtpPacketReceiver.onrtpreceived = () => {
const packetsReceived = rtpPacketReceiver.readReceivedRtp(dstPackets);
for (let i = 0; i < packetsReceived; ++i) {
rtpPacketReceiver.receiveRtp(dstPackets[i]);
}
};
```


## Alternative designs considered
### Example 16: Send with BYOP (Bring Your Own Packets)

```javascript
const dstPackets = [];
for (let i = 0; i < kBatchNumPackets; ++i) {
dstPackets.push(new RTCRtpPacket()); // Dummy until written to.
}

const [pc, rtpSender] = await customPeerConnectionWithRtpSender();
const source = new CustomSource();
const encoder = new CustomEncoder();
const packetizer = new CustomPacketizer();
const rtpPacketSender = await rtpSender.replacePacketSender();
for await (const rawFame in source.frames()) {
encoder.setTargetBitrate(rtpPacketSender.allocatedBandwidth);
const encodedFrame = encoder.encode(rawFrame);
const packetsToSend = packetizer.packetize(encodedFrame, dstPackets);
for (let i = 0; i < packetsToSend; ++i) {
rtpPacketSender.sendRtp(dstPackets[i]);
}
}
```
67 changes: 41 additions & 26 deletions index.bs
Original file line number Diff line number Diff line change
Expand Up @@ -423,6 +423,8 @@ Terminology definitions go here.
interface RTCRtpTransport {
attribute EventHandler onpacketizedrtpavailable;
sequence&lt;RTCRtpPacket&gt; readPacketizedRtp(unsigned long maxNumberOfPackets);
// BYOP: Copies the read packets into `dstPackets`, returning the number of packets written (up to `dstPackets.length`).
unsigned long readPacketizedRtp(sequence&lt;RTCRtpPacket&gt; dstPackets);

attribute EventHandler onsentrtp;
// Batch interface to read RTCRtpSent notifications.
Expand Down Expand Up @@ -492,7 +494,12 @@ interface RTCRtpTransport {

<dl dfn-for="RTCRtpTransport">
<dt>
<dfn method>readPacketizedRtp(maxNumberOfPackets)</dfn>
<dfn method>readPacketizedRtp(unsigned long maxNumberOfPackets)</dfn>
</dt>
<dd>
</dd>
<dt>
<dfn method>readPacketizedRtp(sequence&lt;RTCRtpPacket&gt; dstPackets)</dfn>
</dt>
<dd>
</dd>
Expand All @@ -516,26 +523,25 @@ interface RTCRtpTransport {
[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;
// BYOP: Construct a packet that can be used as destination for writing read packets.
constructor();

attribute boolean marker;
attribute octet payloadType;
attribute unsigned short sequenceNumber;
attribute unsigned long timestamp;
attribute unsigned long ssrc;
sequence&lt;unsigned long&gt; getCsrcs();
Copy link
Contributor Author

@henbos henbos Jan 14, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sequences are copied by value and cannot be attributes, but I think we could use ObservableArray<T> to avoid the array copies as well then nothing is a copy (you would still internally need to copy between JS layer and C++ layer in read and write methods but we would not have any temporary objects imposted on the user of the API IIUC)

undefined setCsrcs(sequence&lt;unsigned long&gt; csrcs);
sequence&lt;RTCRtpHeaderExtension&gt; getHeaderExtensions();
readonly attribute unsigned long paddingBytes;
undefined setHeaderExtensions(sequence&lt;RTCRtpHeaderExtension&gt; headerExtensions);
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;
attribute AllowSharedBufferSource payload;

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

undefined setHeaderExtension(RTCRtpHeaderExtension headerExtension);
attribute DOMHighResTimeStamp? receivedTime;
attribute unsigned long? sequenceNumberRolloverCount;
};
</pre>

Expand Down Expand Up @@ -570,11 +576,6 @@ interface RTCRtpPacket {
</dt>
<dd>
</dd>
<dt>
<dfn attribute>payloadByteLength</dfn>
</dt>
<dd>
</dd>
<dt>
<dfn attribute>receivedTime</dfn>
</dt>
Expand All @@ -594,17 +595,17 @@ interface RTCRtpPacket {
<dd>
</dd>
<dt>
<dfn method>getHeaderExtensions()</dfn>
<dfn method>setCsrcs(sequence&lt;unsigned long&gt; csrcs)</dfn>
</dt>
<dd>
</dd>
<dt>
<dfn method>copyValueTo(AllowSharedBufferSource destination)</dfn>
<dfn method>getHeaderExtensions()</dfn>
</dt>
<dd>
</dd>
<dt>
<dfn method>setHeaderExtension(RTCRtpHeaderExtension headerExtension)</dfn>
<dfn method>setHeaderExtensions(sequence&lt;RTCRtpHeaderExtension&gt; headerExtensions)</dfn>
</dt>
<dd>
</dd>
Expand Down Expand Up @@ -805,7 +806,9 @@ interface RTCRtpPacketSender {
readonly attribute unsigned long rtxSsrc;

attribute EventHandler onpacketizedrtp;
sequence&lt;RTCRtpPacket&gt; readPacketizedRtp(long maxNumberOfPackets);
sequence&lt;RTCRtpPacket&gt; readPacketizedRtp(unsigned long maxNumberOfPackets);
// BYOP: Copies the read packets into `dstPackets`, returning the number of packets written (up to `dstPackets.length`).
unsigned long readPacketizedRtp(sequence&lt;RTCRtpPacket&gt; dstPackets);

// https://github.com/w3c/webrtc-rtptransport/issues/32
undefined sendRtp(RTCRtpPacket packet);
Expand Down Expand Up @@ -846,7 +849,12 @@ interface RTCRtpPacketSender {

<dl dfn-for="RTCRtpPacketSender">
<dt>
<dfn method>readPacketizedRtp(long maxNumberOfPackets)</dfn>
<dfn method>readPacketizedRtp(unsigned long maxNumberOfPackets)</dfn>
</dt>
<dd>
</dd>
<dt>
<dfn method>readPacketizedRtp(sequence&lt;RTCRtpPacket&gt; dstPackets)</dfn>
</dt>
<dd>
</dd>
Expand Down Expand Up @@ -953,6 +961,8 @@ interface RTCRtpPacketReceiver {

attribute EventHandler onreceivedrtp;
sequence&lt;RTCRtpPacket&gt; readReceivedRtp(long maxNumberOfPackets);
// BYOP: Copies the read packets into `dstPackets`, returning the number of packets written (up to `dstPackets.length`).
unsigned long readReceivedRtp(sequence&lt;RTCRtpPacket&gt; dstPackets);

undefined receiveRtp(RTCRtpPacket packet);
};
Expand Down Expand Up @@ -982,6 +992,11 @@ interface RTCRtpPacketReceiver {
</dt>
<dd>
</dd>
<dt>
<dfn method>readReceivedRtp(sequence&lt;RTCRtpPacket&gt; dstPackets)</dfn>
</dt>
<dd>
</dd>
<dt>
<dfn method>receiveRtp(RTCRtpPacket packet)</dfn>
</dt>
Expand Down
Loading
Loading