From: Bernhard Kölbl besentv@gmail.com
To make it independent from set types on node endpoints. --- dlls/mf/topology_loader.c | 211 +++++++++++++++++--------------------- 1 file changed, 93 insertions(+), 118 deletions(-)
diff --git a/dlls/mf/topology_loader.c b/dlls/mf/topology_loader.c index 0c42a93511b..b64e7ff99f2 100644 --- a/dlls/mf/topology_loader.c +++ b/dlls/mf/topology_loader.c @@ -359,12 +359,84 @@ static HRESULT topology_branch_get_current_type(IMFMediaTypeHandler *handler, IM return hr; }
+static BOOL topology_loader_is_node_d3d_aware(IMFTopologyNode *node) +{ + IMFAttributes *attributes; + unsigned int d3d_aware = 0; + IMFTransform *transform; + + if (FAILED(topology_node_get_object(node, &IID_IMFAttributes, (void **)&attributes))) + return FALSE; + + IMFAttributes_GetUINT32(attributes, &MF_SA_D3D_AWARE, &d3d_aware); + IMFAttributes_Release(attributes); + + if (!d3d_aware && SUCCEEDED(topology_node_get_object(node, &IID_IMFTransform, (void **)&transform))) + { + d3d_aware = mf_is_sample_copier_transform(transform); + IMFTransform_Release(transform); + } + + return !!d3d_aware; +} + +static HRESULT topology_loader_create_copier(IMFMediaType *upstream_type, IMFMediaType *downstream_type, IMFTransform **copier) +{ + IMFTransform *transform; + HRESULT hr; + + if (FAILED(hr = MFCreateSampleCopierMFT(&transform))) + return hr; + + if (SUCCEEDED(hr) && FAILED(hr = IMFTransform_SetInputType(transform, 0, upstream_type, 0))) + WARN("Input type wasn't accepted, hr %#lx.\n", hr); + + if (SUCCEEDED(hr) && FAILED(hr = IMFTransform_SetOutputType(transform, 0, downstream_type, 0))) + WARN("Output type wasn't accepted, hr %#lx.\n", hr); + + if (SUCCEEDED(hr)) + { + *copier = transform; + IMFTransform_AddRef(*copier); + } + + IMFTransform_Release(transform); + + return hr; +} + +static HRESULT topology_branch_insert_copier(IMFTopology *topology, struct topology_branch *branch, + IMFMediaType *upstream_type, IMFMediaType *downstream_type) +{ + IMFTopologyNode *copier_node; + IMFTransform *copier; + HRESULT hr; + + if (FAILED(hr = topology_loader_create_copier(upstream_type, downstream_type, &copier))) + return hr; + + if (FAILED(hr = MFCreateTopologyNode(MF_TOPOLOGY_TRANSFORM_NODE, &copier_node))) + return hr; + + IMFTopologyNode_SetObject(copier_node, (IUnknown *)copier); + IMFTopology_AddNode(topology, copier_node); + IMFTopologyNode_ConnectOutput(branch->up.node, branch->up.stream, copier_node, 0); + IMFTopologyNode_ConnectOutput(copier_node, 0, branch->down.node, branch->down.stream); + + IMFTopologyNode_Release(copier_node); + + return S_OK; +} + static HRESULT topology_branch_connect_down(IMFTopology *topology, MF_CONNECT_METHOD method_mask, struct topology_branch *branch, IMFMediaType *up_type) { IMFMediaTypeHandler *down_handler; IMFMediaType *down_type = NULL; + MFT_REGISTER_TYPE_INFO input_info; MF_CONNECT_METHOD method; + MF_TOPOLOGY_TYPE type; + BOOL need_copier = FALSE; DWORD flags; HRESULT hr;
@@ -377,11 +449,25 @@ static HRESULT topology_branch_connect_down(IMFTopology *topology, MF_CONNECT_ME if (FAILED(hr = topology_node_get_type_handler(branch->down.node, branch->down.stream, FALSE, &down_handler))) return hr;
+ /* Insert copier only for video streams. */ + if(SUCCEEDED(IMFTopologyNode_GetNodeType(branch->down.node, &type)) && type == MF_TOPOLOGY_OUTPUT_NODE + && SUCCEEDED(IMFMediaType_GetMajorType(up_type, &input_info.guidMajorType)) + && IsEqualGUID(&input_info.guidMajorType, &MFMediaType_Video)) + { + need_copier = (!topology_loader_is_node_d3d_aware(branch->up.node) + && topology_loader_is_node_d3d_aware(branch->down.node)); + } + if (SUCCEEDED(hr = topology_branch_get_current_type(down_handler, &down_type)) && IMFMediaType_IsEqual(up_type, down_type, &flags) == S_OK) { TRACE("Connecting branch %s with current type %p.\n", debugstr_topology_branch(branch), up_type); - hr = IMFTopologyNode_ConnectOutput(branch->up.node, branch->up.stream, branch->down.node, branch->down.stream); + + if (need_copier) + hr = topology_branch_insert_copier(topology, branch, up_type, up_type); /* Up and downsteam type should be same here. */ + else + hr = IMFTopologyNode_ConnectOutput(branch->up.node, branch->up.stream, branch->down.node, branch->down.stream); + goto done; }
@@ -389,7 +475,12 @@ static HRESULT topology_branch_connect_down(IMFTopology *topology, MF_CONNECT_ME && SUCCEEDED(hr = IMFMediaTypeHandler_SetCurrentMediaType(down_handler, up_type))) { TRACE("Connected branch %s with upstream type %p.\n", debugstr_topology_branch(branch), up_type); - hr = IMFTopologyNode_ConnectOutput(branch->up.node, branch->up.stream, branch->down.node, branch->down.stream); + + if (need_copier) + hr = topology_branch_insert_copier(topology, branch, up_type, up_type); /* Up and downsteam type should be same here. */ + else + hr = IMFTopologyNode_ConnectOutput(branch->up.node, branch->up.stream, branch->down.node, branch->down.stream); + goto done; }
@@ -509,124 +600,11 @@ static HRESULT topology_loader_resolve_branches(struct topoloader_context *conte return hr; }
-static BOOL topology_loader_is_node_d3d_aware(IMFTopologyNode *node) -{ - IMFAttributes *attributes; - unsigned int d3d_aware = 0; - IMFTransform *transform; - - if (FAILED(topology_node_get_object(node, &IID_IMFAttributes, (void **)&attributes))) - return FALSE; - - IMFAttributes_GetUINT32(attributes, &MF_SA_D3D_AWARE, &d3d_aware); - IMFAttributes_Release(attributes); - - if (!d3d_aware && SUCCEEDED(topology_node_get_object(node, &IID_IMFTransform, (void **)&transform))) - { - d3d_aware = mf_is_sample_copier_transform(transform); - IMFTransform_Release(transform); - } - - return !!d3d_aware; -} - -static HRESULT topology_loader_create_copier(IMFTopologyNode *upstream_node, DWORD 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 %#lx.\n", hr); - - if (SUCCEEDED(hr) && FAILED(hr = MFGetTopoNodeCurrentType(downstream_node, downstream_input, FALSE, &output_type))) - WARN("Failed to get downstream media type hr %#lx.\n", hr); - - if (SUCCEEDED(hr) && FAILED(hr = IMFTransform_SetInputType(transform, 0, input_type, 0))) - WARN("Input type wasn't accepted, hr %#lx.\n", hr); - - if (SUCCEEDED(hr) && FAILED(hr = IMFTransform_SetOutputType(transform, 0, output_type, 0))) - WARN("Output type wasn't accepted, hr %#lx.\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, - DWORD upstream_output, IMFTopologyNode *downstream_node, DWORD 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; - IMFTransform *copier = NULL; - IMFStreamSink *stream_sink; - DWORD upstream_output; - HRESULT hr; - - if (FAILED(hr = topology_node_get_object(node, &IID_IMFStreamSink, (void **)&stream_sink))) - return hr; - - 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; IMFTopologyNode *node; WORD i, node_count; - HRESULT hr;
IMFTopology_GetNodeCount(context->output_topology, &node_count);
@@ -641,9 +619,6 @@ 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); - - if (FAILED(hr = topology_loader_connect_d3d_aware_input(context, node))) - WARN("Failed to connect D3D-aware input, hr %#lx.\n", hr); } else if (node_type == MF_TOPOLOGY_SOURCESTREAM_NODE) {