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