Signed-off-by: Nikolay Sivov nsivov@codeweavers.com --- dlls/mf/topology.c | 99 +++++++++++++++++++++++++++++++++++++--------- 1 file changed, 81 insertions(+), 18 deletions(-)
diff --git a/dlls/mf/topology.c b/dlls/mf/topology.c index bbed2cba893..a054eca27e1 100644 --- a/dlls/mf/topology.c +++ b/dlls/mf/topology.c @@ -2010,7 +2010,10 @@ struct connect_context IMFTopologyNode *upstream_node; IMFTopologyNode *sink; IMFMediaTypeHandler *sink_handler; - const GUID *converter_category; + unsigned int output_index; + unsigned int input_index; + GUID converter_category; + GUID decoder_category; };
typedef HRESULT (*p_connect_func)(struct transform_output_type *output_type, struct connect_context *context); @@ -2142,7 +2145,7 @@ static HRESULT connect_to_converter(struct transform_output_type *output_type, s sink_ctx = *context; sink_ctx.upstream_node = node;
- if (SUCCEEDED(hr = topology_loader_enumerate_output_types(context->converter_category, output_type->type, + if (SUCCEEDED(hr = topology_loader_enumerate_output_types(&context->converter_category, output_type->type, connect_to_sink, &sink_ctx))) { hr = IMFTopology_AddNode(context->context->output_topology, node); @@ -2225,13 +2228,62 @@ static HRESULT topology_loader_get_mft_categories(IMFMediaTypeHandler *handler, return S_OK; }
+static HRESULT topology_loader_connect(IMFMediaTypeHandler *sink_handler, unsigned int sink_method, + struct connect_context *sink_ctx, struct connect_context *convert_ctx, IMFMediaType *media_type) +{ + HRESULT hr; + + if (SUCCEEDED(hr = IMFMediaTypeHandler_IsMediaTypeSupported(sink_handler, media_type, NULL)) + && SUCCEEDED(hr = IMFMediaTypeHandler_SetCurrentMediaType(sink_handler, media_type))) + { + hr = IMFTopologyNode_ConnectOutput(sink_ctx->upstream_node, sink_ctx->output_index, sink_ctx->sink, sink_ctx->input_index); + } + + if (FAILED(hr) && sink_method & MF_CONNECT_ALLOW_CONVERTER) + { + hr = topology_loader_enumerate_output_types(&convert_ctx->converter_category, media_type, connect_to_sink, sink_ctx); + } + + if (FAILED(hr) && sink_method & MF_CONNECT_ALLOW_DECODER) + { + hr = topology_loader_enumerate_output_types(&convert_ctx->decoder_category, media_type, + connect_to_converter, convert_ctx); + } + + return hr; +} + +static HRESULT topology_loader_foreach_source_type(IMFMediaTypeHandler *sink_handler, IMFMediaTypeHandler *source_handler, + unsigned int sink_method, struct connect_context *sink_ctx, struct connect_context *convert_ctx) +{ + unsigned int index = 0; + IMFMediaType *media_type; + HRESULT hr; + + while (SUCCEEDED(hr = IMFMediaTypeHandler_GetMediaTypeByIndex(source_handler, index++, &media_type))) + { + hr = topology_loader_connect(sink_handler, sink_method, sink_ctx, convert_ctx, media_type); + if (SUCCEEDED(hr)) break; + IMFMediaType_Release(media_type); + media_type = NULL; + } + + if (media_type) + { + hr = IMFMediaTypeHandler_SetCurrentMediaType(source_handler, media_type); + IMFMediaType_Release(media_type); + } + + return hr; +} + static HRESULT topology_loader_connect_source_to_sink(struct topoloader_context *context, IMFTopologyNode *source, unsigned int output_index, IMFTopologyNode *sink, unsigned int input_index) { IMFMediaTypeHandler *source_handler = NULL, *sink_handler = NULL; struct connect_context convert_ctx, sink_ctx; MF_CONNECT_METHOD source_method, sink_method; - GUID decode_cat, convert_cat; + unsigned int enumerate_source_types = 0; IMFMediaType *media_type; HRESULT hr;
@@ -2248,35 +2300,46 @@ static HRESULT topology_loader_connect_source_to_sink(struct topoloader_context if (FAILED(IMFTopologyNode_GetUINT32(sink, &MF_TOPONODE_CONNECT_METHOD, &sink_method))) sink_method = MF_CONNECT_ALLOW_DECODER;
- if (FAILED(hr = topology_loader_get_mft_categories(source_handler, &decode_cat, &convert_cat))) - goto done; - sink_ctx.context = context; sink_ctx.upstream_node = source; sink_ctx.sink = sink; sink_ctx.sink_handler = sink_handler; + sink_ctx.output_index = output_index; + sink_ctx.input_index = input_index;
convert_ctx = sink_ctx; - convert_ctx.converter_category = &convert_cat; + if (FAILED(hr = topology_loader_get_mft_categories(source_handler, &convert_ctx.decoder_category, + &convert_ctx.converter_category))) + goto done;
- if (SUCCEEDED(hr = IMFMediaTypeHandler_GetCurrentMediaType(source_handler, &media_type))) + IMFTopology_GetUINT32(context->output_topology, &MF_TOPOLOGY_ENUMERATE_SOURCE_TYPES, &enumerate_source_types); + + if (enumerate_source_types) { - /* Direct connection. */ - if (SUCCEEDED(hr = IMFMediaTypeHandler_IsMediaTypeSupported(sink_handler, media_type, NULL)) - && SUCCEEDED(hr = IMFMediaTypeHandler_SetCurrentMediaType(sink_handler, media_type))) + if (source_method & MF_CONNECT_RESOLVE_INDEPENDENT_OUTPUTTYPES) { - hr = IMFTopologyNode_ConnectOutput(source, output_index, sink, input_index); + hr = topology_loader_foreach_source_type(sink_handler, source_handler, MF_CONNECT_ALLOW_DECODER, + &sink_ctx, &convert_ctx); } - if (FAILED(hr) && sink_method & MF_CONNECT_ALLOW_CONVERTER) + else { - hr = topology_loader_enumerate_output_types(&convert_cat, media_type, connect_to_sink, &sink_ctx); + hr = topology_loader_foreach_source_type(sink_handler, source_handler, MF_CONNECT_DIRECT, + &sink_ctx, &convert_ctx); + if (FAILED(hr)) + hr = topology_loader_foreach_source_type(sink_handler, source_handler, MF_CONNECT_ALLOW_CONVERTER, + &sink_ctx, &convert_ctx); + if (FAILED(hr)) + hr = topology_loader_foreach_source_type(sink_handler, source_handler, MF_CONNECT_ALLOW_DECODER, + &sink_ctx, &convert_ctx); } - if (FAILED(hr) && sink_method & MF_CONNECT_ALLOW_DECODER) + } + else + { + if (SUCCEEDED(hr = IMFMediaTypeHandler_GetCurrentMediaType(source_handler, &media_type))) { - hr = topology_loader_enumerate_output_types(&decode_cat, media_type, connect_to_converter, &convert_ctx); + hr = topology_loader_connect(sink_handler, sink_method, &sink_ctx, &convert_ctx, media_type); + IMFMediaType_Release(media_type); } - - IMFMediaType_Release(media_type); }
done: