From a967db3b2068180989f501be474b470cc4493cc5 Mon Sep 17 00:00:00 2001 From: Seungha Yang Date: Wed, 29 Jan 2020 17:29:04 +0900 Subject: [PATCH] d3d11format: Add util methods for mapping DXGI color space with ours Move color space mapping and hdr10 metadata conversion methods to d3d11format in order to reuse the code. --- sys/d3d11/gstd3d11format.c | 343 +++++++++++++++++++++++++++++++++++ sys/d3d11/gstd3d11format.h | 15 ++ sys/d3d11/gstd3d11window.cpp | 254 +++++--------------------- sys/d3d11/gstd3d11window.h | 3 - 4 files changed, 401 insertions(+), 214 deletions(-) diff --git a/sys/d3d11/gstd3d11format.c b/sys/d3d11/gstd3d11format.c index ebdf25806d..292b78482b 100644 --- a/sys/d3d11/gstd3d11format.c +++ b/sys/d3d11/gstd3d11format.c @@ -26,6 +26,8 @@ #include "gstd3d11device.h" #include "gstd3d11memory.h" +#include + GST_DEBUG_CATEGORY_EXTERN (gst_d3d11_format_debug); #define GST_CAT_DEFAULT gst_d3d11_format_debug @@ -164,3 +166,344 @@ gst_d3d11_device_get_supported_caps (GstD3D11Device * device, return supported_caps; } + +#if (DXGI_HEADER_VERSION >= 5) +static inline UINT16 +fraction_to_uint (guint num, guint den, guint scale) +{ + gdouble val; + gst_util_fraction_to_double (num, den, &val); + + return (UINT16) val *scale; +} + +gboolean +gst_d3d11_hdr_meta_data_to_dxgi (GstVideoMasteringDisplayInfo * minfo, + GstVideoContentLightLevel * cll, DXGI_HDR_METADATA_HDR10 * dxgi_hdr10) +{ + g_return_val_if_fail (dxgi_hdr10 != NULL, FALSE); + + memset (dxgi_hdr10, 0, sizeof (DXGI_HDR_METADATA_HDR10)); + + if (minfo) { + dxgi_hdr10->RedPrimary[0] = + fraction_to_uint (minfo->Rx_n, minfo->Rx_d, 50000); + dxgi_hdr10->RedPrimary[1] = + fraction_to_uint (minfo->Ry_n, minfo->Ry_d, 50000); + dxgi_hdr10->GreenPrimary[0] = + fraction_to_uint (minfo->Gx_n, minfo->Gx_d, 50000); + dxgi_hdr10->GreenPrimary[1] = + fraction_to_uint (minfo->Gy_n, minfo->Gy_d, 50000); + dxgi_hdr10->BluePrimary[0] = + fraction_to_uint (minfo->Bx_n, minfo->Bx_d, 50000); + dxgi_hdr10->BluePrimary[1] = + fraction_to_uint (minfo->By_n, minfo->By_d, 50000); + dxgi_hdr10->WhitePoint[0] = + fraction_to_uint (minfo->Wx_n, minfo->Wx_d, 50000); + dxgi_hdr10->WhitePoint[1] = + fraction_to_uint (minfo->Wy_n, minfo->Wy_d, 50000); + dxgi_hdr10->MaxMasteringLuminance = + fraction_to_uint (minfo->max_luma_n, minfo->max_luma_d, 1); + dxgi_hdr10->MinMasteringLuminance = + fraction_to_uint (minfo->min_luma_n, minfo->min_luma_d, 1); + } + + if (cll) { + dxgi_hdr10->MaxContentLightLevel = + fraction_to_uint (cll->maxCLL_n, cll->maxCLL_d, 1); + dxgi_hdr10->MaxFrameAverageLightLevel = + fraction_to_uint (cll->maxFALL_n, cll->maxFALL_d, 1); + } + + return TRUE; +} +#endif + +#if (DXGI_HEADER_VERSION >= 4) +typedef enum +{ + GST_DXGI_COLOR_SPACE_RGB_FULL_G22_NONE_P709 = 0, + GST_DXGI_COLOR_SPACE_RGB_FULL_G10_NONE_P709 = 1, + GST_DXGI_COLOR_SPACE_RGB_STUDIO_G22_NONE_P709 = 2, + GST_DXGI_COLOR_SPACE_RGB_STUDIO_G22_NONE_P2020 = 3, + GST_DXGI_COLOR_SPACE_RESERVED = 4, + GST_DXGI_COLOR_SPACE_YCBCR_FULL_G22_NONE_P709_X601 = 5, + GST_DXGI_COLOR_SPACE_YCBCR_STUDIO_G22_LEFT_P601 = 6, + GST_DXGI_COLOR_SPACE_YCBCR_FULL_G22_LEFT_P601 = 7, + GST_DXGI_COLOR_SPACE_YCBCR_STUDIO_G22_LEFT_P709 = 8, + GST_DXGI_COLOR_SPACE_YCBCR_FULL_G22_LEFT_P709 = 9, + GST_DXGI_COLOR_SPACE_YCBCR_STUDIO_G22_LEFT_P2020 = 10, + GST_DXGI_COLOR_SPACE_YCBCR_FULL_G22_LEFT_P2020 = 11, + GST_DXGI_COLOR_SPACE_RGB_FULL_G2084_NONE_P2020 = 12, + GST_DXGI_COLOR_SPACE_YCBCR_STUDIO_G2084_LEFT_P2020 = 13, + GST_DXGI_COLOR_SPACE_RGB_STUDIO_G2084_NONE_P2020 = 14, + GST_DXGI_COLOR_SPACE_YCBCR_STUDIO_G22_TOPLEFT_P2020 = 15, + GST_DXGI_COLOR_SPACE_YCBCR_STUDIO_G2084_TOPLEFT_P2020 = 16, + GST_DXGI_COLOR_SPACE_RGB_FULL_G22_NONE_P2020 = 17, + GST_DXGI_COLOR_SPACE_YCBCR_STUDIO_GHLG_TOPLEFT_P2020 = 18, + GST_DXGI_COLOR_SPACE_YCBCR_FULL_GHLG_TOPLEFT_P2020 = 19, + GST_DXGI_COLOR_SPACE_RGB_STUDIO_G24_NONE_P709 = 20, + GST_DXGI_COLOR_SPACE_RGB_STUDIO_G24_NONE_P2020 = 21, + GST_DXGI_COLOR_SPACE_YCBCR_STUDIO_G24_LEFT_P709 = 22, + GST_DXGI_COLOR_SPACE_YCBCR_STUDIO_G24_LEFT_P2020 = 23, + GST_DXGI_COLOR_SPACE_YCBCR_STUDIO_G24_TOPLEFT_P2020 = 24, + GST_DXGI_COLOR_SPACE_CUSTOM = 0xFFFFFFFF +} GST_DXGI_COLOR_SPACE_TYPE; + +typedef struct +{ + GST_DXGI_COLOR_SPACE_TYPE type; + GstVideoColorRange range; + GstVideoColorMatrix matrix; + GstVideoTransferFunction transfer; + GstVideoColorPrimaries primaries; +} DxgiColorSpaceMap; + +/* https://docs.microsoft.com/en-us/windows/win32/api/dxgicommon/ne-dxgicommon-dxgi_color_space_type */ + +#define MAKE_COLOR_MAP(d,r,m,t,p) \ + { GST_DXGI_COLOR_SPACE_ ##d, GST_VIDEO_COLOR_RANGE ##r, \ + GST_VIDEO_COLOR_MATRIX_ ##m, GST_VIDEO_TRANSFER_ ##t, \ + GST_VIDEO_COLOR_PRIMARIES_ ##p } + +static const DxgiColorSpaceMap rgb_colorspace_map[] = { + /* RGB_FULL_G22_NONE_P709 */ + MAKE_COLOR_MAP (RGB_FULL_G22_NONE_P709, _0_255, UNKNOWN, BT709, BT709), + + /* RGB_FULL_G10_NONE_P709 */ + MAKE_COLOR_MAP (RGB_FULL_G22_NONE_P709, _0_255, UNKNOWN, GAMMA10, BT709), + + /* RGB_STUDIO_G22_NONE_P709 */ + MAKE_COLOR_MAP (RGB_FULL_G22_NONE_P709, _16_235, UNKNOWN, BT709, BT709), + + /* RGB_STUDIO_G22_NONE_P2020 */ + MAKE_COLOR_MAP (RGB_FULL_G22_NONE_P709, _16_235, UNKNOWN, BT2020_10, BT2020), + MAKE_COLOR_MAP (RGB_FULL_G22_NONE_P709, _16_235, UNKNOWN, BT2020_12, BT2020), + + /* RGB_FULL_G2084_NONE_P2020 */ + MAKE_COLOR_MAP (RGB_FULL_G2084_NONE_P2020, _0_255, UNKNOWN, SMPTE2084, + BT2020), + + /* RGB_STUDIO_G2084_NONE_P2020 */ + MAKE_COLOR_MAP (RGB_STUDIO_G2084_NONE_P2020, + _16_235, UNKNOWN, SMPTE2084, BT2020), + + /* RGB_FULL_G22_NONE_P2020 */ + MAKE_COLOR_MAP (RGB_FULL_G22_NONE_P2020, _0_255, UNKNOWN, BT2020_10, BT2020), + MAKE_COLOR_MAP (RGB_FULL_G22_NONE_P2020, _0_255, UNKNOWN, BT2020_12, BT2020), + + /* RGB_STUDIO_G24_NONE_P709 */ + MAKE_COLOR_MAP (RGB_STUDIO_G24_NONE_P709, _16_235, UNKNOWN, SRGB, BT709), + + /* RGB_STUDIO_G24_NONE_P2020 */ + MAKE_COLOR_MAP (RGB_STUDIO_G24_NONE_P709, _16_235, UNKNOWN, SRGB, BT2020), +}; + +static const DxgiColorSpaceMap yuv_colorspace_map[] = { + /* YCBCR_FULL_G22_NONE_P709_X601 */ + MAKE_COLOR_MAP (YCBCR_FULL_G22_NONE_P709_X601, _0_255, BT601, BT709, BT709), + + /* YCBCR_STUDIO_G22_LEFT_P601 */ + MAKE_COLOR_MAP (YCBCR_STUDIO_G22_LEFT_P601, _16_235, BT601, BT709, SMPTE170M), + + /* YCBCR_FULL_G22_LEFT_P601 */ + MAKE_COLOR_MAP (YCBCR_FULL_G22_LEFT_P601, _0_255, BT601, BT709, SMPTE170M), + + /* YCBCR_STUDIO_G22_LEFT_P709 */ + MAKE_COLOR_MAP (YCBCR_STUDIO_G22_LEFT_P709, _16_235, BT709, BT709, BT709), + + /* YCBCR_FULL_G22_LEFT_P709 */ + MAKE_COLOR_MAP (YCBCR_FULL_G22_LEFT_P709, _0_255, BT709, BT709, BT709), + + /* YCBCR_STUDIO_G22_LEFT_P2020 */ + MAKE_COLOR_MAP (YCBCR_STUDIO_G22_LEFT_P2020, _16_235, BT2020, BT2020_10, + BT2020), + MAKE_COLOR_MAP (YCBCR_STUDIO_G22_LEFT_P2020, _16_235, BT2020, BT2020_12, + BT2020), + + /* YCBCR_FULL_G22_LEFT_P2020 */ + MAKE_COLOR_MAP (YCBCR_FULL_G22_LEFT_P2020, _0_255, BT2020, BT2020_10, BT2020), + MAKE_COLOR_MAP (YCBCR_FULL_G22_LEFT_P2020, _0_255, BT2020, BT2020_12, BT2020), + + /* YCBCR_STUDIO_G2084_LEFT_P2020 */ + MAKE_COLOR_MAP (YCBCR_STUDIO_G2084_LEFT_P2020, _16_235, BT2020, SMPTE2084, + BT2020), + + /* YCBCR_STUDIO_G22_TOPLEFT_P2020 */ + MAKE_COLOR_MAP (YCBCR_STUDIO_G22_TOPLEFT_P2020, _16_235, BT2020, BT2020_10, + BT2020), + MAKE_COLOR_MAP (YCBCR_STUDIO_G22_TOPLEFT_P2020, _16_235, BT2020, BT2020_12, + BT2020), + + /* YCBCR_STUDIO_G2084_TOPLEFT_P2020 */ + /* FIXME: check chroma-site to differentiate this from + * YCBCR_STUDIO_G2084_LEFT_P2020 */ + MAKE_COLOR_MAP (YCBCR_STUDIO_G2084_TOPLEFT_P2020, _16_235, BT2020, SMPTE2084, + BT2020), + + /* YCBCR_STUDIO_GHLG_TOPLEFT_P2020 */ + MAKE_COLOR_MAP (YCBCR_STUDIO_GHLG_TOPLEFT_P2020, _16_235, BT2020, + ARIB_STD_B67, BT2020), + + /* YCBCR_STUDIO_GHLG_TOPLEFT_P2020 */ + MAKE_COLOR_MAP (YCBCR_FULL_GHLG_TOPLEFT_P2020, _0_255, BT2020, ARIB_STD_B67, + BT2020), + + /* YCBCR_STUDIO_G24_LEFT_P709 */ + MAKE_COLOR_MAP (YCBCR_STUDIO_G22_LEFT_P709, _16_235, BT709, SRGB, BT709), + + /* YCBCR_STUDIO_G24_LEFT_P2020 */ + MAKE_COLOR_MAP (YCBCR_STUDIO_G24_LEFT_P2020, _16_235, BT2020, SRGB, BT2020), + + /* YCBCR_STUDIO_G24_TOPLEFT_P2020 */ + /* FIXME: check chroma-site to differentiate this from + * YCBCR_STUDIO_G24_LEFT_P2020 */ + MAKE_COLOR_MAP (YCBCR_STUDIO_G24_TOPLEFT_P2020, _16_235, BT2020, SRGB, + BT2020), +}; + +#define SCORE_RANGE_MISMATCH 1 +#define SCORE_MATRIX_MISMATCH 5 +#define SCORE_TRANSFER_MISMATCH 5 +#define SCORE_PRIMARY_MISMATCH 10 + +static gint +get_score (GstVideoInfo * info, const DxgiColorSpaceMap * color_map, + gboolean is_yuv) +{ + gint loss = 0; + GstVideoColorimetry *color = &info->colorimetry; + + if (color->range != color_map->range) + loss += SCORE_RANGE_MISMATCH; + + if (is_yuv && color->matrix != color_map->matrix) + loss += SCORE_MATRIX_MISMATCH; + + if (color->transfer != color_map->transfer) + loss += SCORE_TRANSFER_MISMATCH; + + if (color->primaries != color_map->primaries) + loss += SCORE_PRIMARY_MISMATCH; + + return loss; +} + +static gboolean +gst_d3d11_video_info_to_dxgi_color_space_rgb (GstVideoInfo * info, + DXGI_COLOR_SPACE_TYPE * colorspace) +{ + gint best_score = G_MAXINT; + gint score, i; + GST_DXGI_COLOR_SPACE_TYPE type = GST_DXGI_COLOR_SPACE_RGB_FULL_G22_NONE_P709; + + for (i = 0; i < G_N_ELEMENTS (rgb_colorspace_map); i++) { + score = get_score (info, &rgb_colorspace_map[i], TRUE); + + if (score < best_score) { + best_score = score; + type = rgb_colorspace_map[i].type; + + if (score == 0) + break; + } + } + + *colorspace = (DXGI_COLOR_SPACE_TYPE) type; + + return TRUE; +} + +static gboolean +gst_d3d11_video_info_to_dxgi_color_space_yuv (GstVideoInfo * info, + DXGI_COLOR_SPACE_TYPE * colorspace) +{ + gint best_score = G_MAXINT; + gint score, i; + GST_DXGI_COLOR_SPACE_TYPE type = + GST_DXGI_COLOR_SPACE_YCBCR_STUDIO_G22_LEFT_P709; + + for (i = 0; i < G_N_ELEMENTS (yuv_colorspace_map); i++) { + score = get_score (info, &yuv_colorspace_map[i], TRUE); + + if (score < best_score) { + best_score = score; + type = yuv_colorspace_map[i].type; + + if (score == 0) + break; + } + } + + *colorspace = (DXGI_COLOR_SPACE_TYPE) type; + + return TRUE; +} + +gboolean +gst_d3d11_video_info_to_dxgi_color_space (GstVideoInfo * info, + DXGI_COLOR_SPACE_TYPE * colorspace) +{ + g_return_val_if_fail (info != NULL, FALSE); + g_return_val_if_fail (colorspace != NULL, FALSE); + + if (GST_VIDEO_INFO_IS_RGB (info)) { + return gst_d3d11_video_info_to_dxgi_color_space_rgb (info, colorspace); + } else if (GST_VIDEO_INFO_IS_YUV (info)) { + return gst_d3d11_video_info_to_dxgi_color_space_yuv (info, colorspace); + } + + return FALSE; +} + +gboolean +gst_d3d11_find_swap_chain_color_space (GstVideoInfo * info, + IDXGISwapChain3 * swapchain, DXGI_COLOR_SPACE_TYPE * colorspace) +{ + GST_DXGI_COLOR_SPACE_TYPE best_type; + gint best_score = G_MAXINT; + gint i; + + g_return_val_if_fail (info != NULL, FALSE); + g_return_val_if_fail (swapchain != NULL, FALSE); + g_return_val_if_fail (colorspace != NULL, FALSE); + + if (!GST_VIDEO_INFO_IS_RGB (info)) { + GST_WARNING ("Swapchain colorspace should be RGB format"); + return FALSE; + } + + for (i = 0; i < G_N_ELEMENTS (rgb_colorspace_map); i++) { + UINT can_support = 0; + HRESULT hr; + gint score; + GST_DXGI_COLOR_SPACE_TYPE cur_type = rgb_colorspace_map[i].type; + + hr = IDXGISwapChain3_CheckColorSpaceSupport (swapchain, + cur_type, &can_support); + + if (FAILED (hr)) + continue; + + if ((can_support & DXGI_SWAP_CHAIN_COLOR_SPACE_SUPPORT_FLAG_PRESENT) == + DXGI_SWAP_CHAIN_COLOR_SPACE_SUPPORT_FLAG_PRESENT) { + score = get_score (info, &rgb_colorspace_map[i], FALSE); + + GST_DEBUG ("colorspace %d supported, score %d", cur_type, score); + + if (score < best_score) { + best_score = score; + best_type = cur_type; + } + } + } + + if (best_score == G_MAXINT) + return FALSE; + + *colorspace = (DXGI_COLOR_SPACE_TYPE) best_type; + + return TRUE; +} + +#endif diff --git a/sys/d3d11/gstd3d11format.h b/sys/d3d11/gstd3d11format.h index 0b9bfef1c7..4c85bcadd1 100644 --- a/sys/d3d11/gstd3d11format.h +++ b/sys/d3d11/gstd3d11format.h @@ -55,6 +55,21 @@ gboolean gst_d3d11_dxgi_format_get_size (DXGI_FORMAT format, GstCaps * gst_d3d11_device_get_supported_caps (GstD3D11Device * device, D3D11_FORMAT_SUPPORT flags); +#if (DXGI_HEADER_VERSION >= 5) +gboolean gst_d3d11_hdr_meta_data_to_dxgi (GstVideoMasteringDisplayInfo * minfo, + GstVideoContentLightLevel * cll, + DXGI_HDR_METADATA_HDR10 * dxgi_hdr10); +#endif + +#if (DXGI_HEADER_VERSION >= 4) +gboolean gst_d3d11_video_info_to_dxgi_color_space (GstVideoInfo * info, + DXGI_COLOR_SPACE_TYPE * colorspace); + +gboolean gst_d3d11_find_swap_chain_color_space (GstVideoInfo * info, + IDXGISwapChain3 * swapchain, + DXGI_COLOR_SPACE_TYPE * colorspace); +#endif + G_END_DECLS #endif /* __GST_D3D11_FORMAT_H__ */ diff --git a/sys/d3d11/gstd3d11window.cpp b/sys/d3d11/gstd3d11window.cpp index c7e8e48a45..922c787df0 100644 --- a/sys/d3d11/gstd3d11window.cpp +++ b/sys/d3d11/gstd3d11window.cpp @@ -404,167 +404,6 @@ gst_d3d11_window_on_mouse_event (GstD3D11Window * window, const gchar * event, event, button, x, y); } -#if (DXGI_HEADER_VERSION >= 5) -static inline UINT16 -fraction_to_uint (guint num, guint den, guint scale) -{ - gdouble val; - gst_util_fraction_to_double (num, den, &val); - - return (UINT16) val *scale; -} - -static void -mastering_display_gst_to_dxgi (GstVideoMasteringDisplayInfo * m, - GstVideoContentLightLevel * c, DXGI_HDR_METADATA_HDR10 * meta) -{ - meta->RedPrimary[0] = fraction_to_uint (m->Rx_n, m->Rx_d, 50000); - meta->RedPrimary[1] = fraction_to_uint (m->Ry_n, m->Ry_d, 50000); - meta->GreenPrimary[0] = fraction_to_uint (m->Gx_n, m->Gx_d, 50000); - meta->GreenPrimary[1] = fraction_to_uint (m->Gy_n, m->Gy_d, 50000); - meta->BluePrimary[0] = fraction_to_uint (m->Bx_n, m->Bx_d, 50000); - meta->BluePrimary[1] = fraction_to_uint (m->By_n, m->By_d, 50000); - meta->WhitePoint[0] = fraction_to_uint (m->Wx_n, m->Wx_d, 50000); - meta->WhitePoint[1] = fraction_to_uint (m->Wy_n, m->Wy_d, 50000); - meta->MaxMasteringLuminance = - fraction_to_uint (m->max_luma_n, m->max_luma_d, 1); - meta->MinMasteringLuminance = - fraction_to_uint (m->min_luma_n, m->min_luma_d, 1); - meta->MaxContentLightLevel = fraction_to_uint (c->maxCLL_n, c->maxCLL_d, 1); - meta->MaxFrameAverageLightLevel = - fraction_to_uint (c->maxFALL_n, c->maxFALL_d, 1); -} - -/* missing in mingw header... */ -typedef enum -{ - GST_DXGI_COLOR_SPACE_RGB_FULL_G22_NONE_P709 = 0, - GST_DXGI_COLOR_SPACE_RGB_FULL_G10_NONE_P709 = 1, - GST_DXGI_COLOR_SPACE_RGB_STUDIO_G22_NONE_P709 = 2, - GST_DXGI_COLOR_SPACE_RGB_STUDIO_G22_NONE_P2020 = 3, - GST_DXGI_COLOR_SPACE_RESERVED = 4, - GST_DXGI_COLOR_SPACE_YCBCR_FULL_G22_NONE_P709_X601 = 5, - GST_DXGI_COLOR_SPACE_YCBCR_STUDIO_G22_LEFT_P601 = 6, - GST_DXGI_COLOR_SPACE_YCBCR_FULL_G22_LEFT_P601 = 7, - GST_DXGI_COLOR_SPACE_YCBCR_STUDIO_G22_LEFT_P709 = 8, - GST_DXGI_COLOR_SPACE_YCBCR_FULL_G22_LEFT_P709 = 9, - GST_DXGI_COLOR_SPACE_YCBCR_STUDIO_G22_LEFT_P2020 = 10, - GST_DXGI_COLOR_SPACE_YCBCR_FULL_G22_LEFT_P2020 = 11, - GST_DXGI_COLOR_SPACE_RGB_FULL_G2084_NONE_P2020 = 12, - GST_DXGI_COLOR_SPACE_YCBCR_STUDIO_G2084_LEFT_P2020 = 13, - GST_DXGI_COLOR_SPACE_RGB_STUDIO_G2084_NONE_P2020 = 14, - GST_DXGI_COLOR_SPACE_YCBCR_STUDIO_G22_TOPLEFT_P2020 = 15, - GST_DXGI_COLOR_SPACE_YCBCR_STUDIO_G2084_TOPLEFT_P2020 = 16, - GST_DXGI_COLOR_SPACE_RGB_FULL_G22_NONE_P2020 = 17, - GST_DXGI_COLOR_SPACE_YCBCR_STUDIO_GHLG_TOPLEFT_P2020 = 18, - GST_DXGI_COLOR_SPACE_YCBCR_FULL_GHLG_TOPLEFT_P2020 = 19, - GST_DXGI_COLOR_SPACE_RGB_STUDIO_G24_NONE_P709 = 20, - GST_DXGI_COLOR_SPACE_RGB_STUDIO_G24_NONE_P2020 = 21, - GST_DXGI_COLOR_SPACE_YCBCR_STUDIO_G24_LEFT_P709 = 22, - GST_DXGI_COLOR_SPACE_YCBCR_STUDIO_G24_LEFT_P2020 = 23, - GST_DXGI_COLOR_SPACE_YCBCR_STUDIO_G24_TOPLEFT_P2020 = 24, - GST_DXGI_COLOR_SPACE_CUSTOM = 0xFFFFFFFF -} GST_DXGI_COLOR_SPACE_TYPE; - -typedef struct -{ - GST_DXGI_COLOR_SPACE_TYPE type; - GstVideoColorRange range; - GstVideoTransferFunction transfer; - GstVideoColorPrimaries primaries; -} DxgiColorSpaceMap; - -/* https://docs.microsoft.com/en-us/windows/win32/api/dxgicommon/ne-dxgicommon-dxgi_color_space_type */ -static const DxgiColorSpaceMap colorspace_map[] = { - /* RGB, bt709 */ - {GST_DXGI_COLOR_SPACE_RGB_FULL_G22_NONE_P709, GST_VIDEO_COLOR_RANGE_0_255, - GST_VIDEO_TRANSFER_BT709, GST_VIDEO_COLOR_PRIMARIES_BT709}, - {GST_DXGI_COLOR_SPACE_RGB_FULL_G10_NONE_P709, GST_VIDEO_COLOR_RANGE_0_255, - GST_VIDEO_TRANSFER_GAMMA10, GST_VIDEO_COLOR_PRIMARIES_BT709}, - {GST_DXGI_COLOR_SPACE_RGB_STUDIO_G22_NONE_P709, GST_VIDEO_COLOR_RANGE_16_235, - GST_VIDEO_TRANSFER_BT709, GST_VIDEO_COLOR_PRIMARIES_BT709}, - /* RGB, bt2020 */ - {GST_DXGI_COLOR_SPACE_RGB_FULL_G22_NONE_P2020, GST_VIDEO_COLOR_RANGE_0_255, - GST_VIDEO_TRANSFER_BT2020_10, GST_VIDEO_COLOR_PRIMARIES_BT2020}, - {GST_DXGI_COLOR_SPACE_RGB_STUDIO_G22_NONE_P2020, GST_VIDEO_COLOR_RANGE_16_235, - GST_VIDEO_TRANSFER_BT2020_10, GST_VIDEO_COLOR_PRIMARIES_BT2020}, - /* RGB, bt2084 */ - {GST_DXGI_COLOR_SPACE_RGB_FULL_G2084_NONE_P2020, GST_VIDEO_COLOR_RANGE_0_255, - GST_VIDEO_TRANSFER_SMPTE2084, GST_VIDEO_COLOR_PRIMARIES_BT2020}, - {GST_DXGI_COLOR_SPACE_RGB_STUDIO_G2084_NONE_P2020, - GST_VIDEO_COLOR_RANGE_16_235, - GST_VIDEO_TRANSFER_SMPTE2084, GST_VIDEO_COLOR_PRIMARIES_BT2020}, - /* RGB, SRGB */ - {GST_DXGI_COLOR_SPACE_RGB_STUDIO_G24_NONE_P709, GST_VIDEO_COLOR_RANGE_16_235, - GST_VIDEO_TRANSFER_SRGB, GST_VIDEO_COLOR_PRIMARIES_BT709}, - {GST_DXGI_COLOR_SPACE_RGB_STUDIO_G24_NONE_P2020, GST_VIDEO_COLOR_RANGE_16_235, - GST_VIDEO_TRANSFER_SRGB, GST_VIDEO_COLOR_PRIMARIES_BT2020}, -}; - -static gboolean -gst_d3d11_window_color_space_from_video_info (GstD3D11Window * self, - GstVideoInfo * info, IDXGISwapChain4 * swapchain, - GST_DXGI_COLOR_SPACE_TYPE * dxgi_colorspace) -{ - guint i; - gint best_idx = -1; - gint best_score = 0; - - g_return_val_if_fail (info != NULL, FALSE); - g_return_val_if_fail (dxgi_colorspace != NULL, FALSE); - - /* We render only RGB for now */ - if (!GST_VIDEO_FORMAT_INFO_IS_RGB (info->finfo)) - return FALSE; - - /* find the best matching colorspace */ - for (i = 0; i < G_N_ELEMENTS (colorspace_map); i++) { - GstVideoColorimetry *cinfo = &info->colorimetry; - UINT can_support = 0; - HRESULT hr; - gint score = 0; - GstVideoTransferFunction transfer = cinfo->transfer; - DXGI_COLOR_SPACE_TYPE type = (DXGI_COLOR_SPACE_TYPE) colorspace_map[i].type; - - if (transfer == GST_VIDEO_TRANSFER_BT2020_12) - transfer = GST_VIDEO_TRANSFER_BT2020_10; - - hr = swapchain->CheckColorSpaceSupport (type, &can_support); - - if (SUCCEEDED (hr) && - (can_support & DXGI_SWAP_CHAIN_COLOR_SPACE_SUPPORT_FLAG_PRESENT) == - DXGI_SWAP_CHAIN_COLOR_SPACE_SUPPORT_FLAG_PRESENT) { - if (cinfo->range == colorspace_map[i].range) - score++; - - if (transfer == colorspace_map[i].transfer) - score++; - - if (cinfo->primaries == colorspace_map[i].primaries) - score++; - - GST_DEBUG_OBJECT (self, - "colorspace %d supported, score %d", type, score); - - if (score > best_score) { - best_score = score; - best_idx = i; - } - } else { - GST_DEBUG_OBJECT (self, - "colorspace %d not supported", type); - } - } - - if (best_idx < 0) - return FALSE; - - *dxgi_colorspace = colorspace_map[best_idx].type; - - return TRUE; -} -#endif - gboolean gst_d3d11_window_prepare (GstD3D11Window * window, guint width, guint height, guint aspect_ratio_n, guint aspect_ratio_d, GstCaps * caps, GError ** error) @@ -572,11 +411,6 @@ gst_d3d11_window_prepare (GstD3D11Window * window, guint width, guint height, GstD3D11WindowClass *klass; GstCaps *render_caps; guint swapchain_flags = 0; -#if (DXGI_HEADER_VERSION >= 5) - gboolean have_cll = FALSE; - gboolean have_mastering = FALSE; - gboolean swapchain4_available = FALSE; -#endif g_return_val_if_fail (GST_IS_D3D11_WINDOW (window), FALSE); g_return_val_if_fail (aspect_ratio_n > 0, FALSE); @@ -658,35 +492,12 @@ gst_d3d11_window_prepare (GstD3D11Window * window, guint width, guint height, } window->allow_tearing = FALSE; -#if (DXGI_HEADER_VERSION >= 5) - if (!gst_video_content_light_level_from_caps (&window->content_light_level, - caps)) { - gst_video_content_light_level_init (&window->content_light_level); - } else { - have_cll = TRUE; + g_object_get (window->device, "allow-tearing", &window->allow_tearing, NULL); + if (window->allow_tearing) { + GST_DEBUG_OBJECT (window, "device support tearning"); + swapchain_flags |= DXGI_SWAP_CHAIN_FLAG_ALLOW_TEARING; } - if (!gst_video_mastering_display_info_from_caps - (&window->mastering_display_info, caps)) { - gst_video_mastering_display_info_init (&window->mastering_display_info); - } else { - have_mastering = TRUE; - } - - if (gst_d3d11_device_get_chosen_dxgi_factory_version (window->device) >= - GST_D3D11_DXGI_FACTORY_5) { - GST_DEBUG_OBJECT (window, "DXGI 1.5 interface is available"); - swapchain4_available = TRUE; - - g_object_get (window->device, - "allow-tearing", &window->allow_tearing, NULL); - if (window->allow_tearing) { - GST_DEBUG_OBJECT (window, "device support tearning"); - swapchain_flags |= DXGI_SWAP_CHAIN_FLAG_ALLOW_TEARING; - } - } -#endif - if (window->swap_chain) { gst_d3d11_device_lock (window->device); gst_d3d11_window_release_resources (window->device, window); @@ -713,41 +524,62 @@ gst_d3d11_window_prepare (GstD3D11Window * window, guint width, guint height, return FALSE; } -#if (DXGI_HEADER_VERSION >= 5) - if (swapchain4_available) { + +#if (DXGI_HEADER_VERSION >= 4) + { + IDXGISwapChain3 *swapchain3 = NULL; HRESULT hr; - GST_DXGI_COLOR_SPACE_TYPE ctype; - IDXGISwapChain4* swap_chain4 = (IDXGISwapChain4 *) window->swap_chain; - if (gst_d3d11_window_color_space_from_video_info (window, - &window->render_info, swap_chain4, &ctype)) { - hr = swap_chain4->SetColorSpace1 ((DXGI_COLOR_SPACE_TYPE) ctype); + hr = window->swap_chain->QueryInterface (IID_IDXGISwapChain3, + (void **) &swapchain3); - if (!gst_d3d11_result (hr, window->device)) { - GST_WARNING_OBJECT (window, "Failed to set colorspace %d, hr: 0x%x", + if (gst_d3d11_result (hr, window->device)) { + DXGI_COLOR_SPACE_TYPE ctype; + + if (gst_d3d11_find_swap_chain_color_space (&window->render_info, + swapchain3, &ctype)) { + hr = swapchain3->SetColorSpace1 (ctype); + if (!gst_d3d11_result (hr, window->device)) { + GST_WARNING_OBJECT (window, "Failed to set colorspace %d, hr: 0x%x", ctype, (guint) hr); - } else { - GST_DEBUG_OBJECT (window, "Set colorspace %d", ctype); + } else { + GST_DEBUG_OBJECT (window, "Set colorspace %d", ctype); + } } - if (have_cll && have_mastering) { + swapchain3->Release (); + } + } +#endif + +#if (DXGI_HEADER_VERSION >= 5) + { + GstVideoMasteringDisplayInfo minfo; + GstVideoContentLightLevel cll; + + if (gst_video_mastering_display_info_from_caps (&minfo, caps) && + gst_video_content_light_level_from_caps (&cll, caps)) { + IDXGISwapChain4 *swapchain4 = NULL; + HRESULT hr; + + hr = window->swap_chain->QueryInterface (IID_IDXGISwapChain4, + (void **) &swapchain4); + if (gst_d3d11_result (hr, window->device)) { DXGI_HDR_METADATA_HDR10 metadata = { 0, }; GST_DEBUG_OBJECT (window, "Have HDR metadata, set to DXGI swapchain"); - mastering_display_gst_to_dxgi (&window->mastering_display_info, - &window->content_light_level, &metadata); + gst_d3d11_hdr_meta_data_to_dxgi (&minfo, &cll, &metadata); - hr = swap_chain4->SetHDRMetaData (DXGI_HDR_METADATA_TYPE_HDR10, + hr = swapchain4->SetHDRMetaData (DXGI_HDR_METADATA_TYPE_HDR10, sizeof (DXGI_HDR_METADATA_HDR10), &metadata); if (!gst_d3d11_result (hr, window->device)) { GST_WARNING_OBJECT (window, "Couldn't set HDR metadata, hr 0x%x", (guint) hr); } + + swapchain4->Release (); } - } else { - GST_DEBUG_OBJECT (window, - "Could not get color space from %" GST_PTR_FORMAT, caps); } } #endif diff --git a/sys/d3d11/gstd3d11window.h b/sys/d3d11/gstd3d11window.h index 6118fd7cac..2d743d3c34 100644 --- a/sys/d3d11/gstd3d11window.h +++ b/sys/d3d11/gstd3d11window.h @@ -82,9 +82,6 @@ struct _GstD3D11Window GstD3D11ColorConverter *converter; GstD3D11OverlayCompositor *compositor; - GstVideoMasteringDisplayInfo mastering_display_info; - GstVideoContentLightLevel content_light_level; - /* calculated rect with aspect ratio and window area */ RECT render_rect;