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"
28 #include "wine/debug.h"
30 WINE_DEFAULT_DEBUG_CHANNEL(mfplat
);
32 struct video_processor
34 IMFTransform IMFTransform_iface
;
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
))
53 IMFTransform_AddRef(iface
);
57 WARN("Unsupported %s.\n", debugstr_guid(riid
));
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
);
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
);
81 if (transform
->attributes
)
82 IMFAttributes_Release(transform
->attributes
);
83 if (transform
->output_attributes
)
84 IMFAttributes_Release(transform
->output_attributes
);
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;
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;
110 static HRESULT WINAPI
video_processor_GetStreamIDs(IMFTransform
*iface
, DWORD input_size
, DWORD
*inputs
,
111 DWORD output_size
, DWORD
*outputs
)
116 static HRESULT WINAPI
video_processor_GetInputStreamInfo(IMFTransform
*iface
, DWORD id
, MFT_INPUT_STREAM_INFO
*info
)
121 static HRESULT WINAPI
video_processor_GetOutputStreamInfo(IMFTransform
*iface
, DWORD id
, MFT_OUTPUT_STREAM_INFO
*info
)
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
);
138 static HRESULT WINAPI
video_processor_GetInputStreamAttributes(IMFTransform
*iface
, DWORD id
,
139 IMFAttributes
**attributes
)
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
);
157 static HRESULT WINAPI
video_processor_DeleteInputStream(IMFTransform
*iface
, DWORD id
)
159 TRACE("%p, %lu.\n", iface
, id
);
164 static HRESULT WINAPI
video_processor_AddInputStreams(IMFTransform
*iface
, DWORD streams
, DWORD
*ids
)
166 TRACE("%p, %lu, %p.\n", iface
, streams
, ids
);
171 static HRESULT WINAPI
video_processor_GetInputAvailableType(IMFTransform
*iface
, DWORD id
, DWORD index
,
174 FIXME("%p, %lu, %lu, %p.\n", iface
, id
, index
, type
);
179 static HRESULT WINAPI
video_processor_GetOutputAvailableType(IMFTransform
*iface
, DWORD id
, DWORD index
,
182 FIXME("%p, %lu, %lu, %p.\n", iface
, id
, index
, type
);
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
);
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
);
201 static HRESULT WINAPI
video_processor_GetInputCurrentType(IMFTransform
*iface
, DWORD id
, IMFMediaType
**type
)
203 FIXME("%p, %lu, %p.\n", iface
, id
, type
);
208 static HRESULT WINAPI
video_processor_GetOutputCurrentType(IMFTransform
*iface
, DWORD id
, IMFMediaType
**type
)
210 FIXME("%p, %lu, %p.\n", iface
, id
, type
);
215 static HRESULT WINAPI
video_processor_GetInputStatus(IMFTransform
*iface
, DWORD id
, DWORD
*flags
)
217 FIXME("%p, %lu, %p.\n", iface
, id
, flags
);
222 static HRESULT WINAPI
video_processor_GetOutputStatus(IMFTransform
*iface
, DWORD
*flags
)
224 FIXME("%p, %p.\n", iface
, flags
);
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
));
236 static HRESULT WINAPI
video_processor_ProcessEvent(IMFTransform
*iface
, DWORD id
, IMFMediaEvent
*event
)
238 TRACE("%p, %lu, %p.\n", iface
, id
, event
);
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
);
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
);
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
);
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
,
297 IClassFactory IClassFactory_iface
;
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
))
315 IClassFactory_AddRef(iface
);
319 WARN("%s is not supported.\n", debugstr_guid(riid
));
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
);
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
);
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
);
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
;
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)))
385 if (FAILED(hr
= MFCreateAttributes(&object
->output_attributes
, 0)))
388 *ret
= &object
->IMFTransform_iface
;
393 IMFTransform_Release(&object
->IMFTransform_iface
);
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
404 HRESULT (*create_instance
)(REFIID riid
, void **obj
);
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
;
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
);
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
},
529 WCHAR name
[MAX_PATH
];
531 UINT32 input_types_count
;
532 MFT_REGISTER_TYPE_INFO
*input_types
;
533 UINT32 output_types_count
;
534 MFT_REGISTER_TYPE_INFO
*output_types
;
539 CLSID_WINEAudioConverter
,
540 MFT_CATEGORY_AUDIO_EFFECT
,
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
,
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
);
590 FIXME("Failed to register MFT, hr %#lx.\n", hr
);
601 enum wg_video_format format
;
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
},
624 enum wg_audio_format format
;
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
)
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
)))
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);
669 static IMFMediaType
*mf_media_type_from_wg_format_video(const struct wg_format
*format
)
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
)))
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
);
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
);
707 case WG_MAJOR_TYPE_UNKNOWN
:
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
);
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
;
726 if (FAILED(IMFMediaType_GetUINT32(type
, &MF_MT_AUDIO_SAMPLES_PER_SECOND
, &rate
)))
728 FIXME("Sample rate is not set.\n");
731 if (FAILED(IMFMediaType_GetUINT32(type
, &MF_MT_AUDIO_NUM_CHANNELS
, &channels
)))
733 FIXME("Channel count is not set.\n");
736 if (FAILED(IMFMediaType_GetUINT32(type
, &MF_MT_AUDIO_BITS_PER_SAMPLE
, &depth
)))
738 FIXME("Depth is not set.\n");
741 if (FAILED(IMFMediaType_GetUINT32(type
, &MF_MT_AUDIO_CHANNEL_MASK
, &channel_mask
)))
744 channel_mask
= KSAUDIO_SPEAKER_MONO
;
745 else if (channels
== 2)
746 channel_mask
= KSAUDIO_SPEAKER_STEREO
;
749 FIXME("Channel mask is not set.\n");
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
;
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
;
775 if (FAILED(IMFMediaType_GetUINT64(type
, &MF_MT_FRAME_SIZE
, &frame_size
)))
777 FIXME("Frame size is not set.\n");
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
;
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
;
810 if (FAILED(IMFMediaType_GetUINT32(type
, &MF_MT_AUDIO_SAMPLES_PER_SECOND
, &rate
)))
812 FIXME("Sample rate is not set.\n");
815 if (FAILED(IMFMediaType_GetUINT32(type
, &MF_MT_AUDIO_NUM_CHANNELS
, &channels
)))
817 FIXME("Channel count is not set.\n");
820 if (FAILED(IMFMediaType_GetUINT32(type
, &MF_MT_AUDIO_BLOCK_ALIGNMENT
, &block_align
)))
822 FIXME("Block alignment is not set.\n");
825 if (FAILED(IMFMediaType_GetUINT32(type
, &MF_MT_AUDIO_BITS_PER_SAMPLE
, &depth
)))
827 FIXME("Depth is not set.\n");
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");
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
))
843 else if (IsEqualGUID(subtype
, &MFAudioFormat_WMAudioV8
))
845 else if (IsEqualGUID(subtype
, &MFAudioFormat_WMAudioV9
))
847 else if (IsEqualGUID(subtype
, &MFAudioFormat_WMAudio_Lossless
))
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
;
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");
909 if (FAILED(IMFMediaType_GetGUID(type
, &MF_MT_SUBTYPE
, &subtype
)))
911 FIXME("Subtype is not set.\n");
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
);
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
);
930 mf_media_type_to_wg_format_video(type
, &subtype
, format
);
933 FIXME("Unrecognized major type %s.\n", debugstr_guid(&major_type
));
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
;
952 if (!(mf_sample
= calloc(1, sizeof(*mf_sample
))))
953 return E_OUTOFMEMORY
;
954 if (FAILED(hr
= IMFSample_ConvertToContiguousBuffer(sample
, &mf_sample
->media_buffer
)))
956 if (FAILED(hr
= IMFMediaBuffer_Lock(mf_sample
->media_buffer
, &buffer
, &max_length
, ¤t_length
)))
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
;
982 if (mf_sample
->media_buffer
)
983 IMFMediaBuffer_Release(mf_sample
->media_buffer
);
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
);