From: "Gabriel Ivăncescu" Subject: [PATCH 2/2] strmbase: Reset the renderer's state event when flushing. Message-Id: <73a6cd2b81b573add86796c5e40daa01a5b3b9c1.1603818649.git.gabrielopcode@gmail.com> Date: Tue, 27 Oct 2020 19:13:33 +0200 In-Reply-To: <5def2d7ec5f6cc93efb5266853c21cc81501ba4b.1603818649.git.gabrielopcode@gmail.com> References: <5def2d7ec5f6cc93efb5266853c21cc81501ba4b.1603818649.git.gabrielopcode@gmail.com> GetState must return VFW_S_STATE_INTERMEDIATE after flushing, until a sample is received. Note the re-checks for 'flushing' after the critical section is acquired, to prevent a race condition in which BeginFlush() is called after Receive() is already in middle of operation, but resets the state_event before the Receive() renderer sets it, which would defeat the whole purpose. Signed-off-by: Gabriel Ivăncescu --- dlls/qedit/tests/nullrenderer.c | 2 +- dlls/qedit/tests/samplegrabber.c | 4 ++-- dlls/quartz/tests/videorenderer.c | 2 +- dlls/quartz/tests/vmr7.c | 2 +- dlls/quartz/tests/vmr9.c | 2 +- dlls/strmbase/renderer.c | 17 +++++++++++++++++ 6 files changed, 23 insertions(+), 6 deletions(-) diff --git a/dlls/qedit/tests/nullrenderer.c b/dlls/qedit/tests/nullrenderer.c index 754228d..fe22d2f 100644 --- a/dlls/qedit/tests/nullrenderer.c +++ b/dlls/qedit/tests/nullrenderer.c @@ -763,7 +763,7 @@ static void test_flushing(IPin *pin, IMemInputPin *input, IFilterGraph2 *graph) /* We dropped the sample we were holding, so now we need a new one... */ hr = IMediaControl_GetState(control, 0, &state); - todo_wine ok(hr == VFW_S_STATE_INTERMEDIATE, "Got hr %#x.\n", hr); + ok(hr == VFW_S_STATE_INTERMEDIATE, "Got hr %#x.\n", hr); thread = send_frame(input); ok(WaitForSingleObject(thread, 100) == WAIT_TIMEOUT, "Thread should block in Receive().\n"); diff --git a/dlls/qedit/tests/samplegrabber.c b/dlls/qedit/tests/samplegrabber.c index e66180f..8f318ab 100644 --- a/dlls/qedit/tests/samplegrabber.c +++ b/dlls/qedit/tests/samplegrabber.c @@ -1239,7 +1239,7 @@ static void test_buffer_flush(void) IPin_EndFlush(sink); hr = IMediaControl_GetState(control, 0, &state); - todo_wine ok(hr == VFW_S_STATE_INTERMEDIATE, "Got hr %#x.\n", hr); + ok(hr == VFW_S_STATE_INTERMEDIATE, "Got hr %#x.\n", hr); ticks = GetTickCount(); thread = send_frame(input, 150); @@ -1254,7 +1254,7 @@ static void test_buffer_flush(void) hr = IMediaControl_Stop(control); ok(hr == S_OK, "Got hr %#x.\n", hr); hr = join_thread(thread); - todo_wine ok(hr == S_OK, "Got hr %#x.\n", hr); + ok(hr == S_OK, "Got hr %#x.\n", hr); IPin_Release(sink); IPin_Release(source); diff --git a/dlls/quartz/tests/videorenderer.c b/dlls/quartz/tests/videorenderer.c index 448efe5..4dd7155 100644 --- a/dlls/quartz/tests/videorenderer.c +++ b/dlls/quartz/tests/videorenderer.c @@ -998,7 +998,7 @@ static void test_flushing(IPin *pin, IMemInputPin *input, IFilterGraph2 *graph) /* We dropped the sample we were holding, so now we need a new one... */ hr = IMediaControl_GetState(control, 0, &state); - todo_wine ok(hr == VFW_S_STATE_INTERMEDIATE, "Got hr %#x.\n", hr); + ok(hr == VFW_S_STATE_INTERMEDIATE, "Got hr %#x.\n", hr); thread = send_frame(input); ok(WaitForSingleObject(thread, 100) == WAIT_TIMEOUT, "Thread should block in Receive().\n"); diff --git a/dlls/quartz/tests/vmr7.c b/dlls/quartz/tests/vmr7.c index 39592af..fd101d7 100644 --- a/dlls/quartz/tests/vmr7.c +++ b/dlls/quartz/tests/vmr7.c @@ -1207,7 +1207,7 @@ static void test_flushing(IPin *pin, IMemInputPin *input, IFilterGraph2 *graph) /* We dropped the sample we were holding, so now we need a new one... */ hr = IMediaControl_GetState(control, 0, &state); - todo_wine ok(hr == VFW_S_STATE_INTERMEDIATE, "Got hr %#x.\n", hr); + ok(hr == VFW_S_STATE_INTERMEDIATE, "Got hr %#x.\n", hr); thread = send_frame(input); ok(WaitForSingleObject(thread, 100) == WAIT_TIMEOUT, "Thread should block in Receive().\n"); diff --git a/dlls/quartz/tests/vmr9.c b/dlls/quartz/tests/vmr9.c index df18bd5..ed7ea9e 100644 --- a/dlls/quartz/tests/vmr9.c +++ b/dlls/quartz/tests/vmr9.c @@ -1219,7 +1219,7 @@ static void test_flushing(IPin *pin, IMemInputPin *input, IMediaControl *control /* We dropped the sample we were holding, so now we need a new one... */ hr = IMediaControl_GetState(control, 0, &state); - todo_wine ok(hr == VFW_S_STATE_INTERMEDIATE, "Got hr %#x.\n", hr); + ok(hr == VFW_S_STATE_INTERMEDIATE, "Got hr %#x.\n", hr); thread = send_frame(input); ok(WaitForSingleObject(thread, 100) == WAIT_TIMEOUT, "Thread should block in Receive().\n"); diff --git a/dlls/strmbase/renderer.c b/dlls/strmbase/renderer.c index dde56b7..c497552 100644 --- a/dlls/strmbase/renderer.c +++ b/dlls/strmbase/renderer.c @@ -194,6 +194,12 @@ static HRESULT WINAPI BaseRenderer_Receive(struct strmbase_sink *pin, IMediaSamp EnterCriticalSection(&filter->csRenderLock); + if (filter->sink.flushing) + { + LeaveCriticalSection(&filter->csRenderLock); + return S_OK; + } + if (filter->filter.clock && SUCCEEDED(IMediaSample_GetTime(sample, &start, &stop))) { strmbase_passthrough_update_time(&filter->passthrough, start); @@ -236,6 +242,12 @@ static HRESULT WINAPI BaseRenderer_Receive(struct strmbase_sink *pin, IMediaSamp } EnterCriticalSection(&filter->csRenderLock); + + if (filter->sink.flushing) + { + LeaveCriticalSection(&filter->csRenderLock); + return S_OK; + } } } @@ -298,8 +310,13 @@ static HRESULT sink_begin_flush(struct strmbase_sink *iface) { struct strmbase_renderer *filter = impl_from_IPin(&iface->pin.IPin_iface); + EnterCriticalSection(&filter->csRenderLock); + + ResetEvent(filter->state_event); SetEvent(filter->flush_event); + LeaveCriticalSection(&filter->csRenderLock); + return S_OK; } -- 2.21.0