Signed-off-by: Sergio Gómez Del Real sdelreal@codeweavers.com --- dlls/mf/topology.c | 134 +++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 129 insertions(+), 5 deletions(-)
diff --git a/dlls/mf/topology.c b/dlls/mf/topology.c index 1284bde12a..3ee8ddc40b 100644 --- a/dlls/mf/topology.c +++ b/dlls/mf/topology.c @@ -2016,6 +2016,107 @@ static HRESULT topology_loader_clone_node(struct topoloader_context *context, IM return hr; }
+static HRESULT topology_loader_is_mediatype_compatible_with_sink(IMFMediaTypeHandler *sink_mediatype_handler, IMFMediaType *mediatype) +{ + IMFMediaType *sink_mediatype; + HRESULT hr; + + if (FAILED(hr = IMFMediaTypeHandler_GetCurrentMediaType(sink_mediatype_handler, &sink_mediatype))) + hr = IMFMediaTypeHandler_GetMediaTypeByIndex(sink_mediatype_handler, 0, &sink_mediatype); + + if (SUCCEEDED(hr)) + { + DWORD flags; + + if (SUCCEEDED(hr = IMFMediaType_IsEqual(mediatype, sink_mediatype, &flags))) + if (!(flags & MF_MEDIATYPE_EQUAL_FORMAT_DATA)) + hr = MF_E_INVALIDMEDIATYPE; + + IMFMediaType_Release(sink_mediatype); + } + + return hr; +} + +static HRESULT topology_loader_connect_direct(IMFTopologyNode *upstream_node, unsigned int output_index, + IMFTopologyNode *downstream_node, unsigned int input_index, IMFMediaType *output_type) +{ + MF_TOPOLOGY_TYPE node_type; + HRESULT hr; + + IMFTopologyNode_GetNodeType(downstream_node, &node_type); + + if (node_type == MF_TOPOLOGY_TRANSFORM_NODE) + { + IMFTransform *mft; + + if (SUCCEEDED(hr = IMFTopologyNode_GetObject(downstream_node, (IUnknown **)&mft))) + { + hr = IMFTransform_SetInputType(mft, input_index, output_type, 0); + IMFTransform_Release(mft); + } + } + else if (node_type == MF_TOPOLOGY_OUTPUT_NODE) + { + IMFMediaTypeHandler *mediatype_handler; + IMFStreamSink *sink; + + if (SUCCEEDED(hr = IMFTopologyNode_GetObject(downstream_node, (IUnknown **)&sink))) + { + if (SUCCEEDED(hr = IMFStreamSink_GetMediaTypeHandler(sink, &mediatype_handler))) + { + if (SUCCEEDED(hr = topology_loader_is_mediatype_compatible_with_sink(mediatype_handler, output_type))) + IMFMediaTypeHandler_SetCurrentMediaType(mediatype_handler, output_type); + IMFMediaTypeHandler_Release(mediatype_handler); + } + IMFStreamSink_Release(sink); + } + } + else if (node_type == MF_TOPOLOGY_TEE_NODE) + { + FIXME("Tee nodes are not supported.\n"); + hr = MF_E_INVALIDTYPE; + } + else + { + WARN("Unexpected node type %d.\n", node_type); + hr = MF_E_INVALIDTYPE; + } + + if (SUCCEEDED(hr)) + hr = IMFTopologyNode_ConnectOutput(upstream_node, output_index, downstream_node, input_index); + + 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) +{ + HRESULT hr; + GUID major; + + if (FAILED(hr = IMFMediaType_GetMajorType(output_type, &major))) + 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) + { + switch (connect_method) + { + case MF_CONNECT_ALLOW_CONVERTER: + hr = S_OK; + break; + case MF_CONNECT_ALLOW_DECODER: + hr = S_OK; + break; + } + } + +out: + return hr; +} + static HRESULT topology_loader_connect_source(struct topoloader_context *context, IMFTopologyNode *source_node, IMFTopologyNode *downstream_node, unsigned int input_index) { @@ -2074,13 +2175,36 @@ static HRESULT topology_loader_connect_source(struct topoloader_context *context src_mediatypes[0] = mtype_src;
hr = IMFAttributes_GetUINT32(attrs_src, &MF_TOPONODE_CONNECT_METHOD, &method); - - for (i = 0; i < num_media_types; i++) + if (!enum_src_types || (hr == S_OK && !(method & MF_CONNECT_RESOLVE_INDEPENDENT_OUTPUTTYPES))) { - if (SUCCEEDED(hr = IMFMediaTypeHandler_SetCurrentMediaType(mth_src, src_mediatypes[i]))) - break; + for (method = MF_CONNECT_DIRECT; method < MF_CONNECT_RESOLVE_INDEPENDENT_OUTPUTTYPES; method++) + { + for (i = 0; i < num_media_types; i++) + { + IMFMediaTypeHandler_SetCurrentMediaType(mth_src, src_mediatypes[i]); + if (SUCCEEDED(hr = topology_loader_connect_nodes(context, source_node, 0, downstream_node, input_index, src_mediatypes[i], method))) + goto out; + } + if (method == MF_CONNECT_ALLOW_CONVERTER) + method++; + } + } + else + { + for (i = 0; i < num_media_types; i++) + { + for (method = MF_CONNECT_DIRECT; method < MF_CONNECT_RESOLVE_INDEPENDENT_OUTPUTTYPES; method++) + { + IMFMediaTypeHandler_SetCurrentMediaType(mth_src, src_mediatypes[i]); + if (SUCCEEDED(hr = topology_loader_connect_nodes(context, source_node, 0, downstream_node, input_index, src_mediatypes[i], method))) + goto out; + if (method == MF_CONNECT_ALLOW_CONVERTER) + method++; + } + } }
+out: while (num_media_types--) IMFMediaType_Release(src_mediatypes[num_media_types]); IMFMediaTypeHandler_Release(mth_src); @@ -2105,7 +2229,7 @@ static HRESULT topology_loader_connect_transform(struct topoloader_context *cont i = 0; while (SUCCEEDED(hr = IMFTransform_GetOutputAvailableType(transform, output_index, i++, &mediatype))) { - hr = S_OK; + hr = topology_loader_connect_nodes(context, transform_node, output_index, downstream_node, input_index, mediatype, method);
IMFMediaType_Release(mediatype);