最近做了一个android项目用到编解码功能。大概需求是:通过摄像头拍摄一段视频,然后抽帧,生成一个短视频,以及倒序视频,刚开始直接用 H.264 编码格式,没有使用MP4容器封装。做了这些功能后,反而觉得使用MP4格式更加兼容各机型,减少BUG出现。举个明显例子:在Android硬编的时候,常常会用到 MediaCodec和MediaExtractor 相结合。但是,如果你用的 H.264 裸视频文件,MediaExtractor 的 setSource 函数会报异常,它在某些机型(如魅族Note2,系统是5.1)无法解析该视频文件。
      得到大概的需求后,最初我们使用FFmpeg来做视频编解码,所谓软件编解码。由于在处理的过程中速率太慢,且需要在解码后快速展示,所以该方案无法达到我们的预想效果(一个FFmpeg视频解码,并保存为jpeg例子:https://github.com/xiaoxiaoqingyi/ffmpeg-android-video-decoder)。但其也有一些优点,比如在兼容方面,颜色转换方面都做得很好,毕竟不是硬件编解码(国内这么多机型,你懂的),其次FFmpeg能输出指定帧,而Android硬解(MediaCodec)不能输出指定帧,需要输入好几帧到解码器,才能解码出一帧。目前我还是没有找到输入一帧解出一帧的方案,哪位大神知道的,可以指导指导。
       在软件编解码不太适合的情况下,就只能考虑用硬件编解码了(MediaCodec)。在前些日子,我参加了腾讯2017LIVE 直播开发者大会,了解到,现在的直播已经大部分使用硬件来编解码了。刚说了,有些机型不能使用MediaExtractor来解析 h.264文件,为了兼容大部分的机型,需要自己来解析,通过分析h.264文件的每一个字节区分每一帧位置且是什么类型帧。实现该需求,首先在从摄像头获取的数据,如果使用 Camera,一般设置为NV21格式, 但有些人使用Camera2,设置的格式是IMAGE。不管是哪种格式,最终都需要转换成yuv420sp或yuv420p(注意:在转码时候,最好使用jni,用C/C++来转格式,效率会高很多倍),才能供MediaCodec编码,然后保存h.264文件。在创建MediaCodec实例化的时候,除了设置必须参数外,也要注意一些地方,比如,选择哪种编码器,一般情况会选择如下:
 MediaCodec.createEncoderByType("video/avc");
这看上去其实没什么问题,大概原理就是获取最优的Encoder,获取Android系统中编码器注册表最前的一个,一般都是硬件解码(MediaCodec也能调用软件编解码)。这样创建编码器其实不太靠谱,虽然官网也是这么推荐,但是在国内众多的Android机型中,有些手机就会出问题,有的编码出现蓝屏,有些直接就闪退了。有个国外的例子,大概的意思就是先获取 "video/avc" 类型的编码器,然后通过 try catch 一个个试验,如果没问题,就选用这个编码器。源码:https://github.com/ldm520/android_mediacodec_rtsp_h264
还有一个问题就是在设置 I 帧间隔的时候,有些手机不起作用,如下设置:
mediaFormat.setInteger(MediaFormat.KEY_I_FRAME_INTERVAL, interval);
 
针对这种情况,需要使用另外一种设置I帧的方式,强制设置:
 
Bundle params = new Bundle();
params.putInt(MediaCodec.PARAMETER_KEY_REQUEST_SYNC_FRAME, 0);
mMediaCodec.setParameters(params);
 
在编解码时,当把所有的数据都输入编解码器的时候,要记得输入结束符,编解码器才会输出所有的帧。
 
    还有一个抽帧问题,如果使用MediaCodec来抽帧,生成一个新的视频。是否可以直接把H.264文件里的帧去掉就行了?这样不行的,通常会出现花屏。这需要重新把h.264文件输入到解码器,然后获取到自己想要的帧,再输入到一个新的编码器中,生成你想要的H.264文件。在这里还有一个格式问题,并不是从解码器解码出来的数据,就能直接使用编码器来编码,有部分手机可以,有些会出现蓝屏,甚至闪退的情况。这时候需要统一解码器处理的格式。如果你使用这种形式获取:
 
mMediaCodec.getOutputBuffer()
 
出来的格式各种各样,你很难去兼容。google已经推出了一种新的格式:
 
mMediaCodec.getOutputImage(outIndex)
 
得出的是一个Image 对象,该对象可以保存为 JPEG格式图片,也可以转换成NV21(参考:http://www.cnblogs.com/welhzh/p/6079631.html),像上面拍摄部分,转换成yuv422格式,再输入到编码器编码。这样不管什么机型都可以兼容了(我试用10多部不同厂商手机),虽然绕了很多弯路。
 
        在使用MediaCodec还是遇到比较多的问题,毕竟官网都说它是一个轻量的编解码器封装。该总结适合使用过MediaCodec或有一定的解码编码经验的童鞋们。如果你还没了解过 MediaCodec,可以参考官网:
 
     在使用MediaCodec的时候还遇到很多问题,这里没有一一列举出来, 欢迎有遇到同样问题或类似问题的童鞋留言讨论!

 
 

Android硬件编解码与软件编解码的更多相关文章

  1. 【GPU编解码】GPU硬解码---CUVID

    问题描述:项目中,需要对高清监控视频分析处理,经测试,其解码过程所占CPU资源较多,导致整个系统处理效率不高,解码成为系统的瓶颈. 解决思路: 利用GPU解码高清视频,降低解码所占用CPU资源,加速解 ...

  2. 使用多字节字符集的跨平台(PC、Android、IOS、WP)编码/解码方法

    随着移动端的发展,跨平台已成为通讯架构设计的重要考虑因素,PC.Android.IOS.WP等跨多平台间的数据通讯,必然要解决字符编码/解码的问题. 多字节字符集MBCS不是跨平台的首选字符集,面向跨 ...

  3. FFmpeg软件只是个解码编码软件,如果支持多种格式必须先安装好对应的库,下面就说下我装的库

    FFmpeg软件只是个解码编码软件,如果支持多种格式必须先安装好对应的库,下面就说下我装的库:1. 安装faad2 # wget http://downloads.sourceforge.net/fa ...

  4. EasyNVR智能云终端硬件与EasyNVR解决方案软件综合对比

    背景分析 互联网视频直播越来越成为当前视频直播的大势,对于传统的安防监控,一般都是局限于内网,无法成批量上云台.传统的海康和大华的平台虽然可以通过自身私有协议上云平台 集总管控,但是往往只是支持自身的 ...

  5. Android版Ftp服务端软件

    分享一款开发的Android版Ftp服务端软件,支持Android4.0及以上版本,可以实现局域网无线传输文件到手机,或者把手机上的多媒体文件分享到iPad等设备来扩展这些设备的存储空间,详情请见软件 ...

  6. Android服务器——使用TomCat实现软件的版本检测,升级,以及下载更新进度!

    Android服务器--使用TomCat实现软件的版本检测,升级,以及下载更新进度! 算下来,TomCat服务器已经写了很长一段时间了,一直说拿他来搞点事 情,也一直没做,今天刚好有空,交流群还有人请 ...

  7. C++的静态联编和动态联编

    联编的概念 联编是指一个计算机程序自身彼此关联的过程,在这个联编过程中,需要确定程序中的操作调用(函数调用)与执行该操作(函数)的代码段之间的映射关系. 意思就是这个函数的实现有多种,联编就是把调用和 ...

  8. C++_类继承3-动态联编和静态联编

    程序调用函数时,将使用哪个可执行代码块呢?编译器负责回答这个问题. 将源代码中的函数调用解释为特定的函数代码块被称为函数名联编(binding). 在C语言中,这非常简单,因为每个函数名对应一个不同的 ...

  9. C++的静态联编和动态联编详解

    一.概述: 通常来说联编就是将模块或者函数合并在一起生成可执行代码的处理过程,同时对每个模块或者函数调用分配内存地址,并且对外部访问也分配正确的内存地址,它是计算机程序彼此关联的过程.按照联编所进行的 ...

随机推荐

  1. 用程序读取CSV文件的方法

    CSV全称 Comma Separated values,是一种用来存储数据的纯文本文件格式,通常用于电子表格或数据库软件.用Excel或者Numbers都可以导出CSV格式的数据. CSV文件的规则 ...

  2. 02 整合IDEA+Maven+SSM框架的高并发的商品秒杀项目之Service层

    作者:nnngu 项目源代码:https://github.com/nnngu/nguSeckill 首先在编写Service层代码前,我们应该首先要知道这一层到底是干什么的. Service层主要负 ...

  3. 2017-06-26(groupadd groupmod groupdel)

    groupadd groupadd  组名  (创建用户组) groupadd -g  组编号   组名 (创建组名 并且指定编号) groupmod groupmod  -n   新组名  旧组名 ...

  4. WEB安全_csrf攻击

    什么是xss跨站攻击? 正常访问服务器A,用户信任并在服务器A上登录操作,服务器A保存着用户的session数据,这时用户并没有退出服务器A的系统,然后访问危险服务器B,本来是用户请求服务器返回数据, ...

  5. python_如何在列表、字典中筛选数据?

    实际问题有哪些? 过滤掉列表[3,9,-1,10.-2......] 中负数 筛选出字典{'li_ming':90,'xiao_hong':60,'li_kang':95,'bei_men':98} ...

  6. 浅谈Await

    1.Await为什么不会导致堵塞 我们都知道Await关键字是.Net FrameWork4.5引入的特性.await使得我们使用异步更加时特别便捷,并且还不会导致线程堵塞.我们在使用时也就莫名其妙的 ...

  7. 【转】DELL R710服务器可以安装的VMWare ESX Server 4.1 全套下载带注册码

    随着R710的停产,R720随之面世,但DELL R720服务器只支持vmware esxi5.0以上,DELL客户经理给了一套系统安装后序列号无法解决,还是用4.1好了,却又发现怎么都无法安装.按网 ...

  8. How to get started with GIT and work with GIT Remote Repo

    https://www.ntu.edu.sg/home/ehchua/programming/howto/Git_HowTo.html#zz-7. 1.  Introduction GIT is a ...

  9. Hadoop-2.6.5安装

    简介 Hadoop是一个由Apache基金会所开发的分布式系统基础架构. 用户可以在不了解分布式底层细节的情况下,开发分布式程序.充分利用集群的威力进行高速运算和存储. Hadoop实现了一个分布式文 ...

  10. linux下磁盘占用达到100%了,找不到哪些大文件耗尽了磁盘

    Linux下的根分区使用率100%,但是查看/分区下的目录都不大,没有占用满,这该怎么处理? 重启是肯定有效的,目前处理情况:重新restart应用后,空间释放出来 1.lsof | grep del ...