MediaCodec Demo

本文介绍了一个简单的音频编解码器实现过程,包括如何使用MediaExtractor读取音频文件、MediaCodec进行解码以及将解码后的数据写入新的文件中。文章详细展示了通过Java代码操作音频文件的方法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

package com.example.wan.audiocodec;

import android.media.MediaCodec;
import android.media.MediaExtractor;
import android.media.MediaFormat;
import android.util.Log;

import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.ByteBuffer;

/**
 * Created by wan on 2016/4/17.
 */
public class AudioCodec {
    private String TAG = "Audio";
    private MediaCodec mDecoder;
    private MediaExtractor mExtractor;

    private String srcPath;
    private String desPath;

    private ByteBuffer[] mInputBuffers;
    private ByteBuffer[] mOutputBuffers;
    private MediaCodec.BufferInfo info;
    private MediaFormat mFormat;
    private int mChannels;
    private long mDurations;
    private int mBitrate;
    private int mSampleRate;

    private boolean mInputEOS = false;
    private boolean mOutputEOS = false;

    private FileOutputStream mOutFile;

    private OnCompletedListner mCompletedListener;

    public interface OnCompletedListner {
        void onCompleted();
    }

    public void setOnCompletedListener(OnCompletedListner listener) {
        this.mCompletedListener = listener;
    }

    public static AudioCodec getInstance() {
        return new AudioCodec();
    }

    public void setIOPath(String srcPath, String desPath) {
        this.srcPath = srcPath;
        this.desPath = desPath;

    }
    public int prepare() {
        mExtractor = new MediaExtractor();
        try {
            mExtractor.setDataSource(srcPath);
            int trackCounts = mExtractor.getTrackCount();
            for (int i = 0; i<trackCounts; i++) {
                mFormat = mExtractor.getTrackFormat(i);
                String mime = mFormat.getString(MediaFormat.KEY_MIME);
                Log.e(TAG, "prepare mime = " + mime + ", mFormat = " + mFormat);
                if (mime.startsWith("audio")) {
                    mExtractor.selectTrack(i);
                    mSampleRate = mFormat.getInteger(MediaFormat.KEY_SAMPLE_RATE);
                    //mBitrate = mFormat.getInteger(MediaFormat.KEY_BIT_RATE);
                    mDurations = mFormat.getLong(MediaFormat.KEY_DURATION);
                    mChannels = mFormat.getInteger(MediaFormat.KEY_CHANNEL_COUNT);
                    Log.e(TAG, "mSampleRate = " + mSampleRate
                            //+  ", mBitrate = " + mBitrate
                            +  ", mDurations = " + mDurations
                            +  ", mChannels = " + mChannels);
                    mDecoder = MediaCodec.createDecoderByType(mime);
                    mDecoder.configure(mFormat, null, null, 0);
                    break;
                }
            }
        } catch (IOException e) {
            e.printStackTrace();
            return -1;
        }
        if (mDecoder == null) {
            Log.e(TAG, "create decoder failed");
            return -1;
        }

        mDecoder.start();
        mInputBuffers = mDecoder.getInputBuffers();
        mOutputBuffers = mDecoder.getOutputBuffers();
        info = new MediaCodec.BufferInfo();
        try {
            mOutFile = new FileOutputStream(desPath);
        } catch (FileNotFoundException e) {
            e.printStackTrace();
            return -1;
        }
        Log.e(TAG, "prepare done");
        return 0;
    }

    private class InputRunnable  implements Runnable {
        @Override
        public void run() {
            processInput();
        }
    }

    private class OutputRunnable  implements Runnable {
        @Override
        public void run() {
            processOutput();
            if (mCompletedListener !=  null) {
                mCompletedListener.onCompleted();
            }
            Log.e(TAG, "Completed");
        }
    }

    public void startAsync() {
        Log.e(TAG, "start Async...");
        new Thread(new InputRunnable()).start();
        new Thread(new OutputRunnable()).start();
    }

    private void processInput() {
        while (!mInputEOS) {
            int inputBufferIndex = mDecoder.dequeueInputBuffer(-1);
            if (inputBufferIndex >= 0) {
                ByteBuffer inputBuffer = mInputBuffers[inputBufferIndex];
                int sampleSize = mExtractor.readSampleData(inputBuffer, 0);
                if (sampleSize >= 0) {
                    mDecoder.queueInputBuffer(inputBufferIndex, 0, sampleSize, 0, 0);
                    mExtractor.advance();
                } else  {
                    Log.e(TAG, "input EOS");
                    mInputEOS = true;
                    mDecoder.queueInputBuffer(inputBufferIndex, 0, 0, 0,
                             MediaCodec.BUFFER_FLAG_END_OF_STREAM );
                }
            }
        }
    }

    private void processOutput() {
        while (!mOutputEOS) {
            int outputBufferIndex = mDecoder.dequeueOutputBuffer(info, -1);
            if (outputBufferIndex >= 0) {
                ByteBuffer outputBuffer = mOutputBuffers[outputBufferIndex];
                byte[] chunkPCM = new byte[info.size];
                outputBuffer.get(chunkPCM);
                outputBuffer.clear();
                try {
                    mOutFile.write(chunkPCM);
                } catch (IOException e) {
                    e.printStackTrace();
                }
                mDecoder.releaseOutputBuffer(outputBufferIndex, false);
                if ((info.flags & MediaCodec.BUFFER_FLAG_END_OF_STREAM) != 0) {
                    Log.e(TAG, "output EOS");
                    mOutputEOS = true;
                }
            }
        }
    }

    public void release() {
        try {
            if (mOutFile != null) {
                mOutFile.close();
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            mOutFile = null;
        }
        if (mDecoder != null) {
            mDecoder.stop();
            mDecoder.release();
            mDecoder = null;
        }
        if (mExtractor != null) {
            mExtractor.release();
            mExtractor = null;
        }
        mOutputEOS = false;
        mInputEOS = false;

    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值