Пропускать кадры при воспроизведении видео с помощью MediaExtractor и MediaCodec

Я использую MediaExtractor/MediaCodec для декодирования видео и рендеринга его в TextureView. В качестве шаблона я использовал код из: https://github.com/vecio/MediaCodecDemo/blob/master/src/io/vec/demo/mediacodec/DecodeActivity.java

Я хотел бы иметь возможность воспроизводить видео на скорости 2x. К счастью, кодирование/декодирование мультимедиа выполняется достаточно быстро, поэтому я могу добиться этого, позволив MediaCodec декодировать каждый кадр, а затем отображать на экране только каждый второй кадр. Однако это не похоже на отличное решение, особенно если вы хотите увеличить воспроизведение на произвольное значение. Например, при 10-кратной скорости кодек не может декодировать кадры достаточно быстро, чтобы воспроизводить каждый 10-й кадр со скоростью 30 кадров в секунду.

Поэтому вместо этого я хотел бы управлять воспроизведением, вызывая MediaExtractor.advance() несколько раз, чтобы пропускать кадры, которые не нужно декодировать. Например:

        ...
        mDecoder.queueInputBuffer(inIndex, 0, sampleSize, mExtractor.getSampleTime(), 0);
        for (i = 0; i < playbackSpeedIncrease; i++) {
               mExtractor.advance();
        }
        ...

Теоретически с этим кодом экстрактор должен извлекать только каждый n-й кадр, где n определяется переменной 'playbackSpeedIncrease'. Например, если n = 5, это должно пройти мимо кадров 1–4 и извлечь только кадр 5.

Однако на практике это не работает. Когда я запускаю этот код, изображение, отображаемое на экране, искажается: введите здесь описание изображения

Кто-нибудь знает, почему это так? Любые предложения по улучшению способов воспроизведения видео с произвольным увеличением скорости?


person Tim    schedule 18.05.2015    source источник


Ответы (1)


Обычно вы не можете сделать это с видео AVC.

Закодированное видео имеет «ключевые» (или «синхронные» или «I») кадры, которые содержат полные изображения, но кадры между ключевыми кадрами содержат «отличия» от предыдущих кадров. Вы можете найти несколько статей в Википедии о методах кодирования видео, например. вот этот. Вы получаете неприятное видео, потому что вы пропустили ключевой кадр, и теперь различия вычисляются для неправильного изображения.

Если вы когда-либо видели, как видео перематывается плавно вперед, но неуклюже перематывается назад, например. на TiVo вот почему: видеодекодер быстро воспроизводит вперед, но в обратном направлении он просто воспроизводит I-кадры, удерживая их на экране достаточно долго, чтобы получить желаемую скорость. При «быстром» движении вперед/назад все выравнивается, потому что устройство просто воспроизводит I-кадры. Вы можете сделать что-то подобное, наблюдая за флагом SAMPLE_FLAG_SYNC на кадрах, которые вы получаете от MediaExtractor.

Как правило, вы ограничены либо воспроизведением видео с такой скоростью, с какой устройство может его декодировать, либо воспроизведением только ключевых кадров. (Если вы достаточно знаете о макете конкретного видео в определенной кодировке, вы можете добиться большего успеха, например, воспроизвести I и P, но не B, но я не уверен, что это вообще возможно в AVC.)

Частота кадров I определяется видеокодером. Обычно это один или два кадра в секунду, но если вы получаете видео из разных источников, вы можете ожидать, что размер GOP (группа изображений, т. е. количество кадров между I-кадрами) будет различаться.

person fadden    schedule 18.05.2015