В категориях CLSID_AudioInputDeviceCategory, CLSID_AudioRendererCategory, AM_KSCATEGORY_CAPTURE, AM_KSCATEGORY_RENDER всегда создается по отдельному экземпляру фильтров для каждого устройства. Хочу создавать такие же экземпляры для своего фильтра, но не могу понять, как это делается. Думал, что перечислитель запрашивает у каждого фильтра IMoniker/IEnumMoniker, но фильтр впервые загружается только при получении ссылки на его объект. Получается, что эти экземпляры создаются перечислителем на основе регистрационных данных из реестра.
Эта кухня где-нибудь описана? Минимально вдумчивым гуглением найти не сумел.
Здравствуйте, Евгений Музыченко, Вы писали:
ЕМ>В категориях CLSID_AudioInputDeviceCategory, CLSID_AudioRendererCategory, AM_KSCATEGORY_CAPTURE, AM_KSCATEGORY_RENDER всегда создается по отдельному экземпляру фильтров для каждого устройства. Хочу создавать такие же экземпляры для своего фильтра, но не могу понять, как это делается. Думал, что перечислитель запрашивает у каждого фильтра IMoniker/IEnumMoniker, но фильтр впервые загружается только при получении ссылки на его объект. Получается, что эти экземпляры создаются перечислителем на основе регистрационных данных из реестра.
Ну вот я в точности прошел тот же путь и для себя решил, что единственное приемлемое решение такое:
1. При регистрации фильтра устройства мы выполняем свой сервисный код, который определяет сколько устройств в системе на данный момент, и регистрируем один и тот же фильтр устройства меняя GUID для каждого экземпляра.
2. Подменяется фабрика класса на свою реализацию, где уже при создании экземпляра класса ему передается GUID c которым его создают.
3. Дальше уже исходя из GUID-а определяем свою роль и т.д.
Правда страдает интерактивность: фильтр устройства может быть зарегистрирован, а самого устройства может не быть на месте и создание фильтра завершится ошибкой, но тем не менее, лучшего способа я пока не нашел.
Re[2]: DirectShow - экземпляры фильтра для разных устройств
Здравствуйте, Videoman, Вы писали:
V>1. При регистрации фильтра устройства мы выполняем свой сервисный код, который определяет сколько устройств в системе на данный момент, и регистрируем один и тот же фильтр устройства меняя GUID для каждого экземпляра.
Я вчера немного поковырял, и обнаружил: если зарегистрировать дополнительную категорию в CLSID_ActiveMovieCategories, и с этим же GUID дополнительно зарегистрировать COM-сервер (можно ту же DLL фильтра), то при запросе перечисления devenum.dll вызывает сервер через DllGetClassObject, запрашивая Class Factory для GUID категории. Затем у фабрики через CreateInstance запрашивается ICreateDevEnum.
Re[3]: DirectShow - экземпляры фильтра для разных устройств
Здравствуйте, Евгений Музыченко, Вы писали:
ЕМ>Я вчера немного поковырял, и обнаружил: если зарегистрировать дополнительную категорию в CLSID_ActiveMovieCategories, и с этим же GUID дополнительно зарегистрировать COM-сервер (можно ту же DLL фильтра), то при запросе перечисления devenum.dll вызывает сервер через DllGetClassObject, запрашивая Class Factory для GUID категории. Затем у фабрики через CreateInstance запрашивается ICreateDevEnum.
Не совсем понимаю как это может помочь ?
Re[4]: DirectShow - экземпляры фильтра для разных устройств
Здравствуйте, Евгений Музыченко, Вы писали:
ЕМ>Через ICreateDevEnum::CreateClassEnumerator вернуть IEnumMoniker. Через IEnumMoniker::Next возвращать экземпляры фильтра для каждого из устройств.
Если подытожить:
1. Регистрирует свой фильтр не только нужной категории, но и еще дополнительно в CLSID_ActiveMovieCategories.
2. Переписываем фабрику для поддержки интерфейса ICreateDevEnum
3. Дальше уже реализуем этот интерфейс для созданий устройств по моникеру
Все так? Что-то я не могу найти в MSDN где это механизм описан
Re[6]: DirectShow - экземпляры фильтра для разных устройств
Здравствуйте, 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 - экземпляры фильтра для разных устройств
ЕМ>У каждой категории должен быть сервер Class Manager. Для некоторых он явно зарегистрирован на GUID категории, для остальных этим занимается, как я понял, сама devenum.dll. Соответственно, для новой категории нужно зарегистрировать сервер с таким же GUID, чтобы devenum.dll могла попросить у него перечислитель.
Ну вот у меня например устройства, обычно это Video Capture Source и Audio Capture Source. Соответствующие категории у них уже есть в системе и там они и регистрируются с помощью фильтр-маппера. Соответственно, перечислениями этих устройств занимает devenum.dll. Но вот устройств обслуживаемых одним и тем же фильтром может быть несколько. Например это может быть виртуальная SDI плата с конфигурируемым количеством входов, каждый из которых должен быть представлен отдельным фильтром. Тогда как мне добавить свои устройства? Не подменять же стандартную фабрику класса в devenum.dll ?
Здравствуйте, 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 не происходит.