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
, const GUID
*subtype
, IMediaSample
*input_sample
, IMFSample
**sample
)
349 IDirect3DSurface9
*surface
;
350 D3DLOCKED_RECT locked_rect
;
351 IMFMediaBuffer
*buffer
;
352 UINT64 frame_size
= 0;
359 if (FAILED(hr
= IMFMediaType_GetUINT32(filter
->media_type
, &MF_MT_DEFAULT_STRIDE
, (UINT32
*)&src_stride
)))
361 WARN("Unknown input buffer stride.\n");
364 IMFMediaType_GetUINT64(filter
->media_type
, &MF_MT_FRAME_SIZE
, &frame_size
);
365 width
= frame_size
>> 32;
369 if (FAILED(hr
= IMediaSample_GetPointer(input_sample
, &src
)))
371 WARN("Failed to get pointer to sample data, hr %#lx.\n", hr
);
375 if (FAILED(hr
= IMFVideoSampleAllocator_AllocateSample(filter
->allocator
, sample
)))
377 WARN("Failed to allocate a sample, hr %#lx.\n", hr
);
381 if (SUCCEEDED(hr
= IMFSample_GetBufferByIndex(*sample
, 0, &buffer
)))
383 if (SUCCEEDED(hr
= evr_get_service(buffer
, &MR_BUFFER_SERVICE
, &IID_IDirect3DSurface9
, (void **)&surface
)))
385 if (SUCCEEDED(hr
= IDirect3DSurface9_LockRect(surface
, &locked_rect
, NULL
, D3DLOCK_DISCARD
)))
387 if (src_stride
< 0) src
+= (-src_stride
) * (lines
- 1);
389 if (IsEqualGUID(subtype
, &MFVideoFormat_YUY2
))
391 width
= (width
+ 1) & ~1;
392 MFCopyImage(locked_rect
.pBits
, locked_rect
.Pitch
, src
, src_stride
, width
* 2, lines
);
394 else if (IsEqualGUID(subtype
, &MFVideoFormat_NV12
))
396 /* Width and height must be rounded up to even. */
397 width
= (width
+ 1) & ~1;
398 lines
= (lines
+ 1) & ~1;
401 MFCopyImage(locked_rect
.pBits
, locked_rect
.Pitch
, src
, src_stride
, width
, lines
);
404 dst_uv
= (BYTE
*)locked_rect
.pBits
+ (lines
* locked_rect
.Pitch
);
405 MFCopyImage(dst_uv
, locked_rect
.Pitch
, src
+ (lines
* src_stride
), src_stride
, width
, lines
/ 2);
409 /* All other formats are 32-bit, single plane. */
410 MFCopyImage(locked_rect
.pBits
, locked_rect
.Pitch
, src
, src_stride
, width
* 4, lines
);
412 IDirect3DSurface9_UnlockRect(surface
);
415 IDirect3DSurface9_Release(surface
);
417 IMFMediaBuffer_Release(buffer
);
422 IMFSample_Release(*sample
);
429 static HRESULT
evr_render(struct strmbase_renderer
*iface
, IMediaSample
*input_sample
)
431 struct evr
*filter
= impl_from_strmbase_renderer(iface
);
432 HRESULT hr
= E_NOTIMPL
;
433 GUID subtype
= { 0 };
436 if (!filter
->media_type
)
438 WARN("Media type wasn't set.\n");
442 IMFMediaType_GetGUID(filter
->media_type
, &MF_MT_SUBTYPE
, &subtype
);
444 if (IsEqualGUID(&subtype
, &MFVideoFormat_ARGB32
)
445 || IsEqualGUID(&subtype
, &MFVideoFormat_RGB32
)
446 || IsEqualGUID(&subtype
, &MFVideoFormat_YUY2
)
447 || IsEqualGUID(&subtype
, &MFVideoFormat_NV12
))
449 if (SUCCEEDED(hr
= evr_copy_sample_buffer(filter
, &subtype
, input_sample
, &sample
)))
451 if (SUCCEEDED(IMFTransform_ProcessInput(filter
->mixer
, 0, sample
, 0)))
452 IMFVideoPresenter_ProcessMessage(filter
->presenter
, MFVP_MESSAGE_PROCESSINPUTNOTIFY
, 0);
454 IMFSample_Release(sample
);
459 FIXME("Unhandled input type %s.\n", debugstr_guid(&subtype
));
465 static HRESULT
evr_query_accept(struct strmbase_renderer
*iface
, const AM_MEDIA_TYPE
*mt
)
467 struct evr
*filter
= impl_from_strmbase_renderer(iface
);
470 EnterCriticalSection(&filter
->renderer
.filter
.filter_cs
);
472 hr
= evr_test_input_type(filter
, mt
, NULL
);
473 evr_release_services(filter
);
475 LeaveCriticalSection(&filter
->renderer
.filter
.filter_cs
);
480 /* FIXME: errors should be propagated from init/start/stop handlers. */
481 static void evr_init_stream(struct strmbase_renderer
*iface
)
483 struct evr
*filter
= impl_from_strmbase_renderer(iface
);
485 if (!filter
->mixer
) return;
487 if (SUCCEEDED(IMFTransform_ProcessMessage(filter
->mixer
, MFT_MESSAGE_NOTIFY_BEGIN_STREAMING
, 0)))
488 IMFVideoPresenter_ProcessMessage(filter
->presenter
, MFVP_MESSAGE_BEGINSTREAMING
, 0);
491 static void evr_start_stream(struct strmbase_renderer
*iface
)
493 struct evr
*filter
= impl_from_strmbase_renderer(iface
);
496 IMFTransform_ProcessMessage(filter
->mixer
, MFT_MESSAGE_NOTIFY_START_OF_STREAM
, 0);
499 static void evr_stop_stream(struct strmbase_renderer
*iface
)
501 struct evr
*filter
= impl_from_strmbase_renderer(iface
);
503 if (!filter
->mixer
) return;
505 if (SUCCEEDED(IMFTransform_ProcessMessage(filter
->mixer
, MFT_MESSAGE_NOTIFY_END_OF_STREAM
, 0)))
507 if (SUCCEEDED(IMFVideoPresenter_ProcessMessage(filter
->presenter
, MFVP_MESSAGE_ENDSTREAMING
, 0)))
508 IMFTransform_ProcessMessage(filter
->mixer
, MFT_MESSAGE_NOTIFY_END_STREAMING
, 0);
512 static const struct strmbase_renderer_ops renderer_ops
=
514 .renderer_query_accept
= evr_query_accept
,
515 .renderer_render
= evr_render
,
516 .renderer_query_interface
= evr_query_interface
,
517 .renderer_connect
= evr_connect
,
518 .renderer_disconnect
= evr_disconnect
,
519 .renderer_destroy
= evr_destroy
,
520 .renderer_init_stream
= evr_init_stream
,
521 .renderer_start_stream
= evr_start_stream
,
522 .renderer_stop_stream
= evr_stop_stream
,
525 static struct evr
*impl_from_IEVRFilterConfig(IEVRFilterConfig
*iface
)
527 return CONTAINING_RECORD(iface
, struct evr
, IEVRFilterConfig_iface
);
530 static HRESULT WINAPI
filter_config_QueryInterface(IEVRFilterConfig
*iface
, REFIID iid
, void **out
)
532 struct evr
*filter
= impl_from_IEVRFilterConfig(iface
);
533 return IUnknown_QueryInterface(filter
->renderer
.filter
.outer_unk
, iid
, out
);
536 static ULONG WINAPI
filter_config_AddRef(IEVRFilterConfig
*iface
)
538 struct evr
*filter
= impl_from_IEVRFilterConfig(iface
);
539 return IUnknown_AddRef(filter
->renderer
.filter
.outer_unk
);
542 static ULONG WINAPI
filter_config_Release(IEVRFilterConfig
*iface
)
544 struct evr
*filter
= impl_from_IEVRFilterConfig(iface
);
545 return IUnknown_Release(filter
->renderer
.filter
.outer_unk
);
548 static HRESULT WINAPI
filter_config_SetNumberOfStreams(IEVRFilterConfig
*iface
, DWORD count
)
550 struct evr
*filter
= impl_from_IEVRFilterConfig(iface
);
552 FIXME("filter %p, count %lu, stub!\n", filter
, count
);
557 static HRESULT WINAPI
filter_config_GetNumberOfStreams(IEVRFilterConfig
*iface
, DWORD
*count
)
559 struct evr
*filter
= impl_from_IEVRFilterConfig(iface
);
561 FIXME("filter %p, count %p, stub!\n", filter
, count
);
566 static const IEVRFilterConfigVtbl filter_config_vtbl
=
568 filter_config_QueryInterface
,
569 filter_config_AddRef
,
570 filter_config_Release
,
571 filter_config_SetNumberOfStreams
,
572 filter_config_GetNumberOfStreams
,
575 static struct evr
*impl_from_IAMFilterMiscFlags(IAMFilterMiscFlags
*iface
)
577 return CONTAINING_RECORD(iface
, struct evr
, IAMFilterMiscFlags_iface
);
580 static HRESULT WINAPI
filter_misc_flags_QueryInterface(IAMFilterMiscFlags
*iface
, REFIID iid
, void **out
)
582 struct evr
*filter
= impl_from_IAMFilterMiscFlags(iface
);
583 return IUnknown_QueryInterface(filter
->renderer
.filter
.outer_unk
, iid
, out
);
586 static ULONG WINAPI
filter_misc_flags_AddRef(IAMFilterMiscFlags
*iface
)
588 struct evr
*filter
= impl_from_IAMFilterMiscFlags(iface
);
589 return IUnknown_AddRef(filter
->renderer
.filter
.outer_unk
);
592 static ULONG WINAPI
filter_misc_flags_Release(IAMFilterMiscFlags
*iface
)
594 struct evr
*filter
= impl_from_IAMFilterMiscFlags(iface
);
595 return IUnknown_Release(filter
->renderer
.filter
.outer_unk
);
598 static ULONG WINAPI
filter_misc_flags_GetMiscFlags(IAMFilterMiscFlags
*iface
)
600 TRACE("%p.\n", iface
);
602 return AM_FILTER_MISC_FLAGS_IS_RENDERER
;
605 static const IAMFilterMiscFlagsVtbl filter_misc_flags_vtbl
=
607 filter_misc_flags_QueryInterface
,
608 filter_misc_flags_AddRef
,
609 filter_misc_flags_Release
,
610 filter_misc_flags_GetMiscFlags
,
613 static struct evr
*impl_from_IMFGetService(IMFGetService
*iface
)
615 return CONTAINING_RECORD(iface
, struct evr
, IMFGetService_iface
);
618 static HRESULT WINAPI
filter_get_service_QueryInterface(IMFGetService
*iface
, REFIID riid
, void **obj
)
620 struct evr
*filter
= impl_from_IMFGetService(iface
);
621 return IUnknown_QueryInterface(filter
->renderer
.filter
.outer_unk
, riid
, obj
);
624 static ULONG WINAPI
filter_get_service_AddRef(IMFGetService
*iface
)
626 struct evr
*filter
= impl_from_IMFGetService(iface
);
627 return IUnknown_AddRef(filter
->renderer
.filter
.outer_unk
);
630 static ULONG WINAPI
filter_get_service_Release(IMFGetService
*iface
)
632 struct evr
*filter
= impl_from_IMFGetService(iface
);
633 return IUnknown_Release(filter
->renderer
.filter
.outer_unk
);
636 static HRESULT WINAPI
filter_get_service_GetService(IMFGetService
*iface
, REFGUID service
, REFIID riid
, void **obj
)
638 struct evr
*filter
= impl_from_IMFGetService(iface
);
639 HRESULT hr
= E_NOINTERFACE
;
640 IMFGetService
*gs
= NULL
;
642 TRACE("iface %p, service %s, riid %s, obj %p.\n", iface
, debugstr_guid(service
), debugstr_guid(riid
), obj
);
644 EnterCriticalSection(&filter
->renderer
.filter
.filter_cs
);
646 if (IsEqualGUID(service
, &MR_VIDEO_RENDER_SERVICE
))
648 if (!filter
->presenter
)
649 hr
= evr_initialize(filter
, NULL
, NULL
);
651 if (filter
->presenter
)
652 hr
= IMFVideoPresenter_QueryInterface(filter
->presenter
, &IID_IMFGetService
, (void **)&gs
);
656 FIXME("Unsupported service %s.\n", debugstr_guid(service
));
659 LeaveCriticalSection(&filter
->renderer
.filter
.filter_cs
);
663 hr
= IMFGetService_GetService(gs
, service
, riid
, obj
);
664 IMFGetService_Release(gs
);
670 static const IMFGetServiceVtbl filter_get_service_vtbl
=
672 filter_get_service_QueryInterface
,
673 filter_get_service_AddRef
,
674 filter_get_service_Release
,
675 filter_get_service_GetService
,
678 static struct evr
*impl_from_IMFVideoRenderer(IMFVideoRenderer
*iface
)
680 return CONTAINING_RECORD(iface
, struct evr
, IMFVideoRenderer_iface
);
683 static HRESULT WINAPI
filter_video_renderer_QueryInterface(IMFVideoRenderer
*iface
, REFIID riid
, void **obj
)
685 struct evr
*filter
= impl_from_IMFVideoRenderer(iface
);
686 return IUnknown_QueryInterface(filter
->renderer
.filter
.outer_unk
, riid
, obj
);
689 static ULONG WINAPI
filter_video_renderer_AddRef(IMFVideoRenderer
*iface
)
691 struct evr
*filter
= impl_from_IMFVideoRenderer(iface
);
692 return IUnknown_AddRef(filter
->renderer
.filter
.outer_unk
);
695 static ULONG WINAPI
filter_video_renderer_Release(IMFVideoRenderer
*iface
)
697 struct evr
*filter
= impl_from_IMFVideoRenderer(iface
);
698 return IUnknown_Release(filter
->renderer
.filter
.outer_unk
);
701 static HRESULT WINAPI
filter_video_renderer_InitializeRenderer(IMFVideoRenderer
*iface
, IMFTransform
*mixer
,
702 IMFVideoPresenter
*presenter
)
704 struct evr
*filter
= impl_from_IMFVideoRenderer(iface
);
707 TRACE("iface %p, mixer %p, presenter %p.\n", iface
, mixer
, presenter
);
709 EnterCriticalSection(&filter
->renderer
.filter
.filter_cs
);
711 hr
= evr_initialize(filter
, mixer
, presenter
);
713 LeaveCriticalSection(&filter
->renderer
.filter
.filter_cs
);
718 static const IMFVideoRendererVtbl filter_video_renderer_vtbl
=
720 filter_video_renderer_QueryInterface
,
721 filter_video_renderer_AddRef
,
722 filter_video_renderer_Release
,
723 filter_video_renderer_InitializeRenderer
,
726 static struct evr
*impl_from_IMediaEventSink(IMediaEventSink
*iface
)
728 return CONTAINING_RECORD(iface
, struct evr
, IMediaEventSink_iface
);
731 static HRESULT WINAPI
filter_media_event_sink_QueryInterface(IMediaEventSink
*iface
, REFIID riid
, void **obj
)
733 struct evr
*filter
= impl_from_IMediaEventSink(iface
);
734 return IUnknown_QueryInterface(filter
->renderer
.filter
.outer_unk
, riid
, obj
);
737 static ULONG WINAPI
filter_media_event_sink_AddRef(IMediaEventSink
*iface
)
739 struct evr
*filter
= impl_from_IMediaEventSink(iface
);
740 return IUnknown_AddRef(filter
->renderer
.filter
.outer_unk
);
743 static ULONG WINAPI
filter_media_event_sink_Release(IMediaEventSink
*iface
)
745 struct evr
*filter
= impl_from_IMediaEventSink(iface
);
746 return IUnknown_Release(filter
->renderer
.filter
.outer_unk
);
749 static HRESULT WINAPI
filter_media_event_sink_Notify(IMediaEventSink
*iface
, LONG event
, LONG_PTR param1
, LONG_PTR param2
)
751 FIXME("iface %p, event %ld, param1 %Id, param2 %Id.\n", iface
, event
, param1
, param2
);
756 static const IMediaEventSinkVtbl filter_media_event_sink_vtbl
=
758 filter_media_event_sink_QueryInterface
,
759 filter_media_event_sink_AddRef
,
760 filter_media_event_sink_Release
,
761 filter_media_event_sink_Notify
,
764 static struct evr
*impl_from_IMFTopologyServiceLookup(IMFTopologyServiceLookup
*iface
)
766 return CONTAINING_RECORD(iface
, struct evr
, IMFTopologyServiceLookup_iface
);
769 static HRESULT WINAPI
filter_service_lookup_QueryInterface(IMFTopologyServiceLookup
*iface
, REFIID riid
, void **obj
)
771 struct evr
*filter
= impl_from_IMFTopologyServiceLookup(iface
);
772 return IUnknown_QueryInterface(filter
->renderer
.filter
.outer_unk
, riid
, obj
);
775 static ULONG WINAPI
filter_service_lookup_AddRef(IMFTopologyServiceLookup
*iface
)
777 struct evr
*filter
= impl_from_IMFTopologyServiceLookup(iface
);
778 return IUnknown_AddRef(filter
->renderer
.filter
.outer_unk
);
781 static ULONG WINAPI
filter_service_lookup_Release(IMFTopologyServiceLookup
*iface
)
783 struct evr
*filter
= impl_from_IMFTopologyServiceLookup(iface
);
784 return IUnknown_Release(filter
->renderer
.filter
.outer_unk
);
787 static HRESULT WINAPI
filter_service_lookup_LookupService(IMFTopologyServiceLookup
*iface
, MF_SERVICE_LOOKUP_TYPE lookup_type
,
788 DWORD index
, REFGUID service
, REFIID riid
, void **objects
, DWORD
*num_objects
)
790 struct evr
*filter
= impl_from_IMFTopologyServiceLookup(iface
);
793 TRACE("iface %p, lookup_type %d, index %lu, service %s, riid %s, objects %p, num_objects %p.\n",
794 iface
, lookup_type
, index
, debugstr_guid(service
), debugstr_guid(riid
), objects
, num_objects
);
796 EnterCriticalSection(&filter
->renderer
.filter
.filter_cs
);
798 if (!(filter
->flags
& EVR_INIT_SERVICES
))
799 hr
= MF_E_NOTACCEPTING
;
800 else if (IsEqualGUID(service
, &MR_VIDEO_RENDER_SERVICE
))
802 if (IsEqualIID(riid
, &IID_IMediaEventSink
))
804 *objects
= &filter
->IMediaEventSink_iface
;
805 IUnknown_AddRef((IUnknown
*)*objects
);
808 else if (IsEqualGUID(service
, &MR_VIDEO_MIXER_SERVICE
))
810 hr
= IMFTransform_QueryInterface(filter
->mixer
, riid
, objects
);
814 WARN("Unsupported service %s.\n", debugstr_guid(service
));
815 hr
= MF_E_UNSUPPORTED_SERVICE
;
818 LeaveCriticalSection(&filter
->renderer
.filter
.filter_cs
);
823 static const IMFTopologyServiceLookupVtbl filter_service_lookup_vtbl
=
825 filter_service_lookup_QueryInterface
,
826 filter_service_lookup_AddRef
,
827 filter_service_lookup_Release
,
828 filter_service_lookup_LookupService
,
831 HRESULT
evr_filter_create(IUnknown
*outer
, void **out
)
835 if (!(object
= calloc(1, sizeof(*object
))))
836 return E_OUTOFMEMORY
;
838 strmbase_renderer_init(&object
->renderer
, outer
,
839 &CLSID_EnhancedVideoRenderer
, L
"EVR Input0", &renderer_ops
);
840 object
->IEVRFilterConfig_iface
.lpVtbl
= &filter_config_vtbl
;
841 object
->IAMFilterMiscFlags_iface
.lpVtbl
= &filter_misc_flags_vtbl
;
842 object
->IMFGetService_iface
.lpVtbl
= &filter_get_service_vtbl
;
843 object
->IMFVideoRenderer_iface
.lpVtbl
= &filter_video_renderer_vtbl
;
844 object
->IMediaEventSink_iface
.lpVtbl
= &filter_media_event_sink_vtbl
;
845 object
->IMFTopologyServiceLookup_iface
.lpVtbl
= &filter_service_lookup_vtbl
;
847 TRACE("Created EVR %p.\n", object
);
848 *out
= &object
->renderer
.filter
.IUnknown_inner
;