首页
题库
公司真题
专项练习
面试题库
在线编程
面试
面试经验
AI 模拟面试
简历
求职
学习
基础学习课
实战项目课
求职辅导课
专栏&文章
竞赛
我要招人
发布职位
发布职位、邀约牛人
更多企业解决方案
AI面试、笔试、校招、雇品
HR免费试用AI面试
最新面试提效必备
登录
/
注册
白竹dragonsakura
Monash University 研发工程师
发布于上海
关注
已关注
取消关注
@爱吃萝卜炖土豆:
3个重点,20个函数分析,浅析FFmpeg转码过程
写在前面 最近在做和转码有关的项目,接触到ffmpeg这个神器。从一开始简单的写脚本直接调用ffmpeg的可执行文件做些转码的工作,到后来需要写程序调用ffmpeg的API。虽然上网搜了别人的demo稍微改改顺利完成了工作,但是对于ffmpeg这个黑盒子,还是有些好奇心和担心(项目中使用不了解的代码总是不那么放心),于是抽空翻了翻ffmpeg的源码,整理成文章给大家分享分享。 由于我并非做音频出身,对于音频一窍不通。ffmpeg整个也非常庞大,所以这篇文章从ffmpeg提供的转码的demo开始,侧重于讲清楚整个输入->转码->输出的流程,并学习ffmpeg如何做到通用和可扩展性。 注:本文基于ffmpeg提供的transcode_aac.c样例。 三个重点 转码的过程是怎么样的?简单来说就是从输入读取数据,解析原来的数据格式,转成目标数据格式,再将最终数据输出。这里就涉及到三个<stron>:数据输入和输出方式,数据的编码方式及数据的容器格式(容器是用来区分不同文件的数据类型的,而编码格式则由音视频的压缩算法决定,一般所说的文件格式或者后缀名指的就是文件的容器。对于一种容器,可以包含不同编码格式的一种视频和音频)。</stron> ffmpeg是一个非常非常通用的工具,支持非常广的数据输入和输出,包括:hls流,文件,内存等,支持各类数据编码格式,包括:aac,mp3等等,同时支持多种容器格式,包括ts,aac等。另外ffmpeg是通过C语言实现的,如果是C++,我们可以通过继承和多态来实现。定义一个IO的基类,一个Format的基类和一个Codec的基类,具体的输入输出协议继承IO基类实现各自的输入输出方法,具体的容器格式继承Format基类,具体的编码格式继承Codec基类。这篇文章也会简单讲解ffmpeg如何用C语言实现类似C++的继承和多态。 基本数据结构 ffmpeg转码中最基本的结构为AVFormatContext和AVCodecContext。AVCodecContext负责编码,AVFormatContext负责IO和容器格式。 我从AVFormatContext类抽离出三个基本的成员iformat,oformat,pb。分别属于AVInputFormat,AVOutputFormat,AVIOContext类。iformat为输入的数据格式,oformat为输出的数据格式,pb则负责输入输出。 我把这三个类的定义抽离了出来简化了下,可以看出AVInputFormat声明了read_packet方法,AVOutputFormat声明了write_packet方法,AVIOContext声明了read_packet, write_packet方法。同时AVInputFormat和AVOutputFormat还有一个成员变量name用以标识该格式的后缀名。 下一节我们会看到Input/OutputForm的read/write packet方法和IOContext的关系。 输入函数调用图 下面是初始化输入的整个过程的函数调用图。 首先从调用open_input_file开始,首先解析输入的protocol。avio_open2函数会调用一系列helper函数(ffurl_open,ffio_fdopen)分析输入的协议,设置AVFormatContext的pb变量的read_packet方法。而av_probe_input_buffer2函数则会分析输入文件的格式(从文件名解析或输入数据做判断),设置AVFormatContext的iformat的read_packet方法。 两个read_packet有什么关系呢?第二个函数调用图可以看出,iformat的read_packet最终会调用pb的read_packet方法。意思就是数据本身由pb的read_packet方法来读取,而iformat则会在输入的数据上做些格式相关的解析操作(比如解析输入数据的头部,提取出输入数据中真正的音频/视频数据,再加以转码)。 IO相关代码 直接看上面的图不太直观,这一节我把源码中各个步骤截图下来进行分析。 转码开始步骤,调用open_input_file函数,传入文件名。 avformat_open_input函数会调用init_input()来处理输入文件。 init_input函数主要做两个事情,一是解析输入协议(如何读取数据?hls流?文件?内存?),二是解析输入数据的格式(输入数据为aac?ts?m4a?) avio_open2函数首先调用ffurl_open函数,根据文件名来推断所属的输入协议(URLProtocol)。之后再调用ffio_fdopen设置pb的read_packet方法。 上面几段代码的逻辑为:根据文件名查找对应的URLProtocol->把该URLProtocol赋值给URLContext的prot成员变量->创建AVIOContext实例,赋值给AVFormatContext的pb成员变量。 这里设置了AVIOContext实例的read_packet为ffurl_read方法。 ffurl_read方法其实就是调用URLContext的prot(上面赋值的)的url_read方法。通过函数指针去调用具体的URLContext对象的prot成员变量的url_read方法。 接下来看看解析输入数据格式的代码。av_probe_input_buffer2函数调用av_probe_input_format2函数来推断数据数据的格式。从之前的图我们知道*fmt其实就是&s->iformat。因此这里设置了AVFormatContext的iformat成员变量。 至此AVFormatContext对象的iformat和pb成员变量就设置好了。接下来看看如何读取输入开始转码。 av_read_frame函数调用read_frame_internal函数开始读取数据。 read_frame_internal会调用ff_read_packet,后者最终调用的是iformat成员变量的read_packet方法。 拿aac举例,aac的read_packet方法实际上是ff_raw_read_partial_packet函数。 ff_raw_read_partial_packet会调用ffio_read_partial,后者最终调用的是AVFormatContext的pb成员变量的read_packet方法。而我们知道pb成员的read_packet其实就是ffurl_read,也就是具体输入URLProtocl的read_packet方法。 至此已经走完了整个输入的流程,输出也是类似的代码,这里就不再赘述。 转码函数调用图 上面关于IO的介绍我从输入的角度进行分析。接下来的转码过程我则从输出的角度进行分析。下图是转码过程的函数调用图(做了简化)。load_encode_and_write调用encode_audio_frame, encode_audio_frame调用avcodec_encode_audio2来做实际的编码工作,最后调用av_write_frame将编码完的数据写入输出。 转码相关代码 首先需要设置输出目标编码格式,下面的代码为设置编码格式(aac)的片段: 在这里设置了output_codec_context(AVCodecContext类对象)之后,从前面的函数调用图,我们知道是avcodec_encode_audio2函数执行的转码过程: 这里看到调用了avctx(AVCodecContext类对象)的codec(AVCodec类对象)成员变量的encode2方法去做编码操作。 转码这里专业性比较强,我并没有细读,因此这里简单带过。 总结 可以看出ffmpeg大量使用函数指针来实现类似C++的继承/多态的效果。并且ffmpeg具有非常好的扩展性。如果我需要自定义一个新的输入协议,只需要自己定义一个新的URLProtocol对象,实现read_packet方法即可。如果需要自定义一个新的容器格式,只需要定义一个新的AVInputFormat对象,实现read_packet方法即可。如果需要自定义一个新的编码格式,只需要定义一个新的AVCodec对象,实现encode2方法即可。真是非常赞的代码架构设计! 本文涉及的资料全部打包放到我Github仓:GitHub:2022年,最新 ffmpeg 资料整理,项目(调试可用),命令手册,文章,编解码论文,视频讲解,面试题全套资料有需要的可以前去下载,或者觉得还不错,请给我Star,感谢支持!
点赞 1
评论 1
全部评论
推荐
最新
楼层
暂无评论,快来抢首评~
相关推荐
10-13 12:16
传音控股_技术运维工程师(准入职员工)
传音内推,传音内推码
我投递的是供应链的岗位,有需求的宝宝可以参考一下~ 一开始投递简历后,会有一个线上**,大家可以去一些软件刷刷题再去做(因为这个题库有时候真的有点怪怪的),通过后经过漫长的审批,有些岗位会有专业测试(研发岗之类的),然后又是漫长的审批,你就会进入面试阶段啦! 首先是11月中旬的时候hr会打一个电话面试: 时间不一定,早中晚都有可能,当时我以为是骚扰电话给挂了,幸好hr小姐姐打了第二个,听说有人挂了之后就没有接到第二个电话了,大家一定要注意(广东)种地方的来电!!!说不定就是你的面试通知!!! 电话面的问题: 1.对传音的了解(可以多搜索传音相关的资料了解) 2.对薪资的期望(看个人需求) 3....
点赞
评论
收藏
分享
10-05 11:46
重庆三峡学院 新媒体运营
花60改的简历大家觉得如何
千千倩倩:
简历问题有点多,加v细聊
点赞
评论
收藏
分享
09-12 14:26
已编辑
门头沟学院 Java
好累
为什么啊为什么啊 别人找实习我也在找实习 别人找暑期还在找实习 别人秋招我还是在找实习 哪里都投遍了为什么一个机会都没有 😅😅好累好累 友友们可以看看有什么问题吗😭😭
点赞
评论
收藏
分享
10-14 21:02
已编辑
西安邮电大学 Java
双非秋招timeline供参考(腾讯字节阿里快手美团)
bg: 双非本+两端大厂实习(蔚来+美团) 主包农村低保,穷哥们中的穷哥们。bg太拉了,担心allin后端导致失业回家种地所以大厂基本投递的测开岗位只想要一份工作测开TimelIne: 腾讯cdg:投递9.8--> 一面9.15 (1h30min) --> 二面9.22 (45min) --> hr面9.25 --> 10.11意向 字节抖音研发: 一面9.12 (1h40min) --> 二面 9.17 (1h20min) --> 三面9.22 (55min) --> hr面9.26 -->10.13意向 快手:一面9.24 (1h) --&g...
在游泳的小冤种很好奇:
都是投的测开吗?
发面经攒人品
点赞
评论
收藏
分享
评论
点赞成功,聊一聊 >
点赞
收藏
分享
评论
提到的真题
返回内容
全站热榜
更多
1
...
BG一般,如何逆天改命拿下后端秋招SSP?
1.5W
2
...
族望留原籍,家贫走四方
4913
3
...
团、节、东孝子全部启动启动启动!(26届后端秋招总结)
4267
4
...
大厂这么卷,去国企,外企“上岸”?
3110
5
...
待了一年,一点没亏
3097
6
...
被秋招面试感动了
2945
7
...
找工作,不用等许可
2864
8
...
一眼望到头的生活VS望不到头的生活
2389
9
...
字节日常实习面试记录
2258
10
...
应届生们听我一句劝,一个老学长的肺腑之言
2153
创作者周榜
更多
正在热议
更多
#
实习在多还是在精
#
34014次浏览
238人参与
#
我的求职进度条
#
82484次浏览
1115人参与
#
平安产险科技校招
#
572次浏览
0人参与
#
你现在会用到哪些AI技能?
#
4834次浏览
74人参与
#
实习下班不想学习,正常吗?
#
19250次浏览
172人参与
#
秋招踩过的“雷”,希望你别再踩
#
80929次浏览
1054人参与
#
未岚大陆求职进展汇总
#
6634次浏览
83人参与
#
你还有多少年退休?
#
26550次浏览
192人参与
#
你的房租占工资的比例是多少?
#
64450次浏览
797人参与
#
你见过哪些工贼行为
#
15988次浏览
88人参与
#
校招谈薪一定要知道的事
#
12726次浏览
112人参与
#
小马智行求职进展汇总
#
13385次浏览
49人参与
#
反问环节如何提问
#
115038次浏览
2453人参与
#
找工作中的小确幸
#
25648次浏览
259人参与
#
顺丰求职进展汇总
#
63141次浏览
314人参与
#
我对___祛魅了
#
132023次浏览
734人参与
#
你觉得什么岗位会被AI替代
#
15882次浏览
174人参与
#
大厂VS公务员你怎么选
#
24676次浏览
362人参与
#
非技术岗投递进展
#
157753次浏览
1314人参与
#
总结:哪家公司面试体验感最好
#
69948次浏览
416人参与
#
如果不考虑收入,你最想做什么工作?
#
32535次浏览
186人参与
#
金蝶求职进展汇总
#
53707次浏览
263人参与
牛客网
牛客网在线编程
牛客网题解
牛客企业服务