[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 **)¶ms->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)¶ms, 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