ijkplayer--播放器改动之私有协议注册
2017-09-01 17:43
393 查看
最近升级ijkplayer过程中发现其协议注册接口已经失效了,仔细看了看ffmpeg相关代码基本弄清楚了。
旧版ijkplayer协议注册方式:
使用宏定义来注册私有协议ijkhttphook
代码最终通过方法ffurl_register_protocol来注册协议,此方法位于旧版ffmpeg url.h中声明
ijkff_ijklongurl_protocol 是一个URLProtocol结构体,在旧版ijkplayer代码中位于ijkavformat/ijklongurl.c文件中。
ijklongurl_open, ijklongurl_read等分别为打开文件,读取流的实现方法。
新版ffmpeg协议注册
在新版ffmpeg中删除了ffurl_register_protocol方法及url.h文件,且在av_register_all方法中只保留了REGISTER_MUTEX等封装,解封装,编解码器注册宏,删除了REGISTER_PROTOCOL协议注册宏。
step1, 在实现私有协议的open, read, write,close,init等方法。及URLProtocol结构体对象如ff_async_protocol(可参考旧版ijkplayer对ijktcphook协议的实现或ffmpeg中其他协议实现)于单个.c文件中,如async.c
其中async_open, async_read, async_seek, async_close为要实现的私有协议内容。
step2, 将实现好的私有协议文件(.c文件)加入libavformat目录
step3, 修改ffmpeg/libavformat/protocols.c, 添加自定义网络协议URLProtocol全局变量声明
至此,自定义协议注册到ffmpeg已经完成。我们可进一步看一下protocol_list.c是如何动态生成的:
生成后的protocol_list.c内容:
上面代码为生成protocol_list.c的脚本文件ffmpeg/configure,可见其遍历将所有protocol加入到了url_protocols[]中。因此,在新版 ffmpeg中不再提供url.h及ffurl_register_protocol等方法来注册了。而新版ijkplayer中的注册宏IJK_REGISTER_PROTOCOL内部的ijkav_register_**_protocol方法函数体都没有实现,是个空定义。ijkplayer实验性的一些协议(主要用于IO控制和统计):ijklongurl,
ijktcphook, ijkhttphook等实际上都没有注册。可能他们还没有找到合适的方式来提供方便的私有协议注册接口。
旧版ijkplayer协议注册方式:
使用宏定义来注册私有协议ijkhttphook
//调用宏实现私有协议注册 IJK_REGISTER_PROTOCOL(ijklongurl); //宏定义代码实现,#号为连接符号,最终执行代码 //ijkav_register_protocol(&ijkff_ijklongurl_protocol); #define IJK_REGISTER_PROTOCOL(x) \ { \ extern URLProtocol ijkff_##x##_protocol; \ ijkav_register_protocol(&ijkff_##x##_protocol); \ } //ijkav_register_protocol代码实现 static void ijkav_register_protocol(URLProtocol *protocol) { if (ijkav_find_protocol(protocol->name)) { av_log(NULL, AV_LOG_WARNING, "skip protocol: %s (duplicated)\n", protocol->name); } else { av_log(NULL, AV_LOG_INFO, "register protocol: %s\n", protocol->name); ffurl_register_protocol(protocol); } }
代码最终通过方法ffurl_register_protocol来注册协议,此方法位于旧版ffmpeg url.h中声明
ijkff_ijklongurl_protocol 是一个URLProtocol结构体,在旧版ijkplayer代码中位于ijkavformat/ijklongurl.c文件中。
URLProtocol ijkff_ijklongurl_protocol = { .name = "ijklongurl", .url_open2 = ijklongurl_open, .url_read = ijklongurl_read, .url_seek = ijklongurl_seek, .url_close = ijklongurl_close, .priv_data_size = sizeof(Context), .priv_data_class = &ijklongurl_context_class, };
ijklongurl_open, ijklongurl_read等分别为打开文件,读取流的实现方法。
新版ffmpeg协议注册
在新版ffmpeg中删除了ffurl_register_protocol方法及url.h文件,且在av_register_all方法中只保留了REGISTER_MUTEX等封装,解封装,编解码器注册宏,删除了REGISTER_PROTOCOL协议注册宏。
step1, 在实现私有协议的open, read, write,close,init等方法。及URLProtocol结构体对象如ff_async_protocol(可参考旧版ijkplayer对ijktcphook协议的实现或ffmpeg中其他协议实现)于单个.c文件中,如async.c
static const AVClass async_context_class = { .class_name = "Async", .item_name = av_default_item_name, .option = options, .version = LIBAVUTIL_VERSION_INT, }; const URLProtocol ff_async_protocol = 4000 { .name = "async", .url_open2 = async_open, .url_read = async_read, .url_seek = async_seek, .url_close = async_close, .priv_data_size = sizeof(Context), .priv_data_class = &async_context_class, };
其中async_open, async_read, async_seek, async_close为要实现的私有协议内容。
step2, 将实现好的私有协议文件(.c文件)加入libavformat目录
step3, 修改ffmpeg/libavformat/protocols.c, 添加自定义网络协议URLProtocol全局变量声明
#include "config.h" #include "libavutil/avstring.h" #include "libavutil/mem.h" #include "url.h" extern const URLProtocol ff_async_protocol; extern const URLProtocol ff_bluray_protocol; extern const URLProtocol ff_cache_protocol; extern const URLProtocol ff_concat_protocol; extern const URLProtocol ff_crypto_protocol; extern const URLProtocol ff_data_protocol; extern const URLProtocol ff_ffrtmpcrypt_protocol; extern const URLProtocol ff_ffrtmphttp_protocol; extern const URLProtocol ff_file_protocol; extern const URLProtocol ff_ftp_protocol; extern const URLProtocol ff_gopher_protocol; extern const URLProtocol ff_hls_protocol; extern const URLProtocol ff_http_protocol; extern const URLProtocol ff_httpproxy_protocol; extern const URLProtocol ff_https_protocol; extern const URLProtocol ff_icecast_protocol; extern const URLProtocol ff_mmsh_protocol; extern const URLProtocol ff_mmst_protocol; extern const URLProtocol ff_md5_protocol; extern const URLProtocol ff_pipe_protocol; extern const URLProtocol ff_prompeg_protocol; extern const URLProtocol ff_rtmp_protocol; extern const URLProtocol ff_rtmpe_protocol; extern const URLProtocol ff_rtmps_protocol; extern const URLProtocol ff_rtmpt_protocol; extern const URLProtocol ff_rtmpte_protocol; extern const URLProtocol ff_rtmpts_protocol; extern const URLProtocol ff_rtp_protocol; extern const URLProtocol ff_sctp_protocol; extern const URLProtocol ff_srtp_protocol; extern const URLProtocol ff_subfile_protocol; extern const URLProtocol ff_tee_protocol; extern const URLProtocol ff_tcp_protocol; extern const URLProtocol ff_tls_gnutls_protocol; extern const URLProtocol ff_tls_schannel_protocol; extern const URLProtocol ff_tls_securetransport_protocol; extern const URLProtocol ff_tls_openssl_protocol; extern const URLProtocol ff_udp_protocol; extern const URLProtocol ff_udplite_protocol; extern const URLProtocol ff_unix_protocol; extern const URLProtocol ff_librtmp_protocol; extern const URLProtocol ff_librtmpe_protocol; extern const URLProtocol ff_librtmps_protocol; extern const URLProtocol ff_librtmpt_protocol; extern const URLProtocol ff_librtmpte_protocol; extern const URLProtocol ff_libssh_protocol; extern const URLProtocol ff_libsmbclient_protocol; //可在此处继续添加一个自定义URLProtocol全局变量的外部声明如ff_async_protocol #include "libavformat/protocol_list.c" //此文件为动态生成文件,在编译时由shell脚本文件生成。
至此,自定义协议注册到ffmpeg已经完成。我们可进一步看一下protocol_list.c是如何动态生成的:
# generate the lists of enabled components print_enabled_components(){ file=$1 struct_name=$2 name=$3 shift 3 echo "static const $struct_name *$name[] = {" > $TMPH for c in $*; do enabled $c && printf " &ff_%s,\n" $c >> $TMPH done echo " NULL };" >> $TMPH cp_if_changed $TMPH $file } print_enabled_components libavcodec/bsf_list.c AVBitStreamFilter bitstream_filters $BSF_LIST print_enabled_components libavformat/protocol_list.c URLProtocol url_protocols $PROTOCOL_LIST
生成后的protocol_list.c内容:
static const URLProtocol *url_protocols[] = { &ff_async_protocol, &ff_cache_protocol, &ff_concat_protocol, &ff_crypto_protocol,
上面代码为生成protocol_list.c的脚本文件ffmpeg/configure,可见其遍历将所有protocol加入到了url_protocols[]中。因此,在新版 ffmpeg中不再提供url.h及ffurl_register_protocol等方法来注册了。而新版ijkplayer中的注册宏IJK_REGISTER_PROTOCOL内部的ijkav_register_**_protocol方法函数体都没有实现,是个空定义。ijkplayer实验性的一些协议(主要用于IO控制和统计):ijklongurl,
ijktcphook, ijkhttphook等实际上都没有注册。可能他们还没有找到合适的方式来提供方便的私有协议注册接口。
相关文章推荐
- NET(C#)接入Dubbo服务,Zookeeper作为Dubbo服务的注册中心,实现thrift协议访问接口(2)
- netty 私有协议开发
- Js注册协议倒计时的小例子
- Servlet之HTTP协议、注册案例、Servlet运行原理、请求方式、乱码解决方案
- Dubbo多协议和多注册中心
- Dubbo原理解析-注册中心之基于dubbo协议的简单注册中心实现
- ijkplayer 播放器库
- flex播放器代码支持rtmp协议
- C#注册URL协议,使用浏览器打开本地程序,类似网页上点了QQ交谈打开本地QQ客户端程序
- 注册协议操作集
- 关于ios object-c 类别-分类 category 的静态方法与私有变量,协议 protocol 
- stream_register_wrapper 注册一个用 PHP 类实现的 URL 封装协议 允许用户实现自定义的协议处理器和流
- SIP 协议之 注册流程 (二)
- 国标GBT28181协议,注册功能服务端与客户端实现代码
- ns2添加注册新协议
- Dubbo原理解析-注册中心之基于dubbo协议的简单注册中心实现
- Word转换为Html (用处:生成一些注册协议之类的)
- Dubbo入门学习--协议及注册中心
- oracle RAC修改私有IB网卡协议为RDS协议
- 根据gbt28181协议,注册到SPVMN平台的方法