DirectShow - экземпляры фильтра для разных устройств
От: Евгений Музыченко Франция https://software.muzychenko.net/ru
Дата: 12.01.20 14:43
Оценка:
В категориях CLSID_AudioInputDeviceCategory, CLSID_AudioRendererCategory, AM_KSCATEGORY_CAPTURE, AM_KSCATEGORY_RENDER всегда создается по отдельному экземпляру фильтров для каждого устройства. Хочу создавать такие же экземпляры для своего фильтра, но не могу понять, как это делается. Думал, что перечислитель запрашивает у каждого фильтра IMoniker/IEnumMoniker, но фильтр впервые загружается только при получении ссылки на его объект. Получается, что эти экземпляры создаются перечислителем на основе регистрационных данных из реестра.

Эта кухня где-нибудь описана? Минимально вдумчивым гуглением найти не сумел.
directshow filter enumerator device instance capture render wave directsound
Re: DirectShow - экземпляры фильтра для разных устройств
От: Videoman Россия https://hts.tv/
Дата: 12.01.20 15:38
Оценка:
Здравствуйте, Евгений Музыченко, Вы писали:

ЕМ>В категориях CLSID_AudioInputDeviceCategory, CLSID_AudioRendererCategory, AM_KSCATEGORY_CAPTURE, AM_KSCATEGORY_RENDER всегда создается по отдельному экземпляру фильтров для каждого устройства. Хочу создавать такие же экземпляры для своего фильтра, но не могу понять, как это делается. Думал, что перечислитель запрашивает у каждого фильтра IMoniker/IEnumMoniker, но фильтр впервые загружается только при получении ссылки на его объект. Получается, что эти экземпляры создаются перечислителем на основе регистрационных данных из реестра.


Ну вот я в точности прошел тот же путь и для себя решил, что единственное приемлемое решение такое:
1. При регистрации фильтра устройства мы выполняем свой сервисный код, который определяет сколько устройств в системе на данный момент, и регистрируем один и тот же фильтр устройства меняя GUID для каждого экземпляра.
2. Подменяется фабрика класса на свою реализацию, где уже при создании экземпляра класса ему передается GUID c которым его создают.
3. Дальше уже исходя из GUID-а определяем свою роль и т.д.

Правда страдает интерактивность: фильтр устройства может быть зарегистрирован, а самого устройства может не быть на месте и создание фильтра завершится ошибкой, но тем не менее, лучшего способа я пока не нашел.
Re[2]: DirectShow - экземпляры фильтра для разных устройств
От: Евгений Музыченко Франция https://software.muzychenko.net/ru
Дата: 13.01.20 10:38
Оценка:
Здравствуйте, Videoman, Вы писали:

V>1. При регистрации фильтра устройства мы выполняем свой сервисный код, который определяет сколько устройств в системе на данный момент, и регистрируем один и тот же фильтр устройства меняя GUID для каждого экземпляра.


Я вчера немного поковырял, и обнаружил: если зарегистрировать дополнительную категорию в CLSID_ActiveMovieCategories, и с этим же GUID дополнительно зарегистрировать COM-сервер (можно ту же DLL фильтра), то при запросе перечисления devenum.dll вызывает сервер через DllGetClassObject, запрашивая Class Factory для GUID категории. Затем у фабрики через CreateInstance запрашивается ICreateDevEnum.
Re[3]: DirectShow - экземпляры фильтра для разных устройств
От: Videoman Россия https://hts.tv/
Дата: 13.01.20 11:57
Оценка:
Здравствуйте, Евгений Музыченко, Вы писали:

ЕМ>Я вчера немного поковырял, и обнаружил: если зарегистрировать дополнительную категорию в CLSID_ActiveMovieCategories, и с этим же GUID дополнительно зарегистрировать COM-сервер (можно ту же DLL фильтра), то при запросе перечисления devenum.dll вызывает сервер через DllGetClassObject, запрашивая Class Factory для GUID категории. Затем у фабрики через CreateInstance запрашивается ICreateDevEnum.


Не совсем понимаю как это может помочь ?
Re[4]: DirectShow - экземпляры фильтра для разных устройств
От: Евгений Музыченко Франция https://software.muzychenko.net/ru
Дата: 13.01.20 12:16
Оценка:
Здравствуйте, Videoman, Вы писали:

V>Не совсем понимаю как это может помочь ?


Через ICreateDevEnum::CreateClassEnumerator вернуть IEnumMoniker. Через IEnumMoniker::Next возвращать экземпляры фильтра для каждого из устройств.
Re[5]: DirectShow - экземпляры фильтра для разных устройств
От: Videoman Россия https://hts.tv/
Дата: 13.01.20 19:41
Оценка:
Здравствуйте, Евгений Музыченко, Вы писали:

