Carregadores de topologia personalizados
Quando um aplicativo enfileira uma topologia parcial na Sessão de Mídia, a Sessão de Mídia usa um carregador de topologia para resolve a topologia. Por padrão, a Sessão de Mídia usa a implementação padrão do Media Foundation do carregador de topologia, mas você também pode fornecer uma implementação personalizada. Isso lhe dá mais controle sobre a topologia final. Um carregador de topologia personalizado deve implementar a interface IMFTopoLoader .
Para definir um carregador de topologia personalizado na Sessão de Mídia, faça o seguinte:
- Crie um repositório de atributos vazio chamando MFCreateAttributes.
- Defina o atributo MF_SESSION_TOPOLOADER no repositório de atributos. O valor do atributo é o CLSID do carregador personalizado.
- Chame MFCreateMediaSession para criar a Sessão de Mídia para conteúdo desprotegido ou MFCreatePMPMediaSession para criar a Sessão de Mídia dentro do PMP (caminho de mídia protegido).
Observação
Para usar um carregador de topologia personalizado dentro do PMP, o carregador de topologia deve ser um componente confiável. Para obter mais informações, consulte Caminho de mídia protegida.
O código a seguir mostra como definir um carregador de topologia personalizado na Sessão de Mídia.
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;
}
Não é necessário implementar todo o algoritmo de carregamento de topologia no carregador de topologia. Como alternativa, você pode encapsular o carregador de topologia padrão do Media Foundation. Na implementação do método IMFTopoLoader::Load , modifique a topologia conforme necessário e passe a topologia modificada para o carregador de topologia padrão. Em seguida, o carregador de topologia padrão conclui a topologia. Você também pode modificar a topologia concluída antes de passá-la de volta para a Sessão de Mídia.
O código a seguir mostra a estrutura de tópicos geral dessa abordagem. Ele não mostra detalhes do método Load , pois eles dependerão dos requisitos específicos do seu aplicativo.
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.
};
Tópicos relacionados