ffmpeg是一套多媒体音视频处理工具,集成了采集、转码、转流、编解码等的功能,最近遇到了需要替换ffmpeg中传输协议的问题(添加自定义的编解码器道理是一样的),苦于网上没有详细教程,所以费了好大周章才搞清楚这一套流程。 所以特别写了这个帖子,希望其他小伙伴们遇到相同问题时可以参考一下,编写的时间比较仓促,不详细的地方还请见谅。
私有传输协议编写:
1. 当我们想要添加私有协议到ffmpeg中时,需要按照ffmpeg框架的要求实现对外的一些数据结构和接口,首先需要再libavformat目录下新建一个协议的源文件(如果想要添加私有的编解码器,那么就添加在libavcodec目录中),例如:XXXprotocols.c。在源文件中实现URLProtocol和AVClass的结构体, 以及一些对外访问的接口,如图所示:被红色部分盖住的地方为协议的名字
其中.name是ffmpeg在解析完url后,查找对应协议的匹配字符。
.url_open .url_read .url_write .url_close是ffmpeg对外开放的四个接口函数,等号的右边为函数名称,需要在这个源文件中实现成静态函数,详细参数实现过程,请参考源码中的rtmpproto.c文件。
2. 如果自身的协议是用c++编写,那么编译成的库就是用g++编译的,但是ffmpeg默认是用gcc编译的,所以在ffmpeg源码编译的最后链接的过程会出现一些问题。作者建议,可以参照x265编解码的方法,将私有协议打包成动态库,并且实现好对外的C的接口,然后通过dlopen 和 dlsym找到动态库的起始地址,寻找对应接口函数。
dlopne用法详细参考教程:http://www.cnblogs.com/Anker/p/3746802.html
x256源码: https://github.com/videolan/x265 (详细参考encoder目录下的api.cpp)
源码编译过程:
1. 最新版FFmpeg需要在 libavformat/protocols.c中添加ff_XXX_protocol的全局变量, 如下图所示:
2. 在libavformat/protocol_list.c的全局数组中添加ff_XXX_protocol,如下图所示:
(注意: 在旧版ffmpeg中,协议的声明是在ibavformat/allformats.c中注册的,在/* protocols */后面添加
REGISTER_PROTOCOL (XXX, xxx); 完成私有协议的全局声明和注册步骤
开头声明如下:其中##是字符串连接的意思。
#define REGISTER_PROTOCOL(X,x) { \
externURLProtocol ff_##x##_protocol; \
if(CONFIG_##X##_PROTOCOL) ffurl_register_protocol(&ff_##x##_protocol,sizeof(ff_##x##_protocol)); })
3. 修改libavformat 目录下的makefile,在#protocols I/O 下面添加定义的
OBJS-$(CONFIG_XXX_PROTOCOL)+=XXXnameXXX.o, 将预先实现的C接口文件编译成对应的目标文件。
4. 修改ffmeg根目录下的config.h和config.mak文件:
在config.h文件中添加 #define CONFIG_XXX_PROTOCOL 1
在config.mak文件中添加CONFIG_XXX_PROTOCOL=yes. 修改完这两处后,就不用重新./configure了。
5. 进行 make 操作(然后 make install 之后 make clean)
6. 通过命令 ./ffmpeg -protocols 查看自己编写的私有协议是否添加进了ffmpeg体系中。