I am trying to decode mp3 in android using OMX.google.mp3.decoder and play it using AudioTrack but it gets failed returning
I/OMXClient( 3506): Using client-side OMX mux.
I/SW ( 3506): Codec ==== codec name:OMX.google.mp3.decoder
I/SW ( 3506): type supported by codec:audio/mpeg
I/SW ( 3506): is encoder:false
E/OMXNodeInstance( 3506): OMX_GetExtensionIndex failed
I/SWAudioPlayer( 3506): decoder ready: true
E/SoftMP3 ( 3506): mp3 decoder returned error 2
E/ACodec ( 3506): [OMX.google.mp3.decoder] ERROR(0x80001001)
E/MediaCodec( 3506): Codec reported an error. (omx error 0x80001001, internalError -2147483648)
E/SWAudioPlayer( 3506): Exception in audio play java.lang.IllegalStateException
Here is my decoder setup code (tried using playBufSize from 4kb to 64kb but no luck in decoding mp3)
private static MediaCodecInfo getCodecInfo(String mimeType) {
String info = "";
int numCodecs = MediaCodecList.getCodecCount();
for (int i = 0; i < numCodecs; i++) {
MediaCodecInfo codecInfo = MediaCodecList.getCodecInfoAt(i);
String[] types = codecInfo.getSupportedTypes();
for (int j = 0; j < types.length; j++) {
if (types[j].equalsIgnoreCase(mimeType)) {
info += "codec name:" + codecInfo.getName() + "\n";
info += "type supported by codec:" + types[j] + "\n";
info += "is encoder:" + codecInfo.isEncoder() + "\n";
CodecCapabilities codecCapabilities = codecInfo.getCapabilitiesForType(types[j]);
Log.i("SW","Codec ==== "+ info);
for(final CodecProfileLevel codecProfileLevel : codecCapabilities.profileLevels) {
Log.i("SW","codec level "+codecProfileLevel.level);
Log.i("SW","codec profile "+codecProfileLevel.profile);
}
return codecInfo;
}
}
}
return null;
}
private boolean setDecoder() throws IOException {
String mimeType = "audio/mpeg";
int rate = 48000;
decoder = MediaCodec.createDecoderByType(mimeType);
mCodecInfo = getCodecInfo(mimeType);
if(mCodecInfo != null) {
MediaFormat format = new MediaFormat();
format.setString(MediaFormat.KEY_MIME, mimeType);
format.setInteger(MediaFormat.KEY_CHANNEL_COUNT, 2);
format.setInteger(MediaFormat.KEY_SAMPLE_RATE, rate);
format.setInteger(MediaFormat.KEY_BIT_RATE, 320 * 1024); /* 320 kbps */
format.setInteger(MediaFormat.KEY_MAX_INPUT_SIZE, playBufSize);
decoder.configure(format, null, null, 0);
return true;
}
return false;
}`
Mp3 data is received in buffer from server (streaming mp3 data from android to android)
public void play_audio() {
inputBuffers = decoder.getInputBuffers();
outputBuffers = decoder.getOutputBuffers();
inputBufferIndex = decoder.dequeueInputBuffer(-1);
try {
if (inputBufferIndex >= 0)
{
inputBuffer = inputBuffers[inputBufferIndex];
inputBuffer.clear();
inputBuffer.put(playData);
decoder.queueInputBuffer(inputBufferIndex, 0, playData.length, 0, 0);
}
bufferInfo = new MediaCodec.BufferInfo();
outputBufferIndex = decoder.dequeueOutputBuffer(bufferInfo, 0);
Log.i("SWA","outputBufferIndex "+outputBufferIndex);
while (outputBufferIndex >= 0)
{
outputBuffer = outputBuffers[outputBufferIndex];
outputBuffer.position(bufferInfo.offset);
outputBuffer.limit(bufferInfo.offset + bufferInfo.size);
Log.i("SWA","bufferInfo.offset "+bufferInfo.offset);
Log.i("SWA","bufferInfo.size "+bufferInfo.size);
outData = new byte[bufferInfo.size];
outputBuffer.get(outData);
Log.i("SWA", outData.length + " bytes decoded");
audioTrack.write(outData, 0, outData.length);
decoder.releaseOutputBuffer(outputBufferIndex, false);
outputBufferIndex = decoder.dequeueOutputBuffer(bufferInfo, 0);
}
}
catch (Exception e)
{
Log.e("SWAudioPlayer","Exception in audio play "+e);
}
}
I have used buffer size from 4kb to 64kb (size of received mp3 data received in playData byte array) but still getting mp3 decoder error.Getting error exactly at decoder.queueInputBuffer(inputBufferIndex, 0, playData.length, 0, 0); How to resolve it? Do we need to skip Mp3 header before decoding?
The number 2 in "mp3 decoder returned error 2" seems to mean UNSUPPORTED_FREE_BITRATE. Judging by the referenced SoftMP3 source code it seems the mp3 has "free bit rate" and/or reserved frequency, which is not supported by SoftMP3.
That should be rare. I'd find it more likely that bad data is fed into the decoder (especially since "free bit rate" happens to be the number 0 in mp3 standard).
I notice that dequeInputBuffer() is only called once. I think the problem is that it should be called every lap; see Synchronous Processing using Buffer Arrays.