2 * Copyright 2020 Nikolay Sivov
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2.1 of the License, or (at your option) any later version.
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
27 #include "evr_classes.h"
28 #include "evr_private.h"
34 #include "wine/debug.h"
36 WINE_DEFAULT_DEBUG_CHANNEL(evr
);
38 #define MAX_MIXER_INPUT_STREAMS 16
43 IMFAttributes
*attributes
;
44 IMFMediaType
*media_type
;
45 MFVideoNormalizedRect rect
;
48 unsigned int sample_requested
: 1;
55 IMFMediaType
*media_type
;
60 IMFMediaType
*media_type
;
61 struct rt_format
*rt_formats
;
62 unsigned int rt_formats_count
;
67 IMFTransform IMFTransform_iface
;
68 IMFVideoDeviceID IMFVideoDeviceID_iface
;
69 IMFTopologyServiceLookupClient IMFTopologyServiceLookupClient_iface
;
70 IMFVideoMixerControl2 IMFVideoMixerControl2_iface
;
71 IMFGetService IMFGetService_iface
;
72 IMFVideoMixerBitmap IMFVideoMixerBitmap_iface
;
73 IMFVideoPositionMapper IMFVideoPositionMapper_iface
;
74 IMFVideoProcessor IMFVideoProcessor_iface
;
75 IMFAttributes IMFAttributes_iface
;
76 IMFQualityAdvise IMFQualityAdvise_iface
;
77 IMFClockStateSink IMFClockStateSink_iface
;
78 IUnknown IUnknown_inner
;
82 struct input_stream inputs
[MAX_MIXER_INPUT_STREAMS
];
83 unsigned int input_ids
[MAX_MIXER_INPUT_STREAMS
];
84 struct input_stream
*zorder
[MAX_MIXER_INPUT_STREAMS
];
85 unsigned int input_count
;
86 struct output_stream output
;
88 IDirect3DDeviceManager9
*device_manager
;
89 IDirectXVideoProcessor
*processor
;
92 IMediaEventSink
*event_sink
;
93 IMFAttributes
*attributes
;
94 IMFAttributes
*internal_attributes
;
95 unsigned int mixing_flags
;
96 unsigned int is_streaming
;
103 static struct video_mixer
*impl_from_IUnknown(IUnknown
*iface
)
105 return CONTAINING_RECORD(iface
, struct video_mixer
, IUnknown_inner
);
108 static struct video_mixer
*impl_from_IMFTransform(IMFTransform
*iface
)
110 return CONTAINING_RECORD(iface
, struct video_mixer
, IMFTransform_iface
);
113 static struct video_mixer
*impl_from_IMFVideoDeviceID(IMFVideoDeviceID
*iface
)
115 return CONTAINING_RECORD(iface
, struct video_mixer
, IMFVideoDeviceID_iface
);
118 static struct video_mixer
*impl_from_IMFTopologyServiceLookupClient(IMFTopologyServiceLookupClient
*iface
)
120 return CONTAINING_RECORD(iface
, struct video_mixer
, IMFTopologyServiceLookupClient_iface
);
123 static struct video_mixer
*impl_from_IMFVideoMixerControl2(IMFVideoMixerControl2
*iface
)
125 return CONTAINING_RECORD(iface
, struct video_mixer
, IMFVideoMixerControl2_iface
);
128 static struct video_mixer
*impl_from_IMFGetService(IMFGetService
*iface
)
130 return CONTAINING_RECORD(iface
, struct video_mixer
, IMFGetService_iface
);
133 static struct video_mixer
*impl_from_IMFVideoMixerBitmap(IMFVideoMixerBitmap
*iface
)
135 return CONTAINING_RECORD(iface
, struct video_mixer
, IMFVideoMixerBitmap_iface
);
138 static struct video_mixer
*impl_from_IMFVideoPositionMapper(IMFVideoPositionMapper
*iface
)
140 return CONTAINING_RECORD(iface
, struct video_mixer
, IMFVideoPositionMapper_iface
);
143 static struct video_mixer
*impl_from_IMFVideoProcessor(IMFVideoProcessor
*iface
)
145 return CONTAINING_RECORD(iface
, struct video_mixer
, IMFVideoProcessor_iface
);
148 static struct video_mixer
*impl_from_IMFAttributes(IMFAttributes
*iface
)
150 return CONTAINING_RECORD(iface
, struct video_mixer
, IMFAttributes_iface
);
153 static struct video_mixer
*impl_from_IMFQualityAdvise(IMFQualityAdvise
*iface
)
155 return CONTAINING_RECORD(iface
, struct video_mixer
, IMFQualityAdvise_iface
);
158 static struct video_mixer
*impl_from_IMFClockStateSink(IMFClockStateSink
*iface
)
160 return CONTAINING_RECORD(iface
, struct video_mixer
, IMFClockStateSink_iface
);
163 static int __cdecl
video_mixer_compare_input_id(const void *a
, const void *b
)
165 const unsigned int *key
= a
;
166 const struct input_stream
*input
= b
;
168 if (*key
> input
->id
) return 1;
169 if (*key
< input
->id
) return -1;
173 static HRESULT
video_mixer_get_input(const struct video_mixer
*mixer
, unsigned int id
, struct input_stream
**stream
)
175 *stream
= bsearch(&id
, mixer
->inputs
, mixer
->input_count
, sizeof(*mixer
->inputs
), video_mixer_compare_input_id
);
176 return *stream
? S_OK
: MF_E_INVALIDSTREAMNUMBER
;
179 static void video_mixer_init_input(struct input_stream
*stream
)
181 if (SUCCEEDED(MFCreateAttributes(&stream
->attributes
, 1)))
182 IMFAttributes_SetUINT32(stream
->attributes
, &MF_SA_REQUIRED_SAMPLE_COUNT
, 1);
183 stream
->rect
.left
= stream
->rect
.top
= 0.0f
;
184 stream
->rect
.right
= stream
->rect
.bottom
= 1.0f
;
187 static int __cdecl
video_mixer_zorder_sort_compare(const void *a
, const void *b
)
189 const struct input_stream
*left
= *(void **)a
, *right
= *(void **)b
;
190 return left
->zorder
!= right
->zorder
? (left
->zorder
< right
->zorder
? -1 : 1) : 0;
193 static void video_mixer_update_zorder_map(struct video_mixer
*mixer
)
197 for (i
= 0; i
< mixer
->input_count
; ++i
)
198 mixer
->zorder
[i
] = &mixer
->inputs
[i
];
200 qsort(mixer
->zorder
, mixer
->input_count
, sizeof(*mixer
->zorder
), video_mixer_zorder_sort_compare
);
203 static void video_mixer_clear_types(struct video_mixer
*mixer
)
207 for (i
= 0; i
< mixer
->input_count
; ++i
)
209 if (mixer
->inputs
[i
].media_type
)
210 IMFMediaType_Release(mixer
->inputs
[i
].media_type
);
211 mixer
->inputs
[i
].media_type
= NULL
;
212 if (mixer
->inputs
[i
].sample
)
213 IMFSample_Release(mixer
->inputs
[i
].sample
);
214 mixer
->inputs
[i
].sample
= NULL
;
216 for (i
= 0; i
< mixer
->output
.rt_formats_count
; ++i
)
218 IMFMediaType_Release(mixer
->output
.rt_formats
[i
].media_type
);
220 free(mixer
->output
.rt_formats
);
221 if (mixer
->output
.media_type
)
222 IMFMediaType_Release(mixer
->output
.media_type
);
223 mixer
->output
.media_type
= NULL
;
226 static HRESULT WINAPI
video_mixer_inner_QueryInterface(IUnknown
*iface
, REFIID riid
, void **obj
)
228 struct video_mixer
*mixer
= impl_from_IUnknown(iface
);
230 TRACE("%p, %s, %p.\n", iface
, debugstr_guid(riid
), obj
);
232 if (IsEqualIID(riid
, &IID_IUnknown
))
236 else if (IsEqualIID(riid
, &IID_IMFTransform
))
238 *obj
= &mixer
->IMFTransform_iface
;
240 else if (IsEqualIID(riid
, &IID_IMFVideoDeviceID
))
242 *obj
= &mixer
->IMFVideoDeviceID_iface
;
244 else if (IsEqualIID(riid
, &IID_IMFTopologyServiceLookupClient
))
246 *obj
= &mixer
->IMFTopologyServiceLookupClient_iface
;
248 else if (IsEqualIID(riid
, &IID_IMFVideoMixerControl2
) ||
249 IsEqualIID(riid
, &IID_IMFVideoMixerControl
))
251 *obj
= &mixer
->IMFVideoMixerControl2_iface
;
253 else if (IsEqualIID(riid
, &IID_IMFGetService
))
255 *obj
= &mixer
->IMFGetService_iface
;
257 else if (IsEqualIID(riid
, &IID_IMFVideoMixerBitmap
))
259 *obj
= &mixer
->IMFVideoMixerBitmap_iface
;
261 else if (IsEqualIID(riid
, &IID_IMFVideoPositionMapper
))
263 *obj
= &mixer
->IMFVideoPositionMapper_iface
;
265 else if (IsEqualIID(riid
, &IID_IMFVideoProcessor
))
267 *obj
= &mixer
->IMFVideoProcessor_iface
;
269 else if (IsEqualIID(riid
, &IID_IMFAttributes
))
271 *obj
= &mixer
->IMFAttributes_iface
;
273 else if (IsEqualIID(riid
, &IID_IMFQualityAdvise
))
275 *obj
= &mixer
->IMFQualityAdvise_iface
;
277 else if (IsEqualIID(riid
, &IID_IMFClockStateSink
))
279 *obj
= &mixer
->IMFClockStateSink_iface
;
283 WARN("Unsupported interface %s.\n", debugstr_guid(riid
));
285 return E_NOINTERFACE
;
288 IUnknown_AddRef((IUnknown
*)*obj
);
292 static ULONG WINAPI
video_mixer_inner_AddRef(IUnknown
*iface
)
294 struct video_mixer
*mixer
= impl_from_IUnknown(iface
);
295 ULONG refcount
= InterlockedIncrement(&mixer
->refcount
);
297 TRACE("%p, refcount %u.\n", iface
, refcount
);
302 static void video_mixer_release_device_manager(struct video_mixer
*mixer
)
304 if (mixer
->processor
)
305 IDirectXVideoProcessor_Release(mixer
->processor
);
306 if (mixer
->device_manager
)
308 IDirect3DDeviceManager9_CloseDeviceHandle(mixer
->device_manager
, mixer
->device_handle
);
309 IDirect3DDeviceManager9_Release(mixer
->device_manager
);
311 mixer
->device_handle
= NULL
;
312 mixer
->device_manager
= NULL
;
313 mixer
->processor
= NULL
;
316 static ULONG WINAPI
video_mixer_inner_Release(IUnknown
*iface
)
318 struct video_mixer
*mixer
= impl_from_IUnknown(iface
);
319 ULONG refcount
= InterlockedDecrement(&mixer
->refcount
);
322 TRACE("%p, refcount %u.\n", iface
, refcount
);
326 for (i
= 0; i
< mixer
->input_count
; ++i
)
328 if (mixer
->inputs
[i
].attributes
)
329 IMFAttributes_Release(mixer
->inputs
[i
].attributes
);
331 video_mixer_clear_types(mixer
);
332 video_mixer_release_device_manager(mixer
);
333 if (mixer
->attributes
)
334 IMFAttributes_Release(mixer
->attributes
);
335 if (mixer
->internal_attributes
)
336 IMFAttributes_Release(mixer
->internal_attributes
);
337 DeleteCriticalSection(&mixer
->cs
);
344 static const IUnknownVtbl video_mixer_inner_vtbl
=
346 video_mixer_inner_QueryInterface
,
347 video_mixer_inner_AddRef
,
348 video_mixer_inner_Release
,
351 static HRESULT WINAPI
video_mixer_transform_QueryInterface(IMFTransform
*iface
, REFIID riid
, void **obj
)
353 struct video_mixer
*mixer
= impl_from_IMFTransform(iface
);
354 return IUnknown_QueryInterface(mixer
->outer_unk
, riid
, obj
);
357 static ULONG WINAPI
video_mixer_transform_AddRef(IMFTransform
*iface
)
359 struct video_mixer
*mixer
= impl_from_IMFTransform(iface
);
360 return IUnknown_AddRef(mixer
->outer_unk
);
363 static ULONG WINAPI
video_mixer_transform_Release(IMFTransform
*iface
)
365 struct video_mixer
*mixer
= impl_from_IMFTransform(iface
);
366 return IUnknown_Release(mixer
->outer_unk
);
369 static HRESULT WINAPI
video_mixer_transform_GetStreamLimits(IMFTransform
*iface
, DWORD
*input_minimum
,
370 DWORD
*input_maximum
, DWORD
*output_minimum
, DWORD
*output_maximum
)
372 TRACE("%p, %p, %p, %p, %p.\n", iface
, input_minimum
, input_maximum
, output_minimum
, output_maximum
);
375 *input_maximum
= MAX_MIXER_INPUT_STREAMS
;
382 static HRESULT WINAPI
video_mixer_transform_GetStreamCount(IMFTransform
*iface
, DWORD
*inputs
, DWORD
*outputs
)
384 struct video_mixer
*mixer
= impl_from_IMFTransform(iface
);
386 TRACE("%p, %p, %p.\n", iface
, inputs
, outputs
);
388 EnterCriticalSection(&mixer
->cs
);
389 if (inputs
) *inputs
= mixer
->input_count
;
390 if (outputs
) *outputs
= 1;
391 LeaveCriticalSection(&mixer
->cs
);
396 static HRESULT WINAPI
video_mixer_transform_GetStreamIDs(IMFTransform
*iface
, DWORD input_size
, DWORD
*inputs
,
397 DWORD output_size
, DWORD
*outputs
)
399 struct video_mixer
*mixer
= impl_from_IMFTransform(iface
);
402 TRACE("%p, %u, %p, %u, %p.\n", iface
, input_size
, inputs
, output_size
, outputs
);
404 EnterCriticalSection(&mixer
->cs
);
405 if (mixer
->input_count
> input_size
|| !output_size
)
406 hr
= MF_E_BUFFERTOOSMALL
;
408 memcpy(inputs
, mixer
->input_ids
, mixer
->input_count
* sizeof(*inputs
));
409 if (outputs
) *outputs
= 0;
410 LeaveCriticalSection(&mixer
->cs
);
415 static HRESULT WINAPI
video_mixer_transform_GetInputStreamInfo(IMFTransform
*iface
, DWORD id
, MFT_INPUT_STREAM_INFO
*info
)
417 struct video_mixer
*mixer
= impl_from_IMFTransform(iface
);
418 struct input_stream
*input
;
421 TRACE("%p, %u, %p.\n", iface
, id
, info
);
423 EnterCriticalSection(&mixer
->cs
);
425 if (SUCCEEDED(hr
= video_mixer_get_input(mixer
, id
, &input
)))
427 memset(info
, 0, sizeof(*info
));
429 info
->dwFlags
|= MFT_INPUT_STREAM_REMOVABLE
| MFT_INPUT_STREAM_OPTIONAL
;
432 LeaveCriticalSection(&mixer
->cs
);
437 static HRESULT WINAPI
video_mixer_transform_GetOutputStreamInfo(IMFTransform
*iface
, DWORD id
, MFT_OUTPUT_STREAM_INFO
*info
)
439 TRACE("%p, %u, %p.\n", iface
, id
, info
);
442 return MF_E_INVALIDSTREAMNUMBER
;
444 memset(info
, 0, sizeof(*info
));
449 static HRESULT WINAPI
video_mixer_transform_GetAttributes(IMFTransform
*iface
, IMFAttributes
**attributes
)
451 struct video_mixer
*mixer
= impl_from_IMFTransform(iface
);
453 TRACE("%p, %p.\n", iface
, attributes
);
458 *attributes
= mixer
->attributes
;
459 IMFAttributes_AddRef(*attributes
);
464 static HRESULT WINAPI
video_mixer_transform_GetInputStreamAttributes(IMFTransform
*iface
, DWORD id
,
465 IMFAttributes
**attributes
)
467 struct video_mixer
*mixer
= impl_from_IMFTransform(iface
);
468 struct input_stream
*input
;
471 TRACE("%p, %u, %p.\n", iface
, id
, attributes
);
473 EnterCriticalSection(&mixer
->cs
);
475 if (SUCCEEDED(hr
= video_mixer_get_input(mixer
, id
, &input
)))
477 *attributes
= input
->attributes
;
479 IMFAttributes_AddRef(*attributes
);
482 LeaveCriticalSection(&mixer
->cs
);
487 static HRESULT WINAPI
video_mixer_transform_GetOutputStreamAttributes(IMFTransform
*iface
, DWORD id
,
488 IMFAttributes
**attributes
)
490 TRACE("%p, %u, %p.\n", iface
, id
, attributes
);
495 static HRESULT WINAPI
video_mixer_transform_DeleteInputStream(IMFTransform
*iface
, DWORD id
)
497 struct video_mixer
*mixer
= impl_from_IMFTransform(iface
);
498 struct input_stream
*input
;
502 TRACE("%p, %u.\n", iface
, id
);
505 return MF_E_INVALIDSTREAMNUMBER
;
507 EnterCriticalSection(&mixer
->cs
);
509 /* Can't delete reference stream. */
510 if (SUCCEEDED(hr
= video_mixer_get_input(mixer
, id
, &input
)))
512 mixer
->input_count
--;
513 idx
= input
- mixer
->inputs
;
514 if (idx
< mixer
->input_count
)
516 if (mixer
->inputs
[idx
].attributes
)
517 IMFAttributes_Release(mixer
->inputs
[idx
].attributes
);
518 memmove(&mixer
->inputs
[idx
], &mixer
->inputs
[idx
+ 1], (mixer
->input_count
- idx
) * sizeof(*mixer
->inputs
));
519 memmove(&mixer
->input_ids
[idx
], &mixer
->input_ids
[idx
+ 1], (mixer
->input_count
- idx
) *
520 sizeof(*mixer
->input_ids
));
521 video_mixer_update_zorder_map(mixer
);
525 LeaveCriticalSection(&mixer
->cs
);
530 static int __cdecl
video_mixer_add_input_sort_compare(const void *a
, const void *b
)
532 const struct input_stream
*left
= a
, *right
= b
;
533 return left
->id
!= right
->id
? (left
->id
< right
->id
? -1 : 1) : 0;
536 static HRESULT WINAPI
video_mixer_transform_AddInputStreams(IMFTransform
*iface
, DWORD count
, DWORD
*ids
)
538 struct video_mixer
*mixer
= impl_from_IMFTransform(iface
);
539 struct input_stream inputs
[MAX_MIXER_INPUT_STREAMS
] = { {0} };
540 struct input_stream
*input
;
544 TRACE("%p, %u, %p.\n", iface
, count
, ids
);
549 EnterCriticalSection(&mixer
->cs
);
550 if (count
> ARRAY_SIZE(mixer
->inputs
) - mixer
->input_count
)
554 /* Test for collisions. */
555 memcpy(inputs
, mixer
->inputs
, mixer
->input_count
* sizeof(*inputs
));
556 for (i
= 0; i
< count
; ++i
)
557 inputs
[i
+ mixer
->input_count
].id
= ids
[i
];
559 len
= mixer
->input_count
+ count
;
561 qsort(inputs
, len
, sizeof(*inputs
), video_mixer_add_input_sort_compare
);
563 for (i
= 1; i
< len
; ++i
)
565 if (inputs
[i
- 1].id
== inputs
[i
].id
)
574 unsigned int zorder
= mixer
->input_count
;
576 for (i
= 0; i
< count
; ++i
)
578 if ((input
= bsearch(&ids
[i
], inputs
, len
, sizeof(*inputs
), video_mixer_compare_input_id
)))
579 video_mixer_init_input(input
);
581 memcpy(&mixer
->input_ids
[mixer
->input_count
], ids
, count
* sizeof(*ids
));
582 memcpy(mixer
->inputs
, inputs
, len
* sizeof(*inputs
));
583 mixer
->input_count
+= count
;
585 for (i
= 0; i
< count
; ++i
)
587 if (SUCCEEDED(video_mixer_get_input(mixer
, ids
[i
], &input
)))
588 input
->zorder
= zorder
;
592 video_mixer_update_zorder_map(mixer
);
595 LeaveCriticalSection(&mixer
->cs
);
600 static HRESULT WINAPI
video_mixer_transform_GetInputAvailableType(IMFTransform
*iface
, DWORD id
, DWORD index
,
603 TRACE("%p, %u, %u, %p.\n", iface
, id
, index
, type
);
608 static HRESULT WINAPI
video_mixer_transform_GetOutputAvailableType(IMFTransform
*iface
, DWORD id
, DWORD index
,
611 struct video_mixer
*mixer
= impl_from_IMFTransform(iface
);
614 TRACE("%p, %u, %u, %p.\n", iface
, id
, index
, type
);
617 return MF_E_INVALIDSTREAMNUMBER
;
619 EnterCriticalSection(&mixer
->cs
);
621 if (!mixer
->inputs
[0].media_type
)
622 hr
= MF_E_TRANSFORM_TYPE_NOT_SET
;
623 else if (index
>= mixer
->output
.rt_formats_count
)
624 hr
= MF_E_NO_MORE_TYPES
;
627 if (SUCCEEDED(hr
= MFCreateMediaType(type
)))
628 hr
= IMFMediaType_CopyAllItems(mixer
->output
.rt_formats
[index
].media_type
, (IMFAttributes
*)*type
);
631 LeaveCriticalSection(&mixer
->cs
);
636 static HRESULT
video_mixer_init_dxva_videodesc(IMFMediaType
*media_type
, DXVA2_VideoDesc
*video_desc
)
638 const MFVIDEOFORMAT
*video_format
;
639 IMFVideoMediaType
*video_type
;
640 BOOL is_compressed
= TRUE
;
643 if (FAILED(IMFMediaType_QueryInterface(media_type
, &IID_IMFVideoMediaType
, (void **)&video_type
)))
644 return MF_E_INVALIDMEDIATYPE
;
646 video_format
= IMFVideoMediaType_GetVideoFormat(video_type
);
647 IMFVideoMediaType_IsCompressedFormat(video_type
, &is_compressed
);
649 if (!video_format
|| !video_format
->videoInfo
.dwWidth
|| !video_format
->videoInfo
.dwHeight
|| is_compressed
)
651 hr
= MF_E_INVALIDMEDIATYPE
;
655 memset(video_desc
, 0, sizeof(*video_desc
));
656 video_desc
->SampleWidth
= video_format
->videoInfo
.dwWidth
;
657 video_desc
->SampleHeight
= video_format
->videoInfo
.dwHeight
;
658 video_desc
->Format
= video_format
->surfaceInfo
.Format
;
661 IMFVideoMediaType_Release(video_type
);
666 static void video_mixer_append_rt_format(struct rt_format
*rt_formats
, unsigned int *count
,
667 const GUID
*device
, D3DFORMAT format
)
671 for (i
= 0; i
< *count
; ++i
)
673 if (rt_formats
[i
].format
== format
) return;
676 rt_formats
[*count
].format
= format
;
677 rt_formats
[*count
].device
= *device
;
681 static unsigned int video_mixer_get_interlace_mode_from_video_desc(const DXVA2_VideoDesc
*video_desc
)
683 switch (video_desc
->SampleFormat
.SampleFormat
)
685 case DXVA2_SampleFieldInterleavedEvenFirst
:
686 return MFVideoInterlace_FieldInterleavedUpperFirst
;
687 case DXVA2_SampleFieldInterleavedOddFirst
:
688 return MFVideoInterlace_FieldInterleavedLowerFirst
;
689 case DXVA2_SampleFieldSingleEven
:
690 return MFVideoInterlace_FieldSingleUpper
;
691 case DXVA2_SampleFieldSingleOdd
:
692 return MFVideoInterlace_FieldSingleLower
;
694 return MFVideoInterlace_Progressive
;
698 static void mf_get_attribute_uint32(IMFMediaType
*media_type
, const GUID
*key
, UINT32
*value
,
699 UINT32 default_value
)
701 if (FAILED(IMFMediaType_GetUINT32(media_type
, key
, value
)))
702 *value
= default_value
;
705 static void mf_get_attribute_uint64(IMFMediaType
*media_type
, const GUID
*key
, UINT64
*value
,
706 UINT64 default_value
)
708 if (FAILED(IMFMediaType_GetUINT64(media_type
, key
, value
)))
709 *value
= default_value
;
712 static HRESULT
video_mixer_collect_output_types(struct video_mixer
*mixer
, const DXVA2_VideoDesc
*video_desc
,
713 IMFMediaType
*media_type
, IDirectXVideoProcessorService
*service
, unsigned int device_count
,
714 const GUID
*devices
, unsigned int flags
)
716 struct rt_format
*rt_formats
= NULL
, *ptr
;
717 unsigned int i
, j
, format_count
, count
;
718 HRESULT hr
= MF_E_INVALIDMEDIATYPE
;
723 for (i
= 0; i
< device_count
; ++i
)
725 if (SUCCEEDED(IDirectXVideoProcessorService_GetVideoProcessorRenderTargets(service
, &devices
[i
], video_desc
,
726 &format_count
, &formats
)))
728 if (!(ptr
= realloc(rt_formats
, (count
+ format_count
) * sizeof(*rt_formats
))))
732 CoTaskMemFree(formats
);
737 for (j
= 0; j
< format_count
; ++j
)
738 video_mixer_append_rt_format(rt_formats
, &count
, &devices
[i
], formats
[j
]);
740 CoTaskMemFree(formats
);
744 if (count
&& !(flags
& MFT_SET_TYPE_TEST_ONLY
))
746 UINT32 fixed_samples
, interlace_mode
;
747 MFVideoArea aperture
;
750 if (!(mixer
->output
.rt_formats
= calloc(count
, sizeof(*mixer
->output
.rt_formats
))))
753 return E_OUTOFMEMORY
;
756 memcpy(&subtype
, &MFVideoFormat_Base
, sizeof(subtype
));
757 memset(&aperture
, 0, sizeof(aperture
));
758 if (FAILED(IMFMediaType_GetBlob(media_type
, &MF_MT_GEOMETRIC_APERTURE
, (UINT8
*)&aperture
,
759 sizeof(aperture
), NULL
)))
761 aperture
.Area
.cx
= video_desc
->SampleWidth
;
762 aperture
.Area
.cy
= video_desc
->SampleHeight
;
764 interlace_mode
= video_mixer_get_interlace_mode_from_video_desc(video_desc
);
765 mf_get_attribute_uint64(media_type
, &MF_MT_PIXEL_ASPECT_RATIO
, &par
, (UINT64
)1 << 32 | 1);
766 mf_get_attribute_uint32(media_type
, &MF_MT_FIXED_SIZE_SAMPLES
, &fixed_samples
, 1);
768 for (i
= 0; i
< count
; ++i
)
770 IMFMediaType
*rt_media_type
;
772 subtype
.Data1
= rt_formats
[i
].format
;
773 mixer
->output
.rt_formats
[i
] = rt_formats
[i
];
775 MFCreateMediaType(&rt_media_type
);
776 IMFMediaType_CopyAllItems(media_type
, (IMFAttributes
*)rt_media_type
);
777 IMFMediaType_SetGUID(rt_media_type
, &MF_MT_SUBTYPE
, &subtype
);
778 IMFMediaType_SetUINT64(rt_media_type
, &MF_MT_FRAME_SIZE
, (UINT64
)aperture
.Area
.cx
<< 32 | aperture
.Area
.cy
);
779 IMFMediaType_SetBlob(rt_media_type
, &MF_MT_GEOMETRIC_APERTURE
, (const UINT8
*)&aperture
, sizeof(aperture
));
780 IMFMediaType_SetBlob(rt_media_type
, &MF_MT_MINIMUM_DISPLAY_APERTURE
, (const UINT8
*)&aperture
, sizeof(aperture
));
781 IMFMediaType_SetUINT32(rt_media_type
, &MF_MT_INTERLACE_MODE
, interlace_mode
);
782 IMFMediaType_SetUINT64(rt_media_type
, &MF_MT_PIXEL_ASPECT_RATIO
, par
);
783 IMFMediaType_SetUINT32(rt_media_type
, &MF_MT_FIXED_SIZE_SAMPLES
, fixed_samples
);
785 mixer
->output
.rt_formats
[i
].media_type
= rt_media_type
;
787 mixer
->output
.rt_formats_count
= count
;
792 return count
? S_OK
: hr
;
795 static HRESULT
video_mixer_open_device_handle(struct video_mixer
*mixer
)
797 IDirect3DDeviceManager9_CloseDeviceHandle(mixer
->device_manager
, mixer
->device_handle
);
798 mixer
->device_handle
= NULL
;
799 return IDirect3DDeviceManager9_OpenDeviceHandle(mixer
->device_manager
, &mixer
->device_handle
);
802 static HRESULT
video_mixer_get_processor_service(struct video_mixer
*mixer
, IDirectXVideoProcessorService
**service
)
806 if (!mixer
->device_handle
)
808 if (FAILED(hr
= IDirect3DDeviceManager9_OpenDeviceHandle(mixer
->device_manager
, &mixer
->device_handle
)))
814 hr
= IDirect3DDeviceManager9_GetVideoService(mixer
->device_manager
, mixer
->device_handle
,
815 &IID_IDirectXVideoProcessorService
, (void **)service
);
816 if (hr
== DXVA2_E_NEW_VIDEO_DEVICE
)
818 if (SUCCEEDED(hr
= video_mixer_open_device_handle(mixer
)))
827 static HRESULT WINAPI
video_mixer_transform_SetInputType(IMFTransform
*iface
, DWORD id
, IMFMediaType
*media_type
, DWORD flags
)
829 struct video_mixer
*mixer
= impl_from_IMFTransform(iface
);
830 IDirectXVideoProcessorService
*service
;
831 DXVA2_VideoDesc video_desc
;
832 HRESULT hr
= E_NOTIMPL
;
836 TRACE("%p, %u, %p, %#x.\n", iface
, id
, media_type
, flags
);
838 EnterCriticalSection(&mixer
->cs
);
840 if (!(flags
& MFT_SET_TYPE_TEST_ONLY
))
841 video_mixer_clear_types(mixer
);
843 if (!mixer
->device_manager
)
844 hr
= MF_E_NOT_INITIALIZED
;
847 if (SUCCEEDED(hr
= video_mixer_get_processor_service(mixer
, &service
)))
849 if (SUCCEEDED(hr
= video_mixer_init_dxva_videodesc(media_type
, &video_desc
)))
853 if (SUCCEEDED(hr
= IDirectXVideoProcessorService_GetVideoProcessorDeviceGuids(service
, &video_desc
,
856 if (SUCCEEDED(hr
= video_mixer_collect_output_types(mixer
, &video_desc
, media_type
,
857 service
, count
, guids
, flags
)) && !(flags
& MFT_SET_TYPE_TEST_ONLY
))
859 if (mixer
->inputs
[0].media_type
)
860 IMFMediaType_Release(mixer
->inputs
[0].media_type
);
861 mixer
->inputs
[0].media_type
= media_type
;
862 IMFMediaType_AddRef(mixer
->inputs
[0].media_type
);
864 CoTaskMemFree(guids
);
869 FIXME("Unimplemented for substreams.\n");
873 IDirectXVideoProcessorService_Release(service
);
877 LeaveCriticalSection(&mixer
->cs
);
882 static HRESULT WINAPI
video_mixer_transform_SetOutputType(IMFTransform
*iface
, DWORD id
, IMFMediaType
*type
, DWORD flags
)
884 const unsigned int equality_flags
= MF_MEDIATYPE_EQUAL_MAJOR_TYPES
| MF_MEDIATYPE_EQUAL_FORMAT_TYPES
;
885 struct video_mixer
*mixer
= impl_from_IMFTransform(iface
);
886 HRESULT hr
= MF_E_INVALIDMEDIATYPE
;
887 unsigned int i
, compare_flags
;
888 BOOL is_compressed
= TRUE
;
890 TRACE("%p, %u, %p, %#x.\n", iface
, id
, type
, flags
);
893 return MF_E_INVALIDSTREAMNUMBER
;
898 if (FAILED(IMFMediaType_IsCompressedFormat(type
, &is_compressed
)) || is_compressed
)
899 return MF_E_INVALIDMEDIATYPE
;
901 EnterCriticalSection(&mixer
->cs
);
903 for (i
= 0; i
< mixer
->output
.rt_formats_count
; ++i
)
906 if (FAILED(IMFMediaType_IsEqual(type
, mixer
->output
.rt_formats
[i
].media_type
, &compare_flags
)))
909 if ((compare_flags
& equality_flags
) == equality_flags
)
916 if (SUCCEEDED(hr
) && !(flags
& MFT_SET_TYPE_TEST_ONLY
))
918 IDirectXVideoProcessorService
*service
;
920 if (SUCCEEDED(hr
= video_mixer_get_processor_service(mixer
, &service
)))
922 DXVA2_VideoDesc video_desc
;
923 GUID subtype
= { 0 };
926 if (mixer
->processor
)
927 IDirectXVideoProcessor_Release(mixer
->processor
);
928 mixer
->processor
= NULL
;
930 video_mixer_init_dxva_videodesc(mixer
->inputs
[0].media_type
, &video_desc
);
931 IMFMediaType_GetGUID(type
, &MF_MT_SUBTYPE
, &subtype
);
932 rt_format
= subtype
.Data1
;
934 if (SUCCEEDED(hr
= IDirectXVideoProcessorService_CreateVideoProcessor(service
, &mixer
->output
.rt_formats
[i
].device
,
935 &video_desc
, rt_format
, MAX_MIXER_INPUT_STREAMS
, &mixer
->processor
)))
937 if (mixer
->output
.media_type
)
938 IMFMediaType_Release(mixer
->output
.media_type
);
939 mixer
->output
.media_type
= type
;
940 IMFMediaType_AddRef(mixer
->output
.media_type
);
943 IDirectXVideoProcessorService_Release(service
);
947 LeaveCriticalSection(&mixer
->cs
);
952 static HRESULT WINAPI
video_mixer_transform_GetInputCurrentType(IMFTransform
*iface
, DWORD id
, IMFMediaType
**type
)
954 struct video_mixer
*mixer
= impl_from_IMFTransform(iface
);
955 struct input_stream
*stream
;
958 TRACE("%p, %u, %p.\n", iface
, id
, type
);
960 EnterCriticalSection(&mixer
->cs
);
962 if (SUCCEEDED(hr
= video_mixer_get_input(mixer
, id
, &stream
)))
964 if (!stream
->media_type
)
965 hr
= MF_E_TRANSFORM_TYPE_NOT_SET
;
968 *type
= stream
->media_type
;
969 IMFMediaType_AddRef(*type
);
973 LeaveCriticalSection(&mixer
->cs
);
978 static HRESULT WINAPI
video_mixer_transform_GetOutputCurrentType(IMFTransform
*iface
, DWORD id
, IMFMediaType
**type
)
980 struct video_mixer
*mixer
= impl_from_IMFTransform(iface
);
983 TRACE("%p, %u, %p.\n", iface
, id
, type
);
986 return MF_E_INVALIDSTREAMNUMBER
;
988 EnterCriticalSection(&mixer
->cs
);
990 if (!mixer
->output
.media_type
)
991 hr
= MF_E_TRANSFORM_TYPE_NOT_SET
;
994 *type
= mixer
->output
.media_type
;
995 IMFMediaType_AddRef(*type
);
998 LeaveCriticalSection(&mixer
->cs
);
1003 static HRESULT WINAPI
video_mixer_transform_GetInputStatus(IMFTransform
*iface
, DWORD id
, DWORD
*status
)
1005 struct video_mixer
*mixer
= impl_from_IMFTransform(iface
);
1006 struct input_stream
*stream
;
1009 TRACE("%p, %u, %p.\n", iface
, id
, status
);
1014 EnterCriticalSection(&mixer
->cs
);
1016 if (!mixer
->output
.media_type
)
1017 hr
= MF_E_TRANSFORM_TYPE_NOT_SET
;
1018 else if (SUCCEEDED(hr
= video_mixer_get_input(mixer
, id
, &stream
)))
1020 *status
= stream
->sample
? 0 : MFT_INPUT_STATUS_ACCEPT_DATA
;
1023 LeaveCriticalSection(&mixer
->cs
);
1028 static HRESULT WINAPI
video_mixer_transform_GetOutputStatus(IMFTransform
*iface
, DWORD
*status
)
1030 struct video_mixer
*mixer
= impl_from_IMFTransform(iface
);
1034 TRACE("%p, %p.\n", iface
, status
);
1039 EnterCriticalSection(&mixer
->cs
);
1041 if (!mixer
->output
.media_type
)
1042 hr
= MF_E_TRANSFORM_TYPE_NOT_SET
;
1045 *status
= MFT_OUTPUT_STATUS_SAMPLE_READY
;
1046 for (i
= 0; i
< mixer
->input_count
; ++i
)
1048 if (!mixer
->inputs
[i
].sample
)
1056 LeaveCriticalSection(&mixer
->cs
);
1061 static HRESULT WINAPI
video_mixer_transform_SetOutputBounds(IMFTransform
*iface
, LONGLONG lower
, LONGLONG upper
)
1063 struct video_mixer
*mixer
= impl_from_IMFTransform(iface
);
1065 TRACE("%p, %s, %s.\n", iface
, wine_dbgstr_longlong(lower
), wine_dbgstr_longlong(upper
));
1067 EnterCriticalSection(&mixer
->cs
);
1069 mixer
->lower_bound
= lower
;
1070 mixer
->upper_bound
= upper
;
1072 LeaveCriticalSection(&mixer
->cs
);
1077 static HRESULT WINAPI
video_mixer_transform_ProcessEvent(IMFTransform
*iface
, DWORD id
, IMFMediaEvent
*event
)
1079 FIXME("%p, %u, %p.\n", iface
, id
, event
);
1084 static void video_mixer_request_sample(struct video_mixer
*mixer
, unsigned int idx
)
1086 if (!mixer
->event_sink
|| mixer
->inputs
[idx
].sample_requested
)
1089 IMediaEventSink_Notify(mixer
->event_sink
, EC_SAMPLE_NEEDED
, idx
, 0);
1090 mixer
->inputs
[idx
].sample_requested
= 1;
1093 static HRESULT WINAPI
video_mixer_transform_ProcessMessage(IMFTransform
*iface
, MFT_MESSAGE_TYPE message
, ULONG_PTR param
)
1095 struct video_mixer
*mixer
= impl_from_IMFTransform(iface
);
1099 TRACE("%p, %#x, %#lx.\n", iface
, message
, param
);
1103 case MFT_MESSAGE_SET_D3D_MANAGER
:
1105 EnterCriticalSection(&mixer
->cs
);
1107 video_mixer_release_device_manager(mixer
);
1109 hr
= IUnknown_QueryInterface((IUnknown
*)param
, &IID_IDirect3DDeviceManager9
, (void **)&mixer
->device_manager
);
1111 LeaveCriticalSection(&mixer
->cs
);
1115 case MFT_MESSAGE_COMMAND_FLUSH
:
1117 EnterCriticalSection(&mixer
->cs
);
1119 for (i
= 0; i
< mixer
->input_count
; ++i
)
1121 if (mixer
->inputs
[i
].sample
)
1123 IMFSample_Release(mixer
->inputs
[i
].sample
);
1124 mixer
->inputs
[i
].sample
= NULL
;
1125 mixer
->inputs
[i
].sample_requested
= 0;
1129 LeaveCriticalSection(&mixer
->cs
);
1133 case MFT_MESSAGE_NOTIFY_BEGIN_STREAMING
:
1134 case MFT_MESSAGE_NOTIFY_END_STREAMING
:
1136 EnterCriticalSection(&mixer
->cs
);
1138 if (!mixer
->is_streaming
)
1140 for (i
= 0; i
< mixer
->input_count
; ++i
)
1141 video_mixer_request_sample(mixer
, i
);
1144 mixer
->is_streaming
= message
== MFT_MESSAGE_NOTIFY_BEGIN_STREAMING
;
1146 LeaveCriticalSection(&mixer
->cs
);
1150 case MFT_MESSAGE_COMMAND_DRAIN
:
1154 WARN("Message not handled %d.\n", message
);
1161 static HRESULT WINAPI
video_mixer_transform_ProcessInput(IMFTransform
*iface
, DWORD id
, IMFSample
*sample
, DWORD flags
)
1163 struct video_mixer
*mixer
= impl_from_IMFTransform(iface
);
1164 struct input_stream
*input
;
1167 TRACE("%p, %u, %p, %#x.\n", iface
, id
, sample
, flags
);
1172 EnterCriticalSection(&mixer
->cs
);
1174 if (SUCCEEDED(hr
= video_mixer_get_input(mixer
, id
, &input
)))
1176 if (!input
->media_type
|| !mixer
->output
.media_type
)
1177 hr
= MF_E_TRANSFORM_TYPE_NOT_SET
;
1178 else if (input
->sample
)
1179 hr
= MF_E_NOTACCEPTING
;
1182 mixer
->is_streaming
= 1;
1183 input
->sample_requested
= 0;
1184 input
->sample
= sample
;
1185 IMFSample_AddRef(input
->sample
);
1189 LeaveCriticalSection(&mixer
->cs
);
1194 static HRESULT
video_mixer_get_sample_surface(IMFSample
*sample
, IDirect3DSurface9
**surface
)
1196 IMFMediaBuffer
*buffer
;
1200 if (FAILED(hr
= IMFSample_GetBufferByIndex(sample
, 0, &buffer
)))
1203 hr
= IMFMediaBuffer_QueryInterface(buffer
, &IID_IMFGetService
, (void **)&gs
);
1204 IMFMediaBuffer_Release(buffer
);
1208 hr
= IMFGetService_GetService(gs
, &MR_BUFFER_SERVICE
, &IID_IDirect3DSurface9
, (void **)surface
);
1209 IMFGetService_Release(gs
);
1213 static HRESULT
video_mixer_get_d3d_device(struct video_mixer
*mixer
, IDirect3DDevice9
**device
)
1219 hr
= IDirect3DDeviceManager9_LockDevice(mixer
->device_manager
, mixer
->device_handle
,
1221 if (hr
== DXVA2_E_NEW_VIDEO_DEVICE
)
1223 if (SUCCEEDED(hr
= video_mixer_open_device_handle(mixer
)))
1232 static void video_mixer_scale_rect(RECT
*rect
, unsigned int width
, unsigned int height
,
1233 const MFVideoNormalizedRect
*scale
)
1235 if (rect
->left
== 0.0f
&& rect
->top
== 0.0f
&& rect
->right
== 1.0f
&& rect
->bottom
== 1.0f
)
1237 SetRect(rect
, 0, 0, width
, height
);
1241 rect
->left
= width
* scale
->left
;
1242 rect
->right
= width
* scale
->right
;
1243 rect
->top
= height
* scale
->top
;
1244 rect
->bottom
= height
* scale
->bottom
;
1248 static void video_mixer_normalize_rect(const RECT
*full
, const RECT
*part
, MFVideoNormalizedRect
*ret
)
1250 float width
= full
->right
- full
->left
;
1251 float height
= full
->bottom
- full
->top
;
1253 ret
->left
= (part
->left
- full
->left
) / width
;
1254 ret
->right
= (part
->right
- full
->left
) / width
;
1255 ret
->bottom
= (part
->bottom
- full
->top
) / height
;
1256 ret
->top
= (part
->top
- full
->top
) / height
;
1259 static void video_mixer_render(struct video_mixer
*mixer
, IDirect3DSurface9
*rt
)
1261 DXVA2_VideoSample samples
[MAX_MIXER_INPUT_STREAMS
] = {{ 0 }};
1262 DXVA2_VideoProcessBltParams params
= { 0 };
1263 MFVideoNormalizedRect zoom_rect
, norm
;
1264 unsigned int i
, sample_count
= 0;
1265 D3DSURFACE_DESC desc
, rt_desc
;
1266 struct input_stream
*stream
;
1270 IDirect3DSurface9_GetDesc(rt
, &rt_desc
);
1272 if (FAILED(IMFAttributes_GetBlob(mixer
->attributes
, &VIDEO_ZOOM_RECT
, (UINT8
*)&zoom_rect
,
1273 sizeof(zoom_rect
), NULL
)))
1275 zoom_rect
.left
= zoom_rect
.top
= 0.0f
;
1276 zoom_rect
.right
= zoom_rect
.bottom
= 1.0f
;
1279 SetRect(¶ms
.TargetRect
, 0, 0, rt_desc
.Width
, rt_desc
.Height
);
1280 video_mixer_scale_rect(&dst
, rt_desc
.Width
, rt_desc
.Height
, &zoom_rect
);
1282 for (i
= 0; i
< mixer
->input_count
; ++i
)
1284 RECT stream_dst
, stream_vis
;
1286 IDirect3DSurface9
*surface
;
1288 stream
= mixer
->zorder
[i
];
1290 if (FAILED(hr
= video_mixer_get_sample_surface(stream
->sample
, &surface
)))
1292 WARN("Failed to get source surface for stream %u, hr %#x.\n", i
, hr
);
1296 IDirect3DSurface9_GetDesc(surface
, &desc
);
1298 /* In order to compute source/destination rectangles for each stream:
1300 * per-stream rectangle is used to get destination rectangle in target coordinates;
1301 * destination per-stream rectangle is clipped with zoom rectangle, applied to target coordinates;
1302 * visible rectangle is scaled back to get source area of the stream that would be visible;
1303 * visible rectangle is scaled back to get destination area in target coordinates for given steam.
1307 video_mixer_scale_rect(&stream_dst
, rt_desc
.Width
, rt_desc
.Height
, &stream
->rect
);
1309 /* Part of the stream that's visible after zooming. */
1310 if (!IntersectRect(&stream_vis
, &stream_dst
, &dst
))
1312 IDirect3DSurface9_Release(surface
);
1316 samples
[sample_count
].SampleFormat
.SampleFormat
= stream
->id
== 0 ?
1317 DXVA2_SampleProgressiveFrame
: DXVA2_SampleSubStream
;
1318 samples
[sample_count
].SrcSurface
= surface
;
1320 video_mixer_normalize_rect(&stream_dst
, &stream_vis
, &norm
);
1321 video_mixer_scale_rect(&samples
[sample_count
].SrcRect
, desc
.Width
, desc
.Height
, &norm
);
1323 video_mixer_normalize_rect(&dst
, &stream_vis
, &norm
);
1324 video_mixer_scale_rect(&samples
[sample_count
].DstRect
, rt_desc
.Width
, rt_desc
.Height
, &norm
);
1331 if (FAILED(hr
= IDirectXVideoProcessor_VideoProcessBlt(mixer
->processor
, rt
, ¶ms
, samples
,
1332 sample_count
, NULL
)))
1334 WARN("Failed to process samples, hr %#x.\n", hr
);
1338 for (i
= 0; i
< sample_count
; ++i
)
1340 if (samples
[i
].SrcSurface
)
1341 IDirect3DSurface9_Release(samples
[i
].SrcSurface
);
1345 static HRESULT
video_mixer_get_sample_desired_time(IMFSample
*sample
, LONGLONG
*timestamp
, LONGLONG
*duration
)
1347 IMFDesiredSample
*desired
;
1350 if (SUCCEEDED(hr
= IMFSample_QueryInterface(sample
, &IID_IMFDesiredSample
, (void **)&desired
)))
1352 hr
= IMFDesiredSample_GetDesiredSampleTimeAndDuration(desired
, timestamp
, duration
);
1353 IMFDesiredSample_Release(desired
);
1359 static HRESULT WINAPI
video_mixer_transform_ProcessOutput(IMFTransform
*iface
, DWORD flags
, DWORD count
,
1360 MFT_OUTPUT_DATA_BUFFER
*buffers
, DWORD
*status
)
1362 struct video_mixer
*mixer
= impl_from_IMFTransform(iface
);
1363 LONGLONG timestamp
, duration
;
1364 IDirect3DSurface9
*surface
;
1365 IDirect3DDevice9
*device
;
1369 TRACE("%p, %#x, %u, %p, %p.\n", iface
, flags
, count
, buffers
, status
);
1371 if (!buffers
|| !count
|| count
> 1 || !buffers
->pSample
)
1372 return E_INVALIDARG
;
1374 if (buffers
->dwStreamID
)
1375 return MF_E_INVALIDSTREAMNUMBER
;
1379 EnterCriticalSection(&mixer
->cs
);
1381 if (SUCCEEDED(hr
= video_mixer_get_sample_surface(buffers
->pSample
, &surface
)))
1383 if (mixer
->is_streaming
)
1385 for (i
= 0; i
< mixer
->input_count
; ++i
)
1387 if (!mixer
->inputs
[i
].sample
)
1389 hr
= MF_E_TRANSFORM_NEED_MORE_INPUT
;
1396 video_mixer_render(mixer
, surface
);
1398 timestamp
= duration
= 0;
1399 if (SUCCEEDED(IMFSample_GetSampleTime(mixer
->inputs
[0].sample
, ×tamp
)))
1401 IMFSample_SetSampleTime(buffers
->pSample
, timestamp
);
1403 IMFSample_GetSampleDuration(mixer
->inputs
[0].sample
, &duration
);
1404 IMFSample_SetSampleDuration(buffers
->pSample
, duration
);
1410 for (i
= 0; i
< mixer
->input_count
; ++i
)
1412 if (mixer
->inputs
[i
].sample
)
1413 IMFSample_Release(mixer
->inputs
[i
].sample
);
1414 mixer
->inputs
[i
].sample
= NULL
;
1415 video_mixer_request_sample(mixer
, i
);
1421 if (SUCCEEDED(video_mixer_get_sample_desired_time(buffers
->pSample
, ×tamp
, &duration
)))
1423 if (SUCCEEDED(hr
= video_mixer_get_d3d_device(mixer
, &device
)))
1425 IDirect3DDevice9_ColorFill(device
, surface
, NULL
, 0);
1426 IDirect3DDeviceManager9_UnlockDevice(mixer
->device_manager
, mixer
->device_handle
, FALSE
);
1427 IDirect3DDevice9_Release(device
);
1431 hr
= MF_E_TRANSFORM_NEED_MORE_INPUT
;
1433 IDirect3DSurface9_Release(surface
);
1436 LeaveCriticalSection(&mixer
->cs
);
1441 static const IMFTransformVtbl video_mixer_transform_vtbl
=
1443 video_mixer_transform_QueryInterface
,
1444 video_mixer_transform_AddRef
,
1445 video_mixer_transform_Release
,
1446 video_mixer_transform_GetStreamLimits
,
1447 video_mixer_transform_GetStreamCount
,
1448 video_mixer_transform_GetStreamIDs
,
1449 video_mixer_transform_GetInputStreamInfo
,
1450 video_mixer_transform_GetOutputStreamInfo
,
1451 video_mixer_transform_GetAttributes
,
1452 video_mixer_transform_GetInputStreamAttributes
,
1453 video_mixer_transform_GetOutputStreamAttributes
,
1454 video_mixer_transform_DeleteInputStream
,
1455 video_mixer_transform_AddInputStreams
,
1456 video_mixer_transform_GetInputAvailableType
,
1457 video_mixer_transform_GetOutputAvailableType
,
1458 video_mixer_transform_SetInputType
,
1459 video_mixer_transform_SetOutputType
,
1460 video_mixer_transform_GetInputCurrentType
,
1461 video_mixer_transform_GetOutputCurrentType
,
1462 video_mixer_transform_GetInputStatus
,
1463 video_mixer_transform_GetOutputStatus
,
1464 video_mixer_transform_SetOutputBounds
,
1465 video_mixer_transform_ProcessEvent
,
1466 video_mixer_transform_ProcessMessage
,
1467 video_mixer_transform_ProcessInput
,
1468 video_mixer_transform_ProcessOutput
,
1471 static HRESULT WINAPI
video_mixer_device_id_QueryInterface(IMFVideoDeviceID
*iface
, REFIID riid
, void **obj
)
1473 struct video_mixer
*mixer
= impl_from_IMFVideoDeviceID(iface
);
1474 return IMFTransform_QueryInterface(&mixer
->IMFTransform_iface
, riid
, obj
);
1477 static ULONG WINAPI
video_mixer_device_id_AddRef(IMFVideoDeviceID
*iface
)
1479 struct video_mixer
*mixer
= impl_from_IMFVideoDeviceID(iface
);
1480 return IMFTransform_AddRef(&mixer
->IMFTransform_iface
);
1483 static ULONG WINAPI
video_mixer_device_id_Release(IMFVideoDeviceID
*iface
)
1485 struct video_mixer
*mixer
= impl_from_IMFVideoDeviceID(iface
);
1486 return IMFTransform_Release(&mixer
->IMFTransform_iface
);
1489 static HRESULT WINAPI
video_mixer_device_id_GetDeviceID(IMFVideoDeviceID
*iface
, IID
*device_id
)
1491 TRACE("%p, %p.\n", iface
, device_id
);
1496 memcpy(device_id
, &IID_IDirect3DDevice9
, sizeof(*device_id
));
1501 static const IMFVideoDeviceIDVtbl video_mixer_device_id_vtbl
=
1503 video_mixer_device_id_QueryInterface
,
1504 video_mixer_device_id_AddRef
,
1505 video_mixer_device_id_Release
,
1506 video_mixer_device_id_GetDeviceID
,
1509 static HRESULT WINAPI
video_mixer_service_client_QueryInterface(IMFTopologyServiceLookupClient
*iface
,
1510 REFIID riid
, void **obj
)
1512 struct video_mixer
*mixer
= impl_from_IMFTopologyServiceLookupClient(iface
);
1513 return IMFTransform_QueryInterface(&mixer
->IMFTransform_iface
, riid
, obj
);
1516 static ULONG WINAPI
video_mixer_service_client_AddRef(IMFTopologyServiceLookupClient
*iface
)
1518 struct video_mixer
*mixer
= impl_from_IMFTopologyServiceLookupClient(iface
);
1519 return IMFTransform_AddRef(&mixer
->IMFTransform_iface
);
1522 static ULONG WINAPI
video_mixer_service_client_Release(IMFTopologyServiceLookupClient
*iface
)
1524 struct video_mixer
*mixer
= impl_from_IMFTopologyServiceLookupClient(iface
);
1525 return IMFTransform_Release(&mixer
->IMFTransform_iface
);
1528 static HRESULT WINAPI
video_mixer_service_client_InitServicePointers(IMFTopologyServiceLookupClient
*iface
,
1529 IMFTopologyServiceLookup
*service_lookup
)
1531 struct video_mixer
*mixer
= impl_from_IMFTopologyServiceLookupClient(iface
);
1535 TRACE("%p, %p.\n", iface
, service_lookup
);
1537 if (!service_lookup
)
1540 EnterCriticalSection(&mixer
->cs
);
1543 if (FAILED(hr
= IMFTopologyServiceLookup_LookupService(service_lookup
, MF_SERVICE_LOOKUP_GLOBAL
, 0,
1544 &MR_VIDEO_RENDER_SERVICE
, &IID_IMediaEventSink
, (void **)&mixer
->event_sink
, &count
)))
1546 WARN("Failed to get renderer event sink, hr %#x.\n", hr
);
1549 LeaveCriticalSection(&mixer
->cs
);
1554 static HRESULT WINAPI
video_mixer_service_client_ReleaseServicePointers(IMFTopologyServiceLookupClient
*iface
)
1556 struct video_mixer
*mixer
= impl_from_IMFTopologyServiceLookupClient(iface
);
1558 TRACE("%p.\n", iface
);
1560 EnterCriticalSection(&mixer
->cs
);
1562 if (mixer
->event_sink
)
1563 IMediaEventSink_Release(mixer
->event_sink
);
1564 mixer
->event_sink
= NULL
;
1566 LeaveCriticalSection(&mixer
->cs
);
1571 static const IMFTopologyServiceLookupClientVtbl video_mixer_service_client_vtbl
=
1573 video_mixer_service_client_QueryInterface
,
1574 video_mixer_service_client_AddRef
,
1575 video_mixer_service_client_Release
,
1576 video_mixer_service_client_InitServicePointers
,
1577 video_mixer_service_client_ReleaseServicePointers
,
1580 static HRESULT WINAPI
video_mixer_control_QueryInterface(IMFVideoMixerControl2
*iface
, REFIID riid
, void **obj
)
1582 struct video_mixer
*mixer
= impl_from_IMFVideoMixerControl2(iface
);
1583 return IMFTransform_QueryInterface(&mixer
->IMFTransform_iface
, riid
, obj
);
1586 static ULONG WINAPI
video_mixer_control_AddRef(IMFVideoMixerControl2
*iface
)
1588 struct video_mixer
*mixer
= impl_from_IMFVideoMixerControl2(iface
);
1589 return IMFTransform_AddRef(&mixer
->IMFTransform_iface
);
1592 static ULONG WINAPI
video_mixer_control_Release(IMFVideoMixerControl2
*iface
)
1594 struct video_mixer
*mixer
= impl_from_IMFVideoMixerControl2(iface
);
1595 return IMFTransform_Release(&mixer
->IMFTransform_iface
);
1598 static HRESULT WINAPI
video_mixer_control_SetStreamZOrder(IMFVideoMixerControl2
*iface
, DWORD id
, DWORD zorder
)
1600 struct video_mixer
*mixer
= impl_from_IMFVideoMixerControl2(iface
);
1601 struct input_stream
*stream
;
1604 TRACE("%p, %u, %u.\n", iface
, id
, zorder
);
1606 /* Can't change reference stream. */
1608 return E_INVALIDARG
;
1610 EnterCriticalSection(&mixer
->cs
);
1612 if (zorder
>= mixer
->input_count
)
1614 else if (SUCCEEDED(hr
= video_mixer_get_input(mixer
, id
, &stream
)))
1616 /* Lowest zorder only applies to reference stream. */
1618 hr
= MF_E_INVALIDREQUEST
;
1619 else if (stream
->zorder
!= zorder
)
1621 stream
->zorder
= zorder
;
1622 video_mixer_update_zorder_map(mixer
);
1626 LeaveCriticalSection(&mixer
->cs
);
1631 static HRESULT WINAPI
video_mixer_control_GetStreamZOrder(IMFVideoMixerControl2
*iface
, DWORD id
, DWORD
*zorder
)
1633 struct video_mixer
*mixer
= impl_from_IMFVideoMixerControl2(iface
);
1634 struct input_stream
*stream
;
1637 TRACE("%p, %u, %p.\n", iface
, id
, zorder
);
1642 EnterCriticalSection(&mixer
->cs
);
1644 if (SUCCEEDED(hr
= video_mixer_get_input(mixer
, id
, &stream
)))
1645 *zorder
= stream
->zorder
;
1647 LeaveCriticalSection(&mixer
->cs
);
1652 static HRESULT WINAPI
video_mixer_control_SetStreamOutputRect(IMFVideoMixerControl2
*iface
, DWORD id
,
1653 const MFVideoNormalizedRect
*rect
)
1655 struct video_mixer
*mixer
= impl_from_IMFVideoMixerControl2(iface
);
1656 struct input_stream
*stream
;
1659 TRACE("%p, %u, %s.\n", iface
, id
, debugstr_normalized_rect(rect
));
1664 if (rect
->left
> rect
->right
|| rect
->top
> rect
->bottom
||
1665 rect
->left
< 0.0f
|| rect
->top
< 0.0f
|| rect
->right
> 1.0f
|| rect
->bottom
> 1.0f
)
1667 return E_INVALIDARG
;
1670 EnterCriticalSection(&mixer
->cs
);
1672 if (SUCCEEDED(hr
= video_mixer_get_input(mixer
, id
, &stream
)))
1673 stream
->rect
= *rect
;
1675 LeaveCriticalSection(&mixer
->cs
);
1680 static HRESULT WINAPI
video_mixer_control_GetStreamOutputRect(IMFVideoMixerControl2
*iface
, DWORD id
,
1681 MFVideoNormalizedRect
*rect
)
1683 struct video_mixer
*mixer
= impl_from_IMFVideoMixerControl2(iface
);
1684 struct input_stream
*stream
;
1687 TRACE("%p, %u, %p.\n", iface
, id
, rect
);
1692 EnterCriticalSection(&mixer
->cs
);
1694 if (SUCCEEDED(hr
= video_mixer_get_input(mixer
, id
, &stream
)))
1695 *rect
= stream
->rect
;
1697 LeaveCriticalSection(&mixer
->cs
);
1702 static HRESULT WINAPI
video_mixer_control_SetMixingPrefs(IMFVideoMixerControl2
*iface
, DWORD flags
)
1704 struct video_mixer
*mixer
= impl_from_IMFVideoMixerControl2(iface
);
1706 TRACE("%p, %#x.\n", iface
, flags
);
1708 EnterCriticalSection(&mixer
->cs
);
1709 mixer
->mixing_flags
= flags
;
1710 LeaveCriticalSection(&mixer
->cs
);
1715 static HRESULT WINAPI
video_mixer_control_GetMixingPrefs(IMFVideoMixerControl2
*iface
, DWORD
*flags
)
1717 struct video_mixer
*mixer
= impl_from_IMFVideoMixerControl2(iface
);
1719 TRACE("%p, %p.\n", iface
, flags
);
1724 EnterCriticalSection(&mixer
->cs
);
1725 *flags
= mixer
->mixing_flags
;
1726 LeaveCriticalSection(&mixer
->cs
);
1731 static const IMFVideoMixerControl2Vtbl video_mixer_control_vtbl
=
1733 video_mixer_control_QueryInterface
,
1734 video_mixer_control_AddRef
,
1735 video_mixer_control_Release
,
1736 video_mixer_control_SetStreamZOrder
,
1737 video_mixer_control_GetStreamZOrder
,
1738 video_mixer_control_SetStreamOutputRect
,
1739 video_mixer_control_GetStreamOutputRect
,
1740 video_mixer_control_SetMixingPrefs
,
1741 video_mixer_control_GetMixingPrefs
,
1744 static HRESULT WINAPI
video_mixer_getservice_QueryInterface(IMFGetService
*iface
, REFIID riid
, void **obj
)
1746 struct video_mixer
*mixer
= impl_from_IMFGetService(iface
);
1747 return IMFTransform_QueryInterface(&mixer
->IMFTransform_iface
, riid
, obj
);
1750 static ULONG WINAPI
video_mixer_getservice_AddRef(IMFGetService
*iface
)
1752 struct video_mixer
*mixer
= impl_from_IMFGetService(iface
);
1753 return IMFTransform_AddRef(&mixer
->IMFTransform_iface
);
1756 static ULONG WINAPI
video_mixer_getservice_Release(IMFGetService
*iface
)
1758 struct video_mixer
*mixer
= impl_from_IMFGetService(iface
);
1759 return IMFTransform_Release(&mixer
->IMFTransform_iface
);
1762 static HRESULT WINAPI
video_mixer_getservice_GetService(IMFGetService
*iface
, REFGUID service
, REFIID riid
, void **obj
)
1764 TRACE("%p, %s, %s, %p.\n", iface
, debugstr_guid(service
), debugstr_guid(riid
), obj
);
1766 if (IsEqualGUID(service
, &MR_VIDEO_MIXER_SERVICE
))
1768 if (IsEqualIID(riid
, &IID_IMFVideoMixerBitmap
) ||
1769 IsEqualIID(riid
, &IID_IMFVideoProcessor
) ||
1770 IsEqualIID(riid
, &IID_IMFVideoPositionMapper
) ||
1771 IsEqualIID(riid
, &IID_IMFVideoMixerControl
) ||
1772 IsEqualIID(riid
, &IID_IMFVideoMixerControl2
))
1774 return IMFGetService_QueryInterface(iface
, riid
, obj
);
1777 return E_NOINTERFACE
;
1780 FIXME("Unsupported service %s, riid %s.\n", debugstr_guid(service
), debugstr_guid(riid
));
1782 return MF_E_UNSUPPORTED_SERVICE
;
1785 static const IMFGetServiceVtbl video_mixer_getservice_vtbl
=
1787 video_mixer_getservice_QueryInterface
,
1788 video_mixer_getservice_AddRef
,
1789 video_mixer_getservice_Release
,
1790 video_mixer_getservice_GetService
,
1793 static HRESULT WINAPI
video_mixer_bitmap_QueryInterface(IMFVideoMixerBitmap
*iface
, REFIID riid
, void **obj
)
1795 struct video_mixer
*mixer
= impl_from_IMFVideoMixerBitmap(iface
);
1796 return IMFTransform_QueryInterface(&mixer
->IMFTransform_iface
, riid
, obj
);
1799 static ULONG WINAPI
video_mixer_bitmap_AddRef(IMFVideoMixerBitmap
*iface
)
1801 struct video_mixer
*mixer
= impl_from_IMFVideoMixerBitmap(iface
);
1802 return IMFTransform_AddRef(&mixer
->IMFTransform_iface
);
1805 static ULONG WINAPI
video_mixer_bitmap_Release(IMFVideoMixerBitmap
*iface
)
1807 struct video_mixer
*mixer
= impl_from_IMFVideoMixerBitmap(iface
);
1808 return IMFTransform_Release(&mixer
->IMFTransform_iface
);
1811 static HRESULT WINAPI
video_mixer_bitmap_SetAlphaBitmap(IMFVideoMixerBitmap
*iface
, const MFVideoAlphaBitmap
*bitmap
)
1813 FIXME("%p, %p.\n", iface
, bitmap
);
1818 static HRESULT WINAPI
video_mixer_bitmap_ClearAlphaBitmap(IMFVideoMixerBitmap
*iface
)
1820 FIXME("%p.\n", iface
);
1825 static HRESULT WINAPI
video_mixer_bitmap_UpdateAlphaBitmapParameters(IMFVideoMixerBitmap
*iface
,
1826 const MFVideoAlphaBitmapParams
*params
)
1828 FIXME("%p, %p.\n", iface
, params
);
1833 static HRESULT WINAPI
video_mixer_bitmap_GetAlphaBitmapParameters(IMFVideoMixerBitmap
*iface
, MFVideoAlphaBitmapParams
*params
)
1835 FIXME("%p, %p.\n", iface
, params
);
1840 static const IMFVideoMixerBitmapVtbl video_mixer_bitmap_vtbl
=
1842 video_mixer_bitmap_QueryInterface
,
1843 video_mixer_bitmap_AddRef
,
1844 video_mixer_bitmap_Release
,
1845 video_mixer_bitmap_SetAlphaBitmap
,
1846 video_mixer_bitmap_ClearAlphaBitmap
,
1847 video_mixer_bitmap_UpdateAlphaBitmapParameters
,
1848 video_mixer_bitmap_GetAlphaBitmapParameters
,
1851 static HRESULT WINAPI
video_mixer_position_mapper_QueryInterface(IMFVideoPositionMapper
*iface
, REFIID riid
, void **obj
)
1853 struct video_mixer
*mixer
= impl_from_IMFVideoPositionMapper(iface
);
1854 return IMFTransform_QueryInterface(&mixer
->IMFTransform_iface
, riid
, obj
);
1857 static ULONG WINAPI
video_mixer_position_mapper_AddRef(IMFVideoPositionMapper
*iface
)
1859 struct video_mixer
*mixer
= impl_from_IMFVideoPositionMapper(iface
);
1860 return IMFTransform_AddRef(&mixer
->IMFTransform_iface
);
1863 static ULONG WINAPI
video_mixer_position_mapper_Release(IMFVideoPositionMapper
*iface
)
1865 struct video_mixer
*mixer
= impl_from_IMFVideoPositionMapper(iface
);
1866 return IMFTransform_Release(&mixer
->IMFTransform_iface
);
1869 static HRESULT WINAPI
video_mixer_position_mapper_MapOutputCoordinateToInputStream(IMFVideoPositionMapper
*iface
,
1870 float x_out
, float y_out
, DWORD output_stream
, DWORD input_stream
, float *x_in
, float *y_in
)
1872 FIXME("%p, %f, %f, %u, %u, %p, %p.\n", iface
, x_out
, y_out
, output_stream
, input_stream
, x_in
, y_in
);
1877 static const IMFVideoPositionMapperVtbl video_mixer_position_mapper_vtbl
=
1879 video_mixer_position_mapper_QueryInterface
,
1880 video_mixer_position_mapper_AddRef
,
1881 video_mixer_position_mapper_Release
,
1882 video_mixer_position_mapper_MapOutputCoordinateToInputStream
,
1885 static HRESULT WINAPI
video_mixer_processor_QueryInterface(IMFVideoProcessor
*iface
, REFIID riid
, void **obj
)
1887 struct video_mixer
*mixer
= impl_from_IMFVideoProcessor(iface
);
1888 return IMFTransform_QueryInterface(&mixer
->IMFTransform_iface
, riid
, obj
);
1891 static ULONG WINAPI
video_mixer_processor_AddRef(IMFVideoProcessor
*iface
)
1893 struct video_mixer
*mixer
= impl_from_IMFVideoProcessor(iface
);
1894 return IMFTransform_AddRef(&mixer
->IMFTransform_iface
);
1897 static ULONG WINAPI
video_mixer_processor_Release(IMFVideoProcessor
*iface
)
1899 struct video_mixer
*mixer
= impl_from_IMFVideoProcessor(iface
);
1900 return IMFTransform_Release(&mixer
->IMFTransform_iface
);
1903 static HRESULT WINAPI
video_mixer_processor_GetAvailableVideoProcessorModes(IMFVideoProcessor
*iface
, UINT
*count
,
1906 FIXME("%p, %p, %p.\n", iface
, count
, modes
);
1911 static HRESULT WINAPI
video_mixer_processor_GetVideoProcessorCaps(IMFVideoProcessor
*iface
, GUID
*mode
,
1912 DXVA2_VideoProcessorCaps
*caps
)
1914 FIXME("%p, %s, %p.\n", iface
, debugstr_guid(mode
), caps
);
1919 static HRESULT WINAPI
video_mixer_processor_GetVideoProcessorMode(IMFVideoProcessor
*iface
, GUID
*mode
)
1921 FIXME("%p, %p.\n", iface
, mode
);
1926 static HRESULT WINAPI
video_mixer_processor_SetVideoProcessorMode(IMFVideoProcessor
*iface
, GUID
*mode
)
1928 FIXME("%p, %s.\n", iface
, debugstr_guid(mode
));
1933 static HRESULT WINAPI
video_mixer_processor_GetProcAmpRange(IMFVideoProcessor
*iface
, DWORD prop
, DXVA2_ValueRange
*range
)
1935 FIXME("%p, %#x, %p.\n", iface
, prop
, range
);
1940 static HRESULT WINAPI
video_mixer_processor_GetProcAmpValues(IMFVideoProcessor
*iface
, DWORD flags
, DXVA2_ProcAmpValues
*values
)
1942 FIXME("%p, %#x, %p.\n", iface
, flags
, values
);
1947 static HRESULT WINAPI
video_mixer_processor_SetProcAmpValues(IMFVideoProcessor
*iface
, DWORD flags
, DXVA2_ProcAmpValues
*values
)
1949 FIXME("%p, %#x, %p.\n", iface
, flags
, values
);
1954 static HRESULT WINAPI
video_mixer_processor_GetFilteringRange(IMFVideoProcessor
*iface
, DWORD prop
, DXVA2_ValueRange
*range
)
1956 FIXME("%p, %#x, %p.\n", iface
, prop
, range
);
1961 static HRESULT WINAPI
video_mixer_processor_GetFilteringValue(IMFVideoProcessor
*iface
, DWORD prop
, DXVA2_Fixed32
*value
)
1963 FIXME("%p, %#x, %p.\n", iface
, prop
, value
);
1968 static HRESULT WINAPI
video_mixer_processor_SetFilteringValue(IMFVideoProcessor
*iface
, DWORD prop
, DXVA2_Fixed32
*value
)
1970 FIXME("%p, %#x, %p.\n", iface
, prop
, value
);
1975 static HRESULT WINAPI
video_mixer_processor_GetBackgroundColor(IMFVideoProcessor
*iface
, COLORREF
*color
)
1977 struct video_mixer
*mixer
= impl_from_IMFVideoProcessor(iface
);
1979 TRACE("%p, %p.\n", iface
, color
);
1984 EnterCriticalSection(&mixer
->cs
);
1985 *color
= mixer
->bkgnd_color
;
1986 LeaveCriticalSection(&mixer
->cs
);
1991 static HRESULT WINAPI
video_mixer_processor_SetBackgroundColor(IMFVideoProcessor
*iface
, COLORREF color
)
1993 struct video_mixer
*mixer
= impl_from_IMFVideoProcessor(iface
);
1995 TRACE("%p, %#x.\n", iface
, color
);
1997 EnterCriticalSection(&mixer
->cs
);
1998 mixer
->bkgnd_color
= color
;
1999 LeaveCriticalSection(&mixer
->cs
);
2004 static const IMFVideoProcessorVtbl video_mixer_processor_vtbl
=
2006 video_mixer_processor_QueryInterface
,
2007 video_mixer_processor_AddRef
,
2008 video_mixer_processor_Release
,
2009 video_mixer_processor_GetAvailableVideoProcessorModes
,
2010 video_mixer_processor_GetVideoProcessorCaps
,
2011 video_mixer_processor_GetVideoProcessorMode
,
2012 video_mixer_processor_SetVideoProcessorMode
,
2013 video_mixer_processor_GetProcAmpRange
,
2014 video_mixer_processor_GetProcAmpValues
,
2015 video_mixer_processor_SetProcAmpValues
,
2016 video_mixer_processor_GetFilteringRange
,
2017 video_mixer_processor_GetFilteringValue
,
2018 video_mixer_processor_SetFilteringValue
,
2019 video_mixer_processor_GetBackgroundColor
,
2020 video_mixer_processor_SetBackgroundColor
,
2023 static HRESULT WINAPI
video_mixer_attributes_QueryInterface(IMFAttributes
*iface
, REFIID riid
, void **out
)
2025 struct video_mixer
*mixer
= impl_from_IMFAttributes(iface
);
2026 return IMFTransform_QueryInterface(&mixer
->IMFTransform_iface
, riid
, out
);
2029 static ULONG WINAPI
video_mixer_attributes_AddRef(IMFAttributes
*iface
)
2031 struct video_mixer
*mixer
= impl_from_IMFAttributes(iface
);
2032 return IMFTransform_AddRef(&mixer
->IMFTransform_iface
);
2035 static ULONG WINAPI
video_mixer_attributes_Release(IMFAttributes
*iface
)
2037 struct video_mixer
*mixer
= impl_from_IMFAttributes(iface
);
2038 return IMFTransform_Release(&mixer
->IMFTransform_iface
);
2041 static HRESULT WINAPI
video_mixer_attributes_GetItem(IMFAttributes
*iface
, REFGUID key
, PROPVARIANT
*value
)
2043 struct video_mixer
*mixer
= impl_from_IMFAttributes(iface
);
2045 TRACE("%p, %s, %p.\n", iface
, debugstr_guid(key
), value
);
2047 return IMFAttributes_GetItem(mixer
->internal_attributes
, key
, value
);
2050 static HRESULT WINAPI
video_mixer_attributes_GetItemType(IMFAttributes
*iface
, REFGUID key
, MF_ATTRIBUTE_TYPE
*type
)
2052 struct video_mixer
*mixer
= impl_from_IMFAttributes(iface
);
2054 TRACE("%p, %s, %p.\n", iface
, debugstr_guid(key
), type
);
2056 return IMFAttributes_GetItemType(mixer
->internal_attributes
, key
, type
);
2059 static HRESULT WINAPI
video_mixer_attributes_CompareItem(IMFAttributes
*iface
, REFGUID key
,
2060 REFPROPVARIANT value
, BOOL
*result
)
2062 struct video_mixer
*mixer
= impl_from_IMFAttributes(iface
);
2064 TRACE("%p, %s, %p, %p.\n", iface
, debugstr_guid(key
), value
, result
);
2066 return IMFAttributes_CompareItem(mixer
->internal_attributes
, key
, value
, result
);
2069 static HRESULT WINAPI
video_mixer_attributes_Compare(IMFAttributes
*iface
, IMFAttributes
*theirs
,
2070 MF_ATTRIBUTES_MATCH_TYPE match_type
, BOOL
*ret
)
2072 struct video_mixer
*mixer
= impl_from_IMFAttributes(iface
);
2074 TRACE("%p, %p, %d, %p.\n", iface
, theirs
, match_type
, ret
);
2076 return IMFAttributes_Compare(mixer
->internal_attributes
, theirs
, match_type
, ret
);
2079 static HRESULT WINAPI
video_mixer_attributes_GetUINT32(IMFAttributes
*iface
, REFGUID key
, UINT32
*value
)
2081 struct video_mixer
*mixer
= impl_from_IMFAttributes(iface
);
2083 TRACE("%p, %s, %p.\n", iface
, debugstr_guid(key
), value
);
2085 return IMFAttributes_GetUINT32(mixer
->internal_attributes
, key
, value
);
2088 static HRESULT WINAPI
video_mixer_attributes_GetUINT64(IMFAttributes
*iface
, REFGUID key
, UINT64
*value
)
2090 struct video_mixer
*mixer
= impl_from_IMFAttributes(iface
);
2092 TRACE("%p, %s, %p.\n", iface
, debugstr_guid(key
), value
);
2094 return IMFAttributes_GetUINT64(mixer
->internal_attributes
, key
, value
);
2097 static HRESULT WINAPI
video_mixer_attributes_GetDouble(IMFAttributes
*iface
, REFGUID key
, double *value
)
2099 struct video_mixer
*mixer
= impl_from_IMFAttributes(iface
);
2101 TRACE("%p, %s, %p.\n", iface
, debugstr_guid(key
), value
);
2103 return IMFAttributes_GetDouble(mixer
->internal_attributes
, key
, value
);
2106 static HRESULT WINAPI
video_mixer_attributes_GetGUID(IMFAttributes
*iface
, REFGUID key
, GUID
*value
)
2108 struct video_mixer
*mixer
= impl_from_IMFAttributes(iface
);
2110 TRACE("%p, %s, %p.\n", iface
, debugstr_guid(key
), value
);
2112 return IMFAttributes_GetGUID(mixer
->internal_attributes
, key
, value
);
2115 static HRESULT WINAPI
video_mixer_attributes_GetStringLength(IMFAttributes
*iface
, REFGUID key
, UINT32
*length
)
2117 struct video_mixer
*mixer
= impl_from_IMFAttributes(iface
);
2119 TRACE("%p, %s, %p.\n", iface
, debugstr_guid(key
), length
);
2121 return IMFAttributes_GetStringLength(mixer
->internal_attributes
, key
, length
);
2124 static HRESULT WINAPI
video_mixer_attributes_GetString(IMFAttributes
*iface
, REFGUID key
, WCHAR
*value
,
2125 UINT32 size
, UINT32
*length
)
2127 struct video_mixer
*mixer
= impl_from_IMFAttributes(iface
);
2129 TRACE("%p, %s, %p, %d, %p.\n", iface
, debugstr_guid(key
), value
, size
, length
);
2131 return IMFAttributes_GetString(mixer
->internal_attributes
, key
, value
, size
, length
);
2134 static HRESULT WINAPI
video_mixer_attributes_GetAllocatedString(IMFAttributes
*iface
, REFGUID key
,
2135 WCHAR
**value
, UINT32
*length
)
2137 struct video_mixer
*mixer
= impl_from_IMFAttributes(iface
);
2139 TRACE("%p, %s, %p, %p.\n", iface
, debugstr_guid(key
), value
, length
);
2141 return IMFAttributes_GetAllocatedString(mixer
->internal_attributes
, key
, value
, length
);
2144 static HRESULT WINAPI
video_mixer_attributes_GetBlobSize(IMFAttributes
*iface
, REFGUID key
, UINT32
*size
)
2146 struct video_mixer
*mixer
= impl_from_IMFAttributes(iface
);
2148 TRACE("%p, %s, %p.\n", iface
, debugstr_guid(key
), size
);
2150 return IMFAttributes_GetBlobSize(mixer
->internal_attributes
, key
, size
);
2153 static HRESULT WINAPI
video_mixer_attributes_GetBlob(IMFAttributes
*iface
, REFGUID key
, UINT8
*buf
,
2154 UINT32 bufsize
, UINT32
*blobsize
)
2156 struct video_mixer
*mixer
= impl_from_IMFAttributes(iface
);
2158 TRACE("%p, %s, %p, %d, %p.\n", iface
, debugstr_guid(key
), buf
, bufsize
, blobsize
);
2160 return IMFAttributes_GetBlob(mixer
->internal_attributes
, key
, buf
, bufsize
, blobsize
);
2163 static HRESULT WINAPI
video_mixer_attributes_GetAllocatedBlob(IMFAttributes
*iface
, REFGUID key
, UINT8
**buf
, UINT32
*size
)
2165 struct video_mixer
*mixer
= impl_from_IMFAttributes(iface
);
2167 TRACE("%p, %s, %p, %p.\n", iface
, debugstr_guid(key
), buf
, size
);
2169 return IMFAttributes_GetAllocatedBlob(mixer
->internal_attributes
, key
, buf
, size
);
2172 static HRESULT WINAPI
video_mixer_attributes_GetUnknown(IMFAttributes
*iface
, REFGUID key
, REFIID riid
, void **out
)
2174 struct video_mixer
*mixer
= impl_from_IMFAttributes(iface
);
2176 TRACE("%p, %s, %s, %p.\n", iface
, debugstr_guid(key
), debugstr_guid(riid
), out
);
2178 return IMFAttributes_GetUnknown(mixer
->internal_attributes
, key
, riid
, out
);
2181 static HRESULT WINAPI
video_mixer_attributes_SetItem(IMFAttributes
*iface
, REFGUID key
, REFPROPVARIANT value
)
2183 struct video_mixer
*mixer
= impl_from_IMFAttributes(iface
);
2185 TRACE("%p, %s, %p.\n", iface
, debugstr_guid(key
), value
);
2187 return IMFAttributes_SetItem(mixer
->internal_attributes
, key
, value
);
2190 static HRESULT WINAPI
video_mixer_attributes_DeleteItem(IMFAttributes
*iface
, REFGUID key
)
2192 struct video_mixer
*mixer
= impl_from_IMFAttributes(iface
);
2194 TRACE("%p, %s.\n", iface
, debugstr_guid(key
));
2196 return IMFAttributes_DeleteItem(mixer
->internal_attributes
, key
);
2199 static HRESULT WINAPI
video_mixer_attributes_DeleteAllItems(IMFAttributes
*iface
)
2201 struct video_mixer
*mixer
= impl_from_IMFAttributes(iface
);
2203 TRACE("%p.\n", iface
);
2205 return IMFAttributes_DeleteAllItems(mixer
->internal_attributes
);
2208 static HRESULT WINAPI
video_mixer_attributes_SetUINT32(IMFAttributes
*iface
, REFGUID key
, UINT32 value
)
2210 struct video_mixer
*mixer
= impl_from_IMFAttributes(iface
);
2212 TRACE("%p, %s, %u.\n", iface
, debugstr_guid(key
), value
);
2214 return IMFAttributes_SetUINT32(mixer
->internal_attributes
, key
, value
);
2217 static HRESULT WINAPI
video_mixer_attributes_SetUINT64(IMFAttributes
*iface
, REFGUID key
, UINT64 value
)
2219 struct video_mixer
*mixer
= impl_from_IMFAttributes(iface
);
2221 TRACE("%p, %s, %s.\n", iface
, debugstr_guid(key
), wine_dbgstr_longlong(value
));
2223 return IMFAttributes_SetUINT64(mixer
->internal_attributes
, key
, value
);
2226 static HRESULT WINAPI
video_mixer_attributes_SetDouble(IMFAttributes
*iface
, REFGUID key
, double value
)
2228 struct video_mixer
*mixer
= impl_from_IMFAttributes(iface
);
2230 TRACE("%p, %s, %f.\n", iface
, debugstr_guid(key
), value
);
2232 return IMFAttributes_SetDouble(mixer
->internal_attributes
, key
, value
);
2235 static HRESULT WINAPI
video_mixer_attributes_SetGUID(IMFAttributes
*iface
, REFGUID key
, REFGUID value
)
2237 struct video_mixer
*mixer
= impl_from_IMFAttributes(iface
);
2239 TRACE("%p, %s, %s.\n", iface
, debugstr_guid(key
), debugstr_guid(value
));
2241 return IMFAttributes_SetGUID(mixer
->internal_attributes
, key
, value
);
2244 static HRESULT WINAPI
video_mixer_attributes_SetString(IMFAttributes
*iface
, REFGUID key
, const WCHAR
*value
)
2246 struct video_mixer
*mixer
= impl_from_IMFAttributes(iface
);
2248 TRACE("%p, %s, %s.\n", iface
, debugstr_guid(key
), debugstr_w(value
));
2250 return IMFAttributes_SetString(mixer
->internal_attributes
, key
, value
);
2253 static HRESULT WINAPI
video_mixer_attributes_SetBlob(IMFAttributes
*iface
, REFGUID key
, const UINT8
*buf
, UINT32 size
)
2255 struct video_mixer
*mixer
= impl_from_IMFAttributes(iface
);
2257 TRACE("%p, %s, %p, %u.\n", iface
, debugstr_guid(key
), buf
, size
);
2259 return IMFAttributes_SetBlob(mixer
->internal_attributes
, key
, buf
, size
);
2262 static HRESULT WINAPI
video_mixer_attributes_SetUnknown(IMFAttributes
*iface
, REFGUID key
, IUnknown
*unknown
)
2264 struct video_mixer
*mixer
= impl_from_IMFAttributes(iface
);
2266 TRACE("%p, %s, %p.\n", iface
, debugstr_guid(key
), unknown
);
2268 return IMFAttributes_SetUnknown(mixer
->internal_attributes
, key
, unknown
);
2271 static HRESULT WINAPI
video_mixer_attributes_LockStore(IMFAttributes
*iface
)
2273 struct video_mixer
*mixer
= impl_from_IMFAttributes(iface
);
2275 TRACE("%p.\n", iface
);
2277 return IMFAttributes_LockStore(mixer
->internal_attributes
);
2280 static HRESULT WINAPI
video_mixer_attributes_UnlockStore(IMFAttributes
*iface
)
2282 struct video_mixer
*mixer
= impl_from_IMFAttributes(iface
);
2284 TRACE("%p.\n", iface
);
2286 return IMFAttributes_UnlockStore(mixer
->internal_attributes
);
2289 static HRESULT WINAPI
video_mixer_attributes_GetCount(IMFAttributes
*iface
, UINT32
*count
)
2291 struct video_mixer
*mixer
= impl_from_IMFAttributes(iface
);
2293 TRACE("%p, %p.\n", iface
, count
);
2295 return IMFAttributes_GetCount(mixer
->internal_attributes
, count
);
2298 static HRESULT WINAPI
video_mixer_attributes_GetItemByIndex(IMFAttributes
*iface
, UINT32 index
,
2299 GUID
*key
, PROPVARIANT
*value
)
2301 struct video_mixer
*mixer
= impl_from_IMFAttributes(iface
);
2303 TRACE("%p, %u, %p, %p.\n", iface
, index
, key
, value
);
2305 return IMFAttributes_GetItemByIndex(mixer
->internal_attributes
, index
, key
, value
);
2308 static HRESULT WINAPI
video_mixer_attributes_CopyAllItems(IMFAttributes
*iface
, IMFAttributes
*dest
)
2310 struct video_mixer
*mixer
= impl_from_IMFAttributes(iface
);
2312 TRACE("%p, %p.\n", iface
, dest
);
2314 return IMFAttributes_CopyAllItems(mixer
->internal_attributes
, dest
);
2317 static const IMFAttributesVtbl video_mixer_attributes_vtbl
=
2319 video_mixer_attributes_QueryInterface
,
2320 video_mixer_attributes_AddRef
,
2321 video_mixer_attributes_Release
,
2322 video_mixer_attributes_GetItem
,
2323 video_mixer_attributes_GetItemType
,
2324 video_mixer_attributes_CompareItem
,
2325 video_mixer_attributes_Compare
,
2326 video_mixer_attributes_GetUINT32
,
2327 video_mixer_attributes_GetUINT64
,
2328 video_mixer_attributes_GetDouble
,
2329 video_mixer_attributes_GetGUID
,
2330 video_mixer_attributes_GetStringLength
,
2331 video_mixer_attributes_GetString
,
2332 video_mixer_attributes_GetAllocatedString
,
2333 video_mixer_attributes_GetBlobSize
,
2334 video_mixer_attributes_GetBlob
,
2335 video_mixer_attributes_GetAllocatedBlob
,
2336 video_mixer_attributes_GetUnknown
,
2337 video_mixer_attributes_SetItem
,
2338 video_mixer_attributes_DeleteItem
,
2339 video_mixer_attributes_DeleteAllItems
,
2340 video_mixer_attributes_SetUINT32
,
2341 video_mixer_attributes_SetUINT64
,
2342 video_mixer_attributes_SetDouble
,
2343 video_mixer_attributes_SetGUID
,
2344 video_mixer_attributes_SetString
,
2345 video_mixer_attributes_SetBlob
,
2346 video_mixer_attributes_SetUnknown
,
2347 video_mixer_attributes_LockStore
,
2348 video_mixer_attributes_UnlockStore
,
2349 video_mixer_attributes_GetCount
,
2350 video_mixer_attributes_GetItemByIndex
,
2351 video_mixer_attributes_CopyAllItems
2354 static HRESULT WINAPI
video_mixer_quality_advise_QueryInterface(IMFQualityAdvise
*iface
, REFIID riid
, void **out
)
2356 struct video_mixer
*mixer
= impl_from_IMFQualityAdvise(iface
);
2357 return IMFTransform_QueryInterface(&mixer
->IMFTransform_iface
, riid
, out
);
2360 static ULONG WINAPI
video_mixer_quality_advise_AddRef(IMFQualityAdvise
*iface
)
2362 struct video_mixer
*mixer
= impl_from_IMFQualityAdvise(iface
);
2363 return IMFTransform_AddRef(&mixer
->IMFTransform_iface
);
2366 static ULONG WINAPI
video_mixer_quality_advise_Release(IMFQualityAdvise
*iface
)
2368 struct video_mixer
*mixer
= impl_from_IMFQualityAdvise(iface
);
2369 return IMFTransform_Release(&mixer
->IMFTransform_iface
);
2372 static HRESULT WINAPI
video_mixer_quality_advise_SetDropMode(IMFQualityAdvise
*iface
, MF_QUALITY_DROP_MODE mode
)
2374 FIXME("%p, %u.\n", iface
, mode
);
2379 static HRESULT WINAPI
video_mixer_quality_advise_SetQualityLevel(IMFQualityAdvise
*iface
, MF_QUALITY_LEVEL level
)
2381 FIXME("%p, %u.\n", iface
, level
);
2386 static HRESULT WINAPI
video_mixer_quality_advise_GetDropMode(IMFQualityAdvise
*iface
, MF_QUALITY_DROP_MODE
*mode
)
2388 FIXME("%p, %p.\n", iface
, mode
);
2393 static HRESULT WINAPI
video_mixer_quality_advise_GetQualityLevel(IMFQualityAdvise
*iface
, MF_QUALITY_LEVEL
*level
)
2395 FIXME("%p, %p.\n", iface
, level
);
2400 static HRESULT WINAPI
video_mixer_quality_advise_DropTime(IMFQualityAdvise
*iface
, LONGLONG interval
)
2402 FIXME("%p, %s.\n", iface
, wine_dbgstr_longlong(interval
));
2407 static const IMFQualityAdviseVtbl video_mixer_quality_advise_vtbl
=
2409 video_mixer_quality_advise_QueryInterface
,
2410 video_mixer_quality_advise_AddRef
,
2411 video_mixer_quality_advise_Release
,
2412 video_mixer_quality_advise_SetDropMode
,
2413 video_mixer_quality_advise_SetQualityLevel
,
2414 video_mixer_quality_advise_GetDropMode
,
2415 video_mixer_quality_advise_GetQualityLevel
,
2416 video_mixer_quality_advise_DropTime
,
2419 static HRESULT WINAPI
video_mixer_clock_state_sink_QueryInterface(IMFClockStateSink
*iface
,
2420 REFIID riid
, void **out
)
2422 struct video_mixer
*mixer
= impl_from_IMFClockStateSink(iface
);
2423 return IMFTransform_QueryInterface(&mixer
->IMFTransform_iface
, riid
, out
);
2426 static ULONG WINAPI
video_mixer_clock_state_sink_AddRef(IMFClockStateSink
*iface
)
2428 struct video_mixer
*mixer
= impl_from_IMFClockStateSink(iface
);
2429 return IMFTransform_AddRef(&mixer
->IMFTransform_iface
);
2432 static ULONG WINAPI
video_mixer_clock_state_sink_Release(IMFClockStateSink
*iface
)
2434 struct video_mixer
*mixer
= impl_from_IMFClockStateSink(iface
);
2435 return IMFTransform_Release(&mixer
->IMFTransform_iface
);
2438 static HRESULT WINAPI
video_mixer_clock_state_sink_OnClockStart(IMFClockStateSink
*iface
,
2439 MFTIME systime
, LONGLONG offset
)
2441 FIXME("%p.\n", iface
);
2446 static HRESULT WINAPI
video_mixer_clock_state_sink_OnClockStop(IMFClockStateSink
*iface
,
2449 FIXME("%p.\n", iface
);
2454 static HRESULT WINAPI
video_mixer_clock_state_sink_OnClockPause(IMFClockStateSink
*iface
,
2457 FIXME("%p.\n", iface
);
2462 static HRESULT WINAPI
video_mixer_clock_state_sink_OnClockRestart(IMFClockStateSink
*iface
,
2465 FIXME("%p.\n", iface
);
2470 static HRESULT WINAPI
video_mixer_clock_state_sink_OnClockSetRate(IMFClockStateSink
*iface
,
2471 MFTIME systime
, float rate
)
2473 FIXME("%p, %f.\n", iface
, rate
);
2478 static const IMFClockStateSinkVtbl video_mixer_clock_state_sink_vtbl
=
2480 video_mixer_clock_state_sink_QueryInterface
,
2481 video_mixer_clock_state_sink_AddRef
,
2482 video_mixer_clock_state_sink_Release
,
2483 video_mixer_clock_state_sink_OnClockStart
,
2484 video_mixer_clock_state_sink_OnClockStop
,
2485 video_mixer_clock_state_sink_OnClockPause
,
2486 video_mixer_clock_state_sink_OnClockRestart
,
2487 video_mixer_clock_state_sink_OnClockSetRate
,
2490 HRESULT WINAPI
MFCreateVideoMixer(IUnknown
*owner
, REFIID riid_device
, REFIID riid
, void **obj
)
2492 TRACE("%p, %s, %s, %p.\n", owner
, debugstr_guid(riid_device
), debugstr_guid(riid
), obj
);
2496 if (!IsEqualIID(riid_device
, &IID_IDirect3DDevice9
))
2497 return E_INVALIDARG
;
2499 return CoCreateInstance(&CLSID_MFVideoMixer9
, owner
, CLSCTX_INPROC_SERVER
, riid
, obj
);
2502 HRESULT
evr_mixer_create(IUnknown
*outer
, void **out
)
2504 struct video_mixer
*object
;
2505 MFVideoNormalizedRect rect
;
2508 if (!(object
= calloc(1, sizeof(*object
))))
2509 return E_OUTOFMEMORY
;
2511 object
->IMFTransform_iface
.lpVtbl
= &video_mixer_transform_vtbl
;
2512 object
->IMFVideoDeviceID_iface
.lpVtbl
= &video_mixer_device_id_vtbl
;
2513 object
->IMFTopologyServiceLookupClient_iface
.lpVtbl
= &video_mixer_service_client_vtbl
;
2514 object
->IMFVideoMixerControl2_iface
.lpVtbl
= &video_mixer_control_vtbl
;
2515 object
->IMFGetService_iface
.lpVtbl
= &video_mixer_getservice_vtbl
;
2516 object
->IMFVideoMixerBitmap_iface
.lpVtbl
= &video_mixer_bitmap_vtbl
;
2517 object
->IMFVideoPositionMapper_iface
.lpVtbl
= &video_mixer_position_mapper_vtbl
;
2518 object
->IMFVideoProcessor_iface
.lpVtbl
= &video_mixer_processor_vtbl
;
2519 object
->IMFAttributes_iface
.lpVtbl
= &video_mixer_attributes_vtbl
;
2520 object
->IMFQualityAdvise_iface
.lpVtbl
= &video_mixer_quality_advise_vtbl
;
2521 object
->IMFClockStateSink_iface
.lpVtbl
= &video_mixer_clock_state_sink_vtbl
;
2522 object
->IUnknown_inner
.lpVtbl
= &video_mixer_inner_vtbl
;
2523 object
->outer_unk
= outer
? outer
: &object
->IUnknown_inner
;
2524 object
->refcount
= 1;
2525 object
->input_count
= 1;
2526 object
->lower_bound
= MFT_OUTPUT_BOUND_LOWER_UNBOUNDED
;
2527 object
->upper_bound
= MFT_OUTPUT_BOUND_UPPER_UNBOUNDED
;
2528 video_mixer_init_input(&object
->inputs
[0]);
2529 video_mixer_update_zorder_map(object
);
2530 InitializeCriticalSection(&object
->cs
);
2531 if (FAILED(hr
= MFCreateAttributes(&object
->attributes
, 0)))
2533 IUnknown_Release(&object
->IUnknown_inner
);
2536 if (FAILED(hr
= MFCreateAttributes(&object
->internal_attributes
, 0)))
2538 IUnknown_Release(&object
->IUnknown_inner
);
2542 /* Default attributes configuration. */
2544 rect
.left
= rect
.top
= 0.0f
;
2545 rect
.right
= rect
.bottom
= 1.0f
;
2546 IMFAttributes_SetBlob(object
->attributes
, &VIDEO_ZOOM_RECT
, (const UINT8
*)&rect
, sizeof(rect
));
2548 IMFAttributes_SetUINT32(object
->internal_attributes
, &MF_SA_D3D_AWARE
, 1);
2550 *out
= &object
->IUnknown_inner
;