I've run into a few issues with seeking in my usage of FFmpeg and, after
several incarnations, I've found that this code works well...
int defaultStreamIndex = av_find_default_stream_index(m_pFormatContext);
int seekStreamIndex = (m_videoStreamIndex != -1)? m_videoStreamIndex :
defaultStreamIndex;
__int64 seekTime = av_rescale_q(seekTimeDS, ds_time_base,
m_pFormatContext->streams[seekStreamIndex]->time_base);
__int64 seekStreamDuration =
m_pFormatContext->streams[seekStreamIndex]->duration;
int flags = AVSEEK_FLAG_BACKWARD;
if (seekTime > 0 && seekTime < seekStreamDuration)
flags |= AVSEEK_FLAG_ANY; // H.264 I frames don't always register
as "key frames" in FFmpeg
int ret = av_seek_frame(m_pFormatContext, seekStreamIndex, seekTime,
flags);
if (ret < 0)
ret = av_seek_frame(m_pFormatContext, seekStreamIndex, seekTime,
AVSEEK_FLAG_ANY);
My program uses DirectShow timecodes internally which is why I rescale the
incoming timecode. (i.e. seekTimeDS) m_videoStreamIndex is the index of the
video stream I store during the initial open. However I also allow audio only
files in my program, so that check uses the video stream if it exists or the
FFmpeg default stream if it doesn't. You may not need either of those
depending on how your code works. The main things are... You need to be careful
not to use the AVSEEK_FLAG_ANY past the end of the file because that screws up
some of the demuxers and causes future seeks to mess up. And the extra check at
the very end is necessary because on some files the AVSEEK_FLAG_BACKWARDS does
not work when seeking to 0, so you have to catch it and try again with
AVSEEK_FLAG_ANY to make sure you actually end up at the start.
This code works well on all the files I've tested, but we only use FFmpeg for
MP4, MKV and FLV so you may still have trouble with other formats.
Dan
From: [email protected]
Date: Tue, 13 Sep 2011 12:49:14 -0400
To: [email protected]
Subject: Re: [Libav-user] Seeking problem with avformat_seek_file
On Tue, Sep 13, 2011 at 12:42 PM, Benjamin Gretsch <[email protected]> wrote:
Good afternoon,
After days of searching and trying, I still have a problem:
When I use avformat_seek_file() to go back to the very beginning of a file
and then av_read_frame(), I still don't get the first frames again.
The goal is to extract multiple chunks of audio from a stream.
My approach is to read the stream, discard what I don't need. While doing
that I create a list of "points of interest" where I need to go back later.
My intermediate approach is to always go back to the beginning and start
discarding again.
What I am doing exactly is:
//read frames, discard what's not needed:
while(...) av_read_frame(...)
//go back to the beginning (that's the part that doesn't work):
avcodec_flush_buffers(avcc); //flush the codec's buffers
avformat_seek_file(
avf, streamIndex,
bytepos, bytepos, bytepos,
AVSEEK_FLAG_BYTE
); //bytepos is packet.pos of the first packet I have read
//and will later be a position from the index that I will build
Have you tried moving the flush after the seek (not sure if that will make a
difference). Here's how I use it, without any problem:
avformat_seek_file(m_pFormatCtx, m_nVideoStream, INT64_MIN, nTime, INT64_MAX,
0), where nTime would be zero. This is how it'd done (min/max) in in one of the
ffmpeg.c or ffplay.c files.
If you have an example file I can try it and see if I also have that issue.
Which type of file are you using btw?
Matt
_______________________________________________
Libav-user mailing list
[email protected]
http://ffmpeg.org/mailman/listinfo/libav-user
_______________________________________________
Libav-user mailing list
[email protected]
http://ffmpeg.org/mailman/listinfo/libav-user