1 of 55

W3C WebRTC

WG Meeting

October 15, 2024

8 AM - 10 AM

1

Chairs: Bernard Aboba

Jan-Ivar Bruaroey

Guido Urdaneta

2 of 55

Welcome!

  • Welcome to the October 2024 interim meeting of the W3C WebRTC WG, at which we will cover:
    • Codec Issues, WebCodecs/WebRTC Interop, Encode Complexity Control, IceTransport Extensions, RtpTransport, Setting the zoom level on captured tabs.
  • Future meetings:
    • November 19
    • December 10

2

3 of 55

About this Virtual Meeting

3

4 of 55

W3C WG IPR Policy

4

5 of 55

W3C Code of Conduct

  • This meeting operates under W3C Code of Ethics and Professional Conduct
  • We're all passionate about improving WebRTC and the Web, but let's all keep the conversations cordial and professional

5

6 of 55

Virtual Interim Meeting Tips

This session is (still) being recorded

  • Click to get into the speaker queue.
  • Click to get out of the speaker queue.
  • Please wait for microphone access to be granted before speaking.
  • If you jump the speaker queue, you will be muted.
  • Please use headphones when speaking to avoid echo.
  • Please state your full name before speaking.
  • Poll mechanism may be used to gauge the “sense of the room”.

6

7 of 55

Understanding Document Status

  • Hosting within the W3C repo does not imply adoption by the WG.
    • WG adoption requires a Call for Adoption (CfA) on the mailing list.
  • Editor’s drafts do not represent WG consensus.
    • WG drafts do imply consensus, once they’re confirmed by a Call for Consensus (CfC) on the mailing list.
    • Possible to merge PRs that may lack consensus, if a note is attached indicating controversy.

7

8 of 55

Issues for Discussion Today

  • 08:10 - 08:30 AM Codec Issues (Harald and Henrik)
  • 08:30 - 08:40 AM WebRTC/WebCodecs Interop (Harald)
  • 08:40 - 08:50 AM Encode Complexity Control (Erik)
  • 08:50 - 09:10 AM IceTransport Extensions (Sameer)
  • 09:10 - 09:30 AM RtpTransport (Peter Thatcher)
  • 09:30 - 09:50 AM Setting the zoom-level on captured tabs (Elad)
  • 09:50 - 10:00 AM Wrapup and Next Steps (Chairs)

Time control:

  • A warning will be given 2 minutes before time is up.
  • Once time has elapsed we will move on to the next item.

8

9 of 55

Codec Issues

Start Time: 08:10 AM

End Time: 08:30 AM

9

10 of 55

For Discussion Today

  • Issue 3006: Align spec /w codec direction decision
  • Issue 2927: Applying a remote offer with unsupported codecs results in stale transceiver

10

11 of 55

Issue 3006: Align spec /w codec direction decision (Henrik B)

One codec issue to rule them all

Closed the following as dupes of #3006 (= Proposal A from TPAC):

  • Issue 2888: setCodecPreferences vs. unidirectional codecs
  • Issue 2937: setCodecPreferences, sendonly codecs and dummy codecs
  • Issue 2938: If a preferred codec is filtered out, does it still get assigned a PT?
  • Issue 2939: Proposing setCodecPreferences to deal with both send and recv codecs
  • Issue 2989: codec input to setParameters shouldn't be validated by preferred receive codecs

11

12 of 55

Issue 3006: Align spec /w codec direction decision (Henrik B)

TL;DR: Filter codec preferences by m= section direction.

  • We already do this % revisiting amendment

12

13 of 55

Issue 3006: Align spec /w codec direction decision (Henrik B)

Problem: What happens if filtering results in an empty preference list?

No codecs implies rejecting the m= section…

13

etc. (same for recv)

14 of 55

Issue 3006: Align spec /w codec direction decision (Henrik B)

What happens if filtering results in an empty preference list?

Proposal A (it’s ok):

Treat “no preference after filter” as “no preference” (= O/A all codecs) 🦶🤗

Proposal B (fail early):

Throw an exception when setting direction or setCodecPreferences.

