Nikolay Sivov : mf/session: Fix pause command handling from invalid states.

Alexandre Julliard julliard at winehq.org
Wed Jun 23 16:10:08 CDT 2021


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

Author: Nikolay Sivov <nsivov at codeweavers.com>
Date:   Wed Jun 23 14:03:03 2021 +0300

mf/session: Fix pause command handling from invalid states.

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

---

 dlls/mf/session.c | 19 ++++++++++++++-----
 1 file changed, 14 insertions(+), 5 deletions(-)

diff --git a/dlls/mf/session.c b/dlls/mf/session.c
index 76c39631bd9..4e70aba410a 100644
--- a/dlls/mf/session.c
+++ b/dlls/mf/session.c
@@ -903,9 +903,12 @@ static void session_set_started(struct media_session *session)
     session_command_complete(session);
 }
 
-static void session_set_paused(struct media_session *session, HRESULT status)
+static void session_set_paused(struct media_session *session, unsigned int state, HRESULT status)
 {
-    session->state = SESSION_STATE_PAUSED;
+    /* Failed event status could indicate a failure during normal transition to paused state,
+       or an attempt to pause from invalid initial state. To finalize failed transition in the former case,
+       state is still forced to PAUSED, otherwise previous state is retained. */
+    if (state != ~0u) session->state = state;
     if (SUCCEEDED(status))
         session_set_caps(session, session->caps & ~MFSESSIONCAP_PAUSE);
     IMFMediaEventQueue_QueueEventParamVar(session->event_queue, MESessionPaused, &GUID_NULL, status, NULL);
@@ -923,6 +926,7 @@ static void session_set_closed(struct media_session *session, HRESULT status)
 
 static void session_pause(struct media_session *session)
 {
+    unsigned int state = ~0u;
     HRESULT hr;
 
     switch (session->state)
@@ -932,14 +936,19 @@ static void session_pause(struct media_session *session)
             /* Transition in two steps - pause the clock, wait for sinks, then pause sources. */
             if (SUCCEEDED(hr = IMFPresentationClock_Pause(session->clock)))
                 session->state = SESSION_STATE_PAUSING_SINKS;
+            state = SESSION_STATE_PAUSED;
 
             break;
+
+        case SESSION_STATE_STOPPED:
+            hr = MF_E_SESSION_PAUSEWHILESTOPPED;
+            break;
         default:
             hr = MF_E_INVALIDREQUEST;
     }
 
     if (FAILED(hr))
-        session_set_paused(session, hr);
+        session_set_paused(session, state, hr);
 }
 
 static void session_clear_end_of_presentation(struct media_session *session)
@@ -2502,7 +2511,7 @@ static void session_set_source_object_state(struct media_session *session, IUnkn
             if (!session_is_source_nodes_state(session, OBJ_STATE_PAUSED))
                 break;
 
-            session_set_paused(session, S_OK);
+            session_set_paused(session, SESSION_STATE_PAUSED, S_OK);
             break;
         case SESSION_STATE_STOPPING_SOURCES:
             if (!session_is_source_nodes_state(session, OBJ_STATE_STOPPED))
@@ -2578,7 +2587,7 @@ static void session_set_sink_stream_state(struct media_session *session, IMFStre
             }
 
             if (FAILED(hr))
-                session_set_paused(session, hr);
+                session_set_paused(session, SESSION_STATE_PAUSED, hr);
 
             break;
         case SESSION_STATE_STOPPING_SINKS:




More information about the wine-cvs mailing list