Видео в ваших играх: ч.2 - FFmpeg

 

Здравствуйте дорогие читатели моего блога. Сегодня я предлагаю вам вторую статью из мини-цикла статей по воспроизведению видео в играх. Рекомендую так же ознакомиться с первой статьей - "Видео в ваших играх: ч.1 - Ogg Theora". Напомню что основной задачей будет возможность вывода изображения видео используя OpenGL и, конечно же, бесплатность используемых библиотек. И так - встречайте:

Часть 2. FFmpeg -  

Вторым доступным решением в нашем списке идет FFmpeg - набор свободных библиотек с открытым исходным кодом, которые позволяют записывать, конвертировать и передавать цифровые аудио и видео записи в различных форматах. Основными библиотеками FFmpeg являются libavcodec - библиотека для кодирования и декодирования аудио и видео, а так же библиотека libavformat - библиотека для работы с различными медиаконтейнерами (мультиплексирование и демультиплексирование). Библиотеки распространяются под лицензией GNU Lesser General Public License 2.1+ что означает свободное использование в коммерческих продуктах, однако встраивание библиотек доступно лишь при помощи динамического связывания (dynamic linking). Как по мне - совершенно пустяковое неудобство в обмен на огромные возможности. Напоследок - библиотеками FFmpeg не гнушается пользоваться сам великий Valve! Найти их вы сможете в папке Steam/bin:

Библиотеки FFmpeg в Steam

Проект был основан самим Фабрисом Беллардом (Fabrice Bellard) в 2000 году. Список реализованных кодеков:

  • ITU-T video standards: H.261, H.262/MPEG-2 Part 2, H.263 and H.264/MPEG-4 AVC
  • ITU-T vocoder standards: G.711 µ-law, G.711 A-law, G.721 (aka G.726 32k), G.722, G.722.2 (aka AMR-WB), G.723 (aka G.726 24k and 40k), G.723.1, G.726, G.729 and G.729D
  • ISO/IEC MPEG video standards: MPEG-1 Part 2, H.262/MPEG-2 Part 2, MPEG-4 Part 2 and H.264/MPEG-4 AVC
  • ISO/IEC MPEG audio standards: MP1, MP2, MP3, AAC, HE-AAC and MPEG-4 ALS
  • ISO/IEC/ITU-T JPEG image standards: JPEG, JPEG-LS and JPEG 2000
  • SMPTE video standards: VC-1 (aka WMV3), VC-2 (aka Dirac), VC-3 (aka AVID DNxHD) and DPX image
  • SMPTE audio standards: SMPTE 302M
  • DVD Forum standards related / Dolby audio codecs: MLP (aka TrueHD) and AC-3
  • 3GPP vocoder standards: AMR-NB, AMR-WB (aka G.722.2)
  • GSM related voice codecs: Full Rate
  • Windows Media Player related video codecs: Microsoft RLE, Microsoft Video 1, Cinepak, Indeo 2, 3 and 5, Motion JPEG, Microsoft MPEG-4 v1, v2 and v3, WMV1, WMV2 and WMV3 (aka VC-1)
  • Windows Media Player related audio codecs: WMA1, WMA2 and WMA Pro
  • Windows Media Player related voice codecs: WMA Voice and MS-GSM
  • RealPlayer related video codecs: RealVideo 1, 2, 3 and 4
  • RealPlayer related audio codecs: RealAudio 3, 6, 7, 8, 9 and 10
  • RealPlayer related voice codecs: RealAudio 1, 2 (variant of G.728), 4 and 5
  • QuickTime related video codecs: Cinepak, Motion JPEG, ProRes, Sorenson 3 Codec, Animation_codec
  • QuickTime related audio codecs: QDesign Music Codec 2 and ALAC
  • Adobe Flash Player related video codecs: Screen video, Screen video 2, Sorenson 3 Codec, VP6 and Flash Video (FLV)
  • Adobe Flash Player related audio codecs: Adobe SWF ADPCM and Nellymoser Asao
  • Xiph.Org: Theora, Speex (via libspeex), Vorbis and FLAC
  • Sony: ATRAC1 and ATRAC3
  • NTT: TwinVQ
  • On2: Duck TrueMotion 1, Duck TrueMotion 2, VP3, VP5, VP6 and VP8
  • RAD Game Tools: Smacker video and Bink video
  • Truespeech
  • RenderWare: TXD

Список поддерживаемых контейнеров:

  • ASF
  • AVI and also input from AviSynth
  • BFI
  • CAF
  • FLV
  • GXF, General eXchange Format, SMPTE 360M
  • IFF
  • RL2
  • ISO base media file format (including QuickTime, 3GP and MP4)
  • Matroska (including WebM)
  • Maxis XA
  • MPEG program stream
  • MPEG transport stream (including AVCHD)
  • MXF, Material eXchange Format, SMPTE 377M
  • MSN Webcam stream
  • Ogg
  • OMA
  • TXD
  • WTV

Загрузить библиотеки FFmpeg можно с официального сайта - ссылка. Поскольку процесс сборки под Windows довольно нетривиален, скачать собранные библиотеки можно здесь - http://ffmpeg.zeranoe.com/builds/.

