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;
137 gst_d3d11_hdr_meta_data_to_dxgi (GstVideoMasteringDisplayInfo * minfo,
138 GstVideoContentLightLevel * cll, DXGI_HDR_METADATA_HDR10 * dxgi_hdr10)
140 g_return_val_if_fail (dxgi_hdr10 != NULL, FALSE);
142 memset (dxgi_hdr10, 0, sizeof (DXGI_HDR_METADATA_HDR10));
145 dxgi_hdr10->RedPrimary[0] = minfo->display_primaries[0].x;
146 dxgi_hdr10->RedPrimary[1] = minfo->display_primaries[0].y;
147 dxgi_hdr10->GreenPrimary[0] = minfo->display_primaries[1].x;
148 dxgi_hdr10->GreenPrimary[1] = minfo->display_primaries[1].y;
149 dxgi_hdr10->BluePrimary[0] = minfo->display_primaries[2].x;
150 dxgi_hdr10->BluePrimary[1] = minfo->display_primaries[2].y;
152 dxgi_hdr10->WhitePoint[0] = minfo->white_point.x;
153 dxgi_hdr10->WhitePoint[1] = minfo->white_point.y;
154 dxgi_hdr10->MaxMasteringLuminance = minfo->max_display_mastering_luminance;
155 dxgi_hdr10->MinMasteringLuminance = minfo->min_display_mastering_luminance;
159 dxgi_hdr10->MaxContentLightLevel = cll->max_content_light_level;
160 dxgi_hdr10->MaxFrameAverageLightLevel = cll->max_frame_average_light_level;
168 GST_DXGI_COLOR_SPACE_RGB_FULL_G22_NONE_P709 = 0,
169 GST_DXGI_COLOR_SPACE_RGB_FULL_G10_NONE_P709 = 1,
170 GST_DXGI_COLOR_SPACE_RGB_STUDIO_G22_NONE_P709 = 2,
171 GST_DXGI_COLOR_SPACE_RGB_STUDIO_G22_NONE_P2020 = 3,
172 GST_DXGI_COLOR_SPACE_RESERVED = 4,
173 GST_DXGI_COLOR_SPACE_YCBCR_FULL_G22_NONE_P709_X601 = 5,
174 GST_DXGI_COLOR_SPACE_YCBCR_STUDIO_G22_LEFT_P601 = 6,
175 GST_DXGI_COLOR_SPACE_YCBCR_FULL_G22_LEFT_P601 = 7,
176 GST_DXGI_COLOR_SPACE_YCBCR_STUDIO_G22_LEFT_P709 = 8,
177 GST_DXGI_COLOR_SPACE_YCBCR_FULL_G22_LEFT_P709 = 9,
178 GST_DXGI_COLOR_SPACE_YCBCR_STUDIO_G22_LEFT_P2020 = 10,
179 GST_DXGI_COLOR_SPACE_YCBCR_FULL_G22_LEFT_P2020 = 11,
180 GST_DXGI_COLOR_SPACE_RGB_FULL_G2084_NONE_P2020 = 12,
181 GST_DXGI_COLOR_SPACE_YCBCR_STUDIO_G2084_LEFT_P2020 = 13,
182 GST_DXGI_COLOR_SPACE_RGB_STUDIO_G2084_NONE_P2020 = 14,
183 GST_DXGI_COLOR_SPACE_YCBCR_STUDIO_G22_TOPLEFT_P2020 = 15,
184 GST_DXGI_COLOR_SPACE_YCBCR_STUDIO_G2084_TOPLEFT_P2020 = 16,
185 GST_DXGI_COLOR_SPACE_RGB_FULL_G22_NONE_P2020 = 17,
186 GST_DXGI_COLOR_SPACE_YCBCR_STUDIO_GHLG_TOPLEFT_P2020 = 18,
187 GST_DXGI_COLOR_SPACE_YCBCR_FULL_GHLG_TOPLEFT_P2020 = 19,
188 GST_DXGI_COLOR_SPACE_RGB_STUDIO_G24_NONE_P709 = 20,
189 GST_DXGI_COLOR_SPACE_RGB_STUDIO_G24_NONE_P2020 = 21,
190 GST_DXGI_COLOR_SPACE_YCBCR_STUDIO_G24_LEFT_P709 = 22,
191 GST_DXGI_COLOR_SPACE_YCBCR_STUDIO_G24_LEFT_P2020 = 23,
192 GST_DXGI_COLOR_SPACE_YCBCR_STUDIO_G24_TOPLEFT_P2020 = 24,
193 GST_DXGI_COLOR_SPACE_CUSTOM = 0xFFFFFFFF
194 } GST_DXGI_COLOR_SPACE_TYPE;
196 /* https://docs.microsoft.com/en-us/windows/win32/api/dxgicommon/ne-dxgicommon-dxgi_color_space_type */
198 #define MAKE_COLOR_MAP(d,r,m,t,p) \
199 { GST_DXGI_COLOR_SPACE_ ##d, GST_VIDEO_COLOR_RANGE ##r, \
200 GST_VIDEO_COLOR_MATRIX_ ##m, GST_VIDEO_TRANSFER_ ##t, \
201 GST_VIDEO_COLOR_PRIMARIES_ ##p }
203 static const GstDxgiColorSpace rgb_colorspace_map[] = {
204 /* 1) DXGI_COLOR_SPACE_RGB_FULL_G22_NONE_P709
205 * 2) DXGI_COLOR_SPACE_RGB_FULL_G10_NONE_P709
206 * 3) DXGI_COLOR_SPACE_RGB_STUDIO_G22_NONE_P709
207 * 4) DXGI_COLOR_SPACE_RGB_STUDIO_G22_NONE_P2020
208 * 5) DXGI_COLOR_SPACE_RGB_FULL_G2084_NONE_P2020
209 * 6) DXGI_COLOR_SPACE_RGB_STUDIO_G2084_NONE_P2020
210 * 7) DXGI_COLOR_SPACE_RGB_FULL_G22_NONE_P2020
211 * 8) DXGI_COLOR_SPACE_RGB_STUDIO_G24_NONE_P709
212 * 9) DXGI_COLOR_SPACE_RGB_STUDIO_G24_NONE_P2020
214 * NOTE: if G24 (Gamma 2.4, SRGB) transfer is not defined,
215 * it will be approximated as G22.
216 * NOTE: BT470BG ~= BT709
219 /* 1) RGB_FULL_G22_NONE_P709 */
220 MAKE_COLOR_MAP (RGB_FULL_G22_NONE_P709, _0_255, UNKNOWN, BT709, BT709),
221 MAKE_COLOR_MAP (RGB_FULL_G22_NONE_P709, _0_255, UNKNOWN, BT601, BT709),
222 MAKE_COLOR_MAP (RGB_FULL_G22_NONE_P709, _0_255, UNKNOWN, BT2020_10, BT709),
223 MAKE_COLOR_MAP (RGB_FULL_G22_NONE_P709, _0_255, UNKNOWN, BT2020_12, BT709),
224 MAKE_COLOR_MAP (RGB_FULL_G22_NONE_P709, _0_255, UNKNOWN, BT709, BT470BG),
225 MAKE_COLOR_MAP (RGB_FULL_G22_NONE_P709, _0_255, UNKNOWN, BT601, BT470BG),
226 MAKE_COLOR_MAP (RGB_FULL_G22_NONE_P709, _0_255, UNKNOWN, BT2020_10, BT470BG),
227 MAKE_COLOR_MAP (RGB_FULL_G22_NONE_P709, _0_255, UNKNOWN, BT2020_12, BT470BG),
229 /* 1-1) Approximation for RGB_FULL_G22_NONE_P709 */
230 MAKE_COLOR_MAP (RGB_FULL_G22_NONE_P709, _0_255, UNKNOWN, SRGB, BT709),
231 MAKE_COLOR_MAP (RGB_FULL_G22_NONE_P709, _0_255, UNKNOWN, SRGB, BT470BG),
233 /* 2) RGB_FULL_G10_NONE_P709 */
234 MAKE_COLOR_MAP (RGB_FULL_G10_NONE_P709, _0_255, UNKNOWN, GAMMA10, BT709),
235 MAKE_COLOR_MAP (RGB_FULL_G10_NONE_P709, _0_255, UNKNOWN, GAMMA10, BT470BG),
237 /* 3) RGB_STUDIO_G22_NONE_P709 */
238 MAKE_COLOR_MAP (RGB_STUDIO_G22_NONE_P709, _16_235, UNKNOWN, BT709, BT709),
239 MAKE_COLOR_MAP (RGB_STUDIO_G22_NONE_P709, _16_235, UNKNOWN, BT601, BT709),
240 MAKE_COLOR_MAP (RGB_STUDIO_G22_NONE_P709, _16_235, UNKNOWN, BT2020_10, BT709),
241 MAKE_COLOR_MAP (RGB_STUDIO_G22_NONE_P709, _16_235, UNKNOWN, BT2020_12, BT709),
242 MAKE_COLOR_MAP (RGB_STUDIO_G22_NONE_P709, _16_235, UNKNOWN, BT709, BT470BG),
243 MAKE_COLOR_MAP (RGB_STUDIO_G22_NONE_P709, _16_235, UNKNOWN, BT601, BT470BG),
244 MAKE_COLOR_MAP (RGB_STUDIO_G22_NONE_P709, _16_235, UNKNOWN, BT2020_10,
246 MAKE_COLOR_MAP (RGB_STUDIO_G22_NONE_P709, _16_235, UNKNOWN, BT2020_12,
249 /* 3-1) Approximation for RGB_STUDIO_G22_NONE_P709 */
250 MAKE_COLOR_MAP (RGB_STUDIO_G22_NONE_P709, _16_235, UNKNOWN, SRGB, BT709),
251 MAKE_COLOR_MAP (RGB_STUDIO_G22_NONE_P709, _16_235, UNKNOWN, SRGB, BT470BG),
253 /* 4) RGB_STUDIO_G22_NONE_P2020 */
254 MAKE_COLOR_MAP (RGB_STUDIO_G22_NONE_P2020, _16_235, UNKNOWN, BT709, BT2020),
255 MAKE_COLOR_MAP (RGB_STUDIO_G22_NONE_P2020, _16_235, UNKNOWN, BT601, BT2020),
256 MAKE_COLOR_MAP (RGB_STUDIO_G22_NONE_P2020, _16_235, UNKNOWN, BT2020_10,
258 MAKE_COLOR_MAP (RGB_STUDIO_G22_NONE_P2020, _16_235, UNKNOWN, BT2020_12,
261 /* 5) RGB_FULL_G2084_NONE_P2020 */
262 MAKE_COLOR_MAP (RGB_FULL_G2084_NONE_P2020, _0_255, UNKNOWN, SMPTE2084,
265 /* 6) RGB_STUDIO_G2084_NONE_P2020 */
266 MAKE_COLOR_MAP (RGB_STUDIO_G2084_NONE_P2020, _16_235, UNKNOWN, SMPTE2084,
269 /* 7) RGB_FULL_G22_NONE_P2020 */
270 MAKE_COLOR_MAP (RGB_FULL_G22_NONE_P2020, _0_255, UNKNOWN, BT709, BT2020),
271 MAKE_COLOR_MAP (RGB_FULL_G22_NONE_P2020, _0_255, UNKNOWN, BT601, BT2020),
272 MAKE_COLOR_MAP (RGB_FULL_G22_NONE_P2020, _0_255, UNKNOWN, BT2020_10, BT2020),
273 MAKE_COLOR_MAP (RGB_FULL_G22_NONE_P2020, _0_255, UNKNOWN, BT2020_12, BT2020),
275 /* 7-1) Approximation for RGB_FULL_G22_NONE_P2020 */
276 MAKE_COLOR_MAP (RGB_FULL_G22_NONE_P2020, _0_255, UNKNOWN, SRGB, BT2020),
278 /* 8) RGB_STUDIO_G24_NONE_P709 */
279 MAKE_COLOR_MAP (RGB_STUDIO_G24_NONE_P709, _16_235, UNKNOWN, SRGB, BT709),
280 MAKE_COLOR_MAP (RGB_STUDIO_G24_NONE_P709, _16_235, UNKNOWN, SRGB, BT470BG),
282 /* 9) RGB_STUDIO_G24_NONE_P2020 */
283 MAKE_COLOR_MAP (RGB_STUDIO_G24_NONE_P2020, _16_235, UNKNOWN, SRGB, BT2020),
286 static const GstDxgiColorSpace yuv_colorspace_map[] = {
287 /* 1) YCBCR_FULL_G22_NONE_P709_X601
288 * 2) YCBCR_STUDIO_G22_LEFT_P601
289 * 3) YCBCR_FULL_G22_LEFT_P601
290 * 4) YCBCR_STUDIO_G22_LEFT_P709
291 * 5) YCBCR_FULL_G22_LEFT_P709
292 * 6) YCBCR_STUDIO_G22_LEFT_P2020
293 * 7) YCBCR_FULL_G22_LEFT_P2020
294 * 8) YCBCR_STUDIO_G2084_LEFT_P2020
295 * 9) YCBCR_STUDIO_G22_TOPLEFT_P2020
296 * 10) YCBCR_STUDIO_G2084_TOPLEFT_P2020
297 * 11) YCBCR_STUDIO_GHLG_TOPLEFT_P2020
298 * 12) YCBCR_FULL_GHLG_TOPLEFT_P2020
299 * 13) YCBCR_STUDIO_G24_LEFT_P709
300 * 14) YCBCR_STUDIO_G24_LEFT_P2020
301 * 15) YCBCR_STUDIO_G24_TOPLEFT_P2020
303 * NOTE: BT470BG ~= BT709
306 /* 1) YCBCR_FULL_G22_NONE_P709_X601 */
307 MAKE_COLOR_MAP (YCBCR_FULL_G22_NONE_P709_X601, _0_255, BT601, BT709, BT709),
308 MAKE_COLOR_MAP (YCBCR_FULL_G22_NONE_P709_X601, _0_255, BT601, BT601, BT709),
309 MAKE_COLOR_MAP (YCBCR_FULL_G22_NONE_P709_X601, _0_255, BT601, BT2020_10,
311 MAKE_COLOR_MAP (YCBCR_FULL_G22_NONE_P709_X601, _0_255, BT601, BT2020_12,
313 MAKE_COLOR_MAP (YCBCR_FULL_G22_NONE_P709_X601, _0_255, BT601, BT709, BT470BG),
314 MAKE_COLOR_MAP (YCBCR_FULL_G22_NONE_P709_X601, _0_255, BT601, BT601, BT470BG),
315 MAKE_COLOR_MAP (YCBCR_FULL_G22_NONE_P709_X601, _0_255, BT601, BT2020_10,
317 MAKE_COLOR_MAP (YCBCR_FULL_G22_NONE_P709_X601, _0_255, BT601, BT2020_12,
320 /* 2) YCBCR_STUDIO_G22_LEFT_P601 */
321 MAKE_COLOR_MAP (YCBCR_STUDIO_G22_LEFT_P601, _16_235, BT601, BT601, SMPTE170M),
322 MAKE_COLOR_MAP (YCBCR_STUDIO_G22_LEFT_P601, _16_235, BT601, BT709, SMPTE170M),
323 MAKE_COLOR_MAP (YCBCR_STUDIO_G22_LEFT_P601, _16_235, BT601, BT2020_10,
325 MAKE_COLOR_MAP (YCBCR_STUDIO_G22_LEFT_P601, _16_235, BT601, BT2020_12,
327 MAKE_COLOR_MAP (YCBCR_STUDIO_G22_LEFT_P601, _16_235, BT601, BT601, SMPTE240M),
328 MAKE_COLOR_MAP (YCBCR_STUDIO_G22_LEFT_P601, _16_235, BT601, BT709, SMPTE240M),
329 MAKE_COLOR_MAP (YCBCR_STUDIO_G22_LEFT_P601, _16_235, BT601, BT2020_10,
331 MAKE_COLOR_MAP (YCBCR_STUDIO_G22_LEFT_P601, _16_235, BT601, BT2020_12,
334 /* 3) YCBCR_FULL_G22_LEFT_P601 */
335 MAKE_COLOR_MAP (YCBCR_FULL_G22_LEFT_P601, _0_255, BT601, BT601, SMPTE170M),
336 MAKE_COLOR_MAP (YCBCR_FULL_G22_LEFT_P601, _0_255, BT601, BT709, SMPTE170M),
337 MAKE_COLOR_MAP (YCBCR_FULL_G22_LEFT_P601, _0_255, BT601, BT2020_10,
339 MAKE_COLOR_MAP (YCBCR_FULL_G22_LEFT_P601, _0_255, BT601, BT2020_12,
341 MAKE_COLOR_MAP (YCBCR_FULL_G22_LEFT_P601, _0_255, BT601, BT601, SMPTE240M),
342 MAKE_COLOR_MAP (YCBCR_FULL_G22_LEFT_P601, _0_255, BT601, BT709, SMPTE240M),
343 MAKE_COLOR_MAP (YCBCR_FULL_G22_LEFT_P601, _0_255, BT601, BT2020_10,
345 MAKE_COLOR_MAP (YCBCR_FULL_G22_LEFT_P601, _0_255, BT601, BT2020_12,
348 /* 4) YCBCR_STUDIO_G22_LEFT_P709 */
349 MAKE_COLOR_MAP (YCBCR_STUDIO_G22_LEFT_P709, _16_235, BT709, BT709, BT709),
350 MAKE_COLOR_MAP (YCBCR_STUDIO_G22_LEFT_P709, _16_235, BT709, BT601, BT709),
351 MAKE_COLOR_MAP (YCBCR_STUDIO_G22_LEFT_P709, _16_235, BT709, BT2020_10,
353 MAKE_COLOR_MAP (YCBCR_STUDIO_G22_LEFT_P709, _16_235, BT709, BT2020_12,
355 MAKE_COLOR_MAP (YCBCR_STUDIO_G22_LEFT_P709, _16_235, BT709, BT709, BT470BG),
356 MAKE_COLOR_MAP (YCBCR_STUDIO_G22_LEFT_P709, _16_235, BT709, BT601, BT470BG),
357 MAKE_COLOR_MAP (YCBCR_STUDIO_G22_LEFT_P709, _16_235, BT709, BT2020_10,
359 MAKE_COLOR_MAP (YCBCR_STUDIO_G22_LEFT_P709, _16_235, BT709, BT2020_12,
362 /* 5) YCBCR_FULL_G22_LEFT_P709 */
363 MAKE_COLOR_MAP (YCBCR_FULL_G22_LEFT_P709, _0_255, BT709, BT709, BT709),
364 MAKE_COLOR_MAP (YCBCR_FULL_G22_LEFT_P709, _0_255, BT709, BT601, BT709),
365 MAKE_COLOR_MAP (YCBCR_FULL_G22_LEFT_P709, _0_255, BT709, BT2020_10, BT709),
366 MAKE_COLOR_MAP (YCBCR_FULL_G22_LEFT_P709, _0_255, BT709, BT2020_12, BT709),
367 MAKE_COLOR_MAP (YCBCR_FULL_G22_LEFT_P709, _0_255, BT709, BT709, BT470BG),
368 MAKE_COLOR_MAP (YCBCR_FULL_G22_LEFT_P709, _0_255, BT709, BT601, BT470BG),
369 MAKE_COLOR_MAP (YCBCR_FULL_G22_LEFT_P709, _0_255, BT709, BT2020_10, BT470BG),
370 MAKE_COLOR_MAP (YCBCR_FULL_G22_LEFT_P709, _0_255, BT709, BT2020_12, BT470BG),
372 /* 6) YCBCR_STUDIO_G22_LEFT_P2020 */
373 MAKE_COLOR_MAP (YCBCR_STUDIO_G22_LEFT_P2020, _16_235, BT2020, BT709, BT2020),
374 MAKE_COLOR_MAP (YCBCR_STUDIO_G22_LEFT_P2020, _16_235, BT2020, BT601, BT2020),
375 MAKE_COLOR_MAP (YCBCR_STUDIO_G22_LEFT_P2020, _16_235, BT2020, BT2020_10,
377 MAKE_COLOR_MAP (YCBCR_STUDIO_G22_LEFT_P2020, _16_235, BT2020, BT2020_12,
380 /* 7) YCBCR_FULL_G22_LEFT_P2020 */
381 MAKE_COLOR_MAP (YCBCR_FULL_G22_LEFT_P2020, _0_255, BT2020, BT709, BT2020),
382 MAKE_COLOR_MAP (YCBCR_FULL_G22_LEFT_P2020, _0_255, BT2020, BT601, BT2020),
383 MAKE_COLOR_MAP (YCBCR_FULL_G22_LEFT_P2020, _0_255, BT2020, BT2020_10,
385 MAKE_COLOR_MAP (YCBCR_FULL_G22_LEFT_P2020, _0_255, BT2020, BT2020_12,
388 /* 8) YCBCR_STUDIO_G2084_LEFT_P2020 */
389 MAKE_COLOR_MAP (YCBCR_STUDIO_G2084_LEFT_P2020, _16_235, BT2020, SMPTE2084,
392 /* 9) YCBCR_STUDIO_G22_TOPLEFT_P2020 */
393 MAKE_COLOR_MAP (YCBCR_STUDIO_G22_TOPLEFT_P2020, _16_235, BT2020, BT2020_10,
395 MAKE_COLOR_MAP (YCBCR_STUDIO_G22_TOPLEFT_P2020, _16_235, BT2020, BT2020_12,
398 /* 10) YCBCR_STUDIO_G2084_TOPLEFT_P2020 */
399 /* FIXME: check chroma-site to differentiate this from
400 * YCBCR_STUDIO_G2084_LEFT_P2020 */
401 MAKE_COLOR_MAP (YCBCR_STUDIO_G2084_TOPLEFT_P2020, _16_235, BT2020, SMPTE2084,
404 /* 11) YCBCR_STUDIO_GHLG_TOPLEFT_P2020 */
405 MAKE_COLOR_MAP (YCBCR_STUDIO_GHLG_TOPLEFT_P2020, _16_235, BT2020,
406 ARIB_STD_B67, BT2020),
408 /* 12) YCBCR_FULL_GHLG_TOPLEFT_P2020 */
409 MAKE_COLOR_MAP (YCBCR_FULL_GHLG_TOPLEFT_P2020, _0_255, BT2020, ARIB_STD_B67,
412 /* 13) YCBCR_STUDIO_G24_LEFT_P709 */
413 MAKE_COLOR_MAP (YCBCR_STUDIO_G24_LEFT_P709, _16_235, BT709, SRGB, BT709),
415 /* 14) YCBCR_STUDIO_G24_LEFT_P2020 */
416 MAKE_COLOR_MAP (YCBCR_STUDIO_G24_LEFT_P2020, _16_235, BT2020, SRGB, BT2020),
418 /* 15) YCBCR_STUDIO_G24_TOPLEFT_P2020 */
419 /* FIXME: check chroma-site to differentiate this from
420 * YCBCR_STUDIO_G24_LEFT_P2020 */
421 MAKE_COLOR_MAP (YCBCR_STUDIO_G24_TOPLEFT_P2020, _16_235, BT2020, SRGB,
425 #define SCORE_RANGE_MISMATCH 5
426 #define SCORE_MATRIX_MISMATCH 5
427 #define SCORE_TRANSFER_MISMATCH 5
428 #define SCORE_PRIMARY_MISMATCH 10
431 get_score (GstVideoInfo * info, const GstDxgiColorSpace * color_map,
435 GstVideoColorimetry *color = &info->colorimetry;
437 if (color->range != color_map->range)
438 loss += SCORE_RANGE_MISMATCH;
440 if (is_yuv && color->matrix != color_map->matrix)
441 loss += SCORE_MATRIX_MISMATCH;
443 if (color->transfer != color_map->transfer)
444 loss += SCORE_TRANSFER_MISMATCH;
446 if (color->primaries != color_map->primaries)
447 loss += SCORE_PRIMARY_MISMATCH;
452 static const GstDxgiColorSpace *
453 gst_d3d11_video_info_to_dxgi_color_space_rgb (GstVideoInfo * info)
455 gint best_score = G_MAXINT;
458 const GstDxgiColorSpace *colorspace = NULL;
460 for (i = 0; i < G_N_ELEMENTS (rgb_colorspace_map); i++) {
461 score = get_score (info, &rgb_colorspace_map[i], FALSE);
463 if (score < best_score) {
465 colorspace = &rgb_colorspace_map[i];
475 static const GstDxgiColorSpace *
476 gst_d3d11_video_info_to_dxgi_color_space_yuv (GstVideoInfo * info)
478 gint best_score = G_MAXINT;
481 const GstDxgiColorSpace *colorspace = NULL;
483 for (i = 0; i < G_N_ELEMENTS (yuv_colorspace_map); i++) {
484 score = get_score (info, &yuv_colorspace_map[i], TRUE);
486 if (score < best_score) {
488 colorspace = &yuv_colorspace_map[i];
498 const GstDxgiColorSpace *
499 gst_d3d11_video_info_to_dxgi_color_space (GstVideoInfo * info)
501 g_return_val_if_fail (info != NULL, NULL);
503 if (GST_VIDEO_INFO_IS_RGB (info)) {
504 return gst_d3d11_video_info_to_dxgi_color_space_rgb (info);
505 } else if (GST_VIDEO_INFO_IS_YUV (info)) {
506 return gst_d3d11_video_info_to_dxgi_color_space_yuv (info);
512 const GstDxgiColorSpace *
513 gst_d3d11_find_swap_chain_color_space (GstVideoInfo * info,
514 IDXGISwapChain3 * swapchain)
516 const GstDxgiColorSpace *colorspace = NULL;
517 gint best_score = G_MAXINT;
519 /* list of tested display color spaces */
520 static GST_DXGI_COLOR_SPACE_TYPE whitelist[] = {
521 GST_DXGI_COLOR_SPACE_RGB_FULL_G22_NONE_P709,
522 GST_DXGI_COLOR_SPACE_RGB_FULL_G10_NONE_P709,
523 GST_DXGI_COLOR_SPACE_RGB_FULL_G2084_NONE_P2020,
526 g_return_val_if_fail (info != NULL, FALSE);
527 g_return_val_if_fail (swapchain != NULL, FALSE);
529 if (!GST_VIDEO_INFO_IS_RGB (info)) {
530 GST_WARNING ("Swapchain colorspace should be RGB format");
534 for (i = 0; i < G_N_ELEMENTS (rgb_colorspace_map); i++) {
535 UINT can_support = 0;
538 gboolean valid = FALSE;
539 GST_DXGI_COLOR_SPACE_TYPE cur_type =
540 (GST_DXGI_COLOR_SPACE_TYPE) rgb_colorspace_map[i].dxgi_color_space_type;
542 for (guint j = 0; j < G_N_ELEMENTS (whitelist); j++) {
543 if (whitelist[j] == cur_type) {
552 hr = swapchain->CheckColorSpaceSupport ((DXGI_COLOR_SPACE_TYPE) cur_type,
558 if ((can_support & DXGI_SWAP_CHAIN_COLOR_SPACE_SUPPORT_FLAG_PRESENT) ==
559 DXGI_SWAP_CHAIN_COLOR_SPACE_SUPPORT_FLAG_PRESENT) {
560 score = get_score (info, &rgb_colorspace_map[i], FALSE);
562 GST_DEBUG ("colorspace %d supported, score %d", cur_type, score);
564 if (score < best_score) {
566 colorspace = &rgb_colorspace_map[i];
575 fill_staging_desc (const D3D11_TEXTURE2D_DESC * ref,
576 D3D11_TEXTURE2D_DESC * staging)
578 memset (staging, 0, sizeof (D3D11_TEXTURE2D_DESC));
580 staging->Width = ref->Width;
581 staging->Height = ref->Height;
582 staging->MipLevels = 1;
583 staging->Format = ref->Format;
584 staging->SampleDesc.Count = 1;
585 staging->ArraySize = 1;
586 staging->Usage = D3D11_USAGE_STAGING;
587 staging->CPUAccessFlags = (D3D11_CPU_ACCESS_READ | D3D11_CPU_ACCESS_WRITE);
591 gst_d3d11_allocate_staging_buffer_for (GstBuffer * buffer,
592 const GstVideoInfo * info, gboolean add_videometa)
594 GstD3D11Memory *dmem;
595 GstD3D11Device *device;
596 GstD3D11Allocator *alloc = NULL;
597 GstBuffer *staging_buffer = NULL;
598 gint stride[GST_VIDEO_MAX_PLANES] = { 0, };
599 gsize offset[GST_VIDEO_MAX_PLANES] = { 0, };
602 const GstD3D11Format *format;
603 D3D11_TEXTURE2D_DESC desc;
605 for (i = 0; i < gst_buffer_n_memory (buffer); i++) {
606 GstMemory *mem = gst_buffer_peek_memory (buffer, i);
608 if (!gst_is_d3d11_memory (mem)) {
609 GST_DEBUG ("Not a d3d11 memory");
615 dmem = (GstD3D11Memory *) gst_buffer_peek_memory (buffer, 0);
616 device = dmem->device;
617 format = gst_d3d11_device_format_from_gst (device,
618 GST_VIDEO_INFO_FORMAT (info));
620 GST_ERROR ("Unknown d3d11 format");
624 alloc = (GstD3D11Allocator *) gst_allocator_find (GST_D3D11_MEMORY_NAME);
626 GST_ERROR ("D3D11 allocator is not available");
630 staging_buffer = gst_buffer_new ();
631 for (i = 0; i < gst_buffer_n_memory (buffer); i++) {
632 D3D11_TEXTURE2D_DESC staging_desc;
633 GstD3D11Memory *mem = (GstD3D11Memory *) gst_buffer_peek_memory (buffer, i);
634 GstD3D11Memory *new_mem;
636 guint cur_stride = 0;
638 gst_d3d11_memory_get_texture_desc (mem, &desc);
639 fill_staging_desc (&desc, &staging_desc);
641 new_mem = (GstD3D11Memory *)
642 gst_d3d11_allocator_alloc (alloc, mem->device, &staging_desc);
644 GST_ERROR ("Failed to allocate memory");
648 if (!gst_d3d11_memory_get_resource_stride (new_mem, &cur_stride) ||
649 cur_stride < staging_desc.Width) {
650 GST_ERROR ("Failed to calculate memory size");
651 gst_memory_unref (GST_MEMORY_CAST (mem));
656 stride[i] = cur_stride;
657 size += GST_MEMORY_CAST (new_mem)->size;
659 gst_buffer_append_memory (staging_buffer, GST_MEMORY_CAST (new_mem));
662 /* single texture semi-planar formats */
663 if (format->dxgi_format != DXGI_FORMAT_UNKNOWN &&
664 GST_VIDEO_INFO_N_PLANES (info) == 2) {
665 stride[1] = stride[0];
666 offset[1] = stride[0] * desc.Height;
669 gst_buffer_add_video_meta_full (staging_buffer, GST_VIDEO_FRAME_FLAG_NONE,
670 GST_VIDEO_INFO_FORMAT (info), GST_VIDEO_INFO_WIDTH (info),
671 GST_VIDEO_INFO_HEIGHT (info), GST_VIDEO_INFO_N_PLANES (info),
675 gst_object_unref (alloc);
677 return staging_buffer;
680 gst_clear_buffer (&staging_buffer);
681 gst_clear_object (&alloc);
687 gst_d3d11_buffer_copy_into_fallback (GstBuffer * dst, GstBuffer * src,
688 const GstVideoInfo * info)
690 GstVideoFrame in_frame, out_frame;
693 if (!gst_video_frame_map (&in_frame, (GstVideoInfo *) info, src,
694 (GstMapFlags) (GST_MAP_READ | GST_VIDEO_FRAME_MAP_FLAG_NO_REF)))
697 if (!gst_video_frame_map (&out_frame, (GstVideoInfo *) info, dst,
698 (GstMapFlags) (GST_MAP_WRITE | GST_VIDEO_FRAME_MAP_FLAG_NO_REF))) {
699 gst_video_frame_unmap (&in_frame);
703 ret = gst_video_frame_copy (&out_frame, &in_frame);
705 gst_video_frame_unmap (&in_frame);
706 gst_video_frame_unmap (&out_frame);
713 GST_ERROR ("Invalid video buffer");
719 gst_d3d11_buffer_copy_into (GstBuffer * dst, GstBuffer * src,
720 const GstVideoInfo * info)
724 g_return_val_if_fail (GST_IS_BUFFER (dst), FALSE);
725 g_return_val_if_fail (GST_IS_BUFFER (src), FALSE);
726 g_return_val_if_fail (info != NULL, FALSE);
728 if (gst_buffer_n_memory (dst) != gst_buffer_n_memory (src)) {
729 GST_LOG ("different memory layout, perform fallback copy");
730 return gst_d3d11_buffer_copy_into_fallback (dst, src, info);
733 if (!gst_is_d3d11_buffer (dst) || !gst_is_d3d11_buffer (src)) {
734 GST_LOG ("non-d3d11 memory, perform fallback copy");
735 return gst_d3d11_buffer_copy_into_fallback (dst, src, info);
738 for (i = 0; i < gst_buffer_n_memory (dst); i++) {
739 GstMemory *dst_mem, *src_mem;
740 GstD3D11Memory *dst_dmem, *src_dmem;
743 ID3D11Resource *dst_texture, *src_texture;
744 ID3D11DeviceContext *device_context;
745 GstD3D11Device *device;
746 D3D11_BOX src_box = { 0, };
747 D3D11_TEXTURE2D_DESC dst_desc, src_desc;
748 guint dst_subidx, src_subidx;
750 dst_mem = gst_buffer_peek_memory (dst, i);
751 src_mem = gst_buffer_peek_memory (src, i);
753 dst_dmem = (GstD3D11Memory *) dst_mem;
754 src_dmem = (GstD3D11Memory *) src_mem;
756 device = dst_dmem->device;
757 if (device != src_dmem->device) {
758 GST_LOG ("different device, perform fallback copy");
759 return gst_d3d11_buffer_copy_into_fallback (dst, src, info);
762 gst_d3d11_memory_get_texture_desc (dst_dmem, &dst_desc);
763 gst_d3d11_memory_get_texture_desc (src_dmem, &src_desc);
765 if (dst_desc.Format != src_desc.Format) {
766 GST_WARNING ("different dxgi format");
770 device_context = gst_d3d11_device_get_device_context_handle (device);
772 if (!gst_memory_map (dst_mem, &dst_info,
773 (GstMapFlags) (GST_MAP_WRITE | GST_MAP_D3D11))) {
774 GST_ERROR ("Cannot map dst d3d11 memory");
778 if (!gst_memory_map (src_mem, &src_info,
779 (GstMapFlags) (GST_MAP_READ | GST_MAP_D3D11))) {
780 GST_ERROR ("Cannot map src d3d11 memory");
781 gst_memory_unmap (dst_mem, &dst_info);
785 dst_texture = (ID3D11Resource *) dst_info.data;
786 src_texture = (ID3D11Resource *) src_info.data;
788 /* src/dst texture size might be different if padding was used.
789 * select smaller size */
794 src_box.right = MIN (src_desc.Width, dst_desc.Width);
795 src_box.bottom = MIN (src_desc.Height, dst_desc.Height);
797 dst_subidx = gst_d3d11_memory_get_subresource_index (dst_dmem);
798 src_subidx = gst_d3d11_memory_get_subresource_index (src_dmem);
800 gst_d3d11_device_lock (device);
801 device_context->CopySubresourceRegion (dst_texture, dst_subidx, 0, 0, 0,
802 src_texture, src_subidx, &src_box);
803 gst_d3d11_device_unlock (device);
805 gst_memory_unmap (src_mem, &src_info);
806 gst_memory_unmap (dst_mem, &dst_info);
813 gst_is_d3d11_buffer (GstBuffer * buffer)
818 g_return_val_if_fail (GST_IS_BUFFER (buffer), FALSE);
820 size = gst_buffer_n_memory (buffer);
824 for (i = 0; i < size; i++) {
825 GstMemory *mem = gst_buffer_peek_memory (buffer, i);
827 if (!gst_is_d3d11_memory (mem))
835 gst_d3d11_buffer_can_access_device (GstBuffer * buffer, ID3D11Device * device)
839 g_return_val_if_fail (GST_IS_BUFFER (buffer), FALSE);
840 g_return_val_if_fail (device != NULL, FALSE);
842 if (!gst_is_d3d11_buffer (buffer)) {
843 GST_LOG ("Not a d3d11 buffer");
847 for (i = 0; i < gst_buffer_n_memory (buffer); i++) {
848 GstD3D11Memory *mem = (GstD3D11Memory *) gst_buffer_peek_memory (buffer, i);
849 ID3D11Device *handle;
851 handle = gst_d3d11_device_get_device_handle (mem->device);
852 if (handle != device) {
853 GST_LOG ("D3D11 device is incompatible");
862 gst_d3d11_buffer_map (GstBuffer * buffer, ID3D11Device * device,
863 GstMapInfo info[GST_VIDEO_MAX_PLANES], GstMapFlags flags)
865 GstMapFlags map_flags;
866 guint num_mapped = 0;
868 g_return_val_if_fail (GST_IS_BUFFER (buffer), FALSE);
869 g_return_val_if_fail (info != NULL, FALSE);
871 if (!gst_d3d11_buffer_can_access_device (buffer, device))
874 map_flags = (GstMapFlags) (flags | GST_MAP_D3D11);
876 for (num_mapped = 0; num_mapped < gst_buffer_n_memory (buffer); num_mapped++) {
877 GstMemory *mem = gst_buffer_peek_memory (buffer, num_mapped);
879 if (!gst_memory_map (mem, &info[num_mapped], map_flags)) {
880 GST_ERROR ("Couldn't map memory");
890 for (i = 0; i < num_mapped; i++) {
891 GstMemory *mem = gst_buffer_peek_memory (buffer, i);
892 gst_memory_unmap (mem, &info[i]);
900 gst_d3d11_buffer_unmap (GstBuffer * buffer,
901 GstMapInfo info[GST_VIDEO_MAX_PLANES])
905 g_return_val_if_fail (GST_IS_BUFFER (buffer), FALSE);
906 g_return_val_if_fail (info != NULL, FALSE);
908 for (i = 0; i < gst_buffer_n_memory (buffer); i++) {
909 GstMemory *mem = gst_buffer_peek_memory (buffer, i);
911 gst_memory_unmap (mem, &info[i]);
918 gst_d3d11_buffer_get_shader_resource_view (GstBuffer * buffer,
919 ID3D11ShaderResourceView * view[GST_VIDEO_MAX_PLANES])
924 g_return_val_if_fail (GST_IS_BUFFER (buffer), 0);
925 g_return_val_if_fail (view != NULL, 0);
927 if (!gst_is_d3d11_buffer (buffer)) {
928 GST_ERROR ("Buffer contains non-d3d11 memory");
932 for (i = 0; i < gst_buffer_n_memory (buffer); i++) {
933 GstD3D11Memory *mem = (GstD3D11Memory *) gst_buffer_peek_memory (buffer, i);
937 view_size = gst_d3d11_memory_get_shader_resource_view_size (mem);
939 GST_LOG ("SRV is unavailable for memory index %d", i);
943 for (j = 0; j < view_size; j++) {
944 if (num_views >= GST_VIDEO_MAX_PLANES) {
945 GST_ERROR ("Too many SRVs");
949 view[num_views++] = gst_d3d11_memory_get_shader_resource_view (mem, j);
957 gst_d3d11_buffer_get_render_target_view (GstBuffer * buffer,
958 ID3D11RenderTargetView * view[GST_VIDEO_MAX_PLANES])
963 g_return_val_if_fail (GST_IS_BUFFER (buffer), 0);
964 g_return_val_if_fail (view != NULL, 0);
966 if (!gst_is_d3d11_buffer (buffer)) {
967 GST_ERROR ("Buffer contains non-d3d11 memory");
971 for (i = 0; i < gst_buffer_n_memory (buffer); i++) {
972 GstD3D11Memory *mem = (GstD3D11Memory *) gst_buffer_peek_memory (buffer, i);
976 view_size = gst_d3d11_memory_get_render_target_view_size (mem);
978 GST_LOG ("RTV is unavailable for memory index %d", i);
982 for (j = 0; j < view_size; j++) {
983 if (num_views >= GST_VIDEO_MAX_PLANES) {
984 GST_ERROR ("Too many RTVs");
988 view[num_views++] = gst_d3d11_memory_get_render_target_view (mem, j);
996 gst_d3d11_buffer_pool_new_with_options (GstD3D11Device * device,
997 GstCaps * caps, GstD3D11AllocationParams * alloc_params,
998 guint min_buffers, guint max_buffers)
1000 GstBufferPool *pool;
1001 GstStructure *config;
1004 g_return_val_if_fail (GST_IS_D3D11_DEVICE (device), NULL);
1005 g_return_val_if_fail (GST_IS_CAPS (caps), NULL);
1006 g_return_val_if_fail (alloc_params != NULL, NULL);
1008 if (!gst_video_info_from_caps (&info, caps)) {
1009 GST_ERROR_OBJECT (device, "invalid caps");
1013 pool = gst_d3d11_buffer_pool_new (device);
1014 config = gst_buffer_pool_get_config (pool);
1015 gst_buffer_pool_config_set_params (config,
1016 caps, GST_VIDEO_INFO_SIZE (&info), min_buffers, max_buffers);
1018 gst_buffer_pool_config_set_d3d11_allocation_params (config, alloc_params);
1020 gst_buffer_pool_config_add_option (config, GST_BUFFER_POOL_OPTION_VIDEO_META);
1021 if (!gst_buffer_pool_set_config (pool, config)) {
1022 GST_ERROR_OBJECT (pool, "Couldn't set config");
1023 gst_object_unref (pool);