Compartilhar via


Fornecendo um alocador personalizado

[O recurso associado a esta página, DirectShow, é um recurso herdado. Ele foi substituído por MediaPlayer, IMFMediaEngine e Captura de Áudio/Vídeo na Media Foundation. Esses recursos foram otimizados para Windows 10 e Windows 11. A Microsoft recomenda fortemente que o novo código use MediaPlayer, IMFMediaEngine e Captura de Áudio/Vídeo no Media Foundation em vez de DirectShow, quando possível. A Microsoft sugere que o código existente que usa as APIs herdadas seja reescrito para usar as novas APIs, se possível.]

Esta seção descreve como fornecer um alocador personalizado para um filtro. Somente conexões IMemInputPin são descritas, mas as etapas para uma conexão IAsyncReader são semelhantes.

Primeiro, defina uma classe C++ para o alocador. Seu alocador pode derivar de uma das classes de alocador padrão, CBaseAllocator ou CMemAllocator, ou você pode criar uma classe de alocador totalmente nova. Se você criar uma nova classe, ela deverá expor a interface IMemAllocator .

As etapas restantes dependem se o alocador pertence a um pin de entrada ou a um pino de saída no filtro. Os pinos de entrada desempenham uma função diferente dos pinos de saída durante a fase de negociação do alocador, pois o pino de saída seleciona o alocador.

Fornecendo um alocador personalizado para um pin de entrada

Para fornecer um alocador para um pin de entrada, substitua o método CBaseInputPin::GetAllocator do pino de entrada. Dentro desse método, marcar a variável de membro m_pAllocator. Se essa variável não for NULL, isso significa que o alocador já foi selecionado para essa conexão, portanto, o método GetAllocator deve retornar um ponteiro para esse alocador. Se m_pAllocator for NULL, isso significa que o alocador não foi selecionado, portanto, o método GetAllocator deverá retornar um ponteiro para o alocador preferencial do pin de entrada. Nesse caso, crie uma instância do alocador personalizado e retorne o ponteiro IMemAllocator . O código a seguir mostra como implementar o método 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);
}

Quando o filtro upstream seleciona um alocador, ele chama o método IMemInputPin::NotifyAllocator do pin de entrada. Substitua o método CBaseInputPin::NotifyAllocator para marcar as propriedades do alocador. Em alguns casos, o pin de entrada poderá rejeitar o alocador se ele não for seu alocador personalizado, embora isso possa fazer com que toda a conexão de pino falhe.

Fornecendo um alocador personalizado para um pino de saída

Para fornecer um alocador para um pin de saída, substitua o método CBaseOutputPin::InitAllocator para criar uma instância do alocador:

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);
}

Por padrão, a classe CBaseOutputPin solicita um alocador do pin de entrada primeiro. Se esse alocador não for adequado, o pino de saída criará seu próprio alocador. Para forçar a conexão a usar o alocador personalizado, substitua o método CBaseOutputPin::D ecideAllocator . No entanto, lembre-se de que isso pode impedir que o pino de saída se conecte com determinados filtros, pois o outro filtro também pode exigir seu próprio alocador personalizado. Uma terceira opção é alternar a ordem: experimente primeiro o alocador personalizado e, em seguida, volte para o alocador do outro filtro.

Negociando alocadores