This is an archived snapshot of W3C's public bugzilla bug tracker, decommissioned in April 2019. Please see the home page for more details.

Bug 12175 - <video> the order of the loadedmetadata, loadeddata and suspend event is not defined
Summary: <video> the order of the loadedmetadata, loadeddata and suspend event is not ...
Status: RESOLVED WONTFIX
Alias: None
Product: HTML WG
Classification: Unclassified
Component: LC1 HTML5 spec (show other bugs)
Version: unspecified
Hardware: Other other
: P3 normal
Target Milestone: ---
Assignee: Ian 'Hixie' Hickson
QA Contact: HTML WG Bugzilla archive list
URL: http://www.whatwg.org/specs/web-apps/...
Whiteboard:
Keywords:
Depends on: 12267
Blocks:
  Show dependency treegraph
 
Reported: 2011-02-24 17:08 UTC by contributor
Modified: 2011-09-21 21:18 UTC (History)
7 users (show)

See Also:


Attachments

Description contributor 2011-02-24 17:08:19 UTC
Specification: http://www.whatwg.org/specs/web-apps/current-work/multipage/video.html
Section: http://www.whatwg.org/specs/web-apps/current-work/#fire-loadedmetadata

Comment:
the order of the loadedmetadata, loadeddata and suspend event is not defined

Posted from: 83.218.67.122
Comment 1 Philip Jägenstedt 2011-02-24 17:11:34 UTC
The resource fetch algorithm has a note after readyState reaches HAVE_CURRENT_DATA: "A user agent that is attempting to reduce network usage while still fetching the metadata for each media resource would also stop buffering at this point, causing the networkState attribute to switch to the NETWORK_IDLE value."

However, it doesn't define the order of the events normatively, although I take it that the intention is that suspend be fired after loadeddata.
Comment 2 Philip Jägenstedt 2011-04-28 09:07:12 UTC
This is what I've implemented (but not yet shipped) in Opera.

A state machine takes as its input 5 sub-states:

* current preload state: the preload state as per the spec (depends on content attribute only)

* current network state: the actual network state as per the spec

* current ready state: the actual ready state as per the spec

* pending ready state: a target (maximum) ready state that depends on preload

* the playback ended state: as per the spec

The pending ready state is updated whenever the coerced preload state is changed or when the playback ended state changes. If coerced preload is "none" then pending ready is HAVE_NOTHING. If coerced preload is "metadata" or if playback has ended, then the pending ready is HAVE_METADATA. Otherwise, the pending ready state is HAVE_ENOUGH_DATA.

As its output it has:

