MediaExtractor MediaCodec手动解码播放音乐,笔记
private class DecodeAudio implements Runnable {
@Override
public void run() {
//开始播放pcm
audioTrack.play();
MediaExtractor extractor = null;
MediaCodec codec = null;
Log.i(TAG, "run: init");
FileOutputStream fileOutputStream = null;
try (AssetFileDescriptor assetFileDescriptor = context.getAssets().openFd("outfile3.mp3")) {
Thread.sleep(300);
Log.i(TAG, "run: start");
extractor = new MediaExtractor();
extractor.setDataSource(assetFileDescriptor);
int trackIndex = selectAudioTrack(extractor); // 选择音频轨道(如果有多个)
if (trackIndex == -1) {
extractor.release();
throw new Exception("没有音频轨道");
}
extractor.selectTrack(trackIndex); // 选择指定轨道
Log.i(TAG, "run: 获取信息:" + trackIndex);
MediaFormat format = extractor.getTrackFormat(trackIndex);
Log.i(TAG, "run: 获取信息字段:" + format.toString());
String mime = format.getString(MediaFormat.KEY_MIME);
Log.i(TAG, "run: 创建解码器");
codec = MediaCodec.createDecoderByType(mime);
codec.configure(format, null, null, 0);
codec.start();
// start decode
final int TIMEOUT_US = 10000; // 超时时间
MediaCodec.BufferInfo info = new MediaCodec.BufferInfo();
ByteBuffer[] inputBuffers = codec.getInputBuffers();
ByteBuffer[] outputBuffers = codec.getOutputBuffers();
Log.i(TAG, "run: start looper");
fileOutputStream = new FileOutputStream(targetFile2);
while (!isEndOfStream) {
int inputBufferIndex = codec.dequeueInputBuffer(TIMEOUT_US);
if (inputBufferIndex >= 0) {
Log.i(TAG, "run: 读取到数据了 :" + inputBufferIndex);
ByteBuffer inputBuffer = inputBuffers[inputBufferIndex];
int sampleSize = extractor.readSampleData(inputBuffer, 0);
if (sampleSize < 0) {
// 到达流的结束点
codec.queueInputBuffer(inputBufferIndex, 0, 0, 0, MediaCodec.BUFFER_FLAG_END_OF_STREAM);
isEndOfStream = true;
} else {
long presentationTimeUs = extractor.getSampleTime();
codec.queueInputBuffer(inputBufferIndex, 0, sampleSize, presentationTimeUs, 0);
extractor.advance();
}
}
Log.i(TAG, "run: 进入解码过程");
int outputBufferIndex = codec.dequeueOutputBuffer(info, TIMEOUT_US);
if (outputBufferIndex >= 0) {
Log.i(TAG, "run: 开始解码中:" + outputBufferIndex);
ByteBuffer outputBuffer = outputBuffers[outputBufferIndex];
byte[] pcmData = new byte[info.size];
outputBuffer.get(pcmData); // 获取PCM数据
Log.i(TAG, "run: pcm data:" + pcmData.length);
// 写入pcm
audioTrack.write(pcmData, 0, pcmData.length);
fileOutputStream.write(pcmData, 0, pcmData.length);
outputBuffer.clear();
codec.releaseOutputBuffer(outputBufferIndex, false);
}
Thread.sleep(2);
}
Log.i(TAG, "run: 成功解码");
} catch (Exception e) {
e.printStackTrace();
Log.i(TAG, "run: error:" + e.getMessage());
} finally {
try {
Thread.sleep(288);
} catch (InterruptedException e) {
e.printStackTrace();
}
if (fileOutputStream != null) {
try {
fileOutputStream.flush();
fileOutputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (codec != null) {
codec.stop();
codec.release();
}
if (extractor != null) {
extractor.release();
}
isEndOfPlayer = true;
isEndOfRecord = true;
releaseAudioPlayer();
Log.i(TAG, "run: 线程结束");
}
}
private int selectAudioTrack(MediaExtractor extractor) {
for (int i = 0; i < extractor.getTrackCount(); i++) {
MediaFormat format = extractor.getTrackFormat(i);
String mimeType = format.getString(MediaFormat.KEY_MIME);
if (mimeType.startsWith("audio/")) {
// 找到音频轨道
return i;
}
}
return -1;
}
}