[PATCH] mfplat: Add timestamp support for system time source.

Nikolay Sivov nsivov at codeweavers.com
Fri May 24 10:02:36 CDT 2019


Signed-off-by: Nikolay Sivov <nsivov at codeweavers.com>
---
 dlls/mfplat/main.c         |  81 +++++++++++++++-----
 dlls/mfplat/tests/mfplat.c | 152 +++++++++++++++++++++++++++++++++++++
 2 files changed, 216 insertions(+), 17 deletions(-)

diff --git a/dlls/mfplat/main.c b/dlls/mfplat/main.c
index 23f13afa3a..1009f4083b 100644
--- a/dlls/mfplat/main.c
+++ b/dlls/mfplat/main.c
@@ -18,6 +18,7 @@
 
 #include <stdarg.h>
 #include <string.h>
+#include <math.h>
 
 #define COBJMACROS
 #define NONAMELESSUNION
@@ -57,9 +58,20 @@ struct system_time_source
     LONG refcount;
     MFCLOCK_STATE state;
     IMFClock *clock;
+    LONGLONG start_offset;
+    float rate;
+    int i_rate;
     CRITICAL_SECTION cs;
 };
 
+static void system_time_source_apply_rate(const struct system_time_source *source, LONGLONG *value)
+{
+    if (source->i_rate)
+        *value *= source->i_rate;
+    else
+        *value *= source->rate;
+}
+
 static struct system_time_source *impl_from_IMFPresentationTimeSource(IMFPresentationTimeSource *iface)
 {
     return CONTAINING_RECORD(iface, struct system_time_source, IMFPresentationTimeSource_iface);
@@ -6736,11 +6748,26 @@ static HRESULT WINAPI system_time_source_GetClockCharacteristics(IMFPresentation
 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);
+    struct system_time_source *source = impl_from_IMFPresentationTimeSource(iface);
+    HRESULT hr;
 
-    return E_NOTIMPL;
-}
+    TRACE("%p, %#x, %p, %p.\n", iface, reserved, clock_time, system_time);
 
+    EnterCriticalSection(&source->cs);
+    if (SUCCEEDED(hr = IMFClock_GetCorrelatedTime(source->clock, 0, clock_time, system_time)))
+    {
+        if (source->state == MFCLOCK_STATE_RUNNING)
+        {
+            system_time_source_apply_rate(source, clock_time);
+            *clock_time += source->start_offset;
+        }
+        else
+            *clock_time = source->start_offset;
+    }
+    LeaveCriticalSection(&source->cs);
+
+    return hr;
+}
 
 static HRESULT WINAPI system_time_source_GetContinuityKey(IMFPresentationTimeSource *iface, DWORD *key)
 {
@@ -6870,11 +6897,13 @@ static HRESULT WINAPI system_time_source_sink_OnClockStart(IMFClockStateSink *if
     TRACE("%p, %s, %s.\n", iface, wine_dbgstr_longlong(system_time), wine_dbgstr_longlong(start_offset));
 
     EnterCriticalSection(&source->cs);
-    hr = system_time_source_change_state(source, CLOCK_CMD_START);
+    if (SUCCEEDED(hr = system_time_source_change_state(source, CLOCK_CMD_START)))
+    {
+        system_time_source_apply_rate(source, &system_time);
+        source->start_offset = -system_time + start_offset;
+    }
     LeaveCriticalSection(&source->cs);
 
-    /* FIXME: update timestamps */
-
     return hr;
 }
 
@@ -6886,11 +6915,10 @@ static HRESULT WINAPI system_time_source_sink_OnClockStop(IMFClockStateSink *ifa
     TRACE("%p, %s.\n", iface, wine_dbgstr_longlong(system_time));
 
     EnterCriticalSection(&source->cs);
-    hr = system_time_source_change_state(source, CLOCK_CMD_STOP);
+    if (SUCCEEDED(hr = system_time_source_change_state(source, CLOCK_CMD_STOP)))
+        source->start_offset = 0;
     LeaveCriticalSection(&source->cs);
 
-    /* FIXME: update timestamps */
-
     return hr;
 }
 
@@ -6902,11 +6930,13 @@ static HRESULT WINAPI system_time_source_sink_OnClockPause(IMFClockStateSink *if
     TRACE("%p, %s.\n", iface, wine_dbgstr_longlong(system_time));
 
     EnterCriticalSection(&source->cs);
-    hr = system_time_source_change_state(source, CLOCK_CMD_PAUSE);
+    if (SUCCEEDED(hr = system_time_source_change_state(source, CLOCK_CMD_PAUSE)))
+    {
+        system_time_source_apply_rate(source, &system_time);
+        source->start_offset += system_time;
+    }
     LeaveCriticalSection(&source->cs);
 
-    /* FIXME: update timestamps */
-
     return hr;
 }
 
@@ -6918,19 +6948,34 @@ static HRESULT WINAPI system_time_source_sink_OnClockRestart(IMFClockStateSink *
     TRACE("%p, %s.\n", iface, wine_dbgstr_longlong(system_time));
 
     EnterCriticalSection(&source->cs);
-    hr = system_time_source_change_state(source, CLOCK_CMD_RESTART);
+    if (SUCCEEDED(hr = system_time_source_change_state(source, CLOCK_CMD_RESTART)))
+    {
+        system_time_source_apply_rate(source, &system_time);
+        source->start_offset -= system_time;
+    }
     LeaveCriticalSection(&source->cs);
 
-    /* FIXME: update timestamps */
-
     return hr;
 }
 
 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);
