1.MainActivity.java

import android.app.Activity;
import android.os.Bundle;
import android.os.Environment;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button; import java.io.IOException; public class MainActivity extends Activity { private static final String SAMPLE = Environment.getExternalStorageDirectory() + "/test.aac";
protected static AudioDecoderThread mAudioDecoder;
private Button btn; @Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
btn = (Button) findViewById(R.id.play);
mAudioDecoder = new AudioDecoderThread();
btn.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View view) {
try {
mAudioDecoder.startPlay(SAMPLE);
} catch (IOException e) {
e.printStackTrace();
} }
}); } @Override
protected void onStop() {
super.onStop();
mAudioDecoder.stop();
} }

2.AudioDecoderThread.java

import android.media.AudioFormat;
import android.media.AudioManager;
import android.media.AudioTrack;
import android.media.MediaCodec;
import android.media.MediaCodec.BufferInfo;
import android.media.MediaExtractor;
import android.media.MediaFormat;
import android.util.Log; import java.io.IOException;
import java.nio.ByteBuffer; public class AudioDecoderThread {
private static final int TIMEOUT_US = 1000;
private MediaExtractor mExtractor;
private MediaCodec mDecoder; private boolean eosReceived;
private int mSampleRate = 0;
int channel = 0;
private final String TAG = "AACPlay";
public void startPlay(String path) throws IOException {
eosReceived = false;
//创建MediaExtractor对象用来解AAC封装
mExtractor = new MediaExtractor();
try {
//设置需要MediaExtractor解析的文件的路径
mExtractor.setDataSource(path);
} catch (IOException e) {
e.printStackTrace();
} MediaFormat format = mExtractor.getTrackFormat(0);
if (format == null)
{
Log.e(TAG,"format is null");
return;
} //判断当前帧的文件类型是否为audio
String mime = format.getString(MediaFormat.KEY_MIME);
if (mime.startsWith("audio/")) {
Log.d(TAG, "format : " + format);
//获取当前帧的采样率
mExtractor.selectTrack(0);
mSampleRate = format.getInteger(MediaFormat.KEY_SAMPLE_RATE);
//获取当前帧的通道数
channel = format.getInteger(MediaFormat.KEY_CHANNEL_COUNT);
//音频文件长度
long duration = format.getLong(MediaFormat.KEY_DURATION);
Log.d(TAG,"length:"+duration/1000000);
} //创建MediaCodec对象
mDecoder = MediaCodec.createDecoderByType(mime);
//配置MediaCodec
mDecoder.configure(format, null, null, 0); if (mDecoder == null) {
Log.e(TAG, "Can't find video info!");
return;
}
//启动MediaCodec
mDecoder.start(); new Thread(AACDecoderAndPlayRunnable).start();
} Runnable AACDecoderAndPlayRunnable = new Runnable() { @Override
public void run() {
AACDecoderAndPlay();
}
}; public void AACDecoderAndPlay() {
ByteBuffer[] inputBuffers = mDecoder.getInputBuffers();
ByteBuffer[] outputBuffers = mDecoder.getOutputBuffers(); BufferInfo info = new BufferInfo(); int buffsize = AudioTrack.getMinBufferSize(mSampleRate, AudioFormat.CHANNEL_OUT_STEREO, AudioFormat.ENCODING_PCM_16BIT);
// 创建AudioTrack对象
AudioTrack audioTrack = new AudioTrack(AudioManager.STREAM_MUSIC, mSampleRate,
AudioFormat.CHANNEL_OUT_STEREO,
AudioFormat.ENCODING_PCM_16BIT,
buffsize,
AudioTrack.MODE_STREAM);
//启动AudioTrack
audioTrack.play(); while (!eosReceived) {
int inIndex = mDecoder.dequeueInputBuffer(TIMEOUT_US);
if (inIndex >= 0) {
ByteBuffer buffer = inputBuffers[inIndex];
//从MediaExtractor中读取一帧待解数据
int sampleSize = mExtractor.readSampleData(buffer, 0);
if (sampleSize < 0) {
// We shouldn't stop the playback at this point, just pass the EOS
// flag to mDecoder, we will get it again from the
// dequeueOutputBuffer
Log.d(TAG, "InputBuffer BUFFER_FLAG_END_OF_STREAM");
mDecoder.queueInputBuffer(inIndex, 0, 0, 0, MediaCodec.BUFFER_FLAG_END_OF_STREAM); } else {
//向MediaDecoder输入一帧待解码数据
mDecoder.queueInputBuffer(inIndex, 0, sampleSize, mExtractor.getSampleTime(), 0);
mExtractor.advance();
}
//从MediaDecoder队列取出一帧解码后的数据
int outIndex = mDecoder.dequeueOutputBuffer(info, TIMEOUT_US);
switch (outIndex) {
case MediaCodec.INFO_OUTPUT_BUFFERS_CHANGED:
Log.d(TAG, "INFO_OUTPUT_BUFFERS_CHANGED");
outputBuffers = mDecoder.getOutputBuffers();
break; case MediaCodec.INFO_OUTPUT_FORMAT_CHANGED:
MediaFormat format = mDecoder.getOutputFormat();
Log.d(TAG, "New format " + format);
audioTrack.setPlaybackRate(format.getInteger(MediaFormat.KEY_SAMPLE_RATE)); break;
case MediaCodec.INFO_TRY_AGAIN_LATER:
Log.d(TAG, "dequeueOutputBuffer timed out!");
break; default:
ByteBuffer outBuffer = outputBuffers[outIndex];
//Log.v(TAG, "outBuffer: " + outBuffer); final byte[] chunk = new byte[info.size];
// Read the buffer all at once
outBuffer.get(chunk);
//清空buffer,否则下一次得到的还会得到同样的buffer
outBuffer.clear();
// AudioTrack write data
audioTrack.write(chunk, info.offset, info.offset + info.size);
mDecoder.releaseOutputBuffer(outIndex, false);
break;
} // 所有帧都解码、播放完之后退出循环
if ((info.flags & MediaCodec.BUFFER_FLAG_END_OF_STREAM) != 0) {
Log.d(TAG, "OutputBuffer BUFFER_FLAG_END_OF_STREAM");
break;
}
}
} //释放MediaDecoder资源
mDecoder.stop();
mDecoder.release();
mDecoder = null; //释放MediaExtractor资源
mExtractor.release();
mExtractor = null; //释放AudioTrack资源
audioTrack.stop();
audioTrack.release();
audioTrack = null;
} public void stop() {
eosReceived = true;
} }

