Предоставление пользовательского распределителя
[Функция, связанная с этой страницей, DirectShow, является устаревшей функцией. Он был заменен на MediaPlayer, IMFMediaEngineи захват аудио и видео в Media Foundation. Эти функции оптимизированы для Windows 10 и Windows 11. Корпорация Майкрософт настоятельно рекомендует, чтобы новый код использовал MediaPlayer, IMFMediaEngine и Аудио/видеозахват в Media Foundation вместо DirectShow, когда это возможно. Корпорация Майкрософт предлагает, что существующий код, использующий устаревшие API, будет перезаписан для использования новых API, если это возможно.]
В этом разделе описывается, как предоставить пользовательский распределитель для фильтра. Описаны подключения только IMemInputPin, но действия для подключения IAsyncReader аналогичны.
Сначала определите класс C++ для распределителя. Распределитель может быть производным от одного из стандартных классов распределителя, CBaseAllocator или CMemAllocatorили создать совершенно новый класс распределителя. Если вы создаете новый класс, он должен предоставить интерфейс IMemAllocator.
Оставшиеся шаги зависят от того, принадлежит ли ваш аллокатор входному или выходному контакту вашего фильтра. Входные контакты играют другую роль, чем выходные контакты в фазе согласования распределителя, так как выходной контакт в конечном итоге выбирает распределитель.
Предоставление пользовательского аллокатора для входного пина
Чтобы предоставить распределитель для входного контакта, переопределите метод CBaseInputPin::GetAllocator входного контакта. В этом методе проверьте член переменной m_pAllocator. Если эта переменная не являетсяNULL, это означает, что для этого соединения уже выбран распределитель, поэтому метод GetAllocator должен вернуть указатель на этот распределитель. Если m_pAllocator представляет собой NULL, это означает, что распределитель не выбран, поэтому метод GetAllocator должен возвращать указатель на предпочтительный распределитель входного контакта. В этом случае создайте экземпляр пользовательского распределителя и верните указатель IMemAllocator. В следующем коде показано, как реализовать метод getAllocator:
STDMETHODIMP CMyInputPin::GetAllocator(IMemAllocator **ppAllocator)
{
CheckPointer(ppAllocator, E_POINTER);
if (m_pAllocator)
{
// We already have an allocator, so return that one.
*ppAllocator = m_pAllocator;
(*ppAllocator)->AddRef();
return S_OK;
}
// No allocator yet, so propose our custom allocator. The exact code
// here will depend on your custom allocator class definition.
HRESULT hr = S_OK;
CMyAllocator *pAlloc = new CMyAllocator(&hr);
if (!pAlloc)
{
return E_OUTOFMEMORY;
}
if (FAILED(hr))
{
delete pAlloc;
return hr;
}
// Return the IMemAllocator interface to the caller.
return pAlloc->QueryInterface(IID_IMemAllocator, (void**)ppAllocator);
}
Когда вышестоящий фильтр выбирает распределитель, он вызывает метод ввода IMemInputPin::NotifyAllocator. Переопределите метод CBaseInputPin::NotifyAllocator, чтобы проверить свойства распределителя. В некоторых случаях входной пин может отклонить аллокатор, если он не является вашим пользовательским аллокатором, хотя это может привести к отказу всего подключения пина.
Предоставление настраиваемого распределителя для выходного контакта
Чтобы предоставить распределитель для выходного пин-кода, переопределите метод CBaseOutputPin::InitAllocator для создания экземпляра распределителя:
HRESULT MyOutputPin::InitAllocator(IMemAllocator **ppAllocator)
{
HRESULT hr = S_OK;
CMyAllocator *pAlloc = new CMyAllocator(&hr);
if (!pAlloc)
{
return E_OUTOFMEMORY;
}
if (FAILED(hr))
{
delete pAlloc;
return hr;
}
// Return the IMemAllocator interface.
return pAlloc->QueryInterface(IID_IMemAllocator, (void**)ppAllocator);
}
По умолчанию класс CBaseOutputPin сначала запрашивает выделитель у входного пина. Если этот распределитель не подходит, выходной контакт создает собственный распределитель. Чтобы принудительно использовать настраиваемый распределитель, переопределите метод CBaseOutputPin::DecideAllocator. Однако помните, что это может препятствовать подключению выходного контакта с определенными фильтрами, так как другой фильтр также может требовать собственный пользовательский аллокатор. Третий вариант — изменить порядок: сначала попробуйте пользовательский распределитель, а затем используйте распределитель другого фильтра в качестве запасного варианта.
Связанные разделы