From: Conor McCarthy <cmccarthy@codeweavers.com> --- dlls/mf/tests/topology.c | 1 - dlls/mf/topology_loader.c | 114 ++++++++++++++++++++++---------------- 2 files changed, 67 insertions(+), 48 deletions(-) diff --git a/dlls/mf/tests/topology.c b/dlls/mf/tests/topology.c index d7ddb44a59f..1afc5fc5f6e 100644 --- a/dlls/mf/tests/topology.c +++ b/dlls/mf/tests/topology.c @@ -3509,7 +3509,6 @@ todo_wine { /* Non-optional transform is connected to its downstream node after the optional * node is inserted upstream, i.e. after each branch is connected, its optional * nodes are inserted before the next branch is connected. */ - todo_wine ok(optional_transforms[0]->set_output_sequence_id < test_transform->set_output_sequence_id, "Optional transform output was not configured before the non-optional one.\n"); } diff --git a/dlls/mf/topology_loader.c b/dlls/mf/topology_loader.c index 7e2adc2c8ee..6b4aa5c1f50 100644 --- a/dlls/mf/topology_loader.c +++ b/dlls/mf/topology_loader.c @@ -105,6 +105,7 @@ struct topoloader_context { IMFTopology *input_topology; IMFTopology *output_topology; + UINT resolved_count; /* includes accepted and rejected optional nodes */ }; static HRESULT topology_loader_clone_node(struct topoloader_context *context, IMFTopologyNode *node, IMFTopologyNode **clone) @@ -146,8 +147,6 @@ struct topology_branch DWORD stream; IMFMediaTypeHandler *handler; } up, down; - - struct list entry; }; static const char *debugstr_topology_type(MF_TOPOLOGY_TYPE type) @@ -255,28 +254,6 @@ static UINT32 topology_node_get_connect_method_semantics(IMFTopologyNode *node) return method; } -static HRESULT topology_node_list_branches(IMFTopologyNode *node, struct list *branches) -{ - struct topology_branch *branch; - DWORD i, count, down_stream; - IMFTopologyNode *down_node; - HRESULT hr; - - hr = IMFTopologyNode_GetOutputCount(node, &count); - for (i = 0; SUCCEEDED(hr) && i < count; ++i) - { - if (FAILED(IMFTopologyNode_GetOutput(node, i, &down_node, &down_stream))) - continue; - - if (SUCCEEDED(hr = topology_branch_create(node, i, down_node, down_stream, &branch))) - list_add_tail(branches, &branch->entry); - - IMFTopologyNode_Release(down_node); - } - - return hr; -} - static void media_type_try_copy_attr(IMFMediaType *dst, IMFMediaType *src, const GUID *attr, HRESULT *hr) { PROPVARIANT value; @@ -761,24 +738,64 @@ static HRESULT topology_branch_connect(IMFTopology *topology, enum connect_metho return hr; } -static HRESULT topology_loader_resolve_branches(struct topoloader_context *context, struct list *branches) +static HRESULT topology_loader_resolve_subgraph(struct topoloader_context *context, IMFTopologyNode *node, DWORD stream) { enum connect_method method_mask = connect_method_from_mf(MF_CONNECT_ALLOW_DECODER); - struct topology_branch *branch, *next; + struct topology_branch *branch = NULL; + IMFTopologyNode *down_node = NULL; + DWORD down_stream; HRESULT hr = S_OK; + DWORD count; + + if (topology_node_get_connect_method_semantics(node) & MF_CONNECT_AS_OPTIONAL_BRANCH) + FIXME("Optional branches are not supported.\n"); + + if (FAILED(hr = IMFTopologyNode_GetOutput(node, stream, &down_node, &down_stream))) + return hr; + + context->resolved_count++; - LIST_FOR_EACH_ENTRY_SAFE(branch, next, branches, struct topology_branch, entry) + if (FAILED(hr = topology_branch_create(node, stream, down_node, down_stream, &branch))) + goto done; + + if (FAILED(hr = topology_branch_clone_nodes(context, branch))) { - list_remove(&branch->entry); + WARN("Failed to clone nodes for branch %s\n", debugstr_topology_branch(branch)); + goto done; + } - if (FAILED(hr = topology_branch_clone_nodes(context, branch))) - WARN("Failed to clone nodes for branch %s\n", debugstr_topology_branch(branch)); - else - hr = topology_branch_connect(context->output_topology, method_mask, branch, NULL); + if (FAILED(hr = topology_branch_connect(context->output_topology, method_mask, branch, NULL))) + goto done; + topology_branch_destroy(branch); + branch = NULL; + + if (SUCCEEDED(hr) && SUCCEEDED(hr = IMFTopologyNode_GetOutputCount(down_node, &count)) && count > down_stream) + hr = topology_loader_resolve_subgraph(context, down_node, down_stream); + +done: + if (branch) topology_branch_destroy(branch); - if (FAILED(hr)) - break; + IMFTopologyNode_Release(down_node); + + return hr; +} + +static HRESULT topology_loader_resolve_source_branch(struct topoloader_context *context, IMFTopologyNode *node) +{ + DWORD i, count; + HRESULT hr; + + if (FAILED(hr = IMFTopologyNode_GetOutputCount(node, &count))) + return hr; + + for (i = 0; i < count; ++i) + { + if (FAILED(hr = topology_loader_resolve_subgraph(context, node, i))) + { + WARN("Failed to resolve subgraph under source node %p, stream %lu.\n", node, i); + return hr; + } } return hr; @@ -1010,14 +1027,14 @@ static void topology_loader_resolve_complete(struct topoloader_context *context) static HRESULT WINAPI topology_loader_Load(IMFTopoLoader *iface, IMFTopology *input_topology, IMFTopology **ret_topology, IMFTopology *current_topology) { - struct list branches = LIST_INIT(branches); struct topoloader_context context = { 0 }; - struct topology_branch *branch, *next; IMFTopology *output_topology; + UINT source_count = 0; IMFTopologyNode *node; unsigned short i = 0; IMFStreamSink *sink; IUnknown *object; + WORD node_count; TOPOID topoid; HRESULT hr = E_FAIL; @@ -1070,23 +1087,26 @@ static HRESULT WINAPI topology_loader_Load(IMFTopoLoader *iface, IMFTopology *in for (i = 0; SUCCEEDED(IMFTopology_GetNode(input_topology, i, &node)); i++) { - hr = topology_node_list_branches(node, &branches); + if (topology_node_get_type(node) == MF_TOPOLOGY_SOURCESTREAM_NODE) + { + source_count++; + + if (topology_node_get_connect_method_semantics(node) & MF_CONNECT_AS_OPTIONAL_BRANCH) + FIXME("Optional branches are not supported.\n"); + hr = topology_loader_resolve_source_branch(&context, node); + } IMFTopologyNode_Release(node); if (FAILED(hr)) break; } - if (SUCCEEDED(hr) && list_empty(&branches)) - hr = MF_E_TOPO_UNSUPPORTED; + IMFTopology_GetNodeCount(input_topology, &node_count); - while (SUCCEEDED(hr) && !list_empty(&branches)) - hr = topology_loader_resolve_branches(&context, &branches); + if (SUCCEEDED(hr) && !context.resolved_count) + hr = MF_E_TOPO_UNSUPPORTED; - LIST_FOR_EACH_ENTRY_SAFE(branch, next, &branches, struct topology_branch, entry) - { - WARN("Failed to resolve branch %s\n", debugstr_topology_branch(branch)); - list_remove(&branch->entry); - topology_branch_destroy(branch); - } + context.resolved_count += source_count; + if (SUCCEEDED(hr) && context.resolved_count != node_count) + WARN("Failed to resolve %u nodes.\n", node_count - context.resolved_count); if (FAILED(hr)) IMFTopology_Release(output_topology); -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/10645