本文讲述如何使用Android标准的API (MediaCodec)实现H264的硬件解码。

  原本我们是用JNI调用平台提供的硬件解码接口得到YUV帧,再放入opengl脚本里处理渲染的。可是换了新平台之后,没有拿到底层的接口,所以这两天找在Android上的H264解码方案。前天在友人的提示下找到了MediaCodec这个类,Android developer上面有MediaCodec的描述和用法,还算详细可以慢慢摸索。但是在网上关于这个类的用法是比较少。

  那在这里贴代码介绍一下。

 // Video Constants
private final static String MIME_TYPE = "video/avc"; // H.264 Advanced Video
private final static int VIDEO_WIDTH = 1280;
private final static int VIDEO_HEIGHT = 720;
private final static int TIME_INTERNAL = 30; public void initDecoder() { mCodec = MediaCodec.createDecoderByType(MIME_TYPE);
MediaFormat mediaFormat = MediaFormat.createVideoFormat(MIME_TYPE,
VIDEO_WIDTH, VIDEO_HEIGHT);
mCodec.configure(mediaFormat, mSurfaceView.getHolder().getSurface(),
null, 0);
mCodec.start();
}

  这是初始化解码器操作,具体要设置解码类型,高度,宽度,还有一个用于显示视频的surface。

     public boolean onFrame(byte[] buf, int offset, int length) {
Log.e("Media", "onFrame start");
Log.e("Media", "onFrame Thread:" + Thread.currentThread().getId());
// Get input buffer index
ByteBuffer[] inputBuffers = mCodec.getInputBuffers();
int inputBufferIndex = mCodec.dequeueInputBuffer(100); Log.e("Media", "onFrame index:" + inputBufferIndex);
if (inputBufferIndex >= 0) {
ByteBuffer inputBuffer = inputBuffers[inputBufferIndex];
inputBuffer.clear();
inputBuffer.put(buf, offset, length);
mCodec.queueInputBuffer(inputBufferIndex, 0, length, mCount
* TIME_INTERNAL, 0);
mCount++;
} else {
return false;
} // Get output buffer index
MediaCodec.BufferInfo bufferInfo = new MediaCodec.BufferInfo();
int outputBufferIndex = mCodec.dequeueOutputBuffer(bufferInfo, 100);
while (outputBufferIndex >= 0) {
mCodec.releaseOutputBuffer(outputBufferIndex, true);
outputBufferIndex = mCodec.dequeueOutputBuffer(bufferInfo, 0);
}
Log.e("Media", "onFrame end");
return true;
}

具体流程:

  1.获取一个可用的inputBuffer的索引(出列)

  2.将一帧数据放入inputBuffer

  3.将inputBuffer入列进行解码

  4.获得一个outputBuffer的索引(出列)

  5.释放outputBuffer

  6.在4,5间循环直到没有outputBuffer可出列为止

  这里解码器有多个输入缓冲区(我测试是有3个),实现不卡顿。

常见的问题:

  dequeueInputBuffer和dequeueOutputBuffer经常会获取不了缓冲区(跟机器的性能有关),如果参数为-1,则会一直等待;如果参数为正数,则等待相应的微秒后返回,没有可用缓冲区就会返回-1。

结论:
  测试程序是读取一个H264裸流文件,识别每一帧然后将其放入解码器解码以及渲染。读取和识别的代码在Demo中。经测试,不同平台的解码效果还挺大。我播放的是720p的H264文件。最出色的居然是RK(瑞芯微)平台,缓冲区获取很少失败,但是会因为过热重启机器;高通平台试了几台机器(锤子、小米4、还有个别定制机),经常有拿不到缓冲区的情况。MTK的只有一台(TCL么么哒),直接初始化不了解码器。。。
  这里跟GPU性能有关,我们解的是720p8m码率的视频,换成较低码率较低分辨率的,大部分机器还是可以正常运行的(除了么么哒)。当然或许有些平台的实现是软解码(使用cpu,ffmpeg方案),这我暂时还没遇到。 Demo链接如下(注意裸流文件要放置的路径):
http://files.cnblogs.com/files/superping/H264Demo.zip

