[PATCH 2/2] mfplat: Create system clock instance per system time source.
Nikolay Sivov
nsivov at codeweavers.com
Mon May 20 07:25:58 CDT 2019
Signed-off-by: Nikolay Sivov <nsivov at codeweavers.com>
---
dlls/mfplat/main.c | 150 ++++++++++++++++++++++++++++++++++++-
dlls/mfplat/tests/mfplat.c | 65 +++++++++++++++-
2 files changed, 212 insertions(+), 3 deletions(-)
diff --git a/dlls/mfplat/main.c b/dlls/mfplat/main.c
index 77edabec2c..23f13afa3a 100644
--- a/dlls/mfplat/main.c
+++ b/dlls/mfplat/main.c
@@ -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;
diff --git a/dlls/mfplat/tests/mfplat.c b/dlls/mfplat/tests/mfplat.c
index 4adfb1b8ad..e385987f33 100644
--- a/dlls/mfplat/tests/mfplat.c
+++ b/dlls/mfplat/tests/mfplat.c
@@ -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);
}
--
2.20.1
More information about the wine-devel
mailing list