[foms] What data is needed for adaptive stream switching?
Chris Pearce
chris at pearce.org.nz
Mon Nov 22 14:30:46 PST 2010
What data does the browser need to expose to javascript to enable
clients to do adaptive stream switching?
We need to detect the following situations:
(1) The network is not fast enough to play the current stream at real time.
(2) The network is fast enough to play the current stream, but is not
fast enough to play a higher quality stream.
(3) The network is fast enough to play a higher quality stream at real time.
(4) The machine is not powerful enough to play the current stream smoothly.
(5) The machine is powerful enough to play the current stream smoothly,
but not powerful enough to play a higher quality stream smoothly.
(6) The machine is powerful enough to play a higher quality stream smoothly.
(7) Any others?
Browsers can expose counters for frames demuxed, decoded and painted to
enable detection of cases 4-6.
Or we could also expose an attribute which simply reports whether the
browser is dropping frames, and so you can use this to determine whether
you need to switch down to a lower quality stream in order to get smooth
playback. Or maybe have it return the number of dropped frames in the
last second?
Given the painting architecture in Firefox, it's very inconvenient to
separately count the number of frames which were not painted due to the
video being hidden/off screen (this was suggested by Andy Berkheimer).
If you wanted to detect this, you could detect when the "painted frames"
counter completely stops incrementing. Even when we're CPU starved, we
should be able to paint the occasional frame...
How do we detect cases 1-3?
In HTML5 we already have the @buffered attribute, and the @currentTime
attribute. With this you can see the current playback position, and you
can see how many seconds you could play for if the network connection
stopped dead. This isn't a bitrate approximation; in Firefox at least
@buffered is accurate to frame boundaries, I'm not sure about other
browsers' accuracy. During playback you can check periodically, and if
currentTime - bufferedEndTime is decreasing, you know that you're
consuming more video than you're receiving, and you'll run out of data
eventually unless something changes.
I imagine @buffered would be particularly useful in this case for VBR
content.
That would look something like this:
<script>
// Set an interval timer to call this function a few times a second.
function checkRate(video) {
var time = video.currentTime;
var end = findBufferedEnd(video.buffered, time);
var playable = end - time; // seconds of playable video after current
playback position
if (!video.hasAttribute("_playableSeconds") || video.paused) {
video._playableSeconds = playable;
return;
}
// The change in amount of buffered data
var deltaPlayable = playable - video._playableSeconds;
// If deltaPlayable is > 0 we're downloading at a rate faster than
we're playing.
if (isTrendingDownwards(deltaPlayable, video)) {
// We're not downloading playable video at a rate greater than
we're consuming it.
decreaseQuality(video);
} else if (isTrendingUpwards(deltaPlayable, video)) {
increaseQuality(video);
}
video._playableSeconds = playable;
}
function findBufferedEnd(b, t) {
for (var i=0; i<b.length; i++) {
if (b.start(i) <= t && t <= b.end(i))
return b.end(i);
}
return t;
}
function isTrendingDownwards(deltaPlayable, video) {
// Return true if average deltaPlayable is decreasing over the last N
seconds?
}
function isTrendingUpwards(deltaPlayable, video) {
// Return true if average deltaPlayable is increasing over the last N
seconds?
}
</script>
How does that sound? Do you guys think that approach will be sufficient,
or do you need more data exposed by the browser? If so what data?
We used to have download position and playback position counters on the
"progress" events, but these were removed recently (we also used to have
bufferedBytes which Phillip suggested would be a better interface to
reinstate if wanted this functionality). Are these useful? On VBR
content, _can_ they be useful? In Firefox we try to use these to
estimate whether we can play through to the end of media without needing
to stop to buffer (to determine whether we can fire the canplaythrough
event, and whether we should switch to readyState HAVE_ENOUGH_DATA), but
for VBR content this can be _very_ inaccurate.
Do we need to expose any new data in the browser to do adaptive stream
switching?
Chris P.
More information about the foms
mailing list