This includes some fixes for obvious mistakes as well as initial cleanup of the WM async reader, in preparation for implementing proper threading support.
I'm planning on doing some more refactoring first, ultimately implementing the async reader on top of the sync reader, and removing the need for a private interface. I've checked that it can indeed work on Windows too, and it'll make the code simpler overall.
-- v2: winegstreamer: Query IWMReaderCallbackAdvanced interface in Open. winegstreamer: Avoid waiting for callback thread on allocation failure. winegstreamer: Release callback and context in async_reader_close. winegstreamer: Move open_stream / close_stream helpers around. winegstreamer: Leave async reader callback_cs on calloc error. winegstreamer: Leave WM reader CS on invalid output format. winegstreamer: Avoid leaking async ops on release or multiple close. winegstreamer: Rename async reader stream_thread to callback_thread.
From: R��mi Bernon rbernon@codeweavers.com
--- dlls/winegstreamer/wm_asyncreader.c | 97 +++++++++++++++-------------- 1 file changed, 49 insertions(+), 48 deletions(-)
diff --git a/dlls/winegstreamer/wm_asyncreader.c b/dlls/winegstreamer/wm_asyncreader.c index be9f881b9c2..92c6ba88392 100644 --- a/dlls/winegstreamer/wm_asyncreader.c +++ b/dlls/winegstreamer/wm_asyncreader.c @@ -50,9 +50,10 @@ struct async_reader void *context;
LARGE_INTEGER clock_frequency; - HANDLE stream_thread; - CRITICAL_SECTION stream_cs; - CONDITION_VARIABLE stream_cv; + + HANDLE callback_thread; + CRITICAL_SECTION callback_cs; + CONDITION_VARIABLE callback_cv;
bool running; struct list async_ops; @@ -69,7 +70,7 @@ static REFERENCE_TIME get_current_time(const struct async_reader *reader) return (time.QuadPart * 1000) / reader->clock_frequency.QuadPart * 10000; }
-static void stream_thread_running(struct async_reader *reader, IWMReaderCallbackAdvanced *callback_advanced) +static void callback_thread_run(struct async_reader *reader, IWMReaderCallbackAdvanced *callback_advanced) { IWMReaderCallback *callback = reader->callback; REFERENCE_TIME start_time; @@ -85,9 +86,9 @@ static void stream_thread_running(struct async_reader *reader, IWMReaderCallback
while (reader->running && list_empty(&reader->async_ops)) { - LeaveCriticalSection(&reader->stream_cs); + LeaveCriticalSection(&reader->callback_cs); hr = wm_reader_get_stream_sample(&reader->reader, callback_advanced, 0, &sample, &pts, &duration, &flags, &stream_number); - EnterCriticalSection(&reader->stream_cs); + EnterCriticalSection(&reader->callback_cs); if (hr != S_OK) break;
@@ -99,13 +100,13 @@ static void stream_thread_running(struct async_reader *reader, IWMReaderCallback
if (pts > user_time && callback_advanced) { - LeaveCriticalSection(&reader->stream_cs); + LeaveCriticalSection(&reader->callback_cs); IWMReaderCallbackAdvanced_OnTime(callback_advanced, user_time, reader->context); - EnterCriticalSection(&reader->stream_cs); + EnterCriticalSection(&reader->callback_cs); }
while (pts > reader->user_time && reader->running && list_empty(&reader->async_ops)) - SleepConditionVariableCS(&reader->stream_cv, &reader->stream_cs, INFINITE); + SleepConditionVariableCS(&reader->callback_cv, &reader->callback_cs, INFINITE); } else { @@ -116,21 +117,21 @@ static void stream_thread_running(struct async_reader *reader, IWMReaderCallback if (pts <= current_time - start_time) break;
- SleepConditionVariableCS(&reader->stream_cv, &reader->stream_cs, + SleepConditionVariableCS(&reader->callback_cv, &reader->callback_cs, (pts - (current_time - start_time)) / 10000); } }
if (reader->running && list_empty(&reader->async_ops)) { - LeaveCriticalSection(&reader->stream_cs); + LeaveCriticalSection(&reader->callback_cs); if (stream->read_compressed) hr = IWMReaderCallbackAdvanced_OnStreamSample(callback_advanced, stream_number, pts, duration, flags, sample, reader->context); else hr = IWMReaderCallback_OnSample(callback, stream_number - 1, pts, duration, flags, sample, reader->context); - EnterCriticalSection(&reader->stream_cs); + EnterCriticalSection(&reader->callback_cs);
TRACE("Callback returned %#lx.\n", hr); } @@ -143,7 +144,7 @@ static void stream_thread_running(struct async_reader *reader, IWMReaderCallback BOOL user_clock = reader->user_clock; QWORD user_time = reader->user_time;
- LeaveCriticalSection(&reader->stream_cs); + LeaveCriticalSection(&reader->callback_cs);
IWMReaderCallback_OnStatus(callback, WMT_END_OF_STREAMING, S_OK, WMT_TYPE_DWORD, (BYTE *)&zero, reader->context); @@ -159,7 +160,7 @@ static void stream_thread_running(struct async_reader *reader, IWMReaderCallback user_time, reader->context); }
- EnterCriticalSection(&reader->stream_cs); + EnterCriticalSection(&reader->callback_cs);
TRACE("Reached end of stream; exiting.\n"); } @@ -169,7 +170,7 @@ static void stream_thread_running(struct async_reader *reader, IWMReaderCallback } }
-static DWORD WINAPI stream_thread(void *arg) +static DWORD WINAPI async_reader_callback_thread(void *arg) { struct async_reader *reader = arg; IWMReaderCallback *callback = reader->callback; @@ -186,7 +187,7 @@ static DWORD WINAPI stream_thread(void *arg) IWMReaderCallback_OnStatus(reader->callback, WMT_OPENED, S_OK, WMT_TYPE_DWORD, (BYTE *)&zero, reader->context);
- EnterCriticalSection(&reader->stream_cs); + EnterCriticalSection(&reader->callback_cs);
while (reader->running) { @@ -202,28 +203,28 @@ static DWORD WINAPI stream_thread(void *arg) { case ASYNC_OP_START: { - LeaveCriticalSection(&reader->stream_cs); + LeaveCriticalSection(&reader->callback_cs); IWMReaderCallback_OnStatus(reader->callback, WMT_STARTED, hr, WMT_TYPE_DWORD, (BYTE *)&zero, reader->context); - EnterCriticalSection(&reader->stream_cs); + EnterCriticalSection(&reader->callback_cs);
if (SUCCEEDED(hr)) - stream_thread_running(reader, callback_advanced); + callback_thread_run(reader, callback_advanced); break; }
case ASYNC_OP_STOP: - LeaveCriticalSection(&reader->stream_cs); + LeaveCriticalSection(&reader->callback_cs); IWMReaderCallback_OnStatus(reader->callback, WMT_STOPPED, hr, WMT_TYPE_DWORD, (BYTE *)&zero, reader->context); - EnterCriticalSection(&reader->stream_cs); + EnterCriticalSection(&reader->callback_cs); break;
case ASYNC_OP_CLOSE: - LeaveCriticalSection(&reader->stream_cs); + LeaveCriticalSection(&reader->callback_cs); IWMReaderCallback_OnStatus(reader->callback, WMT_CLOSED, hr, WMT_TYPE_DWORD, (BYTE *)&zero, reader->context); - EnterCriticalSection(&reader->stream_cs); + EnterCriticalSection(&reader->callback_cs);
if (SUCCEEDED(hr)) reader->running = false; @@ -234,13 +235,13 @@ static DWORD WINAPI stream_thread(void *arg) }
if (reader->running && list_empty(&reader->async_ops)) - SleepConditionVariableCS(&reader->stream_cv, &reader->stream_cs, INFINITE); + SleepConditionVariableCS(&reader->callback_cv, &reader->callback_cs, INFINITE); }
if (callback_advanced) IWMReaderCallbackAdvanced_Release(callback_advanced);
- LeaveCriticalSection(&reader->stream_cs); + LeaveCriticalSection(&reader->callback_cs);
TRACE("Reader is stopping; exiting.\n"); return 0; @@ -252,7 +253,7 @@ static HRESULT open_stream(struct async_reader *reader, IWMReaderCallback *callb reader->context = context;
reader->running = true; - if (!(reader->stream_thread = CreateThread(NULL, 0, stream_thread, reader, 0, NULL))) + if (!(reader->callback_thread = CreateThread(NULL, 0, async_reader_callback_thread, reader, 0, NULL))) { IWMReaderCallback_Release(reader->callback); reader->running = false; @@ -266,11 +267,11 @@ static HRESULT open_stream(struct async_reader *reader, IWMReaderCallback *callb
static void close_stream(struct async_reader *reader) { - if (reader->stream_thread) + if (reader->callback_thread) { - WaitForSingleObject(reader->stream_thread, INFINITE); - CloseHandle(reader->stream_thread); - reader->stream_thread = NULL; + WaitForSingleObject(reader->callback_thread, INFINITE); + CloseHandle(reader->callback_thread); + reader->callback_thread = NULL; } }
@@ -278,7 +279,7 @@ static HRESULT async_reader_queue_op(struct async_reader *reader, enum async_op_ { struct async_op *op;
- EnterCriticalSection(&reader->stream_cs); + EnterCriticalSection(&reader->callback_cs);
if (!(op = calloc(1, sizeof(*op)))) return E_OUTOFMEMORY; @@ -287,8 +288,8 @@ static HRESULT async_reader_queue_op(struct async_reader *reader, enum async_op_
list_add_tail(&reader->async_ops, &op->entry);
- LeaveCriticalSection(&reader->stream_cs); - WakeConditionVariable(&reader->stream_cv); + LeaveCriticalSection(&reader->callback_cs); + WakeConditionVariable(&reader->callback_cv);
return S_OK; } @@ -430,7 +431,7 @@ static HRESULT WINAPI WMReader_Start(IWMReader *iface,
EnterCriticalSection(&reader->reader.cs);
- if (!reader->stream_thread) + if (!reader->callback_thread) hr = NS_E_INVALID_REQUEST; else { @@ -452,7 +453,7 @@ static HRESULT WINAPI WMReader_Stop(IWMReader *iface)
EnterCriticalSection(&reader->reader.cs);
- if (!reader->stream_thread) + if (!reader->callback_thread) hr = E_UNEXPECTED; else hr = async_reader_queue_op(reader, ASYNC_OP_STOP, NULL); @@ -522,9 +523,9 @@ static HRESULT WINAPI WMReaderAdvanced_SetUserProvidedClock(IWMReaderAdvanced6 *
TRACE("reader %p, user_clock %d.\n", reader, user_clock);
- EnterCriticalSection(&reader->stream_cs); + EnterCriticalSection(&reader->callback_cs); reader->user_clock = !!user_clock; - LeaveCriticalSection(&reader->stream_cs); + LeaveCriticalSection(&reader->callback_cs); return S_OK; }
@@ -541,19 +542,19 @@ static HRESULT WINAPI WMReaderAdvanced_DeliverTime(IWMReaderAdvanced6 *iface, QW
TRACE("reader %p, time %s.\n", reader, debugstr_time(time));
- EnterCriticalSection(&reader->stream_cs); + EnterCriticalSection(&reader->callback_cs);
if (!reader->user_clock) { - LeaveCriticalSection(&reader->stream_cs); + LeaveCriticalSection(&reader->callback_cs); WARN("Not using a user-provided clock; returning E_UNEXPECTED.\n"); return E_UNEXPECTED; }
reader->user_time = time;
- LeaveCriticalSection(&reader->stream_cs); - WakeConditionVariable(&reader->stream_cv); + LeaveCriticalSection(&reader->callback_cs); + WakeConditionVariable(&reader->callback_cv); return S_OK; }
@@ -1674,15 +1675,15 @@ static void async_reader_destroy(struct wm_reader *iface)
TRACE("reader %p.\n", reader);
- EnterCriticalSection(&reader->stream_cs); + EnterCriticalSection(&reader->callback_cs); reader->running = false; - LeaveCriticalSection(&reader->stream_cs); - WakeConditionVariable(&reader->stream_cv); + LeaveCriticalSection(&reader->callback_cs); + WakeConditionVariable(&reader->callback_cv);
close_stream(reader);
- reader->stream_cs.DebugInfo->Spare[0] = 0; - DeleteCriticalSection(&reader->stream_cs); + reader->callback_cs.DebugInfo->Spare[0] = 0; + DeleteCriticalSection(&reader->callback_cs);
wm_reader_close(&reader->reader);
@@ -1718,8 +1719,8 @@ HRESULT WINAPI winegstreamer_create_wm_async_reader(IWMReader **reader) object->IWMReaderStreamClock_iface.lpVtbl = &WMReaderStreamClockVtbl; object->IWMReaderTypeNegotiation_iface.lpVtbl = &WMReaderTypeNegotiationVtbl;
- InitializeCriticalSection(&object->stream_cs); - object->stream_cs.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": async_reader.stream_cs"); + InitializeCriticalSection(&object->callback_cs); + object->callback_cs.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": async_reader.callback_cs");
QueryPerformanceFrequency(&object->clock_frequency); list_init(&object->async_ops);
From: R��mi Bernon rbernon@codeweavers.com
--- dlls/winegstreamer/wm_asyncreader.c | 8 ++++++++ 1 file changed, 8 insertions(+)
diff --git a/dlls/winegstreamer/wm_asyncreader.c b/dlls/winegstreamer/wm_asyncreader.c index 92c6ba88392..6f4aa303d82 100644 --- a/dlls/winegstreamer/wm_asyncreader.c +++ b/dlls/winegstreamer/wm_asyncreader.c @@ -267,12 +267,20 @@ static HRESULT open_stream(struct async_reader *reader, IWMReaderCallback *callb
static void close_stream(struct async_reader *reader) { + struct async_op *op, *next; + if (reader->callback_thread) { WaitForSingleObject(reader->callback_thread, INFINITE); CloseHandle(reader->callback_thread); reader->callback_thread = NULL; } + + LIST_FOR_EACH_ENTRY_SAFE(op, next, &reader->async_ops, struct async_op, entry) + { + list_remove(&op->entry); + free(op); + } }
static HRESULT async_reader_queue_op(struct async_reader *reader, enum async_op_type type, void *context)
From: R��mi Bernon rbernon@codeweavers.com
--- dlls/winegstreamer/wm_reader.c | 35 +++++++++++++++++++--------------- 1 file changed, 20 insertions(+), 15 deletions(-)
diff --git a/dlls/winegstreamer/wm_reader.c b/dlls/winegstreamer/wm_reader.c index 6c15413bba6..156f9d79446 100644 --- a/dlls/winegstreamer/wm_reader.c +++ b/dlls/winegstreamer/wm_reader.c @@ -1764,6 +1764,7 @@ HRESULT wm_reader_set_output_props(struct wm_reader *reader, DWORD output, struct output_props *props = unsafe_impl_from_IWMOutputMediaProps(props_iface); struct wg_format format, pref_format; struct wm_stream *stream; + HRESULT hr = S_OK; int i;
strmbase_dump_media_type(&props->mt); @@ -1786,18 +1787,15 @@ HRESULT wm_reader_set_output_props(struct wm_reader *reader, DWORD output, if (pref_format.major_type != format.major_type) { /* R.U.S.E sets the type of the wrong stream, apparently by accident. */ - LeaveCriticalSection(&reader->cs); - WARN("Major types don't match; returning NS_E_INCOMPATIBLE_FORMAT.\n"); - return NS_E_INCOMPATIBLE_FORMAT; + hr = NS_E_INCOMPATIBLE_FORMAT; } - - switch (pref_format.major_type) + else switch (pref_format.major_type) { case WG_MAJOR_TYPE_AUDIO: if (format.u.audio.format == WG_AUDIO_FORMAT_UNKNOWN) - return NS_E_AUDIO_CODEC_NOT_INSTALLED; - if (format.u.audio.channels > pref_format.u.audio.channels) - return NS_E_AUDIO_CODEC_NOT_INSTALLED; + hr = NS_E_AUDIO_CODEC_NOT_INSTALLED; + else if (format.u.audio.channels > pref_format.u.audio.channels) + hr = NS_E_AUDIO_CODEC_NOT_INSTALLED; break;
case WG_MAJOR_TYPE_VIDEO: @@ -1805,16 +1803,23 @@ HRESULT wm_reader_set_output_props(struct wm_reader *reader, DWORD output, if (format.u.video.format == video_formats[i]) break; if (i == ARRAY_SIZE(video_formats)) - return NS_E_INVALID_OUTPUT_FORMAT; - - if (pref_format.u.video.width != format.u.video.width) - return NS_E_INVALID_OUTPUT_FORMAT; - if (pref_format.u.video.height != format.u.video.height) - return NS_E_INVALID_OUTPUT_FORMAT; + hr = NS_E_INVALID_OUTPUT_FORMAT; + else if (pref_format.u.video.width != format.u.video.width) + hr = NS_E_INVALID_OUTPUT_FORMAT; + else if (pref_format.u.video.height != format.u.video.height) + hr = NS_E_INVALID_OUTPUT_FORMAT; break;
default: - return NS_E_INCOMPATIBLE_FORMAT; + hr = NS_E_INCOMPATIBLE_FORMAT; + break; + } + + if (FAILED(hr)) + { + WARN("Unsupported media type, returning %#lx.\n", hr); + LeaveCriticalSection(&reader->cs); + return hr; }
stream->format = format;
From: R��mi Bernon rbernon@codeweavers.com
--- dlls/winegstreamer/wm_asyncreader.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-)
diff --git a/dlls/winegstreamer/wm_asyncreader.c b/dlls/winegstreamer/wm_asyncreader.c index 6f4aa303d82..1be7e493f99 100644 --- a/dlls/winegstreamer/wm_asyncreader.c +++ b/dlls/winegstreamer/wm_asyncreader.c @@ -287,15 +287,13 @@ static HRESULT async_reader_queue_op(struct async_reader *reader, enum async_op_ { struct async_op *op;
- EnterCriticalSection(&reader->callback_cs); - if (!(op = calloc(1, sizeof(*op)))) return E_OUTOFMEMORY; op->type = type; op->new_context = context;
+ EnterCriticalSection(&reader->callback_cs); list_add_tail(&reader->async_ops, &op->entry); - LeaveCriticalSection(&reader->callback_cs); WakeConditionVariable(&reader->callback_cv);
From: R��mi Bernon rbernon@codeweavers.com
--- dlls/winegstreamer/wm_asyncreader.c | 46 ++++++++++++++--------------- 1 file changed, 23 insertions(+), 23 deletions(-)
diff --git a/dlls/winegstreamer/wm_asyncreader.c b/dlls/winegstreamer/wm_asyncreader.c index 1be7e493f99..bd7e58713f4 100644 --- a/dlls/winegstreamer/wm_asyncreader.c +++ b/dlls/winegstreamer/wm_asyncreader.c @@ -247,25 +247,7 @@ static DWORD WINAPI async_reader_callback_thread(void *arg) return 0; }
-static HRESULT open_stream(struct async_reader *reader, IWMReaderCallback *callback, void *context) -{ - IWMReaderCallback_AddRef((reader->callback = callback)); - reader->context = context; - - reader->running = true; - if (!(reader->callback_thread = CreateThread(NULL, 0, async_reader_callback_thread, reader, 0, NULL))) - { - IWMReaderCallback_Release(reader->callback); - reader->running = false; - reader->callback = NULL; - reader->context = NULL; - return E_OUTOFMEMORY; - } - - return S_OK; -} - -static void close_stream(struct async_reader *reader) +static void async_reader_close(struct async_reader *reader) { struct async_op *op, *next;
@@ -283,6 +265,24 @@ static void close_stream(struct async_reader *reader) } }
+static HRESULT async_reader_open(struct async_reader *reader, IWMReaderCallback *callback, void *context) +{ + IWMReaderCallback_AddRef((reader->callback = callback)); + reader->context = context; + + reader->running = true; + if (!(reader->callback_thread = CreateThread(NULL, 0, async_reader_callback_thread, reader, 0, NULL))) + { + IWMReaderCallback_Release(reader->callback); + reader->running = false; + reader->callback = NULL; + reader->context = NULL; + return E_OUTOFMEMORY; + } + + return S_OK; +} + static HRESULT async_reader_queue_op(struct async_reader *reader, enum async_op_type type, void *context) { struct async_op *op; @@ -345,7 +345,7 @@ static HRESULT WINAPI WMReader_Open(IWMReader *iface, const WCHAR *url, }
if (SUCCEEDED(hr = wm_reader_open_file(&reader->reader, url)) - && FAILED(hr = open_stream(reader, callback, context))) + && FAILED(hr = async_reader_open(reader, callback, context))) wm_reader_close(&reader->reader);
LeaveCriticalSection(&reader->reader.cs); @@ -362,7 +362,7 @@ static HRESULT WINAPI WMReader_Close(IWMReader *iface) EnterCriticalSection(&reader->reader.cs);
async_reader_queue_op(reader, ASYNC_OP_CLOSE, NULL); - close_stream(reader); + async_reader_close(reader);
hr = wm_reader_close(&reader->reader); if (reader->callback) @@ -825,7 +825,7 @@ static HRESULT WINAPI WMReaderAdvanced2_OpenStream(IWMReaderAdvanced6 *iface, }
if (SUCCEEDED(hr = wm_reader_open_stream(&reader->reader, stream)) - && FAILED(hr = open_stream(reader, callback, context))) + && FAILED(hr = async_reader_open(reader, callback, context))) wm_reader_close(&reader->reader);
LeaveCriticalSection(&reader->reader.cs); @@ -1686,7 +1686,7 @@ static void async_reader_destroy(struct wm_reader *iface) LeaveCriticalSection(&reader->callback_cs); WakeConditionVariable(&reader->callback_cv);
- close_stream(reader); + async_reader_close(reader);
reader->callback_cs.DebugInfo->Spare[0] = 0; DeleteCriticalSection(&reader->callback_cs);
From: R��mi Bernon rbernon@codeweavers.com
--- dlls/winegstreamer/wm_asyncreader.c | 25 ++++++++++++------------- 1 file changed, 12 insertions(+), 13 deletions(-)
diff --git a/dlls/winegstreamer/wm_asyncreader.c b/dlls/winegstreamer/wm_asyncreader.c index bd7e58713f4..2a2b7310293 100644 --- a/dlls/winegstreamer/wm_asyncreader.c +++ b/dlls/winegstreamer/wm_asyncreader.c @@ -263,24 +263,29 @@ static void async_reader_close(struct async_reader *reader) list_remove(&op->entry); free(op); } + + if (reader->callback) + IWMReaderCallback_Release(reader->callback); + reader->callback = NULL; + reader->context = NULL; }
static HRESULT async_reader_open(struct async_reader *reader, IWMReaderCallback *callback, void *context) { + HRESULT hr = E_OUTOFMEMORY; + IWMReaderCallback_AddRef((reader->callback = callback)); reader->context = context;
reader->running = true; if (!(reader->callback_thread = CreateThread(NULL, 0, async_reader_callback_thread, reader, 0, NULL))) - { - IWMReaderCallback_Release(reader->callback); - reader->running = false; - reader->callback = NULL; - reader->context = NULL; - return E_OUTOFMEMORY; - } + goto error;
return S_OK; + +error: + async_reader_close(reader); + return hr; }
static HRESULT async_reader_queue_op(struct async_reader *reader, enum async_op_type type, void *context) @@ -365,9 +370,6 @@ static HRESULT WINAPI WMReader_Close(IWMReader *iface) async_reader_close(reader);
hr = wm_reader_close(&reader->reader); - if (reader->callback) - IWMReaderCallback_Release(reader->callback); - reader->callback = NULL;
LeaveCriticalSection(&reader->reader.cs);
@@ -1693,9 +1695,6 @@ static void async_reader_destroy(struct wm_reader *iface)
wm_reader_close(&reader->reader);
- if (reader->callback) - IWMReaderCallback_Release(reader->callback); - wm_reader_cleanup(&reader->reader); free(reader); }
From: R��mi Bernon rbernon@codeweavers.com
--- dlls/winegstreamer/wm_asyncreader.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-)
diff --git a/dlls/winegstreamer/wm_asyncreader.c b/dlls/winegstreamer/wm_asyncreader.c index 2a2b7310293..a5ab2167ab3 100644 --- a/dlls/winegstreamer/wm_asyncreader.c +++ b/dlls/winegstreamer/wm_asyncreader.c @@ -366,10 +366,11 @@ static HRESULT WINAPI WMReader_Close(IWMReader *iface)
EnterCriticalSection(&reader->reader.cs);
- async_reader_queue_op(reader, ASYNC_OP_CLOSE, NULL); - async_reader_close(reader); - - hr = wm_reader_close(&reader->reader); + if (SUCCEEDED(hr = async_reader_queue_op(reader, ASYNC_OP_CLOSE, NULL))) + { + async_reader_close(reader); + hr = wm_reader_close(&reader->reader); + }
LeaveCriticalSection(&reader->reader.cs);
From: R��mi Bernon rbernon@codeweavers.com
And release it on Close. --- dlls/winegstreamer/wm_asyncreader.c | 27 +++++++++++++++------------ 1 file changed, 15 insertions(+), 12 deletions(-)
diff --git a/dlls/winegstreamer/wm_asyncreader.c b/dlls/winegstreamer/wm_asyncreader.c index a5ab2167ab3..f3e2209881a 100644 --- a/dlls/winegstreamer/wm_asyncreader.c +++ b/dlls/winegstreamer/wm_asyncreader.c @@ -46,6 +46,7 @@ struct async_reader IWMReaderTypeNegotiation IWMReaderTypeNegotiation_iface; IReferenceClock IReferenceClock_iface;
+ IWMReaderCallbackAdvanced *callback_advanced; IWMReaderCallback *callback; void *context;
@@ -70,8 +71,9 @@ static REFERENCE_TIME get_current_time(const struct async_reader *reader) return (time.QuadPart * 1000) / reader->clock_frequency.QuadPart * 10000; }
-static void callback_thread_run(struct async_reader *reader, IWMReaderCallbackAdvanced *callback_advanced) +static void callback_thread_run(struct async_reader *reader) { + IWMReaderCallbackAdvanced *callback_advanced = reader->callback_advanced; IWMReaderCallback *callback = reader->callback; REFERENCE_TIME start_time; struct wm_stream *stream; @@ -173,17 +175,10 @@ static void callback_thread_run(struct async_reader *reader, IWMReaderCallbackAd static DWORD WINAPI async_reader_callback_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);
@@ -209,7 +204,7 @@ static DWORD WINAPI async_reader_callback_thread(void *arg) EnterCriticalSection(&reader->callback_cs);
if (SUCCEEDED(hr)) - callback_thread_run(reader, callback_advanced); + callback_thread_run(reader); break; }
@@ -238,9 +233,6 @@ static DWORD WINAPI async_reader_callback_thread(void *arg) SleepConditionVariableCS(&reader->callback_cv, &reader->callback_cs, INFINITE); }
- if (callback_advanced) - IWMReaderCallbackAdvanced_Release(callback_advanced); - LeaveCriticalSection(&reader->callback_cs);
TRACE("Reader is stopping; exiting.\n"); @@ -264,6 +256,10 @@ static void async_reader_close(struct async_reader *reader) free(op); }
+ if (reader->callback_advanced) + IWMReaderCallbackAdvanced_Release(reader->callback_advanced); + reader->callback_advanced = NULL; + if (reader->callback) IWMReaderCallback_Release(reader->callback); reader->callback = NULL; @@ -277,6 +273,13 @@ static HRESULT async_reader_open(struct async_reader *reader, IWMReaderCallback IWMReaderCallback_AddRef((reader->callback = callback)); reader->context = context;
+ if (FAILED(hr = IWMReaderCallback_QueryInterface(callback, &IID_IWMReaderCallbackAdvanced, + (void **)&reader->callback_advanced))) + { + WARN("Failed to retrieve IWMReaderCallbackAdvanced interface, hr %#lx\n", hr); + reader->callback_advanced = NULL; + } + reader->running = true; if (!(reader->callback_thread = CreateThread(NULL, 0, async_reader_callback_thread, reader, 0, NULL))) goto error;
I believe I addressed most if not all the comments in the last version.
This merge request was approved by Zebediah Figura.