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