Примечание.
Для доступа к этой странице требуется авторизация. Вы можете попробовать войти или изменить каталоги.
Для доступа к этой странице требуется авторизация. Вы можете попробовать изменить каталоги.
[Функция, связанная с этой страницей, DirectShow, является устаревшей функцией. Он был заменен MediaPlayer, IMFMediaEngineи аудио- и видеозахватом в технологии Media Foundation. Эти функции оптимизированы для Windows 10 и Windows 11. Корпорация Майкрософт настоятельно рекомендует использовать новый код MediaPlayer, IMFMediaEngine и аудио-видеозахват в Media Foundation вместо DirectShowпо возможности. Корпорация Майкрософт предлагает, что существующий код, использующий устаревшие API, будет перезаписан для использования новых API, если это возможно.]
Это шаг 6 руководства по созданию фильтров преобразования.
Последний шаг — добавить поддержку COM.
Подсчет ссылок
Вам не нужно реализовать IUnknown::AddRef или IUnknown::Release. Все классы фильтров и закреплений являются производными от CUnknown, которая обрабатывает подсчет ссылок.
QueryInterface
Все классы фильтров и привязок реализуют IUnknown::QueryInterface для любых наследуемых COM-интерфейсов. Например, CTransformFilter наследует IBaseFilter (через CBaseFilter). Если фильтр не предоставляет никаких дополнительных интерфейсов, вам не нужно ничего делать.
Чтобы предоставить дополнительные интерфейсы, переопределите метод CUnknown::NonDelegatingQueryInterface. Например, предположим, что фильтр реализует пользовательский интерфейс с именем IMyCustomInterface. Чтобы предоставить этот интерфейс клиентам, сделайте следующее:
- Наследуйте класс фильтра из этого интерфейса.
- Поместите макрос DECLARE_IUNKNOWN в раздел общедоступного объявления.
- Переопределите NonDelegatingQueryInterface, чтобы проверить IID вашего интерфейса и вернуть указатель на ваш фильтр.
В следующем коде показаны следующие действия.
CMyFilter : public CBaseFilter, public IMyCustomInterface
{
public:
DECLARE_IUNKNOWN
STDMETHODIMP NonDelegatingQueryInterface(REFIID iid, void **ppv);
};
STDMETHODIMP CMyFilter::NonDelegatingQueryInterface(REFIID iid, void **ppv)
{
if (riid == IID_IMyCustomInterface) {
return GetInterface(static_cast<IMyCustomInterface*>(this), ppv);
}
return CBaseFilter::NonDelegatingQueryInterface(riid,ppv);
}
Дополнительные сведения см. в разделе How to Implement IUnknown.
Создание объекта
Если вы планируете упаковать фильтр в библиотеку DLL и сделать его доступным для других клиентов, необходимо поддерживать CoCreateInstance и другие связанные функции COM. Библиотека базовых классов реализует большую часть этого. Вам просто нужно предоставить некоторые сведения о фильтре. В этом разделе представлен краткий обзор действий. Дополнительные сведения см. в статье Как создать DLL-фильтр DirectShow.
Сначала напишите метод статического класса, который возвращает новый экземпляр фильтра. Вы можете присвоить этому методу любое имя, но подпись должна соответствовать той, что показана в следующем примере:
CUnknown * WINAPI CRleFilter::CreateInstance(LPUNKNOWN pUnk, HRESULT *pHr)
{
CRleFilter *pFilter = new CRleFilter();
if (pFilter== NULL)
{
*pHr = E_OUTOFMEMORY;
}
return pFilter;
}
Затем объявите глобальный массив экземпляров классов CFactoryTemplate с именем g_Templates. Каждый класс CFactoryTemplate содержит сведения о реестре для одного фильтра. Несколько фильтров могут находиться в одной библиотеке DLL. Просто добавьте дополнительные записи CFactoryTemplate. Вы также можете объявить другие COM-объекты, такие как страницы свойств.
static WCHAR g_wszName[] = L"My RLE Encoder";
CFactoryTemplate g_Templates[] =
{
{
g_wszName,
&CLSID_RLEFilter,
CRleFilter::CreateInstance,
NULL,
NULL
}
};
Определите глобальное целое число с именем g_cTemplates, значение которого равно длине массива g_Templates:
int g_cTemplates = sizeof(g_Templates) / sizeof(g_Templates[0]);
Наконец, реализуйте функции регистрации DLL. В следующем примере показана минимальная реализация этих функций:
STDAPI DllRegisterServer()
{
return AMovieDllRegisterServer2( TRUE );
}
STDAPI DllUnregisterServer()
{
return AMovieDllRegisterServer2( FALSE );
}
Фильтрация записей реестра
В предыдущих примерах показано, как зарегистрировать CLSID фильтра для COM. Для многих фильтров это достаточно. Затем клиент должен создать фильтр с помощью CoCreateInstance и добавить его в граф фильтров путем вызова IFilterGraph::AddFilter. Однако в некоторых случаях может потребоваться предоставить дополнительные сведения о фильтре в реестре. Эта информация выполняет следующие действия.
- Позволяет клиентам обнаруживать фильтр с помощью фильтра или системного перечислителя устройств.
- Позволяет диспетчеру графов фильтров обнаруживать фильтр во время автоматического построения графа.
В следующем примере регистрируется фильтр кодировщика RLE в категории видеокомпрессора. Дополнительные сведения см. в разделе Регистрация фильтров DirectShow. Обязательно ознакомьтесь с разделом руководства по регистрации фильтров, в котором описаны рекомендуемые методики регистрации фильтров.
// Declare media type information.
FOURCCMap fccMap = FCC('MRLE');
REGPINTYPES sudInputTypes = { &MEDIATYPE_Video, &GUID_NULL };
REGPINTYPES sudOutputTypes = { &MEDIATYPE_Video, (GUID*)&fccMap };
// Declare pin information.
REGFILTERPINS sudPinReg[] = {
// Input pin.
{ 0, FALSE, // Rendered?
FALSE, // Output?
FALSE, // Zero?
FALSE, // Many?
0, 0,
1, &sudInputTypes // Media types.
},
// Output pin.
{ 0, FALSE, // Rendered?
TRUE, // Output?
FALSE, // Zero?
FALSE, // Many?
0, 0,
1, &sudOutputTypes // Media types.
}
};
// Declare filter information.
REGFILTER2 rf2FilterReg = {
1, // Version number.
MERIT_DO_NOT_USE, // Merit.
2, // Number of pins.
sudPinReg // Pointer to pin information.
};
STDAPI DllRegisterServer(void)
{
HRESULT hr = AMovieDllRegisterServer2(TRUE);
if (FAILED(hr))
{
return hr;
}
IFilterMapper2 *pFM2 = NULL;
hr = CoCreateInstance(CLSID_FilterMapper2, NULL, CLSCTX_INPROC_SERVER,
IID_IFilterMapper2, (void **)&pFM2);
if (SUCCEEDED(hr))
{
hr = pFM2->RegisterFilter(
CLSID_RLEFilter, // Filter CLSID.
g_wszName, // Filter name.
NULL, // Device moniker.
&CLSID_VideoCompressorCategory, // Video compressor category.
g_wszName, // Instance data.
&rf2FilterReg // Filter information.
);
pFM2->Release();
}
return hr;
}
STDAPI DllUnregisterServer()
{
HRESULT hr = AMovieDllRegisterServer2(FALSE);
if (FAILED(hr))
{
return hr;
}
IFilterMapper2 *pFM2 = NULL;
hr = CoCreateInstance(CLSID_FilterMapper2, NULL, CLSCTX_INPROC_SERVER,
IID_IFilterMapper2, (void **)&pFM2);
if (SUCCEEDED(hr))
{
hr = pFM2->UnregisterFilter(&CLSID_VideoCompressorCategory,
g_wszName, CLSID_RLEFilter);
pFM2->Release();
}
return hr;
}
Кроме того, фильтры не должны упаковываться в библиотеки DLL. В некоторых случаях можно написать специализированный фильтр, предназначенный только для конкретного приложения. В этом случае можно скомпилировать класс фильтра непосредственно в приложении и создать его с помощью оператора new, как показано в следующем примере:
#include "MyFilter.h" // Header file that declares the filter class.
// Compile and link MyFilter.cpp.
int main()
{
IBaseFilter *pFilter = 0;
{
// Scope to hide pF.
CMyFilter* pF = new MyFilter();
if (!pF)
{
printf("Could not create MyFilter.\n");
return 1;
}
pF->QueryInterface(IID_IBaseFilter,
reinterpret_cast<void**>(&pFilter));
}
/* Now use pFilter as normal. */
pFilter->Release(); // Deletes the filter.
return 0;
}
Связанные разделы