没有mediaextractor

时间:2015-05-14 07:34:53

标签: android mp3 decoding pcm mediacodec

我正在尝试使用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标头吗?

1 个答案:

答案 0 :(得分:1)

“mp3解码器返回错误2”中的数字2似乎意味着UNSUPPORTED_FREE_BITRATE。从引用的SoftMP3源代码来看,似乎mp3具有“自由比特率”和/或保留频率,SoftMP3不支持。

那应该是罕见的。我发现错误的数据更有可能被送入解码器(特别是因为“自由比特率”恰好是mp3标准中的数字0)。

我注意到dequeInputBuffer()只被调用一次。我认为问题在于它应该每圈都被调用;见Synchronous Processing using Buffer Arrays