上一篇写到PCM格式文件编码成AAC格式文件,这一步的原因是有利于传输。可以将PCM文件做了很大的压缩力度,使得包变得更小,便于传输。我使用播放器播放了AAC文件听到的是音速明显变快了,声音也变得尖锐了许多,AAC文件变小了很多。

本文主要是讲 AAC文件解码成PCM文件。接收到AAC文件以后,需要还原成PCM文件再播放。

需要用到的类:

MediaCodec  :编解码。上一文简单介绍了它的工作过程,有兴趣请出门左转。

MediaExtractor :主要是用于分离各种轨道。

(这里有必要说明一下,比如说MP4文件,叫它MP4格式并不是很正确,它就像是一个标准,一个容器。因为一个MP4文件包含了许多信息,比如音频,视频,字幕等咱们常见的,而音频,视频等在MP4文件中是以轨道【track】形式存在的)。
     ByteBuffer : 这个类在多媒体开发中经常用到。

直接上代码:

(1)准备各种需要的类:

//用于分离出音频轨道private MediaExtractor mMediaExtractor;private MediaCodec mMediaDecode;private File targetFile;//类型private String mime = "audio/mp4a-latm";//输入缓存组private ByteBuffer[] inputBuffers;//输出缓存组private ByteBuffer[] outputBuffers;private MediaCodec.BufferInfo bufferInfo;private File pcmFile;private FileOutputStream fileOutputStream;private int totalSize = 0;

(2)初始化

