mf: Control time source state from presentation clock.
Signed-off-by: Nikolay Sivov <nsivov@codeweavers.com> Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
parent
7e9559231f
commit
c815f908f9
|
@ -47,6 +47,7 @@ struct presentation_clock
|
|||
IMFShutdown IMFShutdown_iface;
|
||||
LONG refcount;
|
||||
IMFPresentationTimeSource *time_source;
|
||||
IMFClockStateSink *time_source_sink;
|
||||
MFCLOCK_STATE state;
|
||||
CRITICAL_SECTION cs;
|
||||
};
|
||||
|
@ -341,6 +342,8 @@ static ULONG WINAPI present_clock_Release(IMFPresentationClock *iface)
|
|||
{
|
||||
if (clock->time_source)
|
||||
IMFPresentationTimeSource_Release(clock->time_source);
|
||||
if (clock->time_source_sink)
|
||||
IMFClockStateSink_Release(clock->time_source_sink);
|
||||
DeleteCriticalSection(&clock->cs);
|
||||
heap_free(clock);
|
||||
}
|
||||
|
@ -395,9 +398,29 @@ static HRESULT WINAPI present_clock_GetProperties(IMFPresentationClock *iface, M
|
|||
static HRESULT WINAPI present_clock_SetTimeSource(IMFPresentationClock *iface,
|
||||
IMFPresentationTimeSource *time_source)
|
||||
{
|
||||
FIXME("%p, %p.\n", iface, time_source);
|
||||
struct presentation_clock *clock = impl_from_IMFPresentationClock(iface);
|
||||
HRESULT hr;
|
||||
|
||||
return E_NOTIMPL;
|
||||
TRACE("%p, %p.\n", iface, time_source);
|
||||
|
||||
EnterCriticalSection(&clock->cs);
|
||||
if (clock->time_source)
|
||||
IMFPresentationTimeSource_Release(clock->time_source);
|
||||
if (clock->time_source_sink)
|
||||
IMFClockStateSink_Release(clock->time_source_sink);
|
||||
clock->time_source = NULL;
|
||||
clock->time_source_sink = NULL;
|
||||
|
||||
hr = IMFPresentationTimeSource_QueryInterface(time_source, &IID_IMFClockStateSink, (void **)&clock->time_source_sink);
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
clock->time_source = time_source;
|
||||
IMFPresentationTimeSource_AddRef(clock->time_source);
|
||||
}
|
||||
|
||||
LeaveCriticalSection(&clock->cs);
|
||||
|
||||
return hr;
|
||||
}
|
||||
|
||||
static HRESULT WINAPI present_clock_GetTimeSource(IMFPresentationClock *iface,
|
||||
|
@ -443,25 +466,107 @@ static HRESULT WINAPI present_clock_RemoveClockStateSink(IMFPresentationClock *i
|
|||
return E_NOTIMPL;
|
||||
}
|
||||
|
||||
enum clock_command
|
||||
{
|
||||
CLOCK_CMD_START = 0,
|
||||
CLOCK_CMD_STOP,
|
||||
CLOCK_CMD_PAUSE,
|
||||
CLOCK_CMD_MAX,
|
||||
};
|
||||
|
||||
static HRESULT clock_change_state(struct presentation_clock *clock, enum clock_command command)
|
||||
{
|
||||
static const BYTE state_change_is_allowed[MFCLOCK_STATE_PAUSED+1][CLOCK_CMD_MAX] =
|
||||
{ /* S S* P */
|
||||
/* INVALID */ { 1, 1, 1 },
|
||||
/* RUNNING */ { 1, 1, 1 },
|
||||
/* STOPPED */ { 1, 1, 0 },
|
||||
/* PAUSED */ { 1, 1, 0 },
|
||||
};
|
||||
static const MFCLOCK_STATE states[CLOCK_CMD_MAX] =
|
||||
{
|
||||
/* CLOCK_CMD_START */ MFCLOCK_STATE_RUNNING,
|
||||
/* CLOCK_CMD_STOP */ MFCLOCK_STATE_STOPPED,
|
||||
/* CLOCK_CMD_PAUSE */ MFCLOCK_STATE_PAUSED,
|
||||
};
|
||||
HRESULT hr;
|
||||
|
||||
/* FIXME: use correct timestamps. */
|
||||
|
||||
if (clock->state == states[command] && clock->state != MFCLOCK_STATE_RUNNING)
|
||||
return MF_E_CLOCK_STATE_ALREADY_SET;
|
||||
|
||||
if (!state_change_is_allowed[clock->state][command])
|
||||
return MF_E_INVALIDREQUEST;
|
||||
|
||||
switch (command)
|
||||
{
|
||||
case CLOCK_CMD_START:
|
||||
if (clock->state == MFCLOCK_STATE_PAUSED)
|
||||
hr = IMFClockStateSink_OnClockRestart(clock->time_source_sink, 0);
|
||||
else
|
||||
hr = IMFClockStateSink_OnClockStart(clock->time_source_sink, 0, 0);
|
||||
break;
|
||||
case CLOCK_CMD_STOP:
|
||||
hr = IMFClockStateSink_OnClockStop(clock->time_source_sink, 0);
|
||||
break;
|
||||
case CLOCK_CMD_PAUSE:
|
||||
hr = IMFClockStateSink_OnClockPause(clock->time_source_sink, 0);
|
||||
break;
|
||||
default:
|
||||
;
|
||||
}
|
||||
|
||||
if (FAILED(hr))
|
||||
return hr;
|
||||
|
||||
clock->state = states[command];
|
||||
|
||||
/* FIXME: notify registered sinks. */
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
static HRESULT WINAPI present_clock_Start(IMFPresentationClock *iface, LONGLONG start_offset)
|
||||
{
|
||||
FIXME("%p, %s.\n", iface, wine_dbgstr_longlong(start_offset));
|
||||
struct presentation_clock *clock = impl_from_IMFPresentationClock(iface);
|
||||
HRESULT hr;
|
||||
|
||||
return E_NOTIMPL;
|
||||
TRACE("%p, %s.\n", iface, wine_dbgstr_longlong(start_offset));
|
||||
|
||||
EnterCriticalSection(&clock->cs);
|
||||
hr = clock_change_state(clock, CLOCK_CMD_START);
|
||||
LeaveCriticalSection(&clock->cs);
|
||||
|
||||
return hr;
|
||||
}
|
||||
|
||||
static HRESULT WINAPI present_clock_Stop(IMFPresentationClock *iface)
|
||||
{
|
||||
FIXME("%p.\n", iface);
|
||||
struct presentation_clock *clock = impl_from_IMFPresentationClock(iface);
|
||||
HRESULT hr;
|
||||
|
||||
return E_NOTIMPL;
|
||||
TRACE("%p.\n", iface);
|
||||
|
||||
EnterCriticalSection(&clock->cs);
|
||||
hr = clock_change_state(clock, CLOCK_CMD_STOP);
|
||||
LeaveCriticalSection(&clock->cs);
|
||||
|
||||
return hr;
|
||||
}
|
||||
|
||||
static HRESULT WINAPI present_clock_Pause(IMFPresentationClock *iface)
|
||||
{
|
||||
FIXME("%p.\n", iface);
|
||||
struct presentation_clock *clock = impl_from_IMFPresentationClock(iface);
|
||||
HRESULT hr;
|
||||
|
||||
return E_NOTIMPL;
|
||||
TRACE("%p.\n", iface);
|
||||
|
||||
EnterCriticalSection(&clock->cs);
|
||||
hr = clock_change_state(clock, CLOCK_CMD_PAUSE);
|
||||
LeaveCriticalSection(&clock->cs);
|
||||
|
||||
return hr;
|
||||
}
|
||||
|
||||
static const IMFPresentationClockVtbl presentationclockvtbl =
|
||||
|
|
|
@ -735,8 +735,37 @@ static void test_MFShutdownObject(void)
|
|||
ok(hr == S_OK, "Failed to shut down, hr %#x.\n", hr);
|
||||
}
|
||||
|
||||
enum clock_action
|
||||
{
|
||||
CLOCK_START,
|
||||
CLOCK_STOP,
|
||||
CLOCK_PAUSE,
|
||||
};
|
||||
|
||||
static void test_presentation_clock(void)
|
||||
{
|
||||
static const struct clock_state_test
|
||||
{
|
||||
enum clock_action action;
|
||||
MFCLOCK_STATE clock_state;
|
||||
MFCLOCK_STATE source_state;
|
||||
HRESULT hr;
|
||||
}
|
||||
clock_state_change[] =
|
||||
{
|
||||
{ CLOCK_STOP, MFCLOCK_STATE_STOPPED, MFCLOCK_STATE_INVALID },
|
||||
{ CLOCK_PAUSE, MFCLOCK_STATE_STOPPED, MFCLOCK_STATE_INVALID, MF_E_INVALIDREQUEST },
|
||||
{ CLOCK_STOP, MFCLOCK_STATE_STOPPED, MFCLOCK_STATE_INVALID, MF_E_CLOCK_STATE_ALREADY_SET },
|
||||
{ CLOCK_START, MFCLOCK_STATE_RUNNING, MFCLOCK_STATE_RUNNING },
|
||||
{ CLOCK_START, MFCLOCK_STATE_RUNNING, MFCLOCK_STATE_RUNNING },
|
||||
{ CLOCK_PAUSE, MFCLOCK_STATE_PAUSED, MFCLOCK_STATE_PAUSED },
|
||||
{ CLOCK_PAUSE, MFCLOCK_STATE_PAUSED, MFCLOCK_STATE_PAUSED, MF_E_CLOCK_STATE_ALREADY_SET },
|
||||
{ CLOCK_STOP, MFCLOCK_STATE_STOPPED, MFCLOCK_STATE_STOPPED },
|
||||
{ CLOCK_START, MFCLOCK_STATE_RUNNING, MFCLOCK_STATE_RUNNING },
|
||||
{ CLOCK_STOP, MFCLOCK_STATE_STOPPED, MFCLOCK_STATE_STOPPED },
|
||||
{ CLOCK_STOP, MFCLOCK_STATE_STOPPED, MFCLOCK_STATE_STOPPED, MF_E_CLOCK_STATE_ALREADY_SET },
|
||||
{ CLOCK_PAUSE, MFCLOCK_STATE_STOPPED, MFCLOCK_STATE_STOPPED, MF_E_INVALIDREQUEST },
|
||||
};
|
||||
IMFPresentationTimeSource *time_source;
|
||||
IMFRateControl *rate_control;
|
||||
IMFPresentationClock *clock;
|
||||
|
@ -746,6 +775,7 @@ static void test_presentation_clock(void)
|
|||
MFCLOCK_STATE state;
|
||||
IMFTimer *timer;
|
||||
MFTIME systime;
|
||||
unsigned int i;
|
||||
DWORD value;
|
||||
HRESULT hr;
|
||||
|
||||
|
@ -779,6 +809,43 @@ todo_wine
|
|||
todo_wine
|
||||
ok(hr == MF_E_CLOCK_NO_TIME_SOURCE, "Unexpected hr %#x.\n", hr);
|
||||
|
||||
/* Set default time source. */
|
||||
hr = MFCreateSystemTimeSource(&time_source);
|
||||
ok(hr == S_OK, "Failed to create time source, hr %#x.\n", hr);
|
||||
|
||||
hr = IMFPresentationClock_SetTimeSource(clock, time_source);
|
||||
ok(hr == S_OK, "Failed to set time source, hr %#x.\n", hr);
|
||||
|
||||
/* State changes. */
|
||||
for (i = 0; i < ARRAY_SIZE(clock_state_change); ++i)
|
||||
{
|
||||
switch (clock_state_change[i].action)
|
||||
{
|
||||
case CLOCK_STOP:
|
||||
hr = IMFPresentationClock_Stop(clock);
|
||||
break;
|
||||
case CLOCK_PAUSE:
|
||||
hr = IMFPresentationClock_Pause(clock);
|
||||
break;
|
||||
case CLOCK_START:
|
||||
hr = IMFPresentationClock_Start(clock, 0);
|
||||
break;
|
||||
default:
|
||||
;
|
||||
}
|
||||
ok(hr == clock_state_change[i].hr, "%u: unexpected hr %#x.\n", i, hr);
|
||||
|
||||
hr = IMFPresentationTimeSource_GetState(time_source, 0, &state);
|
||||
ok(hr == S_OK, "%u: failed to get state, hr %#x.\n", i, hr);
|
||||
ok(state == clock_state_change[i].source_state, "%u: unexpected state %d.\n", i, state);
|
||||
|
||||
hr = IMFPresentationClock_GetState(clock, 0, &state);
|
||||
ok(hr == S_OK, "%u: failed to get state, hr %#x.\n", i, hr);
|
||||
ok(state == clock_state_change[i].clock_state, "%u: unexpected state %d.\n", i, state);
|
||||
}
|
||||
|
||||
IMFPresentationTimeSource_Release(time_source);
|
||||
|
||||
hr = IMFPresentationClock_QueryInterface(clock, &IID_IMFRateControl, (void **)&rate_control);
|
||||
ok(hr == S_OK, "Failed to get rate control interface, hr %#x.\n", hr);
|
||||
IMFRateControl_Release(rate_control);
|
||||
|
|
|
@ -82,6 +82,7 @@
|
|||
#define MF_E_TOPO_MISSING_SOURCE _HRESULT_TYPEDEF_(0xc00d521a)
|
||||
#define MF_E_TOPO_SINK_ACTIVATES_UNSUPPORTED _HRESULT_TYPEDEF_(0xc00d521b)
|
||||
|
||||
#define MF_E_CLOCK_NO_TIME_SOURCE _HRESULT_TYPEDEF_(0xc00d9c41)
|
||||
#define MF_E_CLOCK_NO_TIME_SOURCE _HRESULT_TYPEDEF_(0xc00d9c41)
|
||||
#define MF_E_CLOCK_STATE_ALREADY_SET _HRESULT_TYPEDEF_(0xc00d9c42)
|
||||
|
||||
#endif /* __WINE_MFERROR_H */
|
||||
|
|
Loading…
Reference in New Issue