[PATCH 3/5] mf: Handle state changes for SAR stream.
Nikolay Sivov
nsivov at codeweavers.com
Tue Apr 21 08:43:02 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 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 */
--
2.26.1
More information about the wine-devel
mailing list