<br><br><div class="gmail_quote">On Tue, Nov 18, 2008 at 1:06 PM, salsaman <span dir="ltr">&lt;<a href="mailto:salsaman@gmail.com">salsaman@gmail.com</a>&gt;</span> wrote:<br><blockquote class="gmail_quote" style="border-left: 1px solid rgb(204, 204, 204); margin: 0pt 0pt 0pt 0.8ex; padding-left: 1ex;">
<div><div></div><div class="Wj3C7c"><br><br><div class="gmail_quote">On Tue, Nov 18, 2008 at 12:47 PM, salsaman <span dir="ltr">&lt;<a href="mailto:salsaman@gmail.com" target="_blank">salsaman@gmail.com</a>&gt;</span> wrote:<br>
<blockquote class="gmail_quote" style="border-left: 1px solid rgb(204, 204, 204); margin: 0pt 0pt 0pt 0.8ex; padding-left: 1ex;">
<div><div></div><div><br><br><div class="gmail_quote">On Tue, Nov 18, 2008 at 7:28 AM, Ralph Giles <span dir="ltr">&lt;<a href="mailto:giles@xiph.org" target="_blank">giles@xiph.org</a>&gt;</span> wrote:<br>
<blockquote class="gmail_quote" style="border-left: 1px solid rgb(204, 204, 204); margin: 0pt 0pt 0pt 0.8ex; padding-left: 1ex;">
<div>On Tue, Nov 18, 2008 at 2:21 AM, salsaman &lt;<a href="mailto:salsaman@gmail.com" target="_blank">salsaman@gmail.com</a>&gt; wrote:<br>
<br>
&gt; Right, that is what I would expect. I think I will write an ogg file checker<br>
&gt; that checks all granulepos and keyframes to make sure the problem is not in<br>
&gt; my test files. Some of the files were created with older versions of the<br>
&gt; encoder. For example I have one file where I need to subtract 2 from all<br>
&gt; keyframe values in order for it to decode properly.<br>
<br>
</div>Hmm. Some of the alpha encoder releases recorded the frame index, not<br>
the frame count. Such stream declare their version to be 3.2.0 instead<br>
of 3.2.1 as in the current theora spec.<br>
<font color="#888888"><br>
&nbsp;-r<br>
</font></blockquote></div><br></div></div>Yes, I think the file <a href="http://upload.wikimedia.org/wikipedia/commons/0/0c/Experience_ubuntu.ogg" target="_blank">http://upload.wikimedia.org/wikipedia/commons/0/0c/Experience_ubuntu.ogg</a><br>

<br>is like that (0 based keyframes).<br>
<br>I am seeing other oddities in the file (I think) maybe somebody can confirm or deny this:<br><br>there is a granulepos 68516 in the file, which is (1070,1106) zero based. If I begin decoding from that page, I get (2 pages) [68516, 68518] 1107 (?), (2 pages) [68518, 70976] 1108 (?)&nbsp; (keyframe) (2 pages) 1109 (?).<br>


<br>However, the keyframe should be 1109 (zero based) according to later gpos.<br><br>I think what is messing me up is that there are 2 granulepos in a row with the same value. If I start from the second page with gpos of x, then I miss a page (because I should be starting on the first occurance of x).<br>


<br>Surely the second page should have granulepos of -1 ? Is this another known issue ?<br><br>Is this something that ogg_page_packetsout() could solve ?<div><div></div><div><br><br><br>Regards,<br>Gabriel.<br>
<a href="http://lives.sourceforge.net" target="_blank">http://lives.sourceforge.net</a><br>
<br><br><br>
</div></div></blockquote></div><br><br><br></div></div>Yes, in fact I can now answer that myself - checking for ogg_page_packets() &gt; 0 does indeed provide a workaround for this particular problem.<br><br>Now I need to know how to get the encoder version number from the stream. Anybody ?<div>
<div></div><div class="Wj3C7c"><br>
<br><br>Gabriel.<br><a href="http://lives.sourceforge.net" target="_blank">http://lives.sourceforge.net</a><br><br><br><br><br>
</div></div></blockquote></div><br><br><br>OK, everything is working now ! I decided not to bother getting the version number - I simply do a test when the file is opened to see what the first granulepos is after a frame is returned. From this I can calculate the first keyframe (either 0 or 1).<br>
<br><br>My decoder looks to be working nicely, with slight adjustments to the method I described.<br><br>Here is the procedure in full for future reference.<br><br>1) Parse stream headers to get data<br><br>2) Begin reading pages until we get at least one packet. Then check the granulepos to find the first keyframe number (0 or 1). Store this as keyframe_offset.<br>
<br>3) To get a target frame, first search through the file to find the largest granulepos&lt;=target, taking into account the keyframe_offset. From this we get the keyframe of the target.<br><br>4) Subtract 1 from the keyframe, then repeat step 3).<br>
<br>5) Begin reading from the frame discovered in step 4. Drop any packets which are output on the first page. Count down until we reach the keyframe, dropping packets until then.<br><br>6) Continue counting down until we reach the target frame, we are now decoding each frame/packet. At the target frame produce the YUV output.<br>
<br>7) If the next frame is &gt; last frame, and &lt;= keyframe_shift/2, continue decoding until we reach the new target; otherwise go back to step 3, unless we have the same keyframe (for example playing backwards) as previous, in which case we go to step 5.<br>
<br><br>As an additional optimisation, the plugin creates and linked list of index_entries on the fly, updating it each time a new granulepos with at least one packet is discovered. However, we only store one index_entry per keyframe, that is, the highest granulepos we have found for a particular keyframe.<br>
<br>The format of the index_entry is:<br><br>struct _index_entry {<br>&nbsp; index_entry *next;<br>&nbsp; index_entry *prev;<br>&nbsp; int64_t granulepos;<br>&nbsp; int64_t pagepos;<br>};<br><br>The index entry list is used to find the keyframe for a frame (if it is in our list), otherwise it provides lower and upper bounds for seeking in the file.<br>
<br>In the case of a 64 bit system, each index_entry adds 256 bytes per keyframe (roughly 4 bytes per frame), or on a 32 bit system, 192 bytes per keyframe (roughly 3 bytes per frame).<br><br><br>As noted previously, the plugin has a very simple API:<br>
- a function to get the plugin version string<br>- a function to return data for the URI (or NULL if the URI has no theora bitstream)<br>- a function to get a given frame from a given URI<br><br>Some of this code might be useful for liboggz or other uses. As ever, the sourcecode is available at:<br>
<br><a href="http://lives.cvs.sourceforge.net/viewvc/lives/lives-plugins/plugins/decoders/ogg_theora_decoder.c">http://lives.cvs.sourceforge.net/viewvc/lives/lives-plugins/plugins/decoders/ogg_theora_decoder.c</a><br><br>
<br>Regards,<br>Gabriel.<br><a href="http://lives.sourceforge.net">http://lives.sourceforge.net</a><br><br>