FFmpeg实现http、https这些标准协议,但是要播放加密视频怎么办呢?ijkplayer在FFmpeg的libavformat模块进行扩展ijkio、ijklongurl、ijktcphook、ijkhttphook,我们也可以在这个基础上,自定义协议来进行解密播放。主要基于URLProtocol和AVClass进行扩展,实现protocol对应的方法。

URLProtocol的结构体如下:

typedef struct URLProtocol {const char *name;int     (*url_open)(URLContext *h, const char *url, int flags);int     (*url_open2)(URLContext *h, const char *url, int flags, AVDictionary **options);int     (*url_accept)(URLContext *s, URLContext **c);int     (*url_handshake)(URLContext *c);int     (*url_read)(URLContext *h, unsigned char *buf, int size);int     (*url_write)(URLContext *h, const unsigned char *buf, int size);int64_t (*url_seek)(URLContext *h, int64_t pos, int whence);int     (*url_close)(URLContext *h);int priv_data_size;const AVClass *priv_data_class;const char *default_whitelist;
} URLProtocol;

FFmpeg实现的标准协议有包括http、https、hls、tcp、rtmp等,如下图所示:

​​​​​​​

1、添加自定义协议

新建一个源文件ijkdecrypt.c放在libavformat,实现ijkdecrypt_open、ijkdecrypt_read、ijkdecrypt_seek、ijkdecrypt_close等方法,然后把方法注册到URLProtocol:

static int ijkdecrypt_open(URLContext *h) {return decrypt_open(h);
}
static int ijkdecrypt_read(URLContext *h, unsigned char *buf, int size) {return decrypt_read(h, buf, size);
}
static int64_t decrypt_seek(URLContext *h, int64_t offset, int whence) {return decrypt_seek(h, offset, whence);
}
static int decrypt_close(URLContext *h) {return decrypt_close(h);
}static const AVClass ijkio_context_class = {.class_name = "IjkDecrypt",.item_name  = av_default_item_name,.option     = options,.version    = LIBAVUTIL_VERSION_INT,
};URLProtocol ijkimp_ff_ijkio_protocol = {.name                = "ijkdecrypt",.url_open2           = ijkdecrypt_open,.url_read            = ijkdecrypt_read,.url_seek            = ijkdecrypt_seek,.url_close           = ijkdecrypt_close,.priv_data_size      = sizeof(Context),.priv_data_class     = &ijkio_context_class,
};

2、声明自定义协议

修该libavformat/protocols.c,添加自定义协议并声明为全局变量:

extern const URLProtocol ff_ijkdecrypt_protocol;

在ffbuild/config.mak会自动生成CONFIG_FF_IJKDECRYPT_PROTOCOL

3、依赖自定义协议

在libavformat/makefile添加依赖文件:

OBJS-$(CONFIG_FF_IJKDECRYPT_PROTOCOL)             += ijkdecrypt.o

4、dummy自定义协议

在libavformat/ijkutils.c添加dummy的ijkdecrypt:

IJK_DUMMY_PROTOCOL(ijkdecrypt);

dummy过程是生成AVClass和URLProtocol:

#define IJK_DUMMY_PROTOCOL(x)                                       \
IJK_FF_PROTOCOL(x);                                                 \
static const AVClass ijk_##x##_context_class = {                    \.class_name = #x,                                               \.item_name  = av_default_item_name,                             \.version    = LIBAVUTIL_VERSION_INT,                            \};                                                              \\
URLProtocol ff_##x##_protocol = {                                   \.name                = #x,                                      \.url_open2           = ijkdummy_open,                           \.priv_data_size      = 1,                                       \.priv_data_class     = &ijk_##x##_context_class,                \
};

5、注册自定义协议

在allformats.c调用ijkav_register_all进行注册自定义协议:

