From: Conor McCarthy <cmccarthy@codeweavers.com> To avoid test failure, decoder connection must also be switched to always use this pathway. The transform output type must not be set before connecting the down branch because types will not be enumerated if the output type is set, and the correct type should be set in topology_branch_connect_up_types(). --- dlls/mf/topology.c | 4 +- dlls/mf/topology_loader.c | 136 +++++++++++++++++++++++++------------- 2 files changed, 91 insertions(+), 49 deletions(-) diff --git a/dlls/mf/topology.c b/dlls/mf/topology.c index 572d4d426d3..48ce941f2dd 100644 --- a/dlls/mf/topology.c +++ b/dlls/mf/topology.c @@ -1887,9 +1887,9 @@ static HRESULT WINAPI type_handler_IsMediaTypeSupported(IMFMediaTypeHandler *ifa if (handler->transform) { if (handler->output) - return IMFTransform_SetOutputType(handler->transform, handler->stream, in_type, MFT_SET_TYPE_TEST_ONLY); + return IMFTransform_SetOutputType(handler->transform, handler->stream, in_type, 0); else - return IMFTransform_SetInputType(handler->transform, handler->stream, in_type, MFT_SET_TYPE_TEST_ONLY); + return IMFTransform_SetInputType(handler->transform, handler->stream, in_type, 0); } if (FAILED(hr = IMFMediaTypeHandler_GetCurrentMediaType(iface, &type))) diff --git a/dlls/mf/topology_loader.c b/dlls/mf/topology_loader.c index e499d84d4aa..6e92e4675b0 100644 --- a/dlls/mf/topology_loader.c +++ b/dlls/mf/topology_loader.c @@ -389,6 +389,24 @@ static void connection_context_init_down_type_enumeration(struct connection_cont IMFMediaTypeHandler_GetMediaTypeByIndex(context->down_types.handler, 0, &context->down_types.index0); } +static HRESULT topology_branch_complete_connection(struct topology_branch *branch, struct connection_context *context, + IMFMediaType *up_type) +{ + HRESULT hr = S_OK; + + /* Current type is set for sources when enumerating, and always for transforms. */ + if (context->up_types.enumerate || context->up_node_type == MF_TOPOLOGY_TRANSFORM_NODE) + hr = IMFMediaTypeHandler_SetCurrentMediaType(context->up_types.handler, up_type); + + if (SUCCEEDED(hr)) + { + TRACE("Connected branch %s with up type %s.\n", debugstr_topology_branch(branch), debugstr_media_subtype(up_type)); + hr = IMFTopologyNode_ConnectOutput(branch->up.node, branch->up.stream, branch->down.node, branch->down.stream); + } + + return hr; +} + static HRESULT clone_media_type(IMFMediaType *in_type, IMFMediaType **out_type) { IMFMediaType *media_type; @@ -425,7 +443,7 @@ static HRESULT clone_media_type_updated_from_upstream(IMFMediaType *in_type, IMF 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, - struct topology_branch *branch, IMFMediaType *up_type, struct connection_context *context); + struct topology_branch *branch, struct connection_context *context); static HRESULT topology_branch_connect_indirect(IMFTopology *topology, struct topology_branch *branch, BOOL enumerate, IMFMediaType *up_type, IMFMediaType *down_type) { @@ -473,46 +491,24 @@ static HRESULT topology_branch_connect_indirect(IMFTopology *topology, struct topology_branch down_branch = {.up.node = node, .down = branch->down}; struct topology_branch up_branch = {.up = branch->up, .down.node = node}; struct connection_context up_context = {0}; - MF_CONNECT_METHOD method = MF_CONNECT_ALLOW_CONVERTER; - IMFMediaType *media_type; if (FAILED(IMFActivate_ActivateObject(activates[i], &IID_IMFTransform, (void **)&transform))) continue; IMFTopologyNode_SetObject(node, (IUnknown *)transform); + IMFTransform_Release(transform); IMFTopologyNode_DeleteItem(node, &MF_TOPONODE_TRANSFORM_OBJECTID); if (SUCCEEDED(IMFActivate_GetGUID(activates[i], &MFT_TRANSFORM_CLSID_Attribute, &guid))) IMFTopologyNode_SetGUID(node, &MF_TOPONODE_TRANSFORM_OBJECTID, &guid); if (FAILED(hr = connection_context_init(&up_context, topology, &up_branch, MF_CONNECT_DIRECT, enumerate))) - { - IMFTransform_Release(transform); continue; - } - - hr = topology_branch_connect_down(topology, MF_CONNECT_DIRECT, &up_branch, up_type, &up_context); + hr = topology_branch_connect_down(topology, MF_CONNECT_DIRECT, &up_branch, &up_context); connection_context_destroy(&up_context); - if (down_type && SUCCEEDED(MFCreateMediaType(&media_type))) - { - if (SUCCEEDED(IMFMediaType_CopyAllItems(down_type, (IMFAttributes *)media_type)) - && SUCCEEDED(update_media_type_from_upstream(media_type, up_type)) - && SUCCEEDED(IMFTransform_SetOutputType(transform, 0, media_type, 0))) - method = MF_CONNECT_DIRECT; - IMFMediaType_Release(media_type); - } - IMFTransform_Release(transform); - - if (SUCCEEDED(hr) && method != MF_CONNECT_DIRECT - && SUCCEEDED(IMFTransform_GetOutputAvailableType(transform, 0, 0, &media_type))) - { - if (SUCCEEDED(update_media_type_from_upstream(media_type, up_type))) - IMFTransform_SetOutputType(transform, 0, media_type, 0); - IMFMediaType_Release(media_type); - } if (SUCCEEDED(hr)) { - hr = topology_branch_connect(topology, method, &down_branch, !down_type); + hr = topology_branch_connect(topology, MF_CONNECT_ALLOW_CONVERTER, &down_branch, FALSE); /* Failure to connect a converter must result in MF_E_TOPO_CODEC_NOT_FOUND */ if (hr == MF_E_INVALIDMEDIATYPE) hr = MF_E_TOPO_CODEC_NOT_FOUND; @@ -600,6 +596,30 @@ failed: return hr; } +static HRESULT topology_branch_connect_up_types(struct topology_branch *branch, struct connection_context *context) +{ + IMFMediaTypeHandler *down_handler = context->down_types.handler; + IMFMediaType *up_type; + HRESULT hr; + + /* The downstream current media type is not used here. Setting it in advance has no effect on the type used. + * TODO: unless MF_TOPONODE_LOCKED is set? + * Up and down transform media types are always set, even if they already match. + * If enumeration is disabled and upstream current type is null, the available type at index 0 is used. */ + + type_enumerator_reset(&context->up_types); + while (SUCCEEDED(hr = type_enumerator_get_next_media_type(&context->up_types, &up_type))) + { + if (SUCCEEDED(hr = IMFMediaTypeHandler_IsMediaTypeSupported(down_handler, up_type, NULL))) + hr = topology_branch_complete_connection(branch, context, up_type); + IMFMediaType_Release(up_type); + if (SUCCEEDED(hr)) + break; + } + + return hr; +} + static HRESULT topology_branch_connect_converter_with_types(IMFTopology *topology, struct topology_branch *branch, IMFMediaType *up_type, IMFMediaType *down_type, struct connection_context *context) { @@ -747,7 +767,7 @@ static HRESULT topology_branch_connect_converter(IMFTopology *topology, return hr; } -static HRESULT topology_branch_connect_down(IMFTopology *topology, MF_CONNECT_METHOD method_mask, +static HRESULT topology_branch_connect_independent_outtypes(IMFTopology *topology, MF_CONNECT_METHOD method_mask, struct topology_branch *branch, IMFMediaType *up_type, struct connection_context *context) { IMFMediaTypeHandler *down_handler = context->down_types.handler; @@ -798,7 +818,7 @@ static HRESULT topology_branch_foreach_up_types(IMFTopology *topology, MF_CONNEC while (SUCCEEDED(hr = IMFMediaTypeHandler_GetMediaTypeByIndex(handler, index++, &type))) { - hr = topology_branch_connect_down(topology, method_mask, branch, type, context); + hr = topology_branch_connect_independent_outtypes(topology, method_mask, branch, type, context); if (SUCCEEDED(hr)) hr = IMFMediaTypeHandler_SetCurrentMediaType(handler, type); IMFMediaType_Release(type); @@ -809,11 +829,43 @@ static HRESULT topology_branch_foreach_up_types(IMFTopology *topology, MF_CONNEC return hr; } +static HRESULT topology_branch_connect_down(IMFTopology *topology, MF_CONNECT_METHOD method, + struct topology_branch *branch, struct connection_context *context) +{ + IMFMediaType *up_type; + HRESULT hr; + + TRACE("topology %p, branch %s.\n", topology, debugstr_topology_branch(branch)); + + if (SUCCEEDED(hr = topology_branch_connect_up_types(branch, context))) + return hr; + + if (!(method & MF_CONNECT_ALLOW_DECODER)) + return hr; + + if (SUCCEEDED(hr = topology_branch_connect_converter(topology, branch, context))) + return hr; + + if ((method & MF_CONNECT_ALLOW_DECODER) != MF_CONNECT_ALLOW_DECODER) + return hr; + + type_enumerator_reset(&context->up_types); + while (SUCCEEDED(hr = type_enumerator_get_next_media_type(&context->up_types, &up_type))) + { + hr = topology_branch_connect_indirect(topology, branch, context->up_types.enumerate, up_type, NULL); + IMFMediaType_Release(up_type); + if (SUCCEEDED(hr)) + return hr; + } + + return MF_E_TOPO_CODEC_NOT_FOUND; +} + 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; + UINT32 up_method, down_method; HRESULT hr; TRACE("topology %p, method_mask %#x, branch %s.\n", topology, method_mask, debugstr_topology_branch(branch)); @@ -821,12 +873,16 @@ static HRESULT topology_branch_connect(IMFTopology *topology, MF_CONNECT_METHOD 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 (FAILED(IMFTopologyNode_GetUINT32(branch->up.node, &MF_TOPONODE_CONNECT_METHOD, &up_method))) + up_method = MF_CONNECT_DIRECT; + + if (FAILED(IMFTopologyNode_GetUINT32(branch->down.node, &MF_TOPONODE_CONNECT_METHOD, &down_method))) + down_method = MF_CONNECT_ALLOW_DECODER; + down_method &= method_mask; if (enumerate_source_types) { - if (method & MF_CONNECT_RESOLVE_INDEPENDENT_OUTPUTTYPES) + if (up_method & MF_CONNECT_RESOLVE_INDEPENDENT_OUTPUTTYPES) hr = topology_branch_foreach_up_types(topology, method_mask & MF_CONNECT_ALLOW_DECODER, branch, &context); else { @@ -839,21 +895,7 @@ static HRESULT topology_branch_connect(IMFTopology *topology, MF_CONNECT_METHOD } else { - IMFMediaType *up_type; - - type_enumerator_reset(&context.up_types); - while (SUCCEEDED(type_enumerator_get_next_media_type(&context.up_types, &up_type))) - { - hr = topology_branch_connect_down(topology, method_mask, branch, up_type, &context); - /* Upstream type is left unset only for an unenumerated media source. */ - if (SUCCEEDED(hr) && context.up_node_type != MF_TOPOLOGY_SOURCESTREAM_NODE) - hr = IMFMediaTypeHandler_SetCurrentMediaType(context.up_types.handler, up_type); - IMFMediaType_Release(up_type); - if (SUCCEEDED(hr)) - break; - } - if (hr == MF_E_INVALIDMEDIATYPE && context.up_types.enumerate) - hr = MF_E_NO_MORE_TYPES; + hr = topology_branch_connect_down(topology, down_method, branch, &context); } connection_context_destroy(&context); -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/10009