[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