mf/topology: Implement MF_CONNECT_RESOLVE_INDEPENDENT_OUTPUTTYPES connection method.

Signed-off-by: Nikolay Sivov <nsivov@codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
Nikolay Sivov 2021-05-31 13:28:45 +03:00 committed by Alexandre Julliard
parent 0abc002a3e
commit 33ea3fc806
1 changed files with 81 additions and 18 deletions

View File

@ -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: