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,
67 IMFSample
*last_presented
;
71 struct streaming_thread
76 struct sample_queue queue
;
79 struct video_presenter
81 IMFVideoPresenter IMFVideoPresenter_iface
;
82 IMFVideoDeviceID IMFVideoDeviceID_iface
;
83 IMFTopologyServiceLookupClient IMFTopologyServiceLookupClient_iface
;
84 IMFVideoDisplayControl IMFVideoDisplayControl_iface
;
85 IMFRateSupport IMFRateSupport_iface
;
86 IMFGetService IMFGetService_iface
;
87 IMFVideoPositionMapper IMFVideoPositionMapper_iface
;
88 IQualProp IQualProp_iface
;
89 IMFQualityAdvise IMFQualityAdvise_iface
;
90 IMFQualityAdviseLimits IMFQualityAdviseLimits_iface
;
91 IDirect3DDeviceManager9 IDirect3DDeviceManager9_iface
;
92 IMFVideoSampleAllocatorNotify allocator_cb
;
93 IUnknown IUnknown_inner
;
99 IMediaEventSink
*event_sink
;
101 IDirect3DDeviceManager9
*device_manager
;
102 IDirect3DSwapChain9
*swapchain
;
105 IMFVideoSampleAllocator
*allocator
;
106 struct streaming_thread thread
;
107 unsigned int allocator_capacity
;
108 IMFMediaType
*media_type
;
109 LONGLONG frame_time_threshold
;
112 MFVideoNormalizedRect src_rect
;
114 DWORD rendering_prefs
;
117 unsigned int ar_mode
;
130 static struct video_presenter
*impl_from_IUnknown(IUnknown
*iface
)
132 return CONTAINING_RECORD(iface
, struct video_presenter
, IUnknown_inner
);
135 static struct video_presenter
*impl_from_IMFVideoPresenter(IMFVideoPresenter
*iface
)
137 return CONTAINING_RECORD(iface
, struct video_presenter
, IMFVideoPresenter_iface
);
140 static struct video_presenter
*impl_from_IMFVideoDeviceID(IMFVideoDeviceID
*iface
)
142 return CONTAINING_RECORD(iface
, struct video_presenter
, IMFVideoDeviceID_iface
);
145 static struct video_presenter
*impl_from_IMFTopologyServiceLookupClient(IMFTopologyServiceLookupClient
*iface
)
147 return CONTAINING_RECORD(iface
, struct video_presenter
, IMFTopologyServiceLookupClient_iface
);
150 static struct video_presenter
*impl_from_IMFVideoDisplayControl(IMFVideoDisplayControl
*iface
)
152 return CONTAINING_RECORD(iface
, struct video_presenter
, IMFVideoDisplayControl_iface
);
155 static struct video_presenter
*impl_from_IMFRateSupport(IMFRateSupport
*iface
)
157 return CONTAINING_RECORD(iface
, struct video_presenter
, IMFRateSupport_iface
);
160 static struct video_presenter
*impl_from_IMFGetService(IMFGetService
*iface
)
162 return CONTAINING_RECORD(iface
, struct video_presenter
, IMFGetService_iface
);
165 static struct video_presenter
*impl_from_IMFVideoPositionMapper(IMFVideoPositionMapper
*iface
)
167 return CONTAINING_RECORD(iface
, struct video_presenter
, IMFVideoPositionMapper_iface
);
170 static struct video_presenter
*impl_from_IMFVideoSampleAllocatorNotify(IMFVideoSampleAllocatorNotify
*iface
)
172 return CONTAINING_RECORD(iface
, struct video_presenter
, allocator_cb
);
175 static struct video_presenter
*impl_from_IQualProp(IQualProp
*iface
)
177 return CONTAINING_RECORD(iface
, struct video_presenter
, IQualProp_iface
);
180 static struct video_presenter
*impl_from_IMFQualityAdvise(IMFQualityAdvise
*iface
)
182 return CONTAINING_RECORD(iface
, struct video_presenter
, IMFQualityAdvise_iface
);
185 static struct video_presenter
*impl_from_IMFQualityAdviseLimits(IMFQualityAdviseLimits
*iface
)
187 return CONTAINING_RECORD(iface
, struct video_presenter
, IMFQualityAdviseLimits_iface
);
190 static struct video_presenter
*impl_from_IDirect3DDeviceManager9(IDirect3DDeviceManager9
*iface
)
192 return CONTAINING_RECORD(iface
, struct video_presenter
, IDirect3DDeviceManager9_iface
);
195 static void video_presenter_notify_renderer(struct video_presenter
*presenter
,
196 LONG event
, LONG_PTR param1
, LONG_PTR param2
)
198 if (presenter
->event_sink
)
199 IMediaEventSink_Notify(presenter
->event_sink
, event
, param1
, param2
);
202 static unsigned int get_gcd(unsigned int a
, unsigned int b
)
216 static HRESULT
video_presenter_get_device(struct video_presenter
*presenter
, IDirect3DDevice9
**device
)
220 if (!presenter
->hdevice
)
222 if (FAILED(hr
= IDirect3DDeviceManager9_OpenDeviceHandle(presenter
->device_manager
, &presenter
->hdevice
)))
226 return IDirect3DDeviceManager9_LockDevice(presenter
->device_manager
, presenter
->hdevice
, device
, TRUE
);
229 static void video_presenter_get_native_video_size(struct video_presenter
*presenter
)
231 IMFMediaType
*media_type
;
232 UINT64 frame_size
= 0;
234 memset(&presenter
->native_size
, 0, sizeof(presenter
->native_size
));
235 memset(&presenter
->native_ratio
, 0, sizeof(presenter
->native_ratio
));
237 if (!presenter
->mixer
)
240 if (FAILED(IMFTransform_GetInputCurrentType(presenter
->mixer
, 0, &media_type
)))
243 if (SUCCEEDED(IMFMediaType_GetUINT64(media_type
, &MF_MT_FRAME_SIZE
, &frame_size
)))
247 presenter
->native_size
.cx
= frame_size
>> 32;
248 presenter
->native_size
.cy
= frame_size
;
250 if ((gcd
= get_gcd(presenter
->native_size
.cx
, presenter
->native_size
.cy
)))
252 presenter
->native_ratio
.cx
= presenter
->native_size
.cx
/ gcd
;
253 presenter
->native_ratio
.cy
= presenter
->native_size
.cy
/ gcd
;
257 IMFMediaType_Release(media_type
);
260 /* It is important this is called to reset callback too to break circular referencing,
261 when allocator keeps a reference of its container, that created it. */
262 static void video_presenter_set_allocator_callback(struct video_presenter
*presenter
,
263 IMFVideoSampleAllocatorNotify
*notify_cb
)
265 IMFVideoSampleAllocatorCallback
*cb
;
267 IMFVideoSampleAllocator_QueryInterface(presenter
->allocator
, &IID_IMFVideoSampleAllocatorCallback
, (void **)&cb
);
268 IMFVideoSampleAllocatorCallback_SetCallback(cb
, notify_cb
);
269 IMFVideoSampleAllocatorCallback_Release(cb
);
272 static void video_presenter_reset_media_type(struct video_presenter
*presenter
)
274 if (presenter
->media_type
)
275 IMFMediaType_Release(presenter
->media_type
);
276 presenter
->media_type
= NULL
;
278 if (presenter
->allocator
)
280 IMFVideoSampleAllocator_UninitializeSampleAllocator(presenter
->allocator
);
281 video_presenter_set_allocator_callback(presenter
, NULL
);
285 static HRESULT
video_presenter_set_media_type(struct video_presenter
*presenter
, IMFMediaType
*media_type
)
292 video_presenter_reset_media_type(presenter
);
296 if (presenter
->media_type
&& IMFMediaType_IsEqual(presenter
->media_type
, media_type
, &flags
) == S_OK
)
299 video_presenter_reset_media_type(presenter
);
301 if (SUCCEEDED(hr
= IMFVideoSampleAllocator_InitializeSampleAllocator(presenter
->allocator
,
302 presenter
->allocator_capacity
, media_type
)))
305 UINT64 rate
, frametime
;
307 presenter
->media_type
= media_type
;
308 IMFMediaType_AddRef(presenter
->media_type
);
310 if (SUCCEEDED(IMFMediaType_GetUINT64(presenter
->media_type
, &MF_MT_FRAME_RATE
, &rate
)))
312 ratio
.Denominator
= rate
;
313 ratio
.Numerator
= rate
>> 32;
317 ratio
.Denominator
= 1;
318 ratio
.Numerator
= 30;
321 MFFrameRateToAverageTimePerFrame(ratio
.Numerator
, ratio
.Denominator
, &frametime
);
322 presenter
->frame_time_threshold
= frametime
/ 4;
325 WARN("Failed to initialize sample allocator, hr %#lx.\n", hr
);
330 static HRESULT
video_presenter_configure_output_type(struct video_presenter
*presenter
, const MFVideoArea
*aperture
,
331 IMFMediaType
*media_type
)
338 hr
= IMFMediaType_SetUINT64(media_type
, &MF_MT_FRAME_SIZE
, (UINT64
)aperture
->Area
.cx
<< 32 | aperture
->Area
.cy
);
340 hr
= IMFMediaType_SetBlob(media_type
, &MF_MT_GEOMETRIC_APERTURE
, (UINT8
*)aperture
, sizeof(*aperture
));
342 hr
= IMFMediaType_SetBlob(media_type
, &MF_MT_MINIMUM_DISPLAY_APERTURE
, (UINT8
*)aperture
, sizeof(*aperture
));
345 hr
= IMFMediaType_GetGUID(media_type
, &MF_MT_SUBTYPE
, &subtype
);
349 hr
= MFGetStrideForBitmapInfoHeader(subtype
.Data1
, aperture
->Area
.cx
, &stride
);
351 hr
= MFGetPlaneSize(subtype
.Data1
, aperture
->Area
.cx
, aperture
->Area
.cy
, &size
);
353 hr
= IMFMediaType_SetUINT32(media_type
, &MF_MT_DEFAULT_STRIDE
, abs(stride
));
355 hr
= IMFMediaType_SetUINT32(media_type
, &MF_MT_SAMPLE_SIZE
, size
);
361 static HRESULT
video_presenter_invalidate_media_type(struct video_presenter
*presenter
)
363 IMFMediaType
*media_type
, *candidate_type
;
364 MFVideoArea aperture
= {{ 0 }};
365 unsigned int idx
= 0;
369 if (!presenter
->mixer
)
370 return MF_E_TRANSFORM_TYPE_NOT_SET
;
372 if (FAILED(hr
= MFCreateMediaType(&media_type
)))
375 video_presenter_get_native_video_size(presenter
);
377 rect
= presenter
->dst_rect
;
378 if (rect
.left
== 0 && rect
.right
== 0 && rect
.bottom
== 0 && rect
.top
== 0)
380 rect
.right
= presenter
->native_size
.cx
;
381 rect
.bottom
= presenter
->native_size
.cy
;
384 aperture
.Area
.cx
= rect
.right
- rect
.left
;
385 aperture
.Area
.cy
= rect
.bottom
- rect
.top
;
387 while (SUCCEEDED(hr
= IMFTransform_GetOutputAvailableType(presenter
->mixer
, 0, idx
++, &candidate_type
)))
389 /* FIXME: check that d3d device supports this format */
391 if (FAILED(hr
= IMFMediaType_CopyAllItems(candidate_type
, (IMFAttributes
*)media_type
)))
392 WARN("Failed to clone a media type, hr %#lx.\n", hr
);
393 IMFMediaType_Release(candidate_type
);
395 hr
= video_presenter_configure_output_type(presenter
, &aperture
, media_type
);
398 hr
= IMFTransform_SetOutputType(presenter
->mixer
, 0, media_type
, MFT_SET_TYPE_TEST_ONLY
);
401 hr
= video_presenter_set_media_type(presenter
, media_type
);
404 hr
= IMFTransform_SetOutputType(presenter
->mixer
, 0, media_type
, 0);
410 IMFMediaType_Release(media_type
);
415 static HRESULT
video_presenter_sample_queue_init(struct video_presenter
*presenter
)
417 struct sample_queue
*queue
= &presenter
->thread
.queue
;
422 memset(queue
, 0, sizeof(*queue
));
423 if (!(queue
->samples
= calloc(presenter
->allocator_capacity
, sizeof(*queue
->samples
))))
424 return E_OUTOFMEMORY
;
426 queue
->size
= presenter
->allocator_capacity
;
427 queue
->back
= queue
->size
- 1;
428 InitializeCriticalSection(&queue
->cs
);
433 static void video_presenter_sample_queue_push(struct video_presenter
*presenter
, IMFSample
*sample
,
436 struct sample_queue
*queue
= &presenter
->thread
.queue
;
439 EnterCriticalSection(&queue
->cs
);
440 if (queue
->used
!= queue
->size
)
443 idx
= queue
->front
= (queue
->size
+ queue
->front
- 1) % queue
->size
;
445 idx
= queue
->back
= (queue
->back
+ 1) % queue
->size
;
446 queue
->samples
[idx
] = sample
;
448 IMFSample_AddRef(sample
);
450 LeaveCriticalSection(&queue
->cs
);
453 static BOOL
video_presenter_sample_queue_pop(struct video_presenter
*presenter
, IMFSample
**sample
)
455 struct sample_queue
*queue
= &presenter
->thread
.queue
;
457 EnterCriticalSection(&queue
->cs
);
460 *sample
= queue
->samples
[queue
->front
];
461 queue
->front
= (queue
->front
+ 1) % queue
->size
;
466 LeaveCriticalSection(&queue
->cs
);
468 return *sample
!= NULL
;
472 static void video_presenter_sample_queue_free(struct video_presenter
*presenter
)
474 struct sample_queue
*queue
= &presenter
->thread
.queue
;
477 while (video_presenter_sample_queue_pop(presenter
, &sample
))
478 IMFSample_Release(sample
);
480 free(queue
->samples
);
481 DeleteCriticalSection(&queue
->cs
);
484 static HRESULT
video_presenter_get_sample_surface(IMFSample
*sample
, IDirect3DSurface9
**surface
)
486 IMFMediaBuffer
*buffer
;
490 if (FAILED(hr
= IMFSample_GetBufferByIndex(sample
, 0, &buffer
)))
493 hr
= IMFMediaBuffer_QueryInterface(buffer
, &IID_IMFGetService
, (void **)&gs
);
494 IMFMediaBuffer_Release(buffer
);
498 hr
= IMFGetService_GetService(gs
, &MR_BUFFER_SERVICE
, &IID_IDirect3DSurface9
, (void **)surface
);
499 IMFGetService_Release(gs
);
503 static void video_presenter_sample_present(struct video_presenter
*presenter
, IMFSample
*sample
)
505 IDirect3DSurface9
*surface
, *backbuffer
;
506 IDirect3DDevice9
*device
;
507 struct sample_queue
*queue
= &presenter
->thread
.queue
;
510 if (FAILED(hr
= video_presenter_get_sample_surface(sample
, &surface
)))
512 WARN("Failed to get sample surface, hr %#lx.\n", hr
);
516 if (presenter
->swapchain
)
518 if (SUCCEEDED(hr
= IDirect3DSwapChain9_GetBackBuffer(presenter
->swapchain
, 0, D3DBACKBUFFER_TYPE_MONO
, &backbuffer
)))
520 IDirect3DSwapChain9_GetDevice(presenter
->swapchain
, &device
);
521 IDirect3DDevice9_StretchRect(device
, surface
, NULL
, backbuffer
, NULL
, D3DTEXF_POINT
);
523 IDirect3DSwapChain9_Present(presenter
->swapchain
, NULL
, NULL
, NULL
, NULL
, 0);
524 presenter
->frame_stats
.presented
++;
526 IDirect3DDevice9_Release(device
);
527 IDirect3DSurface9_Release(backbuffer
);
530 WARN("Failed to get a backbuffer, hr %#lx.\n", hr
);
533 EnterCriticalSection(&queue
->cs
);
534 if (queue
->last_presented
)
535 IMFSample_Release(queue
->last_presented
);
536 queue
->last_presented
= sample
;
537 IMFSample_AddRef(queue
->last_presented
);
538 LeaveCriticalSection(&queue
->cs
);
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
) / 10000;
576 video_presenter_sample_present(presenter
, sample
);
578 video_presenter_sample_queue_push(presenter
, sample
, TRUE
);
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
, FALSE
);
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
->state
== PRESENTER_STATE_SHUT_DOWN
)
619 return MF_E_SHUTDOWN
;
621 if (!presenter
->media_type
)
626 LONGLONG mixing_started
, mixing_finished
;
629 if (!(presenter
->flags
& PRESENTER_MIXER_HAS_INPUT
))
632 if (FAILED(hr
= IMFVideoSampleAllocator_AllocateSample(presenter
->allocator
, &sample
)))
634 WARN("Failed to allocate a sample, hr %#lx.\n", hr
);
638 memset(&buffer
, 0, sizeof(buffer
));
639 buffer
.pSample
= sample
;
641 if (presenter
->clock
)
642 IMFClock_GetCorrelatedTime(presenter
->clock
, 0, &mixing_started
, &systime
);
644 if (FAILED(hr
= IMFTransform_ProcessOutput(presenter
->mixer
, 0, 1, &buffer
, &status
)))
646 /* FIXME: failure path probably needs to handle some errors specifically */
647 presenter
->flags
&= ~PRESENTER_MIXER_HAS_INPUT
;
648 IMFSample_Release(sample
);
653 if (presenter
->clock
)
657 IMFClock_GetCorrelatedTime(presenter
->clock
, 0, &mixing_finished
, &systime
);
658 latency
= mixing_finished
- mixing_started
;
659 video_presenter_notify_renderer(presenter
, EC_PROCESSING_LATENCY
, (LONG_PTR
)&latency
, 0);
663 IMFCollection_Release(buffer
.pEvents
);
665 video_presenter_schedule_sample(presenter
, sample
);
667 IMFSample_Release(sample
);
674 static DWORD CALLBACK
video_presenter_streaming_thread(void *arg
)
676 struct video_presenter
*presenter
= arg
;
677 unsigned int wait
= INFINITE
;
678 BOOL stop_thread
= FALSE
;
681 PeekMessageW(&msg
, NULL
, WM_USER
, WM_USER
, PM_NOREMOVE
);
683 SetEvent(presenter
->thread
.ready_event
);
687 if (MsgWaitForMultipleObjects(0, NULL
, FALSE
, wait
, QS_POSTMESSAGE
) == WAIT_TIMEOUT
)
688 video_presenter_check_queue(presenter
, &wait
);
690 while (PeekMessageW(&msg
, NULL
, 0, 0, PM_REMOVE
))
703 video_presenter_check_queue(presenter
, &wait
);
704 peek
= wait
!= INFINITE
;
717 static HRESULT
video_presenter_start_streaming(struct video_presenter
*presenter
)
721 if (presenter
->state
== PRESENTER_STATE_SHUT_DOWN
)
722 return MF_E_SHUTDOWN
;
724 if (presenter
->thread
.hthread
)
727 if (FAILED(hr
= video_presenter_sample_queue_init(presenter
)))
730 if (!(presenter
->thread
.ready_event
= CreateEventW(NULL
, FALSE
, FALSE
, NULL
)))
731 return HRESULT_FROM_WIN32(GetLastError());
733 if (!(presenter
->thread
.hthread
= CreateThread(NULL
, 0, video_presenter_streaming_thread
,
734 presenter
, 0, &presenter
->thread
.tid
)))
736 WARN("Failed to create streaming thread.\n");
737 CloseHandle(presenter
->thread
.ready_event
);
738 presenter
->thread
.ready_event
= NULL
;
742 video_presenter_set_allocator_callback(presenter
, &presenter
->allocator_cb
);
744 WaitForSingleObject(presenter
->thread
.ready_event
, INFINITE
);
745 CloseHandle(presenter
->thread
.ready_event
);
746 presenter
->thread
.ready_event
= NULL
;
748 TRACE("Started streaming thread, tid %#lx.\n", presenter
->thread
.tid
);
753 static HRESULT
video_presenter_end_streaming(struct video_presenter
*presenter
)
755 if (!presenter
->thread
.hthread
)
758 PostThreadMessageW(presenter
->thread
.tid
, EVRM_STOP
, 0, 0);
760 WaitForSingleObject(presenter
->thread
.hthread
, INFINITE
);
761 CloseHandle(presenter
->thread
.hthread
);
763 TRACE("Terminated streaming thread tid %#lx.\n", presenter
->thread
.tid
);
765 if (presenter
->thread
.queue
.last_presented
)
766 IMFSample_Release(presenter
->thread
.queue
.last_presented
);
767 video_presenter_sample_queue_free(presenter
);
768 memset(&presenter
->thread
, 0, sizeof(presenter
->thread
));
769 video_presenter_set_allocator_callback(presenter
, NULL
);
774 static HRESULT WINAPI
video_presenter_inner_QueryInterface(IUnknown
*iface
, REFIID riid
, void **obj
)
776 struct video_presenter
*presenter
= impl_from_IUnknown(iface
);
778 TRACE("%p, %s, %p.\n", iface
, debugstr_guid(riid
), obj
);
780 if (IsEqualIID(riid
, &IID_IUnknown
))
784 else if (IsEqualIID(riid
, &IID_IMFClockStateSink
)
785 || IsEqualIID(riid
, &IID_IMFVideoPresenter
))
787 *obj
= &presenter
->IMFVideoPresenter_iface
;
789 else if (IsEqualIID(riid
, &IID_IMFVideoDeviceID
))
791 *obj
= &presenter
->IMFVideoDeviceID_iface
;
793 else if (IsEqualIID(riid
, &IID_IMFTopologyServiceLookupClient
))
795 *obj
= &presenter
->IMFTopologyServiceLookupClient_iface
;
797 else if (IsEqualIID(riid
, &IID_IMFVideoDisplayControl
))
799 *obj
= &presenter
->IMFVideoDisplayControl_iface
;
801 else if (IsEqualIID(riid
, &IID_IMFRateSupport
))
803 *obj
= &presenter
->IMFRateSupport_iface
;
805 else if (IsEqualIID(riid
, &IID_IMFGetService
))
807 *obj
= &presenter
->IMFGetService_iface
;
809 else if (IsEqualIID(riid
, &IID_IMFVideoPositionMapper
))
811 *obj
= &presenter
->IMFVideoPositionMapper_iface
;
813 else if (IsEqualIID(riid
, &IID_IQualProp
))
815 *obj
= &presenter
->IQualProp_iface
;
817 else if (IsEqualIID(riid
, &IID_IMFQualityAdvise
))
819 *obj
= &presenter
->IMFQualityAdvise_iface
;
821 else if (IsEqualIID(riid
, &IID_IMFQualityAdviseLimits
))
823 *obj
= &presenter
->IMFQualityAdviseLimits_iface
;
825 else if (IsEqualIID(riid
, &IID_IDirect3DDeviceManager9
))
827 *obj
= &presenter
->IDirect3DDeviceManager9_iface
;
831 WARN("Unimplemented interface %s.\n", debugstr_guid(riid
));
833 return E_NOINTERFACE
;
836 IUnknown_AddRef((IUnknown
*)*obj
);
840 static ULONG WINAPI
video_presenter_inner_AddRef(IUnknown
*iface
)
842 struct video_presenter
*presenter
= impl_from_IUnknown(iface
);
843 ULONG refcount
= InterlockedIncrement(&presenter
->refcount
);
845 TRACE("%p, refcount %lu.\n", iface
, refcount
);
850 static void video_presenter_clear_container(struct video_presenter
*presenter
)
852 if (presenter
->clock
)
853 IMFClock_Release(presenter
->clock
);
854 if (presenter
->mixer
)
855 IMFTransform_Release(presenter
->mixer
);
856 if (presenter
->event_sink
)
857 IMediaEventSink_Release(presenter
->event_sink
);
858 presenter
->clock
= NULL
;
859 presenter
->mixer
= NULL
;
860 presenter
->event_sink
= NULL
;
863 static ULONG WINAPI
video_presenter_inner_Release(IUnknown
*iface
)
865 struct video_presenter
*presenter
= impl_from_IUnknown(iface
);
866 ULONG refcount
= InterlockedDecrement(&presenter
->refcount
);
868 TRACE("%p, refcount %lu.\n", iface
, refcount
);
872 video_presenter_end_streaming(presenter
);
873 video_presenter_clear_container(presenter
);
874 video_presenter_reset_media_type(presenter
);
875 DeleteCriticalSection(&presenter
->cs
);
876 if (presenter
->swapchain
)
877 IDirect3DSwapChain9_Release(presenter
->swapchain
);
878 if (presenter
->device_manager
)
880 IDirect3DDeviceManager9_CloseDeviceHandle(presenter
->device_manager
, presenter
->hdevice
);
881 IDirect3DDeviceManager9_Release(presenter
->device_manager
);
883 if (presenter
->allocator
)
884 IMFVideoSampleAllocator_Release(presenter
->allocator
);
891 static const IUnknownVtbl video_presenter_inner_vtbl
=
893 video_presenter_inner_QueryInterface
,
894 video_presenter_inner_AddRef
,
895 video_presenter_inner_Release
,
898 static HRESULT WINAPI
video_presenter_QueryInterface(IMFVideoPresenter
*iface
, REFIID riid
, void **obj
)
900 struct video_presenter
*presenter
= impl_from_IMFVideoPresenter(iface
);
901 return IUnknown_QueryInterface(presenter
->outer_unk
, riid
, obj
);
904 static ULONG WINAPI
video_presenter_AddRef(IMFVideoPresenter
*iface
)
906 struct video_presenter
*presenter
= impl_from_IMFVideoPresenter(iface
);
907 return IUnknown_AddRef(presenter
->outer_unk
);
910 static ULONG WINAPI
video_presenter_Release(IMFVideoPresenter
*iface
)
912 struct video_presenter
*presenter
= impl_from_IMFVideoPresenter(iface
);
913 return IUnknown_Release(presenter
->outer_unk
);
916 static HRESULT WINAPI
video_presenter_OnClockStart(IMFVideoPresenter
*iface
, MFTIME systime
, LONGLONG offset
)
918 struct video_presenter
*presenter
= impl_from_IMFVideoPresenter(iface
);
920 TRACE("%p, %s, %s.\n", iface
, debugstr_time(systime
), wine_dbgstr_longlong(offset
));
922 EnterCriticalSection(&presenter
->cs
);
923 presenter
->state
= PRESENTER_STATE_STARTED
;
924 LeaveCriticalSection(&presenter
->cs
);
929 static HRESULT WINAPI
video_presenter_OnClockStop(IMFVideoPresenter
*iface
, MFTIME systime
)
931 struct video_presenter
*presenter
= impl_from_IMFVideoPresenter(iface
);
933 TRACE("%p, %s.\n", iface
, debugstr_time(systime
));
935 EnterCriticalSection(&presenter
->cs
);
936 presenter
->state
= PRESENTER_STATE_STOPPED
;
937 presenter
->frame_stats
.presented
= 0;
938 LeaveCriticalSection(&presenter
->cs
);
943 static HRESULT WINAPI
video_presenter_OnClockPause(IMFVideoPresenter
*iface
, MFTIME systime
)
945 struct video_presenter
*presenter
= impl_from_IMFVideoPresenter(iface
);
947 TRACE("%p, %s.\n", iface
, debugstr_time(systime
));
949 EnterCriticalSection(&presenter
->cs
);
950 presenter
->state
= PRESENTER_STATE_PAUSED
;
951 LeaveCriticalSection(&presenter
->cs
);
956 static HRESULT WINAPI
video_presenter_OnClockRestart(IMFVideoPresenter
*iface
, MFTIME systime
)
958 struct video_presenter
*presenter
= impl_from_IMFVideoPresenter(iface
);
960 TRACE("%p, %s.\n", iface
, debugstr_time(systime
));
962 EnterCriticalSection(&presenter
->cs
);
963 presenter
->state
= PRESENTER_STATE_STARTED
;
964 LeaveCriticalSection(&presenter
->cs
);
969 static HRESULT WINAPI
video_presenter_OnClockSetRate(IMFVideoPresenter
*iface
, MFTIME systime
, float rate
)
971 FIXME("%p, %s, %f.\n", iface
, debugstr_time(systime
), rate
);
976 static HRESULT WINAPI
video_presenter_ProcessMessage(IMFVideoPresenter
*iface
, MFVP_MESSAGE_TYPE message
, ULONG_PTR param
)
978 struct video_presenter
*presenter
= impl_from_IMFVideoPresenter(iface
);
981 TRACE("%p, %d, %Iu.\n", iface
, message
, param
);
983 EnterCriticalSection(&presenter
->cs
);
987 case MFVP_MESSAGE_INVALIDATEMEDIATYPE
:
988 if (presenter
->state
== PRESENTER_STATE_SHUT_DOWN
)
990 else if (!presenter
->mixer
)
991 hr
= MF_E_INVALIDREQUEST
;
993 hr
= video_presenter_invalidate_media_type(presenter
);
995 case MFVP_MESSAGE_BEGINSTREAMING
:
996 hr
= video_presenter_start_streaming(presenter
);
998 case MFVP_MESSAGE_ENDSTREAMING
:
999 hr
= video_presenter_end_streaming(presenter
);
1001 case MFVP_MESSAGE_PROCESSINPUTNOTIFY
:
1002 presenter
->flags
|= PRESENTER_MIXER_HAS_INPUT
;
1003 hr
= video_presenter_process_input(presenter
);
1006 FIXME("Unsupported message %u.\n", message
);
1010 LeaveCriticalSection(&presenter
->cs
);
1015 static HRESULT WINAPI
video_presenter_GetCurrentMediaType(IMFVideoPresenter
*iface
,
1016 IMFVideoMediaType
**media_type
)
1018 struct video_presenter
*presenter
= impl_from_IMFVideoPresenter(iface
);
1021 TRACE("%p, %p.\n", iface
, media_type
);
1023 EnterCriticalSection(&presenter
->cs
);
1025 if (presenter
->state
== PRESENTER_STATE_SHUT_DOWN
)
1027 else if (!presenter
->media_type
)
1028 hr
= MF_E_NOT_INITIALIZED
;
1031 hr
= IMFMediaType_QueryInterface(presenter
->media_type
, &IID_IMFVideoMediaType
,
1032 (void **)media_type
);
1035 LeaveCriticalSection(&presenter
->cs
);
1040 static const IMFVideoPresenterVtbl video_presenter_vtbl
=
1042 video_presenter_QueryInterface
,
1043 video_presenter_AddRef
,
1044 video_presenter_Release
,
1045 video_presenter_OnClockStart
,
1046 video_presenter_OnClockStop
,
1047 video_presenter_OnClockPause
,
1048 video_presenter_OnClockRestart
,
1049 video_presenter_OnClockSetRate
,
1050 video_presenter_ProcessMessage
,
1051 video_presenter_GetCurrentMediaType
,
1054 static HRESULT WINAPI
video_presenter_device_id_QueryInterface(IMFVideoDeviceID
*iface
, REFIID riid
, void **obj
)
1056 struct video_presenter
*presenter
= impl_from_IMFVideoDeviceID(iface
);
1057 return IMFVideoPresenter_QueryInterface(&presenter
->IMFVideoPresenter_iface
, riid
, obj
);
1060 static ULONG WINAPI
video_presenter_device_id_AddRef(IMFVideoDeviceID
*iface
)
1062 struct video_presenter
*presenter
= impl_from_IMFVideoDeviceID(iface
);
1063 return IMFVideoPresenter_AddRef(&presenter
->IMFVideoPresenter_iface
);
1066 static ULONG WINAPI
video_presenter_device_id_Release(IMFVideoDeviceID
*iface
)
1068 struct video_presenter
*presenter
= impl_from_IMFVideoDeviceID(iface
);
1069 return IMFVideoPresenter_Release(&presenter
->IMFVideoPresenter_iface
);
1072 static HRESULT WINAPI
video_presenter_device_id_GetDeviceID(IMFVideoDeviceID
*iface
, IID
*device_id
)
1074 TRACE("%p, %p.\n", iface
, device_id
);
1079 memcpy(device_id
, &IID_IDirect3DDevice9
, sizeof(*device_id
));
1084 static const IMFVideoDeviceIDVtbl video_presenter_device_id_vtbl
=
1086 video_presenter_device_id_QueryInterface
,
1087 video_presenter_device_id_AddRef
,
1088 video_presenter_device_id_Release
,
1089 video_presenter_device_id_GetDeviceID
,
1092 static HRESULT WINAPI
video_presenter_service_client_QueryInterface(IMFTopologyServiceLookupClient
*iface
,
1093 REFIID riid
, void **obj
)
1095 struct video_presenter
*presenter
= impl_from_IMFTopologyServiceLookupClient(iface
);
1096 return IMFVideoPresenter_QueryInterface(&presenter
->IMFVideoPresenter_iface
, riid
, obj
);
1099 static ULONG WINAPI
video_presenter_service_client_AddRef(IMFTopologyServiceLookupClient
*iface
)
1101 struct video_presenter
*presenter
= impl_from_IMFTopologyServiceLookupClient(iface
);
1102 return IMFVideoPresenter_AddRef(&presenter
->IMFVideoPresenter_iface
);
1105 static ULONG WINAPI
video_presenter_service_client_Release(IMFTopologyServiceLookupClient
*iface
)
1107 struct video_presenter
*presenter
= impl_from_IMFTopologyServiceLookupClient(iface
);
1108 return IMFVideoPresenter_Release(&presenter
->IMFVideoPresenter_iface
);
1111 static void video_presenter_set_mixer_rect(struct video_presenter
*presenter
)
1113 IMFAttributes
*attributes
;
1116 if (!presenter
->mixer
)
1119 if (SUCCEEDED(IMFTransform_GetAttributes(presenter
->mixer
, &attributes
)))
1121 if (FAILED(hr
= IMFAttributes_SetBlob(attributes
, &VIDEO_ZOOM_RECT
, (const UINT8
*)&presenter
->src_rect
,
1122 sizeof(presenter
->src_rect
))))
1124 WARN("Failed to set zoom rectangle attribute, hr %#lx.\n", hr
);
1126 IMFAttributes_Release(attributes
);
1130 static HRESULT
video_presenter_attach_mixer(struct video_presenter
*presenter
, IMFTopologyServiceLookup
*service_lookup
)
1132 IMFVideoDeviceID
*device_id
;
1138 if (FAILED(hr
= IMFTopologyServiceLookup_LookupService(service_lookup
, MF_SERVICE_LOOKUP_GLOBAL
, 0,
1139 &MR_VIDEO_MIXER_SERVICE
, &IID_IMFTransform
, (void **)&presenter
->mixer
, &count
)))
1141 WARN("Failed to get mixer interface, hr %#lx.\n", hr
);
1145 if (SUCCEEDED(hr
= IMFTransform_QueryInterface(presenter
->mixer
, &IID_IMFVideoDeviceID
, (void **)&device_id
)))
1147 if (SUCCEEDED(hr
= IMFVideoDeviceID_GetDeviceID(device_id
, &id
)))
1149 if (!IsEqualGUID(&id
, &IID_IDirect3DDevice9
))
1150 hr
= MF_E_INVALIDREQUEST
;
1153 IMFVideoDeviceID_Release(device_id
);
1158 IMFTransform_Release(presenter
->mixer
);
1159 presenter
->mixer
= NULL
;
1162 video_presenter_set_mixer_rect(presenter
);
1163 video_presenter_get_native_video_size(presenter
);
1168 static HRESULT WINAPI
video_presenter_service_client_InitServicePointers(IMFTopologyServiceLookupClient
*iface
,
1169 IMFTopologyServiceLookup
*service_lookup
)
1171 struct video_presenter
*presenter
= impl_from_IMFTopologyServiceLookupClient(iface
);
1175 TRACE("%p, %p.\n", iface
, service_lookup
);
1177 if (!service_lookup
)
1180 EnterCriticalSection(&presenter
->cs
);
1182 if (presenter
->state
== PRESENTER_STATE_STARTED
||
1183 presenter
->state
== PRESENTER_STATE_PAUSED
)
1185 hr
= MF_E_INVALIDREQUEST
;
1189 video_presenter_clear_container(presenter
);
1192 IMFTopologyServiceLookup_LookupService(service_lookup
, MF_SERVICE_LOOKUP_GLOBAL
, 0,
1193 &MR_VIDEO_RENDER_SERVICE
, &IID_IMFClock
, (void **)&presenter
->clock
, &count
);
1195 hr
= video_presenter_attach_mixer(presenter
, service_lookup
);
1200 if (FAILED(hr
= IMFTopologyServiceLookup_LookupService(service_lookup
, MF_SERVICE_LOOKUP_GLOBAL
, 0,
1201 &MR_VIDEO_RENDER_SERVICE
, &IID_IMediaEventSink
, (void **)&presenter
->event_sink
, &count
)))
1203 WARN("Failed to get renderer event sink, hr %#lx.\n", hr
);
1208 presenter
->state
= PRESENTER_STATE_STOPPED
;
1211 LeaveCriticalSection(&presenter
->cs
);
1216 static HRESULT WINAPI
video_presenter_service_client_ReleaseServicePointers(IMFTopologyServiceLookupClient
*iface
)
1218 struct video_presenter
*presenter
= impl_from_IMFTopologyServiceLookupClient(iface
);
1220 TRACE("%p.\n", iface
);
1222 EnterCriticalSection(&presenter
->cs
);
1224 presenter
->state
= PRESENTER_STATE_SHUT_DOWN
;
1225 video_presenter_clear_container(presenter
);
1227 LeaveCriticalSection(&presenter
->cs
);
1232 static const IMFTopologyServiceLookupClientVtbl video_presenter_service_client_vtbl
=
1234 video_presenter_service_client_QueryInterface
,
1235 video_presenter_service_client_AddRef
,
1236 video_presenter_service_client_Release
,
1237 video_presenter_service_client_InitServicePointers
,
1238 video_presenter_service_client_ReleaseServicePointers
,
1241 static HRESULT WINAPI
video_presenter_control_QueryInterface(IMFVideoDisplayControl
*iface
, REFIID riid
, void **obj
)
1243 struct video_presenter
*presenter
= impl_from_IMFVideoDisplayControl(iface
);
1244 return IMFVideoPresenter_QueryInterface(&presenter
->IMFVideoPresenter_iface
, riid
, obj
);
1247 static ULONG WINAPI
video_presenter_control_AddRef(IMFVideoDisplayControl
*iface
)
1249 struct video_presenter
*presenter
= impl_from_IMFVideoDisplayControl(iface
);
1250 return IMFVideoPresenter_AddRef(&presenter
->IMFVideoPresenter_iface
);
1253 static ULONG WINAPI
video_presenter_control_Release(IMFVideoDisplayControl
*iface
)
1255 struct video_presenter
*presenter
= impl_from_IMFVideoDisplayControl(iface
);
1256 return IMFVideoPresenter_Release(&presenter
->IMFVideoPresenter_iface
);
1259 static HRESULT WINAPI
video_presenter_control_GetNativeVideoSize(IMFVideoDisplayControl
*iface
, SIZE
*video_size
,
1262 struct video_presenter
*presenter
= impl_from_IMFVideoDisplayControl(iface
);
1265 TRACE("%p, %p, %p.\n", iface
, video_size
, aspect_ratio
);
1267 if (!video_size
&& !aspect_ratio
)
1270 EnterCriticalSection(&presenter
->cs
);
1272 if (presenter
->state
== PRESENTER_STATE_SHUT_DOWN
)
1277 *video_size
= presenter
->native_size
;
1279 *aspect_ratio
= presenter
->native_ratio
;
1282 LeaveCriticalSection(&presenter
->cs
);
1287 static HRESULT WINAPI
video_presenter_control_GetIdealVideoSize(IMFVideoDisplayControl
*iface
, SIZE
*min_size
,
1290 struct video_presenter
*presenter
= impl_from_IMFVideoDisplayControl(iface
);
1293 FIXME("%p, %p, %p.\n", iface
, min_size
, max_size
);
1295 EnterCriticalSection(&presenter
->cs
);
1297 if (presenter
->state
== PRESENTER_STATE_SHUT_DOWN
)
1302 LeaveCriticalSection(&presenter
->cs
);
1307 static HRESULT WINAPI
video_presenter_control_SetVideoPosition(IMFVideoDisplayControl
*iface
,
1308 const MFVideoNormalizedRect
*src_rect
, const RECT
*dst_rect
)
1310 struct video_presenter
*presenter
= impl_from_IMFVideoDisplayControl(iface
);
1313 TRACE("%p, %s, %s.\n", iface
, debugstr_normalized_rect(src_rect
), wine_dbgstr_rect(dst_rect
));
1315 if (!src_rect
&& !dst_rect
)
1318 if (src_rect
&& (src_rect
->left
< 0.0f
|| src_rect
->top
< 0.0f
||
1319 src_rect
->right
> 1.0f
|| src_rect
->bottom
> 1.0f
||
1320 src_rect
->left
> src_rect
->right
||
1321 src_rect
->top
> src_rect
->bottom
))
1323 return E_INVALIDARG
;
1326 if (dst_rect
&& (dst_rect
->left
> dst_rect
->right
||
1327 dst_rect
->top
> dst_rect
->bottom
))
1328 return E_INVALIDARG
;
1330 EnterCriticalSection(&presenter
->cs
);
1331 if (!presenter
->video_window
)
1337 if (memcmp(&presenter
->src_rect
, src_rect
, sizeof(*src_rect
)))
1339 presenter
->src_rect
= *src_rect
;
1340 video_presenter_set_mixer_rect(presenter
);
1343 if (dst_rect
&& !EqualRect(dst_rect
, &presenter
->dst_rect
))
1345 presenter
->dst_rect
= *dst_rect
;
1346 hr
= video_presenter_invalidate_media_type(presenter
);
1347 /* Mixer's input type hasn't been configured yet, this is not an error. */
1348 if (hr
== MF_E_TRANSFORM_TYPE_NOT_SET
) hr
= S_OK
;
1349 /* FIXME: trigger repaint */
1352 LeaveCriticalSection(&presenter
->cs
);
1357 static HRESULT WINAPI
video_presenter_control_GetVideoPosition(IMFVideoDisplayControl
*iface
, MFVideoNormalizedRect
*src_rect
,
1360 struct video_presenter
*presenter
= impl_from_IMFVideoDisplayControl(iface
);
1362 TRACE("%p, %p, %p.\n", iface
, src_rect
, dst_rect
);
1364 if (!src_rect
|| !dst_rect
)
1367 EnterCriticalSection(&presenter
->cs
);
1368 *src_rect
= presenter
->src_rect
;
1369 *dst_rect
= presenter
->dst_rect
;
1370 LeaveCriticalSection(&presenter
->cs
);
1375 static HRESULT WINAPI
video_presenter_control_SetAspectRatioMode(IMFVideoDisplayControl
*iface
, DWORD mode
)
1377 struct video_presenter
*presenter
= impl_from_IMFVideoDisplayControl(iface
);
1379 TRACE("%p, %#lx.\n", iface
, mode
);
1381 if (mode
& ~MFVideoARMode_Mask
)
1382 return E_INVALIDARG
;
1384 EnterCriticalSection(&presenter
->cs
);
1385 presenter
->ar_mode
= mode
;
1386 LeaveCriticalSection(&presenter
->cs
);
1391 static HRESULT WINAPI
video_presenter_control_GetAspectRatioMode(IMFVideoDisplayControl
*iface
, DWORD
*mode
)
1393 struct video_presenter
*presenter
= impl_from_IMFVideoDisplayControl(iface
);
1395 TRACE("%p, %p.\n", iface
, mode
);
1400 EnterCriticalSection(&presenter
->cs
);
1401 *mode
= presenter
->ar_mode
;
1402 LeaveCriticalSection(&presenter
->cs
);
1407 static HRESULT
video_presenter_create_swapchain(struct video_presenter
*presenter
)
1409 D3DPRESENT_PARAMETERS present_params
= { 0 };
1410 IDirect3DDevice9
*d3d_device
;
1413 if (SUCCEEDED(hr
= video_presenter_get_device(presenter
, &d3d_device
)))
1415 present_params
.hDeviceWindow
= presenter
->video_window
;
1416 present_params
.Windowed
= TRUE
;
1417 present_params
.SwapEffect
= D3DSWAPEFFECT_COPY
;
1418 present_params
.Flags
= D3DPRESENTFLAG_VIDEO
;
1419 present_params
.PresentationInterval
= D3DPRESENT_INTERVAL_IMMEDIATE
;
1420 hr
= IDirect3DDevice9_CreateAdditionalSwapChain(d3d_device
, &present_params
, &presenter
->swapchain
);
1422 IDirect3DDevice9_Release(d3d_device
);
1423 IDirect3DDeviceManager9_UnlockDevice(presenter
->device_manager
, presenter
->hdevice
, FALSE
);
1429 static HRESULT WINAPI
video_presenter_control_SetVideoWindow(IMFVideoDisplayControl
*iface
, HWND window
)
1431 struct video_presenter
*presenter
= impl_from_IMFVideoDisplayControl(iface
);
1434 TRACE("%p, %p.\n", iface
, window
);
1436 if (!IsWindow(window
))
1437 return E_INVALIDARG
;
1439 EnterCriticalSection(&presenter
->cs
);
1440 if (presenter
->video_window
!= window
)
1442 if (presenter
->swapchain
)
1443 IDirect3DSwapChain9_Release(presenter
->swapchain
);
1444 presenter
->video_window
= window
;
1445 hr
= video_presenter_create_swapchain(presenter
);
1447 LeaveCriticalSection(&presenter
->cs
);
1452 static HRESULT WINAPI
video_presenter_control_GetVideoWindow(IMFVideoDisplayControl
*iface
, HWND
*window
)
1454 struct video_presenter
*presenter
= impl_from_IMFVideoDisplayControl(iface
);
1456 TRACE("%p, %p.\n", iface
, window
);
1461 EnterCriticalSection(&presenter
->cs
);
1462 *window
= presenter
->video_window
;
1463 LeaveCriticalSection(&presenter
->cs
);
1468 static HRESULT WINAPI
video_presenter_control_RepaintVideo(IMFVideoDisplayControl
*iface
)
1470 struct video_presenter
*presenter
= impl_from_IMFVideoDisplayControl(iface
);
1473 FIXME("%p.\n", iface
);
1475 EnterCriticalSection(&presenter
->cs
);
1477 if (presenter
->state
== PRESENTER_STATE_SHUT_DOWN
)
1482 LeaveCriticalSection(&presenter
->cs
);
1487 static HRESULT WINAPI
video_presenter_control_GetCurrentImage(IMFVideoDisplayControl
*iface
, BITMAPINFOHEADER
*header
,
1488 BYTE
**dib
, DWORD
*dib_size
, LONGLONG
*timestamp
)
1490 struct video_presenter
*presenter
= impl_from_IMFVideoDisplayControl(iface
);
1491 IDirect3DSurface9
*readback
= NULL
, *surface
;
1492 D3DSURFACE_DESC surface_desc
;
1493 D3DLOCKED_RECT mapped_rect
;
1494 IDirect3DDevice9
*device
;
1499 TRACE("%p, %p, %p, %p, %p.\n", iface
, header
, dib
, dib_size
, timestamp
);
1501 EnterCriticalSection(&presenter
->cs
);
1503 sample
= presenter
->thread
.queue
.last_presented
;
1504 presenter
->thread
.queue
.last_presented
= NULL
;
1508 hr
= MF_E_INVALIDREQUEST
;
1510 else if (SUCCEEDED(hr
= video_presenter_get_sample_surface(sample
, &surface
)))
1512 IDirect3DSurface9_GetDevice(surface
, &device
);
1513 IDirect3DSurface9_GetDesc(surface
, &surface_desc
);
1515 if (surface_desc
.Format
!= D3DFMT_X8R8G8B8
)
1517 FIXME("Unexpected surface format %d.\n", surface_desc
.Format
);
1523 if (FAILED(hr
= IDirect3DDevice9_CreateOffscreenPlainSurface(device
, surface_desc
.Width
,
1524 surface_desc
.Height
, D3DFMT_X8R8G8B8
, D3DPOOL_SYSTEMMEM
, &readback
, NULL
)))
1526 WARN("Failed to create readback surface, hr %#lx.\n", hr
);
1531 hr
= IDirect3DDevice9_GetRenderTargetData(device
, surface
, readback
);
1535 MFGetStrideForBitmapInfoHeader(D3DFMT_X8R8G8B8
, surface_desc
.Width
, &stride
);
1536 *dib_size
= abs(stride
) * surface_desc
.Height
;
1537 if (!(*dib
= CoTaskMemAlloc(*dib_size
)))
1543 if (SUCCEEDED(hr
= IDirect3DSurface9_LockRect(readback
, &mapped_rect
, NULL
, D3DLOCK_READONLY
)))
1545 hr
= MFCopyImage(stride
< 0 ? *dib
+ *dib_size
+ stride
: *dib
, stride
,
1546 mapped_rect
.pBits
, mapped_rect
.Pitch
, abs(stride
), surface_desc
.Height
);
1547 IDirect3DSurface9_UnlockRect(readback
);
1551 memset(header
, 0, sizeof(*header
));
1552 header
->biSize
= sizeof(*header
);
1553 header
->biWidth
= surface_desc
.Width
;
1554 header
->biHeight
= surface_desc
.Height
;
1555 header
->biPlanes
= 1;
1556 header
->biBitCount
= 32;
1557 header
->biSizeImage
= *dib_size
;
1558 IMFSample_GetSampleTime(sample
, timestamp
);
1561 IDirect3DSurface9_Release(readback
);
1562 IDirect3DSurface9_Release(surface
);
1564 IDirect3DDevice9_Release(device
);
1568 IMFSample_Release(sample
);
1570 LeaveCriticalSection(&presenter
->cs
);
1575 static HRESULT WINAPI
video_presenter_control_SetBorderColor(IMFVideoDisplayControl
*iface
, COLORREF color
)
1577 FIXME("%p, %#lx.\n", iface
, color
);
1582 static HRESULT WINAPI
video_presenter_control_GetBorderColor(IMFVideoDisplayControl
*iface
, COLORREF
*color
)
1584 FIXME("%p, %p.\n", iface
, color
);
1589 static HRESULT WINAPI
video_presenter_control_SetRenderingPrefs(IMFVideoDisplayControl
*iface
, DWORD flags
)
1591 FIXME("%p, %#lx.\n", iface
, flags
);
1596 static HRESULT WINAPI
video_presenter_control_GetRenderingPrefs(IMFVideoDisplayControl
*iface
, DWORD
*flags
)
1598 struct video_presenter
*presenter
= impl_from_IMFVideoDisplayControl(iface
);
1600 TRACE("%p, %p.\n", iface
, flags
);
1605 EnterCriticalSection(&presenter
->cs
);
1606 *flags
= presenter
->rendering_prefs
;
1607 LeaveCriticalSection(&presenter
->cs
);
1612 static HRESULT WINAPI
video_presenter_control_SetFullscreen(IMFVideoDisplayControl
*iface
, BOOL fullscreen
)
1614 FIXME("%p, %d.\n", iface
, fullscreen
);
1619 static HRESULT WINAPI
video_presenter_control_GetFullscreen(IMFVideoDisplayControl
*iface
, BOOL
*fullscreen
)
1621 FIXME("%p, %p.\n", iface
, fullscreen
);
1626 static const IMFVideoDisplayControlVtbl video_presenter_control_vtbl
=
1628 video_presenter_control_QueryInterface
,
1629 video_presenter_control_AddRef
,
1630 video_presenter_control_Release
,
1631 video_presenter_control_GetNativeVideoSize
,
1632 video_presenter_control_GetIdealVideoSize
,
1633 video_presenter_control_SetVideoPosition
,
1634 video_presenter_control_GetVideoPosition
,
1635 video_presenter_control_SetAspectRatioMode
,
1636 video_presenter_control_GetAspectRatioMode
,
1637 video_presenter_control_SetVideoWindow
,
1638 video_presenter_control_GetVideoWindow
,
1639 video_presenter_control_RepaintVideo
,
1640 video_presenter_control_GetCurrentImage
,
1641 video_presenter_control_SetBorderColor
,
1642 video_presenter_control_GetBorderColor
,
1643 video_presenter_control_SetRenderingPrefs
,
1644 video_presenter_control_GetRenderingPrefs
,
1645 video_presenter_control_SetFullscreen
,
1646 video_presenter_control_GetFullscreen
,
1649 static HRESULT WINAPI
video_presenter_rate_support_QueryInterface(IMFRateSupport
*iface
, REFIID riid
, void **obj
)
1651 struct video_presenter
*presenter
= impl_from_IMFRateSupport(iface
);
1652 return IMFVideoPresenter_QueryInterface(&presenter
->IMFVideoPresenter_iface
, riid
, obj
);
1655 static ULONG WINAPI
video_presenter_rate_support_AddRef(IMFRateSupport
*iface
)
1657 struct video_presenter
*presenter
= impl_from_IMFRateSupport(iface
);
1658 return IMFVideoPresenter_AddRef(&presenter
->IMFVideoPresenter_iface
);
1661 static ULONG WINAPI
video_presenter_rate_support_Release(IMFRateSupport
*iface
)
1663 struct video_presenter
*presenter
= impl_from_IMFRateSupport(iface
);
1664 return IMFVideoPresenter_Release(&presenter
->IMFVideoPresenter_iface
);
1667 static HRESULT WINAPI
video_presenter_rate_support_GetSlowestRate(IMFRateSupport
*iface
, MFRATE_DIRECTION direction
,
1668 BOOL thin
, float *rate
)
1670 TRACE("%p, %d, %d, %p.\n", iface
, direction
, thin
, rate
);
1677 static HRESULT WINAPI
video_presenter_rate_support_GetFastestRate(IMFRateSupport
*iface
, MFRATE_DIRECTION direction
,
1678 BOOL thin
, float *rate
)
1683 static HRESULT WINAPI
video_presenter_rate_support_IsRateSupported(IMFRateSupport
*iface
, BOOL thin
, float rate
,
1684 float *nearest_supported_rate
)
1689 static const IMFRateSupportVtbl video_presenter_rate_support_vtbl
=
1691 video_presenter_rate_support_QueryInterface
,
1692 video_presenter_rate_support_AddRef
,
1693 video_presenter_rate_support_Release
,
1694 video_presenter_rate_support_GetSlowestRate
,
1695 video_presenter_rate_support_GetFastestRate
,
1696 video_presenter_rate_support_IsRateSupported
,
1699 static HRESULT WINAPI
video_presenter_getservice_QueryInterface(IMFGetService
*iface
, REFIID riid
, void **obj
)
1701 struct video_presenter
*presenter
= impl_from_IMFGetService(iface
);
1702 return IMFVideoPresenter_QueryInterface(&presenter
->IMFVideoPresenter_iface
, riid
, obj
);
1705 static ULONG WINAPI
video_presenter_getservice_AddRef(IMFGetService
*iface
)
1707 struct video_presenter
*presenter
= impl_from_IMFGetService(iface
);
1708 return IMFVideoPresenter_AddRef(&presenter
->IMFVideoPresenter_iface
);
1711 static ULONG WINAPI
video_presenter_getservice_Release(IMFGetService
*iface
)
1713 struct video_presenter
*presenter
= impl_from_IMFGetService(iface
);
1714 return IMFVideoPresenter_Release(&presenter
->IMFVideoPresenter_iface
);
1717 static HRESULT WINAPI
video_presenter_getservice_GetService(IMFGetService
*iface
, REFGUID service
, REFIID riid
, void **obj
)
1719 struct video_presenter
*presenter
= impl_from_IMFGetService(iface
);
1721 TRACE("%p, %s, %s, %p.\n", iface
, debugstr_guid(service
), debugstr_guid(riid
), obj
);
1723 if (IsEqualGUID(&MR_VIDEO_ACCELERATION_SERVICE
, service
))
1724 return IDirect3DDeviceManager9_QueryInterface(presenter
->device_manager
, riid
, obj
);
1726 if (IsEqualGUID(&MR_VIDEO_RENDER_SERVICE
, service
))
1727 return IMFVideoPresenter_QueryInterface(&presenter
->IMFVideoPresenter_iface
, riid
, obj
);
1729 FIXME("Unimplemented service %s.\n", debugstr_guid(service
));
1731 return MF_E_UNSUPPORTED_SERVICE
;
1734 static const IMFGetServiceVtbl video_presenter_getservice_vtbl
=
1736 video_presenter_getservice_QueryInterface
,
1737 video_presenter_getservice_AddRef
,
1738 video_presenter_getservice_Release
,
1739 video_presenter_getservice_GetService
,
1742 static HRESULT WINAPI
video_presenter_position_mapper_QueryInterface(IMFVideoPositionMapper
*iface
, REFIID riid
, void **obj
)
1744 struct video_presenter
*presenter
= impl_from_IMFVideoPositionMapper(iface
);
1745 return IMFVideoPresenter_QueryInterface(&presenter
->IMFVideoPresenter_iface
, riid
, obj
);
1748 static ULONG WINAPI
video_presenter_position_mapper_AddRef(IMFVideoPositionMapper
*iface
)
1750 struct video_presenter
*presenter
= impl_from_IMFVideoPositionMapper(iface
);
1751 return IMFVideoPresenter_AddRef(&presenter
->IMFVideoPresenter_iface
);
1754 static ULONG WINAPI
video_presenter_position_mapper_Release(IMFVideoPositionMapper
*iface
)
1756 struct video_presenter
*presenter
= impl_from_IMFVideoPositionMapper(iface
);
1757 return IMFVideoPresenter_Release(&presenter
->IMFVideoPresenter_iface
);
1760 static HRESULT WINAPI
video_presenter_position_mapper_MapOutputCoordinateToInputStream(IMFVideoPositionMapper
*iface
,
1761 float x_out
, float y_out
, DWORD output_stream
, DWORD input_stream
, float *x_in
, float *y_in
)
1763 FIXME("%p, %f, %f, %lu, %lu, %p, %p.\n", iface
, x_out
, y_out
, output_stream
, input_stream
, x_in
, y_in
);
1768 static const IMFVideoPositionMapperVtbl video_presenter_position_mapper_vtbl
=
1770 video_presenter_position_mapper_QueryInterface
,
1771 video_presenter_position_mapper_AddRef
,
1772 video_presenter_position_mapper_Release
,
1773 video_presenter_position_mapper_MapOutputCoordinateToInputStream
,
1776 static HRESULT WINAPI
video_presenter_allocator_cb_QueryInterface(IMFVideoSampleAllocatorNotify
*iface
,
1777 REFIID riid
, void **obj
)
1779 if (IsEqualIID(riid
, &IID_IMFVideoSampleAllocatorNotify
) ||
1780 IsEqualIID(riid
, &IID_IUnknown
))
1783 IMFVideoSampleAllocatorNotify_AddRef(iface
);
1787 WARN("Unsupported interface %s.\n", debugstr_guid(riid
));
1789 return E_NOINTERFACE
;
1792 static ULONG WINAPI
video_presenter_allocator_cb_AddRef(IMFVideoSampleAllocatorNotify
*iface
)
1794 struct video_presenter
*presenter
= impl_from_IMFVideoSampleAllocatorNotify(iface
);
1795 return IMFVideoPresenter_AddRef(&presenter
->IMFVideoPresenter_iface
);
1798 static ULONG WINAPI
video_presenter_allocator_cb_Release(IMFVideoSampleAllocatorNotify
*iface
)
1800 struct video_presenter
*presenter
= impl_from_IMFVideoSampleAllocatorNotify(iface
);
1801 return IMFVideoPresenter_Release(&presenter
->IMFVideoPresenter_iface
);
1804 static HRESULT WINAPI
video_presenter_allocator_cb_NotifyRelease(IMFVideoSampleAllocatorNotify
*iface
)
1806 struct video_presenter
*presenter
= impl_from_IMFVideoSampleAllocatorNotify(iface
);
1808 EnterCriticalSection(&presenter
->cs
);
1809 video_presenter_process_input(presenter
);
1810 LeaveCriticalSection(&presenter
->cs
);
1815 static const IMFVideoSampleAllocatorNotifyVtbl video_presenter_allocator_cb_vtbl
=
1817 video_presenter_allocator_cb_QueryInterface
,
1818 video_presenter_allocator_cb_AddRef
,
1819 video_presenter_allocator_cb_Release
,
1820 video_presenter_allocator_cb_NotifyRelease
,
1823 static HRESULT WINAPI
video_presenter_qualprop_QueryInterface(IQualProp
*iface
, REFIID riid
, void **obj
)
1825 struct video_presenter
*presenter
= impl_from_IQualProp(iface
);
1826 return IMFVideoPresenter_QueryInterface(&presenter
->IMFVideoPresenter_iface
, riid
, obj
);
1829 static ULONG WINAPI
video_presenter_qualprop_AddRef(IQualProp
*iface
)
1831 struct video_presenter
*presenter
= impl_from_IQualProp(iface
);
1832 return IMFVideoPresenter_AddRef(&presenter
->IMFVideoPresenter_iface
);
1835 static ULONG WINAPI
video_presenter_qualprop_Release(IQualProp
*iface
)
1837 struct video_presenter
*presenter
= impl_from_IQualProp(iface
);
1838 return IMFVideoPresenter_Release(&presenter
->IMFVideoPresenter_iface
);
1841 static HRESULT WINAPI
video_presenter_qualprop_get_FramesDroppedInRenderer(IQualProp
*iface
, int *frames
)
1843 FIXME("%p, %p stub.\n", iface
, frames
);
1848 static HRESULT WINAPI
video_presenter_qualprop_get_FramesDrawn(IQualProp
*iface
, int *frames
)
1850 struct video_presenter
*presenter
= impl_from_IQualProp(iface
);
1853 TRACE("%p, %p.\n", iface
, frames
);
1855 EnterCriticalSection(&presenter
->cs
);
1857 switch (presenter
->state
)
1859 case PRESENTER_STATE_STARTED
:
1860 case PRESENTER_STATE_PAUSED
:
1861 if (frames
) *frames
= presenter
->frame_stats
.presented
;
1862 else hr
= E_POINTER
;
1868 LeaveCriticalSection(&presenter
->cs
);
1873 static HRESULT WINAPI
video_presenter_qualprop_get_AvgFrameRate(IQualProp
*iface
, int *avg_frame_rate
)
1875 FIXME("%p, %p stub.\n", iface
, avg_frame_rate
);
1880 static HRESULT WINAPI
video_presenter_qualprop_get_Jitter(IQualProp
*iface
, int *jitter
)
1882 FIXME("%p, %p stub.\n", iface
, jitter
);
1887 static HRESULT WINAPI
video_presenter_qualprop_get_AvgSyncOffset(IQualProp
*iface
, int *offset
)
1889 FIXME("%p, %p stub.\n", iface
, offset
);
1894 static HRESULT WINAPI
video_presenter_qualprop_get_DevSyncOffset(IQualProp
*iface
, int *devoffset
)
1896 FIXME("%p, %p stub.\n", iface
, devoffset
);
1901 static const IQualPropVtbl video_presenter_qualprop_vtbl
=
1903 video_presenter_qualprop_QueryInterface
,
1904 video_presenter_qualprop_AddRef
,
1905 video_presenter_qualprop_Release
,
1906 video_presenter_qualprop_get_FramesDroppedInRenderer
,
1907 video_presenter_qualprop_get_FramesDrawn
,
1908 video_presenter_qualprop_get_AvgFrameRate
,
1909 video_presenter_qualprop_get_Jitter
,
1910 video_presenter_qualprop_get_AvgSyncOffset
,
1911 video_presenter_qualprop_get_DevSyncOffset
,
1914 static HRESULT WINAPI
video_presenter_quality_advise_QueryInterface(IMFQualityAdvise
*iface
, REFIID riid
, void **out
)
1916 struct video_presenter
*presenter
= impl_from_IMFQualityAdvise(iface
);
1917 return IMFVideoPresenter_QueryInterface(&presenter
->IMFVideoPresenter_iface
, riid
, out
);
1920 static ULONG WINAPI
video_presenter_quality_advise_AddRef(IMFQualityAdvise
*iface
)
1922 struct video_presenter
*presenter
= impl_from_IMFQualityAdvise(iface
);
1923 return IMFVideoPresenter_AddRef(&presenter
->IMFVideoPresenter_iface
);
1926 static ULONG WINAPI
video_presenter_quality_advise_Release(IMFQualityAdvise
*iface
)
1928 struct video_presenter
*presenter
= impl_from_IMFQualityAdvise(iface
);
1929 return IMFVideoPresenter_Release(&presenter
->IMFVideoPresenter_iface
);
1932 static HRESULT WINAPI
video_presenter_quality_advise_SetDropMode(IMFQualityAdvise
*iface
,
1933 MF_QUALITY_DROP_MODE mode
)
1935 FIXME("%p, %u.\n", iface
, mode
);
1940 static HRESULT WINAPI
video_presenter_quality_advise_SetQualityLevel(IMFQualityAdvise
*iface
,
1941 MF_QUALITY_LEVEL level
)
1943 FIXME("%p, %u.\n", iface
, level
);
1948 static HRESULT WINAPI
video_presenter_quality_advise_GetDropMode(IMFQualityAdvise
*iface
,
1949 MF_QUALITY_DROP_MODE
*mode
)
1951 FIXME("%p, %p.\n", iface
, mode
);
1956 static HRESULT WINAPI
video_presenter_quality_advise_GetQualityLevel(IMFQualityAdvise
*iface
,
1957 MF_QUALITY_LEVEL
*level
)
1959 FIXME("%p, %p.\n", iface
, level
);
1964 static HRESULT WINAPI
video_presenter_quality_advise_DropTime(IMFQualityAdvise
*iface
, LONGLONG interval
)
1966 FIXME("%p, %s.\n", iface
, wine_dbgstr_longlong(interval
));
1971 static const IMFQualityAdviseVtbl video_presenter_quality_advise_vtbl
=
1973 video_presenter_quality_advise_QueryInterface
,
1974 video_presenter_quality_advise_AddRef
,
1975 video_presenter_quality_advise_Release
,
1976 video_presenter_quality_advise_SetDropMode
,
1977 video_presenter_quality_advise_SetQualityLevel
,
1978 video_presenter_quality_advise_GetDropMode
,
1979 video_presenter_quality_advise_GetQualityLevel
,
1980 video_presenter_quality_advise_DropTime
,
1983 static HRESULT WINAPI
video_presenter_device_manager_QueryInterface(IDirect3DDeviceManager9
*iface
,
1984 REFIID riid
, void **obj
)
1986 struct video_presenter
*presenter
= impl_from_IDirect3DDeviceManager9(iface
);
1987 return IMFVideoPresenter_QueryInterface(&presenter
->IMFVideoPresenter_iface
, riid
, obj
);
1990 static ULONG WINAPI
video_presenter_device_manager_AddRef(IDirect3DDeviceManager9
*iface
)
1992 struct video_presenter
*presenter
= impl_from_IDirect3DDeviceManager9(iface
);
1993 return IMFVideoPresenter_AddRef(&presenter
->IMFVideoPresenter_iface
);
1996 static ULONG WINAPI
video_presenter_device_manager_Release(IDirect3DDeviceManager9
*iface
)
1998 struct video_presenter
*presenter
= impl_from_IDirect3DDeviceManager9(iface
);
1999 return IMFVideoPresenter_Release(&presenter
->IMFVideoPresenter_iface
);
2002 static HRESULT WINAPI
video_presenter_device_manager_ResetDevice(IDirect3DDeviceManager9
*iface
,
2003 IDirect3DDevice9
*device
, UINT token
)
2005 struct video_presenter
*presenter
= impl_from_IDirect3DDeviceManager9(iface
);
2006 return IDirect3DDeviceManager9_ResetDevice(presenter
->device_manager
, device
, token
);
2009 static HRESULT WINAPI
video_presenter_device_manager_OpenDeviceHandle(IDirect3DDeviceManager9
*iface
, HANDLE
*hdevice
)
2011 struct video_presenter
*presenter
= impl_from_IDirect3DDeviceManager9(iface
);
2012 return IDirect3DDeviceManager9_OpenDeviceHandle(presenter
->device_manager
, hdevice
);
2015 static HRESULT WINAPI
video_presenter_device_manager_CloseDeviceHandle(IDirect3DDeviceManager9
*iface
, HANDLE hdevice
)
2017 struct video_presenter
*presenter
= impl_from_IDirect3DDeviceManager9(iface
);
2018 return IDirect3DDeviceManager9_CloseDeviceHandle(presenter
->device_manager
, hdevice
);
2021 static HRESULT WINAPI
video_presenter_device_manager_TestDevice(IDirect3DDeviceManager9
*iface
, HANDLE hdevice
)
2023 struct video_presenter
*presenter
= impl_from_IDirect3DDeviceManager9(iface
);
2024 return IDirect3DDeviceManager9_TestDevice(presenter
->device_manager
, hdevice
);
2027 static HRESULT WINAPI
video_presenter_device_manager_LockDevice(IDirect3DDeviceManager9
*iface
, HANDLE hdevice
,
2028 IDirect3DDevice9
**device
, BOOL block
)
2030 struct video_presenter
*presenter
= impl_from_IDirect3DDeviceManager9(iface
);
2031 return IDirect3DDeviceManager9_LockDevice(presenter
->device_manager
, hdevice
, device
, block
);
2034 static HRESULT WINAPI
video_presenter_device_manager_UnlockDevice(IDirect3DDeviceManager9
*iface
, HANDLE hdevice
,
2037 struct video_presenter
*presenter
= impl_from_IDirect3DDeviceManager9(iface
);
2038 return IDirect3DDeviceManager9_UnlockDevice(presenter
->device_manager
, hdevice
, savestate
);
2041 static HRESULT WINAPI
video_presenter_device_manager_GetVideoService(IDirect3DDeviceManager9
*iface
, HANDLE hdevice
,
2042 REFIID riid
, void **service
)
2044 struct video_presenter
*presenter
= impl_from_IDirect3DDeviceManager9(iface
);
2045 return IDirect3DDeviceManager9_GetVideoService(presenter
->device_manager
, hdevice
, riid
, service
);
2048 static const IDirect3DDeviceManager9Vtbl video_presenter_device_manager_vtbl
=
2050 video_presenter_device_manager_QueryInterface
,
2051 video_presenter_device_manager_AddRef
,
2052 video_presenter_device_manager_Release
,
2053 video_presenter_device_manager_ResetDevice
,
2054 video_presenter_device_manager_OpenDeviceHandle
,
2055 video_presenter_device_manager_CloseDeviceHandle
,
2056 video_presenter_device_manager_TestDevice
,
2057 video_presenter_device_manager_LockDevice
,
2058 video_presenter_device_manager_UnlockDevice
,
2059 video_presenter_device_manager_GetVideoService
,
2062 static HRESULT WINAPI
video_presenter_qa_limits_QueryInterface(IMFQualityAdviseLimits
*iface
, REFIID riid
, void **obj
)
2064 struct video_presenter
*presenter
= impl_from_IMFQualityAdviseLimits(iface
);
2065 return IMFVideoPresenter_QueryInterface(&presenter
->IMFVideoPresenter_iface
, riid
, obj
);
2068 static ULONG WINAPI
video_presenter_qa_limits_AddRef(IMFQualityAdviseLimits
*iface
)
2070 struct video_presenter
*presenter
= impl_from_IMFQualityAdviseLimits(iface
);
2071 return IMFVideoPresenter_AddRef(&presenter
->IMFVideoPresenter_iface
);
2074 static ULONG WINAPI
video_presenter_qa_limits_Release(IMFQualityAdviseLimits
*iface
)
2076 struct video_presenter
*presenter
= impl_from_IMFQualityAdviseLimits(iface
);
2077 return IMFVideoPresenter_Release(&presenter
->IMFVideoPresenter_iface
);
2080 static HRESULT WINAPI
video_presenter_qa_limits_GetMaximumDropMode(IMFQualityAdviseLimits
*iface
, MF_QUALITY_DROP_MODE
*mode
)
2082 FIXME("%p, %p.\n", iface
, mode
);
2087 static HRESULT WINAPI
video_presenter_qa_limits_GetMinimumQualityLevel(IMFQualityAdviseLimits
*iface
, MF_QUALITY_LEVEL
*level
)
2089 FIXME("%p, %p.\n", iface
, level
);
2094 static const IMFQualityAdviseLimitsVtbl video_presenter_qa_limits_vtbl
=
2096 video_presenter_qa_limits_QueryInterface
,
2097 video_presenter_qa_limits_AddRef
,
2098 video_presenter_qa_limits_Release
,
2099 video_presenter_qa_limits_GetMaximumDropMode
,
2100 video_presenter_qa_limits_GetMinimumQualityLevel
,
2103 HRESULT WINAPI
MFCreateVideoPresenter(IUnknown
*owner
, REFIID riid_device
, REFIID riid
, void **obj
)
2105 TRACE("%p, %s, %s, %p.\n", owner
, debugstr_guid(riid_device
), debugstr_guid(riid
), obj
);
2109 if (!IsEqualIID(riid_device
, &IID_IDirect3DDevice9
))
2110 return E_INVALIDARG
;
2112 return CoCreateInstance(&CLSID_MFVideoPresenter9
, owner
, CLSCTX_INPROC_SERVER
, riid
, obj
);
2115 static HRESULT
video_presenter_init_d3d(struct video_presenter
*presenter
)
2117 D3DPRESENT_PARAMETERS present_params
= { 0 };
2118 IDirect3DDevice9
*device
;
2122 d3d
= Direct3DCreate9(D3D_SDK_VERSION
);
2124 present_params
.BackBufferCount
= 1;
2125 present_params
.SwapEffect
= D3DSWAPEFFECT_COPY
;
2126 present_params
.hDeviceWindow
= GetDesktopWindow();
2127 present_params
.Windowed
= TRUE
;
2128 present_params
.Flags
= D3DPRESENTFLAG_VIDEO
;
2129 present_params
.PresentationInterval
= D3DPRESENT_INTERVAL_IMMEDIATE
;
2130 hr
= IDirect3D9_CreateDevice(d3d
, D3DADAPTER_DEFAULT
, D3DDEVTYPE_HAL
, GetDesktopWindow(),
2131 D3DCREATE_HARDWARE_VERTEXPROCESSING
, &present_params
, &device
);
2133 IDirect3D9_Release(d3d
);
2137 WARN("Failed to create d3d device, hr %#lx.\n", hr
);
2141 hr
= IDirect3DDeviceManager9_ResetDevice(presenter
->device_manager
, device
, presenter
->reset_token
);
2142 IDirect3DDevice9_Release(device
);
2144 WARN("Failed to set new device for the manager, hr %#lx.\n", hr
);
2146 if (SUCCEEDED(hr
= create_video_sample_allocator(FALSE
, &IID_IMFVideoSampleAllocator
, (void **)&presenter
->allocator
)))
2148 hr
= IMFVideoSampleAllocator_SetDirectXManager(presenter
->allocator
, (IUnknown
*)presenter
->device_manager
);
2154 HRESULT
evr_presenter_create(IUnknown
*outer
, void **out
)
2156 struct video_presenter
*object
;
2161 if (!(object
= calloc(1, sizeof(*object
))))
2162 return E_OUTOFMEMORY
;
2164 object
->IMFVideoPresenter_iface
.lpVtbl
= &video_presenter_vtbl
;
2165 object
->IMFVideoDeviceID_iface
.lpVtbl
= &video_presenter_device_id_vtbl
;
2166 object
->IMFTopologyServiceLookupClient_iface
.lpVtbl
= &video_presenter_service_client_vtbl
;
2167 object
->IMFVideoDisplayControl_iface
.lpVtbl
= &video_presenter_control_vtbl
;
2168 object
->IMFRateSupport_iface
.lpVtbl
= &video_presenter_rate_support_vtbl
;
2169 object
->IMFGetService_iface
.lpVtbl
= &video_presenter_getservice_vtbl
;
2170 object
->IMFVideoPositionMapper_iface
.lpVtbl
= &video_presenter_position_mapper_vtbl
;
2171 object
->IQualProp_iface
.lpVtbl
= &video_presenter_qualprop_vtbl
;
2172 object
->IMFQualityAdvise_iface
.lpVtbl
= &video_presenter_quality_advise_vtbl
;
2173 object
->IMFQualityAdviseLimits_iface
.lpVtbl
= &video_presenter_qa_limits_vtbl
;
2174 object
->allocator_cb
.lpVtbl
= &video_presenter_allocator_cb_vtbl
;
2175 object
->IUnknown_inner
.lpVtbl
= &video_presenter_inner_vtbl
;
2176 object
->IDirect3DDeviceManager9_iface
.lpVtbl
= &video_presenter_device_manager_vtbl
;
2177 object
->outer_unk
= outer
? outer
: &object
->IUnknown_inner
;
2178 object
->refcount
= 1;
2179 object
->src_rect
.right
= object
->src_rect
.bottom
= 1.0f
;
2180 object
->ar_mode
= MFVideoARMode_PreservePicture
| MFVideoARMode_PreservePixel
;
2181 object
->allocator_capacity
= 3;
2182 InitializeCriticalSection(&object
->cs
);
2184 if (FAILED(hr
= DXVA2CreateDirect3DDeviceManager9(&object
->reset_token
, &object
->device_manager
)))
2187 if (FAILED(hr
= video_presenter_init_d3d(object
)))
2189 WARN("Failed to initialize d3d device, hr %#lx.\n", hr
);
2193 *out
= &object
->IUnknown_inner
;
2199 IUnknown_Release(&object
->IUnknown_inner
);