Видео в ваших играх: ч.1 - Ogg Theora
Здравствуйте дорогие читатели моего блога. Прошу прощения за столь длительный перерыв, в течении которого я не обновлял содержимое сайта. Хочу искупить свою вину и начать небольшой цикл статей по воспроизведению видео в играх. Основной задачей будет возможность вывода изображения видео используя OpenGL и, конечно же, бесплатность используемых библиотек. И так - встречайте:
Часть 1. Ogg Theora
И первым доступным решением в нашем списке идет Theora - свободный (3-х пунктная BSD лицензия) видеокодек. Первый релиз данного кодека состоялся 1-го Июня 2004 года. С тех пор формат видеопотока был заморожен и не будет изменен, что является гарантией обратной совместимости.
Немного истории. Ogg Theora - был разработан компанией Xiph.Org Foundation, и основан на видекодеке VP3.2, который был выпущен компанией On2 Technologies в 2000 году. В качестве контейнера используется Ogg - еще одна разработка Xiph.Org Foundation. Текущая стабильная версия кодека - 1.1.1 . Существует так же версия 1.2.0 alpha 1, однако она на данный момент в разработке и не рекомендуется к использованию в продуктах.
При подготовке статьи использовались следующие библиотеки:
- libOgg версии 1.3.0
- libTheora версии 1.1.1
Загрузить вышеупомянутые библиотеки можно с официальной странички - link.
Как уже упоминалось выше - для вывода видео кадра будет использоваться OpenGL 3, поэтому рекомендую прочитать статью Знакомство с OpenGL 3.0.
Еще одна особенность данной статьи - как вам наверное известно - большинство видеокодеков хранят кадр в YUV цветовом пространстве, и в данной статье будет рассмотрено два варианта преобразования YUV->RGB - как используя процессор (software mode) так и используя мощности видеокарты с помощью шейдеров (hardware mode).
И так, вы скачали готовый пример к статье.
Небольшое отступление. Меня частенько упрекали за отсутствие комментариев в коде примеров. В сегодняшнем примере я постарался исправиться и обильно прокомментировал основной код примера. Я, в основном, пишу комментарии на английском языке по привычке, но надеюсь это не составит вам проблемы.
Код видео плеера представлен в виде класса TheoraPlayer. Не вижу смысла копипастить сюда его код, тем более что он обильно прокомментирован. Давайте просто рассмотрим основные моменты.
Весь Ogg контейнер и его содержимое представлено в виде потоков (stream) для более удобной работы по сети (именно поэтому не реализована возможность узнать длину видеоряда и перемотки, это можно реализовать пробежавшись по всему потоку до конца, запомнив позиции кадров и время последнего кадра, что, однако, выходит за рамки статьи). Основным является поток Ogg, работа с которым осуществляется посредством библиотеки libOgg. Все что от нас требуется - заполнять Ogg поток данными и используя функции libOgg читать интересующие нас данные. Внутри Ogg потока находятся один и более потоков данных (Theora, Vorbis, Subtitles, etc.). Наша задача - распаковывая Ogg-пакеты найти интересующий нас поток Theora и декодировать его посредством функций библиотеки libTheora. Как видите - все достаточно прозрачно и просто, весь этот функционал я инкапсулировал в один класс TheoraPlayer.
Для начала нужно создать объект класса TheoraPlayer и вызвать его метод OpenVideoFile, которому в качестве параметра передать путь к видео-файлу. Данный метод возвращает значение true если открытие видео файла произошло успешно, и false в противном случае.
Если загрузка видео файла произошла успешно, можно узнать немного информации о загруженном файле:
- TheoraPlayer::GetFrameWidth - возвращает ширину видео кадра
- TheoraPlayer::GetFrameHeight - возвращает высоту видео кадра
- TheoraPlayer::GetFramesPerSecond - возвращает количество видео кадров в секунду
Теперь в главном цикле приложения или по таймеру нужно вызывать TheoraPlayer::Advance передавая в качестве параметра количество миллисекунд прошедших со времени предыдущего вызова (delta-time). Метод вернет номер текущего видео кадра, если он сменился и плеер не достиг конца видео файла, можно запросить данные видео кадра. На выбор есть 2 метода:
- TheoraPlayer::GetFrameRGB - заполнит переданный массив RGB значениями пикселов видео кадра. Преобразование YUV -> RGB будет выполнено на CPU.
- TheoraPlayer::GetFrameYUV444 - заполнит переданный массив YUV значениями пикселов видео кадра. Дальнейшее преобразование YUV -> RGB можно выполнить на GPU.
В примере используются оба способа. Переключить используемый метод можно с помощью дефайна USE_HW_YUV2RGB.
На рисунке 1 можно увидеть как выглядит не преобразованный YUV кадр, полученный с помощью метода TheoraPlayer::GetFrameYUV444.
На рисунке 2 можно увидеть как выглядит финальный RGB кадр полученный с помощью метода TheoraPlayer::GetFrameRGB либо после работы шейдера fragment_yuv.glsl использующегося для выполнения преобразования YUV -> RGB на видеокарте.
Скачать видео для теста можно с официальной страницы - http://people.xiph.org/~greg/video/ytcompare/bbb_theora_486kbit.html
PS. Небольшое замечание - данный класс вполне самодостаточен, и его очень легко модифицировать для чтения видео из памяти. Для этого вам всего лишь нужно модифицировать метод TheoraPlayer::BufferData заменив в нем строку
int bytes = fread(buffer, 1, k_SyncBufferSize, m_File); |
на чтение из вашего источника данных.
Скачать исходный код к статье:
TheoraVideo.zip (2778)
Как всегда интересно и практично. Спасибо!
P. S. А где этот "рекламный баннер справа"?
Спасибо за отзыв!
Cпасибо за статью очень пригодилась.
Пожалуйста, всегда рад помочь
Спасибо за статью!
По клику на гугло-баннере пытается выполниться переход на "http:///" -- т.е баннер не работает (и, думается, $-помощь не поступает..)