Я должен предоставить своим пользователям действительно простой способ захвата видеоклипов из главного окна моего приложения OpenGL. Я подумываю добавить кнопки и / или сочетания клавиш для запуска и остановки захвата; при запуске я мог бы запросить имя файла и другие параметры, если таковые имеются. Он должен работать в Windows (XP / Vista), но я также не хотел бы закрывать дверь Linux, которую я до сих пор мог держать открытой.
Приложение использует фрагменты OpenGL и программы шейдеров, эффекты, из-за которых мне абсолютно необходимо иметь в возможных видео.
Мне кажется, что может быть даже несколько разных подходов, которые потенциально могут удовлетворить мои требования (но я действительно не знаю, с чего мне начать):
Библиотека кодирования с такими функциями, как startRecording (имя файла), stopRecording и captureFrame. Я мог бы вызвать captureFrame () после каждого рендеринга кадра (или каждую секунду / треть и т.д.). Если из-за этого моя программа работает медленнее, это не проблема.
Автономная внешняя программа, которой можно программно управлять из моего приложения. В конце концов, отдельная программа, которой можно управлять нет, почти делает то, что мне нужно ... Но, как уже говорилось, она должна быть действительно простой для пользователей, и я также был бы признателен за ее простоту; мое приложение обычно работает в полноэкранном режиме. Кроме того, должно быть возможно распространение как часть установочного пакета для моего приложения, которое я в настоящее время готовлю с помощью NSIS.
Используйте Windows API, чтобы делать снимки экрана покадрово, затем используйте (например) один из упомянутые здесь библиотеки. Кажется, достаточно легко найти примеры того, как делать снимки экрана в Windows; однако мне бы понравилось решение, которое на самом деле не заставляет меня сильно пачкать руки на уровне WinAPI.
Используйте OpenGL для рендеринга в внеэкранную цель, а затем используйте библиотеку для создания видео. Я не знаю, возможно ли это вообще, и боюсь, что в любом случае это не путь наименьшей боли. В частности, я бы не хотел, чтобы реальный рендеринг выполнялся по-разному в зависимости от того, захватывается видео или нет. Кроме того, я бы избегал всего, что могло бы снизить частоту кадров в обычном режиме без захвата.
Если бы решение было бесплатным в любом смысле этого слова, это было бы здорово, но на самом деле это не абсолютное требование. В общем, чем меньше наворотов, тем лучше. С другой стороны, по причинам, выходящим за рамки этого вопроса, я, к сожалению, не могу ссылаться на какой-либо код только под GPL.
Что касается формата файла, я не могу ожидать, что мои пользователи начнут гуглить какие-либо кодеки, но пока отображение видео достаточно просты для пользователя Windows базового уровня, мне все равно, что это за формат. Однако было бы здорово, если бы можно было контролировать качество сжатия вывода.
Просто чтобы уточнить: мне не нужно захватывать видео с внешнего устройства, такого как видеокамера, и меня не особо интересуют движения мыши, хотя их получение тоже не вредит. К звуку требований нет; приложение вообще не издает шума.
Я пишу C++, используя Visual Studio 2008, для этого самого приложения также использую GLUT и GLUI. У меня есть четкое представление о C++, связях в библиотеках и тому подобном, но, с другой стороны, OpenGL для меня совершенно новый: до сих пор я действительно изучил только необходимые биты, чтобы действительно выполнить свою работу.
Мне не нужно решение супер-срочно, так что не торопитесь :)





Здесь есть два разных вопроса: как получить кадры из приложения OpenGL и как превратить их в файл фильма.
Первый вопрос достаточно прост; вы просто захватываете каждый кадр с помощью glReadPixels () (через PBO, если вам нужна производительность).
Второй вопрос немного сложнее, поскольку кроссплатформенные решения (ffmpeg), как правило, имеют GPL или LGPL. Подходит ли LGPL для вашего проекта? Способ Windows сделать это (DirectShow) - это немного головная боль.
Редактировать: Поскольку LGPL в порядке и вы можете использовать ffmpeg, см. здесь для примера того, как кодировать видео.
Самый простой вариант - сохранить каждый визуализированный кадр из вашего приложения, а затем объединить их в AVI. Когда у вас есть AVI, доступно множество библиотек, которые могут преобразовать его в более оптимальный формат или, возможно, вообще пропустить этап AVI.
Что касается получения каждого кадра, вы можете выполнить это либо путем рендеринга в текстуру вне экрана, как вы предлагаете, либо напрямую используя буферный буфер в качестве источника, если ваше оборудование поддерживает это. Выполнение любого из них (и сохранение каждого кадра) будет затруднено без значительного снижения частоты кадров.
Если ваше приложение является детерминированным, вы можете «записывать» действия пользователей как серию входных данных, а затем иметь режим экспорта, который последовательно отображает их за пределами экрана для генерации AVI.
Штраф за частоту кадров вполне приемлем, если он применяется только при реальном захвате видео. Приложение является детерминированным в том смысле, что оно не является стохастическим, но то, что отображается, основывается, помимо действий пользователя, также на результатах внешнего измерительного устройства.
Этот действительно выглядит довольно уместным для слияния с AVI (как было предложено Эндрю), однако я действительно надеялся избежать LPBITMAPINFOHEADER и т. д.
Спасибо за ответы, сообщу об успехах, если они будут :)
Тем временем были бы признательны за дополнительные советы по кодированию необработанных кадров из glReadPixels в видеоклипы.
Редактировать: Пока что ffmpeg, предложенный Майком Ф., кажется правильным решением. Тем не менее, я еще не разобрался с фактической реализацией, но, надеюсь, это изменится в ближайшем будущем!
Имейте в виду, что при использовании VfW и DirectShow можно использовать только те кодеки, которые установлены на компьютере пользователя, поэтому вам нужно либо связать кодек, который вы планируете использовать, либо выяснить, какие кодеки у них уже есть в гарантированный.
Мне пришлось создать демонстрационный проект записи рендеринга OpenGL в видео. Я использовал glReadPixels для получения данных о пикселях и создал видео с помощью OpenCV cvWriteFrame. OpenCV позволяет вам писать в divx или даже x264 / vp8 (со скомпилированным ffmpeg).
У меня есть более подробная запись в моем сообщении в блоге вместе с образцом проекта. http://tommy.chheng.com/2013/09/09/encode-opengl-to-video-with-opencv/
Спасибо, что разместили свой ответ! Обратите внимание, что вы должны опубликовать основные части ответа здесь, на этом сайте, иначе ваше сообщение может быть удалено. См. FAQ, где упоминаются ответы, которые «не более чем ссылка». Вы все равно можете включить ссылку, если хотите, но только в качестве «ссылки». Ответ должен стоять сам по себе, без ссылки.
Привет, bluefeet, основная часть ответа присутствует: «используйте glReadPixels для получения данных пикселей» и используйте OpenCV «cvWriteFrame». Сообщение в блоге содержит более подробную информацию, но это суть ответа.
glReadPixels () действительно кажется тем, что мне нужно для первого вопроса, спасибо!