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