【问题标题】:Android MediaCodec 3gpp encoder output buffer contains incorrect bytesAndroid MediaCodec 3gpp 编码器输出缓冲区包含不正确的字节
【发布时间】:2013-07-09 14:10:54
【问题描述】:

我正在尝试将来自 MIC 的音频流编码为 3gpp (AMR-NB)。问题是输出缓冲区包含奇怪的数据。代码和输出如下:

创建媒体编码器:

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();

来自 MIC 的 PCM 数据似乎是正确的(存储到文件中,用 Audacity 收听)

读取编码字节(缓冲区,在线程中运行):

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 

我用谷歌搜索并没有找到任何帮助。关于 MediaCodec 使用的 Android 文档也不是很好 - 在 outputbuffer 上下文中使用 ByteBuffer.clear() 进行了大量试验和错误。

最好的问候, 阿赫提。

【问题讨论】:

  • outputBuffer 的位置和限制可能在缓冲区交给您时设置不正确。试试outputBuffer.position(bufferInfo.offset)outputBuffer.limit(bufferInfo.offset + bufferInfo.size)

标签: android amr 3gp android-mediacodec


【解决方案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();

将其保留在这里以供将来参考,因为很难找到简单的代码来查看实现。

【讨论】:

  • flip() 设置limit=position 然后position=0clear() 设置limit=capacity 然后position=0。我不确定在提交缓冲区后调用 flip() 有什么好处。
猜你喜欢
  • 1970-01-01
  • 2014-10-06
  • 1970-01-01
  • 2016-05-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-11-30
  • 1970-01-01
相关资源
最近更新 更多