<br><br><div class="gmail_quote">On Thu, Nov 13, 2008 at 2:52 AM, Conrad Parker <span dir="ltr">&lt;<a href="mailto:conrad@metadecks.org">conrad@metadecks.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;">
2008/11/13 salsaman &lt;<a href="mailto:salsaman@gmail.com">salsaman@gmail.com</a>&gt;:<br>
<div class="Ih2E3d">&gt;<br>
&gt; On Wed, Nov 12, 2008 at 6:36 PM, Ralph Giles &lt;<a href="mailto:giles@xiph.org">giles@xiph.org</a>&gt; wrote:<br>
&gt;&gt;<br>
&gt;&gt; On Wed, Nov 12, 2008 at 1:13 PM, salsaman &lt;<a href="mailto:salsaman@gmail.com">salsaman@gmail.com</a>&gt; wrote:<br>
&gt;&gt;<br>
&gt;&gt; &gt; suppose I start decoding from a page with granulepos (kframe=x, frame<br>
&gt;&gt; &gt; =y)<br>
&gt;&gt; &gt; and I continue decoding in sequence until I reach the next page with a<br>
&gt;&gt; &gt; non-negative granulepos (kframe=a, frame=b). Is it possible that there<br>
&gt;&gt; &gt; could<br>
&gt;&gt; &gt; be another keyframe between x and a ? In other words, do &quot;hidden&quot;<br>
&gt;&gt; &gt; keyframes<br>
&gt;&gt; &gt; exist in the ogg stream, or is it safe to assume that every keyframe has<br>
&gt;&gt; &gt; at<br>
&gt;&gt; &gt; least one (non-negative) granulepos ?<br>
&gt;&gt;<br>
&gt;&gt; It&#39;s possible, though unlikely.<br>
<br>
</div>(hence it is not safe to assume that every keyframe is represented by<br>
a granulepos in the stream.)<br>
<div class="Ih2E3d"><br>
&gt;&gt; &gt; Let me give an example. Suppose I am seeking for frame 20. I find a<br>
&gt;&gt; &gt; granulepos of (18,22). Good, so I know that the keyframe is 18 + an<br>
&gt;&gt; &gt; offset<br>
&gt;&gt; &gt; of 2. So now I seek again to find the largest granulepos before 18. I<br>
&gt;&gt; &gt; find<br>
&gt;&gt; &gt; (10,12). Great.<br>
&gt;&gt; &gt; So I start decoding from (10,12) and I reach a keyframe. Can I assume<br>
&gt;&gt; &gt; this<br>
&gt;&gt; &gt; keyframe is 18, and then just decode two more frames ?<br>
&gt;&gt;<br>
&gt;&gt; In this case, you know the answer, because if you know by counting<br>
&gt;&gt; whether the keyframe you just found is frame 18, no? Or are you<br>
&gt;&gt; worried about having the backpropagate the (10,12) to earlier packets<br>
&gt;&gt; in that (10,12) page? You do have to do that, you can&#39;t assume there<br>
&gt;&gt; isn&#39;t a 9,9 in there too.<br>
&gt;<br>
&gt; No, I am not worried about that. But the first keyframe I find could be 14<br>
&gt; instead of 18, for example. Then I count two frames, I would end up at 16<br>
&gt; instead of 20.<br>
<br>
</div>right -- when you found (10,12), the only info that gives you is that<br>
a keyframe exists at frame 10, and interframes 11 and 12 depend on it.<br>
You previously knew that keyframe 18 exists and interframes 19-22<br>
depend on it. You don&#39;t yet know anything about the keyframes and<br>
interframes between 13-17.<br>
<div class="Ih2E3d"><br>
&gt; The only way I can see to be sure is to decode right up to the (18,22) page<br>
&gt; and make sure there are no more keyframes until then.<br>
&gt;<br>
&gt; This would occur for example, if there were continuation packets up to frame<br>
&gt; 13, then on the same page 14 (keyframe in this example) begins and the<br>
&gt; packet continues until we get to 18, then 18 continues until 18,22.<br>
<br>
</div>yes<br>
<div class="Ih2E3d"><br>
&gt; So what I really need to know, if a frame/packet completes on a page, and<br>
&gt; then another frame/packet begins on the same page, but continues, would the<br>
&gt; granulepos be for the completed frame, or would it be a continuation ?<br>
<br>
</div>for the completed frame; the granulepos (which is a field in the page<br>
header) refers to the last completed packet on the page.<br>
<div class="Ih2E3d"><br>
&gt; If<br>
&gt; it&#39;s the former then I think I am OK because in case of a keyframe before<br>
&gt; 18, there should always be a completed frame (e.g. 17 with a granulepos of<br>
&gt; 14,17) before 18 starts, right ?<br>
<br>
</div>No, eg. your next example is possible:<br>
<div class="Ih2E3d"><br>
&gt; The other example I can think of is if 17 is a keyframe, and it completes on<br>
&gt; the same page as 18, also a keyframe, completes. I guess this might be<br>
&gt; possible for very small, rapidly changing frames, right ? In this case I<br>
&gt; would only need to decode to the end of the page where a keyframe first<br>
&gt; appears, and make sure I got the last keyframe on that page.<br>
&gt;<br>
&gt; I hope this makes some sense.<br>
<br>
</div>If you just want to identify keyframe packets, you can skip the full<br>
decode and use theora_packet_is_keyframe(), which just probes the<br>
packet data for the keyframe flag.<br>
<br>
So in general, you can&#39;t make assumptions about keyframe existence<br>
based on granulepos.<br>
<br>
To find the keyframe for a frame you want to render, you should first<br>
try to find the page with the largest granulepos less than the target<br>
keyframe. Let&#39;s call that page G, and we&#39;ll call the last packet<br>
finishing on it P; ie. packet P has G&#39;s granulepos. Once you&#39;ve found<br>
page G, then scan forwards through all the packets following P<br>
(probing for keyframes, or just counting) until you&#39;ve found your<br>
target keyframe.<br>
<br>
Note that the next packet after P may begin on G, so you can&#39;t just skip G.<br>
<br>
So you need to start by pulling packets out of G, and once you see one<br>
with the same granulepos as G you can start your counter. However if P<br>
is continued on G (ie. it starts on an earlier page), and you just<br>
feed G into ogg_stream_pagein(), then ogg_stream_packetout() will not<br>
give you P, so you won&#39;t see any granulepos values and you won&#39;t be<br>
able to initialize your counter. You can detect this condition using<br>
libogg as follows (from ogg/src/framing.c):<br>
<br>
/* NOTE:<br>
If a page consists of a packet begun on a previous page, and a new<br>
packet begun (but not completed) on this page, the return will be:<br>
 &nbsp;ogg_page_packets(page) &nbsp; ==1,<br>
 &nbsp;ogg_page_continued(page) !=0<br>
*/<br>
<br>
In that case you can assume that the first packet coming out of<br>
ogg_stream_packetout() is P+1.<br>
<font color="#888888"><br>
Conrad.<br>
</font></blockquote></div><br><br><br><br><br>Actually I have now realised it`s not that complicated, as you say, just counting frames and not caring about keyframes at all is the way to go.<br><br>My search runs in 2 passes:<br>
<br>pass 1, find largest gpos &lt;= target - this gives us keyframe for target<br>(note that a granulepos with k&lt;= target, f&gt;=target is also acceptable)<br><br>pass 2, calculate gpos from kframe, search for largest gpos &lt; this<br>
<br>then starting from that page:<br>&nbsp;- ignore any packets on that page<br>&nbsp;- count frames starting from the following page<br>&nbsp;- when we reach a page which produces (target -1), we know that is where kframe starts, so store that page offset (this is useful for playing backwards...)<br>
- decode the next packet : this is our target frame<br><br><br>Does that look correct ?<br><br>Cheers,<br>Gabriel.<br><br>