ffmpeg视频云转拉过程中耗时分析与优化

故事的背景是这样的:

在整个视频云的流程中(对于冷流整个流程是比较多的),其中有一个环节是转拉。转拉就是从源站拉流,然后推流到目的服务器上的过程。转拉的技术方案是有多种的,此处我们选择的是用ffmpeg来进行转拉。该环节在优化前的耗时在1.7s以上,经过优化后,目前大概耗时在600+ms左右。值得说明的是,此处的耗时是开始启动ffmpeg到最后和目的站建立连接的过程。

过程分析:

既然是要进行时间的优化,那么首先肯定需要知道ffmpeg中每个调用环节的耗时。首先我们分析下ffmpeg源码。需要说明的是下图的流程只是ffmpeg.c源码中的一小部分,且ffmpeg的版本为3.4.3. 不同的版本可能存在细微的差别。此外,我们主要的优化是从和源站建链到和目的站建连的过程。所以下图的分析虽然不够全,但是对于本次的分析已经足够了。关于更多的ffmpeg源码分析,请参考本文末尾所贴的参考文献链接。

图1, ffmpeg.c 部分源码

从main函数进入,到最后和目的站建立连接,主要是两块函数的调用,av***_register_all 和 ffmpeg_parse_option. 之所以强调了register函数,是因为ffmpeg编译的时候,decoder,encoder以及filter等等都是可选的。不同的编译参数编译出来的ffmpeg大小是不同。 初始的时候,我们以为减小ffmpeg编出来的大小,会有助于加快转拉的速度,事实上并没有。register函数做的事情挺简单的,主要是往链表后面追加一点点的数据,执行过程是非常快的,几乎可以忽略。

那么我们的重点自然就到了ffmpeg_parse_option这个函数中了。这个函数的作用就是解析我们的命令行参数。然后调用open_file函数,分别打开输入文件和输出文件。通过逐步打日志,我们发现,整个耗时主要就集中在两个函数:avformat_open_input和avformat_find_stream_info。其中avformat_open_input 函数的调用相对简单,主要是调动avio_open2与源站建立连接耗时比较严重。通过大量的转拉案例,我们发现,正常情况下,这个建链的过程几十毫秒就能完成。但是建链这个过程主要是网络的相关,在ffmpeg层面可改动优化的空间并不大。所以这里也没过多进行优化,实际上如果想优化,也是有一定的优化空间的。打日志发现,init_input中除了avio_open2耗时之外,av_prob_input_buffer2偶尔也会比较耗时,通过这个函数名字我们也可以知道,既然是探测,当然是可以缩短一些探测的时间的。这里不做深入的讨论,因为大量例子发现,多数时候,avformat_open_input建立连接都是很快的。

事实上最耗时且可优化的是avfomat_find_stream_info函数。

图2, avforamt_find_stream_info函数源码

查看源码可以发现,在avformat_find_stream_info中有个无限循环,该函数的调用耗时也主要是在这个循环里面。这个函数里面会调用read_frame_internal 与 try_decode_frame 进行一些分析和探测,当达到某种条件的时候,就会break,跳出循环。其实我们可以逐个分析循环中break的地方, 如果循环能够尽早break掉,那自然就会减少整个循环的调用时间了。

1) ff_check_interrupt 导致的break。 这个地方显然从代码层面上,没啥可进行改动的。

2) 如下图,有header信息,并且所有的流都解析到了退出。

图3 for(;;)

3)读取数据的大小达到上限,需要说明的是probsize这个值是可配的。命令行参数中指定 -probsize 就行,或者在options_table中avformat_options[]数组中直接设置默认值也是可以的。

图4, for(;;)

4)分析的时间音视频帧时间戳达到了上限,这里的时间上限值也是可设置的。可以命令行指定 -analyzeduration参数,或者options_table.h中设置默认值。

图5, for(;;)

对于第三四处的break, 其实意思是相同的。但是简单的将上限值缩小是不可取的。主要是两方面的原因:1)测试发现,循环并不是因为达到了上限值才退出的;2)通过缩小上限值退出循环,可能导致本来是音视频两条流的,最后推出去的流只有一路。这个情况在某个客户的转拉的过程中就出现了。该客户源站吐流前面几秒钟都是音频数据,并且header信息里面也没有视频帧,当达到阈值退出时。可能只分析到了音频帧,以至于后面即使来了是视频帧,ffmpeg也会将其丢弃,最后导致推到目的站的流是纯音频的。

