ffmpeg 中config 文件一些理解

发布于:2025-07-09 ⋅ 阅读:(28) ⋅ 点赞:(0)

依赖检查

config中看到最多的是:

...
nvenc_deps="ffnvcodec"
nvenc_deps_any="libdl LoadLibrary"
nvenc_encoder_deps="nvenc"
...
h264_crystalhd_decoder_select="crystalhd h264_mp4toannexb_bsf h264_parser"
h264_cuvid_decoder_deps="cuvid"
h264_cuvid_decoder_select="h264_mp4toannexb_bsf"
h264_mediacodec_decoder_deps="mediacodec"
h264_mediacodec_decoder_select="h264_mp4toannexb_bsf h264_parser"
h264_mf_encoder_deps="mediafoundation"
h264_mmal_decoder_deps="mmal"
h264_nvenc_encoder_deps="nvenc"
h264_nvenc_encoder_select="atsc_a53"
...

这个主要用来做依赖检查,比如上面的nvenc_deps="ffnvcodec"表示:
nvenc这个模块依赖ffnvcodec,其余以此类推。

依赖类型:

_deps:必须全部满足的依赖(如 flv_decoder 依赖 h264_decoder)。
_deps_any:只需满足任意一个的依赖。
_conflict:不能同时存在的冲突依赖。
_select:强制启用的依赖(如 flv_decoder 强制启用 h264_parser)。
_suggest:建议启用的可选依赖。
_if 和 _if_any:条件启用的依赖。

依赖检查函数

核心检查在下边:

  • 首先我们看到list列表是从相关的allxxx.c文件中获取到的,然后添加到对应的list中
FILTER_LIST=$(find_filters_extern libavfilter/allfilters.c)
OUTDEV_LIST=$(find_things_extern muxer AVOutputFormat libavdevice/alldevices.c outdev)
INDEV_LIST=$(find_things_extern demuxer AVInputFormat libavdevice/alldevices.c indev)
MUXER_LIST=$(find_things_extern muxer AVOutputFormat libavformat/allformats.c)
DEMUXER_LIST=$(find_things_extern demuxer AVInputFormat libavformat/allformats.c)
ENCODER_LIST=$(find_things_extern encoder AVCodec libavcodec/allcodecs.c)
DECODER_LIST=$(find_things_extern decoder AVCodec libavcodec/allcodecs.c)
CODEC_LIST="
    $ENCODER_LIST
    $DECODER_LIST
"
PARSER_LIST=$(find_things_extern parser AVCodecParser libavcodec/parsers.c)
BSF_LIST=$(find_things_extern bsf AVBitStreamFilter libavcodec/bitstream_filters.c)
HWACCEL_LIST=$(find_things_extern hwaccel AVHWAccel libavcodec/hwaccels.h)
PROTOCOL_LIST=$(find_things_extern protocol URLProtocol libavformat/protocols.c)
...
AVCODEC_COMPONENTS_LIST="
    $BSF_LIST
    $DECODER_LIST
    $ENCODER_LIST
    $HWACCEL_LIST
    $PARSER_LIST
"
...

check_deps $CONFIG_LIST       \
           $CONFIG_EXTRA      \
           $HAVE_LIST         \
           $ALL_COMPONENTS    \
# The cfg loop is very hot (several thousands iterations), and in bash also
# potentialy quite slow. Try to abort the iterations early, preferably without
# calling functions. 70%+ of the time cfg is already done or without deps.
check_deps(){
    for cfg; do
        # 避免重复检查或检测循环依赖
        eval [ x\$${cfg}_checking = xdone ] && continue
        eval [ x\$${cfg}_checking = xinprogress ] && die "Circular dependency for $cfg."

 		# 获取组件的各种依赖配置
        eval "
        dep_all=\$${cfg}_deps
        dep_any=\$${cfg}_deps_any
        dep_con=\$${cfg}_conflict
        dep_sel=\$${cfg}_select
        dep_sgs=\$${cfg}_suggest
        dep_ifa=\$${cfg}_if
        dep_ifn=\$${cfg}_if_any
        "

        # most of the time here $cfg has no deps - avoid costly no-op work
        if [ "$dep_all$dep_any$dep_con$dep_sel$dep_sgs$dep_ifa$dep_ifn" ]; then
            eval ${cfg}_checking=inprogress
            
			# 递归检查当前组件的所有依赖
			#递归策略:先检查当前组件的所有依赖项(如 A 依赖 B,则先检查 B 的依赖),确保依赖链上的所有组件状态都被确定。
            set -- $cfg "$dep_all" "$dep_any" "$dep_con" "$dep_sel" "$dep_sgs" "$dep_ifa" "$dep_ifn"
            check_deps $dep_all $dep_any $dep_con $dep_sel $dep_sgs $dep_ifa $dep_ifn
            cfg=$1; dep_all=$2; dep_any=$3; dep_con=$4; dep_sel=$5 dep_sgs=$6; dep_ifa=$7; dep_ifn=$8

			# 条件启用:若 dep_ifa 中所有项都启用,则弱启用当前组件
            [ -n "$dep_ifa" ] && { enabled_all $dep_ifa && enable_weak $cfg; }
            [ -n "$dep_ifn" ] && { enabled_any $dep_ifn && enable_weak $cfg; }
            
            # 弱启用(enable_weak):仅在其他条件允许时启用,否则保持禁用。
            # 必须依赖:所有 _deps 必须满足
            enabled_all  $dep_all || { disable_with_reason $cfg "not all dependencies are satisfied: $dep_all"; }
            # 可选依赖:_deps_any 中至少满足一个
            enabled_any  $dep_any || { disable_with_reason $cfg "not any dependency is satisfied: $dep_any"; }
            # 冲突检查:_conflict 中所有项必须禁用
            disabled_all $dep_con || { disable_with_reason $cfg "some conflicting dependencies are unsatisfied: $dep_con"; }
            # 强制依赖:_select 中所有项必须启用
            disabled_any $dep_sel && { disable_with_reason $cfg "some selected dependency is unsatisfied: $dep_sel"; }
            
			# 若当前组件启用,则递归启用 _select 和 _suggest 中的依赖
            enabled $cfg && enable_deep_weak $dep_sel $dep_sgs
			# 收集额外库依赖
            for dep in $dep_all $dep_any $dep_sel $dep_sgs; do
                # filter out library deps, these do not belong in extralibs
                is_in $dep $LIBRARY_LIST && continue
                enabled $dep && eval append ${cfg}_extralibs ${dep}_extralibs
            done
        fi

        eval ${cfg}_checking=done
    done
}

