Signed-off-by: Nikolay Sivov nsivov@codeweavers.com --- dlls/mf/copier.c | 8 +++ dlls/mf/mf_private.h | 2 + dlls/mf/tests/mf.c | 2 +- dlls/mf/topology.c | 115 +++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 126 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..a5b23e35773 100644 --- a/dlls/mf/tests/mf.c +++ b/dlls/mf/tests/mf.c @@ -2139,6 +2139,7 @@ static void test_topology_loader_evr(void) UINT64 value64; HWND window; HRESULT hr; + GUID guid;
hr = CoInitialize(NULL); ok(hr == S_OK, "Failed to initialize, hr %#x.\n", hr); @@ -2213,7 +2214,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) {