Поделиться через


Пользовательские загрузчики топологии

Если приложение очереди частичной топологии в сеансе мультимедиа, сеанс мультимедиа использует загрузчик топологии для разрешения топологии. По умолчанию сеанс мультимедиа использует стандартную реализацию Media Foundation для загрузчика топологии, но также можно предоставить настраиваемую реализацию. Это обеспечивает более полный контроль над конечной топологией. Пользовательский загрузчик топологии должен реализовать интерфейс IMFTopoLoader.

Чтобы задать настраиваемый загрузчик топологии в сеансе мультимедиа, сделайте следующее:

  1. Создайте пустое хранилище атрибутов, вызвав MFCreateAttributes.
  2. Задайте атрибут MF_SESSION_TOPOLOADER в хранилище атрибутов. Значение атрибута — CLSID пользовательского загрузчика.
  3. Вызовите MFCreateMediaSession, чтобы создать сеанс мультимедиа для незащищенного содержимого или MFCreatePMPMediaSession, чтобы создать сеанс мультимедиа внутри защищенного пути мультимедиа (PMP).

Заметка

Чтобы использовать настраиваемый загрузчик топологии внутри PMP, загрузчик топологии должен быть доверенным компонентом. Дополнительные сведения см. в пути защищенного носителя.

 

В следующем коде показано, как задать настраиваемый загрузчик топологии в сеансе мультимедиа.

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

Не обязательно реализовать весь алгоритм загрузки топологии в загрузчике топологии. В качестве альтернативы можно упаковать стандартный загрузчик топологии Media Foundation. В реализации метода IMFTopoLoader::Load измените топологию по мере необходимости и передайте измененную топологию в стандартный загрузчик топологии. Затем загрузчик стандартной топологии завершает топологию. Вы также можете изменить завершенную топологию, прежде чем передать ее обратно в сеанс мультимедиа.

В следующем коде показан общий контур этого подхода. В нем нет сведений о методе Load, так как они зависят от конкретных требований приложения.

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

расширенное построение топологии