Re: Thoughts on the TVTuner class in the source-centric API

Hi Steve,

Le 05/12/2016 à 16:04, Steven Morris a écrit :
[...]
> Another alternative is to fully take the approach described by
> getUserMedia(), which does support most of what we want to do, but
> requires using the MediaStreamTrack interface for most of the
> operations.  We would either have to extend MediaDeviceInfo to introduce
> a getChannels() method and other TV-specific APIs and events, or define
> our exisitng APIs in a way that is compatible with this approach.


Regarding alignment with getUserMedia, I think the TV Control Working 
Group should get in touch with the Media Capture task force of the 
Device and Sensors WG and WebRTC WG for feedback. In some ways, this 
seems to be the "intended design". At the same time, some of it feels 
odd. Below is a draft message that I propose to send to that task force.

Any comment on this message and questions it raises?


=====
The TV Control Working Group is re-modeling the TV Control API 
specification around sources. That new model is well aligned with the 
model used in Media Capture and Streams. In fact, it would seem possible 
to re-use Media Capture and Streams interfaces as-is. However, some 
details do not seem entirely right when we do that, and we would like to 
get your feedback on the following questions.


Context
-----
The TV Control API specification defines an API for sourcing audio and 
video media, such as TV and radio from broadcast, IPTV, or other 
sources, and allows presentation of the media using the <video> and 
<audio> HTML elements. The API typically produces MediaStreams, with 
methods to switch from one TV/radio channel to the other, and various 
classes to retrieve associated channel and program metadata.

The current API is designed around the notion of tuners but the group 
agreed to a re-design centered on the notion of sources. To keep things 
simple, a TV source is something attached to a broadcast signal (which 
could come through a cable, terrestrial antennas, satellites, etc.) that 
can be tuned to a specific channel to produce a MediaStream, composed of 
a set of MediaStreamTracks for that channel. User may switch the source 
to another channel at any time.

Looking at it from a getUserMedia perspective, it seems possible to 
consider TV sources as input devices, and channels as a constraint that 
could be applied to the main video track. This would lead to the 
following code:

var source = null;

navigator.mediaDevices.enumerateDevices()
    .then(function (devicesInfo) {
      source = devicesInfo.find(function (deviceInfo) {
        // Or use "getCapabilities" to detect support for the "tvchannel"
        // constraint if kind cannot be extended?
        return deviceInfo.kind === 'tvsource';
      });
      return source.getChannels();
    })
    .then(function (channels) {})
      var channel = channels[0];
      secondChannel = channels[1];
      navigator.mediaDevices.getUserMedia({
        video: {
          deviceId: source.deviceId,
          tvchannel: channel
        }
      })
    })
    .then(function (stream) {
      tvStream = stream;

      // Render the stream
      document.getElementById('video').srcObject = tvStream;

      // Switch to another channel
      return tvStream.getVideoTracks()[0].applyConstraints({ tvchannel: 
secondChannel });
    })
    .then(function () {
      // Stop stream
      tvStream.getVideoTracks()[0].stop();
    });


This triggers a few questions though.

Questions
-----

1. Attaching to "enumerateDevices"?
--
We need some way to enumerate the TV/radio sources but it feels a bit 
strange to mix TV/radio sources with camera/microphone sources. Use 
cases that want to get media from a camera are roughly disjoint from use 
cases that want to tune to a particular TV channel. Shouldn't APIs 
rather be separated?
If not, what would be the proper way to distinguish TV sources? Should 
we introduce a new "tvsource" kind of source for instance?


2. Channel constraint at the track level?
--
Similarly, it does not seem natural to apply the constraint to change 
the channel at the track level. The channel "constraint" rather seems to 
apply at the MediaStream level, as it is going to affect all tracks. Are 
we trying to push the constraint model too far?

The same comment applies to the "stop" method, which again is going to 
affect all tracks of the MediaStream in our case.


3. TV specific semantics?
--
While it works, is also seems counter-intuitive to "apply a constraint" 
to switch from one channel to another. Developers would probably rather 
expect something like a "tuneToChannel" method instead.


4. Extending or wrapping MediaStream?
--
The TV Control API extends MediaStream to add buffering. This seems to 
preserve the spirit of MediaStreams and there has already been exchanges 
about that in the past.

We may need to introduce other attributes at that level, such as an 
"isRecordable" property to tell whether the channel may be recorded. 
This is also where the "stop" method mentioned above would fit. Such 
extensions seem of different nature. We're wondering whether it could be 
preferable to introduce an extra layer that wraps the MediaStream and 
exposes TV specific properties.


Alternative proposal
-----
All in all, an alternative proposal that separates the APIs, moves 
operations back to the source level, and creates a wrapping tuner class 
around MediaStream could lead to the following code:

var source = null;
var secondChannel = null;
var tvTuner = null;

navigator.tv.getSources()
    .then(function (sources) {
      source = sources[0];
      return source.getChannels();
    })
    .then(function (channels) {
      var channel = channels[0];
      secondChannel = channels[1];
      return source.tuneToChannel(channel);
    })
    .then(function (tuner)) {
      tvTuner = tuner;

      // Render the stream
      document.getElementById('video').srcObject = tvTuner.stream;

      // Switch the source to another channel, re-using the same tuner
      return source.tuneToChannel(secondChannel, tuner);
    })
    .then(function () {
      // Stop stream and release resource
      tvTuner.stop();
    });

Note we would be happy to schedule a call as needed to clarify our 
questions.

Thanks,
Francois.

Received on Friday, 9 December 2016 17:24:25 UTC