mf: Keep a list of clock state sinks.

Signed-off-by: Nikolay Sivov <nsivov@codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
Nikolay Sivov 2019-03-07 10:07:53 +03:00 committed by Alexandre Julliard
parent c815f908f9
commit f64f0f266f
2 changed files with 153 additions and 4 deletions

View File

@ -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;

View File

@ -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);