ijkplayer--播放器改动之私有协议注册

最近升级ijkplayer过程中发现其协议注册接口已经失效了,仔细看了看ffmpeg相关代码基本弄清楚了。

旧版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 = {
    .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等实际上都没有注册。可能他们还没有找到合适的方式来提供方便的私有协议注册接口。
  • 2
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
ijkplayer 的动态库v7a 和v8a,支持海康摄像头RTSP h264协议,源码来自最新版本ijkplayer k0.8.0 使用原DEMO即可支持RTSP mp4文件等播放,首画面500ms显示. module-lite-rtsp.sh的内容如下: #! /usr/bin/env bash #-------------------- # Standard options: export COMMON_FF_CFG_FLAGS= # export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --prefix=PREFIX" # Licensing options: export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --disable-gpl" # export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --enable-version3" export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --disable-nonfree" # Configuration options: # export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --disable-static" # export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --enable-shared" # export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --enable-small" export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --enable-runtime-cpudetect" export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --disable-gray" export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --disable-swscale-alpha" # Program options: export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --disable-programs" export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --disable-ffmpeg" export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --disable-ffplay" export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --disable-ffprobe" export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --disable-ffserver" # Documentation options: export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --disable-doc" export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --disable-htmlpages" export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --disable-manpages" export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --disable-podpages" export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --disable-txtpages" # Component options: export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --disable-avdevice" export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --enable-avcodec" export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --enable-avformat" export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --enable-avutil" export COMMON_FF_CF

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值