ffmpeg configure 研究2:分析屏幕输出及文件输出的具体过程
author: hjjdebug
date: 2025年 02月 17日 星期一 16:57:55 CST
description: ffmpeg configure 研究2
分析屏幕输出及文件输出的具体过程
文章目录
- 0. 执行./configure 命令
- 1. sed: can't read 信息是从哪里来的 ?
- 1.1 find_filters_extern()
- 1.2 find_things_extern()
- 2. 屏幕输出信息的来源
- 2.1,查找 prefix 变量在哪里定义的?
- 2.2 函数名称: set_default
- 2.3, 查找其它变量的定义.
- 3 configure 中创建的文件具体创建过程是怎样的?
- 3.1 第一步,要找到变量定义.
- 3.2. 读懂函数代码.
- 3.3 函数名称: print_config
- 3.4 函数名称: cp_if_changed
- 3.5 函数名称: print_enabled_components
- 4 configure 对 Makefile 的影响
0. 执行./configure 命令
在家目录下创建目录t1, 把ffmpeg目录下的 configure 文件copy进去.
在 t1 目录下执行:
cd ~/t1
./configure
sed: can’t read ./libavfilter/allfilters.c: No such file or directory
sed: can’t read ./libavdevice/alldevices.c: No such file or directory
sed: can’t read ./libavdevice/alldevices.c: No such file or directory
sed: can’t read ./libavformat/allformats.c: No such file or directory
sed: can’t read ./libavformat/allformats.c: No such file or directory
sed: can’t read ./libavcodec/allcodecs.c: No such file or directory
sed: can’t read ./libavcodec/allcodecs.c: No such file or directory
sed: can’t read ./libavcodec/parsers.c: No such file or directory
sed: can’t read ./libavcodec/bitstream_filters.c: No such file or directory
sed: can’t read ./libavcodec/hwaccels.h: No such file or directory
sed: can’t read ./libavformat/protocols.c: No such file or directory
install prefix /usr/local
source path .
C compiler gcc
C library glibc
ARCH x86 (generic)
big-endian no
runtime cpu detection yes
standalone assembly yes
x86 assembler nasm
MMX enabled yes
…
运行./configure 后
会惊奇的发现在t1目录下生成了很多文件及目录.
$ tree
.
├── config.asm
├── config.h
├── configure # sh文件本身
├── doc
│ └── config.texi
├── ffbuild
│ ├── config.fate
│ ├── config.log
│ ├── config.mak
│ └── config.sh
├── libavcodec
│ ├── bsf_list.c
│ ├── codec_list.c
│ └── parser_list.c
├── libavdevice
│ ├── indev_list.c
│ └── outdev_list.c
├── libavfilter
│ └── filter_list.c
├── libavformat
│ ├── demuxer_list.c
│ ├── muxer_list.c
│ └── protocol_list.c
├── libavutil
│ └── avconfig.h
├── Makefile
└── tests
└── api
下面我们要阐明3个问题, 出错信息是从哪里来的? 屏幕打印信息从哪里来的? 输出文件是怎样生成的?
1. sed: can’t read 信息是从哪里来的 ?
对应 ./configure 3912 处代码
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)
这里我们看到是调用了2个函数:
1.1 find_filters_extern()
{file=$source_path/$1sed -n 's/^extern AVFilter ff_[avfsinkrc]\{2,5\}_\([[:alnum:]_]\{1,\}\);/\1_filter/p' $file
}
1.2 find_things_extern()
{thing=$1pattern=$2file=$source_path/$3out=${4:-$thing}sed -n "s/^[^#]*extern.*$pattern *ff_\([^ ]*\)_$thing;/\1_$out/p" "$file"
}
很简单,在控制台上执行一下sed命令就知道这些list 是什么内容了.
就是在指定的文件中查找pattern, 满足条件的行被替换内容后输出.保存到不同的变量中
由于t1目录只有一个configure 文件, 没有添加诸如 libavfilter/allfilters.c 文件,所以sed 报错了.
2. 屏幕输出信息的来源
对应 ./configure 7285 处代码. 嗯,bashdb 调试执行太慢了,不能用bashdb 调试了,
在3912设断点等一会能到达,在7285处设断点就慢的没法忍受了.只能放弃,你可以用bash -x -v ./configure 来记录执行的过程
echo “install prefix $prefix”
echo “source path $source_path”
echo “C compiler $cc”
echo “C library $libc_type”
…
2.1,查找 prefix 变量在哪里定义的?
有的变量定义是不太好找的. prefix 变量定义就是这样的.
在bash 中,变量的赋值是通过 a=b 方式进行的,如果是直接定义,可以通过字符串来查找.
但如果变量在函数中定义, 传进去的只是参数, 对参数的引用通过$i 或 $var 进行,则赋值就不能通过字符串直接查找了.
prefix在configure 代码中没有发现直接定义, 即没有prefix=xxx 形式的行.
在3755行 有 prefix_default=“/usr/local”, 与prefix 很接近.
在PATH_LIST 中有 prefix 字符串
由set_default P A T H L I S T , s e t d e f a u l t 函数引用了 PATH_LIST, set_default函数引用了 PATHLIST,setdefault函数引用了PATH_LIST变量,它设置了prefix变量, 具体过程参见函数
2.2 函数名称: set_default
输入参数: 列表
输出: 把列表作为变量名称,为其赋值.
描述: 把xxx_default变量的值送给xxx变量
set_default(){
for opt; do # 对传来的参数列表, 把其default值作为其值, 参数列表都是输出值
eval : ${$opt:=$${opt}_default}
done
}
当枚举到 $opt=prefix
则进行变量扩展后为
- eval : ‘KaTeX parse error: Expected '}', got 'EOF' at end of input: {prefix:=prefix_default}’
再执行一次 eval 命令完成赋值
赋值语句 x x x : = y y y , 当 {xxx:=yyy}, 当 xxx:=yyy,当xxx没有值或为空时,赋值给yyy, 2次扩展.
sh 脚本的难点是函数, 函数也等价于一个命令
configure 有7000多行代码, 包含180个函数, 知道了这180个函数的意思, 也就不怕configure 文件了.
关于具体的函数,以后会慢慢介绍几个关键函数.
2.3, 查找其它变量的定义.
先用grep 查找直接定义,
若找不到则可能是在函数中赋值的,如果代码不长运行较快可以用bashdb辅助查找,也可用bash -x -v输出log记录信息帮助查找
3 configure 中创建的文件具体创建过程是怎样的?
关注config.h 是怎样生成的, 顺便关注一下其它的文件
config.h
代码在7581-7628
向缓冲文件$TMPH 中打印头部信息
cat > $TMPH <<EOF
/* Automatically generated by configure - do not modify! */
#ifndef FFMPEG_CONFIG_H
#define FFMPEG_CONFIG_H
#define FFMPEG_CONFIGURATION "$(c_escape $FFMPEG_CONFIGURATION)"
#省略部分代码....
#define HAVE_MMX2 HAVE_MMXEXT
#define SWS_MAX_FILTER_SIZE $sws_max_filter_size
EOF#省略部分代码....
print_config ARCH_ "$config_files" $ARCH_LIST
print_config HAVE_ "$config_files" $HAVE_LIST
print_config CONFIG_ "$config_files" $CONFIG_LIST \$CONFIG_EXTRA \$ALL_COMPONENTS \
echo "#endif /* FFMPEG_CONFIG_H */" >> $TMPH
echo "endif # FFMPEG_CONFIG_MAK" >> ffbuild/config.makcp_if_changed $TMPH config.h
3.1 第一步,要找到变量定义.
config_files=“$TMPH ffbuild/config.mak doc/config.texi” 3个文件
ARCH_LIST=“aarch64
alpha
arm
avr32
avr32_ap
avr32_uc
bfin
ia64
m68k
mips
mips64
parisc
ppc
ppc64
s390
sh4
sparc
sparc64
tilegx
tilepro
tomi
x86
x86_32
x86_64”
ARCH_LIST 是24种cpu
3.2. 读懂函数代码.
3.3 函数名称: print_config
输入参数: $1, 前缀$2, 输出的文件名称列表$v, 是$@的枚举值, 则\${$v:-no}是其值,默认为no
输出参数: 无
描述. 对$@ 执行显示其配置值信息并通过awk 向文件列表中输出信息print_config(){pfx=$1files=$2 #文件列表shift 2map 'eval echo "$v \${$v:-no}"' "$@" |awk "BEGIN { split(\"$files\", files) } #把文件列表分割为文件{c = \"$pfx\" toupper(\$1); #c变量是前缀和第一列值(即枚举字符串)v = \$2; #v变量是 第2列值,它是yes 或者 no sub(/yes/, 1, v); # 将yes 或no 变成1和0sub(/no/, 0, v);for (f in files) { # 向文件列表中输出内容file = files[f];if (file ~ /\\.h\$/) { # .h 文件, 打印 #define xxx 1 形式printf(\"#define %s %d\\n\", c, v) >>file;} else if (file ~ /\\.asm\$/) { # .asm 文件, 打印 %%define xxx 1形式printf(\"%%define %s %d\\n\", c, v) >>file;} else if (file ~ /\\.mak\$/) { # .mak 文件, 打印xxx 或者!xxxn = -v ? \"\" : \"!\"; # 赋值n 为空或 ‘!'printf(\"%s%s=yes\\n\", n, c) >>file;} else if (file ~ /\\.texi\$/) { # .texi 文件, 打印pre@set xxx yes的形式pre = -v ? \"\" : \"@c \"; # 赋值pre为空或@c yesno = \$2;c2 = tolower(c);gsub(/_/, \"-\", c2);printf(\"%s@set %s %s\\n\", pre, c2, yesno) >>file;}}}"
}
3.4 函数名称: cp_if_changed
输入参数:$1,$2 两个文件名称
输出参数:无
函数功能: 比较2个文件$1,$2是否相同,相同给出提示 "$2 is nuchanged",返回, 不同则进行copy,不提示cp_if_changed(){ cmp -s "$1" "$2" && { test "$quiet" != "yes" && echo "$2 is unchanged"; } && returnmkdir -p "$(dirname $2)"cp -f "$1" "$2"
}
其中9个list 都是由如下命令生成
print_enabled_components libavfilter/filter_list.c AVFilter filter_list $FILTER_LIST
print_enabled_components libavcodec/codec_list.c AVCodec codec_list $CODEC_LIST
print_enabled_components libavcodec/parser_list.c AVCodecParser parser_list $PARSER_LIST
print_enabled_components libavcodec/bsf_list.c AVBitStreamFilter bitstream_filters $BSF_LIST
print_enabled_components libavformat/demuxer_list.c AVInputFormat demuxer_list $DEMUXER_LIST
print_enabled_components libavformat/muxer_list.c AVOutputFormat muxer_list $MUXER_LIST
print_enabled_components libavdevice/indev_list.c AVInputFormat indev_list $INDEV_LIST
print_enabled_components libavdevice/outdev_list.c AVOutputFormat outdev_list $OUTDEV_LIST
print_enabled_components libavformat/protocol_list.c URLProtocol url_protocols $PROTOCOL_LIST
望文生义也可以猜到,例如它从$FILTER_LIST 参数中生成libavfilter/filter_list.c 文件,
使用AVFilter,filter_list 两个关键字
3.5 函数名称: print_enabled_components
输入参数: 第一参数输出文件名, 第二参数结构名称,第三参数一个格式参考关键字,其它为模块名称作为输出文件内容
输出参数: 无
描述: 从一堆信息中,合成一个输出文件, 用printf 打印的print_enabled_components(){file=$1 #输出文件struct_name=$2 #结构名称name=$3 #名称shift 3echo "static const $struct_name * const $name[] = {" > $TMPH # 定义结构名称,向临时文件copyfor c in $*; doif enabled $c; then # 如果变量是enabled , 对输出打印case $name in # 判断输出要求什么格式, 可以进行修饰, 重新赋值给cfilter_list)eval c=\$full_filter_name_${c%_filter};;indev_list)c=${c%_indev}_demuxer;;outdev_list)c=${c%_outdev}_muxer;;esacprintf " &ff_%s,\n" $c >> $TMPH # 打印变量fidoneif [ "$name" = "filter_list" ]; thenfor c in asrc_abuffer vsrc_buffer asink_abuffer vsink_buffer; doprintf " &ff_%s,\n" $c >> $TMPHdonefiecho " NULL };" >> $TMPHcp_if_changed $TMPH $file #跟输出文件不同则copy
}
4 configure 对 Makefile 的影响
Makefile 其时是没有改变的, 但Makefile 有
include ffbuild/config.mak
参考 print_config() 函数,
它同时向3个文件
config_files="$TMPH ffbuild/config.mak doc/config.texi" 打印信息.
其中$TMPH 就是config.h的缓冲文件,
相关文章:
ffmpeg configure 研究2:分析屏幕输出及文件输出的具体过程
author: hjjdebug date: 2025年 02月 17日 星期一 16:57:55 CST description: ffmpeg configure 研究2 分析屏幕输出及文件输出的具体过程 文章目录 0. 执行./configure 命令1. sed: cant read 信息是从哪里来的 ?1.1 find_filters_extern()1.2 find_things_extern() 2. 屏幕输…...
软件内有离线模型,效果也很实用......
今天给大家带来一款超实用的图片画质增强软件,完全不需要联网,随时随地都能用。 图片画质增强 一键增强画质 使用起来也超简单,完全不需要安装。 软件主要有两个功能:图片增强和视频增强。 在使用之前,先确定一下输出…...
Linux下ioctl的应用
文章目录 1、ioctl简介2、示例程序编写2.1、应用程序编写2.2、驱动程序编写 3、ioctl命令的构成4、测试 1、ioctl简介 ioctl(input/output control)是Linux中的一个系统调用,主要用于设备驱动程序与用户空间应用程序之间进行设备特定的输入/…...
如何通过 prometheus-operator 实现服务发现
在之前的章节中,我们讲解了如何编写一个自定义的 Exporter,以便将指标暴露给 Prometheus 进行抓取。现在,我们将进一步扩展这个内容,介绍如何使用 prometheus-operator 在 Kubernetes 集群中自动发现并监控这些暴露的指标。 部署应用 在 Kubernetes 集群中部署我们的自定…...
认识HTML的标签结构
一、HTML的基本概念 1.什么是HTML? ①HTML是描述网页的一种标记语言,也被称为超文本标记语言【并不是一种编程语言】 ②HTML包含了HTML标签和文本内容 ③HTML文档也称为web页面 2.HTML的标签 HTML的标签通常成对出现,HTML文档由标签和受…...
MySQL 之INDEX 索引(Index Index of MySQL)
MySQL 之INDEX 索引 1.4 INDEX 索引 1.4.1 索引介绍 索引:是排序的快速查找的特殊数据结构,定义作为查找条件的字段上,又称为键 key,索引通过存储引擎实现。 优点 大大加快数据的检索速度; 创建唯一性索引,保证数…...
基于flask+vue的租房信息可视化系统
✔️本项目利用 python 网络爬虫抓取某租房网站的租房信息,完成数据清洗和结构化,存储到数据库中,搭建web系统对各个市区的租金、房源信息进行展示,根据各种条件对租金进行预测。 1、数据概览 将爬取到的数据进行展示ÿ…...
开源Web主机控制面板ISPConfig配置DNS
ISPConfig 是一个开源的 Web 主机控制面板,特别适合用于构建虚拟主机环境。 它拥有强大的 DNS 管理功能,可以: 管理 DNS 区域 (主区域、辅助区域)。支持多种记录类型。DNSSEC 支持。远程 DNS 服务器管理。 ISPConfig 优点在于专为主机服务设…...
【Python项目】信息安全领域中语义搜索引擎系统
【Python项目】信息安全领域中语义搜索引擎系统 技术简介:采用Python技术、MYSQL数据库等实现。 系统简介:系统主要是围绕着语义搜索展开的,要将输入的文字在爬取数据时能够通过深层次的内涵理解,来更好的查找到与之相关的精准信息…...
网站搭建基本流程
需求分析: 实现网站搭建的过程:首先进行网站的需求性分析 网站可分为前台系统和后台系统,由不同的功能拆分为不同的模块 如下是一个电商网站可以拆分出的模块: 在编写代码前,我们要先对网站进行架构,通过…...
mysql 存储空间增大解决方案
一:查询数据库中表占比比较多的表 SELECT table_name AS "Tables", round(((data_length index_length) / 1024 / 1024), 2) AS "Size (MB)" FROM information_schema.tables WHERE table_schema "自己的数据库名"; …...
深入解析队列与广度优先搜索(BFS)的算法思想:原理、实现与应用
目录 1. 队列的基本概念 2. 广度优先搜索(BFS)的基本概念 3. 队列在BFS中的作用 4. BFS的实现细节 5. C实现BFS 6. BFS的应用场景 7. 复杂度分析 8. 总结 1. 队列的基本概念 队列(Queue)是一种先进先出(FIFO, …...
Swap to Gather-----
C - 烟销日出不见人 问题陈述 给定一个长度为 NN 的字符串 SS,由 0 和 1 组成。保证 SS 至少包含一个 1。 您可以执行以下操作任意次数(可能为零): 选择一个整数 ii (1≤i≤N−11≤i≤N−1),并交换 SS 的第 ii 个和…...
使用DeepSeek+本地知识库,尝试从0到1搭建高度定制化工作流(自动化篇)
7.5. 配图生成 目的:由于小红书发布文章要求图文格式,因此在生成文案的基础上,我们还需要生成图文搭配文案进行发布。 原实现思路: 起初我打算使用deepseek的文生图模型Janus进行本地部署生成,参考博客:De…...
Python 函数式编程全攻略:从理论到实战的深度解析
本文深入剖析 Python 函数式编程,详细讲解其概念、核心特性(迭代器、生成器等)、内置函数及相关模块(itertools、functools ),结合丰富示例与直观图表,助力读者全面掌握函数式编程技巧ÿ…...
Ollama 在 LangChain 中的使用
文章目录 一、langChain 介绍二、环境安装1.依赖库安装2.下载模型 三、基本使用示例1.使用 ChatPromptTemplate 进行对话2.流式输出3.工具调用4.多模态模型调用 四、进阶使用1.使用 ConversationChain 进行对话2.自定义提示模板3.构建一个简单的 RAG 问答系统 五、遇到问题与解…...
使用apt-rdepends制作软件离线deb安装包
使用apt-rdepends制作软件离线deb安装包 除基础软件外,还要获取软件依赖包。 依赖包工具安装 apt-get install apt-rdependsapt-rdepends工具使用 使用apt-rdepends工具,递归方式分析软件依赖,下载软件包本体,和依赖包。制作时…...
根据POD名称生成 三部曲:get、describe、log、exec
#!/bin/bash# 定义颜色变量 RED\033[0;31m GREEN\033[0;32m YELLOW\033[0;33m NC\033[0m # No Color# 检查是否传入 Pod 名称作为参数 if [ -z "$1" ]; then# 如果没有传参,则提示用户输入 Pod 名称echo -e "${YELLOW}Please enter the Pod name:${…...
SQL sever数据导入导出实验
1.创建数据库TCP-H (1)右键“数据库”,点击“新建数据库”即可 (2)用sql语言创建,此处以创建数据库DB_test为例,代码如下: use master;go--检查在当前服务器系统中的所有数据里面…...
python环境的yolov11.rknn物体检测
1.首先是我手里生成的一个yolo11的.rknn模型: 2.比对一下yolov5的模型: 2.1 yolov5模型的后期处理: outputs rknn.inference(inputs[img2], data_format[nhwc])np.save(./onnx_yolov5_0.npy, outputs[0])np.save(./onnx_yolov5_1.npy, outpu…...
docker详细操作--未完待续
docker介绍 docker官网: Docker:加速容器应用程序开发 harbor官网:Harbor - Harbor 中文 使用docker加速器: Docker镜像极速下载服务 - 毫秒镜像 是什么 Docker 是一种开源的容器化平台,用于将应用程序及其依赖项(如库、运行时环…...
镜像里切换为普通用户
如果你登录远程虚拟机默认就是 root 用户,但你不希望用 root 权限运行 ns-3(这是对的,ns3 工具会拒绝 root),你可以按以下方法创建一个 非 root 用户账号 并切换到它运行 ns-3。 一次性解决方案:创建非 roo…...
【HarmonyOS 5 开发速记】如何获取用户信息(头像/昵称/手机号)
1.获取 authorizationCode: 2.利用 authorizationCode 获取 accessToken:文档中心 3.获取手机:文档中心 4.获取昵称头像:文档中心 首先创建 request 若要获取手机号,scope必填 phone,permissions 必填 …...
【C++特殊工具与技术】优化内存分配(一):C++中的内存分配
目录 一、C 内存的基本概念 1.1 内存的物理与逻辑结构 1.2 C 程序的内存区域划分 二、栈内存分配 2.1 栈内存的特点 2.2 栈内存分配示例 三、堆内存分配 3.1 new和delete操作符 4.2 内存泄漏与悬空指针问题 4.3 new和delete的重载 四、智能指针…...
嵌入式常见 CPU 架构
架构类型架构厂商芯片厂商典型芯片特点与应用场景PICRISC (8/16 位)MicrochipMicrochipPIC16F877A、PIC18F4550简化指令集,单周期执行;低功耗、CIP 独立外设;用于家电、小电机控制、安防面板等嵌入式场景8051CISC (8 位)Intel(原始…...
上位机开发过程中的设计模式体会(1):工厂方法模式、单例模式和生成器模式
简介 在我的 QT/C 开发工作中,合理运用设计模式极大地提高了代码的可维护性和可扩展性。本文将分享我在实际项目中应用的三种创造型模式:工厂方法模式、单例模式和生成器模式。 1. 工厂模式 (Factory Pattern) 应用场景 在我的 QT 项目中曾经有一个需…...
6️⃣Go 语言中的哈希、加密与序列化:通往区块链世界的钥匙
Go 语言中的哈希、加密与序列化:通往区块链世界的钥匙 一、前言:离区块链还有多远? 区块链听起来可能遥不可及,似乎是只有密码学专家和资深工程师才能涉足的领域。但事实上,构建一个区块链的核心并不复杂,尤其当你已经掌握了一门系统编程语言,比如 Go。 要真正理解区…...
解析两阶段提交与三阶段提交的核心差异及MySQL实现方案
引言 在分布式系统的事务处理中,如何保障跨节点数据操作的一致性始终是核心挑战。经典的两阶段提交协议(2PC)通过准备阶段与提交阶段的协调机制,以同步决策模式确保事务原子性。其改进版本三阶段提交协议(3PC…...
书籍“之“字形打印矩阵(8)0609
题目 给定一个矩阵matrix,按照"之"字形的方式打印这个矩阵,例如: 1 2 3 4 5 6 7 8 9 10 11 12 ”之“字形打印的结果为:1,…...
图解JavaScript原型:原型链及其分析 | JavaScript图解
忽略该图的细节(如内存地址值没有用二进制) 以下是对该图进一步的理解和总结 1. JS 对象概念的辨析 对象是什么:保存在堆中一块区域,同时在栈中有一块区域保存其在堆中的地址(也就是我们通常说的该变量指向谁&…...
