2 * Copyright 2020 Nikolay Sivov
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2.1 of the License, or (at your option) any later version.
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
27 #include "evr_classes.h"
33 #include "wine/debug.h"
35 WINE_DEFAULT_DEBUG_CHANNEL(evr
);
37 #define MAX_MIXER_INPUT_STREAMS 16
42 IMFAttributes
*attributes
;
43 IMFMediaType
*media_type
;
44 MFVideoNormalizedRect rect
;
47 unsigned int sample_requested
: 1;
54 IMFMediaType
*media_type
;
59 IMFMediaType
*media_type
;
60 struct rt_format
*rt_formats
;
61 unsigned int rt_formats_count
;
66 IMFTransform IMFTransform_iface
;
67 IMFVideoDeviceID IMFVideoDeviceID_iface
;
68 IMFTopologyServiceLookupClient IMFTopologyServiceLookupClient_iface
;
69 IMFVideoMixerControl2 IMFVideoMixerControl2_iface
;
70 IMFGetService IMFGetService_iface
;
71 IMFVideoMixerBitmap IMFVideoMixerBitmap_iface
;
72 IMFVideoPositionMapper IMFVideoPositionMapper_iface
;
73 IMFVideoProcessor IMFVideoProcessor_iface
;
74 IMFAttributes IMFAttributes_iface
;
75 IMFQualityAdvise IMFQualityAdvise_iface
;
76 IMFClockStateSink IMFClockStateSink_iface
;
77 IUnknown IUnknown_inner
;
81 struct input_stream inputs
[MAX_MIXER_INPUT_STREAMS
];
82 unsigned int input_ids
[MAX_MIXER_INPUT_STREAMS
];
83 unsigned int input_count
;
84 struct output_stream output
;
86 IDirect3DDeviceManager9
*device_manager
;
87 IDirectXVideoProcessor
*processor
;
90 IMediaEventSink
*event_sink
;
91 IMFAttributes
*attributes
;
92 IMFAttributes
*internal_attributes
;
93 unsigned int mixing_flags
;
94 unsigned int is_streaming
;
101 static struct video_mixer
*impl_from_IUnknown(IUnknown
*iface
)
103 return CONTAINING_RECORD(iface
, struct video_mixer
, IUnknown_inner
);
106 static struct video_mixer
*impl_from_IMFTransform(IMFTransform
*iface
)
108 return CONTAINING_RECORD(iface
, struct video_mixer
, IMFTransform_iface
);
111 static struct video_mixer
*impl_from_IMFVideoDeviceID(IMFVideoDeviceID
*iface
)
113 return CONTAINING_RECORD(iface
, struct video_mixer
, IMFVideoDeviceID_iface
);
116 static struct video_mixer
*impl_from_IMFTopologyServiceLookupClient(IMFTopologyServiceLookupClient
*iface
)
118 return CONTAINING_RECORD(iface
, struct video_mixer
, IMFTopologyServiceLookupClient_iface
);
121 static struct video_mixer
*impl_from_IMFVideoMixerControl2(IMFVideoMixerControl2
*iface
)
123 return CONTAINING_RECORD(iface
, struct video_mixer
, IMFVideoMixerControl2_iface
);
126 static struct video_mixer
*impl_from_IMFGetService(IMFGetService
*iface
)
128 return CONTAINING_RECORD(iface
, struct video_mixer
, IMFGetService_iface
);
131 static struct video_mixer
*impl_from_IMFVideoMixerBitmap(IMFVideoMixerBitmap
*iface
)
133 return CONTAINING_RECORD(iface
, struct video_mixer
, IMFVideoMixerBitmap_iface
);
136 static struct video_mixer
*impl_from_IMFVideoPositionMapper(IMFVideoPositionMapper
*iface
)
138 return CONTAINING_RECORD(iface
, struct video_mixer
, IMFVideoPositionMapper_iface
);
141 static struct video_mixer
*impl_from_IMFVideoProcessor(IMFVideoProcessor
*iface
)
143 return CONTAINING_RECORD(iface
, struct video_mixer
, IMFVideoProcessor_iface
);
146 static struct video_mixer
*impl_from_IMFAttributes(IMFAttributes
*iface
)
148 return CONTAINING_RECORD(iface
, struct video_mixer
, IMFAttributes_iface
);
151 static struct video_mixer
*impl_from_IMFQualityAdvise(IMFQualityAdvise
*iface
)
153 return CONTAINING_RECORD(iface
, struct video_mixer
, IMFQualityAdvise_iface
);
156 static struct video_mixer
*impl_from_IMFClockStateSink(IMFClockStateSink
*iface
)
158 return CONTAINING_RECORD(iface
, struct video_mixer
, IMFClockStateSink_iface
);
161 static int __cdecl
video_mixer_compare_input_id(const void *a
, const void *b
)
163 const unsigned int *key
= a
;
164 const struct input_stream
*input
= b
;
166 if (*key
> input
->id
) return 1;
167 if (*key
< input
->id
) return -1;
171 static HRESULT
video_mixer_get_input(const struct video_mixer
*mixer
, unsigned int id
, struct input_stream
**stream
)
173 *stream
= bsearch(&id
, mixer
->inputs
, mixer
->input_count
, sizeof(*mixer
->inputs
), video_mixer_compare_input_id
);
174 return *stream
? S_OK
: MF_E_INVALIDSTREAMNUMBER
;
177 static void video_mixer_init_input(struct input_stream
*stream
)
179 if (SUCCEEDED(MFCreateAttributes(&stream
->attributes
, 1)))
180 IMFAttributes_SetUINT32(stream
->attributes
, &MF_SA_REQUIRED_SAMPLE_COUNT
, 1);
181 stream
->rect
.left
= stream
->rect
.top
= 0.0f
;
182 stream
->rect
.right
= stream
->rect
.bottom
= 1.0f
;
185 static void video_mixer_clear_types(struct video_mixer
*mixer
)
189 for (i
= 0; i
< mixer
->input_count
; ++i
)
191 if (mixer
->inputs
[i
].media_type
)
192 IMFMediaType_Release(mixer
->inputs
[i
].media_type
);
193 mixer
->inputs
[i
].media_type
= NULL
;
194 if (mixer
->inputs
[i
].sample
)
195 IMFSample_Release(mixer
->inputs
[i
].sample
);
196 mixer
->inputs
[i
].sample
= NULL
;
198 for (i
= 0; i
< mixer
->output
.rt_formats_count
; ++i
)
200 IMFMediaType_Release(mixer
->output
.rt_formats
[i
].media_type
);
202 free(mixer
->output
.rt_formats
);
203 if (mixer
->output
.media_type
)
204 IMFMediaType_Release(mixer
->output
.media_type
);
205 mixer
->output
.media_type
= NULL
;
208 static HRESULT WINAPI
video_mixer_inner_QueryInterface(IUnknown
*iface
, REFIID riid
, void **obj
)
210 struct video_mixer
*mixer
= impl_from_IUnknown(iface
);
212 TRACE("%p, %s, %p.\n", iface
, debugstr_guid(riid
), obj
);
214 if (IsEqualIID(riid
, &IID_IUnknown
))
218 else if (IsEqualIID(riid
, &IID_IMFTransform
))
220 *obj
= &mixer
->IMFTransform_iface
;
222 else if (IsEqualIID(riid
, &IID_IMFVideoDeviceID
))
224 *obj
= &mixer
->IMFVideoDeviceID_iface
;
226 else if (IsEqualIID(riid
, &IID_IMFTopologyServiceLookupClient
))
228 *obj
= &mixer
->IMFTopologyServiceLookupClient_iface
;
230 else if (IsEqualIID(riid
, &IID_IMFVideoMixerControl2
) ||
231 IsEqualIID(riid
, &IID_IMFVideoMixerControl
))
233 *obj
= &mixer
->IMFVideoMixerControl2_iface
;
235 else if (IsEqualIID(riid
, &IID_IMFGetService
))
237 *obj
= &mixer
->IMFGetService_iface
;
239 else if (IsEqualIID(riid
, &IID_IMFVideoMixerBitmap
))
241 *obj
= &mixer
->IMFVideoMixerBitmap_iface
;
243 else if (IsEqualIID(riid
, &IID_IMFVideoPositionMapper
))
245 *obj
= &mixer
->IMFVideoPositionMapper_iface
;
247 else if (IsEqualIID(riid
, &IID_IMFVideoProcessor
))
249 *obj
= &mixer
->IMFVideoProcessor_iface
;
251 else if (IsEqualIID(riid
, &IID_IMFAttributes
))
253 *obj
= &mixer
->IMFAttributes_iface
;
255 else if (IsEqualIID(riid
, &IID_IMFQualityAdvise
))
257 *obj
= &mixer
->IMFQualityAdvise_iface
;
259 else if (IsEqualIID(riid
, &IID_IMFClockStateSink
))
261 *obj
= &mixer
->IMFClockStateSink_iface
;
265 WARN("Unsupported interface %s.\n", debugstr_guid(riid
));
267 return E_NOINTERFACE
;
270 IUnknown_AddRef((IUnknown
*)*obj
);
274 static ULONG WINAPI
video_mixer_inner_AddRef(IUnknown
*iface
)
276 struct video_mixer
*mixer
= impl_from_IUnknown(iface
);
277 ULONG refcount
= InterlockedIncrement(&mixer
->refcount
);
279 TRACE("%p, refcount %u.\n", iface
, refcount
);
284 static void video_mixer_release_device_manager(struct video_mixer
*mixer
)
286 if (mixer
->processor
)
287 IDirectXVideoProcessor_Release(mixer
->processor
);
288 if (mixer
->device_manager
)
290 IDirect3DDeviceManager9_CloseDeviceHandle(mixer
->device_manager
, mixer
->device_handle
);
291 IDirect3DDeviceManager9_Release(mixer
->device_manager
);
293 mixer
->device_handle
= NULL
;
294 mixer
->device_manager
= NULL
;
295 mixer
->processor
= NULL
;
298 static ULONG WINAPI
video_mixer_inner_Release(IUnknown
*iface
)
300 struct video_mixer
*mixer
= impl_from_IUnknown(iface
);
301 ULONG refcount
= InterlockedDecrement(&mixer
->refcount
);
304 TRACE("%p, refcount %u.\n", iface
, refcount
);
308 for (i
= 0; i
< mixer
->input_count
; ++i
)
310 if (mixer
->inputs
[i
].attributes
)
311 IMFAttributes_Release(mixer
->inputs
[i
].attributes
);
313 video_mixer_clear_types(mixer
);
314 video_mixer_release_device_manager(mixer
);
315 if (mixer
->attributes
)
316 IMFAttributes_Release(mixer
->attributes
);
317 if (mixer
->internal_attributes
)
318 IMFAttributes_Release(mixer
->internal_attributes
);
319 DeleteCriticalSection(&mixer
->cs
);
326 static const IUnknownVtbl video_mixer_inner_vtbl
=
328 video_mixer_inner_QueryInterface
,
329 video_mixer_inner_AddRef
,
330 video_mixer_inner_Release
,
333 static HRESULT WINAPI
video_mixer_transform_QueryInterface(IMFTransform
*iface
, REFIID riid
, void **obj
)
335 struct video_mixer
*mixer
= impl_from_IMFTransform(iface
);
336 return IUnknown_QueryInterface(mixer
->outer_unk
, riid
, obj
);
339 static ULONG WINAPI
video_mixer_transform_AddRef(IMFTransform
*iface
)
341 struct video_mixer
*mixer
= impl_from_IMFTransform(iface
);
342 return IUnknown_AddRef(mixer
->outer_unk
);
345 static ULONG WINAPI
video_mixer_transform_Release(IMFTransform
*iface
)
347 struct video_mixer
*mixer
= impl_from_IMFTransform(iface
);
348 return IUnknown_Release(mixer
->outer_unk
);
351 static HRESULT WINAPI
video_mixer_transform_GetStreamLimits(IMFTransform
*iface
, DWORD
*input_minimum
,
352 DWORD
*input_maximum
, DWORD
*output_minimum
, DWORD
*output_maximum
)
354 TRACE("%p, %p, %p, %p, %p.\n", iface
, input_minimum
, input_maximum
, output_minimum
, output_maximum
);
357 *input_maximum
= MAX_MIXER_INPUT_STREAMS
;
364 static HRESULT WINAPI
video_mixer_transform_GetStreamCount(IMFTransform
*iface
, DWORD
*inputs
, DWORD
*outputs
)
366 struct video_mixer
*mixer
= impl_from_IMFTransform(iface
);
368 TRACE("%p, %p, %p.\n", iface
, inputs
, outputs
);
370 EnterCriticalSection(&mixer
->cs
);
371 if (inputs
) *inputs
= mixer
->input_count
;
372 if (outputs
) *outputs
= 1;
373 LeaveCriticalSection(&mixer
->cs
);
378 static HRESULT WINAPI
video_mixer_transform_GetStreamIDs(IMFTransform
*iface
, DWORD input_size
, DWORD
*inputs
,
379 DWORD output_size
, DWORD
*outputs
)
381 struct video_mixer
*mixer
= impl_from_IMFTransform(iface
);
384 TRACE("%p, %u, %p, %u, %p.\n", iface
, input_size
, inputs
, output_size
, outputs
);
386 EnterCriticalSection(&mixer
->cs
);
387 if (mixer
->input_count
> input_size
|| !output_size
)
388 hr
= MF_E_BUFFERTOOSMALL
;
390 memcpy(inputs
, mixer
->input_ids
, mixer
->input_count
* sizeof(*inputs
));
391 if (outputs
) *outputs
= 0;
392 LeaveCriticalSection(&mixer
->cs
);
397 static HRESULT WINAPI
video_mixer_transform_GetInputStreamInfo(IMFTransform
*iface
, DWORD id
, MFT_INPUT_STREAM_INFO
*info
)
399 struct video_mixer
*mixer
= impl_from_IMFTransform(iface
);
400 struct input_stream
*input
;
403 TRACE("%p, %u, %p.\n", iface
, id
, info
);
405 EnterCriticalSection(&mixer
->cs
);
407 if (SUCCEEDED(hr
= video_mixer_get_input(mixer
, id
, &input
)))
409 memset(info
, 0, sizeof(*info
));
411 info
->dwFlags
|= MFT_INPUT_STREAM_REMOVABLE
| MFT_INPUT_STREAM_OPTIONAL
;
414 LeaveCriticalSection(&mixer
->cs
);
419 static HRESULT WINAPI
video_mixer_transform_GetOutputStreamInfo(IMFTransform
*iface
, DWORD id
, MFT_OUTPUT_STREAM_INFO
*info
)
421 TRACE("%p, %u, %p.\n", iface
, id
, info
);
424 return MF_E_INVALIDSTREAMNUMBER
;
426 memset(info
, 0, sizeof(*info
));
431 static HRESULT WINAPI
video_mixer_transform_GetAttributes(IMFTransform
*iface
, IMFAttributes
**attributes
)
433 struct video_mixer
*mixer
= impl_from_IMFTransform(iface
);
435 TRACE("%p, %p.\n", iface
, attributes
);
440 *attributes
= mixer
->attributes
;
441 IMFAttributes_AddRef(*attributes
);
446 static HRESULT WINAPI
video_mixer_transform_GetInputStreamAttributes(IMFTransform
*iface
, DWORD id
,
447 IMFAttributes
**attributes
)
449 struct video_mixer
*mixer
= impl_from_IMFTransform(iface
);
450 struct input_stream
*input
;
453 TRACE("%p, %u, %p.\n", iface
, id
, attributes
);
455 EnterCriticalSection(&mixer
->cs
);
457 if (SUCCEEDED(hr
= video_mixer_get_input(mixer
, id
, &input
)))
459 *attributes
= input
->attributes
;
461 IMFAttributes_AddRef(*attributes
);
464 LeaveCriticalSection(&mixer
->cs
);
469 static HRESULT WINAPI
video_mixer_transform_GetOutputStreamAttributes(IMFTransform
*iface
, DWORD id
,
470 IMFAttributes
**attributes
)
472 TRACE("%p, %u, %p.\n", iface
, id
, attributes
);
477 static HRESULT WINAPI
video_mixer_transform_DeleteInputStream(IMFTransform
*iface
, DWORD id
)
479 struct video_mixer
*mixer
= impl_from_IMFTransform(iface
);
480 struct input_stream
*input
;
484 TRACE("%p, %u.\n", iface
, id
);
487 return MF_E_INVALIDSTREAMNUMBER
;
489 EnterCriticalSection(&mixer
->cs
);
491 /* Can't delete reference stream. */
492 if (SUCCEEDED(hr
= video_mixer_get_input(mixer
, id
, &input
)))
494 mixer
->input_count
--;
495 idx
= input
- mixer
->inputs
;
496 if (idx
< mixer
->input_count
)
498 if (mixer
->inputs
[idx
].attributes
)
499 IMFAttributes_Release(mixer
->inputs
[idx
].attributes
);
500 memmove(&mixer
->inputs
[idx
], &mixer
->inputs
[idx
+ 1], (mixer
->input_count
- idx
) * sizeof(*mixer
->inputs
));
501 memmove(&mixer
->input_ids
[idx
], &mixer
->input_ids
[idx
+ 1], (mixer
->input_count
- idx
) *
502 sizeof(*mixer
->input_ids
));
506 LeaveCriticalSection(&mixer
->cs
);
511 static int __cdecl
video_mixer_add_input_sort_compare(const void *a
, const void *b
)
513 const struct input_stream
*left
= a
, *right
= b
;
514 return left
->id
!= right
->id
? (left
->id
< right
->id
? -1 : 1) : 0;
517 static HRESULT WINAPI
video_mixer_transform_AddInputStreams(IMFTransform
*iface
, DWORD count
, DWORD
*ids
)
519 struct video_mixer
*mixer
= impl_from_IMFTransform(iface
);
520 struct input_stream inputs
[MAX_MIXER_INPUT_STREAMS
] = { {0} };
521 struct input_stream
*input
;
525 TRACE("%p, %u, %p.\n", iface
, count
, ids
);
530 EnterCriticalSection(&mixer
->cs
);
531 if (count
> ARRAY_SIZE(mixer
->inputs
) - mixer
->input_count
)
535 /* Test for collisions. */
536 memcpy(inputs
, mixer
->inputs
, mixer
->input_count
* sizeof(*inputs
));
537 for (i
= 0; i
< count
; ++i
)
538 inputs
[i
+ mixer
->input_count
].id
= ids
[i
];
540 len
= mixer
->input_count
+ count
;
542 qsort(inputs
, len
, sizeof(*inputs
), video_mixer_add_input_sort_compare
);
544 for (i
= 1; i
< len
; ++i
)
546 if (inputs
[i
- 1].id
== inputs
[i
].id
)
555 unsigned int zorder
= mixer
->input_count
;
557 for (i
= 0; i
< count
; ++i
)
559 if ((input
= bsearch(&ids
[i
], inputs
, len
, sizeof(*inputs
), video_mixer_compare_input_id
)))
560 video_mixer_init_input(input
);
562 memcpy(&mixer
->input_ids
[mixer
->input_count
], ids
, count
* sizeof(*ids
));
563 memcpy(mixer
->inputs
, inputs
, len
* sizeof(*inputs
));
564 mixer
->input_count
+= count
;
566 for (i
= 0; i
< count
; ++i
)
568 if (SUCCEEDED(video_mixer_get_input(mixer
, ids
[i
], &input
)))
569 input
->zorder
= zorder
;
574 LeaveCriticalSection(&mixer
->cs
);
579 static HRESULT WINAPI
video_mixer_transform_GetInputAvailableType(IMFTransform
*iface
, DWORD id
, DWORD index
,
582 TRACE("%p, %u, %u, %p.\n", iface
, id
, index
, type
);
587 static HRESULT WINAPI
video_mixer_transform_GetOutputAvailableType(IMFTransform
*iface
, DWORD id
, DWORD index
,
590 struct video_mixer
*mixer
= impl_from_IMFTransform(iface
);
593 TRACE("%p, %u, %u, %p.\n", iface
, id
, index
, type
);
596 return MF_E_INVALIDSTREAMNUMBER
;
598 EnterCriticalSection(&mixer
->cs
);
600 if (!mixer
->inputs
[0].media_type
)
601 hr
= MF_E_TRANSFORM_TYPE_NOT_SET
;
602 else if (index
>= mixer
->output
.rt_formats_count
)
603 hr
= MF_E_NO_MORE_TYPES
;
606 if (SUCCEEDED(hr
= MFCreateMediaType(type
)))
607 hr
= IMFMediaType_CopyAllItems(mixer
->output
.rt_formats
[index
].media_type
, (IMFAttributes
*)*type
);
610 LeaveCriticalSection(&mixer
->cs
);
615 static HRESULT
video_mixer_init_dxva_videodesc(IMFMediaType
*media_type
, DXVA2_VideoDesc
*video_desc
)
617 const MFVIDEOFORMAT
*video_format
;
618 IMFVideoMediaType
*video_type
;
619 BOOL is_compressed
= TRUE
;
622 if (FAILED(IMFMediaType_QueryInterface(media_type
, &IID_IMFVideoMediaType
, (void **)&video_type
)))
623 return MF_E_INVALIDMEDIATYPE
;
625 video_format
= IMFVideoMediaType_GetVideoFormat(video_type
);
626 IMFVideoMediaType_IsCompressedFormat(video_type
, &is_compressed
);
628 if (!video_format
|| !video_format
->videoInfo
.dwWidth
|| !video_format
->videoInfo
.dwHeight
|| is_compressed
)
630 hr
= MF_E_INVALIDMEDIATYPE
;
634 memset(video_desc
, 0, sizeof(*video_desc
));
635 video_desc
->SampleWidth
= video_format
->videoInfo
.dwWidth
;
636 video_desc
->SampleHeight
= video_format
->videoInfo
.dwHeight
;
637 video_desc
->Format
= video_format
->surfaceInfo
.Format
;
640 IMFVideoMediaType_Release(video_type
);
645 static void video_mixer_append_rt_format(struct rt_format
*rt_formats
, unsigned int *count
,
646 const GUID
*device
, D3DFORMAT format
)
650 for (i
= 0; i
< *count
; ++i
)
652 if (rt_formats
[i
].format
== format
) return;
655 rt_formats
[*count
].format
= format
;
656 rt_formats
[*count
].device
= *device
;
660 static unsigned int video_mixer_get_interlace_mode_from_video_desc(const DXVA2_VideoDesc
*video_desc
)
662 switch (video_desc
->SampleFormat
.SampleFormat
)
664 case DXVA2_SampleFieldInterleavedEvenFirst
:
665 return MFVideoInterlace_FieldInterleavedUpperFirst
;
666 case DXVA2_SampleFieldInterleavedOddFirst
:
667 return MFVideoInterlace_FieldInterleavedLowerFirst
;
668 case DXVA2_SampleFieldSingleEven
:
669 return MFVideoInterlace_FieldSingleUpper
;
670 case DXVA2_SampleFieldSingleOdd
:
671 return MFVideoInterlace_FieldSingleLower
;
673 return MFVideoInterlace_Progressive
;
677 static HRESULT
video_mixer_collect_output_types(struct video_mixer
*mixer
, const DXVA2_VideoDesc
*video_desc
,
678 IMFMediaType
*media_type
, IDirectXVideoProcessorService
*service
, unsigned int device_count
,
679 const GUID
*devices
, unsigned int flags
)
681 unsigned int i
, j
, format_count
, count
, interlace_mode
;
682 struct rt_format
*rt_formats
= NULL
, *ptr
;
683 HRESULT hr
= MF_E_INVALIDMEDIATYPE
;
684 MFVideoArea aperture
;
689 for (i
= 0; i
< device_count
; ++i
)
691 if (SUCCEEDED(IDirectXVideoProcessorService_GetVideoProcessorRenderTargets(service
, &devices
[i
], video_desc
,
692 &format_count
, &formats
)))
694 if (!(ptr
= realloc(rt_formats
, (count
+ format_count
) * sizeof(*rt_formats
))))
698 CoTaskMemFree(formats
);
703 for (j
= 0; j
< format_count
; ++j
)
704 video_mixer_append_rt_format(rt_formats
, &count
, &devices
[i
], formats
[j
]);
706 CoTaskMemFree(formats
);
710 if (count
&& !(flags
& MFT_SET_TYPE_TEST_ONLY
))
712 if (!(mixer
->output
.rt_formats
= calloc(count
, sizeof(*mixer
->output
.rt_formats
))))
715 return E_OUTOFMEMORY
;
718 memcpy(&subtype
, &MFVideoFormat_Base
, sizeof(subtype
));
719 memset(&aperture
, 0, sizeof(aperture
));
720 aperture
.Area
.cx
= video_desc
->SampleWidth
;
721 aperture
.Area
.cy
= video_desc
->SampleHeight
;
722 interlace_mode
= video_mixer_get_interlace_mode_from_video_desc(video_desc
);
723 for (i
= 0; i
< count
; ++i
)
725 IMFMediaType
*rt_media_type
;
727 subtype
.Data1
= rt_formats
[i
].format
;
728 mixer
->output
.rt_formats
[i
] = rt_formats
[i
];
730 MFCreateMediaType(&rt_media_type
);
731 IMFMediaType_CopyAllItems(media_type
, (IMFAttributes
*)rt_media_type
);
732 IMFMediaType_SetGUID(rt_media_type
, &MF_MT_SUBTYPE
, &subtype
);
733 IMFMediaType_SetBlob(rt_media_type
, &MF_MT_GEOMETRIC_APERTURE
, (const UINT8
*)&aperture
, sizeof(aperture
));
734 IMFMediaType_SetBlob(rt_media_type
, &MF_MT_MINIMUM_DISPLAY_APERTURE
, (const UINT8
*)&aperture
, sizeof(aperture
));
735 IMFMediaType_SetUINT32(rt_media_type
, &MF_MT_INTERLACE_MODE
, interlace_mode
);
737 mixer
->output
.rt_formats
[i
].media_type
= rt_media_type
;
739 mixer
->output
.rt_formats_count
= count
;
744 return count
? S_OK
: hr
;
747 static HRESULT
video_mixer_open_device_handle(struct video_mixer
*mixer
)
749 IDirect3DDeviceManager9_CloseDeviceHandle(mixer
->device_manager
, mixer
->device_handle
);
750 mixer
->device_handle
= NULL
;
751 return IDirect3DDeviceManager9_OpenDeviceHandle(mixer
->device_manager
, &mixer
->device_handle
);
754 static HRESULT
video_mixer_get_processor_service(struct video_mixer
*mixer
, IDirectXVideoProcessorService
**service
)
758 if (!mixer
->device_handle
)
760 if (FAILED(hr
= IDirect3DDeviceManager9_OpenDeviceHandle(mixer
->device_manager
, &mixer
->device_handle
)))
766 hr
= IDirect3DDeviceManager9_GetVideoService(mixer
->device_manager
, mixer
->device_handle
,
767 &IID_IDirectXVideoProcessorService
, (void **)service
);
768 if (hr
== DXVA2_E_NEW_VIDEO_DEVICE
)
770 if (SUCCEEDED(hr
= video_mixer_open_device_handle(mixer
)))
779 static HRESULT WINAPI
video_mixer_transform_SetInputType(IMFTransform
*iface
, DWORD id
, IMFMediaType
*media_type
, DWORD flags
)
781 struct video_mixer
*mixer
= impl_from_IMFTransform(iface
);
782 IDirectXVideoProcessorService
*service
;
783 DXVA2_VideoDesc video_desc
;
784 HRESULT hr
= E_NOTIMPL
;
788 TRACE("%p, %u, %p, %#x.\n", iface
, id
, media_type
, flags
);
790 EnterCriticalSection(&mixer
->cs
);
792 if (!(flags
& MFT_SET_TYPE_TEST_ONLY
))
793 video_mixer_clear_types(mixer
);
795 if (!mixer
->device_manager
)
796 hr
= MF_E_NOT_INITIALIZED
;
799 if (SUCCEEDED(hr
= video_mixer_get_processor_service(mixer
, &service
)))
801 if (SUCCEEDED(hr
= video_mixer_init_dxva_videodesc(media_type
, &video_desc
)))
805 if (SUCCEEDED(hr
= IDirectXVideoProcessorService_GetVideoProcessorDeviceGuids(service
, &video_desc
,
808 if (SUCCEEDED(hr
= video_mixer_collect_output_types(mixer
, &video_desc
, media_type
,
809 service
, count
, guids
, flags
)) && !(flags
& MFT_SET_TYPE_TEST_ONLY
))
811 if (mixer
->inputs
[0].media_type
)
812 IMFMediaType_Release(mixer
->inputs
[0].media_type
);
813 mixer
->inputs
[0].media_type
= media_type
;
814 IMFMediaType_AddRef(mixer
->inputs
[0].media_type
);
816 CoTaskMemFree(guids
);
821 FIXME("Unimplemented for substreams.\n");
825 IDirectXVideoProcessorService_Release(service
);
829 LeaveCriticalSection(&mixer
->cs
);
834 static HRESULT WINAPI
video_mixer_transform_SetOutputType(IMFTransform
*iface
, DWORD id
, IMFMediaType
*type
, DWORD flags
)
836 const unsigned int equality_flags
= MF_MEDIATYPE_EQUAL_MAJOR_TYPES
| MF_MEDIATYPE_EQUAL_FORMAT_TYPES
;
837 struct video_mixer
*mixer
= impl_from_IMFTransform(iface
);
838 HRESULT hr
= MF_E_INVALIDMEDIATYPE
;
839 unsigned int i
, compare_flags
;
840 BOOL is_compressed
= TRUE
;
842 TRACE("%p, %u, %p, %#x.\n", iface
, id
, type
, flags
);
845 return MF_E_INVALIDSTREAMNUMBER
;
850 if (FAILED(IMFMediaType_IsCompressedFormat(type
, &is_compressed
)) || is_compressed
)
851 return MF_E_INVALIDMEDIATYPE
;
853 EnterCriticalSection(&mixer
->cs
);
855 for (i
= 0; i
< mixer
->output
.rt_formats_count
; ++i
)
858 if (FAILED(IMFMediaType_IsEqual(type
, mixer
->output
.rt_formats
[i
].media_type
, &compare_flags
)))
861 if ((compare_flags
& equality_flags
) == equality_flags
)
868 if (SUCCEEDED(hr
) && !(flags
& MFT_SET_TYPE_TEST_ONLY
))
870 IDirectXVideoProcessorService
*service
;
872 if (SUCCEEDED(hr
= video_mixer_get_processor_service(mixer
, &service
)))
874 DXVA2_VideoDesc video_desc
;
875 GUID subtype
= { 0 };
878 if (mixer
->processor
)
879 IDirectXVideoProcessor_Release(mixer
->processor
);
880 mixer
->processor
= NULL
;
882 video_mixer_init_dxva_videodesc(mixer
->inputs
[0].media_type
, &video_desc
);
883 IMFMediaType_GetGUID(type
, &MF_MT_SUBTYPE
, &subtype
);
884 rt_format
= subtype
.Data1
;
886 if (SUCCEEDED(hr
= IDirectXVideoProcessorService_CreateVideoProcessor(service
, &mixer
->output
.rt_formats
[i
].device
,
887 &video_desc
, rt_format
, MAX_MIXER_INPUT_STREAMS
, &mixer
->processor
)))
889 if (mixer
->output
.media_type
)
890 IMFMediaType_Release(mixer
->output
.media_type
);
891 mixer
->output
.media_type
= type
;
892 IMFMediaType_AddRef(mixer
->output
.media_type
);
895 IDirectXVideoProcessorService_Release(service
);
899 LeaveCriticalSection(&mixer
->cs
);
904 static HRESULT WINAPI
video_mixer_transform_GetInputCurrentType(IMFTransform
*iface
, DWORD id
, IMFMediaType
**type
)
906 struct video_mixer
*mixer
= impl_from_IMFTransform(iface
);
907 struct input_stream
*stream
;
910 TRACE("%p, %u, %p.\n", iface
, id
, type
);
912 EnterCriticalSection(&mixer
->cs
);
914 if (SUCCEEDED(hr
= video_mixer_get_input(mixer
, id
, &stream
)))
916 if (!stream
->media_type
)
917 hr
= MF_E_TRANSFORM_TYPE_NOT_SET
;
920 *type
= stream
->media_type
;
921 IMFMediaType_AddRef(*type
);
925 LeaveCriticalSection(&mixer
->cs
);
930 static HRESULT WINAPI
video_mixer_transform_GetOutputCurrentType(IMFTransform
*iface
, DWORD id
, IMFMediaType
**type
)
932 struct video_mixer
*mixer
= impl_from_IMFTransform(iface
);
935 TRACE("%p, %u, %p.\n", iface
, id
, type
);
938 return MF_E_INVALIDSTREAMNUMBER
;
940 EnterCriticalSection(&mixer
->cs
);
942 if (!mixer
->output
.media_type
)
943 hr
= MF_E_TRANSFORM_TYPE_NOT_SET
;
946 *type
= mixer
->output
.media_type
;
947 IMFMediaType_AddRef(*type
);
950 LeaveCriticalSection(&mixer
->cs
);
955 static HRESULT WINAPI
video_mixer_transform_GetInputStatus(IMFTransform
*iface
, DWORD id
, DWORD
*status
)
957 struct video_mixer
*mixer
= impl_from_IMFTransform(iface
);
958 struct input_stream
*stream
;
961 TRACE("%p, %u, %p.\n", iface
, id
, status
);
966 EnterCriticalSection(&mixer
->cs
);
968 if (!mixer
->output
.media_type
)
969 hr
= MF_E_TRANSFORM_TYPE_NOT_SET
;
970 else if (SUCCEEDED(hr
= video_mixer_get_input(mixer
, id
, &stream
)))
972 *status
= stream
->sample
? 0 : MFT_INPUT_STATUS_ACCEPT_DATA
;
975 LeaveCriticalSection(&mixer
->cs
);
980 static HRESULT WINAPI
video_mixer_transform_GetOutputStatus(IMFTransform
*iface
, DWORD
*status
)
982 struct video_mixer
*mixer
= impl_from_IMFTransform(iface
);
986 TRACE("%p, %p.\n", iface
, status
);
991 EnterCriticalSection(&mixer
->cs
);
993 if (!mixer
->output
.media_type
)
994 hr
= MF_E_TRANSFORM_TYPE_NOT_SET
;
997 *status
= MFT_OUTPUT_STATUS_SAMPLE_READY
;
998 for (i
= 0; i
< mixer
->input_count
; ++i
)
1000 if (!mixer
->inputs
[i
].sample
)
1008 LeaveCriticalSection(&mixer
->cs
);
1013 static HRESULT WINAPI
video_mixer_transform_SetOutputBounds(IMFTransform
*iface
, LONGLONG lower
, LONGLONG upper
)
1015 struct video_mixer
*mixer
= impl_from_IMFTransform(iface
);
1017 TRACE("%p, %s, %s.\n", iface
, wine_dbgstr_longlong(lower
), wine_dbgstr_longlong(upper
));
1019 EnterCriticalSection(&mixer
->cs
);
1021 mixer
->lower_bound
= lower
;
1022 mixer
->upper_bound
= upper
;
1024 LeaveCriticalSection(&mixer
->cs
);
1029 static HRESULT WINAPI
video_mixer_transform_ProcessEvent(IMFTransform
*iface
, DWORD id
, IMFMediaEvent
*event
)
1031 FIXME("%p, %u, %p.\n", iface
, id
, event
);
1036 static void video_mixer_request_sample(struct video_mixer
*mixer
, unsigned int idx
)
1038 if (!mixer
->event_sink
|| mixer
->inputs
[idx
].sample_requested
)
1041 IMediaEventSink_Notify(mixer
->event_sink
, EC_SAMPLE_NEEDED
, idx
, 0);
1042 mixer
->inputs
[idx
].sample_requested
= 1;
1045 static HRESULT WINAPI
video_mixer_transform_ProcessMessage(IMFTransform
*iface
, MFT_MESSAGE_TYPE message
, ULONG_PTR param
)
1047 struct video_mixer
*mixer
= impl_from_IMFTransform(iface
);
1051 TRACE("%p, %#x, %#lx.\n", iface
, message
, param
);
1055 case MFT_MESSAGE_SET_D3D_MANAGER
:
1057 EnterCriticalSection(&mixer
->cs
);
1059 video_mixer_release_device_manager(mixer
);
1061 hr
= IUnknown_QueryInterface((IUnknown
*)param
, &IID_IDirect3DDeviceManager9
, (void **)&mixer
->device_manager
);
1063 LeaveCriticalSection(&mixer
->cs
);
1067 case MFT_MESSAGE_COMMAND_FLUSH
:
1069 EnterCriticalSection(&mixer
->cs
);
1071 for (i
= 0; i
< mixer
->input_count
; ++i
)
1073 if (mixer
->inputs
[i
].sample
)
1075 IMFSample_Release(mixer
->inputs
[i
].sample
);
1076 mixer
->inputs
[i
].sample
= NULL
;
1077 mixer
->inputs
[i
].sample_requested
= 0;
1081 LeaveCriticalSection(&mixer
->cs
);
1085 case MFT_MESSAGE_NOTIFY_BEGIN_STREAMING
:
1086 case MFT_MESSAGE_NOTIFY_END_STREAMING
:
1088 EnterCriticalSection(&mixer
->cs
);
1090 if (!mixer
->is_streaming
)
1092 for (i
= 0; i
< mixer
->input_count
; ++i
)
1093 video_mixer_request_sample(mixer
, i
);
1096 mixer
->is_streaming
= message
== MFT_MESSAGE_NOTIFY_BEGIN_STREAMING
;
1098 LeaveCriticalSection(&mixer
->cs
);
1102 case MFT_MESSAGE_COMMAND_DRAIN
:
1106 WARN("Message not handled %d.\n", message
);
1113 static HRESULT WINAPI
video_mixer_transform_ProcessInput(IMFTransform
*iface
, DWORD id
, IMFSample
*sample
, DWORD flags
)
1115 struct video_mixer
*mixer
= impl_from_IMFTransform(iface
);
1116 struct input_stream
*input
;
1119 TRACE("%p, %u, %p, %#x.\n", iface
, id
, sample
, flags
);
1124 EnterCriticalSection(&mixer
->cs
);
1126 if (SUCCEEDED(hr
= video_mixer_get_input(mixer
, id
, &input
)))
1128 if (!input
->media_type
|| !mixer
->output
.media_type
)
1129 hr
= MF_E_TRANSFORM_TYPE_NOT_SET
;
1130 else if (input
->sample
)
1131 hr
= MF_E_NOTACCEPTING
;
1134 mixer
->is_streaming
= 1;
1135 input
->sample_requested
= 0;
1136 input
->sample
= sample
;
1137 IMFSample_AddRef(input
->sample
);
1141 LeaveCriticalSection(&mixer
->cs
);
1146 static HRESULT
video_mixer_get_sample_surface(IMFSample
*sample
, IDirect3DSurface9
**surface
)
1148 IMFMediaBuffer
*buffer
;
1152 if (FAILED(hr
= IMFSample_GetBufferByIndex(sample
, 0, &buffer
)))
1155 hr
= IMFMediaBuffer_QueryInterface(buffer
, &IID_IMFGetService
, (void **)&gs
);
1156 IMFMediaBuffer_Release(buffer
);
1160 hr
= IMFGetService_GetService(gs
, &MR_BUFFER_SERVICE
, &IID_IDirect3DSurface9
, (void **)surface
);
1161 IMFGetService_Release(gs
);
1165 static HRESULT
video_mixer_get_d3d_device(struct video_mixer
*mixer
, IDirect3DDevice9
**device
)
1171 hr
= IDirect3DDeviceManager9_LockDevice(mixer
->device_manager
, mixer
->device_handle
,
1173 if (hr
== DXVA2_E_NEW_VIDEO_DEVICE
)
1175 if (SUCCEEDED(hr
= video_mixer_open_device_handle(mixer
)))
1184 static void video_mixer_scale_rect(RECT
*rect
, unsigned int width
, unsigned int height
,
1185 const MFVideoNormalizedRect
*scale
)
1187 if (rect
->left
== 0.0f
&& rect
->top
== 0.0f
&& rect
->right
== 1.0f
&& rect
->bottom
== 1.0f
)
1189 SetRect(rect
, 0, 0, width
, height
);
1193 rect
->left
= width
* scale
->left
;
1194 rect
->right
= width
* scale
->right
;
1195 rect
->top
= height
* scale
->top
;
1196 rect
->bottom
= height
* scale
->bottom
;
1200 static void video_mixer_render(struct video_mixer
*mixer
, IDirect3DSurface9
*rt
)
1202 DXVA2_VideoSample samples
[1] = {{ 0 }};
1203 DXVA2_VideoProcessBltParams params
= { 0 };
1204 MFVideoNormalizedRect zoom_rect
;
1205 struct input_stream
*stream
;
1206 IDirect3DSurface9
*surface
;
1207 D3DSURFACE_DESC desc
;
1210 IDirect3DSurface9_GetDesc(rt
, &desc
);
1212 if (FAILED(IMFAttributes_GetBlob(mixer
->attributes
, &VIDEO_ZOOM_RECT
, (UINT8
*)&zoom_rect
,
1213 sizeof(zoom_rect
), NULL
)))
1215 zoom_rect
.left
= zoom_rect
.top
= 0.0f
;
1216 zoom_rect
.right
= zoom_rect
.bottom
= 1.0f
;
1219 video_mixer_scale_rect(¶ms
.TargetRect
, desc
.Width
, desc
.Height
, &zoom_rect
);
1221 /* FIXME: for now only handle reference stream. */
1223 video_mixer_get_input(mixer
, 0, &stream
);
1225 if (FAILED(hr
= video_mixer_get_sample_surface(stream
->sample
, &surface
)))
1227 WARN("Failed to get source surface, hr %#x.\n", hr
);
1231 IDirect3DSurface9_GetDesc(surface
, &desc
);
1233 samples
[0].SrcSurface
= surface
;
1234 SetRect(&samples
[0].SrcRect
, 0, 0, desc
.Width
, desc
.Height
);
1235 video_mixer_scale_rect(&samples
[0].DstRect
, desc
.Width
, desc
.Height
, &stream
->rect
);
1237 if (FAILED(hr
= IDirectXVideoProcessor_VideoProcessBlt(mixer
->processor
, rt
, ¶ms
, samples
, 1, NULL
)))
1238 WARN("Failed to process samples, hr %#x.\n", hr
);
1240 IDirect3DSurface9_Release(surface
);
1243 static HRESULT
video_mixer_get_sample_desired_time(IMFSample
*sample
, LONGLONG
*timestamp
, LONGLONG
*duration
)
1245 IMFDesiredSample
*desired
;
1248 if (SUCCEEDED(hr
= IMFSample_QueryInterface(sample
, &IID_IMFDesiredSample
, (void **)&desired
)))
1250 hr
= IMFDesiredSample_GetDesiredSampleTimeAndDuration(desired
, timestamp
, duration
);
1251 IMFDesiredSample_Release(desired
);
1257 static HRESULT WINAPI
video_mixer_transform_ProcessOutput(IMFTransform
*iface
, DWORD flags
, DWORD count
,
1258 MFT_OUTPUT_DATA_BUFFER
*buffers
, DWORD
*status
)
1260 struct video_mixer
*mixer
= impl_from_IMFTransform(iface
);
1261 LONGLONG timestamp
, duration
;
1262 IDirect3DSurface9
*surface
;
1263 IDirect3DDevice9
*device
;
1267 TRACE("%p, %#x, %u, %p, %p.\n", iface
, flags
, count
, buffers
, status
);
1269 if (!buffers
|| !count
|| count
> 1 || !buffers
->pSample
)
1270 return E_INVALIDARG
;
1272 if (buffers
->dwStreamID
)
1273 return MF_E_INVALIDSTREAMNUMBER
;
1277 EnterCriticalSection(&mixer
->cs
);
1279 if (SUCCEEDED(hr
= video_mixer_get_sample_surface(buffers
->pSample
, &surface
)))
1281 if (mixer
->is_streaming
)
1283 for (i
= 0; i
< mixer
->input_count
; ++i
)
1285 if (!mixer
->inputs
[i
].sample
)
1287 hr
= MF_E_TRANSFORM_NEED_MORE_INPUT
;
1294 video_mixer_render(mixer
, surface
);
1296 timestamp
= duration
= 0;
1297 if (SUCCEEDED(IMFSample_GetSampleTime(mixer
->inputs
[0].sample
, ×tamp
)))
1299 IMFSample_SetSampleTime(buffers
->pSample
, timestamp
);
1301 IMFSample_GetSampleDuration(mixer
->inputs
[0].sample
, &duration
);
1302 IMFSample_SetSampleDuration(buffers
->pSample
, duration
);
1308 for (i
= 0; i
< mixer
->input_count
; ++i
)
1310 if (mixer
->inputs
[i
].sample
)
1311 IMFSample_Release(mixer
->inputs
[i
].sample
);
1312 mixer
->inputs
[i
].sample
= NULL
;
1313 video_mixer_request_sample(mixer
, i
);
1319 if (SUCCEEDED(video_mixer_get_sample_desired_time(buffers
->pSample
, ×tamp
, &duration
)))
1321 if (SUCCEEDED(hr
= video_mixer_get_d3d_device(mixer
, &device
)))
1323 IDirect3DDevice9_ColorFill(device
, surface
, NULL
, 0);
1324 IDirect3DDeviceManager9_UnlockDevice(mixer
->device_manager
, mixer
->device_handle
, FALSE
);
1325 IDirect3DDevice9_Release(device
);
1329 hr
= MF_E_TRANSFORM_NEED_MORE_INPUT
;
1331 IDirect3DSurface9_Release(surface
);
1334 LeaveCriticalSection(&mixer
->cs
);
1339 static const IMFTransformVtbl video_mixer_transform_vtbl
=
1341 video_mixer_transform_QueryInterface
,
1342 video_mixer_transform_AddRef
,
1343 video_mixer_transform_Release
,
1344 video_mixer_transform_GetStreamLimits
,
1345 video_mixer_transform_GetStreamCount
,
1346 video_mixer_transform_GetStreamIDs
,
1347 video_mixer_transform_GetInputStreamInfo
,
1348 video_mixer_transform_GetOutputStreamInfo
,
1349 video_mixer_transform_GetAttributes
,
1350 video_mixer_transform_GetInputStreamAttributes
,
1351 video_mixer_transform_GetOutputStreamAttributes
,
1352 video_mixer_transform_DeleteInputStream
,
1353 video_mixer_transform_AddInputStreams
,
1354 video_mixer_transform_GetInputAvailableType
,
1355 video_mixer_transform_GetOutputAvailableType
,
1356 video_mixer_transform_SetInputType
,
1357 video_mixer_transform_SetOutputType
,
1358 video_mixer_transform_GetInputCurrentType
,
1359 video_mixer_transform_GetOutputCurrentType
,
1360 video_mixer_transform_GetInputStatus
,
1361 video_mixer_transform_GetOutputStatus
,
1362 video_mixer_transform_SetOutputBounds
,
1363 video_mixer_transform_ProcessEvent
,
1364 video_mixer_transform_ProcessMessage
,
1365 video_mixer_transform_ProcessInput
,
1366 video_mixer_transform_ProcessOutput
,
1369 static HRESULT WINAPI
video_mixer_device_id_QueryInterface(IMFVideoDeviceID
*iface
, REFIID riid
, void **obj
)
1371 struct video_mixer
*mixer
= impl_from_IMFVideoDeviceID(iface
);
1372 return IMFTransform_QueryInterface(&mixer
->IMFTransform_iface
, riid
, obj
);
1375 static ULONG WINAPI
video_mixer_device_id_AddRef(IMFVideoDeviceID
*iface
)
1377 struct video_mixer
*mixer
= impl_from_IMFVideoDeviceID(iface
);
1378 return IMFTransform_AddRef(&mixer
->IMFTransform_iface
);
1381 static ULONG WINAPI
video_mixer_device_id_Release(IMFVideoDeviceID
*iface
)
1383 struct video_mixer
*mixer
= impl_from_IMFVideoDeviceID(iface
);
1384 return IMFTransform_Release(&mixer
->IMFTransform_iface
);
1387 static HRESULT WINAPI
video_mixer_device_id_GetDeviceID(IMFVideoDeviceID
*iface
, IID
*device_id
)
1389 TRACE("%p, %p.\n", iface
, device_id
);
1394 memcpy(device_id
, &IID_IDirect3DDevice9
, sizeof(*device_id
));
1399 static const IMFVideoDeviceIDVtbl video_mixer_device_id_vtbl
=
1401 video_mixer_device_id_QueryInterface
,
1402 video_mixer_device_id_AddRef
,
1403 video_mixer_device_id_Release
,
1404 video_mixer_device_id_GetDeviceID
,
1407 static HRESULT WINAPI
video_mixer_service_client_QueryInterface(IMFTopologyServiceLookupClient
*iface
,
1408 REFIID riid
, void **obj
)
1410 struct video_mixer
*mixer
= impl_from_IMFTopologyServiceLookupClient(iface
);
1411 return IMFTransform_QueryInterface(&mixer
->IMFTransform_iface
, riid
, obj
);
1414 static ULONG WINAPI
video_mixer_service_client_AddRef(IMFTopologyServiceLookupClient
*iface
)
1416 struct video_mixer
*mixer
= impl_from_IMFTopologyServiceLookupClient(iface
);
1417 return IMFTransform_AddRef(&mixer
->IMFTransform_iface
);
1420 static ULONG WINAPI
video_mixer_service_client_Release(IMFTopologyServiceLookupClient
*iface
)
1422 struct video_mixer
*mixer
= impl_from_IMFTopologyServiceLookupClient(iface
);
1423 return IMFTransform_Release(&mixer
->IMFTransform_iface
);
1426 static HRESULT WINAPI
video_mixer_service_client_InitServicePointers(IMFTopologyServiceLookupClient
*iface
,
1427 IMFTopologyServiceLookup
*service_lookup
)
1429 struct video_mixer
*mixer
= impl_from_IMFTopologyServiceLookupClient(iface
);
1433 TRACE("%p, %p.\n", iface
, service_lookup
);
1435 if (!service_lookup
)
1438 EnterCriticalSection(&mixer
->cs
);
1441 if (FAILED(hr
= IMFTopologyServiceLookup_LookupService(service_lookup
, MF_SERVICE_LOOKUP_GLOBAL
, 0,
1442 &MR_VIDEO_RENDER_SERVICE
, &IID_IMediaEventSink
, (void **)&mixer
->event_sink
, &count
)))
1444 WARN("Failed to get renderer event sink, hr %#x.\n", hr
);
1447 LeaveCriticalSection(&mixer
->cs
);
1452 static HRESULT WINAPI
video_mixer_service_client_ReleaseServicePointers(IMFTopologyServiceLookupClient
*iface
)
1454 struct video_mixer
*mixer
= impl_from_IMFTopologyServiceLookupClient(iface
);
1456 TRACE("%p.\n", iface
);
1458 EnterCriticalSection(&mixer
->cs
);
1460 if (mixer
->event_sink
)
1461 IMediaEventSink_Release(mixer
->event_sink
);
1462 mixer
->event_sink
= NULL
;
1464 LeaveCriticalSection(&mixer
->cs
);
1469 static const IMFTopologyServiceLookupClientVtbl video_mixer_service_client_vtbl
=
1471 video_mixer_service_client_QueryInterface
,
1472 video_mixer_service_client_AddRef
,
1473 video_mixer_service_client_Release
,
1474 video_mixer_service_client_InitServicePointers
,
1475 video_mixer_service_client_ReleaseServicePointers
,
1478 static HRESULT WINAPI
video_mixer_control_QueryInterface(IMFVideoMixerControl2
*iface
, REFIID riid
, void **obj
)
1480 struct video_mixer
*mixer
= impl_from_IMFVideoMixerControl2(iface
);
1481 return IMFTransform_QueryInterface(&mixer
->IMFTransform_iface
, riid
, obj
);
1484 static ULONG WINAPI
video_mixer_control_AddRef(IMFVideoMixerControl2
*iface
)
1486 struct video_mixer
*mixer
= impl_from_IMFVideoMixerControl2(iface
);
1487 return IMFTransform_AddRef(&mixer
->IMFTransform_iface
);
1490 static ULONG WINAPI
video_mixer_control_Release(IMFVideoMixerControl2
*iface
)
1492 struct video_mixer
*mixer
= impl_from_IMFVideoMixerControl2(iface
);
1493 return IMFTransform_Release(&mixer
->IMFTransform_iface
);
1496 static HRESULT WINAPI
video_mixer_control_SetStreamZOrder(IMFVideoMixerControl2
*iface
, DWORD id
, DWORD zorder
)
1498 struct video_mixer
*mixer
= impl_from_IMFVideoMixerControl2(iface
);
1499 struct input_stream
*stream
;
1502 TRACE("%p, %u, %u.\n", iface
, id
, zorder
);
1504 /* Can't change reference stream. */
1506 return E_INVALIDARG
;
1508 EnterCriticalSection(&mixer
->cs
);
1510 if (zorder
>= mixer
->input_count
)
1512 else if (SUCCEEDED(hr
= video_mixer_get_input(mixer
, id
, &stream
)))
1514 /* Lowest zorder only applies to reference stream. */
1516 hr
= MF_E_INVALIDREQUEST
;
1518 stream
->zorder
= zorder
;
1521 LeaveCriticalSection(&mixer
->cs
);
1526 static HRESULT WINAPI
video_mixer_control_GetStreamZOrder(IMFVideoMixerControl2
*iface
, DWORD id
, DWORD
*zorder
)
1528 struct video_mixer
*mixer
= impl_from_IMFVideoMixerControl2(iface
);
1529 struct input_stream
*stream
;
1532 TRACE("%p, %u, %p.\n", iface
, id
, zorder
);
1537 EnterCriticalSection(&mixer
->cs
);
1539 if (SUCCEEDED(hr
= video_mixer_get_input(mixer
, id
, &stream
)))
1540 *zorder
= stream
->zorder
;
1542 LeaveCriticalSection(&mixer
->cs
);
1547 static HRESULT WINAPI
video_mixer_control_SetStreamOutputRect(IMFVideoMixerControl2
*iface
, DWORD id
,
1548 const MFVideoNormalizedRect
*rect
)
1550 struct video_mixer
*mixer
= impl_from_IMFVideoMixerControl2(iface
);
1551 struct input_stream
*stream
;
1554 TRACE("%p, %u, %p.\n", iface
, id
, rect
);
1559 if (rect
->left
> rect
->right
|| rect
->top
> rect
->bottom
||
1560 rect
->left
< 0.0f
|| rect
->top
< 0.0f
|| rect
->right
> 1.0f
|| rect
->bottom
> 1.0f
)
1562 return E_INVALIDARG
;
1565 EnterCriticalSection(&mixer
->cs
);
1567 if (SUCCEEDED(hr
= video_mixer_get_input(mixer
, id
, &stream
)))
1568 stream
->rect
= *rect
;
1570 LeaveCriticalSection(&mixer
->cs
);
1575 static HRESULT WINAPI
video_mixer_control_GetStreamOutputRect(IMFVideoMixerControl2
*iface
, DWORD id
,
1576 MFVideoNormalizedRect
*rect
)
1578 struct video_mixer
*mixer
= impl_from_IMFVideoMixerControl2(iface
);
1579 struct input_stream
*stream
;
1582 TRACE("%p, %u, %p.\n", iface
, id
, rect
);
1587 EnterCriticalSection(&mixer
->cs
);
1589 if (SUCCEEDED(hr
= video_mixer_get_input(mixer
, id
, &stream
)))
1590 *rect
= stream
->rect
;
1592 LeaveCriticalSection(&mixer
->cs
);
1597 static HRESULT WINAPI
video_mixer_control_SetMixingPrefs(IMFVideoMixerControl2
*iface
, DWORD flags
)
1599 struct video_mixer
*mixer
= impl_from_IMFVideoMixerControl2(iface
);
1601 TRACE("%p, %#x.\n", iface
, flags
);
1603 EnterCriticalSection(&mixer
->cs
);
1604 mixer
->mixing_flags
= flags
;
1605 LeaveCriticalSection(&mixer
->cs
);
1610 static HRESULT WINAPI
video_mixer_control_GetMixingPrefs(IMFVideoMixerControl2
*iface
, DWORD
*flags
)
1612 struct video_mixer
*mixer
= impl_from_IMFVideoMixerControl2(iface
);
1614 TRACE("%p, %p.\n", iface
, flags
);
1619 EnterCriticalSection(&mixer
->cs
);
1620 *flags
= mixer
->mixing_flags
;
1621 LeaveCriticalSection(&mixer
->cs
);
1626 static const IMFVideoMixerControl2Vtbl video_mixer_control_vtbl
=
1628 video_mixer_control_QueryInterface
,
1629 video_mixer_control_AddRef
,
1630 video_mixer_control_Release
,
1631 video_mixer_control_SetStreamZOrder
,
1632 video_mixer_control_GetStreamZOrder
,
1633 video_mixer_control_SetStreamOutputRect
,
1634 video_mixer_control_GetStreamOutputRect
,
1635 video_mixer_control_SetMixingPrefs
,
1636 video_mixer_control_GetMixingPrefs
,
1639 static HRESULT WINAPI
video_mixer_getservice_QueryInterface(IMFGetService
*iface
, REFIID riid
, void **obj
)
1641 struct video_mixer
*mixer
= impl_from_IMFGetService(iface
);
1642 return IMFTransform_QueryInterface(&mixer
->IMFTransform_iface
, riid
, obj
);
1645 static ULONG WINAPI
video_mixer_getservice_AddRef(IMFGetService
*iface
)
1647 struct video_mixer
*mixer
= impl_from_IMFGetService(iface
);
1648 return IMFTransform_AddRef(&mixer
->IMFTransform_iface
);
1651 static ULONG WINAPI
video_mixer_getservice_Release(IMFGetService
*iface
)
1653 struct video_mixer
*mixer
= impl_from_IMFGetService(iface
);
1654 return IMFTransform_Release(&mixer
->IMFTransform_iface
);
1657 static HRESULT WINAPI
video_mixer_getservice_GetService(IMFGetService
*iface
, REFGUID service
, REFIID riid
, void **obj
)
1659 TRACE("%p, %s, %s, %p.\n", iface
, debugstr_guid(service
), debugstr_guid(riid
), obj
);
1661 if (IsEqualGUID(service
, &MR_VIDEO_MIXER_SERVICE
))
1663 if (IsEqualIID(riid
, &IID_IMFVideoMixerBitmap
) ||
1664 IsEqualIID(riid
, &IID_IMFVideoProcessor
) ||
1665 IsEqualIID(riid
, &IID_IMFVideoPositionMapper
) ||
1666 IsEqualIID(riid
, &IID_IMFVideoMixerControl
) ||
1667 IsEqualIID(riid
, &IID_IMFVideoMixerControl2
))
1669 return IMFGetService_QueryInterface(iface
, riid
, obj
);
1672 return E_NOINTERFACE
;
1675 FIXME("Unsupported service %s, riid %s.\n", debugstr_guid(service
), debugstr_guid(riid
));
1677 return MF_E_UNSUPPORTED_SERVICE
;
1680 static const IMFGetServiceVtbl video_mixer_getservice_vtbl
=
1682 video_mixer_getservice_QueryInterface
,
1683 video_mixer_getservice_AddRef
,
1684 video_mixer_getservice_Release
,
1685 video_mixer_getservice_GetService
,
1688 static HRESULT WINAPI
video_mixer_bitmap_QueryInterface(IMFVideoMixerBitmap
*iface
, REFIID riid
, void **obj
)
1690 struct video_mixer
*mixer
= impl_from_IMFVideoMixerBitmap(iface
);
1691 return IMFTransform_QueryInterface(&mixer
->IMFTransform_iface
, riid
, obj
);
1694 static ULONG WINAPI
video_mixer_bitmap_AddRef(IMFVideoMixerBitmap
*iface
)
1696 struct video_mixer
*mixer
= impl_from_IMFVideoMixerBitmap(iface
);
1697 return IMFTransform_AddRef(&mixer
->IMFTransform_iface
);
1700 static ULONG WINAPI
video_mixer_bitmap_Release(IMFVideoMixerBitmap
*iface
)
1702 struct video_mixer
*mixer
= impl_from_IMFVideoMixerBitmap(iface
);
1703 return IMFTransform_Release(&mixer
->IMFTransform_iface
);
1706 static HRESULT WINAPI
video_mixer_bitmap_SetAlphaBitmap(IMFVideoMixerBitmap
*iface
, const MFVideoAlphaBitmap
*bitmap
)
1708 FIXME("%p, %p.\n", iface
, bitmap
);
1713 static HRESULT WINAPI
video_mixer_bitmap_ClearAlphaBitmap(IMFVideoMixerBitmap
*iface
)
1715 FIXME("%p.\n", iface
);
1720 static HRESULT WINAPI
video_mixer_bitmap_UpdateAlphaBitmapParameters(IMFVideoMixerBitmap
*iface
,
1721 const MFVideoAlphaBitmapParams
*params
)
1723 FIXME("%p, %p.\n", iface
, params
);
1728 static HRESULT WINAPI
video_mixer_bitmap_GetAlphaBitmapParameters(IMFVideoMixerBitmap
*iface
, MFVideoAlphaBitmapParams
*params
)
1730 FIXME("%p, %p.\n", iface
, params
);
1735 static const IMFVideoMixerBitmapVtbl video_mixer_bitmap_vtbl
=
1737 video_mixer_bitmap_QueryInterface
,
1738 video_mixer_bitmap_AddRef
,
1739 video_mixer_bitmap_Release
,
1740 video_mixer_bitmap_SetAlphaBitmap
,
1741 video_mixer_bitmap_ClearAlphaBitmap
,
1742 video_mixer_bitmap_UpdateAlphaBitmapParameters
,
1743 video_mixer_bitmap_GetAlphaBitmapParameters
,
1746 static HRESULT WINAPI
video_mixer_position_mapper_QueryInterface(IMFVideoPositionMapper
*iface
, REFIID riid
, void **obj
)
1748 struct video_mixer
*mixer
= impl_from_IMFVideoPositionMapper(iface
);
1749 return IMFTransform_QueryInterface(&mixer
->IMFTransform_iface
, riid
, obj
);
1752 static ULONG WINAPI
video_mixer_position_mapper_AddRef(IMFVideoPositionMapper
*iface
)
1754 struct video_mixer
*mixer
= impl_from_IMFVideoPositionMapper(iface
);
1755 return IMFTransform_AddRef(&mixer
->IMFTransform_iface
);
1758 static ULONG WINAPI
video_mixer_position_mapper_Release(IMFVideoPositionMapper
*iface
)
1760 struct video_mixer
*mixer
= impl_from_IMFVideoPositionMapper(iface
);
1761 return IMFTransform_Release(&mixer
->IMFTransform_iface
);
1764 static HRESULT WINAPI
video_mixer_position_mapper_MapOutputCoordinateToInputStream(IMFVideoPositionMapper
*iface
,
1765 float x_out
, float y_out
, DWORD output_stream
, DWORD input_stream
, float *x_in
, float *y_in
)
1767 FIXME("%p, %f, %f, %u, %u, %p, %p.\n", iface
, x_out
, y_out
, output_stream
, input_stream
, x_in
, y_in
);
1772 static const IMFVideoPositionMapperVtbl video_mixer_position_mapper_vtbl
=
1774 video_mixer_position_mapper_QueryInterface
,
1775 video_mixer_position_mapper_AddRef
,
1776 video_mixer_position_mapper_Release
,
1777 video_mixer_position_mapper_MapOutputCoordinateToInputStream
,
1780 static HRESULT WINAPI
video_mixer_processor_QueryInterface(IMFVideoProcessor
*iface
, REFIID riid
, void **obj
)
1782 struct video_mixer
*mixer
= impl_from_IMFVideoProcessor(iface
);
1783 return IMFTransform_QueryInterface(&mixer
->IMFTransform_iface
, riid
, obj
);
1786 static ULONG WINAPI
video_mixer_processor_AddRef(IMFVideoProcessor
*iface
)
1788 struct video_mixer
*mixer
= impl_from_IMFVideoProcessor(iface
);
1789 return IMFTransform_AddRef(&mixer
->IMFTransform_iface
);
1792 static ULONG WINAPI
video_mixer_processor_Release(IMFVideoProcessor
*iface
)
1794 struct video_mixer
*mixer
= impl_from_IMFVideoProcessor(iface
);
1795 return IMFTransform_Release(&mixer
->IMFTransform_iface
);
1798 static HRESULT WINAPI
video_mixer_processor_GetAvailableVideoProcessorModes(IMFVideoProcessor
*iface
, UINT
*count
,
1801 FIXME("%p, %p, %p.\n", iface
, count
, modes
);
1806 static HRESULT WINAPI
video_mixer_processor_GetVideoProcessorCaps(IMFVideoProcessor
*iface
, GUID
*mode
,
1807 DXVA2_VideoProcessorCaps
*caps
)
1809 FIXME("%p, %s, %p.\n", iface
, debugstr_guid(mode
), caps
);
1814 static HRESULT WINAPI
video_mixer_processor_GetVideoProcessorMode(IMFVideoProcessor
*iface
, GUID
*mode
)
1816 FIXME("%p, %p.\n", iface
, mode
);
1821 static HRESULT WINAPI
video_mixer_processor_SetVideoProcessorMode(IMFVideoProcessor
*iface
, GUID
*mode
)
1823 FIXME("%p, %s.\n", iface
, debugstr_guid(mode
));
1828 static HRESULT WINAPI
video_mixer_processor_GetProcAmpRange(IMFVideoProcessor
*iface
, DWORD prop
, DXVA2_ValueRange
*range
)
1830 FIXME("%p, %#x, %p.\n", iface
, prop
, range
);
1835 static HRESULT WINAPI
video_mixer_processor_GetProcAmpValues(IMFVideoProcessor
*iface
, DWORD flags
, DXVA2_ProcAmpValues
*values
)
1837 FIXME("%p, %#x, %p.\n", iface
, flags
, values
);
1842 static HRESULT WINAPI
video_mixer_processor_SetProcAmpValues(IMFVideoProcessor
*iface
, DWORD flags
, DXVA2_ProcAmpValues
*values
)
1844 FIXME("%p, %#x, %p.\n", iface
, flags
, values
);
1849 static HRESULT WINAPI
video_mixer_processor_GetFilteringRange(IMFVideoProcessor
*iface
, DWORD prop
, DXVA2_ValueRange
*range
)
1851 FIXME("%p, %#x, %p.\n", iface
, prop
, range
);
1856 static HRESULT WINAPI
video_mixer_processor_GetFilteringValue(IMFVideoProcessor
*iface
, DWORD prop
, DXVA2_Fixed32
*value
)
1858 FIXME("%p, %#x, %p.\n", iface
, prop
, value
);
1863 static HRESULT WINAPI
video_mixer_processor_SetFilteringValue(IMFVideoProcessor
*iface
, DWORD prop
, DXVA2_Fixed32
*value
)
1865 FIXME("%p, %#x, %p.\n", iface
, prop
, value
);
1870 static HRESULT WINAPI
video_mixer_processor_GetBackgroundColor(IMFVideoProcessor
*iface
, COLORREF
*color
)
1872 struct video_mixer
*mixer
= impl_from_IMFVideoProcessor(iface
);
1874 TRACE("%p, %p.\n", iface
, color
);
1879 EnterCriticalSection(&mixer
->cs
);
1880 *color
= mixer
->bkgnd_color
;
1881 LeaveCriticalSection(&mixer
->cs
);
1886 static HRESULT WINAPI
video_mixer_processor_SetBackgroundColor(IMFVideoProcessor
*iface
, COLORREF color
)
1888 struct video_mixer
*mixer
= impl_from_IMFVideoProcessor(iface
);
1890 TRACE("%p, %#x.\n", iface
, color
);
1892 EnterCriticalSection(&mixer
->cs
);
1893 mixer
->bkgnd_color
= color
;
1894 LeaveCriticalSection(&mixer
->cs
);
1899 static const IMFVideoProcessorVtbl video_mixer_processor_vtbl
=
1901 video_mixer_processor_QueryInterface
,
1902 video_mixer_processor_AddRef
,
1903 video_mixer_processor_Release
,
1904 video_mixer_processor_GetAvailableVideoProcessorModes
,
1905 video_mixer_processor_GetVideoProcessorCaps
,
1906 video_mixer_processor_GetVideoProcessorMode
,
1907 video_mixer_processor_SetVideoProcessorMode
,
1908 video_mixer_processor_GetProcAmpRange
,
1909 video_mixer_processor_GetProcAmpValues
,
1910 video_mixer_processor_SetProcAmpValues
,
1911 video_mixer_processor_GetFilteringRange
,
1912 video_mixer_processor_GetFilteringValue
,
1913 video_mixer_processor_SetFilteringValue
,
1914 video_mixer_processor_GetBackgroundColor
,
1915 video_mixer_processor_SetBackgroundColor
,
1918 static HRESULT WINAPI
video_mixer_attributes_QueryInterface(IMFAttributes
*iface
, REFIID riid
, void **out
)
1920 struct video_mixer
*mixer
= impl_from_IMFAttributes(iface
);
1921 return IMFTransform_QueryInterface(&mixer
->IMFTransform_iface
, riid
, out
);
1924 static ULONG WINAPI
video_mixer_attributes_AddRef(IMFAttributes
*iface
)
1926 struct video_mixer
*mixer
= impl_from_IMFAttributes(iface
);
1927 return IMFTransform_AddRef(&mixer
->IMFTransform_iface
);
1930 static ULONG WINAPI
video_mixer_attributes_Release(IMFAttributes
*iface
)
1932 struct video_mixer
*mixer
= impl_from_IMFAttributes(iface
);
1933 return IMFTransform_Release(&mixer
->IMFTransform_iface
);
1936 static HRESULT WINAPI
video_mixer_attributes_GetItem(IMFAttributes
*iface
, REFGUID key
, PROPVARIANT
*value
)
1938 struct video_mixer
*mixer
= impl_from_IMFAttributes(iface
);
1940 TRACE("%p, %s, %p.\n", iface
, debugstr_guid(key
), value
);
1942 return IMFAttributes_GetItem(mixer
->internal_attributes
, key
, value
);
1945 static HRESULT WINAPI
video_mixer_attributes_GetItemType(IMFAttributes
*iface
, REFGUID key
, MF_ATTRIBUTE_TYPE
*type
)
1947 struct video_mixer
*mixer
= impl_from_IMFAttributes(iface
);
1949 TRACE("%p, %s, %p.\n", iface
, debugstr_guid(key
), type
);
1951 return IMFAttributes_GetItemType(mixer
->internal_attributes
, key
, type
);
1954 static HRESULT WINAPI
video_mixer_attributes_CompareItem(IMFAttributes
*iface
, REFGUID key
,
1955 REFPROPVARIANT value
, BOOL
*result
)
1957 struct video_mixer
*mixer
= impl_from_IMFAttributes(iface
);
1959 TRACE("%p, %s, %p, %p.\n", iface
, debugstr_guid(key
), value
, result
);
1961 return IMFAttributes_CompareItem(mixer
->internal_attributes
, key
, value
, result
);
1964 static HRESULT WINAPI
video_mixer_attributes_Compare(IMFAttributes
*iface
, IMFAttributes
*theirs
,
1965 MF_ATTRIBUTES_MATCH_TYPE match_type
, BOOL
*ret
)
1967 struct video_mixer
*mixer
= impl_from_IMFAttributes(iface
);
1969 TRACE("%p, %p, %d, %p.\n", iface
, theirs
, match_type
, ret
);
1971 return IMFAttributes_Compare(mixer
->internal_attributes
, theirs
, match_type
, ret
);
1974 static HRESULT WINAPI
video_mixer_attributes_GetUINT32(IMFAttributes
*iface
, REFGUID key
, UINT32
*value
)
1976 struct video_mixer
*mixer
= impl_from_IMFAttributes(iface
);
1978 TRACE("%p, %s, %p.\n", iface
, debugstr_guid(key
), value
);
1980 return IMFAttributes_GetUINT32(mixer
->internal_attributes
, key
, value
);
1983 static HRESULT WINAPI
video_mixer_attributes_GetUINT64(IMFAttributes
*iface
, REFGUID key
, UINT64
*value
)
1985 struct video_mixer
*mixer
= impl_from_IMFAttributes(iface
);
1987 TRACE("%p, %s, %p.\n", iface
, debugstr_guid(key
), value
);
1989 return IMFAttributes_GetUINT64(mixer
->internal_attributes
, key
, value
);
1992 static HRESULT WINAPI
video_mixer_attributes_GetDouble(IMFAttributes
*iface
, REFGUID key
, double *value
)
1994 struct video_mixer
*mixer
= impl_from_IMFAttributes(iface
);
1996 TRACE("%p, %s, %p.\n", iface
, debugstr_guid(key
), value
);
1998 return IMFAttributes_GetDouble(mixer
->internal_attributes
, key
, value
);
2001 static HRESULT WINAPI
video_mixer_attributes_GetGUID(IMFAttributes
*iface
, REFGUID key
, GUID
*value
)
2003 struct video_mixer
*mixer
= impl_from_IMFAttributes(iface
);
2005 TRACE("%p, %s, %p.\n", iface
, debugstr_guid(key
), value
);
2007 return IMFAttributes_GetGUID(mixer
->internal_attributes
, key
, value
);
2010 static HRESULT WINAPI
video_mixer_attributes_GetStringLength(IMFAttributes
*iface
, REFGUID key
, UINT32
*length
)
2012 struct video_mixer
*mixer
= impl_from_IMFAttributes(iface
);
2014 TRACE("%p, %s, %p.\n", iface
, debugstr_guid(key
), length
);
2016 return IMFAttributes_GetStringLength(mixer
->internal_attributes
, key
, length
);
2019 static HRESULT WINAPI
video_mixer_attributes_GetString(IMFAttributes
*iface
, REFGUID key
, WCHAR
*value
,
2020 UINT32 size
, UINT32
*length
)
2022 struct video_mixer
*mixer
= impl_from_IMFAttributes(iface
);
2024 TRACE("%p, %s, %p, %d, %p.\n", iface
, debugstr_guid(key
), value
, size
, length
);
2026 return IMFAttributes_GetString(mixer
->internal_attributes
, key
, value
, size
, length
);
2029 static HRESULT WINAPI
video_mixer_attributes_GetAllocatedString(IMFAttributes
*iface
, REFGUID key
,
2030 WCHAR
**value
, UINT32
*length
)
2032 struct video_mixer
*mixer
= impl_from_IMFAttributes(iface
);
2034 TRACE("%p, %s, %p, %p.\n", iface
, debugstr_guid(key
), value
, length
);
2036 return IMFAttributes_GetAllocatedString(mixer
->internal_attributes
, key
, value
, length
);
2039 static HRESULT WINAPI
video_mixer_attributes_GetBlobSize(IMFAttributes
*iface
, REFGUID key
, UINT32
*size
)
2041 struct video_mixer
*mixer
= impl_from_IMFAttributes(iface
);
2043 TRACE("%p, %s, %p.\n", iface
, debugstr_guid(key
), size
);
2045 return IMFAttributes_GetBlobSize(mixer
->internal_attributes
, key
, size
);
2048 static HRESULT WINAPI
video_mixer_attributes_GetBlob(IMFAttributes
*iface
, REFGUID key
, UINT8
*buf
,
2049 UINT32 bufsize
, UINT32
*blobsize
)
2051 struct video_mixer
*mixer
= impl_from_IMFAttributes(iface
);
2053 TRACE("%p, %s, %p, %d, %p.\n", iface
, debugstr_guid(key
), buf
, bufsize
, blobsize
);
2055 return IMFAttributes_GetBlob(mixer
->internal_attributes
, key
, buf
, bufsize
, blobsize
);
2058 static HRESULT WINAPI
video_mixer_attributes_GetAllocatedBlob(IMFAttributes
*iface
, REFGUID key
, UINT8
**buf
, UINT32
*size
)
2060 struct video_mixer
*mixer
= impl_from_IMFAttributes(iface
);
2062 TRACE("%p, %s, %p, %p.\n", iface
, debugstr_guid(key
), buf
, size
);
2064 return IMFAttributes_GetAllocatedBlob(mixer
->internal_attributes
, key
, buf
, size
);
2067 static HRESULT WINAPI
video_mixer_attributes_GetUnknown(IMFAttributes
*iface
, REFGUID key
, REFIID riid
, void **out
)
2069 struct video_mixer
*mixer
= impl_from_IMFAttributes(iface
);
2071 TRACE("%p, %s, %s, %p.\n", iface
, debugstr_guid(key
), debugstr_guid(riid
), out
);
2073 return IMFAttributes_GetUnknown(mixer
->internal_attributes
, key
, riid
, out
);
2076 static HRESULT WINAPI
video_mixer_attributes_SetItem(IMFAttributes
*iface
, REFGUID key
, REFPROPVARIANT value
)
2078 struct video_mixer
*mixer
= impl_from_IMFAttributes(iface
);
2080 TRACE("%p, %s, %p.\n", iface
, debugstr_guid(key
), value
);
2082 return IMFAttributes_SetItem(mixer
->internal_attributes
, key
, value
);
2085 static HRESULT WINAPI
video_mixer_attributes_DeleteItem(IMFAttributes
*iface
, REFGUID key
)
2087 struct video_mixer
*mixer
= impl_from_IMFAttributes(iface
);
2089 TRACE("%p, %s.\n", iface
, debugstr_guid(key
));
2091 return IMFAttributes_DeleteItem(mixer
->internal_attributes
, key
);
2094 static HRESULT WINAPI
video_mixer_attributes_DeleteAllItems(IMFAttributes
*iface
)
2096 struct video_mixer
*mixer
= impl_from_IMFAttributes(iface
);
2098 TRACE("%p.\n", iface
);
2100 return IMFAttributes_DeleteAllItems(mixer
->internal_attributes
);
2103 static HRESULT WINAPI
video_mixer_attributes_SetUINT32(IMFAttributes
*iface
, REFGUID key
, UINT32 value
)
2105 struct video_mixer
*mixer
= impl_from_IMFAttributes(iface
);
2107 TRACE("%p, %s, %u.\n", iface
, debugstr_guid(key
), value
);
2109 return IMFAttributes_SetUINT32(mixer
->internal_attributes
, key
, value
);
2112 static HRESULT WINAPI
video_mixer_attributes_SetUINT64(IMFAttributes
*iface
, REFGUID key
, UINT64 value
)
2114 struct video_mixer
*mixer
= impl_from_IMFAttributes(iface
);
2116 TRACE("%p, %s, %s.\n", iface
, debugstr_guid(key
), wine_dbgstr_longlong(value
));
2118 return IMFAttributes_SetUINT64(mixer
->internal_attributes
, key
, value
);
2121 static HRESULT WINAPI
video_mixer_attributes_SetDouble(IMFAttributes
*iface
, REFGUID key
, double value
)
2123 struct video_mixer
*mixer
= impl_from_IMFAttributes(iface
);
2125 TRACE("%p, %s, %f.\n", iface
, debugstr_guid(key
), value
);
2127 return IMFAttributes_SetDouble(mixer
->internal_attributes
, key
, value
);
2130 static HRESULT WINAPI
video_mixer_attributes_SetGUID(IMFAttributes
*iface
, REFGUID key
, REFGUID value
)
2132 struct video_mixer
*mixer
= impl_from_IMFAttributes(iface
);
2134 TRACE("%p, %s, %s.\n", iface
, debugstr_guid(key
), debugstr_guid(value
));
2136 return IMFAttributes_SetGUID(mixer
->internal_attributes
, key
, value
);
2139 static HRESULT WINAPI
video_mixer_attributes_SetString(IMFAttributes
*iface
, REFGUID key
, const WCHAR
*value
)
2141 struct video_mixer
*mixer
= impl_from_IMFAttributes(iface
);
2143 TRACE("%p, %s, %s.\n", iface
, debugstr_guid(key
), debugstr_w(value
));
2145 return IMFAttributes_SetString(mixer
->internal_attributes
, key
, value
);
2148 static HRESULT WINAPI
video_mixer_attributes_SetBlob(IMFAttributes
*iface
, REFGUID key
, const UINT8
*buf
, UINT32 size
)
2150 struct video_mixer
*mixer
= impl_from_IMFAttributes(iface
);
2152 TRACE("%p, %s, %p, %u.\n", iface
, debugstr_guid(key
), buf
, size
);
2154 return IMFAttributes_SetBlob(mixer
->internal_attributes
, key
, buf
, size
);
2157 static HRESULT WINAPI
video_mixer_attributes_SetUnknown(IMFAttributes
*iface
, REFGUID key
, IUnknown
*unknown
)
2159 struct video_mixer
*mixer
= impl_from_IMFAttributes(iface
);
2161 TRACE("%p, %s, %p.\n", iface
, debugstr_guid(key
), unknown
);
2163 return IMFAttributes_SetUnknown(mixer
->internal_attributes
, key
, unknown
);
2166 static HRESULT WINAPI
video_mixer_attributes_LockStore(IMFAttributes
*iface
)
2168 struct video_mixer
*mixer
= impl_from_IMFAttributes(iface
);
2170 TRACE("%p.\n", iface
);
2172 return IMFAttributes_LockStore(mixer
->internal_attributes
);
2175 static HRESULT WINAPI
video_mixer_attributes_UnlockStore(IMFAttributes
*iface
)
2177 struct video_mixer
*mixer
= impl_from_IMFAttributes(iface
);
2179 TRACE("%p.\n", iface
);
2181 return IMFAttributes_UnlockStore(mixer
->internal_attributes
);
2184 static HRESULT WINAPI
video_mixer_attributes_GetCount(IMFAttributes
*iface
, UINT32
*count
)
2186 struct video_mixer
*mixer
= impl_from_IMFAttributes(iface
);
2188 TRACE("%p, %p.\n", iface
, count
);
2190 return IMFAttributes_GetCount(mixer
->internal_attributes
, count
);
2193 static HRESULT WINAPI
video_mixer_attributes_GetItemByIndex(IMFAttributes
*iface
, UINT32 index
,
2194 GUID
*key
, PROPVARIANT
*value
)
2196 struct video_mixer
*mixer
= impl_from_IMFAttributes(iface
);
2198 TRACE("%p, %u, %p, %p.\n", iface
, index
, key
, value
);
2200 return IMFAttributes_GetItemByIndex(mixer
->internal_attributes
, index
, key
, value
);
2203 static HRESULT WINAPI
video_mixer_attributes_CopyAllItems(IMFAttributes
*iface
, IMFAttributes
*dest
)
2205 struct video_mixer
*mixer
= impl_from_IMFAttributes(iface
);
2207 TRACE("%p, %p.\n", iface
, dest
);
2209 return IMFAttributes_CopyAllItems(mixer
->internal_attributes
, dest
);
2212 static const IMFAttributesVtbl video_mixer_attributes_vtbl
=
2214 video_mixer_attributes_QueryInterface
,
2215 video_mixer_attributes_AddRef
,
2216 video_mixer_attributes_Release
,
2217 video_mixer_attributes_GetItem
,
2218 video_mixer_attributes_GetItemType
,
2219 video_mixer_attributes_CompareItem
,
2220 video_mixer_attributes_Compare
,
2221 video_mixer_attributes_GetUINT32
,
2222 video_mixer_attributes_GetUINT64
,
2223 video_mixer_attributes_GetDouble
,
2224 video_mixer_attributes_GetGUID
,
2225 video_mixer_attributes_GetStringLength
,
2226 video_mixer_attributes_GetString
,
2227 video_mixer_attributes_GetAllocatedString
,
2228 video_mixer_attributes_GetBlobSize
,
2229 video_mixer_attributes_GetBlob
,
2230 video_mixer_attributes_GetAllocatedBlob
,
2231 video_mixer_attributes_GetUnknown
,
2232 video_mixer_attributes_SetItem
,
2233 video_mixer_attributes_DeleteItem
,
2234 video_mixer_attributes_DeleteAllItems
,
2235 video_mixer_attributes_SetUINT32
,
2236 video_mixer_attributes_SetUINT64
,
2237 video_mixer_attributes_SetDouble
,
2238 video_mixer_attributes_SetGUID
,
2239 video_mixer_attributes_SetString
,
2240 video_mixer_attributes_SetBlob
,
2241 video_mixer_attributes_SetUnknown
,
2242 video_mixer_attributes_LockStore
,
2243 video_mixer_attributes_UnlockStore
,
2244 video_mixer_attributes_GetCount
,
2245 video_mixer_attributes_GetItemByIndex
,
2246 video_mixer_attributes_CopyAllItems
2249 static HRESULT WINAPI
video_mixer_quality_advise_QueryInterface(IMFQualityAdvise
*iface
, REFIID riid
, void **out
)
2251 struct video_mixer
*mixer
= impl_from_IMFQualityAdvise(iface
);
2252 return IMFTransform_QueryInterface(&mixer
->IMFTransform_iface
, riid
, out
);
2255 static ULONG WINAPI
video_mixer_quality_advise_AddRef(IMFQualityAdvise
*iface
)
2257 struct video_mixer
*mixer
= impl_from_IMFQualityAdvise(iface
);
2258 return IMFTransform_AddRef(&mixer
->IMFTransform_iface
);
2261 static ULONG WINAPI
video_mixer_quality_advise_Release(IMFQualityAdvise
*iface
)
2263 struct video_mixer
*mixer
= impl_from_IMFQualityAdvise(iface
);
2264 return IMFTransform_Release(&mixer
->IMFTransform_iface
);
2267 static HRESULT WINAPI
video_mixer_quality_advise_SetDropMode(IMFQualityAdvise
*iface
, MF_QUALITY_DROP_MODE mode
)
2269 FIXME("%p, %u.\n", iface
, mode
);
2274 static HRESULT WINAPI
video_mixer_quality_advise_SetQualityLevel(IMFQualityAdvise
*iface
, MF_QUALITY_LEVEL level
)
2276 FIXME("%p, %u.\n", iface
, level
);
2281 static HRESULT WINAPI
video_mixer_quality_advise_GetDropMode(IMFQualityAdvise
*iface
, MF_QUALITY_DROP_MODE
*mode
)
2283 FIXME("%p, %p.\n", iface
, mode
);
2288 static HRESULT WINAPI
video_mixer_quality_advise_GetQualityLevel(IMFQualityAdvise
*iface
, MF_QUALITY_LEVEL
*level
)
2290 FIXME("%p, %p.\n", iface
, level
);
2295 static HRESULT WINAPI
video_mixer_quality_advise_DropTime(IMFQualityAdvise
*iface
, LONGLONG interval
)
2297 FIXME("%p, %s.\n", iface
, wine_dbgstr_longlong(interval
));
2302 static const IMFQualityAdviseVtbl video_mixer_quality_advise_vtbl
=
2304 video_mixer_quality_advise_QueryInterface
,
2305 video_mixer_quality_advise_AddRef
,
2306 video_mixer_quality_advise_Release
,
2307 video_mixer_quality_advise_SetDropMode
,
2308 video_mixer_quality_advise_SetQualityLevel
,
2309 video_mixer_quality_advise_GetDropMode
,
2310 video_mixer_quality_advise_GetQualityLevel
,
2311 video_mixer_quality_advise_DropTime
,
2314 static HRESULT WINAPI
video_mixer_clock_state_sink_QueryInterface(IMFClockStateSink
*iface
,
2315 REFIID riid
, void **out
)
2317 struct video_mixer
*mixer
= impl_from_IMFClockStateSink(iface
);
2318 return IMFTransform_QueryInterface(&mixer
->IMFTransform_iface
, riid
, out
);
2321 static ULONG WINAPI
video_mixer_clock_state_sink_AddRef(IMFClockStateSink
*iface
)
2323 struct video_mixer
*mixer
= impl_from_IMFClockStateSink(iface
);
2324 return IMFTransform_AddRef(&mixer
->IMFTransform_iface
);
2327 static ULONG WINAPI
video_mixer_clock_state_sink_Release(IMFClockStateSink
*iface
)
2329 struct video_mixer
*mixer
= impl_from_IMFClockStateSink(iface
);
2330 return IMFTransform_Release(&mixer
->IMFTransform_iface
);
2333 static HRESULT WINAPI
video_mixer_clock_state_sink_OnClockStart(IMFClockStateSink
*iface
,
2334 MFTIME systime
, LONGLONG offset
)
2336 FIXME("%p.\n", iface
);
2341 static HRESULT WINAPI
video_mixer_clock_state_sink_OnClockStop(IMFClockStateSink
*iface
,
2344 FIXME("%p.\n", iface
);
2349 static HRESULT WINAPI
video_mixer_clock_state_sink_OnClockPause(IMFClockStateSink
*iface
,
2352 FIXME("%p.\n", iface
);
2357 static HRESULT WINAPI
video_mixer_clock_state_sink_OnClockRestart(IMFClockStateSink
*iface
,
2360 FIXME("%p.\n", iface
);
2365 static HRESULT WINAPI
video_mixer_clock_state_sink_OnClockSetRate(IMFClockStateSink
*iface
,
2366 MFTIME systime
, float rate
)
2368 FIXME("%p, %f.\n", iface
, rate
);
2373 static const IMFClockStateSinkVtbl video_mixer_clock_state_sink_vtbl
=
2375 video_mixer_clock_state_sink_QueryInterface
,
2376 video_mixer_clock_state_sink_AddRef
,
2377 video_mixer_clock_state_sink_Release
,
2378 video_mixer_clock_state_sink_OnClockStart
,
2379 video_mixer_clock_state_sink_OnClockStop
,
2380 video_mixer_clock_state_sink_OnClockPause
,
2381 video_mixer_clock_state_sink_OnClockRestart
,
2382 video_mixer_clock_state_sink_OnClockSetRate
,
2385 HRESULT WINAPI
MFCreateVideoMixer(IUnknown
*owner
, REFIID riid_device
, REFIID riid
, void **obj
)
2387 TRACE("%p, %s, %s, %p.\n", owner
, debugstr_guid(riid_device
), debugstr_guid(riid
), obj
);
2391 if (!IsEqualIID(riid_device
, &IID_IDirect3DDevice9
))
2392 return E_INVALIDARG
;
2394 return CoCreateInstance(&CLSID_MFVideoMixer9
, owner
, CLSCTX_INPROC_SERVER
, riid
, obj
);
2397 HRESULT
evr_mixer_create(IUnknown
*outer
, void **out
)
2399 struct video_mixer
*object
;
2400 MFVideoNormalizedRect rect
;
2403 if (!(object
= calloc(1, sizeof(*object
))))
2404 return E_OUTOFMEMORY
;
2406 object
->IMFTransform_iface
.lpVtbl
= &video_mixer_transform_vtbl
;
2407 object
->IMFVideoDeviceID_iface
.lpVtbl
= &video_mixer_device_id_vtbl
;
2408 object
->IMFTopologyServiceLookupClient_iface
.lpVtbl
= &video_mixer_service_client_vtbl
;
2409 object
->IMFVideoMixerControl2_iface
.lpVtbl
= &video_mixer_control_vtbl
;
2410 object
->IMFGetService_iface
.lpVtbl
= &video_mixer_getservice_vtbl
;
2411 object
->IMFVideoMixerBitmap_iface
.lpVtbl
= &video_mixer_bitmap_vtbl
;
2412 object
->IMFVideoPositionMapper_iface
.lpVtbl
= &video_mixer_position_mapper_vtbl
;
2413 object
->IMFVideoProcessor_iface
.lpVtbl
= &video_mixer_processor_vtbl
;
2414 object
->IMFAttributes_iface
.lpVtbl
= &video_mixer_attributes_vtbl
;
2415 object
->IMFQualityAdvise_iface
.lpVtbl
= &video_mixer_quality_advise_vtbl
;
2416 object
->IMFClockStateSink_iface
.lpVtbl
= &video_mixer_clock_state_sink_vtbl
;
2417 object
->IUnknown_inner
.lpVtbl
= &video_mixer_inner_vtbl
;
2418 object
->outer_unk
= outer
? outer
: &object
->IUnknown_inner
;
2419 object
->refcount
= 1;
2420 object
->input_count
= 1;
2421 object
->lower_bound
= MFT_OUTPUT_BOUND_LOWER_UNBOUNDED
;
2422 object
->upper_bound
= MFT_OUTPUT_BOUND_UPPER_UNBOUNDED
;
2423 video_mixer_init_input(&object
->inputs
[0]);
2424 InitializeCriticalSection(&object
->cs
);
2425 if (FAILED(hr
= MFCreateAttributes(&object
->attributes
, 0)))
2427 IUnknown_Release(&object
->IUnknown_inner
);
2430 if (FAILED(hr
= MFCreateAttributes(&object
->internal_attributes
, 0)))
2432 IUnknown_Release(&object
->IUnknown_inner
);
2436 /* Default attributes configuration. */
2438 rect
.left
= rect
.top
= 0.0f
;
2439 rect
.right
= rect
.bottom
= 1.0f
;
2440 IMFAttributes_SetBlob(object
->attributes
, &VIDEO_ZOOM_RECT
, (const UINT8
*)&rect
, sizeof(rect
));
2442 IMFAttributes_SetUINT32(object
->internal_attributes
, &MF_SA_D3D_AWARE
, 1);
2444 *out
= &object
->IUnknown_inner
;