ffmpeg 中config 文件一些理解

依赖检查

config中看到最多的是:

bash 复制代码
...
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中
bash 复制代码
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)为例,假设其依赖配置如下:

bash 复制代码
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)

bash 复制代码
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

组件列表处理分开解析:

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

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

bash 复制代码
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

常规选项处理

bash 复制代码
elif is_in $option $CMDLINE_SELECT; then
    $action $option

CMDLINE_SELECT:包含可直接通过命令行启用 / 禁用的选项列表(如 debug, shared, static 等)。

逻辑:直接执行 action(enable 或 disable)操作对应的选项

示例说明

示例 1:启用所有编码器

bash 复制代码
--enable-encoders

转换为 action=enable option=encoders

由于 encoders 在 COMPONENT_LIST 中,执行 enable ENCODERS_LIST

最终启用所有编码器(通过修改 ENCODERS_LIST 变量)

示例 2:禁用调试模式

bash 复制代码
--disable-debug

转换为 action=disable option=debug

由于 debug 在 CMDLINE_SELECT 中,执行 disable debug

最终禁用调试模式(通过设置 enable_debug=no)

示例 3:启用 libx264 支持

bash 复制代码
--enable-libx264

转换为 action=enable option=libx264

由于 libx264 在 CMDLINE_SELECT 中,执行 enable libx264

最终启用 libx264 外部库支持

bash 复制代码
用户输入 --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- 开头,后跟任意字符串,再以 = 连接另一个任意字符串的参数.

案例:

bash 复制代码
    --enable-decoder=libx264 \
    --enable-decoder=libx265 \

config 中处理代码:

bash 复制代码
        --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
        ;;

示例说明

bash 复制代码
--enable-encoder=h264

参数解析:

action=enable

thing=encoder

list=$ENCODERS_LIST(所有编码器列表)

name=h264_encoder

执行结果:

从 ENCODERS_LIST 中筛选出 h264_encoder。

执行 enable h264_encoder,启用 H.264 编码器。

bash 复制代码
--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的位置:

相关推荐
ι:5 小时前
NUC12 Pro 安装 Ubuntu 24.04 LTS 详细教程
linux·windows·ubuntu·nuc
YCOSA20255 小时前
微软宣布将于10月7日举行Windows与Surface发布会,聚焦“Windows、NVIDIA RTX Spark、Surface,以及更广泛PC生态”
windows
Source.Liu5 小时前
【A11】 labelprinter(Tauri 版)新建步骤
windows·rust
Punchline2786 小时前
解决 Windows 环境变量 Path 设置时提示“字符太长”的完整指南
windows·环境变量·path
chushiyunen7 小时前
claude code笔记(二)、claude桌面端(内网不好用)
windows
d_benhua7 小时前
以太网测试步骤
windows
宝桥南山7 小时前
Microsoft Fabric - 简单尝试一下Microsoft Fabric .NET SDK
microsoft·微软·.net·.netcore·powerbi·fabric
hqyjzsb8 小时前
规划工商管理大学成长:搭建四层能力体系,重视高阶的 AI 能力建设
开发语言·人工智能·python·microsoft·职场和发展·数据挖掘·业界资讯
冯一川8 小时前
DeepSeek在Windows系统上部署
windows·python
解道Jdon9 小时前
JDK 27发布:紧凑对象头、G1默认、量子安全TLS
ide·windows·git·svn·eclipse·github·visual studio