Proporcionar un asignador personalizado

[La característica asociada a esta página, DirectShow, es una característica heredada. Se ha reemplazado por MediaPlayer, IMFMediaEngine y Captura de audio/vídeo en Media Foundation. Esas características se han optimizado para Windows 10 y Windows 11. Microsoft recomienda encarecidamente que el nuevo código use MediaPlayer, IMFMediaEngine y Audio/Video Capture en Media Foundation en lugar de DirectShow, siempre que sea posible. Microsoft sugiere que el código existente que usa las API heredadas se reescriba para usar las nuevas API si es posible.

En esta sección se describe cómo proporcionar un asignador personalizado para un filtro. Solo se describen las conexiones IMemInputPin , pero los pasos de una conexión IAsyncReader son similares.

En primer lugar, defina una clase de C++ para el asignador. El asignador puede derivar de una de las clases de asignador estándar, CBaseAllocator o CMemAllocator, o bien puede crear una clase de asignador completamente nueva. Si crea una nueva clase, debe exponer la interfaz IMemAllocator .

Los pasos restantes dependen de si el asignador pertenece a un pin de entrada o a un pin de salida en el filtro. Los pins de entrada desempeñan un rol diferente de los pins de salida durante la fase de negociación del asignador, ya que el pin de salida selecciona en última instancia el asignador.

Proporcionar un asignador personalizado para un pin de entrada

Para proporcionar un asignador para un pin de entrada, invalide el método CBaseInputPin::GetAllocator del pin de entrada. Dentro de este método, compruebe la variable miembro m_pAllocator . Si esta variable no es NULL, significa que el asignador ya se ha seleccionado para esta conexión, por lo que el método GetAllocator debe devolver un puntero a ese asignador. Si m_pAllocator es NULL, significa que el asignador no se ha seleccionado, por lo que el método GetAllocator debe devolver un puntero al asignador preferido del pin de entrada. En ese caso, cree una instancia del asignador personalizado y devuelva su puntero IMemAllocator . En el código siguiente se muestra cómo implementar el 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);
}

Cuando el filtro ascendente selecciona un asignador, llama al método IMemInputPin::NotifyAllocator del pin de entrada. Invalide el método CBaseInputPin::NotifyAllocator para comprobar las propiedades del asignador. En algunos casos, el pin de entrada podría rechazar el asignador si no es el asignador personalizado, aunque esto puede hacer que se produzca un error en toda la conexión de patillas.

Proporcionar un asignador personalizado para un pin de salida

Para proporcionar un asignador para un pin de salida, invalide el método CBaseOutputPin::InitAllocator para crear una instancia del asignador:

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

De forma predeterminada, la clase CBaseOutputPin solicita un asignador desde el pin de entrada primero. Si ese asignador no es adecuado, el pin de salida crea su propio asignador. Para forzar que la conexión use el asignador personalizado, invalide el método CBaseOutputPin::D ecideAllocator . Sin embargo, tenga en cuenta que esto puede impedir que el pin de salida se conecte con determinados filtros, ya que el otro filtro también puede requerir su propio asignador personalizado. Una tercera opción es cambiar el orden: pruebe primero el asignador personalizado y vuelva al asignador del otro filtro.

Negociación de asignadores