Nikolay Sivov : mf/topoloader: Add copier transform automatically for D3D-aware outputs.

Alexandre Julliard julliard at winehq.org
Tue Dec 1 15:40:35 CST 2020


Module: wine
Branch: master
Commit: 79776e45407f700b4ab0434d5d440516ecde5e14
URL:    https://source.winehq.org/git/wine.git/?a=commit;h=79776e45407f700b4ab0434d5d440516ecde5e14

Author: Nikolay Sivov <nsivov at codeweavers.com>
Date:   Tue Dec  1 15:16:29 2020 +0300

mf/topoloader: Add copier transform automatically for D3D-aware outputs.

Signed-off-by: Nikolay Sivov <nsivov at codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard at winehq.org>

---

 dlls/mf/copier.c     |   8 ++++
 dlls/mf/mf_private.h |   2 +
 dlls/mf/tests/mf.c   |   1 -
 dlls/mf/topology.c   | 115 +++++++++++++++++++++++++++++++++++++++++++++++++++
 4 files changed, 125 insertions(+), 1 deletion(-)

diff --git a/dlls/mf/copier.c b/dlls/mf/copier.c
index ba8e316f7e9..cbdac97292b 100644
--- a/dlls/mf/copier.c
+++ b/dlls/mf/copier.c
@@ -561,6 +561,14 @@ static const IMFTransformVtbl sample_copier_transform_vtbl =
     sample_copier_transform_ProcessOutput,
 };
 
+BOOL mf_is_sample_copier_transform(IUnknown *transform)
+{
+    return transform->lpVtbl == (IUnknownVtbl *)&sample_copier_transform_vtbl;
+}
+
+/***********************************************************************
+ *      MFCreateSampleCopierMFT (mf.@)
+ */
 HRESULT WINAPI MFCreateSampleCopierMFT(IMFTransform **transform)
 {
     struct sample_copier *object;
diff --git a/dlls/mf/mf_private.h b/dlls/mf/mf_private.h
index 66d970dfce5..0c4dde0c4fc 100644
--- a/dlls/mf/mf_private.h
+++ b/dlls/mf/mf_private.h
@@ -79,3 +79,5 @@ static inline const char *debugstr_time(LONGLONG time)
 
     return wine_dbg_sprintf("%s", rev);
 }
+
+extern BOOL mf_is_sample_copier_transform(IUnknown *transform) DECLSPEC_HIDDEN;
diff --git a/dlls/mf/tests/mf.c b/dlls/mf/tests/mf.c
index b2cb45668cb..8272064466f 100644
--- a/dlls/mf/tests/mf.c
+++ b/dlls/mf/tests/mf.c
@@ -2213,7 +2213,6 @@ static void test_topology_loader_evr(void)
 
     hr = IMFTopology_GetNodeCount(full_topology, &node_count);
     ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
-todo_wine
     ok(node_count == 3, "Unexpected node count %u.\n", node_count);
 
     for (i = 0; i < node_count; ++i)
diff --git a/dlls/mf/topology.c b/dlls/mf/topology.c
index 825b9d538f3..e33dbc2efc7 100644
--- a/dlls/mf/topology.c
+++ b/dlls/mf/topology.c
@@ -2364,6 +2364,119 @@ static HRESULT topology_loader_resolve_nodes(struct topoloader_context *context,
     return hr;
 }
 
