[PATCH 1/5] quartz/filtergraph: Create filters on a separate thread if requested.

Zebediah Figura z.figura12 at gmail.com
Wed Oct 2 22:01:06 CDT 2019


Signed-off-by: Zebediah Figura <z.figura12 at gmail.com>
---
 dlls/quartz/filtergraph.c       | 105 +++++++++++++++++++++++++++-----
 dlls/quartz/main.c              |   4 +-
 dlls/quartz/quartz_private.h    |   4 +-
 dlls/quartz/tests/filtergraph.c |   5 +-
 4 files changed, 97 insertions(+), 21 deletions(-)

diff --git a/dlls/quartz/filtergraph.c b/dlls/quartz/filtergraph.c
index d8db871505b..b4d0164fd3a 100644
--- a/dlls/quartz/filtergraph.c
+++ b/dlls/quartz/filtergraph.c
@@ -208,6 +208,9 @@ typedef struct _IFilterGraphImpl {
     LONG recursioncount;
     IUnknown *pSite;
     LONG version;
+
+    HANDLE message_thread, message_thread_ret;
+    DWORD message_thread_id;
 } IFilterGraphImpl;
 
 struct enum_filters
@@ -489,6 +492,13 @@ static ULONG WINAPI FilterGraphInner_Release(IUnknown *iface)
 	CloseHandle(This->hEventCompletion);
 	EventsQueue_Destroy(&This->evqueue);
         This->cs.DebugInfo->Spare[0] = 0;
+        if (This->message_thread)
+        {
+            PostThreadMessageW(This->message_thread_id, WM_USER + 1, 0, 0);
+            WaitForSingleObject(This->message_thread, INFINITE);
+            CloseHandle(This->message_thread);
+            CloseHandle(This->message_thread_ret);
+        }
 	DeleteCriticalSection(&This->cs);
 	CoTaskMemFree(This);
     }
@@ -964,6 +974,63 @@ static HRESULT GetFilterInfo(IMoniker* pMoniker, VARIANT* pvar)
     return hr;
 }
 
+struct filter_create_params
+{
+    HRESULT hr;
+    IMoniker *moniker;
+    IBaseFilter *filter;
+};
+
+static DWORD WINAPI message_thread_run(void *ctx)
+{
+    IFilterGraphImpl *graph = ctx;
+    MSG msg;
+
+    CoInitializeEx(NULL, COINIT_MULTITHREADED);
+
+    for (;;)
+    {
+        GetMessageW(&msg, NULL, 0, 0);
+
+        if (!msg.hwnd && msg.message == WM_USER)
+        {
+            struct filter_create_params *params = (struct filter_create_params *)msg.wParam;
+
+            params->hr = IMoniker_BindToObject(params->moniker, NULL, NULL,
+                    &IID_IBaseFilter, (void **)&params->filter);
+            SetEvent(graph->message_thread_ret);
+        }
+        else if (!msg.hwnd && msg.message == WM_USER + 1)
+        {
+            break;
+        }
+        else
+        {
+            TranslateMessage(&msg);
+            DispatchMessageW(&msg);
+        }
+    }
+
+    CoUninitialize();
+    return 0;
+}
+
+static HRESULT create_filter(IFilterGraphImpl *graph, IMoniker *moniker, IBaseFilter **filter)
+{
+    if (graph->message_thread)
+    {
+        struct filter_create_params params;
+
+        params.moniker = moniker;
+        PostThreadMessageW(graph->message_thread_id, WM_USER, (WPARAM)&params, 0);
+        WaitForSingleObject(graph->message_thread_ret, INFINITE);
+        *filter = params.filter;
+        return params.hr;
+    }
+    else
+        return IMoniker_BindToObject(moniker, NULL, NULL, &IID_IBaseFilter, (void **)filter);
+}
+
 /* Attempt to connect one of the output pins on filter to sink. Helper for
  * FilterGraph2_Connect(). */
 static HRESULT connect_output_pin(IFilterGraphImpl *graph, IBaseFilter *filter, IPin *sink)
@@ -1164,7 +1231,7 @@ static HRESULT WINAPI FilterGraph2_Connect(IFilterGraph2 *iface, IPin *ppinOut,
             goto error;
         }
 
-        hr = IMoniker_BindToObject(pMoniker, NULL, NULL, &IID_IBaseFilter, (LPVOID*)&pfilter);
+        hr = create_filter(This, pMoniker, &pfilter);
         IMoniker_Release(pMoniker);
         if (FAILED(hr)) {
             WARN("Unable to create filter (%x), trying next one\n", hr);
@@ -1497,7 +1564,7 @@ static HRESULT WINAPI FilterGraph2_Render(IFilterGraph2 *iface, IPin *ppinOut)
                 goto error;
             }
 
-            hr = IMoniker_BindToObject(pMoniker, NULL, NULL, &IID_IBaseFilter, (LPVOID*)&pfilter);
+            hr = create_filter(This, pMoniker, &pfilter);
             IMoniker_Release(pMoniker);
             if (FAILED(hr))
             {
@@ -5565,15 +5632,12 @@ static const IUnknownVtbl IInner_VTable =
     FilterGraphInner_Release
 };
 
