evr/mixer: Maintain streaming state flag.
[wine.git] / dlls / evr / mixer.c
blob55acf179bdc0a2591d236c4bc0e57da6cf4fb53b
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 "dxva2api.h"
24 #include "mfapi.h"
25 #include "mferror.h"
27 #include "evr_classes.h"
29 #include "initguid.h"
30 #include "evr9.h"
32 #include "wine/debug.h"
33 #include "wine/heap.h"
35 WINE_DEFAULT_DEBUG_CHANNEL(evr);
37 #define MAX_MIXER_INPUT_STREAMS 16
39 struct input_stream
41 unsigned int id;
42 IMFAttributes *attributes;
43 IMFMediaType *media_type;
44 MFVideoNormalizedRect rect;
45 unsigned int zorder;
46 IMFSample *sample;
49 struct rt_format
51 GUID device;
52 D3DFORMAT format;
53 IMFMediaType *media_type;
56 struct output_stream
58 IMFMediaType *media_type;
59 struct rt_format *rt_formats;
60 unsigned int rt_formats_count;
63 struct video_mixer
65 IMFTransform IMFTransform_iface;
66 IMFVideoDeviceID IMFVideoDeviceID_iface;
67 IMFTopologyServiceLookupClient IMFTopologyServiceLookupClient_iface;
68 IMFVideoMixerControl2 IMFVideoMixerControl2_iface;
69 IMFGetService IMFGetService_iface;
70 IMFVideoMixerBitmap IMFVideoMixerBitmap_iface;
71 IMFVideoPositionMapper IMFVideoPositionMapper_iface;
72 IMFVideoProcessor IMFVideoProcessor_iface;
73 IMFAttributes IMFAttributes_iface;
74 IMFQualityAdvise IMFQualityAdvise_iface;
75 IUnknown IUnknown_inner;
76 IUnknown *outer_unk;
77 LONG refcount;
79 struct input_stream inputs[MAX_MIXER_INPUT_STREAMS];
80 unsigned int input_ids[MAX_MIXER_INPUT_STREAMS];
81 unsigned int input_count;
82 struct output_stream output;
84 IDirect3DDeviceManager9 *device_manager;
85 IDirectXVideoProcessor *processor;
86 HANDLE device_handle;
88 IMediaEventSink *event_sink;
89 IMFAttributes *attributes;
90 IMFAttributes *internal_attributes;
91 unsigned int mixing_flags;
92 unsigned int is_streaming;
93 COLORREF bkgnd_color;
94 LONGLONG lower_bound;
95 LONGLONG upper_bound;
96 CRITICAL_SECTION cs;
99 static struct video_mixer *impl_from_IUnknown(IUnknown *iface)
101 return CONTAINING_RECORD(iface, struct video_mixer, IUnknown_inner);
104 static struct video_mixer *impl_from_IMFTransform(IMFTransform *iface)
106 return CONTAINING_RECORD(iface, struct video_mixer, IMFTransform_iface);
109 static struct video_mixer *impl_from_IMFVideoDeviceID(IMFVideoDeviceID *iface)
111 return CONTAINING_RECORD(iface, struct video_mixer, IMFVideoDeviceID_iface);
114 static struct video_mixer *impl_from_IMFTopologyServiceLookupClient(IMFTopologyServiceLookupClient *iface)
116 return CONTAINING_RECORD(iface, struct video_mixer, IMFTopologyServiceLookupClient_iface);
119 static struct video_mixer *impl_from_IMFVideoMixerControl2(IMFVideoMixerControl2 *iface)
121 return CONTAINING_RECORD(iface, struct video_mixer, IMFVideoMixerControl2_iface);
124 static struct video_mixer *impl_from_IMFGetService(IMFGetService *iface)
126 return CONTAINING_RECORD(iface, struct video_mixer, IMFGetService_iface);
129 static struct video_mixer *impl_from_IMFVideoMixerBitmap(IMFVideoMixerBitmap *iface)
131 return CONTAINING_RECORD(iface, struct video_mixer, IMFVideoMixerBitmap_iface);
134 static struct video_mixer *impl_from_IMFVideoPositionMapper(IMFVideoPositionMapper *iface)
136 return CONTAINING_RECORD(iface, struct video_mixer, IMFVideoPositionMapper_iface);
139 static struct video_mixer *impl_from_IMFVideoProcessor(IMFVideoProcessor *iface)
141 return CONTAINING_RECORD(iface, struct video_mixer, IMFVideoProcessor_iface);
144 static struct video_mixer *impl_from_IMFAttributes(IMFAttributes *iface)
146 return CONTAINING_RECORD(iface, struct video_mixer, IMFAttributes_iface);
149 static struct video_mixer *impl_from_IMFQualityAdvise(IMFQualityAdvise *iface)
151 return CONTAINING_RECORD(iface, struct video_mixer, IMFQualityAdvise_iface);
154 static int video_mixer_compare_input_id(const void *a, const void *b)
156 const unsigned int *key = a;
157 const struct input_stream *input = b;
159 if (*key > input->id) return 1;
160 if (*key < input->id) return -1;
161 return 0;
164 static HRESULT video_mixer_get_input(const struct video_mixer *mixer, unsigned int id, struct input_stream **stream)
166 *stream = bsearch(&id, mixer->inputs, mixer->input_count, sizeof(*mixer->inputs), video_mixer_compare_input_id);
167 return *stream ? S_OK : MF_E_INVALIDSTREAMNUMBER;
170 static void video_mixer_init_input(struct input_stream *stream)
172 if (SUCCEEDED(MFCreateAttributes(&stream->attributes, 1)))
173 IMFAttributes_SetUINT32(stream->attributes, &MF_SA_REQUIRED_SAMPLE_COUNT, 1);
174 stream->rect.left = stream->rect.top = 0.0f;
175 stream->rect.right = stream->rect.bottom = 1.0f;
178 static void video_mixer_clear_types(struct video_mixer *mixer)
180 unsigned int i;
182 for (i = 0; i < mixer->input_count; ++i)
184 if (mixer->inputs[i].media_type)
185 IMFMediaType_Release(mixer->inputs[i].media_type);
186 mixer->inputs[i].media_type = NULL;
187 if (mixer->inputs[i].sample)
188 IMFSample_Release(mixer->inputs[i].sample);
189 mixer->inputs[i].sample = NULL;
191 for (i = 0; i < mixer->output.rt_formats_count; ++i)
193 IMFMediaType_Release(mixer->output.rt_formats[i].media_type);
195 heap_free(mixer->output.rt_formats);
196 if (mixer->output.media_type)
197 IMFMediaType_Release(mixer->output.media_type);
198 mixer->output.media_type = NULL;
201 static HRESULT WINAPI video_mixer_inner_QueryInterface(IUnknown *iface, REFIID riid, void **obj)
203 struct video_mixer *mixer = impl_from_IUnknown(iface);
205 TRACE("%p, %s, %p.\n", iface, debugstr_guid(riid), obj);
207 if (IsEqualIID(riid, &IID_IUnknown))
209 *obj = iface;
211 else if (IsEqualIID(riid, &IID_IMFTransform))
213 *obj = &mixer->IMFTransform_iface;
215 else if (IsEqualIID(riid, &IID_IMFVideoDeviceID))
217 *obj = &mixer->IMFVideoDeviceID_iface;
219 else if (IsEqualIID(riid, &IID_IMFTopologyServiceLookupClient))
221 *obj = &mixer->IMFTopologyServiceLookupClient_iface;
223 else if (IsEqualIID(riid, &IID_IMFVideoMixerControl2) ||
224 IsEqualIID(riid, &IID_IMFVideoMixerControl))
226 *obj = &mixer->IMFVideoMixerControl2_iface;
228 else if (IsEqualIID(riid, &IID_IMFGetService))
230 *obj = &mixer->IMFGetService_iface;
232 else if (IsEqualIID(riid, &IID_IMFVideoMixerBitmap))
234 *obj = &mixer->IMFVideoMixerBitmap_iface;
236 else if (IsEqualIID(riid, &IID_IMFVideoPositionMapper))
238 *obj = &mixer->IMFVideoPositionMapper_iface;
240 else if (IsEqualIID(riid, &IID_IMFVideoProcessor))
242 *obj = &mixer->IMFVideoProcessor_iface;
244 else if (IsEqualIID(riid, &IID_IMFAttributes))
246 *obj = &mixer->IMFAttributes_iface;
248 else if (IsEqualIID(riid, &IID_IMFQualityAdvise))
250 *obj = &mixer->IMFQualityAdvise_iface;
252 else
254 WARN("Unsupported interface %s.\n", debugstr_guid(riid));
255 *obj = NULL;
256 return E_NOINTERFACE;
259 IUnknown_AddRef((IUnknown *)*obj);
260 return S_OK;
263 static ULONG WINAPI video_mixer_inner_AddRef(IUnknown *iface)
265 struct video_mixer *mixer = impl_from_IUnknown(iface);
266 ULONG refcount = InterlockedIncrement(&mixer->refcount);
268 TRACE("%p, refcount %u.\n", iface, refcount);
270 return refcount;
273 static void video_mixer_release_device_manager(struct video_mixer *mixer)
275 if (mixer->processor)
276 IDirectXVideoProcessor_Release(mixer->processor);
277 if (mixer->device_manager)
279 IDirect3DDeviceManager9_CloseDeviceHandle(mixer->device_manager, mixer->device_handle);
280 IDirect3DDeviceManager9_Release(mixer->device_manager);
282 mixer->device_handle = NULL;
283 mixer->device_manager = NULL;
284 mixer->processor = NULL;
287 static ULONG WINAPI video_mixer_inner_Release(IUnknown *iface)
289 struct video_mixer *mixer = impl_from_IUnknown(iface);
290 ULONG refcount = InterlockedDecrement(&mixer->refcount);
291 unsigned int i;
293 TRACE("%p, refcount %u.\n", iface, refcount);
295 if (!refcount)
297 for (i = 0; i < mixer->input_count; ++i)
299 if (mixer->inputs[i].attributes)
300 IMFAttributes_Release(mixer->inputs[i].attributes);
302 video_mixer_clear_types(mixer);
303 video_mixer_release_device_manager(mixer);
304 if (mixer->attributes)
305 IMFAttributes_Release(mixer->attributes);
306 if (mixer->internal_attributes)
307 IMFAttributes_Release(mixer->internal_attributes);
308 DeleteCriticalSection(&mixer->cs);
309 free(mixer);
312 return refcount;
315 static const IUnknownVtbl video_mixer_inner_vtbl =
317 video_mixer_inner_QueryInterface,
318 video_mixer_inner_AddRef,
319 video_mixer_inner_Release,
322 static HRESULT WINAPI video_mixer_transform_QueryInterface(IMFTransform *iface, REFIID riid, void **obj)
324 struct video_mixer *mixer = impl_from_IMFTransform(iface);
325 return IUnknown_QueryInterface(mixer->outer_unk, riid, obj);
328 static ULONG WINAPI video_mixer_transform_AddRef(IMFTransform *iface)
330 struct video_mixer *mixer = impl_from_IMFTransform(iface);
331 return IUnknown_AddRef(mixer->outer_unk);
334 static ULONG WINAPI video_mixer_transform_Release(IMFTransform *iface)
336 struct video_mixer *mixer = impl_from_IMFTransform(iface);
337 return IUnknown_Release(mixer->outer_unk);
340 static HRESULT WINAPI video_mixer_transform_GetStreamLimits(IMFTransform *iface, DWORD *input_minimum,
341 DWORD *input_maximum, DWORD *output_minimum, DWORD *output_maximum)
343 TRACE("%p, %p, %p, %p, %p.\n", iface, input_minimum, input_maximum, output_minimum, output_maximum);
345 *input_minimum = 1;
346 *input_maximum = MAX_MIXER_INPUT_STREAMS;
347 *output_minimum = 1;
348 *output_maximum = 1;
350 return S_OK;
353 static HRESULT WINAPI video_mixer_transform_GetStreamCount(IMFTransform *iface, DWORD *inputs, DWORD *outputs)
355 struct video_mixer *mixer = impl_from_IMFTransform(iface);
357 TRACE("%p, %p, %p.\n", iface, inputs, outputs);
359 EnterCriticalSection(&mixer->cs);
360 if (inputs) *inputs = mixer->input_count;
361 if (outputs) *outputs = 1;
362 LeaveCriticalSection(&mixer->cs);
364 return S_OK;
367 static HRESULT WINAPI video_mixer_transform_GetStreamIDs(IMFTransform *iface, DWORD input_size, DWORD *inputs,
368 DWORD output_size, DWORD *outputs)
370 struct video_mixer *mixer = impl_from_IMFTransform(iface);
371 HRESULT hr = S_OK;
373 TRACE("%p, %u, %p, %u, %p.\n", iface, input_size, inputs, output_size, outputs);
375 EnterCriticalSection(&mixer->cs);
376 if (mixer->input_count > input_size || !output_size)
377 hr = MF_E_BUFFERTOOSMALL;
378 else if (inputs)
379 memcpy(inputs, mixer->input_ids, mixer->input_count * sizeof(*inputs));
380 if (outputs) *outputs = 0;
381 LeaveCriticalSection(&mixer->cs);
383 return hr;
386 static HRESULT WINAPI video_mixer_transform_GetInputStreamInfo(IMFTransform *iface, DWORD id, MFT_INPUT_STREAM_INFO *info)
388 struct video_mixer *mixer = impl_from_IMFTransform(iface);
389 struct input_stream *input;
390 HRESULT hr;
392 TRACE("%p, %u, %p.\n", iface, id, info);
394 EnterCriticalSection(&mixer->cs);
396 if (SUCCEEDED(hr = video_mixer_get_input(mixer, id, &input)))
398 memset(info, 0, sizeof(*info));
399 if (id)
400 info->dwFlags |= MFT_INPUT_STREAM_REMOVABLE | MFT_INPUT_STREAM_OPTIONAL;
403 LeaveCriticalSection(&mixer->cs);
405 return hr;
408 static HRESULT WINAPI video_mixer_transform_GetOutputStreamInfo(IMFTransform *iface, DWORD id, MFT_OUTPUT_STREAM_INFO *info)
410 TRACE("%p, %u, %p.\n", iface, id, info);
412 if (id)
413 return MF_E_INVALIDSTREAMNUMBER;
415 memset(info, 0, sizeof(*info));
417 return S_OK;
420 static HRESULT WINAPI video_mixer_transform_GetAttributes(IMFTransform *iface, IMFAttributes **attributes)
422 struct video_mixer *mixer = impl_from_IMFTransform(iface);
424 TRACE("%p, %p.\n", iface, attributes);
426 if (!attributes)
427 return E_POINTER;
429 *attributes = mixer->attributes;
430 IMFAttributes_AddRef(*attributes);
432 return S_OK;
435 static HRESULT WINAPI video_mixer_transform_GetInputStreamAttributes(IMFTransform *iface, DWORD id,
436 IMFAttributes **attributes)
438 struct video_mixer *mixer = impl_from_IMFTransform(iface);
439 struct input_stream *input;
440 HRESULT hr;
442 TRACE("%p, %u, %p.\n", iface, id, attributes);
444 EnterCriticalSection(&mixer->cs);
446 if (SUCCEEDED(hr = video_mixer_get_input(mixer, id, &input)))
448 *attributes = input->attributes;
449 if (*attributes)
450 IMFAttributes_AddRef(*attributes);
453 LeaveCriticalSection(&mixer->cs);
455 return hr;
458 static HRESULT WINAPI video_mixer_transform_GetOutputStreamAttributes(IMFTransform *iface, DWORD id,
459 IMFAttributes **attributes)
461 TRACE("%p, %u, %p.\n", iface, id, attributes);
463 return E_NOTIMPL;
466 static HRESULT WINAPI video_mixer_transform_DeleteInputStream(IMFTransform *iface, DWORD id)
468 struct video_mixer *mixer = impl_from_IMFTransform(iface);
469 struct input_stream *input;
470 unsigned int idx;
471 HRESULT hr;
473 TRACE("%p, %u.\n", iface, id);
475 if (!id)
476 return MF_E_INVALIDSTREAMNUMBER;
478 EnterCriticalSection(&mixer->cs);
480 /* Can't delete reference stream. */
481 if (SUCCEEDED(hr = video_mixer_get_input(mixer, id, &input)))
483 mixer->input_count--;
484 idx = input - mixer->inputs;
485 if (idx < mixer->input_count)
487 if (mixer->inputs[idx].attributes)
488 IMFAttributes_Release(mixer->inputs[idx].attributes);
489 memmove(&mixer->inputs[idx], &mixer->inputs[idx + 1], (mixer->input_count - idx) * sizeof(*mixer->inputs));
490 memmove(&mixer->input_ids[idx], &mixer->input_ids[idx + 1], (mixer->input_count - idx) *
491 sizeof(*mixer->input_ids));
495 LeaveCriticalSection(&mixer->cs);
497 return hr;
500 static int video_mixer_add_input_sort_compare(const void *a, const void *b)
502 const struct input_stream *left = a, *right = b;
503 return left->id != right->id ? (left->id < right->id ? -1 : 1) : 0;
506 static HRESULT WINAPI video_mixer_transform_AddInputStreams(IMFTransform *iface, DWORD count, DWORD *ids)
508 struct video_mixer *mixer = impl_from_IMFTransform(iface);
509 struct input_stream inputs[MAX_MIXER_INPUT_STREAMS] = { {0} };
510 struct input_stream *input;
511 unsigned int i, len;
512 HRESULT hr = S_OK;
514 TRACE("%p, %u, %p.\n", iface, count, ids);
516 if (!ids)
517 return E_POINTER;
519 EnterCriticalSection(&mixer->cs);
520 if (count > ARRAY_SIZE(mixer->inputs) - mixer->input_count)
521 hr = E_INVALIDARG;
522 else
524 /* Test for collisions. */
525 memcpy(inputs, mixer->inputs, mixer->input_count * sizeof(*inputs));
526 for (i = 0; i < count; ++i)
527 inputs[i + mixer->input_count].id = ids[i];
529 len = mixer->input_count + count;
531 qsort(inputs, len, sizeof(*inputs), video_mixer_add_input_sort_compare);
533 for (i = 1; i < len; ++i)
535 if (inputs[i - 1].id == inputs[i].id)
537 hr = E_INVALIDARG;
538 break;
542 if (SUCCEEDED(hr))
544 unsigned int zorder = mixer->input_count;
546 for (i = 0; i < count; ++i)
548 if ((input = bsearch(&ids[i], inputs, len, sizeof(*inputs), video_mixer_compare_input_id)))
549 video_mixer_init_input(input);
551 memcpy(&mixer->input_ids[mixer->input_count], ids, count * sizeof(*ids));
552 memcpy(mixer->inputs, inputs, len * sizeof(*inputs));
553 mixer->input_count += count;
555 for (i = 0; i < count; ++i)
557 if (SUCCEEDED(video_mixer_get_input(mixer, ids[i], &input)))
558 input->zorder = zorder;
559 zorder++;
563 LeaveCriticalSection(&mixer->cs);
565 return hr;
568 static HRESULT WINAPI video_mixer_transform_GetInputAvailableType(IMFTransform *iface, DWORD id, DWORD index,
569 IMFMediaType **type)
571 TRACE("%p, %u, %u, %p.\n", iface, id, index, type);
573 return E_NOTIMPL;
576 static HRESULT WINAPI video_mixer_transform_GetOutputAvailableType(IMFTransform *iface, DWORD id, DWORD index,
577 IMFMediaType **type)
579 struct video_mixer *mixer = impl_from_IMFTransform(iface);
580 HRESULT hr = S_OK;
582 TRACE("%p, %u, %u, %p.\n", iface, id, index, type);
584 if (id)
585 return MF_E_INVALIDSTREAMNUMBER;
587 EnterCriticalSection(&mixer->cs);
589 if (!mixer->inputs[0].media_type)
590 hr = MF_E_TRANSFORM_TYPE_NOT_SET;
591 else if (index >= mixer->output.rt_formats_count)
592 hr = MF_E_NO_MORE_TYPES;
593 else
595 *type = mixer->output.rt_formats[index].media_type;
596 IMFMediaType_AddRef(*type);
599 LeaveCriticalSection(&mixer->cs);
601 return hr;
604 static HRESULT video_mixer_init_dxva_videodesc(IMFMediaType *media_type, DXVA2_VideoDesc *video_desc)
606 const MFVIDEOFORMAT *video_format;
607 IMFVideoMediaType *video_type;
608 BOOL is_compressed = TRUE;
609 HRESULT hr = S_OK;
611 if (FAILED(IMFMediaType_QueryInterface(media_type, &IID_IMFVideoMediaType, (void **)&video_type)))
612 return MF_E_INVALIDMEDIATYPE;
614 video_format = IMFVideoMediaType_GetVideoFormat(video_type);
615 IMFVideoMediaType_IsCompressedFormat(video_type, &is_compressed);
617 if (!video_format || !video_format->videoInfo.dwWidth || !video_format->videoInfo.dwHeight || is_compressed)
619 hr = MF_E_INVALIDMEDIATYPE;
620 goto done;
623 memset(video_desc, 0, sizeof(*video_desc));
624 video_desc->SampleWidth = video_format->videoInfo.dwWidth;
625 video_desc->SampleHeight = video_format->videoInfo.dwHeight;
626 video_desc->Format = video_format->surfaceInfo.Format;
628 done:
629 IMFVideoMediaType_Release(video_type);
631 return hr;
634 static int rt_formats_sort_compare(const void *left, const void *right)
636 const struct rt_format *format1 = left, *format2 = right;
638 if (format1->format < format2->format) return -1;
639 if (format1->format > format2->format) return 1;
640 return 0;
643 static HRESULT video_mixer_collect_output_types(struct video_mixer *mixer, const DXVA2_VideoDesc *video_desc,
644 IDirectXVideoProcessorService *service, unsigned int device_count, const GUID *devices, unsigned int flags)
646 unsigned int i, j, format_count, count;
647 struct rt_format *rt_formats = NULL, *ptr;
648 HRESULT hr = MF_E_INVALIDMEDIATYPE;
649 D3DFORMAT *formats;
650 GUID subtype;
652 count = 0;
653 for (i = 0; i < device_count; ++i)
655 if (SUCCEEDED(IDirectXVideoProcessorService_GetVideoProcessorRenderTargets(service, &devices[i], video_desc,
656 &format_count, &formats)))
658 if (!(ptr = heap_realloc(rt_formats, (count + format_count) * sizeof(*rt_formats))))
660 hr = E_OUTOFMEMORY;
661 count = 0;
662 CoTaskMemFree(formats);
663 break;
665 rt_formats = ptr;
667 for (j = 0; j < format_count; ++j)
669 rt_formats[count + j].format = formats[j];
670 rt_formats[count + j].device = devices[i];
672 count += format_count;
674 CoTaskMemFree(formats);
678 if (count && !(flags & MFT_SET_TYPE_TEST_ONLY))
680 qsort(rt_formats, count, sizeof(*rt_formats), rt_formats_sort_compare);
682 j = 0;
683 for (i = j + 1; i < count; ++i)
685 if (rt_formats[i].format != rt_formats[j].format)
687 rt_formats[++j] = rt_formats[i];
690 count = j + 1;
692 memcpy(&subtype, &MFVideoFormat_Base, sizeof(subtype));
693 if ((mixer->output.rt_formats = heap_calloc(count, sizeof(*mixer->output.rt_formats))))
695 for (i = 0; i < count; ++i)
697 subtype.Data1 = rt_formats[i].format;
698 mixer->output.rt_formats[i] = rt_formats[i];
699 MFCreateVideoMediaTypeFromSubtype(&subtype, (IMFVideoMediaType **)&mixer->output.rt_formats[i].media_type);
701 mixer->output.rt_formats_count = count;
703 else
705 hr = E_OUTOFMEMORY;
706 count = 0;
710 heap_free(rt_formats);
712 return count ? S_OK : hr;
715 static HRESULT video_mixer_get_processor_service(struct video_mixer *mixer, IDirectXVideoProcessorService **service)
717 HRESULT hr;
719 if (!mixer->device_handle)
721 if (FAILED(hr = IDirect3DDeviceManager9_OpenDeviceHandle(mixer->device_manager, &mixer->device_handle)))
722 return hr;
725 for (;;)
727 hr = IDirect3DDeviceManager9_GetVideoService(mixer->device_manager, mixer->device_handle,
728 &IID_IDirectXVideoProcessorService, (void **)service);
729 if (hr == DXVA2_E_NEW_VIDEO_DEVICE)
731 IDirect3DDeviceManager9_CloseDeviceHandle(mixer->device_manager, mixer->device_handle);
732 mixer->device_handle = NULL;
733 if (SUCCEEDED(hr = IDirect3DDeviceManager9_OpenDeviceHandle(mixer->device_manager, &mixer->device_handle)))
734 continue;
736 break;
739 return hr;
742 static HRESULT WINAPI video_mixer_transform_SetInputType(IMFTransform *iface, DWORD id, IMFMediaType *media_type, DWORD flags)
744 struct video_mixer *mixer = impl_from_IMFTransform(iface);
745 IDirectXVideoProcessorService *service;
746 DXVA2_VideoDesc video_desc;
747 HRESULT hr = E_NOTIMPL;
748 unsigned int count;
749 GUID *guids;
751 TRACE("%p, %u, %p, %#x.\n", iface, id, media_type, flags);
753 EnterCriticalSection(&mixer->cs);
755 if (!(flags & MFT_SET_TYPE_TEST_ONLY))
756 video_mixer_clear_types(mixer);
758 if (!mixer->device_manager)
759 hr = MF_E_NOT_INITIALIZED;
760 else
762 if (SUCCEEDED(hr = video_mixer_get_processor_service(mixer, &service)))
764 if (SUCCEEDED(hr = video_mixer_init_dxva_videodesc(media_type, &video_desc)))
766 if (!id)
768 if (SUCCEEDED(hr = IDirectXVideoProcessorService_GetVideoProcessorDeviceGuids(service, &video_desc,
769 &count, &guids)))
771 if (SUCCEEDED(hr = video_mixer_collect_output_types(mixer, &video_desc, service, count,
772 guids, flags)) && !(flags & MFT_SET_TYPE_TEST_ONLY))
774 if (mixer->inputs[0].media_type)
775 IMFMediaType_Release(mixer->inputs[0].media_type);
776 mixer->inputs[0].media_type = media_type;
777 IMFMediaType_AddRef(mixer->inputs[0].media_type);
779 CoTaskMemFree(guids);
782 else
784 FIXME("Unimplemented for substreams.\n");
785 hr = E_NOTIMPL;
788 IDirectXVideoProcessorService_Release(service);
792 LeaveCriticalSection(&mixer->cs);
794 return hr;
797 static HRESULT WINAPI video_mixer_transform_SetOutputType(IMFTransform *iface, DWORD id, IMFMediaType *type, DWORD flags)
799 const unsigned int equality_flags = MF_MEDIATYPE_EQUAL_MAJOR_TYPES |
800 MF_MEDIATYPE_EQUAL_FORMAT_TYPES | MF_MEDIATYPE_EQUAL_FORMAT_DATA;
801 struct video_mixer *mixer = impl_from_IMFTransform(iface);
802 HRESULT hr = MF_E_INVALIDMEDIATYPE;
803 unsigned int i, compare_flags;
805 TRACE("%p, %u, %p, %#x.\n", iface, id, type, flags);
807 if (id)
808 return MF_E_INVALIDSTREAMNUMBER;
810 EnterCriticalSection(&mixer->cs);
812 for (i = 0; i < mixer->output.rt_formats_count; ++i)
814 compare_flags = 0;
815 if (FAILED(IMFMediaType_IsEqual(type, mixer->output.rt_formats[i].media_type, &compare_flags)))
816 continue;
818 if ((compare_flags & equality_flags) == equality_flags)
820 hr = S_OK;
821 break;
825 if (SUCCEEDED(hr) && !(flags & MFT_SET_TYPE_TEST_ONLY))
827 IDirectXVideoProcessorService *service;
829 if (SUCCEEDED(hr = video_mixer_get_processor_service(mixer, &service)))
831 DXVA2_VideoDesc video_desc;
832 GUID subtype = { 0 };
833 D3DFORMAT rt_format;
835 if (mixer->processor)
836 IDirectXVideoProcessor_Release(mixer->processor);
837 mixer->processor = NULL;
839 video_mixer_init_dxva_videodesc(mixer->inputs[0].media_type, &video_desc);
840 IMFMediaType_GetGUID(type, &MF_MT_SUBTYPE, &subtype);
841 rt_format = subtype.Data1;
843 if (SUCCEEDED(hr = IDirectXVideoProcessorService_CreateVideoProcessor(service, &mixer->output.rt_formats[i].device,
844 &video_desc, rt_format, MAX_MIXER_INPUT_STREAMS, &mixer->processor)))
846 if (mixer->output.media_type)
847 IMFMediaType_Release(mixer->output.media_type);
848 mixer->output.media_type = type;
849 IMFMediaType_AddRef(mixer->output.media_type);
852 IDirectXVideoProcessorService_Release(service);
856 LeaveCriticalSection(&mixer->cs);
858 return hr;
861 static HRESULT WINAPI video_mixer_transform_GetInputCurrentType(IMFTransform *iface, DWORD id, IMFMediaType **type)
863 struct video_mixer *mixer = impl_from_IMFTransform(iface);
864 struct input_stream *stream;
865 HRESULT hr;
867 TRACE("%p, %u, %p.\n", iface, id, type);
869 EnterCriticalSection(&mixer->cs);
871 if (SUCCEEDED(hr = video_mixer_get_input(mixer, id, &stream)))
873 if (!stream->media_type)
874 hr = MF_E_TRANSFORM_TYPE_NOT_SET;
875 else
877 *type = (IMFMediaType *)stream->media_type;
878 IMFMediaType_AddRef(*type);
882 LeaveCriticalSection(&mixer->cs);
884 return hr;
887 static HRESULT WINAPI video_mixer_transform_GetOutputCurrentType(IMFTransform *iface, DWORD id, IMFMediaType **type)
889 struct video_mixer *mixer = impl_from_IMFTransform(iface);
890 HRESULT hr = S_OK;
892 TRACE("%p, %u, %p.\n", iface, id, type);
894 if (id)
895 return MF_E_INVALIDSTREAMNUMBER;
897 EnterCriticalSection(&mixer->cs);
899 if (!mixer->output.media_type)
900 hr = MF_E_TRANSFORM_TYPE_NOT_SET;
901 else
903 *type = (IMFMediaType *)mixer->output.media_type;
904 IMFMediaType_AddRef(*type);
907 LeaveCriticalSection(&mixer->cs);
909 return hr;
912 static HRESULT WINAPI video_mixer_transform_GetInputStatus(IMFTransform *iface, DWORD id, DWORD *flags)
914 FIXME("%p, %u, %p.\n", iface, id, flags);
916 return E_NOTIMPL;
919 static HRESULT WINAPI video_mixer_transform_GetOutputStatus(IMFTransform *iface, DWORD *flags)
921 FIXME("%p, %p.\n", iface, flags);
923 return E_NOTIMPL;
926 static HRESULT WINAPI video_mixer_transform_SetOutputBounds(IMFTransform *iface, LONGLONG lower, LONGLONG upper)
928 struct video_mixer *mixer = impl_from_IMFTransform(iface);
930 TRACE("%p, %s, %s.\n", iface, wine_dbgstr_longlong(lower), wine_dbgstr_longlong(upper));
932 EnterCriticalSection(&mixer->cs);
934 mixer->lower_bound = lower;
935 mixer->upper_bound = upper;
937 LeaveCriticalSection(&mixer->cs);
939 return S_OK;
942 static HRESULT WINAPI video_mixer_transform_ProcessEvent(IMFTransform *iface, DWORD id, IMFMediaEvent *event)
944 FIXME("%p, %u, %p.\n", iface, id, event);
946 return E_NOTIMPL;
949 static HRESULT WINAPI video_mixer_transform_ProcessMessage(IMFTransform *iface, MFT_MESSAGE_TYPE message, ULONG_PTR param)
951 struct video_mixer *mixer = impl_from_IMFTransform(iface);
952 HRESULT hr = S_OK;
953 unsigned int i;
955 TRACE("%p, %u, %#lx.\n", iface, message, param);
957 switch (message)
959 case MFT_MESSAGE_SET_D3D_MANAGER:
961 EnterCriticalSection(&mixer->cs);
963 video_mixer_release_device_manager(mixer);
964 if (param)
965 hr = IUnknown_QueryInterface((IUnknown *)param, &IID_IDirect3DDeviceManager9, (void **)&mixer->device_manager);
967 LeaveCriticalSection(&mixer->cs);
969 break;
971 case MFT_MESSAGE_COMMAND_FLUSH:
973 EnterCriticalSection(&mixer->cs);
975 for (i = 0; i < mixer->input_count; ++i)
977 if (mixer->inputs[i].sample)
979 IMFSample_Release(mixer->inputs[i].sample);
980 mixer->inputs[i].sample = NULL;
984 LeaveCriticalSection(&mixer->cs);
986 break;
988 case MFT_MESSAGE_NOTIFY_BEGIN_STREAMING:
989 case MFT_MESSAGE_NOTIFY_END_STREAMING:
991 EnterCriticalSection(&mixer->cs);
993 mixer->is_streaming = message == MFT_MESSAGE_NOTIFY_BEGIN_STREAMING;
995 LeaveCriticalSection(&mixer->cs);
997 break;
999 case MFT_MESSAGE_COMMAND_DRAIN:
1000 break;
1002 default:
1003 WARN("Message not handled %d.\n", message);
1004 hr = E_NOTIMPL;
1007 return hr;
1010 static HRESULT WINAPI video_mixer_transform_ProcessInput(IMFTransform *iface, DWORD id, IMFSample *sample, DWORD flags)
1012 struct video_mixer *mixer = impl_from_IMFTransform(iface);
1013 struct input_stream *input;
1014 HRESULT hr;
1016 TRACE("%p, %u, %p, %#x.\n", iface, id, sample, flags);
1018 if (!sample)
1019 return E_POINTER;
1021 EnterCriticalSection(&mixer->cs);
1023 if (SUCCEEDED(hr = video_mixer_get_input(mixer, id, &input)))
1025 if (!input->media_type || !mixer->output.media_type)
1026 hr = MF_E_TRANSFORM_TYPE_NOT_SET;
1027 else if (input->sample)
1028 hr = MF_E_NOTACCEPTING;
1029 else
1031 mixer->is_streaming = 1;
1032 input->sample = sample;
1033 IMFSample_AddRef(input->sample);
1037 LeaveCriticalSection(&mixer->cs);
1039 return hr;
1042 static HRESULT WINAPI video_mixer_transform_ProcessOutput(IMFTransform *iface, DWORD flags, DWORD count,
1043 MFT_OUTPUT_DATA_BUFFER *samples, DWORD *status)
1045 FIXME("%p, %#x, %u, %p, %p.\n", iface, flags, count, samples, status);
1047 return E_NOTIMPL;
1050 static const IMFTransformVtbl video_mixer_transform_vtbl =
1052 video_mixer_transform_QueryInterface,
1053 video_mixer_transform_AddRef,
1054 video_mixer_transform_Release,
1055 video_mixer_transform_GetStreamLimits,
1056 video_mixer_transform_GetStreamCount,
1057 video_mixer_transform_GetStreamIDs,
1058 video_mixer_transform_GetInputStreamInfo,
1059 video_mixer_transform_GetOutputStreamInfo,
1060 video_mixer_transform_GetAttributes,
1061 video_mixer_transform_GetInputStreamAttributes,
1062 video_mixer_transform_GetOutputStreamAttributes,
1063 video_mixer_transform_DeleteInputStream,
1064 video_mixer_transform_AddInputStreams,
1065 video_mixer_transform_GetInputAvailableType,
1066 video_mixer_transform_GetOutputAvailableType,
1067 video_mixer_transform_SetInputType,
1068 video_mixer_transform_SetOutputType,
1069 video_mixer_transform_GetInputCurrentType,
1070 video_mixer_transform_GetOutputCurrentType,
1071 video_mixer_transform_GetInputStatus,
1072 video_mixer_transform_GetOutputStatus,
1073 video_mixer_transform_SetOutputBounds,
1074 video_mixer_transform_ProcessEvent,
1075 video_mixer_transform_ProcessMessage,
1076 video_mixer_transform_ProcessInput,
1077 video_mixer_transform_ProcessOutput,
1080 static HRESULT WINAPI video_mixer_device_id_QueryInterface(IMFVideoDeviceID *iface, REFIID riid, void **obj)
1082 struct video_mixer *mixer = impl_from_IMFVideoDeviceID(iface);
1083 return IMFTransform_QueryInterface(&mixer->IMFTransform_iface, riid, obj);
1086 static ULONG WINAPI video_mixer_device_id_AddRef(IMFVideoDeviceID *iface)
1088 struct video_mixer *mixer = impl_from_IMFVideoDeviceID(iface);
1089 return IMFTransform_AddRef(&mixer->IMFTransform_iface);
1092 static ULONG WINAPI video_mixer_device_id_Release(IMFVideoDeviceID *iface)
1094 struct video_mixer *mixer = impl_from_IMFVideoDeviceID(iface);
1095 return IMFTransform_Release(&mixer->IMFTransform_iface);
1098 static HRESULT WINAPI video_mixer_device_id_GetDeviceID(IMFVideoDeviceID *iface, IID *device_id)
1100 TRACE("%p, %p.\n", iface, device_id);
1102 if (!device_id)
1103 return E_POINTER;
1105 memcpy(device_id, &IID_IDirect3DDevice9, sizeof(*device_id));
1107 return S_OK;
1110 static const IMFVideoDeviceIDVtbl video_mixer_device_id_vtbl =
1112 video_mixer_device_id_QueryInterface,
1113 video_mixer_device_id_AddRef,
1114 video_mixer_device_id_Release,
1115 video_mixer_device_id_GetDeviceID,
1118 static HRESULT WINAPI video_mixer_service_client_QueryInterface(IMFTopologyServiceLookupClient *iface,
1119 REFIID riid, void **obj)
1121 struct video_mixer *mixer = impl_from_IMFTopologyServiceLookupClient(iface);
1122 return IMFTransform_QueryInterface(&mixer->IMFTransform_iface, riid, obj);
1125 static ULONG WINAPI video_mixer_service_client_AddRef(IMFTopologyServiceLookupClient *iface)
1127 struct video_mixer *mixer = impl_from_IMFTopologyServiceLookupClient(iface);
1128 return IMFTransform_AddRef(&mixer->IMFTransform_iface);
1131 static ULONG WINAPI video_mixer_service_client_Release(IMFTopologyServiceLookupClient *iface)
1133 struct video_mixer *mixer = impl_from_IMFTopologyServiceLookupClient(iface);
1134 return IMFTransform_Release(&mixer->IMFTransform_iface);
1137 static HRESULT WINAPI video_mixer_service_client_InitServicePointers(IMFTopologyServiceLookupClient *iface,
1138 IMFTopologyServiceLookup *service_lookup)
1140 struct video_mixer *mixer = impl_from_IMFTopologyServiceLookupClient(iface);
1141 unsigned int count;
1142 HRESULT hr;
1144 TRACE("%p, %p.\n", iface, service_lookup);
1146 if (!service_lookup)
1147 return E_POINTER;
1149 EnterCriticalSection(&mixer->cs);
1151 count = 1;
1152 if (FAILED(hr = IMFTopologyServiceLookup_LookupService(service_lookup, MF_SERVICE_LOOKUP_GLOBAL, 0,
1153 &MR_VIDEO_RENDER_SERVICE, &IID_IMediaEventSink, (void **)&mixer->event_sink, &count)))
1155 WARN("Failed to get renderer event sink, hr %#x.\n", hr);
1158 LeaveCriticalSection(&mixer->cs);
1160 return hr;
1163 static HRESULT WINAPI video_mixer_service_client_ReleaseServicePointers(IMFTopologyServiceLookupClient *iface)
1165 struct video_mixer *mixer = impl_from_IMFTopologyServiceLookupClient(iface);
1167 TRACE("%p.\n", iface);
1169 EnterCriticalSection(&mixer->cs);
1171 if (mixer->event_sink)
1172 IMediaEventSink_Release(mixer->event_sink);
1173 mixer->event_sink = NULL;
1175 LeaveCriticalSection(&mixer->cs);
1177 return S_OK;
1180 static const IMFTopologyServiceLookupClientVtbl video_mixer_service_client_vtbl =
1182 video_mixer_service_client_QueryInterface,
1183 video_mixer_service_client_AddRef,
1184 video_mixer_service_client_Release,
1185 video_mixer_service_client_InitServicePointers,
1186 video_mixer_service_client_ReleaseServicePointers,
1189 static HRESULT WINAPI video_mixer_control_QueryInterface(IMFVideoMixerControl2 *iface, REFIID riid, void **obj)
1191 struct video_mixer *mixer = impl_from_IMFVideoMixerControl2(iface);
1192 return IMFTransform_QueryInterface(&mixer->IMFTransform_iface, riid, obj);
1195 static ULONG WINAPI video_mixer_control_AddRef(IMFVideoMixerControl2 *iface)
1197 struct video_mixer *mixer = impl_from_IMFVideoMixerControl2(iface);
1198 return IMFTransform_AddRef(&mixer->IMFTransform_iface);
1201 static ULONG WINAPI video_mixer_control_Release(IMFVideoMixerControl2 *iface)
1203 struct video_mixer *mixer = impl_from_IMFVideoMixerControl2(iface);
1204 return IMFTransform_Release(&mixer->IMFTransform_iface);
1207 static HRESULT WINAPI video_mixer_control_SetStreamZOrder(IMFVideoMixerControl2 *iface, DWORD id, DWORD zorder)
1209 struct video_mixer *mixer = impl_from_IMFVideoMixerControl2(iface);
1210 struct input_stream *stream;
1211 HRESULT hr;
1213 TRACE("%p, %u, %u.\n", iface, id, zorder);
1215 /* Can't change reference stream. */
1216 if (!id && zorder)
1217 return E_INVALIDARG;
1219 EnterCriticalSection(&mixer->cs);
1221 if (zorder >= mixer->input_count)
1222 hr = E_INVALIDARG;
1223 else if (SUCCEEDED(hr = video_mixer_get_input(mixer, id, &stream)))
1225 /* Lowest zorder only applies to reference stream. */
1226 if (id && !zorder)
1227 hr = MF_E_INVALIDREQUEST;
1228 else
1229 stream->zorder = zorder;
1232 LeaveCriticalSection(&mixer->cs);
1234 return hr;
1237 static HRESULT WINAPI video_mixer_control_GetStreamZOrder(IMFVideoMixerControl2 *iface, DWORD id, DWORD *zorder)
1239 struct video_mixer *mixer = impl_from_IMFVideoMixerControl2(iface);
1240 struct input_stream *stream;
1241 HRESULT hr;
1243 TRACE("%p, %u, %p.\n", iface, id, zorder);
1245 if (!zorder)
1246 return E_POINTER;
1248 EnterCriticalSection(&mixer->cs);
1250 if (SUCCEEDED(hr = video_mixer_get_input(mixer, id, &stream)))
1251 *zorder = stream->zorder;
1253 LeaveCriticalSection(&mixer->cs);
1255 return hr;
1258 static HRESULT WINAPI video_mixer_control_SetStreamOutputRect(IMFVideoMixerControl2 *iface, DWORD id,
1259 const MFVideoNormalizedRect *rect)
1261 struct video_mixer *mixer = impl_from_IMFVideoMixerControl2(iface);
1262 struct input_stream *stream;
1263 HRESULT hr;
1265 TRACE("%p, %u, %p.\n", iface, id, rect);
1267 if (!rect)
1268 return E_POINTER;
1270 if (rect->left > rect->right || rect->top > rect->bottom ||
1271 rect->left < 0.0f || rect->top < 0.0f || rect->right > 1.0f || rect->bottom > 1.0f)
1273 return E_INVALIDARG;
1276 EnterCriticalSection(&mixer->cs);
1278 if (SUCCEEDED(hr = video_mixer_get_input(mixer, id, &stream)))
1279 stream->rect = *rect;
1281 LeaveCriticalSection(&mixer->cs);
1283 return hr;
1286 static HRESULT WINAPI video_mixer_control_GetStreamOutputRect(IMFVideoMixerControl2 *iface, DWORD id,
1287 MFVideoNormalizedRect *rect)
1289 struct video_mixer *mixer = impl_from_IMFVideoMixerControl2(iface);
1290 struct input_stream *stream;
1291 HRESULT hr;
1293 TRACE("%p, %u, %p.\n", iface, id, rect);
1295 if (!rect)
1296 return E_POINTER;
1298 EnterCriticalSection(&mixer->cs);
1300 if (SUCCEEDED(hr = video_mixer_get_input(mixer, id, &stream)))
1301 *rect = stream->rect;
1303 LeaveCriticalSection(&mixer->cs);
1305 return hr;
1308 static HRESULT WINAPI video_mixer_control_SetMixingPrefs(IMFVideoMixerControl2 *iface, DWORD flags)
1310 struct video_mixer *mixer = impl_from_IMFVideoMixerControl2(iface);
1312 TRACE("%p, %#x.\n", iface, flags);
1314 EnterCriticalSection(&mixer->cs);
1315 mixer->mixing_flags = flags;
1316 LeaveCriticalSection(&mixer->cs);
1318 return S_OK;
1321 static HRESULT WINAPI video_mixer_control_GetMixingPrefs(IMFVideoMixerControl2 *iface, DWORD *flags)
1323 struct video_mixer *mixer = impl_from_IMFVideoMixerControl2(iface);
1325 TRACE("%p, %p.\n", iface, flags);
1327 if (!flags)
1328 return E_POINTER;
1330 EnterCriticalSection(&mixer->cs);
1331 *flags = mixer->mixing_flags;
1332 LeaveCriticalSection(&mixer->cs);
1334 return S_OK;
1337 static const IMFVideoMixerControl2Vtbl video_mixer_control_vtbl =
1339 video_mixer_control_QueryInterface,
1340 video_mixer_control_AddRef,
1341 video_mixer_control_Release,
1342 video_mixer_control_SetStreamZOrder,
1343 video_mixer_control_GetStreamZOrder,
1344 video_mixer_control_SetStreamOutputRect,
1345 video_mixer_control_GetStreamOutputRect,
1346 video_mixer_control_SetMixingPrefs,
1347 video_mixer_control_GetMixingPrefs,
1350 static HRESULT WINAPI video_mixer_getservice_QueryInterface(IMFGetService *iface, REFIID riid, void **obj)
1352 struct video_mixer *mixer = impl_from_IMFGetService(iface);
1353 return IMFTransform_QueryInterface(&mixer->IMFTransform_iface, riid, obj);
1356 static ULONG WINAPI video_mixer_getservice_AddRef(IMFGetService *iface)
1358 struct video_mixer *mixer = impl_from_IMFGetService(iface);
1359 return IMFTransform_AddRef(&mixer->IMFTransform_iface);
1362 static ULONG WINAPI video_mixer_getservice_Release(IMFGetService *iface)
1364 struct video_mixer *mixer = impl_from_IMFGetService(iface);
1365 return IMFTransform_Release(&mixer->IMFTransform_iface);
1368 static HRESULT WINAPI video_mixer_getservice_GetService(IMFGetService *iface, REFGUID service, REFIID riid, void **obj)
1370 TRACE("%p, %s, %s, %p.\n", iface, debugstr_guid(service), debugstr_guid(riid), obj);
1372 if (IsEqualGUID(service, &MR_VIDEO_MIXER_SERVICE))
1374 if (IsEqualIID(riid, &IID_IMFVideoMixerBitmap) ||
1375 IsEqualIID(riid, &IID_IMFVideoProcessor) ||
1376 IsEqualIID(riid, &IID_IMFVideoPositionMapper) ||
1377 IsEqualIID(riid, &IID_IMFVideoMixerControl) ||
1378 IsEqualIID(riid, &IID_IMFVideoMixerControl2))
1380 return IMFGetService_QueryInterface(iface, riid, obj);
1384 FIXME("Unsupported service %s, riid %s.\n", debugstr_guid(service), debugstr_guid(riid));
1386 return E_NOTIMPL;
1389 static const IMFGetServiceVtbl video_mixer_getservice_vtbl =
1391 video_mixer_getservice_QueryInterface,
1392 video_mixer_getservice_AddRef,
1393 video_mixer_getservice_Release,
1394 video_mixer_getservice_GetService,
1397 static HRESULT WINAPI video_mixer_bitmap_QueryInterface(IMFVideoMixerBitmap *iface, REFIID riid, void **obj)
1399 struct video_mixer *mixer = impl_from_IMFVideoMixerBitmap(iface);
1400 return IMFTransform_QueryInterface(&mixer->IMFTransform_iface, riid, obj);
1403 static ULONG WINAPI video_mixer_bitmap_AddRef(IMFVideoMixerBitmap *iface)
1405 struct video_mixer *mixer = impl_from_IMFVideoMixerBitmap(iface);
1406 return IMFTransform_AddRef(&mixer->IMFTransform_iface);
1409 static ULONG WINAPI video_mixer_bitmap_Release(IMFVideoMixerBitmap *iface)
1411 struct video_mixer *mixer = impl_from_IMFVideoMixerBitmap(iface);
1412 return IMFTransform_Release(&mixer->IMFTransform_iface);
1415 static HRESULT WINAPI video_mixer_bitmap_SetAlphaBitmap(IMFVideoMixerBitmap *iface, const MFVideoAlphaBitmap *bitmap)
1417 FIXME("%p, %p.\n", iface, bitmap);
1419 return E_NOTIMPL;
1422 static HRESULT WINAPI video_mixer_bitmap_ClearAlphaBitmap(IMFVideoMixerBitmap *iface)
1424 FIXME("%p.\n", iface);
1426 return E_NOTIMPL;
1429 static HRESULT WINAPI video_mixer_bitmap_UpdateAlphaBitmapParameters(IMFVideoMixerBitmap *iface,
1430 const MFVideoAlphaBitmapParams *params)
1432 FIXME("%p, %p.\n", iface, params);
1434 return E_NOTIMPL;
1437 static HRESULT WINAPI video_mixer_bitmap_GetAlphaBitmapParameters(IMFVideoMixerBitmap *iface, MFVideoAlphaBitmapParams *params)
1439 FIXME("%p, %p.\n", iface, params);
1441 return E_NOTIMPL;
1444 static const IMFVideoMixerBitmapVtbl video_mixer_bitmap_vtbl =
1446 video_mixer_bitmap_QueryInterface,
1447 video_mixer_bitmap_AddRef,
1448 video_mixer_bitmap_Release,
1449 video_mixer_bitmap_SetAlphaBitmap,
1450 video_mixer_bitmap_ClearAlphaBitmap,
1451 video_mixer_bitmap_UpdateAlphaBitmapParameters,
1452 video_mixer_bitmap_GetAlphaBitmapParameters,
1455 static HRESULT WINAPI video_mixer_position_mapper_QueryInterface(IMFVideoPositionMapper *iface, REFIID riid, void **obj)
1457 struct video_mixer *mixer = impl_from_IMFVideoPositionMapper(iface);
1458 return IMFTransform_QueryInterface(&mixer->IMFTransform_iface, riid, obj);
1461 static ULONG WINAPI video_mixer_position_mapper_AddRef(IMFVideoPositionMapper *iface)
1463 struct video_mixer *mixer = impl_from_IMFVideoPositionMapper(iface);
1464 return IMFTransform_AddRef(&mixer->IMFTransform_iface);
1467 static ULONG WINAPI video_mixer_position_mapper_Release(IMFVideoPositionMapper *iface)
1469 struct video_mixer *mixer = impl_from_IMFVideoPositionMapper(iface);
1470 return IMFTransform_Release(&mixer->IMFTransform_iface);
1473 static HRESULT WINAPI video_mixer_position_mapper_MapOutputCoordinateToInputStream(IMFVideoPositionMapper *iface,
1474 float x_out, float y_out, DWORD output_stream, DWORD input_stream, float *x_in, float *y_in)
1476 FIXME("%p, %f, %f, %u, %u, %p, %p.\n", iface, x_out, y_out, output_stream, input_stream, x_in, y_in);
1478 return E_NOTIMPL;
1481 static const IMFVideoPositionMapperVtbl video_mixer_position_mapper_vtbl =
1483 video_mixer_position_mapper_QueryInterface,
1484 video_mixer_position_mapper_AddRef,
1485 video_mixer_position_mapper_Release,
1486 video_mixer_position_mapper_MapOutputCoordinateToInputStream,
1489 static HRESULT WINAPI video_mixer_processor_QueryInterface(IMFVideoProcessor *iface, REFIID riid, void **obj)
1491 struct video_mixer *mixer = impl_from_IMFVideoProcessor(iface);
1492 return IMFTransform_QueryInterface(&mixer->IMFTransform_iface, riid, obj);
1495 static ULONG WINAPI video_mixer_processor_AddRef(IMFVideoProcessor *iface)
1497 struct video_mixer *mixer = impl_from_IMFVideoProcessor(iface);
1498 return IMFTransform_AddRef(&mixer->IMFTransform_iface);
1501 static ULONG WINAPI video_mixer_processor_Release(IMFVideoProcessor *iface)
1503 struct video_mixer *mixer = impl_from_IMFVideoProcessor(iface);
1504 return IMFTransform_Release(&mixer->IMFTransform_iface);
1507 static HRESULT WINAPI video_mixer_processor_GetAvailableVideoProcessorModes(IMFVideoProcessor *iface, UINT *count,
1508 GUID **modes)
1510 FIXME("%p, %p, %p.\n", iface, count, modes);
1512 return E_NOTIMPL;
1515 static HRESULT WINAPI video_mixer_processor_GetVideoProcessorCaps(IMFVideoProcessor *iface, GUID *mode,
1516 DXVA2_VideoProcessorCaps *caps)
1518 FIXME("%p, %s, %p.\n", iface, debugstr_guid(mode), caps);
1520 return E_NOTIMPL;
1523 static HRESULT WINAPI video_mixer_processor_GetVideoProcessorMode(IMFVideoProcessor *iface, GUID *mode)
1525 FIXME("%p, %p.\n", iface, mode);
1527 return E_NOTIMPL;
1530 static HRESULT WINAPI video_mixer_processor_SetVideoProcessorMode(IMFVideoProcessor *iface, GUID *mode)
1532 FIXME("%p, %s.\n", iface, debugstr_guid(mode));
1534 return E_NOTIMPL;
1537 static HRESULT WINAPI video_mixer_processor_GetProcAmpRange(IMFVideoProcessor *iface, DWORD prop, DXVA2_ValueRange *range)
1539 FIXME("%p, %#x, %p.\n", iface, prop, range);
1541 return E_NOTIMPL;
1544 static HRESULT WINAPI video_mixer_processor_GetProcAmpValues(IMFVideoProcessor *iface, DWORD flags, DXVA2_ProcAmpValues *values)
1546 FIXME("%p, %#x, %p.\n", iface, flags, values);
1548 return E_NOTIMPL;
1551 static HRESULT WINAPI video_mixer_processor_SetProcAmpValues(IMFVideoProcessor *iface, DWORD flags, DXVA2_ProcAmpValues *values)
1553 FIXME("%p, %#x, %p.\n", iface, flags, values);
1555 return E_NOTIMPL;
1558 static HRESULT WINAPI video_mixer_processor_GetFilteringRange(IMFVideoProcessor *iface, DWORD prop, DXVA2_ValueRange *range)
1560 FIXME("%p, %#x, %p.\n", iface, prop, range);
1562 return E_NOTIMPL;
1565 static HRESULT WINAPI video_mixer_processor_GetFilteringValue(IMFVideoProcessor *iface, DWORD prop, DXVA2_Fixed32 *value)
1567 FIXME("%p, %#x, %p.\n", iface, prop, value);
1569 return E_NOTIMPL;
1572 static HRESULT WINAPI video_mixer_processor_SetFilteringValue(IMFVideoProcessor *iface, DWORD prop, DXVA2_Fixed32 *value)
1574 FIXME("%p, %#x, %p.\n", iface, prop, value);
1576 return E_NOTIMPL;
1579 static HRESULT WINAPI video_mixer_processor_GetBackgroundColor(IMFVideoProcessor *iface, COLORREF *color)
1581 struct video_mixer *mixer = impl_from_IMFVideoProcessor(iface);
1583 TRACE("%p, %p.\n", iface, color);
1585 if (!color)
1586 return E_POINTER;
1588 EnterCriticalSection(&mixer->cs);
1589 *color = mixer->bkgnd_color;
1590 LeaveCriticalSection(&mixer->cs);
1592 return S_OK;
1595 static HRESULT WINAPI video_mixer_processor_SetBackgroundColor(IMFVideoProcessor *iface, COLORREF color)
1597 struct video_mixer *mixer = impl_from_IMFVideoProcessor(iface);
1599 TRACE("%p, %#x.\n", iface, color);
1601 EnterCriticalSection(&mixer->cs);
1602 mixer->bkgnd_color = color;
1603 LeaveCriticalSection(&mixer->cs);
1605 return S_OK;
1608 static const IMFVideoProcessorVtbl video_mixer_processor_vtbl =
1610 video_mixer_processor_QueryInterface,
1611 video_mixer_processor_AddRef,
1612 video_mixer_processor_Release,
1613 video_mixer_processor_GetAvailableVideoProcessorModes,
1614 video_mixer_processor_GetVideoProcessorCaps,
1615 video_mixer_processor_GetVideoProcessorMode,
1616 video_mixer_processor_SetVideoProcessorMode,
1617 video_mixer_processor_GetProcAmpRange,
1618 video_mixer_processor_GetProcAmpValues,
1619 video_mixer_processor_SetProcAmpValues,
1620 video_mixer_processor_GetFilteringRange,
1621 video_mixer_processor_GetFilteringValue,
1622 video_mixer_processor_SetFilteringValue,
1623 video_mixer_processor_GetBackgroundColor,
1624 video_mixer_processor_SetBackgroundColor,
1627 static HRESULT WINAPI video_mixer_attributes_QueryInterface(IMFAttributes *iface, REFIID riid, void **out)
1629 struct video_mixer *mixer = impl_from_IMFAttributes(iface);
1630 return IMFTransform_QueryInterface(&mixer->IMFTransform_iface, riid, out);
1633 static ULONG WINAPI video_mixer_attributes_AddRef(IMFAttributes *iface)
1635 struct video_mixer *mixer = impl_from_IMFAttributes(iface);
1636 return IMFTransform_AddRef(&mixer->IMFTransform_iface);
1639 static ULONG WINAPI video_mixer_attributes_Release(IMFAttributes *iface)
1641 struct video_mixer *mixer = impl_from_IMFAttributes(iface);
1642 return IMFTransform_Release(&mixer->IMFTransform_iface);
1645 static HRESULT WINAPI video_mixer_attributes_GetItem(IMFAttributes *iface, REFGUID key, PROPVARIANT *value)
1647 struct video_mixer *mixer = impl_from_IMFAttributes(iface);
1649 TRACE("%p, %s, %p.\n", iface, debugstr_guid(key), value);
1651 return IMFAttributes_GetItem(mixer->internal_attributes, key, value);
1654 static HRESULT WINAPI video_mixer_attributes_GetItemType(IMFAttributes *iface, REFGUID key, MF_ATTRIBUTE_TYPE *type)
1656 struct video_mixer *mixer = impl_from_IMFAttributes(iface);
1658 TRACE("%p, %s, %p.\n", iface, debugstr_guid(key), type);
1660 return IMFAttributes_GetItemType(mixer->internal_attributes, key, type);
1663 static HRESULT WINAPI video_mixer_attributes_CompareItem(IMFAttributes *iface, REFGUID key,
1664 REFPROPVARIANT value, BOOL *result)
1666 struct video_mixer *mixer = impl_from_IMFAttributes(iface);
1668 TRACE("%p, %s, %p, %p.\n", iface, debugstr_guid(key), value, result);
1670 return IMFAttributes_CompareItem(mixer->internal_attributes, key, value, result);
1673 static HRESULT WINAPI video_mixer_attributes_Compare(IMFAttributes *iface, IMFAttributes *theirs,
1674 MF_ATTRIBUTES_MATCH_TYPE match_type, BOOL *ret)
1676 struct video_mixer *mixer = impl_from_IMFAttributes(iface);
1678 TRACE("%p, %p, %d, %p.\n", iface, theirs, match_type, ret);
1680 return IMFAttributes_Compare(mixer->internal_attributes, theirs, match_type, ret);
1683 static HRESULT WINAPI video_mixer_attributes_GetUINT32(IMFAttributes *iface, REFGUID key, UINT32 *value)
1685 struct video_mixer *mixer = impl_from_IMFAttributes(iface);
1687 TRACE("%p, %s, %p.\n", iface, debugstr_guid(key), value);
1689 return IMFAttributes_GetUINT32(mixer->internal_attributes, key, value);
1692 static HRESULT WINAPI video_mixer_attributes_GetUINT64(IMFAttributes *iface, REFGUID key, UINT64 *value)
1694 struct video_mixer *mixer = impl_from_IMFAttributes(iface);
1696 TRACE("%p, %s, %p.\n", iface, debugstr_guid(key), value);
1698 return IMFAttributes_GetUINT64(mixer->internal_attributes, key, value);
1701 static HRESULT WINAPI video_mixer_attributes_GetDouble(IMFAttributes *iface, REFGUID key, double *value)
1703 struct video_mixer *mixer = impl_from_IMFAttributes(iface);
1705 TRACE("%p, %s, %p.\n", iface, debugstr_guid(key), value);
1707 return IMFAttributes_GetDouble(mixer->internal_attributes, key, value);
1710 static HRESULT WINAPI video_mixer_attributes_GetGUID(IMFAttributes *iface, REFGUID key, GUID *value)
1712 struct video_mixer *mixer = impl_from_IMFAttributes(iface);
1714 TRACE("%p, %s, %p.\n", iface, debugstr_guid(key), value);
1716 return IMFAttributes_GetGUID(mixer->internal_attributes, key, value);
1719 static HRESULT WINAPI video_mixer_attributes_GetStringLength(IMFAttributes *iface, REFGUID key, UINT32 *length)
1721 struct video_mixer *mixer = impl_from_IMFAttributes(iface);
1723 TRACE("%p, %s, %p.\n", iface, debugstr_guid(key), length);
1725 return IMFAttributes_GetStringLength(mixer->internal_attributes, key, length);
1728 static HRESULT WINAPI video_mixer_attributes_GetString(IMFAttributes *iface, REFGUID key, WCHAR *value,
1729 UINT32 size, UINT32 *length)
1731 struct video_mixer *mixer = impl_from_IMFAttributes(iface);
1733 TRACE("%p, %s, %p, %d, %p.\n", iface, debugstr_guid(key), value, size, length);
1735 return IMFAttributes_GetString(mixer->internal_attributes, key, value, size, length);
1738 static HRESULT WINAPI video_mixer_attributes_GetAllocatedString(IMFAttributes *iface, REFGUID key,
1739 WCHAR **value, UINT32 *length)
1741 struct video_mixer *mixer = impl_from_IMFAttributes(iface);
1743 TRACE("%p, %s, %p, %p.\n", iface, debugstr_guid(key), value, length);
1745 return IMFAttributes_GetAllocatedString(mixer->internal_attributes, key, value, length);
1748 static HRESULT WINAPI video_mixer_attributes_GetBlobSize(IMFAttributes *iface, REFGUID key, UINT32 *size)
1750 struct video_mixer *mixer = impl_from_IMFAttributes(iface);
1752 TRACE("%p, %s, %p.\n", iface, debugstr_guid(key), size);
1754 return IMFAttributes_GetBlobSize(mixer->internal_attributes, key, size);
1757 static HRESULT WINAPI video_mixer_attributes_GetBlob(IMFAttributes *iface, REFGUID key, UINT8 *buf,
1758 UINT32 bufsize, UINT32 *blobsize)
1760 struct video_mixer *mixer = impl_from_IMFAttributes(iface);
1762 TRACE("%p, %s, %p, %d, %p.\n", iface, debugstr_guid(key), buf, bufsize, blobsize);
1764 return IMFAttributes_GetBlob(mixer->internal_attributes, key, buf, bufsize, blobsize);
1767 static HRESULT WINAPI video_mixer_attributes_GetAllocatedBlob(IMFAttributes *iface, REFGUID key, UINT8 **buf, UINT32 *size)
1769 struct video_mixer *mixer = impl_from_IMFAttributes(iface);
1771 TRACE("%p, %s, %p, %p.\n", iface, debugstr_guid(key), buf, size);
1773 return IMFAttributes_GetAllocatedBlob(mixer->internal_attributes, key, buf, size);
1776 static HRESULT WINAPI video_mixer_attributes_GetUnknown(IMFAttributes *iface, REFGUID key, REFIID riid, void **out)
1778 struct video_mixer *mixer = impl_from_IMFAttributes(iface);
1780 TRACE("%p, %s, %s, %p.\n", iface, debugstr_guid(key), debugstr_guid(riid), out);
1782 return IMFAttributes_GetUnknown(mixer->internal_attributes, key, riid, out);
1785 static HRESULT WINAPI video_mixer_attributes_SetItem(IMFAttributes *iface, REFGUID key, REFPROPVARIANT value)
1787 struct video_mixer *mixer = impl_from_IMFAttributes(iface);
1789 TRACE("%p, %s, %p.\n", iface, debugstr_guid(key), value);
1791 return IMFAttributes_SetItem(mixer->internal_attributes, key, value);
1794 static HRESULT WINAPI video_mixer_attributes_DeleteItem(IMFAttributes *iface, REFGUID key)
1796 struct video_mixer *mixer = impl_from_IMFAttributes(iface);
1798 TRACE("%p, %s.\n", iface, debugstr_guid(key));
1800 return IMFAttributes_DeleteItem(mixer->internal_attributes, key);
1803 static HRESULT WINAPI video_mixer_attributes_DeleteAllItems(IMFAttributes *iface)
1805 struct video_mixer *mixer = impl_from_IMFAttributes(iface);
1807 TRACE("%p.\n", iface);
1809 return IMFAttributes_DeleteAllItems(mixer->internal_attributes);
1812 static HRESULT WINAPI video_mixer_attributes_SetUINT32(IMFAttributes *iface, REFGUID key, UINT32 value)
1814 struct video_mixer *mixer = impl_from_IMFAttributes(iface);
1816 TRACE("%p, %s, %u.\n", iface, debugstr_guid(key), value);
1818 return IMFAttributes_SetUINT32(mixer->internal_attributes, key, value);
1821 static HRESULT WINAPI video_mixer_attributes_SetUINT64(IMFAttributes *iface, REFGUID key, UINT64 value)
1823 struct video_mixer *mixer = impl_from_IMFAttributes(iface);
1825 TRACE("%p, %s, %s.\n", iface, debugstr_guid(key), wine_dbgstr_longlong(value));
1827 return IMFAttributes_SetUINT64(mixer->internal_attributes, key, value);
1830 static HRESULT WINAPI video_mixer_attributes_SetDouble(IMFAttributes *iface, REFGUID key, double value)
1832 struct video_mixer *mixer = impl_from_IMFAttributes(iface);
1834 TRACE("%p, %s, %f.\n", iface, debugstr_guid(key), value);
1836 return IMFAttributes_SetDouble(mixer->internal_attributes, key, value);
1839 static HRESULT WINAPI video_mixer_attributes_SetGUID(IMFAttributes *iface, REFGUID key, REFGUID value)
1841 struct video_mixer *mixer = impl_from_IMFAttributes(iface);
1843 TRACE("%p, %s, %s.\n", iface, debugstr_guid(key), debugstr_guid(value));
1845 return IMFAttributes_SetGUID(mixer->internal_attributes, key, value);
1848 static HRESULT WINAPI video_mixer_attributes_SetString(IMFAttributes *iface, REFGUID key, const WCHAR *value)
1850 struct video_mixer *mixer = impl_from_IMFAttributes(iface);
1852 TRACE("%p, %s, %s.\n", iface, debugstr_guid(key), debugstr_w(value));
1854 return IMFAttributes_SetString(mixer->internal_attributes, key, value);
1857 static HRESULT WINAPI video_mixer_attributes_SetBlob(IMFAttributes *iface, REFGUID key, const UINT8 *buf, UINT32 size)
1859 struct video_mixer *mixer = impl_from_IMFAttributes(iface);
1861 TRACE("%p, %s, %p, %u.\n", iface, debugstr_guid(key), buf, size);
1863 return IMFAttributes_SetBlob(mixer->internal_attributes, key, buf, size);
1866 static HRESULT WINAPI video_mixer_attributes_SetUnknown(IMFAttributes *iface, REFGUID key, IUnknown *unknown)
1868 struct video_mixer *mixer = impl_from_IMFAttributes(iface);
1870 TRACE("%p, %s, %p.\n", iface, debugstr_guid(key), unknown);
1872 return IMFAttributes_SetUnknown(mixer->internal_attributes, key, unknown);
1875 static HRESULT WINAPI video_mixer_attributes_LockStore(IMFAttributes *iface)
1877 struct video_mixer *mixer = impl_from_IMFAttributes(iface);
1879 TRACE("%p.\n", iface);
1881 return IMFAttributes_LockStore(mixer->internal_attributes);
1884 static HRESULT WINAPI video_mixer_attributes_UnlockStore(IMFAttributes *iface)
1886 struct video_mixer *mixer = impl_from_IMFAttributes(iface);
1888 TRACE("%p.\n", iface);
1890 return IMFAttributes_UnlockStore(mixer->internal_attributes);
1893 static HRESULT WINAPI video_mixer_attributes_GetCount(IMFAttributes *iface, UINT32 *count)
1895 struct video_mixer *mixer = impl_from_IMFAttributes(iface);
1897 TRACE("%p, %p.\n", iface, count);
1899 return IMFAttributes_GetCount(mixer->internal_attributes, count);
1902 static HRESULT WINAPI video_mixer_attributes_GetItemByIndex(IMFAttributes *iface, UINT32 index,
1903 GUID *key, PROPVARIANT *value)
1905 struct video_mixer *mixer = impl_from_IMFAttributes(iface);
1907 TRACE("%p, %u, %p, %p.\n", iface, index, key, value);
1909 return IMFAttributes_GetItemByIndex(mixer->internal_attributes, index, key, value);
1912 static HRESULT WINAPI video_mixer_attributes_CopyAllItems(IMFAttributes *iface, IMFAttributes *dest)
1914 struct video_mixer *mixer = impl_from_IMFAttributes(iface);
1916 TRACE("%p, %p.\n", iface, dest);
1918 return IMFAttributes_CopyAllItems(mixer->internal_attributes, dest);
1921 static const IMFAttributesVtbl video_mixer_attributes_vtbl =
1923 video_mixer_attributes_QueryInterface,
1924 video_mixer_attributes_AddRef,
1925 video_mixer_attributes_Release,
1926 video_mixer_attributes_GetItem,
1927 video_mixer_attributes_GetItemType,
1928 video_mixer_attributes_CompareItem,
1929 video_mixer_attributes_Compare,
1930 video_mixer_attributes_GetUINT32,
1931 video_mixer_attributes_GetUINT64,
1932 video_mixer_attributes_GetDouble,
1933 video_mixer_attributes_GetGUID,
1934 video_mixer_attributes_GetStringLength,
1935 video_mixer_attributes_GetString,
1936 video_mixer_attributes_GetAllocatedString,
1937 video_mixer_attributes_GetBlobSize,
1938 video_mixer_attributes_GetBlob,
1939 video_mixer_attributes_GetAllocatedBlob,
1940 video_mixer_attributes_GetUnknown,
1941 video_mixer_attributes_SetItem,
1942 video_mixer_attributes_DeleteItem,
1943 video_mixer_attributes_DeleteAllItems,
1944 video_mixer_attributes_SetUINT32,
1945 video_mixer_attributes_SetUINT64,
1946 video_mixer_attributes_SetDouble,
1947 video_mixer_attributes_SetGUID,
1948 video_mixer_attributes_SetString,
1949 video_mixer_attributes_SetBlob,
1950 video_mixer_attributes_SetUnknown,
1951 video_mixer_attributes_LockStore,
1952 video_mixer_attributes_UnlockStore,
1953 video_mixer_attributes_GetCount,
1954 video_mixer_attributes_GetItemByIndex,
1955 video_mixer_attributes_CopyAllItems
1958 static HRESULT WINAPI video_mixer_quality_advise_QueryInterface(IMFQualityAdvise *iface, REFIID riid, void **out)
1960 struct video_mixer *mixer = impl_from_IMFQualityAdvise(iface);
1961 return IMFTransform_QueryInterface(&mixer->IMFTransform_iface, riid, out);
1964 static ULONG WINAPI video_mixer_quality_advise_AddRef(IMFQualityAdvise *iface)
1966 struct video_mixer *mixer = impl_from_IMFQualityAdvise(iface);
1967 return IMFTransform_AddRef(&mixer->IMFTransform_iface);
1970 static ULONG WINAPI video_mixer_quality_Release(IMFQualityAdvise *iface)
1972 struct video_mixer *mixer = impl_from_IMFQualityAdvise(iface);
1973 return IMFTransform_Release(&mixer->IMFTransform_iface);
1976 static HRESULT WINAPI video_mixer_quality_advise_SetDropMode(IMFQualityAdvise *iface, MF_QUALITY_DROP_MODE mode)
1978 FIXME("%p, %u.\n", iface, mode);
1980 return E_NOTIMPL;
1983 static HRESULT WINAPI video_mixer_quality_advise_SetQualityLevel(IMFQualityAdvise *iface, MF_QUALITY_LEVEL level)
1985 FIXME("%p, %u.\n", iface, level);
1987 return E_NOTIMPL;
1990 static HRESULT WINAPI video_mixer_quality_advise_GetDropMode(IMFQualityAdvise *iface, MF_QUALITY_DROP_MODE *mode)
1992 FIXME("%p, %p.\n", iface, mode);
1994 return E_NOTIMPL;
1997 static HRESULT WINAPI video_mixer_quality_advise_GetQualityLevel(IMFQualityAdvise *iface, MF_QUALITY_LEVEL *level)
1999 FIXME("%p, %p.\n", iface, level);
2001 return E_NOTIMPL;
2004 static HRESULT WINAPI video_mixer_quality_advise_DropTime(IMFQualityAdvise *iface, LONGLONG interval)
2006 FIXME("%p, %s.\n", iface, wine_dbgstr_longlong(interval));
2008 return E_NOTIMPL;
2011 static const IMFQualityAdviseVtbl video_mixer_quality_advise_vtbl =
2013 video_mixer_quality_advise_QueryInterface,
2014 video_mixer_quality_advise_AddRef,
2015 video_mixer_quality_Release,
2016 video_mixer_quality_advise_SetDropMode,
2017 video_mixer_quality_advise_SetQualityLevel,
2018 video_mixer_quality_advise_GetDropMode,
2019 video_mixer_quality_advise_GetQualityLevel,
2020 video_mixer_quality_advise_DropTime,
2023 HRESULT WINAPI MFCreateVideoMixer(IUnknown *owner, REFIID riid_device, REFIID riid, void **obj)
2025 TRACE("%p, %s, %s, %p.\n", owner, debugstr_guid(riid_device), debugstr_guid(riid), obj);
2027 *obj = NULL;
2029 if (!IsEqualIID(riid_device, &IID_IDirect3DDevice9))
2030 return E_INVALIDARG;
2032 return CoCreateInstance(&CLSID_MFVideoMixer9, owner, CLSCTX_INPROC_SERVER, riid, obj);
2035 HRESULT evr_mixer_create(IUnknown *outer, void **out)
2037 struct video_mixer *object;
2038 MFVideoNormalizedRect rect;
2039 HRESULT hr;
2041 if (!(object = calloc(1, sizeof(*object))))
2042 return E_OUTOFMEMORY;
2044 object->IMFTransform_iface.lpVtbl = &video_mixer_transform_vtbl;
2045 object->IMFVideoDeviceID_iface.lpVtbl = &video_mixer_device_id_vtbl;
2046 object->IMFTopologyServiceLookupClient_iface.lpVtbl = &video_mixer_service_client_vtbl;
2047 object->IMFVideoMixerControl2_iface.lpVtbl = &video_mixer_control_vtbl;
2048 object->IMFGetService_iface.lpVtbl = &video_mixer_getservice_vtbl;
2049 object->IMFVideoMixerBitmap_iface.lpVtbl = &video_mixer_bitmap_vtbl;
2050 object->IMFVideoPositionMapper_iface.lpVtbl = &video_mixer_position_mapper_vtbl;
2051 object->IMFVideoProcessor_iface.lpVtbl = &video_mixer_processor_vtbl;
2052 object->IMFAttributes_iface.lpVtbl = &video_mixer_attributes_vtbl;
2053 object->IMFQualityAdvise_iface.lpVtbl = &video_mixer_quality_advise_vtbl;
2054 object->IUnknown_inner.lpVtbl = &video_mixer_inner_vtbl;
2055 object->outer_unk = outer ? outer : &object->IUnknown_inner;
2056 object->refcount = 1;
2057 object->input_count = 1;
2058 object->lower_bound = MFT_OUTPUT_BOUND_LOWER_UNBOUNDED;
2059 object->upper_bound = MFT_OUTPUT_BOUND_UPPER_UNBOUNDED;
2060 video_mixer_init_input(&object->inputs[0]);
2061 InitializeCriticalSection(&object->cs);
2062 if (FAILED(hr = MFCreateAttributes(&object->attributes, 0)))
2064 IUnknown_Release(&object->IUnknown_inner);
2065 return hr;
2067 if (FAILED(hr = MFCreateAttributes(&object->internal_attributes, 0)))
2069 IUnknown_Release(&object->IUnknown_inner);
2070 return hr;
2073 /* Default attributes configuration. */
2075 rect.left = rect.top = 0.0f;
2076 rect.right = rect.bottom = 1.0f;
2077 IMFAttributes_SetBlob(object->attributes, &VIDEO_ZOOM_RECT, (const UINT8 *)&rect, sizeof(rect));
2079 IMFAttributes_SetUINT32(object->internal_attributes, &MF_SA_D3D_AWARE, 1);
2081 *out = &object->IUnknown_inner;
2083 return S_OK;