2 * Copyright 2020 Nikolay Sivov
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
27 #include "evr_classes.h"
28 #include "evr_private.h"
30 #include "wine/debug.h"
32 WINE_DEFAULT_DEBUG_CHANNEL(evr
);
35 Initial state represents just created object, presenter never returns to this state.
36 Shutdown state is entered on ReleaseServicePointers(), terminal state.
37 Started/stopped/paused states are controlled by clock state changes.
42 PRESENTER_STATE_INITIAL
= 0,
43 PRESENTER_STATE_SHUT_DOWN
,
44 PRESENTER_STATE_STARTED
,
45 PRESENTER_STATE_STOPPED
,
46 PRESENTER_STATE_PAUSED
,
51 PRESENTER_MIXER_HAS_INPUT
= 0x1,
54 enum streaming_thread_message
57 EVRM_PRESENT
= WM_USER
+ 1,
58 EVRM_PROCESS_INPUT
= WM_USER
+ 2,
70 struct streaming_thread
75 struct sample_queue queue
;
78 struct video_presenter
80 IMFVideoPresenter IMFVideoPresenter_iface
;
81 IMFVideoDeviceID IMFVideoDeviceID_iface
;
82 IMFTopologyServiceLookupClient IMFTopologyServiceLookupClient_iface
;
83 IMFVideoDisplayControl IMFVideoDisplayControl_iface
;
84 IMFRateSupport IMFRateSupport_iface
;
85 IMFGetService IMFGetService_iface
;
86 IMFVideoPositionMapper IMFVideoPositionMapper_iface
;
87 IQualProp IQualProp_iface
;
88 IMFQualityAdvise IMFQualityAdvise_iface
;
89 IMFQualityAdviseLimits IMFQualityAdviseLimits_iface
;
90 IDirect3DDeviceManager9 IDirect3DDeviceManager9_iface
;
91 IMFVideoSampleAllocatorNotify allocator_cb
;
92 IUnknown IUnknown_inner
;
98 IMediaEventSink
*event_sink
;
100 IDirect3DDeviceManager9
*device_manager
;
101 IDirect3DSwapChain9
*swapchain
;
104 IMFVideoSampleAllocator
*allocator
;
105 struct streaming_thread thread
;
106 unsigned int allocator_capacity
;
107 IMFMediaType
*media_type
;
108 LONGLONG frame_time_threshold
;
111 MFVideoNormalizedRect src_rect
;
113 DWORD rendering_prefs
;
116 unsigned int ar_mode
;
128 static struct video_presenter
*impl_from_IUnknown(IUnknown
*iface
)
130 return CONTAINING_RECORD(iface
, struct video_presenter
, IUnknown_inner
);
133 static struct video_presenter
*impl_from_IMFVideoPresenter(IMFVideoPresenter
*iface
)
135 return CONTAINING_RECORD(iface
, struct video_presenter
, IMFVideoPresenter_iface
);
138 static struct video_presenter
*impl_from_IMFVideoDeviceID(IMFVideoDeviceID
*iface
)
140 return CONTAINING_RECORD(iface
, struct video_presenter
, IMFVideoDeviceID_iface
);
143 static struct video_presenter
*impl_from_IMFTopologyServiceLookupClient(IMFTopologyServiceLookupClient
*iface
)
145 return CONTAINING_RECORD(iface
, struct video_presenter
, IMFTopologyServiceLookupClient_iface
);
148 static struct video_presenter
*impl_from_IMFVideoDisplayControl(IMFVideoDisplayControl
*iface
)
150 return CONTAINING_RECORD(iface
, struct video_presenter
, IMFVideoDisplayControl_iface
);
153 static struct video_presenter
*impl_from_IMFRateSupport(IMFRateSupport
*iface
)
155 return CONTAINING_RECORD(iface
, struct video_presenter
, IMFRateSupport_iface
);
158 static struct video_presenter
*impl_from_IMFGetService(IMFGetService
*iface
)
160 return CONTAINING_RECORD(iface
, struct video_presenter
, IMFGetService_iface
);
163 static struct video_presenter
*impl_from_IMFVideoPositionMapper(IMFVideoPositionMapper
*iface
)
165 return CONTAINING_RECORD(iface
, struct video_presenter
, IMFVideoPositionMapper_iface
);
168 static struct video_presenter
*impl_from_IMFVideoSampleAllocatorNotify(IMFVideoSampleAllocatorNotify
*iface
)
170 return CONTAINING_RECORD(iface
, struct video_presenter
, allocator_cb
);
173 static struct video_presenter
*impl_from_IQualProp(IQualProp
*iface
)
175 return CONTAINING_RECORD(iface
, struct video_presenter
, IQualProp_iface
);
178 static struct video_presenter
*impl_from_IMFQualityAdvise(IMFQualityAdvise
*iface
)
180 return CONTAINING_RECORD(iface
, struct video_presenter
, IMFQualityAdvise_iface
);
183 static struct video_presenter
*impl_from_IMFQualityAdviseLimits(IMFQualityAdviseLimits
*iface
)
185 return CONTAINING_RECORD(iface
, struct video_presenter
, IMFQualityAdviseLimits_iface
);
188 static struct video_presenter
*impl_from_IDirect3DDeviceManager9(IDirect3DDeviceManager9
*iface
)
190 return CONTAINING_RECORD(iface
, struct video_presenter
, IDirect3DDeviceManager9_iface
);
193 static void video_presenter_notify_renderer(struct video_presenter
*presenter
,
194 LONG event
, LONG_PTR param1
, LONG_PTR param2
)
196 if (presenter
->event_sink
)
197 IMediaEventSink_Notify(presenter
->event_sink
, event
, param1
, param2
);
200 static unsigned int get_gcd(unsigned int a
, unsigned int b
)
214 static HRESULT
video_presenter_get_device(struct video_presenter
*presenter
, IDirect3DDevice9
**device
)
218 if (!presenter
->hdevice
)
220 if (FAILED(hr
= IDirect3DDeviceManager9_OpenDeviceHandle(presenter
->device_manager
, &presenter
->hdevice
)))
224 return IDirect3DDeviceManager9_LockDevice(presenter
->device_manager
, presenter
->hdevice
, device
, TRUE
);
227 static void video_presenter_get_native_video_size(struct video_presenter
*presenter
)
229 IMFMediaType
*media_type
;
230 UINT64 frame_size
= 0;
232 memset(&presenter
->native_size
, 0, sizeof(presenter
->native_size
));
233 memset(&presenter
->native_ratio
, 0, sizeof(presenter
->native_ratio
));
235 if (!presenter
->mixer
)
238 if (FAILED(IMFTransform_GetInputCurrentType(presenter
->mixer
, 0, &media_type
)))
241 if (SUCCEEDED(IMFMediaType_GetUINT64(media_type
, &MF_MT_FRAME_SIZE
, &frame_size
)))
245 presenter
->native_size
.cx
= frame_size
>> 32;
246 presenter
->native_size
.cy
= frame_size
;
248 if ((gcd
= get_gcd(presenter
->native_size
.cx
, presenter
->native_size
.cy
)))
250 presenter
->native_ratio
.cx
= presenter
->native_size
.cx
/ gcd
;
251 presenter
->native_ratio
.cy
= presenter
->native_size
.cy
/ gcd
;
255 IMFMediaType_Release(media_type
);
258 /* It is important this is called to reset callback too to break circular referencing,
259 when allocator keeps a reference of its container, that created it. */
260 static void video_presenter_set_allocator_callback(struct video_presenter
*presenter
,
261 IMFVideoSampleAllocatorNotify
*notify_cb
)
263 IMFVideoSampleAllocatorCallback
*cb
;
265 IMFVideoSampleAllocator_QueryInterface(presenter
->allocator
, &IID_IMFVideoSampleAllocatorCallback
, (void **)&cb
);
266 IMFVideoSampleAllocatorCallback_SetCallback(cb
, notify_cb
);
267 IMFVideoSampleAllocatorCallback_Release(cb
);
270 static void video_presenter_reset_media_type(struct video_presenter
*presenter
)
272 if (presenter
->media_type
)
273 IMFMediaType_Release(presenter
->media_type
);
274 presenter
->media_type
= NULL
;
276 if (presenter
->allocator
)
278 IMFVideoSampleAllocator_UninitializeSampleAllocator(presenter
->allocator
);
279 video_presenter_set_allocator_callback(presenter
, NULL
);
283 static HRESULT
video_presenter_set_media_type(struct video_presenter
*presenter
, IMFMediaType
*media_type
)
290 video_presenter_reset_media_type(presenter
);
294 if (presenter
->media_type
&& IMFMediaType_IsEqual(presenter
->media_type
, media_type
, &flags
) == S_OK
)
297 video_presenter_reset_media_type(presenter
);
299 if (SUCCEEDED(hr
= IMFVideoSampleAllocator_InitializeSampleAllocator(presenter
->allocator
,
300 presenter
->allocator_capacity
, media_type
)))
303 UINT64 rate
, frametime
;
305 presenter
->media_type
= media_type
;
306 IMFMediaType_AddRef(presenter
->media_type
);
308 if (SUCCEEDED(IMFMediaType_GetUINT64(presenter
->media_type
, &MF_MT_FRAME_RATE
, &rate
)))
310 ratio
.Denominator
= rate
;
311 ratio
.Numerator
= rate
>> 32;
315 ratio
.Denominator
= 1;
316 ratio
.Numerator
= 30;
319 MFFrameRateToAverageTimePerFrame(ratio
.Numerator
, ratio
.Denominator
, &frametime
);
320 presenter
->frame_time_threshold
= frametime
/ 4;
323 WARN("Failed to initialize sample allocator, hr %#x.\n", hr
);
328 static HRESULT
video_presenter_configure_output_type(struct video_presenter
*presenter
, const MFVideoArea
*aperture
,
329 IMFMediaType
*media_type
)
336 hr
= IMFMediaType_SetUINT64(media_type
, &MF_MT_FRAME_SIZE
, (UINT64
)aperture
->Area
.cx
<< 32 | aperture
->Area
.cy
);
338 hr
= IMFMediaType_SetBlob(media_type
, &MF_MT_GEOMETRIC_APERTURE
, (UINT8
*)aperture
, sizeof(*aperture
));
340 hr
= IMFMediaType_SetBlob(media_type
, &MF_MT_MINIMUM_DISPLAY_APERTURE
, (UINT8
*)aperture
, sizeof(*aperture
));
343 hr
= IMFMediaType_GetGUID(media_type
, &MF_MT_SUBTYPE
, &subtype
);
347 hr
= MFGetStrideForBitmapInfoHeader(subtype
.Data1
, aperture
->Area
.cx
, &stride
);
349 hr
= MFGetPlaneSize(subtype
.Data1
, aperture
->Area
.cx
, aperture
->Area
.cy
, &size
);
351 hr
= IMFMediaType_SetUINT32(media_type
, &MF_MT_DEFAULT_STRIDE
, abs(stride
));
353 hr
= IMFMediaType_SetUINT32(media_type
, &MF_MT_SAMPLE_SIZE
, size
);
359 static HRESULT
video_presenter_invalidate_media_type(struct video_presenter
*presenter
)
361 IMFMediaType
*media_type
, *candidate_type
;
362 MFVideoArea aperture
= {{ 0 }};
363 unsigned int idx
= 0;
367 if (!presenter
->mixer
)
368 return MF_E_TRANSFORM_TYPE_NOT_SET
;
370 if (FAILED(hr
= MFCreateMediaType(&media_type
)))
373 video_presenter_get_native_video_size(presenter
);
375 rect
= presenter
->dst_rect
;
376 if (rect
.left
== 0 && rect
.right
== 0 && rect
.bottom
== 0 && rect
.top
== 0)
378 rect
.right
= presenter
->native_size
.cx
;
379 rect
.bottom
= presenter
->native_size
.cy
;
382 aperture
.Area
.cx
= rect
.right
- rect
.left
;
383 aperture
.Area
.cy
= rect
.bottom
- rect
.top
;
385 while (SUCCEEDED(hr
= IMFTransform_GetOutputAvailableType(presenter
->mixer
, 0, idx
++, &candidate_type
)))
387 /* FIXME: check that d3d device supports this format */
389 if (FAILED(hr
= IMFMediaType_CopyAllItems(candidate_type
, (IMFAttributes
*)media_type
)))
390 WARN("Failed to clone a media type, hr %#x.\n", hr
);
391 IMFMediaType_Release(candidate_type
);
393 hr
= video_presenter_configure_output_type(presenter
, &aperture
, media_type
);
396 hr
= IMFTransform_SetOutputType(presenter
->mixer
, 0, media_type
, MFT_SET_TYPE_TEST_ONLY
);
399 hr
= video_presenter_set_media_type(presenter
, media_type
);
402 hr
= IMFTransform_SetOutputType(presenter
->mixer
, 0, media_type
, 0);
408 IMFMediaType_Release(media_type
);
413 static HRESULT
video_presenter_sample_queue_init(struct video_presenter
*presenter
)
415 struct sample_queue
*queue
= &presenter
->thread
.queue
;
420 memset(queue
, 0, sizeof(*queue
));
421 if (!(queue
->samples
= calloc(presenter
->allocator_capacity
, sizeof(*queue
->samples
))))
422 return E_OUTOFMEMORY
;
424 queue
->size
= presenter
->allocator_capacity
;
425 queue
->back
= queue
->size
- 1;
430 static void video_presenter_sample_queue_push(struct video_presenter
*presenter
, IMFSample
*sample
)
432 struct sample_queue
*queue
= &presenter
->thread
.queue
;
434 EnterCriticalSection(&presenter
->cs
);
435 if (queue
->used
!= queue
->size
)
437 queue
->back
= (queue
->back
+ 1) % queue
->size
;
438 queue
->samples
[queue
->back
] = sample
;
440 IMFSample_AddRef(sample
);
442 LeaveCriticalSection(&presenter
->cs
);
445 static BOOL
video_presenter_sample_queue_pop(struct video_presenter
*presenter
, IMFSample
**sample
)
447 struct sample_queue
*queue
= &presenter
->thread
.queue
;
449 EnterCriticalSection(&presenter
->cs
);
452 *sample
= queue
->samples
[queue
->front
];
453 queue
->front
= (queue
->front
+ 1) % queue
->size
;
458 LeaveCriticalSection(&presenter
->cs
);
460 return *sample
!= NULL
;
463 static HRESULT
video_presenter_get_sample_surface(IMFSample
*sample
, IDirect3DSurface9
**surface
)
465 IMFMediaBuffer
*buffer
;
469 if (FAILED(hr
= IMFSample_GetBufferByIndex(sample
, 0, &buffer
)))
472 hr
= IMFMediaBuffer_QueryInterface(buffer
, &IID_IMFGetService
, (void **)&gs
);
473 IMFMediaBuffer_Release(buffer
);
477 hr
= IMFGetService_GetService(gs
, &MR_BUFFER_SERVICE
, &IID_IDirect3DSurface9
, (void **)surface
);
478 IMFGetService_Release(gs
);
482 static void video_presenter_sample_present(struct video_presenter
*presenter
, IMFSample
*sample
)
484 IDirect3DSurface9
*surface
, *backbuffer
;
485 IDirect3DDevice9
*device
;
488 if (!presenter
->swapchain
)
491 if (FAILED(hr
= video_presenter_get_sample_surface(sample
, &surface
)))
493 WARN("Failed to get sample surface, hr %#x.\n", hr
);
497 if (FAILED(hr
= IDirect3DSwapChain9_GetBackBuffer(presenter
->swapchain
, 0, D3DBACKBUFFER_TYPE_MONO
, &backbuffer
)))
499 WARN("Failed to get a backbuffer, hr %#x.\n", hr
);
500 IDirect3DSurface9_Release(surface
);
504 IDirect3DSwapChain9_GetDevice(presenter
->swapchain
, &device
);
505 IDirect3DDevice9_StretchRect(device
, surface
, NULL
, backbuffer
, NULL
, D3DTEXF_POINT
);
507 IDirect3DSwapChain9_Present(presenter
->swapchain
, NULL
, NULL
, NULL
, NULL
, 0);
508 presenter
->frame_stats
.presented
++;
510 IDirect3DDevice9_Release(device
);
511 IDirect3DSurface9_Release(backbuffer
);
512 IDirect3DSurface9_Release(surface
);
515 static void video_presenter_check_queue(struct video_presenter
*presenter
,
516 unsigned int *next_wait
)
518 LONGLONG pts
, clocktime
, delta
;
519 unsigned int wait
= 0;
525 while (video_presenter_sample_queue_pop(presenter
, &sample
))
530 if (presenter
->clock
)
534 hr
= IMFSample_GetSampleTime(sample
, &pts
);
536 hr
= IMFClock_GetCorrelatedTime(presenter
->clock
, 0, &clocktime
, &systime
);
538 delta
= pts
- clocktime
;
539 if (delta
> 3 * presenter
->frame_time_threshold
)
541 /* Convert 100ns -> msec */
542 wait
= (delta
- 3 * presenter
->frame_time_threshold
) / 100000;
548 video_presenter_sample_present(presenter
, sample
);
550 video_presenter_sample_queue_push(presenter
, sample
);
552 IMFSample_Release(sample
);
564 static void video_presenter_schedule_sample(struct video_presenter
*presenter
, IMFSample
*sample
)
566 if (!presenter
->thread
.tid
)
568 WARN("Streaming thread hasn't been started.\n");
572 if (presenter
->clock
)
574 video_presenter_sample_queue_push(presenter
, sample
);
575 PostThreadMessageW(presenter
->thread
.tid
, EVRM_PRESENT
, 0, 0);
579 video_presenter_sample_present(presenter
, sample
);
583 static HRESULT
video_presenter_process_input(struct video_presenter
*presenter
)
585 MFT_OUTPUT_DATA_BUFFER buffer
;
590 if (presenter
->state
== PRESENTER_STATE_SHUT_DOWN
)
591 return MF_E_SHUTDOWN
;
593 if (!presenter
->media_type
)
598 LONGLONG mixing_started
, mixing_finished
;
601 if (!(presenter
->flags
& PRESENTER_MIXER_HAS_INPUT
))
604 if (FAILED(hr
= IMFVideoSampleAllocator_AllocateSample(presenter
->allocator
, &sample
)))
606 WARN("Failed to allocate a sample, hr %#x.\n", hr
);
610 memset(&buffer
, 0, sizeof(buffer
));
611 buffer
.pSample
= sample
;
613 if (presenter
->clock
)
614 IMFClock_GetCorrelatedTime(presenter
->clock
, 0, &mixing_started
, &systime
);
616 if (FAILED(hr
= IMFTransform_ProcessOutput(presenter
->mixer
, 0, 1, &buffer
, &status
)))
618 /* FIXME: failure path probably needs to handle some errors specifically */
619 presenter
->flags
&= ~PRESENTER_MIXER_HAS_INPUT
;
620 IMFSample_Release(sample
);
625 if (presenter
->clock
)
629 IMFClock_GetCorrelatedTime(presenter
->clock
, 0, &mixing_finished
, &systime
);
630 latency
= mixing_finished
- mixing_started
;
631 video_presenter_notify_renderer(presenter
, EC_PROCESSING_LATENCY
, (LONG_PTR
)&latency
, 0);
635 IMFCollection_Release(buffer
.pEvents
);
637 video_presenter_schedule_sample(presenter
, sample
);
639 IMFSample_Release(sample
);
646 static DWORD CALLBACK
video_presenter_streaming_thread(void *arg
)
648 struct video_presenter
*presenter
= arg
;
649 unsigned int wait
= INFINITE
;
650 BOOL stop_thread
= FALSE
;
653 PeekMessageW(&msg
, NULL
, WM_USER
, WM_USER
, PM_NOREMOVE
);
655 SetEvent(presenter
->thread
.ready_event
);
659 if (MsgWaitForMultipleObjects(0, NULL
, FALSE
, wait
, QS_POSTMESSAGE
) == WAIT_TIMEOUT
)
660 video_presenter_check_queue(presenter
, &wait
);
662 while (PeekMessageW(&msg
, NULL
, 0, 0, PM_REMOVE
))
675 video_presenter_check_queue(presenter
, &wait
);
676 peek
= wait
!= INFINITE
;
680 case EVRM_PROCESS_INPUT
:
681 EnterCriticalSection(&presenter
->cs
);
682 video_presenter_process_input(presenter
);
683 LeaveCriticalSection(&presenter
->cs
);
694 static HRESULT
video_presenter_start_streaming(struct video_presenter
*presenter
)
698 if (presenter
->state
== PRESENTER_STATE_SHUT_DOWN
)
699 return MF_E_SHUTDOWN
;
701 if (presenter
->thread
.hthread
)
704 if (FAILED(hr
= video_presenter_sample_queue_init(presenter
)))
707 if (!(presenter
->thread
.ready_event
= CreateEventW(NULL
, FALSE
, FALSE
, NULL
)))
708 return HRESULT_FROM_WIN32(GetLastError());
710 if (!(presenter
->thread
.hthread
= CreateThread(NULL
, 0, video_presenter_streaming_thread
,
711 presenter
, 0, &presenter
->thread
.tid
)))
713 WARN("Failed to create streaming thread.\n");
714 CloseHandle(presenter
->thread
.ready_event
);
715 presenter
->thread
.ready_event
= NULL
;
719 video_presenter_set_allocator_callback(presenter
, &presenter
->allocator_cb
);
721 WaitForSingleObject(presenter
->thread
.ready_event
, INFINITE
);
722 CloseHandle(presenter
->thread
.ready_event
);
723 presenter
->thread
.ready_event
= NULL
;
725 TRACE("Started streaming thread, tid %#x.\n", presenter
->thread
.tid
);
730 static HRESULT
video_presenter_end_streaming(struct video_presenter
*presenter
)
732 if (!presenter
->thread
.hthread
)
735 PostThreadMessageW(presenter
->thread
.tid
, EVRM_STOP
, 0, 0);
737 WaitForSingleObject(presenter
->thread
.hthread
, INFINITE
);
738 CloseHandle(presenter
->thread
.hthread
);
740 TRACE("Terminated streaming thread tid %#x.\n", presenter
->thread
.tid
);
742 memset(&presenter
->thread
, 0, sizeof(presenter
->thread
));
743 video_presenter_set_allocator_callback(presenter
, NULL
);
748 static HRESULT WINAPI
video_presenter_inner_QueryInterface(IUnknown
*iface
, REFIID riid
, void **obj
)
750 struct video_presenter
*presenter
= impl_from_IUnknown(iface
);
752 TRACE("%p, %s, %p.\n", iface
, debugstr_guid(riid
), obj
);
754 if (IsEqualIID(riid
, &IID_IUnknown
))
758 else if (IsEqualIID(riid
, &IID_IMFClockStateSink
)
759 || IsEqualIID(riid
, &IID_IMFVideoPresenter
))
761 *obj
= &presenter
->IMFVideoPresenter_iface
;
763 else if (IsEqualIID(riid
, &IID_IMFVideoDeviceID
))
765 *obj
= &presenter
->IMFVideoDeviceID_iface
;
767 else if (IsEqualIID(riid
, &IID_IMFTopologyServiceLookupClient
))
769 *obj
= &presenter
->IMFTopologyServiceLookupClient_iface
;
771 else if (IsEqualIID(riid
, &IID_IMFVideoDisplayControl
))
773 *obj
= &presenter
->IMFVideoDisplayControl_iface
;
775 else if (IsEqualIID(riid
, &IID_IMFRateSupport
))
777 *obj
= &presenter
->IMFRateSupport_iface
;
779 else if (IsEqualIID(riid
, &IID_IMFGetService
))
781 *obj
= &presenter
->IMFGetService_iface
;
783 else if (IsEqualIID(riid
, &IID_IMFVideoPositionMapper
))
785 *obj
= &presenter
->IMFVideoPositionMapper_iface
;
787 else if (IsEqualIID(riid
, &IID_IQualProp
))
789 *obj
= &presenter
->IQualProp_iface
;
791 else if (IsEqualIID(riid
, &IID_IMFQualityAdvise
))
793 *obj
= &presenter
->IMFQualityAdvise_iface
;
795 else if (IsEqualIID(riid
, &IID_IMFQualityAdviseLimits
))
797 *obj
= &presenter
->IMFQualityAdviseLimits_iface
;
799 else if (IsEqualIID(riid
, &IID_IDirect3DDeviceManager9
))
801 *obj
= &presenter
->IDirect3DDeviceManager9_iface
;
805 WARN("Unimplemented interface %s.\n", debugstr_guid(riid
));
807 return E_NOINTERFACE
;
810 IUnknown_AddRef((IUnknown
*)*obj
);
814 static ULONG WINAPI
video_presenter_inner_AddRef(IUnknown
*iface
)
816 struct video_presenter
*presenter
= impl_from_IUnknown(iface
);
817 ULONG refcount
= InterlockedIncrement(&presenter
->refcount
);
819 TRACE("%p, refcount %u.\n", iface
, refcount
);
824 static void video_presenter_clear_container(struct video_presenter
*presenter
)
826 if (presenter
->clock
)
827 IMFClock_Release(presenter
->clock
);
828 if (presenter
->mixer
)
829 IMFTransform_Release(presenter
->mixer
);
830 if (presenter
->event_sink
)
831 IMediaEventSink_Release(presenter
->event_sink
);
832 presenter
->clock
= NULL
;
833 presenter
->mixer
= NULL
;
834 presenter
->event_sink
= NULL
;
837 static ULONG WINAPI
video_presenter_inner_Release(IUnknown
*iface
)
839 struct video_presenter
*presenter
= impl_from_IUnknown(iface
);
840 ULONG refcount
= InterlockedDecrement(&presenter
->refcount
);
842 TRACE("%p, refcount %u.\n", iface
, refcount
);
846 video_presenter_end_streaming(presenter
);
847 video_presenter_clear_container(presenter
);
848 video_presenter_reset_media_type(presenter
);
849 DeleteCriticalSection(&presenter
->cs
);
850 if (presenter
->swapchain
)
851 IDirect3DSwapChain9_Release(presenter
->swapchain
);
852 if (presenter
->device_manager
)
854 IDirect3DDeviceManager9_CloseDeviceHandle(presenter
->device_manager
, presenter
->hdevice
);
855 IDirect3DDeviceManager9_Release(presenter
->device_manager
);
857 if (presenter
->allocator
)
858 IMFVideoSampleAllocator_Release(presenter
->allocator
);
865 static const IUnknownVtbl video_presenter_inner_vtbl
=
867 video_presenter_inner_QueryInterface
,
868 video_presenter_inner_AddRef
,
869 video_presenter_inner_Release
,
872 static HRESULT WINAPI
video_presenter_QueryInterface(IMFVideoPresenter
*iface
, REFIID riid
, void **obj
)
874 struct video_presenter
*presenter
= impl_from_IMFVideoPresenter(iface
);
875 return IUnknown_QueryInterface(presenter
->outer_unk
, riid
, obj
);
878 static ULONG WINAPI
video_presenter_AddRef(IMFVideoPresenter
*iface
)
880 struct video_presenter
*presenter
= impl_from_IMFVideoPresenter(iface
);
881 return IUnknown_AddRef(presenter
->outer_unk
);
884 static ULONG WINAPI
video_presenter_Release(IMFVideoPresenter
*iface
)
886 struct video_presenter
*presenter
= impl_from_IMFVideoPresenter(iface
);
887 return IUnknown_Release(presenter
->outer_unk
);
890 static HRESULT WINAPI
video_presenter_OnClockStart(IMFVideoPresenter
*iface
, MFTIME systime
, LONGLONG offset
)
892 struct video_presenter
*presenter
= impl_from_IMFVideoPresenter(iface
);
894 TRACE("%p, %s, %s.\n", iface
, debugstr_time(systime
), wine_dbgstr_longlong(offset
));
896 EnterCriticalSection(&presenter
->cs
);
897 presenter
->state
= PRESENTER_STATE_STARTED
;
898 LeaveCriticalSection(&presenter
->cs
);
903 static HRESULT WINAPI
video_presenter_OnClockStop(IMFVideoPresenter
*iface
, MFTIME systime
)
905 struct video_presenter
*presenter
= impl_from_IMFVideoPresenter(iface
);
907 TRACE("%p, %s.\n", iface
, debugstr_time(systime
));
909 EnterCriticalSection(&presenter
->cs
);
910 presenter
->state
= PRESENTER_STATE_STOPPED
;
911 presenter
->frame_stats
.presented
= 0;
912 LeaveCriticalSection(&presenter
->cs
);
917 static HRESULT WINAPI
video_presenter_OnClockPause(IMFVideoPresenter
*iface
, MFTIME systime
)
919 struct video_presenter
*presenter
= impl_from_IMFVideoPresenter(iface
);
921 TRACE("%p, %s.\n", iface
, debugstr_time(systime
));
923 EnterCriticalSection(&presenter
->cs
);
924 presenter
->state
= PRESENTER_STATE_PAUSED
;
925 LeaveCriticalSection(&presenter
->cs
);
930 static HRESULT WINAPI
video_presenter_OnClockRestart(IMFVideoPresenter
*iface
, MFTIME systime
)
932 struct video_presenter
*presenter
= impl_from_IMFVideoPresenter(iface
);
934 TRACE("%p, %s.\n", iface
, debugstr_time(systime
));
936 EnterCriticalSection(&presenter
->cs
);
937 presenter
->state
= PRESENTER_STATE_STARTED
;
938 LeaveCriticalSection(&presenter
->cs
);
943 static HRESULT WINAPI
video_presenter_OnClockSetRate(IMFVideoPresenter
*iface
, MFTIME systime
, float rate
)
945 FIXME("%p, %s, %f.\n", iface
, debugstr_time(systime
), rate
);
950 static HRESULT WINAPI
video_presenter_ProcessMessage(IMFVideoPresenter
*iface
, MFVP_MESSAGE_TYPE message
, ULONG_PTR param
)
952 struct video_presenter
*presenter
= impl_from_IMFVideoPresenter(iface
);
955 TRACE("%p, %d, %lu.\n", iface
, message
, param
);
957 EnterCriticalSection(&presenter
->cs
);
961 case MFVP_MESSAGE_INVALIDATEMEDIATYPE
:
962 if (presenter
->state
== PRESENTER_STATE_SHUT_DOWN
)
964 else if (!presenter
->mixer
)
965 hr
= MF_E_INVALIDREQUEST
;
967 hr
= video_presenter_invalidate_media_type(presenter
);
969 case MFVP_MESSAGE_BEGINSTREAMING
:
970 hr
= video_presenter_start_streaming(presenter
);
972 case MFVP_MESSAGE_ENDSTREAMING
:
973 hr
= video_presenter_end_streaming(presenter
);
975 case MFVP_MESSAGE_PROCESSINPUTNOTIFY
:
976 presenter
->flags
|= PRESENTER_MIXER_HAS_INPUT
;
977 hr
= video_presenter_process_input(presenter
);
980 FIXME("Unsupported message %u.\n", message
);
984 LeaveCriticalSection(&presenter
->cs
);
989 static HRESULT WINAPI
video_presenter_GetCurrentMediaType(IMFVideoPresenter
*iface
,
990 IMFVideoMediaType
**media_type
)
992 struct video_presenter
*presenter
= impl_from_IMFVideoPresenter(iface
);
995 TRACE("%p, %p.\n", iface
, media_type
);
997 EnterCriticalSection(&presenter
->cs
);
999 if (presenter
->state
== PRESENTER_STATE_SHUT_DOWN
)
1001 else if (!presenter
->media_type
)
1002 hr
= MF_E_NOT_INITIALIZED
;
1005 hr
= IMFMediaType_QueryInterface(presenter
->media_type
, &IID_IMFVideoMediaType
,
1006 (void **)media_type
);
1009 LeaveCriticalSection(&presenter
->cs
);
1014 static const IMFVideoPresenterVtbl video_presenter_vtbl
=
1016 video_presenter_QueryInterface
,
1017 video_presenter_AddRef
,
1018 video_presenter_Release
,
1019 video_presenter_OnClockStart
,
1020 video_presenter_OnClockStop
,
1021 video_presenter_OnClockPause
,
1022 video_presenter_OnClockRestart
,
1023 video_presenter_OnClockSetRate
,
1024 video_presenter_ProcessMessage
,
1025 video_presenter_GetCurrentMediaType
,
1028 static HRESULT WINAPI
video_presenter_device_id_QueryInterface(IMFVideoDeviceID
*iface
, REFIID riid
, void **obj
)
1030 struct video_presenter
*presenter
= impl_from_IMFVideoDeviceID(iface
);
1031 return IMFVideoPresenter_QueryInterface(&presenter
->IMFVideoPresenter_iface
, riid
, obj
);
1034 static ULONG WINAPI
video_presenter_device_id_AddRef(IMFVideoDeviceID
*iface
)
1036 struct video_presenter
*presenter
= impl_from_IMFVideoDeviceID(iface
);
1037 return IMFVideoPresenter_AddRef(&presenter
->IMFVideoPresenter_iface
);
1040 static ULONG WINAPI
video_presenter_device_id_Release(IMFVideoDeviceID
*iface
)
1042 struct video_presenter
*presenter
= impl_from_IMFVideoDeviceID(iface
);
1043 return IMFVideoPresenter_Release(&presenter
->IMFVideoPresenter_iface
);
1046 static HRESULT WINAPI
video_presenter_device_id_GetDeviceID(IMFVideoDeviceID
*iface
, IID
*device_id
)
1048 TRACE("%p, %p.\n", iface
, device_id
);
1053 memcpy(device_id
, &IID_IDirect3DDevice9
, sizeof(*device_id
));
1058 static const IMFVideoDeviceIDVtbl video_presenter_device_id_vtbl
=
1060 video_presenter_device_id_QueryInterface
,
1061 video_presenter_device_id_AddRef
,
1062 video_presenter_device_id_Release
,
1063 video_presenter_device_id_GetDeviceID
,
1066 static HRESULT WINAPI
video_presenter_service_client_QueryInterface(IMFTopologyServiceLookupClient
*iface
,
1067 REFIID riid
, void **obj
)
1069 struct video_presenter
*presenter
= impl_from_IMFTopologyServiceLookupClient(iface
);
1070 return IMFVideoPresenter_QueryInterface(&presenter
->IMFVideoPresenter_iface
, riid
, obj
);
1073 static ULONG WINAPI
video_presenter_service_client_AddRef(IMFTopologyServiceLookupClient
*iface
)
1075 struct video_presenter
*presenter
= impl_from_IMFTopologyServiceLookupClient(iface
);
1076 return IMFVideoPresenter_AddRef(&presenter
->IMFVideoPresenter_iface
);
1079 static ULONG WINAPI
video_presenter_service_client_Release(IMFTopologyServiceLookupClient
*iface
)
1081 struct video_presenter
*presenter
= impl_from_IMFTopologyServiceLookupClient(iface
);
1082 return IMFVideoPresenter_Release(&presenter
->IMFVideoPresenter_iface
);
1085 static void video_presenter_set_mixer_rect(struct video_presenter
*presenter
)
1087 IMFAttributes
*attributes
;
1090 if (!presenter
->mixer
)
1093 if (SUCCEEDED(IMFTransform_GetAttributes(presenter
->mixer
, &attributes
)))
1095 if (FAILED(hr
= IMFAttributes_SetBlob(attributes
, &VIDEO_ZOOM_RECT
, (const UINT8
*)&presenter
->src_rect
,
1096 sizeof(presenter
->src_rect
))))
1098 WARN("Failed to set zoom rectangle attribute, hr %#x.\n", hr
);
1100 IMFAttributes_Release(attributes
);
1104 static HRESULT
video_presenter_attach_mixer(struct video_presenter
*presenter
, IMFTopologyServiceLookup
*service_lookup
)
1106 IMFVideoDeviceID
*device_id
;
1112 if (FAILED(hr
= IMFTopologyServiceLookup_LookupService(service_lookup
, MF_SERVICE_LOOKUP_GLOBAL
, 0,
1113 &MR_VIDEO_MIXER_SERVICE
, &IID_IMFTransform
, (void **)&presenter
->mixer
, &count
)))
1115 WARN("Failed to get mixer interface, hr %#x.\n", hr
);
1119 if (SUCCEEDED(hr
= IMFTransform_QueryInterface(presenter
->mixer
, &IID_IMFVideoDeviceID
, (void **)&device_id
)))
1121 if (SUCCEEDED(hr
= IMFVideoDeviceID_GetDeviceID(device_id
, &id
)))
1123 if (!IsEqualGUID(&id
, &IID_IDirect3DDevice9
))
1124 hr
= MF_E_INVALIDREQUEST
;
1127 IMFVideoDeviceID_Release(device_id
);
1132 IMFTransform_Release(presenter
->mixer
);
1133 presenter
->mixer
= NULL
;
1136 video_presenter_set_mixer_rect(presenter
);
1137 video_presenter_get_native_video_size(presenter
);
1142 static HRESULT WINAPI
video_presenter_service_client_InitServicePointers(IMFTopologyServiceLookupClient
*iface
,
1143 IMFTopologyServiceLookup
*service_lookup
)
1145 struct video_presenter
*presenter
= impl_from_IMFTopologyServiceLookupClient(iface
);
1149 TRACE("%p, %p.\n", iface
, service_lookup
);
1151 if (!service_lookup
)
1154 EnterCriticalSection(&presenter
->cs
);
1156 if (presenter
->state
== PRESENTER_STATE_STARTED
||
1157 presenter
->state
== PRESENTER_STATE_PAUSED
)
1159 hr
= MF_E_INVALIDREQUEST
;
1163 video_presenter_clear_container(presenter
);
1166 IMFTopologyServiceLookup_LookupService(service_lookup
, MF_SERVICE_LOOKUP_GLOBAL
, 0,
1167 &MR_VIDEO_RENDER_SERVICE
, &IID_IMFClock
, (void **)&presenter
->clock
, &count
);
1169 hr
= video_presenter_attach_mixer(presenter
, service_lookup
);
1174 if (FAILED(hr
= IMFTopologyServiceLookup_LookupService(service_lookup
, MF_SERVICE_LOOKUP_GLOBAL
, 0,
1175 &MR_VIDEO_RENDER_SERVICE
, &IID_IMediaEventSink
, (void **)&presenter
->event_sink
, &count
)))
1177 WARN("Failed to get renderer event sink, hr %#x.\n", hr
);
1182 presenter
->state
= PRESENTER_STATE_STOPPED
;
1185 LeaveCriticalSection(&presenter
->cs
);
1190 static HRESULT WINAPI
video_presenter_service_client_ReleaseServicePointers(IMFTopologyServiceLookupClient
*iface
)
1192 struct video_presenter
*presenter
= impl_from_IMFTopologyServiceLookupClient(iface
);
1194 TRACE("%p.\n", iface
);
1196 EnterCriticalSection(&presenter
->cs
);
1198 presenter
->state
= PRESENTER_STATE_SHUT_DOWN
;
1199 video_presenter_clear_container(presenter
);
1201 LeaveCriticalSection(&presenter
->cs
);
1206 static const IMFTopologyServiceLookupClientVtbl video_presenter_service_client_vtbl
=
1208 video_presenter_service_client_QueryInterface
,
1209 video_presenter_service_client_AddRef
,
1210 video_presenter_service_client_Release
,
1211 video_presenter_service_client_InitServicePointers
,
1212 video_presenter_service_client_ReleaseServicePointers
,
1215 static HRESULT WINAPI
video_presenter_control_QueryInterface(IMFVideoDisplayControl
*iface
, REFIID riid
, void **obj
)
1217 struct video_presenter
*presenter
= impl_from_IMFVideoDisplayControl(iface
);
1218 return IMFVideoPresenter_QueryInterface(&presenter
->IMFVideoPresenter_iface
, riid
, obj
);
1221 static ULONG WINAPI
video_presenter_control_AddRef(IMFVideoDisplayControl
*iface
)
1223 struct video_presenter
*presenter
= impl_from_IMFVideoDisplayControl(iface
);
1224 return IMFVideoPresenter_AddRef(&presenter
->IMFVideoPresenter_iface
);
1227 static ULONG WINAPI
video_presenter_control_Release(IMFVideoDisplayControl
*iface
)
1229 struct video_presenter
*presenter
= impl_from_IMFVideoDisplayControl(iface
);
1230 return IMFVideoPresenter_Release(&presenter
->IMFVideoPresenter_iface
);
1233 static HRESULT WINAPI
video_presenter_control_GetNativeVideoSize(IMFVideoDisplayControl
*iface
, SIZE
*video_size
,
1236 struct video_presenter
*presenter
= impl_from_IMFVideoDisplayControl(iface
);
1239 TRACE("%p, %p, %p.\n", iface
, video_size
, aspect_ratio
);
1241 if (!video_size
&& !aspect_ratio
)
1244 EnterCriticalSection(&presenter
->cs
);
1246 if (presenter
->state
== PRESENTER_STATE_SHUT_DOWN
)
1251 *video_size
= presenter
->native_size
;
1253 *aspect_ratio
= presenter
->native_ratio
;
1256 LeaveCriticalSection(&presenter
->cs
);
1261 static HRESULT WINAPI
video_presenter_control_GetIdealVideoSize(IMFVideoDisplayControl
*iface
, SIZE
*min_size
,
1264 struct video_presenter
*presenter
= impl_from_IMFVideoDisplayControl(iface
);
1267 FIXME("%p, %p, %p.\n", iface
, min_size
, max_size
);
1269 EnterCriticalSection(&presenter
->cs
);
1271 if (presenter
->state
== PRESENTER_STATE_SHUT_DOWN
)
1276 LeaveCriticalSection(&presenter
->cs
);
1281 static HRESULT WINAPI
video_presenter_control_SetVideoPosition(IMFVideoDisplayControl
*iface
,
1282 const MFVideoNormalizedRect
*src_rect
, const RECT
*dst_rect
)
1284 struct video_presenter
*presenter
= impl_from_IMFVideoDisplayControl(iface
);
1287 TRACE("%p, %s, %s.\n", iface
, debugstr_normalized_rect(src_rect
), wine_dbgstr_rect(dst_rect
));
1289 if (!src_rect
&& !dst_rect
)
1292 if (src_rect
&& (src_rect
->left
< 0.0f
|| src_rect
->top
< 0.0f
||
1293 src_rect
->right
> 1.0f
|| src_rect
->bottom
> 1.0f
||
1294 src_rect
->left
> src_rect
->right
||
1295 src_rect
->top
> src_rect
->bottom
))
1297 return E_INVALIDARG
;
1300 if (dst_rect
&& (dst_rect
->left
> dst_rect
->right
||
1301 dst_rect
->top
> dst_rect
->bottom
))
1302 return E_INVALIDARG
;
1304 EnterCriticalSection(&presenter
->cs
);
1305 if (!presenter
->video_window
)
1311 if (memcmp(&presenter
->src_rect
, src_rect
, sizeof(*src_rect
)))
1313 presenter
->src_rect
= *src_rect
;
1314 video_presenter_set_mixer_rect(presenter
);
1317 if (dst_rect
&& !EqualRect(dst_rect
, &presenter
->dst_rect
))
1319 presenter
->dst_rect
= *dst_rect
;
1320 hr
= video_presenter_invalidate_media_type(presenter
);
1321 /* Mixer's input type hasn't been configured yet, this is not an error. */
1322 if (hr
== MF_E_TRANSFORM_TYPE_NOT_SET
) hr
= S_OK
;
1323 /* FIXME: trigger repaint */
1326 LeaveCriticalSection(&presenter
->cs
);
1331 static HRESULT WINAPI
video_presenter_control_GetVideoPosition(IMFVideoDisplayControl
*iface
, MFVideoNormalizedRect
*src_rect
,
1334 struct video_presenter
*presenter
= impl_from_IMFVideoDisplayControl(iface
);
1336 TRACE("%p, %p, %p.\n", iface
, src_rect
, dst_rect
);
1338 if (!src_rect
|| !dst_rect
)
1341 EnterCriticalSection(&presenter
->cs
);
1342 *src_rect
= presenter
->src_rect
;
1343 *dst_rect
= presenter
->dst_rect
;
1344 LeaveCriticalSection(&presenter
->cs
);
1349 static HRESULT WINAPI
video_presenter_control_SetAspectRatioMode(IMFVideoDisplayControl
*iface
, DWORD mode
)
1351 struct video_presenter
*presenter
= impl_from_IMFVideoDisplayControl(iface
);
1353 TRACE("%p, %#x.\n", iface
, mode
);
1355 if (mode
& ~MFVideoARMode_Mask
)
1356 return E_INVALIDARG
;
1358 EnterCriticalSection(&presenter
->cs
);
1359 presenter
->ar_mode
= mode
;
1360 LeaveCriticalSection(&presenter
->cs
);
1365 static HRESULT WINAPI
video_presenter_control_GetAspectRatioMode(IMFVideoDisplayControl
*iface
, DWORD
*mode
)
1367 struct video_presenter
*presenter
= impl_from_IMFVideoDisplayControl(iface
);
1369 TRACE("%p, %p.\n", iface
, mode
);
1374 EnterCriticalSection(&presenter
->cs
);
1375 *mode
= presenter
->ar_mode
;
1376 LeaveCriticalSection(&presenter
->cs
);
1381 static HRESULT
video_presenter_create_swapchain(struct video_presenter
*presenter
)
1383 D3DPRESENT_PARAMETERS present_params
= { 0 };
1384 IDirect3DDevice9
*d3d_device
;
1387 if (SUCCEEDED(hr
= video_presenter_get_device(presenter
, &d3d_device
)))
1389 present_params
.hDeviceWindow
= presenter
->video_window
;
1390 present_params
.Windowed
= TRUE
;
1391 present_params
.SwapEffect
= D3DSWAPEFFECT_COPY
;
1392 present_params
.Flags
= D3DPRESENTFLAG_VIDEO
;
1393 present_params
.PresentationInterval
= D3DPRESENT_INTERVAL_IMMEDIATE
;
1394 hr
= IDirect3DDevice9_CreateAdditionalSwapChain(d3d_device
, &present_params
, &presenter
->swapchain
);
1396 IDirect3DDevice9_Release(d3d_device
);
1397 IDirect3DDeviceManager9_UnlockDevice(presenter
->device_manager
, presenter
->hdevice
, FALSE
);
1403 static HRESULT WINAPI
video_presenter_control_SetVideoWindow(IMFVideoDisplayControl
*iface
, HWND window
)
1405 struct video_presenter
*presenter
= impl_from_IMFVideoDisplayControl(iface
);
1408 TRACE("%p, %p.\n", iface
, window
);
1410 if (!IsWindow(window
))
1411 return E_INVALIDARG
;
1413 EnterCriticalSection(&presenter
->cs
);
1414 if (presenter
->video_window
!= window
)
1416 if (presenter
->swapchain
)
1417 IDirect3DSwapChain9_Release(presenter
->swapchain
);
1418 presenter
->video_window
= window
;
1419 hr
= video_presenter_create_swapchain(presenter
);
1421 LeaveCriticalSection(&presenter
->cs
);
1426 static HRESULT WINAPI
video_presenter_control_GetVideoWindow(IMFVideoDisplayControl
*iface
, HWND
*window
)
1428 struct video_presenter
*presenter
= impl_from_IMFVideoDisplayControl(iface
);
1430 TRACE("%p, %p.\n", iface
, window
);
1435 EnterCriticalSection(&presenter
->cs
);
1436 *window
= presenter
->video_window
;
1437 LeaveCriticalSection(&presenter
->cs
);
1442 static HRESULT WINAPI
video_presenter_control_RepaintVideo(IMFVideoDisplayControl
*iface
)
1444 struct video_presenter
*presenter
= impl_from_IMFVideoDisplayControl(iface
);
1447 FIXME("%p.\n", iface
);
1449 EnterCriticalSection(&presenter
->cs
);
1451 if (presenter
->state
== PRESENTER_STATE_SHUT_DOWN
)
1456 LeaveCriticalSection(&presenter
->cs
);
1461 static HRESULT WINAPI
video_presenter_control_GetCurrentImage(IMFVideoDisplayControl
*iface
, BITMAPINFOHEADER
*header
,
1462 BYTE
**dib
, DWORD
*dib_size
, LONGLONG
*timestamp
)
1464 FIXME("%p, %p, %p, %p, %p.\n", iface
, header
, dib
, dib_size
, timestamp
);
1469 static HRESULT WINAPI
video_presenter_control_SetBorderColor(IMFVideoDisplayControl
*iface
, COLORREF color
)
1471 FIXME("%p, %#x.\n", iface
, color
);
1476 static HRESULT WINAPI
video_presenter_control_GetBorderColor(IMFVideoDisplayControl
*iface
, COLORREF
*color
)
1478 FIXME("%p, %p.\n", iface
, color
);
1483 static HRESULT WINAPI
video_presenter_control_SetRenderingPrefs(IMFVideoDisplayControl
*iface
, DWORD flags
)
1485 FIXME("%p, %#x.\n", iface
, flags
);
1490 static HRESULT WINAPI
video_presenter_control_GetRenderingPrefs(IMFVideoDisplayControl
*iface
, DWORD
*flags
)
1492 struct video_presenter
*presenter
= impl_from_IMFVideoDisplayControl(iface
);
1494 TRACE("%p, %p.\n", iface
, flags
);
1499 EnterCriticalSection(&presenter
->cs
);
1500 *flags
= presenter
->rendering_prefs
;
1501 LeaveCriticalSection(&presenter
->cs
);
1506 static HRESULT WINAPI
video_presenter_control_SetFullscreen(IMFVideoDisplayControl
*iface
, BOOL fullscreen
)
1508 FIXME("%p, %d.\n", iface
, fullscreen
);
1513 static HRESULT WINAPI
video_presenter_control_GetFullscreen(IMFVideoDisplayControl
*iface
, BOOL
*fullscreen
)
1515 FIXME("%p, %p.\n", iface
, fullscreen
);
1520 static const IMFVideoDisplayControlVtbl video_presenter_control_vtbl
=
1522 video_presenter_control_QueryInterface
,
1523 video_presenter_control_AddRef
,
1524 video_presenter_control_Release
,
1525 video_presenter_control_GetNativeVideoSize
,
1526 video_presenter_control_GetIdealVideoSize
,
1527 video_presenter_control_SetVideoPosition
,
1528 video_presenter_control_GetVideoPosition
,
1529 video_presenter_control_SetAspectRatioMode
,
1530 video_presenter_control_GetAspectRatioMode
,
1531 video_presenter_control_SetVideoWindow
,
1532 video_presenter_control_GetVideoWindow
,
1533 video_presenter_control_RepaintVideo
,
1534 video_presenter_control_GetCurrentImage
,
1535 video_presenter_control_SetBorderColor
,
1536 video_presenter_control_GetBorderColor
,
1537 video_presenter_control_SetRenderingPrefs
,
1538 video_presenter_control_GetRenderingPrefs
,
1539 video_presenter_control_SetFullscreen
,
1540 video_presenter_control_GetFullscreen
,
1543 static HRESULT WINAPI
video_presenter_rate_support_QueryInterface(IMFRateSupport
*iface
, REFIID riid
, void **obj
)
1545 struct video_presenter
*presenter
= impl_from_IMFRateSupport(iface
);
1546 return IMFVideoPresenter_QueryInterface(&presenter
->IMFVideoPresenter_iface
, riid
, obj
);
1549 static ULONG WINAPI
video_presenter_rate_support_AddRef(IMFRateSupport
*iface
)
1551 struct video_presenter
*presenter
= impl_from_IMFRateSupport(iface
);
1552 return IMFVideoPresenter_AddRef(&presenter
->IMFVideoPresenter_iface
);
1555 static ULONG WINAPI
video_presenter_rate_support_Release(IMFRateSupport
*iface
)
1557 struct video_presenter
*presenter
= impl_from_IMFRateSupport(iface
);
1558 return IMFVideoPresenter_Release(&presenter
->IMFVideoPresenter_iface
);
1561 static HRESULT WINAPI
video_presenter_rate_support_GetSlowestRate(IMFRateSupport
*iface
, MFRATE_DIRECTION direction
,
1562 BOOL thin
, float *rate
)
1564 TRACE("%p, %d, %d, %p.\n", iface
, direction
, thin
, rate
);
1571 static HRESULT WINAPI
video_presenter_rate_support_GetFastestRate(IMFRateSupport
*iface
, MFRATE_DIRECTION direction
,
1572 BOOL thin
, float *rate
)
1577 static HRESULT WINAPI
video_presenter_rate_support_IsRateSupported(IMFRateSupport
*iface
, BOOL thin
, float rate
,
1578 float *nearest_supported_rate
)
1583 static const IMFRateSupportVtbl video_presenter_rate_support_vtbl
=
1585 video_presenter_rate_support_QueryInterface
,
1586 video_presenter_rate_support_AddRef
,
1587 video_presenter_rate_support_Release
,
1588 video_presenter_rate_support_GetSlowestRate
,
1589 video_presenter_rate_support_GetFastestRate
,
1590 video_presenter_rate_support_IsRateSupported
,
1593 static HRESULT WINAPI
video_presenter_getservice_QueryInterface(IMFGetService
*iface
, REFIID riid
, void **obj
)
1595 struct video_presenter
*presenter
= impl_from_IMFGetService(iface
);
1596 return IMFVideoPresenter_QueryInterface(&presenter
->IMFVideoPresenter_iface
, riid
, obj
);
1599 static ULONG WINAPI
video_presenter_getservice_AddRef(IMFGetService
*iface
)
1601 struct video_presenter
*presenter
= impl_from_IMFGetService(iface
);
1602 return IMFVideoPresenter_AddRef(&presenter
->IMFVideoPresenter_iface
);
1605 static ULONG WINAPI
video_presenter_getservice_Release(IMFGetService
*iface
)
1607 struct video_presenter
*presenter
= impl_from_IMFGetService(iface
);
1608 return IMFVideoPresenter_Release(&presenter
->IMFVideoPresenter_iface
);
1611 static HRESULT WINAPI
video_presenter_getservice_GetService(IMFGetService
*iface
, REFGUID service
, REFIID riid
, void **obj
)
1613 struct video_presenter
*presenter
= impl_from_IMFGetService(iface
);
1615 TRACE("%p, %s, %s, %p.\n", iface
, debugstr_guid(service
), debugstr_guid(riid
), obj
);
1617 if (IsEqualGUID(&MR_VIDEO_ACCELERATION_SERVICE
, service
))
1618 return IDirect3DDeviceManager9_QueryInterface(presenter
->device_manager
, riid
, obj
);
1620 if (IsEqualGUID(&MR_VIDEO_RENDER_SERVICE
, service
))
1621 return IMFVideoPresenter_QueryInterface(&presenter
->IMFVideoPresenter_iface
, riid
, obj
);
1623 FIXME("Unimplemented service %s.\n", debugstr_guid(service
));
1625 return MF_E_UNSUPPORTED_SERVICE
;
1628 static const IMFGetServiceVtbl video_presenter_getservice_vtbl
=
1630 video_presenter_getservice_QueryInterface
,
1631 video_presenter_getservice_AddRef
,
1632 video_presenter_getservice_Release
,
1633 video_presenter_getservice_GetService
,
1636 static HRESULT WINAPI
video_presenter_position_mapper_QueryInterface(IMFVideoPositionMapper
*iface
, REFIID riid
, void **obj
)
1638 struct video_presenter
*presenter
= impl_from_IMFVideoPositionMapper(iface
);
1639 return IMFVideoPresenter_QueryInterface(&presenter
->IMFVideoPresenter_iface
, riid
, obj
);
1642 static ULONG WINAPI
video_presenter_position_mapper_AddRef(IMFVideoPositionMapper
*iface
)
1644 struct video_presenter
*presenter
= impl_from_IMFVideoPositionMapper(iface
);
1645 return IMFVideoPresenter_AddRef(&presenter
->IMFVideoPresenter_iface
);
1648 static ULONG WINAPI
video_presenter_position_mapper_Release(IMFVideoPositionMapper
*iface
)
1650 struct video_presenter
*presenter
= impl_from_IMFVideoPositionMapper(iface
);
1651 return IMFVideoPresenter_Release(&presenter
->IMFVideoPresenter_iface
);
1654 static HRESULT WINAPI
video_presenter_position_mapper_MapOutputCoordinateToInputStream(IMFVideoPositionMapper
*iface
,
1655 float x_out
, float y_out
, DWORD output_stream
, DWORD input_stream
, float *x_in
, float *y_in
)
1657 FIXME("%p, %f, %f, %u, %u, %p, %p.\n", iface
, x_out
, y_out
, output_stream
, input_stream
, x_in
, y_in
);
1662 static const IMFVideoPositionMapperVtbl video_presenter_position_mapper_vtbl
=
1664 video_presenter_position_mapper_QueryInterface
,
1665 video_presenter_position_mapper_AddRef
,
1666 video_presenter_position_mapper_Release
,
1667 video_presenter_position_mapper_MapOutputCoordinateToInputStream
,
1670 static HRESULT WINAPI
video_presenter_allocator_cb_QueryInterface(IMFVideoSampleAllocatorNotify
*iface
,
1671 REFIID riid
, void **obj
)
1673 if (IsEqualIID(riid
, &IID_IMFVideoSampleAllocatorNotify
) ||
1674 IsEqualIID(riid
, &IID_IUnknown
))
1677 IMFVideoSampleAllocatorNotify_AddRef(iface
);
1681 WARN("Unsupported interface %s.\n", debugstr_guid(riid
));
1683 return E_NOINTERFACE
;
1686 static ULONG WINAPI
video_presenter_allocator_cb_AddRef(IMFVideoSampleAllocatorNotify
*iface
)
1688 struct video_presenter
*presenter
= impl_from_IMFVideoSampleAllocatorNotify(iface
);
1689 return IMFVideoPresenter_AddRef(&presenter
->IMFVideoPresenter_iface
);
1692 static ULONG WINAPI
video_presenter_allocator_cb_Release(IMFVideoSampleAllocatorNotify
*iface
)
1694 struct video_presenter
*presenter
= impl_from_IMFVideoSampleAllocatorNotify(iface
);
1695 return IMFVideoPresenter_Release(&presenter
->IMFVideoPresenter_iface
);
1698 static HRESULT WINAPI
video_presenter_allocator_cb_NotifyRelease(IMFVideoSampleAllocatorNotify
*iface
)
1700 struct video_presenter
*presenter
= impl_from_IMFVideoSampleAllocatorNotify(iface
);
1702 /* Release notification is executed under allocator lock, instead of processing samples here
1703 notify streaming thread. */
1704 PostThreadMessageW(presenter
->thread
.tid
, EVRM_PROCESS_INPUT
, 0, 0);
1709 static const IMFVideoSampleAllocatorNotifyVtbl video_presenter_allocator_cb_vtbl
=
1711 video_presenter_allocator_cb_QueryInterface
,
1712 video_presenter_allocator_cb_AddRef
,
1713 video_presenter_allocator_cb_Release
,
1714 video_presenter_allocator_cb_NotifyRelease
,
1717 static HRESULT WINAPI
video_presenter_qualprop_QueryInterface(IQualProp
*iface
, REFIID riid
, void **obj
)
1719 struct video_presenter
*presenter
= impl_from_IQualProp(iface
);
1720 return IMFVideoPresenter_QueryInterface(&presenter
->IMFVideoPresenter_iface
, riid
, obj
);
1723 static ULONG WINAPI
video_presenter_qualprop_AddRef(IQualProp
*iface
)
1725 struct video_presenter
*presenter
= impl_from_IQualProp(iface
);
1726 return IMFVideoPresenter_AddRef(&presenter
->IMFVideoPresenter_iface
);
1729 static ULONG WINAPI
video_presenter_qualprop_Release(IQualProp
*iface
)
1731 struct video_presenter
*presenter
= impl_from_IQualProp(iface
);
1732 return IMFVideoPresenter_Release(&presenter
->IMFVideoPresenter_iface
);
1735 static HRESULT WINAPI
video_presenter_qualprop_get_FramesDroppedInRenderer(IQualProp
*iface
, int *frames
)
1737 FIXME("%p, %p stub.\n", iface
, frames
);
1742 static HRESULT WINAPI
video_presenter_qualprop_get_FramesDrawn(IQualProp
*iface
, int *frames
)
1744 struct video_presenter
*presenter
= impl_from_IQualProp(iface
);
1747 TRACE("%p, %p.\n", iface
, frames
);
1749 EnterCriticalSection(&presenter
->cs
);
1751 switch (presenter
->state
)
1753 case PRESENTER_STATE_STARTED
:
1754 case PRESENTER_STATE_PAUSED
:
1755 if (frames
) *frames
= presenter
->frame_stats
.presented
;
1756 else hr
= E_POINTER
;
1762 LeaveCriticalSection(&presenter
->cs
);
1767 static HRESULT WINAPI
video_presenter_qualprop_get_AvgFrameRate(IQualProp
*iface
, int *avg_frame_rate
)
1769 FIXME("%p, %p stub.\n", iface
, avg_frame_rate
);
1774 static HRESULT WINAPI
video_presenter_qualprop_get_Jitter(IQualProp
*iface
, int *jitter
)
1776 FIXME("%p, %p stub.\n", iface
, jitter
);
1781 static HRESULT WINAPI
video_presenter_qualprop_get_AvgSyncOffset(IQualProp
*iface
, int *offset
)
1783 FIXME("%p, %p stub.\n", iface
, offset
);
1788 static HRESULT WINAPI
video_presenter_qualprop_get_DevSyncOffset(IQualProp
*iface
, int *devoffset
)
1790 FIXME("%p, %p stub.\n", iface
, devoffset
);
1795 static const IQualPropVtbl video_presenter_qualprop_vtbl
=
1797 video_presenter_qualprop_QueryInterface
,
1798 video_presenter_qualprop_AddRef
,
1799 video_presenter_qualprop_Release
,
1800 video_presenter_qualprop_get_FramesDroppedInRenderer
,
1801 video_presenter_qualprop_get_FramesDrawn
,
1802 video_presenter_qualprop_get_AvgFrameRate
,
1803 video_presenter_qualprop_get_Jitter
,
1804 video_presenter_qualprop_get_AvgSyncOffset
,
1805 video_presenter_qualprop_get_DevSyncOffset
,
1808 static HRESULT WINAPI
video_presenter_quality_advise_QueryInterface(IMFQualityAdvise
*iface
, REFIID riid
, void **out
)
1810 struct video_presenter
*presenter
= impl_from_IMFQualityAdvise(iface
);
1811 return IMFVideoPresenter_QueryInterface(&presenter
->IMFVideoPresenter_iface
, riid
, out
);
1814 static ULONG WINAPI
video_presenter_quality_advise_AddRef(IMFQualityAdvise
*iface
)
1816 struct video_presenter
*presenter
= impl_from_IMFQualityAdvise(iface
);
1817 return IMFVideoPresenter_AddRef(&presenter
->IMFVideoPresenter_iface
);
1820 static ULONG WINAPI
video_presenter_quality_advise_Release(IMFQualityAdvise
*iface
)
1822 struct video_presenter
*presenter
= impl_from_IMFQualityAdvise(iface
);
1823 return IMFVideoPresenter_Release(&presenter
->IMFVideoPresenter_iface
);
1826 static HRESULT WINAPI
video_presenter_quality_advise_SetDropMode(IMFQualityAdvise
*iface
,
1827 MF_QUALITY_DROP_MODE mode
)
1829 FIXME("%p, %u.\n", iface
, mode
);
1834 static HRESULT WINAPI
video_presenter_quality_advise_SetQualityLevel(IMFQualityAdvise
*iface
,
1835 MF_QUALITY_LEVEL level
)
1837 FIXME("%p, %u.\n", iface
, level
);
1842 static HRESULT WINAPI
video_presenter_quality_advise_GetDropMode(IMFQualityAdvise
*iface
,
1843 MF_QUALITY_DROP_MODE
*mode
)
1845 FIXME("%p, %p.\n", iface
, mode
);
1850 static HRESULT WINAPI
video_presenter_quality_advise_GetQualityLevel(IMFQualityAdvise
*iface
,
1851 MF_QUALITY_LEVEL
*level
)
1853 FIXME("%p, %p.\n", iface
, level
);
1858 static HRESULT WINAPI
video_presenter_quality_advise_DropTime(IMFQualityAdvise
*iface
, LONGLONG interval
)
1860 FIXME("%p, %s.\n", iface
, wine_dbgstr_longlong(interval
));
1865 static const IMFQualityAdviseVtbl video_presenter_quality_advise_vtbl
=
1867 video_presenter_quality_advise_QueryInterface
,
1868 video_presenter_quality_advise_AddRef
,
1869 video_presenter_quality_advise_Release
,
1870 video_presenter_quality_advise_SetDropMode
,
1871 video_presenter_quality_advise_SetQualityLevel
,
1872 video_presenter_quality_advise_GetDropMode
,
1873 video_presenter_quality_advise_GetQualityLevel
,
1874 video_presenter_quality_advise_DropTime
,
1877 static HRESULT WINAPI
video_presenter_device_manager_QueryInterface(IDirect3DDeviceManager9
*iface
,
1878 REFIID riid
, void **obj
)
1880 struct video_presenter
*presenter
= impl_from_IDirect3DDeviceManager9(iface
);
1881 return IMFVideoPresenter_QueryInterface(&presenter
->IMFVideoPresenter_iface
, riid
, obj
);
1884 static ULONG WINAPI
video_presenter_device_manager_AddRef(IDirect3DDeviceManager9
*iface
)
1886 struct video_presenter
*presenter
= impl_from_IDirect3DDeviceManager9(iface
);
1887 return IMFVideoPresenter_AddRef(&presenter
->IMFVideoPresenter_iface
);
1890 static ULONG WINAPI
video_presenter_device_manager_Release(IDirect3DDeviceManager9
*iface
)
1892 struct video_presenter
*presenter
= impl_from_IDirect3DDeviceManager9(iface
);
1893 return IMFVideoPresenter_Release(&presenter
->IMFVideoPresenter_iface
);
1896 static HRESULT WINAPI
video_presenter_device_manager_ResetDevice(IDirect3DDeviceManager9
*iface
,
1897 IDirect3DDevice9
*device
, UINT token
)
1899 struct video_presenter
*presenter
= impl_from_IDirect3DDeviceManager9(iface
);
1900 return IDirect3DDeviceManager9_ResetDevice(presenter
->device_manager
, device
, token
);
1903 static HRESULT WINAPI
video_presenter_device_manager_OpenDeviceHandle(IDirect3DDeviceManager9
*iface
, HANDLE
*hdevice
)
1905 struct video_presenter
*presenter
= impl_from_IDirect3DDeviceManager9(iface
);
1906 return IDirect3DDeviceManager9_OpenDeviceHandle(presenter
->device_manager
, hdevice
);
1909 static HRESULT WINAPI
video_presenter_device_manager_CloseDeviceHandle(IDirect3DDeviceManager9
*iface
, HANDLE hdevice
)
1911 struct video_presenter
*presenter
= impl_from_IDirect3DDeviceManager9(iface
);
1912 return IDirect3DDeviceManager9_CloseDeviceHandle(presenter
->device_manager
, hdevice
);
1915 static HRESULT WINAPI
video_presenter_device_manager_TestDevice(IDirect3DDeviceManager9
*iface
, HANDLE hdevice
)
1917 struct video_presenter
*presenter
= impl_from_IDirect3DDeviceManager9(iface
);
1918 return IDirect3DDeviceManager9_TestDevice(presenter
->device_manager
, hdevice
);
1921 static HRESULT WINAPI
video_presenter_device_manager_LockDevice(IDirect3DDeviceManager9
*iface
, HANDLE hdevice
,
1922 IDirect3DDevice9
**device
, BOOL block
)
1924 struct video_presenter
*presenter
= impl_from_IDirect3DDeviceManager9(iface
);
1925 return IDirect3DDeviceManager9_LockDevice(presenter
->device_manager
, hdevice
, device
, block
);
1928 static HRESULT WINAPI
video_presenter_device_manager_UnlockDevice(IDirect3DDeviceManager9
*iface
, HANDLE hdevice
,
1931 struct video_presenter
*presenter
= impl_from_IDirect3DDeviceManager9(iface
);
1932 return IDirect3DDeviceManager9_UnlockDevice(presenter
->device_manager
, hdevice
, savestate
);
1935 static HRESULT WINAPI
video_presenter_device_manager_GetVideoService(IDirect3DDeviceManager9
*iface
, HANDLE hdevice
,
1936 REFIID riid
, void **service
)
1938 struct video_presenter
*presenter
= impl_from_IDirect3DDeviceManager9(iface
);
1939 return IDirect3DDeviceManager9_GetVideoService(presenter
->device_manager
, hdevice
, riid
, service
);
1942 static const IDirect3DDeviceManager9Vtbl video_presenter_device_manager_vtbl
=
1944 video_presenter_device_manager_QueryInterface
,
1945 video_presenter_device_manager_AddRef
,
1946 video_presenter_device_manager_Release
,
1947 video_presenter_device_manager_ResetDevice
,
1948 video_presenter_device_manager_OpenDeviceHandle
,
1949 video_presenter_device_manager_CloseDeviceHandle
,
1950 video_presenter_device_manager_TestDevice
,
1951 video_presenter_device_manager_LockDevice
,
1952 video_presenter_device_manager_UnlockDevice
,
1953 video_presenter_device_manager_GetVideoService
,
1956 static HRESULT WINAPI
video_presenter_qa_limits_QueryInterface(IMFQualityAdviseLimits
*iface
, REFIID riid
, void **obj
)
1958 struct video_presenter
*presenter
= impl_from_IMFQualityAdviseLimits(iface
);
1959 return IMFVideoPresenter_QueryInterface(&presenter
->IMFVideoPresenter_iface
, riid
, obj
);
1962 static ULONG WINAPI
video_presenter_qa_limits_AddRef(IMFQualityAdviseLimits
*iface
)
1964 struct video_presenter
*presenter
= impl_from_IMFQualityAdviseLimits(iface
);
1965 return IMFVideoPresenter_AddRef(&presenter
->IMFVideoPresenter_iface
);
1968 static ULONG WINAPI
video_presenter_qa_limits_Release(IMFQualityAdviseLimits
*iface
)
1970 struct video_presenter
*presenter
= impl_from_IMFQualityAdviseLimits(iface
);
1971 return IMFVideoPresenter_Release(&presenter
->IMFVideoPresenter_iface
);
1974 static HRESULT WINAPI
video_presenter_qa_limits_GetMaximumDropMode(IMFQualityAdviseLimits
*iface
, MF_QUALITY_DROP_MODE
*mode
)
1976 FIXME("%p, %p.\n", iface
, mode
);
1981 static HRESULT WINAPI
video_presenter_qa_limits_GetMinimumQualityLevel(IMFQualityAdviseLimits
*iface
, MF_QUALITY_LEVEL
*level
)
1983 FIXME("%p, %p.\n", iface
, level
);
1988 static const IMFQualityAdviseLimitsVtbl video_presenter_qa_limits_vtbl
=
1990 video_presenter_qa_limits_QueryInterface
,
1991 video_presenter_qa_limits_AddRef
,
1992 video_presenter_qa_limits_Release
,
1993 video_presenter_qa_limits_GetMaximumDropMode
,
1994 video_presenter_qa_limits_GetMinimumQualityLevel
,
1997 HRESULT WINAPI
MFCreateVideoPresenter(IUnknown
*owner
, REFIID riid_device
, REFIID riid
, void **obj
)
1999 TRACE("%p, %s, %s, %p.\n", owner
, debugstr_guid(riid_device
), debugstr_guid(riid
), obj
);
2003 if (!IsEqualIID(riid_device
, &IID_IDirect3DDevice9
))
2004 return E_INVALIDARG
;
2006 return CoCreateInstance(&CLSID_MFVideoPresenter9
, owner
, CLSCTX_INPROC_SERVER
, riid
, obj
);
2009 static HRESULT
video_presenter_init_d3d(struct video_presenter
*presenter
)
2011 D3DPRESENT_PARAMETERS present_params
= { 0 };
2012 IDirect3DDevice9
*device
;
2016 d3d
= Direct3DCreate9(D3D_SDK_VERSION
);
2018 present_params
.BackBufferCount
= 1;
2019 present_params
.SwapEffect
= D3DSWAPEFFECT_COPY
;
2020 present_params
.hDeviceWindow
= GetDesktopWindow();
2021 present_params
.Windowed
= TRUE
;
2022 present_params
.Flags
= D3DPRESENTFLAG_VIDEO
;
2023 present_params
.PresentationInterval
= D3DPRESENT_INTERVAL_IMMEDIATE
;
2024 hr
= IDirect3D9_CreateDevice(d3d
, D3DADAPTER_DEFAULT
, D3DDEVTYPE_HAL
, GetDesktopWindow(),
2025 D3DCREATE_HARDWARE_VERTEXPROCESSING
, &present_params
, &device
);
2027 IDirect3D9_Release(d3d
);
2031 WARN("Failed to create d3d device, hr %#x.\n", hr
);
2035 hr
= IDirect3DDeviceManager9_ResetDevice(presenter
->device_manager
, device
, presenter
->reset_token
);
2036 IDirect3DDevice9_Release(device
);
2038 WARN("Failed to set new device for the manager, hr %#x.\n", hr
);
2040 if (SUCCEEDED(hr
= MFCreateVideoSampleAllocator(&IID_IMFVideoSampleAllocator
, (void **)&presenter
->allocator
)))
2042 hr
= IMFVideoSampleAllocator_SetDirectXManager(presenter
->allocator
, (IUnknown
*)presenter
->device_manager
);
2048 HRESULT
evr_presenter_create(IUnknown
*outer
, void **out
)
2050 struct video_presenter
*object
;
2055 if (!(object
= calloc(1, sizeof(*object
))))
2056 return E_OUTOFMEMORY
;
2058 object
->IMFVideoPresenter_iface
.lpVtbl
= &video_presenter_vtbl
;
2059 object
->IMFVideoDeviceID_iface
.lpVtbl
= &video_presenter_device_id_vtbl
;
2060 object
->IMFTopologyServiceLookupClient_iface
.lpVtbl
= &video_presenter_service_client_vtbl
;
2061 object
->IMFVideoDisplayControl_iface
.lpVtbl
= &video_presenter_control_vtbl
;
2062 object
->IMFRateSupport_iface
.lpVtbl
= &video_presenter_rate_support_vtbl
;
2063 object
->IMFGetService_iface
.lpVtbl
= &video_presenter_getservice_vtbl
;
2064 object
->IMFVideoPositionMapper_iface
.lpVtbl
= &video_presenter_position_mapper_vtbl
;
2065 object
->IQualProp_iface
.lpVtbl
= &video_presenter_qualprop_vtbl
;
2066 object
->IMFQualityAdvise_iface
.lpVtbl
= &video_presenter_quality_advise_vtbl
;
2067 object
->IMFQualityAdviseLimits_iface
.lpVtbl
= &video_presenter_qa_limits_vtbl
;
2068 object
->allocator_cb
.lpVtbl
= &video_presenter_allocator_cb_vtbl
;
2069 object
->IUnknown_inner
.lpVtbl
= &video_presenter_inner_vtbl
;
2070 object
->IDirect3DDeviceManager9_iface
.lpVtbl
= &video_presenter_device_manager_vtbl
;
2071 object
->outer_unk
= outer
? outer
: &object
->IUnknown_inner
;
2072 object
->refcount
= 1;
2073 object
->src_rect
.right
= object
->src_rect
.bottom
= 1.0f
;
2074 object
->ar_mode
= MFVideoARMode_PreservePicture
| MFVideoARMode_PreservePixel
;
2075 object
->allocator_capacity
= 3;
2076 InitializeCriticalSection(&object
->cs
);
2078 if (FAILED(hr
= DXVA2CreateDirect3DDeviceManager9(&object
->reset_token
, &object
->device_manager
)))
2081 if (FAILED(hr
= video_presenter_init_d3d(object
)))
2083 WARN("Failed to initialize d3d device, hr %#x.\n", hr
);
2087 *out
= &object
->IUnknown_inner
;
2093 IUnknown_Release(&object
->IUnknown_inner
);