[PATCH 4/5] mf: Handle state changes for SAR stream.

Nikolay Sivov nsivov at codeweavers.com
Mon Apr 20 11:25:01 CDT 2020


Signed-off-by: Nikolay Sivov <nsivov at 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 6da66f136a..93ecc6cb47 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;
 };
@@ -500,30 +508,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 511c6a8eb9..f95d088c5c 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 */
-- 
2.26.1




More information about the wine-devel mailing list