1 /* GStreamer
2 * Copyright (C) 2019 Seungha Yang <seungha.yang@navercorp.com>
3 * Copyright (C) 2020 Seungha Yang <seungha@centricular.com>
4 *
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Library General Public
7 * License as published by the Free Software Foundation; either
8 * version 2 of the License, or (at your option) any later version.
9 *
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 * Library General Public License for more details.
14 *
15 * You should have received a copy of the GNU Library General Public
16 * License along with this library; if not, write to the
17 * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
18 * Boston, MA 02110-1301, USA.
19 */
20
21 #ifdef HAVE_CONFIG_H
22 #include "config.h"
23 #endif
24
25 #include "gstmfconfig.h"
26
27 #include "gstmfutils.h"
28 #include <wrl.h>
29
30 /* *INDENT-OFF* */
31 using namespace Microsoft::WRL;
32
33 G_BEGIN_DECLS
34
35 GST_DEBUG_CATEGORY_EXTERN (gst_mf_utils_debug);
36 #define GST_CAT_DEFAULT gst_mf_utils_debug
37
38 G_END_DECLS
39
40 #define MAKE_RAW_FORMAT_CAPS(format) \
41 "video/x-raw, format = (string) " format
42
43 /* No GUID is defined for "Y16 " in mfapi.h, but it's used by several devices */
44 DEFINE_MEDIATYPE_GUID (MFVideoFormat_Y16, FCC ('Y16 '));
45
46 static struct
47 {
48 const GUID &mf_format;
49 const gchar *caps_string;
50 GstVideoFormat format;
51 } raw_video_format_map[] = {
52 /* NOTE: when adding new format, gst_mf_update_video_info_with_stride() must
53 * be updated as well */
54 {MFVideoFormat_RGB32, MAKE_RAW_FORMAT_CAPS ("BGRx"), GST_VIDEO_FORMAT_BGRx},
55 {MFVideoFormat_ARGB32, MAKE_RAW_FORMAT_CAPS ("BGRA"), GST_VIDEO_FORMAT_BGRA},
56 {MFVideoFormat_RGB565, MAKE_RAW_FORMAT_CAPS ("RGB16"), GST_VIDEO_FORMAT_RGB16},
57 {MFVideoFormat_RGB555, MAKE_RAW_FORMAT_CAPS ("RGB15"), GST_VIDEO_FORMAT_RGB15},
58 {MFVideoFormat_RGB24, MAKE_RAW_FORMAT_CAPS ("BGR"), GST_VIDEO_FORMAT_BGR},
59
60 /* packed YUV */
61 {MFVideoFormat_YUY2, MAKE_RAW_FORMAT_CAPS ("YUY2"), GST_VIDEO_FORMAT_YUY2},
62 {MFVideoFormat_YVYU, MAKE_RAW_FORMAT_CAPS ("YVYU"), GST_VIDEO_FORMAT_YVYU},
63 {MFVideoFormat_UYVY, MAKE_RAW_FORMAT_CAPS ("UYVY"), GST_VIDEO_FORMAT_UYVY},
64 {MFVideoFormat_AYUV, MAKE_RAW_FORMAT_CAPS ("VUYA"), GST_VIDEO_FORMAT_VUYA},
65
66 /* semi-planar */
67 {MFVideoFormat_NV12, MAKE_RAW_FORMAT_CAPS ("NV12"), GST_VIDEO_FORMAT_NV12},
68 {MFVideoFormat_P010, MAKE_RAW_FORMAT_CAPS ("P010_10LE"), GST_VIDEO_FORMAT_P010_10LE},
69 {MFVideoFormat_P016, MAKE_RAW_FORMAT_CAPS ("P016_LE"), GST_VIDEO_FORMAT_P016_LE},
70
71 /* planar */
72 {MFVideoFormat_I420, MAKE_RAW_FORMAT_CAPS ("I420"), GST_VIDEO_FORMAT_I420},
73 {MFVideoFormat_IYUV, MAKE_RAW_FORMAT_CAPS ("I420"), GST_VIDEO_FORMAT_I420},
74 {MFVideoFormat_YV12, MAKE_RAW_FORMAT_CAPS ("YV12"), GST_VIDEO_FORMAT_YV12},
75
76 /* complex format */
77 {MFVideoFormat_v210, MAKE_RAW_FORMAT_CAPS ("v210"), GST_VIDEO_FORMAT_v210},
78 {MFVideoFormat_v216, MAKE_RAW_FORMAT_CAPS ("v216"), GST_VIDEO_FORMAT_v216},
79
80 /* gray */
81 {MFVideoFormat_Y16, MAKE_RAW_FORMAT_CAPS ("GRAY16_LE"), GST_VIDEO_FORMAT_GRAY16_LE},
82 };
83
84 static struct
85 {
86 const GUID &mf_format;
87 const gchar *caps_string;
88 } encoded_video_format_map[] = {
89 {MFVideoFormat_H264, "video/x-h264"},
90 {MFVideoFormat_HEVC, "video/x-h265"},
91 {MFVideoFormat_H265, "video/x-h265"},
92 {MFVideoFormat_VP80, "video/x-vp8"},
93 {MFVideoFormat_VP90, "video/x-vp9"},
94 {MFVideoFormat_MJPG, "image/jpeg"},
95 };
96 /* *INDENT-ON* */
97
98 GstVideoFormat
gst_mf_video_subtype_to_video_format(const GUID * subtype)99 gst_mf_video_subtype_to_video_format (const GUID * subtype)
100 {
101 gint i;
102 for (i = 0; i < G_N_ELEMENTS (raw_video_format_map); i++) {
103 if (IsEqualGUID (raw_video_format_map[i].mf_format, *subtype))
104 return raw_video_format_map[i].format;
105 }
106
107 return GST_VIDEO_FORMAT_UNKNOWN;
108 }
109
110 const GUID *
gst_mf_video_subtype_from_video_format(GstVideoFormat format)111 gst_mf_video_subtype_from_video_format (GstVideoFormat format)
112 {
113 gint i;
114 for (i = 0; i < G_N_ELEMENTS (raw_video_format_map); i++) {
115 if (raw_video_format_map[i].format == format)
116 return &raw_video_format_map[i].mf_format;
117 }
118
119 return NULL;
120 }
121
122 static GstCaps *
gst_mf_media_type_to_video_caps(IMFMediaType * media_type)123 gst_mf_media_type_to_video_caps (IMFMediaType * media_type)
124 {
125 HRESULT hr;
126 GstCaps *caps = NULL;
127 gint i;
128 guint32 width = 0;
129 guint32 height = 0;
130 guint32 num, den;
131 guint32 val;
132 gchar *str;
133 GUID subtype;
134 GstVideoChromaSite chroma_site;
135 GstVideoColorimetry colorimetry;
136 gboolean raw_format = TRUE;
137
138 hr = media_type->GetGUID (MF_MT_SUBTYPE, &subtype);
139 if (FAILED (hr)) {
140 GST_WARNING ("Failed to get subtype, hr: 0x%x", (guint) hr);
141 return NULL;
142 }
143
144 for (i = 0; i < G_N_ELEMENTS (raw_video_format_map); i++) {
145 if (IsEqualGUID (raw_video_format_map[i].mf_format, subtype)) {
146 caps = gst_caps_from_string (raw_video_format_map[i].caps_string);
147 break;
148 }
149 }
150
151 if (!caps) {
152 for (i = 0; i < G_N_ELEMENTS (encoded_video_format_map); i++) {
153 if (IsEqualGUID (encoded_video_format_map[i].mf_format, subtype)) {
154 caps = gst_caps_from_string (encoded_video_format_map[i].caps_string);
155 raw_format = FALSE;
156 break;
157 }
158 }
159 }
160
161 if (!caps) {
162 GST_WARNING ("Unknown format %" GST_FOURCC_FORMAT,
163 GST_FOURCC_ARGS (subtype.Data1));
164 return NULL;
165 }
166
167 hr = MFGetAttributeSize (media_type, MF_MT_FRAME_SIZE, &width, &height);
168 if (FAILED (hr) || !width || !height) {
169 GST_WARNING ("Couldn't get frame size, hr: 0x%x", (guint) hr);
170 if (raw_format) {
171 gst_caps_unref (caps);
172
173 return NULL;
174 }
175 }
176
177 if (width > 0 && height > 0) {
178 gst_caps_set_simple (caps, "width", G_TYPE_INT, width,
179 "height", G_TYPE_INT, height, NULL);
180 }
181
182 hr = MFGetAttributeRatio (media_type, MF_MT_FRAME_RATE, &num, &den);
183 if (SUCCEEDED (hr) && num > 0 && den > 0)
184 gst_caps_set_simple (caps, "framerate", GST_TYPE_FRACTION, num, den, NULL);
185
186 hr = MFGetAttributeRatio (media_type, MF_MT_PIXEL_ASPECT_RATIO, &num, &den);
187 if (SUCCEEDED (hr) && num > 0 && den > 0)
188 gst_caps_set_simple (caps,
189 "pixel-aspect-ratio", GST_TYPE_FRACTION, num, den, NULL);
190
191 colorimetry.range = GST_VIDEO_COLOR_RANGE_UNKNOWN;
192 colorimetry.matrix = GST_VIDEO_COLOR_MATRIX_UNKNOWN;
193 colorimetry.transfer = GST_VIDEO_TRANSFER_UNKNOWN;
194 colorimetry.primaries = GST_VIDEO_COLOR_PRIMARIES_UNKNOWN;
195
196 hr = media_type->GetUINT32 (MF_MT_VIDEO_NOMINAL_RANGE, &val);
197 if (SUCCEEDED (hr)) {
198 switch (val) {
199 case MFNominalRange_0_255:
200 colorimetry.range = GST_VIDEO_COLOR_RANGE_0_255;
201 break;
202 case MFNominalRange_16_235:
203 colorimetry.range = GST_VIDEO_COLOR_RANGE_16_235;
204 break;
205 default:
206 break;
207 }
208 }
209
210 hr = media_type->GetUINT32 (MF_MT_VIDEO_PRIMARIES, &val);
211 if (SUCCEEDED (hr)) {
212 switch (val) {
213 case MFVideoPrimaries_BT709:
214 colorimetry.primaries = GST_VIDEO_COLOR_PRIMARIES_BT709;
215 break;
216 case MFVideoPrimaries_BT470_2_SysM:
217 colorimetry.primaries = GST_VIDEO_COLOR_PRIMARIES_BT470M;
218 break;
219 case MFVideoPrimaries_BT470_2_SysBG:
220 colorimetry.primaries = GST_VIDEO_COLOR_PRIMARIES_BT470BG;
221 break;
222 case MFVideoPrimaries_SMPTE170M:
223 colorimetry.primaries = GST_VIDEO_COLOR_PRIMARIES_SMPTE170M;
224 break;
225 case MFVideoPrimaries_SMPTE240M:
226 colorimetry.primaries = GST_VIDEO_COLOR_PRIMARIES_SMPTE240M;
227 break;
228 case MFVideoPrimaries_EBU3213:
229 colorimetry.primaries = GST_VIDEO_COLOR_PRIMARIES_EBU3213;
230 break;
231 case MFVideoPrimaries_BT2020:
232 colorimetry.primaries = GST_VIDEO_COLOR_PRIMARIES_BT2020;
233 break;
234 default:
235 GST_FIXME ("unhandled color primaries %d", val);
236 break;
237 }
238 }
239
240 hr = media_type->GetUINT32 (MF_MT_YUV_MATRIX, &val);
241 if (SUCCEEDED (hr)) {
242 switch (val) {
243 case MFVideoTransferMatrix_BT709:
244 colorimetry.matrix = GST_VIDEO_COLOR_MATRIX_BT709;
245 break;
246 case MFVideoTransferMatrix_BT601:
247 colorimetry.matrix = GST_VIDEO_COLOR_MATRIX_BT601;
248 break;
249 case MFVideoTransferMatrix_SMPTE240M:
250 colorimetry.matrix = GST_VIDEO_COLOR_MATRIX_SMPTE240M;
251 break;
252 case MFVideoTransferMatrix_BT2020_10:
253 case MFVideoTransferMatrix_BT2020_12:
254 colorimetry.matrix = GST_VIDEO_COLOR_MATRIX_BT2020;
255 break;
256 default:
257 GST_FIXME ("unhandled color matrix %d", val);
258 break;
259 }
260 }
261
262 hr = media_type->GetUINT32 (MF_MT_TRANSFER_FUNCTION, &val);
263 if (SUCCEEDED (hr)) {
264 switch (val) {
265 case MFVideoTransFunc_10:
266 colorimetry.transfer = GST_VIDEO_TRANSFER_GAMMA10;
267 break;
268 case MFVideoTransFunc_18:
269 colorimetry.transfer = GST_VIDEO_TRANSFER_GAMMA18;
270 break;
271 case MFVideoTransFunc_20:
272 colorimetry.transfer = GST_VIDEO_TRANSFER_GAMMA20;
273 break;
274 case MFVideoTransFunc_22:
275 colorimetry.transfer = GST_VIDEO_TRANSFER_GAMMA22;
276 break;
277 case MFVideoTransFunc_709:
278 case MFVideoTransFunc_709_sym:
279 colorimetry.transfer = GST_VIDEO_TRANSFER_BT709;
280 break;
281 case MFVideoTransFunc_240M:
282 colorimetry.transfer = GST_VIDEO_TRANSFER_SMPTE240M;
283 break;
284 case MFVideoTransFunc_sRGB:
285 colorimetry.transfer = GST_VIDEO_TRANSFER_SRGB;
286 break;
287 case MFVideoTransFunc_28:
288 colorimetry.transfer = GST_VIDEO_TRANSFER_GAMMA28;
289 break;
290 case MFVideoTransFunc_Log_100:
291 colorimetry.transfer = GST_VIDEO_TRANSFER_LOG100;
292 break;
293 case MFVideoTransFunc_Log_316:
294 colorimetry.transfer = GST_VIDEO_TRANSFER_LOG316;
295 break;
296 case MFVideoTransFunc_2020_const:
297 case MFVideoTransFunc_2020:
298 colorimetry.transfer = GST_VIDEO_TRANSFER_BT2020_10;
299 break;
300 case MFVideoTransFunc_2084:
301 colorimetry.transfer = GST_VIDEO_TRANSFER_SMPTE2084;
302 break;
303 case MFVideoTransFunc_HLG:
304 colorimetry.transfer = GST_VIDEO_TRANSFER_ARIB_STD_B67;
305 break;
306 default:
307 GST_FIXME ("unhandled color transfer %d", val);
308 break;
309 }
310 }
311
312 str = gst_video_colorimetry_to_string (&colorimetry);
313 if (str) {
314 gst_caps_set_simple (caps, "colorimetry", G_TYPE_STRING, str, NULL);
315 g_free (str);
316 str = NULL;
317 }
318
319 chroma_site = GST_VIDEO_CHROMA_SITE_UNKNOWN;
320
321 hr = media_type->GetUINT32 (MF_MT_VIDEO_CHROMA_SITING, &val);
322 if (SUCCEEDED (hr)) {
323 gboolean known_value = TRUE;
324
325 if ((val & MFVideoChromaSubsampling_MPEG2) ==
326 MFVideoChromaSubsampling_MPEG2) {
327 chroma_site = GST_VIDEO_CHROMA_SITE_MPEG2;
328 } else if ((val & MFVideoChromaSubsampling_DV_PAL) ==
329 MFVideoChromaSubsampling_DV_PAL) {
330 chroma_site = GST_VIDEO_CHROMA_SITE_DV;
331 } else if ((val & MFVideoChromaSubsampling_Cosited) ==
332 MFVideoChromaSubsampling_Cosited) {
333 chroma_site = GST_VIDEO_CHROMA_SITE_COSITED;
334 } else {
335 known_value = FALSE;
336 }
337
338 GST_LOG ("have %s chroma site value 0x%x",
339 known_value ? "known" : "unknown", val);
340 }
341
342 if (chroma_site != GST_VIDEO_CHROMA_SITE_UNKNOWN)
343 gst_caps_set_simple (caps, "chroma-site", G_TYPE_STRING,
344 gst_video_chroma_to_string (chroma_site), NULL);
345
346 return caps;
347 }
348
349 GstCaps *
gst_mf_media_type_to_caps(IMFMediaType * media_type)350 gst_mf_media_type_to_caps (IMFMediaType * media_type)
351 {
352 GUID major_type;
353 HRESULT hr;
354
355 g_return_val_if_fail (media_type != NULL, NULL);
356
357 hr = media_type->GetMajorType (&major_type);
358 if (FAILED (hr)) {
359 GST_WARNING ("failed to get major type, hr: 0x%x", (guint) hr);
360 return NULL;
361 }
362
363 if (IsEqualGUID (major_type, MFMediaType_Video))
364 return gst_mf_media_type_to_video_caps (media_type);
365
366 return NULL;
367 }
368
369 void
gst_mf_media_type_release(IMFMediaType * media_type)370 gst_mf_media_type_release (IMFMediaType * media_type)
371 {
372 if (media_type)
373 media_type->Release ();
374 }
375
376 gboolean
gst_mf_update_video_info_with_stride(GstVideoInfo * info,gint stride)377 gst_mf_update_video_info_with_stride (GstVideoInfo * info, gint stride)
378 {
379 guint width, height, cr_h;
380
381 g_return_val_if_fail (info != nullptr, FALSE);
382 g_return_val_if_fail (stride > 0, FALSE);
383 g_return_val_if_fail (GST_VIDEO_INFO_FORMAT (info)
384 != GST_VIDEO_FORMAT_UNKNOWN, FALSE);
385
386 if (GST_VIDEO_INFO_FORMAT (info) == GST_VIDEO_FORMAT_ENCODED)
387 return TRUE;
388
389 width = GST_VIDEO_INFO_WIDTH (info);
390 height = GST_VIDEO_INFO_HEIGHT (info);
391
392 /* copied from video-info */
393 switch (GST_VIDEO_INFO_FORMAT (info)) {
394 /* RGB */
395 case GST_VIDEO_FORMAT_RGBx:
396 case GST_VIDEO_FORMAT_RGBA:
397 case GST_VIDEO_FORMAT_RGB16:
398 case GST_VIDEO_FORMAT_BGR15:
399 case GST_VIDEO_FORMAT_BGR:
400 info->stride[0] = stride;
401 info->offset[0] = 0;
402 info->size = info->stride[0] * height;
403 break;
404 /* packed YUV */
405 case GST_VIDEO_FORMAT_YUY2:
406 case GST_VIDEO_FORMAT_YVYU:
407 case GST_VIDEO_FORMAT_UYVY:
408 case GST_VIDEO_FORMAT_VUYA:
409 info->stride[0] = stride;
410 info->offset[0] = 0;
411 info->size = info->stride[0] * height;
412 break;
413 /* semi-planar */
414 case GST_VIDEO_FORMAT_NV12:
415 case GST_VIDEO_FORMAT_P010_10LE:
416 case GST_VIDEO_FORMAT_P016_LE:
417 if (height % 2) {
418 GST_ERROR ("Height must be even number");
419 return FALSE;
420 }
421
422 cr_h = height / 2;
423
424 info->stride[0] = stride;
425 info->stride[1] = info->stride[0];
426 info->offset[0] = 0;
427 info->offset[1] = info->stride[0] * height;
428 info->size = info->offset[1] + info->stride[0] * cr_h;
429 break;
430 /* planar */
431 case GST_VIDEO_FORMAT_I420:
432 case GST_VIDEO_FORMAT_YV12:
433 if (stride % 2) {
434 GST_ERROR ("Stride must be even number");
435 return FALSE;
436 }
437
438 if (height % 2) {
439 GST_ERROR ("Height must be even number");
440 return FALSE;
441 }
442
443 cr_h = height / 2;
444
445 info->stride[0] = stride;
446 info->stride[1] = stride / 2;
447 info->stride[2] = info->stride[1];
448 info->offset[0] = 0;
449 info->offset[1] = info->stride[0] * height;
450 info->offset[2] = info->offset[1] + info->stride[1] * cr_h;
451 info->size = info->offset[2] + info->stride[2] * cr_h;
452 break;
453 /* complex */
454 case GST_VIDEO_FORMAT_v210:
455 case GST_VIDEO_FORMAT_v216:
456 info->stride[0] = stride;
457 info->offset[0] = 0;
458 info->size = info->stride[0] * height;
459 break;
460 /* gray */
461 case GST_VIDEO_FORMAT_GRAY16_LE:
462 info->stride[0] = stride;
463 info->offset[0] = 0;
464 info->size = info->stride[0] * height;
465 break;
466 default:
467 GST_ERROR ("Unhandled format %s",
468 gst_video_format_to_string (GST_VIDEO_INFO_FORMAT (info)));
469 return FALSE;
470 }
471
472 return TRUE;
473 }
474
475 gboolean
_gst_mf_result(HRESULT hr,GstDebugCategory * cat,const gchar * file,const gchar * function,gint line)476 _gst_mf_result (HRESULT hr, GstDebugCategory * cat, const gchar * file,
477 const gchar * function, gint line)
478 {
479 #ifndef GST_DISABLE_GST_DEBUG
480 gboolean ret = TRUE;
481
482 if (FAILED (hr)) {
483 gchar *error_text = NULL;
484
485 error_text = g_win32_error_message ((gint) hr);
486 /* g_win32_error_message() doesn't cover all HERESULT return code,
487 * so it could be empty string, or null if there was an error
488 * in g_utf16_to_utf8() */
489 gst_debug_log (cat, GST_LEVEL_WARNING, file, function, line,
490 NULL, "MediaFoundation call failed: 0x%x, %s", (guint) hr,
491 GST_STR_NULL (error_text));
492 g_free (error_text);
493
494 ret = FALSE;
495 }
496
497 return ret;
498 #else
499 return SUCCEEDED (hr);
500 #endif
501 }
502
503 /* Reference:
504 * https://docs.microsoft.com/en-us/windows/win32/medfound/media-type-debugging-code */
505 #define GST_MF_IF_EQUAL_RETURN(guid,val) G_STMT_START { \
506 if (IsEqualGUID (guid, val)) \
507 return G_STRINGIFY (val); \
508 } G_STMT_END
509
510 static const gchar *
gst_mf_guid_to_static_string(const GUID & guid)511 gst_mf_guid_to_static_string (const GUID & guid)
512 {
513 GST_MF_IF_EQUAL_RETURN (guid, MF_MT_MAJOR_TYPE);
514 GST_MF_IF_EQUAL_RETURN (guid, MF_MT_MAJOR_TYPE);
515 GST_MF_IF_EQUAL_RETURN (guid, MF_MT_SUBTYPE);
516 GST_MF_IF_EQUAL_RETURN (guid, MF_MT_ALL_SAMPLES_INDEPENDENT);
517 GST_MF_IF_EQUAL_RETURN (guid, MF_MT_FIXED_SIZE_SAMPLES);
518 GST_MF_IF_EQUAL_RETURN (guid, MF_MT_COMPRESSED);
519 GST_MF_IF_EQUAL_RETURN (guid, MF_MT_SAMPLE_SIZE);
520 GST_MF_IF_EQUAL_RETURN (guid, MF_MT_WRAPPED_TYPE);
521 GST_MF_IF_EQUAL_RETURN (guid, MF_MT_AUDIO_NUM_CHANNELS);
522 GST_MF_IF_EQUAL_RETURN (guid, MF_MT_AUDIO_SAMPLES_PER_SECOND);
523 GST_MF_IF_EQUAL_RETURN (guid, MF_MT_AUDIO_FLOAT_SAMPLES_PER_SECOND);
524 GST_MF_IF_EQUAL_RETURN (guid, MF_MT_AUDIO_AVG_BYTES_PER_SECOND);
525 GST_MF_IF_EQUAL_RETURN (guid, MF_MT_AUDIO_BLOCK_ALIGNMENT);
526 GST_MF_IF_EQUAL_RETURN (guid, MF_MT_AUDIO_BITS_PER_SAMPLE);
527 GST_MF_IF_EQUAL_RETURN (guid, MF_MT_AUDIO_VALID_BITS_PER_SAMPLE);
528 GST_MF_IF_EQUAL_RETURN (guid, MF_MT_AUDIO_SAMPLES_PER_BLOCK);
529 GST_MF_IF_EQUAL_RETURN (guid, MF_MT_AUDIO_CHANNEL_MASK);
530 GST_MF_IF_EQUAL_RETURN (guid, MF_MT_AUDIO_FOLDDOWN_MATRIX);
531 GST_MF_IF_EQUAL_RETURN (guid, MF_MT_AUDIO_WMADRC_PEAKREF);
532 GST_MF_IF_EQUAL_RETURN (guid, MF_MT_AUDIO_WMADRC_PEAKTARGET);
533 GST_MF_IF_EQUAL_RETURN (guid, MF_MT_AUDIO_WMADRC_AVGREF);
534 GST_MF_IF_EQUAL_RETURN (guid, MF_MT_AUDIO_WMADRC_AVGTARGET);
535 GST_MF_IF_EQUAL_RETURN (guid, MF_MT_AUDIO_PREFER_WAVEFORMATEX);
536 GST_MF_IF_EQUAL_RETURN (guid, MF_MT_AAC_PAYLOAD_TYPE);
537 GST_MF_IF_EQUAL_RETURN (guid, MF_MT_AAC_AUDIO_PROFILE_LEVEL_INDICATION);
538 GST_MF_IF_EQUAL_RETURN (guid, MF_MT_FRAME_SIZE);
539 GST_MF_IF_EQUAL_RETURN (guid, MF_MT_FRAME_RATE);
540 GST_MF_IF_EQUAL_RETURN (guid, MF_MT_FRAME_RATE_RANGE_MAX);
541 GST_MF_IF_EQUAL_RETURN (guid, MF_MT_FRAME_RATE_RANGE_MIN);
542 GST_MF_IF_EQUAL_RETURN (guid, MF_MT_PIXEL_ASPECT_RATIO);
543 GST_MF_IF_EQUAL_RETURN (guid, MF_MT_DRM_FLAGS);
544 GST_MF_IF_EQUAL_RETURN (guid, MF_MT_PAD_CONTROL_FLAGS);
545 GST_MF_IF_EQUAL_RETURN (guid, MF_MT_SOURCE_CONTENT_HINT);
546 GST_MF_IF_EQUAL_RETURN (guid, MF_MT_VIDEO_CHROMA_SITING);
547 GST_MF_IF_EQUAL_RETURN (guid, MF_MT_INTERLACE_MODE);
548 GST_MF_IF_EQUAL_RETURN (guid, MF_MT_TRANSFER_FUNCTION);
549 GST_MF_IF_EQUAL_RETURN (guid, MF_MT_VIDEO_PRIMARIES);
550 GST_MF_IF_EQUAL_RETURN (guid, MF_MT_YUV_MATRIX);
551 GST_MF_IF_EQUAL_RETURN (guid, MF_MT_VIDEO_LIGHTING);
552 GST_MF_IF_EQUAL_RETURN (guid, MF_MT_VIDEO_NOMINAL_RANGE);
553 GST_MF_IF_EQUAL_RETURN (guid, MF_MT_GEOMETRIC_APERTURE);
554 GST_MF_IF_EQUAL_RETURN (guid, MF_MT_MINIMUM_DISPLAY_APERTURE);
555 GST_MF_IF_EQUAL_RETURN (guid, MF_MT_PAN_SCAN_APERTURE);
556 GST_MF_IF_EQUAL_RETURN (guid, MF_MT_PAN_SCAN_ENABLED);
557 GST_MF_IF_EQUAL_RETURN (guid, MF_MT_AVG_BITRATE);
558 GST_MF_IF_EQUAL_RETURN (guid, MF_MT_AVG_BIT_ERROR_RATE);
559 GST_MF_IF_EQUAL_RETURN (guid, MF_MT_MAX_KEYFRAME_SPACING);
560 GST_MF_IF_EQUAL_RETURN (guid, MF_MT_DEFAULT_STRIDE);
561 GST_MF_IF_EQUAL_RETURN (guid, MF_MT_PALETTE);
562 GST_MF_IF_EQUAL_RETURN (guid, MF_MT_USER_DATA);
563 GST_MF_IF_EQUAL_RETURN (guid, MF_MT_MPEG_START_TIME_CODE);
564 GST_MF_IF_EQUAL_RETURN (guid, MF_MT_MPEG2_PROFILE);
565 GST_MF_IF_EQUAL_RETURN (guid, MF_MT_MPEG2_LEVEL);
566 GST_MF_IF_EQUAL_RETURN (guid, MF_MT_MPEG2_FLAGS);
567 GST_MF_IF_EQUAL_RETURN (guid, MF_MT_MPEG_SEQUENCE_HEADER);
568 GST_MF_IF_EQUAL_RETURN (guid, MF_MT_DV_AAUX_SRC_PACK_0);
569 GST_MF_IF_EQUAL_RETURN (guid, MF_MT_DV_AAUX_CTRL_PACK_0);
570 GST_MF_IF_EQUAL_RETURN (guid, MF_MT_DV_AAUX_SRC_PACK_1);
571 GST_MF_IF_EQUAL_RETURN (guid, MF_MT_DV_AAUX_CTRL_PACK_1);
572 GST_MF_IF_EQUAL_RETURN (guid, MF_MT_DV_VAUX_SRC_PACK);
573 GST_MF_IF_EQUAL_RETURN (guid, MF_MT_DV_VAUX_CTRL_PACK);
574 GST_MF_IF_EQUAL_RETURN (guid, MF_MT_IMAGE_LOSS_TOLERANT);
575 GST_MF_IF_EQUAL_RETURN (guid, MF_MT_MPEG4_SAMPLE_DESCRIPTION);
576 GST_MF_IF_EQUAL_RETURN (guid, MF_MT_MPEG4_CURRENT_SAMPLE_ENTRY);
577
578 GST_MF_IF_EQUAL_RETURN (guid, MFMediaType_Audio);
579 GST_MF_IF_EQUAL_RETURN (guid, MFMediaType_Video);
580 GST_MF_IF_EQUAL_RETURN (guid, MFMediaType_Protected);
581 GST_MF_IF_EQUAL_RETURN (guid, MFMediaType_SAMI);
582 GST_MF_IF_EQUAL_RETURN (guid, MFMediaType_Script);
583 GST_MF_IF_EQUAL_RETURN (guid, MFMediaType_Image);
584 GST_MF_IF_EQUAL_RETURN (guid, MFMediaType_HTML);
585 GST_MF_IF_EQUAL_RETURN (guid, MFMediaType_Binary);
586 GST_MF_IF_EQUAL_RETURN (guid, MFMediaType_FileTransfer);
587
588 GST_MF_IF_EQUAL_RETURN (guid, MFVideoFormat_AI44);
589 GST_MF_IF_EQUAL_RETURN (guid, MFVideoFormat_ARGB32);
590 GST_MF_IF_EQUAL_RETURN (guid, MFVideoFormat_AYUV);
591 GST_MF_IF_EQUAL_RETURN (guid, MFVideoFormat_DV25);
592 GST_MF_IF_EQUAL_RETURN (guid, MFVideoFormat_DV50);
593 GST_MF_IF_EQUAL_RETURN (guid, MFVideoFormat_DVH1);
594 GST_MF_IF_EQUAL_RETURN (guid, MFVideoFormat_DVSD);
595 GST_MF_IF_EQUAL_RETURN (guid, MFVideoFormat_DVSL);
596 GST_MF_IF_EQUAL_RETURN (guid, MFVideoFormat_H264);
597 GST_MF_IF_EQUAL_RETURN (guid, MFVideoFormat_H265);
598 GST_MF_IF_EQUAL_RETURN (guid, MFVideoFormat_HEVC);
599 GST_MF_IF_EQUAL_RETURN (guid, MFVideoFormat_HEVC_ES);
600 GST_MF_IF_EQUAL_RETURN (guid, MFVideoFormat_I420);
601 GST_MF_IF_EQUAL_RETURN (guid, MFVideoFormat_IYUV);
602 GST_MF_IF_EQUAL_RETURN (guid, MFVideoFormat_M4S2);
603 GST_MF_IF_EQUAL_RETURN (guid, MFVideoFormat_MJPG);
604 GST_MF_IF_EQUAL_RETURN (guid, MFVideoFormat_MP43);
605 GST_MF_IF_EQUAL_RETURN (guid, MFVideoFormat_MP4S);
606 GST_MF_IF_EQUAL_RETURN (guid, MFVideoFormat_MP4V);
607 GST_MF_IF_EQUAL_RETURN (guid, MFVideoFormat_MPG1);
608 GST_MF_IF_EQUAL_RETURN (guid, MFVideoFormat_MSS1);
609 GST_MF_IF_EQUAL_RETURN (guid, MFVideoFormat_MSS2);
610 GST_MF_IF_EQUAL_RETURN (guid, MFVideoFormat_NV11);
611 GST_MF_IF_EQUAL_RETURN (guid, MFVideoFormat_NV12);
612 GST_MF_IF_EQUAL_RETURN (guid, MFVideoFormat_P010);
613 GST_MF_IF_EQUAL_RETURN (guid, MFVideoFormat_P016);
614 GST_MF_IF_EQUAL_RETURN (guid, MFVideoFormat_P210);
615 GST_MF_IF_EQUAL_RETURN (guid, MFVideoFormat_P216);
616 GST_MF_IF_EQUAL_RETURN (guid, MFVideoFormat_RGB24);
617 GST_MF_IF_EQUAL_RETURN (guid, MFVideoFormat_RGB32);
618 GST_MF_IF_EQUAL_RETURN (guid, MFVideoFormat_RGB555);
619 GST_MF_IF_EQUAL_RETURN (guid, MFVideoFormat_RGB565);
620 GST_MF_IF_EQUAL_RETURN (guid, MFVideoFormat_RGB8);
621 GST_MF_IF_EQUAL_RETURN (guid, MFVideoFormat_UYVY);
622 GST_MF_IF_EQUAL_RETURN (guid, MFVideoFormat_v210);
623 GST_MF_IF_EQUAL_RETURN (guid, MFVideoFormat_v410);
624 GST_MF_IF_EQUAL_RETURN (guid, MFVideoFormat_VP80);
625 GST_MF_IF_EQUAL_RETURN (guid, MFVideoFormat_VP90);
626 GST_MF_IF_EQUAL_RETURN (guid, MFVideoFormat_WMV1);
627 GST_MF_IF_EQUAL_RETURN (guid, MFVideoFormat_WMV2);
628 GST_MF_IF_EQUAL_RETURN (guid, MFVideoFormat_WMV3);
629 GST_MF_IF_EQUAL_RETURN (guid, MFVideoFormat_WVC1);
630 GST_MF_IF_EQUAL_RETURN (guid, MFVideoFormat_Y210);
631 GST_MF_IF_EQUAL_RETURN (guid, MFVideoFormat_Y216);
632 GST_MF_IF_EQUAL_RETURN (guid, MFVideoFormat_Y410);
633 GST_MF_IF_EQUAL_RETURN (guid, MFVideoFormat_Y416);
634 GST_MF_IF_EQUAL_RETURN (guid, MFVideoFormat_Y41P);
635 GST_MF_IF_EQUAL_RETURN (guid, MFVideoFormat_Y41T);
636 GST_MF_IF_EQUAL_RETURN (guid, MFVideoFormat_YUY2);
637 GST_MF_IF_EQUAL_RETURN (guid, MFVideoFormat_YV12);
638 GST_MF_IF_EQUAL_RETURN (guid, MFVideoFormat_YVYU);
639
640 /* WAVE_FORMAT_PCM */
641 GST_MF_IF_EQUAL_RETURN (guid, MFAudioFormat_PCM);
642 /* WAVE_FORMAT_IEEE_FLOAT */
643 GST_MF_IF_EQUAL_RETURN (guid, MFAudioFormat_Float);
644 /* WAVE_FORMAT_DTS */
645 GST_MF_IF_EQUAL_RETURN (guid, MFAudioFormat_DTS);
646 /* WAVE_FORMAT_DOLBY_AC3_SPDIF */
647 GST_MF_IF_EQUAL_RETURN (guid, MFAudioFormat_Dolby_AC3_SPDIF);
648 /* WAVE_FORMAT_DRM */
649 GST_MF_IF_EQUAL_RETURN (guid, MFAudioFormat_DRM);
650 /* WAVE_FORMAT_WMAUDIO2 */
651 GST_MF_IF_EQUAL_RETURN (guid, MFAudioFormat_WMAudioV8);
652 /* WAVE_FORMAT_WMAUDIO3 */
653 GST_MF_IF_EQUAL_RETURN (guid, MFAudioFormat_WMAudioV9);
654 /* WAVE_FORMAT_WMAUDIO_LOSSLESS */
655 GST_MF_IF_EQUAL_RETURN (guid, MFAudioFormat_WMAudio_Lossless);
656 /* WAVE_FORMAT_WMASPDIF */
657 GST_MF_IF_EQUAL_RETURN (guid, MFAudioFormat_WMASPDIF);
658 /* WAVE_FORMAT_WMAVOICE9 */
659 GST_MF_IF_EQUAL_RETURN (guid, MFAudioFormat_MSP1);
660 /* WAVE_FORMAT_MPEGLAYER3 */
661 GST_MF_IF_EQUAL_RETURN (guid, MFAudioFormat_MP3);
662 /* WAVE_FORMAT_MPEG */
663 GST_MF_IF_EQUAL_RETURN (guid, MFAudioFormat_MPEG);
664 /* WAVE_FORMAT_MPEG_HEAAC */
665 GST_MF_IF_EQUAL_RETURN (guid, MFAudioFormat_AAC);
666 /* WAVE_FORMAT_MPEG_ADTS_AAC */
667 GST_MF_IF_EQUAL_RETURN (guid, MFAudioFormat_ADTS);
668
669 #if GST_MF_WINAPI_DESKTOP
670 GST_MF_IF_EQUAL_RETURN (guid, MF_MT_CUSTOM_VIDEO_PRIMARIES);
671 GST_MF_IF_EQUAL_RETURN (guid, MF_MT_AM_FORMAT_TYPE);
672 GST_MF_IF_EQUAL_RETURN (guid, MF_MT_ARBITRARY_HEADER);
673 GST_MF_IF_EQUAL_RETURN (guid, MF_MT_ARBITRARY_FORMAT);
674 GST_MF_IF_EQUAL_RETURN (guid, MF_MT_ORIGINAL_4CC);
675 GST_MF_IF_EQUAL_RETURN (guid, MF_MT_ORIGINAL_WAVE_FORMAT_TAG);
676 #endif
677
678 return NULL;
679 }
680
681 static gchar *
gst_mf_guid_to_string(const GUID & guid)682 gst_mf_guid_to_string (const GUID & guid)
683 {
684 const gchar *str = NULL;
685 HRESULT hr;
686 WCHAR *name = NULL;
687 gchar *ret = NULL;
688
689 str = gst_mf_guid_to_static_string (guid);
690 if (str)
691 return g_strdup (str);
692
693 hr = StringFromCLSID (guid, &name);
694 if (gst_mf_result (hr) && name) {
695 ret = g_utf16_to_utf8 ((const gunichar2 *) name, -1, NULL, NULL, NULL);
696 CoTaskMemFree (name);
697
698 if (ret)
699 return ret;
700 }
701
702 ret = g_strdup_printf
703 ("%8.8x-%4.4x-%4.4x-%2.2x%2.2x-%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x",
704 (guint) guid.Data1, (guint) guid.Data2, (guint) guid.Data3,
705 guid.Data4[0], guid.Data4[1], guid.Data4[2], guid.Data4[3],
706 guid.Data4[4], guid.Data4[5], guid.Data4[6], guid.Data4[7]);
707
708 return ret;
709 }
710
711 static gchar *
gst_mf_attribute_value_to_string(const GUID & guid,const PROPVARIANT & var)712 gst_mf_attribute_value_to_string (const GUID & guid, const PROPVARIANT & var)
713 {
714 if (IsEqualGUID (guid, MF_MT_FRAME_RATE) ||
715 IsEqualGUID (guid, MF_MT_FRAME_RATE_RANGE_MAX) ||
716 IsEqualGUID (guid, MF_MT_FRAME_RATE_RANGE_MIN) ||
717 IsEqualGUID (guid, MF_MT_FRAME_SIZE) ||
718 IsEqualGUID (guid, MF_MT_PIXEL_ASPECT_RATIO)) {
719 UINT32 high = 0, low = 0;
720
721 Unpack2UINT32AsUINT64 (var.uhVal.QuadPart, &high, &low);
722 return g_strdup_printf ("%dx%d", high, low);
723 }
724
725 if (IsEqualGUID (guid, MF_MT_GEOMETRIC_APERTURE) ||
726 IsEqualGUID (guid, MF_MT_MINIMUM_DISPLAY_APERTURE) ||
727 IsEqualGUID (guid, MF_MT_PAN_SCAN_APERTURE)) {
728 /* FIXME: Not our usecase for now */
729 return g_strdup ("Not parsed");
730 }
731
732 switch (var.vt) {
733 case VT_UI4:
734 return g_strdup_printf ("%d", var.ulVal);
735 case VT_UI8:
736 return g_strdup_printf ("%" G_GUINT64_FORMAT, var.uhVal);
737 case VT_R8:
738 return g_strdup_printf ("%f", var.dblVal);
739 case VT_CLSID:
740 return gst_mf_guid_to_string (*var.puuid);
741 case VT_LPWSTR:
742 return g_utf16_to_utf8 ((const gunichar2 *) var.pwszVal,
743 -1, NULL, NULL, NULL);
744 case VT_UNKNOWN:
745 return g_strdup ("IUnknown");
746 default:
747 return g_strdup_printf ("Unhandled type (vt = %d)", var.vt);
748 }
749
750 return NULL;
751 }
752
753 static void
gst_mf_dump_attribute_value_by_index(IMFAttributes * attr,const gchar * msg,guint index,GstDebugLevel level,GstDebugCategory * cat,const gchar * file,const gchar * function,gint line)754 gst_mf_dump_attribute_value_by_index (IMFAttributes * attr, const gchar * msg,
755 guint index, GstDebugLevel level, GstDebugCategory * cat,
756 const gchar * file, const gchar * function, gint line)
757 {
758 gchar *guid_name = NULL;
759 gchar *value = NULL;
760 GUID guid = GUID_NULL;
761 HRESULT hr;
762
763 PROPVARIANT var;
764 PropVariantInit (&var);
765
766 hr = attr->GetItemByIndex (index, &guid, &var);
767 if (!gst_mf_result (hr))
768 goto done;
769
770 guid_name = gst_mf_guid_to_string (guid);
771 if (!guid_name)
772 goto done;
773
774 value = gst_mf_attribute_value_to_string (guid, var);
775 if (!value)
776 goto done;
777
778 gst_debug_log (cat, level, file, function, line,
779 NULL, "%s attribute %d, %s: %s", msg ? msg : "", index, guid_name, value);
780
781 done:
782 PropVariantClear (&var);
783 g_free (guid_name);
784 g_free (value);
785 }
786
787 void
_gst_mf_dump_attributes(IMFAttributes * attr,const gchar * msg,GstDebugLevel level,GstDebugCategory * cat,const gchar * file,const gchar * function,gint line)788 _gst_mf_dump_attributes (IMFAttributes * attr, const gchar * msg,
789 GstDebugLevel level, GstDebugCategory * cat, const gchar * file,
790 const gchar * function, gint line)
791 {
792 #ifndef GST_DISABLE_GST_DEBUG
793 HRESULT hr;
794 UINT32 count = 0, i;
795
796 if (!attr)
797 return;
798
799 hr = attr->GetCount (&count);
800 if (!gst_mf_result (hr) || count == 0)
801 return;
802
803 for (i = 0; i < count; i++) {
804 gst_mf_dump_attribute_value_by_index (attr,
805 msg, i, level, cat, file, function, line);
806 }
807 #endif
808 }
809