[PATCH 0/8] MR10596: mf/topology_loader: Lookup best matching types when connecting transforms.
And improve compatibility more generally. Supersedes !10009 -- https://gitlab.winehq.org/wine/wine/-/merge_requests/10596
From: Conor McCarthy <cmccarthy@codeweavers.com> --- dlls/mf/topology_loader.c | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/dlls/mf/topology_loader.c b/dlls/mf/topology_loader.c index 6709675673f..81ce1d4e209 100644 --- a/dlls/mf/topology_loader.c +++ b/dlls/mf/topology_loader.c @@ -314,6 +314,16 @@ static HRESULT update_media_type_from_upstream(IMFMediaType *media_type, IMFMedi return hr; } +static HRESULT clone_media_type(IMFMediaType *in_type, IMFMediaType **out_type) +{ + HRESULT hr = MFCreateMediaType(out_type); + if (FAILED(hr) || SUCCEEDED(hr = IMFMediaType_CopyAllItems(in_type, (IMFAttributes *)*out_type))) + return hr; + IMFMediaType_Release(*out_type); + *out_type = NULL; + return hr; +} + static HRESULT topology_branch_connect_with_type(IMFTopology *topology, struct topology_branch *branch, IMFMediaType *type) { HRESULT hr; @@ -406,10 +416,9 @@ static HRESULT topology_branch_connect_indirect(IMFTopology *topology, BOOL deco { if (SUCCEEDED(hr = topology_branch_connect_with_type(topology, up_branch, up_type))) { - if (down_type && SUCCEEDED(MFCreateMediaType(&media_type))) + if (down_type && SUCCEEDED(clone_media_type(down_type, &media_type))) { - if (SUCCEEDED(IMFMediaType_CopyAllItems(down_type, (IMFAttributes *)media_type)) - && SUCCEEDED(update_media_type_from_upstream(media_type, up_type)) + if (SUCCEEDED(update_media_type_from_upstream(media_type, up_type)) && SUCCEEDED(IMFMediaTypeHandler_SetCurrentMediaType(down_branch->up.handler, media_type))) method = CONNECT_DIRECT; IMFMediaType_Release(media_type); -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/10596
From: Rémi Bernon <rbernon@codeweavers.com> Based on patches from Conor McCarthy. --- dlls/mf/tests/topology.c | 46 ++++++-------- dlls/mf/topology_loader.c | 128 +++++++++++++++++++++++++++++++++----- 2 files changed, 131 insertions(+), 43 deletions(-) diff --git a/dlls/mf/tests/topology.c b/dlls/mf/tests/topology.c index 7271359d29b..7e0d3496147 100644 --- a/dlls/mf/tests/topology.c +++ b/dlls/mf/tests/topology.c @@ -2249,7 +2249,6 @@ static IMFSampleGrabberSinkCallback *create_test_grabber_callback(void) enum loader_test_flags { LOADER_TODO = 0x1, - LOADER_TODO_OUT_TYPE = 0x2, LOADER_SET_XVP_FOR_PLAYBACK = 0x4, LOADER_NEEDS_VIDEO_PROCESSOR = 0x8, LOADER_SET_ENUMERATE_SOURCE_TYPES = 0x10, @@ -2259,12 +2258,10 @@ enum loader_test_flags LOADER_ADD_RESAMPLER_MFT = 0x100, LOADER_SUPPORT_ANY = 0x200, LOADER_EXPECT_SINK_ENUMERATED = 0x400, - LOADER_EXPECT_SINK_ENUMERATED_TODO = 0x800, LOADER_ADD_TEST_MFT = 0x1000, LOADER_TEST_MFT_EXPECT_CONVERTER = 0x2000, LOADER_EXPECT_MFT_OUTPUT_ENUMERATED = 0x4000, LOADER_EXPECT_MFT_INPUT_ENUMERATED = 0x8000, - LOADER_EXPECT_MFT_INPUT_ENUMERATED_TODO = 0x10000, LOADER_TODO_MFT_OUT_TYPE = 0x40000, }; @@ -2555,7 +2552,7 @@ static void test_topology_loader(void) /* PCM -> PCM, different enumerated bps, no current type, sink allow converter, no current output type */ .input_types = {&audio_pcm_44100}, .output_types = {&audio_pcm_48000}, .sink_method = MF_CONNECT_ALLOW_CONVERTER, .source_method = MF_CONNECT_DIRECT, .expected_result = S_OK, .converter_class = CLSID_CResamplerMediaObject, - .flags = LOADER_NO_CURRENT_OUTPUT | LOADER_SET_MEDIA_TYPES | LOADER_EXPECT_SINK_ENUMERATED_TODO, + .flags = LOADER_NO_CURRENT_OUTPUT | LOADER_SET_MEDIA_TYPES | LOADER_EXPECT_SINK_ENUMERATED, }, { /* PCM -> PCM, different enumerated bps, no current type, sink allow decoder */ @@ -2622,21 +2619,21 @@ static void test_topology_loader(void) .input_types = {&audio_mp3_44100}, .output_types = {&audio_float_48000}, .sink_method = MF_CONNECT_ALLOW_DECODER, .source_method = -1, .current_input = &audio_mp3_44100, .decoded_type = &audio_float_44100_no_ch, .expected_result = S_OK, .decoder_class = CLSID_CMP3DecMediaObject, .converter_class = CLSID_CResamplerMediaObject, - .flags = LOADER_NO_CURRENT_OUTPUT | LOADER_SET_MEDIA_TYPES | LOADER_EXPECT_SINK_ENUMERATED_TODO, + .flags = LOADER_NO_CURRENT_OUTPUT | LOADER_SET_MEDIA_TYPES | LOADER_EXPECT_SINK_ENUMERATED, }, { /* MP3 -> {float, PCM}, need both decoder and converter, no current output type */ .input_types = {&audio_mp3_44100}, .output_types = {&audio_float_48000, &audio_pcm_48000}, .sink_method = MF_CONNECT_ALLOW_DECODER, .source_method = -1, .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_NO_CURRENT_OUTPUT | LOADER_SET_MEDIA_TYPES | LOADER_EXPECT_SINK_ENUMERATED_TODO, + .flags = LOADER_NO_CURRENT_OUTPUT | LOADER_SET_MEDIA_TYPES | LOADER_EXPECT_SINK_ENUMERATED, }, { /* MP3 -> {PCM, float}, need both decoder and converter, no current output type */ .input_types = {&audio_mp3_44100}, .output_types = {&audio_pcm_48000, &audio_float_48000}, .sink_method = MF_CONNECT_ALLOW_DECODER, .source_method = -1, .current_input = &audio_mp3_44100, .decoded_type = &audio_float_44100_stereo, .expected_output_index = 1, .expected_result = S_OK, .decoder_class = CLSID_CMP3DecMediaObject, .converter_class = CLSID_CResamplerMediaObject, - .flags = LOADER_NO_CURRENT_OUTPUT | LOADER_SET_MEDIA_TYPES | LOADER_TODO_OUT_TYPE | LOADER_EXPECT_SINK_ENUMERATED_TODO, + .flags = LOADER_NO_CURRENT_OUTPUT | LOADER_SET_MEDIA_TYPES | LOADER_EXPECT_SINK_ENUMERATED, }, { @@ -2650,7 +2647,7 @@ static void test_topology_loader(void) .input_types = {&audio_mp3_44100, &audio_pcm_44100}, .output_types = {&audio_pcm_44100}, .sink_method = MF_CONNECT_ALLOW_DECODER, .source_method = MF_CONNECT_RESOLVE_INDEPENDENT_OUTPUTTYPES, .expected_result = S_OK, .decoder_class = CLSID_CMP3DecMediaObject, - .flags = LOADER_NO_CURRENT_OUTPUT | LOADER_SET_MEDIA_TYPES | LOADER_SET_ENUMERATE_SOURCE_TYPES | LOADER_EXPECT_SINK_ENUMERATED_TODO, + .flags = LOADER_NO_CURRENT_OUTPUT | LOADER_SET_MEDIA_TYPES | LOADER_SET_ENUMERATE_SOURCE_TYPES | LOADER_EXPECT_SINK_ENUMERATED, }, { @@ -2690,14 +2687,14 @@ static void test_topology_loader(void) .mft_input_type = &audio_pcm_44100, .mft_output_types = {&audio_pcm_48000}, .decoded_type = &audio_pcm_44100, .expected_result = S_OK, .decoder_class = CLSID_CMP3DecMediaObject, - .flags = LOADER_ADD_TEST_MFT | LOADER_EXPECT_MFT_INPUT_ENUMERATED_TODO, + .flags = LOADER_ADD_TEST_MFT | LOADER_EXPECT_MFT_INPUT_ENUMERATED, }, { /* MP3 -> PCM, different enumerated bps, add incompatible test MFT, configure MFT */ .input_types = {&audio_mp3_44100}, .output_types = {&audio_pcm_48000}, .sink_method = MF_CONNECT_DIRECT, .source_method = MF_CONNECT_DIRECT, .mft_input_type = &audio_aac_44100, .mft_output_types = {&audio_pcm_48000}, .expected_result = MF_E_TOPO_CODEC_NOT_FOUND, - .flags = LOADER_ADD_TEST_MFT | LOADER_EXPECT_MFT_INPUT_ENUMERATED_TODO, + .flags = LOADER_ADD_TEST_MFT | LOADER_EXPECT_MFT_INPUT_ENUMERATED, }, { @@ -2752,7 +2749,7 @@ static void test_topology_loader(void) /* RGB32 -> Any Video, no current output type, refuse input type */ .input_types = {&video_i420_1280}, .output_types = {&video_video_processor_rgb32}, .sink_method = -1, .source_method = -1, .expected_result = S_OK, .converter_class = CLSID_CColorConvertDMO, - .flags = LOADER_NO_CURRENT_OUTPUT | LOADER_SET_INVALID_INPUT | LOADER_SET_MEDIA_TYPES | LOADER_EXPECT_SINK_ENUMERATED_TODO, + .flags = LOADER_NO_CURRENT_OUTPUT | LOADER_SET_INVALID_INPUT | LOADER_SET_MEDIA_TYPES | LOADER_EXPECT_SINK_ENUMERATED, }, { @@ -2760,7 +2757,7 @@ static void test_topology_loader(void) .input_types = {&video_h264_1280}, .output_types = {&video_color_convert_1280_rgb32, &video_video_processor_1280_rgb32}, .sink_method = -1, .source_method = -1, .decoded_type = &video_nv12_1280, .expected_output_index = 1, .expected_result = S_OK, .decoder_class = CLSID_CMSH264DecoderMFT, .converter_class = CLSID_CColorConvertDMO, - .flags = LOADER_NO_CURRENT_OUTPUT | LOADER_SET_MEDIA_TYPES | LOADER_EXPECT_SINK_ENUMERATED_TODO | LOADER_TODO, + .flags = LOADER_NO_CURRENT_OUTPUT | LOADER_SET_MEDIA_TYPES | LOADER_EXPECT_SINK_ENUMERATED | LOADER_TODO, }, { /* H264 -> {DMO_RGB32, MF_RGB32} */ @@ -2775,28 +2772,28 @@ static void test_topology_loader(void) .decoded_type = &video_generic_yuv_1280, .expected_output_index = 1, .decoded_subtypes = {&MFVideoFormat_NV12, &MFVideoFormat_YUY2}, .expected_result = S_OK, .decoder_class = CLSID_CMSH264DecoderMFT, .converter_class = CLSID_CColorConvertDMO, - .flags = LOADER_NO_CURRENT_OUTPUT | LOADER_SET_MEDIA_TYPES | LOADER_TODO_OUT_TYPE | LOADER_EXPECT_SINK_ENUMERATED_TODO, + .flags = LOADER_NO_CURRENT_OUTPUT | LOADER_SET_MEDIA_TYPES | LOADER_EXPECT_SINK_ENUMERATED, }, { /* H264 -> {RGB24, RGB32} */ .input_types = {&video_h264_1280}, .output_types = {&video_video_processor_1280_rgb24, &video_video_processor_1280_rgb32}, .sink_method = -1, .source_method = -1, .decoded_type = &video_nv12_1280, .expected_output_index = 1, .expected_result = S_OK, .decoder_class = CLSID_CMSH264DecoderMFT, .converter_class = CLSID_CColorConvertDMO, - .flags = LOADER_NO_CURRENT_OUTPUT | LOADER_SET_MEDIA_TYPES | LOADER_TODO_OUT_TYPE | LOADER_EXPECT_SINK_ENUMERATED_TODO, + .flags = LOADER_NO_CURRENT_OUTPUT | LOADER_SET_MEDIA_TYPES | LOADER_EXPECT_SINK_ENUMERATED, }, { /* H264 -> {RGB24, RGB555} */ .input_types = {&video_h264_1280}, .output_types = {&video_video_processor_1280_rgb24, &video_video_processor_1280_rgb555}, .sink_method = -1, .source_method = -1, .decoded_type = &video_nv12_1280, .expected_output_index = 1, .expected_result = S_OK, .decoder_class = CLSID_CMSH264DecoderMFT, .converter_class = CLSID_CColorConvertDMO, - .flags = LOADER_NO_CURRENT_OUTPUT | LOADER_SET_MEDIA_TYPES | LOADER_TODO_OUT_TYPE | LOADER_EXPECT_SINK_ENUMERATED_TODO, + .flags = LOADER_NO_CURRENT_OUTPUT | LOADER_SET_MEDIA_TYPES | LOADER_EXPECT_SINK_ENUMERATED, }, { /* H264 -> {RGB555, RGB24} */ .input_types = {&video_h264_1280}, .output_types = {&video_video_processor_1280_rgb555, &video_video_processor_1280_rgb24}, .sink_method = -1, .source_method = -1, .decoded_type = &video_nv12_1280, .expected_output_index = 1, .expected_result = S_OK, .decoder_class = CLSID_CMSH264DecoderMFT, .converter_class = CLSID_CColorConvertDMO, - .flags = LOADER_NO_CURRENT_OUTPUT | LOADER_SET_MEDIA_TYPES | LOADER_TODO_OUT_TYPE | LOADER_EXPECT_SINK_ENUMERATED_TODO, + .flags = LOADER_NO_CURRENT_OUTPUT | LOADER_SET_MEDIA_TYPES | LOADER_EXPECT_SINK_ENUMERATED, }, { @@ -2804,7 +2801,7 @@ static void test_topology_loader(void) .input_types = {&video_h264_1280}, .output_types = {&video_color_convert_1280_rgb32}, .sink_method = -1, .source_method = -1, .decoded_type = &video_nv12_1280, .expected_result = MF_E_TOPO_CODEC_NOT_FOUND, .decoder_class = CLSID_CMSH264DecoderMFT, .converter_class = CLSID_CColorConvertDMO, - .flags = LOADER_NO_CURRENT_OUTPUT | LOADER_SET_MEDIA_TYPES | LOADER_EXPECT_SINK_ENUMERATED_TODO, + .flags = LOADER_NO_CURRENT_OUTPUT | LOADER_SET_MEDIA_TYPES | LOADER_EXPECT_SINK_ENUMERATED, }, { @@ -2813,7 +2810,7 @@ static void test_topology_loader(void) .decoded_type = &video_generic_yuv_1280, .expected_output_index = 1, .decoded_subtypes = {&MFVideoFormat_NV12, &MFVideoFormat_YUY2}, .expected_result = S_OK, .decoder_class = CLSID_CMSH264DecoderMFT, .converter_class = CLSID_VideoProcessorMFT, - .flags = LOADER_NO_CURRENT_OUTPUT | LOADER_SET_MEDIA_TYPES | LOADER_SET_XVP_FOR_PLAYBACK | LOADER_EXPECT_SINK_ENUMERATED_TODO | LOADER_TODO, + .flags = LOADER_NO_CURRENT_OUTPUT | LOADER_SET_MEDIA_TYPES | LOADER_SET_XVP_FOR_PLAYBACK | LOADER_EXPECT_SINK_ENUMERATED | LOADER_TODO, }, { /* H264 -> RGB32, resize, set XVP */ @@ -2828,21 +2825,21 @@ static void test_topology_loader(void) .input_types = {&video_h264_1280}, .output_types = {&video_color_convert_1280_rgb32}, .sink_method = -1, .source_method = -1, .mft_input_type = &video_color_convert_1280_rgb32, .mft_output_types = {&video_color_convert_1280_rgb32}, .expected_result = MF_E_TOPO_CODEC_NOT_FOUND, .decoder_class = CLSID_CMSH264DecoderMFT, - .flags = LOADER_ADD_TEST_MFT | LOADER_EXPECT_MFT_INPUT_ENUMERATED_TODO, + .flags = LOADER_ADD_TEST_MFT | LOADER_EXPECT_MFT_INPUT_ENUMERATED, }, { /* H264 -> RGB32, Video Processor media type, add test MFT */ .input_types = {&video_h264_1280}, .output_types = {&video_video_processor_1280_rgb32}, .sink_method = -1, .source_method = -1, .mft_input_type = &video_video_processor_1280_rgb32, .mft_output_types = {&video_video_processor_1280_rgb32}, .expected_result = S_OK, .decoder_class = CLSID_CMSH264DecoderMFT, .converter_class = CLSID_CColorConvertDMO, - .flags = LOADER_ADD_TEST_MFT | LOADER_TEST_MFT_EXPECT_CONVERTER | LOADER_EXPECT_MFT_INPUT_ENUMERATED_TODO, + .flags = LOADER_ADD_TEST_MFT | LOADER_TEST_MFT_EXPECT_CONVERTER | LOADER_EXPECT_MFT_INPUT_ENUMERATED, }, { /* H264 -> NV12, add test MFT */ .input_types = {&video_h264_1280}, .output_types = {&video_nv12_1280}, .sink_method = -1, .source_method = -1, .mft_input_type = &video_nv12_1280, .mft_output_types = {&video_nv12_1280}, .expected_result = S_OK, .decoder_class = CLSID_CMSH264DecoderMFT, - .flags = LOADER_ADD_TEST_MFT | LOADER_EXPECT_MFT_INPUT_ENUMERATED_TODO, + .flags = LOADER_ADD_TEST_MFT | LOADER_EXPECT_MFT_INPUT_ENUMERATED, }, }; @@ -3334,7 +3331,6 @@ todo_wine { ok(hr == S_OK, "Failed to get transform output type, hr %#lx.\n", hr); hr = IMFMediaType_Compare(output_types[test->expected_output_index], (IMFAttributes *)media_type, MF_ATTRIBUTES_MATCH_OUR_ITEMS, &ret); ok(hr == S_OK, "Failed to compare media types, hr %#lx.\n", hr); - todo_wine_if(test->flags & LOADER_TODO_OUT_TYPE) ok(ret, "Output type of last transform doesn't match sink node type.\n"); IMFMediaType_Release(media_type); @@ -3370,14 +3366,12 @@ todo_wine { else ok(!handler.enum_count, "got %lu GetMediaTypeByIndex\n", handler.enum_count); ok(!handler.set_current_count, "got %lu SetCurrentMediaType\n", handler.set_current_count); - todo_wine_if(test->flags & LOADER_EXPECT_SINK_ENUMERATED_TODO) - ok(handler.enum_complete == !!(test->flags & (LOADER_EXPECT_SINK_ENUMERATED | LOADER_EXPECT_SINK_ENUMERATED_TODO)), + ok(handler.enum_complete == !!(test->flags & LOADER_EXPECT_SINK_ENUMERATED), "Got enum_complete %u.\n", handler.enum_complete); if (test_transform) { - todo_wine_if(test->flags & LOADER_EXPECT_MFT_INPUT_ENUMERATED_TODO) - ok(test_transform->input_enum_complete == !!(test->flags & (LOADER_EXPECT_MFT_INPUT_ENUMERATED | LOADER_EXPECT_MFT_INPUT_ENUMERATED_TODO)), + ok(test_transform->input_enum_complete == !!(test->flags & LOADER_EXPECT_MFT_INPUT_ENUMERATED), "got transform input_enum_complete %u\n", test_transform->input_enum_complete); todo_wine_if(test_transform->output_enum_complete && (test->flags & LOADER_TODO)) ok(test_transform->output_enum_complete == !!(test->flags & LOADER_EXPECT_MFT_OUTPUT_ENUMERATED), diff --git a/dlls/mf/topology_loader.c b/dlls/mf/topology_loader.c index 81ce1d4e209..46d5e80f7f1 100644 --- a/dlls/mf/topology_loader.c +++ b/dlls/mf/topology_loader.c @@ -324,6 +324,113 @@ static HRESULT clone_media_type(IMFMediaType *in_type, IMFMediaType **out_type) return hr; } +/* safe version of IMFMediaTypeHandler_GetCurrentMediaType that makes a copy of the returned type if necessary */ +static HRESULT media_type_handler_get_current(IMFMediaTypeHandler *handler, IMFMediaType **type) +{ + IMFMediaType *tmp; + HRESULT hr; + + if (FAILED(hr = IMFMediaTypeHandler_GetCurrentMediaType(handler, &tmp))) + return hr; + hr = clone_media_type(tmp, type); + IMFMediaType_Release(tmp); + return hr; +} + +/* safe version of IMFMediaTypeHandler_GetMediaTypeByIndex that makes a copy of the returned type if necessary */ +static HRESULT media_type_handler_get_type(IMFMediaTypeHandler *handler, UINT32 i, IMFMediaType **type) +{ + IMFMediaType *tmp; + HRESULT hr; + + if (FAILED(hr = IMFMediaTypeHandler_GetMediaTypeByIndex(handler, i, &tmp))) + return hr; + hr = clone_media_type(tmp, type); + IMFMediaType_Release(tmp); + return hr; +} + +static BOOL is_better_media_type(IMFMediaType *type, IMFMediaType *best) +{ + GUID guid = {0}; + + IMFMediaType_GetGUID(type, &MF_MT_SUBTYPE, &guid); + if (IsEqualGUID(&guid, &MFAudioFormat_Float) || IsEqualGUID(&guid, &MFAudioFormat_PCM)) + { + IMFMediaType_GetGUID(best, &MF_MT_SUBTYPE, &guid); + return !IsEqualGUID(&guid, &MFAudioFormat_Float); + } + + return TRUE; +} + +static void topology_branch_find_best_up_type(struct topology_branch *branch, IMFMediaType *down_type, IMFMediaType **type) +{ + IMFMediaType *up_type; + DWORD flags; + HRESULT hr; + + /* actually set the down type to enforce some transform internal parameters like frame size on the enumerated types */ + if (FAILED(hr = IMFMediaTypeHandler_SetCurrentMediaType(branch->up.handler, down_type))) + { + TRACE("down type %s not supported by upstream, hr %#lx\n", debugstr_media_type(down_type), hr); + return; + } + + for (UINT i = 0; SUCCEEDED(hr = media_type_handler_get_type(branch->up.handler, i, &up_type)); i++) + { + if (FAILED(hr = update_media_type_from_upstream(up_type, down_type))) + WARN("Failed to update media type, hr %#lx\n", hr); + + if ((hr = IMFMediaType_IsEqual(up_type, down_type, &flags)) != S_OK) + TRACE("up type %s differs from down type %s, hr %#lx flags %#lx\n", debugstr_media_type(up_type), + debugstr_media_type(down_type), hr, flags); + else if (FAILED(hr = IMFMediaTypeHandler_IsMediaTypeSupported(branch->down.handler, up_type, NULL))) + TRACE("up type %s not supported by downstream, hr %#lx\n", debugstr_media_type(up_type), hr); + else if (*type && !is_better_media_type(up_type, *type)) + TRACE("up type %s isn't better than selected type %s\n", debugstr_media_type(up_type), + debugstr_media_type(*type)); + else + { + TRACE("selecting up type %s\n", debugstr_media_type(up_type)); + if (*type) + IMFMediaType_Release(*type); + *type = up_type; + continue; + } + IMFMediaType_Release(up_type); + } +} + +static HRESULT topology_branch_find_best_type(struct topology_branch *branch, IMFMediaType *upstream, IMFMediaType **type) +{ + BOOL enumerate = topology_node_get_type(branch->down.node) == MF_TOPOLOGY_TRANSFORM_NODE; + IMFMediaType *down_type; + HRESULT hr; + + *type = NULL; + + if (SUCCEEDED(hr = media_type_handler_get_current(branch->down.handler, &down_type))) + { + if (FAILED(hr = update_media_type_from_upstream(down_type, upstream))) + WARN("Failed to update media type, hr %#lx\n", hr); + topology_branch_find_best_up_type(branch, down_type, type); + IMFMediaType_Release(down_type); + } + else if (enumerate || hr == MF_E_NOT_INITIALIZED) + { + for (UINT i = 0; SUCCEEDED(hr = media_type_handler_get_type(branch->down.handler, i, &down_type)); i++) + { + if (FAILED(hr = update_media_type_from_upstream(down_type, upstream))) + WARN("Failed to update media type, hr %#lx\n", hr); + topology_branch_find_best_up_type(branch, down_type, type); + IMFMediaType_Release(down_type); + } + } + + return *type ? S_OK : MF_E_INVALIDMEDIATYPE; +} + static HRESULT topology_branch_connect_with_type(IMFTopology *topology, struct topology_branch *branch, IMFMediaType *type) { HRESULT hr; @@ -347,8 +454,6 @@ static HRESULT topology_branch_connect_with_type(IMFTopology *topology, struct t static HRESULT topology_branch_connect(IMFTopology *topology, enum connect_method method_mask, struct topology_branch *branch, BOOL enumerate_source_types); -static HRESULT topology_branch_connect_down(IMFTopology *topology, enum connect_method method_mask, - struct topology_branch *branch, IMFMediaType *up_type); static HRESULT topology_branch_connect_indirect(IMFTopology *topology, BOOL decoder, struct topology_branch *branch, IMFMediaType *up_type, IMFMediaType *down_type) { @@ -401,7 +506,6 @@ static HRESULT topology_branch_connect_indirect(IMFTopology *topology, BOOL deco for (i = 0; i < count; ++i) { struct topology_branch *up_branch, *down_branch; - enum connect_method method = method_mask; IMFMediaType *media_type; if (FAILED(IMFActivate_ActivateObject(activates[i], &IID_IMFTransform, (void **)&transform))) @@ -416,23 +520,13 @@ static HRESULT topology_branch_connect_indirect(IMFTopology *topology, BOOL deco { if (SUCCEEDED(hr = topology_branch_connect_with_type(topology, up_branch, up_type))) { - if (down_type && SUCCEEDED(clone_media_type(down_type, &media_type))) + if (FAILED(hr = topology_branch_find_best_type(down_branch, up_type, &media_type))) + hr = topology_branch_connect(topology, method_mask, down_branch, !down_type); + else { - if (SUCCEEDED(update_media_type_from_upstream(media_type, up_type)) - && SUCCEEDED(IMFMediaTypeHandler_SetCurrentMediaType(down_branch->up.handler, media_type))) - method = CONNECT_DIRECT; + hr = topology_branch_connect_with_type(topology, down_branch, media_type); IMFMediaType_Release(media_type); } - - if (method != CONNECT_DIRECT - && SUCCEEDED(IMFMediaTypeHandler_GetMediaTypeByIndex(down_branch->up.handler, 0, &media_type))) - { - if (SUCCEEDED(update_media_type_from_upstream(media_type, up_type))) - IMFMediaTypeHandler_SetCurrentMediaType(down_branch->up.handler, media_type); - IMFMediaType_Release(media_type); - } - - hr = topology_branch_connect(topology, method, down_branch, !down_type); } topology_branch_destroy(down_branch); topology_branch_destroy(up_branch); -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/10596
From: Rémi Bernon <rbernon@codeweavers.com> Based on patches from Conor McCarthy. --- dlls/mf/tests/topology.c | 4 ++-- dlls/mf/topology_loader.c | 13 ++----------- 2 files changed, 4 insertions(+), 13 deletions(-) diff --git a/dlls/mf/tests/topology.c b/dlls/mf/tests/topology.c index 7e0d3496147..d632b60c781 100644 --- a/dlls/mf/tests/topology.c +++ b/dlls/mf/tests/topology.c @@ -2757,7 +2757,7 @@ static void test_topology_loader(void) .input_types = {&video_h264_1280}, .output_types = {&video_color_convert_1280_rgb32, &video_video_processor_1280_rgb32}, .sink_method = -1, .source_method = -1, .decoded_type = &video_nv12_1280, .expected_output_index = 1, .expected_result = S_OK, .decoder_class = CLSID_CMSH264DecoderMFT, .converter_class = CLSID_CColorConvertDMO, - .flags = LOADER_NO_CURRENT_OUTPUT | LOADER_SET_MEDIA_TYPES | LOADER_EXPECT_SINK_ENUMERATED | LOADER_TODO, + .flags = LOADER_NO_CURRENT_OUTPUT | LOADER_SET_MEDIA_TYPES | LOADER_EXPECT_SINK_ENUMERATED, }, { /* H264 -> {DMO_RGB32, MF_RGB32} */ @@ -2810,7 +2810,7 @@ static void test_topology_loader(void) .decoded_type = &video_generic_yuv_1280, .expected_output_index = 1, .decoded_subtypes = {&MFVideoFormat_NV12, &MFVideoFormat_YUY2}, .expected_result = S_OK, .decoder_class = CLSID_CMSH264DecoderMFT, .converter_class = CLSID_VideoProcessorMFT, - .flags = LOADER_NO_CURRENT_OUTPUT | LOADER_SET_MEDIA_TYPES | LOADER_SET_XVP_FOR_PLAYBACK | LOADER_EXPECT_SINK_ENUMERATED | LOADER_TODO, + .flags = LOADER_NO_CURRENT_OUTPUT | LOADER_SET_MEDIA_TYPES | LOADER_SET_XVP_FOR_PLAYBACK | LOADER_EXPECT_SINK_ENUMERATED, }, { /* H264 -> RGB32, resize, set XVP */ diff --git a/dlls/mf/topology_loader.c b/dlls/mf/topology_loader.c index 46d5e80f7f1..18b434346d3 100644 --- a/dlls/mf/topology_loader.c +++ b/dlls/mf/topology_loader.c @@ -458,7 +458,7 @@ static HRESULT topology_branch_connect_indirect(IMFTopology *topology, BOOL deco struct topology_branch *branch, IMFMediaType *up_type, IMFMediaType *down_type) { enum connect_method method_mask = CONNECT_DIRECT; - MFT_REGISTER_TYPE_INFO input_info, output_info; + MFT_REGISTER_TYPE_INFO input_info; IMFTransform *transform; IMFActivate **activates; IMFTopologyNode *node; @@ -473,15 +473,6 @@ static HRESULT topology_branch_connect_indirect(IMFTopology *topology, BOOL deco return hr; if (FAILED(hr = IMFMediaType_GetGUID(up_type, &MF_MT_SUBTYPE, &input_info.guidSubtype))) return hr; - if (!down_type) - output_info = input_info; - else - { - if (FAILED(hr = IMFMediaType_GetMajorType(down_type, &output_info.guidMajorType))) - return hr; - if (FAILED(hr = IMFMediaType_GetGUID(down_type, &MF_MT_SUBTYPE, &output_info.guidSubtype))) - return hr; - } if (IsEqualGUID(&input_info.guidMajorType, &MFMediaType_Audio)) category = decoder ? MFT_CATEGORY_AUDIO_DECODER : MFT_CATEGORY_AUDIO_EFFECT; @@ -500,7 +491,7 @@ static HRESULT topology_branch_connect_indirect(IMFTopology *topology, BOOL deco method_mask |= CONNECT_CONVERTER; } - if (FAILED(hr = MFTEnumEx(category, MFT_ENUM_FLAG_ALL, &input_info, decoder ? NULL : &output_info, &activates, &count))) + if (FAILED(hr = MFTEnumEx(category, MFT_ENUM_FLAG_ALL, &input_info, NULL, &activates, &count))) return hr; for (i = 0; i < count; ++i) -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/10596
From: Rémi Bernon <rbernon@codeweavers.com> Based on patches from Conor McCarthy. --- dlls/mf/topology_loader.c | 69 ++++++++++++++++++++------------------- 1 file changed, 35 insertions(+), 34 deletions(-) diff --git a/dlls/mf/topology_loader.c b/dlls/mf/topology_loader.c index 18b434346d3..4fcd7f9279b 100644 --- a/dlls/mf/topology_loader.c +++ b/dlls/mf/topology_loader.c @@ -620,19 +620,34 @@ done: } static HRESULT topology_branch_foreach_up_types(IMFTopology *topology, enum connect_method method_mask, - struct topology_branch *branch) + struct topology_branch *branch, BOOL enumerate) { - IMFMediaType *type; - DWORD index = 0; - HRESULT hr; + HRESULT hr = MF_E_INVALIDMEDIATYPE; + IMFMediaType *up_type; - while (SUCCEEDED(hr = IMFMediaTypeHandler_GetMediaTypeByIndex(branch->up.handler, index++, &type))) + TRACE("topology %p, method_mask %#x, branch %s.\n", topology, method_mask, debugstr_topology_branch(branch)); + + if (enumerate) { - hr = topology_branch_connect_down(topology, method_mask, branch, type); - IMFMediaType_Release(type); - if (SUCCEEDED(hr)) - break; + for (UINT i = 0; SUCCEEDED(hr = IMFMediaTypeHandler_GetMediaTypeByIndex(branch->up.handler, i, &up_type)); i++) + { + hr = topology_branch_connect_down(topology, method_mask, branch, up_type); + IMFMediaType_Release(up_type); + if (SUCCEEDED(hr)) + return hr; + } + return hr; + } + + if (SUCCEEDED(hr = IMFMediaTypeHandler_GetCurrentMediaType(branch->up.handler, &up_type)) + || SUCCEEDED(hr = IMFMediaTypeHandler_GetMediaTypeByIndex(branch->up.handler, 0, &up_type))) + { + hr = topology_branch_connect_down(topology, method_mask, branch, up_type); + IMFMediaType_Release(up_type); + return hr; } + + TRACE("returning %#lx\n", hr); return hr; } @@ -648,34 +663,20 @@ static HRESULT topology_branch_connect(IMFTopology *topology, enum connect_metho down_method = MF_CONNECT_ALLOW_DECODER; down_method = connect_method_from_mf(down_method) & method_mask; - if (enumerate_source_types) - { - if (topology_node_get_type(branch->up.node) != MF_TOPOLOGY_SOURCESTREAM_NODE - || FAILED(IMFTopologyNode_GetUINT32(branch->up.node, &MF_TOPONODE_CONNECT_METHOD, &up_method))) - up_method = MF_CONNECT_DIRECT; + if (topology_node_get_type(branch->up.node) != MF_TOPOLOGY_SOURCESTREAM_NODE + || FAILED(IMFTopologyNode_GetUINT32(branch->up.node, &MF_TOPONODE_CONNECT_METHOD, &up_method))) + up_method = MF_CONNECT_DIRECT; - if (up_method & MF_CONNECT_RESOLVE_INDEPENDENT_OUTPUTTYPES) - hr = topology_branch_foreach_up_types(topology, down_method, branch); - else - { - if (FAILED(hr) && (down_method & CONNECT_DIRECT)) - hr = topology_branch_foreach_up_types(topology, CONNECT_DIRECT, branch); - if (FAILED(hr) && (down_method & CONNECT_CONVERTER)) - hr = topology_branch_foreach_up_types(topology, CONNECT_CONVERTER, branch); - if (FAILED(hr) && (down_method & CONNECT_DECODER)) - hr = topology_branch_foreach_up_types(topology, CONNECT_DECODER, branch); - } - } + if (up_method & MF_CONNECT_RESOLVE_INDEPENDENT_OUTPUTTYPES) + hr = topology_branch_foreach_up_types(topology, down_method, branch, enumerate_source_types); else { - IMFMediaType *up_type; - - if (SUCCEEDED(hr = IMFMediaTypeHandler_GetCurrentMediaType(branch->up.handler, &up_type)) - || SUCCEEDED(hr = IMFMediaTypeHandler_GetMediaTypeByIndex(branch->up.handler, 0, &up_type))) - { - hr = topology_branch_connect_down(topology, down_method, branch, up_type); - IMFMediaType_Release(up_type); - } + if (FAILED(hr) && (down_method & CONNECT_DIRECT)) + hr = topology_branch_foreach_up_types(topology, CONNECT_DIRECT, branch, enumerate_source_types); + if (FAILED(hr) && (down_method & CONNECT_CONVERTER)) + hr = topology_branch_foreach_up_types(topology, CONNECT_CONVERTER, branch, enumerate_source_types); + if (FAILED(hr) && (down_method & CONNECT_DECODER)) + hr = topology_branch_foreach_up_types(topology, CONNECT_DECODER, branch, enumerate_source_types); } TRACE("returning %#lx\n", hr); -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/10596
From: Rémi Bernon <rbernon@codeweavers.com> Based on patches from Conor McCarthy. --- dlls/mf/topology_loader.c | 76 ++++++++++++++++++++++++++++++--------- 1 file changed, 60 insertions(+), 16 deletions(-) diff --git a/dlls/mf/topology_loader.c b/dlls/mf/topology_loader.c index 4fcd7f9279b..be2a38fd987 100644 --- a/dlls/mf/topology_loader.c +++ b/dlls/mf/topology_loader.c @@ -581,41 +581,85 @@ HRESULT topology_node_init_media_type(IMFTopologyNode *node, DWORD stream, BOOL return hr; } -static HRESULT topology_branch_connect_down(IMFTopology *topology, enum connect_method method, - struct topology_branch *branch, IMFMediaType *up_type) +static HRESULT topology_branch_connect_direct(IMFTopology *topology, struct topology_branch *branch, IMFMediaType *up_type) { - HRESULT hr = MF_E_INVALIDMEDIATYPE; - IMFMediaType *down_type = NULL; + IMFMediaType *down_type, *type; DWORD flags; + HRESULT hr; - TRACE("topology %p, method %#x, branch %s, up_type %s.\n", topology, method, - debugstr_topology_branch(branch), debugstr_media_type(up_type)); - - get_first_supported_media_type(branch->down.handler, &down_type); + TRACE("topology %p, branch %s, up_type %s.\n", topology, debugstr_topology_branch(branch), + debugstr_media_type(up_type)); - if (method & CONNECT_DIRECT) + if (SUCCEEDED(hr = IMFMediaTypeHandler_GetCurrentMediaType(branch->down.handler, &down_type))) { - if (down_type && IMFMediaType_IsEqual(up_type, down_type, &flags) == S_OK) - { + if (IMFMediaType_IsEqual(up_type, down_type, &flags) == S_OK) hr = topology_branch_connect_with_type(topology, branch, up_type); - goto done; + else + { + TRACE("current type %s differs from up type %s, hr %#lx\n", debugstr_media_type(down_type), + debugstr_media_type(up_type), hr); + hr = MF_E_INVALIDMEDIATYPE; } + IMFMediaType_Release(down_type); + TRACE("returning %#lx\n", hr); + return hr; + } - if (SUCCEEDED(hr = IMFMediaTypeHandler_IsMediaTypeSupported(branch->down.handler, up_type, NULL))) + IMFMediaType_AddRef((type = up_type)); + + if (hr == MF_E_NOT_INITIALIZED) + { + for (UINT i = 0; SUCCEEDED(hr = IMFMediaTypeHandler_GetMediaTypeByIndex(branch->down.handler, i, &down_type)); i++) { - hr = topology_branch_connect_with_type(topology, branch, up_type); - goto done; + if ((hr = IMFMediaType_IsEqual(up_type, down_type, &flags)) != S_OK) + TRACE("down type %s differs from up type %s, hr %#lx flags %#lx\n", debugstr_media_type(down_type), + debugstr_media_type(up_type), hr, flags); + else if (FAILED(hr = IMFMediaTypeHandler_IsMediaTypeSupported(branch->down.handler, down_type, NULL))) + TRACE("down type %s not supported by downstream, hr %#lx\n", debugstr_media_type(down_type), hr); + else if (FAILED(hr = IMFMediaTypeHandler_IsMediaTypeSupported(branch->up.handler, down_type, NULL))) + TRACE("down type %s not supported by upstream, hr %#lx\n", debugstr_media_type(down_type), hr); + else + { + TRACE("selecting down type %s\n", debugstr_media_type(down_type)); + IMFMediaType_Release(type); + type = down_type; + continue; + } + IMFMediaType_Release(down_type); } } + if (FAILED(hr = IMFMediaTypeHandler_IsMediaTypeSupported(branch->down.handler, type, NULL))) + TRACE("type %s not supported by downstream, hr %#lx\n", debugstr_media_type(type), hr); + else + hr = topology_branch_connect_with_type(topology, branch, type); + + IMFMediaType_Release(type); + TRACE("returning %#lx\n", hr); + return hr; +} + +static HRESULT topology_branch_connect_down(IMFTopology *topology, enum connect_method method, + struct topology_branch *branch, IMFMediaType *up_type) +{ + HRESULT hr = MF_E_INVALIDMEDIATYPE; + IMFMediaType *down_type = NULL; + + TRACE("topology %p, method %#x, branch %s, up_type %s.\n", topology, method, + debugstr_topology_branch(branch), debugstr_media_type(up_type)); + + get_first_supported_media_type(branch->down.handler, &down_type); + + if (FAILED(hr) && (method & CONNECT_DIRECT)) + hr = topology_branch_connect_direct(topology, branch, up_type); if (FAILED(hr) && (method & CONNECT_CONVERTER)) hr = topology_branch_connect_indirect(topology, FALSE, branch, up_type, down_type); if (FAILED(hr) && (method & CONNECT_DECODER)) hr = topology_branch_connect_indirect(topology, TRUE, branch, up_type, down_type); -done: if (down_type) IMFMediaType_Release(down_type); + TRACE("returning %#lx\n", hr); return hr; } -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/10596
From: Rémi Bernon <rbernon@codeweavers.com> Based on patches from Conor McCarthy. --- dlls/mf/tests/topology.c | 4 +-- dlls/mf/topology_loader.c | 75 +++++++++++++++++++-------------------- 2 files changed, 38 insertions(+), 41 deletions(-) diff --git a/dlls/mf/tests/topology.c b/dlls/mf/tests/topology.c index d632b60c781..eb029e3449e 100644 --- a/dlls/mf/tests/topology.c +++ b/dlls/mf/tests/topology.c @@ -2262,7 +2262,6 @@ enum loader_test_flags LOADER_TEST_MFT_EXPECT_CONVERTER = 0x2000, LOADER_EXPECT_MFT_OUTPUT_ENUMERATED = 0x4000, LOADER_EXPECT_MFT_INPUT_ENUMERATED = 0x8000, - LOADER_TODO_MFT_OUT_TYPE = 0x40000, }; static void test_topology_loader(void) @@ -2656,7 +2655,7 @@ static void test_topology_loader(void) .mft_output_types = {&audio_float_minimal, &audio_pcm_minimal, &audio_float_48000, &audio_pcm_48000}, .mft_current_output = &audio_pcm_minimal, .expected_result = MF_E_INVALIDMEDIATYPE, - .flags = LOADER_ADD_TEST_MFT | LOADER_TODO_MFT_OUT_TYPE | LOADER_TODO, + .flags = LOADER_ADD_TEST_MFT, }, { /* PCM -> PCM, different enumerated bps, add test MFT */ @@ -3378,7 +3377,6 @@ todo_wine { "got transform output_enum_complete %u\n", test_transform->output_enum_complete); ok(test_transform->input_type_set == (test->expected_result != MF_E_TOPO_CODEC_NOT_FOUND), "Got transform input_type_set %u.\n", test_transform->input_type_set); - todo_wine_if(test->flags & LOADER_TODO_MFT_OUT_TYPE) ok(test_transform->output_type_set == SUCCEEDED(test->expected_result), "Got transform output_type_set %u.\n", test_transform->output_type_set); IMFTransform_Release(&test_transform->IMFTransform_iface); diff --git a/dlls/mf/topology_loader.c b/dlls/mf/topology_loader.c index be2a38fd987..51c8254b08f 100644 --- a/dlls/mf/topology_loader.c +++ b/dlls/mf/topology_loader.c @@ -453,9 +453,9 @@ static HRESULT topology_branch_connect_with_type(IMFTopology *topology, struct t } static HRESULT topology_branch_connect(IMFTopology *topology, enum connect_method method_mask, - struct topology_branch *branch, BOOL enumerate_source_types); + struct topology_branch *branch); static HRESULT topology_branch_connect_indirect(IMFTopology *topology, BOOL decoder, - struct topology_branch *branch, IMFMediaType *up_type, IMFMediaType *down_type) + struct topology_branch *branch, IMFMediaType *upstream) { enum connect_method method_mask = CONNECT_DIRECT; MFT_REGISTER_TYPE_INFO input_info; @@ -466,12 +466,12 @@ static HRESULT topology_branch_connect_indirect(IMFTopology *topology, BOOL deco GUID category, guid; HRESULT hr; - TRACE("topology %p, decoder %u, branch %s, up_type %s, down_type %s.\n", topology, decoder, - debugstr_topology_branch(branch), debugstr_media_type(up_type), debugstr_media_type(down_type)); + TRACE("topology %p, decoder %u, branch %s, upstream %s.\n", topology, decoder, + debugstr_topology_branch(branch), debugstr_media_type(upstream)); - if (FAILED(hr = IMFMediaType_GetMajorType(up_type, &input_info.guidMajorType))) + if (FAILED(hr = IMFMediaType_GetMajorType(upstream, &input_info.guidMajorType))) return hr; - if (FAILED(hr = IMFMediaType_GetGUID(up_type, &MF_MT_SUBTYPE, &input_info.guidSubtype))) + if (FAILED(hr = IMFMediaType_GetGUID(upstream, &MF_MT_SUBTYPE, &input_info.guidSubtype))) return hr; if (IsEqualGUID(&input_info.guidMajorType, &MFMediaType_Audio)) @@ -509,10 +509,10 @@ static HRESULT topology_branch_connect_indirect(IMFTopology *topology, BOOL deco if (SUCCEEDED(hr = topology_branch_create_indirect(branch, node, &up_branch, &down_branch))) { - if (SUCCEEDED(hr = topology_branch_connect_with_type(topology, up_branch, up_type))) + if (SUCCEEDED(hr = topology_branch_connect_with_type(topology, up_branch, upstream))) { - if (FAILED(hr = topology_branch_find_best_type(down_branch, up_type, &media_type))) - hr = topology_branch_connect(topology, method_mask, down_branch, !down_type); + if (FAILED(hr = topology_branch_find_best_type(down_branch, upstream, &media_type))) + hr = topology_branch_connect(topology, method_mask, down_branch); else { hr = topology_branch_connect_with_type(topology, down_branch, media_type); @@ -643,34 +643,44 @@ static HRESULT topology_branch_connect_down(IMFTopology *topology, enum connect_ struct topology_branch *branch, IMFMediaType *up_type) { HRESULT hr = MF_E_INVALIDMEDIATYPE; - IMFMediaType *down_type = NULL; - TRACE("topology %p, method %#x, branch %s, up_type %s.\n", topology, method, - debugstr_topology_branch(branch), debugstr_media_type(up_type)); - - get_first_supported_media_type(branch->down.handler, &down_type); + TRACE("topology %p, branch %s, up_type %s.\n", topology, debugstr_topology_branch(branch), debugstr_media_type(up_type)); if (FAILED(hr) && (method & CONNECT_DIRECT)) hr = topology_branch_connect_direct(topology, branch, up_type); if (FAILED(hr) && (method & CONNECT_CONVERTER)) - hr = topology_branch_connect_indirect(topology, FALSE, branch, up_type, down_type); + hr = topology_branch_connect_indirect(topology, FALSE, branch, up_type); if (FAILED(hr) && (method & CONNECT_DECODER)) - hr = topology_branch_connect_indirect(topology, TRUE, branch, up_type, down_type); + hr = topology_branch_connect_indirect(topology, TRUE, branch, up_type); - if (down_type) - IMFMediaType_Release(down_type); TRACE("returning %#lx\n", hr); return hr; } static HRESULT topology_branch_foreach_up_types(IMFTopology *topology, enum connect_method method_mask, - struct topology_branch *branch, BOOL enumerate) + struct topology_branch *branch) { HRESULT hr = MF_E_INVALIDMEDIATYPE; + UINT32 enumerate = TRUE; IMFMediaType *up_type; TRACE("topology %p, method_mask %#x, branch %s.\n", topology, method_mask, debugstr_topology_branch(branch)); + switch (topology_node_get_type(branch->up.node)) + { + case MF_TOPOLOGY_SOURCESTREAM_NODE: + if (FAILED(IMFTopology_GetUINT32(topology, &MF_TOPOLOGY_ENUMERATE_SOURCE_TYPES, &enumerate))) + enumerate = FALSE; + break; + default: + if (SUCCEEDED(IMFMediaTypeHandler_GetCurrentMediaType(branch->up.handler, &up_type))) + { + IMFMediaType_Release(up_type); + enumerate = FALSE; + } + break; + } + if (enumerate) { for (UINT i = 0; SUCCEEDED(hr = IMFMediaTypeHandler_GetMediaTypeByIndex(branch->up.handler, i, &up_type)); i++) @@ -695,8 +705,7 @@ static HRESULT topology_branch_foreach_up_types(IMFTopology *topology, enum conn return hr; } -static HRESULT topology_branch_connect(IMFTopology *topology, enum connect_method method_mask, - struct topology_branch *branch, BOOL enumerate_source_types) +static HRESULT topology_branch_connect(IMFTopology *topology, enum connect_method method_mask, struct topology_branch *branch) { HRESULT hr = MF_E_INVALIDMEDIATYPE; UINT32 up_method, down_method; @@ -712,23 +721,22 @@ static HRESULT topology_branch_connect(IMFTopology *topology, enum connect_metho up_method = MF_CONNECT_DIRECT; if (up_method & MF_CONNECT_RESOLVE_INDEPENDENT_OUTPUTTYPES) - hr = topology_branch_foreach_up_types(topology, down_method, branch, enumerate_source_types); + hr = topology_branch_foreach_up_types(topology, down_method, branch); else { if (FAILED(hr) && (down_method & CONNECT_DIRECT)) - hr = topology_branch_foreach_up_types(topology, CONNECT_DIRECT, branch, enumerate_source_types); + hr = topology_branch_foreach_up_types(topology, CONNECT_DIRECT, branch); if (FAILED(hr) && (down_method & CONNECT_CONVERTER)) - hr = topology_branch_foreach_up_types(topology, CONNECT_CONVERTER, branch, enumerate_source_types); + hr = topology_branch_foreach_up_types(topology, CONNECT_CONVERTER, branch); if (FAILED(hr) && (down_method & CONNECT_DECODER)) - hr = topology_branch_foreach_up_types(topology, CONNECT_DECODER, branch, enumerate_source_types); + hr = topology_branch_foreach_up_types(topology, CONNECT_DECODER, branch); } TRACE("returning %#lx\n", hr); return hr; } -static HRESULT topology_loader_resolve_branches(struct topoloader_context *context, struct list *branches, - BOOL enumerate_source_types) +static HRESULT topology_loader_resolve_branches(struct topoloader_context *context, struct list *branches) { enum connect_method method_mask = connect_method_from_mf(MF_CONNECT_ALLOW_DECODER); struct topology_branch *branch, *next; @@ -741,11 +749,7 @@ static HRESULT topology_loader_resolve_branches(struct topoloader_context *conte 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, method_mask, branch, enumerate_source_types); - if (hr == MF_E_INVALIDMEDIATYPE && !enumerate_source_types && topology_node_get_type(branch->up.node) == MF_TOPOLOGY_TRANSFORM_NODE) - hr = topology_branch_connect(context->output_topology, method_mask, branch, TRUE); - } + hr = topology_branch_connect(context->output_topology, method_mask, branch); topology_branch_destroy(branch); if (FAILED(hr)) @@ -984,7 +988,6 @@ static HRESULT WINAPI topology_loader_Load(IMFTopoLoader *iface, IMFTopology *in struct list branches = LIST_INIT(branches); struct topoloader_context context = { 0 }; struct topology_branch *branch, *next; - UINT32 enumerate_source_types; IMFTopology *output_topology; IMFTopologyNode *node; unsigned short i = 0; @@ -1050,12 +1053,8 @@ static HRESULT WINAPI topology_loader_Load(IMFTopoLoader *iface, IMFTopology *in if (SUCCEEDED(hr) && list_empty(&branches)) hr = MF_E_TOPO_UNSUPPORTED; - if (FAILED(IMFTopology_GetUINT32(input_topology, &MF_TOPOLOGY_ENUMERATE_SOURCE_TYPES, - &enumerate_source_types))) - enumerate_source_types = 0; - while (SUCCEEDED(hr) && !list_empty(&branches)) - hr = topology_loader_resolve_branches(&context, &branches, enumerate_source_types); + hr = topology_loader_resolve_branches(&context, &branches); LIST_FOR_EACH_ENTRY_SAFE(branch, next, &branches, struct topology_branch, entry) { -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/10596
From: Rémi Bernon <rbernon@codeweavers.com> Based on patches from Conor McCarthy. --- dlls/mf/topology_loader.c | 35 +++++++++++++++++++++-------------- 1 file changed, 21 insertions(+), 14 deletions(-) diff --git a/dlls/mf/topology_loader.c b/dlls/mf/topology_loader.c index 51c8254b08f..85d6104a688 100644 --- a/dlls/mf/topology_loader.c +++ b/dlls/mf/topology_loader.c @@ -453,7 +453,7 @@ static HRESULT topology_branch_connect_with_type(IMFTopology *topology, struct t } static HRESULT topology_branch_connect(IMFTopology *topology, enum connect_method method_mask, - struct topology_branch *branch); + struct topology_branch *branch, IMFMediaType *upstream); static HRESULT topology_branch_connect_indirect(IMFTopology *topology, BOOL decoder, struct topology_branch *branch, IMFMediaType *upstream) { @@ -512,7 +512,7 @@ static HRESULT topology_branch_connect_indirect(IMFTopology *topology, BOOL deco if (SUCCEEDED(hr = topology_branch_connect_with_type(topology, up_branch, upstream))) { if (FAILED(hr = topology_branch_find_best_type(down_branch, upstream, &media_type))) - hr = topology_branch_connect(topology, method_mask, down_branch); + hr = topology_branch_connect(topology, method_mask, down_branch, upstream); else { hr = topology_branch_connect_with_type(topology, down_branch, media_type); @@ -658,13 +658,14 @@ static HRESULT topology_branch_connect_down(IMFTopology *topology, enum connect_ } static HRESULT topology_branch_foreach_up_types(IMFTopology *topology, enum connect_method method_mask, - struct topology_branch *branch) + struct topology_branch *branch, IMFMediaType *upstream) { HRESULT hr = MF_E_INVALIDMEDIATYPE; UINT32 enumerate = TRUE; IMFMediaType *up_type; - TRACE("topology %p, method_mask %#x, branch %s.\n", topology, method_mask, debugstr_topology_branch(branch)); + TRACE("topology %p, method_mask %#x, branch %s, upstream %s.\n", topology, method_mask, debugstr_topology_branch(branch), + debugstr_media_type(upstream)); switch (topology_node_get_type(branch->up.node)) { @@ -683,8 +684,10 @@ static HRESULT topology_branch_foreach_up_types(IMFTopology *topology, enum conn if (enumerate) { - for (UINT i = 0; SUCCEEDED(hr = IMFMediaTypeHandler_GetMediaTypeByIndex(branch->up.handler, i, &up_type)); i++) + for (UINT i = 0; SUCCEEDED(hr = media_type_handler_get_type(branch->up.handler, i, &up_type)); i++) { + if (upstream && FAILED(hr = update_media_type_from_upstream(up_type, upstream))) + WARN("Failed to update type from upstream, hr %#lx\n", hr); hr = topology_branch_connect_down(topology, method_mask, branch, up_type); IMFMediaType_Release(up_type); if (SUCCEEDED(hr)) @@ -693,9 +696,11 @@ static HRESULT topology_branch_foreach_up_types(IMFTopology *topology, enum conn return hr; } - if (SUCCEEDED(hr = IMFMediaTypeHandler_GetCurrentMediaType(branch->up.handler, &up_type)) - || SUCCEEDED(hr = IMFMediaTypeHandler_GetMediaTypeByIndex(branch->up.handler, 0, &up_type))) + if (SUCCEEDED(hr = media_type_handler_get_current(branch->up.handler, &up_type)) + || SUCCEEDED(hr = media_type_handler_get_type(branch->up.handler, 0, &up_type))) { + if (upstream && FAILED(hr = update_media_type_from_upstream(up_type, upstream))) + WARN("Failed to update type from upstream, hr %#lx\n", hr); hr = topology_branch_connect_down(topology, method_mask, branch, up_type); IMFMediaType_Release(up_type); return hr; @@ -705,12 +710,14 @@ static HRESULT topology_branch_foreach_up_types(IMFTopology *topology, enum conn return hr; } -static HRESULT topology_branch_connect(IMFTopology *topology, enum connect_method method_mask, struct topology_branch *branch) +static HRESULT topology_branch_connect(IMFTopology *topology, enum connect_method method_mask, + struct topology_branch *branch, IMFMediaType *upstream) { HRESULT hr = MF_E_INVALIDMEDIATYPE; UINT32 up_method, down_method; - TRACE("topology %p, method_mask %#x, branch %s.\n", topology, method_mask, debugstr_topology_branch(branch)); + TRACE("topology %p, method_mask %#x, branch %s, upstream %s.\n", topology, method_mask, debugstr_topology_branch(branch), + debugstr_media_type(upstream)); if (FAILED(IMFTopologyNode_GetUINT32(branch->down.node, &MF_TOPONODE_CONNECT_METHOD, &down_method))) down_method = MF_CONNECT_ALLOW_DECODER; @@ -721,15 +728,15 @@ static HRESULT topology_branch_connect(IMFTopology *topology, enum connect_metho up_method = MF_CONNECT_DIRECT; if (up_method & MF_CONNECT_RESOLVE_INDEPENDENT_OUTPUTTYPES) - hr = topology_branch_foreach_up_types(topology, down_method, branch); + hr = topology_branch_foreach_up_types(topology, down_method, branch, upstream); else { if (FAILED(hr) && (down_method & CONNECT_DIRECT)) - hr = topology_branch_foreach_up_types(topology, CONNECT_DIRECT, branch); + hr = topology_branch_foreach_up_types(topology, CONNECT_DIRECT, branch, upstream); if (FAILED(hr) && (down_method & CONNECT_CONVERTER)) - hr = topology_branch_foreach_up_types(topology, CONNECT_CONVERTER, branch); + hr = topology_branch_foreach_up_types(topology, CONNECT_CONVERTER, branch, upstream); if (FAILED(hr) && (down_method & CONNECT_DECODER)) - hr = topology_branch_foreach_up_types(topology, CONNECT_DECODER, branch); + hr = topology_branch_foreach_up_types(topology, CONNECT_DECODER, branch, upstream); } TRACE("returning %#lx\n", hr); @@ -749,7 +756,7 @@ static HRESULT topology_loader_resolve_branches(struct topoloader_context *conte 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, method_mask, branch); + hr = topology_branch_connect(context->output_topology, method_mask, branch, NULL); topology_branch_destroy(branch); if (FAILED(hr)) -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/10596
From: Conor McCarthy <cmccarthy@codeweavers.com> Unless MF_TOPOLOGY_ENABLE_XVP_FOR_PLAYBACK is set. --- dlls/mf/tests/topology.c | 2 -- dlls/mf/topology_loader.c | 11 +++++++++-- 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/dlls/mf/tests/topology.c b/dlls/mf/tests/topology.c index eb029e3449e..6d433b3e1c2 100644 --- a/dlls/mf/tests/topology.c +++ b/dlls/mf/tests/topology.c @@ -3292,13 +3292,11 @@ todo_wine { hr = IMFTopologyNode_GetGUID(mft_node, &MF_TOPONODE_TRANSFORM_OBJECTID, &class_id); if (test->flags & LOADER_SET_XVP_FOR_PLAYBACK) { - todo_wine ok(hr == MF_E_ATTRIBUTENOTFOUND, "Got attribute hr %#lx.\n", hr); } else { 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)); } diff --git a/dlls/mf/topology_loader.c b/dlls/mf/topology_loader.c index 85d6104a688..9cf4ee0b28c 100644 --- a/dlls/mf/topology_loader.c +++ b/dlls/mf/topology_loader.c @@ -464,6 +464,7 @@ static HRESULT topology_branch_connect_indirect(IMFTopology *topology, BOOL deco IMFTopologyNode *node; unsigned int i, count; GUID category, guid; + UINT32 enable_xvp; HRESULT hr; TRACE("topology %p, decoder %u, branch %s, upstream %s.\n", topology, decoder, @@ -474,10 +475,15 @@ static HRESULT topology_branch_connect_indirect(IMFTopology *topology, BOOL deco if (FAILED(hr = IMFMediaType_GetGUID(upstream, &MF_MT_SUBTYPE, &input_info.guidSubtype))) return hr; + if (FAILED(IMFTopology_GetUINT32(topology, &MF_TOPOLOGY_ENABLE_XVP_FOR_PLAYBACK, &enable_xvp))) + enable_xvp = 0; + if (IsEqualGUID(&input_info.guidMajorType, &MFMediaType_Audio)) category = decoder ? MFT_CATEGORY_AUDIO_DECODER : MFT_CATEGORY_AUDIO_EFFECT; else if (IsEqualGUID(&input_info.guidMajorType, &MFMediaType_Video)) - category = decoder ? MFT_CATEGORY_VIDEO_DECODER : MFT_CATEGORY_VIDEO_PROCESSOR; + category = decoder ? MFT_CATEGORY_VIDEO_DECODER + : enable_xvp ? MFT_CATEGORY_VIDEO_PROCESSOR + : MFT_CATEGORY_VIDEO_EFFECT; else return MF_E_INVALIDMEDIATYPE; @@ -503,7 +509,8 @@ static HRESULT topology_branch_connect_indirect(IMFTopology *topology, BOOL deco continue; IMFTopologyNode_SetObject(node, (IUnknown *)transform); IMFTopologyNode_DeleteItem(node, &MF_TOPONODE_TRANSFORM_OBJECTID); - if (SUCCEEDED(IMFActivate_GetGUID(activates[i], &MFT_TRANSFORM_CLSID_Attribute, &guid))) + if (SUCCEEDED(IMFActivate_GetGUID(activates[i], &MFT_TRANSFORM_CLSID_Attribute, &guid)) + && !IsEqualGUID(&guid, &CLSID_VideoProcessorMFT)) IMFTopologyNode_SetGUID(node, &MF_TOPONODE_TRANSFORM_OBJECTID, &guid); IMFTransform_Release(transform); -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/10596
This merge request was approved by Rémi Bernon. -- https://gitlab.winehq.org/wine/wine/-/merge_requests/10596
participants (3)
-
Conor McCarthy -
Rémi Bernon -
Rémi Bernon (@rbernon)