dinput: Enumerate user format object forwards.
[wine.git] / dlls / winegstreamer / mfplat.c
blob335572112439ae5f3751eac7cae1d9569c5848b0
1 /*
2 * Copyright 2019 Nikolay Sivov for CodeWeavers
3 * Copyright 2020 Zebediah Figura for CodeWeavers
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
8 * version 2.1 of the License, or (at your option) any later version.
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
15 * You should have received a copy of the GNU Lesser General Public
16 * License along with this library; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
20 #include "gst_private.h"
22 #include "ks.h"
23 #include "ksmedia.h"
24 #include "wmcodecdsp.h"
25 #include "initguid.h"
26 #include "d3d9types.h"
27 #include "mfapi.h"
29 #include "wine/debug.h"
30 #include "wine/list.h"
32 WINE_DEFAULT_DEBUG_CHANNEL(mfplat);
34 DEFINE_GUID(DMOVideoFormat_RGB32,D3DFMT_X8R8G8B8,0x524f,0x11ce,0x9f,0x53,0x00,0x20,0xaf,0x0b,0xa7,0x70);
35 DEFINE_GUID(DMOVideoFormat_RGB24,D3DFMT_R8G8B8,0x524f,0x11ce,0x9f,0x53,0x00,0x20,0xaf,0x0b,0xa7,0x70);
36 DEFINE_GUID(DMOVideoFormat_RGB565,D3DFMT_R5G6B5,0x524f,0x11ce,0x9f,0x53,0x00,0x20,0xaf,0x0b,0xa7,0x70);
37 DEFINE_GUID(DMOVideoFormat_RGB555,D3DFMT_X1R5G5B5,0x524f,0x11ce,0x9f,0x53,0x00,0x20,0xaf,0x0b,0xa7,0x70);
38 DEFINE_GUID(DMOVideoFormat_RGB8,D3DFMT_P8,0x524f,0x11ce,0x9f,0x53,0x00,0x20,0xaf,0x0b,0xa7,0x70);
40 struct video_processor
42 IMFTransform IMFTransform_iface;
43 LONG refcount;
44 IMFAttributes *attributes;
45 IMFAttributes *output_attributes;
48 static struct video_processor *impl_video_processor_from_IMFTransform(IMFTransform *iface)
50 return CONTAINING_RECORD(iface, struct video_processor, IMFTransform_iface);
53 static HRESULT WINAPI video_processor_QueryInterface(IMFTransform *iface, REFIID riid, void **obj)
55 TRACE("%p, %s, %p.\n", iface, debugstr_guid(riid), obj);
57 if (IsEqualIID(riid, &IID_IMFTransform) ||
58 IsEqualIID(riid, &IID_IUnknown))
60 *obj = iface;
61 IMFTransform_AddRef(iface);
62 return S_OK;
65 WARN("Unsupported %s.\n", debugstr_guid(riid));
66 *obj = NULL;
67 return E_NOINTERFACE;
70 static ULONG WINAPI video_processor_AddRef(IMFTransform *iface)
72 struct video_processor *transform = impl_video_processor_from_IMFTransform(iface);
73 ULONG refcount = InterlockedIncrement(&transform->refcount);
75 TRACE("%p, refcount %lu.\n", iface, refcount);
77 return refcount;
80 static ULONG WINAPI video_processor_Release(IMFTransform *iface)
82 struct video_processor *transform = impl_video_processor_from_IMFTransform(iface);
83 ULONG refcount = InterlockedDecrement(&transform->refcount);
85 TRACE("%p, refcount %lu.\n", iface, refcount);
87 if (!refcount)
89 if (transform->attributes)
90 IMFAttributes_Release(transform->attributes);
91 if (transform->output_attributes)
92 IMFAttributes_Release(transform->output_attributes);
93 free(transform);
96 return refcount;
99 static HRESULT WINAPI video_processor_GetStreamLimits(IMFTransform *iface, DWORD *input_minimum, DWORD *input_maximum,
100 DWORD *output_minimum, DWORD *output_maximum)
102 TRACE("%p, %p, %p, %p, %p.\n", iface, input_minimum, input_maximum, output_minimum, output_maximum);
104 *input_minimum = *input_maximum = *output_minimum = *output_maximum = 1;
106 return S_OK;
109 static HRESULT WINAPI video_processor_GetStreamCount(IMFTransform *iface, DWORD *inputs, DWORD *outputs)
111 TRACE("%p, %p, %p.\n", iface, inputs, outputs);
113 *inputs = *outputs = 1;
115 return S_OK;
118 static HRESULT WINAPI video_processor_GetStreamIDs(IMFTransform *iface, DWORD input_size, DWORD *inputs,
119 DWORD output_size, DWORD *outputs)
121 return E_NOTIMPL;
124 static HRESULT WINAPI video_processor_GetInputStreamInfo(IMFTransform *iface, DWORD id, MFT_INPUT_STREAM_INFO *info)
126 return E_NOTIMPL;
129 static HRESULT WINAPI video_processor_GetOutputStreamInfo(IMFTransform *iface, DWORD id, MFT_OUTPUT_STREAM_INFO *info)
131 return E_NOTIMPL;
134 static HRESULT WINAPI video_processor_GetAttributes(IMFTransform *iface, IMFAttributes **attributes)
136 struct video_processor *transform = impl_video_processor_from_IMFTransform(iface);
138 TRACE("%p, %p.\n", iface, attributes);
140 *attributes = transform->attributes;
141 IMFAttributes_AddRef(*attributes);
143 return S_OK;
146 static HRESULT WINAPI video_processor_GetInputStreamAttributes(IMFTransform *iface, DWORD id,
147 IMFAttributes **attributes)
149 return E_NOTIMPL;
152 static HRESULT WINAPI video_processor_GetOutputStreamAttributes(IMFTransform *iface, DWORD id,
153 IMFAttributes **attributes)
155 struct video_processor *transform = impl_video_processor_from_IMFTransform(iface);
157 TRACE("%p, %lu, %p.\n", iface, id, attributes);
159 *attributes = transform->output_attributes;
160 IMFAttributes_AddRef(*attributes);
162 return S_OK;
165 static HRESULT WINAPI video_processor_DeleteInputStream(IMFTransform *iface, DWORD id)
167 TRACE("%p, %lu.\n", iface, id);
169 return E_NOTIMPL;
172 static HRESULT WINAPI video_processor_AddInputStreams(IMFTransform *iface, DWORD streams, DWORD *ids)
174 TRACE("%p, %lu, %p.\n", iface, streams, ids);
176 return E_NOTIMPL;
179 static HRESULT WINAPI video_processor_GetInputAvailableType(IMFTransform *iface, DWORD id, DWORD index,
180 IMFMediaType **type)
182 FIXME("%p, %lu, %lu, %p.\n", iface, id, index, type);
184 return E_NOTIMPL;
187 static HRESULT WINAPI video_processor_GetOutputAvailableType(IMFTransform *iface, DWORD id, DWORD index,
188 IMFMediaType **type)
190 FIXME("%p, %lu, %lu, %p.\n", iface, id, index, type);
192 return E_NOTIMPL;
195 static HRESULT WINAPI video_processor_SetInputType(IMFTransform *iface, DWORD id, IMFMediaType *type, DWORD flags)
197 FIXME("%p, %lu, %p, %#lx.\n", iface, id, type, flags);
199 return E_NOTIMPL;
202 static HRESULT WINAPI video_processor_SetOutputType(IMFTransform *iface, DWORD id, IMFMediaType *type, DWORD flags)
204 FIXME("%p, %lu, %p, %#lx.\n", iface, id, type, flags);
206 return E_NOTIMPL;
209 static HRESULT WINAPI video_processor_GetInputCurrentType(IMFTransform *iface, DWORD id, IMFMediaType **type)
211 FIXME("%p, %lu, %p.\n", iface, id, type);
213 return E_NOTIMPL;
216 static HRESULT WINAPI video_processor_GetOutputCurrentType(IMFTransform *iface, DWORD id, IMFMediaType **type)
218 FIXME("%p, %lu, %p.\n", iface, id, type);
220 return E_NOTIMPL;
223 static HRESULT WINAPI video_processor_GetInputStatus(IMFTransform *iface, DWORD id, DWORD *flags)
225 FIXME("%p, %lu, %p.\n", iface, id, flags);
227 return E_NOTIMPL;
230 static HRESULT WINAPI video_processor_GetOutputStatus(IMFTransform *iface, DWORD *flags)
232 FIXME("%p, %p.\n", iface, flags);
234 return E_NOTIMPL;
237 static HRESULT WINAPI video_processor_SetOutputBounds(IMFTransform *iface, LONGLONG lower, LONGLONG upper)
239 FIXME("%p, %s, %s.\n", iface, wine_dbgstr_longlong(lower), wine_dbgstr_longlong(upper));
241 return E_NOTIMPL;
244 static HRESULT WINAPI video_processor_ProcessEvent(IMFTransform *iface, DWORD id, IMFMediaEvent *event)
246 TRACE("%p, %lu, %p.\n", iface, id, event);
248 return E_NOTIMPL;
251 static HRESULT WINAPI video_processor_ProcessMessage(IMFTransform *iface, MFT_MESSAGE_TYPE message, ULONG_PTR param)
253 FIXME("%p, %u, %#Ix.\n", iface, message, param);
255 return E_NOTIMPL;
258 static HRESULT WINAPI video_processor_ProcessInput(IMFTransform *iface, DWORD id, IMFSample *sample, DWORD flags)
260 FIXME("%p, %lu, %p, %#lx.\n", iface, id, sample, flags);
262 return E_NOTIMPL;
265 static HRESULT WINAPI video_processor_ProcessOutput(IMFTransform *iface, DWORD flags, DWORD count,
266 MFT_OUTPUT_DATA_BUFFER *samples, DWORD *status)
268 FIXME("%p, %#lx, %lu, %p, %p.\n", iface, flags, count, samples, status);
270 return E_NOTIMPL;
273 static const IMFTransformVtbl video_processor_vtbl =
275 video_processor_QueryInterface,
276 video_processor_AddRef,
277 video_processor_Release,
278 video_processor_GetStreamLimits,
279 video_processor_GetStreamCount,
280 video_processor_GetStreamIDs,
281 video_processor_GetInputStreamInfo,
282 video_processor_GetOutputStreamInfo,
283 video_processor_GetAttributes,
284 video_processor_GetInputStreamAttributes,
285 video_processor_GetOutputStreamAttributes,
286 video_processor_DeleteInputStream,
287 video_processor_AddInputStreams,
288 video_processor_GetInputAvailableType,
289 video_processor_GetOutputAvailableType,
290 video_processor_SetInputType,
291 video_processor_SetOutputType,
292 video_processor_GetInputCurrentType,
293 video_processor_GetOutputCurrentType,
294 video_processor_GetInputStatus,
295 video_processor_GetOutputStatus,
296 video_processor_SetOutputBounds,
297 video_processor_ProcessEvent,
298 video_processor_ProcessMessage,
299 video_processor_ProcessInput,
300 video_processor_ProcessOutput,
303 struct class_factory
305 IClassFactory IClassFactory_iface;
306 LONG refcount;
307 HRESULT (*create_instance)(REFIID riid, void **obj);
310 static struct class_factory *impl_from_IClassFactory(IClassFactory *iface)
312 return CONTAINING_RECORD(iface, struct class_factory, IClassFactory_iface);
315 static HRESULT WINAPI class_factory_QueryInterface(IClassFactory *iface, REFIID riid, void **obj)
317 TRACE("%p, %s, %p.\n", iface, debugstr_guid(riid), obj);
319 if (IsEqualGUID(riid, &IID_IClassFactory) ||
320 IsEqualGUID(riid, &IID_IUnknown))
322 *obj = iface;
323 IClassFactory_AddRef(iface);
324 return S_OK;
327 WARN("%s is not supported.\n", debugstr_guid(riid));
328 *obj = NULL;
329 return E_NOINTERFACE;
332 static ULONG WINAPI class_factory_AddRef(IClassFactory *iface)
334 struct class_factory *factory = impl_from_IClassFactory(iface);
335 return InterlockedIncrement(&factory->refcount);
338 static ULONG WINAPI class_factory_Release(IClassFactory *iface)
340 struct class_factory *factory = impl_from_IClassFactory(iface);
341 ULONG refcount = InterlockedDecrement(&factory->refcount);
343 if (!refcount)
344 free(factory);
346 return refcount;
349 static HRESULT WINAPI class_factory_CreateInstance(IClassFactory *iface, IUnknown *outer, REFIID riid, void **obj)
351 struct class_factory *factory = impl_from_IClassFactory(iface);
353 TRACE("%p, %p, %s, %p.\n", iface, outer, debugstr_guid(riid), obj);
355 if (outer)
357 *obj = NULL;
358 return CLASS_E_NOAGGREGATION;
361 return factory->create_instance(riid, obj);
364 static HRESULT WINAPI class_factory_LockServer(IClassFactory *iface, BOOL dolock)
366 TRACE("%p, %d.\n", iface, dolock);
367 return S_OK;
370 static const IClassFactoryVtbl class_factory_vtbl =
372 class_factory_QueryInterface,
373 class_factory_AddRef,
374 class_factory_Release,
375 class_factory_CreateInstance,
376 class_factory_LockServer,
379 static HRESULT video_processor_create(REFIID riid, void **ret)
381 struct video_processor *object;
382 HRESULT hr;
384 if (!(object = calloc(1, sizeof(*object))))
385 return E_OUTOFMEMORY;
387 object->IMFTransform_iface.lpVtbl = &video_processor_vtbl;
388 object->refcount = 1;
390 if (FAILED(hr = MFCreateAttributes(&object->attributes, 0)))
391 goto failed;
393 if (FAILED(hr = MFCreateAttributes(&object->output_attributes, 0)))
394 goto failed;
396 *ret = &object->IMFTransform_iface;
397 return S_OK;
399 failed:
401 IMFTransform_Release(&object->IMFTransform_iface);
402 return hr;
405 static const GUID CLSID_GStreamerByteStreamHandler = {0x317df618, 0x5e5a, 0x468a, {0x9f, 0x15, 0xd8, 0x27, 0xa9, 0xa0, 0x81, 0x62}};
407 static const struct class_object
409 const GUID *clsid;
410 HRESULT (*create_instance)(REFIID riid, void **obj);
412 class_objects[] =
414 { &CLSID_VideoProcessorMFT, &video_processor_create },
415 { &CLSID_GStreamerByteStreamHandler, &winegstreamer_stream_handler_create },
416 { &CLSID_MSH264DecoderMFT, &h264_decoder_create },
419 HRESULT mfplat_get_class_object(REFCLSID rclsid, REFIID riid, void **obj)
421 struct class_factory *factory;
422 unsigned int i;
423 HRESULT hr;
425 for (i = 0; i < ARRAY_SIZE(class_objects); ++i)
427 if (IsEqualGUID(class_objects[i].clsid, rclsid))
429 if (!(factory = malloc(sizeof(*factory))))
430 return E_OUTOFMEMORY;
432 factory->IClassFactory_iface.lpVtbl = &class_factory_vtbl;
433 factory->refcount = 1;
434 factory->create_instance = class_objects[i].create_instance;
436 hr = IClassFactory_QueryInterface(&factory->IClassFactory_iface, riid, obj);
437 IClassFactory_Release(&factory->IClassFactory_iface);
438 return hr;
442 return CLASS_E_CLASSNOTAVAILABLE;
445 HRESULT mfplat_DllRegisterServer(void)
447 MFT_REGISTER_TYPE_INFO resampler_types[] =
449 {MFMediaType_Audio, MFAudioFormat_PCM},
450 {MFMediaType_Audio, MFAudioFormat_Float},
453 MFT_REGISTER_TYPE_INFO wma_decoder_input_types[] =
455 {MFMediaType_Audio, MEDIASUBTYPE_MSAUDIO1},
456 {MFMediaType_Audio, MFAudioFormat_WMAudioV8},
457 {MFMediaType_Audio, MFAudioFormat_WMAudioV9},
458 {MFMediaType_Audio, MFAudioFormat_WMAudio_Lossless},
460 MFT_REGISTER_TYPE_INFO wma_decoder_output_types[] =
462 {MFMediaType_Audio, MFAudioFormat_PCM},
463 {MFMediaType_Audio, MFAudioFormat_Float},
466 MFT_REGISTER_TYPE_INFO h264_decoder_input_types[] =
468 {MFMediaType_Video, MFVideoFormat_H264},
469 {MFMediaType_Video, MFVideoFormat_H264_ES},
471 MFT_REGISTER_TYPE_INFO h264_decoder_output_types[] =
473 {MFMediaType_Video, MFVideoFormat_NV12},
474 {MFMediaType_Video, MFVideoFormat_YV12},
475 {MFMediaType_Video, MFVideoFormat_IYUV},
476 {MFMediaType_Video, MFVideoFormat_I420},
477 {MFMediaType_Video, MFVideoFormat_YUY2},
480 MFT_REGISTER_TYPE_INFO video_processor_input_types[] =
482 {MFMediaType_Video, MFVideoFormat_IYUV},
483 {MFMediaType_Video, MFVideoFormat_YV12},
484 {MFMediaType_Video, MFVideoFormat_NV12},
485 {MFMediaType_Video, MFVideoFormat_YUY2},
486 {MFMediaType_Video, MFVideoFormat_ARGB32},
487 {MFMediaType_Video, MFVideoFormat_RGB32},
488 {MFMediaType_Video, MFVideoFormat_NV11},
489 {MFMediaType_Video, MFVideoFormat_AYUV},
490 {MFMediaType_Video, MFVideoFormat_UYVY},
491 {MFMediaType_Video, MEDIASUBTYPE_P208},
492 {MFMediaType_Video, MFVideoFormat_RGB24},
493 {MFMediaType_Video, MFVideoFormat_RGB555},
494 {MFMediaType_Video, MFVideoFormat_RGB565},
495 {MFMediaType_Video, MFVideoFormat_RGB8},
496 {MFMediaType_Video, MFVideoFormat_I420},
497 {MFMediaType_Video, MFVideoFormat_Y216},
498 {MFMediaType_Video, MFVideoFormat_v410},
499 {MFMediaType_Video, MFVideoFormat_Y41P},
500 {MFMediaType_Video, MFVideoFormat_Y41T},
501 {MFMediaType_Video, MFVideoFormat_Y42T},
502 {MFMediaType_Video, MFVideoFormat_YVYU},
503 {MFMediaType_Video, MFVideoFormat_420O},
505 MFT_REGISTER_TYPE_INFO video_processor_output_types[] =
507 {MFMediaType_Video, MFVideoFormat_IYUV},
508 {MFMediaType_Video, MFVideoFormat_YV12},
509 {MFMediaType_Video, MFVideoFormat_NV12},
510 {MFMediaType_Video, MFVideoFormat_YUY2},
511 {MFMediaType_Video, MFVideoFormat_ARGB32},
512 {MFMediaType_Video, MFVideoFormat_RGB32},
513 {MFMediaType_Video, MFVideoFormat_NV11},
514 {MFMediaType_Video, MFVideoFormat_AYUV},
515 {MFMediaType_Video, MFVideoFormat_UYVY},
516 {MFMediaType_Video, MEDIASUBTYPE_P208},
517 {MFMediaType_Video, MFVideoFormat_RGB24},
518 {MFMediaType_Video, MFVideoFormat_RGB555},
519 {MFMediaType_Video, MFVideoFormat_RGB565},
520 {MFMediaType_Video, MFVideoFormat_RGB8},
521 {MFMediaType_Video, MFVideoFormat_I420},
522 {MFMediaType_Video, MFVideoFormat_Y216},
523 {MFMediaType_Video, MFVideoFormat_v410},
524 {MFMediaType_Video, MFVideoFormat_Y41P},
525 {MFMediaType_Video, MFVideoFormat_Y41T},
526 {MFMediaType_Video, MFVideoFormat_Y42T},
527 {MFMediaType_Video, MFVideoFormat_YVYU},
530 MFT_REGISTER_TYPE_INFO color_convert_input_types[] =
532 {MFMediaType_Video, MFVideoFormat_YV12},
533 {MFMediaType_Video, MFVideoFormat_YUY2},
534 {MFMediaType_Video, MFVideoFormat_UYVY},
535 {MFMediaType_Video, MFVideoFormat_AYUV},
536 {MFMediaType_Video, MFVideoFormat_NV12},
537 {MFMediaType_Video, DMOVideoFormat_RGB32},
538 {MFMediaType_Video, DMOVideoFormat_RGB565},
539 {MFMediaType_Video, MFVideoFormat_I420},
540 {MFMediaType_Video, MFVideoFormat_IYUV},
541 {MFMediaType_Video, MFVideoFormat_YVYU},
542 {MFMediaType_Video, DMOVideoFormat_RGB24},
543 {MFMediaType_Video, DMOVideoFormat_RGB555},
544 {MFMediaType_Video, DMOVideoFormat_RGB8},
545 {MFMediaType_Video, MEDIASUBTYPE_V216},
546 {MFMediaType_Video, MEDIASUBTYPE_V410},
547 {MFMediaType_Video, MFVideoFormat_NV11},
548 {MFMediaType_Video, MFVideoFormat_Y41P},
549 {MFMediaType_Video, MFVideoFormat_Y41T},
550 {MFMediaType_Video, MFVideoFormat_Y42T},
551 {MFMediaType_Video, MFVideoFormat_YVU9},
553 MFT_REGISTER_TYPE_INFO color_convert_output_types[] =
555 {MFMediaType_Video, MFVideoFormat_YV12},
556 {MFMediaType_Video, MFVideoFormat_YUY2},
557 {MFMediaType_Video, MFVideoFormat_UYVY},
558 {MFMediaType_Video, MFVideoFormat_AYUV},
559 {MFMediaType_Video, MFVideoFormat_NV12},
560 {MFMediaType_Video, DMOVideoFormat_RGB32},
561 {MFMediaType_Video, DMOVideoFormat_RGB565},
562 {MFMediaType_Video, MFVideoFormat_I420},
563 {MFMediaType_Video, MFVideoFormat_IYUV},
564 {MFMediaType_Video, MFVideoFormat_YVYU},
565 {MFMediaType_Video, DMOVideoFormat_RGB24},
566 {MFMediaType_Video, DMOVideoFormat_RGB555},
567 {MFMediaType_Video, DMOVideoFormat_RGB8},
568 {MFMediaType_Video, MEDIASUBTYPE_V216},
569 {MFMediaType_Video, MEDIASUBTYPE_V410},
570 {MFMediaType_Video, MFVideoFormat_NV11},
573 struct mft
575 GUID clsid;
576 GUID category;
577 WCHAR name[MAX_PATH];
578 UINT32 flags;
579 UINT32 input_types_count;
580 MFT_REGISTER_TYPE_INFO *input_types;
581 UINT32 output_types_count;
582 MFT_REGISTER_TYPE_INFO *output_types;
584 mfts[] =
587 CLSID_WMADecMediaObject,
588 MFT_CATEGORY_AUDIO_DECODER,
589 L"WMAudio Decoder MFT",
590 MFT_ENUM_FLAG_SYNCMFT,
591 ARRAY_SIZE(wma_decoder_input_types),
592 wma_decoder_input_types,
593 ARRAY_SIZE(wma_decoder_output_types),
594 wma_decoder_output_types,
597 CLSID_MSH264DecoderMFT,
598 MFT_CATEGORY_VIDEO_DECODER,
599 L"Microsoft H264 Video Decoder MFT",
600 MFT_ENUM_FLAG_SYNCMFT,
601 ARRAY_SIZE(h264_decoder_input_types),
602 h264_decoder_input_types,
603 ARRAY_SIZE(h264_decoder_output_types),
604 h264_decoder_output_types,
607 CLSID_VideoProcessorMFT,
608 MFT_CATEGORY_VIDEO_PROCESSOR,
609 L"Microsoft Video Processor MFT",
610 MFT_ENUM_FLAG_SYNCMFT,
611 ARRAY_SIZE(video_processor_input_types),
612 video_processor_input_types,
613 ARRAY_SIZE(video_processor_output_types),
614 video_processor_output_types,
617 CLSID_CResamplerMediaObject,
618 MFT_CATEGORY_AUDIO_EFFECT,
619 L"Resampler MFT",
620 MFT_ENUM_FLAG_SYNCMFT,
621 ARRAY_SIZE(resampler_types),
622 resampler_types,
623 ARRAY_SIZE(resampler_types),
624 resampler_types,
627 CLSID_CColorConvertDMO,
628 MFT_CATEGORY_VIDEO_EFFECT,
629 L"Color Converter MFT",
630 MFT_ENUM_FLAG_SYNCMFT,
631 ARRAY_SIZE(color_convert_input_types),
632 color_convert_input_types,
633 ARRAY_SIZE(color_convert_output_types),
634 color_convert_output_types,
638 unsigned int i;
639 HRESULT hr;
641 for (i = 0; i < ARRAY_SIZE(mfts); i++)
643 hr = MFTRegister(mfts[i].clsid, mfts[i].category, mfts[i].name, mfts[i].flags, mfts[i].input_types_count,
644 mfts[i].input_types, mfts[i].output_types_count, mfts[i].output_types, NULL);
646 if (FAILED(hr))
648 FIXME("Failed to register MFT, hr %#lx.\n", hr);
649 return hr;
653 return S_OK;
656 static const struct
658 const GUID *subtype;
659 enum wg_video_format format;
661 video_formats[] =
663 {&MFVideoFormat_ARGB32, WG_VIDEO_FORMAT_BGRA},
664 {&MFVideoFormat_RGB32, WG_VIDEO_FORMAT_BGRx},
665 {&MFVideoFormat_RGB24, WG_VIDEO_FORMAT_BGR},
666 {&MFVideoFormat_RGB555, WG_VIDEO_FORMAT_RGB15},
667 {&MFVideoFormat_RGB565, WG_VIDEO_FORMAT_RGB16},
668 {&MFVideoFormat_AYUV, WG_VIDEO_FORMAT_AYUV},
669 {&MFVideoFormat_I420, WG_VIDEO_FORMAT_I420},
670 {&MFVideoFormat_IYUV, WG_VIDEO_FORMAT_I420},
671 {&MFVideoFormat_NV12, WG_VIDEO_FORMAT_NV12},
672 {&MFVideoFormat_UYVY, WG_VIDEO_FORMAT_UYVY},
673 {&MFVideoFormat_YUY2, WG_VIDEO_FORMAT_YUY2},
674 {&MFVideoFormat_YV12, WG_VIDEO_FORMAT_YV12},
675 {&MFVideoFormat_YVYU, WG_VIDEO_FORMAT_YVYU},
678 static const struct
680 const GUID *subtype;
681 UINT32 depth;
682 enum wg_audio_format format;
684 audio_formats[] =
686 {&MFAudioFormat_PCM, 8, WG_AUDIO_FORMAT_U8},
687 {&MFAudioFormat_PCM, 16, WG_AUDIO_FORMAT_S16LE},
688 {&MFAudioFormat_PCM, 24, WG_AUDIO_FORMAT_S24LE},
689 {&MFAudioFormat_PCM, 32, WG_AUDIO_FORMAT_S32LE},
690 {&MFAudioFormat_Float, 32, WG_AUDIO_FORMAT_F32LE},
691 {&MFAudioFormat_Float, 64, WG_AUDIO_FORMAT_F64LE},
694 static inline UINT64 make_uint64(UINT32 high, UINT32 low)
696 return ((UINT64)high << 32) | low;
699 static IMFMediaType *mf_media_type_from_wg_format_audio(const struct wg_format *format)
701 IMFMediaType *type;
702 unsigned int i;
704 for (i = 0; i < ARRAY_SIZE(audio_formats); ++i)
706 if (format->u.audio.format == audio_formats[i].format)
708 if (FAILED(MFCreateMediaType(&type)))
709 return NULL;
711 IMFMediaType_SetGUID(type, &MF_MT_MAJOR_TYPE, &MFMediaType_Audio);
712 IMFMediaType_SetGUID(type, &MF_MT_SUBTYPE, audio_formats[i].subtype);
713 IMFMediaType_SetUINT32(type, &MF_MT_AUDIO_BITS_PER_SAMPLE, audio_formats[i].depth);
714 IMFMediaType_SetUINT32(type, &MF_MT_AUDIO_SAMPLES_PER_SECOND, format->u.audio.rate);
715 IMFMediaType_SetUINT32(type, &MF_MT_AUDIO_NUM_CHANNELS, format->u.audio.channels);
716 IMFMediaType_SetUINT32(type, &MF_MT_AUDIO_CHANNEL_MASK, format->u.audio.channel_mask);
717 IMFMediaType_SetUINT32(type, &MF_MT_ALL_SAMPLES_INDEPENDENT, TRUE);
718 IMFMediaType_SetUINT32(type, &MF_MT_AUDIO_BLOCK_ALIGNMENT, format->u.audio.channels * audio_formats[i].depth / 8);
720 return type;
724 return NULL;
727 static IMFMediaType *mf_media_type_from_wg_format_video(const struct wg_format *format)
729 IMFMediaType *type;
730 unsigned int i;
732 for (i = 0; i < ARRAY_SIZE(video_formats); ++i)
734 if (format->u.video.format == video_formats[i].format)
736 if (FAILED(MFCreateMediaType(&type)))
737 return NULL;
739 IMFMediaType_SetGUID(type, &MF_MT_MAJOR_TYPE, &MFMediaType_Video);
740 IMFMediaType_SetGUID(type, &MF_MT_SUBTYPE, video_formats[i].subtype);
741 IMFMediaType_SetUINT64(type, &MF_MT_FRAME_SIZE,
742 make_uint64(format->u.video.width, format->u.video.height));
743 IMFMediaType_SetUINT64(type, &MF_MT_FRAME_RATE,
744 make_uint64(format->u.video.fps_n, format->u.video.fps_d));
745 IMFMediaType_SetUINT32(type, &MF_MT_COMPRESSED, FALSE);
746 IMFMediaType_SetUINT32(type, &MF_MT_ALL_SAMPLES_INDEPENDENT, TRUE);
747 IMFMediaType_SetUINT32(type, &MF_MT_VIDEO_ROTATION, MFVideoRotationFormat_0);
749 if (!IsRectEmpty(&format->u.video.padding))
751 MFVideoArea aperture =
753 .OffsetX = {.value = format->u.video.padding.left},
754 .OffsetY = {.value = format->u.video.padding.top},
755 .Area.cx = format->u.video.width - format->u.video.padding.right - format->u.video.padding.left,
756 .Area.cy = format->u.video.height - format->u.video.padding.bottom - format->u.video.padding.top,
759 IMFMediaType_SetBlob(type, &MF_MT_MINIMUM_DISPLAY_APERTURE,
760 (BYTE *)&aperture, sizeof(aperture));
763 return type;
767 return NULL;
770 IMFMediaType *mf_media_type_from_wg_format(const struct wg_format *format)
772 switch (format->major_type)
774 case WG_MAJOR_TYPE_H264:
775 case WG_MAJOR_TYPE_WMA:
776 case WG_MAJOR_TYPE_MPEG1_AUDIO:
777 FIXME("Format %u not implemented!\n", format->major_type);
778 /* fallthrough */
779 case WG_MAJOR_TYPE_UNKNOWN:
780 return NULL;
782 case WG_MAJOR_TYPE_AUDIO:
783 return mf_media_type_from_wg_format_audio(format);
785 case WG_MAJOR_TYPE_VIDEO:
786 return mf_media_type_from_wg_format_video(format);
789 assert(0);
790 return NULL;
793 static void mf_media_type_to_wg_format_audio(IMFMediaType *type, const GUID *subtype, struct wg_format *format)
795 UINT32 rate, channels, channel_mask, depth;
796 unsigned int i;
798 if (FAILED(IMFMediaType_GetUINT32(type, &MF_MT_AUDIO_SAMPLES_PER_SECOND, &rate)))
800 FIXME("Sample rate is not set.\n");
801 return;
803 if (FAILED(IMFMediaType_GetUINT32(type, &MF_MT_AUDIO_NUM_CHANNELS, &channels)))
805 FIXME("Channel count is not set.\n");
806 return;
808 if (FAILED(IMFMediaType_GetUINT32(type, &MF_MT_AUDIO_BITS_PER_SAMPLE, &depth)))
810 FIXME("Depth is not set.\n");
811 return;
813 if (FAILED(IMFMediaType_GetUINT32(type, &MF_MT_AUDIO_CHANNEL_MASK, &channel_mask)))
815 if (channels == 1)
816 channel_mask = KSAUDIO_SPEAKER_MONO;
817 else if (channels == 2)
818 channel_mask = KSAUDIO_SPEAKER_STEREO;
819 else
821 FIXME("Channel mask is not set.\n");
822 return;
826 format->major_type = WG_MAJOR_TYPE_AUDIO;
827 format->u.audio.channels = channels;
828 format->u.audio.channel_mask = channel_mask;
829 format->u.audio.rate = rate;
831 for (i = 0; i < ARRAY_SIZE(audio_formats); ++i)
833 if (IsEqualGUID(subtype, audio_formats[i].subtype) && depth == audio_formats[i].depth)
835 format->u.audio.format = audio_formats[i].format;
836 return;
839 FIXME("Unrecognized audio subtype %s, depth %u.\n", debugstr_guid(subtype), depth);
842 static void mf_media_type_to_wg_format_video(IMFMediaType *type, const GUID *subtype, struct wg_format *format)
844 UINT64 frame_rate, frame_size;
845 MFVideoArea aperture;
846 unsigned int i;
847 UINT32 size;
849 if (FAILED(IMFMediaType_GetUINT64(type, &MF_MT_FRAME_SIZE, &frame_size)))
851 FIXME("Frame size is not set.\n");
852 return;
855 format->major_type = WG_MAJOR_TYPE_VIDEO;
856 format->u.video.width = (UINT32)(frame_size >> 32);
857 format->u.video.height = (UINT32)frame_size;
858 format->u.video.fps_n = 1;
859 format->u.video.fps_d = 1;
861 if (SUCCEEDED(IMFMediaType_GetBlob(type, &MF_MT_MINIMUM_DISPLAY_APERTURE, (BYTE *)&aperture,
862 sizeof(aperture), &size)) && size == sizeof(aperture))
864 format->u.video.padding.left = aperture.OffsetX.value;
865 format->u.video.padding.top = aperture.OffsetY.value;
866 format->u.video.padding.right = format->u.video.width - aperture.Area.cx - aperture.OffsetX.value;
867 format->u.video.padding.bottom = format->u.video.height - aperture.Area.cy - aperture.OffsetY.value;
870 if (SUCCEEDED(IMFMediaType_GetUINT64(type, &MF_MT_FRAME_RATE, &frame_rate)) && (UINT32)frame_rate)
872 format->u.video.fps_n = (UINT32)(frame_rate >> 32);
873 format->u.video.fps_d = (UINT32)frame_rate;
876 for (i = 0; i < ARRAY_SIZE(video_formats); ++i)
878 if (IsEqualGUID(subtype, video_formats[i].subtype))
880 format->u.video.format = video_formats[i].format;
881 return;
884 FIXME("Unrecognized video subtype %s.\n", debugstr_guid(subtype));
887 static void mf_media_type_to_wg_format_wma(IMFMediaType *type, const GUID *subtype, struct wg_format *format)
889 UINT32 rate, depth, channels, block_align, bytes_per_second, codec_data_len;
890 BYTE codec_data[64];
891 UINT32 version;
893 if (FAILED(IMFMediaType_GetUINT32(type, &MF_MT_AUDIO_SAMPLES_PER_SECOND, &rate)))
895 FIXME("Sample rate is not set.\n");
896 return;
898 if (FAILED(IMFMediaType_GetUINT32(type, &MF_MT_AUDIO_NUM_CHANNELS, &channels)))
900 FIXME("Channel count is not set.\n");
901 return;
903 if (FAILED(IMFMediaType_GetUINT32(type, &MF_MT_AUDIO_BLOCK_ALIGNMENT, &block_align)))
905 FIXME("Block alignment is not set.\n");
906 return;
908 if (FAILED(IMFMediaType_GetUINT32(type, &MF_MT_AUDIO_BITS_PER_SAMPLE, &depth)))
910 FIXME("Depth is not set.\n");
911 return;
913 if (FAILED(IMFMediaType_GetBlob(type, &MF_MT_USER_DATA, codec_data, sizeof(codec_data), &codec_data_len)))
915 FIXME("Codec data is not set.\n");
916 return;
918 if (FAILED(IMFMediaType_GetUINT32(type, &MF_MT_AUDIO_AVG_BYTES_PER_SECOND, &bytes_per_second)))
920 FIXME("Bitrate is not set.\n");
921 bytes_per_second = 0;
924 if (IsEqualGUID(subtype, &MEDIASUBTYPE_MSAUDIO1))
925 version = 1;
926 else if (IsEqualGUID(subtype, &MFAudioFormat_WMAudioV8))
927 version = 2;
928 else if (IsEqualGUID(subtype, &MFAudioFormat_WMAudioV9))
929 version = 3;
930 else if (IsEqualGUID(subtype, &MFAudioFormat_WMAudio_Lossless))
931 version = 4;
932 else
934 assert(0);
935 return;
938 format->major_type = WG_MAJOR_TYPE_WMA;
939 format->u.wma.version = version;
940 format->u.wma.bitrate = bytes_per_second * 8;
941 format->u.wma.rate = rate;
942 format->u.wma.depth = depth;
943 format->u.wma.channels = channels;
944 format->u.wma.block_align = block_align;
945 format->u.wma.codec_data_len = codec_data_len;
946 memcpy(format->u.wma.codec_data, codec_data, codec_data_len);
949 static void mf_media_type_to_wg_format_h264(IMFMediaType *type, struct wg_format *format)
951 UINT64 frame_rate, frame_size;
952 UINT32 profile, level;
954 memset(format, 0, sizeof(*format));
955 format->major_type = WG_MAJOR_TYPE_H264;
957 if (SUCCEEDED(IMFMediaType_GetUINT64(type, &MF_MT_FRAME_SIZE, &frame_size)))
959 format->u.h264.width = frame_size >> 32;
960 format->u.h264.height = (UINT32)frame_size;
963 if (SUCCEEDED(IMFMediaType_GetUINT64(type, &MF_MT_FRAME_RATE, &frame_rate)) && (UINT32)frame_rate)
965 format->u.h264.fps_n = frame_rate >> 32;
966 format->u.h264.fps_d = (UINT32)frame_rate;
968 else
970 format->u.h264.fps_n = 1;
971 format->u.h264.fps_d = 1;
974 if (SUCCEEDED(IMFMediaType_GetUINT32(type, &MF_MT_MPEG2_PROFILE, &profile)))
975 format->u.h264.profile = profile;
977 if (SUCCEEDED(IMFMediaType_GetUINT32(type, &MF_MT_MPEG2_LEVEL, &level)))
978 format->u.h264.level = level;
981 void mf_media_type_to_wg_format(IMFMediaType *type, struct wg_format *format)
983 GUID major_type, subtype;
985 memset(format, 0, sizeof(*format));
987 if (FAILED(IMFMediaType_GetMajorType(type, &major_type)))
989 FIXME("Major type is not set.\n");
990 return;
992 if (FAILED(IMFMediaType_GetGUID(type, &MF_MT_SUBTYPE, &subtype)))
994 FIXME("Subtype is not set.\n");
995 return;
998 if (IsEqualGUID(&major_type, &MFMediaType_Audio))
1000 if (IsEqualGUID(&subtype, &MEDIASUBTYPE_MSAUDIO1) ||
1001 IsEqualGUID(&subtype, &MFAudioFormat_WMAudioV8) ||
1002 IsEqualGUID(&subtype, &MFAudioFormat_WMAudioV9) ||
1003 IsEqualGUID(&subtype, &MFAudioFormat_WMAudio_Lossless))
1004 mf_media_type_to_wg_format_wma(type, &subtype, format);
1005 else
1006 mf_media_type_to_wg_format_audio(type, &subtype, format);
1008 else if (IsEqualGUID(&major_type, &MFMediaType_Video))
1010 if (IsEqualGUID(&subtype, &MFVideoFormat_H264))
1011 mf_media_type_to_wg_format_h264(type, format);
1012 else
1013 mf_media_type_to_wg_format_video(type, &subtype, format);
1015 else
1016 FIXME("Unrecognized major type %s.\n", debugstr_guid(&major_type));