Как декодировать аудио формат MPA с помощью Mediacodec в Android - PullRequest
0 голосов
/ 25 февраля 2019

Мое приложение воспроизводит потоки RTSP с помощью клиента Live555 rtsp.Поток тестирования создается VLC Player (H264 + MP3 (TS)).Видео H264 воспроизводится хорошо.Но звук (формат MPA) не воспроизводится и приложение вылетает.Я использую отдельный класс Mediacodec для декодирования видео и аудио.Я использовал mime-тип «audio / mpeg» для декодирования звука.Как я могу успешно воспроизводить аудио.

Класс аудиодекодера

public class ADecoder extends Thread {

    private static final boolean VERBOSE = true;
    private static final String LOG_TAG = ADecoder.class.getSimpleName();
    private static final String AUDIO_FORMAT = "audio/mpeg";
    private static final long mTimeoutUs = 10000l;

    private MediaCodec mMediaCodec;
    volatile boolean m_bConfigured;
    volatile boolean m_bRunning;
    long startMs;
    Bitmap lastimage = null;
    ByteBuffer[] outputBuffers = null;
    private AudioTrack audioTrack;

    public ADecoder() {
    }

    public void decode(byte[] encodedData) {
        if(!m_bConfigured) {
            Configure(encodedData);
        }
        if(m_bConfigured) {
            decodeData(encodedData);
        }
    }

    public void Start() {
        if(m_bRunning)
            return;
        m_bRunning = true;
        start();
    }

    public void Stop() {
        if(!m_bRunning)
            return;
        m_bRunning = false;
    }

    private void _Stop(){
        if( mMediaCodec != null ) {
            Log.i(LOG_TAG, "Trying to Stop & Release Audio Decoder");
            try {
                Thread.sleep(100);
            } catch (InterruptedException ignore) {
            }
            mMediaCodec.stop();
            mMediaCodec.release();
        }

        if( audioTrack != null ){
            audioTrack.stop();
            audioTrack.release();
        }
    }

    private void Configure( byte[] csd0) {
        try {
            if (m_bConfigured) {
                Log.e(LOG_TAG, "Audio Decoder is already configured");
                return;
            }

            MediaFormat format = MediaFormat.createAudioFormat(AUDIO_FORMAT, 44100, 2);
            byte[] bytes = new byte[]{(byte) 0x12, (byte) 0x12};
            ByteBuffer bb = ByteBuffer.wrap(bytes);
            format.setByteBuffer("csd-0", bb);

            try {
                mMediaCodec = MediaCodec.createDecoderByType(AUDIO_FORMAT);
            } catch (IOException e) {
                Log.d(LOG_TAG, "Failed to create Audio Decodec: " + e.getMessage());
            }

            startMs = System.currentTimeMillis();
            mMediaCodec.configure(format, null, null, 0);
            if (VERBOSE) Log.d(LOG_TAG, "Audio Decoder configured.");

            mMediaCodec.start();
            Log.d(LOG_TAG, "Audio Decoder initialized.");

            audioTrack = new AudioTrack(AudioManager.STREAM_MUSIC,
                    44100, AudioFormat.CHANNEL_OUT_STEREO,
                    AudioFormat.ENCODING_PCM_16BIT,
                    44100,
                    AudioTrack.MODE_STREAM);

            audioTrack.play();
            m_bConfigured = true;
        } catch (Exception e){
            e.printStackTrace();
        }
    }

