MediaCodec декодирует видео и аудио асинхронно в API 17 - PullRequest
0 голосов
/ 29 января 2019

У меня есть старое устройство с Android 4.2, на котором я пытаюсь воспроизвести видеопоток.Я использую MediaCodec и MediaExtractor, но последовательное декодирование видео и аудио кажется довольно медленным.Воспроизведение звука замедляет его почти до 20 кадров в секунду с 30, а звук заикается, но если я уберу аудиодекодер, он будет очень плавным.Есть ли способ сделать это асинхронным, чтобы при рендеринге видео не приходилось ждать аудио?Также в моем коде «extractor.getSampleTrackIndex ()», кажется, занимает большую часть времени обработки, поскольку он пытается выяснить, является ли блок данных аудио или видео дорожкой, и это, кажется, замедляет все.

extractor.setDataSource(uri);

for (int i = 0; i < extractor.getTrackCount(); i++) {
    MediaFormat format = extractor.getTrackFormat(i);
    String mime = format.getString(MediaFormat.KEY_MIME);
    if (mime.startsWith("video/")) {
        Log.d(TAG, "Found video track with format " + mime);
        mVideoTrackIndex = i;
        extractor.selectTrack(mVideoTrackIndex);
        format_h264 = format;
        videoDecoder = MediaCodec.createDecoderByType(mime);
        videoDecoder.configure(format, surface, null, 0);
        Log.d(TAG, "Found a videoDecoder for " + mime);
    } else if (mime.startsWith("audio/") && audioDecoder == null) {
        Log.d(TAG, "Found audio track with format " + mime);
        audio_mime = mime;
        audio_format = extractor.getTrackFormat(i);
        try {
            audioDecoder = MediaCodec.createDecoderByType(audio_mime);
            if (audioDecoder != null) {
                audioDecoder.configure(audio_format, null, null, 0);
                mAudioTrackIndex = i;
                extractor.selectTrack(mAudioTrackIndex);
                MediaFormat extractorTrackFormat = extractor.getTrackFormat(mAudioTrackIndex);
                mAudioSampleRate = extractorTrackFormat.getInteger(MediaFormat.KEY_SAMPLE_RATE);
                Log.d(TAG, "Found an audioDecoder for " + mime);
            }
        } catch (Exception e) {
            Log.w(TAG, "no audioDecoder found for" + mime);
            e.printStackTrace();
        }
    } else {
        Log.d(TAG, "Unknown mime type: " + mime + " on format: " + format.toString());
    }
}


videoDecoder.start();
VideoDecoderThread videoDecoderThread = new VideoDecoderThread();
videoDecoderThread.start();

ByteBuffer[] videoInputBuffers = videoDecoder.getInputBuffers();

AudioDecoderThread audioDecoderThread = null;

if (audioDecoder != null) {
    audioDecoder.start();
    audioInputBuffers = audioDecoder.getInputBuffers();
    audioDecoderThread = new AudioDecoderThread();
    audioDecoderThread.start();
}

while (!Thread.interrupted()) {    
    if (!isEOS) {
        render(extractor, videoInputBuffers, audioInputBuffers);
        extractor.advance();
    } else {Thread.sleep(1);}
}


void render(MediaExtractor extractor, ByteBuffer[] videoInputBuffers, ByteBuffer[] audioInputBuffers) {
    int videoInIndex;
    int audioinIndex;
    ByteBuffer buffer;

   int trackIndex = extractor.getSampleTrackIndex();

    if (trackIndex == mVideoTrackIndex) {
        videoInIndex = videoDecoder.dequeueInputBuffer(0);
        if (videoInIndex < 0) return;
        buffer = videoInputBuffers[videoInIndex];
        videoDecoder.queueInputBuffer(videoInIndex, 0, extractor.readSampleData(buffer, 0), extractor.getSampleTime(), 0);
    } else {
        if (audioDecoder != null) {
            audioinIndex = audioDecoder.dequeueInputBuffer(0);
            if (audioinIndex < 0) return;
            buffer = audioInputBuffers[audioinIndex];
            audioDecoder.queueInputBuffer(audioinIndex, 0, extractor.readSampleData(buffer, 0), extractor.getSampleTime(), 0);
        }
    }
}
...