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