Zebediah Figura : winegstreamer: Implement IWMReaderAdvanced::SetUserProvidedClock().

Alexandre Julliard julliard at winehq.org
Fri Nov 5 17:15:52 CDT 2021


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

Author: Zebediah Figura <zfigura at codeweavers.com>
Date:   Thu Nov  4 15:46:28 2021 -0500

winegstreamer: Implement IWMReaderAdvanced::SetUserProvidedClock().

Signed-off-by: Zebediah Figura <zfigura at codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard at winehq.org>

---

 dlls/winegstreamer/wm_asyncreader.c | 67 ++++++++++++++++++++++++++++---------
 dlls/wmvcore/tests/wmvcore.c        | 47 ++++++++++++--------------
 2 files changed, 74 insertions(+), 40 deletions(-)

diff --git a/dlls/winegstreamer/wm_asyncreader.c b/dlls/winegstreamer/wm_asyncreader.c
index d4bd8914dd6..4193d7d75de 100644
--- a/dlls/winegstreamer/wm_asyncreader.c
+++ b/dlls/winegstreamer/wm_asyncreader.c
@@ -41,6 +41,9 @@ struct async_reader
     CONDITION_VARIABLE stream_cv;
 
     bool running;
+
+    bool user_clock;
+    QWORD user_time;
 };
 
 static REFERENCE_TIME get_current_time(const struct async_reader *reader)
