Nikolay Sivov : mf: Set presentation clock for sinks, subscribe to sink events.

Alexandre Julliard julliard at winehq.org
Fri Oct 4 16:34:05 CDT 2019


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

Author: Nikolay Sivov <nsivov at codeweavers.com>
Date:   Fri Oct  4 14:42:48 2019 +0300

mf: Set presentation clock for sinks, subscribe to sink events.

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

---

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

diff --git a/dlls/mf/session.c b/dlls/mf/session.c
index fa8d58ad9d..bf1e48aaf7 100644
--- a/dlls/mf/session.c
+++ b/dlls/mf/session.c
@@ -99,6 +99,12 @@ struct media_source
     struct list streams;
 };
 
+struct media_sink
+{
+    struct list entry;
+    IMFMediaSink *sink;
+};
+
 struct media_session
 {
     IMFMediaSession IMFMediaSession_iface;
@@ -117,6 +123,7 @@ struct media_session
     {
         struct queued_topology current_topology;
         struct list sources;
+        struct list sinks;
     } presentation;
     struct list topologies;
     enum session_state state;
@@ -467,6 +474,7 @@ static void session_clear_presentation(struct media_session *session)
 {
     struct media_source *source, *source2;
     struct media_stream *stream, *stream2;
+    struct media_sink *sink, *sink2;
 
     if (session->presentation.current_topology.topology)
     {
@@ -490,6 +498,15 @@ static void session_clear_presentation(struct media_session *session)
             IMFMediaSource_Release(source->source);
         heap_free(source);
     }
+
+    LIST_FOR_EACH_ENTRY_SAFE(sink, sink2, &session->presentation.sinks, struct media_sink, entry)
+    {
+        list_remove(&sink->entry);
+
+        if (sink->sink)
+            IMFMediaSink_Release(sink->sink);
+        heap_free(sink);
+    }
 }
 
 static void session_start(struct media_session *session, const GUID *time_format, const PROPVARIANT *start_position)
@@ -1142,6 +1159,71 @@ static BOOL session_set_source_state(struct media_session *session, IMFMediaSour
     return ret;
 }
 
+static HRESULT session_set_sinks_clock(struct media_session *session)
+{
+    IMFTopology *topology = session->presentation.current_topology.topology;
+    IMFTopologyNode *node;
+    IMFCollection *nodes;
+    DWORD count, i;
+    HRESULT hr;
+
+    if (!list_empty(&session->presentation.sinks))
+        return S_OK;
+
+    if (FAILED(hr = IMFTopology_GetOutputNodeCollection(topology, &nodes)))
+        return hr;
+
+    if (FAILED(hr = IMFCollection_GetElementCount(nodes, &count)))
+    {
+        IMFCollection_Release(nodes);
+        return hr;
+    }
+
+    for (i = 0; i < count; ++i)
+    {
+        IMFStreamSink *stream_sink = NULL;
+        struct media_sink *sink;
+
+        if (FAILED(hr = IMFCollection_GetElement(nodes, i, (IUnknown **)&node)))
+            break;
+
+        if (!(sink = heap_alloc_zero(sizeof(*sink))))
+            hr = E_OUTOFMEMORY;
+
+        if (SUCCEEDED(hr))
+            hr = IMFTopologyNode_GetObject(node, (IUnknown **)&stream_sink);
+
+        if (SUCCEEDED(hr))
+            hr = IMFStreamSink_GetMediaSink(stream_sink, &sink->sink);
+
+        if (SUCCEEDED(hr))
+            hr = IMFMediaSink_SetPresentationClock(sink->sink, session->clock);
+
+        if (SUCCEEDED(hr))
+            hr = IMFStreamSink_BeginGetEvent(stream_sink, &session->events_callback, (IUnknown *)stream_sink);
+
+        if (stream_sink)
+            IMFStreamSink_Release(stream_sink);
+
+        if (SUCCEEDED(hr))
+        {
+            list_add_tail(&session->presentation.sinks, &sink->entry);
+        }
+        else if (sink)
+        {
+            if (sink->sink)
+                IMFMediaSink_Release(sink->sink);
+            heap_free(sink);
+        }
+
+        IMFTopologyNode_Release(node);
+    }
+
+    IMFCollection_Release(nodes);
+
+    return hr;
+}
+
 static HRESULT WINAPI session_events_callback_Invoke(IMFAsyncCallback *iface, IMFAsyncResult *result)
 {
     struct media_session *session = impl_from_events_callback_IMFAsyncCallback(iface);
@@ -1194,9 +1276,19 @@ static HRESULT WINAPI session_events_callback_Invoke(IMFAsyncCallback *iface, IM
 
             ret = session_set_source_state(session, (IMFMediaSource *)event_source, source_state);
             if (ret && event_type == MESourceStarted)
+            {
                 session_set_topo_status(session, &session->presentation.current_topology, S_OK,
                         MF_TOPOSTATUS_STARTED_SOURCE);
 
+                if (session->state == SESSION_STATE_STARTING)
+                {
+                    if (SUCCEEDED(session_set_sinks_clock(session)))
+                    {
+                        session->state = SESSION_STATE_RUNNING;
+                    }
+                }
+            }
+
             LeaveCriticalSection(&session->cs);
             break;
         case MENewStream:
@@ -1371,6 +1463,7 @@ HRESULT WINAPI MFCreateMediaSession(IMFAttributes *config, IMFMediaSession **ses
     object->refcount = 1;
     list_init(&object->topologies);
     list_init(&object->presentation.sources);
+    list_init(&object->presentation.sinks);
     InitializeCriticalSection(&object->cs);
 
     if (FAILED(hr = MFCreateEventQueue(&object->event_queue)))




More information about the wine-cvs mailing list