W3C WebRTC
WG Meeting
Stockholm, Sweden
June 20, 2018
1
Chairs: Stefan Hakansson
Bernard Aboba
Harald Alvestrand
W3C WG IPR Policy
2
Welcome!
3
About this Meeting
Information on the meeting:
4
Proposed Agenda for June 20
9:00 AM - 9:30AM: Transports (Peter Thatcher)
9:30 AM - 10 AM Use Case Reprise - includes API level discussion (Peter Thatcher)
10:00 AM - 11 AM QUIC (Peter Thatcher)
Reference: https://w3c.github.io/webrtc-quic/
11 AM - noon: SCTP, Data Channel and Streams (Lennart Grahl)
Noon - 12:30 PM: Scalable Video Coding (Sergio and Bernard)
12:30 PM - 1 PM: E2E Security Drill-down (Goran, Youenn & Dr. Alex)
1PM - 1:30 PM: Lunch break
1:30 PM - 2 PM: Protocol dependencies (Stefan)
2 PM - 2:30 PM: WebRTC-Stats (Varun)
2:30 PM - 3:00 PM: WebRTC NV Repriese (Bernard)
3:00 PM - 3:30 PM: Worker reprise (Peter Thatcher)
3:30 PM - 4:00 PM: RtpTransport (Bernard Aboba)
4 PM - 5 PM Wrapup and next steps
5
Proposed update to Agenda June 20
9:00 AM - 9:30 AM: E2E Security Drill-down (Goran, Youenn & Dr. Alex)
9:30 AM - 10:00AM: NV Transports (Peter Thatcher)
10 AM - 10:30 AM Use Case Reprise - includes API level discussion (Peter Thatcher)
10:30 AM - 11:30 AM QUIC (Peter Thatcher)
Reference: https://w3c.github.io/webrtc-quic/
11:30 - noon AM: Scalable Video Coding (Sergio and Bernard)
noon - 1pm: SCTP, Data Channel and Streams (Lennart Grahl)
1PM - 1:30 PM: Lunch break
1:30 PM - 2 PM: Protocol dependencies (Stefan)
2 PM - 2:30 PM: WebRTC-Stats (Varun)
2:30 PM - 3:00 PM: Worker reprise (Peter Thatcher)
3:00 PM - 3:30 PM: ORTC Object Model Overview (Bernard and Peter)
4 PM - 5 PM Wrapup and next steps
6
On request from some...
Private exchange with WebRTC
Context
Trust model
Web App is trusted
Web App is partially trusted
Web App is untrusted
Conclusion
WebRTC NV Transports
6/2018 f2f
Do apps want to send audio, video, or data?
Do apps want to send audio video or data?
Yes
Do apps want to send over RTP, SCTP, or QUIC?
Do apps want to send over RTP, SCTP, or QUIC?
Yes
What WebRTC has right now
| RTP | SCTP | QUIC |
Audio | Yes | | |
Video | Yes | | |
Data | | Yes | Yes (ORTC) |
Unified audio/video/data
Track
Transport
Decoder
Track
Transport
Encoder
Receiver
Sender
Data Channel
Data Channel
Unified audio/video data
If you're doing audio, video, and data (games, VR, conference share, remote control):
We could do all of them
| RTP | SCTP | QUIC |
Audio | Done | Add Encoders | Add Encoders + QuicTransport |
Video | Done | ||
Data | Add RtpTransport | Done | Add QuicTransport |
�Apps can choose which protocols are easiest/best for its use case
DtlsTransport
Just like in ORTC:
SctpTransport
Just like in ORTC:
QuicTransport
Just like in ORTC and extension spec:
RtpTransport
Not like ORTC! ORTC doesn't provide RTP data channels, nor low-level control (e2ee, etc)
RtpTransport
interface RtpTransport {� sendRtpPacket(RtpPacket packet);� sendRtcpPacket(RtcpPacket packet);� attribute eventhandler onrtppacket;� attribute eventhandler onrtcppacket;�}
dictionary RtpPacket {� unsigned octet payloadType;� unsigned int sequenceNumber;� unsigned long ssrc;� array<RtpHeaderExtension> header_extensions;� array<unsigned long> csrcs;� bytes payload;�}
Questions for the WG
WebRTC NV Use Cases Round 2
Needs separate encoders/transport:
Needs unified audio/video/data:
29
Other stuff
30
WebRTC NV Use Cases Round 2
If we don't split encoders from transports, how will we:
Or do we just say no to these requirements?
31
Once possible course of action
Many of our doubts about a low-level API revolve around two things:
So... what if someone goes and does a proof of concept combination of low-level browser API + library on top that proves it can be performant and provides the library on top, or finds that it really isn't feasible?
32
QUIC
(Peter Thatcher)
https://w3c.github.io/webrtc-quic/
33
Thin layer on top of QUIC protocol; App controls the rest
RTCQuicTransport Interface
35
Source: https://w3c.github.io/webrtc-quic/#quic-transport*
RTCQuicStream Interface
36
Source: https://w3c.github.io/webrtc-quic/#quicstream*
Questions for the WG
What about worklets?
As you will see, there's a lot of complexity around buffering and backpressure on the receive side, all because JS can pause and not keep up with incoming data.
But what if we used a worklet on the received side?
// Called synchronously off main thread when data comes in. �// If it takes along time or doesn't call consume(), back pressure is applied.�QuicStream.setReceiver(worklet);�QuicStream.consume(count); // Called by receiver to consume or not
Similarly on the send side?
// Called synchronously off main thread when more can be written�QuicStream.setSender(worklet);
Could be a lot more simple and performant!
Alternative
I think we're much more future proof and get benefits sooner by letting apps/libraries do this.
Buffering and back-pressure
Buffering and back-pressure aren't simple. Because Javascript. Can freeze up.
We don't want throughput to suffer.
But we don't want to buffer a lot.
Properties of an ideal buffering/back-pressure solution
JS
Zzzzz
Browser
Plenty of data to send
Buffer
Success:
JS
Zzzzz
Browser
Zzzzz
Failure:
Properties of an ideal buffering/back-pressure solution
2. If the sending JS has a very large amount, the browser applies back pressure to the JS and doesn't buffer huge amounts. Scenario to avoid: a huge amount gets buffered.
JS
OK, I'll wait
Browser
Gotta wait for network
Buffer
Success:
JS
Huh? More Data!
Browser
Gotta wait for network
Failure:
Buffer
Buffer
Buffer
Buffer
Buffer
Buffer
Buffer
Properties of an ideal buffering/back-pressure solution
3. If the receiving JS can't process data as quickly as it comes across the network, the browser applies back-pressure across the network and the send side stops sending. Scenario to avoid: the receive buffer grows unbounded.
JS
Zzzz
Browser
Please stop sending!
Buffer
Success:
JS
Zzzz
Browser
Gotta do something with this.
Failure:
Buffer
Buffer
Buffer
Buffer
Buffer
Buffer
Buffer
Properties of an ideal buffering/back-pressure solution
4. If the receiving JS freezes up, the browser keeps receiving and buffers what is received enough to keep throughput high. Scenario to avoid: the receive buffer is full or non-existent, and nothing is received for a while, throughput suffering.
JS
Zzzz
Browser
Buffering a little is OK
Buffer
Success:
JS
Zzzz
Browser
Zzzz
Failure:
Current solution (alternatives can be considered)
As an app, you:
And you get:
Current solution (alternatives can be considered)
Or if you're sending lots of small, regular messages where reliability doesn't matter and you don't want buffering, all you have to do is:
That's it. If it succeeds, great. If not, oh well.
Current solution (in detail)
Alternative solution
Each QUIC stream has:
(see https://github.com/lgrahl/ortc-streams-demo)�
So waiting and buffering is (cross your fingers) taken care of by WritableStream and ReadableStream.
Note that one could implement these streams *on top* of the current solution. And the apparatus of WritableStream might be a too much overhead for many small streams.
TBD (more questions)
SCTP, Data Channel, Streams
Evolutionary Steps
(Lennart Grahl)
50
Tackling Use Case Requirements
Status Quo: Sender Side Buffering/Backpressure
JS
Browser
Messages
Success!
It works… but only under certain circumstances.
Status Quo: Sender Side Buffering/Backpressure
JS
Browser
Ouch!
Large messages still blow up the buffer.
Message (1 GiB)
Status Quo: Receiver Side Buffering/Backpressure
Ouch!
The receiver can’t say no.
JS
Browser
Buffer
Buffer
Buffer
Buffer
Buffer
Buffer
Messages
Ouch!
Message (1 GiB)
Browser
JS
Fixing Buffering/Backpressure: What Does SCTP Offer?
SCTP is message-oriented:
How:
Fixing Buffering/Backpressure: Quick & Dirty
Sending:
Receiving:
IMHO a brittle API.
Fixing Buffering/Backpressure: Streams
Sending:
Receiving:
More details in webrtc-pc#1732.
Fixing Buffering/Backpressure: Streams
Message
Chunk
Chunk
Chunk
createWritableStream(): Writable Stream
writer.write(chunk)
writer.write(chunk)
writer.write(chunk)
writer.close()
Message
Chunk
Chunk
Chunk
message (event): Readable Stream
reader.read(view)
reader.read(view)
reader.read(view)
reader.closed
httpResponseStream.pipeTo(dataChannel.createWritableStream())
Fixing Buffering/Backpressure: Streams
Advantages:
Questions for the WG:
More Control Knobs
Expose more ways to control data channel behaviour:
Ideally not controlled by RTCDataChannelParameters because it’s a dictionary that fails silently.
new RTCDataChannel(sctpTransport, {
maxRetransmits: 0,
label: ‘call me ordered UDP’,
});
sctpTransport.newChannel()
.withMaxRetransmits(0)
.withLabel(‘call me ordered UDP’)
.create();
Improving SCTP For Our Requirements
WebRTC NV & SCTP
Questions for the WG
Scalable Video Coding
(Sergio and Bernard)
64
SVC Use cases
Simulcast and SVC use cases are very similar (if not identical): content adaptation without transcoding
Adaptation will happen as a combination and/or trade off of the following items:
Typically you would always love to have the best quality, with biggest image size and most fps, but most of the times you have will be restricted to do that and have to adapt video stream to the match certain limits.
Also, another interesting use case would be for increasing reliability against packet losses by applying different protection levels to each layer and maximizing the probability that at least the base layer is received.
What do Application developers need?
What do SFU developers need?
How should we deliver SVC support?
Given the big differences on the SVC codecs it is not easy to come up with a common parameter/apis that will match all the functionalities provided by all present and future codecs in an easy way.
The proposed way forward for enabling SVC support is:
WebRTC 1.0
Background info:
We need a way to signal the SVC/Simulcast support on the browser and a basic on/off switch. Some alternatives:
Do we need to allow configuring image sizes, bitrates, fps and degradation of each layer or is it too complex?
WebRTC NV
Seems that we will split the RTPSender into different components so we will have a VideoEncoder interface (yay!).
We can just follow the same approach for WebRTC 1.0 and have a generic method(s) for setting the svc settings for all codecs:
dictionary SVCEncodingParamers {
// We know that defining a generic SVC parameters dictionary for all codecs is complex!
}
interface SVCVideoEncoder: VideoEncoder {
setSVCEcodingParameters(SVCEncodingParamers)
};
But, we don’t have any requirement to provide a single interface for all codecs, so we could specialice each SVC encoder and provide specific APIs for each codec that matches exactly its features:
interface AV1Encoder: SVCVideoEncoder {
//Specific AV1 SVC control API
};
Protocol Dependencies (Bernard)
71
ICE
Changes needed to protocol if we go with FlexICE
72
QUIC
73
SCTP
74
webrtc-stats
Varun Singh*
Harald Alvestrand
Spec Status
Experimental stats
Implementation Status
A lot of implementation work is needed here
Audio-only
A lot of implementation work is needed here
Video-only
A lot of implementation work is needed here
Verify the implementations
Adding Validations
webrtc-stats lessons learnt
Some suggestions for NV
Webrtc-stats lessons learnt
Alternatives
86
Experimental Stats
How do we make it happen?
How do we enable these?
87
WebRTC NV: What We’ve Talked About
88
ORTC Object Model
89
Source: http://draft.ortc.org/
WebRTC NV: Missing Pieces
90
WebRTC NV: Goals or Non-Goals
91
Do we move forward? If so, how?
92
Wrapup and Next Steps (Chairs)
93
Wrapup and Next Steps (Chairs)
94
For extra credit
95
Name that bird!
Thank you
Special thanks to:
W3C/MIT for WebEx
WG Participants, Editors & Chairs
The bird
96
Extra Slides
97
Worklets Galore
Lots of high perf stuff is already using worklets or JS callbacks:
WebAudio (https://webaudio.github.io/web-audio-api/#AudioWorklet)
Animation worklets (https://github.com/WICG/animation-worklet)
CSS paint worklets ( https://drafts.css-houdini.org/css-paint-api/#dom-css-paintworklet)
Layout worklet( https://drafts.css-houdini.org/css-layout-api/#dom-css-layoutworklet)
requestAnimationFrame
So... why not in the media pipeline? It might help with a few use cases:
98
Worklets Galore?
// RawFrame -> list<EncodedFrame> (simulcast/SVC)
RtpSender.setEncoder(worklet);
RtpSender.encode(rawFrame); // -> list<EncodedFrame>, to get default behavior
// EncodedFrame -> list<RtpPacket>
RtpSender.setPacketizer(worklet);
RtpSender.packetize(encodedFrame); // -> list<RtpPacket>, to get default behavior
// RtpPacket -> list<EncodedFrame> (RED; FEC)
RtpReceiver.setDepacketizer(worklet);
RtpReceiver.depacketize(rtpPacket); // -> list<EncodedFrame>, to get default behavior
// EncodedFrame -> list<RawFrame> (queued dependent frames)
RtpReceiver.setDecoder(worklet);
RtpReceiver.decode(encodedFrame); // -> list<RawFrame>, to get default behavior�
// This would allow sending and receiving over custom transports (SCTP or QUIC) and SFU in JS, but on the main thread.
RtpReceiver.injectEncodedFrame(EncodedFrame);
99
Can WebCrypto be synchronous in a worklet?
Worklets + ReadableStream Galore?
100
Worklets + ReadableStream Galore?
Custom encoder/decoder:
RtpSender.setEncodedFrameSource(RtcWorklet(MediaStreamTrack.frames, ...))
MediaStreamTrack.setFrameSource(RtcWorklet(RtpReceiver.encodedFrames, ...))
Double encryption per packet:
RtpSender.setRtpPacketSource(RtcWorklet(RtpSender.rtpPacket, ...))
RtpReceiver.setRtpPacketSource(RtcWorklet(RtpReceiver.rtpPackets, ...))
Custom transport for encoded frames
QuicTransport.setStreamSource(RtcWorklet(RtpSender.encodeFrames), ...)
RtpReceiver.setEncodedFrameSource(RtcWorklet(QuicTransport.getStreamSource()), ...)
RTP Data Channel
RtpSender.setRtpPacketSource(...);
101
RtpTransport
RtpTransport (ReadableStream version)
interface RtpTransport {� void sendRtpPackets(ReadableStream);� void sendRtcpPackets(ReadableStream);� readonly attribute ReadableStream receivedRtpPackets;� readonly attribute ReadableStream receivedRtcpPackets;�}
dictionary RtpPacket {� unsigned octet payloadType;� unsigned int sequenceNumber;� unsigned long ssrc;� array<RtpHeaderExtension> header_extensions;� array<unsigned long> csrcs;� bytes payload;�}
dictionary RtcpPacket {� ...�}
RtpTransport
interface RtpTransport {� void sendRtpPacket(RtpPacket packet);� void sendRtcpPacket(RtcpPacket packet);� attribute eventhandler onrtppacket;� attribute eventhandler onrtcppacket;�}
dictionary RtpPacket {� unsigned octet payloadType;� unsigned int sequenceNumber;� unsigned long ssrc;� array<RtpHeaderExtension> header_extensions;� array<unsigned long> csrcs;� bytes payload;�}
dictionary RtcpPacket {� ...�}