[Ffmpeg-devel] Timestamps on Decoding

Ronald S. Bultje rbultje
Sun Oct 23 17:58:44 CEST 2005


Heya,

On Sun, 2005-10-23 at 11:17 -0400, Paul Curtis wrote:
> In reviewing the e-mails on this subject, and searching the lists, I 
> haven't found a single example of how to access the PTS across different 
> formats and codec. Since the decoder timestamp is present in the formats 
> I've tested, it will have to do.

I've had this same issue with integrating in GStreamer; I've found that
a few hacks can definitely do the trick most of the time. I'm making a
fair amount of assumptions, but right now, most of them appear to hold.
First of all, the container will contain full single frames for you or
not (e.g. compare avi vs. mpeg), and those may or may not contain video
streams with backwards-time-references (B-frames, mostly; compare mjpeg
vs. divx5). Given that your ffmpeg-decoding-wrapper knows those things
from the container, it can do a good job at guessing the next expected
timestamp.

First, if we don't have backwards references and the container frames,
we simply take the timestamp given to us by the demuxer. Simplest case.

If the container frames for us, but the video stream contains b-frames
(ctx->max_b_frames > 0), then we can build a list of timestamps. For
each decoded frame, take the next timestamp from this list, so:

list ts;
ts.pull (input.timestamp);
for (;;) {
  frame = decode (input.data);
  if (frame) {
    frame.timestamp = ts.pop;
    // do something with frame
  } else {
    break;
  }
}

Also, if frame is an I-frame (no references anywhere), then we can
validly assume that the input contained this I-frame, and thus that we
should use the input timestamp for this (in case of a stream where part
of the bitdata was missing, we may otherwise use/guess the wrong
timestamp), so you empty the list then. Somewhat more complex, but still
not very hard. Theoretically, it may happen that the list is empty, in
which case you could try to guess the next timestamp as last_timestamp +
1 / framerate (where framerate is somewhere hidden in ctx as well,
called time_base or so). So you'll need quite some timestamp logic in
your processor function, but it's not all too hard.

Now, assume the case where the container does not parse for you. In that
case, you'll have to extract timestamps yourself. Fortunately, lavc has
the excellent AVParser class for that, with which we'll get presentation
timestamps over the next parsed frame, which we can use in a similar
fashion as given above.

I'm using the combination of all of those above, and it seems to do the
trick in all the cases that I'm aware of.

Ronald





More information about the ffmpeg-devel mailing list