Как уже упоминалось выше - для вывода видео кадра будет использоваться OpenGL 3, поэтому рекомендую прочитать статью Знакомство с OpenGL 3.0.

Код видео плеера представлен в виде класса FFmpegPlayer. Не вижу смысла копипастить сюда его код, тем более что он обильно прокомментирован. Давайте просто рассмотрим основные моменты.

Практически любой медиаконтейнер содержит в себе несколько потоков (видео, аудио, субтитры, и т.д.) Работа с контейнерами осуществляется с помощью библиотеки libavformat. Для начала нам нужно открыть контейнер, найти в нем видеопоток и декодировать его использую библиотеку libavcodec. Как видите - все достаточно прозрачно и просто, весь этот функционал я инкапсулировал в один класс FFmpegPlayer.

Для начала нужно создать объект класса FFmpegPlayer и вызвать его метод OpenVideoFile, которому в качестве параметра передать путь к видео-файлу. Данный метод возвращает значение true если открытие видео файла произошло успешно, и false в противном случае.

Если загрузка видео файла произошла успешно, можно узнать немного информации о загруженном файле:

  • FFmpegPlayer::GetFrameWidth  - возвращает ширину видео кадра
  • FFmpegPlayer::GetFrameHeight  - возвращает высоту видео кадра
  • FFmpegPlayer::GetFramesPerSecond  - возвращает количество видео кадров в секунду

Теперь в главном цикле приложения или по таймеру нужно вызывать FFmpegPlayer::Advance передавая в качестве параметра количество миллисекунд прошедших со времени предыдущего вызова (delta-time). Метод вернет номер текущего видео кадра, если он сменился и плеер не достиг конца видео файла, можно запросить данные видео кадра. На выбор есть 2 метода:

  • FFmpegPlayer::GetFrameRGB  - заполнит переданный массив RGB значениями пикселов видео кадра. Преобразование YUV -> RGB будет выполнено на CPU.
  • FFmpegPlayer::GetFrameYUV444  - заполнит переданный массив YUV значениями пикселов видео кадра. Дальнейшее преобразование YUV -> RGB можно выполнить на GPU.

В примере используются оба способа. Переключить используемый метод можно с помощью дефайна USE_HW_YUV2RGB.

В примере так же реализована возможность использования собственных функций чтения данных (например для воспроизведения видео из памяти). Для этого мы вручную создаем объект AVIOContext посредством функции avio_alloc_context, где и регистрируем свои функции чтения и перемещения по файлу. Здесь есть очень важный нюанс тактично упущенный в документации - в seek-функцию в качестве параметра отвечающего за точку отсчета смещения могут передаваться, кроме стандартных BEG/CUR/END, еще и 2 специальных AVSEEK_FORCE и AVSEEK_SIZE. В моем примере эти параметры успешно обрабатываются. Если вы захотите заменить функции чтения на свои, просто замените внутренности методов FFmpegPlayer::ReadPacket и FFmpegPlayer::Seek.

Рис. 1 - Так выглядит не преобразованный YUV кадр

На рисунке 1 можно увидеть как выглядит не преобразованный YUV кадр, полученный с помощью метода FFmpegPlayer::GetFrameYUV444.

Рис. 2 - Так выглядит финальный RGB кадр

На рисунке 2 можно увидеть как выглядит финальный RGB кадр полученный с помощью метода FFmpegPlayer::GetFrameRGB либо после работы шейдера fragment_yuv.glsl использующегося для выполнения преобразования YUV -> RGB на видеокарте.

При подготовке примера к статье использовался эпизод "The Werewolf Transformation" из сериала "Теория Большого Взрыва" (The Big Bang Theory). Права на сериал принадлежат компании Warner Bros. Television.

Скачать исходный код к статье:
FFmpegVideo.zip (1772)

  4 Ответов в “Видео в ваших играх: ч.2 - FFmpeg”

  1. Отличная статья! Правда в программе вшит полный путь к видео файлу, но это мелочь которая быстро правится в main.cpp :)

    • Спасибо. Путь к файлу прописан в коде для упрощения примера, но сам класс плеера вполне автономен.

  2. Спасибо! Статья очень помогла. Жалко что для FFmpeg мало хороших и современных туториалов, те что есть пестрят устаревшими функциями. Приходится на примерах разбираться.

  3. все отлично - спасибо.... мне надо сделать тумбнайлер для iphone android win..

    я просто компилю ffmgeg под эти платформы и далее вытаскиваю кадры через
    FFmpegPlayer::DecodeVideoFrame

    потом генерю gif и показываю....

    ну можно еще бонусом сделать плеер..

    круто - статья ОЧЕНЬ помогла - здоровья/!!
    .................

    если приложение коммерческое то мне главное статически не линковать ффмпег - то есть чтобы видели что я юзаю чужое - и еще упомянуть в кредитах... и можно в appstore продавать????

Оставить комментарий на ASD Отменить ответ

(required)

(required)

Вы можете использовать HTML теги и атрибуты: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>

© 2011 3D-Orange.com.ua
e-mail me

3D-Orange.com.ua is proudly powered by WordPress.
Suffusion theme by Sayontan Sinha