From: Brendan McGrath <bmcgrath@codeweavers.com> --- dlls/mf/clock.c | 161 ++++++++++++++------------------------------- dlls/mf/tests/mf.c | 2 - 2 files changed, 48 insertions(+), 115 deletions(-) diff --git a/dlls/mf/clock.c b/dlls/mf/clock.c index 364d5a69c01..b13faaf44c9 100644 --- a/dlls/mf/clock.c +++ b/dlls/mf/clock.c @@ -72,9 +72,8 @@ struct clock_timer { IUnknown IUnknown_iface; LONG refcount; + LONGLONG time; IMFAsyncResult *result; - IMFAsyncCallback *callback; - MFWORKITEM_KEY key; struct list entry; }; @@ -85,7 +84,6 @@ struct presentation_clock IMFTimer IMFTimer_iface; IMFShutdown IMFShutdown_iface; IMFAsyncCallback sink_callback; - IMFAsyncCallback timer_callback; LONG refcount; IMFPresentationTimeSource *time_source; IMFClockStateSink *time_source_sink; @@ -97,6 +95,7 @@ struct presentation_clock LONGLONG frequency; CRITICAL_SECTION cs; BOOL is_shut_down; + DWORD key; }; static struct presentation_clock *impl_from_IMFPresentationClock(IMFPresentationClock *iface) @@ -124,11 +123,6 @@ static struct presentation_clock *impl_from_sink_callback_IMFAsyncCallback(IMFAs return CONTAINING_RECORD(iface, struct presentation_clock, sink_callback); } -static struct presentation_clock *impl_from_timer_callback_IMFAsyncCallback(IMFAsyncCallback *iface) -{ - return CONTAINING_RECORD(iface, struct presentation_clock, timer_callback); -} - static struct clock_timer *impl_clock_timer_from_IUnknown(IUnknown *iface) { return CONTAINING_RECORD(iface, struct clock_timer, IUnknown_iface); @@ -555,6 +549,39 @@ static HRESULT clock_call_state_change(MFTIME system_time, struct clock_state_ch return hr; } +static struct clock_timer *presentation_clock_next_timer(struct presentation_clock *clock, LONGLONG time) +{ + struct clock_timer *timer; + + LIST_FOR_EACH_ENTRY(timer, &clock->timers, struct clock_timer, entry) + { + if (timer->time <= time + 50000) + return timer; + } + + return NULL; +} + +static void CALLBACK presentation_clock_timer_callback(IUnknown *context) +{ + struct presentation_clock *clock = impl_from_IMFPresentationClock((IMFPresentationClock*)context); + struct clock_timer *timer; + LONGLONG time, systime; + + EnterCriticalSection(&clock->cs); + if (clock->time_source && + SUCCEEDED(IMFPresentationTimeSource_GetCorrelatedTime(clock->time_source, 0, &time, &systime))) + { + while ( (timer = presentation_clock_next_timer(clock, time)) ) + { + list_remove(&timer->entry); + MFInvokeCallback(timer->result); + IUnknown_Release(&timer->IUnknown_iface); + } + } + LeaveCriticalSection(&clock->cs); +} + static HRESULT clock_change_state(struct presentation_clock *clock, enum clock_command command, struct clock_state_change_param param) { @@ -574,7 +601,6 @@ static HRESULT clock_change_state(struct presentation_clock *clock, enum clock_c enum clock_notification notification; struct clock_sink *sink; MFCLOCK_STATE old_state; - IMFAsyncResult *result; MFTIME system_time; HRESULT hr; @@ -609,31 +635,17 @@ static HRESULT clock_change_state(struct presentation_clock *clock, enum clock_c transitioning from running state. */ if ((clock->state == MFCLOCK_STATE_RUNNING) ^ (old_state == MFCLOCK_STATE_RUNNING)) { - struct clock_timer *timer, *timer2; - if (clock->state == MFCLOCK_STATE_RUNNING) { - LIST_FOR_EACH_ENTRY_SAFE(timer, timer2, &clock->timers, struct clock_timer, entry) - { - list_remove(&timer->entry); - hr = MFCreateAsyncResult(&timer->IUnknown_iface, &clock->timer_callback, NULL, &result); - IUnknown_Release(&timer->IUnknown_iface); - if (SUCCEEDED(hr)) - { - MFPutWorkItemEx(MFASYNC_CALLBACK_QUEUE_TIMER, result); - IMFAsyncResult_Release(result); - } - } + if (FAILED(hr = MFAddPeriodicCallback(presentation_clock_timer_callback, (IUnknown*)&clock->IMFPresentationClock_iface, &clock->key))) + ERR("Failed to start periodic callback %#lx\n", hr); } else { - LIST_FOR_EACH_ENTRY(timer, &clock->timers, struct clock_timer, entry) + if (clock->key) { - if (timer->key) - { - MFCancelWorkItem(timer->key); - timer->key = 0; - } + MFRemovePeriodicCallback(clock->key); + clock->key = 0; } } } @@ -799,39 +811,24 @@ static ULONG WINAPI present_clock_timer_Release(IMFTimer *iface) } static HRESULT present_clock_schedule_timer(struct presentation_clock *clock, DWORD flags, LONGLONG time, - struct clock_timer *timer) + IMFAsyncCallback *callback, IUnknown *state, struct clock_timer *timer) { - IMFAsyncResult *result; MFTIME systime, clocktime; - LONGLONG frequency; HRESULT hr; - if (!(flags & MFTIMER_RELATIVE)) + timer->time = time; + + if (flags & MFTIMER_RELATIVE) { if (FAILED(hr = IMFPresentationTimeSource_GetCorrelatedTime(clock->time_source, 0, &clocktime, &systime))) { WARN("Failed to get clock time, hr %#lx.\n", hr); return hr; } - if (time > clocktime) - time -= clocktime; - else - time = 0; + timer->time += clocktime; } - frequency = clock->frequency / 1000; - time /= frequency; - - /* Scheduled item is using clock instance callback, with timer instance as an object. Clock callback will - call user callback and cleanup timer list. */ - - if (FAILED(hr = MFCreateAsyncResult(&timer->IUnknown_iface, &clock->timer_callback, NULL, &result))) - return hr; - - hr = MFScheduleWorkItemEx(result, -time, &timer->key); - IMFAsyncResult_Release(result); - - return hr; + return MFCreateAsyncResult(NULL, callback, state, &timer->result); } static HRESULT WINAPI clock_timer_QueryInterface(IUnknown *iface, REFIID riid, void **obj) @@ -861,7 +858,6 @@ static ULONG WINAPI clock_timer_Release(IUnknown *iface) if (!refcount) { IMFAsyncResult_Release(timer->result); - IMFAsyncCallback_Release(timer->callback); free(timer); } @@ -887,7 +883,7 @@ static HRESULT WINAPI present_clock_timer_SetTimer(IMFTimer *iface, DWORD flags, if (!(clock_timer = calloc(1, sizeof(*clock_timer)))) return E_OUTOFMEMORY; - if (FAILED(hr = MFCreateAsyncResult(NULL, NULL, state, &clock_timer->result))) + if (FAILED(hr = present_clock_schedule_timer(clock, flags, time, callback, state, clock_timer))) { free(clock_timer); return hr; @@ -895,14 +891,10 @@ static HRESULT WINAPI present_clock_timer_SetTimer(IMFTimer *iface, DWORD flags, clock_timer->IUnknown_iface.lpVtbl = &clock_timer_vtbl; clock_timer->refcount = 1; - clock_timer->callback = callback; - IMFAsyncCallback_AddRef(clock_timer->callback); EnterCriticalSection(&clock->cs); - if (clock->state == MFCLOCK_STATE_RUNNING) - hr = present_clock_schedule_timer(clock, flags, time, clock_timer); - else if (clock->state == MFCLOCK_STATE_STOPPED) + if (clock->state == MFCLOCK_STATE_STOPPED) hr = MF_S_CLOCK_STOPPED; if (SUCCEEDED(hr)) @@ -937,11 +929,6 @@ static HRESULT WINAPI present_clock_timer_CancelTimer(IMFTimer *iface, IUnknown if (&timer->IUnknown_iface == cancel_key) { list_remove(&timer->entry); - if (timer->key) - { - MFCancelWorkItem(timer->key); - timer->key = 0; - } IUnknown_Release(&timer->IUnknown_iface); break; } @@ -1080,57 +1067,6 @@ static const IMFAsyncCallbackVtbl presentclocksinkcallbackvtbl = present_clock_sink_callback_Invoke, }; -static ULONG WINAPI present_clock_timer_callback_AddRef(IMFAsyncCallback *iface) -{ - struct presentation_clock *clock = impl_from_timer_callback_IMFAsyncCallback(iface); - return IMFPresentationClock_AddRef(&clock->IMFPresentationClock_iface); -} - -static ULONG WINAPI present_clock_timer_callback_Release(IMFAsyncCallback *iface) -{ - struct presentation_clock *clock = impl_from_timer_callback_IMFAsyncCallback(iface); - return IMFPresentationClock_Release(&clock->IMFPresentationClock_iface); -} - -static HRESULT WINAPI present_clock_timer_callback_Invoke(IMFAsyncCallback *iface, IMFAsyncResult *result) -{ - struct presentation_clock *clock = impl_from_timer_callback_IMFAsyncCallback(iface); - struct clock_timer *timer; - IUnknown *object; - HRESULT hr; - - if (FAILED(hr = IMFAsyncResult_GetObject(result, &object))) - return hr; - - EnterCriticalSection(&clock->cs); - LIST_FOR_EACH_ENTRY(timer, &clock->timers, struct clock_timer, entry) - { - if (&timer->IUnknown_iface == object) - { - list_remove(&timer->entry); - IUnknown_Release(&timer->IUnknown_iface); - break; - } - } - LeaveCriticalSection(&clock->cs); - - timer = impl_clock_timer_from_IUnknown(object); - IMFAsyncCallback_Invoke(timer->callback, timer->result); - - IUnknown_Release(object); - - return S_OK; -} - -static const IMFAsyncCallbackVtbl presentclocktimercallbackvtbl = -{ - present_clock_callback_QueryInterface, - present_clock_timer_callback_AddRef, - present_clock_timer_callback_Release, - present_clock_callback_GetParameters, - present_clock_timer_callback_Invoke, -}; - /*********************************************************************** * MFCreatePresentationClock (mf.@) */ @@ -1148,7 +1084,6 @@ HRESULT WINAPI MFCreatePresentationClock(IMFPresentationClock **clock) object->IMFTimer_iface.lpVtbl = &presentclocktimervtbl; object->IMFShutdown_iface.lpVtbl = &presentclockshutdownvtbl; object->sink_callback.lpVtbl = &presentclocksinkcallbackvtbl; - object->timer_callback.lpVtbl = &presentclocktimercallbackvtbl; object->refcount = 1; list_init(&object->sinks); list_init(&object->timers); diff --git a/dlls/mf/tests/mf.c b/dlls/mf/tests/mf.c index 77386d8ec32..8bc3f83019c 100644 --- a/dlls/mf/tests/mf.c +++ b/dlls/mf/tests/mf.c @@ -4418,7 +4418,6 @@ static void test_presentation_clock(void) timer_callback = impl_from_IMFAsyncCallback(callback); hr = IMFTimer_SetTimer(timer, 0, 1000000, callback, NULL, &timer_cancel_key); ok(hr == S_OK, "got hr %#lx.\n", hr); - todo_wine ok(WaitForSingleObject(timer_callback->event, 4000) == WAIT_TIMEOUT, "WaitForSingleObject should timeout.\n"); /* the timer will only trigger when the time of the time source is within 5ms of the target time */ @@ -4426,7 +4425,6 @@ static void test_presentation_clock(void) ok(WaitForSingleObject(timer_callback->event, 4000) == WAIT_TIMEOUT, "WaitForSingleObject should timeout.\n"); test_time_source->time = 1000000-50000; - todo_wine ok(WaitForSingleObject(timer_callback->event, 4000) == WAIT_OBJECT_0, "WaitForSingleObject failed.\n"); IUnknown_Release(timer_cancel_key); -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/10095