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
);
36 PRESENTER_STATE_SHUT_DOWN
= 0,
37 PRESENTER_STATE_STARTED
,
38 PRESENTER_STATE_STOPPED
,
39 PRESENTER_STATE_PAUSED
,
44 PRESENTER_MIXER_HAS_INPUT
= 0x1,
47 enum streaming_thread_message
50 EVRM_PRESENT
= WM_USER
+ 1,
51 EVRM_PROCESS_INPUT
= WM_USER
+ 2,
63 struct streaming_thread
68 struct sample_queue queue
;
71 struct video_presenter
73 IMFVideoPresenter IMFVideoPresenter_iface
;
74 IMFVideoDeviceID IMFVideoDeviceID_iface
;
75 IMFTopologyServiceLookupClient IMFTopologyServiceLookupClient_iface
;
76 IMFVideoDisplayControl IMFVideoDisplayControl_iface
;
77 IMFRateSupport IMFRateSupport_iface
;
78 IMFGetService IMFGetService_iface
;
79 IMFVideoPositionMapper IMFVideoPositionMapper_iface
;
80 IQualProp IQualProp_iface
;
81 IMFQualityAdvise IMFQualityAdvise_iface
;
82 IMFQualityAdviseLimits IMFQualityAdviseLimits_iface
;
83 IDirect3DDeviceManager9 IDirect3DDeviceManager9_iface
;
84 IMFVideoSampleAllocatorNotify allocator_cb
;
85 IUnknown IUnknown_inner
;
91 IMediaEventSink
*event_sink
;
93 IDirect3DDeviceManager9
*device_manager
;
94 IDirect3DSwapChain9
*swapchain
;
97 IMFVideoSampleAllocator
*allocator
;
98 struct streaming_thread thread
;
99 unsigned int allocator_capacity
;
100 IMFMediaType
*media_type
;
101 LONGLONG frame_time_threshold
;
104 MFVideoNormalizedRect src_rect
;
106 DWORD rendering_prefs
;
109 unsigned int ar_mode
;
115 static struct video_presenter
*impl_from_IUnknown(IUnknown
*iface
)
117 return CONTAINING_RECORD(iface
, struct video_presenter
, IUnknown_inner
);
120 static struct video_presenter
*impl_from_IMFVideoPresenter(IMFVideoPresenter
*iface
)
122 return CONTAINING_RECORD(iface
, struct video_presenter
, IMFVideoPresenter_iface
);
125 static struct video_presenter
*impl_from_IMFVideoDeviceID(IMFVideoDeviceID
*iface
)
127 return CONTAINING_RECORD(iface
, struct video_presenter
, IMFVideoDeviceID_iface
);
130 static struct video_presenter
*impl_from_IMFTopologyServiceLookupClient(IMFTopologyServiceLookupClient
*iface
)
132 return CONTAINING_RECORD(iface
, struct video_presenter
, IMFTopologyServiceLookupClient_iface
);
135 static struct video_presenter
*impl_from_IMFVideoDisplayControl(IMFVideoDisplayControl
*iface
)
137 return CONTAINING_RECORD(iface
, struct video_presenter
, IMFVideoDisplayControl_iface
);
140 static struct video_presenter
*impl_from_IMFRateSupport(IMFRateSupport
*iface
)
142 return CONTAINING_RECORD(iface
, struct video_presenter
, IMFRateSupport_iface
);
145 static struct video_presenter
*impl_from_IMFGetService(IMFGetService
*iface
)
147 return CONTAINING_RECORD(iface
, struct video_presenter
, IMFGetService_iface
);
150 static struct video_presenter
*impl_from_IMFVideoPositionMapper(IMFVideoPositionMapper
*iface
)
152 return CONTAINING_RECORD(iface
, struct video_presenter
, IMFVideoPositionMapper_iface
);
155 static struct video_presenter
*impl_from_IMFVideoSampleAllocatorNotify(IMFVideoSampleAllocatorNotify
*iface
)
157 return CONTAINING_RECORD(iface
, struct video_presenter
, allocator_cb
);
160 static struct video_presenter
*impl_from_IQualProp(IQualProp
*iface
)
162 return CONTAINING_RECORD(iface
, struct video_presenter
, IQualProp_iface
);
165 static struct video_presenter
*impl_from_IMFQualityAdvise(IMFQualityAdvise
*iface
)
167 return CONTAINING_RECORD(iface
, struct video_presenter
, IMFQualityAdvise_iface
);
170 static struct video_presenter
*impl_from_IMFQualityAdviseLimits(IMFQualityAdviseLimits
*iface
)
172 return CONTAINING_RECORD(iface
, struct video_presenter
, IMFQualityAdviseLimits_iface
);
175 static struct video_presenter
*impl_from_IDirect3DDeviceManager9(IDirect3DDeviceManager9
*iface
)
177 return CONTAINING_RECORD(iface
, struct video_presenter
, IDirect3DDeviceManager9_iface
);
180 static void video_presenter_notify_renderer(struct video_presenter
*presenter
,
181 LONG event
, LONG_PTR param1
, LONG_PTR param2
)
183 if (presenter
->event_sink
)
184 IMediaEventSink_Notify(presenter
->event_sink
, event
, param1
, param2
);
187 static unsigned int get_gcd(unsigned int a
, unsigned int b
)
201 static HRESULT
video_presenter_get_device(struct video_presenter
*presenter
, IDirect3DDevice9
**device
)
205 if (!presenter
->hdevice
)
207 if (FAILED(hr
= IDirect3DDeviceManager9_OpenDeviceHandle(presenter
->device_manager
, &presenter
->hdevice
)))
211 return IDirect3DDeviceManager9_LockDevice(presenter
->device_manager
, presenter
->hdevice
, device
, TRUE
);
214 static void video_presenter_get_native_video_size(struct video_presenter
*presenter
)
216 IMFMediaType
*media_type
;
217 UINT64 frame_size
= 0;
219 memset(&presenter
->native_size
, 0, sizeof(presenter
->native_size
));
220 memset(&presenter
->native_ratio
, 0, sizeof(presenter
->native_ratio
));
222 if (!presenter
->mixer
)
225 if (FAILED(IMFTransform_GetInputCurrentType(presenter
->mixer
, 0, &media_type
)))
228 if (SUCCEEDED(IMFMediaType_GetUINT64(media_type
, &MF_MT_FRAME_SIZE
, &frame_size
)))
232 presenter
->native_size
.cx
= frame_size
>> 32;
233 presenter
->native_size
.cy
= frame_size
;
235 if ((gcd
= get_gcd(presenter
->native_size
.cx
, presenter
->native_size
.cy
)))
237 presenter
->native_ratio
.cx
= presenter
->native_size
.cx
/ gcd
;
238 presenter
->native_ratio
.cy
= presenter
->native_size
.cy
/ gcd
;
242 IMFMediaType_Release(media_type
);
245 /* It is important this is called to reset callback too to break circular referencing,
246 when allocator keeps a reference of its container, that created it. */
247 static void video_presenter_set_allocator_callback(struct video_presenter
*presenter
,
248 IMFVideoSampleAllocatorNotify
*notify_cb
)
250 IMFVideoSampleAllocatorCallback
*cb
;
252 IMFVideoSampleAllocator_QueryInterface(presenter
->allocator
, &IID_IMFVideoSampleAllocatorCallback
, (void **)&cb
);
253 IMFVideoSampleAllocatorCallback_SetCallback(cb
, notify_cb
);
254 IMFVideoSampleAllocatorCallback_Release(cb
);
257 static void video_presenter_reset_media_type(struct video_presenter
*presenter
)
259 if (presenter
->media_type
)
260 IMFMediaType_Release(presenter
->media_type
);
261 presenter
->media_type
= NULL
;
263 IMFVideoSampleAllocator_UninitializeSampleAllocator(presenter
->allocator
);
264 video_presenter_set_allocator_callback(presenter
, NULL
);
267 static HRESULT
video_presenter_set_media_type(struct video_presenter
*presenter
, IMFMediaType
*media_type
)
274 video_presenter_reset_media_type(presenter
);
278 if (presenter
->media_type
&& IMFMediaType_IsEqual(presenter
->media_type
, media_type
, &flags
) == S_OK
)
281 video_presenter_reset_media_type(presenter
);
283 if (SUCCEEDED(hr
= IMFVideoSampleAllocator_InitializeSampleAllocator(presenter
->allocator
,
284 presenter
->allocator_capacity
, media_type
)))
287 UINT64 rate
, frametime
;
289 presenter
->media_type
= media_type
;
290 IMFMediaType_AddRef(presenter
->media_type
);
292 if (SUCCEEDED(IMFMediaType_GetUINT64(presenter
->media_type
, &MF_MT_FRAME_RATE
, &rate
)))
294 ratio
.Denominator
= rate
;
295 ratio
.Numerator
= rate
>> 32;
299 ratio
.Denominator
= 1;
300 ratio
.Numerator
= 30;
303 MFFrameRateToAverageTimePerFrame(ratio
.Numerator
, ratio
.Denominator
, &frametime
);
304 presenter
->frame_time_threshold
= frametime
/ 4;
307 WARN("Failed to initialize sample allocator, hr %#x.\n", hr
);
312 static HRESULT
video_presenter_configure_output_type(struct video_presenter
*presenter
, const MFVideoArea
*aperture
,
313 IMFMediaType
*media_type
)
320 hr
= IMFMediaType_SetUINT64(media_type
, &MF_MT_FRAME_SIZE
, (UINT64
)aperture
->Area
.cx
<< 32 | aperture
->Area
.cy
);
322 hr
= IMFMediaType_SetBlob(media_type
, &MF_MT_GEOMETRIC_APERTURE
, (UINT8
*)aperture
, sizeof(*aperture
));
324 hr
= IMFMediaType_SetBlob(media_type
, &MF_MT_MINIMUM_DISPLAY_APERTURE
, (UINT8
*)aperture
, sizeof(*aperture
));
327 hr
= IMFMediaType_GetGUID(media_type
, &MF_MT_SUBTYPE
, &subtype
);
331 hr
= MFGetStrideForBitmapInfoHeader(subtype
.Data1
, aperture
->Area
.cx
, &stride
);
333 hr
= MFGetPlaneSize(subtype
.Data1
, aperture
->Area
.cx
, aperture
->Area
.cy
, &size
);
335 hr
= IMFMediaType_SetUINT32(media_type
, &MF_MT_DEFAULT_STRIDE
, abs(stride
));
337 hr
= IMFMediaType_SetUINT32(media_type
, &MF_MT_SAMPLE_SIZE
, size
);
343 static HRESULT
video_presenter_invalidate_media_type(struct video_presenter
*presenter
)
345 IMFMediaType
*media_type
, *candidate_type
;
346 MFVideoArea aperture
= {{ 0 }};
347 unsigned int idx
= 0;
351 if (FAILED(hr
= MFCreateMediaType(&media_type
)))
354 video_presenter_get_native_video_size(presenter
);
356 rect
= presenter
->dst_rect
;
357 if (rect
.left
== 0 && rect
.right
== 0 && rect
.bottom
== 0 && rect
.top
== 0)
359 rect
.right
= presenter
->native_size
.cx
;
360 rect
.bottom
= presenter
->native_size
.cy
;
363 aperture
.Area
.cx
= rect
.right
- rect
.left
;
364 aperture
.Area
.cy
= rect
.bottom
- rect
.top
;
366 while (SUCCEEDED(hr
= IMFTransform_GetOutputAvailableType(presenter
->mixer
, 0, idx
++, &candidate_type
)))
368 /* FIXME: check that d3d device supports this format */
370 if (FAILED(hr
= IMFMediaType_CopyAllItems(candidate_type
, (IMFAttributes
*)media_type
)))
371 WARN("Failed to clone a media type, hr %#x.\n", hr
);
372 IMFMediaType_Release(candidate_type
);
374 hr
= video_presenter_configure_output_type(presenter
, &aperture
, media_type
);
377 hr
= IMFTransform_SetOutputType(presenter
->mixer
, 0, media_type
, MFT_SET_TYPE_TEST_ONLY
);
380 hr
= video_presenter_set_media_type(presenter
, media_type
);
383 hr
= IMFTransform_SetOutputType(presenter
->mixer
, 0, media_type
, 0);
389 IMFMediaType_Release(media_type
);
394 static HRESULT
video_presenter_sample_queue_init(struct video_presenter
*presenter
)
396 struct sample_queue
*queue
= &presenter
->thread
.queue
;
401 memset(queue
, 0, sizeof(*queue
));
402 if (!(queue
->samples
= calloc(presenter
->allocator_capacity
, sizeof(*queue
->samples
))))
403 return E_OUTOFMEMORY
;
405 queue
->size
= presenter
->allocator_capacity
;
406 queue
->back
= queue
->size
- 1;
411 static void video_presenter_sample_queue_push(struct video_presenter
*presenter
, IMFSample
*sample
)
413 struct sample_queue
*queue
= &presenter
->thread
.queue
;
415 EnterCriticalSection(&presenter
->cs
);
416 if (queue
->used
!= queue
->size
)
418 queue
->back
= (queue
->back
+ 1) % queue
->size
;
419 queue
->samples
[queue
->back
] = sample
;
421 IMFSample_AddRef(sample
);
423 LeaveCriticalSection(&presenter
->cs
);
426 static BOOL
video_presenter_sample_queue_pop(struct video_presenter
*presenter
, IMFSample
**sample
)
428 struct sample_queue
*queue
= &presenter
->thread
.queue
;
430 EnterCriticalSection(&presenter
->cs
);
433 *sample
= queue
->samples
[queue
->front
];
434 queue
->front
= (queue
->front
+ 1) % queue
->size
;
439 LeaveCriticalSection(&presenter
->cs
);
441 return *sample
!= NULL
;
444 static HRESULT
video_presenter_get_sample_surface(IMFSample
*sample
, IDirect3DSurface9
**surface
)
446 IMFMediaBuffer
*buffer
;
450 if (FAILED(hr
= IMFSample_GetBufferByIndex(sample
, 0, &buffer
)))
453 hr
= IMFMediaBuffer_QueryInterface(buffer
, &IID_IMFGetService
, (void **)&gs
);
454 IMFMediaBuffer_Release(buffer
);
458 hr
= IMFGetService_GetService(gs
, &MR_BUFFER_SERVICE
, &IID_IDirect3DSurface9
, (void **)surface
);
459 IMFGetService_Release(gs
);
463 static void scale_rect(RECT
*rect
, unsigned int width
, unsigned int height
, const MFVideoNormalizedRect
*scale
)
465 if (rect
->left
== 0.0f
&& rect
->top
== 0.0f
&& rect
->right
== 1.0f
&& rect
->bottom
== 1.0f
)
467 SetRect(rect
, 0, 0, width
, height
);
471 rect
->left
= width
* scale
->left
;
472 rect
->right
= width
* scale
->right
;
473 rect
->top
= height
* scale
->top
;
474 rect
->bottom
= height
* scale
->bottom
;
478 static void video_presenter_sample_present(struct video_presenter
*presenter
, IMFSample
*sample
)
480 IDirect3DSurface9
*surface
, *backbuffer
;
481 IDirect3DDevice9
*device
;
482 D3DSURFACE_DESC desc
;
486 if (!presenter
->swapchain
)
489 if (FAILED(hr
= video_presenter_get_sample_surface(sample
, &surface
)))
491 WARN("Failed to get sample surface, hr %#x.\n", hr
);
495 if (FAILED(hr
= IDirect3DSwapChain9_GetBackBuffer(presenter
->swapchain
, 0, D3DBACKBUFFER_TYPE_MONO
, &backbuffer
)))
497 WARN("Failed to get a backbuffer, hr %#x.\n", hr
);
498 IDirect3DSurface9_Release(surface
);
502 IDirect3DSwapChain9_GetDevice(presenter
->swapchain
, &device
);
503 IDirect3DDevice9_StretchRect(device
, surface
, NULL
, backbuffer
, NULL
, D3DTEXF_POINT
);
505 IDirect3DSurface9_GetDesc(surface
, &desc
);
506 scale_rect(&src
, desc
.Width
, desc
.Height
, &presenter
->src_rect
);
508 IDirect3DSurface9_GetDesc(backbuffer
, &desc
);
509 SetRect(&dst
, 0, 0, desc
.Width
, desc
.Height
);
511 if (presenter
->ar_mode
& MFVideoARMode_PreservePicture
)
513 unsigned int src_width
= src
.right
- src
.left
, src_height
= src
.bottom
- src
.top
;
514 unsigned int dst_width
= dst
.right
- dst
.left
, dst_height
= dst
.bottom
- dst
.top
;
516 if (src_width
* dst_height
> dst_width
* src_height
)
518 /* src is "wider" than dst. */
519 unsigned int dst_center
= (dst
.top
+ dst
.bottom
) / 2;
520 unsigned int scaled_height
= src_height
* dst_width
/ src_width
;
522 dst
.top
= dst_center
- scaled_height
/ 2;
523 dst
.bottom
= dst
.top
+ scaled_height
;
525 else if (src_width
* dst_height
< dst_width
* src_height
)
527 /* src is "taller" than dst. */
528 unsigned int dst_center
= (dst
.left
+ dst
.right
) / 2;
529 unsigned int scaled_width
= src_width
* dst_height
/ src_height
;
531 dst
.left
= dst_center
- scaled_width
/ 2;
532 dst
.right
= dst
.left
+ scaled_width
;
536 IDirect3DSwapChain9_Present(presenter
->swapchain
, &src
, &dst
, NULL
, NULL
, 0);
538 IDirect3DDevice9_Release(device
);
539 IDirect3DSurface9_Release(backbuffer
);
540 IDirect3DSurface9_Release(surface
);
543 static void video_presenter_check_queue(struct video_presenter
*presenter
,
544 unsigned int *next_wait
)
546 LONGLONG pts
, clocktime
, delta
;
547 unsigned int wait
= 0;
553 while (video_presenter_sample_queue_pop(presenter
, &sample
))
558 if (presenter
->clock
)
562 hr
= IMFSample_GetSampleTime(sample
, &pts
);
564 hr
= IMFClock_GetCorrelatedTime(presenter
->clock
, 0, &clocktime
, &systime
);
566 delta
= pts
- clocktime
;
567 if (delta
> 3 * presenter
->frame_time_threshold
)
569 /* Convert 100ns -> msec */
570 wait
= (delta
- 3 * presenter
->frame_time_threshold
) / 100000;
576 video_presenter_sample_present(presenter
, sample
);
578 video_presenter_sample_queue_push(presenter
, sample
);
580 IMFSample_Release(sample
);
592 static void video_presenter_schedule_sample(struct video_presenter
*presenter
, IMFSample
*sample
)
594 if (!presenter
->thread
.tid
)
596 WARN("Streaming thread hasn't been started.\n");
600 if (presenter
->clock
)
602 video_presenter_sample_queue_push(presenter
, sample
);
603 PostThreadMessageW(presenter
->thread
.tid
, EVRM_PRESENT
, 0, 0);
607 video_presenter_sample_present(presenter
, sample
);
611 static HRESULT
video_presenter_process_input(struct video_presenter
*presenter
)
613 MFT_OUTPUT_DATA_BUFFER buffer
;
618 if (!presenter
->media_type
)
623 LONGLONG mixing_started
, mixing_finished
;
626 if (!(presenter
->flags
& PRESENTER_MIXER_HAS_INPUT
))
629 if (FAILED(hr
= IMFVideoSampleAllocator_AllocateSample(presenter
->allocator
, &sample
)))
631 WARN("Failed to allocate a sample, hr %#x.\n", hr
);
635 memset(&buffer
, 0, sizeof(buffer
));
636 buffer
.pSample
= sample
;
638 if (presenter
->clock
)
639 IMFClock_GetCorrelatedTime(presenter
->clock
, 0, &mixing_started
, &systime
);
641 if (FAILED(hr
= IMFTransform_ProcessOutput(presenter
->mixer
, 0, 1, &buffer
, &status
)))
643 /* FIXME: failure path probably needs to handle some errors specifically */
644 presenter
->flags
&= ~PRESENTER_MIXER_HAS_INPUT
;
645 IMFSample_Release(sample
);
650 if (presenter
->clock
)
654 IMFClock_GetCorrelatedTime(presenter
->clock
, 0, &mixing_finished
, &systime
);
655 latency
= mixing_finished
- mixing_started
;
656 video_presenter_notify_renderer(presenter
, EC_PROCESSING_LATENCY
, (LONG_PTR
)&latency
, 0);
660 IMFCollection_Release(buffer
.pEvents
);
662 video_presenter_schedule_sample(presenter
, sample
);
664 IMFSample_Release(sample
);
671 static DWORD CALLBACK
video_presenter_streaming_thread(void *arg
)
673 struct video_presenter
*presenter
= arg
;
674 unsigned int wait
= INFINITE
;
675 BOOL stop_thread
= FALSE
;
678 PeekMessageW(&msg
, NULL
, WM_USER
, WM_USER
, PM_NOREMOVE
);
680 SetEvent(presenter
->thread
.ready_event
);
684 if (MsgWaitForMultipleObjects(0, NULL
, FALSE
, wait
, QS_POSTMESSAGE
) == WAIT_TIMEOUT
)
685 video_presenter_check_queue(presenter
, &wait
);
687 while (PeekMessageW(&msg
, NULL
, 0, 0, PM_REMOVE
))
700 video_presenter_check_queue(presenter
, &wait
);
701 peek
= wait
!= INFINITE
;
705 case EVRM_PROCESS_INPUT
:
706 EnterCriticalSection(&presenter
->cs
);
707 video_presenter_process_input(presenter
);
708 LeaveCriticalSection(&presenter
->cs
);
719 static HRESULT
video_presenter_start_streaming(struct video_presenter
*presenter
)
723 if (presenter
->thread
.hthread
)
726 if (FAILED(hr
= video_presenter_sample_queue_init(presenter
)))
729 if (!(presenter
->thread
.ready_event
= CreateEventW(NULL
, FALSE
, FALSE
, NULL
)))
730 return HRESULT_FROM_WIN32(GetLastError());
732 if (!(presenter
->thread
.hthread
= CreateThread(NULL
, 0, video_presenter_streaming_thread
,
733 presenter
, 0, &presenter
->thread
.tid
)))
735 WARN("Failed to create streaming thread.\n");
736 CloseHandle(presenter
->thread
.ready_event
);
737 presenter
->thread
.ready_event
= NULL
;
741 video_presenter_set_allocator_callback(presenter
, &presenter
->allocator_cb
);
743 WaitForSingleObject(presenter
->thread
.ready_event
, INFINITE
);
744 CloseHandle(presenter
->thread
.ready_event
);
745 presenter
->thread
.ready_event
= NULL
;
747 TRACE("Started streaming thread, tid %#x.\n", presenter
->thread
.tid
);
752 static HRESULT
video_presenter_end_streaming(struct video_presenter
*presenter
)
754 if (!presenter
->thread
.hthread
)
757 PostThreadMessageW(presenter
->thread
.tid
, EVRM_STOP
, 0, 0);
759 WaitForSingleObject(presenter
->thread
.hthread
, INFINITE
);
760 CloseHandle(presenter
->thread
.hthread
);
762 TRACE("Terminated streaming thread tid %#x.\n", presenter
->thread
.tid
);
764 memset(&presenter
->thread
, 0, sizeof(presenter
->thread
));
765 video_presenter_set_allocator_callback(presenter
, NULL
);
770 static HRESULT WINAPI
video_presenter_inner_QueryInterface(IUnknown
*iface
, REFIID riid
, void **obj
)
772 struct video_presenter
*presenter
= impl_from_IUnknown(iface
);
774 TRACE("%p, %s, %p.\n", iface
, debugstr_guid(riid
), obj
);
776 if (IsEqualIID(riid
, &IID_IUnknown
))
780 else if (IsEqualIID(riid
, &IID_IMFClockStateSink
)
781 || IsEqualIID(riid
, &IID_IMFVideoPresenter
))
783 *obj
= &presenter
->IMFVideoPresenter_iface
;
785 else if (IsEqualIID(riid
, &IID_IMFVideoDeviceID
))
787 *obj
= &presenter
->IMFVideoDeviceID_iface
;
789 else if (IsEqualIID(riid
, &IID_IMFTopologyServiceLookupClient
))
791 *obj
= &presenter
->IMFTopologyServiceLookupClient_iface
;
793 else if (IsEqualIID(riid
, &IID_IMFVideoDisplayControl
))
795 *obj
= &presenter
->IMFVideoDisplayControl_iface
;
797 else if (IsEqualIID(riid
, &IID_IMFRateSupport
))
799 *obj
= &presenter
->IMFRateSupport_iface
;
801 else if (IsEqualIID(riid
, &IID_IMFGetService
))
803 *obj
= &presenter
->IMFGetService_iface
;
805 else if (IsEqualIID(riid
, &IID_IMFVideoPositionMapper
))
807 *obj
= &presenter
->IMFVideoPositionMapper_iface
;
809 else if (IsEqualIID(riid
, &IID_IQualProp
))
811 *obj
= &presenter
->IQualProp_iface
;
813 else if (IsEqualIID(riid
, &IID_IMFQualityAdvise
))
815 *obj
= &presenter
->IMFQualityAdvise_iface
;
817 else if (IsEqualIID(riid
, &IID_IMFQualityAdviseLimits
))
819 *obj
= &presenter
->IMFQualityAdviseLimits_iface
;
821 else if (IsEqualIID(riid
, &IID_IDirect3DDeviceManager9
))
823 *obj
= &presenter
->IDirect3DDeviceManager9_iface
;
827 WARN("Unimplemented interface %s.\n", debugstr_guid(riid
));
829 return E_NOINTERFACE
;
832 IUnknown_AddRef((IUnknown
*)*obj
);
836 static ULONG WINAPI
video_presenter_inner_AddRef(IUnknown
*iface
)
838 struct video_presenter
*presenter
= impl_from_IUnknown(iface
);
839 ULONG refcount
= InterlockedIncrement(&presenter
->refcount
);
841 TRACE("%p, refcount %u.\n", iface
, refcount
);
846 static void video_presenter_clear_container(struct video_presenter
*presenter
)
848 if (presenter
->clock
)
849 IMFClock_Release(presenter
->clock
);
850 if (presenter
->mixer
)
851 IMFTransform_Release(presenter
->mixer
);
852 if (presenter
->event_sink
)
853 IMediaEventSink_Release(presenter
->event_sink
);
854 presenter
->clock
= NULL
;
855 presenter
->mixer
= NULL
;
856 presenter
->event_sink
= NULL
;
859 static ULONG WINAPI
video_presenter_inner_Release(IUnknown
*iface
)
861 struct video_presenter
*presenter
= impl_from_IUnknown(iface
);
862 ULONG refcount
= InterlockedDecrement(&presenter
->refcount
);
864 TRACE("%p, refcount %u.\n", iface
, refcount
);
868 video_presenter_end_streaming(presenter
);
869 video_presenter_clear_container(presenter
);
870 video_presenter_reset_media_type(presenter
);
871 DeleteCriticalSection(&presenter
->cs
);
872 if (presenter
->swapchain
)
873 IDirect3DSwapChain9_Release(presenter
->swapchain
);
874 if (presenter
->device_manager
)
876 IDirect3DDeviceManager9_CloseDeviceHandle(presenter
->device_manager
, presenter
->hdevice
);
877 IDirect3DDeviceManager9_Release(presenter
->device_manager
);
879 if (presenter
->allocator
)
880 IMFVideoSampleAllocator_Release(presenter
->allocator
);
887 static const IUnknownVtbl video_presenter_inner_vtbl
=
889 video_presenter_inner_QueryInterface
,
890 video_presenter_inner_AddRef
,
891 video_presenter_inner_Release
,
894 static HRESULT WINAPI
video_presenter_QueryInterface(IMFVideoPresenter
*iface
, REFIID riid
, void **obj
)
896 struct video_presenter
*presenter
= impl_from_IMFVideoPresenter(iface
);
897 return IUnknown_QueryInterface(presenter
->outer_unk
, riid
, obj
);
900 static ULONG WINAPI
video_presenter_AddRef(IMFVideoPresenter
*iface
)
902 struct video_presenter
*presenter
= impl_from_IMFVideoPresenter(iface
);
903 return IUnknown_AddRef(presenter
->outer_unk
);
906 static ULONG WINAPI
video_presenter_Release(IMFVideoPresenter
*iface
)
908 struct video_presenter
*presenter
= impl_from_IMFVideoPresenter(iface
);
909 return IUnknown_Release(presenter
->outer_unk
);
912 static HRESULT WINAPI
video_presenter_OnClockStart(IMFVideoPresenter
*iface
, MFTIME systime
, LONGLONG offset
)
914 struct video_presenter
*presenter
= impl_from_IMFVideoPresenter(iface
);
916 TRACE("%p, %s, %s.\n", iface
, debugstr_time(systime
), wine_dbgstr_longlong(offset
));
918 EnterCriticalSection(&presenter
->cs
);
919 presenter
->state
= PRESENTER_STATE_STARTED
;
920 LeaveCriticalSection(&presenter
->cs
);
925 static HRESULT WINAPI
video_presenter_OnClockStop(IMFVideoPresenter
*iface
, MFTIME systime
)
927 struct video_presenter
*presenter
= impl_from_IMFVideoPresenter(iface
);
929 TRACE("%p, %s.\n", iface
, debugstr_time(systime
));
931 EnterCriticalSection(&presenter
->cs
);
932 presenter
->state
= PRESENTER_STATE_STOPPED
;
933 LeaveCriticalSection(&presenter
->cs
);
938 static HRESULT WINAPI
video_presenter_OnClockPause(IMFVideoPresenter
*iface
, MFTIME systime
)
940 struct video_presenter
*presenter
= impl_from_IMFVideoPresenter(iface
);
942 TRACE("%p, %s.\n", iface
, debugstr_time(systime
));
944 EnterCriticalSection(&presenter
->cs
);
945 presenter
->state
= PRESENTER_STATE_PAUSED
;
946 LeaveCriticalSection(&presenter
->cs
);
951 static HRESULT WINAPI
video_presenter_OnClockRestart(IMFVideoPresenter
*iface
, MFTIME systime
)
953 struct video_presenter
*presenter
= impl_from_IMFVideoPresenter(iface
);
955 TRACE("%p, %s.\n", iface
, debugstr_time(systime
));
957 EnterCriticalSection(&presenter
->cs
);
958 presenter
->state
= PRESENTER_STATE_STARTED
;
959 LeaveCriticalSection(&presenter
->cs
);
964 static HRESULT WINAPI
video_presenter_OnClockSetRate(IMFVideoPresenter
*iface
, MFTIME systime
, float rate
)
966 FIXME("%p, %s, %f.\n", iface
, debugstr_time(systime
), rate
);
971 static HRESULT WINAPI
video_presenter_ProcessMessage(IMFVideoPresenter
*iface
, MFVP_MESSAGE_TYPE message
, ULONG_PTR param
)
973 struct video_presenter
*presenter
= impl_from_IMFVideoPresenter(iface
);
976 TRACE("%p, %d, %lu.\n", iface
, message
, param
);
978 EnterCriticalSection(&presenter
->cs
);
982 case MFVP_MESSAGE_INVALIDATEMEDIATYPE
:
983 hr
= video_presenter_invalidate_media_type(presenter
);
985 case MFVP_MESSAGE_BEGINSTREAMING
:
986 hr
= video_presenter_start_streaming(presenter
);
988 case MFVP_MESSAGE_ENDSTREAMING
:
989 hr
= video_presenter_end_streaming(presenter
);
991 case MFVP_MESSAGE_PROCESSINPUTNOTIFY
:
992 presenter
->flags
|= PRESENTER_MIXER_HAS_INPUT
;
993 hr
= video_presenter_process_input(presenter
);
996 FIXME("Unsupported message %u.\n", message
);
1000 LeaveCriticalSection(&presenter
->cs
);
1005 static HRESULT WINAPI
video_presenter_GetCurrentMediaType(IMFVideoPresenter
*iface
,
1006 IMFVideoMediaType
**media_type
)
1008 struct video_presenter
*presenter
= impl_from_IMFVideoPresenter(iface
);
1011 TRACE("%p, %p.\n", iface
, media_type
);
1013 EnterCriticalSection(&presenter
->cs
);
1015 if (presenter
->state
== PRESENTER_STATE_SHUT_DOWN
)
1017 else if (!presenter
->media_type
)
1018 hr
= MF_E_NOT_INITIALIZED
;
1021 hr
= IMFMediaType_QueryInterface(presenter
->media_type
, &IID_IMFVideoMediaType
,
1022 (void **)media_type
);
1025 LeaveCriticalSection(&presenter
->cs
);
1030 static const IMFVideoPresenterVtbl video_presenter_vtbl
=
1032 video_presenter_QueryInterface
,
1033 video_presenter_AddRef
,
1034 video_presenter_Release
,
1035 video_presenter_OnClockStart
,
1036 video_presenter_OnClockStop
,
1037 video_presenter_OnClockPause
,
1038 video_presenter_OnClockRestart
,
1039 video_presenter_OnClockSetRate
,
1040 video_presenter_ProcessMessage
,
1041 video_presenter_GetCurrentMediaType
,
1044 static HRESULT WINAPI
video_presenter_device_id_QueryInterface(IMFVideoDeviceID
*iface
, REFIID riid
, void **obj
)
1046 struct video_presenter
*presenter
= impl_from_IMFVideoDeviceID(iface
);
1047 return IMFVideoPresenter_QueryInterface(&presenter
->IMFVideoPresenter_iface
, riid
, obj
);
1050 static ULONG WINAPI
video_presenter_device_id_AddRef(IMFVideoDeviceID
*iface
)
1052 struct video_presenter
*presenter
= impl_from_IMFVideoDeviceID(iface
);
1053 return IMFVideoPresenter_AddRef(&presenter
->IMFVideoPresenter_iface
);
1056 static ULONG WINAPI
video_presenter_device_id_Release(IMFVideoDeviceID
*iface
)
1058 struct video_presenter
*presenter
= impl_from_IMFVideoDeviceID(iface
);
1059 return IMFVideoPresenter_Release(&presenter
->IMFVideoPresenter_iface
);
1062 static HRESULT WINAPI
video_presenter_device_id_GetDeviceID(IMFVideoDeviceID
*iface
, IID
*device_id
)
1064 TRACE("%p, %p.\n", iface
, device_id
);
1069 memcpy(device_id
, &IID_IDirect3DDevice9
, sizeof(*device_id
));
1074 static const IMFVideoDeviceIDVtbl video_presenter_device_id_vtbl
=
1076 video_presenter_device_id_QueryInterface
,
1077 video_presenter_device_id_AddRef
,
1078 video_presenter_device_id_Release
,
1079 video_presenter_device_id_GetDeviceID
,
1082 static HRESULT WINAPI
video_presenter_service_client_QueryInterface(IMFTopologyServiceLookupClient
*iface
,
1083 REFIID riid
, void **obj
)
1085 struct video_presenter
*presenter
= impl_from_IMFTopologyServiceLookupClient(iface
);
1086 return IMFVideoPresenter_QueryInterface(&presenter
->IMFVideoPresenter_iface
, riid
, obj
);
1089 static ULONG WINAPI
video_presenter_service_client_AddRef(IMFTopologyServiceLookupClient
*iface
)
1091 struct video_presenter
*presenter
= impl_from_IMFTopologyServiceLookupClient(iface
);
1092 return IMFVideoPresenter_AddRef(&presenter
->IMFVideoPresenter_iface
);
1095 static ULONG WINAPI
video_presenter_service_client_Release(IMFTopologyServiceLookupClient
*iface
)
1097 struct video_presenter
*presenter
= impl_from_IMFTopologyServiceLookupClient(iface
);
1098 return IMFVideoPresenter_Release(&presenter
->IMFVideoPresenter_iface
);
1101 static void video_presenter_set_mixer_rect(struct video_presenter
*presenter
)
1103 IMFAttributes
*attributes
;
1106 if (!presenter
->mixer
)
1109 if (SUCCEEDED(IMFTransform_GetAttributes(presenter
->mixer
, &attributes
)))
1111 if (FAILED(hr
= IMFAttributes_SetBlob(attributes
, &VIDEO_ZOOM_RECT
, (const UINT8
*)&presenter
->src_rect
,
1112 sizeof(presenter
->src_rect
))))
1114 WARN("Failed to set zoom rectangle attribute, hr %#x.\n", hr
);
1116 IMFAttributes_Release(attributes
);
1120 static HRESULT
video_presenter_attach_mixer(struct video_presenter
*presenter
, IMFTopologyServiceLookup
*service_lookup
)
1122 IMFVideoDeviceID
*device_id
;
1128 if (FAILED(hr
= IMFTopologyServiceLookup_LookupService(service_lookup
, MF_SERVICE_LOOKUP_GLOBAL
, 0,
1129 &MR_VIDEO_MIXER_SERVICE
, &IID_IMFTransform
, (void **)&presenter
->mixer
, &count
)))
1131 WARN("Failed to get mixer interface, hr %#x.\n", hr
);
1135 if (SUCCEEDED(hr
= IMFTransform_QueryInterface(presenter
->mixer
, &IID_IMFVideoDeviceID
, (void **)&device_id
)))
1137 if (SUCCEEDED(hr
= IMFVideoDeviceID_GetDeviceID(device_id
, &id
)))
1139 if (!IsEqualGUID(&id
, &IID_IDirect3DDevice9
))
1140 hr
= MF_E_INVALIDREQUEST
;
1143 IMFVideoDeviceID_Release(device_id
);
1148 IMFTransform_Release(presenter
->mixer
);
1149 presenter
->mixer
= NULL
;
1152 video_presenter_set_mixer_rect(presenter
);
1153 video_presenter_get_native_video_size(presenter
);
1158 static HRESULT WINAPI
video_presenter_service_client_InitServicePointers(IMFTopologyServiceLookupClient
*iface
,
1159 IMFTopologyServiceLookup
*service_lookup
)
1161 struct video_presenter
*presenter
= impl_from_IMFTopologyServiceLookupClient(iface
);
1165 TRACE("%p, %p.\n", iface
, service_lookup
);
1167 if (!service_lookup
)
1170 EnterCriticalSection(&presenter
->cs
);
1172 if (presenter
->state
== PRESENTER_STATE_STARTED
||
1173 presenter
->state
== PRESENTER_STATE_PAUSED
)
1175 hr
= MF_E_INVALIDREQUEST
;
1179 video_presenter_clear_container(presenter
);
1182 IMFTopologyServiceLookup_LookupService(service_lookup
, MF_SERVICE_LOOKUP_GLOBAL
, 0,
1183 &MR_VIDEO_RENDER_SERVICE
, &IID_IMFClock
, (void **)&presenter
->clock
, &count
);
1185 hr
= video_presenter_attach_mixer(presenter
, service_lookup
);
1190 if (FAILED(hr
= IMFTopologyServiceLookup_LookupService(service_lookup
, MF_SERVICE_LOOKUP_GLOBAL
, 0,
1191 &MR_VIDEO_RENDER_SERVICE
, &IID_IMediaEventSink
, (void **)&presenter
->event_sink
, &count
)))
1193 WARN("Failed to get renderer event sink, hr %#x.\n", hr
);
1198 presenter
->state
= PRESENTER_STATE_STOPPED
;
1201 LeaveCriticalSection(&presenter
->cs
);
1206 static HRESULT WINAPI
video_presenter_service_client_ReleaseServicePointers(IMFTopologyServiceLookupClient
*iface
)
1208 struct video_presenter
*presenter
= impl_from_IMFTopologyServiceLookupClient(iface
);
1210 TRACE("%p.\n", iface
);
1212 EnterCriticalSection(&presenter
->cs
);
1214 presenter
->state
= PRESENTER_STATE_SHUT_DOWN
;
1215 video_presenter_clear_container(presenter
);
1217 LeaveCriticalSection(&presenter
->cs
);
1222 static const IMFTopologyServiceLookupClientVtbl video_presenter_service_client_vtbl
=
1224 video_presenter_service_client_QueryInterface
,
1225 video_presenter_service_client_AddRef
,
1226 video_presenter_service_client_Release
,
1227 video_presenter_service_client_InitServicePointers
,
1228 video_presenter_service_client_ReleaseServicePointers
,
1231 static HRESULT WINAPI
video_presenter_control_QueryInterface(IMFVideoDisplayControl
*iface
, REFIID riid
, void **obj
)
1233 struct video_presenter
*presenter
= impl_from_IMFVideoDisplayControl(iface
);
1234 return IMFVideoPresenter_QueryInterface(&presenter
->IMFVideoPresenter_iface
, riid
, obj
);
1237 static ULONG WINAPI
video_presenter_control_AddRef(IMFVideoDisplayControl
*iface
)
1239 struct video_presenter
*presenter
= impl_from_IMFVideoDisplayControl(iface
);
1240 return IMFVideoPresenter_AddRef(&presenter
->IMFVideoPresenter_iface
);
1243 static ULONG WINAPI
video_presenter_control_Release(IMFVideoDisplayControl
*iface
)
1245 struct video_presenter
*presenter
= impl_from_IMFVideoDisplayControl(iface
);
1246 return IMFVideoPresenter_Release(&presenter
->IMFVideoPresenter_iface
);
1249 static HRESULT WINAPI
video_presenter_control_GetNativeVideoSize(IMFVideoDisplayControl
*iface
, SIZE
*video_size
,
1252 struct video_presenter
*presenter
= impl_from_IMFVideoDisplayControl(iface
);
1254 TRACE("%p, %p, %p.\n", iface
, video_size
, aspect_ratio
);
1256 if (!video_size
&& !aspect_ratio
)
1259 EnterCriticalSection(&presenter
->cs
);
1261 *video_size
= presenter
->native_size
;
1263 *aspect_ratio
= presenter
->native_ratio
;
1264 LeaveCriticalSection(&presenter
->cs
);
1269 static HRESULT WINAPI
video_presenter_control_GetIdealVideoSize(IMFVideoDisplayControl
*iface
, SIZE
*min_size
,
1272 FIXME("%p, %p, %p.\n", iface
, min_size
, max_size
);
1277 static HRESULT WINAPI
video_presenter_control_SetVideoPosition(IMFVideoDisplayControl
*iface
,
1278 const MFVideoNormalizedRect
*src_rect
, const RECT
*dst_rect
)
1280 struct video_presenter
*presenter
= impl_from_IMFVideoDisplayControl(iface
);
1283 TRACE("%p, %p, %s.\n", iface
, src_rect
, wine_dbgstr_rect(dst_rect
));
1285 if (!src_rect
&& !dst_rect
)
1288 if (src_rect
&& (src_rect
->left
< 0.0f
|| src_rect
->top
< 0.0f
||
1289 src_rect
->right
> 1.0f
|| src_rect
->bottom
> 1.0f
||
1290 src_rect
->left
> src_rect
->right
||
1291 src_rect
->top
> src_rect
->bottom
))
1293 return E_INVALIDARG
;
1296 if (dst_rect
&& (dst_rect
->left
> dst_rect
->right
||
1297 dst_rect
->top
> dst_rect
->bottom
))
1298 return E_INVALIDARG
;
1300 EnterCriticalSection(&presenter
->cs
);
1301 if (!presenter
->video_window
)
1307 if (memcmp(&presenter
->src_rect
, src_rect
, sizeof(*src_rect
)))
1309 presenter
->src_rect
= *src_rect
;
1310 video_presenter_set_mixer_rect(presenter
);
1314 presenter
->dst_rect
= *dst_rect
;
1316 LeaveCriticalSection(&presenter
->cs
);
1321 static HRESULT WINAPI
video_presenter_control_GetVideoPosition(IMFVideoDisplayControl
*iface
, MFVideoNormalizedRect
*src_rect
,
1324 struct video_presenter
*presenter
= impl_from_IMFVideoDisplayControl(iface
);
1326 TRACE("%p, %p, %p.\n", iface
, src_rect
, dst_rect
);
1328 if (!src_rect
|| !dst_rect
)
1331 EnterCriticalSection(&presenter
->cs
);
1332 *src_rect
= presenter
->src_rect
;
1333 *dst_rect
= presenter
->dst_rect
;
1334 LeaveCriticalSection(&presenter
->cs
);
1339 static HRESULT WINAPI
video_presenter_control_SetAspectRatioMode(IMFVideoDisplayControl
*iface
, DWORD mode
)
1341 struct video_presenter
*presenter
= impl_from_IMFVideoDisplayControl(iface
);
1343 TRACE("%p, %#x.\n", iface
, mode
);
1345 if (mode
& ~MFVideoARMode_Mask
)
1346 return E_INVALIDARG
;
1348 EnterCriticalSection(&presenter
->cs
);
1349 presenter
->ar_mode
= mode
;
1350 LeaveCriticalSection(&presenter
->cs
);
1355 static HRESULT WINAPI
video_presenter_control_GetAspectRatioMode(IMFVideoDisplayControl
*iface
, DWORD
*mode
)
1357 struct video_presenter
*presenter
= impl_from_IMFVideoDisplayControl(iface
);
1359 TRACE("%p, %p.\n", iface
, mode
);
1364 EnterCriticalSection(&presenter
->cs
);
1365 *mode
= presenter
->ar_mode
;
1366 LeaveCriticalSection(&presenter
->cs
);
1371 static HRESULT
video_presenter_create_swapchain(struct video_presenter
*presenter
)
1373 D3DPRESENT_PARAMETERS present_params
= { 0 };
1374 IDirect3DDevice9
*d3d_device
;
1377 if (SUCCEEDED(hr
= video_presenter_get_device(presenter
, &d3d_device
)))
1379 present_params
.hDeviceWindow
= presenter
->video_window
;
1380 present_params
.Windowed
= TRUE
;
1381 present_params
.SwapEffect
= D3DSWAPEFFECT_COPY
;
1382 present_params
.Flags
= D3DPRESENTFLAG_VIDEO
;
1383 present_params
.PresentationInterval
= D3DPRESENT_INTERVAL_IMMEDIATE
;
1384 hr
= IDirect3DDevice9_CreateAdditionalSwapChain(d3d_device
, &present_params
, &presenter
->swapchain
);
1386 IDirect3DDevice9_Release(d3d_device
);
1387 IDirect3DDeviceManager9_UnlockDevice(presenter
->device_manager
, presenter
->hdevice
, FALSE
);
1393 static HRESULT WINAPI
video_presenter_control_SetVideoWindow(IMFVideoDisplayControl
*iface
, HWND window
)
1395 struct video_presenter
*presenter
= impl_from_IMFVideoDisplayControl(iface
);
1398 TRACE("%p, %p.\n", iface
, window
);
1400 if (!IsWindow(window
))
1401 return E_INVALIDARG
;
1403 EnterCriticalSection(&presenter
->cs
);
1404 if (presenter
->video_window
!= window
)
1406 if (presenter
->swapchain
)
1407 IDirect3DSwapChain9_Release(presenter
->swapchain
);
1408 presenter
->video_window
= window
;
1409 hr
= video_presenter_create_swapchain(presenter
);
1411 LeaveCriticalSection(&presenter
->cs
);
1416 static HRESULT WINAPI
video_presenter_control_GetVideoWindow(IMFVideoDisplayControl
*iface
, HWND
*window
)
1418 struct video_presenter
*presenter
= impl_from_IMFVideoDisplayControl(iface
);
1420 TRACE("%p, %p.\n", iface
, window
);
1425 EnterCriticalSection(&presenter
->cs
);
1426 *window
= presenter
->video_window
;
1427 LeaveCriticalSection(&presenter
->cs
);
1432 static HRESULT WINAPI
video_presenter_control_RepaintVideo(IMFVideoDisplayControl
*iface
)
1434 FIXME("%p.\n", iface
);
1439 static HRESULT WINAPI
video_presenter_control_GetCurrentImage(IMFVideoDisplayControl
*iface
, BITMAPINFOHEADER
*header
,
1440 BYTE
**dib
, DWORD
*dib_size
, LONGLONG
*timestamp
)
1442 FIXME("%p, %p, %p, %p, %p.\n", iface
, header
, dib
, dib_size
, timestamp
);
1447 static HRESULT WINAPI
video_presenter_control_SetBorderColor(IMFVideoDisplayControl
*iface
, COLORREF color
)
1449 FIXME("%p, %#x.\n", iface
, color
);
1454 static HRESULT WINAPI
video_presenter_control_GetBorderColor(IMFVideoDisplayControl
*iface
, COLORREF
*color
)
1456 FIXME("%p, %p.\n", iface
, color
);
1461 static HRESULT WINAPI
video_presenter_control_SetRenderingPrefs(IMFVideoDisplayControl
*iface
, DWORD flags
)
1463 FIXME("%p, %#x.\n", iface
, flags
);
1468 static HRESULT WINAPI
video_presenter_control_GetRenderingPrefs(IMFVideoDisplayControl
*iface
, DWORD
*flags
)
1470 struct video_presenter
*presenter
= impl_from_IMFVideoDisplayControl(iface
);
1472 TRACE("%p, %p.\n", iface
, flags
);
1477 EnterCriticalSection(&presenter
->cs
);
1478 *flags
= presenter
->rendering_prefs
;
1479 LeaveCriticalSection(&presenter
->cs
);
1484 static HRESULT WINAPI
video_presenter_control_SetFullscreen(IMFVideoDisplayControl
*iface
, BOOL fullscreen
)
1486 FIXME("%p, %d.\n", iface
, fullscreen
);
1491 static HRESULT WINAPI
video_presenter_control_GetFullscreen(IMFVideoDisplayControl
*iface
, BOOL
*fullscreen
)
1493 FIXME("%p, %p.\n", iface
, fullscreen
);
1498 static const IMFVideoDisplayControlVtbl video_presenter_control_vtbl
=
1500 video_presenter_control_QueryInterface
,
1501 video_presenter_control_AddRef
,
1502 video_presenter_control_Release
,
1503 video_presenter_control_GetNativeVideoSize
,
1504 video_presenter_control_GetIdealVideoSize
,
1505 video_presenter_control_SetVideoPosition
,
1506 video_presenter_control_GetVideoPosition
,
1507 video_presenter_control_SetAspectRatioMode
,
1508 video_presenter_control_GetAspectRatioMode
,
1509 video_presenter_control_SetVideoWindow
,
1510 video_presenter_control_GetVideoWindow
,
1511 video_presenter_control_RepaintVideo
,
1512 video_presenter_control_GetCurrentImage
,
1513 video_presenter_control_SetBorderColor
,
1514 video_presenter_control_GetBorderColor
,
1515 video_presenter_control_SetRenderingPrefs
,
1516 video_presenter_control_GetRenderingPrefs
,
1517 video_presenter_control_SetFullscreen
,
1518 video_presenter_control_GetFullscreen
,
1521 static HRESULT WINAPI
video_presenter_rate_support_QueryInterface(IMFRateSupport
*iface
, REFIID riid
, void **obj
)
1523 struct video_presenter
*presenter
= impl_from_IMFRateSupport(iface
);
1524 return IMFVideoPresenter_QueryInterface(&presenter
->IMFVideoPresenter_iface
, riid
, obj
);
1527 static ULONG WINAPI
video_presenter_rate_support_AddRef(IMFRateSupport
*iface
)
1529 struct video_presenter
*presenter
= impl_from_IMFRateSupport(iface
);
1530 return IMFVideoPresenter_AddRef(&presenter
->IMFVideoPresenter_iface
);
1533 static ULONG WINAPI
video_presenter_rate_support_Release(IMFRateSupport
*iface
)
1535 struct video_presenter
*presenter
= impl_from_IMFRateSupport(iface
);
1536 return IMFVideoPresenter_Release(&presenter
->IMFVideoPresenter_iface
);
1539 static HRESULT WINAPI
video_presenter_rate_support_GetSlowestRate(IMFRateSupport
*iface
, MFRATE_DIRECTION direction
,
1540 BOOL thin
, float *rate
)
1542 TRACE("%p, %d, %d, %p.\n", iface
, direction
, thin
, rate
);
1549 static HRESULT WINAPI
video_presenter_rate_support_GetFastestRate(IMFRateSupport
*iface
, MFRATE_DIRECTION direction
,
1550 BOOL thin
, float *rate
)
1555 static HRESULT WINAPI
video_presenter_rate_support_IsRateSupported(IMFRateSupport
*iface
, BOOL thin
, float rate
,
1556 float *nearest_supported_rate
)
1561 static const IMFRateSupportVtbl video_presenter_rate_support_vtbl
=
1563 video_presenter_rate_support_QueryInterface
,
1564 video_presenter_rate_support_AddRef
,
1565 video_presenter_rate_support_Release
,
1566 video_presenter_rate_support_GetSlowestRate
,
1567 video_presenter_rate_support_GetFastestRate
,
1568 video_presenter_rate_support_IsRateSupported
,
1571 static HRESULT WINAPI
video_presenter_getservice_QueryInterface(IMFGetService
*iface
, REFIID riid
, void **obj
)
1573 struct video_presenter
*presenter
= impl_from_IMFGetService(iface
);
1574 return IMFVideoPresenter_QueryInterface(&presenter
->IMFVideoPresenter_iface
, riid
, obj
);
1577 static ULONG WINAPI
video_presenter_getservice_AddRef(IMFGetService
*iface
)
1579 struct video_presenter
*presenter
= impl_from_IMFGetService(iface
);
1580 return IMFVideoPresenter_AddRef(&presenter
->IMFVideoPresenter_iface
);
1583 static ULONG WINAPI
video_presenter_getservice_Release(IMFGetService
*iface
)
1585 struct video_presenter
*presenter
= impl_from_IMFGetService(iface
);
1586 return IMFVideoPresenter_Release(&presenter
->IMFVideoPresenter_iface
);
1589 static HRESULT WINAPI
video_presenter_getservice_GetService(IMFGetService
*iface
, REFGUID service
, REFIID riid
, void **obj
)
1591 struct video_presenter
*presenter
= impl_from_IMFGetService(iface
);
1593 TRACE("%p, %s, %s, %p.\n", iface
, debugstr_guid(service
), debugstr_guid(riid
), obj
);
1595 if (IsEqualGUID(&MR_VIDEO_ACCELERATION_SERVICE
, service
))
1596 return IDirect3DDeviceManager9_QueryInterface(presenter
->device_manager
, riid
, obj
);
1598 if (IsEqualGUID(&MR_VIDEO_RENDER_SERVICE
, service
))
1599 return IMFVideoPresenter_QueryInterface(&presenter
->IMFVideoPresenter_iface
, riid
, obj
);
1601 FIXME("Unimplemented service %s.\n", debugstr_guid(service
));
1603 return MF_E_UNSUPPORTED_SERVICE
;
1606 static const IMFGetServiceVtbl video_presenter_getservice_vtbl
=
1608 video_presenter_getservice_QueryInterface
,
1609 video_presenter_getservice_AddRef
,
1610 video_presenter_getservice_Release
,
1611 video_presenter_getservice_GetService
,
1614 static HRESULT WINAPI
video_presenter_position_mapper_QueryInterface(IMFVideoPositionMapper
*iface
, REFIID riid
, void **obj
)
1616 struct video_presenter
*presenter
= impl_from_IMFVideoPositionMapper(iface
);
1617 return IMFVideoPresenter_QueryInterface(&presenter
->IMFVideoPresenter_iface
, riid
, obj
);
1620 static ULONG WINAPI
video_presenter_position_mapper_AddRef(IMFVideoPositionMapper
*iface
)
1622 struct video_presenter
*presenter
= impl_from_IMFVideoPositionMapper(iface
);
1623 return IMFVideoPresenter_AddRef(&presenter
->IMFVideoPresenter_iface
);
1626 static ULONG WINAPI
video_presenter_position_mapper_Release(IMFVideoPositionMapper
*iface
)
1628 struct video_presenter
*presenter
= impl_from_IMFVideoPositionMapper(iface
);
1629 return IMFVideoPresenter_Release(&presenter
->IMFVideoPresenter_iface
);
1632 static HRESULT WINAPI
video_presenter_position_mapper_MapOutputCoordinateToInputStream(IMFVideoPositionMapper
*iface
,
1633 float x_out
, float y_out
, DWORD output_stream
, DWORD input_stream
, float *x_in
, float *y_in
)
1635 FIXME("%p, %f, %f, %u, %u, %p, %p.\n", iface
, x_out
, y_out
, output_stream
, input_stream
, x_in
, y_in
);
1640 static const IMFVideoPositionMapperVtbl video_presenter_position_mapper_vtbl
=
1642 video_presenter_position_mapper_QueryInterface
,
1643 video_presenter_position_mapper_AddRef
,
1644 video_presenter_position_mapper_Release
,
1645 video_presenter_position_mapper_MapOutputCoordinateToInputStream
,
1648 static HRESULT WINAPI
video_presenter_allocator_cb_QueryInterface(IMFVideoSampleAllocatorNotify
*iface
,
1649 REFIID riid
, void **obj
)
1651 if (IsEqualIID(riid
, &IID_IMFVideoSampleAllocatorNotify
) ||
1652 IsEqualIID(riid
, &IID_IUnknown
))
1655 IMFVideoSampleAllocatorNotify_AddRef(iface
);
1659 WARN("Unsupported interface %s.\n", debugstr_guid(riid
));
1661 return E_NOINTERFACE
;
1664 static ULONG WINAPI
video_presenter_allocator_cb_AddRef(IMFVideoSampleAllocatorNotify
*iface
)
1666 struct video_presenter
*presenter
= impl_from_IMFVideoSampleAllocatorNotify(iface
);
1667 return IMFVideoPresenter_AddRef(&presenter
->IMFVideoPresenter_iface
);
1670 static ULONG WINAPI
video_presenter_allocator_cb_Release(IMFVideoSampleAllocatorNotify
*iface
)
1672 struct video_presenter
*presenter
= impl_from_IMFVideoSampleAllocatorNotify(iface
);
1673 return IMFVideoPresenter_Release(&presenter
->IMFVideoPresenter_iface
);
1676 static HRESULT WINAPI
video_presenter_allocator_cb_NotifyRelease(IMFVideoSampleAllocatorNotify
*iface
)
1678 struct video_presenter
*presenter
= impl_from_IMFVideoSampleAllocatorNotify(iface
);
1680 /* Release notification is executed under allocator lock, instead of processing samples here
1681 notify streaming thread. */
1682 PostThreadMessageW(presenter
->thread
.tid
, EVRM_PROCESS_INPUT
, 0, 0);
1687 static const IMFVideoSampleAllocatorNotifyVtbl video_presenter_allocator_cb_vtbl
=
1689 video_presenter_allocator_cb_QueryInterface
,
1690 video_presenter_allocator_cb_AddRef
,
1691 video_presenter_allocator_cb_Release
,
1692 video_presenter_allocator_cb_NotifyRelease
,
1695 static HRESULT WINAPI
video_presenter_qualprop_QueryInterface(IQualProp
*iface
, REFIID riid
, void **obj
)
1697 struct video_presenter
*presenter
= impl_from_IQualProp(iface
);
1698 return IMFVideoPresenter_QueryInterface(&presenter
->IMFVideoPresenter_iface
, riid
, obj
);
1701 static ULONG WINAPI
video_presenter_qualprop_AddRef(IQualProp
*iface
)
1703 struct video_presenter
*presenter
= impl_from_IQualProp(iface
);
1704 return IMFVideoPresenter_AddRef(&presenter
->IMFVideoPresenter_iface
);
1707 static ULONG WINAPI
video_presenter_qualprop_Release(IQualProp
*iface
)
1709 struct video_presenter
*presenter
= impl_from_IQualProp(iface
);
1710 return IMFVideoPresenter_Release(&presenter
->IMFVideoPresenter_iface
);
1713 static HRESULT WINAPI
video_presenter_qualprop_get_FramesDroppedInRenderer(IQualProp
*iface
, int *frames
)
1715 FIXME("%p, %p stub.\n", iface
, frames
);
1720 static HRESULT WINAPI
video_presenter_qualprop_get_FramesDrawn(IQualProp
*iface
, int *frames
)
1722 FIXME("%p, %p stub.\n", iface
, frames
);
1727 static HRESULT WINAPI
video_presenter_qualprop_get_AvgFrameRate(IQualProp
*iface
, int *avg_frame_rate
)
1729 FIXME("%p, %p stub.\n", iface
, avg_frame_rate
);
1734 static HRESULT WINAPI
video_presenter_qualprop_get_Jitter(IQualProp
*iface
, int *jitter
)
1736 FIXME("%p, %p stub.\n", iface
, jitter
);
1741 static HRESULT WINAPI
video_presenter_qualprop_get_AvgSyncOffset(IQualProp
*iface
, int *offset
)
1743 FIXME("%p, %p stub.\n", iface
, offset
);
1748 static HRESULT WINAPI
video_presenter_qualprop_get_DevSyncOffset(IQualProp
*iface
, int *devoffset
)
1750 FIXME("%p, %p stub.\n", iface
, devoffset
);
1755 static const IQualPropVtbl video_presenter_qualprop_vtbl
=
1757 video_presenter_qualprop_QueryInterface
,
1758 video_presenter_qualprop_AddRef
,
1759 video_presenter_qualprop_Release
,
1760 video_presenter_qualprop_get_FramesDroppedInRenderer
,
1761 video_presenter_qualprop_get_FramesDrawn
,
1762 video_presenter_qualprop_get_AvgFrameRate
,
1763 video_presenter_qualprop_get_Jitter
,
1764 video_presenter_qualprop_get_AvgSyncOffset
,
1765 video_presenter_qualprop_get_DevSyncOffset
,
1768 static HRESULT WINAPI
video_presenter_quality_advise_QueryInterface(IMFQualityAdvise
*iface
, REFIID riid
, void **out
)
1770 struct video_presenter
*presenter
= impl_from_IMFQualityAdvise(iface
);
1771 return IMFVideoPresenter_QueryInterface(&presenter
->IMFVideoPresenter_iface
, riid
, out
);
1774 static ULONG WINAPI
video_presenter_quality_advise_AddRef(IMFQualityAdvise
*iface
)
1776 struct video_presenter
*presenter
= impl_from_IMFQualityAdvise(iface
);
1777 return IMFVideoPresenter_AddRef(&presenter
->IMFVideoPresenter_iface
);
1780 static ULONG WINAPI
video_presenter_quality_advise_Release(IMFQualityAdvise
*iface
)
1782 struct video_presenter
*presenter
= impl_from_IMFQualityAdvise(iface
);
1783 return IMFVideoPresenter_Release(&presenter
->IMFVideoPresenter_iface
);
1786 static HRESULT WINAPI
video_presenter_quality_advise_SetDropMode(IMFQualityAdvise
*iface
,
1787 MF_QUALITY_DROP_MODE mode
)
1789 FIXME("%p, %u.\n", iface
, mode
);
1794 static HRESULT WINAPI
video_presenter_quality_advise_SetQualityLevel(IMFQualityAdvise
*iface
,
1795 MF_QUALITY_LEVEL level
)
1797 FIXME("%p, %u.\n", iface
, level
);
1802 static HRESULT WINAPI
video_presenter_quality_advise_GetDropMode(IMFQualityAdvise
*iface
,
1803 MF_QUALITY_DROP_MODE
*mode
)
1805 FIXME("%p, %p.\n", iface
, mode
);
1810 static HRESULT WINAPI
video_presenter_quality_advise_GetQualityLevel(IMFQualityAdvise
*iface
,
1811 MF_QUALITY_LEVEL
*level
)
1813 FIXME("%p, %p.\n", iface
, level
);
1818 static HRESULT WINAPI
video_presenter_quality_advise_DropTime(IMFQualityAdvise
*iface
, LONGLONG interval
)
1820 FIXME("%p, %s.\n", iface
, wine_dbgstr_longlong(interval
));
1825 static const IMFQualityAdviseVtbl video_presenter_quality_advise_vtbl
=
1827 video_presenter_quality_advise_QueryInterface
,
1828 video_presenter_quality_advise_AddRef
,
1829 video_presenter_quality_advise_Release
,
1830 video_presenter_quality_advise_SetDropMode
,
1831 video_presenter_quality_advise_SetQualityLevel
,
1832 video_presenter_quality_advise_GetDropMode
,
1833 video_presenter_quality_advise_GetQualityLevel
,
1834 video_presenter_quality_advise_DropTime
,
1837 static HRESULT WINAPI
video_presenter_device_manager_QueryInterface(IDirect3DDeviceManager9
*iface
,
1838 REFIID riid
, void **obj
)
1840 struct video_presenter
*presenter
= impl_from_IDirect3DDeviceManager9(iface
);
1841 return IMFVideoPresenter_QueryInterface(&presenter
->IMFVideoPresenter_iface
, riid
, obj
);
1844 static ULONG WINAPI
video_presenter_device_manager_AddRef(IDirect3DDeviceManager9
*iface
)
1846 struct video_presenter
*presenter
= impl_from_IDirect3DDeviceManager9(iface
);
1847 return IMFVideoPresenter_AddRef(&presenter
->IMFVideoPresenter_iface
);
1850 static ULONG WINAPI
video_presenter_device_manager_Release(IDirect3DDeviceManager9
*iface
)
1852 struct video_presenter
*presenter
= impl_from_IDirect3DDeviceManager9(iface
);
1853 return IMFVideoPresenter_Release(&presenter
->IMFVideoPresenter_iface
);
1856 static HRESULT WINAPI
video_presenter_device_manager_ResetDevice(IDirect3DDeviceManager9
*iface
,
1857 IDirect3DDevice9
*device
, UINT token
)
1859 struct video_presenter
*presenter
= impl_from_IDirect3DDeviceManager9(iface
);
1860 return IDirect3DDeviceManager9_ResetDevice(presenter
->device_manager
, device
, token
);
1863 static HRESULT WINAPI
video_presenter_device_manager_OpenDeviceHandle(IDirect3DDeviceManager9
*iface
, HANDLE
*hdevice
)
1865 struct video_presenter
*presenter
= impl_from_IDirect3DDeviceManager9(iface
);
1866 return IDirect3DDeviceManager9_OpenDeviceHandle(presenter
->device_manager
, hdevice
);
1869 static HRESULT WINAPI
video_presenter_device_manager_CloseDeviceHandle(IDirect3DDeviceManager9
*iface
, HANDLE hdevice
)
1871 struct video_presenter
*presenter
= impl_from_IDirect3DDeviceManager9(iface
);
1872 return IDirect3DDeviceManager9_CloseDeviceHandle(presenter
->device_manager
, hdevice
);
1875 static HRESULT WINAPI
video_presenter_device_manager_TestDevice(IDirect3DDeviceManager9
*iface
, HANDLE hdevice
)
1877 struct video_presenter
*presenter
= impl_from_IDirect3DDeviceManager9(iface
);
1878 return IDirect3DDeviceManager9_TestDevice(presenter
->device_manager
, hdevice
);
1881 static HRESULT WINAPI
video_presenter_device_manager_LockDevice(IDirect3DDeviceManager9
*iface
, HANDLE hdevice
,
1882 IDirect3DDevice9
**device
, BOOL block
)
1884 struct video_presenter
*presenter
= impl_from_IDirect3DDeviceManager9(iface
);
1885 return IDirect3DDeviceManager9_LockDevice(presenter
->device_manager
, hdevice
, device
, block
);
1888 static HRESULT WINAPI
video_presenter_device_manager_UnlockDevice(IDirect3DDeviceManager9
*iface
, HANDLE hdevice
,
1891 struct video_presenter
*presenter
= impl_from_IDirect3DDeviceManager9(iface
);
1892 return IDirect3DDeviceManager9_UnlockDevice(presenter
->device_manager
, hdevice
, savestate
);
1895 static HRESULT WINAPI
video_presenter_device_manager_GetVideoService(IDirect3DDeviceManager9
*iface
, HANDLE hdevice
,
1896 REFIID riid
, void **service
)
1898 struct video_presenter
*presenter
= impl_from_IDirect3DDeviceManager9(iface
);
1899 return IDirect3DDeviceManager9_GetVideoService(presenter
->device_manager
, hdevice
, riid
, service
);
1902 static const IDirect3DDeviceManager9Vtbl video_presenter_device_manager_vtbl
=
1904 video_presenter_device_manager_QueryInterface
,
1905 video_presenter_device_manager_AddRef
,
1906 video_presenter_device_manager_Release
,
1907 video_presenter_device_manager_ResetDevice
,
1908 video_presenter_device_manager_OpenDeviceHandle
,
1909 video_presenter_device_manager_CloseDeviceHandle
,
1910 video_presenter_device_manager_TestDevice
,
1911 video_presenter_device_manager_LockDevice
,
1912 video_presenter_device_manager_UnlockDevice
,
1913 video_presenter_device_manager_GetVideoService
,
1916 static HRESULT WINAPI
video_presenter_qa_limits_QueryInterface(IMFQualityAdviseLimits
*iface
, REFIID riid
, void **obj
)
1918 struct video_presenter
*presenter
= impl_from_IMFQualityAdviseLimits(iface
);
1919 return IMFVideoPresenter_QueryInterface(&presenter
->IMFVideoPresenter_iface
, riid
, obj
);
1922 static ULONG WINAPI
video_presenter_qa_limits_AddRef(IMFQualityAdviseLimits
*iface
)
1924 struct video_presenter
*presenter
= impl_from_IMFQualityAdviseLimits(iface
);
1925 return IMFVideoPresenter_AddRef(&presenter
->IMFVideoPresenter_iface
);
1928 static ULONG WINAPI
video_presenter_qa_limits_Release(IMFQualityAdviseLimits
*iface
)
1930 struct video_presenter
*presenter
= impl_from_IMFQualityAdviseLimits(iface
);
1931 return IMFVideoPresenter_Release(&presenter
->IMFVideoPresenter_iface
);
1934 static HRESULT WINAPI
video_presenter_qa_limits_GetMaximumDropMode(IMFQualityAdviseLimits
*iface
, MF_QUALITY_DROP_MODE
*mode
)
1936 FIXME("%p, %p.\n", iface
, mode
);
1941 static HRESULT WINAPI
video_presenter_qa_limits_GetMinimumQualityLevel(IMFQualityAdviseLimits
*iface
, MF_QUALITY_LEVEL
*level
)
1943 FIXME("%p, %p.\n", iface
, level
);
1948 static const IMFQualityAdviseLimitsVtbl video_presenter_qa_limits_vtbl
=
1950 video_presenter_qa_limits_QueryInterface
,
1951 video_presenter_qa_limits_AddRef
,
1952 video_presenter_qa_limits_Release
,
1953 video_presenter_qa_limits_GetMaximumDropMode
,
1954 video_presenter_qa_limits_GetMinimumQualityLevel
,
1957 HRESULT WINAPI
MFCreateVideoPresenter(IUnknown
*owner
, REFIID riid_device
, REFIID riid
, void **obj
)
1959 TRACE("%p, %s, %s, %p.\n", owner
, debugstr_guid(riid_device
), debugstr_guid(riid
), obj
);
1963 if (!IsEqualIID(riid_device
, &IID_IDirect3DDevice9
))
1964 return E_INVALIDARG
;
1966 return CoCreateInstance(&CLSID_MFVideoPresenter9
, owner
, CLSCTX_INPROC_SERVER
, riid
, obj
);
1969 static HRESULT
video_presenter_init_d3d(struct video_presenter
*presenter
)
1971 D3DPRESENT_PARAMETERS present_params
= { 0 };
1972 IDirect3DDevice9
*device
;
1976 d3d
= Direct3DCreate9(D3D_SDK_VERSION
);
1978 present_params
.BackBufferCount
= 1;
1979 present_params
.SwapEffect
= D3DSWAPEFFECT_COPY
;
1980 present_params
.hDeviceWindow
= GetDesktopWindow();
1981 present_params
.Windowed
= TRUE
;
1982 present_params
.Flags
= D3DPRESENTFLAG_VIDEO
;
1983 present_params
.PresentationInterval
= D3DPRESENT_INTERVAL_IMMEDIATE
;
1984 hr
= IDirect3D9_CreateDevice(d3d
, D3DADAPTER_DEFAULT
, D3DDEVTYPE_HAL
, GetDesktopWindow(),
1985 D3DCREATE_HARDWARE_VERTEXPROCESSING
, &present_params
, &device
);
1987 IDirect3D9_Release(d3d
);
1991 WARN("Failed to create d3d device, hr %#x.\n", hr
);
1995 hr
= IDirect3DDeviceManager9_ResetDevice(presenter
->device_manager
, device
, presenter
->reset_token
);
1996 IDirect3DDevice9_Release(device
);
1998 WARN("Failed to set new device for the manager, hr %#x.\n", hr
);
2000 if (SUCCEEDED(hr
= MFCreateVideoSampleAllocator(&IID_IMFVideoSampleAllocator
, (void **)&presenter
->allocator
)))
2002 hr
= IMFVideoSampleAllocator_SetDirectXManager(presenter
->allocator
, (IUnknown
*)presenter
->device_manager
);
2008 HRESULT
evr_presenter_create(IUnknown
*outer
, void **out
)
2010 struct video_presenter
*object
;
2015 if (!(object
= calloc(1, sizeof(*object
))))
2016 return E_OUTOFMEMORY
;
2018 object
->IMFVideoPresenter_iface
.lpVtbl
= &video_presenter_vtbl
;
2019 object
->IMFVideoDeviceID_iface
.lpVtbl
= &video_presenter_device_id_vtbl
;
2020 object
->IMFTopologyServiceLookupClient_iface
.lpVtbl
= &video_presenter_service_client_vtbl
;
2021 object
->IMFVideoDisplayControl_iface
.lpVtbl
= &video_presenter_control_vtbl
;
2022 object
->IMFRateSupport_iface
.lpVtbl
= &video_presenter_rate_support_vtbl
;
2023 object
->IMFGetService_iface
.lpVtbl
= &video_presenter_getservice_vtbl
;
2024 object
->IMFVideoPositionMapper_iface
.lpVtbl
= &video_presenter_position_mapper_vtbl
;
2025 object
->IQualProp_iface
.lpVtbl
= &video_presenter_qualprop_vtbl
;
2026 object
->IMFQualityAdvise_iface
.lpVtbl
= &video_presenter_quality_advise_vtbl
;
2027 object
->IMFQualityAdviseLimits_iface
.lpVtbl
= &video_presenter_qa_limits_vtbl
;
2028 object
->allocator_cb
.lpVtbl
= &video_presenter_allocator_cb_vtbl
;
2029 object
->IUnknown_inner
.lpVtbl
= &video_presenter_inner_vtbl
;
2030 object
->IDirect3DDeviceManager9_iface
.lpVtbl
= &video_presenter_device_manager_vtbl
;
2031 object
->outer_unk
= outer
? outer
: &object
->IUnknown_inner
;
2032 object
->refcount
= 1;
2033 object
->src_rect
.right
= object
->src_rect
.bottom
= 1.0f
;
2034 object
->ar_mode
= MFVideoARMode_PreservePicture
| MFVideoARMode_PreservePixel
;
2035 object
->allocator_capacity
= 3;
2036 InitializeCriticalSection(&object
->cs
);
2038 if (FAILED(hr
= DXVA2CreateDirect3DDeviceManager9(&object
->reset_token
, &object
->device_manager
)))
2041 if (FAILED(hr
= video_presenter_init_d3d(object
)))
2044 *out
= &object
->IUnknown_inner
;
2050 IUnknown_Release(&object
->IUnknown_inner
);