Pull to refresh

Видео-плеер на основе VLC. Часть 2: используем Direct3D

Reading time3 min
Views6.9K

Вступление


Привет хабралюдям!

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

image
Главное окно программы

Отрисовка кадра на экран с помощью Direct3D


Итак, как я уже говорил для декодирования потокового видео используется библиотека LibVLC, которая является основной частью плеера VLC. Плагин VMem позволяет декодировать видео поток, применяя к нему различные фильтры и в конце концов сохранять ее в пользовательский участок памяти. Для того, чтобы ускорить вывод картинки я использовал Direct3D 9. В Direct3D есть понятие поверхностей(surfaces) а также текстур(textures). Поверхность — это массив байтов имеющий размер width x height:

image
Схематичное изображение поверхности

Т.е. по сути поверхность есть bitmap
Текстура отличается от поверхности тем, что ее можно «накладывать» на примитивы(полигоны). Также текстура имеет mip-map уровни — уменьшенные копии текстуры(применяется в 3D графике)

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

image
Процесс отрисовки

Промежуточное копирование поверхности в текстуру необходимо в силу особенности доступа к поверхностям и текстурам в Direct3D.
Числа в скобках при отрисовке — это текстурные координаты, они показывают каким образом текстура будет накладываться на примитив.

Проблема многопоточности и растягивания окна


При растягивании окна back buffer, используемый при отрисовке остается тех же самых размеров, и поэтому при ресайзе окна, изображение растягивается и размывается. Чтобы этого не происходило нужно пересоздавать буфер. В Direct3D это делается вызовом IDIrect3DDevice9::Reset. При этом обязательным условием для успешного пересоздания буфера является удаление всех ресурсов из видео памяти. А поскольку LibVLC работает в отдельном потоке и записывает данные в нашу видео-поверхность, то необходимо синхронизироваться мютексами ну или секциями(кому как удобнее).
Также нужно решить вопрос об отрисовке. Поскольку кроме отрисовки видео в приложении были элементы, которые нужно было анимировать с частотой > 25 кадров сек. Реализовать это можно так: элементы GUI при отрисовке вызывают принудительную перерисовку окна также как и видео поток. Либо окно постоянно перерисовывается при простое приложения(как это делается в играх). При первом способе поток, декодирующий видео должен посылать сообщения в главный поток о том, что приложение нуждается в перерисовке, что дополнительно нагружает очередь сообщений. При втором способе посылать сообщения не нужно — приложение перерисовывается всегда.

Пользовательский интерфейс


Все кнопки и прочие элементы управления рисуются посредством вывода полупрозрачных примитивов с натянутыми на них текстурами. Каждый элемент имеет ограничивающий прямоугольник, при нажатии в котором происходит вызов «прикрепеленного» слота с нужным действием.
Для канала передач использовалась технология «kinetic scrolling»:

image
Для прокрутки используется «kinetic scrolling»

Технология скроллинга довольно простая, тем более в интернете есть множество статей по реализации данного эффекта.
Больше сказать по поводу пользовательского интерфейса нечего, кроме того, что над некоторыми эффектами типа «затухающее» название телепередачи пришлось поломать голову.

image

Заключение


Как я ни старался, а изложение моих мыслей получилось довольно сумбурным — хотелось рассказать о многих вещах, но в тоже время не писать целый талмуд о том, как писать приложения на DirectX. Если есть вопросы или предложения — буду рад!
P.S.(правка:)изначально картинки были загружены на dropbox, что привело к блокировке аккаунта. Исходные файлы не сохранились, поэтому схемы я перерисовал.
Tags:
Hubs:
Total votes 49: ↑35 and ↓14+21
Comments52

Articles