Partilhar via


Fornecendo um alocador personalizado

[O recurso associado a esta página, DirectShow, é um recurso herdado. Foi substituído por MediaPlayer, IMFMediaEnginee Audio/Video Capture in Media Foundation. Esses recursos foram otimizados para Windows 10 e Windows 11. A Microsoft recomenda vivamente que o novo código utilize 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 IMemInputPinsão descritas, mas as etapas para uma conexão de IAsyncReadersã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 se criar uma nova classe, ela deve expor a interface IMemAllocator.

As etapas restantes dependem de o fato de o alocador pertencer a um pino de entrada ou a um pino de saída no filtro. Os pinos de entrada desempenham um papel diferente dos pinos de saída durante a fase de negociação do alocador, porque o pino de saída seleciona o alocador.

Fornecendo um alocador personalizado para um pino de entrada

Para fornecer um alocador para um pino de entrada, substitua o método CBaseInputPin::GetAllocator do pino de entrada. Dentro deste método, verifique a variável membro m_pAllocator. Se essa variável não forNULL, 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 estiver NULL , isso significa que o alocador não foi selecionado, portanto, o método GetAllocator deve retornar um ponteiro para o alocador preferido do pino de entrada. Nesse caso, crie uma instância do seu alocador personalizado e retorne o seu ponteiro IMemAllocator. O código a seguir mostra como implementar o GetAllocator método:

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::NotifyAllocatordo pino de entrada. Substitua o métodoCBaseInputPin::NotifyAllocator para verificar as propriedades do alocador. Em alguns casos, o pino de entrada pode rejeitar o alocador se não for o seu alocador personalizado, embora isso possa fazer com que toda a conexão do pino falhe.

Fornecendo um alocador personalizado para um pino de saída

Para fornecer um alocador para um pino de saída, substitua o método CBaseOutputPin::InitAllocator para criar uma instância do seu próprio 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 pino de entrada primeiro. Se esse alocador não for adequado, o pino de saída cria seu próprio alocador. Para forçar a conexão a usar o seu alocador personalizado, substitua o método CBaseOutputPin::DecideAllocator. No entanto, esteja ciente de que isso pode impedir que o seu pino de saída se ligue a determinados filtros, uma vez que o outro filtro pode também requerer o seu próprio alocador personalizado. Uma terceira opção é mudar a ordem: tente primeiro o seu alocador personalizado e, em seguida, volte para o alocador do outro filtro.

Negociação de alocadores