Примечание.
Для доступа к этой странице требуется авторизация. Вы можете попробовать войти или изменить каталоги.
Для доступа к этой странице требуется авторизация. Вы можете попробовать изменить каталоги.
[Функция, связанная с этой страницей, DirectShow, является устаревшей функцией. Он был заменён MediaPlayer, IMFMediaEngineи Аудио- и видеозахватом в Media Foundation. Эти функции оптимизированы для Windows 10 и Windows 11. Корпорация Майкрософт настоятельно рекомендует в новом коде использовать MediaPlayer, IMFMediaEngine и захват аудио/видео в Media Foundation вместо DirectShow, по возможности. Корпорация Майкрософт предлагает, что существующий код, использующий устаревшие API, будет перезаписан для использования новых API, если это возможно.]
Несмотря на своё название, построитель графов захвата полезен для создания множества типов настраиваемых графов фильтров, а не только графов захвата. В этой статье представлен краткий обзор использования этого объекта.
Построитель графов записи предоставляет интерфейс ICaptureGraphBuilder2. Начните с вызова CoCreateInstance для создания построителя графов записи и диспетчера графов фильтров. Затем инициализируйте построитель графов захвата, вызвав ICaptureGraphBuilder2::SetFiltergraph с указателем на менеджер графов фильтров, как показано ниже.
IGraphBuilder *pGraph = NULL;
ICaptureGraphBuilder2 *pBuilder = NULL;
// Create the Filter Graph Manager.
HRESULT hr = CoCreateInstance(CLSID_FilterGraph, NULL,
CLSCTX_INPROC_SERVER, IID_IGraphBuilder, (void **)&pGraph);
if (SUCCEEDED(hr))
{
// Create the Capture Graph Builder.
hr = CoCreateInstance(CLSID_CaptureGraphBuilder2, NULL,
CLSCTX_INPROC_SERVER, IID_ICaptureGraphBuilder2,
(void **)&pBuilder);
if (SUCCEEDED(hr))
{
pBuilder->SetFiltergraph(pGraph);
}
};
Подключение фильтров
Метод ICaptureGraphBuilder2::RenderStream соединяет два или три фильтра в цепочке. Как правило, метод лучше всего работает, если у каждого фильтра не более одного входного контакта или выходного контакта одного типа. Это обсуждение начинается с игнорирования первых двух параметров RenderStream и сосредоточившись на последних трех параметрах. Третий параметр — это указатель IUnknown, который может указать фильтр (как указатель интерфейса IBaseFilter) или выходной вывод (в качестве указателя интерфейса IPin). Четвертые и пятые параметры указывают указатели IBaseFilter. Метод RenderStream подключает все три фильтра в цепочке. Например, предположим, что A, Bи C являются фильтрами. Предположим, что каждый фильтр имеет ровно один входной пин-код и один выходной пин-код. Следующий вызов подключает A к B, а затем B к C:
- "RenderStream(NULL, NULL, A, B, C)"
Все подключения являются "интеллектуальными", что означает, что дополнительные фильтры добавляются в граф по мере необходимости. Дополнительные сведения см. в разделе Intelligent Connect. Чтобы подключить только два фильтра, задайте для среднего значения значение NULL. Например, этот вызов подключает A к C:
- "RenderStream(NULL, NULL, A, NULL, C)"
Можно создать более длинные цепочки, вызвав метод дважды:
- "RenderStream(NULL, NULL, A, B, C)" "RenderStream(NULL, NULL, C, D, E)"
Если последний параметр NULL, метод автоматически находит стандартный рендерер (отрисовщик). Для видео используется видео-рендер , а для звука — DirectSound Renderer . Таким образом:
- "RenderStream(NULL, NULL, A, NULL, NULL)"
эквивалентно
- "RenderStream(NULL, NULL, A, NULL, R)"
где R является соответствующим визуализатором. Чтобы подключить фильтр видеомиксера вместо отрисовщика видео, необходимо указать это явно.
Если в третьем параметре указан фильтр, а не пин-код, может потребоваться указать, какой выходной пин-код следует использовать для подключения. Это цель первых двух параметров метода. Первый параметр применяется только к фильтрам записи. Он задает GUID, указывающий категорию пинов. Полный список категорий см. в разделе Набор свойств pin. Две категории допустимы для всех фильтров записи:
- PIN_CATEGORY_CAPTURE
- PIN_CATEGORY_PREVIEW
Если фильтр захвата не предоставляет отдельные контакты для захвата и предварительного просмотра, метод RenderStream вставляет фильтр Smart Tee, который разбивает поток на поток захвата и поток предварительного просмотра. С точки зрения приложения, вы можете просто обрабатывать все фильтры захвата как отдельные контакты и игнорировать базовую топологию графа.
Для захвата файлов подключите контакт захвата к мультиплексору. Для динамической предварительной версии подключите пин-код предварительного просмотра к отрисовщику. При переключении двух категорий граф может удалить чрезмерное количество кадров во время записи файла; но если граф подключен правильно, он удаляет кадры предварительного просмотра при необходимости для поддержания пропускной способности в потоке записи.
В следующем примере показано, как подключить оба потока:
// Capture to file:
pBuilder->RenderStream(&PIN_CATEGORY_CAPTURE, NULL, pCapFilter, NULL, pMux);
// Preview:
pBuilder->RenderStream(&PIN_CATEGORY_PREVIEW, NULL, pCapFilter, NULL, NULL);
Некоторые фильтры записи также поддерживают закрытые субтитры, указанные PIN_CATEGORY_VBI. Чтобы записать закрытые субтитры в файл, передайте эту категорию фильтру мультиплексора. Чтобы просмотреть закрытые субтитры в окне предварительного просмотра, подключитесь к отрисовщику:
// Capture to file:
pBuilder->RenderStream(&PIN_CATEGORY_VBI, NULL, pCapFilter, NULL, pMux);
// Preview on screen:
pBuilder->RenderStream(&PIN_CATEGORY_VBI, NULL, pCapFilter, NULL, NULL);
Второй параметр для RenderStream определяет тип носителя и обычно является одним из следующих:
- ТИП_МЕДИА_Аудио
- MEDIATYPE_Видео
- MEDIATYPE_Interleaved (DV)
Этот параметр можно использовать всякий раз, когда выходные контакты фильтра поддерживают перечисление предпочтительных типов носителей. Для источников файлов конструктор графов захвата автоматически добавляет фильтр синтаксического анализа при необходимости, а затем запрашивает типы носителей у средства синтаксического анализа. (Пример см. в статье Повторное сжатие файла AVI.) Кроме того, если последний фильтр в цепочке имеет несколько входных пинов, метод пытается перечислить их мультимедийные типы. Однако не все фильтры поддерживают эту функцию.
Поиск интерфейсов на фильтрах и штырях
После создания графа обычно требуется найти различные интерфейсы, предоставляемые фильтрами и пинами в графе. Например, фильтр захвата может предоставлять интерфейс IAMDroppedFrames, а выходные контакты фильтра могут предоставлять интерфейс IAMStreamConfig.
Самый простой способ найти интерфейс — использовать метод ICaptureGraphBuilder2::FindInterface. Этот метод проходит по графу (фильтрам и пинам), пока не найдет нужный интерфейс. Можно указать начальную точку для поиска, и можно ограничить поиск фильтрами вверх или вниз по начальной точке.
В следующем примере выполняется поиск интерфейса IAMStreamConfig на пин-коде предварительного просмотра видео:
IAMStreamConfig *pConfig = NULL;
HRESULT hr = pBuild->FindInterface(
&PIN_CATEGORY_PREVIEW,
&MEDIATYPE_Video,
pVCap,
IID_IAMStreamConfig,
(void**)&pConfig
);
if (SUCCESSFUL(hr))
{
/* ... */
pConfig->Release();
}
Заметка
В теме Поиск интерфейса в фильтре или пине показан альтернативный подход, который использует интерфейс IGraphBuilder вместо ICaptureGraphBuilder2. Какой подход к использованию зависит от приложения. Если приложение уже использует ICaptureGraphBuilder2 для построения графа, то ICaptureGraphBuilder2::FindInterface является хорошим подходом. В противном случае рассмотрите использование методов IGraphBuilder.
Поиск закреплений
Менее часто может потребоваться найти отдельный штырь на фильтре, хотя в большинстве случаев методы RenderStream и FindInterface помогут вам сэкономить. Если вам нужно найти определенный вывод фильтра, полезно использовать вспомогательный метод ICaptureGraphBuilder2::FindPin. Укажите категорию, тип носителя (видео или аудио), направление и требование, чтобы пин был неподключён.
Например, следующий код ищет несоединяемый пин-код предварительного просмотра видео в фильтре записи:
IPin *pPin = NULL;
hr = pBuild->FindPin(
pCap, // Pointer to the filter to search.
PINDIR_OUTPUT, // Search for an output pin.
&PIN_CATEGORY_PREVIEW, // Search for a preview pin.
&MEDIATYPE_Video, // Search for a video pin.
TRUE, // The pin must be unconnected.
0, // Return the first matching pin (index 0).
&pPin); // This variable receives the IPin pointer.
if (SUCCESSFUL(hr))
{
/* ... */
pPin->Release();
}
Связанные разделы