我正在尝试使用OMX.google.mp3.decoder在Android中解码mp3并使用AudioTrack播放它但返回失败
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
这是我的解码器设置代码(尝试使用从4kb到64kb的playBufSize但在解码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数据(从android到android的流式mp3数据)
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);
}
}
我使用了4kb到64kb的缓冲区大小(在playData字节数组中接收到的mp3数据的大小)但仍然得到mp3解码器错误。准确地获取错误 decoder.queueInputBuffer(inputBufferIndex,0,playData.length,0,0); 怎么解决? 我们需要在解码之前跳过Mp3标头吗?
答案 0 :(得分:1)
“mp3解码器返回错误2”中的数字2似乎意味着UNSUPPORTED_FREE_BITRATE。从引用的SoftMP3源代码来看,似乎mp3具有“自由比特率”和/或保留频率,SoftMP3不支持。
那应该是罕见的。我发现错误的数据更有可能被送入解码器(特别是因为“自由比特率”恰好是mp3标准中的数字0)。
我注意到dequeInputBuffer()只被调用一次。我认为问题在于它应该每圈都被调用;见Synchronous Processing using Buffer Arrays。