wined3d: Correctly destroy the adapter on format initialization failure in no3d mode.
[wine/zf.git] / dlls / mf / evr.c
blob8a4aa3c350d4b2c0e12ecb3bf7a583c6cf6f7448
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"
25 WINE_DEFAULT_DEBUG_CHANNEL(mfplat);
27 enum video_renderer_flags
29 EVR_SHUT_DOWN = 0x1,
30 EVR_INIT_SERVICES = 0x2, /* Currently in InitServices() call. */
31 EVR_MIXER_INITED_SERVICES = 0x4,
32 EVR_PRESENTER_INITED_SERVICES = 0x8,
35 struct video_renderer
37 IMFMediaSink IMFMediaSink_iface;
38 IMFMediaSinkPreroll IMFMediaSinkPreroll_iface;
39 IMFVideoRenderer IMFVideoRenderer_iface;
40 IMFClockStateSink IMFClockStateSink_iface;
41 IMFMediaEventGenerator IMFMediaEventGenerator_iface;
42 IMFGetService IMFGetService_iface;
43 IMFTopologyServiceLookup IMFTopologyServiceLookup_iface;
44 IMediaEventSink IMediaEventSink_iface;
45 LONG refcount;
47 IMFMediaEventQueue *event_queue;
48 IMFPresentationClock *clock;
50 IMFTransform *mixer;
51 IMFVideoPresenter *presenter;
52 unsigned int flags;
53 CRITICAL_SECTION cs;
56 static struct video_renderer *impl_from_IMFMediaSink(IMFMediaSink *iface)
58 return CONTAINING_RECORD(iface, struct video_renderer, IMFMediaSink_iface);
61 static struct video_renderer *impl_from_IMFMediaSinkPreroll(IMFMediaSinkPreroll *iface)
63 return CONTAINING_RECORD(iface, struct video_renderer, IMFMediaSinkPreroll_iface);
66 static struct video_renderer *impl_from_IMFVideoRenderer(IMFVideoRenderer *iface)
68 return CONTAINING_RECORD(iface, struct video_renderer, IMFVideoRenderer_iface);
71 static struct video_renderer *impl_from_IMFMediaEventGenerator(IMFMediaEventGenerator *iface)
73 return CONTAINING_RECORD(iface, struct video_renderer, IMFMediaEventGenerator_iface);
76 static struct video_renderer *impl_from_IMFClockStateSink(IMFClockStateSink *iface)
78 return CONTAINING_RECORD(iface, struct video_renderer, IMFClockStateSink_iface);
81 static struct video_renderer *impl_from_IMFGetService(IMFGetService *iface)
83 return CONTAINING_RECORD(iface, struct video_renderer, IMFGetService_iface);
86 static struct video_renderer *impl_from_IMFTopologyServiceLookup(IMFTopologyServiceLookup *iface)
88 return CONTAINING_RECORD(iface, struct video_renderer, IMFTopologyServiceLookup_iface);
91 static struct video_renderer *impl_from_IMediaEventSink(IMediaEventSink *iface)
93 return CONTAINING_RECORD(iface, struct video_renderer, IMediaEventSink_iface);
96 static void video_renderer_release_services(struct video_renderer *renderer)
98 IMFTopologyServiceLookupClient *lookup_client;
100 if (renderer->flags & EVR_MIXER_INITED_SERVICES && SUCCEEDED(IMFTransform_QueryInterface(renderer->mixer,
101 &IID_IMFTopologyServiceLookupClient, (void **)&lookup_client)))
103 IMFTopologyServiceLookupClient_ReleaseServicePointers(lookup_client);
104 IMFTopologyServiceLookupClient_Release(lookup_client);
105 renderer->flags &= ~EVR_MIXER_INITED_SERVICES;
108 if (renderer->flags & EVR_PRESENTER_INITED_SERVICES && SUCCEEDED(IMFVideoPresenter_QueryInterface(renderer->presenter,
109 &IID_IMFTopologyServiceLookupClient, (void **)&lookup_client)))
111 IMFTopologyServiceLookupClient_ReleaseServicePointers(lookup_client);
112 IMFTopologyServiceLookupClient_Release(lookup_client);
113 renderer->flags &= ~EVR_PRESENTER_INITED_SERVICES;
117 static HRESULT WINAPI video_renderer_sink_QueryInterface(IMFMediaSink *iface, REFIID riid, void **obj)
119 struct video_renderer *renderer = impl_from_IMFMediaSink(iface);
121 TRACE("%p, %s, %p.\n", iface, debugstr_guid(riid), obj);
123 if (IsEqualIID(riid, &IID_IMFMediaSink) ||
124 IsEqualIID(riid, &IID_IUnknown))
126 *obj = &renderer->IMFMediaSink_iface;
128 else if (IsEqualIID(riid, &IID_IMFMediaSinkPreroll))
130 *obj = &renderer->IMFMediaSinkPreroll_iface;
132 else if (IsEqualIID(riid, &IID_IMFVideoRenderer))
134 *obj = &renderer->IMFVideoRenderer_iface;
136 else if (IsEqualIID(riid, &IID_IMFMediaEventGenerator))
138 *obj = &renderer->IMFMediaEventGenerator_iface;
140 else if (IsEqualIID(riid, &IID_IMFClockStateSink))
142 *obj = &renderer->IMFClockStateSink_iface;
144 else if (IsEqualIID(riid, &IID_IMFGetService))
146 *obj = &renderer->IMFGetService_iface;
148 else
150 WARN("Unsupported interface %s.\n", debugstr_guid(riid));
151 *obj = NULL;
152 return E_NOINTERFACE;
155 IUnknown_AddRef((IUnknown *)*obj);
157 return S_OK;
160 static ULONG WINAPI video_renderer_sink_AddRef(IMFMediaSink *iface)
162 struct video_renderer *renderer = impl_from_IMFMediaSink(iface);
163 ULONG refcount = InterlockedIncrement(&renderer->refcount);
164 TRACE("%p, refcount %u.\n", iface, refcount);
165 return refcount;
168 static ULONG WINAPI video_renderer_sink_Release(IMFMediaSink *iface)
170 struct video_renderer *renderer = impl_from_IMFMediaSink(iface);
171 ULONG refcount = InterlockedDecrement(&renderer->refcount);
173 TRACE("%p, refcount %u.\n", iface, refcount);
175 if (!refcount)
177 if (renderer->event_queue)
178 IMFMediaEventQueue_Release(renderer->event_queue);
179 if (renderer->mixer)
180 IMFTransform_Release(renderer->mixer);
181 if (renderer->presenter)
182 IMFVideoPresenter_Release(renderer->presenter);
183 if (renderer->clock)
184 IMFPresentationClock_Release(renderer->clock);
185 DeleteCriticalSection(&renderer->cs);
186 heap_free(renderer);
189 return refcount;
192 static HRESULT WINAPI video_renderer_sink_GetCharacteristics(IMFMediaSink *iface, DWORD *flags)
194 struct video_renderer *renderer = impl_from_IMFMediaSink(iface);
196 TRACE("%p, %p.\n", iface, flags);
198 if (renderer->flags & EVR_SHUT_DOWN)
199 return MF_E_SHUTDOWN;
201 *flags = MEDIASINK_CLOCK_REQUIRED | MEDIASINK_CAN_PREROLL;
203 return S_OK;
206 static HRESULT WINAPI video_renderer_sink_AddStreamSink(IMFMediaSink *iface, DWORD stream_sink_id,
207 IMFMediaType *media_type, IMFStreamSink **stream_sink)
209 FIXME("%p, %#x, %p, %p.\n", iface, stream_sink_id, media_type, stream_sink);
211 return E_NOTIMPL;
214 static HRESULT WINAPI video_renderer_sink_RemoveStreamSink(IMFMediaSink *iface, DWORD stream_sink_id)
216 FIXME("%p, %#x.\n", iface, stream_sink_id);
218 return E_NOTIMPL;
221 static HRESULT WINAPI video_renderer_sink_GetStreamSinkCount(IMFMediaSink *iface, DWORD *count)
223 FIXME("%p, %p.\n", iface, count);
225 return E_NOTIMPL;
228 static HRESULT WINAPI video_renderer_sink_GetStreamSinkByIndex(IMFMediaSink *iface, DWORD index,
229 IMFStreamSink **stream)
231 FIXME("%p, %u, %p.\n", iface, index, stream);
233 return E_NOTIMPL;
236 static HRESULT WINAPI video_renderer_sink_GetStreamSinkById(IMFMediaSink *iface, DWORD stream_sink_id,
237 IMFStreamSink **stream)
239 FIXME("%p, %#x, %p.\n", iface, stream_sink_id, stream);
241 return E_NOTIMPL;
244 static void video_renderer_set_presentation_clock(struct video_renderer *renderer, IMFPresentationClock *clock)
246 if (renderer->clock)
248 IMFPresentationClock_RemoveClockStateSink(renderer->clock, &renderer->IMFClockStateSink_iface);
249 IMFPresentationClock_Release(renderer->clock);
251 renderer->clock = clock;
252 if (renderer->clock)
254 IMFPresentationClock_AddRef(renderer->clock);
255 IMFPresentationClock_AddClockStateSink(renderer->clock, &renderer->IMFClockStateSink_iface);
259 static HRESULT WINAPI video_renderer_sink_SetPresentationClock(IMFMediaSink *iface, IMFPresentationClock *clock)
261 struct video_renderer *renderer = impl_from_IMFMediaSink(iface);
262 HRESULT hr = S_OK;
264 TRACE("%p, %p.\n", iface, clock);
266 EnterCriticalSection(&renderer->cs);
268 if (renderer->flags & EVR_SHUT_DOWN)
269 hr = MF_E_SHUTDOWN;
270 else
271 video_renderer_set_presentation_clock(renderer, clock);
273 LeaveCriticalSection(&renderer->cs);
275 return hr;
278 static HRESULT WINAPI video_renderer_sink_GetPresentationClock(IMFMediaSink *iface, IMFPresentationClock **clock)
280 struct video_renderer *renderer = impl_from_IMFMediaSink(iface);
281 HRESULT hr = S_OK;
283 TRACE("%p, %p.\n", iface, clock);
285 if (!clock)
286 return E_POINTER;
288 EnterCriticalSection(&renderer->cs);
290 if (renderer->flags & EVR_SHUT_DOWN)
291 hr = MF_E_SHUTDOWN;
292 else if (renderer->clock)
294 *clock = renderer->clock;
295 IMFPresentationClock_AddRef(*clock);
297 else
298 hr = MF_E_NO_CLOCK;
300 LeaveCriticalSection(&renderer->cs);
302 return hr;
305 static HRESULT WINAPI video_renderer_sink_Shutdown(IMFMediaSink *iface)
307 struct video_renderer *renderer = impl_from_IMFMediaSink(iface);
309 TRACE("%p.\n", iface);
311 if (renderer->flags & EVR_SHUT_DOWN)
312 return MF_E_SHUTDOWN;
314 EnterCriticalSection(&renderer->cs);
315 renderer->flags |= EVR_SHUT_DOWN;
316 IMFMediaEventQueue_Shutdown(renderer->event_queue);
317 video_renderer_set_presentation_clock(renderer, NULL);
318 video_renderer_release_services(renderer);
319 LeaveCriticalSection(&renderer->cs);
321 return S_OK;
324 static const IMFMediaSinkVtbl video_renderer_sink_vtbl =
326 video_renderer_sink_QueryInterface,
327 video_renderer_sink_AddRef,
328 video_renderer_sink_Release,
329 video_renderer_sink_GetCharacteristics,
330 video_renderer_sink_AddStreamSink,
331 video_renderer_sink_RemoveStreamSink,
332 video_renderer_sink_GetStreamSinkCount,
333 video_renderer_sink_GetStreamSinkByIndex,
334 video_renderer_sink_GetStreamSinkById,
335 video_renderer_sink_SetPresentationClock,
336 video_renderer_sink_GetPresentationClock,
337 video_renderer_sink_Shutdown,
340 static HRESULT WINAPI video_renderer_preroll_QueryInterface(IMFMediaSinkPreroll *iface, REFIID riid, void **obj)
342 struct video_renderer *renderer = impl_from_IMFMediaSinkPreroll(iface);
343 return IMFMediaSink_QueryInterface(&renderer->IMFMediaSink_iface, riid, obj);
346 static ULONG WINAPI video_renderer_preroll_AddRef(IMFMediaSinkPreroll *iface)
348 struct video_renderer *renderer = impl_from_IMFMediaSinkPreroll(iface);
349 return IMFMediaSink_AddRef(&renderer->IMFMediaSink_iface);
352 static ULONG WINAPI video_renderer_preroll_Release(IMFMediaSinkPreroll *iface)
354 struct video_renderer *renderer = impl_from_IMFMediaSinkPreroll(iface);
355 return IMFMediaSink_Release(&renderer->IMFMediaSink_iface);
358 static HRESULT WINAPI video_renderer_preroll_NotifyPreroll(IMFMediaSinkPreroll *iface, MFTIME start_time)
360 FIXME("%p, %s.\n", iface, debugstr_time(start_time));
362 return E_NOTIMPL;
365 static const IMFMediaSinkPrerollVtbl video_renderer_preroll_vtbl =
367 video_renderer_preroll_QueryInterface,
368 video_renderer_preroll_AddRef,
369 video_renderer_preroll_Release,
370 video_renderer_preroll_NotifyPreroll,
373 static HRESULT WINAPI video_renderer_QueryInterface(IMFVideoRenderer *iface, REFIID riid, void **obj)
375 struct video_renderer *renderer = impl_from_IMFVideoRenderer(iface);
376 return IMFMediaSink_QueryInterface(&renderer->IMFMediaSink_iface, riid, obj);
379 static ULONG WINAPI video_renderer_AddRef(IMFVideoRenderer *iface)
381 struct video_renderer *renderer = impl_from_IMFVideoRenderer(iface);
382 return IMFMediaSink_AddRef(&renderer->IMFMediaSink_iface);
385 static ULONG WINAPI video_renderer_Release(IMFVideoRenderer *iface)
387 struct video_renderer *renderer = impl_from_IMFVideoRenderer(iface);
388 return IMFMediaSink_Release(&renderer->IMFMediaSink_iface);
391 static HRESULT WINAPI video_renderer_InitializeRenderer(IMFVideoRenderer *iface, IMFTransform *mixer,
392 IMFVideoPresenter *presenter)
394 FIXME("%p, %p, %p.\n", iface, mixer, presenter);
396 return E_NOTIMPL;
399 static const IMFVideoRendererVtbl video_renderer_vtbl =
401 video_renderer_QueryInterface,
402 video_renderer_AddRef,
403 video_renderer_Release,
404 video_renderer_InitializeRenderer,
407 static HRESULT WINAPI video_renderer_events_QueryInterface(IMFMediaEventGenerator *iface, REFIID riid, void **obj)
409 struct video_renderer *renderer = impl_from_IMFMediaEventGenerator(iface);
410 return IMFMediaSink_QueryInterface(&renderer->IMFMediaSink_iface, riid, obj);
413 static ULONG WINAPI video_renderer_events_AddRef(IMFMediaEventGenerator *iface)
415 struct video_renderer *renderer = impl_from_IMFMediaEventGenerator(iface);
416 return IMFMediaSink_AddRef(&renderer->IMFMediaSink_iface);
419 static ULONG WINAPI video_renderer_events_Release(IMFMediaEventGenerator *iface)
421 struct video_renderer *renderer = impl_from_IMFMediaEventGenerator(iface);
422 return IMFMediaSink_Release(&renderer->IMFMediaSink_iface);
425 static HRESULT WINAPI video_renderer_events_GetEvent(IMFMediaEventGenerator *iface, DWORD flags, IMFMediaEvent **event)
427 struct video_renderer *renderer = impl_from_IMFMediaEventGenerator(iface);
429 TRACE("%p, %#x, %p.\n", iface, flags, event);
431 return IMFMediaEventQueue_GetEvent(renderer->event_queue, flags, event);
434 static HRESULT WINAPI video_renderer_events_BeginGetEvent(IMFMediaEventGenerator *iface, IMFAsyncCallback *callback,
435 IUnknown *state)
437 struct video_renderer *renderer = impl_from_IMFMediaEventGenerator(iface);
439 TRACE("%p, %p, %p.\n", iface, callback, state);
441 return IMFMediaEventQueue_BeginGetEvent(renderer->event_queue, callback, state);
444 static HRESULT WINAPI video_renderer_events_EndGetEvent(IMFMediaEventGenerator *iface, IMFAsyncResult *result,
445 IMFMediaEvent **event)
447 struct video_renderer *renderer = impl_from_IMFMediaEventGenerator(iface);
449 TRACE("%p, %p, %p.\n", iface, result, event);
451 return IMFMediaEventQueue_EndGetEvent(renderer->event_queue, result, event);
454 static HRESULT WINAPI video_renderer_events_QueueEvent(IMFMediaEventGenerator *iface, MediaEventType event_type,
455 REFGUID ext_type, HRESULT hr, const PROPVARIANT *value)
457 struct video_renderer *renderer = impl_from_IMFMediaEventGenerator(iface);
459 TRACE("%p, %u, %s, %#x, %p.\n", iface, event_type, debugstr_guid(ext_type), hr, value);
461 return IMFMediaEventQueue_QueueEventParamVar(renderer->event_queue, event_type, ext_type, hr, value);
464 static const IMFMediaEventGeneratorVtbl video_renderer_events_vtbl =
466 video_renderer_events_QueryInterface,
467 video_renderer_events_AddRef,
468 video_renderer_events_Release,
469 video_renderer_events_GetEvent,
470 video_renderer_events_BeginGetEvent,
471 video_renderer_events_EndGetEvent,
472 video_renderer_events_QueueEvent,
475 static HRESULT WINAPI video_renderer_clock_sink_QueryInterface(IMFClockStateSink *iface, REFIID riid, void **obj)
477 struct video_renderer *renderer = impl_from_IMFClockStateSink(iface);
478 return IMFMediaSink_QueryInterface(&renderer->IMFMediaSink_iface, riid, obj);
481 static ULONG WINAPI video_renderer_clock_sink_AddRef(IMFClockStateSink *iface)
483 struct video_renderer *renderer = impl_from_IMFClockStateSink(iface);
484 return IMFMediaSink_AddRef(&renderer->IMFMediaSink_iface);
487 static ULONG WINAPI video_renderer_clock_sink_Release(IMFClockStateSink *iface)
489 struct video_renderer *renderer = impl_from_IMFClockStateSink(iface);
490 return IMFMediaSink_Release(&renderer->IMFMediaSink_iface);
493 static HRESULT WINAPI video_renderer_clock_sink_OnClockStart(IMFClockStateSink *iface, MFTIME systime, LONGLONG offset)
495 FIXME("%p, %s, %s.\n", iface, debugstr_time(systime), debugstr_time(offset));
497 return E_NOTIMPL;
500 static HRESULT WINAPI video_renderer_clock_sink_OnClockStop(IMFClockStateSink *iface, MFTIME systime)
502 FIXME("%p, %s.\n", iface, debugstr_time(systime));
504 return E_NOTIMPL;
507 static HRESULT WINAPI video_renderer_clock_sink_OnClockPause(IMFClockStateSink *iface, MFTIME systime)
509 FIXME("%p, %s.\n", iface, debugstr_time(systime));
511 return E_NOTIMPL;
514 static HRESULT WINAPI video_renderer_clock_sink_OnClockRestart(IMFClockStateSink *iface, MFTIME systime)
516 FIXME("%p, %s.\n", iface, debugstr_time(systime));
518 return E_NOTIMPL;
521 static HRESULT WINAPI video_renderer_clock_sink_OnClockSetRate(IMFClockStateSink *iface, MFTIME systime, float rate)
523 FIXME("%p, %s, %f.\n", iface, debugstr_time(systime), rate);
525 return E_NOTIMPL;
528 static const IMFClockStateSinkVtbl video_renderer_clock_sink_vtbl =
530 video_renderer_clock_sink_QueryInterface,
531 video_renderer_clock_sink_AddRef,
532 video_renderer_clock_sink_Release,
533 video_renderer_clock_sink_OnClockStart,
534 video_renderer_clock_sink_OnClockStop,
535 video_renderer_clock_sink_OnClockPause,
536 video_renderer_clock_sink_OnClockRestart,
537 video_renderer_clock_sink_OnClockSetRate,
540 static HRESULT WINAPI video_renderer_get_service_QueryInterface(IMFGetService *iface, REFIID riid, void **obj)
542 struct video_renderer *renderer = impl_from_IMFGetService(iface);
543 return IMFMediaSink_QueryInterface(&renderer->IMFMediaSink_iface, riid, obj);
546 static ULONG WINAPI video_renderer_get_service_AddRef(IMFGetService *iface)
548 struct video_renderer *renderer = impl_from_IMFGetService(iface);
549 return IMFMediaSink_AddRef(&renderer->IMFMediaSink_iface);
552 static ULONG WINAPI video_renderer_get_service_Release(IMFGetService *iface)
554 struct video_renderer *renderer = impl_from_IMFGetService(iface);
555 return IMFMediaSink_Release(&renderer->IMFMediaSink_iface);
558 static HRESULT WINAPI video_renderer_get_service_GetService(IMFGetService *iface, REFGUID service, REFIID riid, void **obj)
560 struct video_renderer *renderer = impl_from_IMFGetService(iface);
561 HRESULT hr = E_NOINTERFACE;
562 IMFGetService *gs = NULL;
564 TRACE("%p, %s, %s, %p.\n", iface, debugstr_guid(service), debugstr_guid(riid), obj);
566 if (IsEqualGUID(service, &MR_VIDEO_MIXER_SERVICE))
568 hr = IMFTransform_QueryInterface(renderer->mixer, &IID_IMFGetService, (void **)&gs);
570 else if (IsEqualGUID(service, &MR_VIDEO_RENDER_SERVICE))
572 hr = IMFVideoPresenter_QueryInterface(renderer->presenter, &IID_IMFGetService, (void **)&gs);
574 else
576 FIXME("Unsupported service %s.\n", debugstr_guid(service));
579 if (gs)
581 hr = IMFGetService_GetService(gs, service, riid, obj);
582 IMFGetService_Release(gs);
585 return hr;
588 static const IMFGetServiceVtbl video_renderer_get_service_vtbl =
590 video_renderer_get_service_QueryInterface,
591 video_renderer_get_service_AddRef,
592 video_renderer_get_service_Release,
593 video_renderer_get_service_GetService,
596 static HRESULT WINAPI video_renderer_service_lookup_QueryInterface(IMFTopologyServiceLookup *iface, REFIID riid, void **obj)
598 TRACE("%p, %s, %p.\n", iface, debugstr_guid(riid), obj);
600 if (IsEqualIID(riid, &IID_IMFTopologyServiceLookup) ||
601 IsEqualIID(riid, &IID_IUnknown))
603 *obj = iface;
604 IMFTopologyServiceLookup_AddRef(iface);
605 return S_OK;
608 WARN("Unsupported interface %s.\n", debugstr_guid(riid));
609 *obj = NULL;
610 return E_NOINTERFACE;
613 static ULONG WINAPI video_renderer_service_lookup_AddRef(IMFTopologyServiceLookup *iface)
615 struct video_renderer *renderer = impl_from_IMFTopologyServiceLookup(iface);
616 return IMFMediaSink_AddRef(&renderer->IMFMediaSink_iface);
619 static ULONG WINAPI video_renderer_service_lookup_Release(IMFTopologyServiceLookup *iface)
621 struct video_renderer *renderer = impl_from_IMFTopologyServiceLookup(iface);
622 return IMFMediaSink_Release(&renderer->IMFMediaSink_iface);
625 static HRESULT WINAPI video_renderer_service_lookup_LookupService(IMFTopologyServiceLookup *iface,
626 MF_SERVICE_LOOKUP_TYPE lookup_type, DWORD index, REFGUID service, REFIID riid,
627 void **objects, DWORD *num_objects)
629 struct video_renderer *renderer = impl_from_IMFTopologyServiceLookup(iface);
630 HRESULT hr = S_OK;
632 TRACE("%p, %u, %u, %s, %s, %p, %p.\n", iface, lookup_type, index, debugstr_guid(service), debugstr_guid(riid),
633 objects, num_objects);
635 EnterCriticalSection(&renderer->cs);
637 if (!(renderer->flags & EVR_INIT_SERVICES))
638 hr = MF_E_NOTACCEPTING;
639 else if (IsEqualGUID(service, &MR_VIDEO_RENDER_SERVICE))
641 if (IsEqualIID(riid, &IID_IMediaEventSink))
643 *objects = &renderer->IMediaEventSink_iface;
644 IUnknown_AddRef((IUnknown *)*objects);
646 else
648 FIXME("Unsupported interface %s for render service.\n", debugstr_guid(riid));
649 hr = E_NOINTERFACE;
652 else if (IsEqualGUID(service, &MR_VIDEO_MIXER_SERVICE))
654 if (IsEqualIID(riid, &IID_IMFTransform))
656 *objects = renderer->mixer;
657 IUnknown_AddRef((IUnknown *)*objects);
659 else
661 FIXME("Unsupported interface %s for mixer service.\n", debugstr_guid(riid));
662 hr = E_NOINTERFACE;
665 else
667 WARN("Unsupported service %s.\n", debugstr_guid(service));
668 hr = MF_E_UNSUPPORTED_SERVICE;
671 LeaveCriticalSection(&renderer->cs);
673 return hr;
676 static const IMFTopologyServiceLookupVtbl video_renderer_service_lookup_vtbl =
678 video_renderer_service_lookup_QueryInterface,
679 video_renderer_service_lookup_AddRef,
680 video_renderer_service_lookup_Release,
681 video_renderer_service_lookup_LookupService,
684 static HRESULT WINAPI video_renderer_event_sink_QueryInterface(IMediaEventSink *iface, REFIID riid, void **obj)
686 TRACE("%p, %s, %p.\n", iface, debugstr_guid(riid), obj);
688 if (IsEqualIID(riid, &IID_IMediaEventSink) ||
689 IsEqualIID(riid, &IID_IUnknown))
691 *obj = iface;
692 IMediaEventSink_AddRef(iface);
693 return S_OK;
696 WARN("Unsupported interface %s.\n", debugstr_guid(riid));
697 *obj = NULL;
698 return E_NOINTERFACE;
701 static ULONG WINAPI video_renderer_event_sink_AddRef(IMediaEventSink *iface)
703 struct video_renderer *renderer = impl_from_IMediaEventSink(iface);
704 return IMFMediaSink_AddRef(&renderer->IMFMediaSink_iface);
707 static ULONG WINAPI video_renderer_event_sink_Release(IMediaEventSink *iface)
709 struct video_renderer *renderer = impl_from_IMediaEventSink(iface);
710 return IMFMediaSink_Release(&renderer->IMFMediaSink_iface);
713 static HRESULT WINAPI video_renderer_event_sink_Notify(IMediaEventSink *iface, LONG event, LONG_PTR param1, LONG_PTR param2)
715 FIXME("%p, %d, %ld, %ld.\n", iface, event, param1, param2);
717 return E_NOTIMPL;
720 static const IMediaEventSinkVtbl media_event_sink_vtbl =
722 video_renderer_event_sink_QueryInterface,
723 video_renderer_event_sink_AddRef,
724 video_renderer_event_sink_Release,
725 video_renderer_event_sink_Notify,
728 static HRESULT video_renderer_create_mixer(struct video_renderer *renderer, IMFAttributes *attributes,
729 IMFTransform **out)
731 IMFTopologyServiceLookupClient *lookup_client;
732 unsigned int flags = 0;
733 IMFActivate *activate;
734 CLSID clsid;
735 HRESULT hr;
737 if (SUCCEEDED(IMFAttributes_GetUnknown(attributes, &MF_ACTIVATE_CUSTOM_VIDEO_MIXER_ACTIVATE,
738 &IID_IMFActivate, (void **)&activate)))
740 IMFAttributes_GetUINT32(attributes, &MF_ACTIVATE_CUSTOM_VIDEO_MIXER_FLAGS, &flags);
741 hr = IMFActivate_ActivateObject(activate, &IID_IMFTransform, (void **)out);
742 IMFActivate_Release(activate);
743 if (FAILED(hr) && !(flags & MF_ACTIVATE_CUSTOM_MIXER_ALLOWFAIL))
744 return hr;
747 if (FAILED(IMFAttributes_GetGUID(attributes, &MF_ACTIVATE_CUSTOM_VIDEO_MIXER_CLSID, &clsid)))
748 memcpy(&clsid, &CLSID_MFVideoMixer9, sizeof(clsid));
750 if (SUCCEEDED(hr = CoCreateInstance(&clsid, NULL, CLSCTX_INPROC_SERVER, &IID_IMFTransform, (void **)out)))
752 if (SUCCEEDED(hr = IMFTransform_QueryInterface(*out, &IID_IMFTopologyServiceLookupClient,
753 (void **)&lookup_client)))
755 renderer->flags |= EVR_INIT_SERVICES;
756 if (SUCCEEDED(hr = IMFTopologyServiceLookupClient_InitServicePointers(lookup_client,
757 &renderer->IMFTopologyServiceLookup_iface)))
759 renderer->flags |= EVR_MIXER_INITED_SERVICES;
761 renderer->flags &= ~EVR_INIT_SERVICES;
762 IMFTopologyServiceLookupClient_Release(lookup_client);
766 return hr;
769 static HRESULT video_renderer_create_presenter(struct video_renderer *renderer, IMFAttributes *attributes,
770 IMFVideoPresenter **out)
772 IMFTopologyServiceLookupClient *lookup_client;
773 unsigned int flags = 0;
774 IMFActivate *activate;
775 CLSID clsid;
776 HRESULT hr;
778 if (SUCCEEDED(IMFAttributes_GetUnknown(attributes, &MF_ACTIVATE_CUSTOM_VIDEO_PRESENTER_ACTIVATE,
779 &IID_IMFActivate, (void **)&activate)))
781 IMFAttributes_GetUINT32(attributes, &MF_ACTIVATE_CUSTOM_VIDEO_PRESENTER_FLAGS, &flags);
782 hr = IMFActivate_ActivateObject(activate, &IID_IMFVideoPresenter, (void **)out);
783 IMFActivate_Release(activate);
784 if (FAILED(hr) && !(flags & MF_ACTIVATE_CUSTOM_PRESENTER_ALLOWFAIL))
785 return hr;
788 if (FAILED(IMFAttributes_GetGUID(attributes, &MF_ACTIVATE_CUSTOM_VIDEO_PRESENTER_CLSID, &clsid)))
789 memcpy(&clsid, &CLSID_MFVideoPresenter9, sizeof(clsid));
791 if (SUCCEEDED(hr = CoCreateInstance(&clsid, NULL, CLSCTX_INPROC_SERVER, &IID_IMFVideoPresenter, (void **)out)))
793 if (SUCCEEDED(hr = IMFVideoPresenter_QueryInterface(*out, &IID_IMFTopologyServiceLookupClient,
794 (void **)&lookup_client)))
796 renderer->flags |= EVR_INIT_SERVICES;
797 if (SUCCEEDED(hr = IMFTopologyServiceLookupClient_InitServicePointers(lookup_client,
798 &renderer->IMFTopologyServiceLookup_iface)))
800 renderer->flags |= EVR_PRESENTER_INITED_SERVICES;
802 renderer->flags &= ~EVR_INIT_SERVICES;
803 IMFTopologyServiceLookupClient_Release(lookup_client);
807 return hr;
810 static HRESULT evr_create_object(IMFAttributes *attributes, void *user_context, IUnknown **obj)
812 struct video_renderer *object;
813 HRESULT hr;
815 TRACE("%p, %p, %p.\n", attributes, user_context, obj);
817 if (!(object = heap_alloc_zero(sizeof(*object))))
818 return E_OUTOFMEMORY;
820 object->IMFMediaSink_iface.lpVtbl = &video_renderer_sink_vtbl;
821 object->IMFMediaSinkPreroll_iface.lpVtbl = &video_renderer_preroll_vtbl;
822 object->IMFVideoRenderer_iface.lpVtbl = &video_renderer_vtbl;
823 object->IMFMediaEventGenerator_iface.lpVtbl = &video_renderer_events_vtbl;
824 object->IMFClockStateSink_iface.lpVtbl = &video_renderer_clock_sink_vtbl;
825 object->IMFGetService_iface.lpVtbl = &video_renderer_get_service_vtbl;
826 object->IMFTopologyServiceLookup_iface.lpVtbl = &video_renderer_service_lookup_vtbl;
827 object->IMediaEventSink_iface.lpVtbl = &media_event_sink_vtbl;
828 object->refcount = 1;
829 InitializeCriticalSection(&object->cs);
831 if (FAILED(hr = MFCreateEventQueue(&object->event_queue)))
832 goto failed;
834 /* Create mixer and presenter. */
835 if (FAILED(hr = video_renderer_create_mixer(object, attributes, &object->mixer)))
836 goto failed;
838 if (FAILED(hr = video_renderer_create_presenter(object, attributes, &object->presenter)))
839 goto failed;
841 *obj = (IUnknown *)&object->IMFMediaSink_iface;
843 return S_OK;
845 failed:
847 video_renderer_release_services(object);
848 IMFMediaSink_Release(&object->IMFMediaSink_iface);
850 return hr;
853 static void evr_shutdown_object(void *user_context, IUnknown *obj)
855 IMFMediaSink *sink;
857 if (SUCCEEDED(IUnknown_QueryInterface(obj, &IID_IMFMediaSink, (void **)&sink)))
859 IMFMediaSink_Shutdown(sink);
860 IMFMediaSink_Release(sink);
864 static const struct activate_funcs evr_activate_funcs =
866 .create_object = evr_create_object,
867 .shutdown_object = evr_shutdown_object,
870 /***********************************************************************
871 * MFCreateVideoRendererActivate (mf.@)
873 HRESULT WINAPI MFCreateVideoRendererActivate(HWND hwnd, IMFActivate **activate)
875 HRESULT hr;
877 TRACE("%p, %p.\n", hwnd, activate);
879 if (!activate)
880 return E_POINTER;
882 hr = create_activation_object(NULL, &evr_activate_funcs, activate);
883 if (SUCCEEDED(hr))
884 IMFActivate_SetUINT64(*activate, &MF_ACTIVATE_VIDEO_WINDOW, (ULONG_PTR)hwnd);
886 return hr;