forked from Mirrors/wine-wine
mf: Add support to get/set presentation clock for SAR.
Signed-off-by: Nikolay Sivov <nsivov@codeweavers.com> Signed-off-by: Alexandre Julliard <julliard@winehq.org>feature/deterministic
parent
ee6b083173
commit
0507ba6aab
131
dlls/mf/sar.c
131
dlls/mf/sar.c
|
@ -32,9 +32,11 @@ struct audio_renderer
|
||||||
{
|
{
|
||||||
IMFMediaSink IMFMediaSink_iface;
|
IMFMediaSink IMFMediaSink_iface;
|
||||||
IMFMediaSinkPreroll IMFMediaSinkPreroll_iface;
|
IMFMediaSinkPreroll IMFMediaSinkPreroll_iface;
|
||||||
|
IMFClockStateSink IMFClockStateSink_iface;
|
||||||
IMFMediaEventGenerator IMFMediaEventGenerator_iface;
|
IMFMediaEventGenerator IMFMediaEventGenerator_iface;
|
||||||
LONG refcount;
|
LONG refcount;
|
||||||
IMFMediaEventQueue *event_queue;
|
IMFMediaEventQueue *event_queue;
|
||||||
|
IMFPresentationClock *clock;
|
||||||
BOOL is_shut_down;
|
BOOL is_shut_down;
|
||||||
CRITICAL_SECTION cs;
|
CRITICAL_SECTION cs;
|
||||||
};
|
};
|
||||||
|
@ -49,6 +51,11 @@ static struct audio_renderer *impl_from_IMFMediaSinkPreroll(IMFMediaSinkPreroll
|
||||||
return CONTAINING_RECORD(iface, struct audio_renderer, IMFMediaSinkPreroll_iface);
|
return CONTAINING_RECORD(iface, struct audio_renderer, IMFMediaSinkPreroll_iface);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static struct audio_renderer *impl_from_IMFClockStateSink(IMFClockStateSink *iface)
|
||||||
|
{
|
||||||
|
return CONTAINING_RECORD(iface, struct audio_renderer, IMFClockStateSink_iface);
|
||||||
|
}
|
||||||
|
|
||||||
static struct audio_renderer *impl_from_IMFMediaEventGenerator(IMFMediaEventGenerator *iface)
|
static struct audio_renderer *impl_from_IMFMediaEventGenerator(IMFMediaEventGenerator *iface)
|
||||||
{
|
{
|
||||||
return CONTAINING_RECORD(iface, struct audio_renderer, IMFMediaEventGenerator_iface);
|
return CONTAINING_RECORD(iface, struct audio_renderer, IMFMediaEventGenerator_iface);
|
||||||
|
@ -69,6 +76,10 @@ static HRESULT WINAPI audio_renderer_sink_QueryInterface(IMFMediaSink *iface, RE
|
||||||
{
|
{
|
||||||
*obj = &renderer->IMFMediaSinkPreroll_iface;
|
*obj = &renderer->IMFMediaSinkPreroll_iface;
|
||||||
}
|
}
|
||||||
|
else if (IsEqualIID(riid, &IID_IMFClockStateSink))
|
||||||
|
{
|
||||||
|
*obj = &renderer->IMFClockStateSink_iface;
|
||||||
|
}
|
||||||
else if (IsEqualIID(riid, &IID_IMFMediaEventGenerator))
|
else if (IsEqualIID(riid, &IID_IMFMediaEventGenerator))
|
||||||
{
|
{
|
||||||
*obj = &renderer->IMFMediaEventGenerator_iface;
|
*obj = &renderer->IMFMediaEventGenerator_iface;
|
||||||
|
@ -104,6 +115,8 @@ static ULONG WINAPI audio_renderer_sink_Release(IMFMediaSink *iface)
|
||||||
{
|
{
|
||||||
if (renderer->event_queue)
|
if (renderer->event_queue)
|
||||||
IMFMediaEventQueue_Release(renderer->event_queue);
|
IMFMediaEventQueue_Release(renderer->event_queue);
|
||||||
|
if (renderer->clock)
|
||||||
|
IMFPresentationClock_Release(renderer->clock);
|
||||||
DeleteCriticalSection(&renderer->cs);
|
DeleteCriticalSection(&renderer->cs);
|
||||||
heap_free(renderer);
|
heap_free(renderer);
|
||||||
}
|
}
|
||||||
|
@ -179,16 +192,60 @@ static HRESULT WINAPI audio_renderer_sink_GetStreamSinkById(IMFMediaSink *iface,
|
||||||
|
|
||||||
static HRESULT WINAPI audio_renderer_sink_SetPresentationClock(IMFMediaSink *iface, IMFPresentationClock *clock)
|
static HRESULT WINAPI audio_renderer_sink_SetPresentationClock(IMFMediaSink *iface, IMFPresentationClock *clock)
|
||||||
{
|
{
|
||||||
FIXME("%p, %p.\n", iface, clock);
|
struct audio_renderer *renderer = impl_from_IMFMediaSink(iface);
|
||||||
|
HRESULT hr = S_OK;
|
||||||
|
|
||||||
return E_NOTIMPL;
|
TRACE("%p, %p.\n", iface, clock);
|
||||||
|
|
||||||
|
EnterCriticalSection(&renderer->cs);
|
||||||
|
|
||||||
|
if (renderer->is_shut_down)
|
||||||
|
hr = MF_E_SHUTDOWN;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (renderer->clock)
|
||||||
|
{
|
||||||
|
IMFPresentationClock_RemoveClockStateSink(renderer->clock, &renderer->IMFClockStateSink_iface);
|
||||||
|
IMFPresentationClock_Release(renderer->clock);
|
||||||
|
}
|
||||||
|
renderer->clock = clock;
|
||||||
|
if (renderer->clock)
|
||||||
|
{
|
||||||
|
IMFPresentationClock_AddRef(renderer->clock);
|
||||||
|
IMFPresentationClock_AddClockStateSink(renderer->clock, &renderer->IMFClockStateSink_iface);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
LeaveCriticalSection(&renderer->cs);
|
||||||
|
|
||||||
|
return hr;
|
||||||
}
|
}
|
||||||
|
|
||||||
static HRESULT WINAPI audio_renderer_sink_GetPresentationClock(IMFMediaSink *iface, IMFPresentationClock **clock)
|
static HRESULT WINAPI audio_renderer_sink_GetPresentationClock(IMFMediaSink *iface, IMFPresentationClock **clock)
|
||||||
{
|
{
|
||||||
FIXME("%p, %p.\n", iface, clock);
|
struct audio_renderer *renderer = impl_from_IMFMediaSink(iface);
|
||||||
|
HRESULT hr = S_OK;
|
||||||
|
|
||||||
return E_NOTIMPL;
|
TRACE("%p, %p.\n", iface, clock);
|
||||||
|
|
||||||
|
if (!clock)
|
||||||
|
return E_POINTER;
|
||||||
|
|
||||||
|
EnterCriticalSection(&renderer->cs);
|
||||||
|
|
||||||
|
if (renderer->is_shut_down)
|
||||||
|
hr = MF_E_SHUTDOWN;
|
||||||
|
else if (renderer->clock)
|
||||||
|
{
|
||||||
|
*clock = renderer->clock;
|
||||||
|
IMFPresentationClock_AddRef(*clock);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
hr = MF_E_NO_CLOCK;
|
||||||
|
|
||||||
|
LeaveCriticalSection(&renderer->cs);
|
||||||
|
|
||||||
|
return hr;
|
||||||
}
|
}
|
||||||
|
|
||||||
static HRESULT WINAPI audio_renderer_sink_Shutdown(IMFMediaSink *iface)
|
static HRESULT WINAPI audio_renderer_sink_Shutdown(IMFMediaSink *iface)
|
||||||
|
@ -325,6 +382,71 @@ static const IMFMediaEventGeneratorVtbl audio_renderer_events_vtbl =
|
||||||
audio_renderer_events_QueueEvent,
|
audio_renderer_events_QueueEvent,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static HRESULT WINAPI audio_renderer_clock_sink_QueryInterface(IMFClockStateSink *iface, REFIID riid, void **obj)
|
||||||
|
{
|
||||||
|
struct audio_renderer *renderer = impl_from_IMFClockStateSink(iface);
|
||||||
|
return IMFMediaSink_QueryInterface(&renderer->IMFMediaSink_iface, riid, obj);
|
||||||
|
}
|
||||||
|
|
||||||
|
static ULONG WINAPI audio_renderer_clock_sink_AddRef(IMFClockStateSink *iface)
|
||||||
|
{
|
||||||
|
struct audio_renderer *renderer = impl_from_IMFClockStateSink(iface);
|
||||||
|
return IMFMediaSink_AddRef(&renderer->IMFMediaSink_iface);
|
||||||
|
}
|
||||||
|
|
||||||
|
static ULONG WINAPI audio_renderer_clock_sink_Release(IMFClockStateSink *iface)
|
||||||
|
{
|
||||||
|
struct audio_renderer *renderer = impl_from_IMFClockStateSink(iface);
|
||||||
|
return IMFMediaSink_Release(&renderer->IMFMediaSink_iface);
|
||||||
|
}
|
||||||
|
|
||||||
|
static HRESULT WINAPI audio_renderer_clock_sink_OnClockStart(IMFClockStateSink *iface, MFTIME systime, LONGLONG offset)
|
||||||
|
{
|
||||||
|
FIXME("%p, %s, %s.\n", iface, debugstr_time(systime), debugstr_time(offset));
|
||||||
|
|
||||||
|
return E_NOTIMPL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static HRESULT WINAPI audio_renderer_clock_sink_OnClockStop(IMFClockStateSink *iface, MFTIME systime)
|
||||||
|
{
|
||||||
|
FIXME("%p, %s.\n", iface, debugstr_time(systime));
|
||||||
|
|
||||||
|
return E_NOTIMPL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static HRESULT WINAPI audio_renderer_clock_sink_OnClockPause(IMFClockStateSink *iface, MFTIME systime)
|
||||||
|
{
|
||||||
|
FIXME("%p, %s.\n", iface, debugstr_time(systime));
|
||||||
|
|
||||||
|
return E_NOTIMPL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static HRESULT WINAPI audio_renderer_clock_sink_OnClockRestart(IMFClockStateSink *iface, MFTIME systime)
|
||||||
|
{
|
||||||
|
FIXME("%p, %s.\n", iface, debugstr_time(systime));
|
||||||
|
|
||||||
|
return E_NOTIMPL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static HRESULT WINAPI audio_renderer_clock_sink_OnClockSetRate(IMFClockStateSink *iface, MFTIME systime, float rate)
|
||||||
|
{
|
||||||
|
FIXME("%p, %s, %f.\n", iface, debugstr_time(systime), rate);
|
||||||
|
|
||||||
|
return E_NOTIMPL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static const IMFClockStateSinkVtbl audio_renderer_clock_sink_vtbl =
|
||||||
|
{
|
||||||
|
audio_renderer_clock_sink_QueryInterface,
|
||||||
|
audio_renderer_clock_sink_AddRef,
|
||||||
|
audio_renderer_clock_sink_Release,
|
||||||
|
audio_renderer_clock_sink_OnClockStart,
|
||||||
|
audio_renderer_clock_sink_OnClockStop,
|
||||||
|
audio_renderer_clock_sink_OnClockPause,
|
||||||
|
audio_renderer_clock_sink_OnClockRestart,
|
||||||
|
audio_renderer_clock_sink_OnClockSetRate,
|
||||||
|
};
|
||||||
|
|
||||||
static HRESULT sar_create_object(IMFAttributes *attributes, void *user_context, IUnknown **obj)
|
static HRESULT sar_create_object(IMFAttributes *attributes, void *user_context, IUnknown **obj)
|
||||||
{
|
{
|
||||||
struct audio_renderer *renderer;
|
struct audio_renderer *renderer;
|
||||||
|
@ -337,6 +459,7 @@ static HRESULT sar_create_object(IMFAttributes *attributes, void *user_context,
|
||||||
|
|
||||||
renderer->IMFMediaSink_iface.lpVtbl = &audio_renderer_sink_vtbl;
|
renderer->IMFMediaSink_iface.lpVtbl = &audio_renderer_sink_vtbl;
|
||||||
renderer->IMFMediaSinkPreroll_iface.lpVtbl = &audio_renderer_preroll_vtbl;
|
renderer->IMFMediaSinkPreroll_iface.lpVtbl = &audio_renderer_preroll_vtbl;
|
||||||
|
renderer->IMFClockStateSink_iface.lpVtbl = &audio_renderer_clock_sink_vtbl;
|
||||||
renderer->IMFMediaEventGenerator_iface.lpVtbl = &audio_renderer_events_vtbl;
|
renderer->IMFMediaEventGenerator_iface.lpVtbl = &audio_renderer_events_vtbl;
|
||||||
renderer->refcount = 1;
|
renderer->refcount = 1;
|
||||||
InitializeCriticalSection(&renderer->cs);
|
InitializeCriticalSection(&renderer->cs);
|
||||||
|
|
|
@ -2631,6 +2631,7 @@ static void test_quality_manager(void)
|
||||||
|
|
||||||
static void test_sar(void)
|
static void test_sar(void)
|
||||||
{
|
{
|
||||||
|
IMFPresentationClock *present_clock, *present_clock2;
|
||||||
IMFPresentationTimeSource *time_source;
|
IMFPresentationTimeSource *time_source;
|
||||||
IMFClockStateSink *state_sink;
|
IMFClockStateSink *state_sink;
|
||||||
IMFMediaSink *sink, *sink2;
|
IMFMediaSink *sink, *sink2;
|
||||||
|
@ -2654,6 +2655,12 @@ static void test_sar(void)
|
||||||
}
|
}
|
||||||
ok(hr == S_OK, "Failed to create renderer, hr %#x.\n", hr);
|
ok(hr == S_OK, "Failed to create renderer, hr %#x.\n", hr);
|
||||||
|
|
||||||
|
hr = MFStartup(MF_VERSION, MFSTARTUP_FULL);
|
||||||
|
ok(hr == S_OK, "Startup failure, hr %#x.\n", hr);
|
||||||
|
|
||||||
|
hr = MFCreatePresentationClock(&present_clock);
|
||||||
|
ok(hr == S_OK, "Failed to create presentation clock, hr %#x.\n", hr);
|
||||||
|
|
||||||
hr = IMFMediaSink_QueryInterface(sink, &IID_IMFPresentationTimeSource, (void **)&time_source);
|
hr = IMFMediaSink_QueryInterface(sink, &IID_IMFPresentationTimeSource, (void **)&time_source);
|
||||||
todo_wine
|
todo_wine
|
||||||
ok(hr == S_OK, "Failed to get time source interface, hr %#x.\n", hr);
|
ok(hr == S_OK, "Failed to get time source interface, hr %#x.\n", hr);
|
||||||
|
@ -2707,6 +2714,36 @@ if (SUCCEEDED(hr))
|
||||||
ok(hr == S_OK, "Failed to get interface, hr %#x.\n", hr);
|
ok(hr == S_OK, "Failed to get interface, hr %#x.\n", hr);
|
||||||
IUnknown_Release(unk);
|
IUnknown_Release(unk);
|
||||||
|
|
||||||
|
/* Clock */
|
||||||
|
hr = IMFMediaSink_QueryInterface(sink, &IID_IMFClockStateSink, (void **)&unk);
|
||||||
|
ok(hr == S_OK, "Failed to get interface, hr %#x.\n", hr);
|
||||||
|
IUnknown_Release(unk);
|
||||||
|
|
||||||
|
hr = IMFMediaSink_SetPresentationClock(sink, NULL);
|
||||||
|
ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
|
||||||
|
|
||||||
|
hr = IMFMediaSink_SetPresentationClock(sink, present_clock);
|
||||||
|
todo_wine
|
||||||
|
ok(hr == MF_E_CLOCK_NO_TIME_SOURCE, "Unexpected hr %#x.\n", hr);
|
||||||
|
|
||||||
|
hr = MFCreateSystemTimeSource(&time_source);
|
||||||
|
ok(hr == S_OK, "Failed to create time source, hr %#x.\n", hr);
|
||||||
|
|
||||||
|
hr = IMFPresentationClock_SetTimeSource(present_clock, time_source);
|
||||||
|
ok(hr == S_OK, "Failed to set time source, hr %#x.\n", hr);
|
||||||
|
IMFPresentationTimeSource_Release(time_source);
|
||||||
|
|
||||||
|
hr = IMFMediaSink_SetPresentationClock(sink, present_clock);
|
||||||
|
ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
|
||||||
|
|
||||||
|
hr = IMFMediaSink_GetPresentationClock(sink, NULL);
|
||||||
|
ok(hr == E_POINTER, "Unexpected hr %#x.\n", hr);
|
||||||
|
|
||||||
|
hr = IMFMediaSink_GetPresentationClock(sink, &present_clock2);
|
||||||
|
ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
|
||||||
|
ok(present_clock == present_clock2, "Unexpected instance.\n");
|
||||||
|
IMFPresentationClock_Release(present_clock2);
|
||||||
|
|
||||||
/* Shutdown */
|
/* Shutdown */
|
||||||
hr = IMFMediaSink_Shutdown(sink);
|
hr = IMFMediaSink_Shutdown(sink);
|
||||||
ok(hr == S_OK, "Failed to shut down, hr %#x.\n", hr);
|
ok(hr == S_OK, "Failed to shut down, hr %#x.\n", hr);
|
||||||
|
@ -2729,6 +2766,18 @@ if (SUCCEEDED(hr))
|
||||||
hr = IMFMediaSink_GetCharacteristics(sink, &flags);
|
hr = IMFMediaSink_GetCharacteristics(sink, &flags);
|
||||||
ok(hr == MF_E_SHUTDOWN, "Unexpected hr %#x.\n", hr);
|
ok(hr == MF_E_SHUTDOWN, "Unexpected hr %#x.\n", hr);
|
||||||
|
|
||||||
|
hr = IMFMediaSink_SetPresentationClock(sink, NULL);
|
||||||
|
ok(hr == MF_E_SHUTDOWN, "Unexpected hr %#x.\n", hr);
|
||||||
|
|
||||||
|
hr = IMFMediaSink_SetPresentationClock(sink, present_clock);
|
||||||
|
ok(hr == MF_E_SHUTDOWN, "Unexpected hr %#x.\n", hr);
|
||||||
|
|
||||||
|
hr = IMFMediaSink_GetPresentationClock(sink, NULL);
|
||||||
|
ok(hr == E_POINTER, "Unexpected hr %#x.\n", hr);
|
||||||
|
|
||||||
|
hr = IMFMediaSink_GetPresentationClock(sink, &present_clock2);
|
||||||
|
ok(hr == MF_E_SHUTDOWN, "Unexpected hr %#x.\n", hr);
|
||||||
|
|
||||||
IMFMediaSink_Release(sink);
|
IMFMediaSink_Release(sink);
|
||||||
|
|
||||||
/* Activation */
|
/* Activation */
|
||||||
|
@ -2769,6 +2818,11 @@ todo_wine
|
||||||
|
|
||||||
IMFActivate_Release(activate);
|
IMFActivate_Release(activate);
|
||||||
|
|
||||||
|
IMFPresentationClock_Release(present_clock);
|
||||||
|
|
||||||
|
hr = MFShutdown();
|
||||||
|
ok(hr == S_OK, "Shutdown failure, hr %#x.\n", hr);
|
||||||
|
|
||||||
CoUninitialize();
|
CoUninitialize();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue