Предоставление пользовательского распределителя
[Функция, связанная с этой страницей 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::D ecideAllocator . Однако имейте в виду, что это может помешать выходному контакту подключаться к определенным фильтрам, так как для другого фильтра также может потребоваться собственный пользовательский распределитель. Третий вариант — изменить порядок. Сначала попробуйте пользовательский распределитель, а затем вернитесь к распределителю другого фильтра.
Связанные темы