Nikolay Sivov : mfsrcsnk/wave: Add clock state callbacks.
Alexandre Julliard
julliard at winehq.org
Mon Aug 15 15:22:31 CDT 2022
Module: wine
Branch: master
Commit: bfdf5c775d27dce58af3069dc80d5e31a7e965be
URL: https://gitlab.winehq.org/wine/wine/-/commit/bfdf5c775d27dce58af3069dc80d5e31a7e965be
Author: Nikolay Sivov <nsivov at codeweavers.com>
Date: Sat Aug 13 15:23:44 2022 +0300
mfsrcsnk/wave: Add clock state callbacks.
Don't bother with state handling for now, it's possible it's ignored entirely.
Signed-off-by: Nikolay Sivov <nsivov at codeweavers.com>
---
dlls/mfsrcsnk/tests/Makefile.in | 2 +-
dlls/mfsrcsnk/tests/mfsrcsnk.c | 14 ++++
dlls/mfsrcsnk/wave.c | 162 +++++++++++++++++++++++++++++++++++++++-
3 files changed, 173 insertions(+), 5 deletions(-)
diff --git a/dlls/mfsrcsnk/tests/Makefile.in b/dlls/mfsrcsnk/tests/Makefile.in
index 59ee4830573..32e5637db4f 100644
--- a/dlls/mfsrcsnk/tests/Makefile.in
+++ b/dlls/mfsrcsnk/tests/Makefile.in
@@ -1,5 +1,5 @@
TESTDLL = mfsrcsnk.dll
-IMPORTS = ole32 mfsrcsnk mfplat uuid mfuuid
+IMPORTS = ole32 mfsrcsnk mfplat mf uuid mfuuid
C_SRCS = \
mfsrcsnk.c
diff --git a/dlls/mfsrcsnk/tests/mfsrcsnk.c b/dlls/mfsrcsnk/tests/mfsrcsnk.c
index df3fcfbee38..e3d5b100b09 100644
--- a/dlls/mfsrcsnk/tests/mfsrcsnk.c
+++ b/dlls/mfsrcsnk/tests/mfsrcsnk.c
@@ -46,6 +46,7 @@ static void check_interface_(unsigned int line, void *iface_ptr, REFIID iid, BOO
static void test_wave_sink(void)
{
+ IMFPresentationClock *clock;
IMFStreamSink *stream_sink;
IMFMediaSink *sink, *sink2;
IMFByteStream *bytestream;
@@ -101,6 +102,19 @@ static void test_wave_sink(void)
check_interface(sink, &IID_IMFMediaEventGenerator, TRUE);
check_interface(sink, &IID_IMFFinalizableMediaSink, TRUE);
+ check_interface(sink, &IID_IMFClockStateSink, TRUE);
+
+ /* Clock */
+ hr = MFCreatePresentationClock(&clock);
+ ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
+
+ hr = IMFMediaSink_SetPresentationClock(sink, NULL);
+ ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
+
+ hr = IMFMediaSink_SetPresentationClock(sink, clock);
+ ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
+
+ IMFPresentationClock_Release(clock);
/* Stream tests */
hr = IMFMediaSink_GetStreamSinkByIndex(sink, 0, &stream_sink);
diff --git a/dlls/mfsrcsnk/wave.c b/dlls/mfsrcsnk/wave.c
index 9f271375e1e..b9951b3e2b6 100644
--- a/dlls/mfsrcsnk/wave.c
+++ b/dlls/mfsrcsnk/wave.c
@@ -26,6 +26,27 @@
WINE_DEFAULT_DEBUG_CHANNEL(mfplat);
+static inline const char *debugstr_time(LONGLONG time)
+{
+ ULONGLONG abstime = time >= 0 ? time : -time;
+ unsigned int i = 0, j = 0;
+ char buffer[23], rev[23];
+
+ while (abstime || i <= 8)
+ {
+ buffer[i++] = '0' + (abstime % 10);
+ abstime /= 10;
+ if (i == 7) buffer[i++] = '.';
+ }
+ if (time < 0) buffer[i++] = '-';
+
+ while (i--) rev[j++] = buffer[i];
+ while (rev[j-1] == '0' && rev[j-2] != '.') --j;
+ rev[j] = 0;
+
+ return wine_dbg_sprintf("%s", rev);
+}
+
enum wave_sink_flags
{
SINK_SHUT_DOWN = 0x1,
@@ -35,11 +56,13 @@ struct wave_sink
{
IMFFinalizableMediaSink IMFFinalizableMediaSink_iface;
IMFMediaEventGenerator IMFMediaEventGenerator_iface;
+ IMFClockStateSink IMFClockStateSink_iface;
IMFStreamSink IMFStreamSink_iface;
LONG refcount;
IMFMediaEventQueue *event_queue;
IMFMediaEventQueue *stream_event_queue;
+ IMFPresentationClock *clock;
IMFByteStream *bytestream;
@@ -62,6 +85,11 @@ static struct wave_sink *impl_from_IMFStreamSink(IMFStreamSink *iface)
return CONTAINING_RECORD(iface, struct wave_sink, IMFStreamSink_iface);
}
+static struct wave_sink *impl_from_IMFClockStateSink(IMFClockStateSink *iface)
+{
+ return CONTAINING_RECORD(iface, struct wave_sink, IMFClockStateSink_iface);
+}
+
static HRESULT WINAPI wave_sink_QueryInterface(IMFFinalizableMediaSink *iface, REFIID riid, void **obj)
{
struct wave_sink *sink = impl_from_IMFFinalizableMediaSink(iface);
@@ -78,6 +106,10 @@ static HRESULT WINAPI wave_sink_QueryInterface(IMFFinalizableMediaSink *iface, R
{
*obj = &sink->IMFMediaEventGenerator_iface;
}
+ else if (IsEqualIID(riid, &IID_IMFClockStateSink))
+ {
+ *obj = &sink->IMFClockStateSink_iface;
+ }
else
{
WARN("Unsupported %s.\n", debugstr_guid(riid));
@@ -219,18 +251,65 @@ static HRESULT WINAPI wave_sink_GetStreamSinkById(IMFFinalizableMediaSink *iface
return hr;
}
+static void wave_sink_set_presentation_clock(struct wave_sink *sink, IMFPresentationClock *clock)
+{
+ if (sink->clock)
+ {
+ IMFPresentationClock_RemoveClockStateSink(sink->clock, &sink->IMFClockStateSink_iface);
+ IMFPresentationClock_Release(sink->clock);
+ }
+ sink->clock = clock;
+ if (sink->clock)
+ {
+ IMFPresentationClock_AddRef(sink->clock);
+ IMFPresentationClock_AddClockStateSink(sink->clock, &sink->IMFClockStateSink_iface);
+ }
+}
+
static HRESULT WINAPI wave_sink_SetPresentationClock(IMFFinalizableMediaSink *iface, IMFPresentationClock *clock)
{
- FIXME("%p, %p.\n", iface, clock);
+ struct wave_sink *sink = impl_from_IMFFinalizableMediaSink(iface);
+ HRESULT hr = S_OK;
- return E_NOTIMPL;
+ TRACE("%p, %p.\n", iface, clock);
+
+ EnterCriticalSection(&sink->cs);
+
+ if (sink->flags & SINK_SHUT_DOWN)
+ hr = MF_E_SHUTDOWN;
+ else
+ wave_sink_set_presentation_clock(sink, clock);
+
+ LeaveCriticalSection(&sink->cs);
+
+ return hr;
}
static HRESULT WINAPI wave_sink_GetPresentationClock(IMFFinalizableMediaSink *iface, IMFPresentationClock **clock)
{
- FIXME("%p, %p.\n", iface, clock);
+ struct wave_sink *sink = impl_from_IMFFinalizableMediaSink(iface);
+ HRESULT hr = S_OK;
- return E_NOTIMPL;
+ TRACE("%p, %p.\n", iface, clock);
+
+ if (!clock)
+ return E_POINTER;
+
+ EnterCriticalSection(&sink->cs);
+
+ if (sink->flags & SINK_SHUT_DOWN)
+ hr = MF_E_SHUTDOWN;
+ else if (sink->clock)
+ {
+ *clock = sink->clock;
+ IMFPresentationClock_AddRef(*clock);
+ }
+ else
+ hr = MF_E_NO_CLOCK;
+
+ LeaveCriticalSection(&sink->cs);
+
+ return hr;
}
static HRESULT WINAPI wave_sink_Shutdown(IMFFinalizableMediaSink *iface)
@@ -249,6 +328,7 @@ static HRESULT WINAPI wave_sink_Shutdown(IMFFinalizableMediaSink *iface)
sink->flags |= SINK_SHUT_DOWN;
IMFMediaEventQueue_Shutdown(sink->event_queue);
IMFMediaEventQueue_Shutdown(sink->stream_event_queue);
+ wave_sink_set_presentation_clock(sink, NULL);
}
LeaveCriticalSection(&sink->cs);
@@ -518,6 +598,79 @@ static const IMFStreamSinkVtbl wave_stream_sink_vtbl =
wave_stream_sink_Flush,
};
+static HRESULT WINAPI wave_sink_clock_sink_QueryInterface(IMFClockStateSink *iface, REFIID riid, void **obj)
+{
+ struct wave_sink *sink = impl_from_IMFClockStateSink(iface);
+ return IMFFinalizableMediaSink_QueryInterface(&sink->IMFFinalizableMediaSink_iface, riid, obj);
+}
+
+static ULONG WINAPI wave_sink_clock_sink_AddRef(IMFClockStateSink *iface)
+{
+ struct wave_sink *sink = impl_from_IMFClockStateSink(iface);
+ return IMFFinalizableMediaSink_AddRef(&sink->IMFFinalizableMediaSink_iface);
+}
+
+static ULONG WINAPI wave_sink_clock_sink_Release(IMFClockStateSink *iface)
+{
+ struct wave_sink *sink = impl_from_IMFClockStateSink(iface);
+ return IMFFinalizableMediaSink_Release(&sink->IMFFinalizableMediaSink_iface);
+}
+
+static HRESULT WINAPI wave_sink_clock_sink_OnClockStart(IMFClockStateSink *iface, MFTIME systime, LONGLONG offset)
+{
+ struct wave_sink *sink = impl_from_IMFClockStateSink(iface);
+
+ TRACE("%p, %s, %s.\n", iface, debugstr_time(systime), debugstr_time(offset));
+
+ return IMFMediaEventQueue_QueueEventParamVar(sink->stream_event_queue, MEStreamSinkStarted, &GUID_NULL, S_OK, NULL);
+}
+
+static HRESULT WINAPI wave_sink_clock_sink_OnClockStop(IMFClockStateSink *iface, MFTIME systime)
+{
+ struct wave_sink *sink = impl_from_IMFClockStateSink(iface);
+
+ TRACE("%p, %s.\n", iface, debugstr_time(systime));
+
+ return IMFMediaEventQueue_QueueEventParamVar(sink->stream_event_queue, MEStreamSinkStopped, &GUID_NULL, S_OK, NULL);
+}
+
+static HRESULT WINAPI wave_sink_clock_sink_OnClockPause(IMFClockStateSink *iface, MFTIME systime)
+{
+ struct wave_sink *sink = impl_from_IMFClockStateSink(iface);
+
+ TRACE("%p, %s.\n", iface, debugstr_time(systime));
+
+ return IMFMediaEventQueue_QueueEventParamVar(sink->stream_event_queue, MEStreamSinkPaused, &GUID_NULL, S_OK, NULL);
+}
+
+static HRESULT WINAPI wave_sink_clock_sink_OnClockRestart(IMFClockStateSink *iface, MFTIME systime)
+{
+ struct wave_sink *sink = impl_from_IMFClockStateSink(iface);
+
+ TRACE("%p, %s.\n", iface, debugstr_time(systime));
+
+ return IMFMediaEventQueue_QueueEventParamVar(sink->stream_event_queue, MEStreamSinkStarted, &GUID_NULL, S_OK, NULL);
+}
+
+static HRESULT WINAPI wave_sink_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 wave_sink_clock_sink_vtbl =
+{
+ wave_sink_clock_sink_QueryInterface,
+ wave_sink_clock_sink_AddRef,
+ wave_sink_clock_sink_Release,
+ wave_sink_clock_sink_OnClockStart,
+ wave_sink_clock_sink_OnClockStop,
+ wave_sink_clock_sink_OnClockPause,
+ wave_sink_clock_sink_OnClockRestart,
+ wave_sink_clock_sink_OnClockSetRate,
+};
+
/***********************************************************************
* MFCreateWAVEMediaSink (mfsrcsnk.@)
*/
@@ -544,6 +697,7 @@ HRESULT WINAPI MFCreateWAVEMediaSink(IMFByteStream *bytestream, IMFMediaType *me
object->IMFFinalizableMediaSink_iface.lpVtbl = &wave_sink_vtbl;
object->IMFMediaEventGenerator_iface.lpVtbl = &wave_sink_events_vtbl;
object->IMFStreamSink_iface.lpVtbl = &wave_stream_sink_vtbl;
+ object->IMFClockStateSink_iface.lpVtbl = &wave_sink_clock_sink_vtbl;
object->refcount = 1;
IMFByteStream_AddRef((object->bytestream = bytestream));
InitializeCriticalSection(&object->cs);
More information about the wine-cvs
mailing list