使用没有 mediaextractor 的 mediacodec 的 MP3 解码失败
MP3 decoding failed using mediacodec without mediaextractor
我正在尝试使用 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 数据(将 mp3 数据从 android 流式传输到 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);
}
}
我使用了从 4kb 到 64kb 的缓冲区大小(在 playData 字节数组中接收到的 mp3 数据的大小),但仍然出现 mp3 解码器 error.Getting 错误
decoder.queueInputBuffer(inputBufferIndex, 0, playData.length, 0, 0);
如何解决?
我们需要在解码之前跳过 Mp3 header 吗?
"mp3 decoder returned error 2"中的数字2好像是UNSUPPORTED_FREE_BITRATE的意思。从引用的 SoftMP3 源代码来看,mp3 似乎有 "free bit rate" and/or 保留频率,SoftMP3 不支持。
这应该很少见。我发现更有可能将错误数据输入解码器(特别是因为 "free bit rate" 恰好是 mp3 标准中的数字 0)。
我注意到 dequeInputBuffer() 只被调用了一次。我认为问题在于它应该在每一圈都被调用;参见 Synchronous Processing using Buffer Arrays。
我正在尝试使用 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 数据(将 mp3 数据从 android 流式传输到 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);
}
}
我使用了从 4kb 到 64kb 的缓冲区大小(在 playData 字节数组中接收到的 mp3 数据的大小),但仍然出现 mp3 解码器 error.Getting 错误 decoder.queueInputBuffer(inputBufferIndex, 0, playData.length, 0, 0); 如何解决? 我们需要在解码之前跳过 Mp3 header 吗?
"mp3 decoder returned error 2"中的数字2好像是UNSUPPORTED_FREE_BITRATE的意思。从引用的 SoftMP3 源代码来看,mp3 似乎有 "free bit rate" and/or 保留频率,SoftMP3 不支持。
这应该很少见。我发现更有可能将错误数据输入解码器(特别是因为 "free bit rate" 恰好是 mp3 标准中的数字 0)。
我注意到 dequeInputBuffer() 只被调用了一次。我认为问题在于它应该在每一圈都被调用;参见 Synchronous Processing using Buffer Arrays。