2 * Copyright (C) 2019 Seungha Yang <seungha.yang@navercorp.com>
3 * Copyright (C) 2020 Seungha Yang <seungha@centricular.com>
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.
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.
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.
25 #include "gstd3d11pluginutils.h"
28 #include <versionhelpers.h>
30 GST_DEBUG_CATEGORY_EXTERN (gst_d3d11_plugin_utils_debug);
31 #define GST_CAT_DEFAULT gst_d3d11_plugin_utils_debug
33 /* Max Texture Dimension for feature level 11_0 ~ 12_1 */
34 static guint _gst_d3d11_texture_max_dimension = 16384;
37 gst_d3d11_plugin_utils_init (D3D_FEATURE_LEVEL feature_level)
39 static gsize _init_once = 0;
41 if (g_once_init_enter (&_init_once)) {
42 /* https://docs.microsoft.com/en-us/windows/win32/direct3d11/overviews-direct3d-11-devices-downlevel-intro */
43 if (feature_level >= D3D_FEATURE_LEVEL_11_0)
44 _gst_d3d11_texture_max_dimension = 16384;
45 else if (feature_level >= D3D_FEATURE_LEVEL_10_0)
46 _gst_d3d11_texture_max_dimension = 8192;
48 _gst_d3d11_texture_max_dimension = 4096;
50 g_once_init_leave (&_init_once, 1);
55 gst_d3d11_get_updated_template_caps (GstStaticCaps * template_caps)
59 g_return_val_if_fail (template_caps != NULL, NULL);
61 caps = gst_static_caps_get (template_caps);
63 GST_ERROR ("Couldn't get caps from static caps");
67 caps = gst_caps_make_writable (caps);
68 gst_caps_set_simple (caps,
69 "width", GST_TYPE_INT_RANGE, 1, _gst_d3d11_texture_max_dimension,
70 "height", GST_TYPE_INT_RANGE, 1, _gst_d3d11_texture_max_dimension, NULL);
76 gst_d3d11_is_windows_8_or_greater (void)
78 static gsize version_once = 0;
79 static gboolean ret = FALSE;
81 if (g_once_init_enter (&version_once)) {
82 #if (!GST_D3D11_WINAPI_ONLY_APP)
83 if (IsWindows8OrGreater ())
89 g_once_init_leave (&version_once, 1);
96 gst_d3d11_get_device_vendor (GstD3D11Device * device)
101 GstD3D11DeviceVendor vendor = GST_D3D11_DEVICE_VENDOR_UNKNOWN;
103 g_return_val_if_fail (GST_IS_D3D11_DEVICE (device),
104 GST_D3D11_DEVICE_VENDOR_UNKNOWN);
106 g_object_get (device, "device-id", &device_id, "vendor-id", &vendor_id,
107 "description", &desc, NULL);
111 if (device_id == 0 && desc && g_strrstr (desc, "SraKmd"))
112 vendor = GST_D3D11_DEVICE_VENDOR_XBOX;
116 vendor = GST_D3D11_DEVICE_VENDOR_AMD;
119 vendor = GST_D3D11_DEVICE_VENDOR_INTEL;
122 vendor = GST_D3D11_DEVICE_VENDOR_NVIDIA;
125 vendor = GST_D3D11_DEVICE_VENDOR_QUALCOMM;
136 #if (GST_D3D11_DXGI_HEADER_VERSION >= 5)
138 gst_d3d11_hdr_meta_data_to_dxgi (GstVideoMasteringDisplayInfo * minfo,
139 GstVideoContentLightLevel * cll, DXGI_HDR_METADATA_HDR10 * dxgi_hdr10)
141 g_return_val_if_fail (dxgi_hdr10 != NULL, FALSE);
143 memset (dxgi_hdr10, 0, sizeof (DXGI_HDR_METADATA_HDR10));
146 dxgi_hdr10->RedPrimary[0] = minfo->display_primaries[0].x;
147 dxgi_hdr10->RedPrimary[1] = minfo->display_primaries[0].y;
148 dxgi_hdr10->GreenPrimary[0] = minfo->display_primaries[1].x;
149 dxgi_hdr10->GreenPrimary[1] = minfo->display_primaries[1].y;
150 dxgi_hdr10->BluePrimary[0] = minfo->display_primaries[2].x;
151 dxgi_hdr10->BluePrimary[1] = minfo->display_primaries[2].y;
153 dxgi_hdr10->WhitePoint[0] = minfo->white_point.x;
154 dxgi_hdr10->WhitePoint[1] = minfo->white_point.y;
155 dxgi_hdr10->MaxMasteringLuminance = minfo->max_display_mastering_luminance;
156 dxgi_hdr10->MinMasteringLuminance = minfo->min_display_mastering_luminance;
160 dxgi_hdr10->MaxContentLightLevel = cll->max_content_light_level;
161 dxgi_hdr10->MaxFrameAverageLightLevel = cll->max_frame_average_light_level;
168 #if (GST_D3D11_DXGI_HEADER_VERSION >= 4)
171 GST_DXGI_COLOR_SPACE_RGB_FULL_G22_NONE_P709 = 0,
172 GST_DXGI_COLOR_SPACE_RGB_FULL_G10_NONE_P709 = 1,
173 GST_DXGI_COLOR_SPACE_RGB_STUDIO_G22_NONE_P709 = 2,
174 GST_DXGI_COLOR_SPACE_RGB_STUDIO_G22_NONE_P2020 = 3,
175 GST_DXGI_COLOR_SPACE_RESERVED = 4,
176 GST_DXGI_COLOR_SPACE_YCBCR_FULL_G22_NONE_P709_X601 = 5,
177 GST_DXGI_COLOR_SPACE_YCBCR_STUDIO_G22_LEFT_P601 = 6,
178 GST_DXGI_COLOR_SPACE_YCBCR_FULL_G22_LEFT_P601 = 7,
179 GST_DXGI_COLOR_SPACE_YCBCR_STUDIO_G22_LEFT_P709 = 8,
180 GST_DXGI_COLOR_SPACE_YCBCR_FULL_G22_LEFT_P709 = 9,
181 GST_DXGI_COLOR_SPACE_YCBCR_STUDIO_G22_LEFT_P2020 = 10,
182 GST_DXGI_COLOR_SPACE_YCBCR_FULL_G22_LEFT_P2020 = 11,
183 GST_DXGI_COLOR_SPACE_RGB_FULL_G2084_NONE_P2020 = 12,
184 GST_DXGI_COLOR_SPACE_YCBCR_STUDIO_G2084_LEFT_P2020 = 13,
185 GST_DXGI_COLOR_SPACE_RGB_STUDIO_G2084_NONE_P2020 = 14,
186 GST_DXGI_COLOR_SPACE_YCBCR_STUDIO_G22_TOPLEFT_P2020 = 15,
187 GST_DXGI_COLOR_SPACE_YCBCR_STUDIO_G2084_TOPLEFT_P2020 = 16,
188 GST_DXGI_COLOR_SPACE_RGB_FULL_G22_NONE_P2020 = 17,
189 GST_DXGI_COLOR_SPACE_YCBCR_STUDIO_GHLG_TOPLEFT_P2020 = 18,
190 GST_DXGI_COLOR_SPACE_YCBCR_FULL_GHLG_TOPLEFT_P2020 = 19,
191 GST_DXGI_COLOR_SPACE_RGB_STUDIO_G24_NONE_P709 = 20,
192 GST_DXGI_COLOR_SPACE_RGB_STUDIO_G24_NONE_P2020 = 21,
193 GST_DXGI_COLOR_SPACE_YCBCR_STUDIO_G24_LEFT_P709 = 22,
194 GST_DXGI_COLOR_SPACE_YCBCR_STUDIO_G24_LEFT_P2020 = 23,
195 GST_DXGI_COLOR_SPACE_YCBCR_STUDIO_G24_TOPLEFT_P2020 = 24,
196 GST_DXGI_COLOR_SPACE_CUSTOM = 0xFFFFFFFF
197 } GST_DXGI_COLOR_SPACE_TYPE;
199 /* https://docs.microsoft.com/en-us/windows/win32/api/dxgicommon/ne-dxgicommon-dxgi_color_space_type */
201 #define MAKE_COLOR_MAP(d,r,m,t,p) \
202 { GST_DXGI_COLOR_SPACE_ ##d, GST_VIDEO_COLOR_RANGE ##r, \
203 GST_VIDEO_COLOR_MATRIX_ ##m, GST_VIDEO_TRANSFER_ ##t, \
204 GST_VIDEO_COLOR_PRIMARIES_ ##p }
206 static const GstDxgiColorSpace rgb_colorspace_map[] = {
207 /* 1) DXGI_COLOR_SPACE_RGB_FULL_G22_NONE_P709
208 * 2) DXGI_COLOR_SPACE_RGB_FULL_G10_NONE_P709
209 * 3) DXGI_COLOR_SPACE_RGB_STUDIO_G22_NONE_P709
210 * 4) DXGI_COLOR_SPACE_RGB_STUDIO_G22_NONE_P2020
211 * 5) DXGI_COLOR_SPACE_RGB_FULL_G2084_NONE_P2020
212 * 6) DXGI_COLOR_SPACE_RGB_STUDIO_G2084_NONE_P2020
213 * 7) DXGI_COLOR_SPACE_RGB_FULL_G22_NONE_P2020
214 * 8) DXGI_COLOR_SPACE_RGB_STUDIO_G24_NONE_P709
215 * 9) DXGI_COLOR_SPACE_RGB_STUDIO_G24_NONE_P2020
217 * NOTE: if G24 (Gamma 2.4, SRGB) transfer is not defined,
218 * it will be approximated as G22.
219 * NOTE: BT470BG ~= BT709
222 /* 1) RGB_FULL_G22_NONE_P709 */
223 MAKE_COLOR_MAP (RGB_FULL_G22_NONE_P709, _0_255, UNKNOWN, BT709, BT709),
224 MAKE_COLOR_MAP (RGB_FULL_G22_NONE_P709, _0_255, UNKNOWN, BT601, BT709),
225 MAKE_COLOR_MAP (RGB_FULL_G22_NONE_P709, _0_255, UNKNOWN, BT2020_10, BT709),
226 MAKE_COLOR_MAP (RGB_FULL_G22_NONE_P709, _0_255, UNKNOWN, BT2020_12, BT709),
227 MAKE_COLOR_MAP (RGB_FULL_G22_NONE_P709, _0_255, UNKNOWN, BT709, BT470BG),
228 MAKE_COLOR_MAP (RGB_FULL_G22_NONE_P709, _0_255, UNKNOWN, BT601, BT470BG),
229 MAKE_COLOR_MAP (RGB_FULL_G22_NONE_P709, _0_255, UNKNOWN, BT2020_10, BT470BG),
230 MAKE_COLOR_MAP (RGB_FULL_G22_NONE_P709, _0_255, UNKNOWN, BT2020_12, BT470BG),
232 /* 1-1) Approximation for RGB_FULL_G22_NONE_P709 */
233 MAKE_COLOR_MAP (RGB_FULL_G22_NONE_P709, _0_255, UNKNOWN, SRGB, BT709),
234 MAKE_COLOR_MAP (RGB_FULL_G22_NONE_P709, _0_255, UNKNOWN, SRGB, BT470BG),
236 /* 2) RGB_FULL_G10_NONE_P709 */
237 MAKE_COLOR_MAP (RGB_FULL_G10_NONE_P709, _0_255, UNKNOWN, GAMMA10, BT709),
238 MAKE_COLOR_MAP (RGB_FULL_G10_NONE_P709, _0_255, UNKNOWN, GAMMA10, BT470BG),
240 /* 3) RGB_STUDIO_G22_NONE_P709 */
241 MAKE_COLOR_MAP (RGB_STUDIO_G22_NONE_P709, _16_235, UNKNOWN, BT709, BT709),
242 MAKE_COLOR_MAP (RGB_STUDIO_G22_NONE_P709, _16_235, UNKNOWN, BT601, BT709),
243 MAKE_COLOR_MAP (RGB_STUDIO_G22_NONE_P709, _16_235, UNKNOWN, BT2020_10, BT709),
244 MAKE_COLOR_MAP (RGB_STUDIO_G22_NONE_P709, _16_235, UNKNOWN, BT2020_12, BT709),
245 MAKE_COLOR_MAP (RGB_STUDIO_G22_NONE_P709, _16_235, UNKNOWN, BT709, BT470BG),
246 MAKE_COLOR_MAP (RGB_STUDIO_G22_NONE_P709, _16_235, UNKNOWN, BT601, BT470BG),
247 MAKE_COLOR_MAP (RGB_STUDIO_G22_NONE_P709, _16_235, UNKNOWN, BT2020_10,
249 MAKE_COLOR_MAP (RGB_STUDIO_G22_NONE_P709, _16_235, UNKNOWN, BT2020_12,
252 /* 3-1) Approximation for RGB_STUDIO_G22_NONE_P709 */
253 MAKE_COLOR_MAP (RGB_STUDIO_G22_NONE_P709, _16_235, UNKNOWN, SRGB, BT709),
254 MAKE_COLOR_MAP (RGB_STUDIO_G22_NONE_P709, _16_235, UNKNOWN, SRGB, BT470BG),
256 /* 4) RGB_STUDIO_G22_NONE_P2020 */
257 MAKE_COLOR_MAP (RGB_STUDIO_G22_NONE_P2020, _16_235, UNKNOWN, BT709, BT2020),
258 MAKE_COLOR_MAP (RGB_STUDIO_G22_NONE_P2020, _16_235, UNKNOWN, BT601, BT2020),
259 MAKE_COLOR_MAP (RGB_STUDIO_G22_NONE_P2020, _16_235, UNKNOWN, BT2020_10,
261 MAKE_COLOR_MAP (RGB_STUDIO_G22_NONE_P2020, _16_235, UNKNOWN, BT2020_12,
264 /* 5) RGB_FULL_G2084_NONE_P2020 */
265 MAKE_COLOR_MAP (RGB_FULL_G2084_NONE_P2020, _0_255, UNKNOWN, SMPTE2084,
268 /* 6) RGB_STUDIO_G2084_NONE_P2020 */
269 MAKE_COLOR_MAP (RGB_STUDIO_G2084_NONE_P2020, _16_235, UNKNOWN, SMPTE2084,
272 /* 7) RGB_FULL_G22_NONE_P2020 */
273 MAKE_COLOR_MAP (RGB_FULL_G22_NONE_P2020, _0_255, UNKNOWN, BT709, BT2020),
274 MAKE_COLOR_MAP (RGB_FULL_G22_NONE_P2020, _0_255, UNKNOWN, BT601, BT2020),
275 MAKE_COLOR_MAP (RGB_FULL_G22_NONE_P2020, _0_255, UNKNOWN, BT2020_10, BT2020),
276 MAKE_COLOR_MAP (RGB_FULL_G22_NONE_P2020, _0_255, UNKNOWN, BT2020_12, BT2020),
278 /* 7-1) Approximation for RGB_FULL_G22_NONE_P2020 */
279 MAKE_COLOR_MAP (RGB_FULL_G22_NONE_P2020, _0_255, UNKNOWN, SRGB, BT2020),
281 /* 8) RGB_STUDIO_G24_NONE_P709 */
282 MAKE_COLOR_MAP (RGB_STUDIO_G24_NONE_P709, _16_235, UNKNOWN, SRGB, BT709),
283 MAKE_COLOR_MAP (RGB_STUDIO_G24_NONE_P709, _16_235, UNKNOWN, SRGB, BT470BG),
285 /* 9) RGB_STUDIO_G24_NONE_P2020 */
286 MAKE_COLOR_MAP (RGB_STUDIO_G24_NONE_P2020, _16_235, UNKNOWN, SRGB, BT2020),
289 static const GstDxgiColorSpace yuv_colorspace_map[] = {
290 /* 1) YCBCR_FULL_G22_NONE_P709_X601
291 * 2) YCBCR_STUDIO_G22_LEFT_P601
292 * 3) YCBCR_FULL_G22_LEFT_P601
293 * 4) YCBCR_STUDIO_G22_LEFT_P709
294 * 5) YCBCR_FULL_G22_LEFT_P709
295 * 6) YCBCR_STUDIO_G22_LEFT_P2020
296 * 7) YCBCR_FULL_G22_LEFT_P2020
297 * 8) YCBCR_STUDIO_G2084_LEFT_P2020
298 * 9) YCBCR_STUDIO_G22_TOPLEFT_P2020
299 * 10) YCBCR_STUDIO_G2084_TOPLEFT_P2020
300 * 11) YCBCR_STUDIO_GHLG_TOPLEFT_P2020
301 * 12) YCBCR_FULL_GHLG_TOPLEFT_P2020
302 * 13) YCBCR_STUDIO_G24_LEFT_P709
303 * 14) YCBCR_STUDIO_G24_LEFT_P2020
304 * 15) YCBCR_STUDIO_G24_TOPLEFT_P2020
306 * NOTE: BT470BG ~= BT709
309 /* 1) YCBCR_FULL_G22_NONE_P709_X601 */
310 MAKE_COLOR_MAP (YCBCR_FULL_G22_NONE_P709_X601, _0_255, BT601, BT709, BT709),
311 MAKE_COLOR_MAP (YCBCR_FULL_G22_NONE_P709_X601, _0_255, BT601, BT601, BT709),
312 MAKE_COLOR_MAP (YCBCR_FULL_G22_NONE_P709_X601, _0_255, BT601, BT2020_10,
314 MAKE_COLOR_MAP (YCBCR_FULL_G22_NONE_P709_X601, _0_255, BT601, BT2020_12,
316 MAKE_COLOR_MAP (YCBCR_FULL_G22_NONE_P709_X601, _0_255, BT601, BT709, BT470BG),
317 MAKE_COLOR_MAP (YCBCR_FULL_G22_NONE_P709_X601, _0_255, BT601, BT601, BT470BG),
318 MAKE_COLOR_MAP (YCBCR_FULL_G22_NONE_P709_X601, _0_255, BT601, BT2020_10,
320 MAKE_COLOR_MAP (YCBCR_FULL_G22_NONE_P709_X601, _0_255, BT601, BT2020_12,
323 /* 2) YCBCR_STUDIO_G22_LEFT_P601 */
324 MAKE_COLOR_MAP (YCBCR_STUDIO_G22_LEFT_P601, _16_235, BT601, BT601, SMPTE170M),
325 MAKE_COLOR_MAP (YCBCR_STUDIO_G22_LEFT_P601, _16_235, BT601, BT709, SMPTE170M),
326 MAKE_COLOR_MAP (YCBCR_STUDIO_G22_LEFT_P601, _16_235, BT601, BT2020_10,
328 MAKE_COLOR_MAP (YCBCR_STUDIO_G22_LEFT_P601, _16_235, BT601, BT2020_12,
330 MAKE_COLOR_MAP (YCBCR_STUDIO_G22_LEFT_P601, _16_235, BT601, BT601, SMPTE240M),
331 MAKE_COLOR_MAP (YCBCR_STUDIO_G22_LEFT_P601, _16_235, BT601, BT709, SMPTE240M),
332 MAKE_COLOR_MAP (YCBCR_STUDIO_G22_LEFT_P601, _16_235, BT601, BT2020_10,
334 MAKE_COLOR_MAP (YCBCR_STUDIO_G22_LEFT_P601, _16_235, BT601, BT2020_12,
337 /* 3) YCBCR_FULL_G22_LEFT_P601 */
338 MAKE_COLOR_MAP (YCBCR_FULL_G22_LEFT_P601, _0_255, BT601, BT601, SMPTE170M),
339 MAKE_COLOR_MAP (YCBCR_FULL_G22_LEFT_P601, _0_255, BT601, BT709, SMPTE170M),
340 MAKE_COLOR_MAP (YCBCR_FULL_G22_LEFT_P601, _0_255, BT601, BT2020_10,
342 MAKE_COLOR_MAP (YCBCR_FULL_G22_LEFT_P601, _0_255, BT601, BT2020_12,
344 MAKE_COLOR_MAP (YCBCR_FULL_G22_LEFT_P601, _0_255, BT601, BT601, SMPTE240M),
345 MAKE_COLOR_MAP (YCBCR_FULL_G22_LEFT_P601, _0_255, BT601, BT709, SMPTE240M),
346 MAKE_COLOR_MAP (YCBCR_FULL_G22_LEFT_P601, _0_255, BT601, BT2020_10,
348 MAKE_COLOR_MAP (YCBCR_FULL_G22_LEFT_P601, _0_255, BT601, BT2020_12,
351 /* 4) YCBCR_STUDIO_G22_LEFT_P709 */
352 MAKE_COLOR_MAP (YCBCR_STUDIO_G22_LEFT_P709, _16_235, BT709, BT709, BT709),
353 MAKE_COLOR_MAP (YCBCR_STUDIO_G22_LEFT_P709, _16_235, BT709, BT601, BT709),
354 MAKE_COLOR_MAP (YCBCR_STUDIO_G22_LEFT_P709, _16_235, BT709, BT2020_10,
356 MAKE_COLOR_MAP (YCBCR_STUDIO_G22_LEFT_P709, _16_235, BT709, BT2020_12,
358 MAKE_COLOR_MAP (YCBCR_STUDIO_G22_LEFT_P709, _16_235, BT709, BT709, BT470BG),
359 MAKE_COLOR_MAP (YCBCR_STUDIO_G22_LEFT_P709, _16_235, BT709, BT601, BT470BG),
360 MAKE_COLOR_MAP (YCBCR_STUDIO_G22_LEFT_P709, _16_235, BT709, BT2020_10,
362 MAKE_COLOR_MAP (YCBCR_STUDIO_G22_LEFT_P709, _16_235, BT709, BT2020_12,
365 /* 5) YCBCR_FULL_G22_LEFT_P709 */
366 MAKE_COLOR_MAP (YCBCR_FULL_G22_LEFT_P709, _0_255, BT709, BT709, BT709),
367 MAKE_COLOR_MAP (YCBCR_FULL_G22_LEFT_P709, _0_255, BT709, BT601, BT709),
368 MAKE_COLOR_MAP (YCBCR_FULL_G22_LEFT_P709, _0_255, BT709, BT2020_10, BT709),
369 MAKE_COLOR_MAP (YCBCR_FULL_G22_LEFT_P709, _0_255, BT709, BT2020_12, BT709),
370 MAKE_COLOR_MAP (YCBCR_FULL_G22_LEFT_P709, _0_255, BT709, BT709, BT470BG),
371 MAKE_COLOR_MAP (YCBCR_FULL_G22_LEFT_P709, _0_255, BT709, BT601, BT470BG),
372 MAKE_COLOR_MAP (YCBCR_FULL_G22_LEFT_P709, _0_255, BT709, BT2020_10, BT470BG),
373 MAKE_COLOR_MAP (YCBCR_FULL_G22_LEFT_P709, _0_255, BT709, BT2020_12, BT470BG),
375 /* 6) YCBCR_STUDIO_G22_LEFT_P2020 */
376 MAKE_COLOR_MAP (YCBCR_STUDIO_G22_LEFT_P2020, _16_235, BT2020, BT709, BT2020),
377 MAKE_COLOR_MAP (YCBCR_STUDIO_G22_LEFT_P2020, _16_235, BT2020, BT601, BT2020),
378 MAKE_COLOR_MAP (YCBCR_STUDIO_G22_LEFT_P2020, _16_235, BT2020, BT2020_10,
380 MAKE_COLOR_MAP (YCBCR_STUDIO_G22_LEFT_P2020, _16_235, BT2020, BT2020_12,
383 /* 7) YCBCR_FULL_G22_LEFT_P2020 */
384 MAKE_COLOR_MAP (YCBCR_FULL_G22_LEFT_P2020, _0_255, BT2020, BT709, BT2020),
385 MAKE_COLOR_MAP (YCBCR_FULL_G22_LEFT_P2020, _0_255, BT2020, BT601, BT2020),
386 MAKE_COLOR_MAP (YCBCR_FULL_G22_LEFT_P2020, _0_255, BT2020, BT2020_10,
388 MAKE_COLOR_MAP (YCBCR_FULL_G22_LEFT_P2020, _0_255, BT2020, BT2020_12,
391 /* 8) YCBCR_STUDIO_G2084_LEFT_P2020 */
392 MAKE_COLOR_MAP (YCBCR_STUDIO_G2084_LEFT_P2020, _16_235, BT2020, SMPTE2084,
395 /* 9) YCBCR_STUDIO_G22_TOPLEFT_P2020 */
396 MAKE_COLOR_MAP (YCBCR_STUDIO_G22_TOPLEFT_P2020, _16_235, BT2020, BT2020_10,
398 MAKE_COLOR_MAP (YCBCR_STUDIO_G22_TOPLEFT_P2020, _16_235, BT2020, BT2020_12,
401 /* 10) YCBCR_STUDIO_G2084_TOPLEFT_P2020 */
402 /* FIXME: check chroma-site to differentiate this from
403 * YCBCR_STUDIO_G2084_LEFT_P2020 */
404 MAKE_COLOR_MAP (YCBCR_STUDIO_G2084_TOPLEFT_P2020, _16_235, BT2020, SMPTE2084,
407 /* 11) YCBCR_STUDIO_GHLG_TOPLEFT_P2020 */
408 MAKE_COLOR_MAP (YCBCR_STUDIO_GHLG_TOPLEFT_P2020, _16_235, BT2020,
409 ARIB_STD_B67, BT2020),
411 /* 12) YCBCR_FULL_GHLG_TOPLEFT_P2020 */
412 MAKE_COLOR_MAP (YCBCR_FULL_GHLG_TOPLEFT_P2020, _0_255, BT2020, ARIB_STD_B67,
415 /* 13) YCBCR_STUDIO_G24_LEFT_P709 */
416 MAKE_COLOR_MAP (YCBCR_STUDIO_G24_LEFT_P709, _16_235, BT709, SRGB, BT709),
418 /* 14) YCBCR_STUDIO_G24_LEFT_P2020 */
419 MAKE_COLOR_MAP (YCBCR_STUDIO_G24_LEFT_P2020, _16_235, BT2020, SRGB, BT2020),
421 /* 15) YCBCR_STUDIO_G24_TOPLEFT_P2020 */
422 /* FIXME: check chroma-site to differentiate this from
423 * YCBCR_STUDIO_G24_LEFT_P2020 */
424 MAKE_COLOR_MAP (YCBCR_STUDIO_G24_TOPLEFT_P2020, _16_235, BT2020, SRGB,
428 #define SCORE_RANGE_MISMATCH 5
429 #define SCORE_MATRIX_MISMATCH 5
430 #define SCORE_TRANSFER_MISMATCH 5
431 #define SCORE_PRIMARY_MISMATCH 10
434 get_score (GstVideoInfo * info, const GstDxgiColorSpace * color_map,
438 GstVideoColorimetry *color = &info->colorimetry;
440 if (color->range != color_map->range)
441 loss += SCORE_RANGE_MISMATCH;
443 if (is_yuv && color->matrix != color_map->matrix)
444 loss += SCORE_MATRIX_MISMATCH;
446 if (color->transfer != color_map->transfer)
447 loss += SCORE_TRANSFER_MISMATCH;
449 if (color->primaries != color_map->primaries)
450 loss += SCORE_PRIMARY_MISMATCH;
455 static const GstDxgiColorSpace *
456 gst_d3d11_video_info_to_dxgi_color_space_rgb (GstVideoInfo * info)
458 gint best_score = G_MAXINT;
461 const GstDxgiColorSpace *colorspace = NULL;
463 for (i = 0; i < G_N_ELEMENTS (rgb_colorspace_map); i++) {
464 score = get_score (info, &rgb_colorspace_map[i], FALSE);
466 if (score < best_score) {
468 colorspace = &rgb_colorspace_map[i];
478 static const GstDxgiColorSpace *
479 gst_d3d11_video_info_to_dxgi_color_space_yuv (GstVideoInfo * info)
481 gint best_score = G_MAXINT;
484 const GstDxgiColorSpace *colorspace = NULL;
486 for (i = 0; i < G_N_ELEMENTS (yuv_colorspace_map); i++) {
487 score = get_score (info, &yuv_colorspace_map[i], TRUE);
489 if (score < best_score) {
491 colorspace = &yuv_colorspace_map[i];
501 const GstDxgiColorSpace *
502 gst_d3d11_video_info_to_dxgi_color_space (GstVideoInfo * info)
504 g_return_val_if_fail (info != NULL, NULL);
506 if (GST_VIDEO_INFO_IS_RGB (info)) {
507 return gst_d3d11_video_info_to_dxgi_color_space_rgb (info);
508 } else if (GST_VIDEO_INFO_IS_YUV (info)) {
509 return gst_d3d11_video_info_to_dxgi_color_space_yuv (info);
515 const GstDxgiColorSpace *
516 gst_d3d11_find_swap_chain_color_space (GstVideoInfo * info,
517 IDXGISwapChain3 * swapchain, gboolean use_hdr10)
519 const GstDxgiColorSpace *colorspace = NULL;
520 gint best_score = G_MAXINT;
523 g_return_val_if_fail (info != NULL, FALSE);
524 g_return_val_if_fail (swapchain != NULL, FALSE);
526 if (!GST_VIDEO_INFO_IS_RGB (info)) {
527 GST_WARNING ("Swapchain colorspace should be RGB format");
531 for (i = 0; i < G_N_ELEMENTS (rgb_colorspace_map); i++) {
532 UINT can_support = 0;
535 DXGI_COLOR_SPACE_TYPE cur_type =
536 (DXGI_COLOR_SPACE_TYPE) rgb_colorspace_map[i].dxgi_color_space_type;
538 /* FIXME: Non-HDR colorspace with BT2020 primaries will break rendering.
539 * https://gitlab.freedesktop.org/gstreamer/gst-plugins-bad/issues/1175
540 * To workaround it, BT709 colorspace will be chosen for non-HDR case.
543 rgb_colorspace_map[i].primaries == GST_VIDEO_COLOR_PRIMARIES_BT2020)
546 hr = swapchain->CheckColorSpaceSupport (cur_type, &can_support);
551 if ((can_support & DXGI_SWAP_CHAIN_COLOR_SPACE_SUPPORT_FLAG_PRESENT) ==
552 DXGI_SWAP_CHAIN_COLOR_SPACE_SUPPORT_FLAG_PRESENT) {
553 score = get_score (info, &rgb_colorspace_map[i], FALSE);
555 GST_DEBUG ("colorspace %d supported, score %d", cur_type, score);
557 if (score < best_score) {
559 colorspace = &rgb_colorspace_map[i];
569 fill_staging_desc (const D3D11_TEXTURE2D_DESC * ref,
570 D3D11_TEXTURE2D_DESC * staging)
572 memset (staging, 0, sizeof (D3D11_TEXTURE2D_DESC));
574 staging->Width = ref->Width;
575 staging->Height = ref->Height;
576 staging->MipLevels = 1;
577 staging->Format = ref->Format;
578 staging->SampleDesc.Count = 1;
579 staging->ArraySize = 1;
580 staging->Usage = D3D11_USAGE_STAGING;
581 staging->CPUAccessFlags = (D3D11_CPU_ACCESS_READ | D3D11_CPU_ACCESS_WRITE);
585 gst_d3d11_allocate_staging_buffer_for (GstBuffer * buffer,
586 const GstVideoInfo * info, gboolean add_videometa)
588 GstD3D11Memory *dmem;
589 GstD3D11Device *device;
590 GstD3D11Allocator *alloc = NULL;
591 GstBuffer *staging_buffer = NULL;
592 gint stride[GST_VIDEO_MAX_PLANES] = { 0, };
593 gsize offset[GST_VIDEO_MAX_PLANES] = { 0, };
596 const GstD3D11Format *format;
597 D3D11_TEXTURE2D_DESC desc;
599 for (i = 0; i < gst_buffer_n_memory (buffer); i++) {
600 GstMemory *mem = gst_buffer_peek_memory (buffer, i);
602 if (!gst_is_d3d11_memory (mem)) {
603 GST_DEBUG ("Not a d3d11 memory");
609 dmem = (GstD3D11Memory *) gst_buffer_peek_memory (buffer, 0);
610 device = dmem->device;
611 format = gst_d3d11_device_format_from_gst (device,
612 GST_VIDEO_INFO_FORMAT (info));
614 GST_ERROR ("Unknown d3d11 format");
618 alloc = (GstD3D11Allocator *) gst_allocator_find (GST_D3D11_MEMORY_NAME);
620 GST_ERROR ("D3D11 allocator is not available");
624 staging_buffer = gst_buffer_new ();
625 for (i = 0; i < gst_buffer_n_memory (buffer); i++) {
626 D3D11_TEXTURE2D_DESC staging_desc;
627 GstD3D11Memory *mem = (GstD3D11Memory *) gst_buffer_peek_memory (buffer, i);
628 GstD3D11Memory *new_mem;
630 guint cur_stride = 0;
632 gst_d3d11_memory_get_texture_desc (mem, &desc);
633 fill_staging_desc (&desc, &staging_desc);
635 new_mem = (GstD3D11Memory *)
636 gst_d3d11_allocator_alloc (alloc, mem->device, &staging_desc);
638 GST_ERROR ("Failed to allocate memory");
642 if (!gst_d3d11_memory_get_texture_stride (new_mem, &cur_stride) ||
643 cur_stride < staging_desc.Width) {
644 GST_ERROR ("Failed to calculate memory size");
645 gst_memory_unref (GST_MEMORY_CAST (mem));
650 stride[i] = cur_stride;
651 size += GST_MEMORY_CAST (new_mem)->size;
653 gst_buffer_append_memory (staging_buffer, GST_MEMORY_CAST (new_mem));
656 /* single texture semi-planar formats */
657 if (format->dxgi_format != DXGI_FORMAT_UNKNOWN &&
658 GST_VIDEO_INFO_N_PLANES (info) == 2) {
659 stride[1] = stride[0];
660 offset[1] = stride[0] * desc.Height;
663 gst_buffer_add_video_meta_full (staging_buffer, GST_VIDEO_FRAME_FLAG_NONE,
664 GST_VIDEO_INFO_FORMAT (info), GST_VIDEO_INFO_WIDTH (info),
665 GST_VIDEO_INFO_HEIGHT (info), GST_VIDEO_INFO_N_PLANES (info),
669 gst_object_unref (alloc);
671 return staging_buffer;
674 gst_clear_buffer (&staging_buffer);
675 gst_clear_object (&alloc);
681 gst_d3d11_buffer_copy_into_fallback (GstBuffer * dst, GstBuffer * src,
682 const GstVideoInfo * info)
684 GstVideoFrame in_frame, out_frame;
687 if (!gst_video_frame_map (&in_frame, (GstVideoInfo *) info, src,
688 (GstMapFlags) (GST_MAP_READ | GST_VIDEO_FRAME_MAP_FLAG_NO_REF)))
691 if (!gst_video_frame_map (&out_frame, (GstVideoInfo *) info, dst,
692 (GstMapFlags) (GST_MAP_WRITE | GST_VIDEO_FRAME_MAP_FLAG_NO_REF))) {
693 gst_video_frame_unmap (&in_frame);
697 ret = gst_video_frame_copy (&out_frame, &in_frame);
699 gst_video_frame_unmap (&in_frame);
700 gst_video_frame_unmap (&out_frame);
707 GST_ERROR ("Invalid video buffer");
713 gst_d3d11_buffer_copy_into (GstBuffer * dst, GstBuffer * src,
714 const GstVideoInfo * info)
718 g_return_val_if_fail (GST_IS_BUFFER (dst), FALSE);
719 g_return_val_if_fail (GST_IS_BUFFER (src), FALSE);
720 g_return_val_if_fail (info != NULL, FALSE);
722 if (gst_buffer_n_memory (dst) != gst_buffer_n_memory (src)) {
723 GST_LOG ("different memory layout, perform fallback copy");
724 return gst_d3d11_buffer_copy_into_fallback (dst, src, info);
727 if (!gst_is_d3d11_buffer (dst) || !gst_is_d3d11_buffer (src)) {
728 GST_LOG ("non-d3d11 memory, perform fallback copy");
729 return gst_d3d11_buffer_copy_into_fallback (dst, src, info);
732 for (i = 0; i < gst_buffer_n_memory (dst); i++) {
733 GstMemory *dst_mem, *src_mem;
734 GstD3D11Memory *dst_dmem, *src_dmem;
737 ID3D11Resource *dst_texture, *src_texture;
738 ID3D11DeviceContext *device_context;
739 GstD3D11Device *device;
740 D3D11_BOX src_box = { 0, };
741 D3D11_TEXTURE2D_DESC dst_desc, src_desc;
742 guint dst_subidx, src_subidx;
744 dst_mem = gst_buffer_peek_memory (dst, i);
745 src_mem = gst_buffer_peek_memory (src, i);
747 dst_dmem = (GstD3D11Memory *) dst_mem;
748 src_dmem = (GstD3D11Memory *) src_mem;
750 device = dst_dmem->device;
751 if (device != src_dmem->device) {
752 GST_LOG ("different device, perform fallback copy");
753 return gst_d3d11_buffer_copy_into_fallback (dst, src, info);
756 gst_d3d11_memory_get_texture_desc (dst_dmem, &dst_desc);
757 gst_d3d11_memory_get_texture_desc (src_dmem, &src_desc);
759 if (dst_desc.Format != src_desc.Format) {
760 GST_WARNING ("different dxgi format");
764 device_context = gst_d3d11_device_get_device_context_handle (device);
766 if (!gst_memory_map (dst_mem, &dst_info,
767 (GstMapFlags) (GST_MAP_WRITE | GST_MAP_D3D11))) {
768 GST_ERROR ("Cannot map dst d3d11 memory");
772 if (!gst_memory_map (src_mem, &src_info,
773 (GstMapFlags) (GST_MAP_READ | GST_MAP_D3D11))) {
774 GST_ERROR ("Cannot map src d3d11 memory");
775 gst_memory_unmap (dst_mem, &dst_info);
779 dst_texture = (ID3D11Resource *) dst_info.data;
780 src_texture = (ID3D11Resource *) src_info.data;
782 /* src/dst texture size might be different if padding was used.
783 * select smaller size */
788 src_box.right = MIN (src_desc.Width, dst_desc.Width);
789 src_box.bottom = MIN (src_desc.Height, dst_desc.Height);
791 dst_subidx = gst_d3d11_memory_get_subresource_index (dst_dmem);
792 src_subidx = gst_d3d11_memory_get_subresource_index (src_dmem);
794 gst_d3d11_device_lock (device);
795 device_context->CopySubresourceRegion (dst_texture, dst_subidx, 0, 0, 0,
796 src_texture, src_subidx, &src_box);
797 gst_d3d11_device_unlock (device);
799 gst_memory_unmap (src_mem, &src_info);
800 gst_memory_unmap (dst_mem, &dst_info);
807 gst_is_d3d11_buffer (GstBuffer * buffer)
812 g_return_val_if_fail (GST_IS_BUFFER (buffer), FALSE);
814 size = gst_buffer_n_memory (buffer);
818 for (i = 0; i < size; i++) {
819 GstMemory *mem = gst_buffer_peek_memory (buffer, i);
821 if (!gst_is_d3d11_memory (mem))
829 gst_d3d11_buffer_can_access_device (GstBuffer * buffer, ID3D11Device * device)
833 g_return_val_if_fail (GST_IS_BUFFER (buffer), FALSE);
834 g_return_val_if_fail (device != NULL, FALSE);
836 if (!gst_is_d3d11_buffer (buffer)) {
837 GST_LOG ("Not a d3d11 buffer");
841 for (i = 0; i < gst_buffer_n_memory (buffer); i++) {
842 GstD3D11Memory *mem = (GstD3D11Memory *) gst_buffer_peek_memory (buffer, i);
843 ID3D11Device *handle;
845 handle = gst_d3d11_device_get_device_handle (mem->device);
846 if (handle != device) {
847 GST_LOG ("D3D11 device is incompatible");
856 gst_d3d11_buffer_map (GstBuffer * buffer, ID3D11Device * device,
857 GstMapInfo info[GST_VIDEO_MAX_PLANES], GstMapFlags flags)
859 GstMapFlags map_flags;
860 guint num_mapped = 0;
862 g_return_val_if_fail (GST_IS_BUFFER (buffer), FALSE);
863 g_return_val_if_fail (info != NULL, FALSE);
865 if (!gst_d3d11_buffer_can_access_device (buffer, device))
868 map_flags = (GstMapFlags) (flags | GST_MAP_D3D11);
870 for (num_mapped = 0; num_mapped < gst_buffer_n_memory (buffer); num_mapped++) {
871 GstMemory *mem = gst_buffer_peek_memory (buffer, num_mapped);
873 if (!gst_memory_map (mem, &info[num_mapped], map_flags)) {
874 GST_ERROR ("Couldn't map memory");
884 for (i = 0; i < num_mapped; i++) {
885 GstMemory *mem = gst_buffer_peek_memory (buffer, i);
886 gst_memory_unmap (mem, &info[i]);
894 gst_d3d11_buffer_unmap (GstBuffer * buffer,
895 GstMapInfo info[GST_VIDEO_MAX_PLANES])
899 g_return_val_if_fail (GST_IS_BUFFER (buffer), FALSE);
900 g_return_val_if_fail (info != NULL, FALSE);
902 for (i = 0; i < gst_buffer_n_memory (buffer); i++) {
903 GstMemory *mem = gst_buffer_peek_memory (buffer, i);
905 gst_memory_unmap (mem, &info[i]);
912 gst_d3d11_buffer_get_shader_resource_view (GstBuffer * buffer,
913 ID3D11ShaderResourceView * view[GST_VIDEO_MAX_PLANES])
918 g_return_val_if_fail (GST_IS_BUFFER (buffer), 0);
919 g_return_val_if_fail (view != NULL, 0);
921 if (!gst_is_d3d11_buffer (buffer)) {
922 GST_ERROR ("Buffer contains non-d3d11 memory");
926 for (i = 0; i < gst_buffer_n_memory (buffer); i++) {
927 GstD3D11Memory *mem = (GstD3D11Memory *) gst_buffer_peek_memory (buffer, i);
931 view_size = gst_d3d11_memory_get_shader_resource_view_size (mem);
933 GST_LOG ("SRV is unavailable for memory index %d", i);
937 for (j = 0; j < view_size; j++) {
938 if (num_views >= GST_VIDEO_MAX_PLANES) {
939 GST_ERROR ("Too many SRVs");
943 view[num_views++] = gst_d3d11_memory_get_shader_resource_view (mem, j);
951 gst_d3d11_buffer_get_render_target_view (GstBuffer * buffer,
952 ID3D11RenderTargetView * view[GST_VIDEO_MAX_PLANES])
957 g_return_val_if_fail (GST_IS_BUFFER (buffer), 0);
958 g_return_val_if_fail (view != NULL, 0);
960 if (!gst_is_d3d11_buffer (buffer)) {
961 GST_ERROR ("Buffer contains non-d3d11 memory");
965 for (i = 0; i < gst_buffer_n_memory (buffer); i++) {
966 GstD3D11Memory *mem = (GstD3D11Memory *) gst_buffer_peek_memory (buffer, i);
970 view_size = gst_d3d11_memory_get_render_target_view_size (mem);
972 GST_LOG ("RTV is unavailable for memory index %d", i);
976 for (j = 0; j < view_size; j++) {
977 if (num_views >= GST_VIDEO_MAX_PLANES) {
978 GST_ERROR ("Too many RTVs");
982 view[num_views++] = gst_d3d11_memory_get_render_target_view (mem, j);
990 gst_d3d11_buffer_pool_new_with_options (GstD3D11Device * device,
991 GstCaps * caps, GstD3D11AllocationParams * alloc_params,
992 guint min_buffers, guint max_buffers)
995 GstStructure *config;
998 g_return_val_if_fail (GST_IS_D3D11_DEVICE (device), NULL);
999 g_return_val_if_fail (GST_IS_CAPS (caps), NULL);
1000 g_return_val_if_fail (alloc_params != NULL, NULL);
1002 if (!gst_video_info_from_caps (&info, caps)) {
1003 GST_ERROR_OBJECT (device, "invalid caps");
1007 pool = gst_d3d11_buffer_pool_new (device);
1008 config = gst_buffer_pool_get_config (pool);
1009 gst_buffer_pool_config_set_params (config,
1010 caps, GST_VIDEO_INFO_SIZE (&info), min_buffers, max_buffers);
1012 gst_buffer_pool_config_set_d3d11_allocation_params (config, alloc_params);
1014 gst_buffer_pool_config_add_option (config, GST_BUFFER_POOL_OPTION_VIDEO_META);
1015 if (!gst_buffer_pool_set_config (pool, config)) {
1016 GST_ERROR_OBJECT (pool, "Couldn't set config");
1017 gst_object_unref (pool);