闲话
知道ffmpeg很久了,可是一直没有深入研究。最近在研究一款显卡的ffmpeg下的硬解,因此想记录下自己研究所得。关于ffmpeg的基本知识,推荐雷神博客,感谢雷神。废话少说,开始填坑。
思路
1.ffmpeg中如何实现硬件解码接口;
2.编译deb包;
3.编译sm768硬解驱动库;
4.测试总结;
ffmpeg硬解框架
开始干之前一定要有一个总体框架,有了指导思想,方向就不会错。sm768支持硬件解码,怎么将硬件解码接口提供给ffmpeg,让其支持硬件解码。接下来用smi_h264为例,梳理下流程。如下图所示,一开始将smi_h264注册成h264,那么一旦格式是h264的视频就会调用sm768的硬解。随后打开解码器对其初始化,就会调用ff_smi_h264_init对硬解初始化。读入视频包后,开始调用硬件解码smi_decode_frame,最后解码器关闭后,也会对硬件解码关闭。梳理完整个流程后,对硬件解码一定会豁然开朗。
开始编包
既然思路方向有了,just do it。我的需求是将smi硬件接口封装成库,供ffmpeg调用,最后生成deb包供用户使用。由于ffmpeg的源码制作成了deb的方式,所以采用dpkg去编包。
1.解压源码:dpkg-source -x
2.安装依赖:
sudo apt-get update
sudo apt-get install fakeroot
安装依赖的包在安装的时候会有提示,照提示安装。
3.编包:dpkg-buildpackage -b -j4
在编包的时候会遇到test过不去,折腾了好久,最后才发现编包的时候不能插sm768显卡,不然测试通不过,在此记录下,希望大家可以避免踩坑。如下图,生成如下的包。dev的包是开发者除了有库还会有有些头文件,开发者可以用此包。
4.安装包:dpkg -i
制作库
静态库
在Linux系统中,库分为静态库和共享库。这两者的区别在于链接的时候,静态库是在编译阶段链接,所以形成的程序较大。动态库是在程序运行的时候链接,因此程序较小。动态库相较于静态库最大的y优点在于一旦库发生了改变,只需重新编译库,而程序不需重新编译。因此
在这里两种库都制作了一遍,静态库较简单,编译成库,放入ffmeg源码中,再重新编译整个ffmpeg。
动态库
制作动态库不难,这里重点说下动态加载。为了使硬件解码库与ffmpeg耦合度低,使用动态加载,只需添加几行代码,就可以实现ffmpeg支持SM768硬件解码功能。pci设备首先遍历,遍历vendor id和device id,找到以后便调用register_dec注册SM768硬件解码器。
注册函数具体实现在硬件解码库中,实现代码如下:
extern AVCodec ff_smi_mpeg1video_decoder;
extern AVCodec ff_smi_mpeg2video_decoder;
extern AVCodec ff_smi_mpeg4video_decoder;
extern AVCodec ff_smi_vc1_decoder;
void register_sm768dec()
{
avcodec_register(&ff_smi_h264_decoder);
avcodec_register(&ff_smi_mpeg1video_decoder);
avcodec_register(&ff_smi_mpeg2video_decoder);
avcodec_register(&ff_smi_mpeg4video_decoder);
avcodec_register(&ff_smi_vc1_decoder);
av_log(NULL,AV_LOG_INFO,"*** smi avcodec register ***\n");
}
测试
最后用mplayer 播放视频测试,可以看出当硬件解码时CPU占用率较低。