diff --git a/dlls/mfplat/main.c b/dlls/mfplat/main.c index 2d7e02e4730..4ce97b1ffd2 100644 --- a/dlls/mfplat/main.c +++ b/dlls/mfplat/main.c @@ -39,6 +39,23 @@ WINE_DEFAULT_DEBUG_CHANNEL(mfplat); static LONG platform_lock; +struct system_time_source +{ + IMFPresentationTimeSource IMFPresentationTimeSource_iface; + IMFClockStateSink IMFClockStateSink_iface; + LONG refcount; +}; + +static struct system_time_source *impl_from_IMFPresentationTimeSource(IMFPresentationTimeSource *iface) +{ + return CONTAINING_RECORD(iface, struct system_time_source, IMFPresentationTimeSource_iface); +} + +static struct system_time_source *impl_from_IMFClockStateSink(IMFClockStateSink *iface) +{ + return CONTAINING_RECORD(iface, struct system_time_source, IMFClockStateSink_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','\\', @@ -3023,3 +3040,201 @@ HRESULT WINAPI MFCreateMFByteStreamOnStreamEx(IUnknown *stream, IMFByteStream ** return E_NOTIMPL; } + +static HRESULT WINAPI system_time_source_QueryInterface(IMFPresentationTimeSource *iface, REFIID riid, void **obj) +{ + struct system_time_source *source = impl_from_IMFPresentationTimeSource(iface); + + TRACE("%p, %s, %p.\n", iface, debugstr_guid(riid), obj); + + if (IsEqualIID(riid, &IID_IMFPresentationTimeSource) || + IsEqualIID(riid, &IID_IUnknown)) + { + *obj = &source->IMFPresentationTimeSource_iface; + } + else if (IsEqualIID(riid, &IID_IMFClockStateSink)) + { + *obj = &source->IMFClockStateSink_iface; + } + else + { + WARN("Unsupported %s.\n", debugstr_guid(riid)); + *obj = NULL; + return E_NOINTERFACE; + } + + IUnknown_AddRef((IUnknown *)*obj); + return S_OK; +} + +static ULONG WINAPI system_time_source_AddRef(IMFPresentationTimeSource *iface) +{ + struct system_time_source *source = impl_from_IMFPresentationTimeSource(iface); + ULONG refcount = InterlockedIncrement(&source->refcount); + + TRACE("%p, refcount %u.\n", iface, refcount); + + return refcount; +} + +static ULONG WINAPI system_time_source_Release(IMFPresentationTimeSource *iface) +{ + struct system_time_source *source = impl_from_IMFPresentationTimeSource(iface); + ULONG refcount = InterlockedDecrement(&source->refcount); + + TRACE("%p, refcount %u.\n", iface, refcount); + + if (!refcount) + heap_free(source); + + return refcount; +} + +static HRESULT WINAPI system_time_source_GetClockCharacteristics(IMFPresentationTimeSource *iface, DWORD *flags) +{ + TRACE("%p, %p.\n", iface, flags); + + *flags = MFCLOCK_CHARACTERISTICS_FLAG_FREQUENCY_10MHZ | MFCLOCK_CHARACTERISTICS_FLAG_IS_SYSTEM_CLOCK; + + return S_OK; +} + +static HRESULT WINAPI system_time_source_GetCorrelatedTime(IMFPresentationTimeSource *iface, DWORD reserved, + LONGLONG *clock_time, MFTIME *system_time) +{ + FIXME("%p, %#x, %p, %p.\n", iface, reserved, clock_time, system_time); + + return E_NOTIMPL; +} + + +static HRESULT WINAPI system_time_source_GetContinuityKey(IMFPresentationTimeSource *iface, DWORD *key) +{ + TRACE("%p, %p.\n", iface, key); + + *key = 0; + + return S_OK; +} + +static HRESULT WINAPI system_time_source_GetState(IMFPresentationTimeSource *iface, DWORD reserved, + MFCLOCK_STATE *state) +{ + FIXME("%p, %#x, %p.\n", iface, reserved, state); + + return E_NOTIMPL; +} + +static HRESULT WINAPI system_time_source_GetProperties(IMFPresentationTimeSource *iface, MFCLOCK_PROPERTIES *props) +{ + FIXME("%p, %p.\n", iface, props); + + return E_NOTIMPL; +} + +static HRESULT WINAPI system_time_source_GetUnderlyingClock(IMFPresentationTimeSource *iface, IMFClock **clock) +{ + FIXME("%p, %p.\n", iface, clock); + + return E_NOTIMPL; +} + +static const IMFPresentationTimeSourceVtbl systemtimesourcevtbl = +{ + system_time_source_QueryInterface, + system_time_source_AddRef, + system_time_source_Release, + system_time_source_GetClockCharacteristics, + system_time_source_GetCorrelatedTime, + system_time_source_GetContinuityKey, + system_time_source_GetState, + system_time_source_GetProperties, + system_time_source_GetUnderlyingClock, +}; + +static HRESULT WINAPI system_time_source_sink_QueryInterface(IMFClockStateSink *iface, REFIID riid, void **out) +{ + struct system_time_source *source = impl_from_IMFClockStateSink(iface); + return IMFPresentationTimeSource_QueryInterface(&source->IMFPresentationTimeSource_iface, riid, out); +} + +static ULONG WINAPI system_time_source_sink_AddRef(IMFClockStateSink *iface) +{ + struct system_time_source *source = impl_from_IMFClockStateSink(iface); + return IMFPresentationTimeSource_AddRef(&source->IMFPresentationTimeSource_iface); +} + +static ULONG WINAPI system_time_source_sink_Release(IMFClockStateSink *iface) +{ + struct system_time_source *source = impl_from_IMFClockStateSink(iface); + return IMFPresentationTimeSource_Release(&source->IMFPresentationTimeSource_iface); +} + +static HRESULT WINAPI system_time_source_sink_OnClockStart(IMFClockStateSink *iface, MFTIME system_time, LONGLONG start_offset) +{ + FIXME("%p, %s, %s.\n", iface, wine_dbgstr_longlong(system_time), wine_dbgstr_longlong(start_offset)); + + return E_NOTIMPL; +} + +static HRESULT WINAPI system_time_source_sink_OnClockStop(IMFClockStateSink *iface, MFTIME system_time) +{ + FIXME("%p, %s.\n", iface, wine_dbgstr_longlong(system_time)); + + return E_NOTIMPL; +} + +static HRESULT WINAPI system_time_source_sink_OnClockPause(IMFClockStateSink *iface, MFTIME system_time) +{ + FIXME("%p, %s.\n", iface, wine_dbgstr_longlong(system_time)); + + return E_NOTIMPL; +} + +static HRESULT WINAPI system_time_source_sink_OnClockRestart(IMFClockStateSink *iface, MFTIME system_time) +{ + FIXME("%p, %s.\n", iface, wine_dbgstr_longlong(system_time)); + + return E_NOTIMPL; +} + +static HRESULT WINAPI system_time_source_sink_OnClockSetRate(IMFClockStateSink *iface, MFTIME system_time, float rate) +{ + FIXME("%p, %s, %f.\n", iface, wine_dbgstr_longlong(system_time), rate); + + return E_NOTIMPL; +} + +static const IMFClockStateSinkVtbl systemtimesourcesinkvtbl = +{ + system_time_source_sink_QueryInterface, + system_time_source_sink_AddRef, + system_time_source_sink_Release, + system_time_source_sink_OnClockStart, + system_time_source_sink_OnClockStop, + system_time_source_sink_OnClockPause, + system_time_source_sink_OnClockRestart, + system_time_source_sink_OnClockSetRate, +}; + +/*********************************************************************** + * MFCreateSystemTimeSource (mfplat.@) + */ +HRESULT WINAPI MFCreateSystemTimeSource(IMFPresentationTimeSource **time_source) +{ + struct system_time_source *object; + + TRACE("%p.\n", time_source); + + object = heap_alloc(sizeof(*object)); + if (!object) + return E_OUTOFMEMORY; + + object->IMFPresentationTimeSource_iface.lpVtbl = &systemtimesourcevtbl; + object->IMFClockStateSink_iface.lpVtbl = &systemtimesourcesinkvtbl; + object->refcount = 1; + + *time_source = &object->IMFPresentationTimeSource_iface; + + return S_OK; +} diff --git a/dlls/mfplat/mfplat.spec b/dlls/mfplat/mfplat.spec index 900efc37804..c47af72ed87 100644 --- a/dlls/mfplat/mfplat.spec +++ b/dlls/mfplat/mfplat.spec @@ -61,7 +61,7 @@ @ stub MFCreateSocketListener @ stdcall MFCreateSourceResolver(ptr) @ stdcall MFCreateStreamDescriptor(long long ptr ptr) -@ stub MFCreateSystemTimeSource +@ stdcall MFCreateSystemTimeSource(ptr) @ stub MFCreateSystemUnderlyingClock @ stub MFCreateTempFile @ stub MFCreateTransformActivate diff --git a/dlls/mfplat/tests/mfplat.c b/dlls/mfplat/tests/mfplat.c index 19ec6ec6d13..cb3f2a9e7d0 100644 --- a/dlls/mfplat/tests/mfplat.c +++ b/dlls/mfplat/tests/mfplat.c @@ -1598,6 +1598,39 @@ static void test_presentation_descriptor(void) IMFMediaType_Release(media_type); } +static void test_system_time_source(void) +{ + IMFPresentationTimeSource *time_source; + IMFClockStateSink *statesink; + MFCLOCK_STATE state; + DWORD value; + HRESULT hr; + + hr = MFCreateSystemTimeSource(&time_source); + ok(hr == S_OK, "Failed to create time source, hr %#x.\n", hr); + + hr = IMFPresentationTimeSource_GetClockCharacteristics(time_source, &value); + ok(hr == S_OK, "Failed to get flags, hr %#x.\n", hr); + ok(value == (MFCLOCK_CHARACTERISTICS_FLAG_FREQUENCY_10MHZ | MFCLOCK_CHARACTERISTICS_FLAG_IS_SYSTEM_CLOCK), + "Unexpected flags %#x.\n", value); + + value = 1; + hr = IMFPresentationTimeSource_GetContinuityKey(time_source, &value); + ok(hr == S_OK, "Unexpected hr %#x.\n", hr); + ok(value == 0, "Unexpected value %u.\n", value); + + hr = IMFPresentationTimeSource_GetState(time_source, 0, &state); +todo_wine { + ok(hr == S_OK, "Failed to get state, hr %#x.\n", hr); + ok(state == MFCLOCK_STATE_INVALID, "Unexpected state %d.\n", state); +} + hr = IMFPresentationTimeSource_QueryInterface(time_source, &IID_IMFClockStateSink, (void **)&statesink); + ok(hr == S_OK, "Failed to get state sink, hr %#x.\n", hr); + IMFClockStateSink_Release(statesink); + + IMFPresentationTimeSource_Release(time_source); +} + START_TEST(mfplat) { CoInitialize(NULL); @@ -1624,6 +1657,7 @@ START_TEST(mfplat) test_periodic_callback(); test_event_queue(); test_presentation_descriptor(); + test_system_time_source(); CoUninitialize(); } diff --git a/include/mfidl.idl b/include/mfidl.idl index 21157ee95de..252099e145a 100644 --- a/include/mfidl.idl +++ b/include/mfidl.idl @@ -57,6 +57,13 @@ typedef struct _MFCLOCK_PROPERTIES DWORD dwClockJitter; } MFCLOCK_PROPERTIES; +typedef enum _MFCLOCK_CHARACTERISTICS_FLAGS +{ + MFCLOCK_CHARACTERISTICS_FLAG_FREQUENCY_10MHZ = 0x00000002, + MFCLOCK_CHARACTERISTICS_FLAG_ALWAYS_RUNNING = 0x00000004, + MFCLOCK_CHARACTERISTICS_FLAG_IS_SYSTEM_CLOCK = 0x00000008, +} MFCLOCK_CHARACTERISTICS_FLAGS; + [ object, uuid(2eb1e945-18b8-4139-9b1a-d5d584818530), @@ -357,6 +364,7 @@ cpp_quote("HRESULT WINAPI MFCreateSequencerSource(IUnknown *reserved, IMFSequenc cpp_quote("HRESULT WINAPI MFCreateSourceResolver(IMFSourceResolver **resolver);") cpp_quote("HRESULT WINAPI MFCreateStreamDescriptor(DWORD identifier, DWORD cMediaTypes,") cpp_quote(" IMFMediaType **types, IMFStreamDescriptor **descriptor);") +cpp_quote("HRESULT WINAPI MFCreateSystemTimeSource(IMFPresentationTimeSource **time_source);") cpp_quote("HRESULT WINAPI MFCreateTopology(IMFTopology **topology);") cpp_quote("HRESULT WINAPI MFCreateTopologyNode(MF_TOPOLOGY_TYPE node_type, IMFTopologyNode **node);") cpp_quote("HRESULT WINAPI MFCreateTopoLoader(IMFTopoLoader **loader);")