+    struct system_time_source *source = impl_from_IMFClockStateSink(iface);
+    double intpart;
 
-    return E_NOTIMPL;
+    TRACE("%p, %s, %f.\n", iface, wine_dbgstr_longlong(system_time), rate);
+
+    if (rate == 0.0f)
+        return MF_E_UNSUPPORTED_RATE;
+
+    modf(rate, &intpart);
+
+    EnterCriticalSection(&source->cs);
+    source->rate = rate;
+    source->i_rate = rate == intpart ? rate : 0;
+    LeaveCriticalSection(&source->cs);
+
+    return S_OK;
 }
 
 static const IMFClockStateSinkVtbl systemtimesourcesinkvtbl =
@@ -6962,6 +7007,8 @@ HRESULT WINAPI MFCreateSystemTimeSource(IMFPresentationTimeSource **time_source)
     object->IMFPresentationTimeSource_iface.lpVtbl = &systemtimesourcevtbl;
     object->IMFClockStateSink_iface.lpVtbl = &systemtimesourcesinkvtbl;
     object->refcount = 1;
+    object->rate = 1.0f;
+    object->i_rate = 1;
     InitializeCriticalSection(&object->cs);
 
     if (FAILED(hr = create_system_clock(&object->clock)))
diff --git a/dlls/mfplat/tests/mfplat.c b/dlls/mfplat/tests/mfplat.c
index e385987f33..295863716b 100644
--- a/dlls/mfplat/tests/mfplat.c
+++ b/dlls/mfplat/tests/mfplat.c
@@ -2675,6 +2675,158 @@ static void test_system_time_source(void)
 
     IMFClock_Release(clock);
 
