ffmpeg # probesize & analyzeduration

avformat_find_stream_info的调用堆栈.png

ffmpeg在avformat_find_stream_info中会读取一部分源文件的音视频数据,来分析文件信息,那么这个操作读取多少数据呢?
答案是: 通过probesize和analyzeduration两个参数来控制

Some applications, including the ffmpeg command-line tool, can only work with streams that were detected during the initial scan; streams that are detected later are ignored.

The size of the initial scan is controlled by two options: probesize (default ~5 Mo) and analyzeduration (default 5,000,000 µs = 5 s). For the subtitle stream to be detected, both values must be large enough.

直接用命令行查看这两个参数:

[root@localhost ffmpeg_v4.0]# ./ffmpeg -h full | grep 'analyzeduration\|probesize'
ffmpeg version N-91445-g6cc6b61 Copyright (c) 2000-2018 the FFmpeg developers
  built with gcc 4.8.5 (GCC) 20150623 (Red Hat 4.8.5-11)
  configuration: --enable-gpl --enable-debug=3 --enable-libmfx --disable-optimizations --disable-stripping
  libavutil      56. 18.102 / 56. 18.102
  libavcodec     58. 21.104 / 58. 21.104
  libavformat    58. 17.101 / 58. 17.101
  libavdevice    58.  4.101 / 58.  4.101
  libavfilter     7. 25.100 /  7. 25.100
  libswscale      5.  2.100 /  5.  2.100
  libswresample   3.  2.100 /  3.  2.100
  libpostproc    55.  2.100 / 55.  2.100
  -probesize         <int64>      .D....... set probing size (from 32 to I64_MAX) (default 5e+06)
  -formatprobesize   <int>        .D....... number of bytes to probe file format (from 0 to 2.14748e+09) (default 1.04858e+06)
  -analyzeduration   <int64>      .D....... specify how many microseconds are analyzed to probe the input (from 0 to I64_MAX) (default 0)
  -fpsprobesize      <int>        .D....... number of frames used to probe fps (from -1 to 2.14748e+09) (default -1)

-probesize和 -analyzeduration定义在libavformat/options_table.h

static const AVOption avformat_options[] = {
...
{"probesize", "set probing size", OFFSET(probesize), AV_OPT_TYPE_INT64, {.i64 = 5000000 }, 32, INT64_MAX, D},
...
{"analyzeduration", "specify how many microseconds are analyzed to probe the input", OFFSET(max_analyze_duration), AV_OPT_TYPE_INT64, {.i64 = 0 }, 0, INT64_MAX, D},
...
}

可以看到probesize默认为5000000, 而analyzeduration默认为0.

传入的参数保存在libavformat/avformat.h中AVFormatContext的probesize和max_analyze_duration变量中。

typedef struct AVFormatContext {
...
    /**
     * Maximum size of the data read from input for determining
     * the input container format.
     * Demuxing only, set by the caller before avformat_open_input().
     */
    int64_t probesize;

    /**
     * Maximum duration (in AV_TIME_BASE units) of the data read
     * from input in avformat_find_stream_info().
     * Demuxing only, set by the caller before avformat_find_stream_info().
     * Can be set to 0 to let avformat choose using a heuristic.
     */
    int64_t max_analyze_duration;
...
}

从上可以看出probesize是从源文件中读取的最大字节数,单位为字节。
max_analyze_duration是从文件中读取的最大时长,单位为 AV_TIME_BASE units

/**
 * Internal time base represented as integer
 */

#define AV_TIME_BASE            1000000
‘probesize integer (input)’

Set probing size in bytes, i.e. the size of the data to analyze to get stream information.
A higher value will enable detecting more information in case it is dispersed into the stream, but will increase latency.
Must be an integer not lesser than 32.
It is 5000000 by default.

probesize的单位是字节。
最小是32字节。
默认是 5000000字节。

‘analyzeduration integer (input)’

Specify how many microseconds are analyzed to probe the input.
A higher value will enable detecting more accurate information, but will increase latency.
It defaults to 5,000,000 microseconds = 5 seconds.

avformat_find_stream_info函数中:

    max_stream_analyze_duration = max_analyze_duration;
    max_subtitle_analyze_duration = max_analyze_duration;
    if (!max_analyze_duration) {
        max_stream_analyze_duration =
        max_analyze_duration        = 5*AV_TIME_BASE;
        max_subtitle_analyze_duration = 30*AV_TIME_BASE;
        if (!strcmp(ic->iformat->name, "flv"))
            max_stream_analyze_duration = 90*AV_TIME_BASE;
        if (!strcmp(ic->iformat->name, "mpeg") || !strcmp(ic->iformat->name, "mpegts"))
            max_stream_analyze_duration = 7*AV_TIME_BASE;
    }

可以看到analyzeduration参数不设置时,即analyzeduration默认等于0时,可以看到默认的分析时长为5秒:

 max_analyze_duration        = 5*AV_TIME_BASE;

而如果是flv文件的时候, 默认为90秒

if (!strcmp(ic->iformat->name, "flv"))
            max_stream_analyze_duration = 90*AV_TIME_BASE;

mpeg和mpegts文件的时候,默认7秒:

 if (!strcmp(ic->iformat->name, "mpeg") || !strcmp(ic->iformat->name, "mpegts"))
            max_stream_analyze_duration = 7*AV_TIME_BASE;

probesize & analyzeduration 同时存在 听谁的?

To coerce ffmpeg to search further for the subtitle stream, use options:

 -probesize <bytes> -analyzeduration <Maximum duration in AV_TIME_BASE units>

which will cause ffmpeg to search until the first of those limits is reached.
Note that both of these options must appear on the command line before the specification of the input via -i. For example:

ffmpeg -probesize 50M -analyzeduration 100M -i vts.vob

will search through vts.vob for all streams until it has read 50 MB of data or 100 seconds of video, whichever comes first.

结论是: 谁先达到就听谁的
以上的例子是读取50M的数据或100秒的数据,那个标准先达到,那就听谁的,停止probe

References:

ffmpeg/doc/ffmpeg-formats.texi
ffmpeg/doc/faq.texi
https://ffmpeg.org/ffmpeg-formats.html

推荐阅读更多精彩内容