[PATCH 1/5] mf: Add a stub for default presentation clock.

Nikolay Sivov nsivov at codeweavers.com
Tue Mar 5 01:49:38 CST 2019


Signed-off-by: Nikolay Sivov <nsivov at codeweavers.com>
---
 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 7ec8e57c1f..2d02ef8fec 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 b576a0f184..2961abe879 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 2d005547b7..9fa0bda839 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 54f09fefdc..be35e6e20f 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 be8795c854..48d7c8e501 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,
-- 
2.20.1




More information about the wine-devel mailing list