Использование DirectShow в Windows
Часть 1: Основы
DirectShow For
Media Playback In Windows
Part I: Basics
By Chris Thompson
(aka Lightman)
28 July 2000
Введение
Несколько лет назад Microsoft ввела надстройку над DirectX для организации
потока медиа-данных, что означало возможность с легкостью управляться с любыми
типами мультимедиа, которые поддерживает эта надстройка. Ну и называлась она,
соответственно, DirectShow.
DShow является частью DirectX Media, куда кроме нее еще входит DirectAnimation
(фича для веб-страничек), DirectX Transform (еще фича для веб-страничек),
а так же старичок Direct3D Retained Mode, который теперь плавно влился
в основную часть DirectX. Этот учебник покажет вам как проигрывать стандартные
медиа-типы в вашей игре или приложении при помощи DirectShow из C++
Microsoft в лучших традициях заботы о клиентах не предлагает нам скачать DirectX
Media SDK, поэтому вам надо предварительно запастить диском с указанным
набором разработки или разжиться самым последним Platform SDK.
Заметка о COM
Как и все библиотеки DirectX, DirectShow доступен через интерфейсы COM, поэтому
я предполагаю, что для начала вы знакомы с COM и такими приемами как получение
указателей на интерфейсы, нужные вам и правильное их уничтожение.
Объяснение DirectShow
DirectShow строится на идее использования некоторого количества "фильтров",
которые будучи объединены вместе, образуют "граф". Вот вам визуальная
репрезентация графа фильтров, который получился при использовании утилиты, поставляемой
вместе с DirectXMedia SDK, под названием GraphEdit.

Каждый прямоугольник представляет собой фильтр. Стрелки, соединяющие прямоугольники,
изображают как выходные данные из одного фильтра поступают на вход другого.
Стрелки так же показывают поток данных в графе. GraphEdit полезен для тех, кто
только начинает разбираться с DirectShow, так как дает ясный эквивалент тому,
чем мы будем заниматься позже на программном уровне. GraphEdit так же позволяет
вам перемещать фильтры туда-сюда, играться с соединяющими стрелками, ну и наконец
испробовать финальную версию.
Каждый построенный граф должен следовать определенным принципам. Для начала,
должен быть исходный фильтр. Это первичный источник ваших данных и он может
являться например файлом, адресом URL для потокового мультимедиа или каким-либо
устройством наподобие fireware-карты присоединенной к видеокамере. Выходящий
поток исходного фильтра затем может проходить через любое количество преобразующих
фильтров. Преобразующие фильтры - это промежуточные фильтры, которые берут некие
данные, каким-то образом трансформируют их, а затем переправляют на выход. Наконец,
последний элемент в графе - это выводящий фильтр.Выводящие фильтры - это финальная
точка путешествия любого байта, попавшего в граф. Выводящие фильтры могут представлять
собой такие вещи, как окно для вывода видео, звуковую карту для вывода звуков
или устройство записи для сохранения данных на диск.
Фильтры в графе соединены с помощью контактов (пинов). Каждый фильтр, неважно
какого типа, должен иметь хотя бы один контакт для взаимодействия с другими
фильтрами. При попытке соединения двух фильтров, пины на обоих пересылают информацию
назад и вперед для выяснения того, может ли нижний фильтр (тот, который лежит
вниз по течению потока информации) обрабатывать данные, передаваемые ему верхним
фильтром (посылающим данные). Если контакты договорятся о взаимном понимании
информации, которой они собираются обмениваться, то создается соединение между
двумя фильтрами. Как вы можете видеть на картинке вверху, фильтр не ограничен
в количестве входов и выходов и много раз будет случаться такое, что фильтр
будет требовать больше, чем один вход или выход для обрабатываемых данных. Например,
фильтр - делитель потока MPEG-1 требует, чтобы аудио и видео информация MPEG-1
данных проходили через раздельные декодирующие фильтры.
DirectShow распространяется с некоторым количеством фильтров, предоставленных
Microsoft, включая исходные фильтры, трансформирующие фильтры и выводящие фильтры.
Они предоставили в наше пользование полезный "File Source Filter",
то бишь исходный фильтр, берущий данные из любого типа файла, трансформирующие
фильтры, способные работать с MPEG-1 видео, AVI видео, WAV аудио и другими форматами,
и наконец, фильтры для вывода аудио и видео. Для стандартных случаев, фильтры,
предоставленные Microsoft - это все, что вам может потребоваться для проигрывания.
Строим и тестируем граф в GraphEdit
GraphEdit - это превосходный инструмент, который вы можете использовать для
создания и тестирования графа фильтров выполняющего проигрывание любого медиа-типа,
какой вы только захотите применит в вашей программе. Я не буду тут расписывать
все детали использования GraphEdit, но это важно для вас разбираться в нем вместо
того, чтобы тратить время на отладку кода, прежде чем догадаться, что это всего
лишь два фильтра не согласованы по типу данных. Первая вещь, которую вы должны
сделать - это выбрать "Render Media File" и выбрать медиа-файл, который
вы хотите проиграть.

