#116 ✓ checked-in
gerv

Rework timeupdate code to be more efficient

Reported by gerv | October 19th, 2010 @ 11:40 AM | in 0.2 release

The key performance-related bit of code in popcorn.js is that which runs when you get a video update event - popcorn.update(). At the moment, it does two loops through the entire list of commands, and multiple comparisons for each. This is not going to work well for a high rate of update or a large number of commands.

The best data structure I can think of is as follows: you have a set of command objects, read from the XML, and two arrays 'pointing' at them - one array is ordered by in time ("commands_by_in"), and the other by out time ("commands_by_out"). You also have, preserved between functions, the value of the video timer last time you were called ("previous_time"), and a pointer into each array - a variable holding an index ("out_index" and "in_index"). The invariant is that, as you leave the function, the pointers point at the first array element in their array whose sort-key timestamp is strictly greater than the current video timestamp.

The aim here is to only have to deal with objects whose state needs to be changed.

The code for the update function then looks something like this:

popcorn.update = function(vid) {
var current_time = vid.currentTime; while (commands_by_out[out_index].out < current_time) {

commands_by_out[out_index].onOut();
out_index++;

}

while (commands_by_in[in_index].in < current_time) {

if (commamds_by_in[in_index].out > current_time) {
  commands_by_in[in_index].onIn();
}
in_index++;

} }

In many cases, when the increment in time is small, both these while loops will execute 0 times, and that'll be it. Very efficient.

It's a little more complicated than this, because you have to check if current_time is smaller or larger than previous_time, and if it's smaller (i.e. the user has seeked backwards), you need to go backwards through the arrays rather than forwards. But that's just another test, and a copy of the same code with > instead of < and -- instead of ++. You could write functions called e.g. cmp() and move() to encapsulate this and avoid code duplication. And you need to think about falling off the ends.

If you want to preload stuff, just have another pointer into "commands_by_in", but have it compare against current_time + preload_time rather than just current_time, and execute the preload() function.

Comments and changes to this ticket

Please Sign in or create a free account to add a new ticket.

With your very own profile, you can contribute to projects, track your activity, watch tickets, receive and update tickets through your email and much more.

New-ticket Create new ticket

Create your profile

Help contribute to this project by taking a few moments to create your personal profile. Create your profile »

Popcorn.js is an HTML5 video framework that lets you bring elements of the web into your videos.

Popcorn.js is a project of Web Made Movies, Mozilla's Open Video Lab.

Shared Ticket Bins

People watching this ticket

Referenced by

Pages