Before https://gitlab.winehq.org/wine/wine/-/merge_requests/140, and to avoid a situation in the future where we might decide to implement this, and where the callback would be called asynchronously as they are supposed to, without the ASF reader filter supporting it.
-- v3: winegstreamer: Make IWMReader state transitions asynchronous. winegstreamer: Leave the stream CS while waiting for a sample. winegstreamer: Move IWMReaderCallbackAdvanced *callback_advanced to a local variable. wmvcore/tests: Add more IWMReader_(Open|Start|Stop|Close) async checks.
From: R��mi Bernon rbernon@codeweavers.com
--- dlls/wmvcore/tests/wmvcore.c | 214 ++++++++++++++++++++++++++--------- 1 file changed, 158 insertions(+), 56 deletions(-)
diff --git a/dlls/wmvcore/tests/wmvcore.c b/dlls/wmvcore/tests/wmvcore.c index f639184de90..ee2e685bc0a 100644 --- a/dlls/wmvcore/tests/wmvcore.c +++ b/dlls/wmvcore/tests/wmvcore.c @@ -1422,8 +1422,11 @@ struct callback IWMReaderCallbackAdvanced IWMReaderCallbackAdvanced_iface; IWMReaderAllocatorEx IWMReaderAllocatorEx_iface; LONG refcount; - HANDLE got_opened, got_stopped, eof_event; - unsigned int got_closed, got_started, got_sample, got_end_of_streaming, got_eof; + HANDLE expect_opened, got_opened; + HANDLE expect_started, got_started; + HANDLE expect_stopped, got_stopped; + HANDLE expect_eof, got_eof; + unsigned int closed_count, started_count, end_of_streaming_count, eof_count, sample_count; bool all_streams_off; bool allocated_samples;
@@ -1480,6 +1483,7 @@ static HRESULT WINAPI callback_OnStatus(IWMReaderCallback *iface, WMT_STATUS sta HRESULT hr, WMT_ATTR_DATATYPE type, BYTE *value, void *context) { struct callback *callback = impl_from_IWMReaderCallback(iface); + DWORD ret;
if (winetest_debug > 1) trace("%lu: %04lx: IWMReaderCallback::OnStatus(status %u, hr %#lx, type %#x, value %p)\n", @@ -1491,6 +1495,9 @@ static HRESULT WINAPI callback_OnStatus(IWMReaderCallback *iface, WMT_STATUS sta ok(type == WMT_TYPE_DWORD, "Got type %#x.\n", type); ok(!*(DWORD *)value, "Got value %#lx.\n", *(DWORD *)value); ok(context == (void *)0xdeadbeef, "Got unexpected context %p.\n", context); + ret = WaitForSingleObject(callback->expect_opened, 100); + todo_wine + ok(!ret, "Wait timed out.\n"); SetEvent(callback->got_opened); break;
@@ -1498,14 +1505,22 @@ static HRESULT WINAPI callback_OnStatus(IWMReaderCallback *iface, WMT_STATUS sta ok(type == WMT_TYPE_DWORD, "Got type %#x.\n", type); ok(!*(DWORD *)value, "Got value %#lx.\n", *(DWORD *)value); ok(context == (void *)0xfacade, "Got unexpected context %p.\n", context); - callback->got_end_of_streaming = callback->got_eof = callback->got_sample = 0; - ++callback->got_started; + ret = WaitForSingleObject(callback->expect_started, 100); + todo_wine + ok(!ret, "Wait timed out.\n"); + callback->end_of_streaming_count = callback->eof_count = callback->sample_count = 0; + ++callback->started_count; + ResetEvent(callback->got_eof); + SetEvent(callback->got_started); break;
case WMT_STOPPED: ok(type == WMT_TYPE_DWORD, "Got type %#x.\n", type); ok(!*(DWORD *)value, "Got value %#lx.\n", *(DWORD *)value); ok(context == (void *)0xfacade, "Got unexpected context %p.\n", context); + ret = WaitForSingleObject(callback->expect_stopped, 100); + todo_wine + ok(!ret, "Wait timed out.\n"); SetEvent(callback->got_stopped); break;
@@ -1513,15 +1528,14 @@ static HRESULT WINAPI callback_OnStatus(IWMReaderCallback *iface, WMT_STATUS sta ok(type == WMT_TYPE_DWORD, "Got type %#x.\n", type); ok(!*(DWORD *)value, "Got value %#lx.\n", *(DWORD *)value); ok(context == (void *)0xfacade, "Got unexpected context %p.\n", context); - ++callback->got_closed; + ++callback->closed_count; break;
case WMT_END_OF_STREAMING: ok(type == WMT_TYPE_DWORD, "Got type %#x.\n", type); ok(!*(DWORD *)value, "Got value %#lx.\n", *(DWORD *)value); ok(context == (void *)0xfacade, "Got unexpected context %p.\n", context); - ok(!callback->got_eof, "Got %u WMT_EOF callbacks.\n", callback->got_eof); - ++callback->got_end_of_streaming; + ++callback->end_of_streaming_count; break;
case WMT_EOF: @@ -1529,13 +1543,15 @@ static HRESULT WINAPI callback_OnStatus(IWMReaderCallback *iface, WMT_STATUS sta ok(!*(DWORD *)value, "Got value %#lx.\n", *(DWORD *)value); ok(context == (void *)0xfacade, "Got unexpected context %p.\n", context); if (callback->all_streams_off) - ok(callback->got_sample == 0, "Got %u samples.\n", callback->got_sample); + ok(callback->sample_count == 0, "Got %u samples.\n", callback->sample_count); else - ok(callback->got_sample > 0, "Got no samples.\n"); - ok(callback->got_end_of_streaming == 1, "Got %u WMT_END_OF_STREAMING callbacks.\n", - callback->got_end_of_streaming); - ++callback->got_eof; - SetEvent(callback->eof_event); + ok(callback->sample_count > 0, "Got no samples.\n"); + ret = WaitForSingleObject(callback->expect_eof, 100); + ok(!ret, "Wait timed out.\n"); + ++callback->eof_count; + SetEvent(callback->got_eof); + ok(callback->end_of_streaming_count == 1, "Got %u WMT_END_OF_STREAMING callbacks.\n", + callback->end_of_streaming_count); break;
/* Not sent when not using IWMReaderAdvanced::DeliverTime(). */ @@ -1544,17 +1560,18 @@ static HRESULT WINAPI callback_OnStatus(IWMReaderCallback *iface, WMT_STATUS sta ok(*(QWORD *)value == 3000, "Got value %#lx.\n", *(DWORD *)value); ok(context == (void *)0xfacade, "Got unexpected context %p.\n", context); if (callback->all_streams_off) - ok(callback->got_sample == 0, "Got %u samples.\n", callback->got_sample); + ok(callback->sample_count == 0, "Got %u samples.\n", callback->sample_count); else - ok(callback->got_sample > 0, "Got no samples.\n"); - ok(callback->got_eof == 1, "Got %u WMT_EOF callbacks.\n", callback->got_eof); + ok(callback->sample_count > 0, "Got no samples.\n"); + ok(callback->eof_count == 1, "Got %u WMT_EOF callbacks.\n", + callback->eof_count); break;
default: ok(0, "Unexpected status %#x.\n", status); }
- ok(hr == S_OK, "Got hr %#lx.\n", hr); + ok(hr == S_OK || hr == E_ABORT, "Got hr %#lx.\n", hr); return S_OK; }
@@ -1613,9 +1630,9 @@ static HRESULT WINAPI callback_OnSample(IWMReaderCallback *iface, DWORD output, check_async_sample(callback, sample);
ok(!callback->read_compressed, "OnSample() should not be called when reading compressed samples.\n"); - ok(callback->got_started > 0, "Got %u WMT_STARTED callbacks.\n", callback->got_started); - ok(!callback->got_eof, "Got %u WMT_EOF callbacks.\n", callback->got_eof); - ++callback->got_sample; + ok(callback->started_count > 0, "Got %u WMT_STARTED callbacks.\n", callback->started_count); + ok(!callback->eof_count, "Got %u WMT_EOF callbacks.\n", callback->eof_count); + ++callback->sample_count;
return S_OK; } @@ -1666,9 +1683,9 @@ static HRESULT WINAPI callback_advanced_OnStreamSample(IWMReaderCallbackAdvanced check_async_sample(callback, sample);
ok(callback->read_compressed, "OnStreamSample() should not be called unless reading compressed samples.\n"); - ok(callback->got_started > 0, "Got %u WMT_STARTED callbacks.\n", callback->got_started); - ok(!callback->got_eof, "Got %u WMT_EOF callbacks.\n", callback->got_eof); - ++callback->got_sample; + ok(callback->started_count > 0, "Got %u WMT_STARTED callbacks.\n", callback->started_count); + ok(!callback->eof_count, "Got %u WMT_EOF callbacks.\n", callback->eof_count); + ++callback->sample_count;
return S_OK; } @@ -1681,6 +1698,7 @@ static HRESULT WINAPI callback_advanced_OnTime(IWMReaderCallbackAdvanced *iface, trace("%lu: %04lx: IWMReaderCallbackAdvanced::OnTime(time %I64u)\n", GetTickCount(), GetCurrentThreadId(), time);
+ todo_wine_if(time == 0 && callback->expect_ontime) ok(time == callback->expect_ontime, "Got time %I64u.\n", time); ok(context == (void *)0xfacade, "Got unexpected context %p.\n", context); SetEvent(callback->ontime_event); @@ -1840,47 +1858,132 @@ static void callback_init(struct callback *callback) callback->IWMReaderCallbackAdvanced_iface.lpVtbl = &callback_advanced_vtbl; callback->IWMReaderAllocatorEx_iface.lpVtbl = &callback_allocator_vtbl; callback->refcount = 1; + callback->expect_opened = CreateEventW(NULL, FALSE, FALSE, NULL); callback->got_opened = CreateEventW(NULL, FALSE, FALSE, NULL); + callback->expect_started = CreateEventW(NULL, FALSE, FALSE, NULL); + callback->got_started = CreateEventW(NULL, FALSE, FALSE, NULL); + callback->expect_stopped = CreateEventW(NULL, FALSE, FALSE, NULL); callback->got_stopped = CreateEventW(NULL, FALSE, FALSE, NULL); - callback->eof_event = CreateEventW(NULL, FALSE, FALSE, NULL); + callback->expect_eof = CreateEventW(NULL, FALSE, FALSE, NULL); + callback->got_eof = CreateEventW(NULL, FALSE, FALSE, NULL); callback->ontime_event = CreateEventW(NULL, FALSE, FALSE, NULL); }
static void callback_cleanup(struct callback *callback) { CloseHandle(callback->got_opened); + CloseHandle(callback->expect_opened); + CloseHandle(callback->got_started); + CloseHandle(callback->expect_started); CloseHandle(callback->got_stopped); - CloseHandle(callback->eof_event); + CloseHandle(callback->expect_stopped); + CloseHandle(callback->got_eof); + CloseHandle(callback->expect_eof); CloseHandle(callback->ontime_event); }
+#define wait_opened_callback(a) wait_opened_callback_(__LINE__, a) +static void wait_opened_callback_(int line, struct callback *callback) +{ + DWORD ret; + + ret = WaitForSingleObject(callback->got_opened, 0); + todo_wine + ok_(__FILE__, line)(ret == WAIT_TIMEOUT, "Got unexpected WMT_OPENED.\n"); + if (ret == WAIT_TIMEOUT) + { + SetEvent(callback->expect_opened); + ret = WaitForSingleObject(callback->got_opened, 1000); + ok_(__FILE__, line)(!ret, "Wait timed out.\n"); + } +} + +#define wait_started_callback(a) wait_started_callback_(__LINE__, a) +static void wait_started_callback_(int line, struct callback *callback) +{ + DWORD ret; + + ret = WaitForSingleObject(callback->got_started, 0); + todo_wine + ok_(__FILE__, line)(ret == WAIT_TIMEOUT, "Got unexpected WMT_STARTED.\n"); + if (ret == WAIT_TIMEOUT) + { + SetEvent(callback->expect_started); + ret = WaitForSingleObject(callback->got_started, 1000); + ok_(__FILE__, line)(!ret, "Wait timed out.\n"); + } +} + +#define wait_stopped_callback(a) wait_stopped_callback_(__LINE__, a) +static void wait_stopped_callback_(int line, struct callback *callback) +{ + DWORD ret; + + ret = WaitForSingleObject(callback->got_stopped, 0); + todo_wine + ok_(__FILE__, line)(ret == WAIT_TIMEOUT, "Got unexpected WMT_STOPPED.\n"); + if (ret == WAIT_TIMEOUT) + { + SetEvent(callback->expect_stopped); + ret = WaitForSingleObject(callback->got_stopped, 1000); + ok_(__FILE__, line)(!ret, "Wait timed out.\n"); + } +} + +#define wait_eof_callback(a) wait_eof_callback_(__LINE__, a) +static void wait_eof_callback_(int line, struct callback *callback) +{ + DWORD ret; + + ret = WaitForSingleObject(callback->got_eof, 0); + ok_(__FILE__, line)(ret == WAIT_TIMEOUT, "Got unexpected WMT_EOF.\n"); + SetEvent(callback->expect_eof); + ret = WaitForSingleObject(callback->got_eof, 1000); + ok_(__FILE__, line)(!ret, "Wait timed out.\n"); + ok_(__FILE__, line)(callback->eof_count == 1, "Got %u WMT_EOF callbacks.\n", callback->eof_count); +} + static void run_async_reader(IWMReader *reader, IWMReaderAdvanced2 *advanced, struct callback *callback) { HRESULT hr; - DWORD ret;
- callback->got_closed = 0; - callback->got_started = 0; - callback->got_sample = 0; - callback->got_end_of_streaming = 0; - callback->got_eof = 0; + callback->closed_count = 0; + callback->started_count = 0; + callback->sample_count = 0; + callback->end_of_streaming_count = 0; + callback->eof_count = 0;
hr = IWMReader_Start(reader, 0, 0, 1.0f, (void *)0xfacade); ok(hr == S_OK, "Got hr %#lx.\n", hr);
+ /* When all streams are disabled we may get an EOF callback right + * after the first Start, or after the second if it took a bit more + * time to be processed. This is unpredictable so skip the test + */ + if (!callback->all_streams_off) + { + hr = IWMReader_Start(reader, 0, 0, 1.0f, (void *)0xfacade); + ok(hr == S_OK, "Got hr %#lx.\n", hr); + wait_started_callback(callback); + } + + if (callback->all_streams_off || strcmp(winetest_platform, "wine")) + wait_started_callback(callback); + hr = IWMReaderAdvanced2_SetUserProvidedClock(advanced, TRUE); ok(hr == S_OK, "Got hr %#lx.\n", hr); hr = IWMReaderAdvanced2_DeliverTime(advanced, 3000 * 10000); ok(hr == S_OK, "Got hr %#lx.\n", hr);
- ret = WaitForSingleObject(callback->eof_event, 1000); - ok(!ret, "Wait timed out.\n"); - ok(callback->got_eof == 1, "Got %u WMT_EOF callbacks.\n", callback->got_eof); + wait_eof_callback(callback);
hr = IWMReader_Stop(reader); ok(hr == S_OK, "Got hr %#lx.\n", hr); - ret = WaitForSingleObject(callback->got_stopped, 1000); - ok(!ret, "Wait timed out.\n"); + hr = IWMReader_Stop(reader); + ok(hr == S_OK, "Got hr %#lx.\n", hr); + wait_stopped_callback(callback); + if (strcmp(winetest_platform, "wine")) + wait_stopped_callback(callback);
ok(!outstanding_buffers, "Got %ld outstanding buffers.\n", outstanding_buffers); } @@ -2178,8 +2281,7 @@ static void test_async_reader_streaming(void) ok(hr == S_OK, "Got hr %#lx.\n", hr); ok(stream.refcount > 1, "Got refcount %ld.\n", stream.refcount); ok(callback.refcount > 1, "Got refcount %ld.\n", callback.refcount); - ret = WaitForSingleObject(callback.got_opened, 1000); - ok(!ret, "Wait timed out.\n"); + wait_opened_callback(&callback);
hr = IWMReaderAdvanced2_OpenStream(advanced, &stream.IStream_iface, &callback.IWMReaderCallback_iface, (void **)0xdeadbee0); ok(hr == E_UNEXPECTED, "Got hr %#lx.\n", hr); @@ -2205,6 +2307,7 @@ static void test_async_reader_streaming(void)
hr = IWMReader_Start(reader, 0, 0, 1.0f, (void *)0xfacade); ok(hr == S_OK, "Got hr %#lx.\n", hr); + wait_started_callback(&callback);
/* By default the reader will time itself, and attempt to deliver samples * according to their presentation time. Call DeliverTime with the file @@ -2226,32 +2329,28 @@ static void test_async_reader_streaming(void) callback.expect_ontime = 3000 * 10000; hr = IWMReaderAdvanced2_DeliverTime(advanced, 3000 * 10000); ok(hr == S_OK, "Got hr %#lx.\n", hr); - ret = WaitForSingleObject(callback.ontime_event, 1000); - ok(!ret, "Wait timed out.\n");
- ret = WaitForSingleObject(callback.eof_event, 1000); + wait_eof_callback(&callback); + + ret = WaitForSingleObject(callback.ontime_event, 1000); ok(!ret, "Wait timed out.\n"); - ok(callback.got_eof == 1, "Got %u WMT_EOF callbacks.\n", callback.got_eof);
hr = IWMReader_Start(reader, 0, 0, 1.0f, (void *)0xfacade); ok(hr == S_OK, "Got hr %#lx.\n", hr); + wait_started_callback(&callback);
hr = IWMReaderAdvanced2_DeliverTime(advanced, 3000 * 10000); ok(hr == S_OK, "Got hr %#lx.\n", hr);
- ret = WaitForSingleObject(callback.eof_event, 1000); - ok(!ret, "Wait timed out.\n"); - ok(callback.got_eof == 1, "Got %u WMT_EOF callbacks.\n", callback.got_eof); + wait_eof_callback(&callback);
hr = IWMReader_Stop(reader); ok(hr == S_OK, "Got hr %#lx.\n", hr); - ret = WaitForSingleObject(callback.got_stopped, 1000); - ok(!ret, "Wait timed out.\n"); + wait_stopped_callback(&callback);
hr = IWMReader_Stop(reader); ok(hr == S_OK, "Got hr %#lx.\n", hr); - ret = WaitForSingleObject(callback.got_stopped, 1000); - ok(!ret, "Wait timed out.\n"); + wait_stopped_callback(&callback);
test_reader_attributes(profile); test_async_reader_selection(reader, advanced, &callback); @@ -2261,8 +2360,10 @@ static void test_async_reader_streaming(void)
hr = IWMReader_Close(reader); ok(hr == S_OK, "Got hr %#lx.\n", hr); - ok(callback.got_closed == 1, "Got %u WMT_CLOSED callbacks.\n", callback.got_closed); + ok(callback.closed_count == 1, "Got %u WMT_CLOSED callbacks.\n", callback.closed_count); ok(callback.refcount == 1, "Got outstanding refcount %ld.\n", callback.refcount); + ret = WaitForSingleObject(callback.got_stopped, 0); + ok(ret == WAIT_TIMEOUT, "Got unexpected WMT_STOPPED.\n"); callback_cleanup(&callback);
hr = IWMReader_Stop(reader); @@ -2318,8 +2419,7 @@ static void test_async_reader_types(void) ok(hr == S_OK, "Got hr %#lx.\n", hr); ok(stream.refcount > 1, "Got refcount %ld.\n", stream.refcount); ok(callback.refcount > 1, "Got refcount %ld.\n", callback.refcount); - ret = WaitForSingleObject(callback.got_opened, 1000); - ok(!ret, "Wait timed out.\n"); + wait_opened_callback(&callback);
for (i = 0; i < 2; ++i) { @@ -2541,8 +2641,7 @@ static void test_async_reader_file(void) hr = IWMReader_Open(reader, filename, &callback.IWMReaderCallback_iface, (void **)0xdeadbeef); ok(hr == S_OK, "Got hr %#lx.\n", hr); ok(callback.refcount > 1, "Got refcount %ld.\n", callback.refcount); - ret = WaitForSingleObject(callback.got_opened, 1000); - ok(!ret, "Wait timed out.\n"); + wait_opened_callback(&callback);
hr = IWMReader_Open(reader, filename, &callback.IWMReaderCallback_iface, (void **)0xdeadbee0); ok(hr == E_UNEXPECTED, "Got hr %#lx.\n", hr); @@ -2554,11 +2653,14 @@ static void test_async_reader_file(void)
hr = IWMReader_Start(reader, 0, 0, 1.0f, (void *)0xfacade); ok(hr == S_OK, "Got hr %#lx.\n", hr); + wait_started_callback(&callback);
hr = IWMReader_Close(reader); ok(hr == S_OK, "Got hr %#lx.\n", hr); - ok(callback.got_closed == 1, "Got %u WMT_CLOSED callbacks.\n", callback.got_closed); + ok(callback.closed_count == 1, "Got %u WMT_CLOSED callbacks.\n", callback.closed_count); ok(callback.refcount == 1, "Got outstanding refcount %ld.\n", callback.refcount); + ret = WaitForSingleObject(callback.got_stopped, 0); + ok(ret == WAIT_TIMEOUT, "Got unexpected WMT_STOPPED.\n"); callback_cleanup(&callback);
hr = IWMReader_Close(reader); @@ -2566,7 +2668,7 @@ static void test_async_reader_file(void)
ref = IWMReader_Release(reader); ok(!ref, "Got outstanding refcount %ld.\n", ref); - ok(callback.got_closed == 1, "Got %u WMT_CLOSED callbacks.\n", callback.got_closed); + ok(callback.closed_count == 1, "Got %u WMT_CLOSED callbacks.\n", callback.closed_count); ok(callback.refcount == 1, "Got outstanding refcount %ld.\n", callback.refcount); callback_cleanup(&callback);
From: R��mi Bernon rbernon@codeweavers.com
--- dlls/winegstreamer/gst_private.h | 4 +--- dlls/winegstreamer/wm_asyncreader.c | 27 +++++++++++++++------------ dlls/winegstreamer/wm_reader.c | 7 +------ dlls/winegstreamer/wm_syncreader.c | 2 +- 4 files changed, 18 insertions(+), 22 deletions(-)
diff --git a/dlls/winegstreamer/gst_private.h b/dlls/winegstreamer/gst_private.h index 8348d2e8360..2c3039acbe9 100644 --- a/dlls/winegstreamer/gst_private.h +++ b/dlls/winegstreamer/gst_private.h @@ -180,8 +180,6 @@ struct wm_reader struct wm_stream *streams; WORD stream_count;
- IWMReaderCallbackAdvanced *callback_advanced; - const struct wm_reader_ops *ops; };
@@ -201,7 +199,7 @@ HRESULT wm_reader_get_output_props(struct wm_reader *reader, DWORD output, IWMOutputMediaProps **props); struct wm_stream *wm_reader_get_stream_by_stream_number(struct wm_reader *reader, WORD stream_number); -HRESULT wm_reader_get_stream_sample(struct wm_reader *reader, WORD stream_number, +HRESULT wm_reader_get_stream_sample(struct wm_reader *reader, IWMReaderCallbackAdvanced *callback_advanced, WORD stream_number, INSSBuffer **ret_sample, QWORD *pts, QWORD *duration, DWORD *flags, WORD *ret_stream_number); HRESULT wm_reader_get_stream_selection(struct wm_reader *reader, WORD stream_number, WMT_STREAM_SELECTION *selection); diff --git a/dlls/winegstreamer/wm_asyncreader.c b/dlls/winegstreamer/wm_asyncreader.c index ef6e445a51b..9d8c2be45cb 100644 --- a/dlls/winegstreamer/wm_asyncreader.c +++ b/dlls/winegstreamer/wm_asyncreader.c @@ -57,22 +57,17 @@ static REFERENCE_TIME get_current_time(const struct async_reader *reader) static void open_stream(struct async_reader *reader, IWMReaderCallback *callback, void *context) { static const DWORD zero; - HRESULT hr;
IWMReaderCallback_AddRef(reader->callback = callback); reader->context = context; IWMReaderCallback_OnStatus(callback, WMT_OPENED, S_OK, WMT_TYPE_DWORD, (BYTE *)&zero, context); - - if (FAILED(hr = IWMReaderCallback_QueryInterface(callback, - &IID_IWMReaderCallbackAdvanced, (void **)&reader->reader.callback_advanced))) - reader->reader.callback_advanced = NULL; - TRACE("Querying for IWMReaderCallbackAdvanced returned %#lx.\n", hr); }
static DWORD WINAPI stream_thread(void *arg) { struct async_reader *reader = arg; IWMReaderCallback *callback = reader->callback; + IWMReaderCallbackAdvanced *callback_advanced; REFERENCE_TIME start_time; struct wm_stream *stream; static const DWORD zero; @@ -86,9 +81,14 @@ static DWORD WINAPI stream_thread(void *arg)
EnterCriticalSection(&reader->stream_cs);
+ if (FAILED(hr = IWMReaderCallback_QueryInterface(callback, + &IID_IWMReaderCallbackAdvanced, (void **)&callback_advanced))) + callback_advanced = NULL; + TRACE("Querying for IWMReaderCallbackAdvanced returned %#lx.\n", hr); + while (reader->running) { - hr = wm_reader_get_stream_sample(&reader->reader, 0, &sample, &pts, &duration, &flags, &stream_number); + hr = wm_reader_get_stream_sample(&reader->reader, callback_advanced, 0, &sample, &pts, &duration, &flags, &stream_number); if (hr != S_OK) break;
@@ -98,10 +98,10 @@ static DWORD WINAPI stream_thread(void *arg) { QWORD user_time = reader->user_time;
- if (pts > user_time && reader->reader.callback_advanced) + if (pts > user_time && callback_advanced) { LeaveCriticalSection(&reader->stream_cs); - IWMReaderCallbackAdvanced_OnTime(reader->reader.callback_advanced, user_time, reader->context); + IWMReaderCallbackAdvanced_OnTime(callback_advanced, user_time, reader->context); EnterCriticalSection(&reader->stream_cs); }
@@ -126,7 +126,7 @@ static DWORD WINAPI stream_thread(void *arg) { LeaveCriticalSection(&reader->stream_cs); if (stream->read_compressed) - hr = IWMReaderCallbackAdvanced_OnStreamSample(reader->reader.callback_advanced, + hr = IWMReaderCallbackAdvanced_OnStreamSample(callback_advanced, stream_number, pts, duration, flags, sample, reader->context); else hr = IWMReaderCallback_OnSample(callback, stream_number - 1, pts, duration, @@ -148,12 +148,12 @@ static DWORD WINAPI stream_thread(void *arg) IWMReaderCallback_OnStatus(callback, WMT_EOF, S_OK, WMT_TYPE_DWORD, (BYTE *)&zero, reader->context);
- if (reader->user_clock && reader->reader.callback_advanced) + if (reader->user_clock && callback_advanced) { /* We can only get here if user_time is greater than the PTS * of all samples, in which case we cannot have sent this * notification already. */ - IWMReaderCallbackAdvanced_OnTime(reader->reader.callback_advanced, + IWMReaderCallbackAdvanced_OnTime(callback_advanced, reader->user_time, reader->context); }
@@ -164,6 +164,9 @@ static DWORD WINAPI stream_thread(void *arg) ERR("Failed to get sample, hr %#lx.\n", hr); }
+ if (callback_advanced) + IWMReaderCallbackAdvanced_Release(callback_advanced); + TRACE("Reader is stopping; exiting.\n"); return 0; } diff --git a/dlls/winegstreamer/wm_reader.c b/dlls/winegstreamer/wm_reader.c index 03adea8a318..8038b61f7a7 100644 --- a/dlls/winegstreamer/wm_reader.c +++ b/dlls/winegstreamer/wm_reader.c @@ -1607,10 +1607,6 @@ HRESULT wm_reader_close(struct wm_reader *reader) CloseHandle(reader->read_thread); reader->read_thread = NULL;
- if (reader->callback_advanced) - IWMReaderCallbackAdvanced_Release(reader->callback_advanced); - reader->callback_advanced = NULL; - wg_parser_destroy(reader->wg_parser); reader->wg_parser = NULL;
@@ -1871,10 +1867,9 @@ static WORD get_earliest_buffer(struct wm_reader *reader, struct wg_parser_buffe return stream_number; }
-HRESULT wm_reader_get_stream_sample(struct wm_reader *reader, WORD stream_number, +HRESULT wm_reader_get_stream_sample(struct wm_reader *reader, IWMReaderCallbackAdvanced *callback_advanced, WORD stream_number, INSSBuffer **ret_sample, QWORD *pts, QWORD *duration, DWORD *flags, WORD *ret_stream_number) { - IWMReaderCallbackAdvanced *callback_advanced = reader->callback_advanced; struct wg_parser_stream *wg_stream; struct wg_parser_buffer wg_buffer; struct wm_stream *stream; diff --git a/dlls/winegstreamer/wm_syncreader.c b/dlls/winegstreamer/wm_syncreader.c index c7cccd52c4f..c80574b87fd 100644 --- a/dlls/winegstreamer/wm_syncreader.c +++ b/dlls/winegstreamer/wm_syncreader.c @@ -92,7 +92,7 @@ static HRESULT WINAPI WMSyncReader_GetNextSample(IWMSyncReader2 *iface,
EnterCriticalSection(&reader->reader.cs);
- hr = wm_reader_get_stream_sample(&reader->reader, stream_number, sample, pts, duration, flags, &stream_number); + hr = wm_reader_get_stream_sample(&reader->reader, NULL, stream_number, sample, pts, duration, flags, &stream_number); if (output_number && hr == S_OK) *output_number = stream_number - 1; if (ret_stream_number && (hr == S_OK || stream_number))
From: R��mi Bernon rbernon@codeweavers.com
This may call AllocateForOutput/Stream callbacks, and it may block. --- dlls/winegstreamer/wm_asyncreader.c | 2 ++ 1 file changed, 2 insertions(+)
diff --git a/dlls/winegstreamer/wm_asyncreader.c b/dlls/winegstreamer/wm_asyncreader.c index 9d8c2be45cb..a4dc077d341 100644 --- a/dlls/winegstreamer/wm_asyncreader.c +++ b/dlls/winegstreamer/wm_asyncreader.c @@ -88,7 +88,9 @@ static DWORD WINAPI stream_thread(void *arg)
while (reader->running) { + LeaveCriticalSection(&reader->stream_cs); hr = wm_reader_get_stream_sample(&reader->reader, callback_advanced, 0, &sample, &pts, &duration, &flags, &stream_number); + EnterCriticalSection(&reader->stream_cs); if (hr != S_OK) break;
From: R��mi Bernon rbernon@codeweavers.com
--- dlls/winegstreamer/wm_asyncreader.c | 248 +++++++++++++++++++--------- dlls/wmvcore/tests/wmvcore.c | 40 ++--- 2 files changed, 178 insertions(+), 110 deletions(-)
diff --git a/dlls/winegstreamer/wm_asyncreader.c b/dlls/winegstreamer/wm_asyncreader.c index a4dc077d341..be9f881b9c2 100644 --- a/dlls/winegstreamer/wm_asyncreader.c +++ b/dlls/winegstreamer/wm_asyncreader.c @@ -18,8 +18,22 @@
#include "gst_private.h"
+#include "wine/list.h" + WINE_DEFAULT_DEBUG_CHANNEL(wmvcore);
+struct async_op +{ + enum async_op_type + { + ASYNC_OP_START, + ASYNC_OP_STOP, + ASYNC_OP_CLOSE, + } type; + void *new_context; + struct list entry; +}; + struct async_reader { struct wm_reader reader; @@ -41,6 +55,7 @@ struct async_reader CONDITION_VARIABLE stream_cv;
bool running; + struct list async_ops;
bool user_clock; QWORD user_time; @@ -54,20 +69,9 @@ static REFERENCE_TIME get_current_time(const struct async_reader *reader) return (time.QuadPart * 1000) / reader->clock_frequency.QuadPart * 10000; }
-static void open_stream(struct async_reader *reader, IWMReaderCallback *callback, void *context) -{ - static const DWORD zero; - - IWMReaderCallback_AddRef(reader->callback = callback); - reader->context = context; - IWMReaderCallback_OnStatus(callback, WMT_OPENED, S_OK, WMT_TYPE_DWORD, (BYTE *)&zero, context); -} - -static DWORD WINAPI stream_thread(void *arg) +static void stream_thread_running(struct async_reader *reader, IWMReaderCallbackAdvanced *callback_advanced) { - struct async_reader *reader = arg; IWMReaderCallback *callback = reader->callback; - IWMReaderCallbackAdvanced *callback_advanced; REFERENCE_TIME start_time; struct wm_stream *stream; static const DWORD zero; @@ -79,14 +83,7 @@ static DWORD WINAPI stream_thread(void *arg)
start_time = get_current_time(reader);
- EnterCriticalSection(&reader->stream_cs); - - if (FAILED(hr = IWMReaderCallback_QueryInterface(callback, - &IID_IWMReaderCallbackAdvanced, (void **)&callback_advanced))) - callback_advanced = NULL; - TRACE("Querying for IWMReaderCallbackAdvanced returned %#lx.\n", hr); - - while (reader->running) + while (reader->running && list_empty(&reader->async_ops)) { LeaveCriticalSection(&reader->stream_cs); hr = wm_reader_get_stream_sample(&reader->reader, callback_advanced, 0, &sample, &pts, &duration, &flags, &stream_number); @@ -107,12 +104,12 @@ static DWORD WINAPI stream_thread(void *arg) EnterCriticalSection(&reader->stream_cs); }
- while (pts > reader->user_time && reader->running) + while (pts > reader->user_time && reader->running && list_empty(&reader->async_ops)) SleepConditionVariableCS(&reader->stream_cv, &reader->stream_cs, INFINITE); } else { - while (reader->running) + while (reader->running && list_empty(&reader->async_ops)) { REFERENCE_TIME current_time = get_current_time(reader);
@@ -124,7 +121,7 @@ static DWORD WINAPI stream_thread(void *arg) } }
- if (reader->running) + if (reader->running && list_empty(&reader->async_ops)) { LeaveCriticalSection(&reader->stream_cs); if (stream->read_compressed) @@ -141,52 +138,161 @@ static DWORD WINAPI stream_thread(void *arg) INSSBuffer_Release(sample); }
- LeaveCriticalSection(&reader->stream_cs); - if (hr == NS_E_NO_MORE_SAMPLES) { + BOOL user_clock = reader->user_clock; + QWORD user_time = reader->user_time; + + LeaveCriticalSection(&reader->stream_cs); + IWMReaderCallback_OnStatus(callback, WMT_END_OF_STREAMING, S_OK, WMT_TYPE_DWORD, (BYTE *)&zero, reader->context); IWMReaderCallback_OnStatus(callback, WMT_EOF, S_OK, WMT_TYPE_DWORD, (BYTE *)&zero, reader->context);
- if (reader->user_clock && callback_advanced) + if (user_clock && callback_advanced) { /* We can only get here if user_time is greater than the PTS * of all samples, in which case we cannot have sent this * notification already. */ IWMReaderCallbackAdvanced_OnTime(callback_advanced, - reader->user_time, reader->context); + user_time, reader->context); }
+ EnterCriticalSection(&reader->stream_cs); + TRACE("Reached end of stream; exiting.\n"); } else if (hr != S_OK) { ERR("Failed to get sample, hr %#lx.\n", hr); } +} + +static DWORD WINAPI stream_thread(void *arg) +{ + struct async_reader *reader = arg; + IWMReaderCallback *callback = reader->callback; + IWMReaderCallbackAdvanced *callback_advanced; + static const DWORD zero; + struct list *entry; + HRESULT hr = S_OK; + + if (FAILED(hr = IWMReaderCallback_QueryInterface(callback, + &IID_IWMReaderCallbackAdvanced, (void **)&callback_advanced))) + callback_advanced = NULL; + TRACE("Querying for IWMReaderCallbackAdvanced returned %#lx.\n", hr); + + IWMReaderCallback_OnStatus(reader->callback, WMT_OPENED, S_OK, + WMT_TYPE_DWORD, (BYTE *)&zero, reader->context); + + EnterCriticalSection(&reader->stream_cs); + + while (reader->running) + { + if ((entry = list_head(&reader->async_ops))) + { + struct async_op *op = LIST_ENTRY(entry, struct async_op, entry); + list_remove(&op->entry); + + if (op->new_context) + reader->context = op->new_context; + hr = list_empty(&reader->async_ops) ? S_OK : E_ABORT; + switch (op->type) + { + case ASYNC_OP_START: + { + LeaveCriticalSection(&reader->stream_cs); + IWMReaderCallback_OnStatus(reader->callback, WMT_STARTED, hr, + WMT_TYPE_DWORD, (BYTE *)&zero, reader->context); + EnterCriticalSection(&reader->stream_cs); + + if (SUCCEEDED(hr)) + stream_thread_running(reader, callback_advanced); + break; + } + + case ASYNC_OP_STOP: + LeaveCriticalSection(&reader->stream_cs); + IWMReaderCallback_OnStatus(reader->callback, WMT_STOPPED, hr, + WMT_TYPE_DWORD, (BYTE *)&zero, reader->context); + EnterCriticalSection(&reader->stream_cs); + break; + + case ASYNC_OP_CLOSE: + LeaveCriticalSection(&reader->stream_cs); + IWMReaderCallback_OnStatus(reader->callback, WMT_CLOSED, hr, + WMT_TYPE_DWORD, (BYTE *)&zero, reader->context); + EnterCriticalSection(&reader->stream_cs); + + if (SUCCEEDED(hr)) + reader->running = false; + break; + } + + free(op); + } + + if (reader->running && list_empty(&reader->async_ops)) + SleepConditionVariableCS(&reader->stream_cv, &reader->stream_cs, INFINITE); + }
if (callback_advanced) IWMReaderCallbackAdvanced_Release(callback_advanced);
+ LeaveCriticalSection(&reader->stream_cs); + TRACE("Reader is stopping; exiting.\n"); return 0; }
-static void stop_streaming(struct async_reader *reader) +static HRESULT open_stream(struct async_reader *reader, IWMReaderCallback *callback, void *context) { - if (reader->stream_thread) + IWMReaderCallback_AddRef((reader->callback = callback)); + reader->context = context; + + reader->running = true; + if (!(reader->stream_thread = CreateThread(NULL, 0, stream_thread, reader, 0, NULL))) { - EnterCriticalSection(&reader->stream_cs); + IWMReaderCallback_Release(reader->callback); reader->running = false; - LeaveCriticalSection(&reader->stream_cs); - WakeConditionVariable(&reader->stream_cv); + reader->callback = NULL; + reader->context = NULL; + return E_OUTOFMEMORY; + } + + return S_OK; +} + +static void close_stream(struct async_reader *reader) +{ + if (reader->stream_thread) + { WaitForSingleObject(reader->stream_thread, INFINITE); CloseHandle(reader->stream_thread); reader->stream_thread = NULL; } }
+static HRESULT async_reader_queue_op(struct async_reader *reader, enum async_op_type type, void *context) +{ + struct async_op *op; + + EnterCriticalSection(&reader->stream_cs); + + if (!(op = calloc(1, sizeof(*op)))) + return E_OUTOFMEMORY; + op->type = type; + op->new_context = context; + + list_add_tail(&reader->async_ops, &op->entry); + + LeaveCriticalSection(&reader->stream_cs); + WakeConditionVariable(&reader->stream_cv); + + return S_OK; +} + static struct async_reader *impl_from_IWMReader(IWMReader *iface) { return CONTAINING_RECORD(iface, struct async_reader, IWMReader_iface); @@ -231,8 +337,9 @@ static HRESULT WINAPI WMReader_Open(IWMReader *iface, const WCHAR *url, return E_UNEXPECTED; }
- if (SUCCEEDED(hr = wm_reader_open_file(&reader->reader, url))) - open_stream(reader, callback, context); + if (SUCCEEDED(hr = wm_reader_open_file(&reader->reader, url)) + && FAILED(hr = open_stream(reader, callback, context))) + wm_reader_close(&reader->reader);
LeaveCriticalSection(&reader->reader.cs); return hr; @@ -241,22 +348,18 @@ static HRESULT WINAPI WMReader_Open(IWMReader *iface, const WCHAR *url, static HRESULT WINAPI WMReader_Close(IWMReader *iface) { struct async_reader *reader = impl_from_IWMReader(iface); - static const DWORD zero; HRESULT hr;
TRACE("reader %p.\n", reader);
EnterCriticalSection(&reader->reader.cs);
- stop_streaming(reader); + async_reader_queue_op(reader, ASYNC_OP_CLOSE, NULL); + close_stream(reader);
hr = wm_reader_close(&reader->reader); if (reader->callback) - { - IWMReaderCallback_OnStatus(reader->callback, WMT_CLOSED, S_OK, - WMT_TYPE_DWORD, (BYTE *)&zero, reader->context); IWMReaderCallback_Release(reader->callback); - } reader->callback = NULL;
LeaveCriticalSection(&reader->reader.cs); @@ -317,7 +420,7 @@ static HRESULT WINAPI WMReader_Start(IWMReader *iface, QWORD start, QWORD duration, float rate, void *context) { struct async_reader *reader = impl_from_IWMReader(iface); - static const DWORD zero; + HRESULT hr;
TRACE("reader %p, start %s, duration %s, rate %.8e, context %p.\n", reader, debugstr_time(start), debugstr_time(duration), rate, context); @@ -327,56 +430,36 @@ static HRESULT WINAPI WMReader_Start(IWMReader *iface,
EnterCriticalSection(&reader->reader.cs);
- if (!reader->reader.wg_parser) - { - LeaveCriticalSection(&reader->reader.cs); - WARN("No stream is open; returning NS_E_INVALID_REQUEST.\n"); - return NS_E_INVALID_REQUEST; - } - - stop_streaming(reader); - - IWMReaderCallback_OnStatus(reader->callback, WMT_STARTED, S_OK, WMT_TYPE_DWORD, (BYTE *)&zero, context); - reader->context = context; - - wm_reader_seek(&reader->reader, start, duration); - - reader->running = true; - reader->user_time = 0; - - if (!(reader->stream_thread = CreateThread(NULL, 0, stream_thread, reader, 0, NULL))) + if (!reader->stream_thread) + hr = NS_E_INVALID_REQUEST; + else { - LeaveCriticalSection(&reader->reader.cs); - return E_OUTOFMEMORY; + wm_reader_seek(&reader->reader, start, duration); + hr = async_reader_queue_op(reader, ASYNC_OP_START, context); }
LeaveCriticalSection(&reader->reader.cs); - WakeConditionVariable(&reader->stream_cv);
- return S_OK; + return hr; }
static HRESULT WINAPI WMReader_Stop(IWMReader *iface) { struct async_reader *reader = impl_from_IWMReader(iface); - static const DWORD zero; + HRESULT hr;
TRACE("reader %p.\n", reader);
EnterCriticalSection(&reader->reader.cs);
- if (!reader->reader.wg_parser) - { - LeaveCriticalSection(&reader->reader.cs); - WARN("No stream is open; returning E_UNEXPECTED.\n"); - return E_UNEXPECTED; - } + if (!reader->stream_thread) + hr = E_UNEXPECTED; + else + hr = async_reader_queue_op(reader, ASYNC_OP_STOP, NULL);
- stop_streaming(reader); - IWMReaderCallback_OnStatus(reader->callback, WMT_STOPPED, S_OK, - WMT_TYPE_DWORD, (BYTE *)&zero, reader->context); LeaveCriticalSection(&reader->reader.cs); - return S_OK; + + return hr; }
static HRESULT WINAPI WMReader_Pause(IWMReader *iface) @@ -734,8 +817,9 @@ static HRESULT WINAPI WMReaderAdvanced2_OpenStream(IWMReaderAdvanced6 *iface, return E_UNEXPECTED; }
- if (SUCCEEDED(hr = wm_reader_open_stream(&reader->reader, stream))) - open_stream(reader, callback, context); + if (SUCCEEDED(hr = wm_reader_open_stream(&reader->reader, stream)) + && FAILED(hr = open_stream(reader, callback, context))) + wm_reader_close(&reader->reader);
LeaveCriticalSection(&reader->reader.cs); return hr; @@ -1590,11 +1674,12 @@ static void async_reader_destroy(struct wm_reader *iface)
TRACE("reader %p.\n", reader);
- if (reader->stream_thread) - { - WaitForSingleObject(reader->stream_thread, INFINITE); - CloseHandle(reader->stream_thread); - } + EnterCriticalSection(&reader->stream_cs); + reader->running = false; + LeaveCriticalSection(&reader->stream_cs); + WakeConditionVariable(&reader->stream_cv); + + close_stream(reader);
reader->stream_cs.DebugInfo->Spare[0] = 0; DeleteCriticalSection(&reader->stream_cs); @@ -1637,6 +1722,7 @@ HRESULT WINAPI winegstreamer_create_wm_async_reader(IWMReader **reader) object->stream_cs.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": async_reader.stream_cs");
QueryPerformanceFrequency(&object->clock_frequency); + list_init(&object->async_ops);
TRACE("Created async reader %p.\n", object); *reader = (IWMReader *)&object->IWMReader_iface; diff --git a/dlls/wmvcore/tests/wmvcore.c b/dlls/wmvcore/tests/wmvcore.c index ee2e685bc0a..fa58caeae35 100644 --- a/dlls/wmvcore/tests/wmvcore.c +++ b/dlls/wmvcore/tests/wmvcore.c @@ -1496,7 +1496,6 @@ static HRESULT WINAPI callback_OnStatus(IWMReaderCallback *iface, WMT_STATUS sta ok(!*(DWORD *)value, "Got value %#lx.\n", *(DWORD *)value); ok(context == (void *)0xdeadbeef, "Got unexpected context %p.\n", context); ret = WaitForSingleObject(callback->expect_opened, 100); - todo_wine ok(!ret, "Wait timed out.\n"); SetEvent(callback->got_opened); break; @@ -1506,7 +1505,6 @@ static HRESULT WINAPI callback_OnStatus(IWMReaderCallback *iface, WMT_STATUS sta ok(!*(DWORD *)value, "Got value %#lx.\n", *(DWORD *)value); ok(context == (void *)0xfacade, "Got unexpected context %p.\n", context); ret = WaitForSingleObject(callback->expect_started, 100); - todo_wine ok(!ret, "Wait timed out.\n"); callback->end_of_streaming_count = callback->eof_count = callback->sample_count = 0; ++callback->started_count; @@ -1519,7 +1517,6 @@ static HRESULT WINAPI callback_OnStatus(IWMReaderCallback *iface, WMT_STATUS sta ok(!*(DWORD *)value, "Got value %#lx.\n", *(DWORD *)value); ok(context == (void *)0xfacade, "Got unexpected context %p.\n", context); ret = WaitForSingleObject(callback->expect_stopped, 100); - todo_wine ok(!ret, "Wait timed out.\n"); SetEvent(callback->got_stopped); break; @@ -1698,7 +1695,6 @@ static HRESULT WINAPI callback_advanced_OnTime(IWMReaderCallbackAdvanced *iface, trace("%lu: %04lx: IWMReaderCallbackAdvanced::OnTime(time %I64u)\n", GetTickCount(), GetCurrentThreadId(), time);
- todo_wine_if(time == 0 && callback->expect_ontime) ok(time == callback->expect_ontime, "Got time %I64u.\n", time); ok(context == (void *)0xfacade, "Got unexpected context %p.\n", context); SetEvent(callback->ontime_event); @@ -1888,14 +1884,10 @@ static void wait_opened_callback_(int line, struct callback *callback) DWORD ret;
ret = WaitForSingleObject(callback->got_opened, 0); - todo_wine ok_(__FILE__, line)(ret == WAIT_TIMEOUT, "Got unexpected WMT_OPENED.\n"); - if (ret == WAIT_TIMEOUT) - { - SetEvent(callback->expect_opened); - ret = WaitForSingleObject(callback->got_opened, 1000); - ok_(__FILE__, line)(!ret, "Wait timed out.\n"); - } + SetEvent(callback->expect_opened); + ret = WaitForSingleObject(callback->got_opened, 1000); + ok_(__FILE__, line)(!ret, "Wait timed out.\n"); }
#define wait_started_callback(a) wait_started_callback_(__LINE__, a) @@ -1904,14 +1896,10 @@ static void wait_started_callback_(int line, struct callback *callback) DWORD ret;
ret = WaitForSingleObject(callback->got_started, 0); - todo_wine ok_(__FILE__, line)(ret == WAIT_TIMEOUT, "Got unexpected WMT_STARTED.\n"); - if (ret == WAIT_TIMEOUT) - { - SetEvent(callback->expect_started); - ret = WaitForSingleObject(callback->got_started, 1000); - ok_(__FILE__, line)(!ret, "Wait timed out.\n"); - } + SetEvent(callback->expect_started); + ret = WaitForSingleObject(callback->got_started, 1000); + ok_(__FILE__, line)(!ret, "Wait timed out.\n"); }
#define wait_stopped_callback(a) wait_stopped_callback_(__LINE__, a) @@ -1920,14 +1908,10 @@ static void wait_stopped_callback_(int line, struct callback *callback) DWORD ret;
ret = WaitForSingleObject(callback->got_stopped, 0); - todo_wine ok_(__FILE__, line)(ret == WAIT_TIMEOUT, "Got unexpected WMT_STOPPED.\n"); - if (ret == WAIT_TIMEOUT) - { - SetEvent(callback->expect_stopped); - ret = WaitForSingleObject(callback->got_stopped, 1000); - ok_(__FILE__, line)(!ret, "Wait timed out.\n"); - } + SetEvent(callback->expect_stopped); + ret = WaitForSingleObject(callback->got_stopped, 1000); + ok_(__FILE__, line)(!ret, "Wait timed out.\n"); }
#define wait_eof_callback(a) wait_eof_callback_(__LINE__, a) @@ -1967,8 +1951,7 @@ static void run_async_reader(IWMReader *reader, IWMReaderAdvanced2 *advanced, st wait_started_callback(callback); }
- if (callback->all_streams_off || strcmp(winetest_platform, "wine")) - wait_started_callback(callback); + wait_started_callback(callback);
hr = IWMReaderAdvanced2_SetUserProvidedClock(advanced, TRUE); ok(hr == S_OK, "Got hr %#lx.\n", hr); @@ -1982,8 +1965,7 @@ static void run_async_reader(IWMReader *reader, IWMReaderAdvanced2 *advanced, st hr = IWMReader_Stop(reader); ok(hr == S_OK, "Got hr %#lx.\n", hr); wait_stopped_callback(callback); - if (strcmp(winetest_platform, "wine")) - wait_stopped_callback(callback); + wait_stopped_callback(callback);
ok(!outstanding_buffers, "Got %ld outstanding buffers.\n", outstanding_buffers); }
This merge request was approved by Zebediah Figura.