[PATCH 3/3] mf/topoloader: Add a structure for iterative branch resolution.

Nikolay Sivov nsivov at codeweavers.com
Wed Jul 15 07:55:47 CDT 2020


Signed-off-by: Nikolay Sivov <nsivov at codeweavers.com>
---
 dlls/mf/tests/mf.c |   9 ++-
 dlls/mf/topology.c | 138 ++++++++++++++++++++++++++++++++++++++++++++-
 2 files changed, 143 insertions(+), 4 deletions(-)

diff --git a/dlls/mf/tests/mf.c b/dlls/mf/tests/mf.c
index aa2c5199b95..f01385cc46c 100644
--- a/dlls/mf/tests/mf.c
+++ b/dlls/mf/tests/mf.c
@@ -1400,6 +1400,7 @@ static void test_topology_loader(void)
     IMFPresentationDescriptor *pd;
     IMFSourceResolver *resolver;
     IMFActivate *sink_activate;
+    IMFStreamSink *stream_sink;
     unsigned int count, value;
     IMFMediaType *media_type;
     IMFStreamDescriptor *sd;
@@ -1512,15 +1513,19 @@ todo_wine
     hr = IMFActivate_ActivateObject(sink_activate, &IID_IMFMediaSink, (void **)&sink);
     ok(hr == S_OK, "Failed to activate, hr %#x.\n", hr);
 
-    hr = IMFTopologyNode_SetObject(sink_node, (IUnknown *)sink);
+    hr = IMFMediaSink_GetStreamSinkByIndex(sink, 0, &stream_sink);
+    ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
+
+    hr = IMFTopologyNode_SetObject(sink_node, (IUnknown *)stream_sink);
     ok(hr == S_OK, "Failed to set object, hr %#x.\n", hr);
 
+    IMFStreamSink_Release(stream_sink);
+
     hr = IMFTopology_GetCount(topology, &count);
     ok(hr == S_OK, "Failed to get attribute count, hr %#x.\n", hr);
     ok(count == 0, "Unexpected count %u.\n", count);
 
     hr = IMFTopoLoader_Load(loader, topology, &full_topology, NULL);
-todo_wine
     ok(hr == S_OK, "Failed to resolve topology, hr %#x.\n", hr);
     ok(full_topology != topology, "Unexpected instance.\n");
 
diff --git a/dlls/mf/topology.c b/dlls/mf/topology.c
index 038d6214d4a..d21c84ac8f7 100644
--- a/dlls/mf/topology.c
+++ b/dlls/mf/topology.c
@@ -1935,17 +1935,41 @@ static ULONG WINAPI topology_loader_Release(IMFTopoLoader *iface)
 
 struct topoloader_context
 {
+    IMFTopology *input_topology;
     IMFTopology *output_topology;
+    unsigned int marker;
     GUID key;
 };
 
