ffmpeg中当av_seek_frame的时候需要读文件的开始位置,调用方式
ret = av_read_frame(pFormatCtx, packet);
if (ret < 0)
{
ret = av_seek_frame(pFormatCtx, videoindex, pFormatCtx->streams[videoindex]->start_time, 0); //seek到视频的开始位置
if (ret<0) {
printf("av_seek_frame ==video== error\n");
}
avcodec_flush_buffers(pFormatCtx->streams[videoindex]->codec); //清空解码器的缓存
printf("av_seek_frame ==video== error\n");
continue;
}
/**
* Seek to the keyframe at timestamp.
* 'timestamp' in 'stream_index'.
*
* @param s media file handle
* @param stream_index If stream_index is (-1), a default
* stream is selected, and timestamp is automatically converted
* from AV_TIME_BASE units to the stream specific time_base.
* @param timestamp Timestamp in AVStream.time_base units
* or, if no stream is specified, in AV_TIME_BASE units.
* @param flags flags which select direction and seeking mode
* @return >= 0 on success
*/
int av_seek_frame(AVFormatContext *s, int stream_index, int64_t timestamp,
int flags);
/**
* Reset the internal decoder state / flush internal buffers. Should be called
* e.g. when seeking or when switching to a different stream. <span style="font-family: Arial, Helvetica, sans-serif;">//当seek的时候调用或者转到另一个流的时候调用</span>
*
* @note when refcounted frames are not used (i.e. avctx->refcounted_frames is 0),
* this invalidates the frames previously returned from the decoder. When
* refcounted frames are used, the decoder just releases any references it might
* keep internally, but the caller's reference remains valid.
*/
void avcodec_flush_buffers(AVCodecContext *avctx);
ffmpeg.c中的seek_to_start 调用
还是需要将ffmpeg中各功能的代码 了解透彻,各功能在ffmpeg中应该都能了解到
static int seek_to_start(InputFile *ifile, AVFormatContext *is)
{
InputStream *ist;
AVCodecContext *avctx;
int i, ret, has_audio = 0;
int64_t duration = 0;
ret = av_seek_frame(is, -1, is->start_time, 0); <span style="font-family: Arial, Helvetica, sans-serif;">//=================================***************************** </span>
if (ret < 0)
return ret;
for (i = 0; i < ifile->nb_streams; i++) {
ist = input_streams[ifile->ist_index + i];
avctx = ist->dec_ctx;
// flush decoders
if (ist->decoding_needed) {
process_input_packet(ist, NULL, 1);
avcodec_flush_buffers(avctx); //=================================*****************************
}
/* duration is the length of the last frame in a stream
* when audio stream is present we don't care about
* last video frame length because it's not defined exactly */
if (avctx->codec_type == AVMEDIA_TYPE_AUDIO && ist->nb_samples)
has_audio = 1;
}
for (i = 0; i < ifile->nb_streams; i++) {
ist = input_streams[ifile->ist_index + i];
avctx = ist->dec_ctx;
if (has_audio) {
if (avctx->codec_type == AVMEDIA_TYPE_AUDIO && ist->nb_samples) {
AVRational sample_rate = {1, avctx->sample_rate};
duration = av_rescale_q(ist->nb_samples, sample_rate, ist->st->time_base);
} else
continue;
} else {
if (ist->framerate.num) {
duration = av_rescale_q(1, ist->framerate, ist->st->time_base);
} else if (ist->st->avg_frame_rate.num) {
duration = av_rescale_q(1, ist->st->avg_frame_rate, ist->st->time_base);
} else duration = 1;
}
if (!ifile->duration)
ifile->time_base = ist->st->time_base;
/* the total duration of the stream, max_pts - min_pts is
* the duration of the stream without the last frame */
duration += ist->max_pts - ist->min_pts;
ifile->time_base = duration_max(duration, &ifile->duration, ist->st->time_base,
ifile->time_base);
}
if (ifile->loop > 0)
ifile->loop--;
return ret;
}