【Android 多媒体应用】使用MediaCodec解码使用AudioTrack播放音频数据
来源:互联网 发布:淘宝双11是什么意思 编辑:程序博客网 时间:2024/05/17 11:05
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>
阅读全文
0 0
- 【Android 多媒体应用】使用MediaCodec解码使用AudioTrack播放音频数据
- 【多媒体】Android使用MediaCodec硬解码播放H264格式视频文件
- [AudioTrack]使用AudioTrack播放PCM音频数据
- 使用AudioTrack播放PCM音频数据(android)
- Android开发:使用AudioTrack播放PCM音频数据【附源码】
- 使用AudioTrack播放PCM音频数据(android)
- 使用AudioTrack播放PCM音频数据
- 使用AudioTrack播放PCM音频数据
- 使用AudioTrack进行音频播放
- 使用AudioTrack进行音频播放
- 使用AudioTrack进行音频播放
- 【Android开发】多媒体应用开发-使用MediaPlayer播放音频
- 【Android开发】多媒体应用开发-使用SoundPool播放音频
- Android使用MediaCodec硬解码播放H264格式视频文件
- Android使用MediaCodec硬解码播放H264格式视频文件
- Android音频: 如何使用AudioTrack播放一个WAV格式文件?
- [译]Android音频: 如何使用AudioTrack播放一个WAV格式文件?
- 《android多媒体api》之AudioTrack原始音频pcm播放api
- android写数据到手机内存
- [RK3288][Android6.0] 调试笔记 --- date命令无法修改日期和时间
- 从ADIL跨进程绑定通讯再探Service知识
- Android Studio new raw/assets file
- 损失函数整理
- 【Android 多媒体应用】使用MediaCodec解码使用AudioTrack播放音频数据
- Hadoop系列-MapReduce设计思想与原理机制(九)
- 0001+1=0002
- Hdu1796 How many integers can you find
- map的详细用法
- 说说 JavaScript 事件流之模拟事件
- Sql语句优化总结
- DE(差分进化)优化算法MATLAB源码详细中文注解
- Redis Cluster 简介与部署