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_SUBSTREAMS (15)
39 #define MAX_MIXER_INPUT_STREAMS (MAX_MIXER_INPUT_SUBSTREAMS + 1)
44 IMFAttributes
*attributes
;
45 IMFMediaType
*media_type
;
46 MFVideoNormalizedRect rect
;
50 unsigned int sample_requested
: 1;
57 IMFMediaType
*media_type
;
62 IMFMediaType
*media_type
;
63 struct rt_format
*rt_formats
;
64 unsigned int rt_formats_count
;
69 IMFTransform IMFTransform_iface
;
70 IMFVideoDeviceID IMFVideoDeviceID_iface
;
71 IMFTopologyServiceLookupClient IMFTopologyServiceLookupClient_iface
;
72 IMFVideoMixerControl2 IMFVideoMixerControl2_iface
;
73 IMFGetService IMFGetService_iface
;
74 IMFVideoMixerBitmap IMFVideoMixerBitmap_iface
;
75 IMFVideoPositionMapper IMFVideoPositionMapper_iface
;
76 IMFVideoProcessor IMFVideoProcessor_iface
;
77 IMFAttributes IMFAttributes_iface
;
78 IMFQualityAdvise IMFQualityAdvise_iface
;
79 IMFClockStateSink IMFClockStateSink_iface
;
80 IUnknown IUnknown_inner
;
84 struct input_stream inputs
[MAX_MIXER_INPUT_STREAMS
];
85 unsigned int input_ids
[MAX_MIXER_INPUT_STREAMS
];
86 struct input_stream
*zorder
[MAX_MIXER_INPUT_STREAMS
];
87 unsigned int input_count
;
88 struct output_stream output
;
90 IDirect3DDeviceManager9
*device_manager
;
91 IDirectXVideoProcessor
*processor
;
94 IMediaEventSink
*event_sink
;
95 IMFAttributes
*attributes
;
96 IMFAttributes
*internal_attributes
;
97 unsigned int mixing_flags
;
98 unsigned int is_streaming
: 1;
99 unsigned int output_rendered
: 1;
103 DXVA2_AYUVSample16 ayuv
;
105 LONGLONG lower_bound
;
106 LONGLONG upper_bound
;
110 static struct video_mixer
*impl_from_IUnknown(IUnknown
*iface
)
112 return CONTAINING_RECORD(iface
, struct video_mixer
, IUnknown_inner
);
115 static struct video_mixer
*impl_from_IMFTransform(IMFTransform
*iface
)
117 return CONTAINING_RECORD(iface
, struct video_mixer
, IMFTransform_iface
);
120 static struct video_mixer
*impl_from_IMFVideoDeviceID(IMFVideoDeviceID
*iface
)
122 return CONTAINING_RECORD(iface
, struct video_mixer
, IMFVideoDeviceID_iface
);
125 static struct video_mixer
*impl_from_IMFTopologyServiceLookupClient(IMFTopologyServiceLookupClient
*iface
)
127 return CONTAINING_RECORD(iface
, struct video_mixer
, IMFTopologyServiceLookupClient_iface
);
130 static struct video_mixer
*impl_from_IMFVideoMixerControl2(IMFVideoMixerControl2
*iface
)
132 return CONTAINING_RECORD(iface
, struct video_mixer
, IMFVideoMixerControl2_iface
);
135 static struct video_mixer
*impl_from_IMFGetService(IMFGetService
*iface
)
137 return CONTAINING_RECORD(iface
, struct video_mixer
, IMFGetService_iface
);
140 static struct video_mixer
*impl_from_IMFVideoMixerBitmap(IMFVideoMixerBitmap
*iface
)
142 return CONTAINING_RECORD(iface
, struct video_mixer
, IMFVideoMixerBitmap_iface
);
145 static struct video_mixer
*impl_from_IMFVideoPositionMapper(IMFVideoPositionMapper
*iface
)
147 return CONTAINING_RECORD(iface
, struct video_mixer
, IMFVideoPositionMapper_iface
);
150 static struct video_mixer
*impl_from_IMFVideoProcessor(IMFVideoProcessor
*iface
)
152 return CONTAINING_RECORD(iface
, struct video_mixer
, IMFVideoProcessor_iface
);
155 static struct video_mixer
*impl_from_IMFAttributes(IMFAttributes
*iface
)
157 return CONTAINING_RECORD(iface
, struct video_mixer
, IMFAttributes_iface
);
160 static struct video_mixer
*impl_from_IMFQualityAdvise(IMFQualityAdvise
*iface
)
162 return CONTAINING_RECORD(iface
, struct video_mixer
, IMFQualityAdvise_iface
);
165 static struct video_mixer
*impl_from_IMFClockStateSink(IMFClockStateSink
*iface
)
167 return CONTAINING_RECORD(iface
, struct video_mixer
, IMFClockStateSink_iface
);
170 static int __cdecl
video_mixer_compare_input_id(const void *a
, const void *b
)
172 const unsigned int *key
= a
;
173 const struct input_stream
*input
= b
;
175 if (*key
> input
->id
) return 1;
176 if (*key
< input
->id
) return -1;
180 static HRESULT
video_mixer_get_input(const struct video_mixer
*mixer
, unsigned int id
, struct input_stream
**stream
)
182 *stream
= bsearch(&id
, mixer
->inputs
, mixer
->input_count
, sizeof(*mixer
->inputs
), video_mixer_compare_input_id
);
183 return *stream
? S_OK
: MF_E_INVALIDSTREAMNUMBER
;
186 static void video_mixer_init_input(struct input_stream
*stream
)
188 if (SUCCEEDED(MFCreateAttributes(&stream
->attributes
, 1)))
189 IMFAttributes_SetUINT32(stream
->attributes
, &MF_SA_REQUIRED_SAMPLE_COUNT
, 1);
190 stream
->rect
.left
= stream
->rect
.top
= 0.0f
;
191 stream
->rect
.right
= stream
->rect
.bottom
= 1.0f
;
194 static int __cdecl
video_mixer_zorder_sort_compare(const void *a
, const void *b
)
196 const struct input_stream
*left
= *(void **)a
, *right
= *(void **)b
;
197 return left
->zorder
!= right
->zorder
? (left
->zorder
< right
->zorder
? -1 : 1) : 0;
200 static void video_mixer_update_zorder_map(struct video_mixer
*mixer
)
204 for (i
= 0; i
< mixer
->input_count
; ++i
)
205 mixer
->zorder
[i
] = &mixer
->inputs
[i
];
207 qsort(mixer
->zorder
, mixer
->input_count
, sizeof(*mixer
->zorder
), video_mixer_zorder_sort_compare
);
210 static void video_mixer_flush_input(struct video_mixer
*mixer
)
214 for (i
= 0; i
< mixer
->input_count
; ++i
)
216 if (mixer
->inputs
[i
].sample
)
217 IMFSample_Release(mixer
->inputs
[i
].sample
);
218 mixer
->inputs
[i
].sample
= NULL
;
219 mixer
->inputs
[i
].sample_requested
= 0;
221 mixer
->output_rendered
= 0;
224 static void video_mixer_clear_types(struct video_mixer
*mixer
)
228 for (i
= 0; i
< mixer
->input_count
; ++i
)
230 if (mixer
->inputs
[i
].media_type
)
231 IMFMediaType_Release(mixer
->inputs
[i
].media_type
);
232 mixer
->inputs
[i
].media_type
= NULL
;
234 video_mixer_flush_input(mixer
);
235 for (i
= 0; i
< mixer
->output
.rt_formats_count
; ++i
)
237 IMFMediaType_Release(mixer
->output
.rt_formats
[i
].media_type
);
239 free(mixer
->output
.rt_formats
);
240 if (mixer
->output
.media_type
)
241 IMFMediaType_Release(mixer
->output
.media_type
);
242 memset(&mixer
->output
, 0, sizeof(mixer
->output
));
245 static HRESULT WINAPI
video_mixer_inner_QueryInterface(IUnknown
*iface
, REFIID riid
, void **obj
)
247 struct video_mixer
*mixer
= impl_from_IUnknown(iface
);
249 TRACE("%p, %s, %p.\n", iface
, debugstr_guid(riid
), obj
);
251 if (IsEqualIID(riid
, &IID_IUnknown
))
255 else if (IsEqualIID(riid
, &IID_IMFTransform
))
257 *obj
= &mixer
->IMFTransform_iface
;
259 else if (IsEqualIID(riid
, &IID_IMFVideoDeviceID
))
261 *obj
= &mixer
->IMFVideoDeviceID_iface
;
263 else if (IsEqualIID(riid
, &IID_IMFTopologyServiceLookupClient
))
265 *obj
= &mixer
->IMFTopologyServiceLookupClient_iface
;
267 else if (IsEqualIID(riid
, &IID_IMFVideoMixerControl2
) ||
268 IsEqualIID(riid
, &IID_IMFVideoMixerControl
))
270 *obj
= &mixer
->IMFVideoMixerControl2_iface
;
272 else if (IsEqualIID(riid
, &IID_IMFGetService
))
274 *obj
= &mixer
->IMFGetService_iface
;
276 else if (IsEqualIID(riid
, &IID_IMFVideoMixerBitmap
))
278 *obj
= &mixer
->IMFVideoMixerBitmap_iface
;
280 else if (IsEqualIID(riid
, &IID_IMFVideoPositionMapper
))
282 *obj
= &mixer
->IMFVideoPositionMapper_iface
;
284 else if (IsEqualIID(riid
, &IID_IMFVideoProcessor
))
286 *obj
= &mixer
->IMFVideoProcessor_iface
;
288 else if (IsEqualIID(riid
, &IID_IMFAttributes
))
290 *obj
= &mixer
->IMFAttributes_iface
;
292 else if (IsEqualIID(riid
, &IID_IMFQualityAdvise
))
294 *obj
= &mixer
->IMFQualityAdvise_iface
;
296 else if (IsEqualIID(riid
, &IID_IMFClockStateSink
))
298 *obj
= &mixer
->IMFClockStateSink_iface
;
302 WARN("Unsupported interface %s.\n", debugstr_guid(riid
));
304 return E_NOINTERFACE
;
307 IUnknown_AddRef((IUnknown
*)*obj
);
311 static ULONG WINAPI
video_mixer_inner_AddRef(IUnknown
*iface
)
313 struct video_mixer
*mixer
= impl_from_IUnknown(iface
);
314 ULONG refcount
= InterlockedIncrement(&mixer
->refcount
);
316 TRACE("%p, refcount %lu.\n", iface
, refcount
);
321 static void video_mixer_release_device_manager(struct video_mixer
*mixer
)
323 if (mixer
->processor
)
324 IDirectXVideoProcessor_Release(mixer
->processor
);
325 if (mixer
->device_manager
)
327 IDirect3DDeviceManager9_CloseDeviceHandle(mixer
->device_manager
, mixer
->device_handle
);
328 IDirect3DDeviceManager9_Release(mixer
->device_manager
);
330 mixer
->device_handle
= NULL
;
331 mixer
->device_manager
= NULL
;
332 mixer
->processor
= NULL
;
335 static ULONG WINAPI
video_mixer_inner_Release(IUnknown
*iface
)
337 struct video_mixer
*mixer
= impl_from_IUnknown(iface
);
338 ULONG refcount
= InterlockedDecrement(&mixer
->refcount
);
341 TRACE("%p, refcount %lu.\n", iface
, refcount
);
345 for (i
= 0; i
< mixer
->input_count
; ++i
)
347 if (mixer
->inputs
[i
].attributes
)
348 IMFAttributes_Release(mixer
->inputs
[i
].attributes
);
350 video_mixer_clear_types(mixer
);
351 video_mixer_release_device_manager(mixer
);
352 if (mixer
->attributes
)
353 IMFAttributes_Release(mixer
->attributes
);
354 if (mixer
->internal_attributes
)
355 IMFAttributes_Release(mixer
->internal_attributes
);
356 DeleteCriticalSection(&mixer
->cs
);
363 static const IUnknownVtbl video_mixer_inner_vtbl
=
365 video_mixer_inner_QueryInterface
,
366 video_mixer_inner_AddRef
,
367 video_mixer_inner_Release
,
370 static HRESULT WINAPI
video_mixer_transform_QueryInterface(IMFTransform
*iface
, REFIID riid
, void **obj
)
372 struct video_mixer
*mixer
= impl_from_IMFTransform(iface
);
373 return IUnknown_QueryInterface(mixer
->outer_unk
, riid
, obj
);
376 static ULONG WINAPI
video_mixer_transform_AddRef(IMFTransform
*iface
)
378 struct video_mixer
*mixer
= impl_from_IMFTransform(iface
);
379 return IUnknown_AddRef(mixer
->outer_unk
);
382 static ULONG WINAPI
video_mixer_transform_Release(IMFTransform
*iface
)
384 struct video_mixer
*mixer
= impl_from_IMFTransform(iface
);
385 return IUnknown_Release(mixer
->outer_unk
);
388 static HRESULT WINAPI
video_mixer_transform_GetStreamLimits(IMFTransform
*iface
, DWORD
*input_minimum
,
389 DWORD
*input_maximum
, DWORD
*output_minimum
, DWORD
*output_maximum
)
391 TRACE("%p, %p, %p, %p, %p.\n", iface
, input_minimum
, input_maximum
, output_minimum
, output_maximum
);
394 *input_maximum
= MAX_MIXER_INPUT_STREAMS
;
401 static HRESULT WINAPI
video_mixer_transform_GetStreamCount(IMFTransform
*iface
, DWORD
*inputs
, DWORD
*outputs
)
403 struct video_mixer
*mixer
= impl_from_IMFTransform(iface
);
405 TRACE("%p, %p, %p.\n", iface
, inputs
, outputs
);
407 EnterCriticalSection(&mixer
->cs
);
408 if (inputs
) *inputs
= mixer
->input_count
;
409 if (outputs
) *outputs
= 1;
410 LeaveCriticalSection(&mixer
->cs
);
415 static HRESULT WINAPI
video_mixer_transform_GetStreamIDs(IMFTransform
*iface
, DWORD input_size
, DWORD
*inputs
,
416 DWORD output_size
, DWORD
*outputs
)
418 struct video_mixer
*mixer
= impl_from_IMFTransform(iface
);
421 TRACE("%p, %lu, %p, %lu, %p.\n", iface
, input_size
, inputs
, output_size
, outputs
);
423 EnterCriticalSection(&mixer
->cs
);
424 if (mixer
->input_count
> input_size
|| !output_size
)
425 hr
= MF_E_BUFFERTOOSMALL
;
427 memcpy(inputs
, mixer
->input_ids
, mixer
->input_count
* sizeof(*inputs
));
428 if (outputs
) *outputs
= 0;
429 LeaveCriticalSection(&mixer
->cs
);
434 static HRESULT WINAPI
video_mixer_transform_GetInputStreamInfo(IMFTransform
*iface
, DWORD id
, MFT_INPUT_STREAM_INFO
*info
)
436 struct video_mixer
*mixer
= impl_from_IMFTransform(iface
);
437 struct input_stream
*input
;
440 TRACE("%p, %lu, %p.\n", iface
, id
, info
);
442 EnterCriticalSection(&mixer
->cs
);
444 if (SUCCEEDED(hr
= video_mixer_get_input(mixer
, id
, &input
)))
446 memset(info
, 0, sizeof(*info
));
448 info
->dwFlags
|= MFT_INPUT_STREAM_REMOVABLE
| MFT_INPUT_STREAM_OPTIONAL
;
451 LeaveCriticalSection(&mixer
->cs
);
456 static HRESULT WINAPI
video_mixer_transform_GetOutputStreamInfo(IMFTransform
*iface
, DWORD id
, MFT_OUTPUT_STREAM_INFO
*info
)
458 TRACE("%p, %lu, %p.\n", iface
, id
, info
);
461 return MF_E_INVALIDSTREAMNUMBER
;
463 memset(info
, 0, sizeof(*info
));
468 static HRESULT WINAPI
video_mixer_transform_GetAttributes(IMFTransform
*iface
, IMFAttributes
**attributes
)
470 struct video_mixer
*mixer
= impl_from_IMFTransform(iface
);
472 TRACE("%p, %p.\n", iface
, attributes
);
477 *attributes
= mixer
->attributes
;
478 IMFAttributes_AddRef(*attributes
);
483 static HRESULT WINAPI
video_mixer_transform_GetInputStreamAttributes(IMFTransform
*iface
, DWORD id
,
484 IMFAttributes
**attributes
)
486 struct video_mixer
*mixer
= impl_from_IMFTransform(iface
);
487 struct input_stream
*input
;
490 TRACE("%p, %lu, %p.\n", iface
, id
, attributes
);
492 EnterCriticalSection(&mixer
->cs
);
494 if (SUCCEEDED(hr
= video_mixer_get_input(mixer
, id
, &input
)))
496 *attributes
= input
->attributes
;
498 IMFAttributes_AddRef(*attributes
);
501 LeaveCriticalSection(&mixer
->cs
);
506 static HRESULT WINAPI
video_mixer_transform_GetOutputStreamAttributes(IMFTransform
*iface
, DWORD id
,
507 IMFAttributes
**attributes
)
509 TRACE("%p, %lu, %p.\n", iface
, id
, attributes
);
514 static HRESULT WINAPI
video_mixer_transform_DeleteInputStream(IMFTransform
*iface
, DWORD id
)
516 struct video_mixer
*mixer
= impl_from_IMFTransform(iface
);
517 struct input_stream
*input
;
521 TRACE("%p, %lu.\n", iface
, id
);
524 return MF_E_INVALIDSTREAMNUMBER
;
526 EnterCriticalSection(&mixer
->cs
);
528 /* Can't delete reference stream. */
529 if (SUCCEEDED(hr
= video_mixer_get_input(mixer
, id
, &input
)))
531 mixer
->input_count
--;
532 idx
= input
- mixer
->inputs
;
533 if (idx
< mixer
->input_count
)
535 if (mixer
->inputs
[idx
].attributes
)
536 IMFAttributes_Release(mixer
->inputs
[idx
].attributes
);
537 memmove(&mixer
->inputs
[idx
], &mixer
->inputs
[idx
+ 1], (mixer
->input_count
- idx
) * sizeof(*mixer
->inputs
));
538 memmove(&mixer
->input_ids
[idx
], &mixer
->input_ids
[idx
+ 1], (mixer
->input_count
- idx
) *
539 sizeof(*mixer
->input_ids
));
540 video_mixer_update_zorder_map(mixer
);
544 LeaveCriticalSection(&mixer
->cs
);
549 static int __cdecl
video_mixer_add_input_sort_compare(const void *a
, const void *b
)
551 const struct input_stream
*left
= a
, *right
= b
;
552 return left
->id
!= right
->id
? (left
->id
< right
->id
? -1 : 1) : 0;
555 static HRESULT WINAPI
video_mixer_transform_AddInputStreams(IMFTransform
*iface
, DWORD count
, DWORD
*ids
)
557 struct video_mixer
*mixer
= impl_from_IMFTransform(iface
);
558 struct input_stream inputs
[MAX_MIXER_INPUT_STREAMS
] = { {0} };
559 struct input_stream
*input
;
563 TRACE("%p, %lu, %p.\n", iface
, count
, ids
);
568 EnterCriticalSection(&mixer
->cs
);
569 if (count
> ARRAY_SIZE(mixer
->inputs
) - mixer
->input_count
)
573 /* Test for collisions. */
574 memcpy(inputs
, mixer
->inputs
, mixer
->input_count
* sizeof(*inputs
));
575 for (i
= 0; i
< count
; ++i
)
576 inputs
[i
+ mixer
->input_count
].id
= ids
[i
];
578 len
= mixer
->input_count
+ count
;
580 qsort(inputs
, len
, sizeof(*inputs
), video_mixer_add_input_sort_compare
);
582 for (i
= 1; i
< len
; ++i
)
584 if (inputs
[i
- 1].id
== inputs
[i
].id
)
593 unsigned int zorder
= mixer
->input_count
;
595 for (i
= 0; i
< count
; ++i
)
597 if ((input
= bsearch(&ids
[i
], inputs
, len
, sizeof(*inputs
), video_mixer_compare_input_id
)))
598 video_mixer_init_input(input
);
600 memcpy(&mixer
->input_ids
[mixer
->input_count
], ids
, count
* sizeof(*ids
));
601 memcpy(mixer
->inputs
, inputs
, len
* sizeof(*inputs
));
602 mixer
->input_count
+= count
;
604 for (i
= 0; i
< count
; ++i
)
606 if (SUCCEEDED(video_mixer_get_input(mixer
, ids
[i
], &input
)))
607 input
->zorder
= zorder
;
611 video_mixer_update_zorder_map(mixer
);
614 LeaveCriticalSection(&mixer
->cs
);
619 static HRESULT WINAPI
video_mixer_transform_GetInputAvailableType(IMFTransform
*iface
, DWORD id
, DWORD index
,
622 TRACE("%p, %lu, %lu, %p.\n", iface
, id
, index
, type
);
627 static HRESULT WINAPI
video_mixer_transform_GetOutputAvailableType(IMFTransform
*iface
, DWORD id
, DWORD index
,
630 struct video_mixer
*mixer
= impl_from_IMFTransform(iface
);
633 TRACE("%p, %lu, %lu, %p.\n", iface
, id
, index
, type
);
636 return MF_E_INVALIDSTREAMNUMBER
;
638 EnterCriticalSection(&mixer
->cs
);
640 if (!mixer
->inputs
[0].media_type
)
641 hr
= MF_E_TRANSFORM_TYPE_NOT_SET
;
642 else if (index
>= mixer
->output
.rt_formats_count
)
643 hr
= MF_E_NO_MORE_TYPES
;
646 if (SUCCEEDED(hr
= MFCreateMediaType(type
)))
647 hr
= IMFMediaType_CopyAllItems(mixer
->output
.rt_formats
[index
].media_type
, (IMFAttributes
*)*type
);
650 LeaveCriticalSection(&mixer
->cs
);
655 static HRESULT
video_mixer_init_dxva_videodesc(IMFMediaType
*media_type
, DXVA2_VideoDesc
*video_desc
)
657 const MFVIDEOFORMAT
*video_format
;
658 IMFVideoMediaType
*video_type
;
659 BOOL is_compressed
= TRUE
;
662 if (FAILED(IMFMediaType_QueryInterface(media_type
, &IID_IMFVideoMediaType
, (void **)&video_type
)))
663 return MF_E_INVALIDMEDIATYPE
;
665 video_format
= IMFVideoMediaType_GetVideoFormat(video_type
);
666 IMFVideoMediaType_IsCompressedFormat(video_type
, &is_compressed
);
668 if (!video_format
|| !video_format
->videoInfo
.dwWidth
|| !video_format
->videoInfo
.dwHeight
|| is_compressed
)
670 hr
= MF_E_INVALIDMEDIATYPE
;
674 memset(video_desc
, 0, sizeof(*video_desc
));
675 video_desc
->SampleWidth
= video_format
->videoInfo
.dwWidth
;
676 video_desc
->SampleHeight
= video_format
->videoInfo
.dwHeight
;
677 video_desc
->Format
= video_format
->surfaceInfo
.Format
;
680 IMFVideoMediaType_Release(video_type
);
685 static void video_mixer_append_rt_format(struct rt_format
*rt_formats
, unsigned int *count
,
686 const GUID
*device
, D3DFORMAT format
)
690 for (i
= 0; i
< *count
; ++i
)
692 if (rt_formats
[i
].format
== format
) return;
695 rt_formats
[*count
].format
= format
;
696 rt_formats
[*count
].device
= *device
;
700 static unsigned int video_mixer_get_interlace_mode_from_video_desc(const DXVA2_VideoDesc
*video_desc
)
702 switch (video_desc
->SampleFormat
.SampleFormat
)
704 case DXVA2_SampleFieldInterleavedEvenFirst
:
705 return MFVideoInterlace_FieldInterleavedUpperFirst
;
706 case DXVA2_SampleFieldInterleavedOddFirst
:
707 return MFVideoInterlace_FieldInterleavedLowerFirst
;
708 case DXVA2_SampleFieldSingleEven
:
709 return MFVideoInterlace_FieldSingleUpper
;
710 case DXVA2_SampleFieldSingleOdd
:
711 return MFVideoInterlace_FieldSingleLower
;
713 return MFVideoInterlace_Progressive
;
717 static void mf_get_attribute_uint32(IMFMediaType
*media_type
, const GUID
*key
, UINT32
*value
,
718 UINT32 default_value
)
720 if (FAILED(IMFMediaType_GetUINT32(media_type
, key
, value
)))
721 *value
= default_value
;
724 static void mf_get_attribute_uint64(IMFMediaType
*media_type
, const GUID
*key
, UINT64
*value
,
725 UINT64 default_value
)
727 if (FAILED(IMFMediaType_GetUINT64(media_type
, key
, value
)))
728 *value
= default_value
;
731 static HRESULT
video_mixer_collect_output_types(struct video_mixer
*mixer
, const DXVA2_VideoDesc
*video_desc
,
732 IMFMediaType
*media_type
, IDirectXVideoProcessorService
*service
, unsigned int device_count
,
733 const GUID
*devices
, unsigned int flags
)
735 struct rt_format
*rt_formats
= NULL
, *ptr
;
736 unsigned int i
, j
, format_count
, count
;
737 HRESULT hr
= MF_E_INVALIDMEDIATYPE
;
742 for (i
= 0; i
< device_count
; ++i
)
744 if (SUCCEEDED(IDirectXVideoProcessorService_GetVideoProcessorRenderTargets(service
, &devices
[i
], video_desc
,
745 &format_count
, &formats
)))
747 if (!(ptr
= realloc(rt_formats
, (count
+ format_count
) * sizeof(*rt_formats
))))
751 CoTaskMemFree(formats
);
756 for (j
= 0; j
< format_count
; ++j
)
757 video_mixer_append_rt_format(rt_formats
, &count
, &devices
[i
], formats
[j
]);
759 CoTaskMemFree(formats
);
763 if (count
&& !(flags
& MFT_SET_TYPE_TEST_ONLY
))
765 UINT32 fixed_samples
, interlace_mode
, width
= video_desc
->SampleWidth
, height
= video_desc
->SampleHeight
;
766 MFVideoArea aperture
;
769 if (!(mixer
->output
.rt_formats
= calloc(count
, sizeof(*mixer
->output
.rt_formats
))))
772 return E_OUTOFMEMORY
;
775 memcpy(&subtype
, &MFVideoFormat_Base
, sizeof(subtype
));
776 memset(&aperture
, 0, sizeof(aperture
));
777 if (SUCCEEDED(IMFMediaType_GetBlob(media_type
, &MF_MT_GEOMETRIC_APERTURE
, (UINT8
*)&aperture
,
778 sizeof(aperture
), NULL
)))
780 width
= aperture
.OffsetX
.value
+ aperture
.Area
.cx
;
781 height
= aperture
.OffsetX
.value
+ aperture
.Area
.cy
;
785 aperture
.Area
.cx
= width
;
786 aperture
.Area
.cy
= height
;
789 interlace_mode
= video_mixer_get_interlace_mode_from_video_desc(video_desc
);
790 mf_get_attribute_uint64(media_type
, &MF_MT_PIXEL_ASPECT_RATIO
, &par
, (UINT64
)1 << 32 | 1);
791 mf_get_attribute_uint32(media_type
, &MF_MT_FIXED_SIZE_SAMPLES
, &fixed_samples
, 1);
793 for (i
= 0; i
< count
; ++i
)
795 IMFMediaType
*rt_media_type
;
797 subtype
.Data1
= rt_formats
[i
].format
;
798 mixer
->output
.rt_formats
[i
] = rt_formats
[i
];
800 MFCreateMediaType(&rt_media_type
);
801 IMFMediaType_CopyAllItems(media_type
, (IMFAttributes
*)rt_media_type
);
802 IMFMediaType_SetGUID(rt_media_type
, &MF_MT_SUBTYPE
, &subtype
);
803 IMFMediaType_SetUINT64(rt_media_type
, &MF_MT_FRAME_SIZE
, (UINT64
)width
<< 32 | height
);
804 IMFMediaType_SetBlob(rt_media_type
, &MF_MT_GEOMETRIC_APERTURE
, (const UINT8
*)&aperture
, sizeof(aperture
));
805 IMFMediaType_SetBlob(rt_media_type
, &MF_MT_MINIMUM_DISPLAY_APERTURE
, (const UINT8
*)&aperture
, sizeof(aperture
));
806 IMFMediaType_SetUINT32(rt_media_type
, &MF_MT_INTERLACE_MODE
, interlace_mode
);
807 IMFMediaType_SetUINT64(rt_media_type
, &MF_MT_PIXEL_ASPECT_RATIO
, par
);
808 IMFMediaType_SetUINT32(rt_media_type
, &MF_MT_FIXED_SIZE_SAMPLES
, fixed_samples
);
810 mixer
->output
.rt_formats
[i
].media_type
= rt_media_type
;
812 mixer
->output
.rt_formats_count
= count
;
817 return count
? S_OK
: hr
;
820 static HRESULT
video_mixer_open_device_handle(struct video_mixer
*mixer
)
822 IDirect3DDeviceManager9_CloseDeviceHandle(mixer
->device_manager
, mixer
->device_handle
);
823 mixer
->device_handle
= NULL
;
824 return IDirect3DDeviceManager9_OpenDeviceHandle(mixer
->device_manager
, &mixer
->device_handle
);
827 static HRESULT
video_mixer_get_processor_service(struct video_mixer
*mixer
, IDirectXVideoProcessorService
**service
)
831 if (!mixer
->device_handle
)
833 if (FAILED(hr
= IDirect3DDeviceManager9_OpenDeviceHandle(mixer
->device_manager
, &mixer
->device_handle
)))
839 hr
= IDirect3DDeviceManager9_GetVideoService(mixer
->device_manager
, mixer
->device_handle
,
840 &IID_IDirectXVideoProcessorService
, (void **)service
);
841 if (hr
== DXVA2_E_NEW_VIDEO_DEVICE
)
843 if (SUCCEEDED(hr
= video_mixer_open_device_handle(mixer
)))
852 static HRESULT WINAPI
video_mixer_transform_SetInputType(IMFTransform
*iface
, DWORD id
, IMFMediaType
*media_type
, DWORD flags
)
854 struct video_mixer
*mixer
= impl_from_IMFTransform(iface
);
855 IDirectXVideoProcessorService
*service
;
856 DXVA2_VideoDesc video_desc
;
857 HRESULT hr
= E_NOTIMPL
;
861 TRACE("%p, %lu, %p, %#lx.\n", iface
, id
, media_type
, flags
);
863 if (!media_type
&& (flags
& MFT_SET_TYPE_TEST_ONLY
))
866 EnterCriticalSection(&mixer
->cs
);
868 if (!(flags
& MFT_SET_TYPE_TEST_ONLY
))
869 video_mixer_clear_types(mixer
);
873 else if (!mixer
->device_manager
)
874 hr
= MF_E_NOT_INITIALIZED
;
877 if (SUCCEEDED(hr
= video_mixer_get_processor_service(mixer
, &service
)))
879 if (SUCCEEDED(hr
= video_mixer_init_dxva_videodesc(media_type
, &video_desc
)))
883 if (SUCCEEDED(hr
= IDirectXVideoProcessorService_GetVideoProcessorDeviceGuids(service
, &video_desc
,
886 if (SUCCEEDED(hr
= video_mixer_collect_output_types(mixer
, &video_desc
, media_type
,
887 service
, count
, guids
, flags
)) && !(flags
& MFT_SET_TYPE_TEST_ONLY
))
889 if (mixer
->inputs
[0].media_type
)
890 IMFMediaType_Release(mixer
->inputs
[0].media_type
);
891 mixer
->inputs
[0].media_type
= media_type
;
893 if (FAILED(IMFMediaType_GetBlob(media_type
, &MF_MT_GEOMETRIC_APERTURE
,
894 (BYTE
*)&mixer
->inputs
[0].aperture
, sizeof(mixer
->inputs
[0].aperture
), NULL
)))
896 memset(&mixer
->inputs
[0].aperture
, 0, sizeof(mixer
->inputs
[0].aperture
));
897 mixer
->inputs
[0].aperture
.Area
.cx
= video_desc
.SampleWidth
;
898 mixer
->inputs
[0].aperture
.Area
.cy
= video_desc
.SampleHeight
;
901 IMFMediaType_AddRef(mixer
->inputs
[0].media_type
);
903 CoTaskMemFree(guids
);
908 FIXME("Unimplemented for substreams.\n");
912 IDirectXVideoProcessorService_Release(service
);
916 LeaveCriticalSection(&mixer
->cs
);
921 static HRESULT WINAPI
video_mixer_transform_SetOutputType(IMFTransform
*iface
, DWORD id
, IMFMediaType
*type
, DWORD flags
)
923 const unsigned int equality_flags
= MF_MEDIATYPE_EQUAL_MAJOR_TYPES
| MF_MEDIATYPE_EQUAL_FORMAT_TYPES
;
924 struct video_mixer
*mixer
= impl_from_IMFTransform(iface
);
925 HRESULT hr
= MF_E_INVALIDMEDIATYPE
;
926 BOOL is_compressed
= TRUE
;
930 TRACE("%p, %lu, %p, %#lx.\n", iface
, id
, type
, flags
);
933 return MF_E_INVALIDSTREAMNUMBER
;
938 if (FAILED(IMFMediaType_IsCompressedFormat(type
, &is_compressed
)) || is_compressed
)
939 return MF_E_INVALIDMEDIATYPE
;
941 EnterCriticalSection(&mixer
->cs
);
943 for (i
= 0; i
< mixer
->output
.rt_formats_count
; ++i
)
946 if (FAILED(IMFMediaType_IsEqual(type
, mixer
->output
.rt_formats
[i
].media_type
, &compare_flags
)))
949 if ((compare_flags
& equality_flags
) == equality_flags
)
956 if (SUCCEEDED(hr
) && !(flags
& MFT_SET_TYPE_TEST_ONLY
))
958 IDirectXVideoProcessorService
*service
;
960 if (SUCCEEDED(hr
= video_mixer_get_processor_service(mixer
, &service
)))
962 DXVA2_VideoDesc video_desc
;
963 GUID subtype
= { 0 };
966 if (mixer
->processor
)
967 IDirectXVideoProcessor_Release(mixer
->processor
);
968 mixer
->processor
= NULL
;
970 video_mixer_init_dxva_videodesc(mixer
->inputs
[0].media_type
, &video_desc
);
971 IMFMediaType_GetGUID(type
, &MF_MT_SUBTYPE
, &subtype
);
972 rt_format
= subtype
.Data1
;
974 if (SUCCEEDED(hr
= IDirectXVideoProcessorService_CreateVideoProcessor(service
, &mixer
->output
.rt_formats
[i
].device
,
975 &video_desc
, rt_format
, MAX_MIXER_INPUT_SUBSTREAMS
, &mixer
->processor
)))
977 if (mixer
->output
.media_type
)
978 IMFMediaType_Release(mixer
->output
.media_type
);
979 mixer
->output
.media_type
= type
;
980 IMFMediaType_AddRef(mixer
->output
.media_type
);
983 IDirectXVideoProcessorService_Release(service
);
987 LeaveCriticalSection(&mixer
->cs
);
992 static HRESULT WINAPI
video_mixer_transform_GetInputCurrentType(IMFTransform
*iface
, DWORD id
, IMFMediaType
**type
)
994 struct video_mixer
*mixer
= impl_from_IMFTransform(iface
);
995 struct input_stream
*stream
;
998 TRACE("%p, %lu, %p.\n", iface
, id
, type
);
1000 EnterCriticalSection(&mixer
->cs
);
1002 if (SUCCEEDED(hr
= video_mixer_get_input(mixer
, id
, &stream
)))
1004 if (!stream
->media_type
)
1005 hr
= MF_E_TRANSFORM_TYPE_NOT_SET
;
1008 *type
= stream
->media_type
;
1009 IMFMediaType_AddRef(*type
);
1013 LeaveCriticalSection(&mixer
->cs
);
1018 static HRESULT WINAPI
video_mixer_transform_GetOutputCurrentType(IMFTransform
*iface
, DWORD id
, IMFMediaType
**type
)
1020 struct video_mixer
*mixer
= impl_from_IMFTransform(iface
);
1023 TRACE("%p, %lu, %p.\n", iface
, id
, type
);
1026 return MF_E_INVALIDSTREAMNUMBER
;
1028 EnterCriticalSection(&mixer
->cs
);
1030 if (!mixer
->output
.media_type
)
1031 hr
= MF_E_TRANSFORM_TYPE_NOT_SET
;
1034 *type
= mixer
->output
.media_type
;
1035 IMFMediaType_AddRef(*type
);
1038 LeaveCriticalSection(&mixer
->cs
);
1043 static HRESULT WINAPI
video_mixer_transform_GetInputStatus(IMFTransform
*iface
, DWORD id
, DWORD
*status
)
1045 struct video_mixer
*mixer
= impl_from_IMFTransform(iface
);
1046 struct input_stream
*stream
;
1049 TRACE("%p, %lu, %p.\n", iface
, id
, status
);
1054 EnterCriticalSection(&mixer
->cs
);
1056 if (!mixer
->output
.media_type
)
1057 hr
= MF_E_TRANSFORM_TYPE_NOT_SET
;
1058 else if (SUCCEEDED(hr
= video_mixer_get_input(mixer
, id
, &stream
)))
1060 *status
= stream
->sample
? 0 : MFT_INPUT_STATUS_ACCEPT_DATA
;
1063 LeaveCriticalSection(&mixer
->cs
);
1068 static HRESULT WINAPI
video_mixer_transform_GetOutputStatus(IMFTransform
*iface
, DWORD
*status
)
1070 struct video_mixer
*mixer
= impl_from_IMFTransform(iface
);
1074 TRACE("%p, %p.\n", iface
, status
);
1079 EnterCriticalSection(&mixer
->cs
);
1081 if (!mixer
->output
.media_type
)
1082 hr
= MF_E_TRANSFORM_TYPE_NOT_SET
;
1085 *status
= MFT_OUTPUT_STATUS_SAMPLE_READY
;
1086 for (i
= 0; i
< mixer
->input_count
; ++i
)
1088 if (!mixer
->inputs
[i
].sample
)
1096 LeaveCriticalSection(&mixer
->cs
);
1101 static HRESULT WINAPI
video_mixer_transform_SetOutputBounds(IMFTransform
*iface
, LONGLONG lower
, LONGLONG upper
)
1103 struct video_mixer
*mixer
= impl_from_IMFTransform(iface
);
1105 TRACE("%p, %s, %s.\n", iface
, wine_dbgstr_longlong(lower
), wine_dbgstr_longlong(upper
));
1107 EnterCriticalSection(&mixer
->cs
);
1109 mixer
->lower_bound
= lower
;
1110 mixer
->upper_bound
= upper
;
1112 LeaveCriticalSection(&mixer
->cs
);
1117 static HRESULT WINAPI
video_mixer_transform_ProcessEvent(IMFTransform
*iface
, DWORD id
, IMFMediaEvent
*event
)
1119 FIXME("%p, %lu, %p.\n", iface
, id
, event
);
1124 static void video_mixer_request_sample(struct video_mixer
*mixer
, unsigned int idx
)
1126 if (!mixer
->event_sink
|| mixer
->inputs
[idx
].sample_requested
)
1129 IMediaEventSink_Notify(mixer
->event_sink
, EC_SAMPLE_NEEDED
, idx
, 0);
1130 mixer
->inputs
[idx
].sample_requested
= 1;
1133 static HRESULT WINAPI
video_mixer_transform_ProcessMessage(IMFTransform
*iface
, MFT_MESSAGE_TYPE message
, ULONG_PTR param
)
1135 struct video_mixer
*mixer
= impl_from_IMFTransform(iface
);
1139 TRACE("%p, %#x, %Iu.\n", iface
, message
, param
);
1141 EnterCriticalSection(&mixer
->cs
);
1145 case MFT_MESSAGE_SET_D3D_MANAGER
:
1146 video_mixer_release_device_manager(mixer
);
1148 hr
= IUnknown_QueryInterface((IUnknown
*)param
, &IID_IDirect3DDeviceManager9
, (void **)&mixer
->device_manager
);
1152 case MFT_MESSAGE_COMMAND_FLUSH
:
1153 video_mixer_flush_input(mixer
);
1157 case MFT_MESSAGE_NOTIFY_BEGIN_STREAMING
:
1158 case MFT_MESSAGE_NOTIFY_END_STREAMING
:
1159 if (mixer
->is_streaming
)
1160 video_mixer_flush_input(mixer
);
1163 for (i
= 0; i
< mixer
->input_count
; ++i
)
1164 video_mixer_request_sample(mixer
, i
);
1167 mixer
->is_streaming
= message
== MFT_MESSAGE_NOTIFY_BEGIN_STREAMING
;
1171 case MFT_MESSAGE_COMMAND_DRAIN
:
1175 WARN("Message not handled %d.\n", message
);
1179 LeaveCriticalSection(&mixer
->cs
);
1184 static HRESULT WINAPI
video_mixer_transform_ProcessInput(IMFTransform
*iface
, DWORD id
, IMFSample
*sample
, DWORD flags
)
1186 struct video_mixer
*mixer
= impl_from_IMFTransform(iface
);
1187 struct input_stream
*input
;
1190 TRACE("%p, %lu, %p, %#lx.\n", iface
, id
, sample
, flags
);
1195 EnterCriticalSection(&mixer
->cs
);
1197 if (SUCCEEDED(hr
= video_mixer_get_input(mixer
, id
, &input
)))
1199 if (!input
->media_type
|| !mixer
->output
.media_type
)
1200 hr
= MF_E_TRANSFORM_TYPE_NOT_SET
;
1201 else if (input
->sample
&& !mixer
->output_rendered
)
1202 hr
= MF_E_NOTACCEPTING
;
1205 if (input
->sample
&& mixer
->output_rendered
)
1206 video_mixer_flush_input(mixer
);
1207 mixer
->is_streaming
= 1;
1208 input
->sample_requested
= 0;
1209 input
->sample
= sample
;
1210 IMFSample_AddRef(input
->sample
);
1214 LeaveCriticalSection(&mixer
->cs
);
1219 static HRESULT
video_mixer_get_sample_surface(IMFSample
*sample
, IDirect3DSurface9
**surface
)
1221 IMFMediaBuffer
*buffer
;
1225 if (FAILED(hr
= IMFSample_GetBufferByIndex(sample
, 0, &buffer
)))
1228 hr
= IMFMediaBuffer_QueryInterface(buffer
, &IID_IMFGetService
, (void **)&gs
);
1229 IMFMediaBuffer_Release(buffer
);
1233 hr
= IMFGetService_GetService(gs
, &MR_BUFFER_SERVICE
, &IID_IDirect3DSurface9
, (void **)surface
);
1234 IMFGetService_Release(gs
);
1238 static HRESULT
video_mixer_get_d3d_device(struct video_mixer
*mixer
, IDirect3DDevice9
**device
)
1244 hr
= IDirect3DDeviceManager9_LockDevice(mixer
->device_manager
, mixer
->device_handle
,
1246 if (hr
== DXVA2_E_NEW_VIDEO_DEVICE
)
1248 if (SUCCEEDED(hr
= video_mixer_open_device_handle(mixer
)))
1257 static BOOL
video_mixer_rect_needs_scaling(const MFVideoNormalizedRect
*scale
)
1259 return scale
->left
!= 0.0f
|| scale
->top
!= 0.0f
|| scale
->right
!= 1.0f
|| scale
->bottom
!= 1.0f
;
1262 static void video_mixer_scale_rect(RECT
*rect
, unsigned int width
, unsigned int height
,
1263 const MFVideoNormalizedRect
*scale
)
1265 if (video_mixer_rect_needs_scaling(scale
))
1267 rect
->left
= width
* scale
->left
;
1268 rect
->right
= width
* scale
->right
;
1269 rect
->top
= height
* scale
->top
;
1270 rect
->bottom
= height
* scale
->bottom
;
1273 SetRect(rect
, 0, 0, width
, height
);
1276 static void video_mixer_correct_aspect_ratio(const RECT
*src
, RECT
*dst
)
1278 unsigned int src_width
= src
->right
- src
->left
, src_height
= src
->bottom
- src
->top
;
1279 unsigned int dst_width
= dst
->right
- dst
->left
, dst_height
= dst
->bottom
- dst
->top
;
1281 if (src_width
* dst_height
> dst_width
* src_height
)
1283 /* src is "wider" than dst. */
1284 unsigned int dst_center
= (dst
->top
+ dst
->bottom
) / 2;
1285 unsigned int scaled_height
= src_height
* dst_width
/ src_width
;
1287 dst
->top
= dst_center
- scaled_height
/ 2;
1288 dst
->bottom
= dst
->top
+ scaled_height
;
1290 else if (src_width
* dst_height
< dst_width
* src_height
)
1292 /* src is "taller" than dst. */
1293 unsigned int dst_center
= (dst
->left
+ dst
->right
) / 2;
1294 unsigned int scaled_width
= src_width
* dst_height
/ src_height
;
1296 dst
->left
= dst_center
- scaled_width
/ 2;
1297 dst
->right
= dst
->left
+ scaled_width
;
1301 static void video_mixer_render(struct video_mixer
*mixer
, IDirect3DSurface9
*rt
)
1303 DXVA2_VideoSample samples
[MAX_MIXER_INPUT_STREAMS
] = {{ 0 }};
1304 DXVA2_VideoProcessBltParams params
= { 0 };
1305 MFVideoNormalizedRect zoom_rect
;
1306 struct input_stream
*stream
;
1307 MFVideoArea aperture
;
1311 if (FAILED(IMFAttributes_GetBlob(mixer
->attributes
, &VIDEO_ZOOM_RECT
, (UINT8
*)&zoom_rect
,
1312 sizeof(zoom_rect
), NULL
)))
1314 zoom_rect
.left
= zoom_rect
.top
= 0.0f
;
1315 zoom_rect
.right
= zoom_rect
.bottom
= 1.0f
;
1318 if (FAILED(IMFMediaType_GetBlob(mixer
->output
.media_type
, &MF_MT_GEOMETRIC_APERTURE
,
1319 (UINT8
*)&aperture
, sizeof(aperture
), NULL
)))
1320 aperture
= mixer
->inputs
[0].aperture
;
1321 SetRect(¶ms
.TargetRect
, 0, 0, aperture
.Area
.cx
, aperture
.Area
.cy
);
1322 OffsetRect(¶ms
.TargetRect
, aperture
.OffsetX
.value
, aperture
.OffsetY
.value
);
1324 for (i
= 0; i
< mixer
->input_count
; ++i
)
1326 DXVA2_VideoSample
*sample
= &samples
[i
];
1327 IDirect3DSurface9
*surface
;
1329 stream
= mixer
->zorder
[i
];
1331 if (FAILED(hr
= video_mixer_get_sample_surface(stream
->sample
, &surface
)))
1333 WARN("Failed to get source surface for stream %u, hr %#lx.\n", i
, hr
);
1337 /* Full input frame corrected to full destination rectangle. */
1339 video_mixer_scale_rect(&sample
->SrcRect
, stream
->aperture
.Area
.cx
, stream
->aperture
.Area
.cy
, &zoom_rect
);
1340 OffsetRect(&sample
->SrcRect
, stream
->aperture
.OffsetX
.value
, stream
->aperture
.OffsetY
.value
);
1341 CopyRect(&sample
->DstRect
, ¶ms
.TargetRect
);
1342 video_mixer_correct_aspect_ratio(&sample
->SrcRect
, &sample
->DstRect
);
1344 if (video_mixer_rect_needs_scaling(&stream
->rect
))
1345 WARN("Ignoring stream %u rectangle %s.\n", stream
->id
, debugstr_normalized_rect(&stream
->rect
));
1347 sample
->SampleFormat
.SampleFormat
= stream
->id
== 0 ? DXVA2_SampleProgressiveFrame
: DXVA2_SampleSubStream
;
1348 sample
->SrcSurface
= surface
;
1349 sample
->PlanarAlpha
= DXVA2_Fixed32OpaqueAlpha();
1354 params
.BackgroundColor
= mixer
->bkgnd_color
.ayuv
;
1355 params
.Alpha
= DXVA2_Fixed32OpaqueAlpha();
1357 if (FAILED(hr
= IDirectXVideoProcessor_VideoProcessBlt(mixer
->processor
, rt
, ¶ms
, samples
,
1358 mixer
->input_count
, NULL
)))
1360 WARN("Failed to process samples, hr %#lx.\n", hr
);
1364 for (i
= 0; i
< mixer
->input_count
; ++i
)
1366 if (samples
[i
].SrcSurface
)
1367 IDirect3DSurface9_Release(samples
[i
].SrcSurface
);
1371 static HRESULT
video_mixer_get_sample_desired_time(IMFSample
*sample
, LONGLONG
*timestamp
, LONGLONG
*duration
)
1373 IMFDesiredSample
*desired
;
1376 *timestamp
= *duration
= 0;
1377 if (SUCCEEDED(hr
= IMFSample_QueryInterface(sample
, &IID_IMFDesiredSample
, (void **)&desired
)))
1379 hr
= IMFDesiredSample_GetDesiredSampleTimeAndDuration(desired
, timestamp
, duration
);
1380 IMFDesiredSample_Release(desired
);
1386 static BOOL
video_mixer_has_input(const struct video_mixer
*mixer
)
1390 for (i
= 0; i
< mixer
->input_count
; ++i
)
1392 if (!mixer
->inputs
[i
].sample
) return FALSE
;
1398 static HRESULT WINAPI
video_mixer_transform_ProcessOutput(IMFTransform
*iface
, DWORD flags
, DWORD count
,
1399 MFT_OUTPUT_DATA_BUFFER
*buffers
, DWORD
*status
)
1401 struct video_mixer
*mixer
= impl_from_IMFTransform(iface
);
1402 LONGLONG timestamp
, duration
;
1403 IDirect3DSurface9
*surface
;
1404 IDirect3DDevice9
*device
;
1405 BOOL repaint
= FALSE
;
1409 TRACE("%p, %#lx, %lu, %p, %p.\n", iface
, flags
, count
, buffers
, status
);
1411 if (!buffers
|| !count
|| count
> 1 || !buffers
->pSample
)
1412 return E_INVALIDARG
;
1414 if (buffers
->dwStreamID
)
1415 return MF_E_INVALIDSTREAMNUMBER
;
1419 EnterCriticalSection(&mixer
->cs
);
1421 if (SUCCEEDED(hr
= video_mixer_get_sample_surface(buffers
->pSample
, &surface
)))
1423 if (mixer
->is_streaming
)
1425 /* Desired timestamp is ignored, duration is required to be non-zero but is not used either. */
1426 if (SUCCEEDED(video_mixer_get_sample_desired_time(buffers
->pSample
, ×tamp
, &duration
)))
1428 if (!(repaint
= !!duration
))
1430 WARN("Unexpected sample duration.\n");
1435 /* Not enough input, or no new input. */
1436 if (SUCCEEDED(hr
) && (!video_mixer_has_input(mixer
) || (!repaint
&& mixer
->output_rendered
)))
1437 hr
= MF_E_TRANSFORM_NEED_MORE_INPUT
;
1441 video_mixer_render(mixer
, surface
);
1443 timestamp
= duration
= 0;
1444 if (SUCCEEDED(IMFSample_GetSampleTime(mixer
->inputs
[0].sample
, ×tamp
)))
1446 IMFSample_GetSampleDuration(mixer
->inputs
[0].sample
, &duration
);
1447 IMFSample_SetSampleTime(buffers
->pSample
, timestamp
);
1448 IMFSample_SetSampleDuration(buffers
->pSample
, duration
);
1450 mixer
->output_rendered
= 1;
1453 if (SUCCEEDED(hr
) && !repaint
)
1455 for (i
= 0; i
< mixer
->input_count
; ++i
)
1456 video_mixer_request_sample(mixer
, i
);
1461 if (SUCCEEDED(video_mixer_get_sample_desired_time(buffers
->pSample
, ×tamp
, &duration
)))
1463 if (SUCCEEDED(hr
= video_mixer_get_d3d_device(mixer
, &device
)))
1465 IDirect3DDevice9_ColorFill(device
, surface
, NULL
, 0);
1466 IDirect3DDeviceManager9_UnlockDevice(mixer
->device_manager
, mixer
->device_handle
, FALSE
);
1467 IDirect3DDevice9_Release(device
);
1471 hr
= MF_E_TRANSFORM_NEED_MORE_INPUT
;
1473 IDirect3DSurface9_Release(surface
);
1476 LeaveCriticalSection(&mixer
->cs
);
1481 static const IMFTransformVtbl video_mixer_transform_vtbl
=
1483 video_mixer_transform_QueryInterface
,
1484 video_mixer_transform_AddRef
,
1485 video_mixer_transform_Release
,
1486 video_mixer_transform_GetStreamLimits
,
1487 video_mixer_transform_GetStreamCount
,
1488 video_mixer_transform_GetStreamIDs
,
1489 video_mixer_transform_GetInputStreamInfo
,
1490 video_mixer_transform_GetOutputStreamInfo
,
1491 video_mixer_transform_GetAttributes
,
1492 video_mixer_transform_GetInputStreamAttributes
,
1493 video_mixer_transform_GetOutputStreamAttributes
,
1494 video_mixer_transform_DeleteInputStream
,
1495 video_mixer_transform_AddInputStreams
,
1496 video_mixer_transform_GetInputAvailableType
,
1497 video_mixer_transform_GetOutputAvailableType
,
1498 video_mixer_transform_SetInputType
,
1499 video_mixer_transform_SetOutputType
,
1500 video_mixer_transform_GetInputCurrentType
,
1501 video_mixer_transform_GetOutputCurrentType
,
1502 video_mixer_transform_GetInputStatus
,
1503 video_mixer_transform_GetOutputStatus
,
1504 video_mixer_transform_SetOutputBounds
,
1505 video_mixer_transform_ProcessEvent
,
1506 video_mixer_transform_ProcessMessage
,
1507 video_mixer_transform_ProcessInput
,
1508 video_mixer_transform_ProcessOutput
,
1511 static HRESULT WINAPI
video_mixer_device_id_QueryInterface(IMFVideoDeviceID
*iface
, REFIID riid
, void **obj
)
1513 struct video_mixer
*mixer
= impl_from_IMFVideoDeviceID(iface
);
1514 return IMFTransform_QueryInterface(&mixer
->IMFTransform_iface
, riid
, obj
);
1517 static ULONG WINAPI
video_mixer_device_id_AddRef(IMFVideoDeviceID
*iface
)
1519 struct video_mixer
*mixer
= impl_from_IMFVideoDeviceID(iface
);
1520 return IMFTransform_AddRef(&mixer
->IMFTransform_iface
);
1523 static ULONG WINAPI
video_mixer_device_id_Release(IMFVideoDeviceID
*iface
)
1525 struct video_mixer
*mixer
= impl_from_IMFVideoDeviceID(iface
);
1526 return IMFTransform_Release(&mixer
->IMFTransform_iface
);
1529 static HRESULT WINAPI
video_mixer_device_id_GetDeviceID(IMFVideoDeviceID
*iface
, IID
*device_id
)
1531 TRACE("%p, %p.\n", iface
, device_id
);
1536 memcpy(device_id
, &IID_IDirect3DDevice9
, sizeof(*device_id
));
1541 static const IMFVideoDeviceIDVtbl video_mixer_device_id_vtbl
=
1543 video_mixer_device_id_QueryInterface
,
1544 video_mixer_device_id_AddRef
,
1545 video_mixer_device_id_Release
,
1546 video_mixer_device_id_GetDeviceID
,
1549 static HRESULT WINAPI
video_mixer_service_client_QueryInterface(IMFTopologyServiceLookupClient
*iface
,
1550 REFIID riid
, void **obj
)
1552 struct video_mixer
*mixer
= impl_from_IMFTopologyServiceLookupClient(iface
);
1553 return IMFTransform_QueryInterface(&mixer
->IMFTransform_iface
, riid
, obj
);
1556 static ULONG WINAPI
video_mixer_service_client_AddRef(IMFTopologyServiceLookupClient
*iface
)
1558 struct video_mixer
*mixer
= impl_from_IMFTopologyServiceLookupClient(iface
);
1559 return IMFTransform_AddRef(&mixer
->IMFTransform_iface
);
1562 static ULONG WINAPI
video_mixer_service_client_Release(IMFTopologyServiceLookupClient
*iface
)
1564 struct video_mixer
*mixer
= impl_from_IMFTopologyServiceLookupClient(iface
);
1565 return IMFTransform_Release(&mixer
->IMFTransform_iface
);
1568 static HRESULT WINAPI
video_mixer_service_client_InitServicePointers(IMFTopologyServiceLookupClient
*iface
,
1569 IMFTopologyServiceLookup
*service_lookup
)
1571 struct video_mixer
*mixer
= impl_from_IMFTopologyServiceLookupClient(iface
);
1575 TRACE("%p, %p.\n", iface
, service_lookup
);
1577 if (!service_lookup
)
1580 EnterCriticalSection(&mixer
->cs
);
1583 if (FAILED(hr
= IMFTopologyServiceLookup_LookupService(service_lookup
, MF_SERVICE_LOOKUP_GLOBAL
, 0,
1584 &MR_VIDEO_RENDER_SERVICE
, &IID_IMediaEventSink
, (void **)&mixer
->event_sink
, &count
)))
1586 WARN("Failed to get renderer event sink, hr %#lx.\n", hr
);
1589 LeaveCriticalSection(&mixer
->cs
);
1594 static HRESULT WINAPI
video_mixer_service_client_ReleaseServicePointers(IMFTopologyServiceLookupClient
*iface
)
1596 struct video_mixer
*mixer
= impl_from_IMFTopologyServiceLookupClient(iface
);
1598 TRACE("%p.\n", iface
);
1600 EnterCriticalSection(&mixer
->cs
);
1602 if (mixer
->event_sink
)
1603 IMediaEventSink_Release(mixer
->event_sink
);
1604 mixer
->event_sink
= NULL
;
1606 LeaveCriticalSection(&mixer
->cs
);
1611 static const IMFTopologyServiceLookupClientVtbl video_mixer_service_client_vtbl
=
1613 video_mixer_service_client_QueryInterface
,
1614 video_mixer_service_client_AddRef
,
1615 video_mixer_service_client_Release
,
1616 video_mixer_service_client_InitServicePointers
,
1617 video_mixer_service_client_ReleaseServicePointers
,
1620 static HRESULT WINAPI
video_mixer_control_QueryInterface(IMFVideoMixerControl2
*iface
, REFIID riid
, void **obj
)
1622 struct video_mixer
*mixer
= impl_from_IMFVideoMixerControl2(iface
);
1623 return IMFTransform_QueryInterface(&mixer
->IMFTransform_iface
, riid
, obj
);
1626 static ULONG WINAPI
video_mixer_control_AddRef(IMFVideoMixerControl2
*iface
)
1628 struct video_mixer
*mixer
= impl_from_IMFVideoMixerControl2(iface
);
1629 return IMFTransform_AddRef(&mixer
->IMFTransform_iface
);
1632 static ULONG WINAPI
video_mixer_control_Release(IMFVideoMixerControl2
*iface
)
1634 struct video_mixer
*mixer
= impl_from_IMFVideoMixerControl2(iface
);
1635 return IMFTransform_Release(&mixer
->IMFTransform_iface
);
1638 static HRESULT WINAPI
video_mixer_control_SetStreamZOrder(IMFVideoMixerControl2
*iface
, DWORD id
, DWORD zorder
)
1640 struct video_mixer
*mixer
= impl_from_IMFVideoMixerControl2(iface
);
1641 struct input_stream
*stream
;
1644 TRACE("%p, %lu, %lu.\n", iface
, id
, zorder
);
1646 /* Can't change reference stream. */
1648 return E_INVALIDARG
;
1650 EnterCriticalSection(&mixer
->cs
);
1652 if (zorder
>= mixer
->input_count
)
1654 else if (SUCCEEDED(hr
= video_mixer_get_input(mixer
, id
, &stream
)))
1656 /* Lowest zorder only applies to reference stream. */
1658 hr
= MF_E_INVALIDREQUEST
;
1659 else if (stream
->zorder
!= zorder
)
1661 stream
->zorder
= zorder
;
1662 video_mixer_update_zorder_map(mixer
);
1666 LeaveCriticalSection(&mixer
->cs
);
1671 static HRESULT WINAPI
video_mixer_control_GetStreamZOrder(IMFVideoMixerControl2
*iface
, DWORD id
, DWORD
*zorder
)
1673 struct video_mixer
*mixer
= impl_from_IMFVideoMixerControl2(iface
);
1674 struct input_stream
*stream
;
1677 TRACE("%p, %lu, %p.\n", iface
, id
, zorder
);
1682 EnterCriticalSection(&mixer
->cs
);
1684 if (SUCCEEDED(hr
= video_mixer_get_input(mixer
, id
, &stream
)))
1685 *zorder
= stream
->zorder
;
1687 LeaveCriticalSection(&mixer
->cs
);
1692 static HRESULT WINAPI
video_mixer_control_SetStreamOutputRect(IMFVideoMixerControl2
*iface
, DWORD id
,
1693 const MFVideoNormalizedRect
*rect
)
1695 struct video_mixer
*mixer
= impl_from_IMFVideoMixerControl2(iface
);
1696 struct input_stream
*stream
;
1699 TRACE("%p, %lu, %s.\n", iface
, id
, debugstr_normalized_rect(rect
));
1704 if (rect
->left
> rect
->right
|| rect
->top
> rect
->bottom
||
1705 rect
->left
< 0.0f
|| rect
->top
< 0.0f
|| rect
->right
> 1.0f
|| rect
->bottom
> 1.0f
)
1707 return E_INVALIDARG
;
1710 EnterCriticalSection(&mixer
->cs
);
1712 if (SUCCEEDED(hr
= video_mixer_get_input(mixer
, id
, &stream
)))
1713 stream
->rect
= *rect
;
1715 LeaveCriticalSection(&mixer
->cs
);
1720 static HRESULT WINAPI
video_mixer_control_GetStreamOutputRect(IMFVideoMixerControl2
*iface
, DWORD id
,
1721 MFVideoNormalizedRect
*rect
)
1723 struct video_mixer
*mixer
= impl_from_IMFVideoMixerControl2(iface
);
1724 struct input_stream
*stream
;
1727 TRACE("%p, %lu, %p.\n", iface
, id
, rect
);
1732 EnterCriticalSection(&mixer
->cs
);
1734 if (SUCCEEDED(hr
= video_mixer_get_input(mixer
, id
, &stream
)))
1735 *rect
= stream
->rect
;
1737 LeaveCriticalSection(&mixer
->cs
);
1742 static HRESULT WINAPI
video_mixer_control_SetMixingPrefs(IMFVideoMixerControl2
*iface
, DWORD flags
)
1744 struct video_mixer
*mixer
= impl_from_IMFVideoMixerControl2(iface
);
1746 TRACE("%p, %#lx.\n", iface
, flags
);
1748 EnterCriticalSection(&mixer
->cs
);
1749 mixer
->mixing_flags
= flags
;
1750 LeaveCriticalSection(&mixer
->cs
);
1755 static HRESULT WINAPI
video_mixer_control_GetMixingPrefs(IMFVideoMixerControl2
*iface
, DWORD
*flags
)
1757 struct video_mixer
*mixer
= impl_from_IMFVideoMixerControl2(iface
);
1759 TRACE("%p, %p.\n", iface
, flags
);
1764 EnterCriticalSection(&mixer
->cs
);
1765 *flags
= mixer
->mixing_flags
;
1766 LeaveCriticalSection(&mixer
->cs
);
1771 static const IMFVideoMixerControl2Vtbl video_mixer_control_vtbl
=
1773 video_mixer_control_QueryInterface
,
1774 video_mixer_control_AddRef
,
1775 video_mixer_control_Release
,
1776 video_mixer_control_SetStreamZOrder
,
1777 video_mixer_control_GetStreamZOrder
,
1778 video_mixer_control_SetStreamOutputRect
,
1779 video_mixer_control_GetStreamOutputRect
,
1780 video_mixer_control_SetMixingPrefs
,
1781 video_mixer_control_GetMixingPrefs
,
1784 static HRESULT WINAPI
video_mixer_getservice_QueryInterface(IMFGetService
*iface
, REFIID riid
, void **obj
)
1786 struct video_mixer
*mixer
= impl_from_IMFGetService(iface
);
1787 return IMFTransform_QueryInterface(&mixer
->IMFTransform_iface
, riid
, obj
);
1790 static ULONG WINAPI
video_mixer_getservice_AddRef(IMFGetService
*iface
)
1792 struct video_mixer
*mixer
= impl_from_IMFGetService(iface
);
1793 return IMFTransform_AddRef(&mixer
->IMFTransform_iface
);
1796 static ULONG WINAPI
video_mixer_getservice_Release(IMFGetService
*iface
)
1798 struct video_mixer
*mixer
= impl_from_IMFGetService(iface
);
1799 return IMFTransform_Release(&mixer
->IMFTransform_iface
);
1802 static HRESULT WINAPI
video_mixer_getservice_GetService(IMFGetService
*iface
, REFGUID service
, REFIID riid
, void **obj
)
1804 TRACE("%p, %s, %s, %p.\n", iface
, debugstr_guid(service
), debugstr_guid(riid
), obj
);
1806 if (IsEqualGUID(service
, &MR_VIDEO_MIXER_SERVICE
))
1808 if (IsEqualIID(riid
, &IID_IMFVideoMixerBitmap
) ||
1809 IsEqualIID(riid
, &IID_IMFVideoProcessor
) ||
1810 IsEqualIID(riid
, &IID_IMFVideoPositionMapper
) ||
1811 IsEqualIID(riid
, &IID_IMFVideoMixerControl
) ||
1812 IsEqualIID(riid
, &IID_IMFVideoMixerControl2
))
1814 return IMFGetService_QueryInterface(iface
, riid
, obj
);
1817 return E_NOINTERFACE
;
1820 FIXME("Unsupported service %s, riid %s.\n", debugstr_guid(service
), debugstr_guid(riid
));
1822 return MF_E_UNSUPPORTED_SERVICE
;
1825 static const IMFGetServiceVtbl video_mixer_getservice_vtbl
=
1827 video_mixer_getservice_QueryInterface
,
1828 video_mixer_getservice_AddRef
,
1829 video_mixer_getservice_Release
,
1830 video_mixer_getservice_GetService
,
1833 static HRESULT WINAPI
video_mixer_bitmap_QueryInterface(IMFVideoMixerBitmap
*iface
, REFIID riid
, void **obj
)
1835 struct video_mixer
*mixer
= impl_from_IMFVideoMixerBitmap(iface
);
1836 return IMFTransform_QueryInterface(&mixer
->IMFTransform_iface
, riid
, obj
);
1839 static ULONG WINAPI
video_mixer_bitmap_AddRef(IMFVideoMixerBitmap
*iface
)
1841 struct video_mixer
*mixer
= impl_from_IMFVideoMixerBitmap(iface
);
1842 return IMFTransform_AddRef(&mixer
->IMFTransform_iface
);
1845 static ULONG WINAPI
video_mixer_bitmap_Release(IMFVideoMixerBitmap
*iface
)
1847 struct video_mixer
*mixer
= impl_from_IMFVideoMixerBitmap(iface
);
1848 return IMFTransform_Release(&mixer
->IMFTransform_iface
);
1851 static HRESULT WINAPI
video_mixer_bitmap_SetAlphaBitmap(IMFVideoMixerBitmap
*iface
, const MFVideoAlphaBitmap
*bitmap
)
1853 FIXME("%p, %p.\n", iface
, bitmap
);
1858 static HRESULT WINAPI
video_mixer_bitmap_ClearAlphaBitmap(IMFVideoMixerBitmap
*iface
)
1860 FIXME("%p.\n", iface
);
1865 static HRESULT WINAPI
video_mixer_bitmap_UpdateAlphaBitmapParameters(IMFVideoMixerBitmap
*iface
,
1866 const MFVideoAlphaBitmapParams
*params
)
1868 FIXME("%p, %p.\n", iface
, params
);
1873 static HRESULT WINAPI
video_mixer_bitmap_GetAlphaBitmapParameters(IMFVideoMixerBitmap
*iface
, MFVideoAlphaBitmapParams
*params
)
1875 FIXME("%p, %p.\n", iface
, params
);
1880 static const IMFVideoMixerBitmapVtbl video_mixer_bitmap_vtbl
=
1882 video_mixer_bitmap_QueryInterface
,
1883 video_mixer_bitmap_AddRef
,
1884 video_mixer_bitmap_Release
,
1885 video_mixer_bitmap_SetAlphaBitmap
,
1886 video_mixer_bitmap_ClearAlphaBitmap
,
1887 video_mixer_bitmap_UpdateAlphaBitmapParameters
,
1888 video_mixer_bitmap_GetAlphaBitmapParameters
,
1891 static HRESULT WINAPI
video_mixer_position_mapper_QueryInterface(IMFVideoPositionMapper
*iface
, REFIID riid
, void **obj
)
1893 struct video_mixer
*mixer
= impl_from_IMFVideoPositionMapper(iface
);
1894 return IMFTransform_QueryInterface(&mixer
->IMFTransform_iface
, riid
, obj
);
1897 static ULONG WINAPI
video_mixer_position_mapper_AddRef(IMFVideoPositionMapper
*iface
)
1899 struct video_mixer
*mixer
= impl_from_IMFVideoPositionMapper(iface
);
1900 return IMFTransform_AddRef(&mixer
->IMFTransform_iface
);
1903 static ULONG WINAPI
video_mixer_position_mapper_Release(IMFVideoPositionMapper
*iface
)
1905 struct video_mixer
*mixer
= impl_from_IMFVideoPositionMapper(iface
);
1906 return IMFTransform_Release(&mixer
->IMFTransform_iface
);
1909 static HRESULT WINAPI
video_mixer_position_mapper_MapOutputCoordinateToInputStream(IMFVideoPositionMapper
*iface
,
1910 float x_out
, float y_out
, DWORD output_stream
, DWORD input_stream
, float *x_in
, float *y_in
)
1912 FIXME("%p, %f, %f, %lu, %lu, %p, %p.\n", iface
, x_out
, y_out
, output_stream
, input_stream
, x_in
, y_in
);
1917 static const IMFVideoPositionMapperVtbl video_mixer_position_mapper_vtbl
=
1919 video_mixer_position_mapper_QueryInterface
,
1920 video_mixer_position_mapper_AddRef
,
1921 video_mixer_position_mapper_Release
,
1922 video_mixer_position_mapper_MapOutputCoordinateToInputStream
,
1925 static HRESULT WINAPI
video_mixer_processor_QueryInterface(IMFVideoProcessor
*iface
, REFIID riid
, void **obj
)
1927 struct video_mixer
*mixer
= impl_from_IMFVideoProcessor(iface
);
1928 return IMFTransform_QueryInterface(&mixer
->IMFTransform_iface
, riid
, obj
);
1931 static ULONG WINAPI
video_mixer_processor_AddRef(IMFVideoProcessor
*iface
)
1933 struct video_mixer
*mixer
= impl_from_IMFVideoProcessor(iface
);
1934 return IMFTransform_AddRef(&mixer
->IMFTransform_iface
);
1937 static ULONG WINAPI
video_mixer_processor_Release(IMFVideoProcessor
*iface
)
1939 struct video_mixer
*mixer
= impl_from_IMFVideoProcessor(iface
);
1940 return IMFTransform_Release(&mixer
->IMFTransform_iface
);
1943 static HRESULT WINAPI
video_mixer_processor_GetAvailableVideoProcessorModes(IMFVideoProcessor
*iface
, UINT
*count
,
1946 struct video_mixer
*mixer
= impl_from_IMFVideoProcessor(iface
);
1947 IDirectXVideoProcessorService
*service
;
1948 DXVA2_VideoDesc video_desc
;
1951 TRACE("%p, %p, %p.\n", iface
, count
, modes
);
1953 EnterCriticalSection(&mixer
->cs
);
1955 if (!mixer
->inputs
[0].media_type
|| !mixer
->output
.media_type
)
1956 hr
= MF_E_TRANSFORM_TYPE_NOT_SET
;
1957 else if (SUCCEEDED(hr
= video_mixer_get_processor_service(mixer
, &service
)))
1959 video_mixer_init_dxva_videodesc(mixer
->inputs
[0].media_type
, &video_desc
);
1960 hr
= IDirectXVideoProcessorService_GetVideoProcessorDeviceGuids(service
, &video_desc
, count
, modes
);
1961 IDirectXVideoProcessorService_Release(service
);
1964 LeaveCriticalSection(&mixer
->cs
);
1969 static HRESULT WINAPI
video_mixer_processor_GetVideoProcessorCaps(IMFVideoProcessor
*iface
, GUID
*mode
,
1970 DXVA2_VideoProcessorCaps
*caps
)
1972 struct video_mixer
*mixer
= impl_from_IMFVideoProcessor(iface
);
1973 IDirectXVideoProcessorService
*service
;
1974 DXVA2_VideoDesc video_desc
;
1975 GUID subtype
= { 0 };
1978 TRACE("%p, %s, %p.\n", iface
, debugstr_guid(mode
), caps
);
1980 EnterCriticalSection(&mixer
->cs
);
1982 if (!mixer
->inputs
[0].media_type
|| !mixer
->output
.media_type
)
1983 hr
= MF_E_TRANSFORM_TYPE_NOT_SET
;
1984 else if (SUCCEEDED(hr
= video_mixer_get_processor_service(mixer
, &service
)))
1986 video_mixer_init_dxva_videodesc(mixer
->inputs
[0].media_type
, &video_desc
);
1987 IMFMediaType_GetGUID(mixer
->output
.media_type
, &MF_MT_SUBTYPE
, &subtype
);
1989 hr
= IDirectXVideoProcessorService_GetVideoProcessorCaps(service
, mode
, &video_desc
, subtype
.Data1
, caps
);
1990 IDirectXVideoProcessorService_Release(service
);
1993 LeaveCriticalSection(&mixer
->cs
);
1998 static HRESULT WINAPI
video_mixer_processor_GetVideoProcessorMode(IMFVideoProcessor
*iface
, GUID
*mode
)
2000 FIXME("%p, %p.\n", iface
, mode
);
2005 static HRESULT WINAPI
video_mixer_processor_SetVideoProcessorMode(IMFVideoProcessor
*iface
, GUID
*mode
)
2007 FIXME("%p, %s.\n", iface
, debugstr_guid(mode
));
2012 static HRESULT WINAPI
video_mixer_processor_GetProcAmpRange(IMFVideoProcessor
*iface
, DWORD prop
, DXVA2_ValueRange
*range
)
2014 FIXME("%p, %#lx, %p.\n", iface
, prop
, range
);
2019 static HRESULT WINAPI
video_mixer_processor_GetProcAmpValues(IMFVideoProcessor
*iface
, DWORD flags
, DXVA2_ProcAmpValues
*values
)
2021 FIXME("%p, %#lx, %p.\n", iface
, flags
, values
);
2026 static HRESULT WINAPI
video_mixer_processor_SetProcAmpValues(IMFVideoProcessor
*iface
, DWORD flags
, DXVA2_ProcAmpValues
*values
)
2028 FIXME("%p, %#lx, %p.\n", iface
, flags
, values
);
2033 static HRESULT WINAPI
video_mixer_processor_GetFilteringRange(IMFVideoProcessor
*iface
, DWORD prop
, DXVA2_ValueRange
*range
)
2035 FIXME("%p, %#lx, %p.\n", iface
, prop
, range
);
2040 static HRESULT WINAPI
video_mixer_processor_GetFilteringValue(IMFVideoProcessor
*iface
, DWORD prop
, DXVA2_Fixed32
*value
)
2042 FIXME("%p, %#lx, %p.\n", iface
, prop
, value
);
2047 static HRESULT WINAPI
video_mixer_processor_SetFilteringValue(IMFVideoProcessor
*iface
, DWORD prop
, DXVA2_Fixed32
*value
)
2049 FIXME("%p, %#lx, %p.\n", iface
, prop
, value
);
2054 static HRESULT WINAPI
video_mixer_processor_GetBackgroundColor(IMFVideoProcessor
*iface
, COLORREF
*color
)
2056 struct video_mixer
*mixer
= impl_from_IMFVideoProcessor(iface
);
2058 TRACE("%p, %p.\n", iface
, color
);
2063 EnterCriticalSection(&mixer
->cs
);
2064 *color
= mixer
->bkgnd_color
.rgba
;
2065 LeaveCriticalSection(&mixer
->cs
);
2070 static void video_mixer_rgb_to_ycbcr(COLORREF rgb
, DXVA2_AYUVSample16
*ayuv
)
2072 int y
, cb
, cr
, r
, g
, b
;
2074 r
= GetRValue(rgb
); g
= GetGValue(rgb
); b
= GetBValue(rgb
);
2075 /* Coefficients according to SDTV ITU-R BT.601 */
2076 y
= (77 * r
+ 150 * g
+ 29 * b
+ 128) / 256 + 16;
2077 cb
= (-44 * r
- 87 * g
+ 131 * b
+ 128) / 256 + 128;
2078 cr
= (131 * r
- 110 * g
- 21 * b
+ 128) / 256 + 128;
2080 ayuv
->Y
= y
* 0x100;
2081 ayuv
->Cb
= cb
* 0x100;
2082 ayuv
->Cr
= cr
* 0x100;
2083 ayuv
->Alpha
= 0xffff;
2086 static HRESULT WINAPI
video_mixer_processor_SetBackgroundColor(IMFVideoProcessor
*iface
, COLORREF color
)
2088 struct video_mixer
*mixer
= impl_from_IMFVideoProcessor(iface
);
2090 TRACE("%p, %#lx.\n", iface
, color
);
2092 EnterCriticalSection(&mixer
->cs
);
2093 if (mixer
->bkgnd_color
.rgba
!= color
)
2095 video_mixer_rgb_to_ycbcr(color
, &mixer
->bkgnd_color
.ayuv
);
2096 mixer
->bkgnd_color
.rgba
= color
;
2098 LeaveCriticalSection(&mixer
->cs
);
2103 static const IMFVideoProcessorVtbl video_mixer_processor_vtbl
=
2105 video_mixer_processor_QueryInterface
,
2106 video_mixer_processor_AddRef
,
2107 video_mixer_processor_Release
,
2108 video_mixer_processor_GetAvailableVideoProcessorModes
,
2109 video_mixer_processor_GetVideoProcessorCaps
,
2110 video_mixer_processor_GetVideoProcessorMode
,
2111 video_mixer_processor_SetVideoProcessorMode
,
2112 video_mixer_processor_GetProcAmpRange
,
2113 video_mixer_processor_GetProcAmpValues
,
2114 video_mixer_processor_SetProcAmpValues
,
2115 video_mixer_processor_GetFilteringRange
,
2116 video_mixer_processor_GetFilteringValue
,
2117 video_mixer_processor_SetFilteringValue
,
2118 video_mixer_processor_GetBackgroundColor
,
2119 video_mixer_processor_SetBackgroundColor
,
2122 static HRESULT WINAPI
video_mixer_attributes_QueryInterface(IMFAttributes
*iface
, REFIID riid
, void **out
)
2124 struct video_mixer
*mixer
= impl_from_IMFAttributes(iface
);
2125 return IMFTransform_QueryInterface(&mixer
->IMFTransform_iface
, riid
, out
);
2128 static ULONG WINAPI
video_mixer_attributes_AddRef(IMFAttributes
*iface
)
2130 struct video_mixer
*mixer
= impl_from_IMFAttributes(iface
);
2131 return IMFTransform_AddRef(&mixer
->IMFTransform_iface
);
2134 static ULONG WINAPI
video_mixer_attributes_Release(IMFAttributes
*iface
)
2136 struct video_mixer
*mixer
= impl_from_IMFAttributes(iface
);
2137 return IMFTransform_Release(&mixer
->IMFTransform_iface
);
2140 static HRESULT WINAPI
video_mixer_attributes_GetItem(IMFAttributes
*iface
, REFGUID key
, PROPVARIANT
*value
)
2142 struct video_mixer
*mixer
= impl_from_IMFAttributes(iface
);
2144 TRACE("%p, %s, %p.\n", iface
, debugstr_guid(key
), value
);
2146 return IMFAttributes_GetItem(mixer
->internal_attributes
, key
, value
);
2149 static HRESULT WINAPI
video_mixer_attributes_GetItemType(IMFAttributes
*iface
, REFGUID key
, MF_ATTRIBUTE_TYPE
*type
)
2151 struct video_mixer
*mixer
= impl_from_IMFAttributes(iface
);
2153 TRACE("%p, %s, %p.\n", iface
, debugstr_guid(key
), type
);
2155 return IMFAttributes_GetItemType(mixer
->internal_attributes
, key
, type
);
2158 static HRESULT WINAPI
video_mixer_attributes_CompareItem(IMFAttributes
*iface
, REFGUID key
,
2159 REFPROPVARIANT value
, BOOL
*result
)
2161 struct video_mixer
*mixer
= impl_from_IMFAttributes(iface
);
2163 TRACE("%p, %s, %p, %p.\n", iface
, debugstr_guid(key
), value
, result
);
2165 return IMFAttributes_CompareItem(mixer
->internal_attributes
, key
, value
, result
);
2168 static HRESULT WINAPI
video_mixer_attributes_Compare(IMFAttributes
*iface
, IMFAttributes
*theirs
,
2169 MF_ATTRIBUTES_MATCH_TYPE match_type
, BOOL
*ret
)
2171 struct video_mixer
*mixer
= impl_from_IMFAttributes(iface
);
2173 TRACE("%p, %p, %d, %p.\n", iface
, theirs
, match_type
, ret
);
2175 return IMFAttributes_Compare(mixer
->internal_attributes
, theirs
, match_type
, ret
);
2178 static HRESULT WINAPI
video_mixer_attributes_GetUINT32(IMFAttributes
*iface
, REFGUID key
, UINT32
*value
)
2180 struct video_mixer
*mixer
= impl_from_IMFAttributes(iface
);
2182 TRACE("%p, %s, %p.\n", iface
, debugstr_guid(key
), value
);
2184 return IMFAttributes_GetUINT32(mixer
->internal_attributes
, key
, value
);
2187 static HRESULT WINAPI
video_mixer_attributes_GetUINT64(IMFAttributes
*iface
, REFGUID key
, UINT64
*value
)
2189 struct video_mixer
*mixer
= impl_from_IMFAttributes(iface
);
2191 TRACE("%p, %s, %p.\n", iface
, debugstr_guid(key
), value
);
2193 return IMFAttributes_GetUINT64(mixer
->internal_attributes
, key
, value
);
2196 static HRESULT WINAPI
video_mixer_attributes_GetDouble(IMFAttributes
*iface
, REFGUID key
, double *value
)
2198 struct video_mixer
*mixer
= impl_from_IMFAttributes(iface
);
2200 TRACE("%p, %s, %p.\n", iface
, debugstr_guid(key
), value
);
2202 return IMFAttributes_GetDouble(mixer
->internal_attributes
, key
, value
);
2205 static HRESULT WINAPI
video_mixer_attributes_GetGUID(IMFAttributes
*iface
, REFGUID key
, GUID
*value
)
2207 struct video_mixer
*mixer
= impl_from_IMFAttributes(iface
);
2209 TRACE("%p, %s, %p.\n", iface
, debugstr_guid(key
), value
);
2211 return IMFAttributes_GetGUID(mixer
->internal_attributes
, key
, value
);
2214 static HRESULT WINAPI
video_mixer_attributes_GetStringLength(IMFAttributes
*iface
, REFGUID key
, UINT32
*length
)
2216 struct video_mixer
*mixer
= impl_from_IMFAttributes(iface
);
2218 TRACE("%p, %s, %p.\n", iface
, debugstr_guid(key
), length
);
2220 return IMFAttributes_GetStringLength(mixer
->internal_attributes
, key
, length
);
2223 static HRESULT WINAPI
video_mixer_attributes_GetString(IMFAttributes
*iface
, REFGUID key
, WCHAR
*value
,
2224 UINT32 size
, UINT32
*length
)
2226 struct video_mixer
*mixer
= impl_from_IMFAttributes(iface
);
2228 TRACE("%p, %s, %p, %d, %p.\n", iface
, debugstr_guid(key
), value
, size
, length
);
2230 return IMFAttributes_GetString(mixer
->internal_attributes
, key
, value
, size
, length
);
2233 static HRESULT WINAPI
video_mixer_attributes_GetAllocatedString(IMFAttributes
*iface
, REFGUID key
,
2234 WCHAR
**value
, UINT32
*length
)
2236 struct video_mixer
*mixer
= impl_from_IMFAttributes(iface
);
2238 TRACE("%p, %s, %p, %p.\n", iface
, debugstr_guid(key
), value
, length
);
2240 return IMFAttributes_GetAllocatedString(mixer
->internal_attributes
, key
, value
, length
);
2243 static HRESULT WINAPI
video_mixer_attributes_GetBlobSize(IMFAttributes
*iface
, REFGUID key
, UINT32
*size
)
2245 struct video_mixer
*mixer
= impl_from_IMFAttributes(iface
);
2247 TRACE("%p, %s, %p.\n", iface
, debugstr_guid(key
), size
);
2249 return IMFAttributes_GetBlobSize(mixer
->internal_attributes
, key
, size
);
2252 static HRESULT WINAPI
video_mixer_attributes_GetBlob(IMFAttributes
*iface
, REFGUID key
, UINT8
*buf
,
2253 UINT32 bufsize
, UINT32
*blobsize
)
2255 struct video_mixer
*mixer
= impl_from_IMFAttributes(iface
);
2257 TRACE("%p, %s, %p, %d, %p.\n", iface
, debugstr_guid(key
), buf
, bufsize
, blobsize
);
2259 return IMFAttributes_GetBlob(mixer
->internal_attributes
, key
, buf
, bufsize
, blobsize
);
2262 static HRESULT WINAPI
video_mixer_attributes_GetAllocatedBlob(IMFAttributes
*iface
, REFGUID key
, UINT8
**buf
, UINT32
*size
)
2264 struct video_mixer
*mixer
= impl_from_IMFAttributes(iface
);
2266 TRACE("%p, %s, %p, %p.\n", iface
, debugstr_guid(key
), buf
, size
);
2268 return IMFAttributes_GetAllocatedBlob(mixer
->internal_attributes
, key
, buf
, size
);
2271 static HRESULT WINAPI
video_mixer_attributes_GetUnknown(IMFAttributes
*iface
, REFGUID key
, REFIID riid
, void **out
)
2273 struct video_mixer
*mixer
= impl_from_IMFAttributes(iface
);
2275 TRACE("%p, %s, %s, %p.\n", iface
, debugstr_guid(key
), debugstr_guid(riid
), out
);
2277 return IMFAttributes_GetUnknown(mixer
->internal_attributes
, key
, riid
, out
);
2280 static HRESULT WINAPI
video_mixer_attributes_SetItem(IMFAttributes
*iface
, REFGUID key
, REFPROPVARIANT value
)
2282 struct video_mixer
*mixer
= impl_from_IMFAttributes(iface
);
2284 TRACE("%p, %s, %p.\n", iface
, debugstr_guid(key
), value
);
2286 return IMFAttributes_SetItem(mixer
->internal_attributes
, key
, value
);
2289 static HRESULT WINAPI
video_mixer_attributes_DeleteItem(IMFAttributes
*iface
, REFGUID key
)
2291 struct video_mixer
*mixer
= impl_from_IMFAttributes(iface
);
2293 TRACE("%p, %s.\n", iface
, debugstr_guid(key
));
2295 return IMFAttributes_DeleteItem(mixer
->internal_attributes
, key
);
2298 static HRESULT WINAPI
video_mixer_attributes_DeleteAllItems(IMFAttributes
*iface
)
2300 struct video_mixer
*mixer
= impl_from_IMFAttributes(iface
);
2302 TRACE("%p.\n", iface
);
2304 return IMFAttributes_DeleteAllItems(mixer
->internal_attributes
);
2307 static HRESULT WINAPI
video_mixer_attributes_SetUINT32(IMFAttributes
*iface
, REFGUID key
, UINT32 value
)
2309 struct video_mixer
*mixer
= impl_from_IMFAttributes(iface
);
2311 TRACE("%p, %s, %u.\n", iface
, debugstr_guid(key
), value
);
2313 return IMFAttributes_SetUINT32(mixer
->internal_attributes
, key
, value
);
2316 static HRESULT WINAPI
video_mixer_attributes_SetUINT64(IMFAttributes
*iface
, REFGUID key
, UINT64 value
)
2318 struct video_mixer
*mixer
= impl_from_IMFAttributes(iface
);
2320 TRACE("%p, %s, %s.\n", iface
, debugstr_guid(key
), wine_dbgstr_longlong(value
));
2322 return IMFAttributes_SetUINT64(mixer
->internal_attributes
, key
, value
);
2325 static HRESULT WINAPI
video_mixer_attributes_SetDouble(IMFAttributes
*iface
, REFGUID key
, double value
)
2327 struct video_mixer
*mixer
= impl_from_IMFAttributes(iface
);
2329 TRACE("%p, %s, %f.\n", iface
, debugstr_guid(key
), value
);
2331 return IMFAttributes_SetDouble(mixer
->internal_attributes
, key
, value
);
2334 static HRESULT WINAPI
video_mixer_attributes_SetGUID(IMFAttributes
*iface
, REFGUID key
, REFGUID value
)
2336 struct video_mixer
*mixer
= impl_from_IMFAttributes(iface
);
2338 TRACE("%p, %s, %s.\n", iface
, debugstr_guid(key
), debugstr_guid(value
));
2340 return IMFAttributes_SetGUID(mixer
->internal_attributes
, key
, value
);
2343 static HRESULT WINAPI
video_mixer_attributes_SetString(IMFAttributes
*iface
, REFGUID key
, const WCHAR
*value
)
2345 struct video_mixer
*mixer
= impl_from_IMFAttributes(iface
);
2347 TRACE("%p, %s, %s.\n", iface
, debugstr_guid(key
), debugstr_w(value
));
2349 return IMFAttributes_SetString(mixer
->internal_attributes
, key
, value
);
2352 static HRESULT WINAPI
video_mixer_attributes_SetBlob(IMFAttributes
*iface
, REFGUID key
, const UINT8
*buf
, UINT32 size
)
2354 struct video_mixer
*mixer
= impl_from_IMFAttributes(iface
);
2356 TRACE("%p, %s, %p, %u.\n", iface
, debugstr_guid(key
), buf
, size
);
2358 return IMFAttributes_SetBlob(mixer
->internal_attributes
, key
, buf
, size
);
2361 static HRESULT WINAPI
video_mixer_attributes_SetUnknown(IMFAttributes
*iface
, REFGUID key
, IUnknown
*unknown
)
2363 struct video_mixer
*mixer
= impl_from_IMFAttributes(iface
);
2365 TRACE("%p, %s, %p.\n", iface
, debugstr_guid(key
), unknown
);
2367 return IMFAttributes_SetUnknown(mixer
->internal_attributes
, key
, unknown
);
2370 static HRESULT WINAPI
video_mixer_attributes_LockStore(IMFAttributes
*iface
)
2372 struct video_mixer
*mixer
= impl_from_IMFAttributes(iface
);
2374 TRACE("%p.\n", iface
);
2376 return IMFAttributes_LockStore(mixer
->internal_attributes
);
2379 static HRESULT WINAPI
video_mixer_attributes_UnlockStore(IMFAttributes
*iface
)
2381 struct video_mixer
*mixer
= impl_from_IMFAttributes(iface
);
2383 TRACE("%p.\n", iface
);
2385 return IMFAttributes_UnlockStore(mixer
->internal_attributes
);
2388 static HRESULT WINAPI
video_mixer_attributes_GetCount(IMFAttributes
*iface
, UINT32
*count
)
2390 struct video_mixer
*mixer
= impl_from_IMFAttributes(iface
);
2392 TRACE("%p, %p.\n", iface
, count
);
2394 return IMFAttributes_GetCount(mixer
->internal_attributes
, count
);
2397 static HRESULT WINAPI
video_mixer_attributes_GetItemByIndex(IMFAttributes
*iface
, UINT32 index
,
2398 GUID
*key
, PROPVARIANT
*value
)
2400 struct video_mixer
*mixer
= impl_from_IMFAttributes(iface
);
2402 TRACE("%p, %u, %p, %p.\n", iface
, index
, key
, value
);
2404 return IMFAttributes_GetItemByIndex(mixer
->internal_attributes
, index
, key
, value
);
2407 static HRESULT WINAPI
video_mixer_attributes_CopyAllItems(IMFAttributes
*iface
, IMFAttributes
*dest
)
2409 struct video_mixer
*mixer
= impl_from_IMFAttributes(iface
);
2411 TRACE("%p, %p.\n", iface
, dest
);
2413 return IMFAttributes_CopyAllItems(mixer
->internal_attributes
, dest
);
2416 static const IMFAttributesVtbl video_mixer_attributes_vtbl
=
2418 video_mixer_attributes_QueryInterface
,
2419 video_mixer_attributes_AddRef
,
2420 video_mixer_attributes_Release
,
2421 video_mixer_attributes_GetItem
,
2422 video_mixer_attributes_GetItemType
,
2423 video_mixer_attributes_CompareItem
,
2424 video_mixer_attributes_Compare
,
2425 video_mixer_attributes_GetUINT32
,
2426 video_mixer_attributes_GetUINT64
,
2427 video_mixer_attributes_GetDouble
,
2428 video_mixer_attributes_GetGUID
,
2429 video_mixer_attributes_GetStringLength
,
2430 video_mixer_attributes_GetString
,
2431 video_mixer_attributes_GetAllocatedString
,
2432 video_mixer_attributes_GetBlobSize
,
2433 video_mixer_attributes_GetBlob
,
2434 video_mixer_attributes_GetAllocatedBlob
,
2435 video_mixer_attributes_GetUnknown
,
2436 video_mixer_attributes_SetItem
,
2437 video_mixer_attributes_DeleteItem
,
2438 video_mixer_attributes_DeleteAllItems
,
2439 video_mixer_attributes_SetUINT32
,
2440 video_mixer_attributes_SetUINT64
,
2441 video_mixer_attributes_SetDouble
,
2442 video_mixer_attributes_SetGUID
,
2443 video_mixer_attributes_SetString
,
2444 video_mixer_attributes_SetBlob
,
2445 video_mixer_attributes_SetUnknown
,
2446 video_mixer_attributes_LockStore
,
2447 video_mixer_attributes_UnlockStore
,
2448 video_mixer_attributes_GetCount
,
2449 video_mixer_attributes_GetItemByIndex
,
2450 video_mixer_attributes_CopyAllItems
2453 static HRESULT WINAPI
video_mixer_quality_advise_QueryInterface(IMFQualityAdvise
*iface
, REFIID riid
, void **out
)
2455 struct video_mixer
*mixer
= impl_from_IMFQualityAdvise(iface
);
2456 return IMFTransform_QueryInterface(&mixer
->IMFTransform_iface
, riid
, out
);
2459 static ULONG WINAPI
video_mixer_quality_advise_AddRef(IMFQualityAdvise
*iface
)
2461 struct video_mixer
*mixer
= impl_from_IMFQualityAdvise(iface
);
2462 return IMFTransform_AddRef(&mixer
->IMFTransform_iface
);
2465 static ULONG WINAPI
video_mixer_quality_advise_Release(IMFQualityAdvise
*iface
)
2467 struct video_mixer
*mixer
= impl_from_IMFQualityAdvise(iface
);
2468 return IMFTransform_Release(&mixer
->IMFTransform_iface
);
2471 static HRESULT WINAPI
video_mixer_quality_advise_SetDropMode(IMFQualityAdvise
*iface
, MF_QUALITY_DROP_MODE mode
)
2473 FIXME("%p, %u.\n", iface
, mode
);
2478 static HRESULT WINAPI
video_mixer_quality_advise_SetQualityLevel(IMFQualityAdvise
*iface
, MF_QUALITY_LEVEL level
)
2480 FIXME("%p, %u.\n", iface
, level
);
2485 static HRESULT WINAPI
video_mixer_quality_advise_GetDropMode(IMFQualityAdvise
*iface
, MF_QUALITY_DROP_MODE
*mode
)
2487 FIXME("%p, %p.\n", iface
, mode
);
2492 static HRESULT WINAPI
video_mixer_quality_advise_GetQualityLevel(IMFQualityAdvise
*iface
, MF_QUALITY_LEVEL
*level
)
2494 FIXME("%p, %p.\n", iface
, level
);
2499 static HRESULT WINAPI
video_mixer_quality_advise_DropTime(IMFQualityAdvise
*iface
, LONGLONG interval
)
2501 FIXME("%p, %s.\n", iface
, wine_dbgstr_longlong(interval
));
2506 static const IMFQualityAdviseVtbl video_mixer_quality_advise_vtbl
=
2508 video_mixer_quality_advise_QueryInterface
,
2509 video_mixer_quality_advise_AddRef
,
2510 video_mixer_quality_advise_Release
,
2511 video_mixer_quality_advise_SetDropMode
,
2512 video_mixer_quality_advise_SetQualityLevel
,
2513 video_mixer_quality_advise_GetDropMode
,
2514 video_mixer_quality_advise_GetQualityLevel
,
2515 video_mixer_quality_advise_DropTime
,
2518 static HRESULT WINAPI
video_mixer_clock_state_sink_QueryInterface(IMFClockStateSink
*iface
,
2519 REFIID riid
, void **out
)
2521 struct video_mixer
*mixer
= impl_from_IMFClockStateSink(iface
);
2522 return IMFTransform_QueryInterface(&mixer
->IMFTransform_iface
, riid
, out
);
2525 static ULONG WINAPI
video_mixer_clock_state_sink_AddRef(IMFClockStateSink
*iface
)
2527 struct video_mixer
*mixer
= impl_from_IMFClockStateSink(iface
);
2528 return IMFTransform_AddRef(&mixer
->IMFTransform_iface
);
2531 static ULONG WINAPI
video_mixer_clock_state_sink_Release(IMFClockStateSink
*iface
)
2533 struct video_mixer
*mixer
= impl_from_IMFClockStateSink(iface
);
2534 return IMFTransform_Release(&mixer
->IMFTransform_iface
);
2537 static HRESULT WINAPI
video_mixer_clock_state_sink_OnClockStart(IMFClockStateSink
*iface
,
2538 MFTIME systime
, LONGLONG offset
)
2540 FIXME("%p.\n", iface
);
2545 static HRESULT WINAPI
video_mixer_clock_state_sink_OnClockStop(IMFClockStateSink
*iface
,
2548 FIXME("%p.\n", iface
);
2553 static HRESULT WINAPI
video_mixer_clock_state_sink_OnClockPause(IMFClockStateSink
*iface
,
2556 FIXME("%p.\n", iface
);
2561 static HRESULT WINAPI
video_mixer_clock_state_sink_OnClockRestart(IMFClockStateSink
*iface
,
2564 FIXME("%p.\n", iface
);
2569 static HRESULT WINAPI
video_mixer_clock_state_sink_OnClockSetRate(IMFClockStateSink
*iface
,
2570 MFTIME systime
, float rate
)
2572 FIXME("%p, %f.\n", iface
, rate
);
2577 static const IMFClockStateSinkVtbl video_mixer_clock_state_sink_vtbl
=
2579 video_mixer_clock_state_sink_QueryInterface
,
2580 video_mixer_clock_state_sink_AddRef
,
2581 video_mixer_clock_state_sink_Release
,
2582 video_mixer_clock_state_sink_OnClockStart
,
2583 video_mixer_clock_state_sink_OnClockStop
,
2584 video_mixer_clock_state_sink_OnClockPause
,
2585 video_mixer_clock_state_sink_OnClockRestart
,
2586 video_mixer_clock_state_sink_OnClockSetRate
,
2589 HRESULT WINAPI
MFCreateVideoMixer(IUnknown
*owner
, REFIID riid_device
, REFIID riid
, void **obj
)
2591 TRACE("%p, %s, %s, %p.\n", owner
, debugstr_guid(riid_device
), debugstr_guid(riid
), obj
);
2595 if (!IsEqualIID(riid_device
, &IID_IDirect3DDevice9
))
2596 return E_INVALIDARG
;
2598 return CoCreateInstance(&CLSID_MFVideoMixer9
, owner
, CLSCTX_INPROC_SERVER
, riid
, obj
);
2601 HRESULT
evr_mixer_create(IUnknown
*outer
, void **out
)
2603 struct video_mixer
*object
;
2604 MFVideoNormalizedRect rect
;
2607 if (!(object
= calloc(1, sizeof(*object
))))
2608 return E_OUTOFMEMORY
;
2610 object
->IMFTransform_iface
.lpVtbl
= &video_mixer_transform_vtbl
;
2611 object
->IMFVideoDeviceID_iface
.lpVtbl
= &video_mixer_device_id_vtbl
;
2612 object
->IMFTopologyServiceLookupClient_iface
.lpVtbl
= &video_mixer_service_client_vtbl
;
2613 object
->IMFVideoMixerControl2_iface
.lpVtbl
= &video_mixer_control_vtbl
;
2614 object
->IMFGetService_iface
.lpVtbl
= &video_mixer_getservice_vtbl
;
2615 object
->IMFVideoMixerBitmap_iface
.lpVtbl
= &video_mixer_bitmap_vtbl
;
2616 object
->IMFVideoPositionMapper_iface
.lpVtbl
= &video_mixer_position_mapper_vtbl
;
2617 object
->IMFVideoProcessor_iface
.lpVtbl
= &video_mixer_processor_vtbl
;
2618 object
->IMFAttributes_iface
.lpVtbl
= &video_mixer_attributes_vtbl
;
2619 object
->IMFQualityAdvise_iface
.lpVtbl
= &video_mixer_quality_advise_vtbl
;
2620 object
->IMFClockStateSink_iface
.lpVtbl
= &video_mixer_clock_state_sink_vtbl
;
2621 object
->IUnknown_inner
.lpVtbl
= &video_mixer_inner_vtbl
;
2622 object
->outer_unk
= outer
? outer
: &object
->IUnknown_inner
;
2623 object
->refcount
= 1;
2624 object
->input_count
= 1;
2625 object
->lower_bound
= MFT_OUTPUT_BOUND_LOWER_UNBOUNDED
;
2626 object
->upper_bound
= MFT_OUTPUT_BOUND_UPPER_UNBOUNDED
;
2627 video_mixer_init_input(&object
->inputs
[0]);
2628 video_mixer_update_zorder_map(object
);
2629 video_mixer_rgb_to_ycbcr(object
->bkgnd_color
.rgba
, &object
->bkgnd_color
.ayuv
);
2630 InitializeCriticalSection(&object
->cs
);
2631 if (FAILED(hr
= MFCreateAttributes(&object
->attributes
, 0)))
2633 IUnknown_Release(&object
->IUnknown_inner
);
2636 if (FAILED(hr
= MFCreateAttributes(&object
->internal_attributes
, 0)))
2638 IUnknown_Release(&object
->IUnknown_inner
);
2642 /* Default attributes configuration. */
2644 rect
.left
= rect
.top
= 0.0f
;
2645 rect
.right
= rect
.bottom
= 1.0f
;
2646 IMFAttributes_SetBlob(object
->attributes
, &VIDEO_ZOOM_RECT
, (const UINT8
*)&rect
, sizeof(rect
));
2648 IMFAttributes_SetUINT32(object
->internal_attributes
, &MF_SA_D3D_AWARE
, 1);
2650 *out
= &object
->IUnknown_inner
;