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