RE: Track cloning behavior of MediaStream() constructor and addTrack()

In generaly, I like this idea.

>The proposed sourceId would 
>make the pairing easier, as long as we keep the restriction that only 
>one track can represent a source in a MediaStream.

I do disagree with the idea of a 1:1 track to sourceId, as this seems 
unnatural, but of course isn't required given your proposal for an 
explicit clone.

-travis

-----Original Message-----
From: Adam Bergkvist [mailto:adam.bergkvist@ericsson.com] 
Sent: Monday, March 18, 2013 7:47 AM
To: public-media-capture@w3.org
Subject: Track cloning behavior of MediaStream() constructor and addTrack()

Hi

As the spec is currently written, the MediaStream() constructor and the 
addTrack() method create a new MediaStreamTrack instance to represent a 
given track argument. Some of the changes we done lately, like removed 
the ordered track list attributes, have made this API harder to work with.

Independent track instances (or clones) are useful to control the output 
to different consumers. In the case below, the self-view will show video 
but the video to the other peer is disabled.

var peerStream = new MediaStream(selfViewStream); // clone the stream
pc.addStream(peerStream);
peerStream.getVideoTracks()[0].enabled = false;
selfViewStream.getVideoTracks()[0].enabled = true;

However, the cloning behavior of MediaStream() and addTrack() causes 
some unintuitive API behavior. For example, if we do:

stream.addTrack(track);

Then the following calls won't behave as one might expect.

stream.getTrackbyId(track.id); // is null
stream.removeTrack(track); // is a no-op and won't remove track from
                            // stream

The instance track is not a part of stream and the new track instance 
has a different id. This may also cause confustion if one tries to use 
the track reference passed to addTrack() to influence the output of 
stream (example below).

stream.addTrack(track); // as above
pc.addStream(stream);
track.enabled = false; // won't disable the output of any track in
                        // stream

If we take the proposed approach for sync getUserMedia() as an example.

var video1 = new VideoStreamTrack(constraints1);
var video2 = new VideoStreamTrack(constraints2);
var stream = new MediaStream([video1, video2]);

The instances video1 and video2 are pretty much useless since new track 
instances are created when the stream is constructed. It's also not 
obvious which video tracks in stream that correspond to video1 and 
video2, since the track order is undefined. The proposed sourceId would 
make the pairing easier, as long as we keep the restriction that only 
one track can represent a source in a MediaStream.

I think the API would be more intuitive if MediaStream() and addTrack() 
"adopted" the track arguments instead of cloned them. Cloning would then 
be an explicit operation.

To still support cloning, we could either support cloning of both tracks 
and streams or simply only tracks.

var clonedStream = stream.clone();

A stream clone can be created by adding cloned tracks to a new stream.

var tracks = stream.getAudioTracks().concat(stream.getVideoTracks());
var trackClones = tracks.map(function (track) {
     return track.clone();
});
var streamClone = new MediaStream(trackClones);

What do people think about this?

BR
Adam

Received on Monday, 18 March 2013 15:52:47 UTC