依赖关系示例

以 FLV 解码器(flv_decoder)为例,假设其依赖配置如下:

flv_decoder_deps="h264_decoder aac_decoder"
flv_decoder_select="h264_parser"
flv_decoder_suggest="zlib"

必须依赖:h264_decoder 和 aac_decoder 必须同时启用。
强制启用:若 flv_decoder 启用,则 h264_parser 也会被强制启用。
建议依赖:zlib 可选,若可用则更好(如用于压缩数据)。

函数调用流程
初始化:配置脚本通过 enabled 等函数设置初始组件状态(如用户通过 --enable-xxx 指定)。
调用 check_deps:传入所有组件名,开始递归检查。
递归验证:从叶子节点(无依赖的组件)开始,逐层向上验证依赖关系。
状态传播:根据依赖结果,启用或禁用组件,并记录原因(如 “缺少 xyz 依赖”)。

命令参数–enable-xxx

这个处理在config :--enable-*=*|--disable-*=*)中处理。

–enable-?:匹配以 --enable- 开头,后跟至少一个字符的参数(如 --enable-libx264)。
–disable-?
:匹配以 --disable- 开头,后跟至少一个字符的参数(如 --disable-debug)

for opt do
    optval="${opt#*=}"
    case "$opt" in
        --extra-ldflags=*)
            add_ldflags $optval
        ;;
        ...
       --enable-?*|--disable-?*)
       # 使用 sed 命令将参数转换为 shell 变量赋值语句:
       # --enable-libx264 → action=enable option=libx264
       # --disable-debug → action=disable option=debug
       # 通过 eval 执行转换后的语句,将 action 和 option 设为当前 shell 变量。
            eval $(echo "$opt" | sed 's/--/action=/;s/-/ option=/;s/-/_/g')
            # 判断是否在$COMPONENT_LIST中
            if is_in $option $COMPONENT_LIST; then
                test $action = disable && action=unset
                eval $action \$$(toupper ${option%s})_LIST
            elif is_in $option $CMDLINE_SELECT; then
                $action $option
            else
                die_unknown $opt
            fi
        ;;
        ...
                --help|-h) show_help
        ;;
        --quiet|-q) quiet=yes
        ;;
        --fatal-warnings) enable fatal_warnings
        ;;
        --libfuzzer=*)
            libfuzzer_path="$optval"
        ;;
        *)
            optname="${opt%%=*}"
            optname="${optname#--}"
            optname=$(echo "$optname" | sed 's/-/_/g')
            if is_in $optname $CMDLINE_SET; then
                eval $optname='$optval'
            elif is_in $optname $CMDLINE_APPEND; then
                append $optname "$optval"
            else
                die_unknown $opt
            fi
        ;;
    esac
done

组件列表处理分开解析:

if is_in $option $COMPONENT_LIST; then
    test $action = disable && action=unset
    eval $action \$$(toupper ${option%s})_LIST

COMPONENT_LIST:包含 FFmpeg 中可独立配置的组件类型(如 encoders, decoders, filters 等)。

COMPONENT_LIST="
    $AVCODEC_COMPONENTS
    $AVDEVICE_COMPONENTS
    $AVFILTER_COMPONENTS
    $AVFORMAT_COMPONENTS
"

