2013-07-11 89 views
1

我試圖從MIC編碼音頻流爲3gpp(AMR-NB)。問題是輸出緩衝區包含奇怪的數據。代碼和輸出如下:Android MediaCodec 3gpp編碼器輸出緩衝區包含不正確的字節

創建媒體編碼器:從MIC

MediaFormat format = MediaFormat.createAudioFormat("audio/3gpp", 8*1024, 1); 
format.setInteger(MediaFormat.KEY_BIT_RATE, 8*1024); 
format.setInteger(MediaFormat.KEY_MAX_INPUT_SIZE, minBufSize); 
MediaCodec encoder = MediaCodec.createEncoderByType("audio/3gpp"); 
encoder.configure(format, null, null, MediaCodec.CONFIGURE_FLAG_ENCODE); 
encoder.start(); 

PCM數據似乎是正確的(存儲到文件,聽着無畏)

讀取編碼的字節(緩衝區,在線程中運行):

ByteBuffer[] outputBuffers = encoder.getOutputBuffers(); 
int outputBufferIndex = 0; 
while(outputBufferIndex >= 0) 
{ 
    MediaCodec.BufferInfo bufferInfo = new MediaCodec.BufferInfo(); 
    outputBufferIndex = encoder.dequeueOutputBuffer(bufferInfo, -1); 
    if (outputBufferIndex >= 0) 
    { 
     ByteBuffer outputBuffer = outputBuffers[outputBufferIndex]; 
     byte[] outData = new byte[bufferInfo.size]; 
     outputBuffer.get(outData); 
     outputBuffer.clear(); 
     encoder.releaseOutputBuffer(outputBufferIndex, false); 
     Log.d(LOG_TAG_ENCODING, util.bytesToString(outData)); 
    } 
    else if (outputBufferIndex == MediaCodec.INFO_OUTPUT_BUFFERS_CHANGED) 
    { 
     outputBuffers = encoder.getOutputBuffers(); 
    } 
} 

並且輸出是:

07-11 13:13:58.622: 34 6c 1e 08 27 80 05 28 56 40 00 00 03 00 00 00 00 00 00 00 00 00 00 00 00 00 00 
07-11 13:13:58.632: 34 6c 1e 08 27 80 05 28 56 40 00 00 03 00 00 00 00 00 00 00 00 00 00 00 00 00 00 
07-11 13:13:58.667: 34 ff d9 08 27 80 05 28 56 40 00 00 03 00 00 00 00 00 00 00 00 00 00 00 00 00 00 
07-11 13:13:58.672: 34 6c 1e 08 27 80 05 28 56 40 00 00 03 00 00 00 00 00 00 00 00 00 00 00 00 00 00 
07-11 13:13:58.677: 34 6c 1e 08 27 80 05 28 56 40 00 00 03 00 00 00 00 00 00 00 00 00 00 00 00 00 00 

我google了,並沒有找到任何幫助。關於MediaCodec使用情況的Android文檔也不是很好 - 在輸出緩衝區上下文中使用ByteBuffer.clear()方法的嘗試和錯誤很多。

最好的問候, Ahti。

+0

緩衝區交給您時,'outputBuffer'的位置和限制可能無法正確設置。嘗試'outputBuffer.position(bufferInfo.offset)'和'outputBuffer.limit(bufferInfo.offset + bufferInfo.size)'。 – fadden

回答

1

給那裏的所有同胞回答我自己的問題。

真正的問題實際上是將原始PCM數據送入編碼器輸入。 Android的文檔是關於如何在數據準確送入輸入緩衝器模糊的(好吧,它實際上更多的是與ByteBuffer的行爲是誠實的):

int inputBufferIndex = codec.dequeueInputBuffer(timeoutUs); 
if (inputBufferIndex >= 0) { 
    // fill inputBuffers[inputBufferIndex] with valid data 
    ... 
    codec.queueInputBuffer(inputBufferIndex, ...); 
} 

我的解釋是將數據添加如下:

inputBuffers[inputBufferIndex].clear(); 
inputBuffers[inputBufferIndex].put(audioPCMbuffer); 
codec.queueInputBuffer(inputBufferIndex, ...); 

上面的代碼有一點遺漏:翻轉ByteBuffer的位置!

inputBuffers[inputBufferIndex].flip(); 

將它留在這裏供將來參考,因爲很難找到簡單的代碼來查看實現。

+0

'flip()'設置'limit = position'然後'position = 0'。 'clear()'設置'limit = capacity'然後'position = 0'。我不確定在提交緩衝區後調用'flip()'會帶來什麼好處。 – fadden

相關問題