-- v2: winegstreamer: Implement H264 decoder GetInputCurrentType. mf/topology_loader: Try to connect transform nodes with their current types first. mf/topology_loader: Initialize transform output type before adding converter. mf/topology_loader: Ignore SetOutputType errors when doing indirect connect. mf/topology_loader: Use a local variable for the indirect connection method. mf/tests: Check inserted topology loader transforms explicitly.
From: Rémi Bernon rbernon@codeweavers.com
--- dlls/mf/tests/mf.c | 180 ++++++++++++++++++++++++++++++--------------- 1 file changed, 120 insertions(+), 60 deletions(-)
diff --git a/dlls/mf/tests/mf.c b/dlls/mf/tests/mf.c index 13b55b1f836..0add2863454 100644 --- a/dlls/mf/tests/mf.c +++ b/dlls/mf/tests/mf.c @@ -2983,8 +2983,6 @@ static IMFSampleGrabberSinkCallback *create_test_grabber_callback(void)
enum loader_test_flags { - LOADER_EXPECTED_DECODER = 0x1, - LOADER_EXPECTED_CONVERTER = 0x2, LOADER_TODO = 0x4, LOADER_NEEDS_VIDEO_PROCESSOR = 0x8, LOADER_SET_ENUMERATE_SOURCE_TYPES = 0x10, @@ -3066,6 +3064,18 @@ static void test_topology_loader(void) ATTR_UINT32(MF_MT_AUDIO_BLOCK_ALIGNMENT, 1), ATTR_UINT32(MF_MT_AUDIO_BITS_PER_SAMPLE, 8), }; + static const media_type_desc audio_float_44100_stereo = + { + ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Audio), + ATTR_GUID(MF_MT_SUBTYPE, MFAudioFormat_Float), + ATTR_UINT32(MF_MT_AUDIO_NUM_CHANNELS, 2), + ATTR_UINT32(MF_MT_AUDIO_BLOCK_ALIGNMENT, 2 * 4), + ATTR_UINT32(MF_MT_AUDIO_SAMPLES_PER_SECOND, 44100), + ATTR_UINT32(MF_MT_AUDIO_AVG_BYTES_PER_SECOND, 2 * 4 * 44100), + ATTR_UINT32(MF_MT_AUDIO_BITS_PER_SAMPLE, 4 * 8), + ATTR_UINT32(MF_MT_AUDIO_CHANNEL_MASK, 3), + ATTR_UINT32(MF_MT_ALL_SAMPLES_INDEPENDENT, 1), + }; static const media_type_desc video_i420_1280 = { ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Video), @@ -3089,6 +3099,25 @@ static void test_topology_loader(void) ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Video), ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_RGB32), }; + static const media_type_desc video_h264_1280 = + { + ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Video), + ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_H264), + ATTR_RATIO(MF_MT_FRAME_SIZE, 1280, 720), + }; + static const media_type_desc video_nv12_1280 = + { + ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Video), + ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_NV12), + ATTR_RATIO(MF_MT_FRAME_RATE, 30000, 1001), + ATTR_RATIO(MF_MT_FRAME_SIZE, 1280, 720), + ATTR_RATIO(MF_MT_PIXEL_ASPECT_RATIO, 1, 1), + ATTR_UINT32(MF_MT_SAMPLE_SIZE, 1280 * 720 * 3 / 2), + ATTR_UINT32(MF_MT_ALL_SAMPLES_INDEPENDENT, 1), + ATTR_UINT32(MF_MT_DEFAULT_STRIDE, 1280), + ATTR_UINT32(MF_MT_FIXED_SIZE_SAMPLES, 1), + ATTR_UINT32(MF_MT_INTERLACE_MODE, 7), + }; static const media_type_desc video_dummy = { ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Video), @@ -3099,10 +3128,13 @@ static void test_topology_loader(void) const media_type_desc *input_type; const media_type_desc *output_type; const media_type_desc *current_input; + const media_type_desc *decoded_type; MF_CONNECT_METHOD source_method; MF_CONNECT_METHOD sink_method; HRESULT expected_result; unsigned int flags; + GUID decoder_class; + GUID converter_class; } loader_tests[] = { @@ -3167,27 +3199,24 @@ static void test_topology_loader(void) { /* PCM -> PCM, different enumerated bps, no current type, sink allow converter */ .input_type = &audio_pcm_44100, .output_type = &audio_pcm_48000, .sink_method = MF_CONNECT_ALLOW_CONVERTER, .source_method = MF_CONNECT_DIRECT, - .expected_result = S_OK, - .flags = LOADER_EXPECTED_CONVERTER, + .expected_result = S_OK, .converter_class = CLSID_CResamplerMediaObject, }, { /* PCM -> PCM, different enumerated bps, same current type, sink allow converter, force enumerate */ .input_type = &audio_pcm_44100, .output_type = &audio_pcm_48000, .sink_method = MF_CONNECT_ALLOW_CONVERTER, .source_method = -1, .current_input = &audio_pcm_48000, - .expected_result = S_OK, - .flags = LOADER_EXPECTED_CONVERTER | LOADER_SET_ENUMERATE_SOURCE_TYPES, + .expected_result = S_OK, .converter_class = CLSID_CResamplerMediaObject, + .flags = LOADER_SET_ENUMERATE_SOURCE_TYPES, }, { /* PCM -> PCM, different enumerated bps, no current type, sink allow decoder */ .input_type = &audio_pcm_44100, .output_type = &audio_pcm_48000, .sink_method = MF_CONNECT_ALLOW_DECODER, .source_method = MF_CONNECT_DIRECT, - .expected_result = S_OK, - .flags = LOADER_EXPECTED_CONVERTER, + .expected_result = S_OK, .converter_class = CLSID_CResamplerMediaObject, }, { /* PCM -> PCM, different enumerated bps, no current type, default methods */ .input_type = &audio_pcm_44100, .output_type = &audio_pcm_48000, .sink_method = -1, .source_method = -1, - .expected_result = S_OK, - .flags = LOADER_EXPECTED_CONVERTER, + .expected_result = S_OK, .converter_class = CLSID_CResamplerMediaObject, }, { /* PCM -> PCM, different enumerated bps, no current type, source allow converter */ @@ -3198,14 +3227,14 @@ static void test_topology_loader(void) { /* Float -> PCM, refuse input type, add converter */ .input_type = &audio_float_44100, .output_type = &audio_pcm_48000, .sink_method = MF_CONNECT_DIRECT, .source_method = -1, - .expected_result = MF_E_NO_MORE_TYPES, - .flags = LOADER_SET_INVALID_INPUT | LOADER_ADD_RESAMPLER_MFT | LOADER_EXPECTED_CONVERTER, + .expected_result = MF_E_NO_MORE_TYPES, .converter_class = CLSID_CResamplerMediaObject, + .flags = LOADER_SET_INVALID_INPUT | LOADER_ADD_RESAMPLER_MFT, }, { /* Float -> PCM, refuse input type, add converter, allow resampler output type */ .input_type = &audio_float_44100, .output_type = &audio_pcm_48000_resampler, .sink_method = MF_CONNECT_DIRECT, .source_method = -1, - .expected_result = S_OK, - .flags = LOADER_SET_INVALID_INPUT | LOADER_ADD_RESAMPLER_MFT | LOADER_EXPECTED_CONVERTER, + .expected_result = S_OK, .converter_class = CLSID_CResamplerMediaObject, + .flags = LOADER_SET_INVALID_INPUT | LOADER_ADD_RESAMPLER_MFT, },
{ @@ -3232,34 +3261,39 @@ static void test_topology_loader(void) /* MP3 -> PCM */ .input_type = &audio_mp3_44100, .output_type = &audio_pcm_44100, .sink_method = MF_CONNECT_ALLOW_DECODER, .source_method = -1, .current_input = &audio_mp3_44100, - .expected_result = S_OK, - .flags = LOADER_EXPECTED_DECODER | LOADER_TODO, + .expected_result = S_OK, .decoder_class = CLSID_CMP3DecMediaObject, + .flags = LOADER_TODO, }, { /* MP3 -> PCM, need both decoder and converter */ .input_type = &audio_mp3_44100, .output_type = &audio_float_48000, .sink_method = MF_CONNECT_ALLOW_DECODER, .source_method = -1, - .current_input = &audio_mp3_44100, - .expected_result = S_OK, - .flags = LOADER_EXPECTED_DECODER | LOADER_EXPECTED_CONVERTER | LOADER_TODO, + .current_input = &audio_mp3_44100, .decoded_type = &audio_float_44100_stereo, + .expected_result = S_OK, .decoder_class = CLSID_CMP3DecMediaObject, .converter_class = CLSID_CResamplerMediaObject, + .flags = LOADER_TODO, },
{ /* I420 -> RGB32, Color Convert media type */ .input_type = &video_i420_1280, .output_type = &video_color_convert_1280_rgb32, .sink_method = -1, .source_method = -1, - .expected_result = MF_E_TOPO_CODEC_NOT_FOUND, - .flags = LOADER_NEEDS_VIDEO_PROCESSOR | LOADER_EXPECTED_CONVERTER, + .expected_result = MF_E_TOPO_CODEC_NOT_FOUND, .converter_class = CLSID_CColorConvertDMO, + .flags = LOADER_NEEDS_VIDEO_PROCESSOR, }, { /* I420 -> RGB32, Video Processor media type */ .input_type = &video_i420_1280, .output_type = &video_video_processor_1280_rgb32, .sink_method = -1, .source_method = -1, - .expected_result = S_OK, - .flags = LOADER_EXPECTED_CONVERTER, + .expected_result = S_OK, .converter_class = CLSID_CColorConvertDMO, }, { /* I420 -> RGB32, Video Processor media type without frame size */ .input_type = &video_i420_1280, .output_type = &video_video_processor_rgb32, .sink_method = -1, .source_method = -1, - .expected_result = S_OK, - .flags = LOADER_EXPECTED_CONVERTER, + .expected_result = S_OK, .converter_class = CLSID_CColorConvertDMO, + }, + { + /* H264 -> RGB32, Video Processor media type */ + .input_type = &video_h264_1280, .output_type = &video_video_processor_1280_rgb32, .sink_method = -1, .source_method = -1, + .decoded_type = &video_nv12_1280, + .expected_result = S_OK, .decoder_class = CLSID_CMSH264DecoderMFT, .converter_class = CLSID_CColorConvertDMO, + .flags = LOADER_TODO, }, { /* RGB32 -> Any Video, no current output type */ @@ -3270,14 +3304,14 @@ static void test_topology_loader(void) { /* RGB32 -> Any Video, no current output type, refuse input type */ .input_type = &video_i420_1280, .output_type = &video_dummy, .sink_method = -1, .source_method = -1, - .expected_result = S_OK, - .flags = LOADER_NO_CURRENT_OUTPUT | LOADER_SET_INVALID_INPUT | LOADER_EXPECTED_CONVERTER, + .expected_result = S_OK, .converter_class = CLSID_CColorConvertDMO, + .flags = LOADER_NO_CURRENT_OUTPUT | LOADER_SET_INVALID_INPUT, }, { /* RGB32 -> Any Video, no current output type, refuse input type */ .input_type = &video_i420_1280, .output_type = &video_video_processor_rgb32, .sink_method = -1, .source_method = -1, - .expected_result = S_OK, - .flags = LOADER_NO_CURRENT_OUTPUT | LOADER_SET_INVALID_INPUT | LOADER_SET_MEDIA_TYPES | LOADER_EXPECTED_CONVERTER, + .expected_result = S_OK, .converter_class = CLSID_CColorConvertDMO, + .flags = LOADER_NO_CURRENT_OUTPUT | LOADER_SET_INVALID_INPUT | LOADER_SET_MEDIA_TYPES, }, };
@@ -3536,14 +3570,14 @@ todo_wine { ok(value == MF_TOPOLOGY_RESOLUTION_SUCCEEDED, "Unexpected value %#x.\n", value); } count = 2; - if (test->flags & LOADER_EXPECTED_DECODER) + if (!IsEqualGUID(&test->decoder_class, &GUID_NULL)) count++; - if (test->flags & LOADER_EXPECTED_CONVERTER) + if (!IsEqualGUID(&test->converter_class, &GUID_NULL)) count++;
hr = IMFTopology_GetNodeCount(full_topology, &node_count); ok(hr == S_OK, "Failed to get node count, hr %#lx.\n", hr); - todo_wine_if(test->flags & LOADER_EXPECTED_DECODER) + todo_wine_if(!IsEqualGUID(&test->decoder_class, &GUID_NULL)) ok(node_count == count, "Unexpected node count %u.\n", node_count);
hr = IMFTopologyNode_GetTopoNodeID(src_node, &node_id); @@ -3558,29 +3592,31 @@ todo_wine { hr = IMFTopology_GetNodeByID(full_topology, node_id, &sink_node2); ok(hr == S_OK, "Failed to get sink in resolved topology, hr %#lx.\n", hr);
- if (test->flags & (LOADER_EXPECTED_DECODER | LOADER_EXPECTED_CONVERTER)) + if (!IsEqualGUID(&test->decoder_class, &GUID_NULL)) { + GUID class_id; + hr = IMFTopologyNode_GetOutput(src_node2, 0, &mft_node, &index); - ok(hr == S_OK, "Failed to get transform node in resolved topology, hr %#lx.\n", hr); + ok(hr == S_OK, "Failed to get decoder in resolved topology, hr %#lx.\n", hr); ok(!index, "Unexpected stream index %lu.\n", index);
hr = IMFTopologyNode_GetNodeType(mft_node, &node_type); ok(hr == S_OK, "Failed to get transform node type in resolved topology, hr %#lx.\n", hr); ok(node_type == MF_TOPOLOGY_TRANSFORM_NODE, "Unexpected node type %u.\n", node_type);
- hr = IMFTopologyNode_GetObject(mft_node, &node_object); - ok(hr == S_OK, "Failed to get object of transform node, hr %#lx.\n", hr); - - if (test->flags & LOADER_EXPECTED_DECODER) - { - value = 0; - hr = IMFTopologyNode_GetUINT32(mft_node, &MF_TOPONODE_DECODER, &value); - ok(hr == S_OK, "Failed to get attribute, hr %#lx.\n", hr); - ok(value == 1, "Unexpected value.\n"); - } + value = 0; + hr = IMFTopologyNode_GetUINT32(mft_node, &MF_TOPONODE_DECODER, &value); + ok(hr == S_OK, "Failed to get attribute, hr %#lx.\n", hr); + ok(value == 1, "Unexpected value.\n");
- hr = IMFTopologyNode_GetItem(mft_node, &MF_TOPONODE_TRANSFORM_OBJECTID, NULL); + class_id = GUID_NULL; + hr = IMFTopologyNode_GetGUID(mft_node, &MF_TOPONODE_TRANSFORM_OBJECTID, &class_id); ok(hr == S_OK, "Failed to get attribute, hr %#lx.\n", hr); + ok(IsEqualGUID(&class_id, &test->decoder_class), "got MF_TOPONODE_TRANSFORM_OBJECTID %s.\n", debugstr_guid(&class_id)); + + hr = IMFTopologyNode_GetObject(mft_node, &node_object); + ok(hr == S_OK, "Failed to get object of transform node, hr %#lx.\n", hr); + IMFTopologyNode_Release(mft_node);
hr = IUnknown_QueryInterface(node_object, &IID_IMFTransform, (void **)&transform); ok(hr == S_OK, "Failed to get IMFTransform from transform node's object, hr %#lx.\n", hr); @@ -3588,51 +3624,75 @@ todo_wine {
hr = IMFTransform_GetInputCurrentType(transform, 0, &media_type); ok(hr == S_OK, "Failed to get transform input type, hr %#lx.\n", hr); - hr = IMFMediaType_Compare(input_type, (IMFAttributes *)media_type, MF_ATTRIBUTES_MATCH_OUR_ITEMS, &ret); ok(hr == S_OK, "Failed to compare media types, hr %#lx.\n", hr); ok(ret, "Input type of first transform doesn't match source node type.\n"); + IMFMediaType_Release(media_type);
- IMFTopologyNode_Release(mft_node); + hr = IMFTransform_GetOutputCurrentType(transform, 0, &media_type); + ok(hr == S_OK, "Failed to get transform input type, hr %#lx.\n", hr); + if (IsEqualGUID(&test->converter_class, &GUID_NULL)) + { + hr = IMFMediaType_Compare(output_type, (IMFAttributes *)media_type, MF_ATTRIBUTES_MATCH_OUR_ITEMS, &ret); + ok(hr == S_OK, "Failed to compare media types, hr %#lx.\n", hr); + ok(ret, "Output type of first transform doesn't match sink node type.\n"); + } + else if (test->decoded_type) + { + check_media_type(media_type, *test->decoded_type, -1); + } IMFMediaType_Release(media_type); + IMFTransform_Release(transform); + } + + if (!IsEqualGUID(&test->converter_class, &GUID_NULL)) + { + GUID class_id;
hr = IMFTopologyNode_GetInput(sink_node2, 0, &mft_node, &index); - ok(hr == S_OK, "Failed to get transform node in resolved topology, hr %#lx.\n", hr); + ok(hr == S_OK, "Failed to get decoder in resolved topology, hr %#lx.\n", hr); ok(!index, "Unexpected stream index %lu.\n", index);
hr = IMFTopologyNode_GetNodeType(mft_node, &node_type); ok(hr == S_OK, "Failed to get transform node type in resolved topology, hr %#lx.\n", hr); ok(node_type == MF_TOPOLOGY_TRANSFORM_NODE, "Unexpected node type %u.\n", node_type);
- hr = IMFTopologyNode_GetItem(mft_node, &MF_TOPONODE_TRANSFORM_OBJECTID, NULL); + class_id = GUID_NULL; + hr = IMFTopologyNode_GetGUID(mft_node, &MF_TOPONODE_TRANSFORM_OBJECTID, &class_id); ok(hr == S_OK, "Failed to get attribute, hr %#lx.\n", hr); + todo_wine_if(IsEqualGUID(&test->converter_class, &CLSID_CColorConvertDMO)) + ok(IsEqualGUID(&class_id, &test->converter_class), "got MF_TOPONODE_TRANSFORM_OBJECTID %s.\n", debugstr_guid(&class_id));
hr = IMFTopologyNode_GetObject(mft_node, &node_object); ok(hr == S_OK, "Failed to get object of transform node, hr %#lx.\n", hr); + IMFTopologyNode_Release(mft_node);
- hr = IUnknown_QueryInterface(node_object, &IID_IMFTransform, (void**) &transform); + hr = IUnknown_QueryInterface(node_object, &IID_IMFTransform, (void **)&transform); ok(hr == S_OK, "Failed to get IMFTransform from transform node's object, hr %#lx.\n", hr); IUnknown_Release(node_object);
- hr = IMFTransform_GetOutputCurrentType(transform, 0, &media_type); - ok(hr == S_OK, "Failed to get transform output type, hr %#lx.\n", hr); - hr = IMFMediaType_Compare(output_type, (IMFAttributes *)media_type, MF_ATTRIBUTES_MATCH_OUR_ITEMS, &ret); - ok(hr == S_OK, "Failed to compare media types, hr %#lx.\n", hr); - ok(ret, "Output type of last transform doesn't match sink node type.\n"); - IMFMediaType_Release(media_type); - hr = IMFTransform_GetInputCurrentType(transform, 0, &media_type); ok(hr == S_OK, "Failed to get transform input type, hr %#lx.\n", hr); - if ((test->flags & (LOADER_EXPECTED_CONVERTER | LOADER_EXPECTED_DECODER)) != (LOADER_EXPECTED_CONVERTER | LOADER_EXPECTED_DECODER)) + if (IsEqualGUID(&test->decoder_class, &GUID_NULL)) { hr = IMFMediaType_Compare(input_type, (IMFAttributes *)media_type, MF_ATTRIBUTES_MATCH_OUR_ITEMS, &ret); ok(hr == S_OK, "Failed to compare media types, hr %#lx.\n", hr); - ok(ret, "Input type of transform doesn't match source node type.\n"); + ok(ret, "Input type of last transform doesn't match source node type.\n"); + } + else if (test->decoded_type) + { + check_media_type(media_type, *test->decoded_type, -1); } IMFMediaType_Release(media_type);
- IMFTopologyNode_Release(mft_node); + hr = IMFTransform_GetOutputCurrentType(transform, 0, &media_type); + ok(hr == S_OK, "Failed to get transform input type, hr %#lx.\n", hr); + hr = IMFMediaType_Compare(output_type, (IMFAttributes *)media_type, MF_ATTRIBUTES_MATCH_OUR_ITEMS, &ret); + ok(hr == S_OK, "Failed to compare media types, hr %#lx.\n", hr); + ok(ret, "Output type of last transform doesn't match sink node type.\n"); + IMFMediaType_Release(media_type); + IMFTransform_Release(transform); }
From: Rémi Bernon rbernon@codeweavers.com
Instead of modifying the method_mask parameter, in case we need to retry with another transform. --- dlls/mf/topology_loader.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-)
diff --git a/dlls/mf/topology_loader.c b/dlls/mf/topology_loader.c index 6b6d39d76d1..e482807e777 100644 --- a/dlls/mf/topology_loader.c +++ b/dlls/mf/topology_loader.c @@ -296,6 +296,7 @@ static HRESULT topology_branch_connect_indirect(IMFTopology *topology, MF_CONNEC { struct topology_branch down_branch = {.up.node = node, .down = branch->down}; struct topology_branch up_branch = {.up = branch->up, .down.node = node}; + MF_CONNECT_METHOD method = method_mask;
if (FAILED(IMFActivate_ActivateObject(activates[i], &IID_IMFTransform, (void **)&transform))) continue; @@ -313,12 +314,12 @@ static HRESULT topology_branch_connect_indirect(IMFTopology *topology, MF_CONNEC if (SUCCEEDED(hr)) hr = IMFTransform_SetOutputType(transform, 0, down_type, 0); if (SUCCEEDED(hr)) - method_mask = MF_CONNECT_DIRECT; + method = MF_CONNECT_DIRECT; } IMFTransform_Release(transform);
if (SUCCEEDED(hr)) - hr = topology_branch_connect(topology, method_mask, &down_branch, !down_type); + hr = topology_branch_connect(topology, method, &down_branch, !down_type); if (SUCCEEDED(hr)) hr = IMFTopology_AddNode(topology, node); if (SUCCEEDED(hr))
From: Rémi Bernon rbernon@codeweavers.com
It only succeeds with converters, or if a decoder can directly output the downstream media type.
If it fails we may have to add a converter after the decoder, and we will call topology_branch_connect on the downstream branch for that. --- dlls/mf/tests/mf.c | 15 +++++++++++++-- dlls/mf/topology_loader.c | 7 ++----- 2 files changed, 15 insertions(+), 7 deletions(-)
diff --git a/dlls/mf/tests/mf.c b/dlls/mf/tests/mf.c index 0add2863454..2c1e1020bee 100644 --- a/dlls/mf/tests/mf.c +++ b/dlls/mf/tests/mf.c @@ -3293,7 +3293,6 @@ static void test_topology_loader(void) .input_type = &video_h264_1280, .output_type = &video_video_processor_1280_rgb32, .sink_method = -1, .source_method = -1, .decoded_type = &video_nv12_1280, .expected_result = S_OK, .decoder_class = CLSID_CMSH264DecoderMFT, .converter_class = CLSID_CColorConvertDMO, - .flags = LOADER_TODO, }, { /* RGB32 -> Any Video, no current output type */ @@ -3577,7 +3576,7 @@ todo_wine {
hr = IMFTopology_GetNodeCount(full_topology, &node_count); ok(hr == S_OK, "Failed to get node count, hr %#lx.\n", hr); - todo_wine_if(!IsEqualGUID(&test->decoder_class, &GUID_NULL)) + todo_wine_if(IsEqualGUID(&test->decoder_class, &CLSID_CMP3DecMediaObject)) ok(node_count == count, "Unexpected node count %u.\n", node_count);
hr = IMFTopologyNode_GetTopoNodeID(src_node, &node_id); @@ -3623,14 +3622,21 @@ todo_wine { IUnknown_Release(node_object);
hr = IMFTransform_GetInputCurrentType(transform, 0, &media_type); + todo_wine ok(hr == S_OK, "Failed to get transform input type, hr %#lx.\n", hr); + if (hr == S_OK) + { hr = IMFMediaType_Compare(input_type, (IMFAttributes *)media_type, MF_ATTRIBUTES_MATCH_OUR_ITEMS, &ret); ok(hr == S_OK, "Failed to compare media types, hr %#lx.\n", hr); ok(ret, "Input type of first transform doesn't match source node type.\n"); IMFMediaType_Release(media_type); + }
hr = IMFTransform_GetOutputCurrentType(transform, 0, &media_type); + todo_wine ok(hr == S_OK, "Failed to get transform input type, hr %#lx.\n", hr); + if (hr == S_OK) + { if (IsEqualGUID(&test->converter_class, &GUID_NULL)) { hr = IMFMediaType_Compare(output_type, (IMFAttributes *)media_type, MF_ATTRIBUTES_MATCH_OUR_ITEMS, &ret); @@ -3642,6 +3648,7 @@ todo_wine { check_media_type(media_type, *test->decoded_type, -1); } IMFMediaType_Release(media_type); + }
IMFTransform_Release(transform); } @@ -3702,13 +3709,17 @@ todo_wine { hr = IMFTopology_SetUINT32(full_topology, &IID_IMFTopology, 123); ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); hr = IMFTopoLoader_Load(loader, full_topology, &topology2, NULL); + todo_wine_if(IsEqualGUID(&test->decoder_class, &CLSID_MSH264DecoderMFT)) ok(hr == S_OK, "Failed to resolve topology, hr %#lx.\n", hr); + if (hr == S_OK) + { ok(full_topology != topology2, "Unexpected instance.\n"); hr = IMFTopology_GetUINT32(topology2, &IID_IMFTopology, &value); ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
ref = IMFTopology_Release(topology2); ok(ref == 0, "Release returned %ld\n", ref); + } ref = IMFTopology_Release(full_topology); ok(ref == 0, "Release returned %ld\n", ref); } diff --git a/dlls/mf/topology_loader.c b/dlls/mf/topology_loader.c index e482807e777..57f9cfa9bf6 100644 --- a/dlls/mf/topology_loader.c +++ b/dlls/mf/topology_loader.c @@ -309,11 +309,8 @@ static HRESULT topology_branch_connect_indirect(IMFTopology *topology, MF_CONNEC hr = topology_branch_connect_down(topology, MF_CONNECT_DIRECT, &up_branch, up_type); if (down_type) { - if (SUCCEEDED(hr)) - hr = topology_branch_fill_media_type(up_type, down_type); - if (SUCCEEDED(hr)) - hr = IMFTransform_SetOutputType(transform, 0, down_type, 0); - if (SUCCEEDED(hr)) + if (SUCCEEDED(topology_branch_fill_media_type(up_type, down_type)) + && SUCCEEDED(IMFTransform_SetOutputType(transform, 0, down_type, 0))) method = MF_CONNECT_DIRECT; } IMFTransform_Release(transform);
From: Rémi Bernon rbernon@codeweavers.com
Otherwise the next topology_branch_connect call will fail when it will try to lookup the upstream element media type. --- dlls/mf/tests/mf.c | 4 ---- dlls/mf/topology_loader.c | 9 +++++++++ 2 files changed, 9 insertions(+), 4 deletions(-)
diff --git a/dlls/mf/tests/mf.c b/dlls/mf/tests/mf.c index 2c1e1020bee..b8859091424 100644 --- a/dlls/mf/tests/mf.c +++ b/dlls/mf/tests/mf.c @@ -3633,10 +3633,7 @@ todo_wine { }
hr = IMFTransform_GetOutputCurrentType(transform, 0, &media_type); - todo_wine ok(hr == S_OK, "Failed to get transform input type, hr %#lx.\n", hr); - if (hr == S_OK) - { if (IsEqualGUID(&test->converter_class, &GUID_NULL)) { hr = IMFMediaType_Compare(output_type, (IMFAttributes *)media_type, MF_ATTRIBUTES_MATCH_OUR_ITEMS, &ret); @@ -3648,7 +3645,6 @@ todo_wine { check_media_type(media_type, *test->decoded_type, -1); } IMFMediaType_Release(media_type); - }
IMFTransform_Release(transform); } diff --git a/dlls/mf/topology_loader.c b/dlls/mf/topology_loader.c index 57f9cfa9bf6..83398dbb12f 100644 --- a/dlls/mf/topology_loader.c +++ b/dlls/mf/topology_loader.c @@ -297,6 +297,7 @@ static HRESULT topology_branch_connect_indirect(IMFTopology *topology, MF_CONNEC struct topology_branch down_branch = {.up.node = node, .down = branch->down}; struct topology_branch up_branch = {.up = branch->up, .down.node = node}; MF_CONNECT_METHOD method = method_mask; + IMFMediaType *media_type;
if (FAILED(IMFActivate_ActivateObject(activates[i], &IID_IMFTransform, (void **)&transform))) continue; @@ -315,6 +316,14 @@ static HRESULT topology_branch_connect_indirect(IMFTopology *topology, MF_CONNEC } IMFTransform_Release(transform);
+ if (SUCCEEDED(hr) && method != MF_CONNECT_DIRECT + && SUCCEEDED(IMFTransform_GetOutputAvailableType(transform, 0, 0, &media_type))) + { + if (SUCCEEDED(topology_branch_fill_media_type(up_type, media_type))) + IMFTransform_SetOutputType(transform, 0, media_type, 0); + IMFMediaType_Release(media_type); + } + if (SUCCEEDED(hr)) hr = topology_branch_connect(topology, method, &down_branch, !down_type); if (SUCCEEDED(hr))
From: Rémi Bernon rbernon@codeweavers.com
And only if that fails try again by enumerating types. --- dlls/mf/tests/mf.c | 4 ---- dlls/mf/topology_loader.c | 7 +++++-- 2 files changed, 5 insertions(+), 6 deletions(-)
diff --git a/dlls/mf/tests/mf.c b/dlls/mf/tests/mf.c index b8859091424..c8145d23d9f 100644 --- a/dlls/mf/tests/mf.c +++ b/dlls/mf/tests/mf.c @@ -3705,17 +3705,13 @@ todo_wine { hr = IMFTopology_SetUINT32(full_topology, &IID_IMFTopology, 123); ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); hr = IMFTopoLoader_Load(loader, full_topology, &topology2, NULL); - todo_wine_if(IsEqualGUID(&test->decoder_class, &CLSID_MSH264DecoderMFT)) ok(hr == S_OK, "Failed to resolve topology, hr %#lx.\n", hr); - if (hr == S_OK) - { ok(full_topology != topology2, "Unexpected instance.\n"); hr = IMFTopology_GetUINT32(topology2, &IID_IMFTopology, &value); ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
ref = IMFTopology_Release(topology2); ok(ref == 0, "Release returned %ld\n", ref); - } ref = IMFTopology_Release(full_topology); ok(ref == 0, "Release returned %ld\n", ref); } diff --git a/dlls/mf/topology_loader.c b/dlls/mf/topology_loader.c index 83398dbb12f..806f61f8c33 100644 --- a/dlls/mf/topology_loader.c +++ b/dlls/mf/topology_loader.c @@ -525,8 +525,11 @@ static HRESULT topology_loader_resolve_branches(struct topoloader_context *conte else if (FAILED(hr = topology_branch_clone_nodes(context, branch))) WARN("Failed to clone nodes for branch %s\n", debugstr_topology_branch(branch)); else - hr = topology_branch_connect(context->output_topology, MF_CONNECT_ALLOW_DECODER, - branch, enumerate_source_types || node_type == MF_TOPOLOGY_TRANSFORM_NODE); + { + hr = topology_branch_connect(context->output_topology, MF_CONNECT_ALLOW_DECODER, branch, enumerate_source_types); + if (hr == MF_E_INVALIDMEDIATYPE && !enumerate_source_types && node_type == MF_TOPOLOGY_TRANSFORM_NODE) + hr = topology_branch_connect(context->output_topology, MF_CONNECT_ALLOW_DECODER, branch, TRUE); + }
topology_branch_destroy(branch); if (FAILED(hr))
From: Rémi Bernon rbernon@codeweavers.com
--- dlls/mf/tests/mf.c | 4 ---- dlls/mf/tests/transform.c | 2 +- dlls/winegstreamer/h264_decoder.c | 16 +++++++++++++--- 3 files changed, 14 insertions(+), 8 deletions(-)
diff --git a/dlls/mf/tests/mf.c b/dlls/mf/tests/mf.c index c8145d23d9f..6b13551de9a 100644 --- a/dlls/mf/tests/mf.c +++ b/dlls/mf/tests/mf.c @@ -3622,15 +3622,11 @@ todo_wine { IUnknown_Release(node_object);
hr = IMFTransform_GetInputCurrentType(transform, 0, &media_type); - todo_wine ok(hr == S_OK, "Failed to get transform input type, hr %#lx.\n", hr); - if (hr == S_OK) - { hr = IMFMediaType_Compare(input_type, (IMFAttributes *)media_type, MF_ATTRIBUTES_MATCH_OUR_ITEMS, &ret); ok(hr == S_OK, "Failed to compare media types, hr %#lx.\n", hr); ok(ret, "Input type of first transform doesn't match source node type.\n"); IMFMediaType_Release(media_type); - }
hr = IMFTransform_GetOutputCurrentType(transform, 0, &media_type); ok(hr == S_OK, "Failed to get transform input type, hr %#lx.\n", hr); diff --git a/dlls/mf/tests/transform.c b/dlls/mf/tests/transform.c index f9e6b3b45cd..06e638bea16 100644 --- a/dlls/mf/tests/transform.c +++ b/dlls/mf/tests/transform.c @@ -4262,7 +4262,7 @@ static void test_h264_decoder(void)
check_mft_set_input_type_required(transform, input_type_desc); check_mft_set_input_type(transform, input_type_desc); - check_mft_get_input_current_type_(transform, expect_input_type_desc, TRUE, FALSE); + check_mft_get_input_current_type_(transform, expect_input_type_desc, FALSE, TRUE);
check_mft_get_input_stream_info(transform, S_OK, &input_info); check_mft_get_output_stream_info(transform, S_OK, &output_info); diff --git a/dlls/winegstreamer/h264_decoder.c b/dlls/winegstreamer/h264_decoder.c index 5c48130eee9..a187c744549 100644 --- a/dlls/winegstreamer/h264_decoder.c +++ b/dlls/winegstreamer/h264_decoder.c @@ -574,8 +574,18 @@ static HRESULT WINAPI transform_SetOutputType(IMFTransform *iface, DWORD id, IMF
static HRESULT WINAPI transform_GetInputCurrentType(IMFTransform *iface, DWORD id, IMFMediaType **type) { - FIXME("iface %p, id %#lx, type %p stub!\n", iface, id, type); - return E_NOTIMPL; + struct h264_decoder *decoder = impl_from_IMFTransform(iface); + HRESULT hr; + + TRACE("iface %p, id %#lx, type %p\n", iface, id, type); + + if (!decoder->input_type) + return MF_E_TRANSFORM_TYPE_NOT_SET; + + if (FAILED(hr = MFCreateMediaType(type))) + return hr; + + return IMFMediaType_CopyAllItems(decoder->input_type, (IMFAttributes *)*type); }
static HRESULT WINAPI transform_GetOutputCurrentType(IMFTransform *iface, DWORD id, IMFMediaType **type) @@ -583,7 +593,7 @@ static HRESULT WINAPI transform_GetOutputCurrentType(IMFTransform *iface, DWORD struct h264_decoder *decoder = impl_from_IMFTransform(iface); HRESULT hr;
- FIXME("iface %p, id %#lx, type %p stub!\n", iface, id, type); + TRACE("iface %p, id %#lx, type %p\n", iface, id, type);
if (!decoder->output_type) return MF_E_TRANSFORM_TYPE_NOT_SET;
Hi,
It looks like your patch introduced the new failures shown below. Please investigate and fix them before resubmitting your patch. If they are not new, fixing them anyway would help a lot. Otherwise please ask for the known failures list to be updated.
The tests also ran into some preexisting test failures. If you know how to fix them that would be helpful. See the TestBot job for the details:
The full results can be found at: https://testbot.winehq.org/JobDetails.pl?Key=142335
Your paranoid android.
=== debian11b (64 bit WoW report) ===
mf: Unhandled exception: divide by zero in 64-bit code (0x0000000042e74c).
Added some tests to validate that and some more fixes to make the new tests fully pass.
Anything I should do here?
On Mon Jan 29 09:23:10 2024 +0000, Rémi Bernon wrote:
Anything I should do here?
Tests are crashing for me for 64-bit build. See the log[crash.log](/uploads/12ad7abd9f468a263dabf4698634b076/crash.log). I've verified that building without this MR does not crash.
On Mon Jan 29 09:23:10 2024 +0000, Nikolay Sivov wrote:
Tests are crashing for me for 64-bit build. See the log[crash.log](/uploads/12ad7abd9f468a263dabf4698634b076/crash.log). I've verified that building without this MR does not crash.
I don't understand how it can end up with that result, the todo_wine is removed at the same time the H264 decoder transform_GetInputCurrentType is implemented? It should not even print a FIXME anymore. Does it somehow match with a different decoder? Would you mind making a +mfplat trace?
On Mon Jan 29 11:14:28 2024 +0000, Rémi Bernon wrote:
I don't understand how it can end up with that result, the todo_wine is removed at the same time the H264 decoder transform_GetInputCurrentType is implemented? It should not even print a FIXME anymore. Does it somehow match with a different decoder? Would you mind making a +mfplat trace?
I don't know if it's helpful [crash.log](/uploads/77a67a102d4f40403770d873ef441679/crash.log). It does not make it clear to have every decoder use the same method function names.
On Mon Jan 29 16:42:25 2024 +0000, Nikolay Sivov wrote:
I don't know if it's helpful [crash.log](/uploads/77a67a102d4f40403770d873ef441679/crash.log). It does not make it clear to have every decoder use the same method function names.
There's a `00d8:trace:mfplat:h264_decoder_create Created decoder 00007FFFFE8A7A70`, and later `00d8:fixme:mfplat:transform_GetInputCurrentType iface 00007FFFFE8A7A70, id 0, type 00007FFFFE2FF228 stub!`.
Are you sure you're trying with the latest version of this MR and rebuilt winegstreamer.dll? 88922a1002b646100b1f7b52ba1247ebdeeec22c is the commit that removes the `if (hr == S_OK)` and it also removes the transform_GetInputCurrentType FIXME.
On Mon Jan 29 16:52:42 2024 +0000, Rémi Bernon wrote:
There's a `00d8:trace:mfplat:h264_decoder_create Created decoder 00007FFFFE8A7A70`, and later `00d8:fixme:mfplat:transform_GetInputCurrentType iface 00007FFFFE8A7A70, id 0, type 00007FFFFE2FF228 stub!`. Are you sure you're trying with the latest version of this MR and rebuilt winegstreamer.dll? 88922a1002b646100b1f7b52ba1247ebdeeec22c is the commit that removes the `if (hr == S_OK)` and it also removes the transform_GetInputCurrentType FIXME.
Of course, winegstreamer is outdated, because some package did not survive updates.
This merge request was approved by Nikolay Sivov.