共用方式為


如何從網路來源取得事件

來源解析程式可讓應用程式建立網路來源,並開啟特定 URL 的連線。 網路來源會引發事件,以標示開啟連線的非同步作業的開頭和結尾。 應用程式可以使用 IMFSourceOpenMonitor 介面來註冊這些事件。

此介面會公開當網路來源以非同步方式開啟 URL 時直接呼叫的 IMFSourceOpenMonitor::OnSourceEvent 方法。 網路來源會在應用程式啟動 URL 時發出通知,方法是引發 MEConnectStart 事件。 然後,網路來源會在完成開啟作業時引發 MEConnectEnd 事件。

注意

若要將這些事件傳送至應用程式,網路來源不會使用 IMFMediaEventGenerator 介面,因為這些事件會在建立網路來源之前引發。 應用程式可以使用媒體會話的 IMFMediaEventGenerator 介面來取得所有其他網路來源事件。

 

從網路來源取得事件

  1. 實作 IMFSourceOpenMonitor 介面。 在您的 IMFSourceOpenMonitor::OnSourceEvent 方法實作中,執行下列動作:
    1. 呼叫 IMFMediaEvent::GetStatus以取得事件狀態。 這個方法會指出觸發事件的作業是否成功,例如來源解析程式方法呼叫。 如果作業未成功,則狀態為失敗碼。
    2. 根據事件種類處理事件: MEConnectStartMEConnectEnd,應用程式可以藉由呼叫 IMFMediaEvent::GetType來取得此事件。
  2. 在屬性存放區物件中設定索引鍵/值組,以儲存步驟 1 中所述 之 IMFSourceOpenMonitor 實作的指標。
    1. 呼叫 PSCreateMemoryPropertyStore 函式來建立屬性存放區物件。
    2. PROPERTYKEY結構中設定MFPKEY_SourceOpenMonitor屬性。
    3. 藉由將IUnknown指標設定為應用程式之IMFSourceOpenMonitor介面實作,在PROPVARIANT結構中提供VT_UNKNOWN類型資料值。
    4. 呼叫 IPropertyStore::SetValue,在屬性存放區中設定機碼/值組。
  3. 將屬性存放區指標傳遞至應用程式用來建立網路來源的來源解析程式方法,例如 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;
}

媒體基礎中的網路功能