Эта статья представляет мой «Hobby» проект — CaptureManager для настольной платформы Windows. Этот проект является простым набором функционала (SDK) для включения поддержки широкого набора видео и аудио источников в разрабатываемое приложение.
CaptureManager построен на основе Microsoft Media Foundation — нового поколения медиа технологий, заменившем объявленное устаревшем DirectShow. Microsoft Media Foundation была впервые включена в Windows Vista и получила поддержку видео и аудио источников начиная с Windows 7. Достоинством Microsoft Media Foundation является новая модель конвейера обработки медиа данных, оптимальная для многопроцессорных систем, и продолжающееся её развитие, и поддержка со стороны Microsoft.
В проекте CaptureManager я хотел решить ряд проблем, с которыми столкнулся при написании приложений с использованием Microsoft Media Foundation:
- Реализация СОМ функционала. Как-бы странно это не звучало, но с технологией Microsoft Media Foundation корпорация Microsoft отступила от своей-же модели приложений – от СОМ. Конечно, все интерфейсы классов в Microsoft Media Foundation всё также являются производными от IUnknown и связаны с GUID. Но сами классы создаются через прямые «С» вызовы функций из статически линкованных системных библиотек. Это отличается от реализации DirectShow, которая требует вызова CoCreateInstance и обращения через СОМ абстракцию. На мой взгляд, данное решение корпорация Microsoft является недостатком – во-первых, затрудняется интеграция Microsoft Media Foundation в проекты, написанные не на С/С++, к примеру С# проекты, которые, кстати, на Windows взаимодействуют с СОМ объектами практически бесшовно, генерируя требуемые определения интерфейсов из TLB. Во-вторых, повышается риск потери совместимости приложения со следующей версией Windows при миграции функции из одной статически линкованной библиотеки в другую – с Microsoft Media Foundation это уже произошло однажды: Library Changes in Windows 7 — «Starting in Windows 7, certain Media Foundation functions are exported from different DLL files than previous versions.».
- На мой взгляд Microsoft Media Foundation черезмерно перегружена функциями и интерфейсами – было-бы неплохо спрятать большинство из них за дополнительным уровнем абстракции для оптимизации задачи захвата и записи видео и аудио данных.
- Значительным недостатком, на мой взгляд, является ограничения в поддержке записи видео и аудио в Microsoft Media Foundation. Microsoft Media Foundation предоставляет два механизма работы с медиа данными: через граф-топологию и SourceReader-SinkWriter. Первый предполагает сборку требуемой конфигурации из узлов-преобразователей и позволяет гибко настроить требуемую конфигурацию. Второй предлагает получение порций медиа данных от SourceReader и отправки их в SinkWriter в контексте разрабатываемого приложения. Граф-топология весьма удобна, на мой взгляд, и позволяет легко генерировать требуемую конфигурацию записи по требованию пользователя. Однако, данное решение от Microsoft не позволяет решить задачу записи – дело в том, что объект для создания рабочей сессии записи на базе топологии с интерфейсом IMFMediaSession из функции MFCreateMediaSession оптимизирован для воспроизведения медиа данных, и не выполняет ряд требуемых операций – к примеру, при окончании записи в файл, требуется выполнить расчёт метрик – подсчитать средний скорость потоков и рассчитать длительность воспроизведения – но IMFMediaSession из функции MFCreateMediaSession этого не делает – для задачи воспроизведения операция расчёта метрик бессмысленна. Также существует проблема с таймингом — IMFMediaSession из функции MFCreateMediaSession рассматривает начало воспроизведения с нулевого времени – это логично при воспроизведении медиа файла. Однако, видео и аудио источники, такие как веб-камеры или микрофоны используют текущее системное время – согласно документации Microsoft Media Foundation они должны инициализироваться нулевым значением времени, но они не выполняют данное требование.
Я полагаю, и думаю многие согласятся, что указанные выше проблемы существенны и было-бы желательно их разрешить. Это и послужило причиной начала проекта CaptureManager (а также задача захвата видео с двух веб-камер и записи этого видео в один медиа файл).
Вкратце, что из себя представляет CaptureManager:
- Полноценный СОМ In-Process Server – или как иногда называют – ActiveX. Он включает TLB и может быть интегрирован в проекты на С++, С#, Python наравне с DirectShow.
- CaptureManager связан с библиотеками Microsoft Media Foundation, но использует «отложенное связывание» — библиотеки Microsoft Media Foundation загружаются в коде CaptureManager и связываются с соответствующими функциями во время выполнения приложения. При невозможности найти функцию в библиотеках, она замещается на функцию-пробку, возвращающую код ошибки – E_NOTIMPL. Таким образом, CaptureManager позволяет уменьшить риск аварийного прекращения работы целевого приложения в ситуации миграции функций из одной библиотеки Microsoft Media Foundation в другую.
- CaptureManager имеет упрощённый набор интерфейсов. Важной особенностью является генерация данных, описывающих медиа источники, кодеки и медиа контейнеры в формате XML документа – обрабатывать XML документ намного легче, чем многочисленные Variant и PropVariant, особенно на высокоуровневых API, как WPF.
- CaptureManager включает в себя ряд видео и аудио источников, отсутствующих в исходном Microsoft Media Foundation: Screen Capture – для захвата изображений с дисплея (или нескольких дисплеев), AudioLoop Capture – для захвата звукового потока с аудио выхода, DirectShow-Crossbar Capture – для захвата видео с карт видео захвата.
- CaptureManager включает в себя «аккумулятор кадров», позволяющий получить серию крайних кадров.
- CaptureManager включает собственную реализацию IMFMediaSession интерфейса, оптимизированную для задачи записи – т.е. реализован полный отказ от вызова MFCreateMediaSession функции.
- CaptureManager включает функционал для изменения параметров видео процессора веб-камеры и параметров камеры (фокус, экспозиция, и т.п.).
Функционал CaptureManager представлен в демонстрационных программах, доступных на GitHub — CaptureManager-SDK-Demos:
- CPPDemos:
- EVRWebCapViewerViaCOMServer – простое C++ приложение для демонстрации функционала просмотра видео источников через CaptureManager рендерер.
- OpenGLWebCamViewerViaCOMServer – простое C++ приложение для демонстрации функционала просмотра видео источников через OpenGL рендерер.
- TextInjectorDemo – простое C++ приложение для демонстрации функционала смешивания теста с видео потоком с камеры.
- WaterMarkInjectorDemo – простое C++ приложение для демонстрации функционала смешивания изображений с видео потоком с камеры.
- EVRVieweingAndRecording – простое C++ приложение для демонстрации функционала записи с видео и аудио источников в один медиа файл.
- NativeMediaFoundationPlayer – простое C++ приложение для демонстрации воспроизведения множества видео файлов в общем рендерере.
- CSharpDemos:
- WPFMultiSourceRecorder – простое C# приложение для демонстрации функционала записи с одного, двух и более видео и аудио источников в один общий медиа файл.
- WPFMediaFoundationPlayer – простое C# приложение для демонстрации воспроизведения множества видео файлов в общем рендерере.
- WPFVideoAndAudioRecorder – простое C# приложение для демонстрации функционала записи с видео и аудио источников в один медиа файл.
- WPFIPCameraMJPEGMultiSourceViewer – простое C# приложение для демонстрации функционала захвата видео с нескольких Интернет камер и воспроизведения их в общем рендерере.
- WPFMultiSourceViewer – простое C# приложение для демонстрации функционала захвата видео с нескольких нескольких и воспроизведения их в общем рендерере.
- WPFViewerEVRDisplay – простое C# приложение для демонстрации функционала интеграции CaptureManager рендерера в WPF приложение.
- WPFIPCameraMJPEGViewer – простое C# приложение для демонстрации функционала захвата видео с Интернет камеры.
- WPFImageViewer – простое C# приложение для демонстрации функционала захвата изображения из файла.
- WindowsFormsDemo – простое C# приложение для демонстрации функционала просмотра и записи видео источников.
- WPFWebCamSerialShots – простое C# приложение для демонстрации функционала «аккумулятор кадров».
- WPFWebCamShot – простое C# приложение для демонстрации функционала захвата кадров с видео источника.
- WPFRecorder – простое C# приложение для демонстрации функционала просмотра и записи видео источников.
- WPFWebViewerEVR – простое C# приложение для демонстрации функционала просмотра видео источников через CaptureManager рендерер.
- WPFWebViewerCallback – простое C# приложение для демонстрации функционала захвата кадров с видео источника через копирование из потока CaptureManager.
- WPFWebViewerCall – простое C# приложение для демонстрации функционала захвата кадров с видео источника через прямой вызов методов CaptureManager.
- WPFSourceInfoViewer – простое C# приложение для демонстрации функционала получения информации о доступных видео и аудио источников.
- WPFMultiSourceRecorder – простое C# приложение для демонстрации функционала записи с одного, двух и более видео и аудио источников в один общий медиа файл.
- PythonDemos:
- CaptureManagerSDKPythonDemo – простое Python приложение для демонстрации функционала просмотра и записи видео источников.
- CaptureManagerSDKPythonDemo – простое Python приложение для демонстрации функционала просмотра и записи видео источников.
- QtMinGWDemos:
- CaptureManagerSDKQtMinGWDemo – простое С++ приложение на Qt для демонстрации функционала просмотра и записи видео источников.
- CaptureManagerSDKQtMinGWDemo – простое С++ приложение на Qt для демонстрации функционала просмотра и записи видео источников.
- UnityDemos:
- UnityWebCamViewer — простое приложение для демонстрации функционала работы с видео источником в Unity3D.
- UnityWebCamViewer — простое приложение для демонстрации функционала работы с видео источником в Unity3D.
Больше информации о проекте можно найти сайте CaptureManager SDK. На NuGet существует C# оболочка CaptureManager.
Автор: Евгений Перегуда