Nikolay Sivov : mf: Clone node connections when cloning topology.

Alexandre Julliard julliard at winehq.org
Mon Oct 7 17:02:16 CDT 2019


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

Author: Nikolay Sivov <nsivov at codeweavers.com>
Date:   Mon Oct  7 15:57:01 2019 +0300

mf: Clone node connections when cloning topology.

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

---

 dlls/mf/topology.c | 126 ++++++++++++++++++++++++++++++++++-------------------
 1 file changed, 81 insertions(+), 45 deletions(-)

diff --git a/dlls/mf/topology.c b/dlls/mf/topology.c
index dacb57d264..8d928ad3f9 100644
--- a/dlls/mf/topology.c
+++ b/dlls/mf/topology.c
@@ -111,6 +111,10 @@ static struct topology_node *unsafe_impl_from_IMFTopologyNode(IMFTopologyNode *i
     return impl_from_IMFTopologyNode(iface);
 }
 
+static HRESULT create_topology_node(MF_TOPOLOGY_TYPE node_type, struct topology_node **node);
+static HRESULT topology_node_connect_output(struct topology_node *node, DWORD output_index,
+        struct topology_node *connection, DWORD input_index);
+
 static struct topology *unsafe_impl_from_IMFTopology(IMFTopology *iface);
 
 static struct topology_loader *impl_from_IMFTopoLoader(IMFTopoLoader *iface)
@@ -568,7 +572,6 @@ static HRESULT topology_get_node_by_id(const struct topology *topology, TOPOID i
         if (topology->nodes.nodes[i]->id == id)
         {
             *node = topology->nodes.nodes[i];
-            IMFTopologyNode_AddRef(&(*node)->IMFTopologyNode_iface);
             return S_OK;
         }
     }
@@ -576,19 +579,15 @@ static HRESULT topology_get_node_by_id(const struct topology *topology, TOPOID i
     return MF_E_NOT_FOUND;
 }
 
