[PATCH 07/14] mf: Keep a list of output streams.

Nikolay Sivov nsivov at codeweavers.com
Fri Feb 28 06:00:57 CST 2020


Signed-off-by: Nikolay Sivov <nsivov at codeweavers.com>
---
 dlls/mf/session.c | 93 +++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 93 insertions(+)

diff --git a/dlls/mf/session.c b/dlls/mf/session.c
index 12685583e2..288ea60e6f 100644
--- a/dlls/mf/session.c
+++ b/dlls/mf/session.c
@@ -109,6 +109,13 @@ struct media_sink
     IMFMediaSink *sink;
 };
 
+struct output_node
+{
+    struct list entry;
+    IMFStreamSink *stream;
+    enum object_state state;
+};
+
 struct media_session
 {
     IMFMediaSession IMFMediaSession_iface;
@@ -130,6 +137,7 @@ struct media_session
         struct list sources;
         struct list source_nodes;
         struct list sinks;
+        struct list output_nodes;
     } presentation;
     struct list topologies;
     enum session_state state;
@@ -788,6 +796,89 @@ static void session_raise_topology_set(struct media_session *session, IMFTopolog
     IMFMediaEventQueue_QueueEventParamVar(session->event_queue, MESessionTopologySet, &GUID_NULL, status, &param);
 }
 
+static HRESULT session_add_media_sink(struct media_session *session, IMFTopologyNode *node, IMFMediaSink *sink)
+{
+    struct media_sink *media_sink;
+
+    LIST_FOR_EACH_ENTRY(media_sink, &session->presentation.sinks, struct media_sink, entry)
+    {
+        if (sink == media_sink->sink)
+            return S_FALSE;
+    }
+
+    if (!(media_sink = heap_alloc_zero(sizeof(*media_sink))))
+        return E_OUTOFMEMORY;
+
+    media_sink->sink = sink;
+    IMFMediaSink_AddRef(media_sink->sink);
+
+    list_add_tail(&session->presentation.sinks, &media_sink->entry);
+
+    return S_OK;
+}
+
+static HRESULT session_collect_output_nodes(struct media_session *session)
+{
+    IMFTopology *topology = session->presentation.current_topology;
+    IMFTopologyNode *topo_node;
+    struct output_node *node;
+    IMFCollection *nodes;
+    DWORD count, i;
+    HRESULT hr;
+
+    if (!list_empty(&session->presentation.output_nodes))
+        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)
+    {
+        IMFMediaSink *media_sink = NULL;
+
+        if (FAILED(hr = IMFCollection_GetElement(nodes, i, (IUnknown **)&topo_node)))
+            break;
+
+        if (!(node = heap_alloc_zero(sizeof(*node))))
+            hr = E_OUTOFMEMORY;
+
+        if (SUCCEEDED(hr))
+            hr = IMFTopologyNode_GetObject(topo_node, (IUnknown **)&node->stream);
+
+        if (SUCCEEDED(hr))
+            hr = IMFStreamSink_GetMediaSink(node->stream, &media_sink);
+
+        if (SUCCEEDED(hr))
+            hr = session_add_media_sink(session, topo_node, media_sink);
+
+        if (media_sink)
+            IMFMediaSink_Release(media_sink);
+
+        if (SUCCEEDED(hr))
+        {
+            list_add_tail(&session->presentation.output_nodes, &node->entry);
+        }
+        else if (node)
+        {
+            if (node->stream)
+                IMFStreamSink_Release(node->stream);
+            heap_free(node);
+        }
+
+        IMFTopologyNode_Release(topo_node);
+    }
+
+    IMFCollection_Release(nodes);
+
+    return hr;
+}
+
 static void session_set_current_topology(struct media_session *session, IMFTopology *topology)
 {
     IMFMediaEvent *event;
@@ -800,6 +891,7 @@ static void session_set_current_topology(struct media_session *session, IMFTopol
     }
 
     session_collect_source_nodes(session);
+    session_collect_output_nodes(session);
 
     /* FIXME: attributes are all zero for now */
     if (SUCCEEDED(MFCreateMediaEvent(MESessionNotifyPresentationTime, &GUID_NULL, S_OK, NULL, &event)))
@@ -1752,6 +1844,7 @@ HRESULT WINAPI MFCreateMediaSession(IMFAttributes *config, IMFMediaSession **ses
     list_init(&object->presentation.sources);
     list_init(&object->presentation.source_nodes);
     list_init(&object->presentation.sinks);
+    list_init(&object->presentation.output_nodes);
     InitializeCriticalSection(&object->cs);
 
     if (FAILED(hr = MFCreateTopology(&object->presentation.current_topology)))
-- 
2.25.0




More information about the wine-devel mailing list