3.activity_main.xml

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"> <Button
android:id="@+id/play"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Play" /> </LinearLayout>

【Android 多媒体应用】使用MediaCodec解码使用AudioTrack播放音频数据的更多相关文章

  1. Android多媒体框架总结(1) - 利用MediaMuxer合成音视频数据流程分析

    场景介绍: 设备端通过服务器传向客户端(Android手机)实时发送视频数据(H.264)和音频数据(g711a或g711u), 需要在客户端将音视频数据保存为MP4文件存放在本地,用户可以通过APP ...

  2. Android 音视频开发(三):使用 AudioTrack 播放PCM音频

    一.AudioTrack 基本使用 AudioTrack 类可以完成Android平台上音频数据的输出任务.AudioTrack有两种数据加载模式(MODE_STREAM和MODE_STATIC),对 ...

  3. Android音视频之AudioTrack播放音频(二)

    前一篇讲了如何录制wav音频文件,本篇就来讲讲如何播放wav文件,这里就是使用AudioTrack来播放音频,确切的说是播放pcm格式数据,使用AudioTrack播放也没什么难度,主要就是将数据写入 ...

  4. Android 音视频开发(二):使用 AudioRecord 采集音频数据并保存到文件

    版权声明:转载请说明出处:http://www.cnblogs.com/renhui/p/7457321.html 一.AudioRecord API详解 AudioRecord是Android系统提 ...

  5. Android学习总结(十六) ———— MediaPlayer播放音频与视频

    一.基本概念 本文主要介绍的是Android中很重要也最为复杂的媒体播放器(MediaPlayer)部分的架构.Android的MediaPlayer包含了Audio和video的播放功能,在Andr ...

  6. 【Android 多媒体应用】使用MediaRecoder录制,MediaPlayer播放音频数据

    1.MainActivity.java import android.annotation.TargetApi; import android.app.Activity; import android ...

  7. 【Android】实验6 在应用程序中播放音频和视频 截止提交报告时间2016.4.21

    注:也可以在数独游戏项目中完成该实验的内容.

  8. 使用AudioTrack播放PCM音频数据(android)

    众所周知,Android的MediaPlayer包含了Audio和video的播放功能,在Android的界面上,Music和Video两个应用程序都是调用MediaPlayer实现的.MediaPl ...

  9. Android 音视频深入 二 AudioTrack播放pcm(附源码下载)

    本篇项目地址,名字是录音和播放PCM,求starhttps://github.com/979451341/Audio-and-video-learning-materials 1.AudioTrack ...