But… going from sendonly to recvonly may require a “reset preference dance”.

🦶🔫

Proposal C (fail late):

Reject transceiver as part of negotiation due to no codecs. 💣🦶💣

14

15 of 55

WebCodecs/WebRTC Interop (Harald)

Start Time: 08:30 AM

End Time: 08:40 AM

15

16 of 55

Marrying EncodedSource and WebCodecs is powerful

Enables applications where control of encoding details is critical

Allows apps to make per-frame decisions on encoding

16

17 of 55

WebCodecs and Encoded Transform frame formats differ

interface EncodedVideoChunk {

constructor(EncodedVideoChunkInit init);

readonly attribute EncodedVideoChunkType type; // “key” or “not key”

readonly attribute long long timestamp; // microseconds

readonly attribute unsigned long long? duration; // microseconds

readonly attribute unsigned long byteLength;

undefined copyTo(AllowSharedBufferSource destination);

};

17

18 of 55

Merging is not possible. Mapping is.

  • Data access: Attribute vs CopyTo
  • Configuration info: Metadata vs Configuration
    • Even such basics as MIME type and frame size
  • RTP level data should not need to be set
    • The outgoing packetizer/sender handles that

18

19 of 55

Proposed API shape

RTCEncodedVideoFrame {

constructor(EncodedVideoChunk, RTCEncodedVideoFrameMetadata metadata)

}

EncodedVideoChunk {

constructor(RTCEncodedVideoFrame)

}

Discuss!

19

20 of 55

Discussion (End Time: 08:40)

20

21 of 55

Encoder Complexity (Erik)

Start Time: 08:40 AM

End Time: 08:50 AM

21

22 of 55

Issue 191: Add API to control encode complexity

22

Add encodeComplexityMode to RTCRtpEncodingParameters:

enum RTCEncodeComplexityMode {

"low",

"normal",

"high"

};

partial dictionary RTCRtpEncodingParameters {

RTCEncodeComplexityMode encodeComplexityMode = "normal";

};

Specifies the encoding complexity mode relative to "normal" mode:

  • "low" mode results in lower device resource usage and worse compression efficiency
  • "high" mode results in higher device resource usage and better compression efficiency

23 of 55

Issue 191: Add API to control encode complexity

23

Intended use cases:

  • Allow an application to balance bandwidth/CPU usage
    • Possible to reduce bandwidth usage without regressing quality at the expense of higher CPU usage. Choice that can depend on both device type and organizational requirements.

  • Better ability to adapt to type of device
    • Reduce CPU usage for devices with known thermal-throttling issues
    • Increase quality for non-constrained devices (e.g. plugged in meeting room devices)

24 of 55

Discussion (End Time: 08:50)

24

25 of 55

IceTransport Extensions (Sameer)

Start Time: 08:50 AM

End Time: 09:10 AM

25

26 of 55

