Closed maikmerten closed 10 years ago
The expensive set() invocations seem to be part of emscripten's memcpy routine.
I tried sticking a console.log into _emscripten_memcpy_big ... some of the data's relatively small and consistent, but it copies larger chunks as well which seem to increase in size over time, up to chunks over 8 megabytes -- much larger than the framebuffer size -- and to higher and higher positions in memory.
This makes me suspect there's some kind of reallocing going on and we've got memory fragmentation inside the C program.
I actually see the same large memcpy's going on in Firefox and Chrome, but I think IE's TypedArray 'set' is just badly implemented and so is exposing the problem. :)
On the 'Jarry' video (which doesn't slow down) I never see memcpy's larger than 65536 and the addresses don't go up as fast.
Compiled with --js-opts 0 -g4
It appears the problem is in libogg, ogg_stream_pagein()
Ah, that's much more legible. :D
If I'm reading this right, the affected ogv files appear to have multiple theora packets/frames per ogg page -- we're only decoding one theora packet per page, so the extras queue up in the stream state structure.
I can hack around this by replacing:
if (ogg_stream_packetout(&theoraStreamState, &oggPacket) > 0 ){
with
while (ogg_stream_packetout(&theoraStreamState, &oggPacket) > 0 ){
in processDecoding() in ogv-libs.c however this appears to skip frames which is not ideal. May need to retool the loop so it only fetches another page once packets are exhausted.
(Note also I've had to make a tweak to demo.js to work around a temporary issue with the video files -- I've enabled lower-resolution transcodes but it'll be a while before they're done and the old demo code assumed everything was complete, so it either loads a super-low res file or fails altogether. Temporary tweak keeps the current behavior and only loads 480p or source .ogv. Will make the sizes selectable later.)
Yes, it appears that pages should only be fetched once the packets are exhausted. In
http://svn.xiph.org/trunk/theora/examples/player_example.c
this is coded as
if(!videobuf_ready || !audiobuf_ready){
/* no data yet for somebody. Grab another page */
buffer_data(infile,&oy);
while(ogg_sync_pageout(&oy,&og)>0){
queue_page(&og);
}
}
A conversation on freenodes's #theora confirmed the suspicions regarding the order of consuming packets and pages.
Excellent, that should be doable...
Fixed in 69c59a6. Thanks for the debugging help!
Depending on what video is played, playback in Internet Explorer 11 will progressively get slower. The profiler will show huge amounts of time spent in the "set" function (no location given).
Some affected files:
https://commons.wikimedia.org/wiki/File%3AEgg_grooming_behaviour_of_Reticulitermes_speratus_workers_in_a_nursery_cell_-_pone.0000813.s006.ogv
https://commons.wikimedia.org/wiki/File%3AExploring-Eye-Movements-in-Patients-with-Glaucoma-When-Viewing-a-Driving-Scene-pone.0009710.s001.ogv
https://commons.wikimedia.org/wiki/File%3ABorkumer_Kleinbahn_01.webmhd.webm
Some unaffected files:
https://commons.wikimedia.org/wiki/File%3AMunising_Falls.ogv
https://commons.wikimedia.org/wiki/File%3AJarry_-_M%C3%A9tro_de_Montr%C3%A9al_%28640%C3%97360%29.ogv