Monday 21 September 2009
v1.mozLoadFrom(v2) behaves much like the
load method of
HTMLMediaElement. It stops playing the currently loaded resource and loads a new resource. However, it does not run the HTML5 media selection algorithm; instead it just takes
currentSrc and loads that. What makes
mozLoadFrom useful is that it tries to avoid re-downloading the resource data. It grabs all the cached and buffered data already associated with
v2 and makes it available to
v1 as well. In fact these elements carry on sharing data, so that any future data downloaded by
v2 is available to the other. Typically this means that only one of the elements will actually be downloading data and the other one won't need to download anything at all. (Although if the entire resource doesn't fit in the media cache, you can end up in situations where the elements are playing different points in the stream and both reading from different offsets.)
mozLoadFrom is useful if you need to manipulate multiple views of the same video/audio stream. For example you might be playing a video and at the same time you want a script to seek forwards or backwards and gather periodic snapshots into a series of <canvas>es. Or you might have a set of videos playing in the page at a smallish size and want to display a selected one in the front covering most of the window, without having to mess with the original thumbnail video. The main reason I implemented
mozLoadFrom is to make it easier to display full-screen video in Firefox or extensions.
The tricky part of the implementation is that the media cache was originally designed so that a block in the cache could only belong to one decoder at a time. With
mozLoadFrom a block can be owned by multiple decoders at a time. In the original design, a block is always in exactly one of four states: free, readahead (it's ahead of the current playback point), played (it's behind the current playback point), and metadata. Now a block can be a readahead block for one decoder and a played block for another decoder.
I was quite worried it would be hard to extend the design this way, but in fact I was able to do it in about a day of intense hacking. This probably reflects well on the original design of the media cache. In particular, basing eviction decisions on the "predicted time of next use" was easy to extend; when a block has multiple owners, its predicted time of next use is the earliest time that any of its owners predicts for it.
Update Ian Hickson points out that new API is not needed here since HTML5 allows concurrent loads of the same absolute URI to share data regardless of HTTP caching instructions. So instead of
mozLoadFrom we could just use
v1.src = v2.currentSrc to get the same effect. I should do that...