Ошибка декодирования MP3 с использованием медиакодека без медиаэкстрактора

Я пытаюсь декодировать mp3 в Android с помощью OMX.google.mp3.decoder и воспроизводить его с помощью 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

Вот мой код настройки декодера (пробовал использовать playBufSize от 4kb до 64kb, но не повезло с декодированием 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 с андроида на андроид)

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);
    }
}

Я использовал размер буфера от 4 КБ до 64 КБ (размер полученных mp3-данных, полученных в байтовом массиве playData), но все еще получаю ошибку декодера mp3. Ошибка получения точно в decoder.queueInputBuffer(inputBufferIndex, 0, playData.length, 0, 0); Как это решить? Нужно ли пропускать заголовок Mp3 перед декодированием?


person Arunraj Shanmugam    schedule 14.05.2015    source источник


Ответы (1)


Число 2 в строке «декодер mp3 вернул ошибку 2», по-видимому, означает UNSUPPORTED_FREE_BITRATE. Судя по указанному исходному коду SoftMP3, кажется, что mp3 имеет «бесплатную скорость передачи данных» и/или зарезервированную частоту, которая не поддерживается SoftMP3.

Это должно быть редко. Я бы счел более вероятным, что в декодер подаются неверные данные (тем более, что «свободный битрейт» является числом 0 в стандарте mp3).

Я заметил, что dequeInputBuffer() вызывается только один раз. Я думаю, проблема в том, что его нужно вызывать каждый круг; см. Синхронная обработка с использованием буферных массивов.

person volley    schedule 30.11.2015
comment
Спасибо Волей. Одной из причин этой ошибки декодера является MediaFormat.KEY_BIT_RATE, который является параметром кодировщика. - person Arunraj Shanmugam; 21.01.2016