* coerced preload state: the preload state actually used internally (not exposed to scripts, that's always just a reflection of the content attribute, limited to known values)

* coerced network state: what scripts see in networkState

* coerced ready state: what scripts see in readyState

Whenever any of the input states are changed, the following rules are applied (in order):

* coerced preload = max(coerced preload, current preload), i.e. it can only increase, as going from e.g. auto to none makes no sense.

* if coerced ready state < pending ready state and coerced network == IDLE, then coerced network state is set to LOADING, regardless of the current network state. (this clamps networkState to be LOADING while readyState is expected to go through positive transitions, and ensures that the suspend event is only fired once the pending ready state has been reached).

* if current network state != coerced network state and it's not because of the clamping in the previous step, update coerced network state to current network state.

* if coerced ready state < min(current ready state, pending ready state), then increase coerced ready state. (this ensures that readyState is not allowed to increase past HAVE_CURRENT_DATA for preload=metadata, for example)

* if coerced ready state > current ready state, then decrease coerced ready state.

The rules are applied over and over until none of them apply (i.e. until there are no more transitions on the coerced states).
Comment 3 Philip Jägenstedt 2011-04-28 09:11:37 UTC
Take that as an FYI. The terminology might be a bit confusing in parts and I don't expect that exactly this would be spec'd, but it is what I concluded is necessary to make the state transition order reliable. It's a lie of course, but I don't think the truth (readyState and networkState) is worth much in this case.
Comment 4 Ian 'Hixie' Hickson 2011-06-03 00:36:01 UTC
The relative order of loadedmetadata and loadeddata seems well-defined, I don't understand the problem there.

The relative order of suspend vs those other two events is entirely up to the UA. I don't see how we _could_ define that while still allowing the UA to stall at any time.


EDITOR'S RESPONSE: This is an Editor's Response to your comment. If you are satisfied with this response, please change the state of this bug to CLOSED. If you have additional information and would like the editor to reconsider, please reopen this bug. If you would like to escalate the issue to the full HTML Working Group, please add the TrackerRequest keyword to this bug, and suggest title and text for the tracker issue; or you may create a tracker issue yourself, if you are able to do so. For more details, see this document:
   http://dev.w3.org/html5/decision-policy/decision-policy.html

Status: Rejected
Change Description: no spec change
Rationale: see above.
Comment 5 Ian 'Hixie' Hickson 2011-06-03 00:42:03 UTC
Clarification:

In http://lists.w3.org/Archives/Public/public-html/2011Feb/0437.html you say that "<video preload="metadata">" could result in any of these:

   slow network: loadstart, progress, loadedmetadata, loadeddata, suspend
   unlucky timing: loadstart, progress, loadedmetadata, suspend, loadeddata
   fast network: loadstart, progress, suspend, loadedmetadata, loadeddata

I understand how "slow network" could occur, but I don't understand how the other two could occur. How could you ever get more data after you've suspended, assuming you've not resumed? All these events use the same task source, and 'suspend' occurs after the network has been suspended, at which point there can't be any more data to change the readyState.

I guess one could argue that the CPU might be really slow and thus decoding the data could take substantially longer than it takes for the UA to give up and suspend the network even though it doesn't know it has gotten the metadata yet; is that what you mean?

(Please reopen the bug if you reply to the above, so that I see the reply. Thanks.)
Comment 6 Philip Jägenstedt 2011-06-09 13:07:02 UTC
(In reply to comment #5)
> Clarification:
> 
> In http://lists.w3.org/Archives/Public/public-html/2011Feb/0437.html you say
> that "<video preload="metadata">" could result in any of these:
> 
>    slow network: loadstart, progress, loadedmetadata, loadeddata, suspend
>    unlucky timing: loadstart, progress, loadedmetadata, suspend, loadeddata
>    fast network: loadstart, progress, suspend, loadedmetadata, loadeddata
> 
> I understand how "slow network" could occur, but I don't understand how the
> other two could occur. How could you ever get more data after you've suspended,
> assuming you've not resumed? All these events use the same task source, and
> 'suspend' occurs after the network has been suspended, at which point there
> can't be any more data to change the readyState.
> 
> I guess one could argue that the CPU might be really slow and thus decoding the
> data could take substantially longer than it takes for the UA to give up and
> suspend the network even though it doesn't know it has gotten the metadata yet;
> is that what you mean?

The issue is that loadstart, progress and suspend are related to networkState while loadedmetadata and loadeddata are related to readyState and these states independent to some extent. Data isn't examined/decoded synchronously as it comes in over the network. This is approximately what might happen in the "fast network example"

1. fire loadstart
1. start loading
2. some data arrives
3. sniff the type from the data and start setting up a decoding pipeline (in another thread)
4. the entire resource is loaded; fire suspend
5. pipeline is set up and we know the duration; fire loadedmetadata
6. the first frame has been decoded; fire loadeddata

The steps that are related to the network and the steps that are related to the decoding have no order imposed between them, so neither do the events.

There's also the issue of when to fire canplaythrough. You know that it can be fired already at step 4 when you fire suspend, but you have to delay it until after canplay for any kind of sanity.

If the intent of the spec is that networkState and readyState be coupled so that they don't vary independently like this, it needs to say so. I've had to add conditions on the state transitions to force a stable order, it does not happen automatically.
Comment 7 Ian 'Hixie' Hickson 2011-07-26 17:33:51 UTC
Ok, the situation you describe is the "CPU is slow" case I was referring to. The spec was written assuming the CPU would take no time to do those steps. I'll look into it. I'm not sure it's a real problem though.
Comment 8 Michael[tm] Smith 2011-08-04 05:36:18 UTC
mass-move component to LC1
Comment 9 Ian 'Hixie' Hickson 2011-09-21 18:23:52 UTC
I don't see how we can resolve this without making the API laggy and even more confusing to authors.
Comment 10 Ian 'Hixie' Hickson 2011-09-21 21:18:29 UTC
EDITOR'S RESPONSE: This is an Editor's Response to your comment. If you are satisfied with this response, please change the state of this bug to CLOSED. If you have additional information and would like the editor to reconsider, please reopen this bug. If you would like to escalate the issue to the full HTML Working Group, please add the TrackerRequest keyword to this bug, and suggest title and text for the tracker issue; or you may create a tracker issue yourself, if you are able to do so. For more details, see this document:
   http://dev.w3.org/html5/decision-policy/decision-policy.html

Status: Rejected
Change Description: no spec change
Rationale: I'm willing to consider concrete focused suggestions for making specific changes to this API to make it more predictable, but at a high level I think I've done pretty much as much as can be done.