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"
24 #include "wmcodecdsp.h"
26 #include "d3d9types.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
;
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
))
61 IMFTransform_AddRef(iface
);
65 WARN("Unsupported %s.\n", debugstr_guid(riid
));
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
);
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
);
89 if (transform
->attributes
)
90 IMFAttributes_Release(transform
->attributes
);
91 if (transform
->output_attributes
)
92 IMFAttributes_Release(transform
->output_attributes
);
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;
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;
118 static HRESULT WINAPI
video_processor_GetStreamIDs(IMFTransform
*iface
, DWORD input_size
, DWORD
*inputs
,
119 DWORD output_size
, DWORD
*outputs
)
124 static HRESULT WINAPI
video_processor_GetInputStreamInfo(IMFTransform
*iface
, DWORD id
, MFT_INPUT_STREAM_INFO
*info
)
129 static HRESULT WINAPI
video_processor_GetOutputStreamInfo(IMFTransform
*iface
, DWORD id
, MFT_OUTPUT_STREAM_INFO
*info
)
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
);
146 static HRESULT WINAPI
video_processor_GetInputStreamAttributes(IMFTransform
*iface
, DWORD id
,
147 IMFAttributes
**attributes
)
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
);
165 static HRESULT WINAPI
video_processor_DeleteInputStream(IMFTransform
*iface
, DWORD id
)
167 TRACE("%p, %lu.\n", iface
, id
);
172 static HRESULT WINAPI
video_processor_AddInputStreams(IMFTransform
*iface
, DWORD streams
, DWORD
*ids
)
174 TRACE("%p, %lu, %p.\n", iface
, streams
, ids
);
179 static HRESULT WINAPI
video_processor_GetInputAvailableType(IMFTransform
*iface
, DWORD id
, DWORD index
,
182 FIXME("%p, %lu, %lu, %p.\n", iface
, id
, index
, type
);
187 static HRESULT WINAPI
video_processor_GetOutputAvailableType(IMFTransform
*iface
, DWORD id
, DWORD index
,
190 FIXME("%p, %lu, %lu, %p.\n", iface
, id
, index
, type
);
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
);
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
);
209 static HRESULT WINAPI
video_processor_GetInputCurrentType(IMFTransform
*iface
, DWORD id
, IMFMediaType
**type
)
211 FIXME("%p, %lu, %p.\n", iface
, id
, type
);
216 static HRESULT WINAPI
video_processor_GetOutputCurrentType(IMFTransform
*iface
, DWORD id
, IMFMediaType
**type
)
218 FIXME("%p, %lu, %p.\n", iface
, id
, type
);
223 static HRESULT WINAPI
video_processor_GetInputStatus(IMFTransform
*iface
, DWORD id
, DWORD
*flags
)
225 FIXME("%p, %lu, %p.\n", iface
, id
, flags
);
230 static HRESULT WINAPI
video_processor_GetOutputStatus(IMFTransform
*iface
, DWORD
*flags
)
232 FIXME("%p, %p.\n", iface
, flags
);
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
));
244 static HRESULT WINAPI
video_processor_ProcessEvent(IMFTransform
*iface
, DWORD id
, IMFMediaEvent
*event
)
246 TRACE("%p, %lu, %p.\n", iface
, id
, event
);
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
);
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
);
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
);
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
,
305 IClassFactory IClassFactory_iface
;
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
))
323 IClassFactory_AddRef(iface
);
327 WARN("%s is not supported.\n", debugstr_guid(riid
));
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
);
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
);
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
);
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
;
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)))
393 if (FAILED(hr
= MFCreateAttributes(&object
->output_attributes
, 0)))
396 *ret
= &object
->IMFTransform_iface
;
401 IMFTransform_Release(&object
->IMFTransform_iface
);
405 static const GUID CLSID_GStreamerByteStreamHandler
= {0x317df618, 0x5e5a, 0x468a, {0x9f, 0x15, 0xd8, 0x27, 0xa9, 0xa0, 0x81, 0x62}};
407 static const struct class_object
410 HRESULT (*create_instance
)(REFIID riid
, void **obj
);
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
;
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
);
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
},
577 WCHAR name
[MAX_PATH
];
579 UINT32 input_types_count
;
580 MFT_REGISTER_TYPE_INFO
*input_types
;
581 UINT32 output_types_count
;
582 MFT_REGISTER_TYPE_INFO
*output_types
;
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
,
620 MFT_ENUM_FLAG_SYNCMFT
,
621 ARRAY_SIZE(resampler_types
),
623 ARRAY_SIZE(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
,
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
);
648 FIXME("Failed to register MFT, hr %#lx.\n", hr
);
659 enum wg_video_format format
;
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
},
682 enum wg_audio_format format
;
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
)
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
)))
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);
727 static IMFMediaType
*mf_media_type_from_wg_format_video(const struct wg_format
*format
)
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
)))
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
));
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
);
779 case WG_MAJOR_TYPE_UNKNOWN
:
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
);
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
;
798 if (FAILED(IMFMediaType_GetUINT32(type
, &MF_MT_AUDIO_SAMPLES_PER_SECOND
, &rate
)))
800 FIXME("Sample rate is not set.\n");
803 if (FAILED(IMFMediaType_GetUINT32(type
, &MF_MT_AUDIO_NUM_CHANNELS
, &channels
)))
805 FIXME("Channel count is not set.\n");
808 if (FAILED(IMFMediaType_GetUINT32(type
, &MF_MT_AUDIO_BITS_PER_SAMPLE
, &depth
)))
810 FIXME("Depth is not set.\n");
813 if (FAILED(IMFMediaType_GetUINT32(type
, &MF_MT_AUDIO_CHANNEL_MASK
, &channel_mask
)))
816 channel_mask
= KSAUDIO_SPEAKER_MONO
;
817 else if (channels
== 2)
818 channel_mask
= KSAUDIO_SPEAKER_STEREO
;
821 FIXME("Channel mask is not set.\n");
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
;
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
;
849 if (FAILED(IMFMediaType_GetUINT64(type
, &MF_MT_FRAME_SIZE
, &frame_size
)))
851 FIXME("Frame size is not set.\n");
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
;
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
;
893 if (FAILED(IMFMediaType_GetUINT32(type
, &MF_MT_AUDIO_SAMPLES_PER_SECOND
, &rate
)))
895 FIXME("Sample rate is not set.\n");
898 if (FAILED(IMFMediaType_GetUINT32(type
, &MF_MT_AUDIO_NUM_CHANNELS
, &channels
)))
900 FIXME("Channel count is not set.\n");
903 if (FAILED(IMFMediaType_GetUINT32(type
, &MF_MT_AUDIO_BLOCK_ALIGNMENT
, &block_align
)))
905 FIXME("Block alignment is not set.\n");
908 if (FAILED(IMFMediaType_GetUINT32(type
, &MF_MT_AUDIO_BITS_PER_SAMPLE
, &depth
)))
910 FIXME("Depth is not set.\n");
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");
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
))
926 else if (IsEqualGUID(subtype
, &MFAudioFormat_WMAudioV8
))
928 else if (IsEqualGUID(subtype
, &MFAudioFormat_WMAudioV9
))
930 else if (IsEqualGUID(subtype
, &MFAudioFormat_WMAudio_Lossless
))
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
;
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");
992 if (FAILED(IMFMediaType_GetGUID(type
, &MF_MT_SUBTYPE
, &subtype
)))
994 FIXME("Subtype is not set.\n");
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
);
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
);
1013 mf_media_type_to_wg_format_video(type
, &subtype
, format
);
1016 FIXME("Unrecognized major type %s.\n", debugstr_guid(&major_type
));