2016-01-15 2 views
1

Я реализую видеоплеер с использованием мультимедийной рамки ffmpeg. Я могу добиться воспроизведения, паузы, увеличения скорости, уменьшения скорости, поиска вперед, обратного поиска функциональности. Но обратное воспроизведение видео не так гладко, оно заикается много. Пожалуйста, помогите мне в понимании воспроизведения видео в обратном направлении. Какой лучший подход для этого?Обратное воспроизведение видео через ffmpeg

Есть ли другие мультимедийные рамки, поддерживающие воспроизведение в обратном направлении?

Большое спасибо заранее.

+0

Попробуйте кодировать свои видео с помощью небольшой GOP, скажем, '-g 9' или ниже – Mulvya

+0

Есть также [reverse] (https: // ffmpeg.org/ffmpeg-filters.html # reverse_002c-reverse), которые могут дать некоторые идеи. – LordNeckbeard

ответ

2

Итак, во-первых, некоторые обрамления этой проблемы. FFmpeg - это чрезвычайно низкоуровневая библиотека, которая пытается дать тонкий API поверх доступа к файлу raw media. Это означает, что вы в основном получаете буквально то, что находится в медиафайле. Для видео это поток сжатых видеопакетов из демультиплексирования, а затем поток декодированных изображений из декодера. Из-за предсказания B/P-frame это строго линейный и однонаправленный процесс. Отметим также, что FFmpeg в большинстве практических случаев использует многопоточность, что опять-таки является строго линейным процессом. Если у вас есть 4 кадра декодирования потока 8, 9, 10, 11, и вы пытаетесь создать кадр 7 после этого (таким образом, декодирование кадров 7, 8, 9 и 10), вы по существу генерируете вечные отходы.

Итак: обратное воспроизведение с использованием инверсного заказа av_seek_frame() по своей сути несовместимо с базовой конструкцией FFmpeg. Это не значит, что вы не можете сделать это, используя FFmpeg вообще, но это делает означает, что если вы используете 0FL, то для этого требуется некоторое усилие. Сказав это, как бы вы сделали обратное воспроизведение? Вы кешируете!

Вы можете создавать группы из N кадров (где N не меньше, чем количество потоков, но по-прежнему позволяет удерживать так много кадров в памяти), например. N = 10 или N = 100 (в зависимости от размера рамки). Затем forward-decode N кадров, используя последовательные вызовы av_read_frame() и avcodec_decode_videoN(), и удерживайте их в памяти в приложении. Например, теперь вы можете иметь фрейм 7-17 в памяти. Начните отображение кадра 17 и следующего отображения 16, 15 и т. Д. (Из памяти), пока не нажмете index = 7. Когда вы нажмете 7, найдите следующую позицию, позволяющую удерживать N кадров в памяти (в случае N = 10, это будет индекс = 0) и удерживать фрейм 0-6 в памяти и отображать индекс = 6, 5 и т. Д. До 0.

Я действительно реализовал эту точную функцию, и она хорошо работает с использованием этого подхода, и она по-прежнему использует многопоточность (почти) правильно. Для больших значений N на видео высокого разрешения требуется довольно много памяти, поэтому вам рекомендуется сделать N зависимым от размера кадра и сделать разрешение N * либо настраиваемым в настройках вашего приложения, либо, по крайней мере, зависеть от его размера на общем объеме памяти, доступной на компьютере, программное обеспечение работает.

Обратите внимание, что поиск - это не самая простая вещь, потому что вы не можете случайно искать любую точку в любом видео и ожидать, что она будет работать. Для большинства кодеков, реализующих P-кадры или B-кадры, вы можете искать только ключевые кадры или I/IDR-фреймы. Это означает, что формат файла должен установить флаг ключевого кадра в его индексе. Если это не так, вам придется синтетически генерировать индекс при первоначальной загрузке файла (например, вызов av_read_frame(), пока вы не нажмете EOF).

Что касается вашего другого вопроса: я уверен, что есть другие медиа-рамки, реализующие трюковую игру (воспроизведение в обратном направлении и т. Д.), Например. GStreamer. Однако это обычно работает только для ограниченного количества форматов файлов, not for all supported file formats в медиа-среде.

+0

Здравствуйте, Рональд, большое спасибо за подробное объяснение. В настоящее время я реализовал ту же логику, которую вы объяснили. Он работает хорошо для нескольких файлов, которые имеют меньшую гопи. Я проанализирую структуру gstreamer. У вас есть gd time :) – Raju

+0

Вы найдете, что для больших GOP GStreamer предварительно кэширует досрочно, т. Е. Представляет один ключевой кадр каждые 25 кадров, но вы кешируете только 10 кадров. Это означает, что вы должны декодировать 25 кадров для воспроизведения 15-25, еще 15 кадров для декодирования 5-15 и кадров f для воспроизведения первого 5. Чем больше интервал KF, тем больше накладные расходы. Решениями являются увеличение N (размер кеша) и предварительная загрузка, когда вы приближаетесь к началу вашего кеша (т. Е. Начните загрузку 5-15, когда играете 17, а не 15). GStreamer, вероятно, делает большую часть этого автоматически. –

Смежные вопросы