MediaExtractor MediaCodec手动解码播放音乐
MediaExtractor MediaCodec手动解码播放音乐,笔记
private class DecodeAudio implements Runnable {@Overridepublic void run() {//开始播放pcmaudioTrack.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 decodefinal 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);// 写入pcmaudioTrack.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;}}