[web-animations] Making players stop

Dear all,

Following is a summary of changes I intend to make to the operation of 
players in Web Animations.

Background reading:
* What are players?: 
http://brian.sol1.net/svg/2013/07/25/players-wanted-the-pause-and-seek-game/
* Initial proposal to make players stop: 
http://lists.w3.org/Archives/Public/public-fx/2013JulSep/0009.html, point 6
* Follow-up discussion: 
http://lists.w3.org/Archives/Public/public-fx/2013JulSep/0043.html, point 2

Objective: Make players "stop" when they reach the end of their source 
content.

Motivation:
* Analogous to how video "players" etc. work
* Allows defining onend events for players or making them then-able
* Allows defining a reverse() method which, if called twice, is a no-op 
(maybe)
* Closer to how HTML media elements work

Current model:
* Players are content-agnostic. It's like a stubborn record player where 
the needle just keeps moving out indefinitely even past the end of the 
record.

Proposed alternatives:

Option A: Clamp the current time
================================

* We calculate the current time as usual but before reporting it back by 
the API, we clamp it to the range:
   [0, content end time]
   (I'm calling this the "content range" from here on.)

* In effect, you end up with an "actual current time" and a "reported 
current time".

+ The primary benefit of this model is that it's not stative. You can 
make all the changes you like to the source content and regardless of 
the order or timing of the operations the result is going to be the same.

   For example, if you play 5s of source content through to the end, 
wait 1s, then add some more content, it picks up playback from the 6s 
mark--the same as if you made that change earlier.

- The primary drawback is the distinction between actual current time vs 
reported current time. Either we confuse the API by exposing both, or we 
hide the actual current time which could lead to surprising results.

- It also differs from what happens with video players etc.

Option B: The DVD player - times outside the content range are
           disallowed
===============================================================

* With a DVD player, you can't possibly seek to a point outside the 
source content so in this model we do the same. Attempts to set times 
outside this range simply get silently adjusted to fall within the range.

For example, if you play 5s of source content through to the end, then 
adjust the source content so it is *shorter*, say 3s long, the current 
time is updated to 3s. Note that unlike Option A, this is the *actual* 
current time. If we then extend the source content to say, 7s, playback 
starts from the 3s mark.

+ The primary advantage of this is it easy to reason about to the extent 
that it mimicks a DVD player. However, you can't change the length of 
the content of a DVD while it is in play--and when you replace the DVD 
in a DVD player it either resets its position or bases it on a cached 
position for the new DVD; so it's actually not a great parallel.

- On the other hand there are some disadvantages including:

* You can't set the current time to 5s *then* add source content and 
start playing. (That *may* be problematic when we introduce media 
reference items, I'm not sure.)

* You can't swap the source content of two players since here's what 
will happen:

  // Swap
  var tmp = playerA.source;
  playerA.source = playerB.source;
  playerB.source = tmp;

  // playerA maintains its current time (although possibly truncated if 
playerB's source is shorter)
  // playerB's current time is reset to 0 since after the second line it 
has no source content

Option C: The record player
===========================

* This model is similar to option B except you *can* set the position to 
somewhere outside the content range but it won't move when outside that 
range. It's like the needle on a record player--you can position it off 
the record but it won't move if you do that.

In effect, we add another kind of auto-pausing that is orthogonal to the 
existing pause state of a player. We enter this "auto-paused" state if:
* we get a sample that would give us a current time outside the content 
range and we're not already in the auto-paused state
* we are seeked to a current time outside the content range

We exit the "auto-paused" state if:
* sampling with the current timeline time would give us a current time 
inside the content range

So if you were to play 5s of content to end and *then* update the source 
content to 3s the current time would continue to be 5s and would not 
change. Then if you were to update the source content to 7s, it would 
begin playing from 5s.

+ This means you can:
* Set the current time to 5s *then* add source content and it picks up 
playing from the 5s mark
* Swap the content of two players and have them keep their positions

- The primary disadvantage is you're making the behaviour of the player 
more dependant on current state and hence the timing of operations matters.

For example, if you start a player whose source content is an empty 
group, but don't add anything to the group for a while--perhaps you're 
waiting on some async resource to load--and *then* you add it, you will 
be out of sync with any other players started at the same time (since 
you will have accumulated time lag while waiting for content to be 
added). On the up-side, you *will* start playback from the beginning of 
the content.

Remedies for this particular situation:
a) Add a catchUp() method to reset the timeLag of a player.
b) Don't create the player until you're ready to play, then give it the 
appropriate start time.
c) Create the player with source content of infinite length initially 
and then add the content in when ready.

But this is just one example. In general you will observe differences in 
behaviour between making a change to source content *before* the player 
reaches the end (and hence no time lag is accumulated) and making the 
same change *after* the player has reached the end. What's more the 
difference comes down to timing and might only manifest when you start 
running the content on a different kind of device.


So they are the three models. We've previously said we'll do option C 
but I don't know if we quite appreciated how dependent it is on timing. 
I still lean towards C, but what do you think? If nothing else, I wanted 
to document some of the thinking behind this design.

It's worthwhile considering how media reference items would behave in 
these cases too.

I'll follow up this post with a rough sketch of how I think the API 
might look for option C.

Thanks,

Brian

Received on Wednesday, 16 October 2013 05:29:23 UTC