File root = Environment.getExternalStorageDirectory();targetFile = new File(root, "生成的aac.aac");pcmFile = new File(root, "解码的pcm.pcm");if (!pcmFile.exists()) {try {pcmFile.createNewFile();} catch (IOException e) {e.printStackTrace();}}try {fileOutputStream = new FileOutputStream(pcmFile.getAbsoluteFile());} catch (FileNotFoundException e) {e.printStackTrace();}mMediaExtractor = new MediaExtractor();try {//设置资源mMediaExtractor.setDataSource(targetFile.getAbsolutePath());//获取含有音频的MediaFormatMediaFormat mediaFormat = createMediaFormat();mMediaDecode = MediaCodec.createDecoderByType(mime);mMediaDecode.configure(mediaFormat, null, null, 0);//当解压的时候最后一个参数为0mMediaDecode.start();//开始,进入runnable状态//只有MediaCodec进入到Runnable状态后,才能过去缓存组inputBuffers = mMediaDecode.getInputBuffers();outputBuffers = mMediaDecode.getOutputBuffers();bufferInfo = new MediaCodec.BufferInfo();} catch (IOException e) {Log.e("tag_ioException",e.getMessage()+"");e.printStackTrace();}

设置文件资源:
mMediaExtractor.setDataSource();
          支持本地文件(文件描述),网络文件。需要主要的是,设置的资源必须是可用的,不然程序会报错。
          从MediaExtractor中获取音频轨道的MediaFormat:

private MediaFormat createMediaFormat() {//获取文件的轨道数,做循环得到含有音频的mediaFormatfor (int i = 0; i < mMediaExtractor.getTrackCount(); i++) {MediaFormat mediaFormat = mMediaExtractor.getTrackFormat(i);//MediaFormat键值对应String mime = mediaFormat.getString(MediaFormat.KEY_MIME);if (mime.contains("audio/")) {mMediaExtractor.selectTrack(i);return mediaFormat;}}return null;}

mMediaDecode.configure(mediaFormat, null, null, 0);当解压的时候最后一个参数为0
(3)解码操作

public void decode() {boolean inputSawEos = false;boolean outputSawEos = false;long kTimes = 5000;//循环时间while (!outputSawEos) {if (!inputSawEos) {//每5000毫秒查询一次int inputBufferIndex = mMediaDecode.dequeueInputBuffer(kTimes);//输入缓存index可用if (inputBufferIndex >= 0) {//获取可用的输入缓存ByteBuffer inputBuffer = inputBuffers[inputBufferIndex];//从MediaExtractor读取数据到输入缓存中,返回读取长度int bufferSize = mMediaExtractor.readSampleData(inputBuffer, 0);if (bufferSize <= 0) {//已经读取完//标志输入完毕inputSawEos = true;//做标识mMediaDecode.queueInputBuffer(inputBufferIndex, 0, 0, kTimes, MediaCodec.BUFFER_FLAG_END_OF_STREAM);} else {long time = mMediaExtractor.getSampleTime();//将输入缓存放入MediaCodec中mMediaDecode.queueInputBuffer(inputBufferIndex, 0, bufferSize, time, 0);//指向下一帧mMediaExtractor.advance();}}}//获取输出缓存,需要传入MediaCodec.BufferInfo 用于存储ByteBuffer信息int outputBufferIndex = mMediaDecode.dequeueOutputBuffer(bufferInfo, kTimes);if (outputBufferIndex >= 0) {int id = outputBufferIndex;if ((bufferInfo.flags & MediaCodec.BUFFER_FLAG_CODEC_CONFIG) != 0) {mMediaDecode.releaseOutputBuffer(id, false);continue;}//有输出数据if (bufferInfo.size > 0) {//获取输出缓存ByteBuffer outputBuffer = outputBuffers[id];//设置ByteBuffer的position位置outputBuffer.position(bufferInfo.offset);//设置ByteBuffer访问的结点outputBuffer.limit(bufferInfo.offset + bufferInfo.size);byte[] targetData = new byte[bufferInfo.size];//将数据填充到数组中outputBuffer.get(targetData);try {fileOutputStream.write(targetData);} catch (IOException e) {e.printStackTrace();}}//释放输出缓存mMediaDecode.releaseOutputBuffer(id, false);//判断缓存是否完结if ((bufferInfo.flags & MediaCodec.BUFFER_FLAG_END_OF_STREAM) != 0) {outputSawEos = true;}} else if (outputBufferIndex == MediaCodec.INFO_OUTPUT_BUFFERS_CHANGED) {outputBuffers = mMediaDecode.getOutputBuffers();}else if(outputBufferIndex == MediaCodec.INFO_OUTPUT_FORMAT_CHANGED){MediaFormat  mediaFormat = mMediaDecode.getOutputFormat();}}//释放资源try {fileOutputStream.flush();fileOutputStream.close();mMediaDecode.stop();mMediaDecode.release();mMediaExtractor.release();} catch (IOException e) {e.printStackTrace();}}

这部分的操作完全是遵循MediaCodec的操作原理实现的:获取输入缓存,将数据存储到输入缓存中,将输入缓存放回MediaCodec中,获取输出缓存,处理输出缓存的数据。
站在巨人的肩膀上: http://yedaxia.me/Android-MediaExtractor-And-MediaCodec/

AAC文件解码成PCM格式文件相关推荐

  1. python打包zip文件_python 解压文件,合并文件 打包成zip格式文件 生成MD5值

    #!/usr/bin/env python #_*_encoding:utf-8 # 2018/05/29 #augustyang #2.0 ''' 解压文件,合并文件 打包成zip格式文件 生成MD ...

  2. 如何将字库生成工具生成的 .DZK/ . bin格式的文件转成.c格式文件

    如何将字库生成工具生成的 .DZK/ . bin格式的文件转成.c格式文件 在我们项目开发的过程中,特别是做界面显示的时候,经常会遇到如 :多国文字点阵字库生成器TS3等软件其生成的.DZK格式文件, ...

  3. java将excel文件转换成txt格式文件

    在实际应用中,我们难免会遇到解析excel文件入库事情,有时候为了方便,需要将excel文件转成txt格式文件.下面代码里面提供对xls.xlsx两种格式的excel文件解析,并写入到一个新的txt文 ...

  4. 如何将pdf文件转换成cad格式文件

    pdf文件是一个封闭性文件,文件不仅不容易编辑修改,而且还可能被加密了,那么如何将pdf文件转换成cad格式文件呢? 下面小编教大家使用pdf转换器实现以上操作,具体步骤如下. 第一步:搜索迅捷pdf ...

  5. docx格式文件转成doc格式文件时保持公式可编辑状态的方法

    0 提出问题 现在很多论文投稿甚至是毕业论文都要求doc格式的文档(Word2003以前的版本文档),如果大家像我一样习惯使用WPS或者更高级版本的Word,并且在编辑公式过程中未使用MathType ...

  6. python把.CSV文件转换成.JSON格式文件并格式化储存

    先来看看.JSON对象的一些操作方法: 我们这次用到的主要就是json.dumps 再来看看我们将要转换的.CSV文件的样子: 可以看出,是一张再普通不过的表了,话不多说,直接上代码: import ...

  7. java生成wav格式文件_Python--生成Wav格式文件

    1.下载与安装scipy 2.wav文件写操作 3.signal.chirp函数使用说明 4.点击按钮实现信号生成,点击按钮实现信号显示 5.Python代码 #!usr/bin/env python ...

  8. Acrobat如何将word文件转换成pdf格式

    很多朋友电脑装了Adobe Acrobat,却不知道Acrobat如何将word文件转换成pdf格式,现在就给大家讲解一下.比如,我们电脑安装Adobe Acrobat  Professional 7 ...

  9. 如何将GeoJson格式文件转换成Tab格式的MapInfo数据文件

    前言 GeoJson格式文件:GeoJSON是一种对各种地理数据结构进行编码的格式,基于Javascript对象表示法(JavaScript Object Notation, 简称JSON)的地理空间 ...

最新文章

  1. HDLBits 系列(42)根据仿真波形来设计电路之时序逻辑
  2. MyBatis基本运行环境
  3. 协议crc计算_从零了解modbus协议 第三篇
  4. 发改委:扩大优质民营企业债券发行规模
  5. Python新手需要掌握的知识点
  6. 啦啦外卖最新版41.9啦啦外卖41.9版本全开源
  7. VS2010旗舰版安装图解
  8. 大数据技术原理与应用(第三版)林子雨教材配套实验答案---实验二 熟悉常用的hdfs操作
  9. Activate Scrolling with Middle Trackpad Button
  10. Linux下终端的快捷键及建立打开终端的快捷键
  11. 大厂智力题讲解,学它!!!!(一)
  12. 单片机遥控车c语言程序,基于51单片机的无线遥控小车设计[附发射接收程序]
  13. [NSSRound#8 Basic] MyPage
  14. 游戏框架 核心科技与面试精粹 (樊松阳 著)
  15. js 数组扁平化和树之间相互转换
  16. 电信短信网关ISAG-SMS二次开发
  17. AI顶会ACL发榜,腾讯30篇论文入选
  18. tf.expand_dims
  19. Worthington弹性蛋白酶的应用和相关研究
  20. 产品经理培训行业---以起点学院为主体的相关竞品分析报告

热门文章

  1. Linux USB虚拟串口设备
  2. 手机组态软件利用4G网络直接通信三菱E700变频器
  3. AIX系统安装sqluldr2
  4. Eclipse 字体推荐
  5. 路桥凝冰在线监测系统装置
  6. selenium+phantomjs 爬虫 获取中国移动,电信,联通通话记录
  7. Excel表格只能以打开模式打开如何解决?
  8. Facebook网络模拟测试工具ATC使用
  9. LiveGBS国标GB/T28181前端设备录像历史视音频回放下载接口调用说明
  10. FPGA实现SPI协议