Signed-off-by: Derek Lesho dlesho@codeweavers.com --- I'm not sure if this is too many of too few tests, and if the kinds of tests I have here are wanted. I was going to add tests for MF_ENUMERATE_SOURCE_TYPES and MF_CONNECT_RESOLVE_INDEPENDENT_OUTPUTTYPES, but they got really large, and didn't really prove much beyond what is already documented in the MSDN. Another test I chose to leave out is for what happens on topologies with sources without a currently selected media type, since Microsoft is pretty clear that will never happen.
Also note that these tests aren't un-todo'd in this patchset. The first test requires 1) the more correct sample grabber IsMediaTypeSupportedImplementation and 2) the audio resampler MFT. The second tests requires the media source to output compressed MPEG streams and for a MPEG decoder to be present. --- dlls/mf/tests/mf.c | 200 +++++++++++++++++++++++++++++++++++++- dlls/mf/tests/resource.rc | 3 + dlls/mf/tests/test.mp3 | Bin 0 -> 2551 bytes 3 files changed, 201 insertions(+), 2 deletions(-) create mode 100644 dlls/mf/tests/test.mp3
diff --git a/dlls/mf/tests/mf.c b/dlls/mf/tests/mf.c index 43dc9a49ee7..4c70f7ee857 100644 --- a/dlls/mf/tests/mf.c +++ b/dlls/mf/tests/mf.c @@ -1418,22 +1418,27 @@ static const IMFSampleGrabberSinkCallbackVtbl test_grabber_callback_vtbl = static void test_topology_loader(void) { IMFSampleGrabberSinkCallback test_grabber_callback = { &test_grabber_callback_vtbl }; + IMFTopologyNode *src_node, *sink_node, *src_node2, *mft_node; IMFTopology *topology, *topology2, *full_topology; - IMFTopologyNode *src_node, *sink_node; + unsigned int count, value, index; IMFPresentationDescriptor *pd; IMFSourceResolver *resolver; IMFActivate *sink_activate; IMFStreamSink *stream_sink; - unsigned int count, value; + MF_TOPOLOGY_TYPE node_type; IMFMediaType *media_type; IMFStreamDescriptor *sd; MF_OBJECT_TYPE obj_type; + IMFTransform *transform; IMFMediaSource *source; IMFTopoLoader *loader; IMFByteStream *stream; + IUnknown *node_object; IMFAttributes *attr; IMFMediaSink *sink; + WORD node_count; WCHAR *filename; + TOPOID node_id; BOOL selected; HRESULT hr; GUID guid; @@ -1581,9 +1586,200 @@ todo_wine { IMFTopology_Release(topology2); IMFTopology_Release(full_topology);
+ /* Partial topology (requires converter) */ + + hr = MFCreateMediaType(&media_type); + ok(hr == S_OK, "Failed to create media type, hr %#x.\n", hr); + + hr = IMFMediaType_SetGUID(media_type, &MF_MT_MAJOR_TYPE, &MFMediaType_Audio); + ok(hr == S_OK, "Failed to set attribute, hr %#x.\n", hr); + hr = IMFMediaType_SetGUID(media_type, &MF_MT_SUBTYPE, &MFAudioFormat_PCM); + ok(hr == S_OK, "Failed to set attribute, hr %#x.\n", hr); + /* resample from 44100hz to 48000hz */ + hr = IMFMediaType_SetUINT32(media_type, &MF_MT_AUDIO_SAMPLES_PER_SECOND, 48000); + ok(hr == S_OK, "Failed to set attribute, hr %#x.\n", hr); + + hr = MFCreateSampleGrabberSinkActivate(media_type, &test_grabber_callback, &sink_activate); + ok(hr == S_OK, "Failed to create grabber sink, hr %#x.\n", hr); + + IMFMediaType_Release(media_type); + + hr = IMFActivate_ActivateObject(sink_activate, &IID_IMFMediaSink, (void **)&sink); + ok(hr == S_OK, "Failed to activate, hr %#x.\n", hr); + + hr = IMFMediaSink_GetStreamSinkByIndex(sink, 0, &stream_sink); + ok(hr == S_OK, "Unexpected hr %#x.\n", hr); + + hr = IMFTopologyNode_SetObject(sink_node, (IUnknown *)stream_sink); + ok(hr == S_OK, "Failed to set object, hr %#x.\n", hr); + + hr = IMFTopologyNode_SetUINT32(sink_node, &MF_TOPONODE_CONNECT_METHOD, MF_CONNECT_ALLOW_CONVERTER); + ok(hr == S_OK, "Failed to set connect method, hr %#x.\n", hr); + + IMFStreamSink_Release(stream_sink); + + hr = IMFTopoLoader_Load(loader, topology, &full_topology, NULL); + 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 %u\n", node_count); + if (node_count != 3) + { + IMFMediaSource_Release(source); + IMFSourceResolver_Release(resolver); + IMFByteStream_Release(stream); + + IMFTopoLoader_Release(loader); + + hr = MFShutdown(); + ok(hr == S_OK, "Shutdown failure, hr %#x.\n", hr); + return; + } + + hr = IMFTopologyNode_GetTopoNodeID(src_node, &node_id); + ok(hr == S_OK, "Failed to get source node id, hr %#x.\n", hr); + + hr = IMFTopology_GetNodeByID(full_topology, node_id, &src_node2); + ok(hr == S_OK, "Failed to get source in resolved topology, hr %#x.\n", hr); + + hr = IMFTopologyNode_GetOutput(src_node2, 0, &mft_node, &index); + ok(hr == S_OK, "Failed to get transform node in resolved topology, hr %#x.\n", hr); + ok(index == 0, "Unexpected stream index %u.\n", index); + + hr = IMFTopologyNode_GetNodeType(mft_node, &node_type); + ok(hr == S_OK, "Failed to get transform node type in resolved topology, hr %#x.\n", hr); + ok(node_type == MF_TOPOLOGY_TRANSFORM_NODE, "Unexpected node type %u, expected MF_TOPOLOGY_TRANSFORM_NODE.\n", node_type); + + hr = IMFTopologyNode_GetObject(mft_node, &node_object); + ok(hr == S_OK, "Failed to get object of transform node, hr %#x.\n", hr); + + hr = IUnknown_QueryInterface(node_object, &IID_IMFTransform, (void**) &transform); + ok(hr == S_OK, "Failed to get IMFTransform from transform node's object, hr %#x.\n", hr); + IUnknown_Release(node_object); + + hr = IMFTransform_GetInputCurrentType(transform, 0, &media_type); + ok(hr == S_OK, "Failed to get transform input type, hr %#x.\n", hr); + + hr = IMFMediaType_GetUINT32(media_type, &MF_MT_AUDIO_SAMPLES_PER_SECOND, &value); + ok(hr == S_OK, "Failed to get MF_MT_AUDIO_SAMPLES_PER_SECOND on transform input type, hr %#x.\n", hr); + ok(value == 44100, "Unexpected sample rate of transform input type %u, expected 44100\n", value); + + IMFMediaType_Release(media_type); + + hr = IMFTransform_GetOutputCurrentType(transform, 0, &media_type); + ok(hr == S_OK, "Failed to get transform output type, hr %#x.\n", hr); + + hr = IMFMediaType_GetUINT32(media_type, &MF_MT_AUDIO_SAMPLES_PER_SECOND, &value); + ok(hr == S_OK, "Failed to get MF_MT_AUDIO_SAMPLES_PER_SECOND on transform output type, hr %#x.\n", hr); + ok(value == 48000, "Unexpected sample rate of transform input type %u, expected 48000\n", value); + + IMFMediaType_Release(media_type); + IMFTransform_Release(transform); + IMFTopology_Release(full_topology); + IMFMediaSource_Release(source); IMFSourceResolver_Release(resolver); IMFByteStream_Release(stream); + + /* Test MF_TOPONODE_CONNECT_METHOD: + - 0x1 (MF_CONNECT_ALLOW_CONVERTER) allows converters + - 0x3 (MF_CONNECT_ALLOW_DECODER) allows converters and decoders + - 0x2 allows neither */ + + hr = MFCreateSourceResolver(&resolver); + ok(hr == S_OK, "Failed to create source resolver, hr %#x.\n", hr); + + filename = load_resource(L"test.mp3"); + + hr = MFCreateFile(MF_ACCESSMODE_READ, MF_OPENMODE_FAIL_IF_NOT_EXIST, MF_FILEFLAGS_NONE, filename, &stream); + ok(hr == S_OK, "Failed to create file stream, hr %#x.\n", hr); + + IMFByteStream_QueryInterface(stream, &IID_IMFAttributes, (void **)&attr); + IMFAttributes_SetString(attr, &MF_BYTESTREAM_CONTENT_TYPE, L"audio/mpeg"); + IMFAttributes_Release(attr); + + hr = IMFSourceResolver_CreateObjectFromByteStream(resolver, stream, NULL, MF_RESOLUTION_MEDIASOURCE, NULL, + &obj_type, (IUnknown **)&source); + ok(hr == S_OK || broken(FAILED(hr)) /* Vista */, "Failed to create source, hr %#x.\n", hr); + if (FAILED(hr)) + return; + + hr = IMFMediaSource_CreatePresentationDescriptor(source, &pd); + ok(hr == S_OK, "Failed to create descriptor, hr %#x.\n", hr); + if (FAILED(hr)) + return; + + hr = IMFPresentationDescriptor_GetStreamDescriptorByIndex(pd, 0, &selected, &sd); + ok(hr == S_OK, "Failed to get stream descriptor, hr %#x.\n", hr); + + hr = IMFTopologyNode_SetUnknown(src_node, &MF_TOPONODE_SOURCE, (IUnknown *)source); + ok(hr == S_OK, "Failed to set node source, hr %#x.\n", hr); + + hr = IMFTopologyNode_SetUnknown(src_node, &MF_TOPONODE_PRESENTATION_DESCRIPTOR, (IUnknown *)pd); + ok(hr == S_OK, "Failed to set node pd, hr %#x.\n", hr); + + hr = IMFTopologyNode_SetUnknown(src_node, &MF_TOPONODE_STREAM_DESCRIPTOR, (IUnknown *)sd); + ok(hr == S_OK, "Failed to set node sd, hr %#x.\n", hr); + + hr = MFCreateMediaType(&media_type); + ok(hr == S_OK, "Failed to create media type, hr %#x.\n", hr); + + hr = IMFMediaType_SetGUID(media_type, &MF_MT_MAJOR_TYPE, &MFMediaType_Audio); + ok(hr == S_OK, "Failed to set attribute, hr %#x.\n", hr); + hr = IMFMediaType_SetGUID(media_type, &MF_MT_SUBTYPE, &MFAudioFormat_PCM); + ok(hr == S_OK, "Failed to set attribute, hr %#x.\n", hr); + + hr = MFCreateSampleGrabberSinkActivate(media_type, &test_grabber_callback, &sink_activate); + ok(hr == S_OK, "Failed to create grabber sink, hr %#x.\n", hr); + + IMFMediaType_Release(media_type); + + hr = IMFActivate_ActivateObject(sink_activate, &IID_IMFMediaSink, (void **)&sink); + ok(hr == S_OK, "Failed to activate, hr %#x.\n", hr); + + hr = IMFMediaSink_GetStreamSinkByIndex(sink, 0, &stream_sink); + ok(hr == S_OK, "Unexpected hr %#x.\n", hr); + + hr = IMFTopologyNode_SetObject(sink_node, (IUnknown *)stream_sink); + ok(hr == S_OK, "Failed to set object, hr %#x.\n", hr); + + IMFStreamSink_Release(stream_sink); + + hr = IMFTopologyNode_SetUINT32(sink_node, &MF_TOPONODE_CONNECT_METHOD, MF_CONNECT_DIRECT); + ok(hr == S_OK, "Failed to set connect method, hr %#x.\n", hr); + + hr = IMFTopoLoader_Load(loader, topology, &full_topology, NULL); + ok(hr == MF_E_INVALIDMEDIATYPE, "Unexpected hr %#x.\n", hr); + + hr = IMFTopologyNode_SetUINT32(sink_node, &MF_TOPONODE_CONNECT_METHOD, MF_CONNECT_ALLOW_CONVERTER); + ok(hr == S_OK, "Failed to set connect method, hr %#x.\n", hr); + + hr = IMFTopoLoader_Load(loader, topology, &full_topology, NULL); + ok(hr == MF_E_TRANSFORM_NOT_POSSIBLE_FOR_CURRENT_MEDIATYPE_COMBINATION, "Unexpected hr %#x.\n", hr); + + hr = IMFTopologyNode_SetUINT32(sink_node, &MF_TOPONODE_CONNECT_METHOD, 2); + ok(hr == S_OK, "Failed to set connect method, hr %#x.\n", hr); + + hr = IMFTopoLoader_Load(loader, topology, &full_topology, NULL); + ok(hr == MF_E_INVALIDMEDIATYPE, "Failed to resolve topology, hr %#x.\n", hr); + + hr = IMFTopologyNode_SetUINT32(sink_node, &MF_TOPONODE_CONNECT_METHOD, MF_CONNECT_ALLOW_DECODER); + ok(hr == S_OK, "Failed to set connect method, hr %#x.\n", hr); + + hr = IMFTopoLoader_Load(loader, topology, &full_topology, NULL); + 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); + ok(node_count == 3, "Unexpected node count %u\n", node_count); + + IMFTopology_Release(full_topology); + IMFMediaSource_Release(source); + IMFSourceResolver_Release(resolver); + IMFByteStream_Release(stream); + IMFTopoLoader_Release(loader);
hr = MFShutdown(); diff --git a/dlls/mf/tests/resource.rc b/dlls/mf/tests/resource.rc index f54212a8c8f..5e847cd0b3b 100644 --- a/dlls/mf/tests/resource.rc +++ b/dlls/mf/tests/resource.rc @@ -20,3 +20,6 @@
/* @makedep: test.wav */ test.wav RCDATA test.wav + +/* @makedep: test.mp3 */ +test.mp3 RCDATA test.mp3 diff --git a/dlls/mf/tests/test.mp3 b/dlls/mf/tests/test.mp3 new file mode 100644 index 0000000000000000000000000000000000000000..8b66f19da24624d58beda20187e1f6f85bdc4f44 GIT binary patch literal 2551 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
literal 0 HcmV?d00001
Signed-off-by: Derek Lesho dlesho@codeweavers.com --- dlls/mf/topology.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-)
diff --git a/dlls/mf/topology.c b/dlls/mf/topology.c index 8032e438b73..a09f6ef0ef4 100644 --- a/dlls/mf/topology.c +++ b/dlls/mf/topology.c @@ -2022,8 +2022,6 @@ static HRESULT topology_loader_resolve_branch(struct topoloader_context *context if (FAILED(IMFTopology_GetNodeByID(context->output_topology, id, &node))) topology_loader_clone_node(context, downstream_node, &node, context->marker + 1);
- IMFTopologyNode_ConnectOutput(upstream_node, output_index, node, input_index); - IMFTopologyNode_GetNodeType(upstream_node, &u_type); IMFTopologyNode_GetNodeType(downstream_node, &d_type);
@@ -2033,7 +2031,7 @@ static HRESULT topology_loader_resolve_branch(struct topoloader_context *context return E_FAIL; }
- return connectors[u_type][d_type](context, upstream_node, output_index, downstream_node, input_index); + return connectors[u_type][d_type](context, upstream_node, output_index, node, input_index); }
static HRESULT topology_loader_resolve_nodes(struct topoloader_context *context, unsigned int *layer_size)
Signed-off-by: Derek Lesho dlesho@codeweavers.com --- dlls/mf/topology.c | 268 ++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 266 insertions(+), 2 deletions(-)
diff --git a/dlls/mf/topology.c b/dlls/mf/topology.c index a09f6ef0ef4..4756a30895b 100644 --- a/dlls/mf/topology.c +++ b/dlls/mf/topology.c @@ -1992,15 +1992,279 @@ static HRESULT topology_loader_clone_node(struct topoloader_context *context, IM return hr; }
+struct available_output_type +{ + IMFMediaType *type; + IMFTransform *transform; +}; + +static HRESULT topology_loader_enumerate_output_types(GUID *category, IMFMediaType *input_type, HRESULT (*new_type)(struct available_output_type *, void *), void *context) +{ + MFT_REGISTER_TYPE_INFO mft_typeinfo; + GUID major_type, subtype; + IMFActivate **activates; + UINT32 num_activates; + HRESULT hr; + + if (FAILED(hr = IMFMediaType_GetMajorType(input_type, &major_type))) + return hr; + + if (FAILED(hr = IMFMediaType_GetGUID(input_type, &MF_MT_SUBTYPE, &subtype))) + return hr; + + mft_typeinfo.guidMajorType = major_type; + mft_typeinfo.guidSubtype = subtype; + + if (FAILED(hr = MFTEnumEx(*category, MFT_ENUM_FLAG_ALL, &mft_typeinfo, NULL, &activates, &num_activates))) + return hr; + + hr = E_FAIL; + + for (unsigned int i = 0; i < num_activates; i++) + { + IMFTransform *mft; + + if (FAILED(IMFActivate_ActivateObject(activates[i], &IID_IMFTransform, (void**) &mft))) + { + IMFActivate_Release(activates[i]); + continue; + } + + if (SUCCEEDED(hr = IMFTransform_SetInputType(mft, 0, input_type, 0))) + { + struct available_output_type avail = {.transform = mft}; + unsigned int output_count = 0; + + while (SUCCEEDED(IMFTransform_GetOutputAvailableType(mft, 0, output_count++, &avail.type))) + { + if (SUCCEEDED(hr = new_type(&avail, context))) + { + IMFActivate_Release(activates[i]); + return hr; + } + } + } + + IMFActivate_ShutdownObject(activates[i]); + IMFActivate_Release(activates[i]); + } + + return hr; +} + +struct connect_to_sink_context +{ + struct topoloader_context *context; + IMFTopologyNode *src, *sink; + IMFMediaTypeHandler *sink_mth; +}; + +HRESULT connect_to_sink(struct available_output_type *type, void *context) +{ + IMFTopologyNode *node; + struct connect_to_sink_context *ctx = context; + + if (SUCCEEDED(IMFMediaTypeHandler_IsMediaTypeSupported(ctx->sink_mth, type->type, NULL))) + { + MFCreateTopologyNode(MF_TOPOLOGY_TRANSFORM_NODE, &node); + IMFTopologyNode_SetObject(node, (IUnknown *) type->transform); + IMFTopologyNode_ConnectOutput(ctx->src, 0, node, 0); + IMFTopologyNode_ConnectOutput(node, 0, ctx->sink, 0); + + IMFTopology_AddNode(ctx->context->output_topology, node); + IMFTopologyNode_Release(node); + + IMFMediaTypeHandler_SetCurrentMediaType(ctx->sink_mth, type->type); + IMFTransform_SetOutputType(type->transform, 0, type->type, 0); + + return S_OK; + } + return MF_E_TRANSFORM_NOT_POSSIBLE_FOR_CURRENT_MEDIATYPE_COMBINATION; +} + +struct connect_to_converter_context +{ + struct connect_to_sink_context sink_ctx; + GUID *converter_category; +}; + +HRESULT connect_to_converter(struct available_output_type *type, void *context) +{ + struct connect_to_converter_context *ctx = context; + struct connect_to_sink_context sink_ctx; + IMFTopologyNode *node; + HRESULT hr; + + if (SUCCEEDED(connect_to_sink(type, &ctx->sink_ctx))) + return S_OK; + + MFCreateTopologyNode(MF_TOPOLOGY_TRANSFORM_NODE, &node); + IMFTopologyNode_SetObject(node, (IUnknown *) type->transform); + + sink_ctx = ctx->sink_ctx; + sink_ctx.src = node; + if (SUCCEEDED(hr = topology_loader_enumerate_output_types(ctx->converter_category, type->type, connect_to_sink, &sink_ctx))) + { + IMFTopologyNode_ConnectOutput(ctx->sink_ctx.src, 0, node, 0); + + IMFTopology_AddNode(ctx->sink_ctx.context->output_topology, node); + + IMFTransform_SetOutputType(type->transform, 0, type->type, 0); + + return S_OK; + } + IMFTopologyNode_Release(node); + return hr; +} + typedef HRESULT (*p_topology_loader_connect_func)(struct topoloader_context *context, IMFTopologyNode *upstream_node, unsigned int output_index, IMFTopologyNode *downstream_node, unsigned int input_index);
static HRESULT topology_loader_connect_source_node(struct topoloader_context *context, IMFTopologyNode *upstream_node, unsigned int output_index, IMFTopologyNode *downstream_node, unsigned int input_index) { - FIXME("Unimplemented.\n"); + UINT32 enum_src_types, src_method = 0, sink_method = MF_CONNECT_ALLOW_DECODER; + IMFMediaTypeHandler *src_mth = NULL, *sink_mth = NULL; + struct connect_to_converter_context convert_ctx; + unsigned int i, k, i_, k_, src_type_count; + GUID major_type, decode_cat, convert_cat; + struct connect_to_sink_context sink_ctx; + IMFStreamDescriptor *desc = NULL; + IMFStreamSink *stream_sink; + IMFMediaType *media_type; + HRESULT hr;
- return E_NOTIMPL; + TRACE("attempting to connect %p:%u to %p:%u\n", upstream_node, output_index, downstream_node, input_index); + + IMFTopologyNode_GetUnknown(upstream_node, &MF_TOPONODE_STREAM_DESCRIPTOR, &IID_IMFStreamDescriptor, (void **)&desc); + + if (FAILED(hr = IMFStreamDescriptor_GetMediaTypeHandler(desc, &src_mth))) + goto done; + + if (FAILED(hr = IMFMediaTypeHandler_GetMediaTypeCount(src_mth, &src_type_count))) + goto done; + + IMFTopologyNode_GetObject(downstream_node, (IUnknown **)&stream_sink); + + if (FAILED(hr = IMFStreamSink_GetMediaTypeHandler(stream_sink, &sink_mth))) + { + IMFStreamSink_Release(stream_sink); + goto done; + } + IMFStreamSink_Release(stream_sink); + + IMFTopologyNode_GetUINT32(upstream_node, &MF_TOPONODE_CONNECT_METHOD, &src_method); + IMFTopologyNode_GetUINT32(downstream_node, &MF_TOPONODE_CONNECT_METHOD, &sink_method); + IMFTopology_GetUINT32(context->input_topology, &MF_TOPOLOGY_ENUMERATE_SOURCE_TYPES, &enum_src_types); + + if (FAILED(hr = IMFMediaTypeHandler_GetMajorType(src_mth, &major_type))) + goto done; + + if (IsEqualGUID(&major_type, &MFMediaType_Audio)) + { + decode_cat = MFT_CATEGORY_AUDIO_DECODER; + convert_cat = MFT_CATEGORY_AUDIO_EFFECT; + } + else if (IsEqualGUID(&major_type, &MFMediaType_Video)) + { + decode_cat = MFT_CATEGORY_VIDEO_DECODER; + convert_cat = MFT_CATEGORY_VIDEO_EFFECT; + } + else + { + hr = MF_E_INVALIDTYPE; + goto done; + } + + sink_ctx.context = context; + sink_ctx.src = upstream_node; + sink_ctx.sink = downstream_node; + sink_ctx.sink_mth = sink_mth; + + convert_ctx.sink_ctx = sink_ctx; + convert_ctx.converter_category = &convert_cat; + + i_ = (enum_src_types && src_method & MF_CONNECT_RESOLVE_INDEPENDENT_OUTPUTTYPES) ? src_type_count : 1; + k_ = (enum_src_types && !(src_method & MF_CONNECT_RESOLVE_INDEPENDENT_OUTPUTTYPES)) ? src_type_count : 1; + for(i = 0; i < i_; i++) + { + /* MF_CONNECT_DIRECT */ + for (k = 0; k < k_; k++) + { + if (enum_src_types) + { + if (FAILED(hr = IMFMediaTypeHandler_GetMediaTypeByIndex(src_mth, i * k, &media_type))) goto done; + } + else + if (FAILED(hr = IMFMediaTypeHandler_GetCurrentMediaType(src_mth, &media_type))) goto done; + + if (SUCCEEDED(hr = IMFMediaTypeHandler_IsMediaTypeSupported(sink_mth, media_type, NULL))) + { + IMFMediaTypeHandler_SetCurrentMediaType(src_mth, media_type); + IMFMediaTypeHandler_SetCurrentMediaType(sink_mth, media_type); + IMFTopologyNode_ConnectOutput(upstream_node, output_index, downstream_node, input_index); + IMFMediaType_Release(media_type); + goto done; + } + + IMFMediaType_Release(media_type); + } + + for (k = 0; k < k_; k++) + { + if (enum_src_types) + { + if (FAILED(hr = IMFMediaTypeHandler_GetMediaTypeByIndex(src_mth, i * k, &media_type))) goto done; + } + else + if (FAILED(hr = IMFMediaTypeHandler_GetCurrentMediaType(src_mth, &media_type))) goto done; + + if (sink_method & MF_CONNECT_ALLOW_CONVERTER) + { + if (SUCCEEDED(hr = topology_loader_enumerate_output_types(&convert_cat, media_type, connect_to_sink, &sink_ctx))) + { + IMFMediaTypeHandler_SetCurrentMediaType(src_mth, media_type); + IMFMediaType_Release(media_type); + goto done; + } + } + + IMFMediaType_Release(media_type); + } + + for (k = 0; k < k_; k++) + { + if (enum_src_types) + { + if (FAILED(hr = IMFMediaTypeHandler_GetMediaTypeByIndex(src_mth, i * k, &media_type))) goto done; + } + else + if (FAILED(hr = IMFMediaTypeHandler_GetCurrentMediaType(src_mth, &media_type))) goto done; + + if (sink_method & MF_CONNECT_ALLOW_DECODER) + { + if (SUCCEEDED(hr = topology_loader_enumerate_output_types(&decode_cat, media_type, connect_to_converter, &convert_ctx))) + { + IMFMediaTypeHandler_SetCurrentMediaType(src_mth, media_type); + IMFMediaType_Release(media_type); + goto done; + } + } + + IMFMediaType_Release(media_type); + } + } + hr = MF_E_INVALIDMEDIATYPE; + + done: + if (desc) + IMFStreamDescriptor_Release(desc); + if (src_mth) + IMFMediaTypeHandler_Release(src_mth); + if (sink_mth) + IMFMediaTypeHandler_Release(sink_mth); + + return hr; }
static HRESULT topology_loader_resolve_branch(struct topoloader_context *context, IMFTopologyNode *upstream_node,
Signed-off-by: Derek Lesho dlesho@codeweavers.com --- dlls/mf/topology.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-)
diff --git a/dlls/mf/topology.c b/dlls/mf/topology.c index 4756a30895b..99f3c12f190 100644 --- a/dlls/mf/topology.c +++ b/dlls/mf/topology.c @@ -2430,11 +2430,9 @@ static HRESULT WINAPI topology_loader_Load(IMFTopoLoader *iface, IMFTopology *in break; }
- /* For now return original topology. */ - *ret_topology = output_topology;
- return IMFTopology_CloneFrom(output_topology, input_topology); + return hr; }
static const IMFTopoLoaderVtbl topologyloadervtbl =
On 11/25/20 12:29 AM, Derek Lesho wrote:
Signed-off-by: Derek Lesho dlesho@codeweavers.com
I'm not sure if this is too many of too few tests, and if the kinds of tests I have here are wanted. I was going to add tests for MF_ENUMERATE_SOURCE_TYPES and MF_CONNECT_RESOLVE_INDEPENDENT_OUTPUTTYPES, but they got really large, and didn't really prove much beyond what is already documented in the MSDN. Another test I chose to leave out is for what happens on topologies with sources without a currently selected media type, since Microsoft is pretty clear that will never happen.
No, I agree. I'm fine with leaving these enumeration tweaks out for now, we will add them later if we find something using them (might be a good idea to put out a warning in Load() on such attributes, but that's clearly optional). Trying to test permutations we might never get in practice is not very interesting for initial tests.
The test in this patch is fine in principle, and that's what we should stick to for partial topology in initial tests: (source) -> (sample grabber). Next could be (source) -> (SAR) and (source) -> (EVR).
What I found is that this could be simplified because source instance is in fact unnecessary. Everything seems to work exactly the same without MF_TOPONODE_SOURCE, which makes sense. That opens a possibility for more compact tests in a form of [ input type, output type ] pairs + additional arguments as connect method, etc. This way we can easily extend them to trigger converters using mismatching subtypes or similar.