GraphEdit попробует построить граф, который подойдет для проигрывания типа
файла, который вы выбрали. Если программа в этом добьется успеха, вы можете
нажать на кнопку 'play' на панели инструментов для запуска вашего графа. Если
же попытка будет неудачна, вам нужно будет выбрать "Graph->Insert Filters"
из меню и посмотреть на наличие альтернативных фильтров, которые бы могли работать
с вашим типом мультимедиа и которые вы бы могли присандалить к вашему графу.
Иногда случается, что декодер по умолчанию или выводящий фильтр который ставит
GraphEdit на самом деле вовсе не является желаемым вами или не работает, и в
этом случае вы можете поискать альтернативный фильтр, который будет работать
лучше.
Это важная вещь - найти комбинацию фильтров, которые благополучно будут выводить
ваши данные, потому что если это не будет работать в GraphEdit, это и подавно
не будет работать в вашей программе.
Простой граф, выполненный на C++
Следующий код - это пример на C++, который создает граф для проигрывания WAV-файла.
Он проигрывает 10 секунд из из этого файла, а затем замолкает и программа завершается
Загрузите исходный
код примера (2k)
Если вы собираетесь компилировать этот пример, удостоверьтесь, что вы проинсталлировали
DirectX Media SDK и включили strmbasd.lib (для отладки) или strmbase.lib (для
релиза) для успешной компиляции.
Запустите программу из командной строки, а имя файла, который надо проигрывать
передайте в качестве аргумента. Например: dshowtut1.exe test.wav
Заметки о потоках
Важная вещь, на которую следует обращать внимание при использовании DirectShow
- это то, что в процессе выполнения графа используются для проигрывания несколько
отдельных потоков. Используя Spy++ вы можете увидеть, что DShowTut1 имеет 10
потоков в процессе выполнения. Я не смог сосчитать все потоки, но так думаю,
что DirectShow создает одну штуку для менеджера графов (IGraphBuilder) и по
отдельному потоку для каждого из фильтров. У этой особенности есть как хорошие,
так и плохие стороны. Вывод медиа-данных в различных потоках подразумевает,
что вы без проблем можете заниматься в своей программе другими вещами в процессе
проигрывания. Но это так же значит, что вам надо освобождать системное время,
чтобы дать этим потокам завершиться.
Если вы играетесь на полную катушку в какую-нибудь игру и хотели бы использовать
DirectShow для вывода фоновой музыки, то это дело скорее всего закончится прерывистым
звуковым выводом, потому что главный цикл игры ьудет работать с большим приоритетом
потока, чем потоки DirectShow, поэтому Windows будет отнимать системное время
у игры только когда уж совсем припрет. Вот из-за этого, DirectShow может стать
не лучшим решением для некоторых приложений. Если ваша программа может запастить
некоторым временем, например в промежуточных мультиках, или не имеет насколько-только-можно-быстрый
главный цикл, вам нужно освободить главный поток для того, чтобы позволить другим
хотя бы запуститься. Вообще, потоки - довольно серьезный предмет для изучения,
поэтому я больше не буду морочить ими ваши головы. Просто имейте в виду, что
вам нужно освободить пару ресурсов, чтобы потоки DirectShow могли запускаться,
а если звук в программе прерывается, видео тормозит, а из системного блока уже
пошел дымок, то причина в главном потоке.
Заключение
Эта часть учебника не занималась копанием в недра DirectShow, но как минимум,
у вас теперь должно сложиться представление об основных концепциях DShow. Так
же, теперь вам должно стать ясно - сможете ли вы использовать DirectShow в ваших
приложениях, строя и тестируя графы, используя GraphEdit. Пример кода под названием
DShowTut1.cpp не делает многого, я знаю это, но вы можете увидеть то, что делает
GraphEdit со стороны C++.
В следующей части учебника, я объясню более осмысленно главные интерфейсы DirectShow
и как их использовать. Так же я вам погрызть намного больше кода.
Chris Thompson (aka Lightman)
cdthompson@home.net
На русский язык статью перевел Anti
|
 |
 |
|