@@ -85,22 +88,35 @@ static DWORD WINAPI stream_thread(void *arg)
             hr = wm_reader_get_stream_sample(&reader->reader.streams[i], &sample, &pts, &duration, &flags);
             if (hr == S_OK)
             {
-                for (;;)
+                if (reader->user_clock)
                 {
-                    REFERENCE_TIME current_time = get_current_time(reader);
-
-                    if (pts <= current_time - start_time)
-                        break;
-
-                    SleepConditionVariableCS(&reader->stream_cv, &reader->stream_cs,
-                            (pts - (current_time - start_time)) / 10000);
-
+                    while (pts > reader->user_time && reader->running)
+                        SleepConditionVariableCS(&reader->stream_cv, &reader->stream_cs, INFINITE);
                     if (!reader->running)
                     {
                         INSSBuffer_Release(sample);
                         goto out;
                     }
                 }
+                else
+                {
+                    for (;;)
+                    {
+                        REFERENCE_TIME current_time = get_current_time(reader);
+
+                        if (pts <= current_time - start_time)
+                            break;
+
+                        SleepConditionVariableCS(&reader->stream_cv, &reader->stream_cs,
+                                (pts - (current_time - start_time)) / 10000);
+
+                        if (!reader->running)
+                        {
+                            INSSBuffer_Release(sample);
+                            goto out;
+                        }
+                    }
+                }
 
                 IWMReaderCallback_OnSample(callback, i, pts, duration, flags, sample, reader->context);
                 INSSBuffer_Release(sample);
@@ -276,6 +292,7 @@ static HRESULT WINAPI WMReader_Start(IWMReader *iface,
     wm_reader_seek(&reader->reader, start, duration);
 
     reader->running = true;
+    reader->user_time = 0;
 
     if (!(reader->stream_thread = CreateThread(NULL, 0, stream_thread, reader, 0, NULL)))
     {
@@ -360,9 +377,14 @@ static ULONG WINAPI WMReaderAdvanced_Release(IWMReaderAdvanced6 *iface)
 
 static HRESULT WINAPI WMReaderAdvanced_SetUserProvidedClock(IWMReaderAdvanced6 *iface, BOOL user_clock)
 {
-    struct async_reader *This = impl_from_IWMReaderAdvanced6(iface);
-    FIXME("(%p)->(%x)\n", This, user_clock);
-    return E_NOTIMPL;
+    struct async_reader *reader = impl_from_IWMReaderAdvanced6(iface);
+
+    TRACE("reader %p, user_clock %d.\n", reader, user_clock);
+
+    EnterCriticalSection(&reader->stream_cs);
+    reader->user_clock = !!user_clock;
+    LeaveCriticalSection(&reader->stream_cs);
+    return S_OK;
 }
 
 static HRESULT WINAPI WMReaderAdvanced_GetUserProvidedClock(IWMReaderAdvanced6 *iface, BOOL *user_clock)
@@ -374,9 +396,24 @@ static HRESULT WINAPI WMReaderAdvanced_GetUserProvidedClock(IWMReaderAdvanced6 *
 
 static HRESULT WINAPI WMReaderAdvanced_DeliverTime(IWMReaderAdvanced6 *iface, QWORD time)
 {
-    struct async_reader *This = impl_from_IWMReaderAdvanced6(iface);
-    FIXME("(%p)->(%s)\n", This, wine_dbgstr_longlong(time));
-    return E_NOTIMPL;
+    struct async_reader *reader = impl_from_IWMReaderAdvanced6(iface);
+
+    TRACE("reader %p, time %s.\n", reader, debugstr_time(time));
+
+    EnterCriticalSection(&reader->stream_cs);
+
+    if (!reader->user_clock)
+    {
+        LeaveCriticalSection(&reader->stream_cs);
+        WARN("Not using a user-provided clock; returning E_UNEXPECTED.\n");
+        return E_UNEXPECTED;
+    }
+
+    reader->user_time = time;
+
+    LeaveCriticalSection(&reader->stream_cs);
+    WakeConditionVariable(&reader->stream_cv);
+    return S_OK;
 }
 
 static HRESULT WINAPI WMReaderAdvanced_SetManualStreamSelection(IWMReaderAdvanced6 *iface, BOOL selection)
diff --git a/dlls/wmvcore/tests/wmvcore.c b/dlls/wmvcore/tests/wmvcore.c
index 4cc285c2c73..0e7c6380c92 100644
--- a/dlls/wmvcore/tests/wmvcore.c
+++ b/dlls/wmvcore/tests/wmvcore.c
@@ -1288,38 +1288,35 @@ static void test_async_reader_streaming(void)
      * according to their presentation time. Call DeliverTime with the file
      * duration in order to request all samples as fast as possible. */
     hr = IWMReaderAdvanced2_DeliverTime(advanced, 3000 * 10000);
-    todo_wine ok(hr == E_UNEXPECTED, "Got hr %#x.\n", hr);
+    ok(hr == E_UNEXPECTED, "Got hr %#x.\n", hr);
     hr = IWMReaderAdvanced2_SetUserProvidedClock(advanced, TRUE);
-    todo_wine ok(hr == S_OK, "Got hr %#x.\n", hr);
-    if (hr == S_OK)
-    {
-        hr = IWMReaderAdvanced2_DeliverTime(advanced, 3000 * 10000);
-        ok(hr == S_OK, "Got hr %#x.\n", hr);
+    ok(hr == S_OK, "Got hr %#x.\n", hr);
+    hr = IWMReaderAdvanced2_DeliverTime(advanced, 3000 * 10000);
+    ok(hr == S_OK, "Got hr %#x.\n", hr);
 
-        ret = WaitForSingleObject(callback.eof_event, 1000);
-        ok(!ret, "Wait timed out.\n");
-        ok(callback.got_eof == 1, "Got %u WMT_EOF callbacks.\n", callback.got_eof);
+    ret = WaitForSingleObject(callback.eof_event, 1000);
+    ok(!ret, "Wait timed out.\n");
+    ok(callback.got_eof == 1, "Got %u WMT_EOF callbacks.\n", callback.got_eof);
 
-        hr = IWMReader_Start(reader, 0, 0, 1.0f, (void *)0xfacade);
-        ok(hr == S_OK, "Got hr %#x.\n", hr);
+    hr = IWMReader_Start(reader, 0, 0, 1.0f, (void *)0xfacade);
+    ok(hr == S_OK, "Got hr %#x.\n", hr);
 
-        hr = IWMReaderAdvanced2_DeliverTime(advanced, 3000 * 10000);
-        ok(hr == S_OK, "Got hr %#x.\n", hr);
+    hr = IWMReaderAdvanced2_DeliverTime(advanced, 3000 * 10000);
+    ok(hr == S_OK, "Got hr %#x.\n", hr);
 
-        ret = WaitForSingleObject(callback.eof_event, 1000);
-        ok(!ret, "Wait timed out.\n");
-        ok(callback.got_eof == 1, "Got %u WMT_EOF callbacks.\n", callback.got_eof);
+    ret = WaitForSingleObject(callback.eof_event, 1000);
+    ok(!ret, "Wait timed out.\n");
+    ok(callback.got_eof == 1, "Got %u WMT_EOF callbacks.\n", callback.got_eof);
 
-        hr = IWMReader_Stop(reader);
-        ok(hr == S_OK, "Got hr %#x.\n", hr);
-        ret = WaitForSingleObject(callback.got_stopped, 1000);
-        ok(!ret, "Wait timed out.\n");
+    hr = IWMReader_Stop(reader);
+    ok(hr == S_OK, "Got hr %#x.\n", hr);
+    ret = WaitForSingleObject(callback.got_stopped, 1000);
+    ok(!ret, "Wait timed out.\n");
 
-        hr = IWMReader_Stop(reader);
-        ok(hr == S_OK, "Got hr %#x.\n", hr);
-        ret = WaitForSingleObject(callback.got_stopped, 1000);
-        ok(!ret, "Wait timed out.\n");
-    }
+    hr = IWMReader_Stop(reader);
+    ok(hr == S_OK, "Got hr %#x.\n", hr);
+    ret = WaitForSingleObject(callback.got_stopped, 1000);
+    ok(!ret, "Wait timed out.\n");
 
     test_reader_attributes(profile);
 




More information about the wine-cvs mailing list