diff --git a/dlls/mf/session.c b/dlls/mf/session.c index 5034255339c..af58a47ed7a 100644 --- a/dlls/mf/session.c +++ b/dlls/mf/session.c @@ -319,12 +319,19 @@ struct presentation_clock BOOL is_shut_down; }; +enum quality_manager_state +{ + QUALITY_MANAGER_READY = 0, + QUALITY_MANAGER_SHUT_DOWN, +}; + struct quality_manager { IMFQualityManager IMFQualityManager_iface; LONG refcount; IMFPresentationClock *clock; + unsigned int state; CRITICAL_SECTION cs; }; @@ -4794,24 +4801,35 @@ static HRESULT WINAPI standard_quality_manager_NotifyTopology(IMFQualityManager return S_OK; } +static void standard_quality_manager_release_clock(struct quality_manager *manager) +{ + if (manager->clock) + IMFPresentationClock_Release(manager->clock); + manager->clock = NULL; +} + static HRESULT WINAPI standard_quality_manager_NotifyPresentationClock(IMFQualityManager *iface, IMFPresentationClock *clock) { struct quality_manager *manager = impl_from_IMFQualityManager(iface); + HRESULT hr = S_OK; TRACE("%p, %p.\n", iface, clock); - if (!clock) - return E_POINTER; - EnterCriticalSection(&manager->cs); - if (manager->clock) - IMFPresentationClock_Release(manager->clock); - manager->clock = clock; - IMFPresentationClock_AddRef(manager->clock); + if (manager->state == QUALITY_MANAGER_SHUT_DOWN) + hr = MF_E_SHUTDOWN; + else if (!clock) + hr = E_POINTER; + else + { + standard_quality_manager_release_clock(manager); + manager->clock = clock; + IMFPresentationClock_AddRef(manager->clock); + } LeaveCriticalSection(&manager->cs); - return S_OK; + return hr; } static HRESULT WINAPI standard_quality_manager_NotifyProcessInput(IMFQualityManager *iface, IMFTopologyNode *node, @@ -4840,9 +4858,19 @@ static HRESULT WINAPI standard_quality_manager_NotifyQualityEvent(IMFQualityMana static HRESULT WINAPI standard_quality_manager_Shutdown(IMFQualityManager *iface) { - FIXME("%p stub.\n", iface); + struct quality_manager *manager = impl_from_IMFQualityManager(iface); - return E_NOTIMPL; + TRACE("%p.\n", iface); + + EnterCriticalSection(&manager->cs); + if (manager->state != QUALITY_MANAGER_SHUT_DOWN) + { + standard_quality_manager_release_clock(manager); + manager->state = QUALITY_MANAGER_SHUT_DOWN; + } + LeaveCriticalSection(&manager->cs); + + return S_OK; } static IMFQualityManagerVtbl standard_quality_manager_vtbl = diff --git a/dlls/mf/tests/mf.c b/dlls/mf/tests/mf.c index 846d311c877..aad1564c3f0 100644 --- a/dlls/mf/tests/mf.c +++ b/dlls/mf/tests/mf.c @@ -3647,16 +3647,67 @@ failed: static void test_quality_manager(void) { + IMFPresentationClock *clock; IMFQualityManager *manager; HRESULT hr; + hr = MFStartup(MF_VERSION, MFSTARTUP_FULL); + ok(hr == S_OK, "Startup failure, hr %#x.\n", hr); + + hr = MFCreatePresentationClock(&clock); + ok(hr == S_OK, "Failed to create presentation clock, hr %#x.\n", hr); + hr = MFCreateStandardQualityManager(&manager); ok(hr == S_OK, "Failed to create quality manager, hr %#x.\n", hr); + check_interface(manager, &IID_IMFQualityManager, TRUE); +todo_wine + check_interface(manager, &IID_IMFClockStateSink, TRUE); + hr = IMFQualityManager_NotifyPresentationClock(manager, NULL); ok(hr == E_POINTER, "Unexpected hr %#x.\n", hr); + /* Set clock, then shutdown. */ + EXPECT_REF(clock, 1); + EXPECT_REF(manager, 1); + hr = IMFQualityManager_NotifyPresentationClock(manager, clock); + ok(hr == S_OK, "Unexpected hr %#x.\n", hr); + EXPECT_REF(clock, 2); +todo_wine + EXPECT_REF(manager, 2); + + hr = IMFQualityManager_Shutdown(manager); + ok(hr == S_OK, "Unexpected hr %#x.\n", hr); + EXPECT_REF(clock, 1); + + hr = IMFQualityManager_NotifyPresentationClock(manager, clock); + ok(hr == MF_E_SHUTDOWN, "Unexpected hr %#x.\n", hr); + + hr = IMFQualityManager_NotifyPresentationClock(manager, NULL); + ok(hr == MF_E_SHUTDOWN, "Unexpected hr %#x.\n", hr); + + hr = IMFQualityManager_Shutdown(manager); + ok(hr == S_OK, "Unexpected hr %#x.\n", hr); + IMFQualityManager_Release(manager); + + /* Set clock, then release without shutting down. */ + hr = MFCreateStandardQualityManager(&manager); + ok(hr == S_OK, "Failed to create quality manager, hr %#x.\n", hr); + + EXPECT_REF(clock, 1); + hr = IMFQualityManager_NotifyPresentationClock(manager, clock); + ok(hr == S_OK, "Unexpected hr %#x.\n", hr); + EXPECT_REF(clock, 2); + + IMFQualityManager_Release(manager); +todo_wine + EXPECT_REF(clock, 2); + + IMFPresentationClock_Release(clock); + + hr = MFShutdown(); + ok(hr == S_OK, "Shutdown failure, hr %#x.\n", hr); } static void test_sar(void)