[PATCH v5 6/8] mf: Introduce branch resolver topology_loader_resolver_branch_connect_nodes() for use by topology loader.

Sergio Gómez Del Real sdelreal at codeweavers.com
Wed Apr 22 22:28:33 CDT 2020


Signed-off-by: Sergio Gómez Del Real <sdelreal at codeweavers.com>
---
 dlls/mf/topology.c | 170 +++++++++++++++++++++++++++++++++++++++++++--
 1 file changed, 166 insertions(+), 4 deletions(-)

diff --git a/dlls/mf/topology.c b/dlls/mf/topology.c
index 4298ab1bc5..f1b3c3c9e4 100644
--- a/dlls/mf/topology.c
+++ b/dlls/mf/topology.c
@@ -31,6 +31,7 @@
 #include "mfidl.h"
 
 #include "wine/debug.h"
+#include "wine/list.h"
 
 #include "mf_private.h"
 
@@ -39,6 +40,12 @@ WINE_DEFAULT_DEBUG_CHANNEL(mfplat);
 static LONG next_node_id;
 static TOPOID next_topology_id;
 
+struct list_topologies
+{
+    struct list entry;
+    struct topology *topology;
+};
+
 struct node_stream
 {
     IMFMediaType *preferred_type;
@@ -1913,6 +1920,161 @@ static ULONG WINAPI topology_loader_Release(IMFTopoLoader *iface)
     return refcount;
 }
 
