【ARM-Linux开发】【CUDA开发】【视频开发】关于Linux下利用GPU对视频进行硬件加速转
2019-07-12 23:33发布
生成海报
最近一直在研究Linux下利用GPU进行硬件加速转码的方案,折腾了很久,至今没有找到比较理想的硬加速转码方案。似乎网上讨论这一方案的文章也特别少,这个过程中也进行了各种尝试,遇到很多具体问题,以下便对之前所作的一些工作做一些总结和分享,省的时间长了自己也忘记了,也希望后来者能少走弯路,并找到适合自己的最佳方案。
背景:
项目需要在指定的linux服务器上对视频源进行转码存储,以节省存储空间。操作系统必须是Linux,用来硬加速转码的GPU是nViDIA的GT440。
方案1:
由于nViDIA的CUDA SDK中提供了现成的硬加速encoder和decoder,最简单、性能最有保障的方式就是调用CUDA中的编解码API进行转码。国内比较有名的MediaCoder就是这么搞的,当然它只用了CUDA的encoder,解码还是用CPU来做的。但问题是,安装了CUDA SDK之后才发现,CUDA提供的编解码API只有windows的版本,没有Linux的版本。于是,只能退而求其次地尝试在Linux下安装Windows虚拟机试一下。
首先,试了一下Wine,安装好Wine之后,尝试安装N卡的windows驱动,提示如下错误:;
接着,又尝试了在VisualBox中安装Windows,再安装N卡驱动,提示找不到N卡硬件,如图:。
据说MediaCoder支持Linux的方式,就是让MediaCoder在Wine下面运行的,但是不知道为什么我的环境下连驱动都装不上。所以方案1对我来说,基本上属于死路一条。
方案2:
用ffmpeg进行转码。因为发现ffmpeg自带了VDPAU和VAAPI的硬加速解码模块,所以想是不是通过参数设置就可以让ffmpeg通过GPU来硬加速解码。但是ffmpeg的说明文档关于硬加速这块的描述不是很清楚,只能自己结合网上的零星文章做参考,慢慢摸索前进。
首先,编译ffmpeg,确认configure的时候它的几个decoders(h264_vdpau,mpeg4_vdpau,...)和hwaccels(h264_vaapi,mpeg4_vaapi,...)都是enable的。但是编译好ffmpeg之后,通过设置强制解码codec,比如h264_vdpau,运行ffmpeg时,会报一个PIX_FMT_XXX的错误,意思是解码之后的格式不对,不能继续用于编码。
然后,下载了mplayer-vaapi-20110127和hwdecode-demos,经过各种磨难之后,终于都编译通过。经过测试,发现它们都可以利用vdpau和vaapi进行硬加速解码,于是认为ffmpeg也应该可以利用vdpau和vaapi进行硬加速解码。但又折腾了很久,找了很多资料,最后终于在ffmpeg-user上看到一个老外给别人的回帖,明确说了ffmpeg不能用vdpau和vaapi来转码,ffmpeg提供vdpau和vaapi的硬加速decoder,目的是为了给类似mplayer的应用来进行硬加速的视频播放,当时就崩溃了!!!
最后,硬加速decode不行,咱就整encode吧。网上找到一个用OpenCL来硬加速的x264版本,x264demo。又经历了各种磨难,终于将它编译通过并和ffmpeg集成在一起了,期间还修复了x264若干bug。但是最后测试的结果,令人大失所望。虽然使用OpenCL方式加速之后,确实比原版x264快了20%-30%,但问题是:一、转出来的视频根本没法用,存在大面积的花屏,本人对H.264编码的算法不甚了解,故这个大bug只能先放着了;二、H.264的编码算法还是蛮复杂的,因此x264编码的效率比普通的mpeg编码慢了10倍左右。这样的话,用x264+OpenCL的方式对我来说就完全没有必要了。
方案3:
用VLC+VAAPI进行硬加速转码。因为VAAPI的机制是在各个厂家提供的driver层上进行了统一的接口封装,对于N卡,其底层调用的是VDPAU,因此硬件加速仅限于解码部分,编码还是用的软编码。前面说到ffmpeg无法利用VDPAU进行转码,是因为VDPAU解码出来的格式不是YUV的,我想VLC应该是对VDPAU解码出来的东东进行了进一步的加工,然后进行的编码。测试下来的结果显示,VLC硬加速转码的时候确实用到了GPU,但实际转码的时间和CPU占用率并未得到很大的改善。
方案4:
纯硬件加速方案,即利用成熟的DSP芯片进行转码。该方案可以根据需要,将多块硬编解码芯片集成在一起,实现多路视频的同编同解。好处是,利用成熟芯片,不用太关心编解码的具体算法,方案可大可小,甚至可以用来做云转码。可问题是,该方案不符合我的项目需求,哎,只能先放一放了。
打开微信“扫一扫”,打开网页后点击屏幕右上角分享按钮