Signed-off-by: Sergio Gómez Del Real sdelreal@codeweavers.com --- dlls/mf/Makefile.in | 2 +- dlls/mf/tests/mf.c | 4 -- dlls/mf/topology.c | 124 +++++++++++++++++++++++++++++++++++++++++++- 3 files changed, 123 insertions(+), 7 deletions(-)
diff --git a/dlls/mf/Makefile.in b/dlls/mf/Makefile.in index fe156e43ab..34118fed67 100644 --- a/dlls/mf/Makefile.in +++ b/dlls/mf/Makefile.in @@ -1,6 +1,6 @@ MODULE = mf.dll IMPORTLIB = mf -IMPORTS = advapi32 mfplat ole32 uuid mfuuid +IMPORTS = advapi32 mfplat ole32 uuid mfuuid wmcodecdspuuid
EXTRADLLFLAGS = -mno-cygwin
diff --git a/dlls/mf/tests/mf.c b/dlls/mf/tests/mf.c index 6d0a3176ac..cec6d66f77 100644 --- a/dlls/mf/tests/mf.c +++ b/dlls/mf/tests/mf.c @@ -1841,7 +1841,6 @@ todo_wine
/* if no current media type set, loader uses first index exclusively */ hr = IMFTopoLoader_Load(loader, topology, &full_topology, NULL); -todo_wine ok(hr == MF_E_TOPO_CODEC_NOT_FOUND, "Unexpected hr %#x.\n", hr);
hr = IMFStreamDescriptor_GetMediaTypeHandler(sd, &mth); @@ -1855,7 +1854,6 @@ todo_wine ok(hr == S_OK, "Failed setting current media type, hr %#x.\n", hr);
hr = IMFTopoLoader_Load(loader, topology, &full_topology, NULL); -todo_wine ok(hr == MF_E_TOPO_CODEC_NOT_FOUND, "Unexpected hr %#x.\n", hr);
hr = IMFMediaTypeHandler_GetMediaTypeByIndex(mth, 1, &media_type); @@ -1935,7 +1933,6 @@ todo_wine ok(hr == S_OK, "Failed to resolve topology, hr %#x.\n", hr); hr = IMFTopology_GetNodeCount(full_topology, &node_count); ok(hr == S_OK, "Failed to get node count, hr %#x.\n", hr); -todo_wine ok(node_count == 3, "Unexpected node count %d.\n", node_count); IMFTopology_Release(full_topology);
@@ -1952,7 +1949,6 @@ todo_wine
hr = IMFTopology_GetNodeCount(full_topology, &node_count); ok(hr == S_OK, "Failed to get node count, hr %#x.\n", hr); -todo_wine ok(node_count == 3, "Unexpected node count %d.\n", node_count);
/* now test without MF_CONNECT_RESOLVE_INDEPENDENT_OUTPUTTYPES on source */ diff --git a/dlls/mf/topology.c b/dlls/mf/topology.c index 7aaffaf807..c29e3e36b0 100644 --- a/dlls/mf/topology.c +++ b/dlls/mf/topology.c @@ -29,6 +29,7 @@ #include "mfapi.h" #include "mferror.h" #include "mfidl.h" +#include "wmcodecdsp.h"
#include "wine/debug.h"
@@ -2089,15 +2090,134 @@ static HRESULT topology_loader_connect_direct(IMFTopologyNode *upstream_node, un return hr; }
+static HRESULT topology_loader_connect_converter_node(struct topoloader_context *context, IMFTopologyNode *upstream_node, unsigned int output_index, + IMFTopologyNode *downstream_node, unsigned int input_index, IMFMediaType *output_type, const CLSID *clsid) +{ + IMFTransform *transform = NULL; + IMFMediaType *mediatype = NULL; + HRESULT hr; + + if (FAILED(hr = CoCreateInstance(clsid, NULL, CLSCTX_INPROC_SERVER, &IID_IMFTransform, (void **)&transform))) + { + WARN("Failed to create converter transform for %s, hr %#x.\n", debugstr_guid(clsid), hr); + return hr; + } + + if (SUCCEEDED(hr = IMFTransform_SetInputType(transform, 0, output_type, 0))) + { + IMFTopologyNode *converter_node; + + MFCreateTopologyNode(MF_TOPOLOGY_TRANSFORM_NODE, &converter_node); + IMFTopologyNode_SetObject(converter_node, (IUnknown *)transform); + + if (SUCCEEDED(hr = topology_loader_connect_direct(upstream_node, output_index, converter_node, 0, mediatype))) + { + unsigned int i = 0; + while (SUCCEEDED(hr = IMFTransform_GetOutputAvailableType(transform, 0, i++, &mediatype))) + { + hr = topology_loader_connect_direct(converter_node, 0, downstream_node, input_index, mediatype); + + IMFMediaType_Release(mediatype); + + if (SUCCEEDED(hr)) + { + IMFTopology_AddNode(context->output_topology, converter_node); + break; + } + } + } + + IMFTransform_Release(transform); + IMFTopologyNode_Release(converter_node); + } + + return hr; +} + +static HRESULT topology_loader_connect_decoder_node(struct topoloader_context *context, IMFTopologyNode *upstream_node, unsigned int output_index, + IMFTopologyNode *downstream_node, unsigned int input_index, IMFMediaType *input_type, const CLSID *clsid) +{ + HRESULT hr = MF_E_TOPO_CODEC_NOT_FOUND; + unsigned int i = 0, j = 0, count = 0; + MFT_REGISTER_TYPE_INFO input_info; + IMFMediaType *current_mediatype; + IMFActivate **activators = NULL; + IMFTransform *transform = NULL; + IMFTopologyNode *decoder_node; + const GUID *category; + + IMFMediaType_GetMajorType(input_type, &input_info.guidMajorType); + IMFMediaType_GetGUID(input_type, &MF_MT_SUBTYPE, &input_info.guidSubtype); + + if (IsEqualGUID(&MFMediaType_Audio, &input_info.guidMajorType)) + category = &MFT_CATEGORY_AUDIO_DECODER; + else + category = &MFT_CATEGORY_VIDEO_DECODER; + + if (SUCCEEDED(MFTEnumEx(*category, MFT_ENUM_FLAG_ALL, &input_info, NULL, &activators, &count))) + { + for (i = 0; i < count; ++i) + { + if (FAILED(IMFActivate_ActivateObject(activators[i], &IID_IMFTransform, (void **)&transform))) + { + WARN("Failed to activate transform, hr %#x.\n", hr); + continue; + } + + if (SUCCEEDED(MFCreateTopologyNode(MF_TOPOLOGY_TRANSFORM_NODE, &decoder_node)) + && SUCCEEDED(IMFTransform_SetInputType(transform, 0, input_type, 0)) + && SUCCEEDED(IMFTopologyNode_SetObject(decoder_node, (IUnknown *)transform))) + { + j = 0; + while (SUCCEEDED(IMFTransform_GetOutputAvailableType(transform, 0, j++, ¤t_mediatype))) + { + if (SUCCEEDED(hr = topology_loader_connect_direct(decoder_node, 0, downstream_node, input_index, current_mediatype)) + || SUCCEEDED(hr = topology_loader_connect_converter_node(context, decoder_node, 0, downstream_node, input_index, current_mediatype, clsid))) + { + IMFTopology_AddNode(context->output_topology, decoder_node); + IMFTransform_SetOutputType(transform, 0, current_mediatype, 0); + IMFMediaType_Release(current_mediatype); + break; + } + IMFMediaType_Release(current_mediatype); + } + IMFTopologyNode_Release(decoder_node); + } + + IMFTransform_Release(transform); + + if (SUCCEEDED(hr)) + break; + } + for (i = 0; i < count; ++i) + IMFActivate_Release(activators[i]); + CoTaskMemFree(activators); + } + + 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) { + const GUID *clsid; HRESULT hr; GUID major;
if (FAILED(hr = IMFMediaType_GetMajorType(output_type, &major))) goto out;
+ if (IsEqualGUID(&major, &MFMediaType_Video)) + clsid = &CLSID_VideoProcessorMFT; + else if (IsEqualGUID(&major, &MFMediaType_Audio)) + clsid = &CLSID_CResamplerMediaObject; + else + { + WARN("Unexpected major type %s.\n", debugstr_guid(&major)); + hr = E_UNEXPECTED; + 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) @@ -2105,10 +2225,10 @@ static HRESULT topology_loader_connect_nodes(struct topoloader_context *context, switch (connect_method) { case MF_CONNECT_ALLOW_CONVERTER: - hr = S_OK; + hr = topology_loader_connect_converter_node(context, upstream_node, output_index, downstream_node, input_index, output_type, clsid); break; case MF_CONNECT_ALLOW_DECODER: - hr = S_OK; + hr = topology_loader_connect_decoder_node(context, upstream_node, output_index, downstream_node, input_index, output_type, clsid); break; } }