如何从网络源获取事件
源解析程序使应用程序能够创建网络源并打开与特定 URL 的连接。 网络源引发事件以标记打开连接的异步操作的开始和结束。 应用程序可以使用 IMFSourceOpenMonitor 接口注册这些事件。
此接口公开网络源在异步打开 URL 时直接调用的 IMFSourceOpenMonitor::OnSourceEvent 方法。 网络源通过引发 MEConnectStart 事件在应用程序开始打开 URL 时通知应用程序。 然后,网络源在完成打开操作时引发 MEConnectEnd 事件。
注意
若要将这些事件发送到应用程序,网络源不使用 IMFMediaEventGenerator 接口,因为这些事件是在创建网络源之前引发的。 应用程序可以使用媒体会话的 IMFMediaEventGenerator 接口获取所有其他网络源事件。
从网络源获取事件
- 实现 IMFSourceOpenMonitor 接口。 在 IMFSourceOpenMonitor::OnSourceEvent 方法的实现中,执行以下操作:
- 通过调用 IMFMediaEvent::GetStatus 获取事件状态。 此方法指示触发事件的操作(如源解析程序方法调用)是否成功。 如果操作不成功,则状态为失败代码。
- 根据事件类型 MEConnectStart 或 MEConnectEnd 处理事件,应用程序可以通过调用 IMFMediaEvent::GetType 获取该类型。
- 在属性存储对象中配置键值对,以存储指向步骤 1 中所述的 IMFSourceOpenMonitor 实现的指针。
- 通过调用 PSCreateMemoryPropertyStore 函数创建属性存储对象。
- 在 PROPERTYKEY 结构中设置 MFPKEY_SourceOpenMonitor 属性。
- 通过将 IUnknown 指针设置为应用程序实现的 IMFSourceOpenMonitor 接口,在 PROPVARIANT 结构中提供VT_UNKNOWN类型数据值。
- 通过调用 IPropertyStore::SetValue 在属性存储中设置键值对。
- 将属性存储指针传递给应用程序用于创建网络源的源解析程序方法,例如 IMFSourceResolver::CreateObjectFromURL 等。
示例
以下示例演示如何实现 IMFSourceOpenMonitor 接口以从网络源获取事件。
class CSourceOpenMonitor : public IMFSourceOpenMonitor
{
public:
CSourceOpenMonitor () : m_cRef(1) { }
STDMETHODIMP QueryInterface(REFIID riid, void** ppv)
{
static const QITAB qit[] =
{
QITABENT(CSourceOpenMonitor, IMFSourceOpenMonitor),
{ 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;
}
// For thread safety, return a temporary variable.
return cRef;
}
STDMETHODIMP OnSourceEvent(IMFMediaEvent* pEvent)
{
MediaEventType eventType = MEUnknown; // Event type
HRESULT hrStatus = S_OK; // Event status
// Get the event type.
HRESULT hr = pEvent->GetType(&eventType);
// Get the event status. If the operation that triggered the event
// did not succeed, the status is a failure code.
if (SUCCEEDED(hr))
{
hr = pEvent->GetStatus(&hrStatus);
}
if (FAILED(hrStatus))
{
hr = hrStatus;
}
if (SUCCEEDED(hr))
{
// Switch on the event type.
switch(eventType)
{
case MEConnectStart:
// The application does something. (Not shown.)
OutputDebugString(L"Connecting...\n");
break;
case MEConnectEnd:
// The application does something. (Not shown.)
OutputDebugString(L"Connect End.\n");
break;
}
}
else
{
// Event failed.
// The application handled a failure. (Not shown.)
}
return S_OK;
}
private:
long m_cRef;
};
以下示例演示如何在打开 URL 时在网络源上设置 MFPKEY_SourceOpenMonitor 属性:
HRESULT CreateMediaSourceWithSourceOpenMonitor(
PCWSTR pszURL,
IMFMediaSource **ppSource
)
{
IPropertyStore *pConfig = NULL;
CSourceOpenMonitor *pMonitor = new (std::nothrow) CSourceOpenMonitor();
if (pMonitor == NULL)
{
return E_OUTOFMEMORY;
}
// Configure the property store.
HRESULT hr = PSCreateMemoryPropertyStore(IID_PPV_ARGS(&pConfig));
if (SUCCEEDED(hr))
{
PROPVARIANT var;
var.vt = VT_UNKNOWN;
pMonitor->QueryInterface(IID_PPV_ARGS(&var.punkVal));
hr = pConfig->SetValue(MFPKEY_SourceOpenMonitor, var);
PropVariantClear(&var);
}
// Create the source media source.
if (SUCCEEDED(hr))
{
hr = CreateMediaSource(pszURL, pConfig, ppSource);
}
SafeRelease(&pConfig);
SafeRelease(&pMonitor);
return hr;
}
相关主题