自定义拓扑加载程序
当应用程序在媒体会话上对部分拓扑进行排队时,媒体会话使用拓扑加载程序解析拓扑。 默认情况下,媒体会话使用拓扑加载程序的标准 Media Foundation 实现,但也可以提供自定义实现。 这样就可以更好地控制最终拓扑。 自定义拓扑加载程序必须实现 IMFTopoLoader 接口。
若要在媒体会话上设置自定义拓扑加载程序,请执行以下操作:
- 通过调用 MFCreateAttributes 创建空属性存储。
- 设置属性存储区上的 MF_SESSION_TOPOLOADER 属性。 特性的值是自定义加载程序 CLSID。
- 调用 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.
};
相关主题