[ffmpeg] 中 avformat_seek_file 的用法?

20 阅读2分钟

avformat_seek_file :用于在媒体文件中进行时间定位(seek)操作

  • 原型如下

/**
 * Seek to timestamp ts.
 * Seeking will be done so that the point from which all active streams
 * can be presented successfully will be closest to ts and within min/max_ts.
 * Active streams are all streams that have AVStream.discard < AVDISCARD_ALL.
 *
 * If flags contain AVSEEK_FLAG_BYTE, then all timestamps are in bytes and
 * are the file position (this may not be supported by all demuxers).
 * If flags contain AVSEEK_FLAG_FRAME, then all timestamps are in frames
 * in the stream with stream_index (this may not be supported by all demuxers).
 * Otherwise all timestamps are in units of the stream selected by stream_index
 * or if stream_index is -1, in AV_TIME_BASE units.
 * If flags contain AVSEEK_FLAG_ANY, then non-keyframes are treated as
 * keyframes (this may not be supported by all demuxers).
 * If flags contain AVSEEK_FLAG_BACKWARD, it is ignored.
 *
 * @param s media file handle
 * @param stream_index index of the stream which is used as time base reference
 * @param min_ts smallest acceptable timestamp
 * @param ts target timestamp
 * @param max_ts largest acceptable timestamp
 * @param flags flags
 * @return >=0 on success, error code otherwise
 *
 * @note This is part of the new seek API which is still under construction.
 *       Thus do not use this yet. It may change at any time, do not expect
 *       ABI compatibility yet!
 */
int avformat_seek_file(AVFormatContext *s, int stream_index, int64_t min_ts, int64_t ts, int64_t max_ts, int flags);
  • 参数解释
  • s: 指向 AVFormatContext 结构体的指针,表示媒体文件的上下文信息。
  • stream_index: 需要进行定位的流的索引。可以通过 av_find_best_stream 等函数获取。
  • min_ts: 允许的最小时间戳(timestamp),以 AV_TIME_BASE 为单位。如果没有合适的时间戳,会选择最接近的时间戳。
  • target_ts: 目标时间戳,以 AV_TIME_BASE 为单位。函数将尝试定位到与目标时间戳最接近的位置。
  • max_ts: 允许的最大时间戳,以 AV_TIME_BASE 为单位。如果没有合适的时间戳,会选择最接近的时间戳。
  • flags: 控制定位行为的标志位。
    • flags 解释
      • AVSEEK_FLAG_BACKWARD:向后定位(从目标时间戳向前搜索)。
      • AVSEEK_FLAG_ANY :允许任意帧的定位,而不仅仅是关键帧。
      • AVSEEK_FLAG_FRAME:定位到目标时间戳所在的最接近的关键帧。

调用范例

#include <stdio.h>
#include <libavformat/avformat.h>

int main() {
    // step-1
    av_register_all();

    AVFormatContext *formatContext = NULL;
        // step-2
    int ret = avformat_open_input(&formatContext, "input.mp4", NULL, NULL);
    if (ret < 0) {
        printf("Error opening input file\n");
        return ret;
    }
        // step-3
    ret = avformat_find_stream_info(formatContext, NULL);
    if (ret < 0) {
        printf("Error finding stream information\n");
        avformat_close_input(&formatContext);
        return ret;
    }
        // step-4
    int streamIndex = av_find_best_stream(formatContext, AVMEDIA_TYPE_VIDEO, -1, -1, NULL, 0);
    if (streamIndex < 0) {
        printf("Error finding video stream\n");
        avformat_close_input(&formatContext);
        return streamIndex;
    }
        // step-5
    AVStream *stream = formatContext->streams[streamIndex];

    int64_t targetTimestamp = 5000000;  // Target timestamp in microseconds
    int64_t minTimestamp = INT64_MIN;
    int64_t maxTimestamp = INT64_MAX;
    int flags = AVSEEK_FLAG_BACKWARD;
         // step-6
    ret = avformat_seek_file(formatContext, streamIndex, minTimestamp, targetTimestamp, maxTimestamp, flags);
    if (ret < 0) {
        printf("Error seeking to target timestamp\n");
        avformat_close_input(&formatContext);
        return ret;
    }

    // Perform necessary operations after seeking (e.g., decoding frames)

    avformat_close_input(&formatContext);

    return 0;
}