MediaCodec进行AAC编码(AudioRecord采集录音)

一、使用AudioRecord采集录音,创建一个采集录音管理类AudioRecorderManager.java

public class AudioRecorderManager {

    private static final String TAG = "AudioRecorderManager";

    // 音频获取
    private final static int SOURCE = MediaRecorder.AudioSource.MIC;

    // 设置音频采样率,44100是目前的标准,但是某些设备仍然支 2050 6000 1025
    private final static int SAMPLE_HZ = 44100;

    // 设置音频的录制的声道CHANNEL_IN_STEREO为双声道,CHANNEL_CONFIGURATION_MONO为单声道
    private final static int CHANNEL_CONFIG = AudioFormat.CHANNEL_IN_MONO;

    // 音频数据格式:PCM 16位每个样本保证设备支持。PCM 8位每个样本 不一定能得到设备支持
    private final static int FORMAT = AudioFormat.ENCODING_PCM_16BIT;

    private AudioRecord mAudioRecord = null;
    private int bufferSizeInBytes = 0;

    private boolean start = false;
    private Thread recordThread;
    private int readsize = 0;
    private int mBufferSize;
    public interface AudioDataListener {
        void audioData(byte[] data, int readSize);
    }

    private AudioDataListener audioDataListener;

    public void setAudioDataListener(AudioDataListener audioDataListener) {
        this.audioDataListener = audioDataListener;
    }

    public AudioRecorderManager() {
        bufferSizeInBytes = AudioRecord.getMinBufferSize(SAMPLE_HZ, CHANNEL_CONFIG, FORMAT);
        mAudioRecord = new AudioRecord(SOURCE, SAMPLE_HZ, CHANNEL_CONFIG, FORMAT, bufferSizeInBytes);
        mBufferSize = 4 * 1024;
    }

    public void startRecord() {
        recordThread = new Thread() {
            @Override
            public void run() {
                    if(mAudioRecord == null){
                        mAudioRecord = new AudioRecord(SOURCE, SAMPLE_HZ, CHANNEL_CONFIG, FORMAT, bufferSizeInBytes);
                    }
                    mAudioRecord.startRecording();
                    byte[] audioData = new byte[mBufferSize];
                    int readsize = 0;
                    while (start) {
                        try {
                            readsize += mAudioRecord.read(audioData, readsize, mBufferSize);
                            byte[] ralAudio = new byte[readsize];
                            //每次录音读取4K数据
                            System.arraycopy(audioData, 0, ralAudio, 0, readsize);
                            if (audioDataListener != null) {
                                audioDataListener.audioData(audioData, readsize);
                            }
                            readsize = 0;
                            Arrays.fill(audioData, (byte)0);

                        }catch(Exception e) {
                            e.printStackTrace();
                        }
                    }
                }

        };
        start = true;
        recordThread.start();
    }

    public void stopRecord() {
        if(mAudioRecord != null){
            start = false;
            mAudioRecord.stop();
            mAudioRecord.release();
            mAudioRecord = null;
        }
    }
    public boolean isStart()
    {
        return start;
    }
}

采用AudioRecord进行录音,添加一个接口AudioDataListener类,该接口中audioData()方法便于把读取到的原始音频PCM数据回调出去进行编码成AAC。
二、获取到了原始数据PCM,然后采用MediaCodec进行编码为AAC。
1、初始化音频编码器

 private MediaCodec audioEncodec;
 private MediaFormat audioFormat;
 private MediaCodec.BufferInfo audioBufferinfo;
 initAudioEncodec(MediaFormat.MIMETYPE_AUDIO_AAC, 44100, 1);
 private void initAudioEncodec(String mimeType, int sampleRate, int channelCount)
    {
            this.sampleRate = sampleRate;
            audioBufferinfo = new MediaCodec.BufferInfo();
            audioFormat = MediaFormat.createAudioFormat(mimeType, sampleRate, channelCount);
            audioFormat.setInteger(MediaFormat.KEY_BIT_RATE, ABITRATE);
            audioFormat.setInteger(MediaFormat.KEY_MAX_INPUT_SIZE, 0);
    }

