Nikolay Sivov : mf/topology: Implement MF_CONNECT_RESOLVE_INDEPENDENT_OUTPUTTYPES connection method.
Alexandre Julliard
julliard at winehq.org
Mon May 31 15:58:39 CDT 2021
Module: wine
Branch: master
Commit: 33ea3fc8060b55b074a6234c3cb681685a023580
URL: https://source.winehq.org/git/wine.git/?a=commit;h=33ea3fc8060b55b074a6234c3cb681685a023580
Author: Nikolay Sivov <nsivov at codeweavers.com>
Date: Mon May 31 13:28:45 2021 +0300
mf/topology: Implement MF_CONNECT_RESOLVE_INDEPENDENT_OUTPUTTYPES connection method.
Signed-off-by: Nikolay Sivov <nsivov at codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard at winehq.org>
---
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:
More information about the wine-cvs
mailing list