FFmpeg深度学习模块2019年小结

FFmpeg是什么,通俗的说,在看片子的时候,需要用到视频播放器,而很多视频播放器的底层用的就是FFmpeg。这是我在2019年在FFmpeg深度学习模块中所做事情的总结,由于我在19年是这个模块的主要贡献者,所以,这个总结也差不多就是FFmpeg深度学习模块的现状总结了。

在2018年的时候,Pedro Arthur (bygrandao@gmail.com)带着学生Sergey Lavrushkin (dualfal@gmail.com)完成了一个GSoC项目,将TensorFlow引入FFmpeg,并且增加了一个超分辨率(super resolution)的video filer(vf_sr.c),来演示如何使用深度学习模型。

这里简单介绍一下GSoC,即Google Summer of Code,是Google公司赞助的项目,每年一次,到2020年将是第16次,用来鼓励学生参与各种开源项目的实际代码开发(不限于Google的开源项目,当然此项目也需要Google的同意),还有一定的经济资助。如果你是学生身份,强烈建议尽量参加。

回到FFmpeg,在18年的时候,我参与了这个模块的讨论,当时我的想法是,支持各种深度学习框架的模型,根据传入模型的类型,再调用相应的深度学习框架在后端加载执行。在今天事后来看,这个建议存在的一个问题是,有些深度学习框架没有提供C接口(可能提供了C++接口),而FFmpeg社区要求使用C接口,这个问题我现在也还没有解决方法。另外,我当时还建议把这个作为单独的模块,或者起码放在libavutil中,但是,最终还是放在了libavfilter目录下面,因为考虑到目前主要是被filter调用。

最后完成的代码支持深度学习框架TensorFlow,FFmpeg可以接受TensorFlow的网络模型文件(.pb),准备好输入输出后,再在后端调用TensorFlow的C库文件加载并执行这个模型。另外,考虑到某些系统可能没有TensorFlow,所以,在FFmpeg中增加了native cpu path的支持,即可以fallback到cpu path,这个native后端也定义了一套模型文件格式,即native model。为什么在native模式下不是直接接受.pb文件呢,因为在不使用第三方库(比如protobuf)的情况下解析加载pb文件也是挺麻烦的事情,需要很多的代码支持,没必要也不应该在FFmpeg中增加这样的代码。

由于其中不少代码都是hard code形式写死的,所以,我在2019年的时候,开始发patch来改进这里的代码,并且思考和实践如何让FFmpeg的用户将深度学习的相关功能用起来。大致总结如下。

  • 调整了深度学习模块的目录结构

虽然我把这个写在第一点,刚好可以顺便先做一个框架性的介绍。但是,实际是在发了不少patch被社区初步信任后,才做的目录调整,这也是参加开源社区工作的一个经验,仅供参考。

原先所有的代码文件都直接放在libavfilter目录下面,考虑到支持native mode将会需要很多代码,所以,在libavfilter目录下创建了子目录dnn,除了将dnn_interface.h这个接口文件继续直接放在libavfilter目录下,其他的dnn相关文件都被移到了dnn子目录中,当然,基于dnn的filter文件还是直接在libavfilter目录中。如下图所示。


FFmpeg中深度学习架构图

其中,vf_sr.c就是前面介绍的2018年GSoC完成的超分辨率filter;而去除雨点等功能的vf_derain.c则是刘歧(网名悟空,Steven Liu lq@chinaffmpeg.org)带着学生Xuewei Meng (xwmeng96@gmail.com)完成的GSoC2019项目;vf_dnn_processing.c是我做的基于dnn模型的一个通用的图像处理filter,希望所有只改变AVFrame内容的功能都可以用这一个filter来实现,目前已支持RGB和Gray等格式,而YUV相关格式的支持还在完成中;vf_dnn_analytic.c则是我设想中的filter,可以基于dnn模型从frame中提取一些信息,比如目标检测、人脸识别等等,可能会扩展成多个不同用途的filter,初步计划在2020年完成。

在libavfilter/dnn目录下,目前有两部分的内容,一是调用TensorFlow C library的接口层,二是实现native layer的代码,如果以后有需要,还可以增加更多的深度学习框架的C库支持。因为DNN interface接口层的存在,dnn的实现和基于dnn的filter之间是解耦的。

我在2019年在FFmpeg中的主要工作,除了从头开始支持ROI encoding外,就是从dnn filter到DNN interface再到dnn实现的全覆盖。filter和dnn实现互为表里,相互促进,目前两者都还处于比较初始的阶段,我希望可以做好初始推动力的作用,使得两者可以尽快形成良性循环正反馈,可以吸引更多的开发者和用户参加进来,也欢迎您的参与!

  • 模型文件转换的python脚本