逻辑:
若 option 是组件类型(如 encoders),则:
若为 disable 操作,将其转换为 unset(从列表中移除)。
通过 eval 动态操作对应的大写组件列表变量:
例如 --enable-encoders → enable ENCODERS_LIST
例如 --disable-decoders → unset DECODERS_LIST

常规选项处理

elif is_in $option $CMDLINE_SELECT; then
    $action $option

CMDLINE_SELECT:包含可直接通过命令行启用 / 禁用的选项列表(如 debug, shared, static 等)。
逻辑:直接执行 action(enable 或 disable)操作对应的选项

示例说明

示例 1:启用所有编码器

--enable-encoders

转换为 action=enable option=encoders
由于 encoders 在 COMPONENT_LIST 中,执行 enable ENCODERS_LIST
最终启用所有编码器(通过修改 ENCODERS_LIST 变量)

示例 2:禁用调试模式

--disable-debug

转换为 action=disable option=debug
由于 debug 在 CMDLINE_SELECT 中,执行 disable debug
最终禁用调试模式(通过设置 enable_debug=no)

示例 3:启用 libx264 支持

--enable-libx264

转换为 action=enable option=libx264
由于 libx264 在 CMDLINE_SELECT 中,执行 enable libx264
最终启用 libx264 外部库支持

用户输入 --enable-libx264
  ↓
configure 脚本解析参数,匹配 --enable-?* 模式
  ↓
调用 enable libx264 → 设置 libx264=yes 由于 libx264 在 CMDLINE_SELECT 中,执行 enable libx264
  ↓
遍历 AUTODETECT_LIBS,发现 libx264 已启用
  ↓
调用 request libx264 → 强制验证依赖
  ↓
check_deps 验证 libx264 的系统依赖(通过 pkg-config 等)
  ↓
若验证通过,生成编译配置(CFLAGS/LDFLAGS、config.h)
  ↓
启用依赖 libx264 的组件(如 h264_libx264_encoder)

命令参数—enable-=|–disable-=)

-enable-=
匹配以 --enable- 开头,后跟任意字符串,再以 = 连接另一个任意字符串的参数.
案例:

    --enable-decoder=libx264 \
    --enable-decoder=libx265 \

config 中处理代码:

        --enable-*=*|--disable-*=*)
            # ${opt%%=*}:提取参数等号前的部分(如 --enable-encoder → --enable-encoder)。
			# sed 替换:将 --enable-encoder 转换为 action=enable thing=encoder,并通过 eval 设置为变量。
            eval $(echo "${opt%%=*}" | sed 's/--/action=/;s/-/ thing=/')
            # ${thing}s:将组件类型转为复数形式(如 encoder → encoders)
            is_in "${thing}s" $COMPONENT_LIST || die_unknown "$opt"
            # 态获取组件列表:将组件类型转为大写并添加 _LIST 后缀(如 encoder → ENCODERS_LIST)。
            # 示例:thing=encoder → list=$ENCODERS_LIST,获取所有编码器列表。
            eval list=\$$(toupper $thing)_LIST
            # 将逗号分隔的多个组件名转为正则表达式(如 h264,mp3 → h264_encoder|mp3_encoder)。
			# 添加 _${thing} 后缀以匹配内部组件命名(如 h264 → h264_encoder)。
            name=$(echo "${optval}" | sed "s/,/_${thing}|/g")_${thing}
            #filter 函数:从 $list 中筛选出匹配 $name 的组件。
			# 示例:若 name=h264_encoder,则从 ENCODERS_LIST 中筛选出 h264_encoder
            list=$(filter "$name" $list)
            # 空检查:若未找到匹配组件,发出警告。
            # 依赖检查:若启用组件,先检查其依赖是否满足(warn_if_gets_disabled)。
            # 执行操作:调用 enable 或 disable 函数处理筛选出的组件。
            [ "$list" = "" ] && warn "Option $opt did not match anything"
            test $action = enable && warn_if_gets_disabled $list
            $action $list
        ;;

示例说明

--enable-encoder=h264

参数解析:
action=enable
thing=encoder
list=$ENCODERS_LIST(所有编码器列表)
name=h264_encoder
执行结果:
从 ENCODERS_LIST 中筛选出 h264_encoder。
执行 enable h264_encoder,启用 H.264 编码器。

--disable-filter=scale,transpose

参数解析:
action=disable
thing=filter
list=$FILTERS_LIST(所有滤镜列表)
name=scale_filter|transpose_filter
执行结果:
从 FILTERS_LIST 中筛选出 scale_filter 和 transpose_filter。
执行 disable scale_filter transpose_filter,禁用这两个滤镜。

auto detect

auto detect 的模块都在下图所示的位置enable, enable_weak的意思是如果模块已经被设置过了,就不设置,没有设置的时候才设置。
比如下图nvdec和nvenc只有disable:在这里插入图片描述configure自动设置enable的位置:在这里插入图片描述


网站公告

今日签到

点亮在社区的每一天
去签到