Issue 209 - App control over ICE checks

  • Allow an App to observe and send ICE checks
  • Learn RTT from ICE checks to determine the best candidate pair to use for transport at any given time
  • Consent renewal checks are sent every 4-6 seconds in connected state
  • If the active pair is degrading, App can respond before an ICE disconnect by
    • Sending checks on active pair to verify connectivity
    • Sending checks on backup pairs to evaluate alternate paths
    • Switching to a different candidate pair (Issue 171 ✅, TPAC '23)

26

27 of 55

Proposal

partial interface RTCIceTransport {

// Send an ICE check.

Promise<RTCIceCheckRequest> checkCandidatePair(RTCIceCandidatePair pair);

// Fired before ICE agent sends an ICE check.

attribute EventHandler /* RTCIceCheckEvent */ onicecandidatepaircheck;

}

interface RTCIceCheckEvent : Event {

readonly attribute RTCIceCandidatePair candidatePair;

// Resolves when the check is actually sent. Rejected => send failure.

readonly attribute Promise<RTCIceCheckRequest> request;

}

interface RTCIceCheckRequest {

readonly attribute ArrayBuffer transactionId;

readonly attribute DOMHighResTimeStamp sentTime;

// Resolves when response is received. Rejected => timeout.

readonly attribute Promise<RTCIceCheckResponse> response;

}

interface RTCIceCheckResponse {

readonly attribute DOMHighResTimeStamp receivedTime;

readonly attribute boolean retransmitted;

// No error => success.

readonly attribute RTCIceCheckResponseError? error;

}

  • Event fired before ICE check is sent; or App can initiate an ICE check
  • A promise resolves when an ICE check is sent
  • Another promise resolves when a response is received or the check times out

27

28 of 55

Proposal

  • Only STUN binding requests are notified to the App
    • Not other STUN methods eg. Allocate, Refresh, Send or Data indications
    • Not STUN binding indications - these don't generate a response
  • Retransmits are not notified to the App
    • RTCIceCheckResponse indicates if retransmission occurred
    • Response should not be used to compute RTT, only to gauge reachability
  • App can only send STUN binding requests, not other STUN methods
    • Always a new STUN transaction, rate-limited
    • Possible to have multiple outstanding checks for a candidate pair

28

29 of 55

Usage

const pc = …;

const ice = pc.getTransceivers()[0].sender.transport.iceTransport;

ice.onicecandidatepaircheck = async(event) => {

try {

const request = await event.request;

handleCheck(request);

} catch(error) {

// … do something with error

}

}

// send a check

const request = await ice.checkCandidatePair(alternatePair);

handleCheck(request);

function handleCheck(request) {

try {

const response = await request.response;

if (response.error) {

// … do something with error

return;

}

const rtt = response.receivedTime - request.sentTime;

if (!response.retransmitted) {

// … do something with rtt

}

} catch(error) {

// … do something with timeout

}

}

29

30 of 55

Future extensibility

  • Prevent outgoing checks by allowing App to call preventDefault() in onicecandidatepaircheck handler
  • Read STUN attributes in binding request and response

partial interface RTCIceCheckRequest { partial interface RTCIceCheckResponse {

readonly attribute RTCStunAttributes attributes; readonly attribute RTCStunAttributes attributes;

} }

dictionary RTCStunAttributes { dictionary RTCUnrecognizedStunAttribute {

boolean useCandidate; required ArrayBuffer type;

sequence<ArrayBuffer> unknownAttributes; ArrayBuffer value;

sequence<RTCUnrecognizedStunAttribute> unrecognizedAttributes; }

}

  • Set STUN attributes in an outgoing binding request

Promise<RTCIceCheckRequest> checkCandidatePair(RTCIceCandidatePair pair, optional RTCStunAttributes attributes);

  • Set timeout, max retransmission on an outgoing binding request

Promise<RTCIceCheckRequest> checkCandidatePair(RTCIceCandidatePair pair, optional double timeout, optional unsigned short maxRetransmissions);

30

31 of 55

How do ICE checks work today?

  • ICE connectivity checks sent at the beginning of an ICE session
    • ICE agent cycles through the discovered candidate pairs
    • Paced ~50ms apart
    • Retransmitted on timeout with exponential backoff
    • Triggered checks to converge faster on working pairs
    • A selected candidate pair is nominated

  • Keepalives sent every 15 seconds when no RTP/RTCP packets sent

  • Consent renewal sent every 4-6 seconds
    • Consent expires after 30 seconds without renewal
    • Makes keepalives redundant

31

32 of 55

Discussion (End Time: 09:10)

32

33 of 55

RtpTransport (Peter Thatcher)

Start Time: 09:10 AM

End Time: 09:30 AM

33

34 of 55

Reminder about use cases

Control/customization of:

  • Payloads and Header Extensions (Codecs, Data, Metadata)
  • Packetization (WebCodecs, WASM)
  • Reliability (FEC, NACK/RTX)
  • Jitter Buffer
  • Congestion Control (bandwidth estimation, pacing, probing)
  • Rate Control (bitrate allocation, encoder rates)
  • Control/Feedback messages

34

35 of 55

Example Use Cases

  • Send arbitrary data within the same congestion control as audio/video
  • Do processing (face tracking) on video and attach metadata
  • WebCodecs-based support for:
    • AAC over RTP
    • Control of hardware/software failover
    • Per-frame QP rate control
    • Long-term references (LTRs)
    • Spatial scalability with Layer Refresh (LRR)
  • Implement an audio codec using WASM
  • Implement FEC designed for high-loss scenarios
  • Implement a jitter buffer more suitable to streaming applications
  • Forward RTP packets from one PeerConnection to another
  • Implement a congestion control algorithm using L4S signals
  • Implement RTCP messages like LRR, RPSI, SLI, RTCP-XR

35

36 of 55

Status Update

  • A while ago
    • Agreement in the Working Group to add "piecemeal" (incremental) low-level RTP/RTCP functionality
  • Progress made since then

36

37 of 55

Things That Have Been Figured Out

  • Transferability/Workers
    • RtpTransport requires DedicatedWorker
    • RtpSendStream/RtpReceiveStream are Transferable
  • Processing lots of packets (optional batch processing)
    • Events have no payloads
    • You read out the event payloads with pattern of "readFoo(long maxNumber)"
  • Custom BWE/Pacing/Probing
    • JS told what RTP packets would have been sent
    • JS can send packets with a particular send time
    • JS told what RTP packets have been sent and what RTCP feedback has been received
    • JS told if a packet is dropped because of "overuse" (according to a lenient congestion controller)
  • BYOB

37

38 of 55

Things In Progress

  • Custom NACK/RTX (Explainer coming)
  • Simulcast (per-MID vs per-RID objects in the API)
  • Going "SDP-less" (Explainer coming)

38

39 of 55

Conclusion

  • We're making good progress
  • Still much work to do

39

40 of 55

Discussion (End Time: 09:30)

40

41 of 55

Setting the zoom-level on captured tabs�(Elad)

Start Time: 09:30 AM

End Time: 09:50 AM

41

42 of 55

Captured Surface Control - Reminder

  • An API for limited control of a shared tab. (In the future, possibly also windows.)
  • Allows scrolling and zooming.
  • Previously:
    • Agreement in the WG that this should be solved.
    • Agreement about our general approach.
    • Concerns allowing control by a remote user.
    • Agreement that captureWheel() dispels such concerns.
    • Agreement that a similar approach could be applied to zoom.

42

43 of 55

setZoomLevel() – Desired Properties

Properties sought:

  • Should only be callable in response to the user’s direct interaction with the capturing page.
  • No consensus that transient activation is sufficient;�tighter guarantees sought.

43

44 of 55

Gating setZoomLevel() – General Idea

44

…but how do we specify this formally?

45 of 55

Gating setZoomLevel() – First Stab

45

46 of 55

Gating setZoomLevel() – Simpler Approaches

  • Recognize that typical code is already running from the context of an event handler for some user-visible element.
  • Try harder to specify the restriction that setZoomLevel() must only be callable from certain contexts.

46

47 of 55

Gating setZoomLevel() – Simpler Approach #1

Use clear and descriptive language in the spec, although it would not be optimally spec-y. Something along the lines of:

47

48 of 55

Gating setZoomLevel() – Simpler Approach #2

Rely on Window.event.

It is marked as “legacy”, but it does not appear problematic.

48

49 of 55

Gating setZoomLevel() – Simpler Approach #3

Require that the Web application provide the event it’s handling as further input to setZoomLevel().

Note: The dispatch flag check ensures cached events can’t be used.

49

50 of 55

Gating setZoomLevel() – Suggestion

  • I propose we go with option #2.
  • Wdyt?

50

51 of 55

Gating setZoomLevel() – Event Types

I don’t think this is a problem, but in the interest of starting out conservatively, I propose:

51

52 of 55

Discussion (End Time: 09:50)

52

53 of 55

Wrapup and Next Steps

Start Time: 09:50 AM

End Time: 10:00 AM

53

54 of 55

Next Steps

  • Content goes here

54

55 of 55

Thank you

Special thanks to:

WG Participants, Editors & Chairs

55