[v2 PATCH 3/4] mfmediaengine/renderer: Add clock state sink.
Nikolay Sivov
nsivov at codeweavers.com
Mon Nov 2 06:54:20 CST 2020
Signed-off-by: Nikolay Sivov <nsivov at codeweavers.com>
---
dlls/mfmediaengine/renderer.c | 207 +++++++++++++++++++++++++++++++++-
1 file changed, 203 insertions(+), 4 deletions(-)
diff --git a/dlls/mfmediaengine/renderer.c b/dlls/mfmediaengine/renderer.c
index 98807f23d0f..d747f42774a 100644
--- a/dlls/mfmediaengine/renderer.c
+++ b/dlls/mfmediaengine/renderer.c
@@ -29,6 +29,34 @@
WINE_DEFAULT_DEBUG_CHANNEL(mfplat);
+static 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 stream_state
+{
+ STREAM_STATE_STOPPED = 0,
+ STREAM_STATE_RUNNING,
+ STREAM_STATE_PAUSED,
+};
+
enum video_renderer_flags
{
FLAG_SHUT_DOWN = 0x1,
@@ -39,11 +67,14 @@ struct video_renderer
IMFMediaSink IMFMediaSink_iface;
IMFStreamSink IMFStreamSink_iface;
IMFMediaTypeHandler IMFMediaTypeHandler_iface;
+ IMFClockStateSink IMFClockStateSink_iface;
IMFMediaEventGenerator IMFMediaEventGenerator_iface;
LONG refcount;
IMFMediaEventQueue *event_queue;
IMFMediaEventQueue *stream_event_queue;
+ IMFPresentationClock *clock;
unsigned int flags;
+ unsigned int state;
CRITICAL_SECTION cs;
};
@@ -52,6 +83,11 @@ static struct video_renderer *impl_from_IMFMediaSink(IMFMediaSink *iface)
return CONTAINING_RECORD(iface, struct video_renderer, IMFMediaSink_iface);
}
+static struct video_renderer *impl_from_IMFClockStateSink(IMFClockStateSink *iface)
+{
+ return CONTAINING_RECORD(iface, struct video_renderer, IMFClockStateSink_iface);
+}
+
static struct video_renderer *impl_from_IMFStreamSink(IMFStreamSink *iface)
{
return CONTAINING_RECORD(iface, struct video_renderer, IMFStreamSink_iface);
@@ -78,6 +114,10 @@ static HRESULT WINAPI video_renderer_sink_QueryInterface(IMFMediaSink *iface, RE
{
*obj = iface;
}
+ else if (IsEqualIID(riid, &IID_IMFClockStateSink))
+ {
+ *obj = &renderer->IMFClockStateSink_iface;
+ }
else if (IsEqualIID(riid, &IID_IMFMediaEventGenerator))
{
*obj = &renderer->IMFMediaEventGenerator_iface;
@@ -115,6 +155,8 @@ static ULONG WINAPI video_renderer_sink_Release(IMFMediaSink *iface)
IMFMediaEventQueue_Release(renderer->event_queue);
if (renderer->stream_event_queue)
IMFMediaEventQueue_Release(renderer->stream_event_queue);
+ if (renderer->clock)
+ IMFPresentationClock_Release(renderer->clock);
DeleteCriticalSection(&renderer->cs);
heap_free(renderer);
}
@@ -222,19 +264,66 @@ static HRESULT WINAPI video_renderer_sink_GetStreamSinkById(IMFMediaSink *iface,
return hr;
}
+static void video_renderer_set_presentation_clock(struct video_renderer *renderer, IMFPresentationClock *clock)
+{
+ 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);
+ }
+}
+
static HRESULT WINAPI video_renderer_sink_SetPresentationClock(IMFMediaSink *iface, IMFPresentationClock *clock)
{
- FIXME("%p, %p.\n", iface, clock);
+ struct video_renderer *renderer = impl_from_IMFMediaSink(iface);
+ HRESULT hr = S_OK;
- return E_NOTIMPL;
+ TRACE("%p, %p.\n", iface, clock);
+
+ EnterCriticalSection(&renderer->cs);
+
+ if (renderer->flags & FLAG_SHUT_DOWN)
+ hr = MF_E_SHUTDOWN;
+ else
+ video_renderer_set_presentation_clock(renderer, clock);
+
+ LeaveCriticalSection(&renderer->cs);
+
+ return hr;
}
static HRESULT WINAPI video_renderer_sink_GetPresentationClock(IMFMediaSink *iface,
IMFPresentationClock **clock)
{
- FIXME("%p, %p.\n", iface, clock);
+ struct video_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->flags & FLAG_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 video_renderer_sink_Shutdown(IMFMediaSink *iface)
@@ -250,6 +339,7 @@ static HRESULT WINAPI video_renderer_sink_Shutdown(IMFMediaSink *iface)
renderer->flags |= FLAG_SHUT_DOWN;
IMFMediaEventQueue_Shutdown(renderer->event_queue);
IMFMediaEventQueue_Shutdown(renderer->stream_event_queue);
+ video_renderer_set_presentation_clock(renderer, NULL);
LeaveCriticalSection(&renderer->cs);
return S_OK;
@@ -624,6 +714,114 @@ static const IMFMediaEventGeneratorVtbl video_renderer_events_vtbl =
video_renderer_events_QueueEvent,
};
+static HRESULT WINAPI video_renderer_clock_sink_QueryInterface(IMFClockStateSink *iface, REFIID riid, void **obj)
+{
+ struct video_renderer *renderer = impl_from_IMFClockStateSink(iface);
+ return IMFMediaSink_QueryInterface(&renderer->IMFMediaSink_iface, riid, obj);
+}
+
+static ULONG WINAPI video_renderer_clock_sink_AddRef(IMFClockStateSink *iface)
+{
+ struct video_renderer *renderer = impl_from_IMFClockStateSink(iface);
+ return IMFMediaSink_AddRef(&renderer->IMFMediaSink_iface);
+}
+
+static ULONG WINAPI video_renderer_clock_sink_Release(IMFClockStateSink *iface)
+{
+ struct video_renderer *renderer = impl_from_IMFClockStateSink(iface);
+ return IMFMediaSink_Release(&renderer->IMFMediaSink_iface);
+}
+
+static HRESULT WINAPI video_renderer_clock_sink_OnClockStart(IMFClockStateSink *iface, MFTIME systime, LONGLONG offset)
+{
+ struct video_renderer *renderer = impl_from_IMFClockStateSink(iface);
+
+ TRACE("%p, %s, %s.\n", iface, debugstr_time(systime), debugstr_time(offset));
+
+ EnterCriticalSection(&renderer->cs);
+
+ if (renderer->state == STREAM_STATE_STOPPED)
+ renderer->state = STREAM_STATE_RUNNING;
+
+ IMFMediaEventQueue_QueueEventParamVar(renderer->stream_event_queue, MEStreamSinkStarted, &GUID_NULL, S_OK, NULL);
+
+ LeaveCriticalSection(&renderer->cs);
+
+ return S_OK;
+}
+
+static HRESULT WINAPI video_renderer_clock_sink_OnClockStop(IMFClockStateSink *iface, MFTIME systime)
+{
+ struct video_renderer *renderer = impl_from_IMFClockStateSink(iface);
+
+ TRACE("%p, %s.\n", iface, debugstr_time(systime));
+
+ EnterCriticalSection(&renderer->cs);
+
+ renderer->state = STREAM_STATE_STOPPED;
+ IMFMediaEventQueue_QueueEventParamVar(renderer->stream_event_queue, MEStreamSinkStopped, &GUID_NULL, S_OK, NULL);
+
+ LeaveCriticalSection(&renderer->cs);
+
+ return S_OK;
+}
+
+static HRESULT WINAPI video_renderer_clock_sink_OnClockPause(IMFClockStateSink *iface, MFTIME systime)
+{
+ struct video_renderer *renderer = impl_from_IMFClockStateSink(iface);
+ HRESULT hr = S_OK;
+
+ TRACE("%p, %s.\n", iface, debugstr_time(systime));
+
+ EnterCriticalSection(&renderer->cs);
+
+ if (renderer->state == STREAM_STATE_RUNNING)
+ {
+ renderer->state = STREAM_STATE_PAUSED;
+ IMFMediaEventQueue_QueueEventParamVar(renderer->stream_event_queue, MEStreamSinkPaused, &GUID_NULL, S_OK, NULL);
+ }
+ else
+ hr = MF_E_INVALID_STATE_TRANSITION;
+
+ LeaveCriticalSection(&renderer->cs);
+
+ return hr;
+}
+
+static HRESULT WINAPI video_renderer_clock_sink_OnClockRestart(IMFClockStateSink *iface, MFTIME systime)
+{
+ struct video_renderer *renderer = impl_from_IMFClockStateSink(iface);
+
+ TRACE("%p, %s.\n", iface, debugstr_time(systime));
+
+ EnterCriticalSection(&renderer->cs);
+
+ IMFMediaEventQueue_QueueEventParamVar(renderer->stream_event_queue, MEStreamSinkStarted, &GUID_NULL, S_OK, NULL);
+
+ LeaveCriticalSection(&renderer->cs);
+
+ return S_OK;
+}
+
+static HRESULT WINAPI video_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 video_renderer_clock_sink_vtbl =
+{
+ video_renderer_clock_sink_QueryInterface,
+ video_renderer_clock_sink_AddRef,
+ video_renderer_clock_sink_Release,
+ video_renderer_clock_sink_OnClockStart,
+ video_renderer_clock_sink_OnClockStop,
+ video_renderer_clock_sink_OnClockPause,
+ video_renderer_clock_sink_OnClockRestart,
+ video_renderer_clock_sink_OnClockSetRate,
+};
+
HRESULT media_engine_create_video_renderer(IMFTopologyNode **node)
{
struct video_renderer *renderer;
@@ -638,6 +836,7 @@ HRESULT media_engine_create_video_renderer(IMFTopologyNode **node)
renderer->IMFStreamSink_iface.lpVtbl = &video_renderer_stream_vtbl;
renderer->IMFMediaTypeHandler_iface.lpVtbl = &video_renderer_stream_type_handler_vtbl;
renderer->IMFMediaEventGenerator_iface.lpVtbl = &video_renderer_events_vtbl;
+ renderer->IMFClockStateSink_iface.lpVtbl = &video_renderer_clock_sink_vtbl;
renderer->refcount = 1;
InitializeCriticalSection(&renderer->cs);
--
2.28.0
More information about the wine-devel
mailing list