mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-12-22 16:26:39 +00:00
be957f6c61
See also https://docs.microsoft.com/en-us/windows/win32/medfound/aac-decoder Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/1596>
1003 lines
34 KiB
C++
1003 lines
34 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>
|
|
|
|
/* *INDENT-OFF* */
|
|
using namespace Microsoft::WRL;
|
|
|
|
GST_DEBUG_CATEGORY_EXTERN (gst_mf_utils_debug);
|
|
#define GST_CAT_DEFAULT gst_mf_utils_debug
|
|
|
|
#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[] = {
|
|
/* NOTE: when adding new format, gst_mf_update_video_info_with_stride() must
|
|
* be updated as well */
|
|
{MFVideoFormat_RGB32, MAKE_RAW_FORMAT_CAPS ("BGRx"), GST_VIDEO_FORMAT_BGRx},
|
|
{MFVideoFormat_ARGB32, MAKE_RAW_FORMAT_CAPS ("BGRA"), GST_VIDEO_FORMAT_BGRA},
|
|
{MFVideoFormat_RGB565, MAKE_RAW_FORMAT_CAPS ("RGB16"), GST_VIDEO_FORMAT_RGB16},
|
|
{MFVideoFormat_RGB555, MAKE_RAW_FORMAT_CAPS ("RGB15"), GST_VIDEO_FORMAT_RGB15},
|
|
{MFVideoFormat_RGB24, MAKE_RAW_FORMAT_CAPS ("BGR"), GST_VIDEO_FORMAT_BGR},
|
|
|
|
/* packed YUV */
|
|
{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_AYUV, MAKE_RAW_FORMAT_CAPS ("VUYA"), GST_VIDEO_FORMAT_VUYA},
|
|
|
|
/* semi-planar */
|
|
{MFVideoFormat_NV12, MAKE_RAW_FORMAT_CAPS ("NV12"), GST_VIDEO_FORMAT_NV12},
|
|
{MFVideoFormat_P010, MAKE_RAW_FORMAT_CAPS ("P010_10LE"), GST_VIDEO_FORMAT_P010_10LE},
|
|
{MFVideoFormat_P016, MAKE_RAW_FORMAT_CAPS ("P016_LE"), GST_VIDEO_FORMAT_P016_LE},
|
|
|
|
/* planar */
|
|
{MFVideoFormat_I420, MAKE_RAW_FORMAT_CAPS ("I420"), GST_VIDEO_FORMAT_I420},
|
|
{MFVideoFormat_IYUV, MAKE_RAW_FORMAT_CAPS ("I420"), GST_VIDEO_FORMAT_I420},
|
|
{MFVideoFormat_YV12, MAKE_RAW_FORMAT_CAPS ("YV12"), GST_VIDEO_FORMAT_YV12},
|
|
|
|
/* complex format */
|
|
{MFVideoFormat_v210, MAKE_RAW_FORMAT_CAPS ("v210"), GST_VIDEO_FORMAT_v210},
|
|
{MFVideoFormat_v216, MAKE_RAW_FORMAT_CAPS ("v216"), GST_VIDEO_FORMAT_v216},
|
|
|
|
/* gray */
|
|
{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"},
|
|
};
|
|
/* *INDENT-ON* */
|
|
|
|
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 nullptr;
|
|
}
|
|
|
|
static GstCaps *
|
|
gst_mf_media_type_to_video_caps (IMFMediaType * media_type)
|
|
{
|
|
HRESULT hr;
|
|
GstCaps *caps = nullptr;
|
|
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 nullptr;
|
|
}
|
|
|
|
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 nullptr;
|
|
}
|
|
|
|
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 nullptr;
|
|
}
|
|
}
|
|
|
|
if (width > 0 && height > 0) {
|
|
gst_caps_set_simple (caps, "width", G_TYPE_INT, width,
|
|
"height", G_TYPE_INT, height, nullptr);
|
|
}
|
|
|
|
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,
|
|
nullptr);
|
|
|
|
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, nullptr);
|
|
|
|
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, nullptr);
|
|
g_free (str);
|
|
str = nullptr;
|
|
}
|
|
|
|
chroma_site = GST_VIDEO_CHROMA_SITE_UNKNOWN;
|
|
|
|
hr = media_type->GetUINT32 (MF_MT_VIDEO_CHROMA_SITING, &val);
|
|
if (SUCCEEDED (hr)) {
|
|
gboolean known_value = TRUE;
|
|
|
|
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 {
|
|
known_value = FALSE;
|
|
}
|
|
|
|
GST_LOG ("have %s chroma site value 0x%x",
|
|
known_value ? "known" : "unknown", 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), nullptr);
|
|
|
|
return caps;
|
|
}
|
|
|
|
/* Desktop only defines */
|
|
#ifndef KSAUDIO_SPEAKER_MONO
|
|
#define KSAUDIO_SPEAKER_MONO (SPEAKER_FRONT_CENTER)
|
|
#endif
|
|
#ifndef KSAUDIO_SPEAKER_1POINT1
|
|
#define KSAUDIO_SPEAKER_1POINT1 (SPEAKER_FRONT_CENTER | SPEAKER_LOW_FREQUENCY)
|
|
#endif
|
|
#ifndef KSAUDIO_SPEAKER_STEREO
|
|
#define KSAUDIO_SPEAKER_STEREO (SPEAKER_FRONT_LEFT | SPEAKER_FRONT_RIGHT)
|
|
#endif
|
|
#ifndef KSAUDIO_SPEAKER_2POINT1
|
|
#define KSAUDIO_SPEAKER_2POINT1 (SPEAKER_FRONT_LEFT | SPEAKER_FRONT_RIGHT | SPEAKER_LOW_FREQUENCY)
|
|
#endif
|
|
#ifndef KSAUDIO_SPEAKER_3POINT0
|
|
#define KSAUDIO_SPEAKER_3POINT0 (SPEAKER_FRONT_LEFT | SPEAKER_FRONT_RIGHT | SPEAKER_FRONT_CENTER)
|
|
#endif
|
|
#ifndef KSAUDIO_SPEAKER_3POINT1
|
|
#define KSAUDIO_SPEAKER_3POINT1 (SPEAKER_FRONT_LEFT | SPEAKER_FRONT_RIGHT | \
|
|
SPEAKER_FRONT_CENTER | SPEAKER_LOW_FREQUENCY)
|
|
#endif
|
|
#ifndef KSAUDIO_SPEAKER_QUAD
|
|
#define KSAUDIO_SPEAKER_QUAD (SPEAKER_FRONT_LEFT | SPEAKER_FRONT_RIGHT | \
|
|
SPEAKER_BACK_LEFT | SPEAKER_BACK_RIGHT)
|
|
#endif
|
|
#define KSAUDIO_SPEAKER_SURROUND (SPEAKER_FRONT_LEFT | SPEAKER_FRONT_RIGHT | \
|
|
SPEAKER_FRONT_CENTER | SPEAKER_BACK_CENTER)
|
|
#ifndef KSAUDIO_SPEAKER_5POINT0
|
|
#define KSAUDIO_SPEAKER_5POINT0 (SPEAKER_FRONT_LEFT | SPEAKER_FRONT_RIGHT | SPEAKER_FRONT_CENTER | \
|
|
SPEAKER_SIDE_LEFT | SPEAKER_SIDE_RIGHT)
|
|
#endif
|
|
#define KSAUDIO_SPEAKER_5POINT1 (SPEAKER_FRONT_LEFT | SPEAKER_FRONT_RIGHT | \
|
|
SPEAKER_FRONT_CENTER | SPEAKER_LOW_FREQUENCY | \
|
|
SPEAKER_BACK_LEFT | SPEAKER_BACK_RIGHT)
|
|
#ifndef KSAUDIO_SPEAKER_7POINT0
|
|
#define KSAUDIO_SPEAKER_7POINT0 (SPEAKER_FRONT_LEFT | SPEAKER_FRONT_RIGHT | SPEAKER_FRONT_CENTER | \
|
|
SPEAKER_BACK_LEFT | SPEAKER_BACK_RIGHT | \
|
|
SPEAKER_SIDE_LEFT | SPEAKER_SIDE_RIGHT)
|
|
#endif
|
|
#ifndef KSAUDIO_SPEAKER_7POINT1
|
|
#define KSAUDIO_SPEAKER_7POINT1 (SPEAKER_FRONT_LEFT | SPEAKER_FRONT_RIGHT | \
|
|
SPEAKER_FRONT_CENTER | SPEAKER_LOW_FREQUENCY | \
|
|
SPEAKER_BACK_LEFT | SPEAKER_BACK_RIGHT | \
|
|
SPEAKER_FRONT_LEFT_OF_CENTER | SPEAKER_FRONT_RIGHT_OF_CENTER)
|
|
#endif
|
|
|
|
static struct
|
|
{
|
|
guint64 mf_pos;
|
|
GstAudioChannelPosition gst_pos;
|
|
} mf_to_gst_pos[] = {
|
|
{SPEAKER_FRONT_LEFT, GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT},
|
|
{SPEAKER_FRONT_RIGHT, GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT},
|
|
{SPEAKER_FRONT_CENTER, GST_AUDIO_CHANNEL_POSITION_FRONT_CENTER},
|
|
{SPEAKER_LOW_FREQUENCY, GST_AUDIO_CHANNEL_POSITION_LFE1},
|
|
{SPEAKER_BACK_LEFT, GST_AUDIO_CHANNEL_POSITION_REAR_LEFT},
|
|
{SPEAKER_BACK_RIGHT, GST_AUDIO_CHANNEL_POSITION_REAR_RIGHT},
|
|
{SPEAKER_FRONT_LEFT_OF_CENTER,
|
|
GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT_OF_CENTER},
|
|
{SPEAKER_FRONT_RIGHT_OF_CENTER,
|
|
GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT_OF_CENTER},
|
|
{SPEAKER_BACK_CENTER, GST_AUDIO_CHANNEL_POSITION_REAR_CENTER},
|
|
/* Enum values diverge from this point onwards */
|
|
{SPEAKER_SIDE_LEFT, GST_AUDIO_CHANNEL_POSITION_SIDE_LEFT},
|
|
{SPEAKER_SIDE_RIGHT, GST_AUDIO_CHANNEL_POSITION_SIDE_RIGHT},
|
|
{SPEAKER_TOP_CENTER, GST_AUDIO_CHANNEL_POSITION_TOP_CENTER},
|
|
{SPEAKER_TOP_FRONT_LEFT, GST_AUDIO_CHANNEL_POSITION_TOP_FRONT_LEFT},
|
|
{SPEAKER_TOP_FRONT_CENTER, GST_AUDIO_CHANNEL_POSITION_TOP_FRONT_CENTER},
|
|
{SPEAKER_TOP_FRONT_RIGHT, GST_AUDIO_CHANNEL_POSITION_TOP_FRONT_RIGHT},
|
|
{SPEAKER_TOP_BACK_LEFT, GST_AUDIO_CHANNEL_POSITION_TOP_REAR_LEFT},
|
|
{SPEAKER_TOP_BACK_CENTER, GST_AUDIO_CHANNEL_POSITION_TOP_REAR_CENTER},
|
|
{SPEAKER_TOP_BACK_RIGHT, GST_AUDIO_CHANNEL_POSITION_TOP_REAR_RIGHT}
|
|
};
|
|
|
|
/* *INDENT-OFF* */
|
|
static DWORD default_ch_masks[] = {
|
|
0,
|
|
KSAUDIO_SPEAKER_MONO,
|
|
/* 2ch */
|
|
KSAUDIO_SPEAKER_STEREO,
|
|
/* 2.1ch */
|
|
/* KSAUDIO_SPEAKER_3POINT0 ? */
|
|
KSAUDIO_SPEAKER_2POINT1,
|
|
/* 4ch */
|
|
/* KSAUDIO_SPEAKER_3POINT1 or KSAUDIO_SPEAKER_SURROUND ? */
|
|
KSAUDIO_SPEAKER_QUAD,
|
|
/* 5ch */
|
|
KSAUDIO_SPEAKER_5POINT0,
|
|
/* 5.1ch */
|
|
KSAUDIO_SPEAKER_5POINT1,
|
|
/* 7ch */
|
|
KSAUDIO_SPEAKER_7POINT0,
|
|
/* 7.1ch */
|
|
KSAUDIO_SPEAKER_7POINT1,
|
|
};
|
|
/* *INDENT-ON* */
|
|
|
|
static void
|
|
gst_mf_media_audio_channel_mask_to_position (guint channels, DWORD mask,
|
|
GstAudioChannelPosition * position)
|
|
{
|
|
guint i, ch;
|
|
|
|
for (i = 0, ch = 0; i < G_N_ELEMENTS (mf_to_gst_pos) && ch < channels; i++) {
|
|
if ((mask & mf_to_gst_pos[i].mf_pos) == 0)
|
|
continue;
|
|
|
|
position[ch] = mf_to_gst_pos[i].gst_pos;
|
|
ch++;
|
|
}
|
|
}
|
|
|
|
static GstCaps *
|
|
gst_mf_media_type_to_audio_caps (IMFMediaType * media_type)
|
|
{
|
|
GUID subtype;
|
|
HRESULT hr;
|
|
UINT32 bps;
|
|
GstAudioFormat format = GST_AUDIO_FORMAT_UNKNOWN;
|
|
GstAudioInfo info;
|
|
UINT32 rate, channels, mask;
|
|
GstAudioChannelPosition position[64];
|
|
|
|
hr = media_type->GetGUID (MF_MT_SUBTYPE, &subtype);
|
|
if (FAILED (hr)) {
|
|
GST_WARNING ("failed to get subtype, hr: 0x%x", (guint) hr);
|
|
return nullptr;
|
|
}
|
|
|
|
if (!IsEqualGUID (subtype, MFAudioFormat_PCM) &&
|
|
!IsEqualGUID (subtype, MFAudioFormat_Float)) {
|
|
GST_FIXME ("Unknown subtype");
|
|
return nullptr;
|
|
}
|
|
|
|
hr = media_type->GetUINT32 (MF_MT_AUDIO_BITS_PER_SAMPLE, &bps);
|
|
if (FAILED (hr)) {
|
|
GST_WARNING ("Failed to get bps, hr: 0x%x", (guint) hr);
|
|
return nullptr;
|
|
}
|
|
|
|
if (IsEqualGUID (subtype, MFAudioFormat_PCM)) {
|
|
format = gst_audio_format_build_integer (TRUE, G_LITTLE_ENDIAN, bps, bps);
|
|
} else if (bps == 32) {
|
|
format = GST_AUDIO_FORMAT_F32LE;
|
|
} else if (bps == 64) {
|
|
format = GST_AUDIO_FORMAT_F64LE;
|
|
}
|
|
|
|
if (format == GST_AUDIO_FORMAT_UNKNOWN) {
|
|
GST_WARNING ("Unknown audio format");
|
|
return nullptr;
|
|
}
|
|
|
|
hr = media_type->GetUINT32 (MF_MT_AUDIO_NUM_CHANNELS, &channels);
|
|
if (FAILED (hr) || channels == 0) {
|
|
GST_WARNING ("Unknown channels");
|
|
return nullptr;
|
|
}
|
|
|
|
hr = media_type->GetUINT32 (MF_MT_AUDIO_SAMPLES_PER_SECOND, &rate);
|
|
if (FAILED (hr) || rate == 0) {
|
|
GST_WARNING ("Unknown rate");
|
|
return nullptr;
|
|
}
|
|
|
|
for (guint i = 0; i < G_N_ELEMENTS (position); i++)
|
|
position[i] = GST_AUDIO_CHANNEL_POSITION_NONE;
|
|
|
|
hr = media_type->GetUINT32 (MF_MT_AUDIO_CHANNEL_MASK, &mask);
|
|
if (FAILED (hr)) {
|
|
if (channels == 1) {
|
|
position[0] = GST_AUDIO_CHANNEL_POSITION_MONO;
|
|
} else if (channels == 2) {
|
|
position[0] = GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT;
|
|
position[1] = GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT;
|
|
} else if (channels <= 8) {
|
|
GST_WARNING ("Unknown channel position, use default value");
|
|
gst_mf_media_audio_channel_mask_to_position (channels,
|
|
default_ch_masks[channels], position);
|
|
} else {
|
|
GST_WARNING ("Failed to determine channel position");
|
|
return nullptr;
|
|
}
|
|
} else {
|
|
gst_mf_media_audio_channel_mask_to_position (channels, mask, position);
|
|
}
|
|
|
|
gst_audio_info_set_format (&info, format, rate, channels, position);
|
|
|
|
return gst_audio_info_to_caps (&info);
|
|
}
|
|
|
|
GstCaps *
|
|
gst_mf_media_type_to_caps (IMFMediaType * media_type)
|
|
{
|
|
GUID major_type;
|
|
HRESULT hr;
|
|
|
|
g_return_val_if_fail (media_type != nullptr, nullptr);
|
|
|
|
hr = media_type->GetMajorType (&major_type);
|
|
if (FAILED (hr)) {
|
|
GST_WARNING ("failed to get major type, hr: 0x%x", (guint) hr);
|
|
return nullptr;
|
|
}
|
|
|
|
if (IsEqualGUID (major_type, MFMediaType_Video)) {
|
|
return gst_mf_media_type_to_video_caps (media_type);
|
|
} else if (IsEqualGUID (major_type, MFMediaType_Audio)) {
|
|
return gst_mf_media_type_to_audio_caps (media_type);
|
|
}
|
|
|
|
return nullptr;
|
|
}
|
|
|
|
void
|
|
gst_mf_media_type_release (IMFMediaType * media_type)
|
|
{
|
|
if (media_type)
|
|
media_type->Release ();
|
|
}
|
|
|
|
gboolean
|
|
gst_mf_update_video_info_with_stride (GstVideoInfo * info, gint stride)
|
|
{
|
|
guint width, height, cr_h;
|
|
|
|
g_return_val_if_fail (info != nullptr, FALSE);
|
|
g_return_val_if_fail (stride > 0, FALSE);
|
|
g_return_val_if_fail (GST_VIDEO_INFO_FORMAT (info)
|
|
!= GST_VIDEO_FORMAT_UNKNOWN, FALSE);
|
|
|
|
if (GST_VIDEO_INFO_FORMAT (info) == GST_VIDEO_FORMAT_ENCODED)
|
|
return TRUE;
|
|
|
|
width = GST_VIDEO_INFO_WIDTH (info);
|
|
height = GST_VIDEO_INFO_HEIGHT (info);
|
|
|
|
/* copied from video-info */
|
|
switch (GST_VIDEO_INFO_FORMAT (info)) {
|
|
/* RGB */
|
|
case GST_VIDEO_FORMAT_RGBx:
|
|
case GST_VIDEO_FORMAT_RGBA:
|
|
case GST_VIDEO_FORMAT_RGB16:
|
|
case GST_VIDEO_FORMAT_BGR15:
|
|
case GST_VIDEO_FORMAT_BGR:
|
|
info->stride[0] = stride;
|
|
info->offset[0] = 0;
|
|
info->size = info->stride[0] * height;
|
|
break;
|
|
/* packed YUV */
|
|
case GST_VIDEO_FORMAT_YUY2:
|
|
case GST_VIDEO_FORMAT_YVYU:
|
|
case GST_VIDEO_FORMAT_UYVY:
|
|
case GST_VIDEO_FORMAT_VUYA:
|
|
info->stride[0] = stride;
|
|
info->offset[0] = 0;
|
|
info->size = info->stride[0] * height;
|
|
break;
|
|
/* semi-planar */
|
|
case GST_VIDEO_FORMAT_NV12:
|
|
case GST_VIDEO_FORMAT_P010_10LE:
|
|
case GST_VIDEO_FORMAT_P016_LE:
|
|
if (height % 2) {
|
|
GST_ERROR ("Height must be even number");
|
|
return FALSE;
|
|
}
|
|
|
|
cr_h = height / 2;
|
|
|
|
info->stride[0] = stride;
|
|
info->stride[1] = info->stride[0];
|
|
info->offset[0] = 0;
|
|
info->offset[1] = info->stride[0] * height;
|
|
info->size = info->offset[1] + info->stride[0] * cr_h;
|
|
break;
|
|
/* planar */
|
|
case GST_VIDEO_FORMAT_I420:
|
|
case GST_VIDEO_FORMAT_YV12:
|
|
if (stride % 2) {
|
|
GST_ERROR ("Stride must be even number");
|
|
return FALSE;
|
|
}
|
|
|
|
if (height % 2) {
|
|
GST_ERROR ("Height must be even number");
|
|
return FALSE;
|
|
}
|
|
|
|
cr_h = height / 2;
|
|
|
|
info->stride[0] = stride;
|
|
info->stride[1] = stride / 2;
|
|
info->stride[2] = info->stride[1];
|
|
info->offset[0] = 0;
|
|
info->offset[1] = info->stride[0] * height;
|
|
info->offset[2] = info->offset[1] + info->stride[1] * cr_h;
|
|
info->size = info->offset[2] + info->stride[2] * cr_h;
|
|
break;
|
|
/* complex */
|
|
case GST_VIDEO_FORMAT_v210:
|
|
case GST_VIDEO_FORMAT_v216:
|
|
info->stride[0] = stride;
|
|
info->offset[0] = 0;
|
|
info->size = info->stride[0] * height;
|
|
break;
|
|
/* gray */
|
|
case GST_VIDEO_FORMAT_GRAY16_LE:
|
|
info->stride[0] = stride;
|
|
info->offset[0] = 0;
|
|
info->size = info->stride[0] * height;
|
|
break;
|
|
default:
|
|
GST_ERROR ("Unhandled format %s",
|
|
gst_video_format_to_string (GST_VIDEO_INFO_FORMAT (info)));
|
|
return FALSE;
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
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 = nullptr;
|
|
|
|
error_text = g_win32_error_message ((gint) hr);
|
|
/* g_win32_error_message() doesn't cover all HERESULT return code,
|
|
* so it could be empty string, or null if there was an error
|
|
* in g_utf16_to_utf8() */
|
|
gst_debug_log (cat, GST_LEVEL_WARNING, file, function, line,
|
|
nullptr, "MediaFoundation call failed: 0x%x, %s", (guint) hr,
|
|
GST_STR_NULL (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_DESKTOP
|
|
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 nullptr;
|
|
}
|
|
|
|
static gchar *
|
|
gst_mf_guid_to_string (const GUID & guid)
|
|
{
|
|
const gchar *str = nullptr;
|
|
HRESULT hr;
|
|
WCHAR *name = nullptr;
|
|
gchar *ret = nullptr;
|
|
|
|
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, nullptr, nullptr,
|
|
nullptr);
|
|
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_strdup ("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, nullptr, nullptr, nullptr);
|
|
case VT_UNKNOWN:
|
|
return g_strdup ("IUnknown");
|
|
default:
|
|
return g_strdup_printf ("Unhandled type (vt = %d)", var.vt);
|
|
}
|
|
|
|
return nullptr;
|
|
}
|
|
|
|
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 = nullptr;
|
|
gchar *value = nullptr;
|
|
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,
|
|
nullptr, "%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
|
|
}
|