Carregadores de topologia personalizados

Quando um aplicativo enfileira uma topologia parcial na Sessão de Mídia, a Sessão de Mídia usa um carregador de topologia para resolve a topologia. Por padrão, a Sessão de Mídia usa a implementação padrão do Media Foundation do carregador de topologia, mas você também pode fornecer uma implementação personalizada. Isso lhe dá mais controle sobre a topologia final. Um carregador de topologia personalizado deve implementar a interface IMFTopoLoader .

Para definir um carregador de topologia personalizado na Sessão de Mídia, faça o seguinte:

  1. Crie um repositório de atributos vazio chamando MFCreateAttributes.
  2. Defina o atributo MF_SESSION_TOPOLOADER no repositório de atributos. O valor do atributo é o CLSID do carregador personalizado.
  3. Chame MFCreateMediaSession para criar a Sessão de Mídia para conteúdo desprotegido ou MFCreatePMPMediaSession para criar a Sessão de Mídia dentro do PMP (caminho de mídia protegido).

Observação

Para usar um carregador de topologia personalizado dentro do PMP, o carregador de topologia deve ser um componente confiável. Para obter mais informações, consulte Caminho de mídia protegida.

 

O código a seguir mostra como definir um carregador de topologia personalizado na Sessão de Mídia.

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

Não é necessário implementar todo o algoritmo de carregamento de topologia no carregador de topologia. Como alternativa, você pode encapsular o carregador de topologia padrão do Media Foundation. Na implementação do método IMFTopoLoader::Load , modifique a topologia conforme necessário e passe a topologia modificada para o carregador de topologia padrão. Em seguida, o carregador de topologia padrão conclui a topologia. Você também pode modificar a topologia concluída antes de passá-la de volta para a Sessão de Mídia.

O código a seguir mostra a estrutura de tópicos geral dessa abordagem. Ele não mostra detalhes do método Load , pois eles dependerão dos requisitos específicos do seu aplicativo.

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

Compilação avançada de topologia