[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