使用egypt+graphviz分析ffplay的函数调用关系图

在《Ffplay视频播放流程》文章中我给出了一个ffplay的函数调用关系图,在分析代码上会有不小的帮助。那么本文就详细的描述如何从源码中一步步的得到我们想要的函数调用关系图。

前置条件

下载ffmpeg源码

安装graphviz:sudo>http://www.gson.org/egypt/

编译整个ffmepg

我采用的是默认配置+直接编译的方式,即./configure &&>ffmpeg$ makeCC ffplay.oLD ffplay_gCP ffplaySTRIP ffplay
我们从上述输出中可以看到,编译ffplay主要有四步:编译(CC),链接(LD),重命名(CP),去除符号表操作(STRIP),其中编译阶段是我们重点要分析的,因为编译是对源码的直接分析和处理。

生成RTL文件

确定了需要在编译ffplay的步骤后,我们在makefile中找到具体的编译函数:

define COMPILE
       $(call $(1)DEP,$(1))
       $($(1)) $($(1)FLAGS) $($(1)_DEPFLAGS) $($(1)_C) $($(1)_O) $<
endef

因为是编译ffplay.c文件,即此处的$(1)指的是CC,对应的$($(1)FLAGS)就是$(CCFLAGS),而CCFLAGS的定义中包含$(CFLAGS),即按照 egypt 中的说明,我们在$(CFLAGS)的定义中添加-fdump-rtl-expand参数即可在make的时候成成RTL文件:

CFLAGS     += $(ECFLAGS) -fdump-rtl-expand
并且在COMPILE函数中将$($(1)FLAGS)的值打印出来,那么再次修改ffplay.c并编译后的输出如下:

-I. -I./ -D_ISOC99_SOURCE -D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE -D_POSIX_C_SOURCE=200112 -D_XOPEN_SOURCE=600 -std=c99 -fomit-frame-pointer -pthread -D_GNU_SOURCE=1 -D_REENTRANT -I/usr/include/SDL -g -Wdeclaration-after-statement -Wall -Wno-parentheses -Wno-switch -Wno-format-zero-length -Wdisabled-optimization -Wpointer-arith -Wredundant-decls -Wno-pointer-sign -Wwrite-strings -Wtype-limits -Wundef -Wmissing-prototypes -Wno-pointer-to-int-cast -Wstrict-prototypes -O3 -fno-math-errno -fno-signed-zeros -fno-tree-vectorize -Werror=implicit-function-declaration -Werror=missing-prototypes -Werror=return-type -Werror=vla  -fdump-rtl-expand -D_GNU_SOURCE=1 -D_REENTRANT -I/usr/include/SDL
CC	ffplay.o
LD	ffplay_g
CP	ffplay
STRIP	ffplay

并且在当前目录下生成ffplay.c.144r.expand文件,即我们需要的RTL文件。

生成DOT文件

生成完RTL文件后,我们可以使用现成的一个工具来分析它:egypt,具体命令如下:

egypt ffplay.c.144r.expand > ffplay.dot

生成函数调用图

有了dot文件,使用graphviz提供的工具就可以直接生成图形了:

dot ffplay.dot -Tpng -o ffplay.png
其中ffplay.dot是输入文件,-Tpng表示生成png格式的文件,-o>

文件有点大,请自行保存下来进行查看。

ffplay调用流程图

去除编译优化

这个图看上去有些奇怪,比如在main函数中非常显眼的event_loop函数,哪里去了呢?

神奇之处就在于CFLAYGS中的-O3参数,gcc的man手册中如是说:

[plain]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. -O3 Optimize yet more.  -O3 turns on all optimizations specified by -O2  
  2.     and also turns on the -finline-functions, -funswitch-loops,  
  3.     -fpredictive-commoning, -fgcse-after-reload, -ftree-vectorize and  
  4.     -fipa-cp-clone options.  
我们发现-O3是在-O2优化的基础上,又添加了一系列的优化参数。那么同理,-O2优化肯定也是在-O1优化基础上新增一些优化参数。

因此,为了保持生成的RTL文件和源代码保持一致性,我们去除所有的编译优化选项,即在config.mak文件中,从CFLAGS定义中删除-O3字符串:

[plain]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. CFLAGS=   -std=c99 -fomit-frame-pointer -pthread -D_GNU_SOURCE=1 -D_REENTRANT -I/usr/include/SDL -g -Wdeclaration-after-statement -Wall -Wno-parentheses -Wno-switch -Wno-format-zero-length -Wdisabled-optimization -Wpointer-arith -Wredundant-decls -Wno-pointer-sign -Wwrite-strings -Wtype-limits -Wundef -Wmissing-prototypes -Wno-pointer-to-int-cast -Wstrict-prototypes <span style="color:#FF0000;"><del>-O3 </del></span>-fno-math-errno -fno-signed-zeros -fno-tree-vectorize -Werror=implicit-function-declaration -Werror=missing-prototypes -Werror=return-type -Werror=vla  
然后重新修改编译ffplay.c,并生成RTL文件和png图片。生成的图形如下:

