- From: Iñaki Baz Castillo <ibc@aliax.net>
- Date: Tue, 7 Jan 2014 11:30:28 +0100
- To: Peter Thatcher <pthatcher@google.com>
- Cc: "public-orca@w3.org" <public-orca@w3.org>
It seems really powerful, love it.
2014/1/7 Peter Thatcher <pthatcher@google.com>:
> Some of the discussions in the recent W3C WebRTC WG have centered around the
> idea of having "rtp send doohickeys" and "rtp receive doohickeys", which
> would represent objects that control sending and receiving a single media
> track, respectively. I think this would be a good direction for the ORTC
> API to take, and I think would improve upon the ORTC API greatly. You can
> think of this as splitting the "RTCTrack" into two classes: a "sender" class
> and a "receiver" class, refining their methods and attributes.
>
> I propose an API something like the following. I'm using the names
> "RtpSender" and "RtpReceiver" which Justin Uberti proposed to the W3C.
>
> // An RTCRtpSender sends one MediaStreamTrack
> // over one RTCConnection.
> // If you want to send a whole MediaStream with multiple tracks,
> // Create multiple RtpSenders.
> [Constructor(MediaStreamTrack track, RTCConnection transport)]
> interface RTCRtpSender {
> readonly attribute MediaStreamTrack track;
> readonly attribute RTCConnection transport;
>
> // The way media is sent is controlled by the given "parameters".
> // The sender starts sending when send() is called,
> // And stops sending when stop() is called.
> // send() may be called more than once to change parameters.
> // stop() is final, just like MediaStreamTrack.
> void send(RTCRtpParameters parameters);
> void stop();
>
> // NOTE: We can't have a readonly attribute because apparently
> // In WebIDL, "readonly" doesn't make the returned object
> // readonly, just the reference.
> RTCRtpParameters parameters();
>
> // Instead of a top-level getRtcCapabilities and getRtcCodecs(),
> // We have a static method on the RtpSender and RtpReceiver
> // (send and receive capabilities might be different).
> static RTCRtpCapabilities getCapabilities();
> // While JS can construct and negotiate parameters just based on
> // the capabilities, doing so is usually a pain, so we provide two
> // convenience methods to help with the process. The first
> // creates parameters based on capabilities and the second filters
> // already created paremters based on capabilities. This allows
> // for a lot of flexibility of which side does the neogitation and
> // when.(We're not confined to an offer/answer model).
> static RtpParameters createParameters(
> MediaStreamTrack track
> optional RTCRtpCapabilities capabilities);
> static RTCRtpParameters filterParameters(
> RTCRtpParameters parameters,
> optional RTCRtpCapabilities capabilities);
> }
>
> // An RTCRtpReceiver receives one MediaStreamTrack over one
> // RTCConnection. If you want to receive a whole MediaStream with
> // multiple tracks, create multiple RtpReceivers.
> [Constructor(optional RTCConnection transport)]
> interface RTCRtpReceiver {
> // The media coming from the transport is available from the
> // track. The track is null until receive() is called, and once
> // it is set to non-null, will not changed.
> readonly attribute MediaStreamTrack? track;
> readonly attribute RTCConnection transport;
>
> // The way media is received is controlled by the given
> // "parameters". The receiver starts receiving when receive() is
> // called, and stops sending when stop() is called.
> // receive() may be called more than once to change parameters.
> // stop() is final, and the receive can never receive again.
> void receive(RTCRtpParameters parameters);
> void stop();
>
> // NOTE: We can't have a readonly attribute because apparently
> // In WebIDL, "readonly" doesn't make the returned object
> RTCRtpParameters parameters();
>
> // Instead of a top-level getRtcCapabilities and getRtcCodecs(),
> // We have a static method on the RtpSender and RtpReceiver
> // (send and receive capabilities might be different).
> static RTCRtpCapabilities getCapabilities();
> // While JS can construct and negotiate parameters just based on
> // the capabilities, doing so is usually a pain, so we provide two
> // convenience methods to help with the process. The first
> // creates parameters based on capabilities and the second filters
> // already created paremters based on capabilities. This allows
> // for a lot of flexibility of which side does the neogitation and
> // when. (We're not confined to an offer/answer model).
> static RtpParameters createParameters(
> DOMString kind, // "audio" or "video"
> optional RTCRtpCapabilities capabilities);
> static RTCRtpParameters filterParameters(
> RTCRtpParameters parameters,
> optional RTCRtpCapabilities capabilities);
> }
>
> // The RTCRtpParameters contains much of what currently exists as /
> // attributes of RTCTrack, but as a dictionary, it's much easier to
> // serialize/deserialize for signalling, and pass into and out from
> // convenience methods for neogitation. Finally, it allows changing
> // of parameters in an atomic way.
> dictionary RTCRtpParameters {
> sequence<RTCRtpCodec> codecs;
>
> // Can specify multiple multiple layers or "encodings",
> // such as for simulcast, RTX, FEC, etc in the future.
> sequence<RTCRtpEncodingParameters> encodings;
>
> // TODO: RTP header extensions, "appID", ...
> }
>
> dictionary RTCRtpEncodingParameters {
> unsigned int ssrc;
>
> // TODO: Things to control various layers, simulcast, rtx, etc.
> // For now, let's just recognize that we need more than one
> // and we need more than the SSRC. So let's make a dictionary,
> // and figure out the details later.
> }
>
>
> Finally, here's an example of how it could be used:
>
> // Assume we already have a way to signal, a transport
> // (RTCConnection), and audio and video tracks. This is an example
> // of how to offer them and get back an answer with audio and
> // video tracks, and begin sending and receiving them.
> function initiate(signaller, transport, audioTrack, videoTrack) {
> var audioSender = new RTCRtpSender(audioTrack, transport);
> var videoSender = new RTCRtpSender(videoTrack, transport);
> var audioReceiver = new RTCRtpReceiver(transport);
> var videoReceiver = new RTCRtpReceiver(transport);
>
> var sendAudioParams = RTCRtpSender.createParameters(audioTrack);
> var sendVideoParams = RTCRtpSender.createParameters(videoTrack);
> signaller.offerTracks({
> // The initiator offers parameters it wants to send with,
> // and the capabilities it has for receiving.
> "rtpCaps": RTCRtpReceiver.getCapabilities(),
> "audio": sendAudioParams,
> "video": sendVideoParams
> }, function(answer) {
> // The responder answers with parameters it wants to send with
> // and the capabilities it has for receiving.
> audioSendParams = RTCRtpSender.filterParameters(
> sendAudioParams, answer.rtpCaps);
> videoSendParams = RTCRtpSender.filterParameters(
> sendVideoParams, answer.rtpCaps
> var audioRecvParams = RTCRtpSender.filterParameters(
> answer.audio);
> var videoRecvParams = RTCRtpSender.filterParameters(
> answer.video);
>
> audioSender.send(audioSendParams);
> videoSender.send(videoSendParams)
> audioReceiver.receive(audioRecvParams);
> videoReceiver.receive(videoRecvParams);
>
> // Now we can render/play
> // audioReceiver.track and videoReceiver.track.
> });
> }
>
> // Assume we already have a way to signal, a transport
> // (RTCConnection), and audio and video tracks. This is an example
> // of how to answer an offer with audio and video tracks, and begin
> // sending and receiving them.
> function accept(
> signaller, remote, transport, audioTrack, videoTrack) {
> var audioSender = new RTCRtpSender(audioTrack, transport);
> var videoSender = new RTCRtpSender(videoTrack, transport);
> var audioReceiver = new RTCRtpReceiver(transport);
> var videoReceiver = new RTCRtpReceiver(transport);
>
> var audioSendParams = RTCRtpSender.createParameters(
> audioTrack, remote.rtpCaps);
> var videoSendParams = RTCRtpSender.createParameters(
> videoTrack, remote.rtpCaps);
> var audioRecvParams = RTCRtpSender.filterParameters(
> remote.audio);
> var videoRecvParams = RTCRtpSender.filterParameters(
> remote.video);
>
> audioSender.send(audioSendParams);
> videoSender.send(videoSendParams)
> audioReceiver.receive(audioRecvParams);
> videoReceiver.receive(videoRecvParams);
>
> signaller.answerTracks({
> "rtpCaps": RTCRtpReceiver.getCapabilities(),
> "audio": audioSender.parameters(),
> "video": videoSender.parameters()
> });
>
> // Now we can render/play
> // audioReceiver.track and videoReceiver.track.
> }
>
--
Iñaki Baz Castillo
<ibc@aliax.net>
Received on Tuesday, 7 January 2014 10:31:19 UTC