Re: <video> readyState oddities

On Fri, 25 Feb 2011 16:38:36 +0100, Ian Hickson <ian@hixie.ch> wrote:

> On Fri, 25 Feb 2011, Philip Jägenstedt wrote:
>>
>> "When a media element is potentially playing and its Document is a fully
>> active Document, its current playback position must increase
>> monotonically at playbackRate units of media time per unit time of wall
>> clock time."
>>
>> During normal playback, whether or not currentTime increases depends on
>> "potentially playing":
>>
>> "A media element is said to be potentially playing when its paused
>> attribute is false, the readyState attribute is either HAVE_FUTURE_DATA
>> or HAVE_ENOUGH_DATA, the element has not ended playback, playback has
>> not stopped due to errors, and the element has not paused for user
>> interaction."
>>
>> In other words, when readyState is HAVE_METADATA or HAVE_CURRENT_DATA,
>> currentTime doesn't change, but I can't see that it's clearly defined if
>> readyState should fall back to HAVE_METADATA or HAVE_CURRENT_DATA when
>> playback has ended or you just ran out of buffer.
>
> While it has data, it'll be in HAVE_CURRENT_DATA and will be increasing.
> It'll get to the last frame where it has data, where it will still be in
> HAVE_CURRENT_DATA, and it will thus increase once more, at which point it
> won't have data and it'll therefore switch to HAVE_METADATA and the
> position will stop increasing.
>
> Again, this all seems pretty unambiguous.

Because of the definition of "potentially playing", currentTime cannot  
increase once readyState has falled back to HAVE_CURRENT_DATA, so I assume  
you meant HAVE_FUTURE_DATA in the above?

currentTime could stop increasing by changing readyState to either  
HAVE_CURRENT_DATA or HAVE_METADATA, so things are less than crystal clear.

>> My reading would be that it depends on if the end of buffered  
>> TimeRanges are
>> inclusive or not. Example: if buffered.end(0) == 1 and currentTime ==  
>> 1, is
>> "Data for the immediate current playback position is available"? Is  
>> readyState
>> HAVE_METADATA or HAVE_CURRENT_DATA?
>
> Yeah, that's a good question (but orthogonal to the issue at hand, IMHO).
> I've filed a bug to make sure I specify explicitly that TimeRanges are
> inclusive (which seems like the only behaviour that would be intuitive
> -- you wouldn't want .end(0) to be greater than .currentTime when the
> video has .ended, right?).
>
>    http://www.w3.org/Bugs/Public/show_bug.cgi?id=12186

Good, I agree that inclusive makes sense. It does influence the issue at  
hand, as such:

If buffered is [0,10] then one would reasonably expect currentTime to  
increase monotonically until it is exactly 10. Where else would it stop,  
10.0000001? If buffered end is inclusive, then by definition the time 10  
is buffered and thus when currentTime==10, readyState must be  
HAVE_CURRENT_DATA. Only if buffered end is exclusive does it make sense to  
let readyState be HAVE_METADATA.

>> > > I think it would make sense to behave the same way as at the end of
>> > > the resource, and that HAVE_CURRENT_DATA actually makes sense.
>> >
>> > Not sure what you mean.
>>
>> Running out of data because the network is slow or because the end of
>> the resource has been reached is really very similar on the decoding
>> side of things, so I think the state should be the same for consistency,
>> be that HAVE_METADATA or HAVE_CURRENT_DATA.
>
> It seems extremely different in one key respect: when you have ended, the
> frame you _want_ to be rendering is the last one, but when you have run
> out of data, the frame you _want_ to be rendering is the next one.

Surely the difference between HAVE_METADATA and HAVE_CURRENT_DATA should  
correspond to whether or not currentTime is in the buffered ranges, not be  
special-cased for currentTime==duration?

Think of a video resource sent over HTTP without Content-Length or support  
for range requests, such that one doesn't know when it will end until it  
does. Reaching the end and running out of data because of a slow network  
would be indistinguishable until after the fact. The last byte would be  
received before one knows that the server has closed the connection, after  
all. It would be very strange if readyState had to change when the server  
says "EOS", even though nothing has changed from a decoding perspective.  
It's *possible* to implement, but it seems strange and inconsistent.

Suggestion:

* buffered ranges are inclusive
* whenever currentTime is not in one of the ranges, readyState <=  
HAVE_METADATA
* when currentTime is in one of the ranges, readyState >= HAVE_CURRENT_DATA
* no special casing of EOS

This would mean that readyState would never go back to HAVE_METADATA  
during normal playback, only when first loading the resource and when  
seeking to an unbuffered position. At least to me, this seems consistent  
and logical.

-- 
Philip Jägenstedt
Core Developer
Opera Software

Received on Friday, 25 February 2011 21:45:56 UTC