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/debug.h"
#include "wine/heap.h" #include "wine/heap.h"
#include "wine/list.h"
WINE_DEFAULT_DEBUG_CHANNEL(mfplat); WINE_DEFAULT_DEBUG_CHANNEL(mfplat);
@ -39,6 +40,12 @@ struct media_session
IMFMediaEventQueue *event_queue; IMFMediaEventQueue *event_queue;
}; };
struct clock_sink
{
struct list entry;
IMFClockStateSink *state_sink;
};
struct presentation_clock struct presentation_clock
{ {
IMFPresentationClock IMFPresentationClock_iface; IMFPresentationClock IMFPresentationClock_iface;
@ -49,6 +56,7 @@ struct presentation_clock
IMFPresentationTimeSource *time_source; IMFPresentationTimeSource *time_source;
IMFClockStateSink *time_source_sink; IMFClockStateSink *time_source_sink;
MFCLOCK_STATE state; MFCLOCK_STATE state;
struct list sinks;
CRITICAL_SECTION cs; CRITICAL_SECTION cs;
}; };
@ -335,6 +343,7 @@ static ULONG WINAPI present_clock_Release(IMFPresentationClock *iface)
{ {
struct presentation_clock *clock = impl_from_IMFPresentationClock(iface); struct presentation_clock *clock = impl_from_IMFPresentationClock(iface);
ULONG refcount = InterlockedDecrement(&clock->refcount); ULONG refcount = InterlockedDecrement(&clock->refcount);
struct clock_sink *sink, *sink2;
TRACE("%p, refcount %u.\n", iface, refcount); TRACE("%p, refcount %u.\n", iface, refcount);
@ -344,6 +353,12 @@ static ULONG WINAPI present_clock_Release(IMFPresentationClock *iface)
IMFPresentationTimeSource_Release(clock->time_source); IMFPresentationTimeSource_Release(clock->time_source);
if (clock->time_source_sink) if (clock->time_source_sink)
IMFClockStateSink_Release(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); DeleteCriticalSection(&clock->cs);
heap_free(clock); 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) 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, static HRESULT WINAPI present_clock_RemoveClockStateSink(IMFPresentationClock *iface,
IMFClockStateSink *state_sink) 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 enum clock_command
@ -731,6 +798,7 @@ HRESULT WINAPI MFCreatePresentationClock(IMFPresentationClock **clock)
object->IMFTimer_iface.lpVtbl = &presentclocktimervtbl; object->IMFTimer_iface.lpVtbl = &presentclocktimervtbl;
object->IMFShutdown_iface.lpVtbl = &presentclockshutdownvtbl; object->IMFShutdown_iface.lpVtbl = &presentclockshutdownvtbl;
object->refcount = 1; object->refcount = 1;
list_init(&object->sinks);
InitializeCriticalSection(&object->cs); InitializeCriticalSection(&object->cs);
*clock = &object->IMFPresentationClock_iface; *clock = &object->IMFPresentationClock_iface;

View File

@ -742,6 +742,67 @@ enum clock_action
CLOCK_PAUSE, 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 void test_presentation_clock(void)
{ {
static const struct clock_state_test 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_STOP, MFCLOCK_STATE_STOPPED, MFCLOCK_STATE_STOPPED, MF_E_CLOCK_STATE_ALREADY_SET },
{ CLOCK_PAUSE, MFCLOCK_STATE_STOPPED, MFCLOCK_STATE_STOPPED, MF_E_INVALIDREQUEST }, { CLOCK_PAUSE, MFCLOCK_STATE_STOPPED, MFCLOCK_STATE_STOPPED, MF_E_INVALIDREQUEST },
}; };
IMFClockStateSink test_sink = { &test_clock_sink_vtbl };
IMFPresentationTimeSource *time_source; IMFPresentationTimeSource *time_source;
IMFRateControl *rate_control; IMFRateControl *rate_control;
IMFPresentationClock *clock; IMFPresentationClock *clock;
@ -809,6 +871,25 @@ todo_wine
todo_wine todo_wine
ok(hr == MF_E_CLOCK_NO_TIME_SOURCE, "Unexpected hr %#x.\n", hr); 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. */ /* Set default time source. */
hr = MFCreateSystemTimeSource(&time_source); hr = MFCreateSystemTimeSource(&time_source);
ok(hr == S_OK, "Failed to create time source, hr %#x.\n", hr); ok(hr == S_OK, "Failed to create time source, hr %#x.\n", hr);