+static IMFTopologyNode *topology_loader_get_node_for_marker(struct topoloader_context *context, TOPOID *id)
+{
+    IMFTopologyNode *node;
+    unsigned short i = 0;
+    unsigned int value;
+
+    while (SUCCEEDED(IMFTopology_GetNode(context->output_topology, i++, &node)))
+    {
+        if (SUCCEEDED(IMFTopologyNode_GetUINT32(node, &context->key, &value)) && value == context->marker)
+        {
+            IMFTopologyNode_GetTopoNodeID(node, id);
+            return node;
+        }
+        IMFTopologyNode_Release(node);
+    }
+
+    *id = 0;
+    return NULL;
+}
+
 static HRESULT topology_loader_clone_node(struct topoloader_context *context, IMFTopologyNode *node,
-        unsigned int marker)
+        IMFTopologyNode **ret, unsigned int marker)
 {
     IMFTopologyNode *cloned_node;
     MF_TOPOLOGY_TYPE node_type;
     HRESULT hr;
 
+    if (ret) *ret = NULL;
+
     IMFTopologyNode_GetNodeType(node, &node_type);
 
     if (FAILED(hr = MFCreateTopologyNode(node_type, &cloned_node)))
@@ -1957,17 +1981,113 @@ static HRESULT topology_loader_clone_node(struct topoloader_context *context, IM
     if (SUCCEEDED(hr))
         hr = IMFTopology_AddNode(context->output_topology, cloned_node);
 
+    if (SUCCEEDED(hr) && ret)
+    {
+        *ret = cloned_node;
+        IMFTopologyNode_AddRef(*ret);
+    }
+
     IMFTopologyNode_Release(cloned_node);
 
     return hr;
 }
 
+typedef HRESULT (*p_topology_loader_connect_func)(struct topoloader_context *context, IMFTopologyNode *upstream_node,
+        unsigned int output_index, IMFTopologyNode *downstream_node, unsigned int input_index);
+
+static HRESULT topology_loader_connect_source_node(struct topoloader_context *context, IMFTopologyNode *upstream_node,
+        unsigned int output_index, IMFTopologyNode *downstream_node, unsigned int input_index)
+{
+    FIXME("Unimplemented.\n");
+
+    return E_NOTIMPL;
+}
+
+static HRESULT topology_loader_resolve_branch(struct topoloader_context *context, IMFTopologyNode *upstream_node,
+        unsigned int output_index, IMFTopologyNode *downstream_node, unsigned input_index)
+{
+    static const p_topology_loader_connect_func connectors[MF_TOPOLOGY_TEE_NODE+1][MF_TOPOLOGY_TEE_NODE+1] =
+    {
+          /* OUTPUT */ { NULL },
+    /* SOURCESTREAM */ { topology_loader_connect_source_node, NULL, NULL, NULL },
+       /* TRANSFORM */ { NULL },
+             /* TEE */ { NULL },
+    };
+    MF_TOPOLOGY_TYPE u_type, d_type;
+    IMFTopologyNode *node;
+    TOPOID id;
+
+    /* Downstream node might have already been cloned. */
+    IMFTopologyNode_GetTopoNodeID(downstream_node, &id);
+    if (FAILED(IMFTopology_GetNodeByID(context->output_topology, id, &node)))
+        topology_loader_clone_node(context, downstream_node, &node, context->marker + 1);
+
+    IMFTopologyNode_ConnectOutput(upstream_node, output_index, node, input_index);
+
+    IMFTopologyNode_GetNodeType(upstream_node, &u_type);
+    IMFTopologyNode_GetNodeType(downstream_node, &d_type);
+
+    if (!connectors[u_type][d_type])
+    {
+        WARN("Unsupported branch kind %d -> %d.\n", u_type, d_type);
+        return E_FAIL;
+    }
+
+    return connectors[u_type][d_type](context, upstream_node, output_index, downstream_node, input_index);
+}
+
+static HRESULT topology_loader_resolve_nodes(struct topoloader_context *context, unsigned int *layer_size)
+{
+    IMFTopologyNode *downstream_node, *node, *orig_node;
+    unsigned int input_index, size = 0;
+    MF_TOPOLOGY_TYPE node_type;
+    HRESULT hr = S_OK;
+    TOPOID id;
+
+    while ((node = topology_loader_get_node_for_marker(context, &id)))
+    {
+        ++size;
+
+        IMFTopology_GetNodeByID(context->input_topology, id, &orig_node);
+
+        IMFTopologyNode_GetNodeType(node, &node_type);
+        switch (node_type)
+        {
+            case MF_TOPOLOGY_SOURCESTREAM_NODE:
+                if (FAILED(IMFTopologyNode_GetOutput(orig_node, 0, &downstream_node, &input_index)))
+                {
+                    IMFTopology_RemoveNode(context->output_topology, node);
+                    continue;
+                }
+
+                hr = topology_loader_resolve_branch(context, node, 0, downstream_node, input_index);
+                break;
+            case MF_TOPOLOGY_TRANSFORM_NODE:
+            case MF_TOPOLOGY_TEE_NODE:
+                FIXME("Unsupported node type %d.\n", node_type);
+                break;
+            default:
+                WARN("Unexpected node type %d.\n", node_type);
+        }
+
+        IMFTopologyNode_DeleteItem(node, &context->key);
+
+        if (FAILED(hr))
+            break;
+    }
+
+    *layer_size = size;
+
+    return hr;
+}
+
 static HRESULT WINAPI topology_loader_Load(IMFTopoLoader *iface, IMFTopology *input_topology,
         IMFTopology **ret_topology, IMFTopology *current_topology)
 {
     struct topoloader_context context = { 0 };
     IMFTopology *output_topology;
     MF_TOPOLOGY_TYPE node_type;
+    unsigned int layer_size;
     IMFTopologyNode *node;
     unsigned short i = 0;
     IMFStreamSink *sink;
@@ -2016,6 +2136,7 @@ static HRESULT WINAPI topology_loader_Load(IMFTopoLoader *iface, IMFTopology *in
     if (FAILED(hr = MFCreateTopology(&output_topology)))
         return hr;
 
+    context.input_topology = input_topology;
     context.output_topology = output_topology;
     memset(&context.key, 0xff, sizeof(context.key));
 
@@ -2027,13 +2148,26 @@ static HRESULT WINAPI topology_loader_Load(IMFTopoLoader *iface, IMFTopology *in
 
         if (node_type == MF_TOPOLOGY_SOURCESTREAM_NODE)
         {
-            if (FAILED(hr = topology_loader_clone_node(&context, node, 0)))
+            if (FAILED(hr = topology_loader_clone_node(&context, node, NULL, 0)))
                 WARN("Failed to clone source node, hr %#x.\n", hr);
         }
 
         IMFTopologyNode_Release(node);
     }
 
+    for (context.marker = 0;; ++context.marker)
+    {
+        if (FAILED(hr = topology_loader_resolve_nodes(&context, &layer_size)))
+        {
+            WARN("Failed to resolve for marker %u, hr %#x.\n", context.marker, hr);
+            break;
+        }
+
+        /* Reached last marker value. */
+        if (!layer_size)
+            break;
+    }
+
     /* For now return original topology. */
 
     *ret_topology = output_topology;
-- 
2.27.0




More information about the wine-devel mailing list