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

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


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

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

mf: Implement Stop() 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 | 71 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 71 insertions(+)

diff --git a/dlls/mf/session.c b/dlls/mf/session.c
index 485b336570..76310040ee 100644
--- a/dlls/mf/session.c
+++ b/dlls/mf/session.c
@@ -79,6 +79,8 @@ enum session_state
     SESSION_STATE_PAUSING_SINKS,
     SESSION_STATE_PAUSING_SOURCES,
     SESSION_STATE_PAUSED,
+    SESSION_STATE_STOPPING_SINKS,
+    SESSION_STATE_STOPPING_SOURCES,
     SESSION_STATE_CLOSED,
     SESSION_STATE_SHUT_DOWN,
 };
@@ -676,6 +678,36 @@ static void session_pause(struct media_session *session)
     LeaveCriticalSection(&session->cs);
 }
 
+static void session_stop(struct media_session *session)
+{
+    HRESULT hr = S_OK;
+
+    EnterCriticalSection(&session->cs);
+
+    switch (session->state)
+    {
+        case SESSION_STATE_RUNNING:
+        case SESSION_STATE_PAUSED:
+
+            /* Transition in two steps - pause clock, wait for sinks and pause sources. */
+            if (SUCCEEDED(hr = IMFPresentationClock_Stop(session->clock)))
+                session->state = SESSION_STATE_STOPPING_SINKS;
+
+            break;
+        default:
+            ;
+    }
+
+    if (FAILED(hr))
+    {
+        session->state = SESSION_STATE_STOPPED;
+        IMFMediaEventQueue_QueueEventParamVar(session->event_queue, MESessionStopped, &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;
@@ -1503,6 +1535,9 @@ static HRESULT WINAPI session_commands_callback_Invoke(IMFAsyncCallback *iface,
         case SESSION_CMD_PAUSE:
             session_pause(session);
             break;
+        case SESSION_CMD_STOP:
+            session_stop(session);
+            break;
         case SESSION_CMD_CLOSE:
             EnterCriticalSection(&session->cs);
             if (session->state != SESSION_STATE_CLOSED)
@@ -1724,6 +1759,7 @@ static void session_set_source_object_state(struct media_session *session, IUnkn
         MediaEventType event_type)
 {
     struct source_node *src_node;
+    struct output_node *out_node;
     struct media_source *src;
     enum object_state state;
     BOOL changed = FALSE;
@@ -1788,6 +1824,22 @@ static void session_set_source_object_state(struct media_session *session, IUnkn
 
             IMFMediaEventQueue_QueueEventParamVar(session->event_queue, MESessionPaused, &GUID_NULL, S_OK, NULL);
 
+            break;
+        case SESSION_STATE_STOPPING_SOURCES:
+            if (!session_is_source_nodes_state(session, OBJ_STATE_STOPPED))
+                break;
+
+            session->state = SESSION_STATE_STOPPED;
+
+            LIST_FOR_EACH_ENTRY(out_node, &session->presentation.output_nodes, struct output_node, entry)
+            {
+                IMFStreamSink_Flush(out_node->stream);
+            }
+
+            session_set_caps(session, session->caps & ~MFSESSIONCAP_PAUSE);
+
+            IMFMediaEventQueue_QueueEventParamVar(session->event_queue, MESessionStopped, &GUID_NULL, S_OK, NULL);
+
             break;
         default:
             ;
@@ -1870,6 +1922,25 @@ static void session_set_sink_stream_state(struct media_session *session, IMFStre
                 IMFMediaEventQueue_QueueEventParamVar(session->event_queue, MESessionPaused, &GUID_NULL, hr, NULL);
             }
 
+            break;
+        case SESSION_STATE_STOPPING_SINKS:
+            if (!session_is_output_nodes_state(session, OBJ_STATE_STOPPED))
+                break;
+
+            session->state = SESSION_STATE_STOPPING_SOURCES;
+
+            LIST_FOR_EACH_ENTRY(source, &session->presentation.sources, struct media_source, entry)
+            {
+                if (FAILED(hr = IMFMediaSource_Stop(source->source)))
+                    break;
+            }
+
+            if (FAILED(hr))
+            {
+                session->state = SESSION_STATE_STOPPED;
+                IMFMediaEventQueue_QueueEventParamVar(session->event_queue, MESessionStopped, &GUID_NULL, hr, NULL);
+            }
+
             break;
         default:
             ;




More information about the wine-cvs mailing list