2013-07-11 60 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

相关问题