gstreamer/sys/mediafoundation/gstmfutils.cpp
Seungha Yang 1a68da54b6 mfvideosrc: Add support for jpeg on Win32 application
Enable reading jpeg data from webcam if it's supported.
Note that this would be enabled only for Win32.
For UWP, we need to research more about how to support jpeg.

Part-of: <https://gitlab.freedesktop.org/gstreamer/gst-plugins-bad/-/merge_requests/1342>
2020-06-17 17:45:32 +09:00

712 lines
No EOL
24 KiB
C++

/* GStreamer
* Copyright (C) 2019 Seungha Yang <seungha.yang@navercorp.com>
* Copyright (C) 2020 Seungha Yang <seungha@centricular.com>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
* Boston, MA 02110-1301, USA.
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include "gstmfconfig.h"
#include "gstmfutils.h"
#include <wrl.h>
using namespace Microsoft::WRL;
G_BEGIN_DECLS
GST_DEBUG_CATEGORY_EXTERN (gst_mf_utils_debug);
#define GST_CAT_DEFAULT gst_mf_utils_debug
G_END_DECLS
#define MAKE_RAW_FORMAT_CAPS(format) \
"video/x-raw, format = (string) " format
/* No GUID is defined for "Y16 " in mfapi.h, but it's used by several devices */
DEFINE_MEDIATYPE_GUID (MFVideoFormat_Y16, FCC ('Y16 '));
static struct
{
const GUID &mf_format;
const gchar *caps_string;
GstVideoFormat format;
} raw_video_format_map[] = {
{MFVideoFormat_RGB32, MAKE_RAW_FORMAT_CAPS ("BGRx"), GST_VIDEO_FORMAT_BGRx},
{MFVideoFormat_ARGB32, MAKE_RAW_FORMAT_CAPS ("BGRA"), GST_VIDEO_FORMAT_BGRA},
{MFVideoFormat_RGB24, MAKE_RAW_FORMAT_CAPS ("BGR"), GST_VIDEO_FORMAT_BGR},
{MFVideoFormat_RGB555, MAKE_RAW_FORMAT_CAPS ("RGB15"), GST_VIDEO_FORMAT_RGB15},
{MFVideoFormat_RGB565, MAKE_RAW_FORMAT_CAPS ("RGB16"), GST_VIDEO_FORMAT_RGB16},
{MFVideoFormat_AYUV, MAKE_RAW_FORMAT_CAPS ("VUYA"), GST_VIDEO_FORMAT_VUYA},
{MFVideoFormat_YUY2, MAKE_RAW_FORMAT_CAPS ("YUY2"), GST_VIDEO_FORMAT_YUY2},
{MFVideoFormat_YVYU, MAKE_RAW_FORMAT_CAPS ("YVYU"), GST_VIDEO_FORMAT_YVYU},
{MFVideoFormat_UYVY, MAKE_RAW_FORMAT_CAPS ("UYVY"), GST_VIDEO_FORMAT_UYVY},
{MFVideoFormat_NV12, MAKE_RAW_FORMAT_CAPS ("NV12"), GST_VIDEO_FORMAT_NV12},
{MFVideoFormat_YV12, MAKE_RAW_FORMAT_CAPS ("YV12"), GST_VIDEO_FORMAT_YV12},
{MFVideoFormat_I420, MAKE_RAW_FORMAT_CAPS ("I420"), GST_VIDEO_FORMAT_I420},
{MFVideoFormat_IYUV, MAKE_RAW_FORMAT_CAPS ("I420"), GST_VIDEO_FORMAT_I420},
{MFVideoFormat_P010, MAKE_RAW_FORMAT_CAPS ("P010"), GST_VIDEO_FORMAT_P010_10LE},
{MFVideoFormat_P016, MAKE_RAW_FORMAT_CAPS ("P016"), GST_VIDEO_FORMAT_P016_LE},
{MFVideoFormat_v210, MAKE_RAW_FORMAT_CAPS ("v210"), GST_VIDEO_FORMAT_v210},
{MFVideoFormat_v216, MAKE_RAW_FORMAT_CAPS ("v216"), GST_VIDEO_FORMAT_v216},
{MFVideoFormat_Y16, MAKE_RAW_FORMAT_CAPS ("GRAY16_LE"), GST_VIDEO_FORMAT_GRAY16_LE},
};
static struct
{
const GUID &mf_format;
const gchar *caps_string;
} encoded_video_format_map[] = {
{MFVideoFormat_H264, "video/x-h264"},
{MFVideoFormat_HEVC, "video/x-h265"},
{MFVideoFormat_H265, "video/x-h265"},
{MFVideoFormat_VP80, "video/x-vp8"},
{MFVideoFormat_VP90, "video/x-vp9"},
{MFVideoFormat_MJPG, "image/jpeg"},
};
GstVideoFormat
gst_mf_video_subtype_to_video_format (const GUID * subtype)
{
gint i;
for (i = 0; i < G_N_ELEMENTS (raw_video_format_map); i++) {
if (IsEqualGUID (raw_video_format_map[i].mf_format, *subtype))
return raw_video_format_map[i].format;
}
return GST_VIDEO_FORMAT_UNKNOWN;
}
const GUID *
gst_mf_video_subtype_from_video_format (GstVideoFormat format)
{
gint i;
for (i = 0; i < G_N_ELEMENTS (raw_video_format_map); i++) {
if (raw_video_format_map[i].format == format)
return &raw_video_format_map[i].mf_format;
}
return NULL;
}
static GstCaps *
gst_mf_media_type_to_video_caps (IMFMediaType * media_type)
{
HRESULT hr;
GstCaps *caps = NULL;
gint i;
guint32 width = 0;
guint32 height = 0;
guint32 num, den;
guint32 val;
gchar *str;
GUID subtype;
GstVideoChromaSite chroma_site;
GstVideoColorimetry colorimetry;
gboolean raw_format = TRUE;
hr = media_type->GetGUID (MF_MT_SUBTYPE, &subtype);
if (FAILED (hr)) {
GST_WARNING ("Failed to get subtype, hr: 0x%x", (guint) hr);
return NULL;
}
for (i = 0; i < G_N_ELEMENTS (raw_video_format_map); i++) {
if (IsEqualGUID (raw_video_format_map[i].mf_format, subtype)) {
caps = gst_caps_from_string (raw_video_format_map[i].caps_string);
break;
}
}
if (!caps) {
for (i = 0; i < G_N_ELEMENTS (encoded_video_format_map); i++) {
if (IsEqualGUID (encoded_video_format_map[i].mf_format, subtype)) {
caps = gst_caps_from_string (encoded_video_format_map[i].caps_string);
raw_format = FALSE;
break;
}
}
}
if (!caps) {
GST_WARNING ("Unknown format %" GST_FOURCC_FORMAT,
GST_FOURCC_ARGS (subtype.Data1));
return NULL;
}
hr = MFGetAttributeSize (media_type, MF_MT_FRAME_SIZE, &width, &height);
if (FAILED (hr) || !width || !height) {
GST_WARNING ("Couldn't get frame size, hr: 0x%x", (guint) hr);
if (raw_format) {
gst_caps_unref (caps);
return NULL;
}
}
if (width > 0 && height > 0) {
gst_caps_set_simple (caps, "width", G_TYPE_INT, width,
"height", G_TYPE_INT, height, NULL);
}
hr = MFGetAttributeRatio (media_type, MF_MT_FRAME_RATE, &num, &den);
if (SUCCEEDED (hr) && num > 0 && den > 0)
gst_caps_set_simple (caps, "framerate", GST_TYPE_FRACTION, num, den, NULL);
hr = MFGetAttributeRatio (media_type, MF_MT_PIXEL_ASPECT_RATIO, &num, &den);
if (SUCCEEDED (hr) && num > 0 && den > 0)
gst_caps_set_simple (caps,
"pixel-aspect-ratio", GST_TYPE_FRACTION, num, den, NULL);
colorimetry.range = GST_VIDEO_COLOR_RANGE_UNKNOWN;
colorimetry.matrix = GST_VIDEO_COLOR_MATRIX_UNKNOWN;
colorimetry.transfer = GST_VIDEO_TRANSFER_UNKNOWN;
colorimetry.primaries = GST_VIDEO_COLOR_PRIMARIES_UNKNOWN;
hr = media_type->GetUINT32 (MF_MT_VIDEO_NOMINAL_RANGE, &val);
if (SUCCEEDED (hr)) {
switch (val) {
case MFNominalRange_0_255:
colorimetry.range = GST_VIDEO_COLOR_RANGE_0_255;
break;
case MFNominalRange_16_235:
colorimetry.range = GST_VIDEO_COLOR_RANGE_16_235;
break;
default:
break;
}
}
hr = media_type->GetUINT32 (MF_MT_VIDEO_PRIMARIES, &val);
if (SUCCEEDED (hr)) {
switch (val) {
case MFVideoPrimaries_BT709:
colorimetry.primaries = GST_VIDEO_COLOR_PRIMARIES_BT709;
break;
case MFVideoPrimaries_BT470_2_SysM:
colorimetry.primaries = GST_VIDEO_COLOR_PRIMARIES_BT470M;
break;
case MFVideoPrimaries_BT470_2_SysBG:
colorimetry.primaries = GST_VIDEO_COLOR_PRIMARIES_BT470BG;
break;
case MFVideoPrimaries_SMPTE170M:
colorimetry.primaries = GST_VIDEO_COLOR_PRIMARIES_SMPTE170M;
break;
case MFVideoPrimaries_SMPTE240M:
colorimetry.primaries = GST_VIDEO_COLOR_PRIMARIES_SMPTE240M;
break;
case MFVideoPrimaries_EBU3213:
colorimetry.primaries = GST_VIDEO_COLOR_PRIMARIES_EBU3213;
break;
case MFVideoPrimaries_BT2020:
colorimetry.primaries = GST_VIDEO_COLOR_PRIMARIES_BT2020;
break;
default:
GST_FIXME ("unhandled color primaries %d", val);
break;
}
}
hr = media_type->GetUINT32 (MF_MT_YUV_MATRIX, &val);
if (SUCCEEDED (hr)) {
switch (val) {
case MFVideoTransferMatrix_BT709:
colorimetry.matrix = GST_VIDEO_COLOR_MATRIX_BT709;
break;
case MFVideoTransferMatrix_BT601:
colorimetry.matrix = GST_VIDEO_COLOR_MATRIX_BT601;
break;
case MFVideoTransferMatrix_SMPTE240M:
colorimetry.matrix = GST_VIDEO_COLOR_MATRIX_SMPTE240M;
break;
case MFVideoTransferMatrix_BT2020_10:
case MFVideoTransferMatrix_BT2020_12:
colorimetry.matrix = GST_VIDEO_COLOR_MATRIX_BT2020;
break;
default:
GST_FIXME ("unhandled color matrix %d", val);
break;
}
}
hr = media_type->GetUINT32 (MF_MT_TRANSFER_FUNCTION, &val);
if (SUCCEEDED (hr)) {
switch (val) {
case MFVideoTransFunc_10:
colorimetry.transfer = GST_VIDEO_TRANSFER_GAMMA10;
break;
case MFVideoTransFunc_18:
colorimetry.transfer = GST_VIDEO_TRANSFER_GAMMA18;
break;
case MFVideoTransFunc_20:
colorimetry.transfer = GST_VIDEO_TRANSFER_GAMMA20;
break;
case MFVideoTransFunc_22:
colorimetry.transfer = GST_VIDEO_TRANSFER_GAMMA22;
break;
case MFVideoTransFunc_709:
case MFVideoTransFunc_709_sym:
colorimetry.transfer = GST_VIDEO_TRANSFER_BT709;
break;
case MFVideoTransFunc_240M:
colorimetry.transfer = GST_VIDEO_TRANSFER_SMPTE240M;
break;
case MFVideoTransFunc_sRGB:
colorimetry.transfer = GST_VIDEO_TRANSFER_SRGB;
break;
case MFVideoTransFunc_28:
colorimetry.transfer = GST_VIDEO_TRANSFER_GAMMA28;
break;
case MFVideoTransFunc_Log_100:
colorimetry.transfer = GST_VIDEO_TRANSFER_LOG100;
break;
case MFVideoTransFunc_Log_316:
colorimetry.transfer = GST_VIDEO_TRANSFER_LOG316;
break;
case MFVideoTransFunc_2020_const:
case MFVideoTransFunc_2020:
colorimetry.transfer = GST_VIDEO_TRANSFER_BT2020_10;
break;
case MFVideoTransFunc_2084:
colorimetry.transfer = GST_VIDEO_TRANSFER_SMPTE2084;
break;
case MFVideoTransFunc_HLG:
colorimetry.transfer = GST_VIDEO_TRANSFER_ARIB_STD_B67;
break;
default:
GST_FIXME ("unhandled color transfer %d", val);
break;
}
}
str = gst_video_colorimetry_to_string (&colorimetry);
if (str) {
gst_caps_set_simple (caps, "colorimetry", G_TYPE_STRING, str, NULL);
g_free (str);
str = NULL;
}
chroma_site = GST_VIDEO_CHROMA_SITE_UNKNOWN;
hr = media_type->GetUINT32 (MF_MT_VIDEO_CHROMA_SITING, &val);
if (SUCCEEDED (hr)) {
GST_LOG ("have chroma site 0x%x", val);
if ((val & MFVideoChromaSubsampling_MPEG2) ==
MFVideoChromaSubsampling_MPEG2) {
chroma_site = GST_VIDEO_CHROMA_SITE_MPEG2;
} else if ((val & MFVideoChromaSubsampling_DV_PAL) ==
MFVideoChromaSubsampling_DV_PAL) {
chroma_site = GST_VIDEO_CHROMA_SITE_DV;
} else if ((val & MFVideoChromaSubsampling_Cosited) ==
MFVideoChromaSubsampling_Cosited) {
chroma_site = GST_VIDEO_CHROMA_SITE_COSITED;
} else {
GST_FIXME ("unhandled chroma site 0x%x", val);
}
}
if (chroma_site != GST_VIDEO_CHROMA_SITE_UNKNOWN)
gst_caps_set_simple (caps, "chroma-site", G_TYPE_STRING,
gst_video_chroma_to_string (chroma_site), NULL);
return caps;
}
GstCaps *
gst_mf_media_type_to_caps (IMFMediaType * media_type)
{
GUID major_type;
HRESULT hr;
g_return_val_if_fail (media_type != NULL, NULL);
hr = media_type->GetMajorType (&major_type);
if (FAILED (hr)) {
GST_WARNING ("failed to get major type, hr: 0x%x", (guint) hr);
return NULL;
}
if (IsEqualGUID (major_type, MFMediaType_Video))
return gst_mf_media_type_to_video_caps (media_type);
return NULL;
}
void
gst_mf_media_type_release (IMFMediaType * media_type)
{
if (media_type)
media_type->Release ();
}
static gchar *
gst_mf_hr_to_string (HRESULT hr)
{
DWORD flags;
gchar *ret_text;
LPTSTR error_text = NULL;
flags = FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_ALLOCATE_BUFFER
| FORMAT_MESSAGE_IGNORE_INSERTS;
FormatMessage (flags, NULL, hr, MAKELANGID (LANG_NEUTRAL, SUBLANG_DEFAULT),
(LPTSTR) & error_text, 0, NULL);
#ifdef UNICODE
ret_text = g_utf16_to_utf8 ((const gunichar2 *) error_text,
-1, NULL, NULL, NULL);
#else
ret_text = g_strdup (error_text);
#endif
LocalFree (error_text);
return ret_text;
}
gboolean
_gst_mf_result (HRESULT hr, GstDebugCategory * cat, const gchar * file,
const gchar * function, gint line)
{
#ifndef GST_DISABLE_GST_DEBUG
gboolean ret = TRUE;
if (FAILED (hr)) {
gchar *error_text = NULL;
error_text = gst_mf_hr_to_string (hr);
gst_debug_log (cat, GST_LEVEL_WARNING, file, function, line,
NULL, "MediaFoundation call failed: 0x%x, %s", (guint) hr, error_text);
g_free (error_text);
ret = FALSE;
}
return ret;
#else
return SUCCEEDED (hr);
#endif
}
/* Reference:
* https://docs.microsoft.com/en-us/windows/win32/medfound/media-type-debugging-code */
#define GST_MF_IF_EQUAL_RETURN(guid,val) G_STMT_START { \
if (IsEqualGUID (guid, val)) \
return G_STRINGIFY (val); \
} G_STMT_END
static const gchar *
gst_mf_guid_to_static_string (const GUID& guid)
{
GST_MF_IF_EQUAL_RETURN(guid, MF_MT_MAJOR_TYPE);
GST_MF_IF_EQUAL_RETURN(guid, MF_MT_MAJOR_TYPE);
GST_MF_IF_EQUAL_RETURN(guid, MF_MT_SUBTYPE);
GST_MF_IF_EQUAL_RETURN(guid, MF_MT_ALL_SAMPLES_INDEPENDENT);
GST_MF_IF_EQUAL_RETURN(guid, MF_MT_FIXED_SIZE_SAMPLES);
GST_MF_IF_EQUAL_RETURN(guid, MF_MT_COMPRESSED);
GST_MF_IF_EQUAL_RETURN(guid, MF_MT_SAMPLE_SIZE);
GST_MF_IF_EQUAL_RETURN(guid, MF_MT_WRAPPED_TYPE);
GST_MF_IF_EQUAL_RETURN(guid, MF_MT_AUDIO_NUM_CHANNELS);
GST_MF_IF_EQUAL_RETURN(guid, MF_MT_AUDIO_SAMPLES_PER_SECOND);
GST_MF_IF_EQUAL_RETURN(guid, MF_MT_AUDIO_FLOAT_SAMPLES_PER_SECOND);
GST_MF_IF_EQUAL_RETURN(guid, MF_MT_AUDIO_AVG_BYTES_PER_SECOND);
GST_MF_IF_EQUAL_RETURN(guid, MF_MT_AUDIO_BLOCK_ALIGNMENT);
GST_MF_IF_EQUAL_RETURN(guid, MF_MT_AUDIO_BITS_PER_SAMPLE);
GST_MF_IF_EQUAL_RETURN(guid, MF_MT_AUDIO_VALID_BITS_PER_SAMPLE);
GST_MF_IF_EQUAL_RETURN(guid, MF_MT_AUDIO_SAMPLES_PER_BLOCK);
GST_MF_IF_EQUAL_RETURN(guid, MF_MT_AUDIO_CHANNEL_MASK);
GST_MF_IF_EQUAL_RETURN(guid, MF_MT_AUDIO_FOLDDOWN_MATRIX);
GST_MF_IF_EQUAL_RETURN(guid, MF_MT_AUDIO_WMADRC_PEAKREF);
GST_MF_IF_EQUAL_RETURN(guid, MF_MT_AUDIO_WMADRC_PEAKTARGET);
GST_MF_IF_EQUAL_RETURN(guid, MF_MT_AUDIO_WMADRC_AVGREF);
GST_MF_IF_EQUAL_RETURN(guid, MF_MT_AUDIO_WMADRC_AVGTARGET);
GST_MF_IF_EQUAL_RETURN(guid, MF_MT_AUDIO_PREFER_WAVEFORMATEX);
GST_MF_IF_EQUAL_RETURN(guid, MF_MT_AAC_PAYLOAD_TYPE);
GST_MF_IF_EQUAL_RETURN(guid, MF_MT_AAC_AUDIO_PROFILE_LEVEL_INDICATION);
GST_MF_IF_EQUAL_RETURN(guid, MF_MT_FRAME_SIZE);
GST_MF_IF_EQUAL_RETURN(guid, MF_MT_FRAME_RATE);
GST_MF_IF_EQUAL_RETURN(guid, MF_MT_FRAME_RATE_RANGE_MAX);
GST_MF_IF_EQUAL_RETURN(guid, MF_MT_FRAME_RATE_RANGE_MIN);
GST_MF_IF_EQUAL_RETURN(guid, MF_MT_PIXEL_ASPECT_RATIO);
GST_MF_IF_EQUAL_RETURN(guid, MF_MT_DRM_FLAGS);
GST_MF_IF_EQUAL_RETURN(guid, MF_MT_PAD_CONTROL_FLAGS);
GST_MF_IF_EQUAL_RETURN(guid, MF_MT_SOURCE_CONTENT_HINT);
GST_MF_IF_EQUAL_RETURN(guid, MF_MT_VIDEO_CHROMA_SITING);
GST_MF_IF_EQUAL_RETURN(guid, MF_MT_INTERLACE_MODE);
GST_MF_IF_EQUAL_RETURN(guid, MF_MT_TRANSFER_FUNCTION);
GST_MF_IF_EQUAL_RETURN(guid, MF_MT_VIDEO_PRIMARIES);
GST_MF_IF_EQUAL_RETURN(guid, MF_MT_YUV_MATRIX);
GST_MF_IF_EQUAL_RETURN(guid, MF_MT_VIDEO_LIGHTING);
GST_MF_IF_EQUAL_RETURN(guid, MF_MT_VIDEO_NOMINAL_RANGE);
GST_MF_IF_EQUAL_RETURN(guid, MF_MT_GEOMETRIC_APERTURE);
GST_MF_IF_EQUAL_RETURN(guid, MF_MT_MINIMUM_DISPLAY_APERTURE);
GST_MF_IF_EQUAL_RETURN(guid, MF_MT_PAN_SCAN_APERTURE);
GST_MF_IF_EQUAL_RETURN(guid, MF_MT_PAN_SCAN_ENABLED);
GST_MF_IF_EQUAL_RETURN(guid, MF_MT_AVG_BITRATE);
GST_MF_IF_EQUAL_RETURN(guid, MF_MT_AVG_BIT_ERROR_RATE);
GST_MF_IF_EQUAL_RETURN(guid, MF_MT_MAX_KEYFRAME_SPACING);
GST_MF_IF_EQUAL_RETURN(guid, MF_MT_DEFAULT_STRIDE);
GST_MF_IF_EQUAL_RETURN(guid, MF_MT_PALETTE);
GST_MF_IF_EQUAL_RETURN(guid, MF_MT_USER_DATA);
GST_MF_IF_EQUAL_RETURN(guid, MF_MT_MPEG_START_TIME_CODE);
GST_MF_IF_EQUAL_RETURN(guid, MF_MT_MPEG2_PROFILE);
GST_MF_IF_EQUAL_RETURN(guid, MF_MT_MPEG2_LEVEL);
GST_MF_IF_EQUAL_RETURN(guid, MF_MT_MPEG2_FLAGS);
GST_MF_IF_EQUAL_RETURN(guid, MF_MT_MPEG_SEQUENCE_HEADER);
GST_MF_IF_EQUAL_RETURN(guid, MF_MT_DV_AAUX_SRC_PACK_0);
GST_MF_IF_EQUAL_RETURN(guid, MF_MT_DV_AAUX_CTRL_PACK_0);
GST_MF_IF_EQUAL_RETURN(guid, MF_MT_DV_AAUX_SRC_PACK_1);
GST_MF_IF_EQUAL_RETURN(guid, MF_MT_DV_AAUX_CTRL_PACK_1);
GST_MF_IF_EQUAL_RETURN(guid, MF_MT_DV_VAUX_SRC_PACK);
GST_MF_IF_EQUAL_RETURN(guid, MF_MT_DV_VAUX_CTRL_PACK);
GST_MF_IF_EQUAL_RETURN(guid, MF_MT_IMAGE_LOSS_TOLERANT);
GST_MF_IF_EQUAL_RETURN(guid, MF_MT_MPEG4_SAMPLE_DESCRIPTION);
GST_MF_IF_EQUAL_RETURN(guid, MF_MT_MPEG4_CURRENT_SAMPLE_ENTRY);
GST_MF_IF_EQUAL_RETURN(guid, MFMediaType_Audio);
GST_MF_IF_EQUAL_RETURN(guid, MFMediaType_Video);
GST_MF_IF_EQUAL_RETURN(guid, MFMediaType_Protected);
GST_MF_IF_EQUAL_RETURN(guid, MFMediaType_SAMI);
GST_MF_IF_EQUAL_RETURN(guid, MFMediaType_Script);
GST_MF_IF_EQUAL_RETURN(guid, MFMediaType_Image);
GST_MF_IF_EQUAL_RETURN(guid, MFMediaType_HTML);
GST_MF_IF_EQUAL_RETURN(guid, MFMediaType_Binary);
GST_MF_IF_EQUAL_RETURN(guid, MFMediaType_FileTransfer);
GST_MF_IF_EQUAL_RETURN(guid, MFVideoFormat_AI44);
GST_MF_IF_EQUAL_RETURN(guid, MFVideoFormat_ARGB32);
GST_MF_IF_EQUAL_RETURN(guid, MFVideoFormat_AYUV);
GST_MF_IF_EQUAL_RETURN(guid, MFVideoFormat_DV25);
GST_MF_IF_EQUAL_RETURN(guid, MFVideoFormat_DV50);
GST_MF_IF_EQUAL_RETURN(guid, MFVideoFormat_DVH1);
GST_MF_IF_EQUAL_RETURN(guid, MFVideoFormat_DVSD);
GST_MF_IF_EQUAL_RETURN(guid, MFVideoFormat_DVSL);
GST_MF_IF_EQUAL_RETURN(guid, MFVideoFormat_H264);
GST_MF_IF_EQUAL_RETURN(guid, MFVideoFormat_H265);
GST_MF_IF_EQUAL_RETURN(guid, MFVideoFormat_HEVC);
GST_MF_IF_EQUAL_RETURN(guid, MFVideoFormat_HEVC_ES);
GST_MF_IF_EQUAL_RETURN(guid, MFVideoFormat_I420);
GST_MF_IF_EQUAL_RETURN(guid, MFVideoFormat_IYUV);
GST_MF_IF_EQUAL_RETURN(guid, MFVideoFormat_M4S2);
GST_MF_IF_EQUAL_RETURN(guid, MFVideoFormat_MJPG);
GST_MF_IF_EQUAL_RETURN(guid, MFVideoFormat_MP43);
GST_MF_IF_EQUAL_RETURN(guid, MFVideoFormat_MP4S);
GST_MF_IF_EQUAL_RETURN(guid, MFVideoFormat_MP4V);
GST_MF_IF_EQUAL_RETURN(guid, MFVideoFormat_MPG1);
GST_MF_IF_EQUAL_RETURN(guid, MFVideoFormat_MSS1);
GST_MF_IF_EQUAL_RETURN(guid, MFVideoFormat_MSS2);
GST_MF_IF_EQUAL_RETURN(guid, MFVideoFormat_NV11);
GST_MF_IF_EQUAL_RETURN(guid, MFVideoFormat_NV12);
GST_MF_IF_EQUAL_RETURN(guid, MFVideoFormat_P010);
GST_MF_IF_EQUAL_RETURN(guid, MFVideoFormat_P016);
GST_MF_IF_EQUAL_RETURN(guid, MFVideoFormat_P210);
GST_MF_IF_EQUAL_RETURN(guid, MFVideoFormat_P216);
GST_MF_IF_EQUAL_RETURN(guid, MFVideoFormat_RGB24);
GST_MF_IF_EQUAL_RETURN(guid, MFVideoFormat_RGB32);
GST_MF_IF_EQUAL_RETURN(guid, MFVideoFormat_RGB555);
GST_MF_IF_EQUAL_RETURN(guid, MFVideoFormat_RGB565);
GST_MF_IF_EQUAL_RETURN(guid, MFVideoFormat_RGB8);
GST_MF_IF_EQUAL_RETURN(guid, MFVideoFormat_UYVY);
GST_MF_IF_EQUAL_RETURN(guid, MFVideoFormat_v210);
GST_MF_IF_EQUAL_RETURN(guid, MFVideoFormat_v410);
GST_MF_IF_EQUAL_RETURN(guid, MFVideoFormat_VP80);
GST_MF_IF_EQUAL_RETURN(guid, MFVideoFormat_VP90);
GST_MF_IF_EQUAL_RETURN(guid, MFVideoFormat_WMV1);
GST_MF_IF_EQUAL_RETURN(guid, MFVideoFormat_WMV2);
GST_MF_IF_EQUAL_RETURN(guid, MFVideoFormat_WMV3);
GST_MF_IF_EQUAL_RETURN(guid, MFVideoFormat_WVC1);
GST_MF_IF_EQUAL_RETURN(guid, MFVideoFormat_Y210);
GST_MF_IF_EQUAL_RETURN(guid, MFVideoFormat_Y216);
GST_MF_IF_EQUAL_RETURN(guid, MFVideoFormat_Y410);
GST_MF_IF_EQUAL_RETURN(guid, MFVideoFormat_Y416);
GST_MF_IF_EQUAL_RETURN(guid, MFVideoFormat_Y41P);
GST_MF_IF_EQUAL_RETURN(guid, MFVideoFormat_Y41T);
GST_MF_IF_EQUAL_RETURN(guid, MFVideoFormat_YUY2);
GST_MF_IF_EQUAL_RETURN(guid, MFVideoFormat_YV12);
GST_MF_IF_EQUAL_RETURN(guid, MFVideoFormat_YVYU);
/* WAVE_FORMAT_PCM */
GST_MF_IF_EQUAL_RETURN(guid, MFAudioFormat_PCM);
/* WAVE_FORMAT_IEEE_FLOAT */
GST_MF_IF_EQUAL_RETURN(guid, MFAudioFormat_Float);
/* WAVE_FORMAT_DTS */
GST_MF_IF_EQUAL_RETURN(guid, MFAudioFormat_DTS);
/* WAVE_FORMAT_DOLBY_AC3_SPDIF */
GST_MF_IF_EQUAL_RETURN(guid, MFAudioFormat_Dolby_AC3_SPDIF);
/* WAVE_FORMAT_DRM */
GST_MF_IF_EQUAL_RETURN(guid, MFAudioFormat_DRM);
/* WAVE_FORMAT_WMAUDIO2 */
GST_MF_IF_EQUAL_RETURN(guid, MFAudioFormat_WMAudioV8);
/* WAVE_FORMAT_WMAUDIO3 */
GST_MF_IF_EQUAL_RETURN(guid, MFAudioFormat_WMAudioV9);
/* WAVE_FORMAT_WMAUDIO_LOSSLESS */
GST_MF_IF_EQUAL_RETURN(guid, MFAudioFormat_WMAudio_Lossless);
/* WAVE_FORMAT_WMASPDIF */
GST_MF_IF_EQUAL_RETURN(guid, MFAudioFormat_WMASPDIF);
/* WAVE_FORMAT_WMAVOICE9 */
GST_MF_IF_EQUAL_RETURN(guid, MFAudioFormat_MSP1);
/* WAVE_FORMAT_MPEGLAYER3 */
GST_MF_IF_EQUAL_RETURN(guid, MFAudioFormat_MP3);
/* WAVE_FORMAT_MPEG */
GST_MF_IF_EQUAL_RETURN(guid, MFAudioFormat_MPEG);
/* WAVE_FORMAT_MPEG_HEAAC */
GST_MF_IF_EQUAL_RETURN(guid, MFAudioFormat_AAC);
/* WAVE_FORMAT_MPEG_ADTS_AAC */
GST_MF_IF_EQUAL_RETURN(guid, MFAudioFormat_ADTS);
#if !GST_MF_WINAPI_ONLY_APP
GST_MF_IF_EQUAL_RETURN(guid, MF_MT_CUSTOM_VIDEO_PRIMARIES);
GST_MF_IF_EQUAL_RETURN(guid, MF_MT_AM_FORMAT_TYPE);
GST_MF_IF_EQUAL_RETURN(guid, MF_MT_ARBITRARY_HEADER);
GST_MF_IF_EQUAL_RETURN(guid, MF_MT_ARBITRARY_FORMAT);
GST_MF_IF_EQUAL_RETURN(guid, MF_MT_ORIGINAL_4CC);
GST_MF_IF_EQUAL_RETURN(guid, MF_MT_ORIGINAL_WAVE_FORMAT_TAG);
#endif
return NULL;
}
static gchar *
gst_mf_guid_to_string (const GUID& guid)
{
const gchar *str = NULL;
HRESULT hr;
WCHAR *name = NULL;
gchar *ret = NULL;
str = gst_mf_guid_to_static_string (guid);
if (str)
return g_strdup (str);
hr = StringFromCLSID (guid, &name);
if (gst_mf_result (hr) && name) {
ret = g_utf16_to_utf8 ((const gunichar2 *) name, -1, NULL, NULL, NULL);
CoTaskMemFree (name);
if (ret)
return ret;
}
ret = g_strdup_printf
("%8.8x-%4.4x-%4.4x-%2.2x%2.2x-%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x",
(guint) guid.Data1, (guint) guid.Data2, (guint) guid.Data3,
guid.Data4[0], guid.Data4[1], guid.Data4[2], guid.Data4[3],
guid.Data4[4], guid.Data4[5], guid.Data4[6], guid.Data4[7]);
return ret;
}
static gchar *
gst_mf_attribute_value_to_string (const GUID& guid, const PROPVARIANT& var)
{
if (IsEqualGUID (guid, MF_MT_FRAME_RATE) ||
IsEqualGUID (guid, MF_MT_FRAME_RATE_RANGE_MAX) ||
IsEqualGUID (guid, MF_MT_FRAME_RATE_RANGE_MIN) ||
IsEqualGUID (guid, MF_MT_FRAME_SIZE) ||
IsEqualGUID (guid, MF_MT_PIXEL_ASPECT_RATIO)) {
UINT32 high = 0, low = 0;
Unpack2UINT32AsUINT64(var.uhVal.QuadPart, &high, &low);
return g_strdup_printf ("%dx%d", high, low);
}
if (IsEqualGUID (guid, MF_MT_GEOMETRIC_APERTURE) ||
IsEqualGUID (guid, MF_MT_MINIMUM_DISPLAY_APERTURE) ||
IsEqualGUID (guid, MF_MT_PAN_SCAN_APERTURE)) {
/* FIXME: Not our usecase for now */
return g_strup ("Not parsed");
}
switch (var.vt) {
case VT_UI4:
return g_strdup_printf ("%d", var.ulVal);
case VT_UI8:
return g_strdup_printf ("%" G_GUINT64_FORMAT, var.uhVal);
case VT_R8:
return g_strdup_printf ("%f", var.dblVal);
case VT_CLSID:
return gst_mf_guid_to_string (*var.puuid);
case VT_LPWSTR:
return g_utf16_to_utf8 ((const gunichar2 *) var.pwszVal,
-1, NULL, NULL, NULL);
case VT_UNKNOWN:
return g_strdup ("IUnknown");
default:
return g_strdup_printf ("Unhandled type (vt = %d)", var.vt);
}
return NULL;
}
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)
{
gchar *guid_name = NULL;
gchar *value = NULL;
GUID guid = GUID_NULL;
HRESULT hr;
PROPVARIANT var;
PropVariantInit(&var);
hr = attr->GetItemByIndex(index, &guid, &var);
if (!gst_mf_result (hr))
goto done;
guid_name = gst_mf_guid_to_string (guid);
if (!guid_name)
goto done;
value = gst_mf_attribute_value_to_string (guid, var);
if (!value)
goto done;
gst_debug_log (cat, level, file, function, line,
NULL, "%s attribute %d, %s: %s", msg ? msg : "", index, guid_name,
value);
done:
PropVariantClear(&var);
g_free (guid_name);
g_free (value);
}
void
_gst_mf_dump_attributes (IMFAttributes * attr, const gchar * msg,
GstDebugLevel level, GstDebugCategory * cat, const gchar * file,
const gchar * function, gint line)
{
#ifndef GST_DISABLE_GST_DEBUG
HRESULT hr;
UINT32 count = 0, i;
if (!attr)
return;
hr = attr->GetCount (&count);
if (!gst_mf_result (hr) || count == 0)
return;
for (i = 0; i < count; i++) {
gst_mf_dump_attribute_value_by_index (attr,
msg, i, level, cat, file, function, line);
}
#endif
}