使用MediaCodec将PCM编码为amr-nb

时间:2017-10-23 14:25:20

标签: android mediacodec amr

我需要发送语音留言,但PCM音频太大,所以我尝试使用MediaCodec将PCM转换为AMR-NB。我到处搜索,但我无法正确实施。我需要你的帮助。

private void sendAudioFile() {
    initEncoder();
    translaterThread = new Thread(translaterTask);
    translaterThread.start();
    RLog.d("AudioRecordManager", "sendAudioFile path = " + this.mAudioPath);
    RLog.d("AudioRecordManager", "sendAmrFile path = " + this.mAmrPath);

    if(this.mAmrPath != null) {
        File file = new File(this.mAmr.getPath());
        if(!file.exists() || file.length() == 0L) {
            RLog.e("AudioRecordManager", "sendAudioFile fail cause of file length 0 or audio permission denied");
            return;
        }

        CustomizeMessage customizeMessage = CustomizeMessage.obtain(this.mAmrPath);
        sendMessage(mTargetId,  customizeMessage), (String)null, (String)null);
}

private boolean initEncoder() {
    try {
        encoder = MediaCodec.createEncoderByType(MediaFormat.MIMETYPE_AUDIO_AMR_NB);
        MediaFormat format = new MediaFormat();
        format.setString(MediaFormat.KEY_MIME, MediaFormat.MIMETYPE_AUDIO_AMR_NB);
        format.setInteger(MediaFormat.KEY_SAMPLE_RATE, mSampleRate);
        format.setInteger(MediaFormat.KEY_CHANNEL_COUNT, 1);
        format.setInteger(MediaFormat.KEY_BIT_RATE, BIT_RATE);
        encoder.configure(format, null, null, MediaCodec.CONFIGURE_FLAG_ENCODE);
        return true;
    } catch (IOException e) {
        Log.e(TAG, "init encoder failed.");
        e.printStackTrace();
    }

    return false;
}

private Runnable translaterTask = new Runnable() {
    @Override
    public void run() {

        FileInputStream in = null;
        FileOutputStream out = null;
        byte[] data = new byte[minBufferSize];
        ByteBuffer[] inputBuffers;
        ByteBuffer[] outputBuffers;

        ByteBuffer inputBuffer;
        ByteBuffer outputBuffer;

        MediaCodec.BufferInfo bufferInfo;
        int inputBufferIndex;
        int outputBufferIndex;

        byte[] outData;

        encoder.start();

        try {
            in = new FileInputStream(mAudioPath.getPath());
            out = new FileOutputStream(mAmrPath.getPath());
            while (in.read(data) != -1) {
                inputBuffers = encoder.getInputBuffers();
                outputBuffers = encoder.getOutputBuffers();
                inputBufferIndex = encoder.dequeueInputBuffer(-1);

                if (inputBufferIndex >= 0) {
                    inputBuffer = inputBuffers[inputBufferIndex];
                    inputBuffer.clear();

                    inputBuffer.put(data);

                    encoder.queueInputBuffer(inputBufferIndex, 0, data.length, 0, 0);
                }

                bufferInfo = new MediaCodec.BufferInfo();
                outputBufferIndex = encoder.dequeueOutputBuffer(bufferInfo, 0);

                while (outputBufferIndex >= 0) {
                    try {
                        outputBuffer = outputBuffers[outputBufferIndex];

                        outputBuffer.position(bufferInfo.offset);
                        outputBuffer.limit(bufferInfo.offset + bufferInfo.size);

                        outData = new byte[bufferInfo.size];
                        outputBuffer.get(outData);
                        out.write(outData);
                        Log.d("AudioEncoder", outData.length + " bytes encoded");

                        encoder.releaseOutputBuffer(outputBufferIndex, false);
                        outputBufferIndex = encoder.dequeueOutputBuffer(bufferInfo, 0);
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                }
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (encoder != null) {
                encoder.stop();
                encoder.release();
                encoder = null;
            }
        }


    }
};

当我点击发送按钮时,我得到了线程异常:java.nio.BufferOverflowException

10-22 22:43:22.280 25633-25819/com.jike.hat E/AndroidRuntime: FATAL EXCEPTION: Thread-594
                                                                         Process: com.jikexueyuan.cicada_chat, PID: 25633
                                                                         java.nio.BufferOverflowException
                                                                             at java.nio.Buffer.checkPutBounds(Buffer.java:183)
                                                                             at java.nio.DirectByteBuffer.put(DirectByteBuffer.java:356)
                                                                             at java.nio.ByteBuffer.put(ByteBuffer.java:721)
                                                                             at com.jikexueyuan.cicada_chat.MyAudioRecordManager$4.run(MyAudioRecordManager.java:385)
                                                                             at java.lang.Thread.run(Thread.java:831)

参数设置如下:

private int mSampleRate = 16000;
private int mChannelConfig =  AudioFormat.CHANNEL_IN_MONO;
private int mAudioEncodingBitRate = AudioFormat.ENCODING_PCM_16BIT;
private int BIT_RATE = 15850;

那么,编码器或参数集有问题吗?为什么BufferOverflow?

0 个答案:

没有答案