Nikolay Sivov : mfplat: Fix playback rate handling in system time source.

Alexandre Julliard julliard at winehq.org
Thu Feb 17 15:33:59 CST 2022


Module: wine
Branch: master
Commit: 6971e7e021f03c119f806b386adbdfce002686a2
URL:    https://source.winehq.org/git/wine.git/?a=commit;h=6971e7e021f03c119f806b386adbdfce002686a2

Author: Nikolay Sivov <nsivov at codeweavers.com>
Date:   Thu Feb 17 12:15:28 2022 +0300

mfplat: Fix playback rate handling in system time source.

Signed-off-by: Nikolay Sivov <nsivov at codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard at winehq.org>

---

 dlls/mfplat/main.c         | 49 ++++++++++++++++++++--------------------------
 dlls/mfplat/tests/mfplat.c | 25 +++++++++++++++++++++++
 2 files changed, 46 insertions(+), 28 deletions(-)

diff --git a/dlls/mfplat/main.c b/dlls/mfplat/main.c
index 1992776595d..7991152f7a7 100644
--- a/dlls/mfplat/main.c
+++ b/dlls/mfplat/main.c
@@ -124,17 +124,20 @@ struct system_time_source
     MFCLOCK_STATE state;
     IMFClock *clock;
     LONGLONG start_offset;
+    LONGLONG system_time;
+    LONGLONG clock_time;
     float rate;
     int i_rate;
     CRITICAL_SECTION cs;
 };
 
-static void system_time_source_apply_rate(const struct system_time_source *source, LONGLONG *value)
+static void system_time_source_update_clock_time(struct system_time_source *source, LONGLONG system_time)
 {
-    if (source->i_rate)
-        *value *= source->i_rate;
-    else
-        *value *= source->rate;
+    LONGLONG diff = system_time - source->system_time;
+    if (source->i_rate) diff *= source->i_rate;
+    else if (source->rate != 1.0f) diff *= source->rate;
+    source->clock_time += diff;
+    source->system_time = system_time;
 }
 
 static struct system_time_source *impl_from_IMFPresentationTimeSource(IMFPresentationTimeSource *iface)
@@ -8076,12 +8079,8 @@ static HRESULT WINAPI system_time_source_GetCorrelatedTime(IMFPresentationTimeSo
     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;
+            system_time_source_update_clock_time(source, *system_time);
+        *clock_time = source->start_offset + source->clock_time;
     }
     LeaveCriticalSection(&source->cs);
 
@@ -8220,25 +8219,19 @@ static HRESULT WINAPI system_time_source_sink_OnClockStart(IMFClockStateSink *if
     state = source->state;
     if (SUCCEEDED(hr = system_time_source_change_state(source, CLOCK_CMD_START)))
     {
-        system_time_source_apply_rate(source, &system_time);
         if (start_offset == PRESENTATION_CURRENT_POSITION)
         {
-            switch (state)
+            if (state != MFCLOCK_STATE_RUNNING)
             {
-                case MFCLOCK_STATE_RUNNING:
-                    break;
-                case MFCLOCK_STATE_PAUSED:
-                    source->start_offset -= system_time;
-                    break;
-                default:
-                    source->start_offset = -system_time;
-                    break;
-                    ;
+                source->start_offset -= system_time;
+                source->system_time = 0;
             }
         }
         else
         {
-            source->start_offset = -system_time + start_offset;
+            source->start_offset = start_offset;
+            source->system_time = system_time;
+            source->clock_time = 0;
         }
     }
     LeaveCriticalSection(&source->cs);
@@ -8255,7 +8248,9 @@ static HRESULT WINAPI system_time_source_sink_OnClockStop(IMFClockStateSink *ifa
 
     EnterCriticalSection(&source->cs);
     if (SUCCEEDED(hr = system_time_source_change_state(source, CLOCK_CMD_STOP)))
-        source->start_offset = 0;
+    {
+        source->start_offset = source->system_time = source->clock_time = 0;
+    }
     LeaveCriticalSection(&source->cs);
 
     return hr;
@@ -8271,8 +8266,7 @@ static HRESULT WINAPI system_time_source_sink_OnClockPause(IMFClockStateSink *if
     EnterCriticalSection(&source->cs);
     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;
+        system_time_source_update_clock_time(source, system_time);
     }
     LeaveCriticalSection(&source->cs);
 
@@ -8289,8 +8283,7 @@ static HRESULT WINAPI system_time_source_sink_OnClockRestart(IMFClockStateSink *
     EnterCriticalSection(&source->cs);
     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;
+        source->system_time = system_time;
     }
     LeaveCriticalSection(&source->cs);
 
diff --git a/dlls/mfplat/tests/mfplat.c b/dlls/mfplat/tests/mfplat.c
index c013b7b5c23..91c9d971a3b 100644
--- a/dlls/mfplat/tests/mfplat.c
+++ b/dlls/mfplat/tests/mfplat.c
@@ -3641,6 +3641,31 @@ static void test_system_time_source(void)
     hr = IMFClockStateSink_OnClockStart(statesink, 0, 0);
     ok(hr == S_OK, "Failed to start source, hr %#x.\n", hr);
 
+    hr = IMFClockStateSink_OnClockSetRate(statesink, 5, 2.0f);
+    ok(hr == S_OK, "Failed to set rate, hr %#x.\n", hr);
+
+    hr = IMFClockStateSink_OnClockPause(statesink, 6);
+    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 == 12 && !!systime, "Unexpected time stamp %s, %s.\n", wine_dbgstr_longlong(time),
+            wine_dbgstr_longlong(systime));
+
+    hr = IMFClockStateSink_OnClockRestart(statesink, 7);
+    ok(hr == S_OK, "Failed to restart source, hr %#x.\n", hr);
+
+    hr = IMFClockStateSink_OnClockPause(statesink, 8);
+    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 == 14 && !!systime, "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 == 2 * systime, "Unexpected time stamp %s, %s.\n", wine_dbgstr_longlong(time),




More information about the wine-cvs mailing list