Signed-off-by: Nikolay Sivov nsivov@codeweavers.com --- dlls/mfplat/main.c | 12 ++++++++++-- dlls/mfplat/tests/mfplat.c | 17 +++++++++++++++++ include/mfidl.idl | 6 ++++++ 3 files changed, 33 insertions(+), 2 deletions(-)
diff --git a/dlls/mfplat/main.c b/dlls/mfplat/main.c index e80408d2b2..77edabec2c 100644 --- a/dlls/mfplat/main.c +++ b/dlls/mfplat/main.c @@ -6633,9 +6633,17 @@ static HRESULT WINAPI system_time_source_GetState(IMFPresentationTimeSource *ifa
static HRESULT WINAPI system_time_source_GetProperties(IMFPresentationTimeSource *iface, MFCLOCK_PROPERTIES *props) { - FIXME("%p, %p.\n", iface, props); + TRACE("%p, %p.\n", iface, props);
- return E_NOTIMPL; + 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 HRESULT WINAPI system_time_source_GetUnderlyingClock(IMFPresentationTimeSource *iface, IMFClock **clock) diff --git a/dlls/mfplat/tests/mfplat.c b/dlls/mfplat/tests/mfplat.c index 7fa3ddd876..4adfb1b8ad 100644 --- a/dlls/mfplat/tests/mfplat.c +++ b/dlls/mfplat/tests/mfplat.c @@ -2542,6 +2542,7 @@ static void test_system_time_source(void) }; IMFPresentationTimeSource *time_source; IMFClockStateSink *statesink; + MFCLOCK_PROPERTIES props; MFCLOCK_STATE state; unsigned int i; DWORD value; @@ -2595,6 +2596,22 @@ static void test_system_time_source(void)
IMFClockStateSink_Release(statesink);
+ /* Properties. */ + hr = IMFPresentationTimeSource_GetProperties(time_source, NULL); + ok(hr == E_POINTER, "Unexpected hr %#x.\n", hr); + + hr = IMFPresentationTimeSource_GetProperties(time_source, &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); + IMFPresentationTimeSource_Release(time_source); }
diff --git a/include/mfidl.idl b/include/mfidl.idl index a5882e98e5..2421c06f50 100644 --- a/include/mfidl.idl +++ b/include/mfidl.idl @@ -47,6 +47,12 @@ typedef enum MF_OBJECT_TYPE MF_OBJECT_INVALID } MF_OBJECT_TYPE;
+cpp_quote("#define MFCLOCK_FREQUENCY_HNS 10000000") +cpp_quote("#define MFCLOCK_TOLERANCE_UNKNOWN 50000") +cpp_quote("#define MFCLOCK_JITTER_ISR 1000") +cpp_quote("#define MFCLOCK_JITTER_DPC 4000") +cpp_quote("#define MFCLOCK_JITTER_PASSIVE 10000") + typedef struct _MFCLOCK_PROPERTIES { unsigned __int64 qwCorrelationRate;
Signed-off-by: Nikolay Sivov nsivov@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); }