Android平台对H264视频硬解码的更多相关文章

  1. Android 用MediaCodec实现视频硬解码

    http://blog.csdn.net/halleyzhang3/article/details/11473961 http://www.360doc.com/content/14/0119/10/ ...

  2. Android 用MediaCodec实现视频硬解码(转)

    本文向你讲述如何用android标准的API (MediaCodec)实现视频的硬件编解码.例程将从摄像头采集视频开始,然后进行H264编码,再解码,然后显示.我将尽量讲得简短而清晰,不展示 那些不相 ...

  3. 【Android 直播软件开发:音视频硬解码篇】

    开篇 炙手可热,望而生畏的音视频开发 时至今日,短视频App可谓是如日中天,一片兴兴向荣.随着短视频的兴起,音视频开发也越来越受到重视,但是由于音视频开发涉及知识面比较广,入门门槛相对较高,让许许多多 ...

  4. MediaCodec在Android视频硬解码组件的应用

    https://yq.aliyun.com/articles/632892 云栖社区> 博客列表> 正文 MediaCodec在Android视频硬解码组件的应用   cheenc 201 ...

  5. WPF 视频硬解码渲染播放(无空域)(支持4K、8K、高帧率视频)

    MediaWPF 基于 .NET 6 实现视频硬解码渲染Demo(无空域问题) 代码实现仅供学习参考 本项目视频渲染通过显卡进行视频解码,CPU几乎不参与工作,并且不存在令人烦躁的空域问题. 在播放摄 ...

  6. 【GPU编解码】GPU硬解码---DXVA

    前面介绍利用NVIDIA公司提供的CUVID库进行视频硬解码,下面将介绍利用DXVA进行硬解码. 一.DXVA介绍 DXVA是微软公司专门定制的视频加速规范,是一种接口规范.DXVA规范制定硬件加速解 ...

  7. 【GPU编解码】GPU硬解码---DXVA (转)

    前面介绍利用NVIDIA公司提供的CUVID库进行视频硬解码,下面将介绍利用DXVA进行硬解码. 一.DXVA介绍 DXVA是微软公司专门定制的视频加速规范,是一种接口规范.DXVA规范制定硬件加速解 ...

  8. 【计算机视觉】【并行计算与CUDA开发】GPU硬解码---DXVA

    前面介绍利用NVIDIA公司提供的CUVID库进行视频硬解码,下面将介绍利用DXVA进行硬解码. 一.DXVA介绍 DXVA是微软公司专门定制的视频加速规范,是一种接口规范.DXVA规范制定硬件加速解 ...

  9. iOS8系统H264视频硬件编解码说明

    公司项目原因,接触了一下视频流H264的编解码知识,之前项目使用的是FFMpeg多媒体库,利用CPU做视频的编码和解码,俗称为软编软解.该方法比较通用,但是占用CPU资源,编解码效率不高.一般系统都会 ...

随机推荐

  1. php文件处理

    1. 将数据写入文件步骤 1. 打开这个文件,如果不存在,则新建文件 2. 将数据写入文件 3. 关闭文件 2. 从文件中读取数据步骤 1. 打开一个文件,如果不能打开,如文件不存在,应安全退出 2. ...

  2. HtmlTextNode & HtmlCommentNode

    在HtmlAgilityPack里,HtmlTextNode对应的是文本节点.这是一个非常简单的一个类,方法和字段都比较少. 一.属性 override string InnerHtml { get; ...

  3. 动态绑定ReportViewer控件之经验总结

    以上两篇文章已经很丰富了,但是照做一遍不行,检查了N遍还是不行,就是找不出问题原因,总是提示“尚未为数据源“DataSet1_DataTable1”提供数据源实例.”这主要是说在为ReportView ...

  4. Windows XP SP3中远程桌面实现多用户登陆

    Windows XP SP3配置为支持多用户远程桌面连接,注意:此多用户远程桌面连接必须是不同的用户登录,不能像Windows server 2003那样,同一个用户可以同时登录,只能登陆2个不同用户 ...

  5. UESTC_菲波拉契数制 2015 UESTC Training for Dynamic Programming<Problem E>

    E - 菲波拉契数制 Time Limit: 3000/1000MS (Java/Others)     Memory Limit: 65535/65535KB (Java/Others) Submi ...

  6. 搜索和搜索形式(SEARCHING and its forms)

    什么是搜索? 在计算机科学中,搜索就是在一个事物的集合中找到具有特定特征的一项的过程.这些集合中的元素可能是排好序的数据库中的记录,简单数组中的数据,文件中的文本,树中的节点,几何图形中的点和边或者是 ...

  7. PHP伪静态与短链接

    如今,Web服务高速发展的时代,各式各类的门户网站,如新浪http://www.sina.com.腾讯http://www.qq.com,这些网站大家都很容易记住,因为这种名称都是有规则和含义的.如果 ...

  8. textContent、innerText 以及Event事件兼容性问题

    今天在完成前端的简单练习时发现了一些兼容性的问题,百度后得以解决. 这里主要讨论Firefox与Chrome的兼容性问题. textContent与 innerText 在javascript中, 为 ...

  9. SHDP--Working With HBase (二)之HBase JDBC驱动Phoenix与SpringJDBCTemplate的集成

    Phoenix:Phoenix将SQL查询语句转换成多个scan操作,并编排执行最终生成标准的JDBC结果集.   Spring将数据库访问的样式代码提取到JDBC模板类中,JDBC模板还承担了资源管 ...

  10. java中a++与++a区别

    java中a++与++a区别 a++与++a的区别,如果单独使用没有任何区别,如果在运算中就有区别了,a++是先运算在赋值,而++a是先赋值在运算!! 先看a++的代码哦 class demo1 { ...