void ijkav_register_all(void)
{av_register_all();/* protocols */
#ifdef __ANDROID__IJK_REGISTER_PROTOCOL(ijkmediadatasource);
#endifIJK_REGISTER_PROTOCOL(ijkio);IJK_REGISTER_PROTOCOL(async);IJK_REGISTER_PROTOCOL(ijklongurl);IJK_REGISTER_PROTOCOL(ijktcphook);IJK_REGISTER_PROTOCOL(ijkhttphook);IJK_REGISTER_PROTOCOL(ijksegment);/* demuxers */IJK_REGISTER_DEMUXER(ijklivehook);IJK_REGISTER_DEMUXER(ijklas);
}

IJK_REGISTER_PROTOCOL()对应的宏定义:

#define IJK_REGISTER_PROTOCOL(x)
{                                                                                 \  extern URLProtocol ijkmp_ff_##x##_protocol;                                   \                                    int ijkav_register_##x##_protocol(URLProtocol *protocol, int protocol_size);  \ijkav_register_##x##_protocol(&ijkimp_ff_##x##_protocol, sizeof(URLProtocol));\
}

其中ijkav_register_##x##_protocol的宏定义如下:

int ijkav_register_##x##_protocol(URLProtocol *protocol, int protocol_size)
{                                                                                                   if (protocol_size != sizeof(URLProtocol)) {av_log(NULL, AV_LOG_ERROR, "ABI mismatch.\n");               return -1;                                                                                  }                                                                                               memcpy(&ff_##x##_protocol, protocol, protocol_size);                                           return 0;
}

6、拦截自定义协议

首先在ijkioprotocol.c声明自定义协议:

extern IjkURLProtocol ijkio_decrypt_protocol;

然后对scheme进行拦截,把自定义协议赋值给IjkURLProtocol:

int ijkio_alloc_url(IjkURLContext **ph, const char *url) {if (!ph) {return -1;}IjkURLContext *h = NULL;if (!strncmp(url, "httphook:", strlen("httphook:"))) {h = (IjkURLContext *)calloc(1, sizeof(IjkURLContext));h->prot = &ijkio_httphook_protocol;h->priv_data = calloc(1, ijkio_httphook_protocol.priv_data_size);} else if (!strncmp(url, "decrypt:", strlen("decrypt:"))) {h = (IjkURLContext *)calloc(1, sizeof(IjkURLContext));h->prot = &ijkio_decrypt_protocol;h->priv_data = calloc(1, ijkio_decrypt_protocol.priv_data_size);} else {return -1;}*ph = h;return 0;
}

7、查找自定义协议

在avformat_open_input时,会初始化input、打开avio、根据scheme查找对应协议,完整调用路径为init_input->avio_open2->ffurl_open->ffurl_alloc->url_find_protocol。在avio.c的查找协议过程为:

static const struct URLProtocol *url_find_protocol(const char *filename) {......protocols = ffurl_get_protocols(NULL, NULL);if (!protocols)return NULL;for (i = 0; protocols[i]; i++) {const URLProtocol *up = protocols[i];if (!strcmp(proto_str, up->name)) {av_freep(&protocols);return up;}if (up->flags & URL_PROTOCOL_FLAG_NESTED_SCHEME &&!strcmp(proto_nested, up->name)) {av_freep(&protocols);return up;}}av_freep(&protocols);return NULL;
}

ijkplayer自定义协议播放加密视频相关推荐

  1. 如何在HTML5页面播放加密视频

    如何在HTML5页面播放加密视频 - Polyv blog 如何在HTML5页面播放加密视频 Polyv移动端加密默认是可以直接支持HTML5浏览器播放的,如果担心视频在移动端被下载, 需要在Poly ...

  2. .NET MVC对接POLYV——HTML5播放器播放加密视频

    官方参考文档:http://dev.polyv.net/2017/videoproduct/v-playerapi/html5player/html5-docs/ 1.上传视频之前根据自己需要对所上传 ...

  3. 从blob协议的加密视频地址下载视频

    目标下载视频地址:blob:http://www.yunxiedu.net/2be908de-216b-4b57-badb-1d3be699e077 如下图视频还是弹窗网页视频: I (1)安装插件浏 ...

  4. RTSP协议播放网络视频

    海康摄像头 主码流 rtsp://admin:12345@192.0.0.64:81/h264/ch1/main/av_stream rtsp://admin:12345@192.0.0.64:81/ ...

  5. 移动端加密视频的授权播放

    移动端加密视频的授权播放 Polyv的移动端加密视频由hls(m3u8文件)来实现. 移动端加密视频授权播放分三个级别 1.开放授权 开放授权意味着视频可以被随意观看,视频解密的key不被保护. 2. ...

  6. vep加密视频破解转换翻录为mp4教程

    可能有很多人都没有听说过这个视频格式,这是大黄蜂云课堂播放器所独有的格式,只有通过该播放器才能够打开这个加密的视频,安全系数很高,但也极大的限制了一个视频的传播和播放.如果我们在网络上下载了vep格式 ...

  7. vep加密视频破解转换为mp4教程

    可能有很多人都没有听说过这个视频格式,这是大黄蜂云课堂播放器所独有的格式,只有通过该播放器才能够打开这个加密的视频,安全系数很高,但也极大的限制了一个视频的传播和播放.如果我们在网络上下载了vep格式 ...

  8. Unity 使用 Ffmpeg 加密视频

    Unity 使用 Ffmpeg 加密视频 参考 Ffmpeg 命令加密视频 -i "{STREAMING_ASSETS_PATH}/3D.mp4" -c:v copy -c:a c ...

  9. 开源播放器 ijkplayer (一) :使用Ijkplayer播放直播视频

    1.ijkplayer 编码 IjkPlayer支持硬解码和软解码. 软解码时不会旋转视频角度这时需要你通过onInfo的what == IMediaPlayer.MEDIA_INFO_VIDEO_R ...

  10. Html5视频加密/html5播放器视频加密应用实例

    说说html5的视频加密,HTML5因无需插件可跨平台使用.开发免费.对搜索引擎友好等,深受广大开发者的喜爱,成为主流播放器的发展趋势. 市面上常见的H5加密,采用标准的Apple HLS Encry ...

最新文章

  1. 为什么对高斯分布的方差的极大似然估计是有偏的?
  2. vivo 全球商城:商品系统架构设计与实践
  3. 《虚拟化与云计算》第4章 虚拟化的业界动态
  4. 各种ARM仿真器接口图
  5. Hbase 删表过程
  6. js中的关键子in的使用方法
  7. Citrix 整体架构 端口列表 Tcp Port
  8. demo连接php,PHP获取网页所有连接的方法(附demo源码下载)
  9. nyoj 779 兰州烧饼
  10. CSS 获取当前可视屏幕高度--使用calc()方法动态计算宽度或者高度
  11. 批量检测百度云分享链接有效性方法
  12. 使用 GNU gettext 实现国际化
  13. 【3D目标检测】学习过的论文整理
  14. 三国时期曹魏五大名将-五子良将
  15. Java对URL中的中文进行UrlEncode转码
  16. 大数据技术——HBase简介
  17. ASP.NET Core学习之路03
  18. 音频放大电路制作记录
  19. 【原创】Java获取CPU占用率、内存占用率最简单的方式
  20. assert预处理宏与预处理变量

热门文章

  1. magisk核心功能模式是什么_科技板块——深入解析MM管理器
  2. django学生宿舍管理系统
  3. 漫画小程序支持流量主,自动采集资源,漫画源码漫画小程序源码简单即可发布
  4. 学子商城网站的设计与实现
  5. Java开发童年小游戏
  6. 如何设计会员体系中心
  7. 《编程之美》---求二叉树中节点的最大距离
  8. 商场无线网络方案设计
  9. java actionsupport_struts2为什么action要继承actionSupport类
  10. java 基于jave2实现视频处理 截屏,加水印,压缩,获取时长