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…...

接口测试中缓存处理策略
在接口测试中,缓存处理策略是一个关键环节,直接影响测试结果的准确性和可靠性。合理的缓存处理策略能够确保测试环境的一致性,避免因缓存数据导致的测试偏差。以下是接口测试中常见的缓存处理策略及其详细说明: 一、缓存处理的核…...
【Java学习笔记】Arrays类
Arrays 类 1. 导入包:import java.util.Arrays 2. 常用方法一览表 方法描述Arrays.toString()返回数组的字符串形式Arrays.sort()排序(自然排序和定制排序)Arrays.binarySearch()通过二分搜索法进行查找(前提:数组是…...
大语言模型如何处理长文本?常用文本分割技术详解
为什么需要文本分割? 引言:为什么需要文本分割?一、基础文本分割方法1. 按段落分割(Paragraph Splitting)2. 按句子分割(Sentence Splitting)二、高级文本分割策略3. 重叠分割(Sliding Window)4. 递归分割(Recursive Splitting)三、生产级工具推荐5. 使用LangChain的…...

转转集团旗下首家二手多品类循环仓店“超级转转”开业
6月9日,国内领先的循环经济企业转转集团旗下首家二手多品类循环仓店“超级转转”正式开业。 转转集团创始人兼CEO黄炜、转转循环时尚发起人朱珠、转转集团COO兼红布林CEO胡伟琨、王府井集团副总裁祝捷等出席了开业剪彩仪式。 据「TMT星球」了解,“超级…...

k8s业务程序联调工具-KtConnect
概述 原理 工具作用是建立了一个从本地到集群的单向VPN,根据VPN原理,打通两个内网必然需要借助一个公共中继节点,ktconnect工具巧妙的利用k8s原生的portforward能力,简化了建立连接的过程,apiserver间接起到了中继节…...

回溯算法学习
一、电话号码的字母组合 import java.util.ArrayList; import java.util.List;import javax.management.loading.PrivateClassLoader;public class letterCombinations {private static final String[] KEYPAD {"", //0"", //1"abc", //2"…...

短视频矩阵系统文案创作功能开发实践,定制化开发
在短视频行业迅猛发展的当下,企业和个人创作者为了扩大影响力、提升传播效果,纷纷采用短视频矩阵运营策略,同时管理多个平台、多个账号的内容发布。然而,频繁的文案创作需求让运营者疲于应对,如何高效产出高质量文案成…...

自然语言处理——文本分类
文本分类 传统机器学习方法文本表示向量空间模型 特征选择文档频率互信息信息增益(IG) 分类器设计贝叶斯理论:线性判别函数 文本分类性能评估P-R曲线ROC曲线 将文本文档或句子分类为预定义的类或类别, 有单标签多类别文本分类和多…...

Qt的学习(一)
1.什么是Qt Qt特指用来进行桌面应用开发(电脑上写的程序)涉及到的一套技术Qt无法开发网页前端,也不能开发移动应用。 客户端开发的重要任务:编写和用户交互的界面。一般来说和用户交互的界面,有两种典型风格&…...
简单介绍C++中 string与wstring
在C中,string和wstring是两种用于处理不同字符编码的字符串类型,分别基于char和wchar_t字符类型。以下是它们的详细说明和对比: 1. 基础定义 string 类型:std::string 字符类型:char(通常为8位)…...