quartz/filtergraph: Create filters on a separate thread if requested.
Signed-off-by: Zebediah Figura <z.figura12@gmail.com> Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
parent
5e8eb5f4c5
commit
5994c8cc85
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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 },
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue