mstask: Use wide-char string literals.
[wine.git] / dlls / mf / evr.c
blob8fa4e33f4e36c24fcebd8832a9762cdfb62bf2a9
1 /*
2 * Copyright 2020 Nikolay Sivov for CodeWeavers
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2.1 of the License, or (at your option) any later version.
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
19 #define COBJMACROS
21 #include "mf_private.h"
22 #include "uuids.h"
23 #include "evr.h"
24 #include "evcode.h"
25 #include "d3d9.h"
26 #include "initguid.h"
27 #include "dxva2api.h"
29 WINE_DEFAULT_DEBUG_CHANNEL(mfplat);
31 enum video_renderer_flags
33 EVR_SHUT_DOWN = 0x1,
34 EVR_INIT_SERVICES = 0x2, /* Currently in InitServices() call. */
35 EVR_MIXER_INITED_SERVICES = 0x4,
36 EVR_PRESENTER_INITED_SERVICES = 0x8,
39 enum video_renderer_state
41 EVR_STATE_STOPPED = 0,
42 EVR_STATE_RUNNING,
43 EVR_STATE_PAUSED,
46 enum video_stream_flags
48 EVR_STREAM_PREROLLING = 0x1,
49 EVR_STREAM_PREROLLED = 0x2,
52 struct video_renderer;
54 struct video_stream
56 IMFStreamSink IMFStreamSink_iface;
57 IMFMediaTypeHandler IMFMediaTypeHandler_iface;
58 IMFGetService IMFGetService_iface;
59 LONG refcount;
60 unsigned int id;
61 unsigned int flags;
62 struct video_renderer *parent;
63 IMFMediaEventQueue *event_queue;
64 IMFVideoSampleAllocator *allocator;
65 CRITICAL_SECTION cs;
68 struct video_renderer
70 IMFMediaSink IMFMediaSink_iface;
71 IMFMediaSinkPreroll IMFMediaSinkPreroll_iface;
72 IMFVideoRenderer IMFVideoRenderer_iface;
73 IMFClockStateSink IMFClockStateSink_iface;
74 IMFMediaEventGenerator IMFMediaEventGenerator_iface;
75 IMFGetService IMFGetService_iface;
76 IMFTopologyServiceLookup IMFTopologyServiceLookup_iface;
77 IMediaEventSink IMediaEventSink_iface;
78 IMFAttributes IMFAttributes_iface;
79 IMFQualityAdvise IMFQualityAdvise_iface;
80 LONG refcount;
82 IMFMediaEventQueue *event_queue;
83 IMFAttributes *attributes;
84 IMFPresentationClock *clock;
86 IMFTransform *mixer;
87 IMFVideoPresenter *presenter;
88 HWND window;
89 IUnknown *device_manager;
90 unsigned int flags;
91 unsigned int state;
93 struct video_stream **streams;
94 size_t stream_size;
95 size_t stream_count;
97 CRITICAL_SECTION cs;
100 static struct video_renderer *impl_from_IMFMediaSink(IMFMediaSink *iface)
102 return CONTAINING_RECORD(iface, struct video_renderer, IMFMediaSink_iface);
105 static struct video_renderer *impl_from_IMFMediaSinkPreroll(IMFMediaSinkPreroll *iface)
107 return CONTAINING_RECORD(iface, struct video_renderer, IMFMediaSinkPreroll_iface);
110 static struct video_renderer *impl_from_IMFVideoRenderer(IMFVideoRenderer *iface)
112 return CONTAINING_RECORD(iface, struct video_renderer, IMFVideoRenderer_iface);
115 static struct video_renderer *impl_from_IMFMediaEventGenerator(IMFMediaEventGenerator *iface)
117 return CONTAINING_RECORD(iface, struct video_renderer, IMFMediaEventGenerator_iface);
120 static struct video_renderer *impl_from_IMFClockStateSink(IMFClockStateSink *iface)
122 return CONTAINING_RECORD(iface, struct video_renderer, IMFClockStateSink_iface);
125 static struct video_renderer *impl_from_IMFGetService(IMFGetService *iface)
127 return CONTAINING_RECORD(iface, struct video_renderer, IMFGetService_iface);
130 static struct video_renderer *impl_from_IMFTopologyServiceLookup(IMFTopologyServiceLookup *iface)
132 return CONTAINING_RECORD(iface, struct video_renderer, IMFTopologyServiceLookup_iface);
135 static struct video_renderer *impl_from_IMediaEventSink(IMediaEventSink *iface)
137 return CONTAINING_RECORD(iface, struct video_renderer, IMediaEventSink_iface);
140 static struct video_renderer *impl_from_IMFAttributes(IMFAttributes *iface)
142 return CONTAINING_RECORD(iface, struct video_renderer, IMFAttributes_iface);
145 static struct video_renderer *impl_from_IMFQualityAdvise(IMFQualityAdvise *iface)
147 return CONTAINING_RECORD(iface, struct video_renderer, IMFQualityAdvise_iface);
150 static struct video_stream *impl_from_IMFStreamSink(IMFStreamSink *iface)
152 return CONTAINING_RECORD(iface, struct video_stream, IMFStreamSink_iface);
155 static struct video_stream *impl_from_IMFMediaTypeHandler(IMFMediaTypeHandler *iface)
157 return CONTAINING_RECORD(iface, struct video_stream, IMFMediaTypeHandler_iface);
160 static struct video_stream *impl_from_stream_IMFGetService(IMFGetService *iface)
162 return CONTAINING_RECORD(iface, struct video_stream, IMFGetService_iface);
165 static void video_renderer_release_services(struct video_renderer *renderer)
167 IMFTopologyServiceLookupClient *lookup_client;
169 if (renderer->flags & EVR_MIXER_INITED_SERVICES && SUCCEEDED(IMFTransform_QueryInterface(renderer->mixer,
170 &IID_IMFTopologyServiceLookupClient, (void **)&lookup_client)))
172 IMFTopologyServiceLookupClient_ReleaseServicePointers(lookup_client);
173 IMFTopologyServiceLookupClient_Release(lookup_client);
174 renderer->flags &= ~EVR_MIXER_INITED_SERVICES;
177 if (renderer->flags & EVR_PRESENTER_INITED_SERVICES && SUCCEEDED(IMFVideoPresenter_QueryInterface(renderer->presenter,
178 &IID_IMFTopologyServiceLookupClient, (void **)&lookup_client)))
180 IMFTopologyServiceLookupClient_ReleaseServicePointers(lookup_client);
181 IMFTopologyServiceLookupClient_Release(lookup_client);
182 renderer->flags &= ~EVR_PRESENTER_INITED_SERVICES;
186 static HRESULT WINAPI video_stream_sink_QueryInterface(IMFStreamSink *iface, REFIID riid, void **obj)
188 struct video_stream *stream = impl_from_IMFStreamSink(iface);
190 TRACE("%p, %s, %p.\n", iface, debugstr_guid(riid), obj);
192 *obj = NULL;
194 if (IsEqualIID(riid, &IID_IMFStreamSink) ||
195 IsEqualIID(riid, &IID_IMFMediaEventGenerator) ||
196 IsEqualIID(riid, &IID_IUnknown))
198 *obj = iface;
200 else if (IsEqualIID(riid, &IID_IMFMediaTypeHandler))
202 *obj = &stream->IMFMediaTypeHandler_iface;
204 else if (IsEqualIID(riid, &IID_IMFGetService))
206 *obj = &stream->IMFGetService_iface;
209 if (*obj)
211 IUnknown_AddRef((IUnknown *)*obj);
212 return S_OK;
215 WARN("Unsupported interface %s.\n", debugstr_guid(riid));
216 *obj = NULL;
217 return E_NOINTERFACE;
220 static ULONG WINAPI video_stream_sink_AddRef(IMFStreamSink *iface)
222 struct video_stream *stream = impl_from_IMFStreamSink(iface);
223 ULONG refcount = InterlockedIncrement(&stream->refcount);
225 TRACE("%p, refcount %u.\n", iface, refcount);
227 return refcount;
230 static ULONG WINAPI video_stream_sink_Release(IMFStreamSink *iface)
232 struct video_stream *stream = impl_from_IMFStreamSink(iface);
233 ULONG refcount = InterlockedDecrement(&stream->refcount);
235 if (!refcount)
237 if (stream->event_queue)
238 IMFMediaEventQueue_Release(stream->event_queue);
239 if (stream->allocator)
240 IMFVideoSampleAllocator_Release(stream->allocator);
241 DeleteCriticalSection(&stream->cs);
242 heap_free(stream);
245 return refcount;
248 static HRESULT WINAPI video_stream_sink_GetEvent(IMFStreamSink *iface, DWORD flags, IMFMediaEvent **event)
250 struct video_stream *stream = impl_from_IMFStreamSink(iface);
252 TRACE("%p, %#x, %p.\n", iface, flags, event);
254 return IMFMediaEventQueue_GetEvent(stream->event_queue, flags, event);
257 static HRESULT WINAPI video_stream_sink_BeginGetEvent(IMFStreamSink *iface, IMFAsyncCallback *callback, IUnknown *state)
259 struct video_stream *stream = impl_from_IMFStreamSink(iface);
261 TRACE("%p, %p, %p.\n", iface, callback, state);
263 return IMFMediaEventQueue_BeginGetEvent(stream->event_queue, callback, state);
266 static HRESULT WINAPI video_stream_sink_EndGetEvent(IMFStreamSink *iface, IMFAsyncResult *result,
267 IMFMediaEvent **event)
269 struct video_stream *stream = impl_from_IMFStreamSink(iface);
271 TRACE("%p, %p, %p.\n", iface, result, event);
273 return IMFMediaEventQueue_EndGetEvent(stream->event_queue, result, event);
276 static HRESULT WINAPI video_stream_sink_QueueEvent(IMFStreamSink *iface, MediaEventType event_type,
277 REFGUID ext_type, HRESULT hr, const PROPVARIANT *value)
279 struct video_stream *stream = impl_from_IMFStreamSink(iface);
281 TRACE("%p, %d, %s, %#x, %p.\n", iface, event_type, debugstr_guid(ext_type), hr, value);
283 return IMFMediaEventQueue_QueueEventParamVar(stream->event_queue, event_type, ext_type, hr, value);
286 static HRESULT WINAPI video_stream_sink_GetMediaSink(IMFStreamSink *iface, IMFMediaSink **sink)
288 struct video_stream *stream = impl_from_IMFStreamSink(iface);
289 HRESULT hr = S_OK;
291 TRACE("%p, %p.\n", iface, sink);
293 EnterCriticalSection(&stream->cs);
294 if (!stream->parent)
295 hr = MF_E_STREAMSINK_REMOVED;
296 else if (!sink)
297 hr = E_POINTER;
298 else
300 *sink = &stream->parent->IMFMediaSink_iface;
301 IMFMediaSink_AddRef(*sink);
303 LeaveCriticalSection(&stream->cs);
305 return hr;
308 static HRESULT WINAPI video_stream_sink_GetIdentifier(IMFStreamSink *iface, DWORD *id)
310 struct video_stream *stream = impl_from_IMFStreamSink(iface);
312 TRACE("%p, %p.\n", iface, id);
314 if (!stream->parent)
315 return MF_E_STREAMSINK_REMOVED;
317 if (!id)
318 return E_INVALIDARG;
320 *id = stream->id;
322 return S_OK;
325 static HRESULT WINAPI video_stream_sink_GetMediaTypeHandler(IMFStreamSink *iface, IMFMediaTypeHandler **handler)
327 struct video_stream *stream = impl_from_IMFStreamSink(iface);
329 TRACE("%p, %p.\n", iface, handler);
331 if (!handler)
332 return E_POINTER;
334 if (!stream->parent)
335 return MF_E_STREAMSINK_REMOVED;
337 *handler = &stream->IMFMediaTypeHandler_iface;
338 IMFMediaTypeHandler_AddRef(*handler);
340 return S_OK;
343 static HRESULT WINAPI video_stream_sink_ProcessSample(IMFStreamSink *iface, IMFSample *sample)
345 struct video_stream *stream = impl_from_IMFStreamSink(iface);
346 LONGLONG timestamp;
347 HRESULT hr = S_OK;
349 TRACE("%p, %p.\n", iface, sample);
351 EnterCriticalSection(&stream->cs);
353 if (!stream->parent)
354 hr = MF_E_STREAMSINK_REMOVED;
355 else if (!stream->parent->clock)
356 hr = MF_E_NO_CLOCK;
357 else if (FAILED(hr = IMFSample_GetSampleTime(sample, &timestamp)))
359 WARN("No sample timestamp, hr %#x.\n", hr);
361 else if (stream->parent->state == EVR_STATE_RUNNING || stream->flags & EVR_STREAM_PREROLLING)
363 if (SUCCEEDED(IMFTransform_ProcessInput(stream->parent->mixer, stream->id, sample, 0)))
364 IMFVideoPresenter_ProcessMessage(stream->parent->presenter, MFVP_MESSAGE_PROCESSINPUTNOTIFY, 0);
366 if (stream->flags & EVR_STREAM_PREROLLING)
368 IMFMediaEventQueue_QueueEventParamVar(stream->event_queue, MEStreamSinkPrerolled, &GUID_NULL, S_OK, NULL);
369 stream->flags &= ~EVR_STREAM_PREROLLING;
370 stream->flags |= EVR_STREAM_PREROLLED;
374 LeaveCriticalSection(&stream->cs);
376 return hr;
379 static HRESULT WINAPI video_stream_sink_PlaceMarker(IMFStreamSink *iface, MFSTREAMSINK_MARKER_TYPE marker_type,
380 const PROPVARIANT *marker_value, const PROPVARIANT *context_value)
382 FIXME("%p, %d, %p, %p.\n", iface, marker_type, marker_value, context_value);
384 return E_NOTIMPL;
387 static HRESULT WINAPI video_stream_sink_Flush(IMFStreamSink *iface)
389 FIXME("%p.\n", iface);
391 return E_NOTIMPL;
394 static const IMFStreamSinkVtbl video_stream_sink_vtbl =
396 video_stream_sink_QueryInterface,
397 video_stream_sink_AddRef,
398 video_stream_sink_Release,
399 video_stream_sink_GetEvent,
400 video_stream_sink_BeginGetEvent,
401 video_stream_sink_EndGetEvent,
402 video_stream_sink_QueueEvent,
403 video_stream_sink_GetMediaSink,
404 video_stream_sink_GetIdentifier,
405 video_stream_sink_GetMediaTypeHandler,
406 video_stream_sink_ProcessSample,
407 video_stream_sink_PlaceMarker,
408 video_stream_sink_Flush,
411 static HRESULT WINAPI video_stream_typehandler_QueryInterface(IMFMediaTypeHandler *iface, REFIID riid,
412 void **obj)
414 struct video_stream *stream = impl_from_IMFMediaTypeHandler(iface);
415 return IMFStreamSink_QueryInterface(&stream->IMFStreamSink_iface, riid, obj);
418 static ULONG WINAPI video_stream_typehandler_AddRef(IMFMediaTypeHandler *iface)
420 struct video_stream *stream = impl_from_IMFMediaTypeHandler(iface);
421 return IMFStreamSink_AddRef(&stream->IMFStreamSink_iface);
424 static ULONG WINAPI video_stream_typehandler_Release(IMFMediaTypeHandler *iface)
426 struct video_stream *stream = impl_from_IMFMediaTypeHandler(iface);
427 return IMFStreamSink_Release(&stream->IMFStreamSink_iface);
430 static HRESULT WINAPI video_stream_typehandler_IsMediaTypeSupported(IMFMediaTypeHandler *iface,
431 IMFMediaType *in_type, IMFMediaType **out_type)
433 struct video_stream *stream = impl_from_IMFMediaTypeHandler(iface);
434 HRESULT hr;
436 TRACE("%p, %p, %p.\n", iface, in_type, out_type);
438 if (!in_type)
439 return E_POINTER;
441 if (!stream->parent)
442 return MF_E_INVALIDMEDIATYPE;
444 if (SUCCEEDED(hr = IMFTransform_SetInputType(stream->parent->mixer, stream->id, in_type,
445 MFT_SET_TYPE_TEST_ONLY)))
447 if (out_type) *out_type = NULL;
450 return hr;
453 static HRESULT WINAPI video_stream_typehandler_GetMediaTypeCount(IMFMediaTypeHandler *iface, DWORD *count)
455 TRACE("%p, %p.\n", iface, count);
457 if (!count)
458 return E_POINTER;
460 *count = 0;
462 return S_OK;
465 static HRESULT WINAPI video_stream_typehandler_GetMediaTypeByIndex(IMFMediaTypeHandler *iface, DWORD index,
466 IMFMediaType **type)
468 TRACE("%p, %u, %p.\n", iface, index, type);
470 return MF_E_NO_MORE_TYPES;
473 static HRESULT WINAPI video_stream_typehandler_SetCurrentMediaType(IMFMediaTypeHandler *iface, IMFMediaType *type)
475 struct video_stream *stream = impl_from_IMFMediaTypeHandler(iface);
476 HRESULT hr;
478 TRACE("%p, %p.\n", iface, type);
480 if (!type)
481 return E_POINTER;
483 if (!stream->parent)
484 return MF_E_STREAMSINK_REMOVED;
486 hr = IMFTransform_SetInputType(stream->parent->mixer, stream->id, type, 0);
487 if (SUCCEEDED(hr) && !stream->id)
488 hr = IMFVideoPresenter_ProcessMessage(stream->parent->presenter, MFVP_MESSAGE_INVALIDATEMEDIATYPE, 0);
490 return hr;
493 static HRESULT WINAPI video_stream_typehandler_GetCurrentMediaType(IMFMediaTypeHandler *iface, IMFMediaType **type)
495 struct video_stream *stream = impl_from_IMFMediaTypeHandler(iface);
497 TRACE("%p, %p.\n", iface, type);
499 if (!type)
500 return E_POINTER;
502 if (!stream->parent)
503 return MF_E_STREAMSINK_REMOVED;
505 return IMFTransform_GetInputCurrentType(stream->parent->mixer, stream->id, type);
508 static HRESULT WINAPI video_stream_typehandler_GetMajorType(IMFMediaTypeHandler *iface, GUID *type)
510 struct video_stream *stream = impl_from_IMFMediaTypeHandler(iface);
512 TRACE("%p, %p.\n", iface, type);
514 if (!stream->parent)
515 return MF_E_STREAMSINK_REMOVED;
517 if (!type)
518 return E_POINTER;
520 memcpy(type, &MFMediaType_Video, sizeof(*type));
521 return S_OK;
524 static const IMFMediaTypeHandlerVtbl video_stream_type_handler_vtbl =
526 video_stream_typehandler_QueryInterface,
527 video_stream_typehandler_AddRef,
528 video_stream_typehandler_Release,
529 video_stream_typehandler_IsMediaTypeSupported,
530 video_stream_typehandler_GetMediaTypeCount,
531 video_stream_typehandler_GetMediaTypeByIndex,
532 video_stream_typehandler_SetCurrentMediaType,
533 video_stream_typehandler_GetCurrentMediaType,
534 video_stream_typehandler_GetMajorType,
537 static HRESULT WINAPI video_stream_get_service_QueryInterface(IMFGetService *iface, REFIID riid, void **obj)
539 struct video_stream *stream = impl_from_stream_IMFGetService(iface);
540 return IMFStreamSink_QueryInterface(&stream->IMFStreamSink_iface, riid, obj);
543 static ULONG WINAPI video_stream_get_service_AddRef(IMFGetService *iface)
545 struct video_stream *stream = impl_from_stream_IMFGetService(iface);
546 return IMFStreamSink_AddRef(&stream->IMFStreamSink_iface);
549 static ULONG WINAPI video_stream_get_service_Release(IMFGetService *iface)
551 struct video_stream *stream = impl_from_stream_IMFGetService(iface);
552 return IMFStreamSink_Release(&stream->IMFStreamSink_iface);
555 static HRESULT WINAPI video_stream_get_service_GetService(IMFGetService *iface, REFGUID service, REFIID riid, void **obj)
557 struct video_stream *stream = impl_from_stream_IMFGetService(iface);
558 HRESULT hr = S_OK;
560 TRACE("%p, %s, %s, %p.\n", iface, debugstr_guid(service), debugstr_guid(riid), obj);
562 if (IsEqualGUID(service, &MR_VIDEO_ACCELERATION_SERVICE))
564 if (IsEqualIID(riid, &IID_IMFVideoSampleAllocator))
566 EnterCriticalSection(&stream->cs);
568 if (!stream->allocator)
570 hr = MFCreateVideoSampleAllocator(&IID_IMFVideoSampleAllocator, (void **)&stream->allocator);
571 if (SUCCEEDED(hr))
572 hr = IMFVideoSampleAllocator_SetDirectXManager(stream->allocator, stream->parent->device_manager);
574 if (SUCCEEDED(hr))
575 hr = IMFVideoSampleAllocator_QueryInterface(stream->allocator, riid, obj);
577 LeaveCriticalSection(&stream->cs);
579 return hr;
582 return E_NOINTERFACE;
585 FIXME("Unsupported service %s.\n", debugstr_guid(service));
587 return E_NOTIMPL;
590 static const IMFGetServiceVtbl video_stream_get_service_vtbl =
592 video_stream_get_service_QueryInterface,
593 video_stream_get_service_AddRef,
594 video_stream_get_service_Release,
595 video_stream_get_service_GetService,
598 static HRESULT video_renderer_stream_create(struct video_renderer *renderer, unsigned int id,
599 struct video_stream **ret)
601 struct video_stream *stream;
602 HRESULT hr;
604 if (!(stream = heap_alloc_zero(sizeof(*stream))))
605 return E_OUTOFMEMORY;
607 stream->IMFStreamSink_iface.lpVtbl = &video_stream_sink_vtbl;
608 stream->IMFMediaTypeHandler_iface.lpVtbl = &video_stream_type_handler_vtbl;
609 stream->IMFGetService_iface.lpVtbl = &video_stream_get_service_vtbl;
610 stream->refcount = 1;
611 InitializeCriticalSection(&stream->cs);
613 if (FAILED(hr = MFCreateEventQueue(&stream->event_queue)))
614 goto failed;
616 stream->parent = renderer;
617 IMFMediaSink_AddRef(&stream->parent->IMFMediaSink_iface);
618 stream->id = id;
620 *ret = stream;
622 return S_OK;
624 failed:
626 IMFStreamSink_Release(&stream->IMFStreamSink_iface);
628 return hr;
631 static HRESULT WINAPI video_renderer_sink_QueryInterface(IMFMediaSink *iface, REFIID riid, void **obj)
633 struct video_renderer *renderer = impl_from_IMFMediaSink(iface);
635 TRACE("%p, %s, %p.\n", iface, debugstr_guid(riid), obj);
637 if (IsEqualIID(riid, &IID_IMFMediaSink) ||
638 IsEqualIID(riid, &IID_IUnknown))
640 *obj = &renderer->IMFMediaSink_iface;
642 else if (IsEqualIID(riid, &IID_IMFMediaSinkPreroll))
644 *obj = &renderer->IMFMediaSinkPreroll_iface;
646 else if (IsEqualIID(riid, &IID_IMFVideoRenderer))
648 *obj = &renderer->IMFVideoRenderer_iface;
650 else if (IsEqualIID(riid, &IID_IMFMediaEventGenerator))
652 *obj = &renderer->IMFMediaEventGenerator_iface;
654 else if (IsEqualIID(riid, &IID_IMFClockStateSink))
656 *obj = &renderer->IMFClockStateSink_iface;
658 else if (IsEqualIID(riid, &IID_IMFGetService))
660 *obj = &renderer->IMFGetService_iface;
662 else if (IsEqualIID(riid, &IID_IMFAttributes))
664 *obj = &renderer->IMFAttributes_iface;
666 else if (IsEqualIID(riid, &IID_IMFQualityAdvise))
668 *obj = &renderer->IMFQualityAdvise_iface;
670 else
672 WARN("Unsupported interface %s.\n", debugstr_guid(riid));
673 *obj = NULL;
674 return E_NOINTERFACE;
677 IUnknown_AddRef((IUnknown *)*obj);
679 return S_OK;
682 static ULONG WINAPI video_renderer_sink_AddRef(IMFMediaSink *iface)
684 struct video_renderer *renderer = impl_from_IMFMediaSink(iface);
685 ULONG refcount = InterlockedIncrement(&renderer->refcount);
686 TRACE("%p, refcount %u.\n", iface, refcount);
687 return refcount;
690 static ULONG WINAPI video_renderer_sink_Release(IMFMediaSink *iface)
692 struct video_renderer *renderer = impl_from_IMFMediaSink(iface);
693 ULONG refcount = InterlockedDecrement(&renderer->refcount);
695 TRACE("%p, refcount %u.\n", iface, refcount);
697 if (!refcount)
699 if (renderer->event_queue)
700 IMFMediaEventQueue_Release(renderer->event_queue);
701 if (renderer->mixer)
702 IMFTransform_Release(renderer->mixer);
703 if (renderer->presenter)
704 IMFVideoPresenter_Release(renderer->presenter);
705 if (renderer->device_manager)
706 IUnknown_Release(renderer->device_manager);
707 if (renderer->clock)
708 IMFPresentationClock_Release(renderer->clock);
709 if (renderer->attributes)
710 IMFAttributes_Release(renderer->attributes);
711 DeleteCriticalSection(&renderer->cs);
712 heap_free(renderer);
715 return refcount;
718 static HRESULT WINAPI video_renderer_sink_GetCharacteristics(IMFMediaSink *iface, DWORD *flags)
720 struct video_renderer *renderer = impl_from_IMFMediaSink(iface);
722 TRACE("%p, %p.\n", iface, flags);
724 if (renderer->flags & EVR_SHUT_DOWN)
725 return MF_E_SHUTDOWN;
727 *flags = MEDIASINK_CLOCK_REQUIRED | MEDIASINK_CAN_PREROLL;
729 return S_OK;
732 static HRESULT video_renderer_add_stream(struct video_renderer *renderer, unsigned int id,
733 IMFStreamSink **stream_sink)
735 struct video_stream *stream;
736 HRESULT hr;
738 if (!mf_array_reserve((void **)&renderer->streams, &renderer->stream_size, renderer->stream_count + 1,
739 sizeof(*renderer->streams)))
741 return E_OUTOFMEMORY;
744 if (SUCCEEDED(hr = video_renderer_stream_create(renderer, id, &stream)))
746 if (stream_sink)
748 *stream_sink = &stream->IMFStreamSink_iface;
749 IMFStreamSink_AddRef(*stream_sink);
751 renderer->streams[renderer->stream_count++] = stream;
754 return hr;
757 static HRESULT WINAPI video_renderer_sink_AddStreamSink(IMFMediaSink *iface, DWORD id,
758 IMFMediaType *media_type, IMFStreamSink **stream_sink)
760 struct video_renderer *renderer = impl_from_IMFMediaSink(iface);
761 HRESULT hr;
763 TRACE("%p, %#x, %p, %p.\n", iface, id, media_type, stream_sink);
765 /* Rely on mixer for stream id validation. */
767 EnterCriticalSection(&renderer->cs);
768 if (renderer->flags & EVR_SHUT_DOWN)
769 hr = MF_E_SHUTDOWN;
770 else if (SUCCEEDED(hr = IMFTransform_AddInputStreams(renderer->mixer, 1, &id)))
772 if (FAILED(hr = video_renderer_add_stream(renderer, id, stream_sink)))
773 IMFTransform_DeleteInputStream(renderer->mixer, id);
776 LeaveCriticalSection(&renderer->cs);
778 return hr;
781 static HRESULT WINAPI video_renderer_sink_RemoveStreamSink(IMFMediaSink *iface, DWORD id)
783 struct video_renderer *renderer = impl_from_IMFMediaSink(iface);
784 HRESULT hr;
785 size_t i;
787 TRACE("%p, %#x.\n", iface, id);
789 /* Rely on mixer for stream id validation. */
791 EnterCriticalSection(&renderer->cs);
792 if (renderer->flags & EVR_SHUT_DOWN)
793 hr = MF_E_SHUTDOWN;
794 else if (SUCCEEDED(hr = IMFTransform_DeleteInputStream(renderer->mixer, id)))
796 for (i = 0; i < renderer->stream_count; ++i)
798 if (renderer->streams[i]->id == id)
800 IMFStreamSink_Release(&renderer->streams[i]->IMFStreamSink_iface);
801 renderer->streams[i] = NULL;
802 if (i < renderer->stream_count - 1)
804 memmove(&renderer->streams[i], &renderer->streams[i+1],
805 (renderer->stream_count - i - 1) * sizeof(*renderer->streams));
807 renderer->stream_count--;
808 break;
812 LeaveCriticalSection(&renderer->cs);
814 return hr;
817 static HRESULT WINAPI video_renderer_sink_GetStreamSinkCount(IMFMediaSink *iface, DWORD *count)
819 struct video_renderer *renderer = impl_from_IMFMediaSink(iface);
820 HRESULT hr = S_OK;
822 TRACE("%p, %p.\n", iface, count);
824 if (!count)
825 return E_POINTER;
827 EnterCriticalSection(&renderer->cs);
828 if (renderer->flags & EVR_SHUT_DOWN)
829 hr = MF_E_SHUTDOWN;
830 else if (!count)
831 hr = E_POINTER;
832 else
833 *count = renderer->stream_count;
834 LeaveCriticalSection(&renderer->cs);
836 return hr;
839 static HRESULT WINAPI video_renderer_sink_GetStreamSinkByIndex(IMFMediaSink *iface, DWORD index,
840 IMFStreamSink **stream)
842 struct video_renderer *renderer = impl_from_IMFMediaSink(iface);
843 HRESULT hr = S_OK;
845 TRACE("%p, %u, %p.\n", iface, index, stream);
847 EnterCriticalSection(&renderer->cs);
848 if (renderer->flags & EVR_SHUT_DOWN)
849 hr = MF_E_SHUTDOWN;
850 else if (!stream)
851 hr = E_POINTER;
852 else if (index >= renderer->stream_count)
853 hr = E_INVALIDARG;
854 else
856 *stream = &renderer->streams[index]->IMFStreamSink_iface;
857 IMFStreamSink_AddRef(*stream);
859 LeaveCriticalSection(&renderer->cs);
861 return hr;
864 static HRESULT WINAPI video_renderer_sink_GetStreamSinkById(IMFMediaSink *iface, DWORD id,
865 IMFStreamSink **stream)
867 struct video_renderer *renderer = impl_from_IMFMediaSink(iface);
868 HRESULT hr = S_OK;
869 size_t i;
871 TRACE("%p, %#x, %p.\n", iface, id, stream);
873 EnterCriticalSection(&renderer->cs);
874 if (renderer->flags & EVR_SHUT_DOWN)
875 hr = MF_E_SHUTDOWN;
876 else if (!stream)
877 hr = E_POINTER;
878 else
880 for (i = 0; i < renderer->stream_count; ++i)
882 if (renderer->streams[i]->id == id)
883 break;
886 if (i == renderer->stream_count)
887 hr = MF_E_INVALIDSTREAMNUMBER;
888 else
890 *stream = &renderer->streams[i]->IMFStreamSink_iface;
891 IMFStreamSink_AddRef(*stream);
894 LeaveCriticalSection(&renderer->cs);
896 return hr;
899 static void video_renderer_set_presentation_clock(struct video_renderer *renderer, IMFPresentationClock *clock)
901 if (renderer->clock)
903 IMFPresentationClock_RemoveClockStateSink(renderer->clock, &renderer->IMFClockStateSink_iface);
904 IMFPresentationClock_Release(renderer->clock);
906 renderer->clock = clock;
907 if (renderer->clock)
909 IMFPresentationClock_AddRef(renderer->clock);
910 IMFPresentationClock_AddClockStateSink(renderer->clock, &renderer->IMFClockStateSink_iface);
914 static HRESULT WINAPI video_renderer_sink_SetPresentationClock(IMFMediaSink *iface, IMFPresentationClock *clock)
916 struct video_renderer *renderer = impl_from_IMFMediaSink(iface);
917 HRESULT hr = S_OK;
919 TRACE("%p, %p.\n", iface, clock);
921 EnterCriticalSection(&renderer->cs);
923 if (renderer->flags & EVR_SHUT_DOWN)
924 hr = MF_E_SHUTDOWN;
925 else
926 video_renderer_set_presentation_clock(renderer, clock);
928 LeaveCriticalSection(&renderer->cs);
930 return hr;
933 static HRESULT WINAPI video_renderer_sink_GetPresentationClock(IMFMediaSink *iface, IMFPresentationClock **clock)
935 struct video_renderer *renderer = impl_from_IMFMediaSink(iface);
936 HRESULT hr = S_OK;
938 TRACE("%p, %p.\n", iface, clock);
940 if (!clock)
941 return E_POINTER;
943 EnterCriticalSection(&renderer->cs);
945 if (renderer->flags & EVR_SHUT_DOWN)
946 hr = MF_E_SHUTDOWN;
947 else if (renderer->clock)
949 *clock = renderer->clock;
950 IMFPresentationClock_AddRef(*clock);
952 else
953 hr = MF_E_NO_CLOCK;
955 LeaveCriticalSection(&renderer->cs);
957 return hr;
960 static HRESULT WINAPI video_renderer_sink_Shutdown(IMFMediaSink *iface)
962 struct video_renderer *renderer = impl_from_IMFMediaSink(iface);
963 size_t i;
965 TRACE("%p.\n", iface);
967 if (renderer->flags & EVR_SHUT_DOWN)
968 return MF_E_SHUTDOWN;
970 EnterCriticalSection(&renderer->cs);
971 renderer->flags |= EVR_SHUT_DOWN;
972 /* Detach streams from the sink. */
973 for (i = 0; i < renderer->stream_count; ++i)
975 struct video_stream *stream = renderer->streams[i];
977 EnterCriticalSection(&stream->cs);
978 stream->parent = NULL;
979 LeaveCriticalSection(&stream->cs);
981 IMFMediaEventQueue_Shutdown(stream->event_queue);
982 IMFStreamSink_Release(&stream->IMFStreamSink_iface);
983 IMFMediaSink_Release(iface);
984 renderer->streams[i] = NULL;
986 heap_free(renderer->streams);
987 renderer->stream_count = 0;
988 renderer->stream_size = 0;
989 IMFMediaEventQueue_Shutdown(renderer->event_queue);
990 video_renderer_set_presentation_clock(renderer, NULL);
991 video_renderer_release_services(renderer);
992 LeaveCriticalSection(&renderer->cs);
994 return S_OK;
997 static const IMFMediaSinkVtbl video_renderer_sink_vtbl =
999 video_renderer_sink_QueryInterface,
1000 video_renderer_sink_AddRef,
1001 video_renderer_sink_Release,
1002 video_renderer_sink_GetCharacteristics,
1003 video_renderer_sink_AddStreamSink,
1004 video_renderer_sink_RemoveStreamSink,
1005 video_renderer_sink_GetStreamSinkCount,
1006 video_renderer_sink_GetStreamSinkByIndex,
1007 video_renderer_sink_GetStreamSinkById,
1008 video_renderer_sink_SetPresentationClock,
1009 video_renderer_sink_GetPresentationClock,
1010 video_renderer_sink_Shutdown,
1013 static HRESULT WINAPI video_renderer_preroll_QueryInterface(IMFMediaSinkPreroll *iface, REFIID riid, void **obj)
1015 struct video_renderer *renderer = impl_from_IMFMediaSinkPreroll(iface);
1016 return IMFMediaSink_QueryInterface(&renderer->IMFMediaSink_iface, riid, obj);
1019 static ULONG WINAPI video_renderer_preroll_AddRef(IMFMediaSinkPreroll *iface)
1021 struct video_renderer *renderer = impl_from_IMFMediaSinkPreroll(iface);
1022 return IMFMediaSink_AddRef(&renderer->IMFMediaSink_iface);
1025 static ULONG WINAPI video_renderer_preroll_Release(IMFMediaSinkPreroll *iface)
1027 struct video_renderer *renderer = impl_from_IMFMediaSinkPreroll(iface);
1028 return IMFMediaSink_Release(&renderer->IMFMediaSink_iface);
1031 static HRESULT WINAPI video_renderer_preroll_NotifyPreroll(IMFMediaSinkPreroll *iface, MFTIME start_time)
1033 struct video_renderer *renderer = impl_from_IMFMediaSinkPreroll(iface);
1034 HRESULT hr = S_OK;
1035 size_t i;
1037 TRACE("%p, %s.\n", iface, debugstr_time(start_time));
1039 EnterCriticalSection(&renderer->cs);
1040 if (renderer->flags & EVR_SHUT_DOWN)
1041 hr = MF_E_SHUTDOWN;
1042 else
1044 for (i = 0; i < renderer->stream_count; ++i)
1046 struct video_stream *stream = renderer->streams[i];
1048 EnterCriticalSection(&stream->cs);
1049 if (!(stream->flags & (EVR_STREAM_PREROLLING | EVR_STREAM_PREROLLED)))
1051 IMFMediaEventQueue_QueueEventParamVar(stream->event_queue, MEStreamSinkRequestSample,
1052 &GUID_NULL, S_OK, NULL);
1053 stream->flags |= EVR_STREAM_PREROLLING;
1055 LeaveCriticalSection(&stream->cs);
1058 LeaveCriticalSection(&renderer->cs);
1060 return hr;
1063 static const IMFMediaSinkPrerollVtbl video_renderer_preroll_vtbl =
1065 video_renderer_preroll_QueryInterface,
1066 video_renderer_preroll_AddRef,
1067 video_renderer_preroll_Release,
1068 video_renderer_preroll_NotifyPreroll,
1071 static HRESULT WINAPI video_renderer_QueryInterface(IMFVideoRenderer *iface, REFIID riid, void **obj)
1073 struct video_renderer *renderer = impl_from_IMFVideoRenderer(iface);
1074 return IMFMediaSink_QueryInterface(&renderer->IMFMediaSink_iface, riid, obj);
1077 static ULONG WINAPI video_renderer_AddRef(IMFVideoRenderer *iface)
1079 struct video_renderer *renderer = impl_from_IMFVideoRenderer(iface);
1080 return IMFMediaSink_AddRef(&renderer->IMFMediaSink_iface);
1083 static ULONG WINAPI video_renderer_Release(IMFVideoRenderer *iface)
1085 struct video_renderer *renderer = impl_from_IMFVideoRenderer(iface);
1086 return IMFMediaSink_Release(&renderer->IMFMediaSink_iface);
1089 static HRESULT video_renderer_create_mixer(IMFAttributes *attributes, IMFTransform **out)
1091 unsigned int flags = 0;
1092 IMFActivate *activate;
1093 CLSID clsid;
1094 HRESULT hr;
1096 if (attributes && SUCCEEDED(hr = IMFAttributes_GetUnknown(attributes, &MF_ACTIVATE_CUSTOM_VIDEO_MIXER_ACTIVATE,
1097 &IID_IMFActivate, (void **)&activate)))
1099 IMFAttributes_GetUINT32(attributes, &MF_ACTIVATE_CUSTOM_VIDEO_MIXER_FLAGS, &flags);
1100 hr = IMFActivate_ActivateObject(activate, &IID_IMFTransform, (void **)out);
1101 IMFActivate_Release(activate);
1102 if (SUCCEEDED(hr) || !(flags & MF_ACTIVATE_CUSTOM_MIXER_ALLOWFAIL))
1103 return hr;
1106 if (!attributes || FAILED(IMFAttributes_GetGUID(attributes, &MF_ACTIVATE_CUSTOM_VIDEO_MIXER_CLSID, &clsid)))
1107 memcpy(&clsid, &CLSID_MFVideoMixer9, sizeof(clsid));
1109 return CoCreateInstance(&clsid, NULL, CLSCTX_INPROC_SERVER, &IID_IMFTransform, (void **)out);
1112 static HRESULT video_renderer_create_presenter(struct video_renderer *renderer, IMFAttributes *attributes,
1113 IMFVideoPresenter **out)
1115 unsigned int flags = 0;
1116 IMFActivate *activate;
1117 UINT64 value;
1118 CLSID clsid;
1119 HRESULT hr;
1121 if (attributes && SUCCEEDED(IMFAttributes_GetUINT64(attributes, &MF_ACTIVATE_VIDEO_WINDOW, &value)))
1122 renderer->window = UlongToHandle(value);
1124 if (attributes && SUCCEEDED(IMFAttributes_GetUnknown(attributes, &MF_ACTIVATE_CUSTOM_VIDEO_PRESENTER_ACTIVATE,
1125 &IID_IMFActivate, (void **)&activate)))
1127 IMFAttributes_GetUINT32(attributes, &MF_ACTIVATE_CUSTOM_VIDEO_PRESENTER_FLAGS, &flags);
1128 hr = IMFActivate_ActivateObject(activate, &IID_IMFVideoPresenter, (void **)out);
1129 IMFActivate_Release(activate);
1130 if (SUCCEEDED(hr) || !(flags & MF_ACTIVATE_CUSTOM_PRESENTER_ALLOWFAIL))
1131 return hr;
1134 if (!attributes || FAILED(IMFAttributes_GetGUID(attributes, &MF_ACTIVATE_CUSTOM_VIDEO_PRESENTER_CLSID, &clsid)))
1135 memcpy(&clsid, &CLSID_MFVideoPresenter9, sizeof(clsid));
1137 return CoCreateInstance(&clsid, NULL, CLSCTX_INPROC_SERVER, &IID_IMFVideoPresenter, (void **)out);
1140 static HRESULT video_renderer_configure_mixer(struct video_renderer *renderer)
1142 IMFTopologyServiceLookupClient *lookup_client;
1143 IMFAttributes *attributes;
1144 HRESULT hr;
1146 if (SUCCEEDED(hr = IMFTransform_QueryInterface(renderer->mixer, &IID_IMFTopologyServiceLookupClient,
1147 (void **)&lookup_client)))
1149 renderer->flags |= EVR_INIT_SERVICES;
1150 if (SUCCEEDED(hr = IMFTopologyServiceLookupClient_InitServicePointers(lookup_client,
1151 &renderer->IMFTopologyServiceLookup_iface)))
1153 renderer->flags |= EVR_MIXER_INITED_SERVICES;
1155 renderer->flags &= ~EVR_INIT_SERVICES;
1156 IMFTopologyServiceLookupClient_Release(lookup_client);
1159 if (SUCCEEDED(hr))
1161 unsigned int input_count, output_count;
1162 unsigned int *ids, *oids;
1163 size_t i;
1165 /* Create stream sinks for inputs that mixer already has by default. */
1166 if (SUCCEEDED(IMFTransform_GetStreamCount(renderer->mixer, &input_count, &output_count)))
1168 ids = heap_calloc(input_count, sizeof(*ids));
1169 oids = heap_calloc(output_count, sizeof(*oids));
1171 if (ids && oids)
1173 if (SUCCEEDED(IMFTransform_GetStreamIDs(renderer->mixer, input_count, ids, output_count, oids)))
1175 for (i = 0; i < input_count; ++i)
1177 video_renderer_add_stream(renderer, ids[i], NULL);
1183 heap_free(ids);
1184 heap_free(oids);
1188 /* Set device manager that presenter should have created. */
1189 if (SUCCEEDED(IMFTransform_QueryInterface(renderer->mixer, &IID_IMFAttributes, (void **)&attributes)))
1191 IDirect3DDeviceManager9 *device_manager;
1192 unsigned int value;
1194 if (SUCCEEDED(IMFAttributes_GetUINT32(attributes, &MF_SA_D3D_AWARE, &value)) && value)
1196 if (SUCCEEDED(MFGetService((IUnknown *)renderer->presenter, &MR_VIDEO_ACCELERATION_SERVICE,
1197 &IID_IDirect3DDeviceManager9, (void **)&device_manager)))
1199 IMFTransform_ProcessMessage(renderer->mixer, MFT_MESSAGE_SET_D3D_MANAGER, (ULONG_PTR)device_manager);
1200 IDirect3DDeviceManager9_Release(device_manager);
1203 IMFAttributes_Release(attributes);
1206 return hr;
1209 static HRESULT video_renderer_configure_presenter(struct video_renderer *renderer)
1211 IMFTopologyServiceLookupClient *lookup_client;
1212 IMFVideoDisplayControl *control;
1213 HRESULT hr;
1215 if (SUCCEEDED(IMFVideoPresenter_QueryInterface(renderer->presenter, &IID_IMFVideoDisplayControl, (void **)&control)))
1217 IMFVideoDisplayControl_SetVideoWindow(control, renderer->window);
1218 IMFVideoDisplayControl_Release(control);
1221 if (SUCCEEDED(hr = IMFVideoPresenter_QueryInterface(renderer->presenter, &IID_IMFTopologyServiceLookupClient,
1222 (void **)&lookup_client)))
1224 renderer->flags |= EVR_INIT_SERVICES;
1225 if (SUCCEEDED(hr = IMFTopologyServiceLookupClient_InitServicePointers(lookup_client,
1226 &renderer->IMFTopologyServiceLookup_iface)))
1228 renderer->flags |= EVR_PRESENTER_INITED_SERVICES;
1230 renderer->flags &= ~EVR_INIT_SERVICES;
1231 IMFTopologyServiceLookupClient_Release(lookup_client);
1234 if (FAILED(MFGetService((IUnknown *)renderer->presenter, &MR_VIDEO_ACCELERATION_SERVICE,
1235 &IID_IUnknown, (void **)&renderer->device_manager)))
1237 WARN("Failed to get device manager from the presenter.\n");
1240 return hr;
1243 static HRESULT video_renderer_initialize(struct video_renderer *renderer, IMFTransform *mixer,
1244 IMFVideoPresenter *presenter)
1246 HRESULT hr;
1248 if (renderer->mixer)
1250 IMFTransform_Release(renderer->mixer);
1251 renderer->mixer = NULL;
1254 if (renderer->presenter)
1256 IMFVideoPresenter_Release(renderer->presenter);
1257 renderer->presenter = NULL;
1260 if (renderer->device_manager)
1262 IUnknown_Release(renderer->device_manager);
1263 renderer->device_manager = NULL;
1266 renderer->mixer = mixer;
1267 IMFTransform_AddRef(renderer->mixer);
1269 renderer->presenter = presenter;
1270 IMFVideoPresenter_AddRef(renderer->presenter);
1272 if (SUCCEEDED(hr = video_renderer_configure_mixer(renderer)))
1273 hr = video_renderer_configure_presenter(renderer);
1275 return hr;
1278 static HRESULT WINAPI video_renderer_InitializeRenderer(IMFVideoRenderer *iface, IMFTransform *mixer,
1279 IMFVideoPresenter *presenter)
1281 struct video_renderer *renderer = impl_from_IMFVideoRenderer(iface);
1282 HRESULT hr;
1284 TRACE("%p, %p, %p.\n", iface, mixer, presenter);
1286 if (mixer)
1287 IMFTransform_AddRef(mixer);
1288 else if (FAILED(hr = video_renderer_create_mixer(NULL, &mixer)))
1290 WARN("Failed to create default mixer object, hr %#x.\n", hr);
1291 return hr;
1294 if (presenter)
1295 IMFVideoPresenter_AddRef(presenter);
1296 else if (FAILED(hr = video_renderer_create_presenter(renderer, NULL, &presenter)))
1298 WARN("Failed to create default presenter, hr %#x.\n", hr);
1299 IMFTransform_Release(mixer);
1300 return hr;
1303 EnterCriticalSection(&renderer->cs);
1305 if (renderer->flags & EVR_SHUT_DOWN)
1306 hr = MF_E_SHUTDOWN;
1307 else
1309 /* FIXME: check clock state */
1310 /* FIXME: check that streams are not initialized */
1312 hr = video_renderer_initialize(renderer, mixer, presenter);
1315 LeaveCriticalSection(&renderer->cs);
1317 IMFTransform_Release(mixer);
1318 IMFVideoPresenter_Release(presenter);
1320 return hr;
1323 static const IMFVideoRendererVtbl video_renderer_vtbl =
1325 video_renderer_QueryInterface,
1326 video_renderer_AddRef,
1327 video_renderer_Release,
1328 video_renderer_InitializeRenderer,
1331 static HRESULT WINAPI video_renderer_events_QueryInterface(IMFMediaEventGenerator *iface, REFIID riid, void **obj)
1333 struct video_renderer *renderer = impl_from_IMFMediaEventGenerator(iface);
1334 return IMFMediaSink_QueryInterface(&renderer->IMFMediaSink_iface, riid, obj);
1337 static ULONG WINAPI video_renderer_events_AddRef(IMFMediaEventGenerator *iface)
1339 struct video_renderer *renderer = impl_from_IMFMediaEventGenerator(iface);
1340 return IMFMediaSink_AddRef(&renderer->IMFMediaSink_iface);
1343 static ULONG WINAPI video_renderer_events_Release(IMFMediaEventGenerator *iface)
1345 struct video_renderer *renderer = impl_from_IMFMediaEventGenerator(iface);
1346 return IMFMediaSink_Release(&renderer->IMFMediaSink_iface);
1349 static HRESULT WINAPI video_renderer_events_GetEvent(IMFMediaEventGenerator *iface, DWORD flags, IMFMediaEvent **event)
1351 struct video_renderer *renderer = impl_from_IMFMediaEventGenerator(iface);
1353 TRACE("%p, %#x, %p.\n", iface, flags, event);
1355 return IMFMediaEventQueue_GetEvent(renderer->event_queue, flags, event);
1358 static HRESULT WINAPI video_renderer_events_BeginGetEvent(IMFMediaEventGenerator *iface, IMFAsyncCallback *callback,
1359 IUnknown *state)
1361 struct video_renderer *renderer = impl_from_IMFMediaEventGenerator(iface);
1363 TRACE("%p, %p, %p.\n", iface, callback, state);
1365 return IMFMediaEventQueue_BeginGetEvent(renderer->event_queue, callback, state);
1368 static HRESULT WINAPI video_renderer_events_EndGetEvent(IMFMediaEventGenerator *iface, IMFAsyncResult *result,
1369 IMFMediaEvent **event)
1371 struct video_renderer *renderer = impl_from_IMFMediaEventGenerator(iface);
1373 TRACE("%p, %p, %p.\n", iface, result, event);
1375 return IMFMediaEventQueue_EndGetEvent(renderer->event_queue, result, event);
1378 static HRESULT WINAPI video_renderer_events_QueueEvent(IMFMediaEventGenerator *iface, MediaEventType event_type,
1379 REFGUID ext_type, HRESULT hr, const PROPVARIANT *value)
1381 struct video_renderer *renderer = impl_from_IMFMediaEventGenerator(iface);
1383 TRACE("%p, %u, %s, %#x, %p.\n", iface, event_type, debugstr_guid(ext_type), hr, value);
1385 return IMFMediaEventQueue_QueueEventParamVar(renderer->event_queue, event_type, ext_type, hr, value);
1388 static const IMFMediaEventGeneratorVtbl video_renderer_events_vtbl =
1390 video_renderer_events_QueryInterface,
1391 video_renderer_events_AddRef,
1392 video_renderer_events_Release,
1393 video_renderer_events_GetEvent,
1394 video_renderer_events_BeginGetEvent,
1395 video_renderer_events_EndGetEvent,
1396 video_renderer_events_QueueEvent,
1399 static HRESULT WINAPI video_renderer_clock_sink_QueryInterface(IMFClockStateSink *iface, REFIID riid, void **obj)
1401 struct video_renderer *renderer = impl_from_IMFClockStateSink(iface);
1402 return IMFMediaSink_QueryInterface(&renderer->IMFMediaSink_iface, riid, obj);
1405 static ULONG WINAPI video_renderer_clock_sink_AddRef(IMFClockStateSink *iface)
1407 struct video_renderer *renderer = impl_from_IMFClockStateSink(iface);
1408 return IMFMediaSink_AddRef(&renderer->IMFMediaSink_iface);
1411 static ULONG WINAPI video_renderer_clock_sink_Release(IMFClockStateSink *iface)
1413 struct video_renderer *renderer = impl_from_IMFClockStateSink(iface);
1414 return IMFMediaSink_Release(&renderer->IMFMediaSink_iface);
1417 static HRESULT WINAPI video_renderer_clock_sink_OnClockStart(IMFClockStateSink *iface, MFTIME systime, LONGLONG offset)
1419 struct video_renderer *renderer = impl_from_IMFClockStateSink(iface);
1420 size_t i;
1422 TRACE("%p, %s, %s.\n", iface, debugstr_time(systime), debugstr_time(offset));
1424 EnterCriticalSection(&renderer->cs);
1426 if (renderer->state == EVR_STATE_STOPPED)
1428 IMFTransform_ProcessMessage(renderer->mixer, MFT_MESSAGE_NOTIFY_BEGIN_STREAMING, 0);
1429 IMFVideoPresenter_ProcessMessage(renderer->presenter, MFVP_MESSAGE_BEGINSTREAMING, 0);
1431 for (i = 0; i < renderer->stream_count; ++i)
1433 struct video_stream *stream = renderer->streams[i];
1435 IMFMediaEventQueue_QueueEventParamVar(stream->event_queue, MEStreamSinkStarted, &GUID_NULL, S_OK, NULL);
1437 EnterCriticalSection(&stream->cs);
1438 if (!(stream->flags & EVR_STREAM_PREROLLED))
1439 IMFMediaEventQueue_QueueEventParamVar(stream->event_queue, MEStreamSinkRequestSample,
1440 &GUID_NULL, S_OK, NULL);
1441 stream->flags |= EVR_STREAM_PREROLLED;
1442 LeaveCriticalSection(&stream->cs);
1446 renderer->state = EVR_STATE_RUNNING;
1448 IMFVideoPresenter_OnClockStart(renderer->presenter, systime, offset);
1450 LeaveCriticalSection(&renderer->cs);
1452 return S_OK;
1455 static HRESULT WINAPI video_renderer_clock_sink_OnClockStop(IMFClockStateSink *iface, MFTIME systime)
1457 struct video_renderer *renderer = impl_from_IMFClockStateSink(iface);
1458 size_t i;
1460 TRACE("%p, %s.\n", iface, debugstr_time(systime));
1462 EnterCriticalSection(&renderer->cs);
1464 IMFVideoPresenter_OnClockStop(renderer->presenter, systime);
1466 IMFTransform_ProcessMessage(renderer->mixer, MFT_MESSAGE_COMMAND_FLUSH, 0);
1467 IMFVideoPresenter_ProcessMessage(renderer->presenter, MFVP_MESSAGE_FLUSH, 0);
1469 if (renderer->state == EVR_STATE_RUNNING ||
1470 renderer->state == EVR_STATE_PAUSED)
1472 IMFTransform_ProcessMessage(renderer->mixer, MFT_MESSAGE_NOTIFY_END_STREAMING, 0);
1473 IMFVideoPresenter_ProcessMessage(renderer->presenter, MFVP_MESSAGE_ENDSTREAMING, 0);
1475 for (i = 0; i < renderer->stream_count; ++i)
1477 struct video_stream *stream = renderer->streams[i];
1478 IMFMediaEventQueue_QueueEventParamVar(stream->event_queue, MEStreamSinkStopped, &GUID_NULL, S_OK, NULL);
1480 EnterCriticalSection(&stream->cs);
1481 stream->flags &= ~EVR_STREAM_PREROLLED;
1482 LeaveCriticalSection(&stream->cs);
1484 renderer->state = EVR_STATE_STOPPED;
1487 LeaveCriticalSection(&renderer->cs);
1489 return S_OK;
1492 static HRESULT WINAPI video_renderer_clock_sink_OnClockPause(IMFClockStateSink *iface, MFTIME systime)
1494 struct video_renderer *renderer = impl_from_IMFClockStateSink(iface);
1495 size_t i;
1497 TRACE("%p, %s.\n", iface, debugstr_time(systime));
1499 EnterCriticalSection(&renderer->cs);
1501 IMFVideoPresenter_OnClockPause(renderer->presenter, systime);
1503 if (renderer->state == EVR_STATE_RUNNING)
1505 for (i = 0; i < renderer->stream_count; ++i)
1507 struct video_stream *stream = renderer->streams[i];
1508 IMFMediaEventQueue_QueueEventParamVar(stream->event_queue, MEStreamSinkPaused, &GUID_NULL, S_OK, NULL);
1512 renderer->state = EVR_STATE_PAUSED;
1514 LeaveCriticalSection(&renderer->cs);
1516 return S_OK;
1519 static HRESULT WINAPI video_renderer_clock_sink_OnClockRestart(IMFClockStateSink *iface, MFTIME systime)
1521 struct video_renderer *renderer = impl_from_IMFClockStateSink(iface);
1522 size_t i;
1524 TRACE("%p, %s.\n", iface, debugstr_time(systime));
1526 EnterCriticalSection(&renderer->cs);
1528 IMFVideoPresenter_OnClockRestart(renderer->presenter, systime);
1530 for (i = 0; i < renderer->stream_count; ++i)
1532 struct video_stream *stream = renderer->streams[i];
1533 IMFMediaEventQueue_QueueEventParamVar(stream->event_queue, MEStreamSinkStarted, &GUID_NULL, S_OK, NULL);
1535 renderer->state = EVR_STATE_RUNNING;
1537 LeaveCriticalSection(&renderer->cs);
1539 return S_OK;
1542 static HRESULT WINAPI video_renderer_clock_sink_OnClockSetRate(IMFClockStateSink *iface, MFTIME systime, float rate)
1544 struct video_renderer *renderer = impl_from_IMFClockStateSink(iface);
1545 IMFClockStateSink *sink;
1547 TRACE("%p, %s, %f.\n", iface, debugstr_time(systime), rate);
1549 EnterCriticalSection(&renderer->cs);
1551 IMFVideoPresenter_OnClockSetRate(renderer->presenter, systime, rate);
1552 if (SUCCEEDED(IMFTransform_QueryInterface(renderer->mixer, &IID_IMFClockStateSink, (void **)&sink)))
1554 IMFClockStateSink_OnClockSetRate(sink, systime, rate);
1555 IMFClockStateSink_Release(sink);
1558 LeaveCriticalSection(&renderer->cs);
1560 return S_OK;
1563 static const IMFClockStateSinkVtbl video_renderer_clock_sink_vtbl =
1565 video_renderer_clock_sink_QueryInterface,
1566 video_renderer_clock_sink_AddRef,
1567 video_renderer_clock_sink_Release,
1568 video_renderer_clock_sink_OnClockStart,
1569 video_renderer_clock_sink_OnClockStop,
1570 video_renderer_clock_sink_OnClockPause,
1571 video_renderer_clock_sink_OnClockRestart,
1572 video_renderer_clock_sink_OnClockSetRate,
1575 static HRESULT WINAPI video_renderer_get_service_QueryInterface(IMFGetService *iface, REFIID riid, void **obj)
1577 struct video_renderer *renderer = impl_from_IMFGetService(iface);
1578 return IMFMediaSink_QueryInterface(&renderer->IMFMediaSink_iface, riid, obj);
1581 static ULONG WINAPI video_renderer_get_service_AddRef(IMFGetService *iface)
1583 struct video_renderer *renderer = impl_from_IMFGetService(iface);
1584 return IMFMediaSink_AddRef(&renderer->IMFMediaSink_iface);
1587 static ULONG WINAPI video_renderer_get_service_Release(IMFGetService *iface)
1589 struct video_renderer *renderer = impl_from_IMFGetService(iface);
1590 return IMFMediaSink_Release(&renderer->IMFMediaSink_iface);
1593 static HRESULT WINAPI video_renderer_get_service_GetService(IMFGetService *iface, REFGUID service, REFIID riid, void **obj)
1595 struct video_renderer *renderer = impl_from_IMFGetService(iface);
1596 HRESULT hr = E_NOINTERFACE;
1597 IMFGetService *gs = NULL;
1599 TRACE("%p, %s, %s, %p.\n", iface, debugstr_guid(service), debugstr_guid(riid), obj);
1601 if (IsEqualGUID(service, &MR_VIDEO_MIXER_SERVICE))
1603 hr = IMFTransform_QueryInterface(renderer->mixer, &IID_IMFGetService, (void **)&gs);
1605 else if (IsEqualGUID(service, &MR_VIDEO_RENDER_SERVICE))
1607 hr = IMFVideoPresenter_QueryInterface(renderer->presenter, &IID_IMFGetService, (void **)&gs);
1609 else
1611 FIXME("Unsupported service %s.\n", debugstr_guid(service));
1614 if (gs)
1616 hr = IMFGetService_GetService(gs, service, riid, obj);
1617 IMFGetService_Release(gs);
1620 return hr;
1623 static const IMFGetServiceVtbl video_renderer_get_service_vtbl =
1625 video_renderer_get_service_QueryInterface,
1626 video_renderer_get_service_AddRef,
1627 video_renderer_get_service_Release,
1628 video_renderer_get_service_GetService,
1631 static HRESULT WINAPI video_renderer_service_lookup_QueryInterface(IMFTopologyServiceLookup *iface, REFIID riid, void **obj)
1633 TRACE("%p, %s, %p.\n", iface, debugstr_guid(riid), obj);
1635 if (IsEqualIID(riid, &IID_IMFTopologyServiceLookup) ||
1636 IsEqualIID(riid, &IID_IUnknown))
1638 *obj = iface;
1639 IMFTopologyServiceLookup_AddRef(iface);
1640 return S_OK;
1643 WARN("Unsupported interface %s.\n", debugstr_guid(riid));
1644 *obj = NULL;
1645 return E_NOINTERFACE;
1648 static ULONG WINAPI video_renderer_service_lookup_AddRef(IMFTopologyServiceLookup *iface)
1650 struct video_renderer *renderer = impl_from_IMFTopologyServiceLookup(iface);
1651 return IMFMediaSink_AddRef(&renderer->IMFMediaSink_iface);
1654 static ULONG WINAPI video_renderer_service_lookup_Release(IMFTopologyServiceLookup *iface)
1656 struct video_renderer *renderer = impl_from_IMFTopologyServiceLookup(iface);
1657 return IMFMediaSink_Release(&renderer->IMFMediaSink_iface);
1660 static HRESULT WINAPI video_renderer_service_lookup_LookupService(IMFTopologyServiceLookup *iface,
1661 MF_SERVICE_LOOKUP_TYPE lookup_type, DWORD index, REFGUID service, REFIID riid,
1662 void **objects, DWORD *num_objects)
1664 struct video_renderer *renderer = impl_from_IMFTopologyServiceLookup(iface);
1665 HRESULT hr = S_OK;
1667 TRACE("%p, %u, %u, %s, %s, %p, %p.\n", iface, lookup_type, index, debugstr_guid(service), debugstr_guid(riid),
1668 objects, num_objects);
1670 EnterCriticalSection(&renderer->cs);
1672 if (!(renderer->flags & EVR_INIT_SERVICES))
1673 hr = MF_E_NOTACCEPTING;
1674 else if (IsEqualGUID(service, &MR_VIDEO_RENDER_SERVICE))
1676 if (IsEqualIID(riid, &IID_IMediaEventSink))
1678 *objects = &renderer->IMediaEventSink_iface;
1679 IUnknown_AddRef((IUnknown *)*objects);
1681 else
1683 FIXME("Unsupported interface %s for render service.\n", debugstr_guid(riid));
1684 hr = E_NOINTERFACE;
1687 else if (IsEqualGUID(service, &MR_VIDEO_MIXER_SERVICE))
1689 if (IsEqualIID(riid, &IID_IMFTransform))
1691 *objects = renderer->mixer;
1692 IUnknown_AddRef((IUnknown *)*objects);
1694 else
1696 FIXME("Unsupported interface %s for mixer service.\n", debugstr_guid(riid));
1697 hr = E_NOINTERFACE;
1700 else
1702 WARN("Unsupported service %s.\n", debugstr_guid(service));
1703 hr = MF_E_UNSUPPORTED_SERVICE;
1706 LeaveCriticalSection(&renderer->cs);
1708 return hr;
1711 static const IMFTopologyServiceLookupVtbl video_renderer_service_lookup_vtbl =
1713 video_renderer_service_lookup_QueryInterface,
1714 video_renderer_service_lookup_AddRef,
1715 video_renderer_service_lookup_Release,
1716 video_renderer_service_lookup_LookupService,
1719 static HRESULT WINAPI video_renderer_event_sink_QueryInterface(IMediaEventSink *iface, REFIID riid, void **obj)
1721 TRACE("%p, %s, %p.\n", iface, debugstr_guid(riid), obj);
1723 if (IsEqualIID(riid, &IID_IMediaEventSink) ||
1724 IsEqualIID(riid, &IID_IUnknown))
1726 *obj = iface;
1727 IMediaEventSink_AddRef(iface);
1728 return S_OK;
1731 WARN("Unsupported interface %s.\n", debugstr_guid(riid));
1732 *obj = NULL;
1733 return E_NOINTERFACE;
1736 static ULONG WINAPI video_renderer_event_sink_AddRef(IMediaEventSink *iface)
1738 struct video_renderer *renderer = impl_from_IMediaEventSink(iface);
1739 return IMFMediaSink_AddRef(&renderer->IMFMediaSink_iface);
1742 static ULONG WINAPI video_renderer_event_sink_Release(IMediaEventSink *iface)
1744 struct video_renderer *renderer = impl_from_IMediaEventSink(iface);
1745 return IMFMediaSink_Release(&renderer->IMFMediaSink_iface);
1748 static HRESULT WINAPI video_renderer_event_sink_Notify(IMediaEventSink *iface, LONG event, LONG_PTR param1, LONG_PTR param2)
1750 struct video_renderer *renderer = impl_from_IMediaEventSink(iface);
1751 HRESULT hr = S_OK;
1752 unsigned int idx;
1754 TRACE("%p, %d, %ld, %ld.\n", iface, event, param1, param2);
1756 EnterCriticalSection(&renderer->cs);
1758 if (event == EC_SAMPLE_NEEDED)
1760 idx = param1;
1761 if (idx >= renderer->stream_count)
1762 hr = MF_E_INVALIDSTREAMNUMBER;
1763 else
1765 hr = IMFMediaEventQueue_QueueEventParamVar(renderer->streams[idx]->event_queue,
1766 MEStreamSinkRequestSample, &GUID_NULL, S_OK, NULL);
1769 else if (event >= EC_USER)
1771 PROPVARIANT code;
1773 code.vt = VT_I4;
1774 code.lVal = event;
1775 hr = IMFMediaEventQueue_QueueEventParamVar(renderer->event_queue, MERendererEvent,
1776 &GUID_NULL, S_OK, &code);
1778 else
1780 WARN("Unhandled event %d.\n", event);
1781 hr = MF_E_UNEXPECTED;
1784 LeaveCriticalSection(&renderer->cs);
1786 return hr;
1789 static const IMediaEventSinkVtbl media_event_sink_vtbl =
1791 video_renderer_event_sink_QueryInterface,
1792 video_renderer_event_sink_AddRef,
1793 video_renderer_event_sink_Release,
1794 video_renderer_event_sink_Notify,
1797 static HRESULT WINAPI video_renderer_attributes_QueryInterface(IMFAttributes *iface, REFIID riid, void **obj)
1799 struct video_renderer *renderer = impl_from_IMFAttributes(iface);
1800 return IMFMediaSink_QueryInterface(&renderer->IMFMediaSink_iface, riid, obj);
1803 static ULONG WINAPI video_renderer_attributes_AddRef(IMFAttributes *iface)
1805 struct video_renderer *renderer = impl_from_IMFAttributes(iface);
1806 return IMFMediaSink_AddRef(&renderer->IMFMediaSink_iface);
1809 static ULONG WINAPI video_renderer_attributes_Release(IMFAttributes *iface)
1811 struct video_renderer *renderer = impl_from_IMFAttributes(iface);
1812 return IMFMediaSink_Release(&renderer->IMFMediaSink_iface);
1815 static HRESULT WINAPI video_renderer_attributes_GetItem(IMFAttributes *iface, REFGUID key, PROPVARIANT *value)
1817 struct video_renderer *renderer = impl_from_IMFAttributes(iface);
1819 TRACE("%p, %s, %p.\n", iface, debugstr_guid(key), value);
1821 return IMFAttributes_GetItem(renderer->attributes, key, value);
1824 static HRESULT WINAPI video_renderer_attributes_GetItemType(IMFAttributes *iface, REFGUID key, MF_ATTRIBUTE_TYPE *type)
1826 struct video_renderer *renderer = impl_from_IMFAttributes(iface);
1828 TRACE("%p, %s, %p.\n", iface, debugstr_guid(key), type);
1830 return IMFAttributes_GetItemType(renderer->attributes, key, type);
1833 static HRESULT WINAPI video_renderer_attributes_CompareItem(IMFAttributes *iface, REFGUID key, REFPROPVARIANT value,
1834 BOOL *result)
1836 struct video_renderer *renderer = impl_from_IMFAttributes(iface);
1838 TRACE("%p, %s, %p, %p.\n", iface, debugstr_guid(key), value, result);
1840 return IMFAttributes_CompareItem(renderer->attributes, key, value, result);
1843 static HRESULT WINAPI video_renderer_attributes_Compare(IMFAttributes *iface, IMFAttributes *theirs,
1844 MF_ATTRIBUTES_MATCH_TYPE type, BOOL *result)
1846 struct video_renderer *renderer = impl_from_IMFAttributes(iface);
1848 TRACE("%p, %p, %d, %p.\n", iface, theirs, type, result);
1850 return IMFAttributes_Compare(renderer->attributes, theirs, type, result);
1853 static HRESULT WINAPI video_renderer_attributes_GetUINT32(IMFAttributes *iface, REFGUID key, UINT32 *value)
1855 struct video_renderer *renderer = impl_from_IMFAttributes(iface);
1857 TRACE("%p, %s, %p.\n", iface, debugstr_guid(key), value);
1859 return IMFAttributes_GetUINT32(renderer->attributes, key, value);
1862 static HRESULT WINAPI video_renderer_attributes_GetUINT64(IMFAttributes *iface, REFGUID key, UINT64 *value)
1864 struct video_renderer *renderer = impl_from_IMFAttributes(iface);
1866 TRACE("%p, %s, %p.\n", iface, debugstr_guid(key), value);
1868 return IMFAttributes_GetUINT64(renderer->attributes, key, value);
1871 static HRESULT WINAPI video_renderer_attributes_GetDouble(IMFAttributes *iface, REFGUID key, double *value)
1873 struct video_renderer *renderer = impl_from_IMFAttributes(iface);
1875 TRACE("%p, %s, %p.\n", iface, debugstr_guid(key), value);
1877 return IMFAttributes_GetDouble(renderer->attributes, key, value);
1880 static HRESULT WINAPI video_renderer_attributes_GetGUID(IMFAttributes *iface, REFGUID key, GUID *value)
1882 struct video_renderer *renderer = impl_from_IMFAttributes(iface);
1884 TRACE("%p, %s, %p.\n", iface, debugstr_guid(key), value);
1886 return IMFAttributes_GetGUID(renderer->attributes, key, value);
1889 static HRESULT WINAPI video_renderer_attributes_GetStringLength(IMFAttributes *iface, REFGUID key,
1890 UINT32 *length)
1892 struct video_renderer *renderer = impl_from_IMFAttributes(iface);
1894 TRACE("%p, %s, %p.\n", iface, debugstr_guid(key), length);
1896 return IMFAttributes_GetStringLength(renderer->attributes, key, length);
1899 static HRESULT WINAPI video_renderer_attributes_GetString(IMFAttributes *iface, REFGUID key, WCHAR *value,
1900 UINT32 size, UINT32 *length)
1902 struct video_renderer *renderer = impl_from_IMFAttributes(iface);
1904 TRACE("%p, %s, %p, %u, %p.\n", iface, debugstr_guid(key), value, size, length);
1906 return IMFAttributes_GetString(renderer->attributes, key, value, size, length);
1909 static HRESULT WINAPI video_renderer_attributes_GetAllocatedString(IMFAttributes *iface, REFGUID key,
1910 WCHAR **value, UINT32 *length)
1912 struct video_renderer *renderer = impl_from_IMFAttributes(iface);
1914 TRACE("%p, %s, %p, %p.\n", iface, debugstr_guid(key), value, length);
1916 return IMFAttributes_GetAllocatedString(renderer->attributes, key, value, length);
1919 static HRESULT WINAPI video_renderer_attributes_GetBlobSize(IMFAttributes *iface, REFGUID key, UINT32 *size)
1921 struct video_renderer *renderer = impl_from_IMFAttributes(iface);
1923 TRACE("%p, %s, %p.\n", iface, debugstr_guid(key), size);
1925 return IMFAttributes_GetBlobSize(renderer->attributes, key, size);
1928 static HRESULT WINAPI video_renderer_attributes_GetBlob(IMFAttributes *iface, REFGUID key, UINT8 *buf,
1929 UINT32 bufsize, UINT32 *blobsize)
1931 struct video_renderer *renderer = impl_from_IMFAttributes(iface);
1933 TRACE("%p, %s, %p, %u, %p.\n", iface, debugstr_guid(key), buf, bufsize, blobsize);
1935 return IMFAttributes_GetBlob(renderer->attributes, key, buf, bufsize, blobsize);
1938 static HRESULT WINAPI video_renderer_attributes_GetAllocatedBlob(IMFAttributes *iface, REFGUID key,
1939 UINT8 **buf, UINT32 *size)
1941 struct video_renderer *renderer = impl_from_IMFAttributes(iface);
1943 TRACE("%p, %s, %p, %p.\n", iface, debugstr_guid(key), buf, size);
1945 return IMFAttributes_GetAllocatedBlob(renderer->attributes, key, buf, size);
1948 static HRESULT WINAPI video_renderer_attributes_GetUnknown(IMFAttributes *iface, REFGUID key, REFIID riid, void **out)
1950 struct video_renderer *renderer = impl_from_IMFAttributes(iface);
1952 TRACE("%p, %s, %s, %p.\n", iface, debugstr_guid(key), debugstr_guid(riid), out);
1954 return IMFAttributes_GetUnknown(renderer->attributes, key, riid, out);
1957 static HRESULT WINAPI video_renderer_attributes_SetItem(IMFAttributes *iface, REFGUID key, REFPROPVARIANT value)
1959 struct video_renderer *renderer = impl_from_IMFAttributes(iface);
1961 TRACE("%p, %s, %p.\n", iface, debugstr_guid(key), value);
1963 return IMFAttributes_SetItem(renderer->attributes, key, value);
1966 static HRESULT WINAPI video_renderer_attributes_DeleteItem(IMFAttributes *iface, REFGUID key)
1968 struct video_renderer *renderer = impl_from_IMFAttributes(iface);
1970 TRACE("%p, %s.\n", iface, debugstr_guid(key));
1972 return IMFAttributes_DeleteItem(renderer->attributes, key);
1975 static HRESULT WINAPI video_renderer_attributes_DeleteAllItems(IMFAttributes *iface)
1977 struct video_renderer *renderer = impl_from_IMFAttributes(iface);
1979 TRACE("%p.\n", iface);
1981 return IMFAttributes_DeleteAllItems(renderer->attributes);
1984 static HRESULT WINAPI video_renderer_attributes_SetUINT32(IMFAttributes *iface, REFGUID key, UINT32 value)
1986 struct video_renderer *renderer = impl_from_IMFAttributes(iface);
1988 TRACE("%p, %s, %u.\n", iface, debugstr_guid(key), value);
1990 return IMFAttributes_SetUINT32(renderer->attributes, key, value);
1993 static HRESULT WINAPI video_renderer_attributes_SetUINT64(IMFAttributes *iface, REFGUID key, UINT64 value)
1995 struct video_renderer *renderer = impl_from_IMFAttributes(iface);
1997 TRACE("%p, %s, %s.\n", iface, debugstr_guid(key), wine_dbgstr_longlong(value));
1999 return IMFAttributes_SetUINT64(renderer->attributes, key, value);
2002 static HRESULT WINAPI video_renderer_attributes_SetDouble(IMFAttributes *iface, REFGUID key, double value)
2004 struct video_renderer *renderer = impl_from_IMFAttributes(iface);
2006 TRACE("%p, %s, %f.\n", iface, debugstr_guid(key), value);
2008 return IMFAttributes_SetDouble(renderer->attributes, key, value);
2011 static HRESULT WINAPI video_renderer_attributes_SetGUID(IMFAttributes *iface, REFGUID key, REFGUID value)
2013 struct video_renderer *renderer = impl_from_IMFAttributes(iface);
2015 TRACE("%p, %s, %s.\n", iface, debugstr_guid(key), debugstr_guid(value));
2017 return IMFAttributes_SetGUID(renderer->attributes, key, value);
2020 static HRESULT WINAPI video_renderer_attributes_SetString(IMFAttributes *iface, REFGUID key,
2021 const WCHAR *value)
2023 struct video_renderer *renderer = impl_from_IMFAttributes(iface);
2025 TRACE("%p, %s, %s.\n", iface, debugstr_guid(key), debugstr_w(value));
2027 return IMFAttributes_SetString(renderer->attributes, key, value);
2030 static HRESULT WINAPI video_renderer_attributes_SetBlob(IMFAttributes *iface, REFGUID key,
2031 const UINT8 *buf, UINT32 size)
2033 struct video_renderer *renderer = impl_from_IMFAttributes(iface);
2035 TRACE("%p, %s, %p, %u.\n", iface, debugstr_guid(key), buf, size);
2037 return IMFAttributes_SetBlob(renderer->attributes, key, buf, size);
2040 static HRESULT WINAPI video_renderer_attributes_SetUnknown(IMFAttributes *iface, REFGUID key,
2041 IUnknown *unknown)
2043 struct video_renderer *renderer = impl_from_IMFAttributes(iface);
2045 TRACE("%p, %s, %p.\n", iface, debugstr_guid(key), unknown);
2047 return IMFAttributes_SetUnknown(renderer->attributes, key, unknown);
2050 static HRESULT WINAPI video_renderer_attributes_LockStore(IMFAttributes *iface)
2052 struct video_renderer *renderer = impl_from_IMFAttributes(iface);
2054 TRACE("%p.\n", iface);
2056 return IMFAttributes_LockStore(renderer->attributes);
2059 static HRESULT WINAPI video_renderer_attributes_UnlockStore(IMFAttributes *iface)
2061 struct video_renderer *renderer = impl_from_IMFAttributes(iface);
2063 TRACE("%p.\n", iface);
2065 return IMFAttributes_UnlockStore(renderer->attributes);
2068 static HRESULT WINAPI video_renderer_attributes_GetCount(IMFAttributes *iface, UINT32 *count)
2070 struct video_renderer *renderer = impl_from_IMFAttributes(iface);
2072 TRACE("%p, %p.\n", iface, count);
2074 return IMFAttributes_GetCount(renderer->attributes, count);
2077 static HRESULT WINAPI video_renderer_attributes_GetItemByIndex(IMFAttributes *iface, UINT32 index,
2078 GUID *key, PROPVARIANT *value)
2080 struct video_renderer *renderer = impl_from_IMFAttributes(iface);
2082 TRACE("%p, %u, %p, %p.\n", iface, index, key, value);
2084 return IMFAttributes_GetItemByIndex(renderer->attributes, index, key, value);
2087 static HRESULT WINAPI video_renderer_attributes_CopyAllItems(IMFAttributes *iface, IMFAttributes *dest)
2089 struct video_renderer *renderer = impl_from_IMFAttributes(iface);
2091 TRACE("%p, %p.\n", iface, dest);
2093 return IMFAttributes_CopyAllItems(renderer->attributes, dest);
2096 static const IMFAttributesVtbl video_renderer_attributes_vtbl =
2098 video_renderer_attributes_QueryInterface,
2099 video_renderer_attributes_AddRef,
2100 video_renderer_attributes_Release,
2101 video_renderer_attributes_GetItem,
2102 video_renderer_attributes_GetItemType,
2103 video_renderer_attributes_CompareItem,
2104 video_renderer_attributes_Compare,
2105 video_renderer_attributes_GetUINT32,
2106 video_renderer_attributes_GetUINT64,
2107 video_renderer_attributes_GetDouble,
2108 video_renderer_attributes_GetGUID,
2109 video_renderer_attributes_GetStringLength,
2110 video_renderer_attributes_GetString,
2111 video_renderer_attributes_GetAllocatedString,
2112 video_renderer_attributes_GetBlobSize,
2113 video_renderer_attributes_GetBlob,
2114 video_renderer_attributes_GetAllocatedBlob,
2115 video_renderer_attributes_GetUnknown,
2116 video_renderer_attributes_SetItem,
2117 video_renderer_attributes_DeleteItem,
2118 video_renderer_attributes_DeleteAllItems,
2119 video_renderer_attributes_SetUINT32,
2120 video_renderer_attributes_SetUINT64,
2121 video_renderer_attributes_SetDouble,
2122 video_renderer_attributes_SetGUID,
2123 video_renderer_attributes_SetString,
2124 video_renderer_attributes_SetBlob,
2125 video_renderer_attributes_SetUnknown,
2126 video_renderer_attributes_LockStore,
2127 video_renderer_attributes_UnlockStore,
2128 video_renderer_attributes_GetCount,
2129 video_renderer_attributes_GetItemByIndex,
2130 video_renderer_attributes_CopyAllItems,
2133 static HRESULT WINAPI video_renderer_quality_advise_QueryInterface(IMFQualityAdvise *iface, REFIID riid, void **out)
2135 struct video_renderer *renderer = impl_from_IMFQualityAdvise(iface);
2136 return IMFMediaSink_QueryInterface(&renderer->IMFMediaSink_iface, riid, out);
2139 static ULONG WINAPI video_renderer_quality_advise_AddRef(IMFQualityAdvise *iface)
2141 struct video_renderer *renderer = impl_from_IMFQualityAdvise(iface);
2142 return IMFMediaSink_AddRef(&renderer->IMFMediaSink_iface);
2145 static ULONG WINAPI video_renderer_quality_Release(IMFQualityAdvise *iface)
2147 struct video_renderer *renderer = impl_from_IMFQualityAdvise(iface);
2148 return IMFMediaSink_Release(&renderer->IMFMediaSink_iface);
2151 static HRESULT WINAPI video_renderer_quality_advise_SetDropMode(IMFQualityAdvise *iface,
2152 MF_QUALITY_DROP_MODE mode)
2154 FIXME("%p, %u.\n", iface, mode);
2156 return E_NOTIMPL;
2159 static HRESULT WINAPI video_renderer_quality_advise_SetQualityLevel(IMFQualityAdvise *iface,
2160 MF_QUALITY_LEVEL level)
2162 FIXME("%p, %u.\n", iface, level);
2164 return E_NOTIMPL;
2167 static HRESULT WINAPI video_renderer_quality_advise_GetDropMode(IMFQualityAdvise *iface,
2168 MF_QUALITY_DROP_MODE *mode)
2170 FIXME("%p, %p.\n", iface, mode);
2172 return E_NOTIMPL;
2175 static HRESULT WINAPI video_renderer_quality_advise_GetQualityLevel(IMFQualityAdvise *iface,
2176 MF_QUALITY_LEVEL *level)
2178 FIXME("%p, %p.\n", iface, level);
2180 return E_NOTIMPL;
2183 static HRESULT WINAPI video_renderer_quality_advise_DropTime(IMFQualityAdvise *iface, LONGLONG interval)
2185 FIXME("%p, %s.\n", iface, wine_dbgstr_longlong(interval));
2187 return E_NOTIMPL;
2190 static const IMFQualityAdviseVtbl video_renderer_quality_advise_vtbl =
2192 video_renderer_quality_advise_QueryInterface,
2193 video_renderer_quality_advise_AddRef,
2194 video_renderer_quality_Release,
2195 video_renderer_quality_advise_SetDropMode,
2196 video_renderer_quality_advise_SetQualityLevel,
2197 video_renderer_quality_advise_GetDropMode,
2198 video_renderer_quality_advise_GetQualityLevel,
2199 video_renderer_quality_advise_DropTime,
2202 static HRESULT evr_create_object(IMFAttributes *attributes, void *user_context, IUnknown **obj)
2204 struct video_renderer *object;
2205 IMFVideoPresenter *presenter = NULL;
2206 IMFTransform *mixer = NULL;
2207 HRESULT hr;
2209 TRACE("%p, %p, %p.\n", attributes, user_context, obj);
2211 if (!(object = heap_alloc_zero(sizeof(*object))))
2212 return E_OUTOFMEMORY;
2214 object->IMFMediaSink_iface.lpVtbl = &video_renderer_sink_vtbl;
2215 object->IMFMediaSinkPreroll_iface.lpVtbl = &video_renderer_preroll_vtbl;
2216 object->IMFVideoRenderer_iface.lpVtbl = &video_renderer_vtbl;
2217 object->IMFMediaEventGenerator_iface.lpVtbl = &video_renderer_events_vtbl;
2218 object->IMFClockStateSink_iface.lpVtbl = &video_renderer_clock_sink_vtbl;
2219 object->IMFGetService_iface.lpVtbl = &video_renderer_get_service_vtbl;
2220 object->IMFTopologyServiceLookup_iface.lpVtbl = &video_renderer_service_lookup_vtbl;
2221 object->IMediaEventSink_iface.lpVtbl = &media_event_sink_vtbl;
2222 object->IMFAttributes_iface.lpVtbl = &video_renderer_attributes_vtbl;
2223 object->IMFQualityAdvise_iface.lpVtbl = &video_renderer_quality_advise_vtbl;
2224 object->refcount = 1;
2225 InitializeCriticalSection(&object->cs);
2227 if (FAILED(hr = MFCreateEventQueue(&object->event_queue)))
2228 goto failed;
2230 if (FAILED(hr = MFCreateAttributes(&object->attributes, 0)))
2231 goto failed;
2233 /* Create mixer and presenter. */
2234 if (FAILED(hr = video_renderer_create_mixer(attributes, &mixer)))
2235 goto failed;
2237 if (FAILED(hr = video_renderer_create_presenter(object, attributes, &presenter)))
2238 goto failed;
2240 if (FAILED(hr = video_renderer_initialize(object, mixer, presenter)))
2241 goto failed;
2243 IMFTransform_Release(mixer);
2244 IMFVideoPresenter_Release(presenter);
2246 /* Default attributes */
2247 IMFAttributes_SetUINT32(object->attributes, &EVRConfig_ForceBob, 0);
2248 IMFAttributes_SetUINT32(object->attributes, &EVRConfig_AllowDropToBob, 0);
2249 IMFAttributes_SetUINT32(object->attributes, &EVRConfig_ForceThrottle, 0);
2250 IMFAttributes_SetUINT32(object->attributes, &EVRConfig_AllowDropToThrottle, 0);
2251 IMFAttributes_SetUINT32(object->attributes, &EVRConfig_ForceHalfInterlace, 0);
2252 IMFAttributes_SetUINT32(object->attributes, &EVRConfig_AllowDropToHalfInterlace, 0);
2253 IMFAttributes_SetUINT32(object->attributes, &EVRConfig_ForceScaling, 0);
2254 IMFAttributes_SetUINT32(object->attributes, &EVRConfig_AllowScaling, 0);
2255 IMFAttributes_SetUINT32(object->attributes, &EVRConfig_ForceBatching, 0);
2256 IMFAttributes_SetUINT32(object->attributes, &EVRConfig_AllowBatching, 0);
2258 *obj = (IUnknown *)&object->IMFMediaSink_iface;
2260 return S_OK;
2262 failed:
2264 if (mixer)
2265 IMFTransform_Release(mixer);
2267 if (presenter)
2268 IMFVideoPresenter_Release(presenter);
2270 video_renderer_release_services(object);
2271 IMFMediaSink_Release(&object->IMFMediaSink_iface);
2273 return hr;
2276 static void evr_shutdown_object(void *user_context, IUnknown *obj)
2278 IMFMediaSink *sink;
2280 if (SUCCEEDED(IUnknown_QueryInterface(obj, &IID_IMFMediaSink, (void **)&sink)))
2282 IMFMediaSink_Shutdown(sink);
2283 IMFMediaSink_Release(sink);
2287 static const struct activate_funcs evr_activate_funcs =
2289 .create_object = evr_create_object,
2290 .shutdown_object = evr_shutdown_object,
2293 /***********************************************************************
2294 * MFCreateVideoRendererActivate (mf.@)
2296 HRESULT WINAPI MFCreateVideoRendererActivate(HWND hwnd, IMFActivate **activate)
2298 HRESULT hr;
2300 TRACE("%p, %p.\n", hwnd, activate);
2302 if (!activate)
2303 return E_POINTER;
2305 hr = create_activation_object(NULL, &evr_activate_funcs, activate);
2306 if (SUCCEEDED(hr))
2307 IMFActivate_SetUINT64(*activate, &MF_ACTIVATE_VIDEO_WINDOW, (ULONG_PTR)hwnd);
2309 return hr;
2312 /***********************************************************************
2313 * MFCreateVideoRenderer (mf.@)
2315 HRESULT WINAPI MFCreateVideoRenderer(REFIID riid, void **renderer)
2317 IUnknown *obj;
2318 HRESULT hr;
2320 TRACE("%s, %p.\n", debugstr_guid(riid), renderer);
2322 *renderer = NULL;
2324 if (SUCCEEDED(hr = evr_create_object(NULL, NULL, &obj)))
2326 hr = IUnknown_QueryInterface(obj, riid, renderer);
2327 IUnknown_Release(obj);
2330 return hr;