[PATCH 2/2] strmbase: Reset the renderer's state event when flushing.

Gabriel Ivăncescu gabrielopcode at gmail.com
Tue Oct 27 12:13:33 CDT 2020


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 <gabrielopcode at gmail.com>
---
 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




More information about the wine-devel mailing list