Question

I'm trying to encode Audio stream from MIC as 3gpp (AMR-NB). The problem is that the ouput buffer contains weird data. Code and output follows:

Creating media encoder:

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 data from MIC seems to be correct (stored to file, listened with Audacity)

Reading encoded bytes (buffers, running in thread):

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

And the output is:

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 

I've googled and have found no help. Android docs on MediaCodec usage are not excellent, too - lot of trial and error with ByteBuffer.clear() usage in outputbuffer context.

best regards, Ahti.

Was it helpful?

Solution

To all the fellow sufferers out there, answering my own question.

The real issue actually was feeding raw PCM data to encoder input. Android docs are vague on how to exactly feed in the data into the input buffer (ok, it has actually more to do with ByteBuffer behaviour to be honest):

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

My interpretation was to add data as following:

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

The above code has one bit missing: flip the position of the ByteBuffer!

inputBuffers[inputBufferIndex].flip();

Keeping it here for the future reference as it was quite hard to find simple code to see the implementation.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top