Caricatori di topologie personalizzati

Quando un'applicazione accoda una topologia parziale nella sessione multimediale, la sessione multimediale usa un caricatore di topologia per risolvere la topologia. Per impostazione predefinita, la sessione multimediale usa l'implementazione standard di Media Foundation del caricatore della topologia, ma è anche possibile fornire un'implementazione personalizzata. In questo modo si ottiene un maggiore controllo sulla topologia finale. Un caricatore di topologia personalizzato deve implementare l'interfaccia IMFTopoLoader .

Per impostare un caricatore di topologia personalizzato nella sessione multimediale, eseguire le operazioni seguenti:

  1. Creare un archivio attributi vuoto chiamando MFCreateAttributes.
  2. Impostare l'attributo MF_SESSION_TOPOLOADER nell'archivio attributi. Il valore dell'attributo è il CLSID del caricatore personalizzato.
  3. Chiama MFCreateMediaSession per creare la sessione multimediale per contenuti non protetti o MFCreatePMPMediaSession per creare la sessione multimediale all'interno del percorso multimediale protetto.

Nota

Per usare un caricatore di topologia personalizzato all'interno del PMP, il caricatore della topologia deve essere un componente attendibile. Per altre informazioni, vedere Percorso multimediale protetto.

 

Il codice seguente illustra come impostare un caricatore di topologia personalizzato nella sessione multimediale.

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

Non è necessario implementare l'intero algoritmo di caricamento della topologia nel caricatore della topologia. In alternativa, è possibile eseguire il wrapping del caricatore della topologia Media Foundation standard. Nell'implementazione del metodo IMFTopoLoader::Load modificare la topologia in base alle esigenze e passare la topologia modificata al caricatore della topologia standard. Il caricatore della topologia standard completa quindi la topologia. È anche possibile modificare la topologia completata prima di passarla nuovamente alla sessione multimediale.

Il codice seguente illustra la struttura generale di questo approccio. Non vengono visualizzati dettagli del metodo Load , perché dipendono dai requisiti specifici dell'applicazione.

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

Compilazione avanzata della topologia