2 * Copyright 2017 Fabian Maurer
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 "wine/debug.h"
25 #include "evr_private.h"
33 WINE_DEFAULT_DEBUG_CHANNEL(evr
);
37 EVR_INIT_SERVICES
= 0x1, /* Currently in InitServices() call. */
38 EVR_MIXER_INITED_SERVICES
= 0x2,
39 EVR_PRESENTER_INITED_SERVICES
= 0x4,
44 struct strmbase_renderer renderer
;
45 IEVRFilterConfig IEVRFilterConfig_iface
;
46 IAMFilterMiscFlags IAMFilterMiscFlags_iface
;
47 IMFGetService IMFGetService_iface
;
48 IMFVideoRenderer IMFVideoRenderer_iface
;
49 IMediaEventSink IMediaEventSink_iface
;
50 IMFTopologyServiceLookup IMFTopologyServiceLookup_iface
;
53 IMFVideoPresenter
*presenter
;
54 IMFVideoSampleAllocator
*allocator
;
55 IMFMediaType
*media_type
;
59 static void evr_uninitialize(struct evr
*filter
)
63 IMFTransform_Release(filter
->mixer
);
67 if (filter
->presenter
)
69 IMFVideoPresenter_Release(filter
->presenter
);
70 filter
->presenter
= NULL
;
74 static HRESULT
evr_initialize(struct evr
*filter
, IMFTransform
*mixer
, IMFVideoPresenter
*presenter
)
80 IMFTransform_AddRef(mixer
);
82 else if (FAILED(hr
= CoCreateInstance(&CLSID_MFVideoMixer9
, NULL
, CLSCTX_INPROC_SERVER
,
83 &IID_IMFTransform
, (void **)&mixer
)))
85 WARN("Failed to create default mixer instance, hr %#lx.\n", hr
);
91 IMFVideoPresenter_AddRef(presenter
);
93 else if (FAILED(hr
= CoCreateInstance(&CLSID_MFVideoPresenter9
, NULL
, CLSCTX_INPROC_SERVER
,
94 &IID_IMFVideoPresenter
, (void **)&presenter
)))
96 WARN("Failed to create default presenter instance, hr %#lx.\n", hr
);
97 IMFTransform_Release(mixer
);
101 evr_uninitialize(filter
);
103 filter
->mixer
= mixer
;
104 filter
->presenter
= presenter
;
106 /* FIXME: configure mixer and presenter */
111 static struct evr
*impl_from_strmbase_renderer(struct strmbase_renderer
*iface
)
113 return CONTAINING_RECORD(iface
, struct evr
, renderer
);
116 static HRESULT
evr_query_interface(struct strmbase_renderer
*iface
, REFIID iid
, void **out
)
118 struct evr
*filter
= impl_from_strmbase_renderer(iface
);
120 if (IsEqualGUID(iid
, &IID_IEVRFilterConfig
))
121 *out
= &filter
->IEVRFilterConfig_iface
;
122 else if (IsEqualGUID(iid
, &IID_IAMFilterMiscFlags
))
123 *out
= &filter
->IAMFilterMiscFlags_iface
;
124 else if (IsEqualGUID(iid
, &IID_IMFGetService
))
125 *out
= &filter
->IMFGetService_iface
;
126 else if (IsEqualGUID(iid
, &IID_IMFVideoRenderer
))
127 *out
= &filter
->IMFVideoRenderer_iface
;
128 else if (IsEqualGUID(iid
, &IID_IMediaEventSink
))
129 *out
= &filter
->IMediaEventSink_iface
;
130 else if (IsEqualGUID(iid
, &IID_IMFTopologyServiceLookup
))
131 *out
= &filter
->IMFTopologyServiceLookup_iface
;
133 return E_NOINTERFACE
;
135 IUnknown_AddRef((IUnknown
*)*out
);
139 static BOOL
evr_is_mixer_d3d_aware(const struct evr
*filter
)
141 IMFAttributes
*attributes
;
142 unsigned int value
= 0;
145 if (FAILED(IMFTransform_QueryInterface(filter
->mixer
, &IID_IMFAttributes
, (void **)&attributes
)))
148 ret
= SUCCEEDED(IMFAttributes_GetUINT32(attributes
, &MF_SA_D3D_AWARE
, &value
)) && value
;
149 IMFAttributes_Release(attributes
);
153 static HRESULT
evr_get_service(void *unk
, REFGUID service
, REFIID riid
, void **obj
)
158 if (SUCCEEDED(hr
= IUnknown_QueryInterface((IUnknown
*)unk
, &IID_IMFGetService
, (void **)&gs
)))
160 hr
= IMFGetService_GetService(gs
, service
, riid
, obj
);
161 IMFGetService_Release(gs
);
167 static HRESULT
evr_init_services(struct evr
*filter
)
169 IMFTopologyServiceLookupClient
*lookup_client
;
172 if (SUCCEEDED(hr
= IMFTransform_QueryInterface(filter
->mixer
, &IID_IMFTopologyServiceLookupClient
,
173 (void **)&lookup_client
)))
175 filter
->flags
|= EVR_INIT_SERVICES
;
176 if (SUCCEEDED(hr
= IMFTopologyServiceLookupClient_InitServicePointers(lookup_client
,
177 &filter
->IMFTopologyServiceLookup_iface
)))
179 filter
->flags
|= EVR_MIXER_INITED_SERVICES
;
181 filter
->flags
&= ~EVR_INIT_SERVICES
;
182 IMFTopologyServiceLookupClient_Release(lookup_client
);
185 if (FAILED(hr
)) return hr
;
187 /* Set device manager that presenter should have created. */
188 if (evr_is_mixer_d3d_aware(filter
))
190 IUnknown
*device_manager
;
193 if (SUCCEEDED(IUnknown_QueryInterface(filter
->presenter
, &IID_IMFGetService
, (void **)&gs
)))
195 if (SUCCEEDED(IMFGetService_GetService(gs
, &MR_VIDEO_RENDER_SERVICE
, &IID_IDirect3DDeviceManager9
,
196 (void **)&device_manager
)))
198 IMFTransform_ProcessMessage(filter
->mixer
, MFT_MESSAGE_SET_D3D_MANAGER
, (ULONG_PTR
)device_manager
);
199 IUnknown_Release(device_manager
);
202 IMFGetService_Release(gs
);
206 if (SUCCEEDED(hr
= IMFVideoPresenter_QueryInterface(filter
->presenter
, &IID_IMFTopologyServiceLookupClient
,
207 (void **)&lookup_client
)))
209 filter
->flags
|= EVR_INIT_SERVICES
;
210 if (SUCCEEDED(hr
= IMFTopologyServiceLookupClient_InitServicePointers(lookup_client
,
211 &filter
->IMFTopologyServiceLookup_iface
)))
213 filter
->flags
|= EVR_PRESENTER_INITED_SERVICES
;
215 filter
->flags
&= ~EVR_INIT_SERVICES
;
216 IMFTopologyServiceLookupClient_Release(lookup_client
);
222 static void evr_release_services(struct evr
*filter
)
224 IMFTopologyServiceLookupClient
*lookup_client
;
226 if (filter
->flags
& EVR_MIXER_INITED_SERVICES
&& SUCCEEDED(IMFTransform_QueryInterface(filter
->mixer
,
227 &IID_IMFTopologyServiceLookupClient
, (void **)&lookup_client
)))
229 IMFTopologyServiceLookupClient_ReleaseServicePointers(lookup_client
);
230 IMFTopologyServiceLookupClient_Release(lookup_client
);
231 filter
->flags
&= ~EVR_MIXER_INITED_SERVICES
;
234 if (filter
->flags
& EVR_PRESENTER_INITED_SERVICES
&& SUCCEEDED(IMFVideoPresenter_QueryInterface(filter
->presenter
,
235 &IID_IMFTopologyServiceLookupClient
, (void **)&lookup_client
)))
237 IMFTopologyServiceLookupClient_ReleaseServicePointers(lookup_client
);
238 IMFTopologyServiceLookupClient_Release(lookup_client
);
239 filter
->flags
&= ~EVR_PRESENTER_INITED_SERVICES
;
243 static void evr_set_input_type(struct evr
*filter
, IMFMediaType
*media_type
)
245 if (filter
->media_type
)
246 IMFMediaType_Release(filter
->media_type
);
247 if ((filter
->media_type
= media_type
))
248 IMFMediaType_AddRef(filter
->media_type
);
249 if (!media_type
&& filter
->allocator
)
250 IMFVideoSampleAllocator_UninitializeSampleAllocator(filter
->allocator
);
253 static HRESULT
evr_test_input_type(struct evr
*filter
, const AM_MEDIA_TYPE
*mt
, IMFMediaType
**ret
)
255 IMFMediaType
*media_type
;
258 if (!filter
->presenter
)
259 hr
= evr_initialize(filter
, NULL
, NULL
);
262 hr
= evr_init_services(filter
);
265 hr
= MFCreateMediaType(&media_type
);
269 if (SUCCEEDED(hr
= MFInitMediaTypeFromAMMediaType(media_type
, mt
)))
271 /* TODO: some pin -> mixer input mapping is necessary to test the substreams. */
272 if (SUCCEEDED(hr
= IMFTransform_SetInputType(filter
->mixer
, 0, media_type
, MFT_SET_TYPE_TEST_ONLY
)))
275 IMFMediaType_AddRef((*ret
= media_type
));
279 IMFMediaType_Release(media_type
);
285 static HRESULT
evr_connect(struct strmbase_renderer
*iface
, const AM_MEDIA_TYPE
*mt
)
287 struct evr
*filter
= impl_from_strmbase_renderer(iface
);
288 IMFVideoSampleAllocator
*allocator
;
289 IMFMediaType
*media_type
;
290 IUnknown
*device_manager
;
293 if (SUCCEEDED(hr
= evr_test_input_type(filter
, mt
, &media_type
)))
295 if (SUCCEEDED(hr
= IMFTransform_SetInputType(filter
->mixer
, 0, media_type
, 0)))
296 hr
= IMFVideoPresenter_ProcessMessage(filter
->presenter
, MFVP_MESSAGE_INVALIDATEMEDIATYPE
, 0);
298 if (SUCCEEDED(hr
= MFCreateVideoSampleAllocator(&IID_IMFVideoSampleAllocator
, (void **)&allocator
)))
300 if (SUCCEEDED(hr
= evr_get_service(filter
->presenter
, &MR_VIDEO_RENDER_SERVICE
,
301 &IID_IDirect3DDeviceManager9
, (void **)&device_manager
)))
303 if (SUCCEEDED(hr
= IMFVideoSampleAllocator_SetDirectXManager(allocator
, device_manager
)))
305 if (SUCCEEDED(hr
= IMFVideoSampleAllocator_InitializeSampleAllocator(allocator
, 2, media_type
)))
307 IMFVideoSampleAllocator_AddRef((filter
->allocator
= allocator
));
310 IUnknown_Release(device_manager
);
313 IMFVideoSampleAllocator_Release(allocator
);
317 evr_set_input_type(filter
, media_type
);
319 IMFMediaType_Release(media_type
);
325 static void evr_disconnect(struct strmbase_renderer
*iface
)
327 struct evr
*filter
= impl_from_strmbase_renderer(iface
);
330 IMFTransform_SetInputType(filter
->mixer
, 0, NULL
, 0);
331 evr_set_input_type(filter
, NULL
);
332 evr_release_services(filter
);
335 static void evr_destroy(struct strmbase_renderer
*iface
)
337 struct evr
*filter
= impl_from_strmbase_renderer(iface
);
339 evr_uninitialize(filter
);
340 evr_set_input_type(filter
, NULL
);
341 if (filter
->allocator
)
342 IMFVideoSampleAllocator_Release(filter
->allocator
);
343 strmbase_renderer_cleanup(&filter
->renderer
);
347 static HRESULT
evr_copy_sample_buffer(struct evr
*filter
, IMediaSample
*input_sample
, IMFSample
**sample
)
349 IDirect3DSurface9
*surface
;
350 D3DLOCKED_RECT locked_rect
;
351 IMFMediaBuffer
*buffer
;
352 UINT64 frame_size
= 0;
358 if (FAILED(hr
= IMFMediaType_GetUINT32(filter
->media_type
, &MF_MT_DEFAULT_STRIDE
, (UINT32
*)&src_stride
)))
360 WARN("Unknown input buffer stride.\n");
363 IMFMediaType_GetUINT64(filter
->media_type
, &MF_MT_FRAME_SIZE
, &frame_size
);
364 width
= frame_size
>> 32;
367 if (FAILED(hr
= IMediaSample_GetPointer(input_sample
, &src
)))
369 WARN("Failed to get pointer to sample data, hr %#lx.\n", hr
);
373 if (FAILED(hr
= IMFVideoSampleAllocator_AllocateSample(filter
->allocator
, sample
)))
375 WARN("Failed to allocate a sample, hr %#lx.\n", hr
);
379 if (SUCCEEDED(hr
= IMFSample_GetBufferByIndex(*sample
, 0, &buffer
)))
381 if (SUCCEEDED(hr
= evr_get_service(buffer
, &MR_BUFFER_SERVICE
, &IID_IDirect3DSurface9
, (void **)&surface
)))
383 if (SUCCEEDED(hr
= IDirect3DSurface9_LockRect(surface
, &locked_rect
, NULL
, D3DLOCK_DISCARD
)))
385 if (src_stride
< 0) src
-= src_stride
* (lines
- 1);
386 MFCopyImage(locked_rect
.pBits
, locked_rect
.Pitch
, src
, src_stride
, width
* 4, lines
);
387 IDirect3DSurface9_UnlockRect(surface
);
390 IDirect3DSurface9_Release(surface
);
392 IMFMediaBuffer_Release(buffer
);
397 IMFSample_Release(*sample
);
404 static HRESULT
evr_render(struct strmbase_renderer
*iface
, IMediaSample
*input_sample
)
406 struct evr
*filter
= impl_from_strmbase_renderer(iface
);
407 HRESULT hr
= E_NOTIMPL
;
408 GUID subtype
= { 0 };
411 if (!filter
->media_type
)
413 WARN("Media type wasn't set.\n");
417 IMFMediaType_GetGUID(filter
->media_type
, &MF_MT_SUBTYPE
, &subtype
);
419 if (IsEqualGUID(&subtype
, &MFVideoFormat_ARGB32
)
420 || IsEqualGUID(&subtype
, &MFVideoFormat_RGB32
))
422 if (SUCCEEDED(hr
= evr_copy_sample_buffer(filter
, input_sample
, &sample
)))
424 if (SUCCEEDED(IMFTransform_ProcessInput(filter
->mixer
, 0, sample
, 0)))
425 IMFVideoPresenter_ProcessMessage(filter
->presenter
, MFVP_MESSAGE_PROCESSINPUTNOTIFY
, 0);
427 IMFSample_Release(sample
);
432 FIXME("Unhandled input type %s.\n", debugstr_guid(&subtype
));
438 static HRESULT
evr_query_accept(struct strmbase_renderer
*iface
, const AM_MEDIA_TYPE
*mt
)
440 struct evr
*filter
= impl_from_strmbase_renderer(iface
);
443 EnterCriticalSection(&filter
->renderer
.filter
.filter_cs
);
445 hr
= evr_test_input_type(filter
, mt
, NULL
);
446 evr_release_services(filter
);
448 LeaveCriticalSection(&filter
->renderer
.filter
.filter_cs
);
453 /* FIXME: errors should be propagated from init/start/stop handlers. */
454 static void evr_init_stream(struct strmbase_renderer
*iface
)
456 struct evr
*filter
= impl_from_strmbase_renderer(iface
);
458 if (!filter
->mixer
) return;
460 if (SUCCEEDED(IMFTransform_ProcessMessage(filter
->mixer
, MFT_MESSAGE_NOTIFY_BEGIN_STREAMING
, 0)))
461 IMFVideoPresenter_ProcessMessage(filter
->presenter
, MFVP_MESSAGE_BEGINSTREAMING
, 0);
464 static void evr_start_stream(struct strmbase_renderer
*iface
)
466 struct evr
*filter
= impl_from_strmbase_renderer(iface
);
469 IMFTransform_ProcessMessage(filter
->mixer
, MFT_MESSAGE_NOTIFY_START_OF_STREAM
, 0);
472 static void evr_stop_stream(struct strmbase_renderer
*iface
)
474 struct evr
*filter
= impl_from_strmbase_renderer(iface
);
476 if (!filter
->mixer
) return;
478 if (SUCCEEDED(IMFTransform_ProcessMessage(filter
->mixer
, MFT_MESSAGE_NOTIFY_END_OF_STREAM
, 0)))
480 if (SUCCEEDED(IMFVideoPresenter_ProcessMessage(filter
->presenter
, MFVP_MESSAGE_ENDSTREAMING
, 0)))
481 IMFTransform_ProcessMessage(filter
->mixer
, MFT_MESSAGE_NOTIFY_END_STREAMING
, 0);
485 static const struct strmbase_renderer_ops renderer_ops
=
487 .renderer_query_accept
= evr_query_accept
,
488 .renderer_render
= evr_render
,
489 .renderer_query_interface
= evr_query_interface
,
490 .renderer_connect
= evr_connect
,
491 .renderer_disconnect
= evr_disconnect
,
492 .renderer_destroy
= evr_destroy
,
493 .renderer_init_stream
= evr_init_stream
,
494 .renderer_start_stream
= evr_start_stream
,
495 .renderer_stop_stream
= evr_stop_stream
,
498 static struct evr
*impl_from_IEVRFilterConfig(IEVRFilterConfig
*iface
)
500 return CONTAINING_RECORD(iface
, struct evr
, IEVRFilterConfig_iface
);
503 static HRESULT WINAPI
filter_config_QueryInterface(IEVRFilterConfig
*iface
, REFIID iid
, void **out
)
505 struct evr
*filter
= impl_from_IEVRFilterConfig(iface
);
506 return IUnknown_QueryInterface(filter
->renderer
.filter
.outer_unk
, iid
, out
);
509 static ULONG WINAPI
filter_config_AddRef(IEVRFilterConfig
*iface
)
511 struct evr
*filter
= impl_from_IEVRFilterConfig(iface
);
512 return IUnknown_AddRef(filter
->renderer
.filter
.outer_unk
);
515 static ULONG WINAPI
filter_config_Release(IEVRFilterConfig
*iface
)
517 struct evr
*filter
= impl_from_IEVRFilterConfig(iface
);
518 return IUnknown_Release(filter
->renderer
.filter
.outer_unk
);
521 static HRESULT WINAPI
filter_config_SetNumberOfStreams(IEVRFilterConfig
*iface
, DWORD count
)
523 struct evr
*filter
= impl_from_IEVRFilterConfig(iface
);
525 FIXME("filter %p, count %lu, stub!\n", filter
, count
);
530 static HRESULT WINAPI
filter_config_GetNumberOfStreams(IEVRFilterConfig
*iface
, DWORD
*count
)
532 struct evr
*filter
= impl_from_IEVRFilterConfig(iface
);
534 FIXME("filter %p, count %p, stub!\n", filter
, count
);
539 static const IEVRFilterConfigVtbl filter_config_vtbl
=
541 filter_config_QueryInterface
,
542 filter_config_AddRef
,
543 filter_config_Release
,
544 filter_config_SetNumberOfStreams
,
545 filter_config_GetNumberOfStreams
,
548 static struct evr
*impl_from_IAMFilterMiscFlags(IAMFilterMiscFlags
*iface
)
550 return CONTAINING_RECORD(iface
, struct evr
, IAMFilterMiscFlags_iface
);
553 static HRESULT WINAPI
filter_misc_flags_QueryInterface(IAMFilterMiscFlags
*iface
, REFIID iid
, void **out
)
555 struct evr
*filter
= impl_from_IAMFilterMiscFlags(iface
);
556 return IUnknown_QueryInterface(filter
->renderer
.filter
.outer_unk
, iid
, out
);
559 static ULONG WINAPI
filter_misc_flags_AddRef(IAMFilterMiscFlags
*iface
)
561 struct evr
*filter
= impl_from_IAMFilterMiscFlags(iface
);
562 return IUnknown_AddRef(filter
->renderer
.filter
.outer_unk
);
565 static ULONG WINAPI
filter_misc_flags_Release(IAMFilterMiscFlags
*iface
)
567 struct evr
*filter
= impl_from_IAMFilterMiscFlags(iface
);
568 return IUnknown_Release(filter
->renderer
.filter
.outer_unk
);
571 static ULONG WINAPI
filter_misc_flags_GetMiscFlags(IAMFilterMiscFlags
*iface
)
573 TRACE("%p.\n", iface
);
575 return AM_FILTER_MISC_FLAGS_IS_RENDERER
;
578 static const IAMFilterMiscFlagsVtbl filter_misc_flags_vtbl
=
580 filter_misc_flags_QueryInterface
,
581 filter_misc_flags_AddRef
,
582 filter_misc_flags_Release
,
583 filter_misc_flags_GetMiscFlags
,
586 static struct evr
*impl_from_IMFGetService(IMFGetService
*iface
)
588 return CONTAINING_RECORD(iface
, struct evr
, IMFGetService_iface
);
591 static HRESULT WINAPI
filter_get_service_QueryInterface(IMFGetService
*iface
, REFIID riid
, void **obj
)
593 struct evr
*filter
= impl_from_IMFGetService(iface
);
594 return IUnknown_QueryInterface(filter
->renderer
.filter
.outer_unk
, riid
, obj
);
597 static ULONG WINAPI
filter_get_service_AddRef(IMFGetService
*iface
)
599 struct evr
*filter
= impl_from_IMFGetService(iface
);
600 return IUnknown_AddRef(filter
->renderer
.filter
.outer_unk
);
603 static ULONG WINAPI
filter_get_service_Release(IMFGetService
*iface
)
605 struct evr
*filter
= impl_from_IMFGetService(iface
);
606 return IUnknown_Release(filter
->renderer
.filter
.outer_unk
);
609 static HRESULT WINAPI
filter_get_service_GetService(IMFGetService
*iface
, REFGUID service
, REFIID riid
, void **obj
)
611 struct evr
*filter
= impl_from_IMFGetService(iface
);
612 HRESULT hr
= E_NOINTERFACE
;
613 IMFGetService
*gs
= NULL
;
615 TRACE("iface %p, service %s, riid %s, obj %p.\n", iface
, debugstr_guid(service
), debugstr_guid(riid
), obj
);
617 EnterCriticalSection(&filter
->renderer
.filter
.filter_cs
);
619 if (IsEqualGUID(service
, &MR_VIDEO_RENDER_SERVICE
))
621 if (!filter
->presenter
)
622 hr
= evr_initialize(filter
, NULL
, NULL
);
624 if (filter
->presenter
)
625 hr
= IMFVideoPresenter_QueryInterface(filter
->presenter
, &IID_IMFGetService
, (void **)&gs
);
629 FIXME("Unsupported service %s.\n", debugstr_guid(service
));
632 LeaveCriticalSection(&filter
->renderer
.filter
.filter_cs
);
636 hr
= IMFGetService_GetService(gs
, service
, riid
, obj
);
637 IMFGetService_Release(gs
);
643 static const IMFGetServiceVtbl filter_get_service_vtbl
=
645 filter_get_service_QueryInterface
,
646 filter_get_service_AddRef
,
647 filter_get_service_Release
,
648 filter_get_service_GetService
,
651 static struct evr
*impl_from_IMFVideoRenderer(IMFVideoRenderer
*iface
)
653 return CONTAINING_RECORD(iface
, struct evr
, IMFVideoRenderer_iface
);
656 static HRESULT WINAPI
filter_video_renderer_QueryInterface(IMFVideoRenderer
*iface
, REFIID riid
, void **obj
)
658 struct evr
*filter
= impl_from_IMFVideoRenderer(iface
);
659 return IUnknown_QueryInterface(filter
->renderer
.filter
.outer_unk
, riid
, obj
);
662 static ULONG WINAPI
filter_video_renderer_AddRef(IMFVideoRenderer
*iface
)
664 struct evr
*filter
= impl_from_IMFVideoRenderer(iface
);
665 return IUnknown_AddRef(filter
->renderer
.filter
.outer_unk
);
668 static ULONG WINAPI
filter_video_renderer_Release(IMFVideoRenderer
*iface
)
670 struct evr
*filter
= impl_from_IMFVideoRenderer(iface
);
671 return IUnknown_Release(filter
->renderer
.filter
.outer_unk
);
674 static HRESULT WINAPI
filter_video_renderer_InitializeRenderer(IMFVideoRenderer
*iface
, IMFTransform
*mixer
,
675 IMFVideoPresenter
*presenter
)
677 struct evr
*filter
= impl_from_IMFVideoRenderer(iface
);
680 TRACE("iface %p, mixer %p, presenter %p.\n", iface
, mixer
, presenter
);
682 EnterCriticalSection(&filter
->renderer
.filter
.filter_cs
);
684 hr
= evr_initialize(filter
, mixer
, presenter
);
686 LeaveCriticalSection(&filter
->renderer
.filter
.filter_cs
);
691 static const IMFVideoRendererVtbl filter_video_renderer_vtbl
=
693 filter_video_renderer_QueryInterface
,
694 filter_video_renderer_AddRef
,
695 filter_video_renderer_Release
,
696 filter_video_renderer_InitializeRenderer
,
699 static struct evr
*impl_from_IMediaEventSink(IMediaEventSink
*iface
)
701 return CONTAINING_RECORD(iface
, struct evr
, IMediaEventSink_iface
);
704 static HRESULT WINAPI
filter_media_event_sink_QueryInterface(IMediaEventSink
*iface
, REFIID riid
, void **obj
)
706 struct evr
*filter
= impl_from_IMediaEventSink(iface
);
707 return IUnknown_QueryInterface(filter
->renderer
.filter
.outer_unk
, riid
, obj
);
710 static ULONG WINAPI
filter_media_event_sink_AddRef(IMediaEventSink
*iface
)
712 struct evr
*filter
= impl_from_IMediaEventSink(iface
);
713 return IUnknown_AddRef(filter
->renderer
.filter
.outer_unk
);
716 static ULONG WINAPI
filter_media_event_sink_Release(IMediaEventSink
*iface
)
718 struct evr
*filter
= impl_from_IMediaEventSink(iface
);
719 return IUnknown_Release(filter
->renderer
.filter
.outer_unk
);
722 static HRESULT WINAPI
filter_media_event_sink_Notify(IMediaEventSink
*iface
, LONG event
, LONG_PTR param1
, LONG_PTR param2
)
724 FIXME("iface %p, event %ld, param1 %Id, param2 %Id.\n", iface
, event
, param1
, param2
);
729 static const IMediaEventSinkVtbl filter_media_event_sink_vtbl
=
731 filter_media_event_sink_QueryInterface
,
732 filter_media_event_sink_AddRef
,
733 filter_media_event_sink_Release
,
734 filter_media_event_sink_Notify
,
737 static struct evr
*impl_from_IMFTopologyServiceLookup(IMFTopologyServiceLookup
*iface
)
739 return CONTAINING_RECORD(iface
, struct evr
, IMFTopologyServiceLookup_iface
);
742 static HRESULT WINAPI
filter_service_lookup_QueryInterface(IMFTopologyServiceLookup
*iface
, REFIID riid
, void **obj
)
744 struct evr
*filter
= impl_from_IMFTopologyServiceLookup(iface
);
745 return IUnknown_QueryInterface(filter
->renderer
.filter
.outer_unk
, riid
, obj
);
748 static ULONG WINAPI
filter_service_lookup_AddRef(IMFTopologyServiceLookup
*iface
)
750 struct evr
*filter
= impl_from_IMFTopologyServiceLookup(iface
);
751 return IUnknown_AddRef(filter
->renderer
.filter
.outer_unk
);
754 static ULONG WINAPI
filter_service_lookup_Release(IMFTopologyServiceLookup
*iface
)
756 struct evr
*filter
= impl_from_IMFTopologyServiceLookup(iface
);
757 return IUnknown_Release(filter
->renderer
.filter
.outer_unk
);
760 static HRESULT WINAPI
filter_service_lookup_LookupService(IMFTopologyServiceLookup
*iface
, MF_SERVICE_LOOKUP_TYPE lookup_type
,
761 DWORD index
, REFGUID service
, REFIID riid
, void **objects
, DWORD
*num_objects
)
763 struct evr
*filter
= impl_from_IMFTopologyServiceLookup(iface
);
766 TRACE("iface %p, lookup_type %d, index %lu, service %s, riid %s, objects %p, num_objects %p.\n",
767 iface
, lookup_type
, index
, debugstr_guid(service
), debugstr_guid(riid
), objects
, num_objects
);
769 EnterCriticalSection(&filter
->renderer
.filter
.filter_cs
);
771 if (!(filter
->flags
& EVR_INIT_SERVICES
))
772 hr
= MF_E_NOTACCEPTING
;
773 else if (IsEqualGUID(service
, &MR_VIDEO_RENDER_SERVICE
))
775 if (IsEqualIID(riid
, &IID_IMediaEventSink
))
777 *objects
= &filter
->IMediaEventSink_iface
;
778 IUnknown_AddRef((IUnknown
*)*objects
);
781 else if (IsEqualGUID(service
, &MR_VIDEO_MIXER_SERVICE
))
783 hr
= IMFTransform_QueryInterface(filter
->mixer
, riid
, objects
);
787 WARN("Unsupported service %s.\n", debugstr_guid(service
));
788 hr
= MF_E_UNSUPPORTED_SERVICE
;
791 LeaveCriticalSection(&filter
->renderer
.filter
.filter_cs
);
796 static const IMFTopologyServiceLookupVtbl filter_service_lookup_vtbl
=
798 filter_service_lookup_QueryInterface
,
799 filter_service_lookup_AddRef
,
800 filter_service_lookup_Release
,
801 filter_service_lookup_LookupService
,
804 HRESULT
evr_filter_create(IUnknown
*outer
, void **out
)
808 if (!(object
= calloc(1, sizeof(*object
))))
809 return E_OUTOFMEMORY
;
811 strmbase_renderer_init(&object
->renderer
, outer
,
812 &CLSID_EnhancedVideoRenderer
, L
"EVR Input0", &renderer_ops
);
813 object
->IEVRFilterConfig_iface
.lpVtbl
= &filter_config_vtbl
;
814 object
->IAMFilterMiscFlags_iface
.lpVtbl
= &filter_misc_flags_vtbl
;
815 object
->IMFGetService_iface
.lpVtbl
= &filter_get_service_vtbl
;
816 object
->IMFVideoRenderer_iface
.lpVtbl
= &filter_video_renderer_vtbl
;
817 object
->IMediaEventSink_iface
.lpVtbl
= &filter_media_event_sink_vtbl
;
818 object
->IMFTopologyServiceLookup_iface
.lpVtbl
= &filter_service_lookup_vtbl
;
820 TRACE("Created EVR %p.\n", object
);
821 *out
= &object
->renderer
.filter
.IUnknown_inner
;