Media Event Generators
Media Foundation är ett konsekvent sätt för objekt att skicka händelser. Ett objekt kan använda händelser för att signalera slutförandet av en asynkron metod eller för att meddela programmet om en ändring i objektets tillstånd.
Om ett objekt skickar händelser exponeras IMFMediaEventGenerator--gränssnittet. När objektet skickar en ny händelse placeras händelsen i en kö. Programmet kan begära nästa händelse från kön genom att anropa någon av följande metoder:
Metoden GetEvent är synkron. Om en händelse redan finns i kön returnerar metoden omedelbart. Om det inte finns någon händelse i kön misslyckas metoden antingen omedelbart eller blockerar tills nästa händelse placeras i kö, beroende på vilken flagga du skickar till GetEvent-.
Metoden BeginGetEvent är asynkron, så den blockerar aldrig. Den här metoden tar en pekare till IMFAsyncCallback-gränssnittet, som programmet måste implementera. När återanropet anropas anropar programmet IMFMediaEventGenerator::EndGetEvent för att hämta händelsen från kön. Mer information om IMFAsyncCallbackfinns i Asynkrona återanropsmetoder.
Händelser representeras av IMFMediaEvent- gränssnitt. Det här gränssnittet har följande metoder:
GetType: Hämtar händelsetypen. Händelsetypen anger vad som hände för att utlösa händelsen.
GetStatus: Hämtar ett HRESULT- värde som anger om åtgärden som utlöste händelsen lyckades. Om en åtgärd misslyckas asynkront returnerar GetStatus en felkod.
GetValue: Hämtar en PROPVARIANT- som innehåller händelsedata. Händelsedata beror på händelsetypen. Vissa händelser har inga data.
GetExtendedType: Hämtar en GUID-. Den här metoden gäller för MEExtendedType Eventoch ger ett sätt att definiera anpassade händelser.
IMFMediaEvent gränssnitt ärver också IMFAttributes gränssnitt. Vissa händelser innehåller ytterligare information som attribut.
En lista över händelsetyper och deras associerade data och attribut finns i Media Foundation Events.
Implementera IMFMediaEventGenerator
Om du skriver en plugin-komponent för Media Foundation, till exempel en anpassad mediekälla eller mediemottagare, kan du behöva implementera IMFMediaEventGenerator. För att göra detta enklare tillhandahåller Media Foundation ett hjälpobjekt som implementerar en händelsekö. Skapa händelsekön genom att anropa funktionen MFCreateEventQueue. Händelsekön exponerar IMFMediaEventQueue- gränssnitt. I objektets implementering av IMFMediaEventGenerator metoder anropar du motsvarande metod i händelsekön.
Händelseköobjektet är trådsäkert. Håll aldrig samma kritiska avsnittsobjekt när du anropar GetEvent och QueueEvent, eftersom GetEvent kan blockeras på obestämd tid i väntan på QueueEvent. Om du har samma kritiska avsnitt för båda metoderna orsakar det ett dödläge.
Innan du släpper händelsekön anropar du IMFMediaEventQueue::Shutdown för att frigöra de resurser som objektet innehåller.
När objektet behöver skapa en händelse anropar du någon av följande metoder i händelsekön:
Dessa metoder placerar en ny händelse i kön och signalerar alla anropare som väntar på nästa händelse.
Följande kod visar en klass som implementerar IMFMediaEventGenerator med hjälp av det här hjälpobjektet. Den här klassen definierar en offentlig Avstängning metod som stänger av händelsekön och släpper händelseköpekaren. Det här beteendet skulle vara typiskt för mediekällor och mediemottagare, som alltid har en avstängning metod.
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);
}
};
Relaterade ämnen