From: Brendan McGrath <bmcgrath@codeweavers.com> --- dlls/mf/sar.c | 38 +++++++++++++++++++++++++++++++++----- dlls/mf/tests/mf.c | 10 +--------- 2 files changed, 34 insertions(+), 14 deletions(-) diff --git a/dlls/mf/sar.c b/dlls/mf/sar.c index 4b269f8ab0d..ccc1ad9dccd 100644 --- a/dlls/mf/sar.c +++ b/dlls/mf/sar.c @@ -115,6 +115,7 @@ struct audio_renderer LONGLONG pts; UINT64 position; UINT64 audio_clock_frequency; + float rate; }; static void release_pending_object(struct queued_object *object) @@ -520,7 +521,7 @@ static void audio_renderer_preroll(struct audio_renderer *renderer) { unsigned int i; - if (renderer->flags & SAR_PREROLLED) + if (renderer->flags & SAR_PREROLLED || renderer->rate == 0.0f) return; for (i = 0; i < 2; ++i) @@ -666,7 +667,7 @@ static HRESULT WINAPI audio_renderer_clock_sink_OnClockStart(IMFClockStateSink * renderer->clock_state = MFCLOCK_STATE_RUNNING; if (renderer->state != STREAM_STATE_RUNNING) { - if (FAILED(hr = IAudioClient_Start(renderer->audio_client))) + if (renderer->rate != 0.0f && FAILED(hr = IAudioClient_Start(renderer->audio_client))) WARN("Failed to start audio client, hr %#lx.\n", hr); renderer->state = STREAM_STATE_RUNNING; } @@ -675,6 +676,8 @@ static HRESULT WINAPI audio_renderer_clock_sink_OnClockStart(IMFClockStateSink * hr = MF_E_NOT_INITIALIZED; IMFMediaEventQueue_QueueEventParamVar(renderer->stream_event_queue, MEStreamSinkStarted, &GUID_NULL, hr, NULL); + if (renderer->rate == 0.0f) + IMFMediaEventQueue_QueueEventParamVar(renderer->stream_event_queue, MEStreamSinkScrubSampleComplete, &GUID_NULL, hr, NULL); if (SUCCEEDED(hr)) audio_renderer_preroll(renderer); LeaveCriticalSection(&renderer->cs); @@ -735,6 +738,8 @@ static HRESULT WINAPI audio_renderer_clock_sink_OnClockPause(IMFClockStateSink * renderer->clock_state = MFCLOCK_STATE_PAUSED; if (FAILED(hr = IAudioClient_Stop(renderer->audio_client))) WARN("Failed to stop audio client, hr %#lx.\n", hr); + else + hr = S_OK; renderer->state = STREAM_STATE_PAUSED; } else @@ -762,7 +767,7 @@ static HRESULT WINAPI audio_renderer_clock_sink_OnClockRestart(IMFClockStateSink { if ((preroll = (renderer->state != STREAM_STATE_RUNNING))) { - if (FAILED(hr = IAudioClient_Start(renderer->audio_client))) + if (renderer->rate != 0.0f && FAILED(hr = IAudioClient_Start(renderer->audio_client))) WARN("Failed to start audio client, hr %#lx.\n", hr); renderer->state = STREAM_STATE_RUNNING; } @@ -771,6 +776,8 @@ static HRESULT WINAPI audio_renderer_clock_sink_OnClockRestart(IMFClockStateSink hr = MF_E_NOT_INITIALIZED; IMFMediaEventQueue_QueueEventParamVar(renderer->stream_event_queue, MEStreamSinkStarted, &GUID_NULL, hr, NULL); + if (renderer->rate == 0.0f) + IMFMediaEventQueue_QueueEventParamVar(renderer->stream_event_queue, MEStreamSinkScrubSampleComplete, &GUID_NULL, hr, NULL); if (preroll) audio_renderer_preroll(renderer); @@ -781,9 +788,29 @@ static HRESULT WINAPI audio_renderer_clock_sink_OnClockRestart(IMFClockStateSink static HRESULT WINAPI audio_renderer_clock_sink_OnClockSetRate(IMFClockStateSink *iface, MFTIME systime, float rate) { - FIXME("%p, %s, %f.\n", iface, debugstr_time(systime), rate); + struct audio_renderer *renderer = impl_from_IMFClockStateSink(iface); + HRESULT hr = S_OK; - return E_NOTIMPL; + TRACE("%p, %s, %f.\n", iface, debugstr_time(systime), rate); + + EnterCriticalSection(&renderer->cs); + + if (rate == 0.0 || rate == 1.0) + { + renderer->rate = rate; + } + else + { + WARN("%f is an unsupported rate.\n", rate); + hr = MF_E_UNSUPPORTED_RATE; + } + + if (hr == S_OK) + IMFMediaEventQueue_QueueEventParamVar(renderer->stream_event_queue, MEStreamSinkRateChanged, &GUID_NULL, hr, NULL); + + LeaveCriticalSection(&renderer->cs); + + return hr; } static const IMFClockStateSinkVtbl audio_renderer_clock_sink_vtbl = @@ -2118,6 +2145,7 @@ static HRESULT sar_create_object(IMFAttributes *attributes, void *user_context, renderer->IMFAudioPolicy_iface.lpVtbl = &audio_renderer_policy_vtbl; renderer->IMFPresentationTimeSource_iface.lpVtbl = &audio_renderer_time_source_vtbl; renderer->render_callback.lpVtbl = &audio_renderer_render_callback_vtbl; + renderer->rate = 1.0f; renderer->refcount = 1; InitializeCriticalSection(&renderer->cs); renderer->buffer_ready_event = CreateEventW(NULL, FALSE, FALSE, NULL); diff --git a/dlls/mf/tests/mf.c b/dlls/mf/tests/mf.c index 540c31e0a1d..867a32a987f 100644 --- a/dlls/mf/tests/mf.c +++ b/dlls/mf/tests/mf.c @@ -6576,11 +6576,9 @@ static void test_sar(void) /* they are only requested after a call to OnClockStart */ hr = gen_wait_media_event_until_blocking((IMFMediaEventGenerator*)stream_sink, callback, MEStreamSinkRequestSample, 1000, &propvar); - todo_wine ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); hr = gen_wait_media_event_until_blocking((IMFMediaEventGenerator*)stream_sink, callback, MEStreamSinkRequestSample, 1000, &propvar); - todo_wine ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); /* but if the original requests aren't satisfied ... */ @@ -7001,6 +6999,7 @@ if (time_source) PropVariantClear(&propvar); hr = gen_wait_media_event_until_blocking((IMFMediaEventGenerator*)stream, callback, MEStreamSinkRequestSample, 1000, &propvar); + todo_wine ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); PropVariantClear(&propvar); @@ -7015,7 +7014,6 @@ if (time_source) /* But no MEStreamSinkPrerolled will be provided until we provide a second sample */ hr = gen_wait_media_event_until_blocking((IMFMediaEventGenerator*)stream, callback, MEStreamSinkPrerolled, 100, &propvar); - todo_wine ok(hr == WAIT_TIMEOUT, "Unexpected hr %#lx.\n", hr); PropVariantClear(&propvar); @@ -7050,12 +7048,10 @@ if (time_source) /* Two more samples are immediately requested */ hr = gen_wait_media_event_until_blocking((IMFMediaEventGenerator*)stream, callback, MEStreamSinkRequestSample, 1000, &propvar); - todo_wine ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); PropVariantClear(&propvar); hr = gen_wait_media_event_until_blocking((IMFMediaEventGenerator*)stream, callback, MEStreamSinkRequestSample, 1000, &propvar); - todo_wine ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); PropVariantClear(&propvar); @@ -7273,12 +7269,10 @@ if (time_source) /* Test scrubbing. Start by setting clock rate to zero. */ hr = IMFClockStateSink_OnClockSetRate(state_sink1, 0, 0.0); - todo_wine ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); /* Wait for the rate changed event */ hr = gen_wait_media_event_until_blocking((IMFMediaEventGenerator*)stream, callback, MEStreamSinkRateChanged, 1000, &propvar); - todo_wine ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); PropVariantClear(&propvar); @@ -7350,11 +7344,9 @@ if (time_source) /* ... set rate back to 1 ... */ hr = IMFClockStateSink_OnClockSetRate(state_sink1, 0, 1.0); - todo_wine ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); hr = gen_wait_media_event_until_blocking((IMFMediaEventGenerator*)stream, callback, MEStreamSinkRateChanged, 1000, &propvar); - todo_wine ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); PropVariantClear(&propvar); -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/10126