From 0507ba6aab66c8ec38e375d949052f728ff64f27 Mon Sep 17 00:00:00 2001 From: Nikolay Sivov Date: Wed, 8 Apr 2020 17:21:22 +0300 Subject: [PATCH] mf: Add support to get/set presentation clock for SAR. Signed-off-by: Nikolay Sivov Signed-off-by: Alexandre Julliard --- dlls/mf/sar.c | 131 +++++++++++++++++++++++++++++++++++++++++++-- dlls/mf/tests/mf.c | 54 +++++++++++++++++++ 2 files changed, 181 insertions(+), 4 deletions(-) diff --git a/dlls/mf/sar.c b/dlls/mf/sar.c index 71fd4ed8503..2ef767b7871 100644 --- a/dlls/mf/sar.c +++ b/dlls/mf/sar.c @@ -32,9 +32,11 @@ struct audio_renderer { IMFMediaSink IMFMediaSink_iface; IMFMediaSinkPreroll IMFMediaSinkPreroll_iface; + IMFClockStateSink IMFClockStateSink_iface; IMFMediaEventGenerator IMFMediaEventGenerator_iface; LONG refcount; IMFMediaEventQueue *event_queue; + IMFPresentationClock *clock; BOOL is_shut_down; CRITICAL_SECTION cs; }; @@ -49,6 +51,11 @@ static struct audio_renderer *impl_from_IMFMediaSinkPreroll(IMFMediaSinkPreroll 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) { 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; } + else if (IsEqualIID(riid, &IID_IMFClockStateSink)) + { + *obj = &renderer->IMFClockStateSink_iface; + } else if (IsEqualIID(riid, &IID_IMFMediaEventGenerator)) { *obj = &renderer->IMFMediaEventGenerator_iface; @@ -104,6 +115,8 @@ static ULONG WINAPI audio_renderer_sink_Release(IMFMediaSink *iface) { if (renderer->event_queue) IMFMediaEventQueue_Release(renderer->event_queue); + if (renderer->clock) + IMFPresentationClock_Release(renderer->clock); DeleteCriticalSection(&renderer->cs); 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) { - 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) { - 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) @@ -325,6 +382,71 @@ static const IMFMediaEventGeneratorVtbl audio_renderer_events_vtbl = 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) { 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->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->refcount = 1; InitializeCriticalSection(&renderer->cs); diff --git a/dlls/mf/tests/mf.c b/dlls/mf/tests/mf.c index fcbbde36fb0..98e180e453c 100644 --- a/dlls/mf/tests/mf.c +++ b/dlls/mf/tests/mf.c @@ -2631,6 +2631,7 @@ static void test_quality_manager(void) static void test_sar(void) { + IMFPresentationClock *present_clock, *present_clock2; IMFPresentationTimeSource *time_source; IMFClockStateSink *state_sink; IMFMediaSink *sink, *sink2; @@ -2654,6 +2655,12 @@ static void test_sar(void) } 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); todo_wine 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); 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 */ hr = IMFMediaSink_Shutdown(sink); ok(hr == S_OK, "Failed to shut down, hr %#x.\n", hr); @@ -2729,6 +2766,18 @@ if (SUCCEEDED(hr)) hr = IMFMediaSink_GetCharacteristics(sink, &flags); 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); /* Activation */ @@ -2769,6 +2818,11 @@ todo_wine IMFActivate_Release(activate); + IMFPresentationClock_Release(present_clock); + + hr = MFShutdown(); + ok(hr == S_OK, "Shutdown failure, hr %#x.\n", hr); + CoUninitialize(); }