[Libav-user] Why does av_seek_frame() not seek to a keyframe?

Michael Bradshaw mbradshaw at sorensonmedia.com
Thu Jul 19 01:05:33 CEST 2012

TL;DR: does av_seek_frame() not seek all streams to a keyframe before
the requested timestamp (in either dts or pts)? That is, can I expect
each stream to get a keyframe after seeking when I start decoding
*before* I reach the time I requested to seek to? (in pts or dts;
whatever the demuxer seeks by) Or is there a way (i.e. some flag) that
will make this happen when seeking?

I have a mpg container with an mpeg2video stream in it (there are also
2 ac3 audio streams, but I'm not focusing on these at the moment), and
I'm trying to seek in it. Essentially, my goal is to seek to a time T
(or as close to time T as possible without passing it, seeking to
keyframes, and then decode myself up to time T). But when I seek, the
first packet returned out of the demuxer is not a keyframe packet, and
I have to read several (~45ish) packets until I encounter a keyframe.

Here's some numbers, some more relevant than others:
formatContext.start_time == 87673749689
formatContext.duration == 2526544311

stream.start_time == 7890637472
stream.duration == 227358632
stream.time_base == 1/90000

targetTimestamp == 87712027067 (in AV_TIME_BASE) (I've already added
formatContext.start_time to it; without formatContext.start_time, the
target time stamp is 38277378 (~38.2 seconds)) (in stream.time_base,
this is the equivalent of 7894082436)

Seeking command:
av_seek_frame(formatContext, -1, targetTimestamp ,
AVSEEK_FLAG_BACKWARD); (returns as successful; and yes, I'm flushing
my codec's buffers before seeking)

The first packet retrieved after the seek belongs to the video stream,
and has the following info:
packet.pts == 7894091248
packet.dts == 7894082239
packet.flags == 0

The first fully decoded frame (after feeding in several frames to the
decoder) has the following info:
frame.pkt_pts == 7894226383
frame.pkt_dts == 7894226383
frame.best_effort_timestamp == 7894226383

As you can see, the first packet has flags == 0 (not a keyframe), and
the first decoded frame and the first packet have a difference of
135135 (in pts; ~1.5 seconds) (dts difference is 144144). I've probed
the file, and the closest keyframe packet that has a dts before the
requested timestamp has pts == 7894037194 and dts == 7894028185.

Is there some way to make sure that I seek to a keyframe that's
*before* my requested timestamp instead of after (for all streams)?



More information about the Libav-user mailing list