- From: Adam Bergkvist <adam.bergkvist@ericsson.com>
- Date: Thu, 19 Dec 2013 08:07:13 +0100
- To: Justin Uberti <juberti@google.com>, "public-webrtc@w3.org" <public-webrtc@w3.org>
Great. It's time to advance with this proposal.
On 2013-12-19 04:35, Justin Uberti wrote:
> Based on some feedback I've received, I've slightly updated my proposal
> (originally inspired by Martin) on doohickeys and replacing AddStream
> with AddTrack. See below:
>
> ------------------------------------------------------------------------
>
> I suggest we call the SendDoohickeys RtpSenders and the corresponding
> receive-side objects RtpReceivers. These objects allow control of how a
> MediaStreamTrack is encoded and sent on the wire, including "hold"
> state, prioritization, and multiple encodings (e.g. simulcast).
Do we need to have RTP in the names? I know that these names won't be
used much in code, but we need to talk about them :) and, when we add
the RTC-prefix the name will start with two acronyms (which isn't very
nice IMO). Perhaps we could call them RTCMediaSender/RTCMediaReceiver?
The network behavior is given by "sender"/"receiver" and "media"
distinguish them from the data channel.
> You get a RtpSender as a return value from AddTrack (which replaces
> AddStream). You get a RtpReceiver as an argument to the new onaddtrack
> callback (which replaces onaddstream). The actual track object can be
> obtained as a property from the RtpReceiver (see below).
>
> For getting access to ICE/DTLS info, both RtpSenders and RtpReceivers
> can also have a reference to a DtlsTransport object, which will have its
> own state variables, including the RTCIceConnectionState of that
> particular transport, and the .remoteCertificates for the DTLS
> connection. This allows applications to monitor the state of individual
> transports, as well as inspect the certificates for individual transports.
>
> The actual interface is as follows:
>
> interface DtlsTransport {
> attribute RTCIceConnectionState state;
> attribute sequence<ArrayBuffer> remoteCertificates;
> //... more stuff as needed
> };
>
> interface RtpSender {
> readonly attribute MediaStreamTrack track;
> readonly attribute DtlsTransport transport;
> // various tweakable attributes
> attribute bool active; // controls "am I sending RTP"
> attribute PriorityLevel priority; // for relative bandwidth allocation
> // for multiple encodings: simulcast (audio or video), layered coding
> // specify the codec to use, resolution, bitrate, and any
> dependencies for each encoding
> attribute sequence<EncodingParams> encodings;
> };
>
> interface RtpReceiver {
> readonly attribute Transport transport;
> readonly attribute MediaStreamTrack track;
> // more stuff as needed
> };
>
> partial interface PeerConnection {
> RtpSender addTrack(MST); // replaces addStream
> void removeTrack(RtpSender); // replaces removeStream
> readonly attribute sequence<RtpSender> senders;
> readonly attribute sequence<RtpReceiver> receivers;
Nit: these need to be getter methods.
> EventHandler onaddtrack; // replaces onaddstream; onremovestream is
> not needed
I'm a bit confused by the comment above. Since we don't use streams here
onremovestream goes away naturally, but did you mean that we don't need
onremovetrack?
> };
>
> For backcompat, addStream, removeStream, getLocalStreams,
> getRemoteStreams, and onaddstream can be trivially polyfilled in JS, so
> there is minimal impact on current applications.
>
> All together, the pipeline looks like this:
>
> Source ---> MST ---> RtpSender ---> Transport ---> (The Internet) --->
> Transport ---> RtpReceiver ---> MST ---> <video/>
>
> Each RtpSender/Receiver references a single MST, although a single
> RtpSender/Receiver can send/receive multiple encodings (e.g. simulcast).
> There are N RtpSenders/Receivers per Transport; N is controlled by the
> policy specified for BUNDLE.
>
Diff of needed changes to our simple RTCPeerConnection example:
--- a/webrtc_simple_example_old.js
+++ b/webrtc_simple_example.js
@@ -6,6 +6,9 @@ var pc;
function start() {
pc = new RTCPeerConnection(configuration);
+ // used to render incoming tracks
+ var receiveStream = new MediaStream();
+
// send any ice candidates to the other peer
pc.onicecandidate = function (evt) {
if (evt.candidate)
@@ -17,15 +20,20 @@ function start() {
pc.createOffer(localDescCreated, logError);
}
- // once remote stream arrives, show it in the remote video element
- pc.onaddstream = function (evt) {
- remoteView.src = URL.createObjectURL(evt.stream);
+ // once remote media arrives, add it to a stream to be rendered
+ pc.onaddtrack = function (evt) {
+ receiveStream.addTrack(evt.receiver.track)
+
+ if (!remoteView.srcObject)
+ remoteView.srcObject = receiveStream;
};
- // get a local stream, show it in a self-view and add it to be sent
+ // get a local stream, show it in a self-view and add the tracks to
be sent
navigator.getUserMedia({ "audio": true, "video": true }, function
(stream) {
selfView.src = URL.createObjectURL(stream);
- pc.addStream(stream);
+
+ stream.getAudioTracks().forEach(pc.addTrack);
+ stream.getVideoTracks().forEach(pc.addTrack);
}, logError);
}
/Adam
Received on Thursday, 19 December 2013 07:07:38 UTC