在初始代码中,native模型文件的生成方法,是根据相应的TensorFlow模型,手工一句句地写代码将模型导出到文件中。如果TF模型略有调整,也必须手工修改相应的代码,再重新生成native模型文件。这样的方法,无法扩展也不实用。所以,我写了个python脚本,输入是TF模型文件,输出是native模型文件,并且在native模型文件中增加了文件头和版本号等信息。这个脚本文件目前只支持当前FFmpeg支持的layer,需要继续完善。

  • native layer代码的重构

在原来代码中,native模型的加载由一个函数完成,我将其拆分为了一个入口函数和若干子函数,每个子函数对应一个layer的加载。在原来代码中,所有nativer layer的执行函数放在一个文件中。我为每个layer在libavfilter/dnn目录下创建了一个新文件,对应的加载函数和执行函数都放在这个文件中,实现了不同layer之间在文件级别的隔离。在入口函数中,则用函数指针数组的方式来直接调用相应layer的函数,不使用if/else或者switch的方式,避免了大量的重复代码。

所以,现在如果要修改某个layer的实现,只需要修改相应的一个文件即可,不太会造成side effect。如果要增加一个layer,则只需要增加一个新的代码文件(.c和.h),然后注册到函数指针数组中即可,也不会存在误操作影响到已有代码的功能。

  • 增加FATE测试

FATE (FFmpeg Automated Testing Environment) 是FFmpeg社区开发的自动化测试框架,要持续维护一个良好质量的软件项目,快速的自动化测试(包括单元测试、回归测试等等)都是必不可少的看门人角色,非常重要。基于FATE框架,我为每一个navier layer都增加了单元测试,以后有新的layer加入,只要依葫芦画瓢再增加就可以了。我也为vf_dnn_processing增加了测试。由于当前native layer中的卷积层conv2d的性能不佳,所以,还无法为vf_sr和vf_derain增加FATE测试,否则,耗时太久,反而影响了自动化测试的初始目的。

  • DNN interface接口调整

    • 在使用TF后端的时候,之前代码要求模型的输入变量的名字必须是x,输出变量名字必须是y。我调整了接口,输入输出变量名字可以在filter层次指定。
    • 在使用native后端的时候,之前代码将第一个layer的输入作为模型的输入,将最后一个layer的输出作为模型的输出。我增加了name的支持,可以通过name字符串来找到模型的输入输出变量,也使得行为和TF一致。
    • 之前代码假设模型的输入输出都是float32格式的数据。我调整了数据结构,使得float32和uint8格式都可以指定。
    • 将native模型的输出变量从一个增加到了多个,以适合目标检测等模型的要求。
    • 增加了一个查询接口,在模型文件被加载后,FFmpeg就可以查询模型的输入格式,比如width、height、channel和format等信息,方便检查模型文件是否正确,或者做一些诸如图片缩放等预处理。
  • 增加了更多native layer的支持

为了上述DNN接口层的调整,需要有实际的例子来表明这些调整是需要的,也为了不产生regression问题,需要增加更多nativer layer。另外,从项目本身来说,增加更多的nativer layer以支持更多的深度学习模型,比如目标检测等模型,也是题中应有之义。在19年下半年,带了上海交大密歇根学院5位同学的本科毕业设计课程,增加了一些native layer的实现,但没有upstream。

  • 为native mode引入Operand的概念

在之前的代码中,nativer layer是依次顺序排列,第i层的输出就是第i+1层的输入,无法支持一个层的输出作为多个层的输入,也不支持一个层的输入来自多个层。增加了Operand操作数概念后,层和层之间用Operand连接,就可以实现这些分支合并功能。如何使得Operand更好的节约内存、减少内存拷贝,目前还只有想法,尚未代码实现。

  • 已有代码的一些bug的fix等

这部分工作,赵军Jun Zhao (barryjzhao@tencent.com)、刘歧Steven Liu( lq@chinaffmpeg.org)还有leozhang (leozhang@qiyi.com)、Zhao Zhili (quinkblack@foxmail.com)等也做了不少贡献。话说这样的统计功能怎么做啊,我是手工地肉眼看了一遍,大概率会遗漏什么,,,如有漏人,请告诉我。

最后,感谢老板的支持和社区的认可,我在2019年底成为了FFmpeg深度学习模块的maintainer。另外,我的大部分代码都是Pedro Arthur (bygrandao@gmail.com) review的,在此也表示感谢。

以上内容是本人业余时间兴趣之作,限于水平,差错难免,仅代表个人观点,和本人任职公司无关。

本文首发于微信公众号:那遁去的一

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 216,544评论 6 501
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,430评论 3 392
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 162,764评论 0 353
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,193评论 1 292
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,216评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,182评论 1 299
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,063评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,917评论 0 274
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,329评论 1 310
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,543评论 2 332
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,722评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,425评论 5 343
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,019评论 3 326
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,671评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,825评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,729评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,614评论 2 353

推荐阅读更多精彩内容