[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