[v2 10/10] mf: Introduce topology_loader_connect_converter_node() and topology_loader_connect_decoder_node() helper functions.

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


Signed-off-by: Sergio Gómez Del Real <sdelreal at codeweavers.com>
---
 dlls/mf/Makefile.in |   2 +-
 dlls/mf/tests/mf.c  |   4 --
 dlls/mf/topology.c  | 124 +++++++++++++++++++++++++++++++++++++++++++-
 3 files changed, 123 insertions(+), 7 deletions(-)

diff --git a/dlls/mf/Makefile.in b/dlls/mf/Makefile.in
index fe156e43ab..34118fed67 100644
--- a/dlls/mf/Makefile.in
+++ b/dlls/mf/Makefile.in
@@ -1,6 +1,6 @@
 MODULE    = mf.dll
 IMPORTLIB = mf
-IMPORTS   = advapi32 mfplat ole32 uuid mfuuid
+IMPORTS   = advapi32 mfplat ole32 uuid mfuuid wmcodecdspuuid
 
 EXTRADLLFLAGS = -mno-cygwin
 
diff --git a/dlls/mf/tests/mf.c b/dlls/mf/tests/mf.c
index 28efe310f6..0d7ab15d8a 100644
--- a/dlls/mf/tests/mf.c
+++ b/dlls/mf/tests/mf.c
@@ -1841,7 +1841,6 @@ todo_wine
 
     /* if no current media type set, loader uses first index exclusively */
     hr = IMFTopoLoader_Load(loader, topology, &full_topology, NULL);
-todo_wine
     ok(hr == MF_E_TOPO_CODEC_NOT_FOUND, "Unexpected hr %#x.\n", hr);
 
     hr = IMFStreamDescriptor_GetMediaTypeHandler(sd, &mth);
@@ -1855,7 +1854,6 @@ todo_wine
     ok(hr == S_OK, "Failed setting current media type, hr %#x.\n", hr);
 
     hr = IMFTopoLoader_Load(loader, topology, &full_topology, NULL);
-todo_wine
     ok(hr == MF_E_TOPO_CODEC_NOT_FOUND, "Unexpected hr %#x.\n", hr);
 
     hr = IMFMediaTypeHandler_GetMediaTypeByIndex(mth, 1, &media_type);
@@ -1935,7 +1933,6 @@ todo_wine
     ok(hr == S_OK, "Failed to resolve topology, hr %#x.\n", hr);
     hr = IMFTopology_GetNodeCount(full_topology, &node_count);
     ok(hr == S_OK, "Failed to get node count, hr %#x.\n", hr);
-todo_wine
     ok(node_count == 3, "Unexpected node count %d.\n", node_count);
     IMFTopology_Release(full_topology);
 
@@ -1952,7 +1949,6 @@ todo_wine
 
     hr = IMFTopology_GetNodeCount(full_topology, &node_count);
     ok(hr == S_OK, "Failed to get node count, hr %#x.\n", hr);
-todo_wine
     ok(node_count == 3, "Unexpected node count %d.\n", node_count);
 
     /* now test without MF_CONNECT_RESOLVE_INDEPENDENT_OUTPUTTYPES on source */
diff --git a/dlls/mf/topology.c b/dlls/mf/topology.c
index 3ee8ddc40b..d278f84899 100644
--- a/dlls/mf/topology.c
+++ b/dlls/mf/topology.c
@@ -29,6 +29,7 @@
 #include "mfapi.h"
 #include "mferror.h"
 #include "mfidl.h"
+#include "wmcodecdsp.h"
 
 #include "wine/debug.h"
 
@@ -2089,15 +2090,134 @@ static HRESULT topology_loader_connect_direct(IMFTopologyNode *upstream_node, un
     return hr;
 }
 
