H.265(HEVC)编码格式能够在得到相同编码质量视频的前提下,使用相当于H.264(AVC)一半的存储容量,虽然H.265的算法复杂度比H.264高一个数量级,但是硬件水平在不断提高,因此H.265使用场合逐渐多了起来。好多硬件厂商芯片内部实现了H.265的硬解码。最近调试了vlc-android调用OpenMAX硬解码H.265的部分,使用的硬件平台是ZX-2000,系统是Android5.1。

  OpenMAX的官方网站:https://www.khronos.org/openmax/

  官方文档整理:https://github.com/jiayayao/DataSheet/tree/master/encode-decode/openmax

  官方介绍:The OpenMAX Working Group has been formed by the Khronos Group, to define a set of standard, open Application Programming Interfaces (APIs) for multimedia applications. The goal of this open standard is to reduce the cost and complexity of porting multimedia software to new processors and architectures.  

  可见OpenMAX的核心价值在于抽象了各个硬件平台和框架,减少了多媒体应用软件移植的复杂度。OpenMAX实际上分成三个层次,自上而下分别是,OpenMAX AL(应用层),OpenMAX IL(集成层)和OpenMAX DL(开发层)。在实际的应用中,OpenMAX的三个层次中使用较多的是集成层OpenMAX IL。三个层次的内容如下所示。

  第一层:OpenMAX AL(Appliction Layer,应用层),在应用程序和多媒体中间件之间提供了一个标准化接口,多媒体中间件提供服务以实现被期待的API功能;

  第二层:OpenMAX IL(Integration Layer,集成层),作为音频、视频和图像编解码器能与多媒体编解码器交互,并以统一的行为支持组件(例如,资源和皮肤)。这些编解码器或许是软硬件的混合体,对用户是透明的底层接口应用于嵌入式、移动设备。它提供了应用程序和媒体框架,透明的。编解码器供应商必须写私有的或者封闭的接口,集成进移动设备。IL的主要目的是使用特征集合为编解码器提供一个系统抽象,为解决多个不同媒体系统之间轻便性的问题;

  第三层:OpenMAX DL(Development Layer,开发层),定义了一个API,它是音频、视频和图像功能的集合。供应商能够在一个新的处理器上实现并优化,然后编解码供应商使用它来编写更广泛的编解码器功能。它包括音频信号的处理功能,如FFT和filter,图像原始处理,如颜色空间转换、视频原始处理,以实现例如MPEG-4、H.264、MP3、AAC和JPEG等编解码器的优化。

  OpenMAX对硬解码的事务进行了抽象,提供了一系列的.h文件,各个厂家分别根据头文件实现OpenMAX的标准。在vlc-android工程中,通过调用mediacodec.c文件,查询Android系统的MediaCodec是否支持硬解码,如果支持,则创建对应的硬解码器。mediacodec.c文件的作用是封装Android系统的Mediacodec框架,同时OpenMAX及其实现会作为对应的解码器注册到MediaCodec框架中。当mediacodec_ndk.c文件中调用Start函数创建解码器时:

p_sys->p_codec = syms.AMediaCodec.createCodecByName(api->psz_name);

该语句实际上调用的是MediaCodec框架的AMediaCodec_createCodecByName函数(Android5.1源码:NdkMediaCodec.cpp). Android系统的MediaCodec与OpenMAX的关系如下图:

对H265编码格式的视频来说,创建的解码器名称是:OMX.ZX.video.decoder.hevc,也就是说实际的硬解码走的是ZX-2000对OpenMAX的实现的H265部分,硬解码时打印的日志大部分都是以“S3OMX”等开头也证明了这一点”。从OpenMAX的AL, IL, DL三个层次的理解上来看,mediacodec.c文件及该文件之上的文件封装了OpenMAX,使得OpenMAX在vlc中得以利用,应该属于AL层;ZX-2000的BSP开发部门实现了OpenMAX标准(代码以“S3OMX”开头),BSP中对OpenMAX的实现应该属于IL层;DL层应该是芯片内部硬解码部分的驱动实现。所以对于应用层的开发人员来说,应该了解AL和IL层。

一、OpenMAX IL  

  OpenMAX IL层标准提供了几个头文件:

OMX_Types.h:OpenMAX Il的数据类型定义
OMX_Core.h:OpenMAX IL核心的API
OMX_Component.h:OpenMAX IL 组件相关的 API
OMX_Audio.h:音频相关的常量和数据结构
OMX_IVCommon.h:图像和视频公共的常量和数据结构
OMX_Image.h:图像相关的常量和数据结构
OMX_Video.h:视频相关的常量和数据结构
OMX_Other.h:其他数据结构(包括A/V 同步)
OMX_Index.h:OpenMAX IL定义的数据结构索引
OMX_ContentPipe.h:内容的管道定义

  各个硬件厂商需要根据这些头文件实现OpenMAX标准。比如以Android5.1源码为例,TI的OMAP芯片实现OpenMAX的代码就在文件android5.1\hardware\ti\omap4xxx\ domx\omx_core\src\OMX_Core.c中,其他厂商如果要实现硬解码,也需要按照类似的做法,将自身对于OpenMAX的实现添加到Android系统BSP中。

  Android5.1源码的android5.1\hardware\ti\omap4xxx\domx\test\sample_proxy\test_sample_ proxy.c文件是TI的OMAP芯片OpenMAX部分的简单测试程序。该测试程序仅仅是简单的初始化Component,处理缓冲区,最后通过改变Component状态释放Component。如果需要适配OpenMAX到新的芯片,可以参考OMAP的实现。

二、OpenMAX AL   

  mediacode.c和avcodec.c作用是类似的,mediacodec.c为OpenMAX在VLC下的使用提供了封装,avcodec.c为FFmpeg在VLC下的使用提供了封装。提供封装时,一般需要提供几个函数,如OpenDecoder,CloseDecoder,DecodeBlock等,这些函数会被上层调用。

  当获取到的RTSP流是H.265编码格式后,mediacodec_ndk.c创建解码器“OMX.ZX.video.decoder.hevc”,创建解码器时,会将mediacodec_ndk.c实现的一系列函数赋值给mc_api结构体,包括start(), stop(), configure(), clean()等。解码时解码线程DecodeThread会调用DecodeBlock函数解码数据块,但是与avcodec(软解)的直接解码不同,mediacodec的解码线程是将需要解码的数据块(block_t类型)通过API经mediacodec_ndk.c送入硬解码芯片队列中,另外开启一个新的线程OutThread来从硬解码芯片的图像队列中取出图像的index,赋值一些时间戳信息,再推入图像fifo中,交给渲染线程处理。

  注意,硬解码时推入图像fifo的picture_t只是带有硬件缓冲区的index,最后渲染线程只是根据index将该缓冲区释放(modules/video_out/android/display.c);而软解码时,FFmepg会将带有解码后图像数据的picture_t交给opengl(modules/video_output/opengl/display.c)去渲染。个人的理解是,硬解码时,解码后的图像就直接在GPU里边,GPU在恰当的时机直接把图像交给显示的framebuffer就可以了,无需再取出来再交给opengl渲染;软解码时,解码后的图像在系统内存中,需要交给opengl去渲染。

  解码线程堆栈如下:

  硬解码模块自行创建的输出线程堆栈如下:

   注意,在将图像推入图像fifo之前,会先调用API从硬解码芯片的图像队列中取出图像,调用mediacodec_ndk.c文件的DequeOutput函数。

参考资料:

《Android系统级深入开发—移植与调试》中OpenMAX章节

