Compartir a través de


Cargadores de topología personalizados

Cuando una aplicación pone en cola una topología parcial en la sesión multimedia, la sesión multimedia usa un cargador de topologías para resolver la topología. De forma predeterminada, la sesión multimedia usa la implementación estándar de Media Foundation del cargador de topologías, pero también puede proporcionar una implementación personalizada. Esto proporciona más control sobre la topología final. Un cargador de topología personalizado debe implementar la interfaz IMFTopoLoader .

Para establecer un cargador de topología personalizado en la sesión multimedia, haga lo siguiente:

  1. Cree un almacén de atributos vacío llamando a MFCreateAttributes.
  2. Establezca el atributo MF_SESSION_TOPOLOADER en el almacén de atributos. El valor del atributo es el CLSID del cargador personalizado.
  3. Llame a MFCreateMediaSession para crear la sesión multimedia para contenido no protegido o MFCreatePMPMediaSession para crear la sesión multimedia dentro de la ruta de acceso multimedia protegida (PMP).

Nota

Para usar un cargador de topología personalizado dentro de PMP, el cargador de topología debe ser un componente de confianza. Para obtener más información, vea Ruta de acceso multimedia protegida.

 

En el código siguiente se muestra cómo establecer un cargador de topología personalizado en la sesión multimedia.

HRESULT CreateSession_CustomTopoLoader(REFCLSID clsid, IMFMediaSession **ppSession)
{
    *ppSession = NULL;

    IMFMediaSession *pSession = NULL;
    IMFAttributes *pConfig = NULL;

    // Create an attribute store to configure the media session.
    HRESULT hr = MFCreateAttributes(&pConfig, 1);

    // Set the CLSID of the custom topology loader.
    if (SUCCEEDED(hr))
    {
        hr = pConfig->SetGUID(MF_SESSION_TOPOLOADER, clsid);
    }

    // Create the media session.
    if (SUCCEEDED(hr))
    {
        hr = MFCreateMediaSession(pConfig, &pSession);
    }

    // Return the pointer to the caller.
    if (SUCCEEDED(hr))
    {
        *ppSession = pSession;
        (*ppSession)->AddRef();
    }

    SafeRelease(&pSession);
    SafeRelease(&pConfig);

    return hr;
}

No es necesario implementar todo el algoritmo de carga de topologías en el cargador de topologías. Como alternativa, puede encapsular el cargador de topología estándar de Media Foundation. En la implementación del método IMFTopoLoader::Load , modifique la topología según sea necesario y pase la topología modificada al cargador de topología estándar. A continuación, el cargador de topología estándar completa la topología. También puede modificar la topología completada antes de volver a pasarla a la sesión multimedia.

En el código siguiente se muestra el esquema general de este enfoque. No muestra ningún detalle del método Load , ya que dependerá de los requisitos concretos de la aplicación.

class CTopoLoader : public IMFTopoLoader
{
public:

    static HRESULT CreateInstance(REFIID iid, void **ppv)
    {
        HRESULT hr = S_OK;

        CTopoLoader *pTopoLoader = new (std::nothrow) CTopoLoader(&hr);
        
        if (pTopoLoader == NULL)
        {
            return E_OUTOFMEMORY;
        }

        if (SUCCEEDED(hr))
        {
            hr = pTopoLoader->QueryInterface(iid, ppv);
        }

        SafeRelease(&pTopoLoader);
        return hr;
    }

    // IUnknown methods.
    STDMETHODIMP QueryInterface(REFIID riid, void** ppv)
    {
        static const QITAB qit[] = 
        {
            QITABENT(CTopoLoader, IMFTopoLoader),
            { 0 },
        };
        return QISearch(this, qit, riid, ppv);
    }

    STDMETHODIMP_(ULONG) AddRef()
    {
        return InterlockedIncrement(&m_cRef);
    }

    STDMETHODIMP_(ULONG) Release()
    {
        long cRef = InterlockedDecrement(&m_cRef);
        if (cRef == 0)
        {
            delete this;
        }
        return cRef;
    }

    // IMTopoLoader methods.
    STDMETHODIMP Load(
        IMFTopology *pInput, 
        IMFTopology **ppOutput, 
        IMFTopology *pCurrent
        )
    {
        HRESULT hr = S_OK;

        // TODO: Add custom topology-building code here.
        //       Modify pInput as needed.

        if (SUCCEEDED(hr))
        {
            hr = m_pTopoLoader->Load(pInput, ppOutput, pCurrent);
        }

        // TODO: Add custom topology-building code here.
        //       Modify ppOutput as needed.

        return hr;
    }

private:
    CTopoLoader(HRESULT *phr) : m_cRef(1), m_pTopoLoader(NULL)
    {
        *phr = MFCreateTopoLoader(&m_pTopoLoader);
    }

    virtual ~CTopoLoader()
    {
        SafeRelease(&m_pTopoLoader);
    }

private:
    long            m_cRef;          // Reference count.
    IMFTopoLoader   *m_pTopoLoader;  // Standard topoloader.
};

MFCreateTopoLoader

Compilación avanzada de topología