<br><br><div class="gmail_quote">On Thu, Nov 13, 2008 at 2:52 AM, Conrad Parker <span dir="ltr"><<a href="mailto:conrad@metadecks.org">conrad@metadecks.org</a>></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 <<a href="mailto:salsaman@gmail.com">salsaman@gmail.com</a>>:<br>
<div class="Ih2E3d">><br>
> On Wed, Nov 12, 2008 at 6:36 PM, Ralph Giles <<a href="mailto:giles@xiph.org">giles@xiph.org</a>> wrote:<br>
>><br>
>> On Wed, Nov 12, 2008 at 1:13 PM, salsaman <<a href="mailto:salsaman@gmail.com">salsaman@gmail.com</a>> wrote:<br>
>><br>
>> > suppose I start decoding from a page with granulepos (kframe=x, frame<br>
>> > =y)<br>
>> > and I continue decoding in sequence until I reach the next page with a<br>
>> > non-negative granulepos (kframe=a, frame=b). Is it possible that there<br>
>> > could<br>
>> > be another keyframe between x and a ? In other words, do "hidden"<br>
>> > keyframes<br>
>> > exist in the ogg stream, or is it safe to assume that every keyframe has<br>
>> > at<br>
>> > least one (non-negative) granulepos ?<br>
>><br>
>> It'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>
>> > Let me give an example. Suppose I am seeking for frame 20. I find a<br>
>> > granulepos of (18,22). Good, so I know that the keyframe is 18 + an<br>
>> > offset<br>
>> > of 2. So now I seek again to find the largest granulepos before 18. I<br>
>> > find<br>
>> > (10,12). Great.<br>
>> > So I start decoding from (10,12) and I reach a keyframe. Can I assume<br>
>> > this<br>
>> > keyframe is 18, and then just decode two more frames ?<br>
>><br>
>> In this case, you know the answer, because if you know by counting<br>
>> whether the keyframe you just found is frame 18, no? Or are you<br>
>> worried about having the backpropagate the (10,12) to earlier packets<br>
>> in that (10,12) page? You do have to do that, you can't assume there<br>
>> isn't a 9,9 in there too.<br>
><br>
> No, I am not worried about that. But the first keyframe I find could be 14<br>
> instead of 18, for example. Then I count two frames, I would end up at 16<br>
> 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't yet know anything about the keyframes and<br>
interframes between 13-17.<br>
<div class="Ih2E3d"><br>
> The only way I can see to be sure is to decode right up to the (18,22) page<br>
> and make sure there are no more keyframes until then.<br>
><br>
> This would occur for example, if there were continuation packets up to frame<br>
> 13, then on the same page 14 (keyframe in this example) begins and the<br>
> packet continues until we get to 18, then 18 continues until 18,22.<br>
<br>
</div>yes<br>
<div class="Ih2E3d"><br>
> So what I really need to know, if a frame/packet completes on a page, and<br>
> then another frame/packet begins on the same page, but continues, would the<br>
> 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>
> If<br>
> it's the former then I think I am OK because in case of a keyframe before<br>
> 18, there should always be a completed frame (e.g. 17 with a granulepos of<br>
> 14,17) before 18 starts, right ?<br>
<br>
</div>No, eg. your next example is possible:<br>
<div class="Ih2E3d"><br>
> The other example I can think of is if 17 is a keyframe, and it completes on<br>
> the same page as 18, also a keyframe, completes. I guess this might be<br>
> possible for very small, rapidly changing frames, right ? In this case I<br>
> would only need to decode to the end of the page where a keyframe first<br>
> appears, and make sure I got the last keyframe on that page.<br>
><br>
> 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'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's call that page G, and we'll call the last packet<br>
finishing on it P; ie. packet P has G's granulepos. Once you've found<br>
page G, then scan forwards through all the packets following P<br>
(probing for keyframes, or just counting) until you've found your<br>
target keyframe.<br>
<br>
Note that the next packet after P may begin on G, so you can'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't see any granulepos values and you won'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>
ogg_page_packets(page) ==1,<br>
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 <= target - this gives us keyframe for target<br>(note that a granulepos with k<= target, f>=target is also acceptable)<br><br>pass 2, calculate gpos from kframe, search for largest gpos < this<br>
<br>then starting from that page:<br> - ignore any packets on that page<br> - count frames starting from the following page<br> - 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>