From: Paul Gofman pgofman@codeweavers.com
--- dlls/quartz/dsoundrender.c | 47 ++++++++++++++++++++------------ dlls/quartz/tests/dsoundrender.c | 8 +++--- 2 files changed, 33 insertions(+), 22 deletions(-)
diff --git a/dlls/quartz/dsoundrender.c b/dlls/quartz/dsoundrender.c index 3a562669efe..42d5f5cdd25 100644 --- a/dlls/quartz/dsoundrender.c +++ b/dlls/quartz/dsoundrender.c @@ -64,7 +64,7 @@ struct dsound_render * to immediately unblock the streaming thread. */ HANDLE flush_event; REFERENCE_TIME stream_start; - BOOL eos; + BOOL eos, eos_complete_pending;
IDirectSound8 *dsound; LPDIRECTSOUNDBUFFER dsbuffer; @@ -349,6 +349,22 @@ static HRESULT render_sample(struct dsound_render *filter, IMediaSample *pSample return send_sample_data(filter, start, pbSrcStream, cbSrcStream); }
+static void complete_eos(struct dsound_render *filter) +{ + IFilterGraph *graph = filter->filter.graph; + IMediaEventSink *event_sink; + + if (filter->filter.state == State_Running && graph + && SUCCEEDED(IFilterGraph_QueryInterface(graph, + &IID_IMediaEventSink, (void **)&event_sink))) + { + IMediaEventSink_Notify(event_sink, EC_COMPLETE, S_OK, + (LONG_PTR)&filter->filter.IBaseFilter_iface); + IMediaEventSink_Release(event_sink); + } + SetEvent(filter->state_event); +} + static DWORD WINAPI render_thread_run(void *arg) { struct dsound_render *filter = arg; @@ -361,14 +377,18 @@ static DWORD WINAPI render_thread_run(void *arg) { IMediaSample *sample;
- if (filter->eos) + if (filter->eos && (filter->filter.state != State_Running || !filter->queued_sample_count)) { + BOOL complete_pending; + + complete_pending = filter->eos_complete_pending; + filter->eos_complete_pending = FALSE; LeaveCriticalSection(&filter->render_cs); - TRACE("Got EOS.\n"); /* Clear the buffer. */ send_sample_data(filter, -1, NULL, filter->buf_size); - - TRACE("Render thread exiting.\n"); + if (complete_pending) + complete_eos(filter); + TRACE("Render thread exiting on EOS.\n"); return 0; }
@@ -510,24 +530,15 @@ static void dsound_render_sink_disconnect(struct strmbase_sink *iface) static HRESULT dsound_render_sink_eos(struct strmbase_sink *iface) { struct dsound_render *filter = impl_from_strmbase_pin(&iface->pin); - IFilterGraph *graph = filter->filter.graph; - IMediaEventSink *event_sink; + BOOL complete_pending;
EnterCriticalSection(&filter->render_cs); filter->eos = TRUE; + filter->eos_complete_pending = complete_pending = (filter->filter.state == State_Running); LeaveCriticalSection(&filter->render_cs); WakeConditionVariable(&filter->render_cv); - - if (filter->filter.state == State_Running && graph - && SUCCEEDED(IFilterGraph_QueryInterface(graph, - &IID_IMediaEventSink, (void **)&event_sink))) - { - IMediaEventSink_Notify(event_sink, EC_COMPLETE, S_OK, - (LONG_PTR)&filter->filter.IBaseFilter_iface); - IMediaEventSink_Release(event_sink); - } - SetEvent(filter->state_event); - + if (!complete_pending) + complete_eos(filter); return S_OK; }
diff --git a/dlls/quartz/tests/dsoundrender.c b/dlls/quartz/tests/dsoundrender.c index f3ae13231db..6486a152f32 100644 --- a/dlls/quartz/tests/dsoundrender.c +++ b/dlls/quartz/tests/dsoundrender.c @@ -1141,9 +1141,9 @@ static void test_eos(IPin *pin, IMemInputPin *input, IMediaSeeking *seeking, IMe hr = IPin_EndOfStream(pin); ok(hr == S_OK, "Got hr %#lx.\n", hr); ret = check_ec_complete(eventsrc, 0); - todo_wine ok(!ret, "Got unexpected EC_COMPLETE.\n"); + ok(!ret, "Got unexpected EC_COMPLETE.\n"); ret = check_ec_complete(eventsrc, 2000); - todo_wine ok(ret == 1, "Expected EC_COMPLETE.\n"); + ok(ret == 1, "Expected EC_COMPLETE.\n");
hr = IMediaSeeking_GetCurrentPosition(seeking, &time); ok(hr == 0xdeadbeef, "Got hr %#lx.\n", hr); @@ -1201,7 +1201,7 @@ static void test_eos(IPin *pin, IMemInputPin *input, IMediaSeeking *seeking, IMe hr = IPin_EndOfStream(pin); ok(hr == S_OK, "Got hr %#lx.\n", hr); ret = check_ec_complete(eventsrc, 0); - todo_wine ok(!ret, "Got unexpected EC_COMPLETE.\n"); + ok(!ret, "Got unexpected EC_COMPLETE.\n");
hr = IPin_BeginFlush(pin); ok(hr == S_OK, "Got hr %#lx.\n", hr); @@ -1210,7 +1210,7 @@ static void test_eos(IPin *pin, IMemInputPin *input, IMediaSeeking *seeking, IMe hr = IPin_EndFlush(pin); ok(hr == S_OK, "Got hr %#lx.\n", hr); ret = check_ec_complete(eventsrc, 0); - ok(!ret, "Got unexpected EC_COMPLETE.\n"); + todo_wine ok(!ret, "Got unexpected EC_COMPLETE.\n");
hr = send_frame(input); ok(hr == S_OK, "Got hr %#lx.\n", hr);