Medya Olay Oluşturucuları

Media Foundation, nesnelerin olayları göndermesi için tutarlı bir yol sağlar. Bir nesne, zaman uyumsuz bir yöntemin tamamlanmasının sinyalini vermek veya nesnenin durumundaki bir değişikliği uygulamaya bildirmek için olayları kullanabilir.

Bir nesne olayları gönderirse, IMFMediaEventGenerator arabirimini kullanıma sunar. Nesne yeni bir olay gönderdiğinde, olay bir kuyruğa yerleştirilir. Uygulama aşağıdaki yöntemlerden birini çağırarak kuyruktan bir sonraki olayı isteyebilir:

GetEvent yöntemi zaman uyumlu. Bir olay zaten kuyruktaysa, yöntemi hemen döndürür. Kuyrukta olay yoksa, getEvent geçirdiğiniz bayrağına bağlı olarak yöntemi hemen başarısız olur veya sonraki olay kuyruğa alınana kadar engeller.

BeginGetEvent yöntemi zaman uyumsuz olduğundan hiçbir zaman engellemez. Bu yöntem, uygulamanın uygulaması gereken IMFAsyncCallback arabirimine bir işaretçi alır. Geri çağırma çağrıldığında uygulama, olayı kuyruktan almak için IMFMediaEventGenerator::EndGetEvent çağırır. IMFAsyncCallbackhakkında daha fazla bilgi için bkz. Zaman Uyumsuz Geri Çağırma Yöntemleri.

Olaylar, IMFMediaEvent arabirimiyle temsil edilir. Bu arabirim aşağıdaki yöntemlere sahiptir:

  • gettype: Olay türünü alır. Olay türü, olayı tetikleme işleminin ne olduğunu gösterir.

  • GetStatus: Olayı tetikleyen işlemin başarılı olup olmadığını gösteren bir HRESULT değeri alır. bir işlem zaman uyumsuz olarak başarısız olursa GetStatus bir hata kodu döndürür.

  • GetValue: Olay verilerini içeren bir PROPVARIANT alır. Olay verileri, olay türüne bağlıdır. Bazı olaylarda veri yoktur.

  • getExtendedType: GUIDalır. Bu yöntem, MEExtendedType Olayiçin geçerlidir ve özel olayları tanımlamak için bir yol sağlar.

IMFMediaEvent arabirimi de IMFAttributes arabirimini devralır. Bazı olaylar öznitelik olarak ek bilgiler taşır.

Olay türlerinin ve ilişkili verilerinin ve özniteliklerinin listesi için bkz. Media Foundation Olayları.

IMFMediaEventGenerator Uygulama

Media Foundation için özel medya kaynağı veya medya havuzu gibi bir eklenti bileşeni yazıyorsanız, IMFMediaEventGeneratoruygulamanız gerekebilir. Bunu kolaylaştırmak için Media Foundation, olay kuyruğu uygulayan bir yardımcı nesnesi sağlar. MFCreateEventQueue işlevini çağırarak olay kuyruğu oluşturun. Olay kuyruğu, IMFMediaEventQueue arabirimini kullanıma sunar. Nesnenizin IMFMediaEventGenerator yöntemleri uygulamasında, olay kuyruğunda ilgili yöntemi çağırın.

Olay kuyruğu nesnesi iş parçacığı güvenlidir. GetEventve QueueEventçağrılırken hiçbir zaman aynı kritik bölüm nesnesini tutmayın çünkü GetEvent , QueueEventbeklemeyi süresiz olarak engelleyebilir. Her iki yöntem için de aynı kritik bölümü tutarsanız kilitlenmeye neden olur.

Olay kuyruğu serbest bırakılmadan önce, nesnenin sahip olduğu kaynakları serbest bırakmak için IMFMediaEventQueue::Shutdown çağrısı yapın.

Nesnenizin bir olay oluşturması gerektiğinde, olay kuyruğunda aşağıdaki yöntemlerden birini çağırın:

Bu yöntemler kuyruğa yeni bir olay koyar ve bir sonraki olayı bekleyen çağıranlara sinyal gönderir.

Aşağıdaki kod, bu yardımcı nesnesini kullanarak IMFMediaEventGenerator uygulayan bir sınıfı gösterir. Bu sınıf, olay kuyruğunun kapatılmasını sağlayan ve olay kuyruğu işaretçisini serbest bırakan genel Shutdown yöntemini tanımlar. Bu davranış, her zaman bir Shutdown yöntemine sahip olan medya kaynakları ve medya havuzları için tipik olacaktır.

