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

Reply via email to