2、初始化采集录音管理

  private void initPCMRecord()
    {
        mAudioRecorderManager = new AudioRecorderManager();
        mAudioRecorderManager.setAudioDataListener(new AudioRecorderManager.AudioDataListener() {
            @Override
            public void audioData(byte[] audioData, int readSize) {
                if(mAudioRecorderManager.isStart())
                {
                    //LogUtils.getInstance().I(TAG, "audioData  =   audioData  " + audioData.length);
                    putPCMData(audioData, readSize);
                }
            }
        });
    }

3、将获取到的音频数据PCM添加到MediaCodec 编码器输入缓冲队列中

  public void putPCMData(byte[] buffer, int size)
    {
        if(audioEncodecThread != null && buffer != null && size > 0)
        {
            int inputBufferindex = audioEncodec.dequeueInputBuffer(0);
            if(inputBufferindex >= 0)
            {
                ByteBuffer byteBuffer = audioEncodec.getInputBuffers()[inputBufferindex];
                byteBuffer.clear();
                byteBuffer.put(buffer);
                long pts = getAudioPts(size, sampleRate);
                audioEncodec.queueInputBuffer(inputBufferindex, 0, size, pts, 0);
            }
        }
    }
     private long getAudioPts(int size, int sampleRate)
    {
        audioPts += (long)(1.0 * size / (sampleRate * 2 * 2) * 1000000.0);
        return audioPts;
    }

4、开始把音频数据编码为AAC,其中定义一个接口OnMediaInfoListener,该接口中定义了一个onAudioInfo方法,该方法可以把编码出来的AAC数据进行保存起来或者推流

private long audioPts = 0;
  public void startAudioEncode() {
        try {
            audioEncodec = MediaCodec.createEncoderByType(MediaFormat.MIMETYPE_AUDIO_AAC);
            audioEncodec.configure(audioFormat, null, null, MediaCodec.CONFIGURE_FLAG_ENCODE);
            audioEncodec.start();
            startAudio();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
    //开启一个线程进行编码
      public void startAudio(){
        audioEncodecThread = new Thread() {
            @Override
            public void run() {
                isAudioEncoder = true;
                pts = 0;
                if(audioEncodec!=null){
                    while(isAudioEncoder)
                    {
                        int outputBufferIndex = audioEncodec.dequeueOutputBuffer(audioBufferinfo, 0);
                        if(outputBufferIndex == MediaCodec.INFO_OUTPUT_FORMAT_CHANGED)
                        {
                        }
                        else
                        {
                            while(outputBufferIndex >= 0)
                            {
                                ByteBuffer outputBuffer = audioEncodec.getOutputBuffers()[outputBufferIndex];
                                outputBuffer.position(audioBufferinfo.offset);
                                outputBuffer.limit(audioBufferinfo.offset + audioBufferinfo.size);
                                if(pts == 0)
                                {
                                    pts = audioBufferinfo.presentationTimeUs;
                                }
                                audioBufferinfo.presentationTimeUs = audioBufferinfo.presentationTimeUs - pts;

                                byte[] data = new byte[outputBuffer.remaining()];
                                outputBuffer.get(data, 0, data.length);
                                if(onMediaInfoListener != null)
                                {
                                    onMediaInfoListener.onAudioInfo(data);
                                }
                               // mFlvPacker.onAudioData(outputBuffer, audioBufferinfo);

                                audioEncodec.releaseOutputBuffer(outputBufferIndex, false);
                                outputBufferIndex = audioEncodec.dequeueOutputBuffer(audioBufferinfo, 0);
                            }
                        }
                    }
                }
            }
        };
        audioEncodecThread.start();
    }
      private OnMediaInfoListener onMediaInfoListener;
    public void setOnMediaInfoListener(OnMediaInfoListener onMediaInfoListener) {
        this.onMediaInfoListener = onMediaInfoListener;
    }
    public interface OnMediaInfoListener
    {
        void onAudioInfo(byte[] data);
    }

5、停止录音

  public void stopAudio(){
        try {
            if(audioEncodec!=null){
                isAudioEncoder = false;
                audioEncodec.stop();
                audioEncodec.release();
            }
        } catch (Exception e){
            e.printStackTrace();
            Log.e(TAG, "stopAudio  e.getMessage():   " + e.getMessage());
        }

    }
评论 7
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值