次の方法で共有


カスタム トポロジ ローダー

アプリケーションがメディア セッションで部分的なトポロジをキューに入れると、メディア セッションはトポロジ ローダーを使用してトポロジを解決します。 既定では、メディア セッションはトポロジ ローダーの標準的な 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

高度なトポロジの構築