Вывод буфера Android MediaCodec 3gpp содержит неправильные байты

59
7

Я пытаюсь кодировать аудиопоток от 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();

Данные PCM от MIC кажутся правильными (хранятся в файле, прослушиваются 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

Я googled и не нашел никакой помощи. Android-документы на использование MediaCodec также не очень хороши - много проб и ошибок с использованием ByteBuffer.clear() в контексте outputbuffer.

С наилучшими пожеланиями, Ахти.

спросил(а) 2013-07-11T13:32:00+04:00 7 лет, 4 месяца назад
1
Решение
60

Всем тем, кто страдает от этого, отвечает на мой собственный вопрос.

Реальная проблема на самом деле заключалась в подаче сырых данных 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();

Сохраняя это здесь для будущей ссылки, поскольку было довольно сложно найти простой код, чтобы увидеть реализацию.

ответил(а) 2013-07-11T23:23:00+04:00 7 лет, 4 месяца назад
Ваш ответ
Введите минимум 50 символов
Чтобы , пожалуйста,
Выберите тему жалобы:

Другая проблема