[PATCH 1/7] mf: Add support to get/set presentation clock for SAR.
Nikolay Sivov
nsivov at codeweavers.com
Wed Apr 8 09:21:22 CDT 2020
Signed-off-by: Nikolay Sivov <nsivov at codeweavers.com>
---
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 71fd4ed850..2ef767b787 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 fcbbde36fb..98e180e453 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();
}
--
2.25.1
More information about the wine-devel
mailing list