随机推荐

  1. windows下Mysql5.7.10免安装版配置

    免安装配置: 在环境变量 Path 中追加 %mysql_home%\bin; 配置mysql目录下的 my-default.ini 文件,在mysql 根目录下新建 data 文件夹 使用管理员权限 ...

  2. Linux重置管理员密码

    对于一些非专业的Linux运维工程师或者偶尔使用Linux系统的学习者而言,比如我,经常会碰到忘记密码的尴尬,那这时候,快速的重置密码就相当重要了.废话不多说,今天我们就一起来学习一下如何快速重置密码 ...

  3. UV mapping

    [UV mapping] UV mapping is the 3D modeling process of making a 2D image representation of a 3D model ...

  4. vue 项目搭建

    vue init webpack-simple 工程名字<工程名字不能用中文> 简单部署 vue init webpack 工程名字<工程名字不能用中文> 完整部署

  5. 【BZOJ3926】诸神眷顾的幻想乡 【广义后缀自动机】

    题意 给定一棵树,每个结点有一个颜色,问树上有多少种子串(定义子串为两点上路径颜色的序列).保证叶子结点<=20 分析 我们可以发现一个结论,任意一个子串一定是以某个叶子结点为根的trie的后缀 ...

  6. Thinking in 查询设计

    近日,互联网动物园的各位小伙伴们召开了一次会议,考虑到大火的电子商务,准备在动物园里开发一个电商系统.首先上台的是销售山鸡,清了清嗓子,说道,人类正在进行电商革命,动物园也需要上一个电商系统,必要性有 ...

  7. PHP微信授权登录信息

    文件1:index.php //换成自己的接口信息 $appid = 'XXXXX'; header('location:https://open.weixin.qq.com/connect/oaut ...

  8. HEIDSOFT

    HEIDSOFT ENTHUSIASTIC GITHUB USER heidsoft@sina.com GitHub Profile I'm a developer based in China.sh ...

  9. Python爬虫实战八之利用Selenium抓取淘宝匿名旺旺

    更新 其实本文的初衷是为了获取淘宝的非匿名旺旺,在淘宝详情页的最下方有相关评论,含有非匿名旺旺号,快一年了淘宝都没有修复这个. 可就在今天,淘宝把所有的账号设置成了匿名显示,SO,获取非匿名旺旺号已经 ...

  10. 【转载】Redis优化经验

    转载地址:http://blog.sina.com.cn/s/blog_4be888450100z2ze.html 内存管理优化 Redis Hash是value内部为一个HashMap,如果该Map ...