Nikolay Sivov : mf/evr: Handle mixer sample requests during sink state transitions.

Alexandre Julliard julliard at winehq.org
Mon Apr 26 15:51:31 CDT 2021


Module: wine
Branch: master
Commit: 2a6f0a4093a5465f87615bdbf313e9d82c627d53
URL:    https://source.winehq.org/git/wine.git/?a=commit;h=2a6f0a4093a5465f87615bdbf313e9d82c627d53

Author: Nikolay Sivov <nsivov at codeweavers.com>
Date:   Mon Apr 26 11:23:33 2021 +0300

mf/evr: Handle mixer sample requests during sink state transitions.

Signed-off-by: Nikolay Sivov <nsivov at codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard at winehq.org>

---

 dlls/mf/evr.c | 33 +++++++++++++++++++++++----------
 1 file changed, 23 insertions(+), 10 deletions(-)

diff --git a/dlls/mf/evr.c b/dlls/mf/evr.c
index 8b4a9c03b5f..baa6665853e 100644
--- a/dlls/mf/evr.c
+++ b/dlls/mf/evr.c
@@ -47,6 +47,7 @@ enum video_stream_flags
 {
     EVR_STREAM_PREROLLING = 0x1,
     EVR_STREAM_PREROLLED = 0x2,
+    EVR_STREAM_SAMPLE_NEEDED = 0x4,
 };
 
 struct video_renderer;
@@ -1825,13 +1826,19 @@ static ULONG WINAPI video_renderer_clock_sink_Release(IMFClockStateSink *iface)
 static HRESULT WINAPI video_renderer_clock_sink_OnClockStart(IMFClockStateSink *iface, MFTIME systime, LONGLONG offset)
 {
     struct video_renderer *renderer = impl_from_IMFClockStateSink(iface);
+    unsigned int state, request_sample;
     size_t i;
 
     TRACE("%p, %s, %s.\n", iface, debugstr_time(systime), debugstr_time(offset));
 
     EnterCriticalSection(&renderer->cs);
 
-    if (renderer->state == EVR_STATE_STOPPED)
+    state = renderer->state;
+
+    /* Update sink state before sending sample requests, to avoid potentially receiving new sample in stopped state */
+    renderer->state = EVR_STATE_RUNNING;
+
+    if (state == EVR_STATE_STOPPED)
     {
         IMFTransform_ProcessMessage(renderer->mixer, MFT_MESSAGE_NOTIFY_BEGIN_STREAMING, 0);
         IMFVideoPresenter_ProcessMessage(renderer->presenter, MFVP_MESSAGE_BEGINSTREAMING, 0);
@@ -1840,19 +1847,19 @@ static HRESULT WINAPI video_renderer_clock_sink_OnClockStart(IMFClockStateSink *
         {
             struct video_stream *stream = renderer->streams[i];
 
-            IMFMediaEventQueue_QueueEventParamVar(stream->event_queue, MEStreamSinkStarted, &GUID_NULL, S_OK, NULL);
-
             EnterCriticalSection(&stream->cs);
-            if (!(stream->flags & EVR_STREAM_PREROLLED))
-                IMFMediaEventQueue_QueueEventParamVar(stream->event_queue, MEStreamSinkRequestSample,
-                        &GUID_NULL, S_OK, NULL);
+            request_sample = !(stream->flags & EVR_STREAM_PREROLLED) || (stream->flags & EVR_STREAM_SAMPLE_NEEDED);
             stream->flags |= EVR_STREAM_PREROLLED;
+            stream->flags &= ~EVR_STREAM_SAMPLE_NEEDED;
             LeaveCriticalSection(&stream->cs);
+
+            IMFMediaEventQueue_QueueEventParamVar(stream->event_queue, MEStreamSinkStarted, &GUID_NULL, S_OK, NULL);
+            if (request_sample)
+                IMFMediaEventQueue_QueueEventParamVar(stream->event_queue, MEStreamSinkRequestSample,
+                        &GUID_NULL, S_OK, NULL);
         }
     }
 
-    renderer->state = EVR_STATE_RUNNING;
-
     IMFVideoPresenter_OnClockStart(renderer->presenter, systime, offset);
 
     LeaveCriticalSection(&renderer->cs);
@@ -1886,7 +1893,7 @@ static HRESULT WINAPI video_renderer_clock_sink_OnClockStop(IMFClockStateSink *i
             IMFMediaEventQueue_QueueEventParamVar(stream->event_queue, MEStreamSinkStopped, &GUID_NULL, S_OK, NULL);
 
             EnterCriticalSection(&stream->cs);
-            stream->flags &= ~EVR_STREAM_PREROLLED;
+            stream->flags &= ~(EVR_STREAM_PREROLLED | EVR_STREAM_SAMPLE_NEEDED);
             LeaveCriticalSection(&stream->cs);
         }
         renderer->state = EVR_STATE_STOPPED;
@@ -2184,11 +2191,17 @@ static HRESULT WINAPI video_renderer_event_sink_Notify(IMediaEventSink *iface, L
         idx = param1;
         if (idx >= renderer->stream_count)
             hr = MF_E_INVALIDSTREAMNUMBER;
-        else
+        else if (renderer->state == EVR_STATE_RUNNING)
         {
             hr = IMFMediaEventQueue_QueueEventParamVar(renderer->streams[idx]->event_queue,
                 MEStreamSinkRequestSample, &GUID_NULL, S_OK, NULL);
         }
+        else
+        {
+            /* Mixer asks for more input right after preroll too, before renderer finished running state transition.
+               Mark such streams here, and issue requests later in OnClockStart(). */
+            renderer->streams[idx]->flags |= EVR_STREAM_SAMPLE_NEEDED;
+        }
     }
     else if (event == EC_DISPLAY_CHANGED)
     {




More information about the wine-cvs mailing list