+static HRESULT topology_loader_add_branch(struct topology *topology, IMFTopologyNode *first)
+{
+    IMFTopology *full_topo = &topology->IMFTopology_iface;
+    IMFTopologyNode *in, *out;
+    DWORD index;
+    HRESULT hr;
+
+    if (!topology || !first)
+    {
+        hr = MF_E_INVALIDREQUEST;
+        goto out;
+    }
+
+    in = first;
+    if (SUCCEEDED(hr = IMFTopology_AddNode(full_topo, in)))
+    {
+        while (SUCCEEDED(hr = IMFTopologyNode_GetOutput(in, 0, &out, &index)))
+        {
+            if (FAILED(hr = IMFTopology_AddNode(full_topo, out)))
+                break;
+            IMFTopologyNode_Release(out);
+            in = out;
+        }
+    }
+
+out:
+    return hr == MF_E_NOT_FOUND ? S_OK : hr;
+}
+
+/* iterate through the branch that starts at source node with id srcid, and try to resolve it */
+static HRESULT topology_loader_resolve_branch_connect_nodes(struct topology *topology, TOPOID srcid, MF_CONNECT_METHOD method)
+{
+    IMFTopologyNode *up_clone, *down_clone;
+    IMFTopologyNode *src, *up, *down;
+    struct list *list_topologies;
+    IMFTopology *clone_topo;
+    int num_lists, i;
+    DWORD index;
+    HRESULT hr;
+
+    num_lists = topology->nodes.count-1;
+    list_topologies = heap_alloc_zero(sizeof(struct list) * num_lists);
+    if (!list_topologies)
+        return E_OUTOFMEMORY;
+
+    MFCreateTopology(&clone_topo);
+    IMFTopology_CloneFrom(clone_topo, &topology->IMFTopology_iface);
+    IMFTopology_GetNodeByID(clone_topo, srcid, &src);
+
+    up = src;
+    for (i = 0; i < num_lists; i++)
+    {
+        MF_TOPOLOGY_TYPE type;
+
+        IMFTopologyNode_GetOutput(up, 0, &down, &index);
+
+        IMFTopologyNode_GetNodeType(down, &type);
+        MFCreateTopologyNode(type, &down_clone);
+        IMFTopologyNode_CloneFrom(down_clone, down);
+
+        list_init(&list_topologies[i]);
+
+        if (i == 0)
+        {
+            IMFTopologyNode_GetNodeType(up, &type);
+            MFCreateTopologyNode(type, &up_clone);
+            IMFTopologyNode_CloneFrom(up_clone, up);
+
+            /* 'method' argument passed to function only applies to source media types */
+            if (method == MF_CONNECT_DIRECT)
+            {
+                hr = S_OK;
+                if (list_empty(&list_topologies[i]))
+                {
+                    IMFTopologyNode_Release(up_clone);
+                    IMFTopologyNode_Release(down_clone);
+                    IMFTopologyNode_Release(up);
+                    IMFTopologyNode_Release(down);
+                    IMFTopology_Release(clone_topo);
+                    goto out;
+                }
+            }
+            else
+            {
+                hr = S_OK;
+                if (list_empty(&list_topologies[i]))
+                {
+                    IMFTopologyNode_Release(up_clone);
+                    IMFTopologyNode_Release(down_clone);
+                    IMFTopologyNode_Release(up);
+                    IMFTopologyNode_Release(down);
+                    IMFTopology_Release(clone_topo);
+                    goto out;
+                }
+            }
+        }
+
+        else
+        {
+            struct list_topologies *prev_topologies, *safety_prev;
+
+            /*
+             * Iterate through list of resolved topologies for previous nodes in the branch, and use it as base
+             * to build the list of resolved topologies that include the next node in the branch.
+             */
+            LIST_FOR_EACH_ENTRY_SAFE(prev_topologies, safety_prev, &list_topologies[i-1], struct list_topologies, entry)
+            {
+                struct list_topologies *curr_topologies;
+                struct topology *prev_topology;
+                IMFTopologyNode *up_clone;
+
+                MFCreateTopologyNode(MF_TOPOLOGY_TRANSFORM_NODE, &up_clone);
+
+                prev_topology = prev_topologies->topology;
+                IMFTopologyNode_CloneFrom(up_clone, &prev_topology->nodes.nodes[prev_topology->nodes.count-1]->IMFTopologyNode_iface);
+
+                if (list_empty(&list_topologies[i]))
+                {
+                    IMFTopologyNode_Release(up_clone);
+                    IMFTopologyNode_Release(down_clone);
+                    IMFTopologyNode_Release(up);
+                    IMFTopologyNode_Release(down);
+                    IMFTopology_Release(clone_topo);
+                    goto out;
+                }
+
+                LIST_FOR_EACH_ENTRY(curr_topologies, &list_topologies[i], struct list_topologies, entry)
+                {
+                    struct topology *curr_topology = curr_topologies->topology;
+                    IMFTopologyNode *last_node_prev_topo;
+                    IMFTopology *new_topology;
+
+                    MFCreateTopology(&new_topology);
+                    IMFTopology_CloneFrom(new_topology, &prev_topology->IMFTopology_iface);
+                    IMFTopology_GetNode(new_topology, prev_topology->nodes.count-1, &last_node_prev_topo);
+                    IMFTopologyNode_ConnectOutput(last_node_prev_topo, 0, &curr_topology->nodes.nodes[0]->IMFTopologyNode_iface, 0);
+                    topology_loader_add_branch(impl_from_IMFTopology(new_topology), &curr_topology->nodes.nodes[0]->IMFTopologyNode_iface);
+                    curr_topologies->topology = impl_from_IMFTopology(new_topology);
+                    IMFTopology_Release(&curr_topology->IMFTopology_iface);
+                }
+                list_remove(&prev_topologies->entry);
+                heap_free(prev_topologies);
+                IMFTopology_Release(&prev_topology->IMFTopology_iface);
+            }
+        }
+        IMFTopologyNode_Release(up_clone);
+        IMFTopologyNode_Release(down_clone);
+        IMFTopologyNode_Release(up);
+        up = down;
+    }
+
+out:
+    heap_free(list_topologies);
+    return hr;
+}
 
 /* Resolves a branch with the supplied source and sink */
 static HRESULT topology_loader_resolve_branch(struct topology_node *src, struct topology_node *sink, struct topology *full_topology)
@@ -1977,8 +2139,8 @@ static HRESULT topology_loader_resolve_branch(struct topology_node *src, struct
             for (i = 0; i < num_media_types; i++)
             {
                 IMFMediaTypeHandler_SetCurrentMediaType(mth_src, src_mediatypes[i]);
-                hr = S_OK;
-                goto out;
+                if (SUCCEEDED(hr = topology_loader_resolve_branch_connect_nodes(full_topology, src->id, method)))
+                    goto out;
             }
         }
     }
@@ -1989,8 +2151,8 @@ static HRESULT topology_loader_resolve_branch(struct topology_node *src, struct
             for (method = MF_CONNECT_DIRECT; method < MF_CONNECT_RESOLVE_INDEPENDENT_OUTPUTTYPES; method++)
             {
                 IMFMediaTypeHandler_SetCurrentMediaType(mth_src, src_mediatypes[i]);
-                hr = S_OK;
-                goto out;
+                if (SUCCEEDED(hr = topology_loader_resolve_branch_connect_nodes(full_topology, src->id, method)))
+                    goto out;
             }
         }
     }
-- 
2.17.1




More information about the wine-devel mailing list