到此也可以猜到了,我们的改动主要在第二处break处了了。图2中,有个变量,fps_analyze_frame_count,我们可以看到默认值为20,并且这个for循环里面还有注释,"检查一个编解码器时候还需要被处理",这个变量即使从变量名也能猜到他是要干嘛的——分析帧的数量。这个默认值是比较大的,特别是对于我们的直播转拉环节。所以在此我们适当的减小了这个值。在实际项目中,在确定了有两条流的情况下,我们将音频帧的分析帧数设置为10,视频帧设置为2. 当然这个值的选择参考意义可能不是特别大。用户可以根据不同的需求,自己设置,然后进行测试。

至此,本次分析就差不都结束了。下面展示下实验的结果。

测试结果

测试结果记录了优化前后,每次转拉的平均耗时。因为刚开始是在一台正式环境上测试的,所以数据量有限,另外由于我们的重点是关注优化后的数据,所以优化前相较于优化后的转拉次数是比较少的。

优化前的数据

图6, 优化前的结果

图6是优化前的转拉耗时,总共有记录590条,此处只截图了其中50条记录。图中总共有4列数据时间,单位都是ms。第一列是调用avformat_open_input的耗时,第二列是调用avformat_find_stream_info的耗时,第三列是从和源站建立连接到和目的站建立连接的耗时,即两个avio_open2之间的调用间隔,第四列是从main函数开始到调用与目的站建立连接的avio_open2函数的耗时。可以看到大部分总体耗时都是在几百毫秒内,偶尔会有几个耗时比较多的。

图7, 优化前平均耗时统计

通过对着590条转拉记录统计平均值,我们发现大概在1700+ms。

优化后的数据

图8, 优化后的结果

同样我们也贴上优化后的50次转拉耗时,第一列是流id,可以不管。后面的4列和优化前的4列一一对应。

图9, 优化后平均耗时统计

这些数据是目前一台线上机器上的数据,因为本次优化已经上线了几天了,所以数据相对来说多点,有24000+条数据,平均耗时612ms左右。我登录了几台线上的机器,统计发现差不多都是在 600+ms左右。

整片文章到此就算完结了

参考文献

https://blog.csdn.net/leixiaohua1020/article/details/39760711

原创声明,本文系作者授权云+社区发表,未经许可,不得转载。

如有侵权,请联系 yunjia_community@tencent.com 删除。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏大数据人工智能

ZStack--工作流引擎

在IaaS软件中的任务通常有很长的执行路径,一个错误可能发生在任意一个给定的步骤。为了保持系统的完整性,一个IaaS软件必须提供一套机制用于回滚先前的操作步骤。...

4564
来自专栏小石不识月

微服务编排

在 Jexia 中,我们相信微服务架构是组织我们的后端云的最佳方式 —— 它可以很好地进行关注分离(Separation of concerns),并为特定任务...

5689
来自专栏游戏杂谈

【转】Android开发在路上:少去踩坑,多走捷径

本文是我订阅“腾讯大讲堂”公众帐号时,他们推送的一篇文章,但在腾讯大讲堂官网上我并没有找到这篇文章,不过其它专门“爬”公众号文章的网站倒是有。我觉得写的很不错。...

1043
来自专栏野路子程序员

徒手解剖composer,简单了解其实现过程

2856
来自专栏黑白安全

ASLRay:一个可以绕过ASLR的工具

ASLR(Address Space Layout Randomization,即地址空间格局随机化)是指利用随机方式配置数据地址,一般现代系统中都加设这一机制...

601
来自专栏林冠宏的技术文章

Android 5.0 到 Android 6.0 + 的深坑之一 之 .so 动态库的适配

(原创:https://cloud.tencent.com/developer/user/1148436/activities) 目录:   前序   一,问题...

30010
来自专栏FreeBuf

ASLRay:一个可以绕过ASLR的工具

ASLR(Address Space Layout Randomization,即地址空间格局随机化)是指利用随机方式配置数据地址,一般现代系统中都加设这一机制...

2218
来自专栏张善友的专栏

Google SiteMap Protocol协议

在新浪看到这样的新闻Google雅虎微软联手支持网页手工提交标准, Google、微软和雅虎认为,统一标准有助于从整体上改进站点地图,从而搜索引擎可以将更广泛的...

21610
来自专栏SAP最佳业务实践

想学FM系列(15)-SAP FM模块:预算结构(6)-预算结构操作-过账地址维护

3.2.2.2 过账地址维护 ? 1)FMBSPO - 单个处理 功能:手工维护记账地址 ? 过账分类账:如果使用的是9F付款预算则选则9A,如果使用的是...

4546
来自专栏贾鹏辉的技术专栏@CrazyCodeBoy

INSTALL FAILED CONFLICTING PROVIDER问题完美解决方案

尊重版权,未经授权不得转载 本文出自:贾鹏辉的技术博客(http://www.devio.org) ? 在安装Android应用时出现INSTALL F...

3517

扫码关注云+社区