Seek
FFmpeg提供了一个seek函数,原型如下
/**
* 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);
这个函数不管你当前在什么时间点上,都可以seek到任何合理位置。比如要实现在当前的基础上向后或向前跳转10秒,我们可以在av_read_frame函数拿到的包中含有当前时间戳的基础上增加或减少一个10000(换算成播放时间单位)再seek即可。所以这个函数可以用做进度的拖放、前进/后退一定时间、循环播放等功能。
参数说明:
s
:操作上下文;
stream_index
:基本流索引,表示当前的seek是针对哪个基本流,比如视频或者音频等等。
timestamp
:要seek的时间点,以time_base或者AV_TIME_BASE为单位。
Flags
:seek标志,可以设置为按字节,在按时间seek时取该点之前还是之后的关键帧,以及不按关键帧seek等,详细请参考FFmpeg的
avformat.h说明。基于FFmpeg的所有track mode几乎都是用这个函数来直接或间接实现的。
举例说明
seek功能的实现
- 要转跳到视频100秒(100 000毫秒)处的第一个I帧(如果没有则向前找第一个):
av_seek_frame(pFormatCtx, vid_index, 100000*vid_time_scale/time_base, AVSEEK_FLAG_BACKWARD);
- 跳到音频80秒(80 000毫秒)处的帧(采样):
av_seek_frame(pFormatCtx, aud_index, 80000*aud_time_scale/ time_base, AVSEEK_FLAG_BACKWARD);
- 跳到文件开始的地方开始播放:
av_seek_frame(pFormatCtx, vid_index, 0, AVSEEK_FLAG_BACKWARD);
上面的time_scale、time_base都能通过流信息获取到