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:
parent
c815f908f9
commit
f64f0f266f
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
|
Loading…
Reference in New Issue