+static BOOL topology_loader_is_node_d3d_aware(IMFTopologyNode *node)
+{
+    IMFAttributes *attributes;
+    unsigned int d3d_aware = 0;
+    IUnknown *object = NULL;
+
+    if (FAILED(IMFTopologyNode_GetObject(node, &object)))
+        return FALSE;
+
+    if (SUCCEEDED(IUnknown_QueryInterface(object, &IID_IMFAttributes, (void **)&attributes)))
+    {
+        IMFAttributes_GetUINT32(attributes, &MF_SA_D3D_AWARE, &d3d_aware);
+        IMFAttributes_Release(attributes);
+    }
+
+    if (!d3d_aware)
+        d3d_aware = mf_is_sample_copier_transform(object);
+
+    IUnknown_Release(object);
+
+    return !!d3d_aware;
+}
+
+static HRESULT topology_loader_create_copier(IMFTopologyNode *upstream_node, unsigned int upstream_output,
+        IMFTopologyNode *downstream_node, unsigned int downstream_input, IMFTransform **copier)
+{
+    IMFMediaType *input_type = NULL, *output_type = NULL;
+    IMFTransform *transform;
+    HRESULT hr;
+
+    if (FAILED(hr = MFCreateSampleCopierMFT(&transform)))
+        return hr;
+
+    if (FAILED(hr = MFGetTopoNodeCurrentType(upstream_node, upstream_output, TRUE, &input_type)))
+        WARN("Failed to get upstream media type hr %#x.\n", hr);
+
+    if (SUCCEEDED(hr) && FAILED(hr = MFGetTopoNodeCurrentType(downstream_node, downstream_input, FALSE, &output_type)))
+        WARN("Failed to get downstream media type hr %#x.\n", hr);
+
+    if (SUCCEEDED(hr) && FAILED(hr = IMFTransform_SetInputType(transform, 0, input_type, 0)))
+        WARN("Input type wasn't accepted, hr %#x.\n", hr);
+
+    if (SUCCEEDED(hr) && FAILED(hr = IMFTransform_SetOutputType(transform, 0, output_type, 0)))
+        WARN("Output type wasn't accepted, hr %#x.\n", hr);
+
+    if (SUCCEEDED(hr))
+    {
+        *copier = transform;
+        IMFTransform_AddRef(*copier);
+    }
+
+    if (input_type)
+        IMFMediaType_Release(input_type);
+    if (output_type)
+        IMFMediaType_Release(output_type);
+
+    IMFTransform_Release(transform);
+
+    return hr;
+}
+
+static HRESULT topology_loader_connect_copier(struct topoloader_context *context, IMFTopologyNode *upstream_node,
+        unsigned int upstream_output, IMFTopologyNode *downstream_node, unsigned int downstream_input, IMFTransform *copier)
+{
+    IMFTopologyNode *copier_node;
+    HRESULT hr;
+
+    if (FAILED(hr = MFCreateTopologyNode(MF_TOPOLOGY_TRANSFORM_NODE, &copier_node)))
+        return hr;
+
+    IMFTopologyNode_SetObject(copier_node, (IUnknown *)copier);
+    IMFTopology_AddNode(context->output_topology, copier_node);
+    IMFTopologyNode_ConnectOutput(upstream_node, upstream_output, copier_node, 0);
+    IMFTopologyNode_ConnectOutput(copier_node, 0, downstream_node, downstream_input);
+
+    IMFTopologyNode_Release(copier_node);
+
+    return S_OK;
+}
+
+/* Right now this should be used for output nodes only. */
+static HRESULT topology_loader_connect_d3d_aware_input(struct topoloader_context *context,
+        IMFTopologyNode *node)
+{
+    IMFTopologyNode *upstream_node;
+    unsigned int upstream_output;
+    IMFStreamSink *stream_sink;
+    IMFTransform *copier = NULL;
+    HRESULT hr = S_OK;
+
+    IMFTopologyNode_GetObject(node, (IUnknown **)&stream_sink);
+
+    if (topology_loader_is_node_d3d_aware(node))
+    {
+        if (SUCCEEDED(IMFTopologyNode_GetInput(node, 0, &upstream_node, &upstream_output)))
+        {
+            if (!topology_loader_is_node_d3d_aware(upstream_node))
+            {
+                if (SUCCEEDED(hr = topology_loader_create_copier(upstream_node, upstream_output, node, 0, &copier)))
+                {
+                    hr = topology_loader_connect_copier(context, upstream_node, upstream_output, node, 0, copier);
+                    IMFTransform_Release(copier);
+                }
+            }
+            IMFTopologyNode_Release(upstream_node);
+        }
+    }
+
+    IMFStreamSink_Release(stream_sink);
+
+    return hr;
+}
+
 static void topology_loader_resolve_complete(struct topoloader_context *context)
 {
     MF_TOPOLOGY_TYPE node_type;
@@ -2383,6 +2496,8 @@ static void topology_loader_resolve_complete(struct topoloader_context *context)
                 /* Set MF_TOPONODE_STREAMID for all outputs. */
                 if (FAILED(IMFTopologyNode_GetItem(node, &MF_TOPONODE_STREAMID, NULL)))
                     IMFTopologyNode_SetUINT32(node, &MF_TOPONODE_STREAMID, 0);
+
+                topology_loader_connect_d3d_aware_input(context, node);
             }
             else if (node_type == MF_TOPOLOGY_SOURCESTREAM_NODE)
             {




More information about the wine-cvs mailing list