未优化的函数调用流程图

哇塞,通过这两个图形对比,我们发现编译优化选项做了多大的工作啊,或者说原始代码为了可阅读行,是多么的烂啊!

手动调整

未优化的函数调用关系图太复杂了,在分析问题时,感觉有些老虎吃刺猬无处下嘴啊!

那么我们就可以手动打开刚才处理RTL后生成的dot文件,比如去除一些孤立的点,去除一些细节处理等等。最后,我们得到一个比较概要的函数调用关系图。

函数调用关系概要图

PS:和上述图片对应的dot文件如下:

http://download.csdn.net/detail/nfer_cn/6772321

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
以下是使用HTML绘制气泡的示例代码,展示了15个国家的GDP和人口之间的关系: ```html <!DOCTYPE html> <html> <head> <title>Bubble Chart Example</title> <style> .chart { width: 600px; height: 400px; margin: 0 auto; position: relative; } .chart .country { position: absolute; display: inline-block; width: 10px; height: 10px; border-radius: 50%; background-color: #0077CC; opacity: 0.8; transition: all 0.3s ease-in-out; cursor: pointer; } .chart .country:hover { transform: scale(1.5); opacity: 1; } .chart .country[data-country="China"] { left: 20%; top: 50%; width: 50px; height: 50px; } .chart .country[data-country="India"] { left: 40%; top: 30%; width: 30px; height: 30px; } .chart .country[data-country="United States"] { left: 60%; top: 20%; width: 40px; height: 40px; } .chart .country[data-country="Indonesia"] { left: 70%; top: 50%; width: 20px; height: 20px; } .chart .country[data-country="Pakistan"] { left: 30%; top: 60%; width: 15px; height: 15px; } .chart .country[data-country="Brazil"] { left: 50%; top: 70%; width: 25px; height: 25px; } .chart .country[data-country="Nigeria"] { left: 80%; top: 70%; width: 18px; height: 18px; } .chart .country[data-country="Bangladesh"] { left: 10%; top: 20%; width: 12px; height: 12px; } .chart .country[data-country="Russia"] { left: 30%; top: 10%; width: 35px; height: 35px; } .chart .country[data-country="Japan"] { left: 60%; top: 50%; width: 28px; height: 28px; } .chart .country[data-country="Mexico"] { left: 30%; top: 40%; width: 22px; height: 22px; } .chart .country[data-country="Philippines"] { left: 80%; top: 40%; width: 14px; height: 14px; } .chart .country[data-country="Ethiopia"] { left: 70%; top: 20%; width: 16px; height: 16px; } .chart .country[data-country="Egypt"] { left: 50%; top: 10%; width: 30px; height: 30px; } .chart .country[data-country="Vietnam"] { left: 40%; top: 70%; width: 18px; height: 18px; } </style> </head> <body> <div class="chart"> <div class="country" data-country="China" title="China GDP: $14.14T, Population: 1.39B"></div> <div class="country" data-country="India" title="India GDP: $2.94T, Population: 1.34B"></div> <div class="country" data-country="United States" title="United States GDP: $21.44T, Population: 0.33B"></div> <div class="country" data-country="Indonesia" title="Indonesia GDP: $1.15T, Population: 0.27B"></div> <div class="country" data-country="Pakistan" title="Pakistan GDP: $0.31T, Population: 0.22B"></div> <div class="country" data-country="Brazil" title="Brazil GDP: $2.05T, Population: 0.21B"></div> <div class="country" data-country="Nigeria" title="Nigeria GDP: $0.45T, Population: 0.20B"></div> <div class="country" data-country="Bangladesh" title="Bangladesh GDP: $0.31T, Population: 0.16B"></div> <div class="country" data-country="Russia" title="Russia GDP: $1.64T, Population: 0.14B"></div> <div class="country" data-country="Japan" title="Japan GDP: $5.15T, Population: 0.13B"></div> <div class="country" data-country="Mexico" title="Mexico GDP: $1.27T, Population: 0.13B"></div> <div class="country" data-country="Philippines" title="Philippines GDP: $0.31T, Population: 0.10B"></div> <div class="country" data-country="Ethiopia" title="Ethiopia GDP: $0.10T, Population: 0.10B"></div> <div class="country" data-country="Egypt" title="Egypt GDP: $0.30T, Population: 0.10B"></div> <div class="country" data-country="Vietnam" title="Vietnam GDP: $0.24T, Population: 0.10B"></div> </div> </body> </html> ``` 上述代码中,我们使用了一个包含15个国家的气泡。每个国家都用一个带有 `country` 类名的 div 元素表示,同时使用 `data-country` 属性指定了国家名称,`title` 属性指定了国家的GDP和人口信息。 我们通过CSS设置每个国家的位置、大小、颜色等属性,使它们按照GDP和人口之间的关系呈现出不同的大小和颜色。同时,我们还使用了 CSS 动画效果来使鼠标悬停在某个国家上时它放大并变得更加明显。 你可以将上述代码复制到一个 HTML 文件中并在浏览器中打开,以查看最终效果。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值