ffmpeg # start_time in AVFormatContext

static int open_input_file(OptionsContext *o, const char *filename)
{
    InputFile *f;
    AVFormatContext *ic;
...
    /* get default parameters from command line */
    ic = avformat_alloc_context();
    if (!ic) {
        print_error(filename, AVERROR(ENOMEM));
        exit_program(1);
    }
...
if (find_stream_info) {
        ...
        /* If not enough info to get the stream parameters, we decode the
           first frames to get it. (used in mpeg case for example) */
        ret = avformat_find_stream_info(ic, opts);
        ...
           }

...
    // o->start_time是命令行中"-ss"的时间,单位是AV_TIME_BASE
    timestamp = (o->start_time == AV_NOPTS_VALUE) ? 0 : o->start_time;
    /* add the stream start time */
    if (!o->seek_timestamp && ic->start_time != AV_NOPTS_VALUE)
        timestamp += ic->start_time; // 这里的ic->start_time 是什么呢?

...
/* if seeking requested, we execute it */
    if (o->start_time != AV_NOPTS_VALUE) {
        int64_t seek_timestamp = timestamp; // 最终要seek的时间点 单位AV_TIME_BASE

       ...
                // seek到目标时间点
                ret = avformat_seek_file(ic, -1, INT64_MIN, seek_timestamp, seek_timestamp, 0);
        if (ret < 0) {
            av_log(NULL, AV_LOG_WARNING, "%s: could not seek to position %0.3f\n",
                   filename, (double)timestamp / AV_TIME_BASE);
        }
    }

}

AVFormatContext中的start_time定义如下:

typedef struct AVFormatContext {
...
    /**
     * Position of the first frame of the component, in
     * AV_TIME_BASE fractional seconds. NEVER set this value directly:
     * It is deduced from the AVStream values.
     *
     * Demuxing only, set by libavformat.
     */
    int64_t start_time;
...
}

可见这个是只在解封装的时候用到,是第一帧的时间位置。
其实是该文件所有流中,起始时间戳最小的那个。
它是如何获取的呢?

ffmpeg # start_time in AVFormatContext_第1张图片
1

/**
 * Estimate the stream timings from the one of each components.
 *
 * Also computes the global bitrate if possible.
 */
static void update_stream_timings(AVFormatContext *ic)
{
    int64_t start_time, start_time1, start_time_text, end_time, end_time1, end_time_text;
...
    start_time = INT64_MAX;
    start_time_text = INT64_MAX;
...
for (i = 0; i < ic->nb_streams; i++) {
        AVStream *st = ic->streams[i];
        int is_text = st->codecpar->codec_type == AVMEDIA_TYPE_SUBTITLE ||
                      st->codecpar->codec_type == AVMEDIA_TYPE_DATA;
        if (st->start_time != AV_NOPTS_VALUE && st->time_base.den) {
            start_time1 = av_rescale_q(st->start_time, st->time_base,
                                       AV_TIME_BASE_Q);
            if (is_text)
                start_time_text = FFMIN(start_time_text, start_time1); // 取小值
            else
                start_time = FFMIN(start_time, start_time1); // 取小值
           ...
          }
      } // end of for 

// 比较
    if (start_time == INT64_MAX || (start_time > start_time_text && start_time - (uint64_t)start_time_text < AV_TIME_BASE))
        start_time = start_time_text;
    else if (start_time > start_time_text)
        av_log(ic, AV_LOG_VERBOSE, "Ignoring outlier non primary stream starttime %f\n", start_time_text / (float)AV_TIME_BASE);

...
    if (start_time != INT64_MAX) {
        ic->start_time = start_time; // 真正赋值的地方
...
      }
...
}

ffmpeg # start_time in AVFormatContext_第2张图片
2

你可能感兴趣的:(ffmpeg # start_time in AVFormatContext)