[PATCH 2/3] mf: Keep a list of clock state sinks.

Nikolay Sivov nsivov at codeweavers.com
Thu Mar 7 01:07:53 CST 2019


Signed-off-by: Nikolay Sivov <nsivov at codeweavers.com>
---
 dlls/mf/session.c  | 76 ++++++++++++++++++++++++++++++++++++++++---
 dlls/mf/tests/mf.c | 81 ++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 153 insertions(+), 4 deletions(-)

diff --git a/dlls/mf/session.c b/dlls/mf/session.c
index 27b2c4cce6..d2d1d495a0 100644
--- a/dlls/mf/session.c
+++ b/dlls/mf/session.c
@@ -29,6 +29,7 @@
 
 #include "wine/debug.h"
 #include "wine/heap.h"
+#include "wine/list.h"
 
 WINE_DEFAULT_DEBUG_CHANNEL(mfplat);
 
@@ -39,6 +40,12 @@ struct media_session
     IMFMediaEventQueue *event_queue;
 };
 
+struct clock_sink
+{
+    struct list entry;
+    IMFClockStateSink *state_sink;
+};
+
 struct presentation_clock
 {
     IMFPresentationClock IMFPresentationClock_iface;
@@ -49,6 +56,7 @@ struct presentation_clock
     IMFPresentationTimeSource *time_source;
     IMFClockStateSink *time_source_sink;
     MFCLOCK_STATE state;
+    struct list sinks;
     CRITICAL_SECTION cs;
 };
 
@@ -335,6 +343,7 @@ static ULONG WINAPI present_clock_Release(IMFPresentationClock *iface)
 {
     struct presentation_clock *clock = impl_from_IMFPresentationClock(iface);
     ULONG refcount = InterlockedDecrement(&clock->refcount);
+    struct clock_sink *sink, *sink2;
 
     TRACE("%p, refcount %u.\n", iface, refcount);
 
@@ -344,6 +353,12 @@ static ULONG WINAPI present_clock_Release(IMFPresentationClock *iface)
             IMFPresentationTimeSource_Release(clock->time_source);
         if (clock->time_source_sink)
             IMFClockStateSink_Release(clock->time_source_sink);
+        LIST_FOR_EACH_ENTRY_SAFE(sink, sink2, &clock->sinks, struct clock_sink, entry)
+        {
+            list_remove(&sink->entry);
+            IMFClockStateSink_Release(sink->state_sink);
+            heap_free(sink);
+        }
         DeleteCriticalSection(&clock->cs);
         heap_free(clock);
     }
@@ -453,17 +468,69 @@ static HRESULT WINAPI present_clock_GetTime(IMFPresentationClock *iface, MFTIME
 
 static HRESULT WINAPI present_clock_AddClockStateSink(IMFPresentationClock *iface, IMFClockStateSink *state_sink)
 {
-    FIXME("%p, %p.\n", iface, state_sink);
+    struct presentation_clock *clock = impl_from_IMFPresentationClock(iface);
+    struct clock_sink *sink, *cur;
+    HRESULT hr = S_OK;
 
-    return E_NOTIMPL;
+    TRACE("%p, %p.\n", iface, state_sink);
+
+    if (!state_sink)
+        return E_INVALIDARG;
+
+    sink = heap_alloc(sizeof(*sink));
+    if (!sink)
+        return E_OUTOFMEMORY;
+
+    sink->state_sink = state_sink;
+    IMFClockStateSink_AddRef(sink->state_sink);
+
+    EnterCriticalSection(&clock->cs);
+    LIST_FOR_EACH_ENTRY(cur, &clock->sinks, struct clock_sink, entry)
+    {
+        if (cur->state_sink == state_sink)
+        {
+            hr = E_INVALIDARG;
+            break;
+        }
+    }
+    if (SUCCEEDED(hr))
+        list_add_tail(&clock->sinks, &sink->entry);
+    LeaveCriticalSection(&clock->cs);
+
+    if (FAILED(hr))
+    {
+        IMFClockStateSink_Release(sink->state_sink);
+        heap_free(sink);
+    }
+
+    return hr;
 }
 
 static HRESULT WINAPI present_clock_RemoveClockStateSink(IMFPresentationClock *iface,
         IMFClockStateSink *state_sink)
 {
-    FIXME("%p, %p.\n", iface, state_sink);
+    struct presentation_clock *clock = impl_from_IMFPresentationClock(iface);
+    struct clock_sink *sink;
 
-    return E_NOTIMPL;
+    TRACE("%p, %p.\n", iface, state_sink);
+
+    if (!state_sink)
+        return E_INVALIDARG;
+
+    EnterCriticalSection(&clock->cs);
+    LIST_FOR_EACH_ENTRY(sink, &clock->sinks, struct clock_sink, entry)
+    {
+        if (sink->state_sink == state_sink)
+        {
+            IMFClockStateSink_Release(sink->state_sink);
+            list_remove(&sink->entry);
+            heap_free(sink);
+            break;
+        }
+    }
+    LeaveCriticalSection(&clock->cs);
+
+    return S_OK;
 }
 
 enum clock_command
@@ -731,6 +798,7 @@ HRESULT WINAPI MFCreatePresentationClock(IMFPresentationClock **clock)
     object->IMFTimer_iface.lpVtbl = &presentclocktimervtbl;
     object->IMFShutdown_iface.lpVtbl = &presentclockshutdownvtbl;
     object->refcount = 1;
+    list_init(&object->sinks);
     InitializeCriticalSection(&object->cs);
 
     *clock = &object->IMFPresentationClock_iface;
diff --git a/dlls/mf/tests/mf.c b/dlls/mf/tests/mf.c
index bae674d7fa..42b23d6c3e 100644
--- a/dlls/mf/tests/mf.c
+++ b/dlls/mf/tests/mf.c
@@ -742,6 +742,67 @@ enum clock_action
     CLOCK_PAUSE,
 };
 