class MyObject : public IMFMediaEventGenerator
{
private:
    long                m_nRefCount;    // Reference count.
    CRITICAL_SECTION    m_critSec;      // Critical section.
    IMFMediaEventQueue *m_pQueue;       // Event queue.
    BOOL                m_bShutdown;    // Is the object shut down?

    // CheckShutdown: Returns MF_E_SHUTDOWN if the object was shut down.
    HRESULT CheckShutdown() const 
    {
        return (m_bShutdown? MF_E_SHUTDOWN : S_OK);
    }

public:
    MyObject(HRESULT &hr) : m_nRefCount(0), m_pQueue(NULL), m_bShutdown(FALSE)
    {
        InitializeCriticalSection(&m_critSec);
        
        // Create the event queue.
        hr = MFCreateEventQueue(&m_pQueue);
    }

    // Shutdown: Shuts down this object.
    HRESULT Shutdown()
    {
        EnterCriticalSection(&m_critSec);

        HRESULT hr = CheckShutdown();
        if (SUCCEEDED(hr))
        {
            // Shut down the event queue.
            if (m_pQueue)
            {
                hr = m_pQueue->Shutdown();
            }

            // Release the event queue.
            SAFE_RELEASE(m_pQueue);
            // Release any other objects owned by the class (not shown).

            // Set the shutdown flag.
            m_bShutdown = TRUE;
        }

        LeaveCriticalSection(&m_critSec);
        return hr;
    }

    // TODO: Implement IUnknown (not shown).
    STDMETHODIMP_(ULONG) AddRef();
    STDMETHODIMP_(ULONG) Release();
    STDMETHODIMP QueryInterface(REFIID iid, void** ppv);

    // IMFMediaEventGenerator::BeginGetEvent
    STDMETHODIMP BeginGetEvent(IMFAsyncCallback* pCallback, IUnknown* pState)
    {
        EnterCriticalSection(&m_critSec);

        HRESULT hr = CheckShutdown();
        if (SUCCEEDED(hr))
        {
            hr = m_pQueue->BeginGetEvent(pCallback, pState);
        }

        LeaveCriticalSection(&m_critSec);
        return hr;    
    }

    // IMFMediaEventGenerator::EndGetEvent
    STDMETHODIMP EndGetEvent(IMFAsyncResult* pResult, IMFMediaEvent** ppEvent)
    {
        EnterCriticalSection(&m_critSec);

        HRESULT hr = CheckShutdown();
        if (SUCCEEDED(hr))
        {
            hr = m_pQueue->EndGetEvent(pResult, ppEvent);
        }

        LeaveCriticalSection(&m_critSec);
        return hr;    
    }

    // IMFMediaEventGenerator::GetEvent
    STDMETHODIMP GetEvent(DWORD dwFlags, IMFMediaEvent** ppEvent)
    {
        // Because GetEvent can block indefinitely, it requires
        // a slightly different locking strategy.
        IMFMediaEventQueue *pQueue = NULL;

        // Hold lock.
        EnterCriticalSection(&m_critSec);

        // Check shutdown
        HRESULT hr = CheckShutdown();

        // Store the pointer in a local variable, so that another thread
        // does not release it after we leave the critical section.
        if (SUCCEEDED(hr))
        {
            pQueue = m_pQueue;
            pQueue->AddRef();
        }

        // Release the lock.
        LeaveCriticalSection(&m_critSec);

        if (SUCCEEDED(hr))
        {
            hr = pQueue->GetEvent(dwFlags, ppEvent);
        }

        SAFE_RELEASE(pQueue);
        return hr;
    }

    // IMFMediaEventGenerator::QueueEvent
    STDMETHODIMP QueueEvent(
        MediaEventType met, REFGUID extendedType, 
        HRESULT hrStatus, const PROPVARIANT* pvValue)
    {
        EnterCriticalSection(&m_critSec);

        HRESULT hr = CheckShutdown();
        if (SUCCEEDED(hr))
        {
            hr = m_pQueue->QueueEventParamVar(
                met, extendedType, hrStatus, pvValue);
        }

        LeaveCriticalSection(&m_critSec);
        return hr;
    }

private:

    // The destructor is private. The caller must call Release.
    virtual ~MyObject()
    {
        assert(m_bShutdown);
        assert(m_nRefCount == 0);
    }
};

Media Foundation Platform API'leri