mfplat: Create system clock instance per system time source.

Signed-off-by: Nikolay Sivov <nsivov@codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
Nikolay Sivov 2019-05-20 15:25:58 +03:00 committed by Alexandre Julliard
parent ac2038ef30
commit 5904eb8419
2 changed files with 212 additions and 3 deletions

View File

@ -44,12 +44,19 @@ WINE_DEFAULT_DEBUG_CHANNEL(mfplat);
static LONG platform_lock;
struct system_clock
{
IMFClock IMFClock_iface;
LONG refcount;
};
struct system_time_source
{
IMFPresentationTimeSource IMFPresentationTimeSource_iface;
IMFClockStateSink IMFClockStateSink_iface;
LONG refcount;
MFCLOCK_STATE state;
IMFClock *clock;
CRITICAL_SECTION cs;
};
@ -63,6 +70,11 @@ static struct system_time_source *impl_from_IMFClockStateSink(IMFClockStateSink
return CONTAINING_RECORD(iface, struct system_time_source, IMFClockStateSink_iface);
}
static struct system_clock *impl_from_IMFClock(IMFClock *iface)
{
return CONTAINING_RECORD(iface, struct system_clock, IMFClock_iface);
}
static const WCHAR transform_keyW[] = {'M','e','d','i','a','F','o','u','n','d','a','t','i','o','n','\\',
'T','r','a','n','s','f','o','r','m','s',0};
static const WCHAR categories_keyW[] = {'M','e','d','i','a','F','o','u','n','d','a','t','i','o','n','\\',
@ -6538,6 +6550,126 @@ HRESULT WINAPI MFCreateMFByteStreamOnStreamEx(IUnknown *stream, IMFByteStream **
return E_NOTIMPL;
}
static HRESULT WINAPI system_clock_QueryInterface(IMFClock *iface, REFIID riid, void **obj)
{
TRACE("%p, %s, %p.\n", iface, debugstr_guid(riid), obj);
if (IsEqualIID(riid, &IID_IMFClock) ||
IsEqualIID(riid, &IID_IUnknown))
{
*obj = iface;
IMFClock_AddRef(iface);
return S_OK;
}
WARN("Unsupported %s.\n", debugstr_guid(riid));
*obj = NULL;
return E_NOINTERFACE;
}
static ULONG WINAPI system_clock_AddRef(IMFClock *iface)
{
struct system_clock *clock = impl_from_IMFClock(iface);
ULONG refcount = InterlockedIncrement(&clock->refcount);
TRACE("%p, refcount %u.\n", iface, refcount);
return refcount;
}
static ULONG WINAPI system_clock_Release(IMFClock *iface)
{
struct system_clock *clock = impl_from_IMFClock(iface);
ULONG refcount = InterlockedDecrement(&clock->refcount);
TRACE("%p, refcount %u.\n", iface, refcount);
if (!refcount)
heap_free(clock);
return refcount;
}
static HRESULT WINAPI system_clock_GetClockCharacteristics(IMFClock *iface, DWORD *flags)
{
TRACE("%p, %p.\n", iface, flags);
*flags = MFCLOCK_CHARACTERISTICS_FLAG_FREQUENCY_10MHZ | MFCLOCK_CHARACTERISTICS_FLAG_ALWAYS_RUNNING |
MFCLOCK_CHARACTERISTICS_FLAG_IS_SYSTEM_CLOCK;
return S_OK;
}
static HRESULT WINAPI system_clock_GetCorrelatedTime(IMFClock *iface, DWORD reserved, LONGLONG *clock_time,
MFTIME *system_time)
{
TRACE("%p, %#x, %p, %p.\n", iface, reserved, clock_time, system_time);
*clock_time = *system_time = MFGetSystemTime();
return S_OK;
}
static HRESULT WINAPI system_clock_GetContinuityKey(IMFClock *iface, DWORD *key)
{
TRACE("%p, %p.\n", iface, key);
*key = 0;
return S_OK;
}
static HRESULT WINAPI system_clock_GetState(IMFClock *iface, DWORD reserved, MFCLOCK_STATE *state)
{
TRACE("%p, %#x, %p.\n", iface, reserved, state);
*state = MFCLOCK_STATE_RUNNING;
return S_OK;
}
static HRESULT WINAPI system_clock_GetProperties(IMFClock *iface, MFCLOCK_PROPERTIES *props)
{
TRACE("%p, %p.\n", iface, props);
if (!props)
return E_POINTER;
memset(props, 0, sizeof(*props));
props->qwClockFrequency = MFCLOCK_FREQUENCY_HNS;
props->dwClockTolerance = MFCLOCK_TOLERANCE_UNKNOWN;
props->dwClockJitter = 1;
return S_OK;
}
static const IMFClockVtbl system_clock_vtbl =
{
system_clock_QueryInterface,
system_clock_AddRef,
system_clock_Release,
system_clock_GetClockCharacteristics,
system_clock_GetCorrelatedTime,
system_clock_GetContinuityKey,
system_clock_GetState,
system_clock_GetProperties,
};
static HRESULT create_system_clock(IMFClock **clock)
{
struct system_clock *object;
if (!(object = heap_alloc(sizeof(*object))))
return E_OUTOFMEMORY;
object->IMFClock_iface.lpVtbl = &system_clock_vtbl;
object->refcount = 1;
*clock = &object->IMFClock_iface;
return S_OK;
}
static HRESULT WINAPI system_time_source_QueryInterface(IMFPresentationTimeSource *iface, REFIID riid, void **obj)
{
struct system_time_source *source = impl_from_IMFPresentationTimeSource(iface);
@ -6583,6 +6715,8 @@ static ULONG WINAPI system_time_source_Release(IMFPresentationTimeSource *iface)
if (!refcount)
{
if (source->clock)
IMFClock_Release(source->clock);
DeleteCriticalSection(&source->cs);
heap_free(source);
}
@ -6648,9 +6782,14 @@ static HRESULT WINAPI system_time_source_GetProperties(IMFPresentationTimeSource
static HRESULT WINAPI system_time_source_GetUnderlyingClock(IMFPresentationTimeSource *iface, IMFClock **clock)
{
FIXME("%p, %p.\n", iface, clock);
struct system_time_source *source = impl_from_IMFPresentationTimeSource(iface);
return E_NOTIMPL;
TRACE("%p, %p.\n", iface, clock);
*clock = source->clock;
IMFClock_AddRef(*clock);
return S_OK;
}
static const IMFPresentationTimeSourceVtbl systemtimesourcevtbl =
@ -6812,6 +6951,7 @@ static const IMFClockStateSinkVtbl systemtimesourcesinkvtbl =
HRESULT WINAPI MFCreateSystemTimeSource(IMFPresentationTimeSource **time_source)
{
struct system_time_source *object;
HRESULT hr;
TRACE("%p.\n", time_source);
@ -6824,6 +6964,12 @@ HRESULT WINAPI MFCreateSystemTimeSource(IMFPresentationTimeSource **time_source)
object->refcount = 1;
InitializeCriticalSection(&object->cs);
if (FAILED(hr = create_system_clock(&object->clock)))
{
IMFPresentationTimeSource_Release(&object->IMFPresentationTimeSource_iface);
return hr;
}
*time_source = &object->IMFPresentationTimeSource_iface;
return S_OK;

View File

@ -52,6 +52,15 @@ DEFINE_GUID(CLSID_FileSchemeHandler, 0x477ec299, 0x1421, 0x4bdd, 0x97, 0x1f, 0x7
static BOOL is_win8_plus;
#define EXPECT_REF(obj,ref) _expect_ref((IUnknown*)obj, ref, __LINE__)
static void _expect_ref(IUnknown *obj, ULONG ref, int line)
{
ULONG rc;
IUnknown_AddRef(obj);
rc = IUnknown_Release(obj);
ok_(__FILE__,line)(rc == ref, "Unexpected refcount %d, expected %d.\n", rc, ref);
}
static HRESULT (WINAPI *pMFCopyImage)(BYTE *dest, LONG deststride, const BYTE *src, LONG srcstride,
DWORD width, DWORD lines);
static HRESULT (WINAPI *pMFCreateSourceResolver)(IMFSourceResolver **resolver);
@ -2540,11 +2549,14 @@ static void test_system_time_source(void)
{ CLOCK_STOP, MFCLOCK_STATE_STOPPED },
{ CLOCK_PAUSE, MFCLOCK_STATE_STOPPED, TRUE },
};
IMFPresentationTimeSource *time_source;
IMFPresentationTimeSource *time_source, *time_source2;
IMFClockStateSink *statesink;
IMFClock *clock, *clock2;
MFCLOCK_PROPERTIES props;
MFCLOCK_STATE state;
unsigned int i;
MFTIME systime;
LONGLONG time;
DWORD value;
HRESULT hr;
@ -2612,6 +2624,57 @@ static void test_system_time_source(void)
ok(props.dwClockTolerance == MFCLOCK_TOLERANCE_UNKNOWN, "Unexpected tolerance %u.\n", props.dwClockTolerance);
ok(props.dwClockJitter == 1, "Unexpected jitter %u.\n", props.dwClockJitter);
/* Underlying clock. */
hr = MFCreateSystemTimeSource(&time_source2);
ok(hr == S_OK, "Failed to create time source, hr %#x.\n", hr);
EXPECT_REF(time_source2, 1);
hr = IMFPresentationTimeSource_GetUnderlyingClock(time_source2, &clock2);
ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
EXPECT_REF(time_source2, 1);
EXPECT_REF(clock2, 2);
EXPECT_REF(time_source, 1);
hr = IMFPresentationTimeSource_GetUnderlyingClock(time_source, &clock);
ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
EXPECT_REF(time_source, 1);
EXPECT_REF(clock, 2);
ok(clock != clock2, "Unexpected clock instance.\n");
IMFPresentationTimeSource_Release(time_source2);
IMFClock_Release(clock2);
hr = IMFClock_GetClockCharacteristics(clock, &value);
ok(hr == S_OK, "Failed to get clock flags, hr %#x.\n", hr);
ok(value == (MFCLOCK_CHARACTERISTICS_FLAG_FREQUENCY_10MHZ | MFCLOCK_CHARACTERISTICS_FLAG_ALWAYS_RUNNING |
MFCLOCK_CHARACTERISTICS_FLAG_IS_SYSTEM_CLOCK), "Unexpected flags %#x.\n", value);
hr = IMFClock_GetContinuityKey(clock, &value);
ok(hr == S_OK, "Failed to get clock key, hr %#x.\n", hr);
ok(value == 0, "Unexpected key value %u.\n", value);
hr = IMFClock_GetState(clock, 0, &state);
ok(hr == S_OK, "Failed to get clock state, hr %#x.\n", hr);
ok(state == MFCLOCK_STATE_RUNNING, "Unexpected state %d.\n", state);
hr = IMFClock_GetProperties(clock, &props);
ok(hr == S_OK, "Failed to get clock properties, hr %#x.\n", hr);
ok(props.qwCorrelationRate == 0, "Unexpected correlation rate %s.\n",
wine_dbgstr_longlong(props.qwCorrelationRate));
ok(IsEqualGUID(&props.guidClockId, &GUID_NULL), "Unexpected clock id %s.\n", wine_dbgstr_guid(&props.guidClockId));
ok(props.dwClockFlags == 0, "Unexpected flags %#x.\n", props.dwClockFlags);
ok(props.qwClockFrequency == MFCLOCK_FREQUENCY_HNS, "Unexpected frequency %s.\n",
wine_dbgstr_longlong(props.qwClockFrequency));
ok(props.dwClockTolerance == MFCLOCK_TOLERANCE_UNKNOWN, "Unexpected tolerance %u.\n", props.dwClockTolerance);
ok(props.dwClockJitter == 1, "Unexpected jitter %u.\n", props.dwClockJitter);
hr = IMFClock_GetCorrelatedTime(clock, 0, &time, &systime);
ok(hr == S_OK, "Failed to get clock time, hr %#x.\n", hr);
ok(time == systime, "Unexpected time %s, %s.\n", wine_dbgstr_longlong(time), wine_dbgstr_longlong(systime));
IMFClock_Release(clock);
IMFPresentationTimeSource_Release(time_source);
}