我需要发送语音留言,但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?