    private void decodeData(byte[] data) {
        try {
            if (!m_bConfigured) {
                Log.e(LOG_TAG, "Audio Decoder is not configured yet.");
                return;
            }
            int inIndex = mMediaCodec.dequeueInputBuffer(mTimeoutUs);
            if (inIndex >= 0) {
                ByteBuffer buffer;
                if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) {
                    buffer = mMediaCodec.getInputBuffers()[inIndex];
                    buffer.clear();
                } else {
                    buffer = mMediaCodec.getInputBuffer(inIndex);
                }
                if (buffer != null) {
                    buffer.put(data);
                    long presentationTimeUs = System.currentTimeMillis() - startMs;
                    mMediaCodec.queueInputBuffer(inIndex, 0, data.length, presentationTimeUs, 0);
                }
            }
        } catch (Exception e){
            e.printStackTrace();
        }
    }

    @Override
    public void run() {
        try {
            while(m_bRunning) {
                if(m_bConfigured) {
                    outputBuffers = mMediaCodec.getOutputBuffers();
                    MediaCodec.BufferInfo info = new MediaCodec.BufferInfo();
                    int outIndex = mMediaCodec.dequeueOutputBuffer(info, mTimeoutUs);
                    if(outIndex >= 0) {
                        ByteBuffer buffer = outputBuffers[outIndex];
                        byte[] decoded_chunk = new byte[info.size];
                        buffer.get(decoded_chunk); // Read the buffer all at once
                        buffer.clear();
                        audioTrack.write(decoded_chunk, info.offset, info.offset + info.size);
                        mMediaCodec.releaseOutputBuffer(outIndex, true);
                    } else {
                        if( outIndex == MediaCodec.INFO_OUTPUT_BUFFERS_CHANGED ){
                            Log.i(LOG_TAG, "Info output buffers changed");
                        } else if( outIndex == MediaCodec.INFO_OUTPUT_FORMAT_CHANGED ){
                            Log.i(LOG_TAG, "New format " + mMediaCodec.getOutputFormat());
                        } else if( outIndex == MediaCodec.INFO_OUTPUT_FORMAT_CHANGED ){
                            Log.e(LOG_TAG, "dequeueOutputBuffer timed out!");
                        }
                    }
                } else {
                    try {
                        Thread.sleep(10);
                    } catch (InterruptedException ignore) {
                    }
                }
            }
        } catch (Exception e){
            e.printStackTrace();
        }
        finally {
            _Stop();
        }
    }
}

Сведения о сбое приложения

E/ACodec: [OMX.google.mp3.decoder] ERROR(0x80001001)
E/ACodec: signalError(omxError 0x80001001, internalError -2147483648)
E/MediaCodec: Codec reported err 0x80001001, actionCode 0, while in state 6
I/MediaCodec: name=video/avc isType=true encoder=false
I/MediaCodec: (0x94673800) init name(video/avc) isType(1) encoder(0)
I/OMXClient: Treble IOmx obtained
W/System.err: java.lang.IllegalStateException
W/System.err:     at android.media.MediaCodec.native_dequeueOutputBuffer(Native Method)
W/System.err:     at android.media.MediaCodec.dequeueOutputBuffer(MediaCodec.java:2640)
W/System.err:     at com.mtxlabs.ipcamera.video.ADecoder.run(ADecoder.java:154)

Вывод отладчика Audio Decoder Init

2019-02-25 16:30:41.171  I/MediaCodec: name=audio/mpeg isType=true encoder=false
2019-02-25 16:30:41.172  I/MediaCodec: (0xa616d2c0) init name(audio/mpeg) isType(1) encoder(0)
2019-02-25 16:30:41.174  I/OMXClient: Treble IOmx obtained
2019-02-25 16:30:41.175  I/MediaCodec: (0xa616d2c0) Component Allocated (OMX.google.mp3.decoder)
2019-02-25 16:30:41.176  I/MediaCodec: (0xa616d2c0) configure surface(0x0) crypto(0x0) flags(0)
2019-02-25 16:30:41.176  D/MediaCodec: (0xa616d2c0) configure format: AMessage(what = 0x00000000) = {
          int32_t sample-rate = 44100
          string mime = "audio/mpeg"
          int32_t channel-count = 2
          Buffer csd-0 = {
            00000000:  12 12                                             ..
          }
        }

2019-02-25 16:30:41.178  I/MediaCodec: (0xa616d2c0) start
2019-02-25 16:30:41.179  D/CameraLive: #24 audio/MPA 417 bytes
2019-02-25 16:30:41.184  D/SurfaceUtils: set up nativeWindow 0x9330a008 for 448x336, color 0x7fa30c06, rotation 0, usage 0x20002900
2019-02-25 16:30:41.185  I/MediaCodec: (0xa616d2c0) kWhatStartCompleted
2019-02-25 16:30:41.187  D/ADecoder: Audio Decoder initialized.
2019-02-25 16:30:41.188  D/MediaCodec: (0xa616d2c0) [OMX.google.mp3.decoder] output format changed to: AMessage(what = 0x00000000) = {
          string mime = "audio/raw"
          int32_t channel-count = 2
          int32_t sample-rate = 44100
          int32_t pcm-encoding = 2
        }
2019-02-25 16:30:41.190  D/MediaCodec: (0xa616d040) kWhatOutputBuffersChanged
2019-02-25 16:30:41.193  D/AudioTrack: Client defaulted notificationFrames to 3675 for frameCount 11025
...