[PATCH v2 3/7] quartz: Use a linked list to store media events.

Zebediah Figura z.figura12 at gmail.com
Thu Feb 18 16:58:10 CST 2021


Signed-off-by: Zebediah Figura <z.figura12 at gmail.com>
---
 dlls/quartz/filtergraph.c | 236 +++++++++++++++-----------------------
 1 file changed, 93 insertions(+), 143 deletions(-)

diff --git a/dlls/quartz/filtergraph.c b/dlls/quartz/filtergraph.c
index 681893a1e11..25aa78433b9 100644
--- a/dlls/quartz/filtergraph.c
+++ b/dlls/quartz/filtergraph.c
@@ -49,82 +49,12 @@ typedef struct {
     int      disabled;  /* Disabled messages posting */
 } WndNotify;
 
-typedef struct {
-    LONG lEventCode;   /* Event code */
-    LONG_PTR lParam1;  /* Param1 */
-    LONG_PTR lParam2;  /* Param2 */
-} Event;
-
-/* messages ring implementation for queuing events (taken from winmm) */
-#define EVENTS_RING_BUFFER_INCREMENT      64
-typedef struct {
-    Event* messages;
-    int ring_buffer_size;
-    int msg_tosave;
-    int msg_toget;
-    HANDLE msg_event; /* Signaled for no empty queue */
-} EventsQueue;
-
-static int EventsQueue_Init(EventsQueue* omr)
-{
-    omr->msg_toget = 0;
-    omr->msg_tosave = 0;
-    omr->msg_event = CreateEventW(NULL, TRUE, FALSE, NULL);
-    omr->ring_buffer_size = EVENTS_RING_BUFFER_INCREMENT;
-    omr->messages = CoTaskMemAlloc(omr->ring_buffer_size * sizeof(Event));
-    ZeroMemory(omr->messages, omr->ring_buffer_size * sizeof(Event));
-
-    return TRUE;
-}
-
-static int EventsQueue_Destroy(EventsQueue* omr)
+struct media_event
 {
-    CloseHandle(omr->msg_event);
-    CoTaskMemFree(omr->messages);
-    return TRUE;
-}
-
-static BOOL EventsQueue_PutEvent(EventsQueue* omr, const Event* evt)
-{
-    if (omr->msg_toget == ((omr->msg_tosave + 1) % omr->ring_buffer_size))
-    {
-	int old_ring_buffer_size = omr->ring_buffer_size;
-	omr->ring_buffer_size += EVENTS_RING_BUFFER_INCREMENT;
-	TRACE("omr->ring_buffer_size=%d\n",omr->ring_buffer_size);
-	omr->messages = CoTaskMemRealloc(omr->messages, omr->ring_buffer_size * sizeof(Event));
-	/* Now we need to rearrange the ring buffer so that the new
-	   buffers just allocated are in between omr->msg_tosave and
-	   omr->msg_toget.
-	*/
-	if (omr->msg_tosave < omr->msg_toget)
-	{
-	    memmove(&(omr->messages[omr->msg_toget + EVENTS_RING_BUFFER_INCREMENT]),
-		    &(omr->messages[omr->msg_toget]),
-		    sizeof(Event)*(old_ring_buffer_size - omr->msg_toget)
-		    );
-	    omr->msg_toget += EVENTS_RING_BUFFER_INCREMENT;
-	}
-    }
-    omr->messages[omr->msg_tosave] = *evt;
-    SetEvent(omr->msg_event);
-    omr->msg_tosave = (omr->msg_tosave + 1) % omr->ring_buffer_size;
-    return TRUE;
-}
-
-static BOOL EventsQueue_GetEvent(EventsQueue* omr, Event* evt)
-{
-    if (omr->msg_toget == omr->msg_tosave) /* buffer empty ? */
-	return FALSE;
-
-    *evt = omr->messages[omr->msg_toget];
-    omr->msg_toget = (omr->msg_toget + 1) % omr->ring_buffer_size;
-
-    /* Mark the buffer as empty if needed */
-    if (omr->msg_toget == omr->msg_tosave) /* buffer empty ? */
-	ResetEvent(omr->msg_event);
-
-    return TRUE;
-}
+    struct list entry;
+    LONG code;
+    LONG_PTR param1, param2;
+};
 
 #define MAX_ITF_CACHE_ENTRIES 3
 typedef struct _ITF_CACHE_ENTRY {
@@ -180,7 +110,9 @@ struct filter_graph
 
     IReferenceClock *refClock;
     IBaseFilter *refClockProvider;
-    EventsQueue evqueue;
+
+    struct list media_events;
+    HANDLE media_event_handle;
     HANDLE hEventCompletion;
     int CompletionStatus;
     WndNotify notif;
@@ -189,6 +121,7 @@ struct filter_graph
     int HandleEcComplete;
     int HandleEcRepaint;
     int HandleEcClockChanged;
+
     CRITICAL_SECTION cs;
     ITF_CACHE_ENTRY ItfCacheEntries[MAX_ITF_CACHE_ENTRIES];
     int nItfCacheEntries;
@@ -370,6 +303,26 @@ static HRESULT create_enum_filters(struct filter_graph *graph, struct list *curs
     return S_OK;
 }
 
+static BOOL queue_media_event(struct filter_graph *graph, LONG code,
+        LONG_PTR param1, LONG_PTR param2)
+{
+    struct media_event *event;
+
+    if (!(event = malloc(sizeof(*event))))
+        return FALSE;
+
+    event->code = code;
+    event->param1 = param1;
+    event->param2 = param2;
+    list_add_tail(&graph->media_events, &event->entry);
+
+    SetEvent(graph->media_event_handle);
+    if (graph->notif.hWnd)
+        PostMessageW(graph->notif.hWnd, graph->notif.msg, 0, graph->notif.instance);
+
+    return TRUE;
+}
+
 static struct filter_graph *impl_from_IUnknown(IUnknown *iface)
 {
     return CONTAINING_RECORD(iface, struct filter_graph, IUnknown_inner);
@@ -463,7 +416,7 @@ static ULONG WINAPI FilterGraphInner_Release(IUnknown *iface)
 {
     struct filter_graph *This = impl_from_IUnknown(iface);
     ULONG ref = InterlockedDecrement(&This->ref);
-    struct filter *filter, *next;
+    struct list *cursor;
 
     TRACE("(%p)->(): new ref = %d\n", This, ref);
 
@@ -474,8 +427,10 @@ static ULONG WINAPI FilterGraphInner_Release(IUnknown *iface)
 
         IMediaControl_Stop(&This->IMediaControl_iface);
 
-        LIST_FOR_EACH_ENTRY_SAFE(filter, next, &This->filters, struct filter, entry)
+        while ((cursor = list_head(&This->filters)))
         {
+            struct filter *filter = LIST_ENTRY(cursor, struct filter, entry);
+
             IFilterGraph2_RemoveFilter(&This->IFilterGraph2_iface, filter->filter);
         }
 
@@ -492,8 +447,16 @@ static ULONG WINAPI FilterGraphInner_Release(IUnknown *iface)
 
         if (This->pSite) IUnknown_Release(This->pSite);
 
-	CloseHandle(This->hEventCompletion);
-	EventsQueue_Destroy(&This->evqueue);
+        while ((cursor = list_head(&This->media_events)))
+        {
+            struct media_event *event = LIST_ENTRY(cursor, struct media_event, entry);
+
+            list_remove(&event->entry);
+            free(event);
+        }
+
+        CloseHandle(This->media_event_handle);
+
         This->cs.DebugInfo->Spare[0] = 0;
         if (This->message_thread)
         {
@@ -4751,45 +4714,49 @@ static HRESULT WINAPI MediaEvent_Invoke(IMediaEventEx *iface, DISPID dispIdMembe
 }
 
 /*** IMediaEvent methods ***/
-static HRESULT WINAPI MediaEvent_GetEventHandle(IMediaEventEx *iface, OAEVENT *hEvent)
+static HRESULT WINAPI MediaEvent_GetEventHandle(IMediaEventEx *iface, OAEVENT *event)
 {
-    struct filter_graph *This = impl_from_IMediaEventEx(iface);
-
-    TRACE("(%p/%p)->(%p)\n", This, iface, hEvent);
+    struct filter_graph *graph = impl_from_IMediaEventEx(iface);
 
-    *hEvent = (OAEVENT)This->evqueue.msg_event;
+    TRACE("graph %p, event %p.\n", graph, event);
 
+    *event = (OAEVENT)graph->media_event_handle;
     return S_OK;
 }
 
-static HRESULT WINAPI MediaEvent_GetEvent(IMediaEventEx *iface, LONG *lEventCode, LONG_PTR *lParam1,
-        LONG_PTR *lParam2, LONG msTimeout)
+static HRESULT WINAPI MediaEvent_GetEvent(IMediaEventEx *iface, LONG *code,
+        LONG_PTR *param1, LONG_PTR *param2, LONG timeout)
 {
-    struct filter_graph *This = impl_from_IMediaEventEx(iface);
-    Event evt;
+    struct filter_graph *graph = impl_from_IMediaEventEx(iface);
+    struct media_event *event;
+    struct list *entry;
 
-    TRACE("(%p/%p)->(%p, %p, %p, %d)\n", This, iface, lEventCode, lParam1, lParam2, msTimeout);
+    TRACE("graph %p, code %p, param1 %p, param2 %p, timeout %d.\n", graph, code, param1, param2, timeout);
 
-    if (WaitForSingleObject(This->evqueue.msg_event, msTimeout))
-    {
-        *lEventCode = 0;
+    *code = 0;
+
+    if (WaitForSingleObject(graph->media_event_handle, timeout))
         return E_ABORT;
-    }
 
-    EnterCriticalSection(&This->cs);
+    EnterCriticalSection(&graph->cs);
 
-    if (EventsQueue_GetEvent(&This->evqueue, &evt))
+    if (!(entry = list_head(&graph->media_events)))
     {
-	*lEventCode = evt.lEventCode;
-	*lParam1 = evt.lParam1;
-	*lParam2 = evt.lParam2;
-        LeaveCriticalSection(&This->cs);
-	return S_OK;
+        LeaveCriticalSection(&graph->cs);
+        return E_ABORT;
     }
+    event = LIST_ENTRY(entry, struct media_event, entry);
+    list_remove(&event->entry);
+    *code = event->code;
+    *param1 = event->param1;
+    *param2 = event->param2;
+    free(event);
 
-    LeaveCriticalSection(&This->cs);
-    *lEventCode = 0;
-    return E_ABORT;
+    if (list_empty(&graph->media_events))
+        ResetEvent(graph->media_event_handle);
+
+    LeaveCriticalSection(&graph->cs);
+    return S_OK;
 }
 
 static HRESULT WINAPI MediaEvent_WaitForCompletion(IMediaEventEx *iface, LONG msTimeout,
@@ -5266,58 +5233,38 @@ static ULONG WINAPI MediaEventSink_Release(IMediaEventSink *iface)
     return IUnknown_Release(graph->outer_unk);
 }
 
-static HRESULT WINAPI MediaEventSink_Notify(IMediaEventSink *iface, LONG EventCode,
-        LONG_PTR EventParam1, LONG_PTR EventParam2)
+static HRESULT WINAPI MediaEventSink_Notify(IMediaEventSink *iface, LONG code,
+        LONG_PTR param1, LONG_PTR param2)
 {
-    struct filter_graph *This = impl_from_IMediaEventSink(iface);
-    Event evt;
+    struct filter_graph *graph = impl_from_IMediaEventSink(iface);
 
-    TRACE("(%p/%p)->(%d, %ld, %ld)\n", This, iface, EventCode, EventParam1, EventParam2);
+    TRACE("graph %p, code %#x, param1 %#Ix, param2 %#Ix.\n", graph, code, param1, param2);
 
-    EnterCriticalSection(&This->cs);
+    EnterCriticalSection(&graph->cs);
 
-    if ((EventCode == EC_COMPLETE) && This->HandleEcComplete)
+    if (code == EC_COMPLETE && graph->HandleEcComplete)
     {
-        TRACE("Process EC_COMPLETE notification\n");
-        if (++This->EcCompleteCount == This->nRenderers)
+        if (++graph->EcCompleteCount == graph->nRenderers)
         {
-            if (!This->notif.disabled)
-            {
-                evt.lEventCode = EC_COMPLETE;
-                evt.lParam1 = S_OK;
-                evt.lParam2 = 0;
-                TRACE("Send EC_COMPLETE to app\n");
-                EventsQueue_PutEvent(&This->evqueue, &evt);
-                if (This->notif.hWnd)
-                {
-                    TRACE("Send Window message\n");
-                    PostMessageW(This->notif.hWnd, This->notif.msg, 0, This->notif.instance);
-                }
-            }
+            if (graph->notif.disabled)
+                SetEvent(graph->media_event_handle);
             else
-            {
-                SetEvent(This->evqueue.msg_event);
-            }
-            This->CompletionStatus = EC_COMPLETE;
-            This->got_ec_complete = 1;
-            SetEvent(This->hEventCompletion);
+                queue_media_event(graph, EC_COMPLETE, S_OK, 0);
+            graph->CompletionStatus = EC_COMPLETE;
+            graph->got_ec_complete = 1;
+            SetEvent(graph->hEventCompletion);
         }
     }
-    else if ((EventCode == EC_REPAINT) && This->HandleEcRepaint)
+    else if ((code == EC_REPAINT) && graph->HandleEcRepaint)
     {
-        /* FIXME: Not handled yet */
+        FIXME("EC_REPAINT is not handled.\n");
     }
-    else if (!This->notif.disabled)
+    else if (!graph->notif.disabled)
     {
-        evt.lEventCode = EventCode;
-        evt.lParam1 = EventParam1;
-        evt.lParam2 = EventParam2;
-        EventsQueue_PutEvent(&This->evqueue, &evt);
-        if (This->notif.hWnd)
-            PostMessageW(This->notif.hWnd, This->notif.msg, 0, This->notif.instance);
+        queue_media_event(graph, code, param1, param2);
     }
 
-    LeaveCriticalSection(&This->cs);
+    LeaveCriticalSection(&graph->cs);
     return S_OK;
 }
 
@@ -5625,12 +5572,15 @@ static HRESULT filter_graph_common_create(IUnknown *outer, IUnknown **out, BOOL
     object->cs.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": filter_graph.cs");
 
     object->defaultclock = TRUE;
-    EventsQueue_Init(&object->evqueue);
+
+    object->media_event_handle = CreateEventW(NULL, TRUE, FALSE, NULL);
+    list_init(&object->media_events);
     list_init(&object->filters);
     object->HandleEcClockChanged = TRUE;
     object->HandleEcComplete = TRUE;
     object->HandleEcRepaint = TRUE;
     object->hEventCompletion = CreateEventW(0, TRUE, FALSE, 0);
+
     object->name_index = 1;
     object->timeformatseek = TIME_FORMAT_MEDIA_TIME;
 
-- 
2.30.1




More information about the wine-devel mailing list