+static HRESULT WINAPI test_clock_sink_QueryInterface(IMFClockStateSink *iface, REFIID riid, void **obj)
+{
+    if (IsEqualIID(riid, &IID_IMFClockStateSink) ||
+            IsEqualIID(riid, &IID_IUnknown))
+    {
+        *obj = iface;
+        IMFClockStateSink_AddRef(iface);
+        return S_OK;
+    }
+
+    *obj = NULL;
+    return E_NOINTERFACE;
+}
+
+static ULONG WINAPI test_clock_sink_AddRef(IMFClockStateSink *iface)
+{
+    return 2;
+}
+
+static ULONG WINAPI test_clock_sink_Release(IMFClockStateSink *iface)
+{
+    return 1;
+}
+
+static HRESULT WINAPI test_clock_sink_OnClockStart(IMFClockStateSink *iface, MFTIME system_time, LONGLONG offset)
+{
+    return E_NOTIMPL;
+}
+
+static HRESULT WINAPI test_clock_sink_OnClockStop(IMFClockStateSink *iface, MFTIME system_time)
+{
+    return E_NOTIMPL;
+}
+
+static HRESULT WINAPI test_clock_sink_OnClockPause(IMFClockStateSink *iface, MFTIME system_time)
+{
+    return E_NOTIMPL;
+}
+
+static HRESULT WINAPI test_clock_sink_OnClockRestart(IMFClockStateSink *iface, MFTIME system_time)
+{
+    return E_NOTIMPL;
+}
+
+static HRESULT WINAPI test_clock_sink_OnClockSetRate(IMFClockStateSink *iface, MFTIME system_time, float rate)
+{
+    return E_NOTIMPL;
+}
+
+static const IMFClockStateSinkVtbl test_clock_sink_vtbl =
+{
+    test_clock_sink_QueryInterface,
+    test_clock_sink_AddRef,
+    test_clock_sink_Release,
+    test_clock_sink_OnClockStart,
+    test_clock_sink_OnClockStop,
+    test_clock_sink_OnClockPause,
+    test_clock_sink_OnClockRestart,
+    test_clock_sink_OnClockSetRate,
+};
+
 static void test_presentation_clock(void)
 {
     static const struct clock_state_test
@@ -766,6 +827,7 @@ static void test_presentation_clock(void)
         { CLOCK_STOP, MFCLOCK_STATE_STOPPED, MFCLOCK_STATE_STOPPED, MF_E_CLOCK_STATE_ALREADY_SET },
         { CLOCK_PAUSE, MFCLOCK_STATE_STOPPED, MFCLOCK_STATE_STOPPED, MF_E_INVALIDREQUEST },
     };
+    IMFClockStateSink test_sink = { &test_clock_sink_vtbl };
     IMFPresentationTimeSource *time_source;
     IMFRateControl *rate_control;
     IMFPresentationClock *clock;
@@ -809,6 +871,25 @@ todo_wine
 todo_wine
     ok(hr == MF_E_CLOCK_NO_TIME_SOURCE, "Unexpected hr %#x.\n", hr);
 
+    /* Sinks. */
+    hr = IMFPresentationClock_AddClockStateSink(clock, NULL);
+    ok(hr == E_INVALIDARG, "Unexpected hr %#x.\n", hr);
+
+    hr = IMFPresentationClock_AddClockStateSink(clock, &test_sink);
+    ok(hr == S_OK, "Failed to add a sink, hr %#x.\n", hr);
+
+    hr = IMFPresentationClock_AddClockStateSink(clock, &test_sink);
+    ok(hr == E_INVALIDARG, "Unexpected hr %#x.\n", hr);
+
+    hr = IMFPresentationClock_RemoveClockStateSink(clock, NULL);
+    ok(hr == E_INVALIDARG, "Unexpected hr %#x.\n", hr);
+
+    hr = IMFPresentationClock_RemoveClockStateSink(clock, &test_sink);
+    ok(hr == S_OK, "Failed to remove sink, hr %#x.\n", hr);
+
+    hr = IMFPresentationClock_RemoveClockStateSink(clock, &test_sink);
+    ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
+
     /* Set default time source. */
     hr = MFCreateSystemTimeSource(&time_source);
     ok(hr == S_OK, "Failed to create time source, hr %#x.\n", hr);
-- 
2.20.1




More information about the wine-devel mailing list