ЕМ>Через ICreateDevEnum::CreateClassEnumerator вернуть IEnumMoniker. Через IEnumMoniker::Next возвращать экземпляры фильтра для каждого из устройств.


Если подытожить:
1. Регистрирует свой фильтр не только нужной категории, но и еще дополнительно в CLSID_ActiveMovieCategories.
2. Переписываем фабрику для поддержки интерфейса ICreateDevEnum
3. Дальше уже реализуем этот интерфейс для созданий устройств по моникеру

Все так? Что-то я не могу найти в MSDN где это механизм описан
Re[6]: DirectShow - экземпляры фильтра для разных устройств
От: Евгений Музыченко Франция https://software.muzychenko.net/ru
Дата: 13.01.20 21:02
Оценка:
Здравствуйте, Videoman, Вы писали:

V>1. Регистрирует свой фильтр не только нужной категории, но и еще дополнительно в CLSID_ActiveMovieCategories.


Не совсем так. CLSID_ActiveMovieCategories — это GUID ветки реестра, где перечислены известные категории фильтров. Вроде бы для создания категории можно использовать IFilterMapper2::CreateCategory, но я для проверки тупо добавил ключи/значения в реестр.

У каждой категории должен быть сервер Class Manager. Для некоторых он явно зарегистрирован на GUID категории, для остальных этим занимается, как я понял, сама devenum.dll. Соответственно, для новой категории нужно зарегистрировать сервер с таким же GUID, чтобы devenum.dll могла попросить у него перечислитель.

V>2. Переписываем фабрику для поддержки интерфейса ICreateDevEnum


Ага. А в DllGetClassObject добавляем возможность создания фабрики для класса с GUID категории.

V>3. Дальше уже реализуем этот интерфейс для созданий устройств по моникеру


Вроде так.

V>Что-то я не могу найти в MSDN где это механизм описан


Нигде не описан. Это я позавчера расковырял чисто интуитивно. Реализовать ICreateDevEnum пока руки не дошли, возникли более срочные дела.
Re[7]: DirectShow - экземпляры фильтра для разных устройств
От: Videoman Россия https://hts.tv/
Дата: 13.01.20 22:21
Оценка:
ЕМ>У каждой категории должен быть сервер Class Manager. Для некоторых он явно зарегистрирован на GUID категории, для остальных этим занимается, как я понял, сама devenum.dll. Соответственно, для новой категории нужно зарегистрировать сервер с таким же GUID, чтобы devenum.dll могла попросить у него перечислитель.

Ну вот у меня например устройства, обычно это Video Capture Source и Audio Capture Source. Соответствующие категории у них уже есть в системе и там они и регистрируются с помощью фильтр-маппера. Соответственно, перечислениями этих устройств занимает devenum.dll. Но вот устройств обслуживаемых одним и тем же фильтром может быть несколько. Например это может быть виртуальная SDI плата с конфигурируемым количеством входов, каждый из которых должен быть представлен отдельным фильтром. Тогда как мне добавить свои устройства? Не подменять же стандартную фабрику класса в devenum.dll ?
Отредактировано 13.01.2020 22:22 Videoman . Предыдущая версия .
Re[8]: DirectShow - экземпляры фильтра для разных устройств
От: Евгений Музыченко Франция https://software.muzychenko.net/ru
Дата: 14.01.20 07:46
Оценка:
Здравствуйте, Videoman, Вы писали:

V>Ну вот у меня например устройства, обычно это Video Capture Source и Audio Capture Source. Соответствующие категории у них уже есть в системе и там они и регистрируются с помощью фильтр-маппера


Строго говоря, стандартные категории не являются "соответствующими". Например, для устройств аудиозаписи есть CLSID_AudioInputDeviceCategory (MME/waveIn) и KSCATEGORY_CAPTURE/AM_KSCATEGORY_CAPTURE (WDM/KS). То есть, эти категории больше похожи на группы фильтров, обслуживаемых одним сервером. Соответственно, ничто не мешает иметь отдельную категорию для своей группы фильтров.

V>Соответственно, перечислениями этих устройств занимает devenum.dll.


Да, но devenum, как я понял, не предусматривает вызова какого-либо собственного перечислителя для каждого фильтра. У известных ему фильтров оно, похоже, просит ICreateDevEnum, но я не знаю, можно ли как-то пометить для этого свой фильтр. Возможно, это зависит от значений в FilterData, но там, судя по всему, лежат упакованные данные из REGFILTER2.

V>Тогда как мне добавить свои устройства? Не подменять же стандартную фабрику класса в devenum.dll ?


Если не хотите размещать фильтры в отдельных категориях, то придется копать дальше. devenum загружает DLL сервера категории только после того, как будет запрошено перечисление в данной категории. Когда строится список категорий, обращения к DLL не происходит.
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.