Подтвердить что ты не робот

Захват видео из окна OpenGL в Windows

Я должен предоставить своим пользователям действительно простой способ захвата видеороликов из главного окна приложения OpenGL. Я думаю о добавлении кнопок и/или сочетаний клавиш для запуска и остановки захвата; при запуске я могу попросить имя файла и другие варианты, если они есть. Он должен запускаться в Windows (XP/Vista), но мне также не хотелось бы закрывать дверь Linux, которую я до сих пор мог открыть.

Приложение использует OpenGL-фрагмент и шейдерные программы, эффекты, из-за которых мне абсолютно необходимо иметь в видеороликах.

Мне кажется, что может быть даже несколько разных подходов, которые потенциально могут удовлетворить мои требования (но я не знаю, с чего начать):

  • Библиотека кодирования с функциями, такими как startRecording (имя файла), stopRecording и captureFrame. Я мог бы вызвать captureFrame() после каждого рендеринга кадра (или каждый второй/третий/любой). Если это делает мою программу медленнее, это не проблема.

  • Отдельная внешняя программа, которую можно программно контролировать из моего приложения. В конце концов, автономная программа, которая не может контролироваться, почти делает то, что мне нужно... Но, как сказано, для пользователей должно быть очень просто работать, и я также благодарен за ее бесшовность; мое приложение обычно работает полноэкранным. Кроме того, должно быть возможно распространять как часть установочного пакета для моего приложения, которое я сейчас готовлю, используя NSIS.

  • Используйте Windows API для записи скриншотов по кадру, затем используйте (например) одну из библиотек, упомянутых здесь. Кажется, достаточно легко найти примеры того, как записывать скриншоты в Windows; тем не менее, мне бы понравилось решение, которое на самом деле не заставило меня замаскировать руки на уровне WinAPI.

  • Используйте OpenGL для рендеринга в настройку вне экрана, а затем используйте библиотеку для создания видео. Я не знаю, возможно ли это, и я боюсь, что это может быть не путь наименьшей боли. В частности, мне не хотелось бы, чтобы фактический рендеринг выполнял другой путь выполнения в зависимости от того, захватывается ли видео или нет. Кроме того, я бы избегал всего, что могло бы снизить частоту кадров в обычном режиме без захвата.

Если бы решение было свободным в любом смысле этого слова, то это было бы здорово, но это не абсолютное требование. В общем, чем меньше наворотов, тем лучше. С другой стороны, по причинам, выходящим за рамки этого вопроса, я не могу ссылаться ни на один код GPL, к сожалению.

Что касается формата файла, я не могу ожидать, что мои пользователи начнут работать в Google для любых кодеков, но пока показ видео достаточно просто для пользователя Windows на базовом уровне, мне все равно, какой формат. Однако было бы здорово, если бы можно было контролировать качество сжатия вывода.

Просто пояснить: мне не нужно записывать видео с внешнего устройства, такого как видеокамеру, и мне не очень интересно движение мыши, хотя получение их тоже не наносит вреда. Нет требований к аудио; приложение ничего не делает.

Я пишу С++ с помощью Visual Studio 2008, так как это приложение также использует GLUT и GLUI. У меня есть четкое понимание С++ и ссылок в библиотеках и подобных материалах, но, с другой стороны, OpenGL для меня совершенно новый: до сих пор я действительно только изучил необходимые биты, чтобы выполнить мою работу.

Мне не нужно решение сверхсрочно, поэтому не стесняйтесь тратить свое время:)

4b9b3361

Ответ 1

Здесь есть два разных вопроса: как захватить фреймы из приложения OpenGL и как превратить их в файл фильма.

Первый вопрос достаточно прост; вы просто захватываете каждый кадр с помощью glReadPixels() (через PBO, если вам нужна производительность).

Второй вопрос немного сложнее, поскольку кросс-платформенные решения (ffmpeg) имеют тенденцию быть GPL'd или LGPL'd. Является ли LGPL приемлемым для вашего проекта? Способ Windows для этого (DirectShow) - немного головная боль для использования.

Изменить: Так как LGPL в порядке, и вы можете использовать ffmpeg, см. здесь для примера того, как кодировать видео.

Ответ 2

Это выглядит довольно уместным для слияния с AVI (как было предложено Эндрю), однако я действительно надеялся избежать LPBITMAPINFOHEADER и т.д..

Спасибо за ответы, я сообщу об успехе, если будет что-то:)

Тем временем дополнительные советы по кодированию необработанных кадров из glReadPixels в видеоклипы будут оценены.

Изменить: Пока что ffmpeg, предложенный Майком Ф., кажется, это путь. Тем не менее, я еще не вступил в реальную реализацию, но, надеюсь, это изменится в ближайшем будущем!

Ответ 3

Самый простой вариант - сохранить каждый обработанный фрейм из вашего приложения, а затем слить их в AVI. Когда у вас есть AVI, доступно много доступных библиотек, которые могут преобразовать его в более оптимальный формат или вообще пропустить шаг AVI.

С точки зрения получения каждого кадра вы можете выполнить это либо путем рендеринга в текстуру вне экрана, как вы предлагаете, либо используете backbuffer напрямую в качестве источника, если ваше оборудование поддерживает это. Выполнение любого из этих (и сохранения каждого кадра) будет затруднительным без сильного штрафа за частоту кадров.

Предоставление вашего приложения является детерминированным, вы можете "записывать" действия пользователей в виде серии входов, а затем иметь режим экспорта, который последовательно выводит их на экранную поверхность для генерации AVI.

Ответ 4

Мне пришлось создать демонстрационный проект записи рендеринга OpenGL в видео. Я использовал glReadPixels для получения данных пикселов и создания видео с помощью OpenCV cvWriteFrame. OpenCV позволяет писать в divx или даже x264/vp8 (с ffmpeg скомпилированным в).

У меня есть более подробная запись в моем сообщении в блоге вместе с образцом проекта. http://tommy.chheng.com/2013/09/09/encode-opengl-to-video-with-opencv/