[v2 09/10] mf: Introduce topology_loader_connect_nodes() and topology_loader_connect_direct() helper functions.

Sergio Gómez Del Real sdelreal at codeweavers.com
Sun Jul 5 09:16:14 CDT 2020


Signed-off-by: Sergio Gómez Del Real <sdelreal at codeweavers.com>
---
 dlls/mf/topology.c | 134 +++++++++++++++++++++++++++++++++++++++++++--
 1 file changed, 129 insertions(+), 5 deletions(-)

diff --git a/dlls/mf/topology.c b/dlls/mf/topology.c
index 1284bde12a..3ee8ddc40b 100644
--- a/dlls/mf/topology.c
+++ b/dlls/mf/topology.c
@@ -2016,6 +2016,107 @@ static HRESULT topology_loader_clone_node(struct topoloader_context *context, IM
     return hr;
 }
 
+static HRESULT topology_loader_is_mediatype_compatible_with_sink(IMFMediaTypeHandler *sink_mediatype_handler, IMFMediaType *mediatype)
+{
+    IMFMediaType *sink_mediatype;
+    HRESULT hr;
+
+    if (FAILED(hr = IMFMediaTypeHandler_GetCurrentMediaType(sink_mediatype_handler, &sink_mediatype)))
+        hr = IMFMediaTypeHandler_GetMediaTypeByIndex(sink_mediatype_handler, 0, &sink_mediatype);
+
+    if (SUCCEEDED(hr))
+    {
+        DWORD flags;
+
+        if (SUCCEEDED(hr = IMFMediaType_IsEqual(mediatype, sink_mediatype, &flags)))
+            if (!(flags & MF_MEDIATYPE_EQUAL_FORMAT_DATA))
+                hr = MF_E_INVALIDMEDIATYPE;
+
+        IMFMediaType_Release(sink_mediatype);
+    }
+
+    return hr;
+}
+
+static HRESULT topology_loader_connect_direct(IMFTopologyNode *upstream_node, unsigned int output_index,
+        IMFTopologyNode *downstream_node, unsigned int input_index, IMFMediaType *output_type)
+{
+    MF_TOPOLOGY_TYPE node_type;
+    HRESULT hr;
+
+    IMFTopologyNode_GetNodeType(downstream_node, &node_type);
+
+    if (node_type == MF_TOPOLOGY_TRANSFORM_NODE)
+    {
+        IMFTransform *mft;
+
+        if (SUCCEEDED(hr = IMFTopologyNode_GetObject(downstream_node, (IUnknown **)&mft)))
+        {
+            hr = IMFTransform_SetInputType(mft, input_index, output_type, 0);
+            IMFTransform_Release(mft);
+        }
+    }
+    else if (node_type == MF_TOPOLOGY_OUTPUT_NODE)
+    {
+        IMFMediaTypeHandler *mediatype_handler;
+        IMFStreamSink *sink;
+
+        if (SUCCEEDED(hr = IMFTopologyNode_GetObject(downstream_node, (IUnknown **)&sink)))
+        {
+            if (SUCCEEDED(hr = IMFStreamSink_GetMediaTypeHandler(sink, &mediatype_handler)))
+            {
+                if (SUCCEEDED(hr = topology_loader_is_mediatype_compatible_with_sink(mediatype_handler, output_type)))
+                    IMFMediaTypeHandler_SetCurrentMediaType(mediatype_handler, output_type);
+                IMFMediaTypeHandler_Release(mediatype_handler);
+            }
+            IMFStreamSink_Release(sink);
+        }
+    }
+    else if (node_type == MF_TOPOLOGY_TEE_NODE)
+    {
+        FIXME("Tee nodes are not supported.\n");
+        hr = MF_E_INVALIDTYPE;
+    }
+    else
+    {
+        WARN("Unexpected node type %d.\n", node_type);
+        hr = MF_E_INVALIDTYPE;
+    }
+
+    if (SUCCEEDED(hr))
+        hr = IMFTopologyNode_ConnectOutput(upstream_node, output_index, downstream_node, input_index);
+
+    return hr;
+}
+
+static HRESULT topology_loader_connect_nodes(struct topoloader_context *context, IMFTopologyNode *upstream_node, unsigned int output_index,
+        IMFTopologyNode *downstream_node, unsigned int input_index, IMFMediaType *output_type, UINT32 connect_method)
+{
+    HRESULT hr;
+    GUID major;
+
+    if (FAILED(hr = IMFMediaType_GetMajorType(output_type, &major)))
+        goto out;
+
+    /* always try first a direct connection */
+    if (FAILED(hr = topology_loader_connect_direct(upstream_node, output_index, downstream_node, input_index, output_type))
+        && connect_method != MF_CONNECT_DIRECT)
+    {
+        switch (connect_method)
+        {
+            case MF_CONNECT_ALLOW_CONVERTER:
+                hr = S_OK;
+                break;
+            case MF_CONNECT_ALLOW_DECODER:
+                hr = S_OK;
+                break;
+        }
+    }
+
+out:
+    return hr;
+}
+
 static HRESULT topology_loader_connect_source(struct topoloader_context *context, IMFTopologyNode *source_node,
         IMFTopologyNode *downstream_node, unsigned int input_index)
 {
@@ -2074,13 +2175,36 @@ static HRESULT topology_loader_connect_source(struct topoloader_context *context
         src_mediatypes[0] = mtype_src;
 
     hr = IMFAttributes_GetUINT32(attrs_src, &MF_TOPONODE_CONNECT_METHOD, &method);
-
-    for (i = 0; i < num_media_types; i++)
+    if (!enum_src_types || (hr == S_OK && !(method & MF_CONNECT_RESOLVE_INDEPENDENT_OUTPUTTYPES)))
     {
-        if (SUCCEEDED(hr = IMFMediaTypeHandler_SetCurrentMediaType(mth_src, src_mediatypes[i])))
-            break;
+        for (method = MF_CONNECT_DIRECT; method < MF_CONNECT_RESOLVE_INDEPENDENT_OUTPUTTYPES; method++)
+        {
+            for (i = 0; i < num_media_types; i++)
+            {
+                IMFMediaTypeHandler_SetCurrentMediaType(mth_src, src_mediatypes[i]);
+                if (SUCCEEDED(hr = topology_loader_connect_nodes(context, source_node, 0, downstream_node, input_index, src_mediatypes[i], method)))
+                    goto out;
+            }
+            if (method == MF_CONNECT_ALLOW_CONVERTER)
+                method++;
+        }
+    }
+    else
+    {
+        for (i = 0; i < num_media_types; i++)
+        {
+            for (method = MF_CONNECT_DIRECT; method < MF_CONNECT_RESOLVE_INDEPENDENT_OUTPUTTYPES; method++)
+            {
+                IMFMediaTypeHandler_SetCurrentMediaType(mth_src, src_mediatypes[i]);
+                if (SUCCEEDED(hr = topology_loader_connect_nodes(context, source_node, 0, downstream_node, input_index, src_mediatypes[i], method)))
+                    goto out;
+                if (method == MF_CONNECT_ALLOW_CONVERTER)
+                    method++;
+            }
+        }
     }
 
+out:
     while (num_media_types--)
         IMFMediaType_Release(src_mediatypes[num_media_types]);
     IMFMediaTypeHandler_Release(mth_src);
@@ -2105,7 +2229,7 @@ static HRESULT topology_loader_connect_transform(struct topoloader_context *cont
     i = 0;
     while (SUCCEEDED(hr = IMFTransform_GetOutputAvailableType(transform, output_index, i++, &mediatype)))
     {
-        hr = S_OK;
+        hr = topology_loader_connect_nodes(context, transform_node, output_index, downstream_node, input_index, mediatype, method);
 
         IMFMediaType_Release(mediatype);
 
-- 
2.17.1




More information about the wine-devel mailing list