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/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;
|
||||||
|
|
|
@ -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);
|
||||||
|
|
Loading…
Reference in New Issue