+static HRESULT topology_loader_connect_converter_node(struct topoloader_context *context, IMFTopologyNode *upstream_node, unsigned int output_index,
+        IMFTopologyNode *downstream_node, unsigned int input_index, IMFMediaType *output_type, const CLSID *clsid)
+{
+    IMFTransform *transform = NULL;
+    IMFMediaType *mediatype = NULL;
+    HRESULT hr;
+
+    if (FAILED(hr = CoCreateInstance(clsid, NULL, CLSCTX_INPROC_SERVER, &IID_IMFTransform, (void **)&transform)))
+    {
+        WARN("Failed to create converter transform for %s, hr %#x.\n", debugstr_guid(clsid), hr);
+        return hr;
+    }
+
+    if (SUCCEEDED(hr = IMFTransform_SetInputType(transform, 0, output_type, 0)))
+    {
+        IMFTopologyNode *converter_node;
+
+        MFCreateTopologyNode(MF_TOPOLOGY_TRANSFORM_NODE, &converter_node);
+        IMFTopologyNode_SetObject(converter_node, (IUnknown *)transform);
+
+        if (SUCCEEDED(hr = topology_loader_connect_direct(upstream_node, output_index, converter_node, 0, mediatype)))
+        {
+            unsigned int i = 0;
+            while (SUCCEEDED(hr = IMFTransform_GetOutputAvailableType(transform, 0, i++, &mediatype)))
+            {
+                hr = topology_loader_connect_direct(converter_node, 0, downstream_node, input_index, mediatype);
+
+                IMFMediaType_Release(mediatype);
+
+                if (SUCCEEDED(hr))
+                {
+                    IMFTopology_AddNode(context->output_topology, converter_node);
+                    break;
+                }
+            }
+        }
+
+        IMFTransform_Release(transform);
+        IMFTopologyNode_Release(converter_node);
+    }
+
+    return hr;
+}
+
+static HRESULT topology_loader_connect_decoder_node(struct topoloader_context *context, IMFTopologyNode *upstream_node, unsigned int output_index,
+        IMFTopologyNode *downstream_node, unsigned int input_index, IMFMediaType *input_type, const CLSID *clsid)
+{
+    HRESULT hr = MF_E_TOPO_CODEC_NOT_FOUND;
+    unsigned int i = 0, j = 0, count = 0;
+    MFT_REGISTER_TYPE_INFO input_info;
+    IMFMediaType *current_mediatype;
+    IMFActivate **activators = NULL;
+    IMFTransform *transform = NULL;
+    IMFTopologyNode *decoder_node;
+    const GUID *category;
+
+    IMFMediaType_GetMajorType(input_type, &input_info.guidMajorType);
+    IMFMediaType_GetGUID(input_type, &MF_MT_SUBTYPE, &input_info.guidSubtype);
+
+    if (IsEqualGUID(&MFMediaType_Audio, &input_info.guidMajorType))
+        category = &MFT_CATEGORY_AUDIO_DECODER;
+    else
+        category = &MFT_CATEGORY_VIDEO_DECODER;
+
+    if (SUCCEEDED(MFTEnumEx(*category, MFT_ENUM_FLAG_ALL, &input_info, NULL, &activators, &count)))
+    {
+        for (i = 0; i < count; ++i)
+        {
+            if (FAILED(IMFActivate_ActivateObject(activators[i], &IID_IMFTransform, (void **)&transform)))
+            {
+                WARN("Failed to activate transform, hr %#x.\n", hr);
+                continue;
+            }
+
+            if (SUCCEEDED(MFCreateTopologyNode(MF_TOPOLOGY_TRANSFORM_NODE, &decoder_node))
+                && SUCCEEDED(IMFTransform_SetInputType(transform, 0, input_type, 0))
+                && SUCCEEDED(IMFTopologyNode_SetObject(decoder_node, (IUnknown *)transform)))
+            {
+                j = 0;
+                while (SUCCEEDED(IMFTransform_GetOutputAvailableType(transform, 0, j++, &current_mediatype)))
+                {
+                    if (SUCCEEDED(hr = topology_loader_connect_direct(decoder_node, 0, downstream_node, input_index, current_mediatype))
+                        || SUCCEEDED(hr = topology_loader_connect_converter_node(context, decoder_node, 0, downstream_node, input_index, current_mediatype, clsid)))
+                    {
+                        IMFTopology_AddNode(context->output_topology, decoder_node);
+                        IMFTransform_SetOutputType(transform, 0, current_mediatype, 0);
+                        IMFMediaType_Release(current_mediatype);
+                        break;
+                    }
+                    IMFMediaType_Release(current_mediatype);
+                }
+                IMFTopologyNode_Release(decoder_node);
+            }
+
+            IMFTransform_Release(transform);
+
+            if (SUCCEEDED(hr))
+                break;
+        }
+        for (i = 0; i < count; ++i)
+            IMFActivate_Release(activators[i]);
+        CoTaskMemFree(activators);
+    }
+
+    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)
 {
+    const GUID *clsid;
     HRESULT hr;
     GUID major;
 
     if (FAILED(hr = IMFMediaType_GetMajorType(output_type, &major)))
         goto out;
 
+    if (IsEqualGUID(&major, &MFMediaType_Video))
+        clsid = &CLSID_VideoProcessorMFT;
+    else if (IsEqualGUID(&major, &MFMediaType_Audio))
+        clsid = &CLSID_CResamplerMediaObject;
+    else
+    {
+        WARN("Unexpected major type %s.\n", debugstr_guid(&major));
+        hr = E_UNEXPECTED;
+        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)
@@ -2105,10 +2225,10 @@ static HRESULT topology_loader_connect_nodes(struct topoloader_context *context,
         switch (connect_method)
         {
             case MF_CONNECT_ALLOW_CONVERTER:
-                hr = S_OK;
+                hr = topology_loader_connect_converter_node(context, upstream_node, output_index, downstream_node, input_index, output_type, clsid);
                 break;
             case MF_CONNECT_ALLOW_DECODER:
-                hr = S_OK;
+                hr = topology_loader_connect_decoder_node(context, upstream_node, output_index, downstream_node, input_index, output_type, clsid);
                 break;
         }
     }
-- 
2.17.1




More information about the wine-devel mailing list