Nikolay Sivov : mf: Implement Pause() command for media session.

Alexandre Julliard julliard at winehq.org
Fri Feb 28 13:54:41 CST 2020


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

Author: Nikolay Sivov <nsivov at codeweavers.com>
Date:   Fri Feb 28 15:01:02 2020 +0300

mf: Implement Pause() command for media session.

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

---

 dlls/mf/session.c | 63 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 63 insertions(+)

diff --git a/dlls/mf/session.c b/dlls/mf/session.c
index 70d042cf3d..b2ddad6c96 100644
--- a/dlls/mf/session.c
+++ b/dlls/mf/session.c
@@ -76,6 +76,9 @@ enum session_state
     SESSION_STATE_STARTING_SOURCES,
     SESSION_STATE_STARTING_SINKS,
     SESSION_STATE_RUNNING,
+    SESSION_STATE_PAUSING_SINKS,
+    SESSION_STATE_PAUSING_SOURCES,
+    SESSION_STATE_PAUSED,
     SESSION_STATE_CLOSED,
     SESSION_STATE_SHUT_DOWN,
 };
@@ -644,6 +647,34 @@ static void session_start(struct media_session *session, const GUID *time_format
     LeaveCriticalSection(&session->cs);
 }
 
+static void session_pause(struct media_session *session)
+{
+    HRESULT hr;
+
+    EnterCriticalSection(&session->cs);
+
+    switch (session->state)
+    {
+        case SESSION_STATE_RUNNING:
+
+            /* Transition in two steps - pause clock, wait for sinks and pause sources. */
+            if (SUCCEEDED(hr = IMFPresentationClock_Pause(session->clock)))
+                session->state = SESSION_STATE_PAUSING_SINKS;
+
+            break;
+        default:
+            hr = MF_E_INVALIDREQUEST;
+    }
+
+    if (FAILED(hr))
+    {
+        session->state = SESSION_STATE_PAUSED;
+        IMFMediaEventQueue_QueueEventParamVar(session->event_queue, MESessionPaused, &GUID_NULL, hr, NULL);
+    }
+
+    LeaveCriticalSection(&session->cs);
+}
+
 static struct media_source *session_get_media_source(struct media_session *session, IMFMediaSource *source)
 {
     struct media_source *cur;
@@ -1469,6 +1500,7 @@ static HRESULT WINAPI session_commands_callback_Invoke(IMFAsyncCallback *iface,
             session_start(session, &op->u.start.time_format, &op->u.start.start_position);
             break;
         case SESSION_CMD_PAUSE:
+            session_pause(session);
             break;
         case SESSION_CMD_CLOSE:
             EnterCriticalSection(&session->cs);
@@ -1744,6 +1776,17 @@ static void session_set_source_object_state(struct media_session *session, IUnkn
             if (SUCCEEDED(session_start_clock(session)))
                 session->state = SESSION_STATE_STARTING_SINKS;
 
+            break;
+        case SESSION_STATE_PAUSING_SOURCES:
+            if (!session_is_source_nodes_state(session, OBJ_STATE_PAUSED))
+                break;
+
+            session->state = SESSION_STATE_PAUSED;
+
+            session_set_caps(session, session->caps & ~MFSESSIONCAP_PAUSE);
+
+            IMFMediaEventQueue_QueueEventParamVar(session->event_queue, MESessionPaused, &GUID_NULL, S_OK, NULL);
+
             break;
         default:
             ;
@@ -1759,6 +1802,7 @@ static void session_set_sink_stream_state(struct media_session *session, IMFStre
     BOOL changed = FALSE;
     IMFMediaEvent *event;
     DWORD caps, flags;
+    HRESULT hr;
 
     if ((state = session_get_object_state_for_event(event_type)) == OBJ_STATE_INVALID)
         return;
@@ -1806,6 +1850,25 @@ static void session_set_sink_stream_state(struct media_session *session, IMFStre
                 IMFMediaEventQueue_QueueEvent(session->event_queue, event);
                 IMFMediaEvent_Release(event);
             }
+            break;
+        case SESSION_STATE_PAUSING_SINKS:
+            if (!session_is_output_nodes_state(session, OBJ_STATE_PAUSED))
+                break;
+
+            session->state = SESSION_STATE_PAUSING_SOURCES;
+
+            LIST_FOR_EACH_ENTRY(source, &session->presentation.sources, struct media_source, entry)
+            {
+                if (FAILED(hr = IMFMediaSource_Pause(source->source)))
+                    break;
+            }
+
+            if (FAILED(hr))
+            {
+                session->state = SESSION_STATE_PAUSED;
+                IMFMediaEventQueue_QueueEventParamVar(session->event_queue, MESessionPaused, &GUID_NULL, hr, NULL);
+            }
+
             break;
         default:
             ;




More information about the wine-cvs mailing list