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
21 #include "mf_private.h"
25 WINE_DEFAULT_DEBUG_CHANNEL(mfplat
);
27 enum video_renderer_flags
30 EVR_INIT_SERVICES
= 0x2, /* Currently in InitServices() call. */
31 EVR_MIXER_INITED_SERVICES
= 0x4,
32 EVR_PRESENTER_INITED_SERVICES
= 0x8,
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
;
47 IMFMediaEventQueue
*event_queue
;
48 IMFPresentationClock
*clock
;
51 IMFVideoPresenter
*presenter
;
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
;
150 WARN("Unsupported interface %s.\n", debugstr_guid(riid
));
152 return E_NOINTERFACE
;
155 IUnknown_AddRef((IUnknown
*)*obj
);
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
);
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
);
177 if (renderer
->event_queue
)
178 IMFMediaEventQueue_Release(renderer
->event_queue
);
180 IMFTransform_Release(renderer
->mixer
);
181 if (renderer
->presenter
)
182 IMFVideoPresenter_Release(renderer
->presenter
);
184 IMFPresentationClock_Release(renderer
->clock
);
185 DeleteCriticalSection(&renderer
->cs
);
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
;
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
);
214 static HRESULT WINAPI
video_renderer_sink_RemoveStreamSink(IMFMediaSink
*iface
, DWORD stream_sink_id
)
216 FIXME("%p, %#x.\n", iface
, stream_sink_id
);
221 static HRESULT WINAPI
video_renderer_sink_GetStreamSinkCount(IMFMediaSink
*iface
, DWORD
*count
)
223 FIXME("%p, %p.\n", iface
, count
);
228 static HRESULT WINAPI
video_renderer_sink_GetStreamSinkByIndex(IMFMediaSink
*iface
, DWORD index
,
229 IMFStreamSink
**stream
)
231 FIXME("%p, %u, %p.\n", iface
, index
, stream
);
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
);
244 static void video_renderer_set_presentation_clock(struct video_renderer
*renderer
, IMFPresentationClock
*clock
)
248 IMFPresentationClock_RemoveClockStateSink(renderer
->clock
, &renderer
->IMFClockStateSink_iface
);
249 IMFPresentationClock_Release(renderer
->clock
);
251 renderer
->clock
= 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
);
264 TRACE("%p, %p.\n", iface
, clock
);
266 EnterCriticalSection(&renderer
->cs
);
268 if (renderer
->flags
& EVR_SHUT_DOWN
)
271 video_renderer_set_presentation_clock(renderer
, clock
);
273 LeaveCriticalSection(&renderer
->cs
);
278 static HRESULT WINAPI
video_renderer_sink_GetPresentationClock(IMFMediaSink
*iface
, IMFPresentationClock
**clock
)
280 struct video_renderer
*renderer
= impl_from_IMFMediaSink(iface
);
283 TRACE("%p, %p.\n", iface
, clock
);
288 EnterCriticalSection(&renderer
->cs
);
290 if (renderer
->flags
& EVR_SHUT_DOWN
)
292 else if (renderer
->clock
)
294 *clock
= renderer
->clock
;
295 IMFPresentationClock_AddRef(*clock
);
300 LeaveCriticalSection(&renderer
->cs
);
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
);
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
));
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
);
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
,
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
));
500 static HRESULT WINAPI
video_renderer_clock_sink_OnClockStop(IMFClockStateSink
*iface
, MFTIME systime
)
502 FIXME("%p, %s.\n", iface
, debugstr_time(systime
));
507 static HRESULT WINAPI
video_renderer_clock_sink_OnClockPause(IMFClockStateSink
*iface
, MFTIME systime
)
509 FIXME("%p, %s.\n", iface
, debugstr_time(systime
));
514 static HRESULT WINAPI
video_renderer_clock_sink_OnClockRestart(IMFClockStateSink
*iface
, MFTIME systime
)
516 FIXME("%p, %s.\n", iface
, debugstr_time(systime
));
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
);
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
);
576 FIXME("Unsupported service %s.\n", debugstr_guid(service
));
581 hr
= IMFGetService_GetService(gs
, service
, riid
, obj
);
582 IMFGetService_Release(gs
);
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
))
604 IMFTopologyServiceLookup_AddRef(iface
);
608 WARN("Unsupported interface %s.\n", debugstr_guid(riid
));
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
);
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
);
648 FIXME("Unsupported interface %s for render service.\n", debugstr_guid(riid
));
652 else if (IsEqualGUID(service
, &MR_VIDEO_MIXER_SERVICE
))
654 if (IsEqualIID(riid
, &IID_IMFTransform
))
656 *objects
= renderer
->mixer
;
657 IUnknown_AddRef((IUnknown
*)*objects
);
661 FIXME("Unsupported interface %s for mixer service.\n", debugstr_guid(riid
));
667 WARN("Unsupported service %s.\n", debugstr_guid(service
));
668 hr
= MF_E_UNSUPPORTED_SERVICE
;
671 LeaveCriticalSection(&renderer
->cs
);
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
))
692 IMediaEventSink_AddRef(iface
);
696 WARN("Unsupported interface %s.\n", debugstr_guid(riid
));
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
);
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
,
731 IMFTopologyServiceLookupClient
*lookup_client
;
732 unsigned int flags
= 0;
733 IMFActivate
*activate
;
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
))
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
);
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
;
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
))
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
);
810 static HRESULT
evr_create_object(IMFAttributes
*attributes
, void *user_context
, IUnknown
**obj
)
812 struct video_renderer
*object
;
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
)))
834 /* Create mixer and presenter. */
835 if (FAILED(hr
= video_renderer_create_mixer(object
, attributes
, &object
->mixer
)))
838 if (FAILED(hr
= video_renderer_create_presenter(object
, attributes
, &object
->presenter
)))
841 *obj
= (IUnknown
*)&object
->IMFMediaSink_iface
;
847 video_renderer_release_services(object
);
848 IMFMediaSink_Release(&object
->IMFMediaSink_iface
);
853 static void evr_shutdown_object(void *user_context
, IUnknown
*obj
)
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
)
877 TRACE("%p, %p.\n", hwnd
, activate
);
882 hr
= create_activation_object(NULL
, &evr_activate_funcs
, activate
);
884 IMFActivate_SetUINT64(*activate
, &MF_ACTIVATE_VIDEO_WINDOW
, (ULONG_PTR
)hwnd
);