mirror of
git://source.winehq.org/git/wine.git
synced 2024-10-06 08:54:05 +00:00
quartz: Use a single message thread for all filter graphs.
This matches native, as the test shows, but was motivated by bug 50779, which it may alleviate.
This commit is contained in:
parent
c7a97b5d5d
commit
0ad6d68873
|
@ -42,6 +42,19 @@
|
|||
|
||||
WINE_DEFAULT_DEBUG_CHANNEL(quartz);
|
||||
|
||||
DECLARE_CRITICAL_SECTION(message_cs);
|
||||
|
||||
struct filter_create_params
|
||||
{
|
||||
HRESULT hr;
|
||||
IMoniker *moniker;
|
||||
IBaseFilter *filter;
|
||||
};
|
||||
|
||||
static HANDLE message_thread, message_thread_ret;
|
||||
static DWORD message_thread_id;
|
||||
static unsigned int message_thread_refcount;
|
||||
|
||||
struct media_event
|
||||
{
|
||||
struct list entry;
|
||||
|
@ -132,9 +145,6 @@ struct filter_graph
|
|||
IUnknown *pSite;
|
||||
LONG version;
|
||||
|
||||
HANDLE message_thread, message_thread_ret;
|
||||
DWORD message_thread_id;
|
||||
|
||||
/* Respectively: the last timestamp at which we started streaming, and the
|
||||
* current offset within the stream. */
|
||||
REFERENCE_TIME stream_start, stream_elapsed;
|
||||
|
@ -142,6 +152,7 @@ struct filter_graph
|
|||
LONGLONG current_pos;
|
||||
|
||||
unsigned int needs_async_run : 1;
|
||||
unsigned int threaded : 1;
|
||||
};
|
||||
|
||||
struct enum_filters
|
||||
|
@ -465,14 +476,17 @@ static ULONG WINAPI FilterGraphInner_Release(IUnknown *iface)
|
|||
flush_media_events(This);
|
||||
CloseHandle(This->media_event_handle);
|
||||
|
||||
This->cs.DebugInfo->Spare[0] = 0;
|
||||
if (This->message_thread)
|
||||
EnterCriticalSection(&message_cs);
|
||||
if (This->threaded && !--message_thread_refcount)
|
||||
{
|
||||
PostThreadMessageW(This->message_thread_id, WM_USER + 1, 0, 0);
|
||||
WaitForSingleObject(This->message_thread, INFINITE);
|
||||
CloseHandle(This->message_thread);
|
||||
CloseHandle(This->message_thread_ret);
|
||||
PostThreadMessageW(message_thread_id, WM_USER + 1, 0, 0);
|
||||
WaitForSingleObject(message_thread, INFINITE);
|
||||
CloseHandle(message_thread);
|
||||
CloseHandle(message_thread_ret);
|
||||
}
|
||||
LeaveCriticalSection(&message_cs);
|
||||
|
||||
This->cs.DebugInfo->Spare[0] = 0;
|
||||
DeleteCriticalSection(&This->event_cs);
|
||||
DeleteCriticalSection(&This->cs);
|
||||
free(This);
|
||||
|
@ -1012,21 +1026,13 @@ static HRESULT WINAPI FilterGraph2_SetDefaultSyncSource(IFilterGraph2 *iface)
|
|||
return hr;
|
||||
}
|
||||
|
||||
struct filter_create_params
|
||||
{
|
||||
HRESULT hr;
|
||||
IMoniker *moniker;
|
||||
IBaseFilter *filter;
|
||||
};
|
||||
|
||||
static DWORD WINAPI message_thread_run(void *ctx)
|
||||
{
|
||||
struct filter_graph *graph = ctx;
|
||||
MSG msg;
|
||||
|
||||
/* Make sure we have a message queue. */
|
||||
PeekMessageW(&msg, NULL, 0, 0, PM_NOREMOVE);
|
||||
SetEvent(graph->message_thread_ret);
|
||||
SetEvent(message_thread_ret);
|
||||
|
||||
CoInitializeEx(NULL, COINIT_MULTITHREADED);
|
||||
|
||||
|
@ -1040,7 +1046,7 @@ static DWORD WINAPI message_thread_run(void *ctx)
|
|||
|
||||
params->hr = IMoniker_BindToObject(params->moniker, NULL, NULL,
|
||||
&IID_IBaseFilter, (void **)¶ms->filter);
|
||||
SetEvent(graph->message_thread_ret);
|
||||
SetEvent(message_thread_ret);
|
||||
}
|
||||
else if (!msg.hwnd && msg.message == WM_USER + 1)
|
||||
{
|
||||
|
@ -1059,13 +1065,17 @@ static DWORD WINAPI message_thread_run(void *ctx)
|
|||
|
||||
static HRESULT create_filter(struct filter_graph *graph, IMoniker *moniker, IBaseFilter **filter)
|
||||
{
|
||||
if (graph->message_thread)
|
||||
if (graph->threaded)
|
||||
{
|
||||
struct filter_create_params params;
|
||||
|
||||
params.moniker = moniker;
|
||||
PostThreadMessageW(graph->message_thread_id, WM_USER, (WPARAM)¶ms, 0);
|
||||
WaitForSingleObject(graph->message_thread_ret, INFINITE);
|
||||
|
||||
EnterCriticalSection(&message_cs);
|
||||
PostThreadMessageW(message_thread_id, WM_USER, (WPARAM)¶ms, 0);
|
||||
WaitForSingleObject(message_thread_ret, INFINITE);
|
||||
LeaveCriticalSection(&message_cs);
|
||||
|
||||
*filter = params.filter;
|
||||
return params.hr;
|
||||
}
|
||||
|
@ -5654,14 +5664,16 @@ static HRESULT filter_graph_common_create(IUnknown *outer, IUnknown **out, BOOL
|
|||
object->name_index = 1;
|
||||
object->timeformatseek = TIME_FORMAT_MEDIA_TIME;
|
||||
|
||||
if (threaded)
|
||||
object->threaded = !!threaded;
|
||||
|
||||
EnterCriticalSection(&message_cs);
|
||||
if (threaded && !message_thread_refcount++)
|
||||
{
|
||||
object->message_thread_ret = CreateEventW(NULL, FALSE, FALSE, NULL);
|
||||
object->message_thread = CreateThread(NULL, 0, message_thread_run, object, 0, &object->message_thread_id);
|
||||
WaitForSingleObject(object->message_thread_ret, INFINITE);
|
||||
message_thread_ret = CreateEventW(NULL, FALSE, FALSE, NULL);
|
||||
message_thread = CreateThread(NULL, 0, message_thread_run, object, 0, &message_thread_id);
|
||||
WaitForSingleObject(message_thread_ret, INFINITE);
|
||||
}
|
||||
else
|
||||
object->message_thread = NULL;
|
||||
LeaveCriticalSection(&message_cs);
|
||||
|
||||
TRACE("Created %sthreaded filter graph %p.\n", threaded ? "" : "non-", object);
|
||||
*out = &object->IUnknown_inner;
|
||||
|
|
|
@ -37,6 +37,13 @@
|
|||
#include "wine/strmbase.h"
|
||||
#include "wine/list.h"
|
||||
|
||||
#define DECLARE_CRITICAL_SECTION(cs) \
|
||||
static CRITICAL_SECTION cs; \
|
||||
static CRITICAL_SECTION_DEBUG cs##_debug = \
|
||||
{ 0, 0, &cs, { &cs##_debug.ProcessLocksList, &cs##_debug.ProcessLocksList }, \
|
||||
0, 0, { (DWORD_PTR)(__FILE__ ": " # cs) }}; \
|
||||
static CRITICAL_SECTION cs = { &cs##_debug, -1, 0, 0, 0, 0 };
|
||||
|
||||
static inline const char *debugstr_time(REFERENCE_TIME time)
|
||||
{
|
||||
ULONGLONG abstime = time >= 0 ? time : -time;
|
||||
|
|
|
@ -5213,10 +5213,11 @@ static void test_window_threading(void)
|
|||
};
|
||||
WCHAR *filename = load_resource(L"test.avi");
|
||||
IFilterGraph2 *graph = create_graph();
|
||||
HWND hwnd, hwnd2, parent;
|
||||
IFilterGraph2 *graph2;
|
||||
IVideoWindow *window;
|
||||
HWND hwnd, parent;
|
||||
DWORD tid, tid2;
|
||||
HRESULT hr;
|
||||
DWORD tid;
|
||||
ULONG ref;
|
||||
BOOL ret;
|
||||
|
||||
|
@ -5253,6 +5254,17 @@ static void test_window_threading(void)
|
|||
ok(hr == S_OK, "Got hr %#lx.\n", hr);
|
||||
IVideoWindow_Release(window);
|
||||
ok(!(GetWindowLongW(hwnd, GWL_EXSTYLE) & WS_EX_NOPARENTNOTIFY), "Window has WS_EX_NOPARENTNOTIFY.\n");
|
||||
|
||||
graph2 = create_graph();
|
||||
hr = IFilterGraph2_RenderFile(graph2, filename, NULL);
|
||||
ok(hr == S_OK, "Got hr %#lx.\n", hr);
|
||||
hwnd2 = get_renderer_hwnd(graph);
|
||||
ok(!!hwnd2, "Failed to get renderer window.\n");
|
||||
tid2 = GetWindowThreadProcessId(hwnd, NULL);
|
||||
ok(tid2 == tid, "Expected thread to be shared.\n");
|
||||
|
||||
ref = IFilterGraph2_Release(graph2);
|
||||
ok(!ref, "Got outstanding refcount %ld.\n", ref);
|
||||
}
|
||||
else
|
||||
skip("Could not find renderer window.\n");
|
||||
|
|
Loading…
Reference in a new issue