-/* This is the only function that actually creates a FilterGraph class... */
-HRESULT FilterGraph_create(IUnknown *pUnkOuter, LPVOID *ppObj)
+static HRESULT filter_graph_common_create(IUnknown *outer, void **out, BOOL threaded)
 {
     IFilterGraphImpl *fimpl;
     HRESULT hr;
 
-    TRACE("(%p,%p)\n", pUnkOuter, ppObj);
-
-    *ppObj = NULL;
+    *out = NULL;
 
     fimpl = CoTaskMemAlloc(sizeof(*fimpl));
     fimpl->defaultclock = TRUE;
@@ -5617,10 +5681,15 @@ HRESULT FilterGraph_create(IUnknown *pUnkOuter, LPVOID *ppObj)
     fimpl->recursioncount = 0;
     fimpl->version = 0;
 
-    if (pUnkOuter)
-        fimpl->outer_unk = pUnkOuter;
+    if (threaded)
+    {
+        fimpl->message_thread = CreateThread(NULL, 0, message_thread_run, fimpl, 0, &fimpl->message_thread_id);
+        fimpl->message_thread_ret = CreateEventW(NULL, FALSE, FALSE, NULL);
+    }
     else
-        fimpl->outer_unk = &fimpl->IUnknown_inner;
+        fimpl->message_thread = NULL;
+
+    fimpl->outer_unk = outer ? outer : &fimpl->IUnknown_inner;
 
     /* create Filtermapper aggregated. */
     hr = CoCreateInstance(&CLSID_FilterMapper2, fimpl->outer_unk, CLSCTX_INPROC_SERVER,
@@ -5637,12 +5706,20 @@ HRESULT FilterGraph_create(IUnknown *pUnkOuter, LPVOID *ppObj)
         return hr;
     }
 
-    *ppObj = &fimpl->IUnknown_inner;
+    *out = &fimpl->IUnknown_inner;
     return S_OK;
 }
 
-HRESULT FilterGraphNoThread_create(IUnknown *pUnkOuter, LPVOID *ppObj)
+HRESULT filter_graph_create(IUnknown *outer, void **out)
 {
-    FIXME("CLSID_FilterGraphNoThread partially implemented - Forwarding to CLSID_FilterGraph\n");
-    return FilterGraph_create(pUnkOuter, ppObj);
+    TRACE("outer %p, out %p.\n", outer, out);
+
+    return filter_graph_common_create(outer, out, TRUE);
+}
+
+HRESULT filter_graph_no_thread_create(IUnknown *outer, void **out)
+{
+    TRACE("outer %p, out %p.\n", outer, out);
+
+    return filter_graph_common_create(outer, out, FALSE);
 }
diff --git a/dlls/quartz/main.c b/dlls/quartz/main.c
index 36ec59c4e03..9540fa92935 100644
--- a/dlls/quartz/main.c
+++ b/dlls/quartz/main.c
@@ -63,8 +63,8 @@ struct object_creation_info
 static const struct object_creation_info object_creation[] =
 {
     { &CLSID_SeekingPassThru, SeekingPassThru_create },
-    { &CLSID_FilterGraph, FilterGraph_create },
-    { &CLSID_FilterGraphNoThread, FilterGraphNoThread_create },
+    { &CLSID_FilterGraph, filter_graph_create },
+    { &CLSID_FilterGraphNoThread, filter_graph_no_thread_create },
     { &CLSID_FilterMapper, FilterMapper_create },
     { &CLSID_FilterMapper2, FilterMapper2_create },
     { &CLSID_AsyncReader, AsyncReader_create },
diff --git a/dlls/quartz/quartz_private.h b/dlls/quartz/quartz_private.h
index 353d1e5a577..1213aea352a 100644
--- a/dlls/quartz/quartz_private.h
+++ b/dlls/quartz/quartz_private.h
@@ -40,8 +40,8 @@
 #define MEDIATIME_FROM_BYTES(x) ((LONGLONG)(x) * 10000000)
 #define BYTES_FROM_MEDIATIME(time) ((time) / 10000000)
 
-HRESULT FilterGraph_create(IUnknown *pUnkOuter, LPVOID *ppObj) DECLSPEC_HIDDEN;
-HRESULT FilterGraphNoThread_create(IUnknown *pUnkOuter, LPVOID *ppObj) DECLSPEC_HIDDEN;
+HRESULT filter_graph_create(IUnknown *outer, void **out) DECLSPEC_HIDDEN;
+HRESULT filter_graph_no_thread_create(IUnknown *outer, void **out) DECLSPEC_HIDDEN;
 HRESULT FilterMapper2_create(IUnknown *pUnkOuter, LPVOID *ppObj) DECLSPEC_HIDDEN;
 HRESULT FilterMapper_create(IUnknown *pUnkOuter, LPVOID *ppObj) DECLSPEC_HIDDEN;
 HRESULT AsyncReader_create(IUnknown * pUnkOuter, LPVOID * ppv) DECLSPEC_HIDDEN;
diff --git a/dlls/quartz/tests/filtergraph.c b/dlls/quartz/tests/filtergraph.c
index 2aca4a91c87..8141d928c61 100644
--- a/dlls/quartz/tests/filtergraph.c
+++ b/dlls/quartz/tests/filtergraph.c
@@ -760,10 +760,9 @@ static DWORD WINAPI call_RenderFile_multithread(LPVOID lParam)
     HRESULT hr;
 
     hr = IFilterGraph2_RenderFile(graph, filename, NULL);
-    ok(SUCCEEDED(hr), "RenderFile failed: %x\n", hr);
+    ok(hr == S_OK, "Got hr %#x.\n", hr);
 
-    if (SUCCEEDED(hr))
-        rungraph(graph, TRUE);
+    rungraph(graph, TRUE);
 
     return 0;
 }
-- 
2.23.0




More information about the wine-devel mailing list