前言

上一篇文章中我介绍了如何使用MediaCodec编码,今天我们再来分析一下如何通过 MediaCodec 进行解码。

为了讲解的方便,我们引入了 MediaExtractor 类。它用于打开MP4等媒体文件,并从中抽取出音视频数据。

打开媒体文件

MediaExtractor,音视频数据分离器。每种媒体文件如MP4, FLV, MOOV等都是一种容器,里边存放了音频数据和视频数据。MediaExtractor的作用就是根据容器协议打开容器,并读取其中的音频或视频数据。

在容器文件(MP4)中,音频数据与视频数据是以轨道(track)的概念存放的。取的是两条轨道永远不相交的意思,也就指明音频数据与视频数据是分别存储的。

我们使用MediaExtractor类打开媒体文件,它的使用非常简单,步骤如下:

1. 创建一个MediaExtractor对象。
2. 将媒体文件设置给MediaExtractor对象。
3. 选定要处理的轨道。

我们先来看一下示例代码吧

......MediaExtractor extractor = null;
try {extractor = new MediaExtractor();extractor.setDataSource(sourceFile.toString());int trackIndex = selectTrack(extractor); //根据关键字获取视频Trackif (trackIndex < 0) {throw new RuntimeException("No video track found in " + mSourceFile);}extractor.selectTrack(trackIndex); //选定视频轨......} finally {if (extractor != null) {extractor.release();}
}......

通过上面的步骤我们就选好了要处理的视频轨。下面我们来创建解码器。

创建解码器

在创建解码器之前,需要先通过 MediaExtractor 获取到要处理的视频轨的媒体格式(因为媒体格式中包括了 CSD-0/CSD-1 信息,这个信息对于解码非常重要)。然后通过媒体格式的 mime 信息创建解码器。

CSD-0/CSD-1 指的就是 H264中的 PPS 和 SPS。

另外,在配置解码器时,可以给它传入一个 Surface,这样解码器解码后,就可以直接将图像帧渲染到 Surface里了。代码如下:


......MediaFormat format = extractor.getTrackFormat(trackIndex);// Create a MediaCodec decoder, and configure it with the MediaFormat from the
// extractor.  It's very important to use the format from the extractor because
// it contains a copy of the CSD-0/CSD-1 codec-specific data chunks.
String mime = format.getString(MediaFormat.KEY_MIME);
decoder = MediaCodec.createDecoderByType(mime);
decoder.configure(format, mOutputSurface, null, 0);
decoder.start();......

解码

解码按如下步骤进行:

1. 从InputBuffer队列中取出一个空闲的InputBuffer。
2. 通过 MediaExtractor 对象从视频轨道中取出H264数据存到InputBuffer中。
3. 将InputBuffer放到InputBuffer队列中。此时需要解码的数据已经送入了解码器。
4. 从OutputBuffer队列中取OutputBuffer,如果能取到说明已经有解码好的数据了。
5. 最后调用releaseOutputBuffer释放OutputBuffer。此时OutputBuffer中的数据将被转成纹理进行渲染。

示例代码如下:


......while (!outputDone){......// Feed more data to the decoder.if (!inputDone) {int inputBufIndex = decoder.dequeueInputBuffer(TIMEOUT_USEC);if (inputBufIndex >= 0) {ByteBuffer inputBuf = decoderInputBuffers[inputBufIndex];int chunkSize = extractor.readSampleData(inputBuf, 0);......long presentationTimeUs = extractor.getSampleTime();decoder.queueInputBuffer(inputBufIndex, 0, chunkSize,presentationTimeUs, 0 /*flags*/);extractor.advance(); //处理下一帧......} }if (!outputDone) {int decoderStatus = decoder.dequeueOutputBuffer(mBufferInfo, TIMEOUT_USEC);......if(decoderStatus > 0) {// As soon as we call releaseOutputBuffer, the buffer will be forwarded// to SurfaceTexture to convert to a texture. decoder.releaseOutputBuffer(decoderStatus, doRender); //解码数据}......}
}
......

小结

通过上面的介绍我们知道通过MediaCodec进行解码也非常的简单,主要是三大步:
1. 创建视频解码器。
2. 获取数据。今天我们是通过 MediaExtrator从文件中获取的。如果是直播系统,则是直接从网上获取数据。
3. 在循环中不停的向解码器喂数据,并从解码器中取出解码后的数据。

参考

  1. H264编码

