Итак, во-первых, некоторые обрамления этой проблемы. 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 в медиа-среде.
Попробуйте кодировать свои видео с помощью небольшой GOP, скажем, '-g 9' или ниже – Mulvya
Есть также [reverse] (https: // ffmpeg.org/ffmpeg-filters.html # reverse_002c-reverse), которые могут дать некоторые идеи. – LordNeckbeard