Signed-off-by: Nikolay Sivov nsivov@codeweavers.com --- dlls/mf/sar.c | 30 +++++++++++++++++------------- dlls/mf/tests/mf.c | 2 ++ 2 files changed, 19 insertions(+), 13 deletions(-)
diff --git a/dlls/mf/sar.c b/dlls/mf/sar.c index 80cfd94952..ed59075fc2 100644 --- a/dlls/mf/sar.c +++ b/dlls/mf/sar.c @@ -282,6 +282,21 @@ static HRESULT WINAPI audio_renderer_sink_GetStreamSinkById(IMFMediaSink *iface, return hr; }
+static void audio_renderer_set_presentation_clock(struct audio_renderer *renderer, IMFPresentationClock *clock) +{ + if (renderer->clock) + { + IMFPresentationClock_RemoveClockStateSink(renderer->clock, &renderer->IMFClockStateSink_iface); + IMFPresentationClock_Release(renderer->clock); + } + renderer->clock = clock; + if (renderer->clock) + { + IMFPresentationClock_AddRef(renderer->clock); + IMFPresentationClock_AddClockStateSink(renderer->clock, &renderer->IMFClockStateSink_iface); + } +} + static HRESULT WINAPI audio_renderer_sink_SetPresentationClock(IMFMediaSink *iface, IMFPresentationClock *clock) { struct audio_renderer *renderer = impl_from_IMFMediaSink(iface); @@ -294,19 +309,7 @@ static HRESULT WINAPI audio_renderer_sink_SetPresentationClock(IMFMediaSink *ifa if (renderer->is_shut_down) hr = MF_E_SHUTDOWN; else - { - if (renderer->clock) - { - IMFPresentationClock_RemoveClockStateSink(renderer->clock, &renderer->IMFClockStateSink_iface); - IMFPresentationClock_Release(renderer->clock); - } - renderer->clock = clock; - if (renderer->clock) - { - IMFPresentationClock_AddRef(renderer->clock); - IMFPresentationClock_AddClockStateSink(renderer->clock, &renderer->IMFClockStateSink_iface); - } - } + audio_renderer_set_presentation_clock(renderer, clock);
LeaveCriticalSection(&renderer->cs);
@@ -353,6 +356,7 @@ static HRESULT WINAPI audio_renderer_sink_Shutdown(IMFMediaSink *iface) renderer->is_shut_down = TRUE; IMFMediaEventQueue_Shutdown(renderer->event_queue); IMFMediaEventQueue_Shutdown(renderer->stream_event_queue); + audio_renderer_set_presentation_clock(renderer, NULL); LeaveCriticalSection(&renderer->cs);
return S_OK; diff --git a/dlls/mf/tests/mf.c b/dlls/mf/tests/mf.c index 511c6a8eb9..b7229b4f71 100644 --- a/dlls/mf/tests/mf.c +++ b/dlls/mf/tests/mf.c @@ -2970,8 +2970,10 @@ todo_wine IUnknown_Release(unk);
/* Shutdown */ + EXPECT_REF(present_clock, 2); hr = IMFMediaSink_Shutdown(sink); ok(hr == S_OK, "Failed to shut down, hr %#x.\n", hr); + EXPECT_REF(present_clock, 1);
hr = IMFMediaSink_Shutdown(sink); ok(hr == MF_E_SHUTDOWN, "Unexpected hr %#x.\n", hr);
Signed-off-by: Nikolay Sivov nsivov@codeweavers.com --- dlls/mf/sar.c | 54 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 54 insertions(+)
diff --git a/dlls/mf/sar.c b/dlls/mf/sar.c index ed59075fc2..752f7ceb1e 100644 --- a/dlls/mf/sar.c +++ b/dlls/mf/sar.c @@ -50,6 +50,8 @@ struct audio_renderer IMFMediaType *media_type; IMFMediaType *current_media_type; IMMDevice *device; + IAudioClient *audio_client; + HANDLE buffer_ready_event; BOOL is_shut_down; CRITICAL_SECTION cs; }; @@ -172,6 +174,9 @@ static ULONG WINAPI audio_renderer_sink_Release(IMFMediaSink *iface) IMFMediaType_Release(renderer->media_type); if (renderer->current_media_type) IMFMediaType_Release(renderer->current_media_type); + CloseHandle(renderer->buffer_ready_event); + if (renderer->audio_client) + IAudioClient_Release(renderer->audio_client); DeleteCriticalSection(&renderer->cs); heap_free(renderer); } @@ -1110,6 +1115,52 @@ static HRESULT WINAPI audio_renderer_stream_type_handler_GetMediaTypeByIndex(IMF return S_OK; }
+static HRESULT audio_renderer_create_audio_client(struct audio_renderer *renderer) +{ + WAVEFORMATEX *wfx; + HRESULT hr; + + if (renderer->audio_client) + { + IAudioClient_Release(renderer->audio_client); + renderer->audio_client = NULL; + } + + hr = IMMDevice_Activate(renderer->device, &IID_IAudioClient, CLSCTX_INPROC_SERVER, NULL, + (void **)&renderer->audio_client); + if (FAILED(hr)) + { + WARN("Failed to create audio client, hr %#x.\n", hr); + return hr; + } + + /* FIXME: use SAR configuration for flags and session id. */ + + /* FIXME: for now always use default format. */ + if (FAILED(hr = IAudioClient_GetMixFormat(renderer->audio_client, &wfx))) + { + WARN("Failed to get audio format, hr %#x.\n", hr); + return hr; + } + + hr = IAudioClient_Initialize(renderer->audio_client, AUDCLNT_SHAREMODE_SHARED, AUDCLNT_STREAMFLAGS_EVENTCALLBACK, + 1000000, 0, wfx, NULL); + CoTaskMemFree(wfx); + if (FAILED(hr)) + { + WARN("Failed to initialize audio client, hr %#x.\n", hr); + return hr; + } + + if (FAILED(hr = IAudioClient_SetEventHandle(renderer->audio_client, renderer->buffer_ready_event))) + { + WARN("Failed to set event handle, hr %#x.\n", hr); + return hr; + } + + return hr; +} + static HRESULT WINAPI audio_renderer_stream_type_handler_SetCurrentMediaType(IMFMediaTypeHandler *iface, IMFMediaType *media_type) { @@ -1130,6 +1181,8 @@ static HRESULT WINAPI audio_renderer_stream_type_handler_SetCurrentMediaType(IMF IMFMediaType_Release(renderer->current_media_type); renderer->current_media_type = media_type; IMFMediaType_AddRef(renderer->current_media_type); + + hr = audio_renderer_create_audio_client(renderer); } else hr = MF_E_INVALIDMEDIATYPE; @@ -1249,6 +1302,7 @@ static HRESULT sar_create_object(IMFAttributes *attributes, void *user_context, renderer->IMFAudioPolicy_iface.lpVtbl = &audio_renderer_policy_vtbl; renderer->refcount = 1; InitializeCriticalSection(&renderer->cs); + renderer->buffer_ready_event = CreateEventW(NULL, FALSE, FALSE, NULL);
if (FAILED(hr = MFCreateEventQueue(&renderer->event_queue))) goto failed;
Hi,
While running your changed tests, I think I found new failures. Being a bot and all I'm not very good at pattern recognition, so I might be wrong, but could you please double-check?
Full results can be found at: https://testbot.winehq.org/JobDetails.pl?Key=70189
Your paranoid android.
=== debiant (build log) ===
error: patch failed: dlls/mf/sar.c:353 error: patch failed: dlls/mf/sar.c:50 Task: Patch failed to apply
=== debiant (build log) ===
error: patch failed: dlls/mf/sar.c:353 error: patch failed: dlls/mf/sar.c:50 Task: Patch failed to apply
Signed-off-by: Nikolay Sivov nsivov@codeweavers.com --- dlls/mf/sar.c | 107 +++++++++++++++++++++++++++++++++++++++++---- dlls/mf/tests/mf.c | 38 +++++++++++++++- 2 files changed, 135 insertions(+), 10 deletions(-)
diff --git a/dlls/mf/sar.c b/dlls/mf/sar.c index 752f7ceb1e..6c740abeba 100644 --- a/dlls/mf/sar.c +++ b/dlls/mf/sar.c @@ -31,6 +31,13 @@
WINE_DEFAULT_DEBUG_CHANNEL(mfplat);
+enum stream_state +{ + STREAM_STATE_STOPPED = 0, + STREAM_STATE_RUNNING, + STREAM_STATE_PAUSED, +}; + struct audio_renderer { IMFMediaSink IMFMediaSink_iface; @@ -52,6 +59,7 @@ struct audio_renderer IMMDevice *device; IAudioClient *audio_client; HANDLE buffer_ready_event; + enum stream_state state; BOOL is_shut_down; CRITICAL_SECTION cs; }; @@ -504,30 +512,113 @@ static ULONG WINAPI audio_renderer_clock_sink_Release(IMFClockStateSink *iface)
static HRESULT WINAPI audio_renderer_clock_sink_OnClockStart(IMFClockStateSink *iface, MFTIME systime, LONGLONG offset) { - FIXME("%p, %s, %s.\n", iface, debugstr_time(systime), debugstr_time(offset)); + struct audio_renderer *renderer = impl_from_IMFClockStateSink(iface); + HRESULT hr = S_OK;
- return E_NOTIMPL; + TRACE("%p, %s, %s.\n", iface, debugstr_time(systime), debugstr_time(offset)); + + EnterCriticalSection(&renderer->cs); + if (renderer->audio_client) + { + if (renderer->state == STREAM_STATE_STOPPED) + { + if (FAILED(hr = IAudioClient_Start(renderer->audio_client))) + WARN("Failed to start audio client, hr %#x.\n", hr); + renderer->state = STREAM_STATE_RUNNING; + } + } + else + hr = MF_E_NOT_INITIALIZED; + + IMFMediaEventQueue_QueueEventParamVar(renderer->stream_event_queue, MEStreamSinkStarted, &GUID_NULL, hr, NULL); + LeaveCriticalSection(&renderer->cs); + + return hr; }
static HRESULT WINAPI audio_renderer_clock_sink_OnClockStop(IMFClockStateSink *iface, MFTIME systime) { - FIXME("%p, %s.\n", iface, debugstr_time(systime)); + struct audio_renderer *renderer = impl_from_IMFClockStateSink(iface); + HRESULT hr = S_OK;
- return E_NOTIMPL; + TRACE("%p, %s.\n", iface, debugstr_time(systime)); + + EnterCriticalSection(&renderer->cs); + if (renderer->audio_client) + { + if (renderer->state != STREAM_STATE_STOPPED) + { + if (SUCCEEDED(hr = IAudioClient_Stop(renderer->audio_client))) + { + if (FAILED(hr = IAudioClient_Reset(renderer->audio_client))) + WARN("Failed to reset audio client, hr %#x.\n", hr); + } + else + WARN("Failed to stop audio client, hr %#x.\n", hr); + renderer->state = STREAM_STATE_STOPPED; + } + } + else + hr = MF_E_NOT_INITIALIZED; + + IMFMediaEventQueue_QueueEventParamVar(renderer->stream_event_queue, MEStreamSinkStopped, &GUID_NULL, hr, NULL); + LeaveCriticalSection(&renderer->cs); + + return hr; }
static HRESULT WINAPI audio_renderer_clock_sink_OnClockPause(IMFClockStateSink *iface, MFTIME systime) { - FIXME("%p, %s.\n", iface, debugstr_time(systime)); + struct audio_renderer *renderer = impl_from_IMFClockStateSink(iface); + HRESULT hr;
- return E_NOTIMPL; + TRACE("%p, %s.\n", iface, debugstr_time(systime)); + + EnterCriticalSection(&renderer->cs); + if (renderer->state == STREAM_STATE_RUNNING) + { + if (renderer->audio_client) + { + if (FAILED(hr = IAudioClient_Stop(renderer->audio_client))) + WARN("Failed to stop audio client, hr %#x.\n", hr); + renderer->state = STREAM_STATE_PAUSED; + } + else + hr = MF_E_NOT_INITIALIZED; + + IMFMediaEventQueue_QueueEventParamVar(renderer->stream_event_queue, MEStreamSinkPaused, &GUID_NULL, hr, NULL); + } + else + hr = MF_E_INVALID_STATE_TRANSITION; + LeaveCriticalSection(&renderer->cs); + + return hr; }
static HRESULT WINAPI audio_renderer_clock_sink_OnClockRestart(IMFClockStateSink *iface, MFTIME systime) { - FIXME("%p, %s.\n", iface, debugstr_time(systime)); + struct audio_renderer *renderer = impl_from_IMFClockStateSink(iface); + HRESULT hr = S_OK;
- return E_NOTIMPL; + TRACE("%p, %s.\n", iface, debugstr_time(systime)); + + EnterCriticalSection(&renderer->cs); + if (renderer->audio_client) + { + if (renderer->state == STREAM_STATE_PAUSED) + { + if (FAILED(hr = IAudioClient_Start(renderer->audio_client))) + WARN("Failed to start audio client, hr %#x.\n", hr); + renderer->state = STREAM_STATE_RUNNING; + } + } + else + hr = MF_E_NOT_INITIALIZED; + + IMFMediaEventQueue_QueueEventParamVar(renderer->stream_event_queue, MEStreamSinkStarted, &GUID_NULL, hr, NULL); + LeaveCriticalSection(&renderer->cs); + + return hr; }
static HRESULT WINAPI audio_renderer_clock_sink_OnClockSetRate(IMFClockStateSink *iface, MFTIME systime, float rate) diff --git a/dlls/mf/tests/mf.c b/dlls/mf/tests/mf.c index b7229b4f71..675bc0a443 100644 --- a/dlls/mf/tests/mf.c +++ b/dlls/mf/tests/mf.c @@ -2811,9 +2811,13 @@ if (SUCCEEDED(hr)) IUnknown_Release(unk);
/* Clock */ - hr = IMFMediaSink_QueryInterface(sink, &IID_IMFClockStateSink, (void **)&unk); + hr = IMFMediaSink_QueryInterface(sink, &IID_IMFClockStateSink, (void **)&state_sink); ok(hr == S_OK, "Failed to get interface, hr %#x.\n", hr); - IUnknown_Release(unk); + + hr = IMFClockStateSink_OnClockStart(state_sink, 0, 0); + ok(hr == MF_E_NOT_INITIALIZED, "Unexpected hr %#x.\n", hr); + + IMFClockStateSink_Release(state_sink);
hr = IMFMediaSink_SetPresentationClock(sink, NULL); ok(hr == S_OK, "Unexpected hr %#x.\n", hr); @@ -2947,6 +2951,36 @@ todo_wine
IMFMediaTypeHandler_Release(handler);
+ /* State change with initialized stream. */ + hr = IMFMediaSink_QueryInterface(sink, &IID_IMFClockStateSink, (void **)&state_sink); + ok(hr == S_OK, "Failed to get interface, hr %#x.\n", hr); + + hr = IMFClockStateSink_OnClockStart(state_sink, 0, 0); + ok(hr == S_OK, "Unexpected hr %#x.\n", hr); + + hr = IMFClockStateSink_OnClockStart(state_sink, 0, 0); + ok(hr == S_OK, "Unexpected hr %#x.\n", hr); + + hr = IMFClockStateSink_OnClockPause(state_sink, 0); + ok(hr == S_OK, "Unexpected hr %#x.\n", hr); + + hr = IMFClockStateSink_OnClockStop(state_sink, 0); + ok(hr == S_OK, "Unexpected hr %#x.\n", hr); + + hr = IMFClockStateSink_OnClockStop(state_sink, 0); + ok(hr == S_OK, "Unexpected hr %#x.\n", hr); + + hr = IMFClockStateSink_OnClockPause(state_sink, 0); + ok(hr == MF_E_INVALID_STATE_TRANSITION, "Unexpected hr %#x.\n", hr); + + hr = IMFClockStateSink_OnClockRestart(state_sink, 0); + ok(hr == S_OK, "Unexpected hr %#x.\n", hr); + + hr = IMFClockStateSink_OnClockRestart(state_sink, 0); + ok(hr == S_OK, "Unexpected hr %#x.\n", hr); + + IMFClockStateSink_Release(state_sink); + IMFStreamSink_Release(stream_sink);
/* Volume control */
Hi,
While running your changed tests, I think I found new failures. Being a bot and all I'm not very good at pattern recognition, so I might be wrong, but could you please double-check?
Full results can be found at: https://testbot.winehq.org/JobDetails.pl?Key=70190
Your paranoid android.
=== debiant (build log) ===
error: patch failed: dlls/mf/sar.c:353 error: patch failed: dlls/mf/sar.c:50 error: patch failed: dlls/mf/sar.c:31 error: patch failed: dlls/mf/tests/mf.c:2947 Task: Patch failed to apply
=== debiant (build log) ===
error: patch failed: dlls/mf/sar.c:353 error: patch failed: dlls/mf/sar.c:50 error: patch failed: dlls/mf/sar.c:31 error: patch failed: dlls/mf/tests/mf.c:2947 Task: Patch failed to apply
Signed-off-by: Nikolay Sivov nsivov@codeweavers.com ---
It doesn't wait for samples.
dlls/mf/sar.c | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-)
diff --git a/dlls/mf/sar.c b/dlls/mf/sar.c index 6c740abeba..e426020a08 100644 --- a/dlls/mf/sar.c +++ b/dlls/mf/sar.c @@ -391,6 +391,14 @@ static const IMFMediaSinkVtbl audio_renderer_sink_vtbl = audio_renderer_sink_Shutdown, };
+static void audio_renderer_preroll(struct audio_renderer *renderer) +{ + int i; + + for (i = 0; i < 2; ++i) + IMFMediaEventQueue_QueueEventParamVar(renderer->stream_event_queue, MEStreamSinkRequestSample, &GUID_NULL, S_OK, NULL); +} + static HRESULT WINAPI audio_renderer_preroll_QueryInterface(IMFMediaSinkPreroll *iface, REFIID riid, void **obj) { struct audio_renderer *renderer = impl_from_IMFMediaSinkPreroll(iface); @@ -411,9 +419,15 @@ static ULONG WINAPI audio_renderer_preroll_Release(IMFMediaSinkPreroll *iface)
static HRESULT WINAPI audio_renderer_preroll_NotifyPreroll(IMFMediaSinkPreroll *iface, MFTIME start_time) { - FIXME("%p, %s.\n", iface, debugstr_time(start_time)); + struct audio_renderer *renderer = impl_from_IMFMediaSinkPreroll(iface);
- return E_NOTIMPL; + TRACE("%p, %s.\n", iface, debugstr_time(start_time)); + + if (renderer->is_shut_down) + return MF_E_SHUTDOWN; + + audio_renderer_preroll(renderer); + return IMFMediaEventQueue_QueueEventParamVar(renderer->stream_event_queue, MEStreamSinkPrerolled, &GUID_NULL, S_OK, NULL); }
static const IMFMediaSinkPrerollVtbl audio_renderer_preroll_vtbl =
Hi,
While running your changed tests, I think I found new failures. Being a bot and all I'm not very good at pattern recognition, so I might be wrong, but could you please double-check?
Full results can be found at: https://testbot.winehq.org/JobDetails.pl?Key=70191
Your paranoid android.
=== debiant (build log) ===
error: patch failed: dlls/mf/sar.c:353 error: patch failed: dlls/mf/sar.c:50 error: patch failed: dlls/mf/sar.c:31 error: patch failed: dlls/mf/tests/mf.c:2947 Task: Patch failed to apply
=== debiant (build log) ===
error: patch failed: dlls/mf/sar.c:353 error: patch failed: dlls/mf/sar.c:50 error: patch failed: dlls/mf/sar.c:31 error: patch failed: dlls/mf/tests/mf.c:2947 Task: Patch failed to apply
Signed-off-by: Nikolay Sivov nsivov@codeweavers.com --- dlls/mf/sar.c | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-)
diff --git a/dlls/mf/sar.c b/dlls/mf/sar.c index e426020a08..d14a903eea 100644 --- a/dlls/mf/sar.c +++ b/dlls/mf/sar.c @@ -1271,6 +1271,7 @@ static HRESULT WINAPI audio_renderer_stream_type_handler_SetCurrentMediaType(IMF { struct audio_renderer *renderer = impl_from_IMFMediaTypeHandler(iface); const unsigned int test_flags = MF_MEDIATYPE_EQUAL_MAJOR_TYPES | MF_MEDIATYPE_EQUAL_FORMAT_TYPES; + BOOL compare_result; unsigned int flags; HRESULT hr = S_OK;
@@ -1287,7 +1288,16 @@ static HRESULT WINAPI audio_renderer_stream_type_handler_SetCurrentMediaType(IMF renderer->current_media_type = media_type; IMFMediaType_AddRef(renderer->current_media_type);
- hr = audio_renderer_create_audio_client(renderer); + if (SUCCEEDED(hr = audio_renderer_create_audio_client(renderer))) + { + if (SUCCEEDED(IMFMediaType_Compare(renderer->media_type, (IMFAttributes *)media_type, MF_ATTRIBUTES_MATCH_OUR_ITEMS, + &compare_result)) && !compare_result) + { + IMFMediaEventQueue_QueueEventParamVar(renderer->stream_event_queue, MEStreamSinkFormatInvalidated, &GUID_NULL, + S_OK, NULL); + audio_renderer_preroll(renderer); + } + } } else hr = MF_E_INVALIDMEDIATYPE;
Hi,
While running your changed tests, I think I found new failures. Being a bot and all I'm not very good at pattern recognition, so I might be wrong, but could you please double-check?
Full results can be found at: https://testbot.winehq.org/JobDetails.pl?Key=70192
Your paranoid android.
=== debiant (build log) ===
error: patch failed: dlls/mf/sar.c:353 error: patch failed: dlls/mf/sar.c:50 error: patch failed: dlls/mf/sar.c:31 error: patch failed: dlls/mf/tests/mf.c:2947 error: patch failed: dlls/mf/sar.c:1271 Task: Patch failed to apply
=== debiant (build log) ===
error: patch failed: dlls/mf/sar.c:353 error: patch failed: dlls/mf/sar.c:50 error: patch failed: dlls/mf/sar.c:31 error: patch failed: dlls/mf/tests/mf.c:2947 error: patch failed: dlls/mf/sar.c:1271 Task: Patch failed to apply
Hi,
While running your changed tests, I think I found new failures. Being a bot and all I'm not very good at pattern recognition, so I might be wrong, but could you please double-check?
Full results can be found at: https://testbot.winehq.org/JobDetails.pl?Key=70188
Your paranoid android.
=== debiant (build log) ===
error: patch failed: dlls/mf/sar.c:353 Task: Patch failed to apply
=== debiant (build log) ===
error: patch failed: dlls/mf/sar.c:353 Task: Patch failed to apply
On 4/21/20 4:57 PM, Marvin wrote:
Hi,
While running your changed tests, I think I found new failures. Being a bot and all I'm not very good at pattern recognition, so I might be wrong, but could you please double-check?
Full results can be found at: https://testbot.winehq.org/JobDetails.pl?Key=70188
Your paranoid android.
=== debiant (build log) ===
error: patch failed: dlls/mf/sar.c:353 Task: Patch failed to apply
=== debiant (build log) ===
error: patch failed: dlls/mf/sar.c:353 Task: Patch failed to apply
Bot probably failed to update.