Re: Simplify the new addTrack() API

On 10/02/15 08:09, Harald Alvestrand wrote:
> On 02/09/2015 03:26 PM, Adam Bergkvist wrote:
>> Hi
>>
>> With the introduction of RTCRtpSender/Receiver (Doohickeys), the way to
>> send and receive media will change. We used to add a MediaStream at one
>> end, and dispatch a corresponding stream at the other end.
>>
>> The new addTrack()-based approach is to add one MediaStreamTrack and
>> zero or more MediaStreams, containing the track, at one end, and
>> dispatch a RTCRtpReceiver, the corresponding track and a list of
>> MediaStreams, containting the track, at the other end. This implies
>> creating a new stream if a certain stream isn't represented at the other
>> side, or no stream was supplied for a track, and keeping handles to
>> previously created streams to be able to add future tracks to them.
>>
>> Even though the API call is named addTrack(), MediaStreams are very much
>> involved with increased complexity as the cost. One reason for this is
>> the need to polyfill the old addStream()-API on top of the new.
>
> This is a common thing to have to do, whether it's done as part of
> implementing the spec or as part of making the spec usable for people
> who are used to the "previous style".
>
> These days, it seems common to write new APIs first as polyfills and
> then embed the polyfill (still in Javascript) inside the browser through
> an API-embedding mechanism and call it "platform implementation" - I
> hear this is done for the Chrome Promises API, for instance.
>
>>
>> A different approach could be to keep the new addTrack()-API simple and
>> provide the API points needed to polyfill or implement advanced stream
>> handling in the application. For example:
>>
>> addTrack(MST track, optional DOMString tag);
>>
>> - The optional tag argument is a string that is signalled in SDP that
>> contains application specific info. For example, a list of MediaStream
>> ids.
>
> I take it you're assuming that the app would have to know from
> non-standard sources what the tag was supposed to mean?

Yes.

> If it's going to support the previous addStream() API in the way the
> currently proposed addTrack() does, with multiple streams created, it
> would have to be either a sequence of DOMStrings or a tag with internal
> syntax <ugh>.

A list of tags wold work as well, even though it's quite easy to split 
strings in JavaScript. I believe the support for multiple streams is 
introduced with the new addTrack() API and it's not really needed to 
polyfill the old addStream() API. The tracks belong solely to the 
MediaStream indicated by the argument to addStream().

>>    The corresponding event would expose the string the other side.
>>
>> (Constructor) MediaStream(DOMString id);
>>
>> - Construct a stream with a given id.
>>
>> Feedback and suggestions are welcome.
>
> As an experiment, I'd suggest writing up the polyfill that would give
> the old addstream API on top of the proposed API and see where the
> disconnects (if any) are.

Here's one version:

// addStream() (sending side)
function addStreamPolyfilled(stream) {
     var tracks = stream.getTracks();
     tracks.forEach(function (track) {
         // include info in tag to rebuild stream
         pc.addTrack(track, tracks.length + "," + stream.id);
     });
}

// "addstream" event (receiver side)
pc.ontrack = function (evt) {
     var tags = evt.tag.split(",");
     var trackCount = parseInt(tags[0]);
     var streamId = tags[1];

     var stream = privateStreamHandles[streamId] ||
         new MediaStream(streamId);
     stream.addTrack(evt.track);

     // dispatch when we have rebuilt the entire stream
     if (stream.getTracks().length == trackCount)
         dispatchAddStreamEvent(stream);
};

Regarding polyfilling the addStream() API, the more advanced addTrack() 
(with MediaStreams) do create the MediaStream(s) for you, but when 
should you dispatch the addstream event?

/Adam


Received on Tuesday, 10 February 2015 09:54:42 UTC