From: Conor McCarthy <cmccarthy@codeweavers.com> --- dlls/mf/topology_loader.c | 95 ++++++++++++++++++++++++++++++--------- 1 file changed, 75 insertions(+), 20 deletions(-) diff --git a/dlls/mf/topology_loader.c b/dlls/mf/topology_loader.c index c34e150f27a..7a32a6a0a44 100644 --- a/dlls/mf/topology_loader.c +++ b/dlls/mf/topology_loader.c @@ -271,6 +271,67 @@ static HRESULT update_media_type_from_upstream(IMFMediaType *media_type, IMFMedi return hr; } +struct connection_context_type_enumerator +{ + IMFMediaTypeHandler *handler; + IMFMediaType *current; + IMFMediaType *index0; + BOOL enumerate; + int index; +}; + +static void type_enumerator_release(struct connection_context_type_enumerator *enumerator) +{ + if (enumerator->current) + IMFMediaType_Release(enumerator->current); + if (enumerator->index0) + IMFMediaType_Release(enumerator->index0); + if (enumerator->handler) + IMFMediaTypeHandler_Release(enumerator->handler); +} + +struct connection_context +{ + MF_TOPOLOGY_TYPE up_node_type; + struct connection_context_type_enumerator up_types; +}; + +static void connection_context_destroy(struct connection_context *context) +{ + type_enumerator_release(&context->up_types); +} + +static HRESULT connection_context_init(struct connection_context *context, IMFTopology *topology, + struct topology_branch *branch, MF_CONNECT_METHOD method, BOOL enumerate_source_types) +{ + IMFMediaType *up_type; + HRESULT hr; + + if (FAILED(hr = IMFTopologyNode_GetNodeType(branch->up.node, &context->up_node_type))) + return hr; + + if (FAILED(hr = topology_node_get_type_handler(branch->up.node, branch->up.stream, TRUE, &context->up_types.handler))) + return hr; + + enumerate_source_types = context->up_node_type == MF_TOPOLOGY_SOURCESTREAM_NODE && enumerate_source_types; + if (!(context->up_types.enumerate = enumerate_source_types)) + { + hr = IMFMediaTypeHandler_GetCurrentMediaType(context->up_types.handler, &context->up_types.current); + if (context->up_node_type != MF_TOPOLOGY_SOURCESTREAM_NODE) + context->up_types.enumerate = FAILED(hr); + } + + if (FAILED(hr = IMFMediaTypeHandler_GetMediaTypeByIndex(context->up_types.handler, 0, &up_type))) + goto failed; + context->up_types.index0 = up_type; + + return S_OK; + +failed: + connection_context_destroy(context); + return hr; +} + static HRESULT topology_branch_connect(IMFTopology *topology, MF_CONNECT_METHOD method_mask, struct topology_branch *branch, BOOL enumerate_source_types); static HRESULT topology_branch_connect_down(IMFTopology *topology, MF_CONNECT_METHOD method_mask, @@ -472,16 +533,13 @@ done: } static HRESULT topology_branch_foreach_up_types(IMFTopology *topology, MF_CONNECT_METHOD method_mask, - struct topology_branch *branch) + struct topology_branch *branch, struct connection_context *context) { - IMFMediaTypeHandler *handler; + IMFMediaTypeHandler *handler = context->up_types.handler; IMFMediaType *type; DWORD index = 0; HRESULT hr; - if (FAILED(hr = topology_node_get_type_handler(branch->up.node, branch->up.stream, TRUE, &handler))) - return hr; - while (SUCCEEDED(hr = IMFMediaTypeHandler_GetMediaTypeByIndex(handler, index++, &type))) { hr = topology_branch_connect_down(topology, method_mask, branch, type); @@ -492,50 +550,47 @@ static HRESULT topology_branch_foreach_up_types(IMFTopology *topology, MF_CONNEC break; } - IMFMediaTypeHandler_Release(handler); return hr; } static HRESULT topology_branch_connect(IMFTopology *topology, MF_CONNECT_METHOD method_mask, struct topology_branch *branch, BOOL enumerate_source_types) { + struct connection_context context = {0}; UINT32 method; HRESULT hr; TRACE("topology %p, method_mask %#x, branch %s.\n", topology, method_mask, debugstr_topology_branch(branch)); + if (FAILED(hr = connection_context_init(&context, topology, branch, method_mask, enumerate_source_types))) + return hr; + if (FAILED(IMFTopologyNode_GetUINT32(branch->up.node, &MF_TOPONODE_CONNECT_METHOD, &method))) method = MF_CONNECT_DIRECT; if (enumerate_source_types) { if (method & MF_CONNECT_RESOLVE_INDEPENDENT_OUTPUTTYPES) - hr = topology_branch_foreach_up_types(topology, method_mask & MF_CONNECT_ALLOW_DECODER, branch); + hr = topology_branch_foreach_up_types(topology, method_mask & MF_CONNECT_ALLOW_DECODER, branch, &context); else { - hr = topology_branch_foreach_up_types(topology, method_mask & MF_CONNECT_DIRECT, branch); + hr = topology_branch_foreach_up_types(topology, method_mask & MF_CONNECT_DIRECT, branch, &context); if (FAILED(hr)) - hr = topology_branch_foreach_up_types(topology, method_mask & MF_CONNECT_ALLOW_CONVERTER, branch); + hr = topology_branch_foreach_up_types(topology, method_mask & MF_CONNECT_ALLOW_CONVERTER, branch, &context); if (FAILED(hr)) - hr = topology_branch_foreach_up_types(topology, method_mask & MF_CONNECT_ALLOW_DECODER, branch); + hr = topology_branch_foreach_up_types(topology, method_mask & MF_CONNECT_ALLOW_DECODER, branch, &context); } } else { - IMFMediaTypeHandler *up_handler; IMFMediaType *up_type; - if (FAILED(hr = topology_node_get_type_handler(branch->up.node, branch->up.stream, TRUE, &up_handler))) - return hr; - if (SUCCEEDED(hr = IMFMediaTypeHandler_GetCurrentMediaType(up_handler, &up_type)) - || SUCCEEDED(hr = IMFMediaTypeHandler_GetMediaTypeByIndex(up_handler, 0, &up_type))) - { - hr = topology_branch_connect_down(topology, method_mask, branch, up_type); - IMFMediaType_Release(up_type); - } - IMFMediaTypeHandler_Release(up_handler); + up_type = context.up_types.current ? context.up_types.current : context.up_types.index0; + hr = topology_branch_connect_down(topology, method_mask, branch, up_type); } + connection_context_destroy(&context); + TRACE("returning %#lx\n", hr); return hr; } -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/10009