[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