vlc源码分析(六) 调用OpenMAX硬解码H.265的更多相关文章

  1. vlc源码分析(三) 调用live555接收RTSP数据

    首先了解RTSP/RTP/RTCP相关概念,尤其是了解RTP协议:RTP与RTCP协议介绍(转载). vlc使用模块加载机制调用live555,调用live555的文件是live555.cpp. 一. ...

  2. vlc源码分析(七) 调试学习HLS协议

    HTTP Live Streaming(HLS)是苹果公司提出来的流媒体传输协议.与RTP协议不同的是,HLS可以穿透某些允许HTTP协议通过的防火墙. 一.HLS播放模式 (1) 点播模式(Vide ...

  3. Dubbo 源码分析 - 服务调用过程

    注: 本系列文章已捐赠给 Dubbo 社区,你也可以在 Dubbo 官方文档中阅读本系列文章. 1. 简介 在前面的文章中,我们分析了 Dubbo SPI.服务导出与引入.以及集群容错方面的代码.经过 ...

  4. VLC源码分析知识总结

    1.  关于#和## 1.1).在C语言的宏中,#的功能是将其后面的宏参数进行字符串化操作(Stringfication),简单说就是在对它所引用的宏变量通过替换后在其左右各加上一个双引号. 比如在早 ...

  5. ABP源码分析六:依赖注入的实现

    ABP的依赖注入的实现有一个本质两个途径:1.本质上是依赖于Castle这个老牌依赖注入的框架.2.一种实现途径是通过实现IConventionalDependencyRegistrar的实例定义注入 ...

  6. Duilib源码分析(六)整体流程

    在<Duilib源码分析(一)整体框架>.<Duilib源码分析(二)控件构造器—CDialogBuilder>以及<Duilib源码分析(三)XML解析器—CMarku ...

  7. motan源码分析六:客户端与服务器的通信层分析

    本章将分析motan的序列化和底层通信相关部分的代码. 1.在上一章中,有一个getrefers的操作,来获取所有服务器的引用,每个服务器的引用都是由DefaultRpcReferer来创建的 pub ...

  8. 5.源码分析---SOFARPC调用服务

    我们这一次来接着上一篇文章<4. 源码分析---SOFARPC服务端暴露>讲一下服务暴露之后被客户端调用之后服务端是怎么返回数据的. 示例我们还是和上篇文章一样使用一样的bolt协议来讲: ...

  9. Vue.js 源码分析(六) 基础篇 计算属性 computed 属性详解

    模板内的表达式非常便利,但是设计它们的初衷是用于简单运算的.在模板中放入太多的逻辑会让模板过重且难以维护,比如: <div id="example">{{ messag ...

随机推荐

  1. Chromium base库分割字符串SplitString

    前一段时间在工作过程中遇到一个场景需要将http response中的request header中的cookie字段取出并进行解析,但是手头没有解析cookie的工具类,同时cookie的表现就是个 ...

  2. PAT 1029. Median

    尼玛,数组偶数个数的时候取中位数是取中间两者中的前者,还tmd一直再算平均,卧槽 #include <iostream> #include <cstdio> #include ...

  3. bootstrap 中的 iCheck 全选反选功能的实现

    喜欢bootstrap 风格的同学应该知道,iCheck的样式还是很好看的. 官网: http://www.bootcss.com/p/icheck/ 进入正题,iCheck提供了一些方法,可以进行全 ...

  4. Java内存模型(JMM)以及 垃圾回收机制 小结

    内存模型: 内存模型描述了程序中各个变量(实例域.静态域和数组元素)之间的关系,以及在实际计算机系统中将变量存储到内存和从内存中取出变量这样的底层细节,对象最终是存储在内存里面的,这点没有错,但是编译 ...

  5. EditView插入qq表情,可删除表情或文字

    代码如下: 代码如下: package com.push.notif; import java.lang.reflect.Field; import java.util.Random; import ...

  6. php判断网站收录情况

    php判断网站收录情况 <?php //检测网页是否被百度收录 function checkBaiduIndex($url){ $url='http://www.baidu.com/s?wd=' ...

  7. jquery尺寸和jQuery设置和获取内容方法

    一.jquery尺寸 jQuery 提供多个处理尺寸的重要方法: width()    设置或返回元素的宽度(不包括内边距.边框或外边距),括号中可填数值宽度参数,无单位 height()   设置或 ...

  8. Monte Calro Tree Search (MCTS)

    https://blog.csdn.net/natsu1211/article/details/50986810, 感谢分享! Intro最近阿法狗和李师师的人机大战着实火了一把,还顺带捧红了柯杰,古 ...

  9. CentOS6.5 SSH无法连接

    1.确认连接交机机端口的正常,如查更换多几个端口试 2.确认网络不存在问题. 3.把selinux iptables服务全部关闭 4.查看本机是否侦听22端口和是否开启ssh服务 命令:netstat ...

  10. springMVC入门-01

    这一系列是在看完网上SpringMVC(基于spring3.0)入门视频之后的个人总结,仅供参考,其中会添加一些个人的见解. 1.搭建SpringMVC所需jar包: org.springframew ...