l3codeca.acm: Avoid mpg123 functions with suffix.
[wine.git] / dlls / winegstreamer / mfplat.c
blob2e53afb0542446829c1b54e818428a385a4bd423
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 "mfapi.h"
28 #include "wine/debug.h"
30 WINE_DEFAULT_DEBUG_CHANNEL(mfplat);
32 struct video_processor
34 IMFTransform IMFTransform_iface;
35 LONG refcount;
36 IMFAttributes *attributes;
37 IMFAttributes *output_attributes;
40 static struct video_processor *impl_video_processor_from_IMFTransform(IMFTransform *iface)
42 return CONTAINING_RECORD(iface, struct video_processor, IMFTransform_iface);
45 static HRESULT WINAPI video_processor_QueryInterface(IMFTransform *iface, REFIID riid, void **obj)
47 TRACE("%p, %s, %p.\n", iface, debugstr_guid(riid), obj);
49 if (IsEqualIID(riid, &IID_IMFTransform) ||
50 IsEqualIID(riid, &IID_IUnknown))
52 *obj = iface;
53 IMFTransform_AddRef(iface);
54 return S_OK;
57 WARN("Unsupported %s.\n", debugstr_guid(riid));
58 *obj = NULL;
59 return E_NOINTERFACE;
62 static ULONG WINAPI video_processor_AddRef(IMFTransform *iface)
64 struct video_processor *transform = impl_video_processor_from_IMFTransform(iface);
65 ULONG refcount = InterlockedIncrement(&transform->refcount);
67 TRACE("%p, refcount %lu.\n", iface, refcount);
69 return refcount;
72 static ULONG WINAPI video_processor_Release(IMFTransform *iface)
74 struct video_processor *transform = impl_video_processor_from_IMFTransform(iface);
75 ULONG refcount = InterlockedDecrement(&transform->refcount);
77 TRACE("%p, refcount %lu.\n", iface, refcount);
79 if (!refcount)
81 if (transform->attributes)
82 IMFAttributes_Release(transform->attributes);
83 if (transform->output_attributes)
84 IMFAttributes_Release(transform->output_attributes);
85 free(transform);
88 return refcount;
91 static HRESULT WINAPI video_processor_GetStreamLimits(IMFTransform *iface, DWORD *input_minimum, DWORD *input_maximum,
92 DWORD *output_minimum, DWORD *output_maximum)
94 TRACE("%p, %p, %p, %p, %p.\n", iface, input_minimum, input_maximum, output_minimum, output_maximum);
96 *input_minimum = *input_maximum = *output_minimum = *output_maximum = 1;
98 return S_OK;
101 static HRESULT WINAPI video_processor_GetStreamCount(IMFTransform *iface, DWORD *inputs, DWORD *outputs)
103 TRACE("%p, %p, %p.\n", iface, inputs, outputs);
105 *inputs = *outputs = 1;
107 return S_OK;
110 static HRESULT WINAPI video_processor_GetStreamIDs(IMFTransform *iface, DWORD input_size, DWORD *inputs,
111 DWORD output_size, DWORD *outputs)
113 return E_NOTIMPL;
116 static HRESULT WINAPI video_processor_GetInputStreamInfo(IMFTransform *iface, DWORD id, MFT_INPUT_STREAM_INFO *info)
118 return E_NOTIMPL;
121 static HRESULT WINAPI video_processor_GetOutputStreamInfo(IMFTransform *iface, DWORD id, MFT_OUTPUT_STREAM_INFO *info)
123 return E_NOTIMPL;
126 static HRESULT WINAPI video_processor_GetAttributes(IMFTransform *iface, IMFAttributes **attributes)
128 struct video_processor *transform = impl_video_processor_from_IMFTransform(iface);
130 TRACE("%p, %p.\n", iface, attributes);
132 *attributes = transform->attributes;
133 IMFAttributes_AddRef(*attributes);
135 return S_OK;
138 static HRESULT WINAPI video_processor_GetInputStreamAttributes(IMFTransform *iface, DWORD id,
139 IMFAttributes **attributes)
141 return E_NOTIMPL;
144 static HRESULT WINAPI video_processor_GetOutputStreamAttributes(IMFTransform *iface, DWORD id,
145 IMFAttributes **attributes)
147 struct video_processor *transform = impl_video_processor_from_IMFTransform(iface);
149 TRACE("%p, %lu, %p.\n", iface, id, attributes);
151 *attributes = transform->output_attributes;
152 IMFAttributes_AddRef(*attributes);
154 return S_OK;
157 static HRESULT WINAPI video_processor_DeleteInputStream(IMFTransform *iface, DWORD id)
159 TRACE("%p, %lu.\n", iface, id);
161 return E_NOTIMPL;
164 static HRESULT WINAPI video_processor_AddInputStreams(IMFTransform *iface, DWORD streams, DWORD *ids)
166 TRACE("%p, %lu, %p.\n", iface, streams, ids);
168 return E_NOTIMPL;
171 static HRESULT WINAPI video_processor_GetInputAvailableType(IMFTransform *iface, DWORD id, DWORD index,
172 IMFMediaType **type)
174 FIXME("%p, %lu, %lu, %p.\n", iface, id, index, type);
176 return E_NOTIMPL;
179 static HRESULT WINAPI video_processor_GetOutputAvailableType(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_SetInputType(IMFTransform *iface, DWORD id, IMFMediaType *type, DWORD flags)
189 FIXME("%p, %lu, %p, %#lx.\n", iface, id, type, flags);
191 return E_NOTIMPL;
194 static HRESULT WINAPI video_processor_SetOutputType(IMFTransform *iface, DWORD id, IMFMediaType *type, DWORD flags)
196 FIXME("%p, %lu, %p, %#lx.\n", iface, id, type, flags);
198 return E_NOTIMPL;
201 static HRESULT WINAPI video_processor_GetInputCurrentType(IMFTransform *iface, DWORD id, IMFMediaType **type)
203 FIXME("%p, %lu, %p.\n", iface, id, type);
205 return E_NOTIMPL;
208 static HRESULT WINAPI video_processor_GetOutputCurrentType(IMFTransform *iface, DWORD id, IMFMediaType **type)
210 FIXME("%p, %lu, %p.\n", iface, id, type);
212 return E_NOTIMPL;
215 static HRESULT WINAPI video_processor_GetInputStatus(IMFTransform *iface, DWORD id, DWORD *flags)
217 FIXME("%p, %lu, %p.\n", iface, id, flags);
219 return E_NOTIMPL;
222 static HRESULT WINAPI video_processor_GetOutputStatus(IMFTransform *iface, DWORD *flags)
224 FIXME("%p, %p.\n", iface, flags);
226 return E_NOTIMPL;
229 static HRESULT WINAPI video_processor_SetOutputBounds(IMFTransform *iface, LONGLONG lower, LONGLONG upper)
231 FIXME("%p, %s, %s.\n", iface, wine_dbgstr_longlong(lower), wine_dbgstr_longlong(upper));
233 return E_NOTIMPL;
236 static HRESULT WINAPI video_processor_ProcessEvent(IMFTransform *iface, DWORD id, IMFMediaEvent *event)
238 TRACE("%p, %lu, %p.\n", iface, id, event);
240 return E_NOTIMPL;
243 static HRESULT WINAPI video_processor_ProcessMessage(IMFTransform *iface, MFT_MESSAGE_TYPE message, ULONG_PTR param)
245 FIXME("%p, %u, %#Ix.\n", iface, message, param);
247 return E_NOTIMPL;
250 static HRESULT WINAPI video_processor_ProcessInput(IMFTransform *iface, DWORD id, IMFSample *sample, DWORD flags)
252 FIXME("%p, %lu, %p, %#lx.\n", iface, id, sample, flags);
254 return E_NOTIMPL;
257 static HRESULT WINAPI video_processor_ProcessOutput(IMFTransform *iface, DWORD flags, DWORD count,
258 MFT_OUTPUT_DATA_BUFFER *samples, DWORD *status)
260 FIXME("%p, %#lx, %lu, %p, %p.\n", iface, flags, count, samples, status);
262 return E_NOTIMPL;
265 static const IMFTransformVtbl video_processor_vtbl =
267 video_processor_QueryInterface,
268 video_processor_AddRef,
269 video_processor_Release,
270 video_processor_GetStreamLimits,
271 video_processor_GetStreamCount,
272 video_processor_GetStreamIDs,
273 video_processor_GetInputStreamInfo,
274 video_processor_GetOutputStreamInfo,
275 video_processor_GetAttributes,
276 video_processor_GetInputStreamAttributes,
277 video_processor_GetOutputStreamAttributes,
278 video_processor_DeleteInputStream,
279 video_processor_AddInputStreams,
280 video_processor_GetInputAvailableType,
281 video_processor_GetOutputAvailableType,
282 video_processor_SetInputType,
283 video_processor_SetOutputType,
284 video_processor_GetInputCurrentType,
285 video_processor_GetOutputCurrentType,
286 video_processor_GetInputStatus,
287 video_processor_GetOutputStatus,
288 video_processor_SetOutputBounds,
289 video_processor_ProcessEvent,
290 video_processor_ProcessMessage,
291 video_processor_ProcessInput,
292 video_processor_ProcessOutput,
295 struct class_factory
297 IClassFactory IClassFactory_iface;
298 LONG refcount;
299 HRESULT (*create_instance)(REFIID riid, void **obj);
302 static struct class_factory *impl_from_IClassFactory(IClassFactory *iface)
304 return CONTAINING_RECORD(iface, struct class_factory, IClassFactory_iface);
307 static HRESULT WINAPI class_factory_QueryInterface(IClassFactory *iface, REFIID riid, void **obj)
309 TRACE("%p, %s, %p.\n", iface, debugstr_guid(riid), obj);
311 if (IsEqualGUID(riid, &IID_IClassFactory) ||
312 IsEqualGUID(riid, &IID_IUnknown))
314 *obj = iface;
315 IClassFactory_AddRef(iface);
316 return S_OK;
319 WARN("%s is not supported.\n", debugstr_guid(riid));
320 *obj = NULL;
321 return E_NOINTERFACE;
324 static ULONG WINAPI class_factory_AddRef(IClassFactory *iface)
326 struct class_factory *factory = impl_from_IClassFactory(iface);
327 return InterlockedIncrement(&factory->refcount);
330 static ULONG WINAPI class_factory_Release(IClassFactory *iface)
332 struct class_factory *factory = impl_from_IClassFactory(iface);
333 ULONG refcount = InterlockedDecrement(&factory->refcount);
335 if (!refcount)
336 free(factory);
338 return refcount;
341 static HRESULT WINAPI class_factory_CreateInstance(IClassFactory *iface, IUnknown *outer, REFIID riid, void **obj)
343 struct class_factory *factory = impl_from_IClassFactory(iface);
345 TRACE("%p, %p, %s, %p.\n", iface, outer, debugstr_guid(riid), obj);
347 if (outer)
349 *obj = NULL;
350 return CLASS_E_NOAGGREGATION;
353 return factory->create_instance(riid, obj);
356 static HRESULT WINAPI class_factory_LockServer(IClassFactory *iface, BOOL dolock)
358 TRACE("%p, %d.\n", iface, dolock);
359 return S_OK;
362 static const IClassFactoryVtbl class_factory_vtbl =
364 class_factory_QueryInterface,
365 class_factory_AddRef,
366 class_factory_Release,
367 class_factory_CreateInstance,
368 class_factory_LockServer,
371 static HRESULT video_processor_create(REFIID riid, void **ret)
373 struct video_processor *object;
374 HRESULT hr;
376 if (!(object = calloc(1, sizeof(*object))))
377 return E_OUTOFMEMORY;
379 object->IMFTransform_iface.lpVtbl = &video_processor_vtbl;
380 object->refcount = 1;
382 if (FAILED(hr = MFCreateAttributes(&object->attributes, 0)))
383 goto failed;
385 if (FAILED(hr = MFCreateAttributes(&object->output_attributes, 0)))
386 goto failed;
388 *ret = &object->IMFTransform_iface;
389 return S_OK;
391 failed:
393 IMFTransform_Release(&object->IMFTransform_iface);
394 return hr;
397 static const GUID CLSID_GStreamerByteStreamHandler = {0x317df618, 0x5e5a, 0x468a, {0x9f, 0x15, 0xd8, 0x27, 0xa9, 0xa0, 0x81, 0x62}};
399 static const GUID CLSID_WINEAudioConverter = {0x6a170414,0xaad9,0x4693,{0xb8,0x06,0x3a,0x0c,0x47,0xc5,0x70,0xd6}};
401 static const struct class_object
403 const GUID *clsid;
404 HRESULT (*create_instance)(REFIID riid, void **obj);
406 class_objects[] =
408 { &CLSID_VideoProcessorMFT, &video_processor_create },
409 { &CLSID_GStreamerByteStreamHandler, &winegstreamer_stream_handler_create },
410 { &CLSID_WINEAudioConverter, &audio_converter_create },
411 { &CLSID_MSH264DecoderMFT, &h264_decoder_create },
414 HRESULT mfplat_get_class_object(REFCLSID rclsid, REFIID riid, void **obj)
416 struct class_factory *factory;
417 unsigned int i;
418 HRESULT hr;
420 for (i = 0; i < ARRAY_SIZE(class_objects); ++i)
422 if (IsEqualGUID(class_objects[i].clsid, rclsid))
424 if (!(factory = malloc(sizeof(*factory))))
425 return E_OUTOFMEMORY;
427 factory->IClassFactory_iface.lpVtbl = &class_factory_vtbl;
428 factory->refcount = 1;
429 factory->create_instance = class_objects[i].create_instance;
431 hr = IClassFactory_QueryInterface(&factory->IClassFactory_iface, riid, obj);
432 IClassFactory_Release(&factory->IClassFactory_iface);
433 return hr;
437 return CLASS_E_CLASSNOTAVAILABLE;
440 HRESULT mfplat_DllRegisterServer(void)
442 MFT_REGISTER_TYPE_INFO audio_converter_supported_types[] =
444 {MFMediaType_Audio, MFAudioFormat_PCM},
445 {MFMediaType_Audio, MFAudioFormat_Float},
448 MFT_REGISTER_TYPE_INFO wma_decoder_input_types[] =
450 {MFMediaType_Audio, MEDIASUBTYPE_MSAUDIO1},
451 {MFMediaType_Audio, MFAudioFormat_WMAudioV8},
452 {MFMediaType_Audio, MFAudioFormat_WMAudioV9},
453 {MFMediaType_Audio, MFAudioFormat_WMAudio_Lossless},
455 MFT_REGISTER_TYPE_INFO wma_decoder_output_types[] =
457 {MFMediaType_Audio, MFAudioFormat_PCM},
458 {MFMediaType_Audio, MFAudioFormat_Float},
461 MFT_REGISTER_TYPE_INFO h264_decoder_input_types[] =
463 {MFMediaType_Video, MFVideoFormat_H264},
464 {MFMediaType_Video, MFVideoFormat_H264_ES},
466 MFT_REGISTER_TYPE_INFO h264_decoder_output_types[] =
468 {MFMediaType_Video, MFVideoFormat_NV12},
469 {MFMediaType_Video, MFVideoFormat_YV12},
470 {MFMediaType_Video, MFVideoFormat_IYUV},
471 {MFMediaType_Video, MFVideoFormat_I420},
472 {MFMediaType_Video, MFVideoFormat_YUY2},
475 MFT_REGISTER_TYPE_INFO video_processor_input_types[] =
477 {MFMediaType_Video, MFVideoFormat_IYUV},
478 {MFMediaType_Video, MFVideoFormat_YV12},
479 {MFMediaType_Video, MFVideoFormat_NV12},
480 {MFMediaType_Video, MFVideoFormat_YUY2},
481 {MFMediaType_Video, MFVideoFormat_ARGB32},
482 {MFMediaType_Video, MFVideoFormat_RGB32},
483 {MFMediaType_Video, MFVideoFormat_NV11},
484 {MFMediaType_Video, MFVideoFormat_AYUV},
485 {MFMediaType_Video, MFVideoFormat_UYVY},
486 {MFMediaType_Video, MEDIASUBTYPE_P208},
487 {MFMediaType_Video, MFVideoFormat_RGB24},
488 {MFMediaType_Video, MFVideoFormat_RGB555},
489 {MFMediaType_Video, MFVideoFormat_RGB565},
490 {MFMediaType_Video, MFVideoFormat_RGB8},
491 {MFMediaType_Video, MFVideoFormat_I420},
492 {MFMediaType_Video, MFVideoFormat_Y216},
493 {MFMediaType_Video, MFVideoFormat_v410},
494 {MFMediaType_Video, MFVideoFormat_Y41P},
495 {MFMediaType_Video, MFVideoFormat_Y41T},
496 {MFMediaType_Video, MFVideoFormat_Y42T},
497 {MFMediaType_Video, MFVideoFormat_YVYU},
498 {MFMediaType_Video, MFVideoFormat_420O},
500 MFT_REGISTER_TYPE_INFO video_processor_output_types[] =
502 {MFMediaType_Video, MFVideoFormat_IYUV},
503 {MFMediaType_Video, MFVideoFormat_YV12},
504 {MFMediaType_Video, MFVideoFormat_NV12},
505 {MFMediaType_Video, MFVideoFormat_YUY2},
506 {MFMediaType_Video, MFVideoFormat_ARGB32},
507 {MFMediaType_Video, MFVideoFormat_RGB32},
508 {MFMediaType_Video, MFVideoFormat_NV11},
509 {MFMediaType_Video, MFVideoFormat_AYUV},
510 {MFMediaType_Video, MFVideoFormat_UYVY},
511 {MFMediaType_Video, MEDIASUBTYPE_P208},
512 {MFMediaType_Video, MFVideoFormat_RGB24},
513 {MFMediaType_Video, MFVideoFormat_RGB555},
514 {MFMediaType_Video, MFVideoFormat_RGB565},
515 {MFMediaType_Video, MFVideoFormat_RGB8},
516 {MFMediaType_Video, MFVideoFormat_I420},
517 {MFMediaType_Video, MFVideoFormat_Y216},
518 {MFMediaType_Video, MFVideoFormat_v410},
519 {MFMediaType_Video, MFVideoFormat_Y41P},
520 {MFMediaType_Video, MFVideoFormat_Y41T},
521 {MFMediaType_Video, MFVideoFormat_Y42T},
522 {MFMediaType_Video, MFVideoFormat_YVYU},
525 struct mft
527 GUID clsid;
528 GUID category;
529 WCHAR name[MAX_PATH];
530 UINT32 flags;
531 UINT32 input_types_count;
532 MFT_REGISTER_TYPE_INFO *input_types;
533 UINT32 output_types_count;
534 MFT_REGISTER_TYPE_INFO *output_types;
536 mfts[] =
539 CLSID_WINEAudioConverter,
540 MFT_CATEGORY_AUDIO_EFFECT,
541 L"Audio Converter",
542 MFT_ENUM_FLAG_SYNCMFT,
543 ARRAY_SIZE(audio_converter_supported_types),
544 audio_converter_supported_types,
545 ARRAY_SIZE(audio_converter_supported_types),
546 audio_converter_supported_types,
549 CLSID_WMADecMediaObject,
550 MFT_CATEGORY_AUDIO_DECODER,
551 L"WMAudio Decoder MFT",
552 MFT_ENUM_FLAG_SYNCMFT,
553 ARRAY_SIZE(wma_decoder_input_types),
554 wma_decoder_input_types,
555 ARRAY_SIZE(wma_decoder_output_types),
556 wma_decoder_output_types,
559 CLSID_MSH264DecoderMFT,
560 MFT_CATEGORY_VIDEO_DECODER,
561 L"Microsoft H264 Video Decoder MFT",
562 MFT_ENUM_FLAG_SYNCMFT,
563 ARRAY_SIZE(h264_decoder_input_types),
564 h264_decoder_input_types,
565 ARRAY_SIZE(h264_decoder_output_types),
566 h264_decoder_output_types,
569 CLSID_VideoProcessorMFT,
570 MFT_CATEGORY_VIDEO_PROCESSOR,
571 L"Microsoft Video Processor MFT",
572 MFT_ENUM_FLAG_SYNCMFT,
573 ARRAY_SIZE(video_processor_input_types),
574 video_processor_input_types,
575 ARRAY_SIZE(video_processor_output_types),
576 video_processor_output_types,
580 unsigned int i;
581 HRESULT hr;
583 for (i = 0; i < ARRAY_SIZE(mfts); i++)
585 hr = MFTRegister(mfts[i].clsid, mfts[i].category, mfts[i].name, mfts[i].flags, mfts[i].input_types_count,
586 mfts[i].input_types, mfts[i].output_types_count, mfts[i].output_types, NULL);
588 if (FAILED(hr))
590 FIXME("Failed to register MFT, hr %#lx.\n", hr);
591 return hr;
595 return S_OK;
598 static const struct
600 const GUID *subtype;
601 enum wg_video_format format;
603 video_formats[] =
605 {&MFVideoFormat_ARGB32, WG_VIDEO_FORMAT_BGRA},
606 {&MFVideoFormat_RGB32, WG_VIDEO_FORMAT_BGRx},
607 {&MFVideoFormat_RGB24, WG_VIDEO_FORMAT_BGR},
608 {&MFVideoFormat_RGB555, WG_VIDEO_FORMAT_RGB15},
609 {&MFVideoFormat_RGB565, WG_VIDEO_FORMAT_RGB16},
610 {&MFVideoFormat_AYUV, WG_VIDEO_FORMAT_AYUV},
611 {&MFVideoFormat_I420, WG_VIDEO_FORMAT_I420},
612 {&MFVideoFormat_IYUV, WG_VIDEO_FORMAT_I420},
613 {&MFVideoFormat_NV12, WG_VIDEO_FORMAT_NV12},
614 {&MFVideoFormat_UYVY, WG_VIDEO_FORMAT_UYVY},
615 {&MFVideoFormat_YUY2, WG_VIDEO_FORMAT_YUY2},
616 {&MFVideoFormat_YV12, WG_VIDEO_FORMAT_YV12},
617 {&MFVideoFormat_YVYU, WG_VIDEO_FORMAT_YVYU},
620 static const struct
622 const GUID *subtype;
623 UINT32 depth;
624 enum wg_audio_format format;
626 audio_formats[] =
628 {&MFAudioFormat_PCM, 8, WG_AUDIO_FORMAT_U8},
629 {&MFAudioFormat_PCM, 16, WG_AUDIO_FORMAT_S16LE},
630 {&MFAudioFormat_PCM, 24, WG_AUDIO_FORMAT_S24LE},
631 {&MFAudioFormat_PCM, 32, WG_AUDIO_FORMAT_S32LE},
632 {&MFAudioFormat_Float, 32, WG_AUDIO_FORMAT_F32LE},
633 {&MFAudioFormat_Float, 64, WG_AUDIO_FORMAT_F64LE},
636 static inline UINT64 make_uint64(UINT32 high, UINT32 low)
638 return ((UINT64)high << 32) | low;
641 static IMFMediaType *mf_media_type_from_wg_format_audio(const struct wg_format *format)
643 IMFMediaType *type;
644 unsigned int i;
646 for (i = 0; i < ARRAY_SIZE(audio_formats); ++i)
648 if (format->u.audio.format == audio_formats[i].format)
650 if (FAILED(MFCreateMediaType(&type)))
651 return NULL;
653 IMFMediaType_SetGUID(type, &MF_MT_MAJOR_TYPE, &MFMediaType_Audio);
654 IMFMediaType_SetGUID(type, &MF_MT_SUBTYPE, audio_formats[i].subtype);
655 IMFMediaType_SetUINT32(type, &MF_MT_AUDIO_BITS_PER_SAMPLE, audio_formats[i].depth);
656 IMFMediaType_SetUINT32(type, &MF_MT_AUDIO_SAMPLES_PER_SECOND, format->u.audio.rate);
657 IMFMediaType_SetUINT32(type, &MF_MT_AUDIO_NUM_CHANNELS, format->u.audio.channels);
658 IMFMediaType_SetUINT32(type, &MF_MT_AUDIO_CHANNEL_MASK, format->u.audio.channel_mask);
659 IMFMediaType_SetUINT32(type, &MF_MT_ALL_SAMPLES_INDEPENDENT, TRUE);
660 IMFMediaType_SetUINT32(type, &MF_MT_AUDIO_BLOCK_ALIGNMENT, format->u.audio.channels * audio_formats[i].depth / 8);
662 return type;
666 return NULL;
669 static IMFMediaType *mf_media_type_from_wg_format_video(const struct wg_format *format)
671 IMFMediaType *type;
672 unsigned int i;
674 for (i = 0; i < ARRAY_SIZE(video_formats); ++i)
676 if (format->u.video.format == video_formats[i].format)
678 if (FAILED(MFCreateMediaType(&type)))
679 return NULL;
681 IMFMediaType_SetGUID(type, &MF_MT_MAJOR_TYPE, &MFMediaType_Video);
682 IMFMediaType_SetGUID(type, &MF_MT_SUBTYPE, video_formats[i].subtype);
683 IMFMediaType_SetUINT64(type, &MF_MT_FRAME_SIZE,
684 make_uint64(format->u.video.width, format->u.video.height));
685 IMFMediaType_SetUINT64(type, &MF_MT_FRAME_RATE,
686 make_uint64(format->u.video.fps_n, format->u.video.fps_d));
687 IMFMediaType_SetUINT32(type, &MF_MT_COMPRESSED, FALSE);
688 IMFMediaType_SetUINT32(type, &MF_MT_ALL_SAMPLES_INDEPENDENT, TRUE);
689 IMFMediaType_SetUINT32(type, &MF_MT_VIDEO_ROTATION, MFVideoRotationFormat_0);
691 return type;
695 return NULL;
698 IMFMediaType *mf_media_type_from_wg_format(const struct wg_format *format)
700 switch (format->major_type)
702 case WG_MAJOR_TYPE_H264:
703 case WG_MAJOR_TYPE_WMA:
704 case WG_MAJOR_TYPE_MPEG1_AUDIO:
705 FIXME("Format %u not implemented!\n", format->major_type);
706 /* fallthrough */
707 case WG_MAJOR_TYPE_UNKNOWN:
708 return NULL;
710 case WG_MAJOR_TYPE_AUDIO:
711 return mf_media_type_from_wg_format_audio(format);
713 case WG_MAJOR_TYPE_VIDEO:
714 return mf_media_type_from_wg_format_video(format);
717 assert(0);
718 return NULL;
721 static void mf_media_type_to_wg_format_audio(IMFMediaType *type, const GUID *subtype, struct wg_format *format)
723 UINT32 rate, channels, channel_mask, depth;
724 unsigned int i;
726 if (FAILED(IMFMediaType_GetUINT32(type, &MF_MT_AUDIO_SAMPLES_PER_SECOND, &rate)))
728 FIXME("Sample rate is not set.\n");
729 return;
731 if (FAILED(IMFMediaType_GetUINT32(type, &MF_MT_AUDIO_NUM_CHANNELS, &channels)))
733 FIXME("Channel count is not set.\n");
734 return;
736 if (FAILED(IMFMediaType_GetUINT32(type, &MF_MT_AUDIO_BITS_PER_SAMPLE, &depth)))
738 FIXME("Depth is not set.\n");
739 return;
741 if (FAILED(IMFMediaType_GetUINT32(type, &MF_MT_AUDIO_CHANNEL_MASK, &channel_mask)))
743 if (channels == 1)
744 channel_mask = KSAUDIO_SPEAKER_MONO;
745 else if (channels == 2)
746 channel_mask = KSAUDIO_SPEAKER_STEREO;
747 else
749 FIXME("Channel mask is not set.\n");
750 return;
754 format->major_type = WG_MAJOR_TYPE_AUDIO;
755 format->u.audio.channels = channels;
756 format->u.audio.channel_mask = channel_mask;
757 format->u.audio.rate = rate;
759 for (i = 0; i < ARRAY_SIZE(audio_formats); ++i)
761 if (IsEqualGUID(subtype, audio_formats[i].subtype) && depth == audio_formats[i].depth)
763 format->u.audio.format = audio_formats[i].format;
764 return;
767 FIXME("Unrecognized audio subtype %s, depth %u.\n", debugstr_guid(subtype), depth);
770 static void mf_media_type_to_wg_format_video(IMFMediaType *type, const GUID *subtype, struct wg_format *format)
772 UINT64 frame_rate, frame_size;
773 unsigned int i;
775 if (FAILED(IMFMediaType_GetUINT64(type, &MF_MT_FRAME_SIZE, &frame_size)))
777 FIXME("Frame size is not set.\n");
778 return;
781 format->major_type = WG_MAJOR_TYPE_VIDEO;
782 format->u.video.width = (UINT32)(frame_size >> 32);
783 format->u.video.height = (UINT32)frame_size;
784 format->u.video.fps_n = 1;
785 format->u.video.fps_d = 1;
787 if (SUCCEEDED(IMFMediaType_GetUINT64(type, &MF_MT_FRAME_RATE, &frame_rate)) && (UINT32)frame_rate)
789 format->u.video.fps_n = (UINT32)(frame_rate >> 32);
790 format->u.video.fps_d = (UINT32)frame_rate;
793 for (i = 0; i < ARRAY_SIZE(video_formats); ++i)
795 if (IsEqualGUID(subtype, video_formats[i].subtype))
797 format->u.video.format = video_formats[i].format;
798 return;
801 FIXME("Unrecognized video subtype %s.\n", debugstr_guid(subtype));
804 static void mf_media_type_to_wg_format_wma(IMFMediaType *type, const GUID *subtype, struct wg_format *format)
806 UINT32 rate, depth, channels, block_align, bytes_per_second, codec_data_len;
807 BYTE codec_data[64];
808 UINT32 version;
810 if (FAILED(IMFMediaType_GetUINT32(type, &MF_MT_AUDIO_SAMPLES_PER_SECOND, &rate)))
812 FIXME("Sample rate is not set.\n");
813 return;
815 if (FAILED(IMFMediaType_GetUINT32(type, &MF_MT_AUDIO_NUM_CHANNELS, &channels)))
817 FIXME("Channel count is not set.\n");
818 return;
820 if (FAILED(IMFMediaType_GetUINT32(type, &MF_MT_AUDIO_BLOCK_ALIGNMENT, &block_align)))
822 FIXME("Block alignment is not set.\n");
823 return;
825 if (FAILED(IMFMediaType_GetUINT32(type, &MF_MT_AUDIO_BITS_PER_SAMPLE, &depth)))
827 FIXME("Depth is not set.\n");
828 return;
830 if (FAILED(IMFMediaType_GetBlob(type, &MF_MT_USER_DATA, codec_data, sizeof(codec_data), &codec_data_len)))
832 FIXME("Codec data is not set.\n");
833 return;
835 if (FAILED(IMFMediaType_GetUINT32(type, &MF_MT_AUDIO_AVG_BYTES_PER_SECOND, &bytes_per_second)))
837 FIXME("Bitrate is not set.\n");
838 bytes_per_second = 0;
841 if (IsEqualGUID(subtype, &MEDIASUBTYPE_MSAUDIO1))
842 version = 1;
843 else if (IsEqualGUID(subtype, &MFAudioFormat_WMAudioV8))
844 version = 2;
845 else if (IsEqualGUID(subtype, &MFAudioFormat_WMAudioV9))
846 version = 3;
847 else if (IsEqualGUID(subtype, &MFAudioFormat_WMAudio_Lossless))
848 version = 4;
849 else
851 assert(0);
852 return;
855 format->major_type = WG_MAJOR_TYPE_WMA;
856 format->u.wma.version = version;
857 format->u.wma.bitrate = bytes_per_second * 8;
858 format->u.wma.rate = rate;
859 format->u.wma.depth = depth;
860 format->u.wma.channels = channels;
861 format->u.wma.block_align = block_align;
862 format->u.wma.codec_data_len = codec_data_len;
863 memcpy(format->u.wma.codec_data, codec_data, codec_data_len);
866 static void mf_media_type_to_wg_format_h264(IMFMediaType *type, struct wg_format *format)
868 UINT64 frame_rate, frame_size;
869 UINT32 profile, level;
871 memset(format, 0, sizeof(*format));
872 format->major_type = WG_MAJOR_TYPE_H264;
874 if (SUCCEEDED(IMFMediaType_GetUINT64(type, &MF_MT_FRAME_SIZE, &frame_size)))
876 format->u.h264.width = frame_size >> 32;
877 format->u.h264.height = (UINT32)frame_size;
880 if (SUCCEEDED(IMFMediaType_GetUINT64(type, &MF_MT_FRAME_RATE, &frame_rate)) && (UINT32)frame_rate)
882 format->u.h264.fps_n = frame_rate >> 32;
883 format->u.h264.fps_d = (UINT32)frame_rate;
885 else
887 format->u.h264.fps_n = 1;
888 format->u.h264.fps_d = 1;
891 if (SUCCEEDED(IMFMediaType_GetUINT32(type, &MF_MT_MPEG2_PROFILE, &profile)))
892 format->u.h264.profile = profile;
894 if (SUCCEEDED(IMFMediaType_GetUINT32(type, &MF_MT_MPEG2_LEVEL, &level)))
895 format->u.h264.level = level;
898 void mf_media_type_to_wg_format(IMFMediaType *type, struct wg_format *format)
900 GUID major_type, subtype;
902 memset(format, 0, sizeof(*format));
904 if (FAILED(IMFMediaType_GetMajorType(type, &major_type)))
906 FIXME("Major type is not set.\n");
907 return;
909 if (FAILED(IMFMediaType_GetGUID(type, &MF_MT_SUBTYPE, &subtype)))
911 FIXME("Subtype is not set.\n");
912 return;
915 if (IsEqualGUID(&major_type, &MFMediaType_Audio))
917 if (IsEqualGUID(&subtype, &MEDIASUBTYPE_MSAUDIO1) ||
918 IsEqualGUID(&subtype, &MFAudioFormat_WMAudioV8) ||
919 IsEqualGUID(&subtype, &MFAudioFormat_WMAudioV9) ||
920 IsEqualGUID(&subtype, &MFAudioFormat_WMAudio_Lossless))
921 mf_media_type_to_wg_format_wma(type, &subtype, format);
922 else
923 mf_media_type_to_wg_format_audio(type, &subtype, format);
925 else if (IsEqualGUID(&major_type, &MFMediaType_Video))
927 if (IsEqualGUID(&subtype, &MFVideoFormat_H264))
928 mf_media_type_to_wg_format_h264(type, format);
929 else
930 mf_media_type_to_wg_format_video(type, &subtype, format);
932 else
933 FIXME("Unrecognized major type %s.\n", debugstr_guid(&major_type));
936 struct mf_sample
938 IMFSample *sample;
939 IMFMediaBuffer *media_buffer;
940 struct wg_sample wg_sample;
943 HRESULT mf_create_wg_sample(IMFSample *sample, struct wg_sample **out)
945 DWORD current_length, max_length;
946 struct mf_sample *mf_sample;
947 LONGLONG time, duration;
948 UINT32 value;
949 BYTE *buffer;
950 HRESULT hr;
952 if (!(mf_sample = calloc(1, sizeof(*mf_sample))))
953 return E_OUTOFMEMORY;
954 if (FAILED(hr = IMFSample_ConvertToContiguousBuffer(sample, &mf_sample->media_buffer)))
955 goto out;
956 if (FAILED(hr = IMFMediaBuffer_Lock(mf_sample->media_buffer, &buffer, &max_length, &current_length)))
957 goto out;
959 if (SUCCEEDED(IMFSample_GetSampleTime(sample, &time)))
961 mf_sample->wg_sample.flags |= WG_SAMPLE_FLAG_HAS_PTS;
962 mf_sample->wg_sample.pts = time;
964 if (SUCCEEDED(IMFSample_GetSampleDuration(sample, &duration)))
966 mf_sample->wg_sample.flags |= WG_SAMPLE_FLAG_HAS_DURATION;
967 mf_sample->wg_sample.duration = duration;
969 if (SUCCEEDED(IMFSample_GetUINT32(sample, &MFSampleExtension_CleanPoint, &value)) && value)
970 mf_sample->wg_sample.flags |= WG_SAMPLE_FLAG_SYNC_POINT;
972 IMFSample_AddRef((mf_sample->sample = sample));
973 mf_sample->wg_sample.data = buffer;
974 mf_sample->wg_sample.size = current_length;
975 mf_sample->wg_sample.max_size = max_length;
977 TRACE("Created mf_sample %p for sample %p.\n", mf_sample, sample);
978 *out = &mf_sample->wg_sample;
979 return S_OK;
981 out:
982 if (mf_sample->media_buffer)
983 IMFMediaBuffer_Release(mf_sample->media_buffer);
984 free(mf_sample);
985 return hr;
988 void mf_destroy_wg_sample(struct wg_sample *wg_sample)
990 struct mf_sample *mf_sample = CONTAINING_RECORD(wg_sample, struct mf_sample, wg_sample);
992 IMFMediaBuffer_Unlock(mf_sample->media_buffer);
993 IMFMediaBuffer_SetCurrentLength(mf_sample->media_buffer, wg_sample->size);
994 IMFMediaBuffer_Release(mf_sample->media_buffer);
996 if (wg_sample->flags & WG_SAMPLE_FLAG_HAS_PTS)
997 IMFSample_SetSampleTime(mf_sample->sample, wg_sample->pts);
998 if (wg_sample->flags & WG_SAMPLE_FLAG_HAS_DURATION)
999 IMFSample_SetSampleDuration(mf_sample->sample, wg_sample->duration);
1000 if (wg_sample->flags & WG_SAMPLE_FLAG_SYNC_POINT)
1001 IMFSample_SetUINT32(mf_sample->sample, &MFSampleExtension_CleanPoint, 1);
1003 IMFSample_Release(mf_sample->sample);
1004 free(mf_sample);