-static HRESULT topology_add_node(struct topology *topology, IMFTopologyNode *node_iface)
+static HRESULT topology_add_node(struct topology *topology, struct topology_node *node)
 {
-    struct topology_node *node = unsafe_impl_from_IMFTopologyNode(node_iface);
     struct topology_node *match;
 
     if (!node)
         return E_POINTER;
 
     if (SUCCEEDED(topology_get_node_by_id(topology, node->id, &match)))
-    {
-        IMFTopologyNode_Release(&match->IMFTopologyNode_iface);
         return E_INVALIDARG;
-    }
 
     if (!mf_array_reserve((void **)&topology->nodes.nodes, &topology->nodes.size, topology->nodes.count + 1,
             sizeof(*topology->nodes.nodes)))
@@ -602,11 +601,12 @@ static HRESULT topology_add_node(struct topology *topology, IMFTopologyNode *nod
     return S_OK;
 }
 
-static HRESULT WINAPI topology_AddNode(IMFTopology *iface, IMFTopologyNode *node)
+static HRESULT WINAPI topology_AddNode(IMFTopology *iface, IMFTopologyNode *node_iface)
 {
     struct topology *topology = impl_from_IMFTopology(iface);
+    struct topology_node *node = unsafe_impl_from_IMFTopologyNode(node_iface);
 
-    TRACE("%p, %p.\n", iface, node);
+    TRACE("%p, %p.\n", iface, node_iface);
 
     return topology_add_node(topology, node);
 }
@@ -684,9 +684,9 @@ static HRESULT WINAPI topology_CloneFrom(IMFTopology *iface, IMFTopology *src)
 {
     struct topology *topology = impl_from_IMFTopology(iface);
     struct topology *src_topology = unsafe_impl_from_IMFTopology(src);
-    IMFTopologyNode *node;
+    struct topology_node *node;
+    size_t i, j;
     HRESULT hr;
-    size_t i;
 
     TRACE("%p, %p.\n", iface, src);
 
@@ -695,19 +695,36 @@ static HRESULT WINAPI topology_CloneFrom(IMFTopology *iface, IMFTopology *src)
     /* Clone nodes. */
     for (i = 0; i < src_topology->nodes.count; ++i)
     {
-        if (FAILED(hr = MFCreateTopologyNode(src_topology->nodes.nodes[i]->node_type, &node)))
+        if (FAILED(hr = create_topology_node(src_topology->nodes.nodes[i]->node_type, &node)))
         {
             WARN("Failed to create a node, hr %#x.\n", hr);
             break;
         }
 
-        if (SUCCEEDED(hr = IMFTopologyNode_CloneFrom(node, &src_topology->nodes.nodes[i]->IMFTopologyNode_iface)))
+        if (SUCCEEDED(hr = IMFTopologyNode_CloneFrom(&node->IMFTopologyNode_iface,
+                &src_topology->nodes.nodes[i]->IMFTopologyNode_iface)))
+        {
             topology_add_node(topology, node);
+        }
 
-        IMFTopologyNode_Release(node);
+        IMFTopologyNode_Release(&node->IMFTopologyNode_iface);
     }
 
-    FIXME("Clone node connections.\n");
+    /* Clone connections. */
+    for (i = 0; i < src_topology->nodes.count; ++i)
+    {
+        const struct node_streams *outputs = &src_topology->nodes.nodes[i]->outputs;
+
+        for (j = 0; j < outputs->count; ++j)
+        {
+            DWORD input_index = outputs->streams[j].connection_stream;
+            TOPOID id = outputs->streams[j].connection->id;
+
+            /* Skip node lookup in destination topology, assuming same node order. */
+            if (SUCCEEDED(hr = topology_get_node_by_id(topology, id, &node)))
+                topology_node_connect_output(topology->nodes.nodes[i], j, node, input_index);
+        }
+    }
 
     /* Copy attributes and id. */
     hr = IMFTopology_CopyAllItems(src, (IMFAttributes *)&topology->IMFTopology_iface);
@@ -726,7 +743,10 @@ static HRESULT WINAPI topology_GetNodeByID(IMFTopology *iface, TOPOID id, IMFTop
     TRACE("%p, %p.\n", iface, ret);
 
     if (SUCCEEDED(hr = topology_get_node_by_id(topology, id, &node)))
+    {
         *ret = &node->IMFTopologyNode_iface;
+        IMFTopologyNode_AddRef(*ret);
+    }
     else
         *ret = NULL;
 
@@ -1358,22 +1378,12 @@ static HRESULT WINAPI topology_node_GetOutputCount(IMFTopologyNode *iface, DWORD
     return S_OK;
 }
 
-static HRESULT WINAPI topology_node_ConnectOutput(IMFTopologyNode *iface, DWORD output_index,
-        IMFTopologyNode *peer, DWORD input_index)
+static HRESULT topology_node_connect_output(struct topology_node *node, DWORD output_index,
+        struct topology_node *connection, DWORD input_index)
 {
-    struct topology_node *node = impl_from_IMFTopologyNode(iface);
-    struct topology_node *connection = unsafe_impl_from_IMFTopologyNode(peer);
     struct node_stream *stream;
     HRESULT hr;
 
-    TRACE("%p, %u, %p, %u.\n", iface, output_index, peer, input_index);
-
-    if (!connection)
-    {
-        WARN("External node implementations are not supported.\n");
-        return E_UNEXPECTED;
-    }
-
     if (node->node_type == MF_TOPOLOGY_OUTPUT_NODE || connection->node_type == MF_TOPOLOGY_SOURCESTREAM_NODE)
          return E_FAIL;
 
@@ -1408,6 +1418,23 @@ static HRESULT WINAPI topology_node_ConnectOutput(IMFTopologyNode *iface, DWORD
     return hr;
 }
 
+static HRESULT WINAPI topology_node_ConnectOutput(IMFTopologyNode *iface, DWORD output_index,
+        IMFTopologyNode *peer, DWORD input_index)
+{
+    struct topology_node *node = impl_from_IMFTopologyNode(iface);
+    struct topology_node *connection = unsafe_impl_from_IMFTopologyNode(peer);
+
+    TRACE("%p, %u, %p, %u.\n", iface, output_index, peer, input_index);
+
+    if (!connection)
+    {
+        WARN("External node implementations are not supported.\n");
+        return E_UNEXPECTED;
+    }
+
+    return topology_node_connect_output(node, output_index, connection, input_index);
+}
+
 static HRESULT WINAPI topology_node_DisconnectOutput(IMFTopologyNode *iface, DWORD output_index)
 {
     struct topology_node *node = impl_from_IMFTopologyNode(iface);
@@ -1684,6 +1711,29 @@ static const IMFTopologyNodeVtbl topologynodevtbl =
     topology_node_CloneFrom,
 };
 
+static HRESULT create_topology_node(MF_TOPOLOGY_TYPE node_type, struct topology_node **node)
+{
+    HRESULT hr;
+
+    *node = heap_alloc_zero(sizeof(**node));
+    if (!*node)
+        return E_OUTOFMEMORY;
+
+    (*node)->IMFTopologyNode_iface.lpVtbl = &topologynodevtbl;
+    (*node)->refcount = 1;
+    (*node)->node_type = node_type;
+    hr = MFCreateAttributes(&(*node)->attributes, 0);
+    if (FAILED(hr))
+    {
+        heap_free(*node);
+        return hr;
+    }
+    (*node)->id = ((TOPOID)GetCurrentProcessId() << 32) | InterlockedIncrement(&next_node_id);
+    InitializeCriticalSection(&(*node)->cs);
+
+    return S_OK;
+}
+
 /***********************************************************************
  *      MFCreateTopologyNode (mf.@)
  */
@@ -1692,30 +1742,16 @@ HRESULT WINAPI MFCreateTopologyNode(MF_TOPOLOGY_TYPE node_type, IMFTopologyNode
     struct topology_node *object;
     HRESULT hr;
 
-    TRACE("(%p)\n", node);
+    TRACE("%d, %p.\n", node_type, node);
 
     if (!node)
         return E_POINTER;
 
-    object = heap_alloc_zero(sizeof(*object));
-    if (!object)
-        return E_OUTOFMEMORY;
-
-    object->IMFTopologyNode_iface.lpVtbl = &topologynodevtbl;
-    object->refcount = 1;
-    object->node_type = node_type;
-    hr = MFCreateAttributes(&object->attributes, 0);
-    if (FAILED(hr))
-    {
-        heap_free(object);
-        return hr;
-    }
-    object->id = ((TOPOID)GetCurrentProcessId() << 32) | InterlockedIncrement(&next_node_id);
-    InitializeCriticalSection(&object->cs);
-
-    *node = &object->IMFTopologyNode_iface;
+    hr = create_topology_node(node_type, &object);
+    if (SUCCEEDED(hr))
+        *node = &object->IMFTopologyNode_iface;
 
-    return S_OK;
+    return hr;
 }
 
 static HRESULT WINAPI topology_loader_QueryInterface(IMFTopoLoader *iface, REFIID riid, void **out)




More information about the wine-cvs mailing list