Benutzerdefinierte Topologieladeprogramme

Wenn eine Anwendung eine partielle Topologie in der Mediensitzung in die Warteschlange stellt, verwendet die Mediensitzung ein Topologieladeprogramm, um die Topologie aufzulösen. Standardmäßig verwendet die Media Session die Standardmäßige Media Foundation-Implementierung des Topologieladeprogramms, Sie können aber auch eine benutzerdefinierte Implementierung bereitstellen. Dadurch haben Sie mehr Kontrolle über die endgültige Topologie. Ein benutzerdefiniertes Topologieladeprogramm muss die IMFTopoLoader-Schnittstelle implementieren.

Gehen Sie wie folgt vor, um ein benutzerdefiniertes Topologieladeprogramm für die Mediensitzung festzulegen:

  1. Erstellen Sie einen leeren Attributspeicher, indem Sie MFCreateAttributes aufrufen.
  2. Legen Sie das attribut MF_SESSION_TOPOLOADER für den Attributspeicher fest. Der Wert des Attributs ist die CLSID Ihres benutzerdefinierten Ladeprogramms.
  3. Rufen Sie MFCreateMediaSession auf, um die Mediensitzung für ungeschützte Inhalte zu erstellen, oder MFCreatePMPMediaSession , um die Mediensitzung innerhalb des geschützten Medienpfads (PMP) zu erstellen.

Hinweis

Um einen benutzerdefinierten Topologieladeprogramm innerhalb des PMP verwenden zu können, muss das Topologieladeprogramm eine vertrauenswürdige Komponente sein. Weitere Informationen finden Sie unter Pfad für geschützte Medien.

 

Der folgende Code zeigt, wie Sie ein benutzerdefiniertes Topologieladeprogramm für die Mediensitzung festlegen.

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

Es ist nicht erforderlich, den gesamten Topologieladealgorithmus in Ihrem Topologieladeprogramm zu implementieren. Alternativ können Sie den standardmäßigen Media Foundation-Topologieladeprogramm umschließen. Ändern Sie in Ihrer Implementierung der IMFTopoLoader::Load-Methode die Topologie nach Bedarf, und übergeben Sie die geänderte Topologie an den Standardtopologieladeprogramm. Anschließend schließt der Standardtopologieladeprogramm die Topologie ab. Sie können auch die abgeschlossene Topologie ändern, bevor Sie sie an die Mediensitzung zurückgeben.

Der folgende Code zeigt die allgemeine Gliederung dieses Ansatzes. Es werden keine Details der Load-Methode angezeigt, da diese von den spezifischen Anforderungen Ihrer Anwendung abhängen.

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

Erweiterte Topologieerstellung