「音视频直播技术」Android下H264解码相关推荐

  1. 移动端实时音视频直播技术详解(一):开篇

    移动端实时音视频直播技术详解(一):开篇 1.引言 随着互联网用户消费内容和交互方式的升级,支撑这些内容和交互方式的基础设施也正在悄悄发生变革.手机设备拍摄视频能力和网络的升级催生了大家对视频直播领域 ...

  2. 【音视频第6天】基础知识-移动端实时音视频直播技术详解和开源工程WebRTC的技术原理和使用浅析

    本文是系列文章中的第1篇,本系列文章的大纲如下: <移动端实时音视频直播技术详解(一):开篇> <移动端实时音视频直播技术详解(二):采集> <移动端实时音视频直播技术详 ...

  3. 音视频直播--技术架构

    前言 今天和大家讲一下音视频直播技术架构.之前的关注点主要放在客户端如何采集音频数据上,经过这两天的思考,我觉得应该先给大家讲一下音视频直播技术架构,这样更容易从整体上理解视频直播技术是如何运转的,之 ...

  4. 音视频开发(23)---音视频直播技术--10分钟搭建好直播平台

    音视频直播技术--10分钟搭建好直播平台 前言 今天给大家讲一下如何搭建最简单的音视频直播平台.在之前的文章中我已经给大家介绍过音视频直播技术架构,没看过的同学可以看一下.了解了直播的技术架构,我们就 ...

  5. 微信直播服务器架构,音视频直播--技术架构—易龙天

    今天和大家讲一下音视频直播技术架构.之前的关注点主要放在客户端如何采集音频数据上,经过这两天的思考,我觉得应该先给大家讲一下音视频直播技术架构,这样更容易从整体上理解视频直播技术是如何运转的,之后再逐 ...

  6. 即时通讯开发时移动端实时音视频直播技术之处理

    视频或者音频完成采集之后得到原始数据,为了增强一些现场效果或者加上一些额外的效果,我们一般会在将其编码压缩前进行处理,比如打上时间戳或者公司 Logo 的水印,祛斑美颜和声音混淆等处理.在主播和观众连 ...

  7. 一对一语音直播系统源码——如何解决音视频直播技术难点

    直播作为对实时性和互动性要求较高的音视频应用场景,存在着诸多技术难点,即使是一对一的直播模式也不例外.低延迟.流畅性.回波消除.国内外互操作性.大规模并发等问题都是开发过程中的难点.但是,在开发过程中 ...

  8. 关于音视频直播技术的总结

    流媒体协议 流媒体协议是服务器与客户端之间通信遵循的规定.当前网络上主要的流媒体协议如图所示. 直播平台参数对比 主流互联网视音频平台直播服务的参数对比如图所示: 直播技术架构图: 可以看到直播的流程 ...

  9. 移动端实时音视频直播技术中推流和传输详解

    推流是直播的第一公里,直播的推流对这个直播链路影响非常大,如果推流的网络不稳定,无论我们如何做优化,观众的体验都会很糟糕.所以也是我们排查问题的第一步,如何系统地解决这类问题需要我们对相关理论有基础的 ...

  10. 浅析即时通讯开发之移动端实时音视频直播技术编码和封装

    视频编码是本系列一个重要的部分,如果把整个流媒体比喻成一个物流系统,那么编解码就是其中配货和装货的过程,这个过程非常重要,它的速度和压缩比对物流系统的意义非常大,影响物流系统的整体速度和成本.同样,对 ...

最新文章

  1. c# 小票打印机打条形码_C#打印小票自带条形码打印
  2. MySQL 的备份和恢复机制 MyISAM 和 Innodb
  3. tomcat中关于websocket的性能优化配置
  4. vb简易计算机器程序,vb简易计算器源码
  5. BootStrap笔记-分页
  6. nacis服务注册原理_HwServiceManager篇Android10.0 HwBinder通信原理(五)
  7. 【Codeforces】Gym 101173B Bipartite Blanket 霍尔定理+状压DP
  8. 云桌面终端_云桌面是否真的有被夸大,看完你就知道了
  9. ppc64,ppc64le,ARM,AMD,X86,i386,x86_64(AMD64),AArch64的概念
  10. C#的rdlc报表分组汇总学习
  11. 阿里云购买域名到建站的全流程怎么做?
  12. Fine-grained prosody modeling in neural speech synthesis using ToBI representation
  13. labwindows mysql_LabWindows/CVI(二):基本代码框架函数说明
  14. 关于SCO Unix 串口通讯
  15. 由一个日期, 怎样知道是星期几?
  16. 灰关联分析与语音/音乐信号识别
  17. 调光调压调功智能控制器
  18. 关于 Linux中卷/分区等知识的一些总结
  19. 57 Hive案例(数据ETL)
  20. GT4驾照心得 [ZT]

热门文章

  1. 2021-10-18 构建电影数据库MovieDB(数据库第一次实验)
  2. 51单片机实现流水灯
  3. linux下调用扫描仪sane协议
  4. JeePlus:代码生成器
  5. springboot Junit单元测试之坑--@SpringBootTest注解无法加载src/main/resources目录下资源文件
  6. ​手机APP应用软件开发
  7. asp.net开源资料——国内.NET论坛源代码
  8. 叉姐训练目录,好好搞搞,两个月要搞定哦
  9. 基于S3c2440的多种显示屏测试方案
  10. winpe装双系统linux_在Winpe下安装Ubuntu