+    /* Test returned time regarding specified rate and offset.  */
+    hr = IMFPresentationTimeSource_QueryInterface(time_source, &IID_IMFClockStateSink, (void **)&statesink);
+    ok(hr == S_OK, "Failed to get sink interface, hr %#x.\n", hr);
+
+    hr = IMFPresentationTimeSource_GetState(time_source, 0, &state);
+    ok(hr == S_OK, "Failed to get state %#x.\n", hr);
+    ok(state == MFCLOCK_STATE_STOPPED, "Unexpected state %d.\n", state);
+
+    hr = IMFPresentationTimeSource_GetCorrelatedTime(time_source, 0, &time, &systime);
+    ok(hr == S_OK, "Failed to get time %#x.\n", hr);
+    ok(time == 0, "Unexpected time stamp %s, %s.\n", wine_dbgstr_longlong(time), wine_dbgstr_longlong(systime));
+
+    hr = IMFClockStateSink_OnClockStart(statesink, 0, 0);
+    ok(hr == S_OK, "Failed to start source, hr %#x.\n", hr);
+
+    hr = IMFPresentationTimeSource_GetCorrelatedTime(time_source, 0, &time, &systime);
+    ok(hr == S_OK, "Failed to get time %#x.\n", hr);
+    ok(time == systime, "Unexpected time stamp %s, %s.\n", wine_dbgstr_longlong(time), wine_dbgstr_longlong(systime));
+
+    hr = IMFClockStateSink_OnClockStart(statesink, 0, 1);
+    ok(hr == S_OK, "Failed to start source, hr %#x.\n", hr);
+
+    hr = IMFPresentationTimeSource_GetCorrelatedTime(time_source, 0, &time, &systime);
+    ok(hr == S_OK, "Failed to get time %#x.\n", hr);
+    ok(time == systime + 1, "Unexpected time stamp %s, %s.\n", wine_dbgstr_longlong(time),
+            wine_dbgstr_longlong(systime));
+
+    hr = IMFClockStateSink_OnClockPause(statesink, 2);
+    ok(hr == S_OK, "Failed to pause source, hr %#x.\n", hr);
+
+    hr = IMFPresentationTimeSource_GetCorrelatedTime(time_source, 0, &time, &systime);
+    ok(hr == S_OK, "Failed to get time %#x.\n", hr);
+    ok(time == 3, "Unexpected time stamp %s, %s.\n", wine_dbgstr_longlong(time), wine_dbgstr_longlong(systime));
+
+    hr = IMFClockStateSink_OnClockRestart(statesink, 5);
+    ok(hr == S_OK, "Failed to restart source, hr %#x.\n", hr);
+
+    hr = IMFPresentationTimeSource_GetCorrelatedTime(time_source, 0, &time, &systime);
+    ok(hr == S_OK, "Failed to get time %#x.\n", hr);
+    ok(time == systime - 2, "Unexpected time stamp %s, %s.\n", wine_dbgstr_longlong(time),
+            wine_dbgstr_longlong(systime));
+
+    hr = IMFClockStateSink_OnClockPause(statesink, 0);
+    ok(hr == S_OK, "Failed to pause source, hr %#x.\n", hr);
+
+    hr = IMFPresentationTimeSource_GetCorrelatedTime(time_source, 0, &time, &systime);
+    ok(hr == S_OK, "Failed to get time %#x.\n", hr);
+    ok(time == -2, "Unexpected time stamp %s, %s.\n", wine_dbgstr_longlong(time),
+            wine_dbgstr_longlong(systime));
+
+    hr = IMFClockStateSink_OnClockStop(statesink, 123);
+    ok(hr == S_OK, "Failed to stop source, hr %#x.\n", hr);
+
+    hr = IMFPresentationTimeSource_GetCorrelatedTime(time_source, 0, &time, &systime);
+    ok(hr == S_OK, "Failed to get time %#x.\n", hr);
+    ok(time == 0, "Unexpected time stamp %s, %s.\n", wine_dbgstr_longlong(time), wine_dbgstr_longlong(systime));
+
+    /* Increased rate. */
+    hr = IMFClockStateSink_OnClockSetRate(statesink, 0, 2.0f);
+    ok(hr == S_OK, "Failed to set rate, hr %#x.\n", hr);
+
+    hr = IMFClockStateSink_OnClockStart(statesink, 0, 0);
+    ok(hr == S_OK, "Failed to start source, hr %#x.\n", hr);
+
+    hr = IMFPresentationTimeSource_GetCorrelatedTime(time_source, 0, &time, &systime);
+    ok(hr == S_OK, "Failed to get time %#x.\n", hr);
+    ok(time == 2 * systime, "Unexpected time stamp %s, %s.\n", wine_dbgstr_longlong(time),
+            wine_dbgstr_longlong(2 * systime));
+
+    hr = IMFClockStateSink_OnClockStart(statesink, 0, 10);
+    ok(hr == S_OK, "Failed to start source, hr %#x.\n", hr);
+
+    hr = IMFPresentationTimeSource_GetCorrelatedTime(time_source, 0, &time, &systime);
+    ok(hr == S_OK, "Failed to get time %#x.\n", hr);
+    ok(time == 2 * systime + 10, "Unexpected time stamp %s, %s.\n", wine_dbgstr_longlong(time),
+            wine_dbgstr_longlong(2 * systime));
+
+    hr = IMFClockStateSink_OnClockPause(statesink, 2);
+    ok(hr == S_OK, "Failed to pause source, hr %#x.\n", hr);
+
+    hr = IMFPresentationTimeSource_GetCorrelatedTime(time_source, 0, &time, &systime);
+    ok(hr == S_OK, "Failed to get time %#x.\n", hr);
+    ok(time == 10 + 2 * 2, "Unexpected time stamp %s, %s.\n", wine_dbgstr_longlong(time),
+            wine_dbgstr_longlong(systime));
+
+    hr = IMFClockStateSink_OnClockRestart(statesink, 5);
+    ok(hr == S_OK, "Failed to restart source, hr %#x.\n", hr);
+
+    hr = IMFPresentationTimeSource_GetCorrelatedTime(time_source, 0, &time, &systime);
+    ok(hr == S_OK, "Failed to get time %#x.\n", hr);
+    ok(time == 2 * systime + 14 - 5 * 2, "Unexpected time stamp %s, %s.\n", wine_dbgstr_longlong(time),
+            wine_dbgstr_longlong(systime));
+
+    hr = IMFClockStateSink_OnClockPause(statesink, 0);
+    ok(hr == S_OK, "Failed to pause source, hr %#x.\n", hr);
+
+    hr = IMFPresentationTimeSource_GetCorrelatedTime(time_source, 0, &time, &systime);
+    ok(hr == S_OK, "Failed to get time %#x.\n", hr);
+    ok(time == 4, "Unexpected time stamp %s, %s.\n", wine_dbgstr_longlong(time),
+            wine_dbgstr_longlong(systime));
+
+    hr = IMFClockStateSink_OnClockStop(statesink, 123);
+    ok(hr == S_OK, "Failed to stop source, hr %#x.\n", hr);
+
+    hr = IMFPresentationTimeSource_GetCorrelatedTime(time_source, 0, &time, &systime);
+    ok(hr == S_OK, "Failed to get time %#x.\n", hr);
+    ok(time == 0, "Unexpected time stamp %s, %s.\n", wine_dbgstr_longlong(time), wine_dbgstr_longlong(systime));
+    IMFClockStateSink_Release(statesink);
+
+    hr = IMFClockStateSink_OnClockStart(statesink, 10, 0);
+    ok(hr == S_OK, "Failed to start source, hr %#x.\n", hr);
+
+    hr = IMFPresentationTimeSource_GetCorrelatedTime(time_source, 0, &time, &systime);
+    ok(hr == S_OK, "Failed to get time %#x.\n", hr);
+    ok(time == 2 * systime - 2 * 10, "Unexpected time stamp %s, %s.\n", wine_dbgstr_longlong(time),
+            wine_dbgstr_longlong(2 * systime));
+
+    hr = IMFClockStateSink_OnClockStop(statesink, 123);
+    ok(hr == S_OK, "Failed to stop source, hr %#x.\n", hr);
+
+    hr = IMFClockStateSink_OnClockStart(statesink, 10, 20);
+    ok(hr == S_OK, "Failed to start source, hr %#x.\n", hr);
+
+    hr = IMFPresentationTimeSource_GetCorrelatedTime(time_source, 0, &time, &systime);
+    ok(hr == S_OK, "Failed to get time %#x.\n", hr);
+    ok(time == 2 * systime, "Unexpected time stamp %s, %s.\n", wine_dbgstr_longlong(time),
+            wine_dbgstr_longlong(2 * systime));
+
+    hr = IMFClockStateSink_OnClockPause(statesink, 2);
+    ok(hr == S_OK, "Failed to pause source, hr %#x.\n", hr);
+
+    hr = IMFPresentationTimeSource_GetCorrelatedTime(time_source, 0, &time, &systime);
+    ok(hr == S_OK, "Failed to get time %#x.\n", hr);
+    ok(time == 2 * 2, "Unexpected time stamp %s, %s.\n", wine_dbgstr_longlong(time),
+            wine_dbgstr_longlong(systime));
+
+    hr = IMFClockStateSink_OnClockRestart(statesink, 5);
+    ok(hr == S_OK, "Failed to restart source, hr %#x.\n", hr);
+
+    hr = IMFPresentationTimeSource_GetCorrelatedTime(time_source, 0, &time, &systime);
+    ok(hr == S_OK, "Failed to get time %#x.\n", hr);
+    ok(time == 2 * systime + 4 - 5 * 2, "Unexpected time stamp %s, %s.\n", wine_dbgstr_longlong(time),
+            wine_dbgstr_longlong(systime));
+
+    hr = IMFClockStateSink_OnClockPause(statesink, 0);
+    ok(hr == S_OK, "Failed to pause source, hr %#x.\n", hr);
+
+    hr = IMFPresentationTimeSource_GetCorrelatedTime(time_source, 0, &time, &systime);
+    ok(hr == S_OK, "Failed to get time %#x.\n", hr);
+    ok(time == -6, "Unexpected time stamp %s, %s.\n", wine_dbgstr_longlong(time),
+            wine_dbgstr_longlong(systime));
+
     IMFPresentationTimeSource_Release(time_source);
 }
 
-- 
2.20.1




More information about the wine-devel mailing list