Android – Decoding AAC using MediaCodec API on Android

aacandroid

I'm trying to used the MediaCodec API on Android to decode an AAC stream. (It's raw AAC.) I tried using the MediaFormat.createAudioFormat() to create the format object to pass to MediaCodec.configure(), but I kept getting errors when using AAC (audio/mp4a-latm). (It works with MP3 (audio/mpeg) though…)

Finally I created a MediaExtractor for an AAC file and looked at the format object it was producing. I saw that it included the key "csd-0" for a ByteBuffer composed of two bytes both with the value 0x12. If I include that key and value in the format object that I used to configure the AAC codec, everything works.

Does anyone have an idea what is going on? The documentation states that I shouldn't configure that key. Does anyone have a pointer to MediaCodec examples to decode AAC files without using MediaExtractor to generate the format object?

Best Answer

Yes, the codec config 2 bytes are the initial you receive. And yes it is raw aac data blocks. You can see how I derive the format below while encoding. I initially tried to follow the documentation, which said they are in latm format, and tried to parse that. I then found some 'diff' on the android documentation that said the output was indeed raw blocks. Knowing that then, it was simply a matter of choosing a container for my needs. In particular, I needed the adts container rather than flv or mp4.

Copying the payload data into an array that is large enough for your container, just add on your bits. So after scouring the internet for my solution I produced the following code:

profile = (configParams[0]>>3)&0x1f;

frequency_index = (this.configParams[0]&0x7) <<1 | (this.configParams[1]>>7) &0x1;

channel_config = (this.configParams[1]>>3) &0xf;

int finallength = encoded_length + 7;       
ENCodedByteArray[0] = (byte) 0xff;
ENCodedByteArray[1] = (byte) 0xf1;
ENCodedByteArray[2] = (byte) ( ((profile - 1) << 6) + (frequency_index << 2) +(channel_config >> 2));
ENCodedByteArray[3] = (byte) (((channel_config & 0x3) << 6) + (finallength >> 11));
ENCodedByteArray[4] = (byte)( (finallength & 0x7ff) >> 3);
ENCodedByteArray[5] = (byte) (((finallength & 7) << 5) + 0x1f) ;
ENCodedByteArray[6] = (byte) 0xfc;

Using something like this:

byte chunkADTS[]=new byte[info.size + 7];
fillInADTSHeader(chunkADTS,info.size);
outputBuffers[bR].get(chunkADTS,7,info.size);
buffer.pushData(chunkADTS);