From 98a28d1493df33eef61a9865a86c508b962fd9f8 Mon Sep 17 00:00:00 2001 From: Nikolay Sivov Date: Tue, 5 Mar 2019 10:49:38 +0300 Subject: [PATCH] mf: Add a stub for default presentation clock. Signed-off-by: Nikolay Sivov Signed-off-by: Alexandre Julliard --- dlls/mf/mf.spec | 2 +- dlls/mf/session.c | 381 +++++++++++++++++++++++++++++++++++++++++++++ dlls/mf/tests/mf.c | 63 ++++++++ include/mferror.h | 2 + include/mfidl.idl | 58 ++++++- 5 files changed, 504 insertions(+), 2 deletions(-) diff --git a/dlls/mf/mf.spec b/dlls/mf/mf.spec index 7ec8e57c1f6..2d02ef8fec9 100644 --- a/dlls/mf/mf.spec +++ b/dlls/mf/mf.spec @@ -45,7 +45,7 @@ @ stub MFCreatePMPHost @ stub MFCreatePMPMediaSession @ stub MFCreatePMPServer -@ stub MFCreatePresentationClock +@ stdcall MFCreatePresentationClock(ptr) @ stub MFCreatePresentationDescriptorFromASFProfile @ stub MFCreateProxyLocator @ stub MFCreateRemoteDesktopPlugin diff --git a/dlls/mf/session.c b/dlls/mf/session.c index b576a0f184e..2961abe879c 100644 --- a/dlls/mf/session.c +++ b/dlls/mf/session.c @@ -25,6 +25,7 @@ #include "winbase.h" #include "mfidl.h" #include "mfapi.h" +#include "mferror.h" #include "wine/debug.h" #include "wine/heap.h" @@ -38,11 +39,43 @@ struct media_session IMFMediaEventQueue *event_queue; }; +struct presentation_clock +{ + IMFPresentationClock IMFPresentationClock_iface; + IMFRateControl IMFRateControl_iface; + IMFTimer IMFTimer_iface; + IMFShutdown IMFShutdown_iface; + LONG refcount; + IMFPresentationTimeSource *time_source; + MFCLOCK_STATE state; + CRITICAL_SECTION cs; +}; + static inline struct media_session *impl_from_IMFMediaSession(IMFMediaSession *iface) { return CONTAINING_RECORD(iface, struct media_session, IMFMediaSession_iface); } +static struct presentation_clock *impl_from_IMFPresentationClock(IMFPresentationClock *iface) +{ + return CONTAINING_RECORD(iface, struct presentation_clock, IMFPresentationClock_iface); +} + +static struct presentation_clock *impl_from_IMFRateControl(IMFRateControl *iface) +{ + return CONTAINING_RECORD(iface, struct presentation_clock, IMFRateControl_iface); +} + +static struct presentation_clock *impl_from_IMFTimer(IMFTimer *iface) +{ + return CONTAINING_RECORD(iface, struct presentation_clock, IMFTimer_iface); +} + +static struct presentation_clock *impl_from_IMFShutdown(IMFShutdown *iface) +{ + return CONTAINING_RECORD(iface, struct presentation_clock, IMFShutdown_iface); +} + static HRESULT WINAPI mfsession_QueryInterface(IMFMediaSession *iface, REFIID riid, void **out) { struct media_session *session = impl_from_IMFMediaSession(iface); @@ -251,3 +284,351 @@ HRESULT WINAPI MFCreateMediaSession(IMFAttributes *config, IMFMediaSession **ses return S_OK; } + +static HRESULT WINAPI present_clock_QueryInterface(IMFPresentationClock *iface, REFIID riid, void **out) +{ + struct presentation_clock *clock = impl_from_IMFPresentationClock(iface); + + TRACE("%p, %s, %p.\n", iface, debugstr_guid(riid), out); + + if (IsEqualIID(riid, &IID_IMFPresentationClock) || + IsEqualIID(riid, &IID_IMFClock) || + IsEqualIID(riid, &IID_IUnknown)) + { + *out = &clock->IMFPresentationClock_iface; + } + else if (IsEqualIID(riid, &IID_IMFRateControl)) + { + *out = &clock->IMFRateControl_iface; + } + else if (IsEqualIID(riid, &IID_IMFTimer)) + { + *out = &clock->IMFTimer_iface; + } + else if (IsEqualIID(riid, &IID_IMFShutdown)) + { + *out = &clock->IMFShutdown_iface; + } + else + { + WARN("Unsupported %s.\n", debugstr_guid(riid)); + *out = NULL; + return E_NOINTERFACE; + } + + IUnknown_AddRef((IUnknown *)*out); + return S_OK; +} + +static ULONG WINAPI present_clock_AddRef(IMFPresentationClock *iface) +{ + struct presentation_clock *clock = impl_from_IMFPresentationClock(iface); + ULONG refcount = InterlockedIncrement(&clock->refcount); + + TRACE("%p, refcount %u.\n", iface, refcount); + + return refcount; +} + +static ULONG WINAPI present_clock_Release(IMFPresentationClock *iface) +{ + struct presentation_clock *clock = impl_from_IMFPresentationClock(iface); + ULONG refcount = InterlockedDecrement(&clock->refcount); + + TRACE("%p, refcount %u.\n", iface, refcount); + + if (!refcount) + { + if (clock->time_source) + IMFPresentationTimeSource_Release(clock->time_source); + DeleteCriticalSection(&clock->cs); + heap_free(clock); + } + + return refcount; +} + +static HRESULT WINAPI present_clock_GetClockCharacteristics(IMFPresentationClock *iface, DWORD *flags) +{ + FIXME("%p, %p.\n", iface, flags); + + return E_NOTIMPL; +} + +static HRESULT WINAPI present_clock_GetCorrelatedTime(IMFPresentationClock *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 present_clock_GetContinuityKey(IMFPresentationClock *iface, DWORD *key) +{ + TRACE("%p, %p.\n", iface, key); + + *key = 0; + + return S_OK; +} + +static HRESULT WINAPI present_clock_GetState(IMFPresentationClock *iface, DWORD reserved, MFCLOCK_STATE *state) +{ + struct presentation_clock *clock = impl_from_IMFPresentationClock(iface); + + TRACE("%p, %#x, %p.\n", iface, reserved, state); + + EnterCriticalSection(&clock->cs); + *state = clock->state; + LeaveCriticalSection(&clock->cs); + + return S_OK; +} + +static HRESULT WINAPI present_clock_GetProperties(IMFPresentationClock *iface, MFCLOCK_PROPERTIES *props) +{ + FIXME("%p, %p.\n", iface, props); + + return E_NOTIMPL; +} + +static HRESULT WINAPI present_clock_SetTimeSource(IMFPresentationClock *iface, + IMFPresentationTimeSource *time_source) +{ + FIXME("%p, %p.\n", iface, time_source); + + return E_NOTIMPL; +} + +static HRESULT WINAPI present_clock_GetTimeSource(IMFPresentationClock *iface, + IMFPresentationTimeSource **time_source) +{ + struct presentation_clock *clock = impl_from_IMFPresentationClock(iface); + HRESULT hr = S_OK; + + TRACE("%p, %p.\n", iface, time_source); + + EnterCriticalSection(&clock->cs); + if (clock->time_source) + { + *time_source = clock->time_source; + IMFPresentationTimeSource_AddRef(*time_source); + } + else + hr = MF_E_CLOCK_NO_TIME_SOURCE; + LeaveCriticalSection(&clock->cs); + + return hr; +} + +static HRESULT WINAPI present_clock_GetTime(IMFPresentationClock *iface, MFTIME *time) +{ + FIXME("%p, %p.\n", iface, time); + + return E_NOTIMPL; +} + +static HRESULT WINAPI present_clock_AddClockStateSink(IMFPresentationClock *iface, IMFClockStateSink *state_sink) +{ + FIXME("%p, %p.\n", iface, state_sink); + + return E_NOTIMPL; +} + +static HRESULT WINAPI present_clock_RemoveClockStateSink(IMFPresentationClock *iface, + IMFClockStateSink *state_sink) +{ + FIXME("%p, %p.\n", iface, state_sink); + + return E_NOTIMPL; +} + +static HRESULT WINAPI present_clock_Start(IMFPresentationClock *iface, LONGLONG start_offset) +{ + FIXME("%p, %s.\n", iface, wine_dbgstr_longlong(start_offset)); + + return E_NOTIMPL; +} + +static HRESULT WINAPI present_clock_Stop(IMFPresentationClock *iface) +{ + FIXME("%p.\n", iface); + + return E_NOTIMPL; +} + +static HRESULT WINAPI present_clock_Pause(IMFPresentationClock *iface) +{ + FIXME("%p.\n", iface); + + return E_NOTIMPL; +} + +static const IMFPresentationClockVtbl presentationclockvtbl = +{ + present_clock_QueryInterface, + present_clock_AddRef, + present_clock_Release, + present_clock_GetClockCharacteristics, + present_clock_GetCorrelatedTime, + present_clock_GetContinuityKey, + present_clock_GetState, + present_clock_GetProperties, + present_clock_SetTimeSource, + present_clock_GetTimeSource, + present_clock_GetTime, + present_clock_AddClockStateSink, + present_clock_RemoveClockStateSink, + present_clock_Start, + present_clock_Stop, + present_clock_Pause, +}; + +static HRESULT WINAPI present_clock_rate_control_QueryInterface(IMFRateControl *iface, REFIID riid, void **out) +{ + struct presentation_clock *clock = impl_from_IMFRateControl(iface); + return IMFPresentationClock_QueryInterface(&clock->IMFPresentationClock_iface, riid, out); +} + +static ULONG WINAPI present_clock_rate_control_AddRef(IMFRateControl *iface) +{ + struct presentation_clock *clock = impl_from_IMFRateControl(iface); + return IMFPresentationClock_AddRef(&clock->IMFPresentationClock_iface); +} + +static ULONG WINAPI present_clock_rate_control_Release(IMFRateControl *iface) +{ + struct presentation_clock *clock = impl_from_IMFRateControl(iface); + return IMFPresentationClock_Release(&clock->IMFPresentationClock_iface); +} + +static HRESULT WINAPI present_clock_rate_SetRate(IMFRateControl *iface, BOOL thin, float rate) +{ + FIXME("%p, %d, %f.\n", iface, thin, rate); + + return E_NOTIMPL; +} + +static HRESULT WINAPI present_clock_rate_GetRate(IMFRateControl *iface, BOOL *thin, float *rate) +{ + FIXME("%p, %p, %p.\n", iface, thin, rate); + + return E_NOTIMPL; +} + +static const IMFRateControlVtbl presentclockratecontrolvtbl = +{ + present_clock_rate_control_QueryInterface, + present_clock_rate_control_AddRef, + present_clock_rate_control_Release, + present_clock_rate_SetRate, + present_clock_rate_GetRate, +}; + +static HRESULT WINAPI present_clock_timer_QueryInterface(IMFTimer *iface, REFIID riid, void **out) +{ + struct presentation_clock *clock = impl_from_IMFTimer(iface); + return IMFPresentationClock_QueryInterface(&clock->IMFPresentationClock_iface, riid, out); +} + +static ULONG WINAPI present_clock_timer_AddRef(IMFTimer *iface) +{ + struct presentation_clock *clock = impl_from_IMFTimer(iface); + return IMFPresentationClock_AddRef(&clock->IMFPresentationClock_iface); +} + +static ULONG WINAPI present_clock_timer_Release(IMFTimer *iface) +{ + struct presentation_clock *clock = impl_from_IMFTimer(iface); + return IMFPresentationClock_Release(&clock->IMFPresentationClock_iface); +} + +static HRESULT WINAPI present_clock_timer_SetTimer(IMFTimer *iface, DWORD flags, LONGLONG time, + IMFAsyncCallback *callback, IUnknown *state, IUnknown **cancel_key) +{ + FIXME("%p, %#x, %s, %p, %p, %p.\n", iface, flags, wine_dbgstr_longlong(time), callback, state, cancel_key); + + return E_NOTIMPL; +} + +static HRESULT WINAPI present_clock_timer_CancelTimer(IMFTimer *iface, IUnknown *cancel_key) +{ + FIXME("%p, %p.\n", iface, cancel_key); + + return E_NOTIMPL; +} + +static const IMFTimerVtbl presentclocktimervtbl = +{ + present_clock_timer_QueryInterface, + present_clock_timer_AddRef, + present_clock_timer_Release, + present_clock_timer_SetTimer, + present_clock_timer_CancelTimer, +}; + +static HRESULT WINAPI present_clock_shutdown_QueryInterface(IMFShutdown *iface, REFIID riid, void **out) +{ + struct presentation_clock *clock = impl_from_IMFShutdown(iface); + return IMFPresentationClock_QueryInterface(&clock->IMFPresentationClock_iface, riid, out); +} + +static ULONG WINAPI present_clock_shutdown_AddRef(IMFShutdown *iface) +{ + struct presentation_clock *clock = impl_from_IMFShutdown(iface); + return IMFPresentationClock_AddRef(&clock->IMFPresentationClock_iface); +} + +static ULONG WINAPI present_clock_shutdown_Release(IMFShutdown *iface) +{ + struct presentation_clock *clock = impl_from_IMFShutdown(iface); + return IMFPresentationClock_Release(&clock->IMFPresentationClock_iface); +} + +static HRESULT WINAPI present_clock_shutdown_Shutdown(IMFShutdown *iface) +{ + FIXME("%p.\n", iface); + + return E_NOTIMPL; +} + +static HRESULT WINAPI present_clock_shutdown_GetShutdownStatus(IMFShutdown *iface, MFSHUTDOWN_STATUS *status) +{ + FIXME("%p, %p.\n", iface, status); + + return E_NOTIMPL; +} + +static const IMFShutdownVtbl presentclockshutdownvtbl = +{ + present_clock_shutdown_QueryInterface, + present_clock_shutdown_AddRef, + present_clock_shutdown_Release, + present_clock_shutdown_Shutdown, + present_clock_shutdown_GetShutdownStatus, +}; + +/*********************************************************************** + * MFCreatePresentationClock (mf.@) + */ +HRESULT WINAPI MFCreatePresentationClock(IMFPresentationClock **clock) +{ + struct presentation_clock *object; + + TRACE("%p.\n", clock); + + object = heap_alloc_zero(sizeof(*object)); + if (!object) + return E_OUTOFMEMORY; + + object->IMFPresentationClock_iface.lpVtbl = &presentationclockvtbl; + object->IMFRateControl_iface.lpVtbl = &presentclockratecontrolvtbl; + object->IMFTimer_iface.lpVtbl = &presentclocktimervtbl; + object->IMFShutdown_iface.lpVtbl = &presentclockshutdownvtbl; + object->refcount = 1; + InitializeCriticalSection(&object->cs); + + *clock = &object->IMFPresentationClock_iface; + + return S_OK; +} diff --git a/dlls/mf/tests/mf.c b/dlls/mf/tests/mf.c index 2d005547b7a..9fa0bda8399 100644 --- a/dlls/mf/tests/mf.c +++ b/dlls/mf/tests/mf.c @@ -735,6 +735,68 @@ static void test_MFShutdownObject(void) ok(hr == S_OK, "Failed to shut down, hr %#x.\n", hr); } +static void test_presentation_clock(void) +{ + IMFPresentationTimeSource *time_source; + IMFRateControl *rate_control; + IMFPresentationClock *clock; + MFCLOCK_PROPERTIES props; + IMFShutdown *shutdown; + LONGLONG clock_time; + MFCLOCK_STATE state; + IMFTimer *timer; + MFTIME systime; + DWORD value; + HRESULT hr; + + hr = MFStartup(MF_VERSION, MFSTARTUP_FULL); + ok(hr == S_OK, "Failed to start up, hr %#x.\n", hr); + + hr = MFCreatePresentationClock(&clock); + ok(hr == S_OK, "Failed to create presentation clock, hr %#x.\n", hr); + + hr = IMFPresentationClock_GetTimeSource(clock, &time_source); + ok(hr == MF_E_CLOCK_NO_TIME_SOURCE, "Unexpected hr %#x.\n", hr); + + hr = IMFPresentationClock_GetClockCharacteristics(clock, &value); +todo_wine + ok(hr == MF_E_CLOCK_NO_TIME_SOURCE, "Unexpected hr %#x.\n", hr); + + value = 1; + hr = IMFPresentationClock_GetContinuityKey(clock, &value); + ok(hr == S_OK, "Unexpected hr %#x.\n", hr); + ok(value == 0, "Unexpected value %u.\n", value); + + hr = IMFPresentationClock_GetProperties(clock, &props); +todo_wine + ok(hr == MF_E_CLOCK_NO_TIME_SOURCE, "Unexpected hr %#x.\n", hr); + + hr = IMFPresentationClock_GetState(clock, 0, &state); + ok(hr == S_OK, "Failed to get state, hr %#x.\n", hr); + ok(state == MFCLOCK_STATE_INVALID, "Unexpected state %d.\n", state); + + hr = IMFPresentationClock_GetCorrelatedTime(clock, 0, &clock_time, &systime); +todo_wine + ok(hr == MF_E_CLOCK_NO_TIME_SOURCE, "Unexpected hr %#x.\n", hr); + + hr = IMFPresentationClock_QueryInterface(clock, &IID_IMFRateControl, (void **)&rate_control); + ok(hr == S_OK, "Failed to get rate control interface, hr %#x.\n", hr); + IMFRateControl_Release(rate_control); + + hr = IMFPresentationClock_QueryInterface(clock, &IID_IMFTimer, (void **)&timer); + ok(hr == S_OK, "Failed to get timer interface, hr %#x.\n", hr); + IMFTimer_Release(timer); + + hr = IMFPresentationClock_QueryInterface(clock, &IID_IMFShutdown, (void **)&shutdown); + ok(hr == S_OK, "Failed to get shutdown interface, hr %#x.\n", hr); + IMFShutdown_Release(shutdown); + + IMFPresentationClock_Release(clock); + + hr = MFShutdown(); + ok(hr == S_OK, "Failed to shut down, hr %#x.\n", hr); +} + START_TEST(mf) { test_topology(); @@ -743,4 +805,5 @@ START_TEST(mf) test_MFCreateSequencerSource(); test_media_session(); test_MFShutdownObject(); + test_presentation_clock(); } diff --git a/include/mferror.h b/include/mferror.h index 54f09fefdcc..be35e6e20fd 100644 --- a/include/mferror.h +++ b/include/mferror.h @@ -82,4 +82,6 @@ #define MF_E_TOPO_MISSING_SOURCE _HRESULT_TYPEDEF_(0xc00d521a) #define MF_E_TOPO_SINK_ACTIVATES_UNSUPPORTED _HRESULT_TYPEDEF_(0xc00d521b) +#define MF_E_CLOCK_NO_TIME_SOURCE _HRESULT_TYPEDEF_(0xc00d9c41) + #endif /* __WINE_MFERROR_H */ diff --git a/include/mfidl.idl b/include/mfidl.idl index be8795c8548..48d7c8e5016 100644 --- a/include/mfidl.idl +++ b/include/mfidl.idl @@ -70,6 +70,37 @@ interface IMFClock : IUnknown HRESULT GetProperties([out] MFCLOCK_PROPERTIES *props); } +[ + object, + uuid(88ddcd21-03c3-4275-91ed-55ee3929328f) +] +interface IMFRateControl : IUnknown +{ + HRESULT SetRate( + [in] BOOL thin, + [in] float rate); + HRESULT GetRate( + [in, out, unique] BOOL *thin, + [in, out, unique] float *rate); +} + +[ + object, + uuid(e56e4cbd-8f70-49d8-a0f8-edb3d6ab9bf2), + local +] +interface IMFTimer : IUnknown +{ + HRESULT SetTimer( + [in] DWORD flags, + [in] LONGLONG time, + [in] IMFAsyncCallback *callback, + [in] IUnknown *state, + [out] IUnknown **key); + HRESULT CancelTimer( + [in] IUnknown *key); +} + [ object, uuid(83cf873a-f6da-4bc8-823f-bacfd55dc430), @@ -319,6 +350,7 @@ interface IMFSequencerSource : IUnknown cpp_quote("HRESULT WINAPI MFCreateMediaSession(IMFAttributes *config, IMFMediaSession **session);") cpp_quote("HRESULT WINAPI MFCreateMFByteStreamOnStream(IStream *stream, IMFByteStream **bytestream);" ) cpp_quote("HRESULT WINAPI MFCreateMFByteStreamOnStreamEx(IUnknown *stream, IMFByteStream **bytestream);") +cpp_quote("HRESULT WINAPI MFCreatePresentationClock(IMFPresentationClock **clock);") cpp_quote("HRESULT WINAPI MFCreateSequencerSource(IUnknown *reserved, IMFSequencerSource **seq_source);" ) cpp_quote("HRESULT WINAPI MFCreateSourceResolver(IMFSourceResolver **resolver);") cpp_quote("HRESULT WINAPI MFCreateStreamDescriptor(DWORD identifier, DWORD cMediaTypes,") @@ -360,7 +392,31 @@ interface IMFMediaSource : IMFMediaEventGenerator } interface IMFStreamSink; -interface IMFPresentationClock; + +[ + object, + uuid(7ff12cce-f76f-41c2-863b-1666c8e5e139) +] +interface IMFPresentationTimeSource : IMFClock +{ + HRESULT GetUnderlyingClock([out] IMFClock **clock); +} + +[ + object, + uuid(868ce85c-8ea9-4f55-ab82-b009a910a805) +] +interface IMFPresentationClock : IMFClock +{ + HRESULT SetTimeSource([in] IMFPresentationTimeSource *time_source); + HRESULT GetTimeSource([out] IMFPresentationTimeSource **time_source); + HRESULT GetTime([out] MFTIME *time); + HRESULT AddClockStateSink([in] IMFClockStateSink *state_sink); + HRESULT RemoveClockStateSink([in] IMFClockStateSink *state_sink); + HRESULT Start([in] LONGLONG start_offset); + HRESULT Stop(); + HRESULT Pause(); +} [ object,