From: Conor McCarthy <cmccarthy@codeweavers.com> --- dlls/mf/tests/mf.c | 1 - dlls/mf/tests/topology.c | 14 ++--- dlls/mf/topology_loader.c | 117 ++++++++++++++++++++++++++++++++++++-- 3 files changed, 117 insertions(+), 15 deletions(-) diff --git a/dlls/mf/tests/mf.c b/dlls/mf/tests/mf.c index 7aca38c7fd2..ee727491d1f 100644 --- a/dlls/mf/tests/mf.c +++ b/dlls/mf/tests/mf.c @@ -2977,7 +2977,6 @@ static void test_media_session_events(void) ok(propvar.punkVal != (IUnknown *)topology, "got punkVal %p\n", propvar.punkVal); PropVariantClear(&propvar); - todo_wine ok(!handler->enum_count, "got %lu GetMediaTypeByIndex\n", handler->enum_count); ok(handler->set_current_count, "got %lu SetCurrentMediaType\n", handler->set_current_count); handler->enum_count = handler->set_current_count = 0; diff --git a/dlls/mf/tests/topology.c b/dlls/mf/tests/topology.c index 63a8192aca3..af827b85ba6 100644 --- a/dlls/mf/tests/topology.c +++ b/dlls/mf/tests/topology.c @@ -2265,7 +2265,6 @@ enum loader_test_flags LOADER_EXPECT_MFT_OUTPUT_ENUMERATED = 0x4000, LOADER_EXPECT_MFT_INPUT_ENUMERATED = 0x8000, LOADER_EXPECT_MFT_INPUT_ENUMERATED_TODO = 0x10000, - LOADER_TODO_MFT_IN_TYPE = 0x20000, LOADER_TODO_MFT_OUT_TYPE = 0x40000, }; @@ -2661,7 +2660,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_IN_TYPE | LOADER_TODO_MFT_OUT_TYPE | LOADER_TODO, + .flags = LOADER_ADD_TEST_MFT | LOADER_TODO_MFT_OUT_TYPE | LOADER_TODO, }, { /* PCM -> PCM, different enumerated bps, add test MFT */ @@ -2676,7 +2675,7 @@ static void test_topology_loader(void) .mft_output_types = {&audio_float_minimal, &audio_pcm_minimal, &audio_float_48000, &audio_pcm_48000_resampler}, .mft_current_output = &audio_pcm_48000, .expected_result = S_OK, - .flags = LOADER_ADD_TEST_MFT | LOADER_TODO_MFT_IN_TYPE | LOADER_TODO_MFT_OUT_TYPE, + .flags = LOADER_ADD_TEST_MFT, }, { /* PCM -> PCM, different enumerated bps, add test MFT, configure MFT, no output types */ @@ -2684,7 +2683,7 @@ static void test_topology_loader(void) .mft_output_types = {&audio_float_minimal, &audio_pcm_minimal, &audio_float_48000, &audio_pcm_48000_resampler}, .mft_current_output = &audio_pcm_48000, .expected_result = S_OK, - .flags = LOADER_ADD_TEST_MFT | LOADER_NO_CURRENT_OUTPUT | LOADER_TODO_MFT_IN_TYPE | LOADER_TODO_MFT_OUT_TYPE, + .flags = LOADER_ADD_TEST_MFT | LOADER_NO_CURRENT_OUTPUT, }, { /* MP3 -> PCM, different enumerated bps, add test MFT, configure MFT */ @@ -2692,7 +2691,7 @@ 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 | LOADER_TODO_MFT_OUT_TYPE, + .flags = LOADER_ADD_TEST_MFT | LOADER_EXPECT_MFT_INPUT_ENUMERATED_TODO, }, { /* MP3 -> PCM, different enumerated bps, add incompatible test MFT, configure MFT */ @@ -2837,14 +2836,14 @@ static void test_topology_loader(void) .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_TODO_MFT_OUT_TYPE | 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_TODO, }, { /* 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_TODO_MFT_OUT_TYPE | LOADER_EXPECT_MFT_INPUT_ENUMERATED_TODO, + .flags = LOADER_ADD_TEST_MFT | LOADER_EXPECT_MFT_INPUT_ENUMERATED_TODO, }, }; @@ -3384,7 +3383,6 @@ todo_wine { 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), "got transform output_enum_complete %u\n", test_transform->output_enum_complete); - todo_wine_if(test->flags & LOADER_TODO_MFT_IN_TYPE) 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) diff --git a/dlls/mf/topology_loader.c b/dlls/mf/topology_loader.c index 9eceb66bb5f..4a4828f22d6 100644 --- a/dlls/mf/topology_loader.c +++ b/dlls/mf/topology_loader.c @@ -127,6 +127,7 @@ struct topology_branch { IMFTopologyNode *node; DWORD stream; + BOOL enumerate; } up, down; struct list entry; @@ -265,6 +266,44 @@ static HRESULT update_media_type_from_upstream(IMFMediaType *media_type, IMFMedi return hr; } +struct type_enumerator +{ + IMFMediaTypeHandler *handler; + BOOL enumerate; + BOOL have_current; + int i; +}; + +static void type_enumerator_init(struct type_enumerator *enumerator, IMFMediaTypeHandler *handler, BOOL enumerate) +{ + enumerator->handler = handler; + enumerator->enumerate = enumerate; + enumerator->have_current = FALSE; + enumerator->i = enumerate - 1; +} + +static HRESULT type_enumerator_get_next_media_type(struct type_enumerator *enumerator, IMFMediaType **type) +{ + int i = enumerator->i++; + + if (i < 0) + { + if (SUCCEEDED(IMFMediaTypeHandler_GetCurrentMediaType(enumerator->handler, type))) + { + enumerator->have_current = TRUE; + return S_OK; + } + i = enumerator->i++; + } + + /* If we are not enumerating and we have a current type, do not check index 0. */ + if ((!i && !enumerator->have_current) || enumerator->enumerate) + return IMFMediaTypeHandler_GetMediaTypeByIndex(enumerator->handler, i, type); + + /* return MF_E_INVALIDMEDIATYPE if not enumerating types */ + return MF_E_INVALIDMEDIATYPE; +} + static HRESULT topology_branch_is_input_type_supported(struct topology_branch *branch, IMFMediaType *down_type) { HRESULT hr; @@ -295,6 +334,64 @@ static HRESULT topology_branch_is_input_type_supported(struct topology_branch *b return hr; } +static HRESULT topology_branch_complete_connection(struct topology_branch *branch, IMFMediaTypeHandler *up_handler, + IMFMediaType *up_type) +{ + HRESULT hr = S_OK; + + /* Current type is set for sources when enumerating, and always for transforms. */ + if (branch->up.enumerate || topology_node_get_type(branch->up.node) == MF_TOPOLOGY_TRANSFORM_NODE) + hr = IMFMediaTypeHandler_SetCurrentMediaType(up_handler, up_type); + + if (SUCCEEDED(hr)) + { + TRACE("Connected branch %s with up type %s.\n", debugstr_topology_branch(branch), debugstr_media_type(up_type)); + hr = IMFTopologyNode_ConnectOutput(branch->up.node, branch->up.stream, branch->down.node, branch->down.stream); + } + + return hr; +} + +static HRESULT topology_branch_connect_up_types(struct topology_branch *branch, IMFMediaType **first_up_type) +{ + IMFMediaTypeHandler *up_handler; + struct type_enumerator enumerator; + IMFMediaType *up_type; + HRESULT hr; + + TRACE("branch %s.\n", debugstr_topology_branch(branch)); + + *first_up_type = NULL; + + if (FAILED(hr = topology_node_get_type_handler(branch->up.node, branch->up.stream, TRUE, &up_handler))) + return hr; + + /* The downstream current media type is not used here. Setting it in advance has no effect on the type used. + * TODO: unless MF_TOPONODE_LOCKED is set? + * Up and down transform media types are always set, even if they already match. IsMediaTypeSupported() does + * that here if the down node is a transform. + * If enumeration is disabled and upstream current type is null, the available type at index 0 is used. */ + + type_enumerator_init(&enumerator, up_handler, branch->up.enumerate); + while (SUCCEEDED(hr = type_enumerator_get_next_media_type(&enumerator, &up_type))) + { + if (!*first_up_type) + IMFMediaType_AddRef(*first_up_type = up_type); + + if (SUCCEEDED(hr = topology_branch_is_input_type_supported(branch, up_type))) + hr = topology_branch_complete_connection(branch, up_handler, up_type); + + IMFMediaType_Release(up_type); + + if (SUCCEEDED(hr)) + break; + } + + IMFMediaTypeHandler_Release(up_handler); + + return hr; +} + static HRESULT topology_branch_connect(IMFTopology *topology, MF_CONNECT_METHOD method_mask, struct topology_branch *branch, BOOL enumerate_source_types); static HRESULT topology_branch_connect_down(IMFTopology *topology, MF_CONNECT_METHOD method_mask, @@ -548,15 +645,23 @@ static HRESULT topology_branch_connect(IMFTopology *topology, MF_CONNECT_METHOD IMFMediaTypeHandler *up_handler; IMFMediaType *up_type; - if (FAILED(hr = topology_node_get_type_handler(branch->up.node, branch->up.stream, TRUE, &up_handler))) - return hr; - if (SUCCEEDED(hr = IMFMediaTypeHandler_GetCurrentMediaType(up_handler, &up_type)) - || SUCCEEDED(hr = IMFMediaTypeHandler_GetMediaTypeByIndex(up_handler, 0, &up_type))) + if (topology_node_get_type(branch->up.node) != MF_TOPOLOGY_SOURCESTREAM_NODE) { + if (FAILED(hr = topology_node_get_type_handler(branch->up.node, branch->up.stream, TRUE, &up_handler))) + return hr; + + if (SUCCEEDED(hr = IMFMediaTypeHandler_GetCurrentMediaType(up_handler, &up_type))) + IMFMediaType_Release(up_type); + branch->up.enumerate = FAILED(hr); + + IMFMediaTypeHandler_Release(up_handler); + } + + if (FAILED(hr = topology_branch_connect_up_types(branch, &up_type)) && up_type) hr = topology_branch_connect_down(topology, method_mask, branch, up_type); + + if (up_type) IMFMediaType_Release(up_type); - } - IMFMediaTypeHandler_Release(up_handler); } TRACE("returning %#lx\n", hr); -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/10009