mf: Handle state changes for SAR stream.

Signed-off-by: Nikolay Sivov <nsivov@codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard@winehq.org>
feature/deterministic
Nikolay Sivov 2020-04-21 16:43:02 +03:00 committed by Alexandre Julliard
parent da6ad526e9
commit 0d201a215d
2 changed files with 135 additions and 10 deletions

View File

@ -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)

View File

@ -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 */