1 /* GStreamer
2 * Copyright (C) 2019 Seungha Yang <seungha.yang@navercorp.com>
3 * Copyright (C) 2020 Seungha Yang <seungha@centricular.com>
4 *
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.
9 *
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.
14 *
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.
19 */
20
21 #ifdef HAVE_CONFIG_H
22 #include "config.h"
23 #endif
24
25 #include "gstd3d11pluginutils.h"
26
27 #include <windows.h>
28 #include <versionhelpers.h>
29
30 GST_DEBUG_CATEGORY_EXTERN (gst_d3d11_plugin_utils_debug);
31 #define GST_CAT_DEFAULT gst_d3d11_plugin_utils_debug
32
33 /* Max Texture Dimension for feature level 11_0 ~ 12_1 */
34 static guint _gst_d3d11_texture_max_dimension = 16384;
35
36 void
gst_d3d11_plugin_utils_init(D3D_FEATURE_LEVEL feature_level)37 gst_d3d11_plugin_utils_init (D3D_FEATURE_LEVEL feature_level)
38 {
39 static gsize _init_once = 0;
40
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;
47 else
48 _gst_d3d11_texture_max_dimension = 4096;
49
50 g_once_init_leave (&_init_once, 1);
51 }
52 }
53
54 GstCaps *
gst_d3d11_get_updated_template_caps(GstStaticCaps * template_caps)55 gst_d3d11_get_updated_template_caps (GstStaticCaps * template_caps)
56 {
57 GstCaps *caps;
58
59 g_return_val_if_fail (template_caps != NULL, NULL);
60
61 caps = gst_static_caps_get (template_caps);
62 if (!caps) {
63 GST_ERROR ("Couldn't get caps from static caps");
64 return NULL;
65 }
66
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);
71
72 return caps;
73 }
74
75 gboolean
gst_d3d11_is_windows_8_or_greater(void)76 gst_d3d11_is_windows_8_or_greater (void)
77 {
78 static gsize version_once = 0;
79 static gboolean ret = FALSE;
80
81 if (g_once_init_enter (&version_once)) {
82 #if (!GST_D3D11_WINAPI_ONLY_APP)
83 if (IsWindows8OrGreater ())
84 ret = TRUE;
85 #else
86 ret = TRUE;
87 #endif
88
89 g_once_init_leave (&version_once, 1);
90 }
91
92 return ret;
93 }
94
95 GstD3D11DeviceVendor
gst_d3d11_get_device_vendor(GstD3D11Device * device)96 gst_d3d11_get_device_vendor (GstD3D11Device * device)
97 {
98 guint device_id = 0;
99 guint vendor_id = 0;
100 gchar *desc = NULL;
101 GstD3D11DeviceVendor vendor = GST_D3D11_DEVICE_VENDOR_UNKNOWN;
102
103 g_return_val_if_fail (GST_IS_D3D11_DEVICE (device),
104 GST_D3D11_DEVICE_VENDOR_UNKNOWN);
105
106 g_object_get (device, "device-id", &device_id, "vendor-id", &vendor_id,
107 "description", &desc, NULL);
108
109 switch (vendor_id) {
110 case 0:
111 if (device_id == 0 && desc && g_strrstr (desc, "SraKmd"))
112 vendor = GST_D3D11_DEVICE_VENDOR_XBOX;
113 break;
114 case 0x1002:
115 case 0x1022:
116 vendor = GST_D3D11_DEVICE_VENDOR_AMD;
117 break;
118 case 0x8086:
119 vendor = GST_D3D11_DEVICE_VENDOR_INTEL;
120 break;
121 case 0x10de:
122 vendor = GST_D3D11_DEVICE_VENDOR_NVIDIA;
123 break;
124 case 0x4d4f4351:
125 vendor = GST_D3D11_DEVICE_VENDOR_QUALCOMM;
126 break;
127 default:
128 break;
129 }
130
131 g_free (desc);
132
133 return vendor;
134 }
135
136 #if (GST_D3D11_DXGI_HEADER_VERSION >= 5)
137 gboolean
gst_d3d11_hdr_meta_data_to_dxgi(GstVideoMasteringDisplayInfo * minfo,GstVideoContentLightLevel * cll,DXGI_HDR_METADATA_HDR10 * dxgi_hdr10)138 gst_d3d11_hdr_meta_data_to_dxgi (GstVideoMasteringDisplayInfo * minfo,
139 GstVideoContentLightLevel * cll, DXGI_HDR_METADATA_HDR10 * dxgi_hdr10)
140 {
141 g_return_val_if_fail (dxgi_hdr10 != NULL, FALSE);
142
143 memset (dxgi_hdr10, 0, sizeof (DXGI_HDR_METADATA_HDR10));
144
145 if (minfo) {
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;
152
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;
157 }
158
159 if (cll) {
160 dxgi_hdr10->MaxContentLightLevel = cll->max_content_light_level;
161 dxgi_hdr10->MaxFrameAverageLightLevel = cll->max_frame_average_light_level;
162 }
163
164 return TRUE;
165 }
166 #endif
167
168 #if (GST_D3D11_DXGI_HEADER_VERSION >= 4)
169 typedef enum
170 {
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;
198
199 /* https://docs.microsoft.com/en-us/windows/win32/api/dxgicommon/ne-dxgicommon-dxgi_color_space_type */
200
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 }
205
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
216 *
217 * NOTE: if G24 (Gamma 2.4, SRGB) transfer is not defined,
218 * it will be approximated as G22.
219 * NOTE: BT470BG ~= BT709
220 */
221
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),
231
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),
235
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),
239
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,
248 BT470BG),
249 MAKE_COLOR_MAP (RGB_STUDIO_G22_NONE_P709, _16_235, UNKNOWN, BT2020_12,
250 BT470BG),
251
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),
255
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,
260 BT2020),
261 MAKE_COLOR_MAP (RGB_STUDIO_G22_NONE_P2020, _16_235, UNKNOWN, BT2020_12,
262 BT2020),
263
264 /* 5) RGB_FULL_G2084_NONE_P2020 */
265 MAKE_COLOR_MAP (RGB_FULL_G2084_NONE_P2020, _0_255, UNKNOWN, SMPTE2084,
266 BT2020),
267
268 /* 6) RGB_STUDIO_G2084_NONE_P2020 */
269 MAKE_COLOR_MAP (RGB_STUDIO_G2084_NONE_P2020, _16_235, UNKNOWN, SMPTE2084,
270 BT2020),
271
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),
277
278 /* 7-1) Approximation for RGB_FULL_G22_NONE_P2020 */
279 MAKE_COLOR_MAP (RGB_FULL_G22_NONE_P2020, _0_255, UNKNOWN, SRGB, BT2020),
280
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),
284
285 /* 9) RGB_STUDIO_G24_NONE_P2020 */
286 MAKE_COLOR_MAP (RGB_STUDIO_G24_NONE_P2020, _16_235, UNKNOWN, SRGB, BT2020),
287 };
288
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
305 *
306 * NOTE: BT470BG ~= BT709
307 */
308
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,
313 BT709),
314 MAKE_COLOR_MAP (YCBCR_FULL_G22_NONE_P709_X601, _0_255, BT601, BT2020_12,
315 BT709),
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,
319 BT470BG),
320 MAKE_COLOR_MAP (YCBCR_FULL_G22_NONE_P709_X601, _0_255, BT601, BT2020_12,
321 BT470BG),
322
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,
327 SMPTE170M),
328 MAKE_COLOR_MAP (YCBCR_STUDIO_G22_LEFT_P601, _16_235, BT601, BT2020_12,
329 SMPTE170M),
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,
333 SMPTE240M),
334 MAKE_COLOR_MAP (YCBCR_STUDIO_G22_LEFT_P601, _16_235, BT601, BT2020_12,
335 SMPTE240M),
336
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,
341 SMPTE170M),
342 MAKE_COLOR_MAP (YCBCR_FULL_G22_LEFT_P601, _0_255, BT601, BT2020_12,
343 SMPTE170M),
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,
347 SMPTE240M),
348 MAKE_COLOR_MAP (YCBCR_FULL_G22_LEFT_P601, _0_255, BT601, BT2020_12,
349 SMPTE240M),
350
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,
355 BT709),
356 MAKE_COLOR_MAP (YCBCR_STUDIO_G22_LEFT_P709, _16_235, BT709, BT2020_12,
357 BT709),
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,
361 BT470BG),
362 MAKE_COLOR_MAP (YCBCR_STUDIO_G22_LEFT_P709, _16_235, BT709, BT2020_12,
363 BT470BG),
364
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),
374
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,
379 BT2020),
380 MAKE_COLOR_MAP (YCBCR_STUDIO_G22_LEFT_P2020, _16_235, BT2020, BT2020_12,
381 BT2020),
382
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,
387 BT2020),
388 MAKE_COLOR_MAP (YCBCR_FULL_G22_LEFT_P2020, _0_255, BT2020, BT2020_12,
389 BT2020),
390
391 /* 8) YCBCR_STUDIO_G2084_LEFT_P2020 */
392 MAKE_COLOR_MAP (YCBCR_STUDIO_G2084_LEFT_P2020, _16_235, BT2020, SMPTE2084,
393 BT2020),
394
395 /* 9) YCBCR_STUDIO_G22_TOPLEFT_P2020 */
396 MAKE_COLOR_MAP (YCBCR_STUDIO_G22_TOPLEFT_P2020, _16_235, BT2020, BT2020_10,
397 BT2020),
398 MAKE_COLOR_MAP (YCBCR_STUDIO_G22_TOPLEFT_P2020, _16_235, BT2020, BT2020_12,
399 BT2020),
400
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,
405 BT2020),
406
407 /* 11) YCBCR_STUDIO_GHLG_TOPLEFT_P2020 */
408 MAKE_COLOR_MAP (YCBCR_STUDIO_GHLG_TOPLEFT_P2020, _16_235, BT2020,
409 ARIB_STD_B67, BT2020),
410
411 /* 12) YCBCR_FULL_GHLG_TOPLEFT_P2020 */
412 MAKE_COLOR_MAP (YCBCR_FULL_GHLG_TOPLEFT_P2020, _0_255, BT2020, ARIB_STD_B67,
413 BT2020),
414
415 /* 13) YCBCR_STUDIO_G24_LEFT_P709 */
416 MAKE_COLOR_MAP (YCBCR_STUDIO_G24_LEFT_P709, _16_235, BT709, SRGB, BT709),
417
418 /* 14) YCBCR_STUDIO_G24_LEFT_P2020 */
419 MAKE_COLOR_MAP (YCBCR_STUDIO_G24_LEFT_P2020, _16_235, BT2020, SRGB, BT2020),
420
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,
425 BT2020),
426 };
427
428 #define SCORE_RANGE_MISMATCH 5
429 #define SCORE_MATRIX_MISMATCH 5
430 #define SCORE_TRANSFER_MISMATCH 5
431 #define SCORE_PRIMARY_MISMATCH 10
432
433 static gint
get_score(GstVideoInfo * info,const GstDxgiColorSpace * color_map,gboolean is_yuv)434 get_score (GstVideoInfo * info, const GstDxgiColorSpace * color_map,
435 gboolean is_yuv)
436 {
437 gint loss = 0;
438 GstVideoColorimetry *color = &info->colorimetry;
439
440 if (color->range != color_map->range)
441 loss += SCORE_RANGE_MISMATCH;
442
443 if (is_yuv && color->matrix != color_map->matrix)
444 loss += SCORE_MATRIX_MISMATCH;
445
446 if (color->transfer != color_map->transfer)
447 loss += SCORE_TRANSFER_MISMATCH;
448
449 if (color->primaries != color_map->primaries)
450 loss += SCORE_PRIMARY_MISMATCH;
451
452 return loss;
453 }
454
455 static const GstDxgiColorSpace *
gst_d3d11_video_info_to_dxgi_color_space_rgb(GstVideoInfo * info)456 gst_d3d11_video_info_to_dxgi_color_space_rgb (GstVideoInfo * info)
457 {
458 gint best_score = G_MAXINT;
459 gint score;
460 guint i;
461 const GstDxgiColorSpace *colorspace = NULL;
462
463 for (i = 0; i < G_N_ELEMENTS (rgb_colorspace_map); i++) {
464 score = get_score (info, &rgb_colorspace_map[i], FALSE);
465
466 if (score < best_score) {
467 best_score = score;
468 colorspace = &rgb_colorspace_map[i];
469
470 if (score == 0)
471 break;
472 }
473 }
474
475 return colorspace;
476 }
477
478 static const GstDxgiColorSpace *
gst_d3d11_video_info_to_dxgi_color_space_yuv(GstVideoInfo * info)479 gst_d3d11_video_info_to_dxgi_color_space_yuv (GstVideoInfo * info)
480 {
481 gint best_score = G_MAXINT;
482 gint score;
483 guint i;
484 const GstDxgiColorSpace *colorspace = NULL;
485
486 for (i = 0; i < G_N_ELEMENTS (yuv_colorspace_map); i++) {
487 score = get_score (info, &yuv_colorspace_map[i], TRUE);
488
489 if (score < best_score) {
490 best_score = score;
491 colorspace = &yuv_colorspace_map[i];
492
493 if (score == 0)
494 break;
495 }
496 }
497
498 return colorspace;
499 }
500
501 const GstDxgiColorSpace *
gst_d3d11_video_info_to_dxgi_color_space(GstVideoInfo * info)502 gst_d3d11_video_info_to_dxgi_color_space (GstVideoInfo * info)
503 {
504 g_return_val_if_fail (info != NULL, NULL);
505
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);
510 }
511
512 return NULL;
513 }
514
515 const GstDxgiColorSpace *
gst_d3d11_find_swap_chain_color_space(GstVideoInfo * info,IDXGISwapChain3 * swapchain)516 gst_d3d11_find_swap_chain_color_space (GstVideoInfo * info,
517 IDXGISwapChain3 * swapchain)
518 {
519 const GstDxgiColorSpace *colorspace = NULL;
520 gint best_score = G_MAXINT;
521 guint i;
522 /* list of tested display color spaces */
523 static GST_DXGI_COLOR_SPACE_TYPE whitelist[] = {
524 GST_DXGI_COLOR_SPACE_RGB_FULL_G22_NONE_P709,
525 GST_DXGI_COLOR_SPACE_RGB_FULL_G10_NONE_P709,
526 GST_DXGI_COLOR_SPACE_RGB_FULL_G2084_NONE_P2020,
527 };
528
529 g_return_val_if_fail (info != NULL, FALSE);
530 g_return_val_if_fail (swapchain != NULL, FALSE);
531
532 if (!GST_VIDEO_INFO_IS_RGB (info)) {
533 GST_WARNING ("Swapchain colorspace should be RGB format");
534 return FALSE;
535 }
536
537 for (i = 0; i < G_N_ELEMENTS (rgb_colorspace_map); i++) {
538 UINT can_support = 0;
539 HRESULT hr;
540 gint score;
541 gboolean valid = FALSE;
542 GST_DXGI_COLOR_SPACE_TYPE cur_type =
543 (GST_DXGI_COLOR_SPACE_TYPE) rgb_colorspace_map[i].dxgi_color_space_type;
544
545 for (guint j = 0; j < G_N_ELEMENTS (whitelist); j++) {
546 if (whitelist[j] == cur_type) {
547 valid = TRUE;
548 break;
549 }
550 }
551
552 if (!valid)
553 continue;
554
555 hr = swapchain->CheckColorSpaceSupport ((DXGI_COLOR_SPACE_TYPE) cur_type,
556 &can_support);
557
558 if (FAILED (hr))
559 continue;
560
561 if ((can_support & DXGI_SWAP_CHAIN_COLOR_SPACE_SUPPORT_FLAG_PRESENT) ==
562 DXGI_SWAP_CHAIN_COLOR_SPACE_SUPPORT_FLAG_PRESENT) {
563 score = get_score (info, &rgb_colorspace_map[i], FALSE);
564
565 GST_DEBUG ("colorspace %d supported, score %d", cur_type, score);
566
567 if (score < best_score) {
568 best_score = score;
569 colorspace = &rgb_colorspace_map[i];
570 }
571 }
572 }
573
574 return colorspace;
575 }
576 #endif
577
578 static void
fill_staging_desc(const D3D11_TEXTURE2D_DESC * ref,D3D11_TEXTURE2D_DESC * staging)579 fill_staging_desc (const D3D11_TEXTURE2D_DESC * ref,
580 D3D11_TEXTURE2D_DESC * staging)
581 {
582 memset (staging, 0, sizeof (D3D11_TEXTURE2D_DESC));
583
584 staging->Width = ref->Width;
585 staging->Height = ref->Height;
586 staging->MipLevels = 1;
587 staging->Format = ref->Format;
588 staging->SampleDesc.Count = 1;
589 staging->ArraySize = 1;
590 staging->Usage = D3D11_USAGE_STAGING;
591 staging->CPUAccessFlags = (D3D11_CPU_ACCESS_READ | D3D11_CPU_ACCESS_WRITE);
592 }
593
594 GstBuffer *
gst_d3d11_allocate_staging_buffer_for(GstBuffer * buffer,const GstVideoInfo * info,gboolean add_videometa)595 gst_d3d11_allocate_staging_buffer_for (GstBuffer * buffer,
596 const GstVideoInfo * info, gboolean add_videometa)
597 {
598 GstD3D11Memory *dmem;
599 GstD3D11Device *device;
600 GstD3D11Allocator *alloc = NULL;
601 GstBuffer *staging_buffer = NULL;
602 gint stride[GST_VIDEO_MAX_PLANES] = { 0, };
603 gsize offset[GST_VIDEO_MAX_PLANES] = { 0, };
604 guint i;
605 gsize size = 0;
606 const GstD3D11Format *format;
607 D3D11_TEXTURE2D_DESC desc;
608
609 for (i = 0; i < gst_buffer_n_memory (buffer); i++) {
610 GstMemory *mem = gst_buffer_peek_memory (buffer, i);
611
612 if (!gst_is_d3d11_memory (mem)) {
613 GST_DEBUG ("Not a d3d11 memory");
614
615 return NULL;
616 }
617 }
618
619 dmem = (GstD3D11Memory *) gst_buffer_peek_memory (buffer, 0);
620 device = dmem->device;
621 format = gst_d3d11_device_format_from_gst (device,
622 GST_VIDEO_INFO_FORMAT (info));
623 if (!format) {
624 GST_ERROR ("Unknown d3d11 format");
625 return NULL;
626 }
627
628 alloc = (GstD3D11Allocator *) gst_allocator_find (GST_D3D11_MEMORY_NAME);
629 if (!alloc) {
630 GST_ERROR ("D3D11 allocator is not available");
631 return NULL;
632 }
633
634 staging_buffer = gst_buffer_new ();
635 for (i = 0; i < gst_buffer_n_memory (buffer); i++) {
636 D3D11_TEXTURE2D_DESC staging_desc;
637 GstD3D11Memory *mem = (GstD3D11Memory *) gst_buffer_peek_memory (buffer, i);
638 GstD3D11Memory *new_mem;
639
640 guint cur_stride = 0;
641
642 gst_d3d11_memory_get_texture_desc (mem, &desc);
643 fill_staging_desc (&desc, &staging_desc);
644
645 new_mem = (GstD3D11Memory *)
646 gst_d3d11_allocator_alloc (alloc, mem->device, &staging_desc);
647 if (!new_mem) {
648 GST_ERROR ("Failed to allocate memory");
649 goto error;
650 }
651
652 if (!gst_d3d11_memory_get_texture_stride (new_mem, &cur_stride) ||
653 cur_stride < staging_desc.Width) {
654 GST_ERROR ("Failed to calculate memory size");
655 gst_memory_unref (GST_MEMORY_CAST (mem));
656 goto error;
657 }
658
659 offset[i] = size;
660 stride[i] = cur_stride;
661 size += GST_MEMORY_CAST (new_mem)->size;
662
663 gst_buffer_append_memory (staging_buffer, GST_MEMORY_CAST (new_mem));
664 }
665
666 /* single texture semi-planar formats */
667 if (format->dxgi_format != DXGI_FORMAT_UNKNOWN &&
668 GST_VIDEO_INFO_N_PLANES (info) == 2) {
669 stride[1] = stride[0];
670 offset[1] = stride[0] * desc.Height;
671 }
672
673 gst_buffer_add_video_meta_full (staging_buffer, GST_VIDEO_FRAME_FLAG_NONE,
674 GST_VIDEO_INFO_FORMAT (info), GST_VIDEO_INFO_WIDTH (info),
675 GST_VIDEO_INFO_HEIGHT (info), GST_VIDEO_INFO_N_PLANES (info),
676 offset, stride);
677
678 if (alloc)
679 gst_object_unref (alloc);
680
681 return staging_buffer;
682
683 error:
684 gst_clear_buffer (&staging_buffer);
685 gst_clear_object (&alloc);
686
687 return NULL;
688 }
689
690 static gboolean
gst_d3d11_buffer_copy_into_fallback(GstBuffer * dst,GstBuffer * src,const GstVideoInfo * info)691 gst_d3d11_buffer_copy_into_fallback (GstBuffer * dst, GstBuffer * src,
692 const GstVideoInfo * info)
693 {
694 GstVideoFrame in_frame, out_frame;
695 gboolean ret;
696
697 if (!gst_video_frame_map (&in_frame, (GstVideoInfo *) info, src,
698 (GstMapFlags) (GST_MAP_READ | GST_VIDEO_FRAME_MAP_FLAG_NO_REF)))
699 goto invalid_buffer;
700
701 if (!gst_video_frame_map (&out_frame, (GstVideoInfo *) info, dst,
702 (GstMapFlags) (GST_MAP_WRITE | GST_VIDEO_FRAME_MAP_FLAG_NO_REF))) {
703 gst_video_frame_unmap (&in_frame);
704 goto invalid_buffer;
705 }
706
707 ret = gst_video_frame_copy (&out_frame, &in_frame);
708
709 gst_video_frame_unmap (&in_frame);
710 gst_video_frame_unmap (&out_frame);
711
712 return ret;
713
714 /* ERRORS */
715 invalid_buffer:
716 {
717 GST_ERROR ("Invalid video buffer");
718 return FALSE;
719 }
720 }
721
722 gboolean
gst_d3d11_buffer_copy_into(GstBuffer * dst,GstBuffer * src,const GstVideoInfo * info)723 gst_d3d11_buffer_copy_into (GstBuffer * dst, GstBuffer * src,
724 const GstVideoInfo * info)
725 {
726 guint i;
727
728 g_return_val_if_fail (GST_IS_BUFFER (dst), FALSE);
729 g_return_val_if_fail (GST_IS_BUFFER (src), FALSE);
730 g_return_val_if_fail (info != NULL, FALSE);
731
732 if (gst_buffer_n_memory (dst) != gst_buffer_n_memory (src)) {
733 GST_LOG ("different memory layout, perform fallback copy");
734 return gst_d3d11_buffer_copy_into_fallback (dst, src, info);
735 }
736
737 if (!gst_is_d3d11_buffer (dst) || !gst_is_d3d11_buffer (src)) {
738 GST_LOG ("non-d3d11 memory, perform fallback copy");
739 return gst_d3d11_buffer_copy_into_fallback (dst, src, info);
740 }
741
742 for (i = 0; i < gst_buffer_n_memory (dst); i++) {
743 GstMemory *dst_mem, *src_mem;
744 GstD3D11Memory *dst_dmem, *src_dmem;
745 GstMapInfo dst_info;
746 GstMapInfo src_info;
747 ID3D11Resource *dst_texture, *src_texture;
748 ID3D11DeviceContext *device_context;
749 GstD3D11Device *device;
750 D3D11_BOX src_box = { 0, };
751 D3D11_TEXTURE2D_DESC dst_desc, src_desc;
752 guint dst_subidx, src_subidx;
753
754 dst_mem = gst_buffer_peek_memory (dst, i);
755 src_mem = gst_buffer_peek_memory (src, i);
756
757 dst_dmem = (GstD3D11Memory *) dst_mem;
758 src_dmem = (GstD3D11Memory *) src_mem;
759
760 device = dst_dmem->device;
761 if (device != src_dmem->device) {
762 GST_LOG ("different device, perform fallback copy");
763 return gst_d3d11_buffer_copy_into_fallback (dst, src, info);
764 }
765
766 gst_d3d11_memory_get_texture_desc (dst_dmem, &dst_desc);
767 gst_d3d11_memory_get_texture_desc (src_dmem, &src_desc);
768
769 if (dst_desc.Format != src_desc.Format) {
770 GST_WARNING ("different dxgi format");
771 return FALSE;
772 }
773
774 device_context = gst_d3d11_device_get_device_context_handle (device);
775
776 if (!gst_memory_map (dst_mem, &dst_info,
777 (GstMapFlags) (GST_MAP_WRITE | GST_MAP_D3D11))) {
778 GST_ERROR ("Cannot map dst d3d11 memory");
779 return FALSE;
780 }
781
782 if (!gst_memory_map (src_mem, &src_info,
783 (GstMapFlags) (GST_MAP_READ | GST_MAP_D3D11))) {
784 GST_ERROR ("Cannot map src d3d11 memory");
785 gst_memory_unmap (dst_mem, &dst_info);
786 return FALSE;
787 }
788
789 dst_texture = (ID3D11Resource *) dst_info.data;
790 src_texture = (ID3D11Resource *) src_info.data;
791
792 /* src/dst texture size might be different if padding was used.
793 * select smaller size */
794 src_box.left = 0;
795 src_box.top = 0;
796 src_box.front = 0;
797 src_box.back = 1;
798 src_box.right = MIN (src_desc.Width, dst_desc.Width);
799 src_box.bottom = MIN (src_desc.Height, dst_desc.Height);
800
801 dst_subidx = gst_d3d11_memory_get_subresource_index (dst_dmem);
802 src_subidx = gst_d3d11_memory_get_subresource_index (src_dmem);
803
804 gst_d3d11_device_lock (device);
805 device_context->CopySubresourceRegion (dst_texture, dst_subidx, 0, 0, 0,
806 src_texture, src_subidx, &src_box);
807 gst_d3d11_device_unlock (device);
808
809 gst_memory_unmap (src_mem, &src_info);
810 gst_memory_unmap (dst_mem, &dst_info);
811 }
812
813 return TRUE;
814 }
815
816 gboolean
gst_is_d3d11_buffer(GstBuffer * buffer)817 gst_is_d3d11_buffer (GstBuffer * buffer)
818 {
819 guint i;
820 guint size;
821
822 g_return_val_if_fail (GST_IS_BUFFER (buffer), FALSE);
823
824 size = gst_buffer_n_memory (buffer);
825 if (size == 0)
826 return FALSE;
827
828 for (i = 0; i < size; i++) {
829 GstMemory *mem = gst_buffer_peek_memory (buffer, i);
830
831 if (!gst_is_d3d11_memory (mem))
832 return FALSE;
833 }
834
835 return TRUE;
836 }
837
838 gboolean
gst_d3d11_buffer_can_access_device(GstBuffer * buffer,ID3D11Device * device)839 gst_d3d11_buffer_can_access_device (GstBuffer * buffer, ID3D11Device * device)
840 {
841 guint i;
842
843 g_return_val_if_fail (GST_IS_BUFFER (buffer), FALSE);
844 g_return_val_if_fail (device != NULL, FALSE);
845
846 if (!gst_is_d3d11_buffer (buffer)) {
847 GST_LOG ("Not a d3d11 buffer");
848 return FALSE;
849 }
850
851 for (i = 0; i < gst_buffer_n_memory (buffer); i++) {
852 GstD3D11Memory *mem = (GstD3D11Memory *) gst_buffer_peek_memory (buffer, i);
853 ID3D11Device *handle;
854
855 handle = gst_d3d11_device_get_device_handle (mem->device);
856 if (handle != device) {
857 GST_LOG ("D3D11 device is incompatible");
858 return FALSE;
859 }
860 }
861
862 return TRUE;
863 }
864
865 gboolean
gst_d3d11_buffer_map(GstBuffer * buffer,ID3D11Device * device,GstMapInfo info[GST_VIDEO_MAX_PLANES],GstMapFlags flags)866 gst_d3d11_buffer_map (GstBuffer * buffer, ID3D11Device * device,
867 GstMapInfo info[GST_VIDEO_MAX_PLANES], GstMapFlags flags)
868 {
869 GstMapFlags map_flags;
870 guint num_mapped = 0;
871
872 g_return_val_if_fail (GST_IS_BUFFER (buffer), FALSE);
873 g_return_val_if_fail (info != NULL, FALSE);
874
875 if (!gst_d3d11_buffer_can_access_device (buffer, device))
876 return FALSE;
877
878 map_flags = (GstMapFlags) (flags | GST_MAP_D3D11);
879
880 for (num_mapped = 0; num_mapped < gst_buffer_n_memory (buffer); num_mapped++) {
881 GstMemory *mem = gst_buffer_peek_memory (buffer, num_mapped);
882
883 if (!gst_memory_map (mem, &info[num_mapped], map_flags)) {
884 GST_ERROR ("Couldn't map memory");
885 goto error;
886 }
887 }
888
889 return TRUE;
890
891 error:
892 {
893 guint i;
894 for (i = 0; i < num_mapped; i++) {
895 GstMemory *mem = gst_buffer_peek_memory (buffer, i);
896 gst_memory_unmap (mem, &info[i]);
897 }
898
899 return FALSE;
900 }
901 }
902
903 gboolean
gst_d3d11_buffer_unmap(GstBuffer * buffer,GstMapInfo info[GST_VIDEO_MAX_PLANES])904 gst_d3d11_buffer_unmap (GstBuffer * buffer,
905 GstMapInfo info[GST_VIDEO_MAX_PLANES])
906 {
907 guint i;
908
909 g_return_val_if_fail (GST_IS_BUFFER (buffer), FALSE);
910 g_return_val_if_fail (info != NULL, FALSE);
911
912 for (i = 0; i < gst_buffer_n_memory (buffer); i++) {
913 GstMemory *mem = gst_buffer_peek_memory (buffer, i);
914
915 gst_memory_unmap (mem, &info[i]);
916 }
917
918 return TRUE;
919 }
920
921 guint
gst_d3d11_buffer_get_shader_resource_view(GstBuffer * buffer,ID3D11ShaderResourceView * view[GST_VIDEO_MAX_PLANES])922 gst_d3d11_buffer_get_shader_resource_view (GstBuffer * buffer,
923 ID3D11ShaderResourceView * view[GST_VIDEO_MAX_PLANES])
924 {
925 guint i;
926 guint num_views = 0;
927
928 g_return_val_if_fail (GST_IS_BUFFER (buffer), 0);
929 g_return_val_if_fail (view != NULL, 0);
930
931 if (!gst_is_d3d11_buffer (buffer)) {
932 GST_ERROR ("Buffer contains non-d3d11 memory");
933 return 0;
934 }
935
936 for (i = 0; i < gst_buffer_n_memory (buffer); i++) {
937 GstD3D11Memory *mem = (GstD3D11Memory *) gst_buffer_peek_memory (buffer, i);
938 guint view_size;
939 guint j;
940
941 view_size = gst_d3d11_memory_get_shader_resource_view_size (mem);
942 if (!view_size) {
943 GST_LOG ("SRV is unavailable for memory index %d", i);
944 return 0;
945 }
946
947 for (j = 0; j < view_size; j++) {
948 if (num_views >= GST_VIDEO_MAX_PLANES) {
949 GST_ERROR ("Too many SRVs");
950 return 0;
951 }
952
953 view[num_views++] = gst_d3d11_memory_get_shader_resource_view (mem, j);
954 }
955 }
956
957 return num_views;
958 }
959
960 guint
gst_d3d11_buffer_get_render_target_view(GstBuffer * buffer,ID3D11RenderTargetView * view[GST_VIDEO_MAX_PLANES])961 gst_d3d11_buffer_get_render_target_view (GstBuffer * buffer,
962 ID3D11RenderTargetView * view[GST_VIDEO_MAX_PLANES])
963 {
964 guint i;
965 guint num_views = 0;
966
967 g_return_val_if_fail (GST_IS_BUFFER (buffer), 0);
968 g_return_val_if_fail (view != NULL, 0);
969
970 if (!gst_is_d3d11_buffer (buffer)) {
971 GST_ERROR ("Buffer contains non-d3d11 memory");
972 return 0;
973 }
974
975 for (i = 0; i < gst_buffer_n_memory (buffer); i++) {
976 GstD3D11Memory *mem = (GstD3D11Memory *) gst_buffer_peek_memory (buffer, i);
977 guint view_size;
978 guint j;
979
980 view_size = gst_d3d11_memory_get_render_target_view_size (mem);
981 if (!view_size) {
982 GST_LOG ("RTV is unavailable for memory index %d", i);
983 return 0;
984 }
985
986 for (j = 0; j < view_size; j++) {
987 if (num_views >= GST_VIDEO_MAX_PLANES) {
988 GST_ERROR ("Too many RTVs");
989 return 0;
990 }
991
992 view[num_views++] = gst_d3d11_memory_get_render_target_view (mem, j);
993 }
994 }
995
996 return num_views;
997 }
998
999 GstBufferPool *
gst_d3d11_buffer_pool_new_with_options(GstD3D11Device * device,GstCaps * caps,GstD3D11AllocationParams * alloc_params,guint min_buffers,guint max_buffers)1000 gst_d3d11_buffer_pool_new_with_options (GstD3D11Device * device,
1001 GstCaps * caps, GstD3D11AllocationParams * alloc_params,
1002 guint min_buffers, guint max_buffers)
1003 {
1004 GstBufferPool *pool;
1005 GstStructure *config;
1006 GstVideoInfo info;
1007
1008 g_return_val_if_fail (GST_IS_D3D11_DEVICE (device), NULL);
1009 g_return_val_if_fail (GST_IS_CAPS (caps), NULL);
1010 g_return_val_if_fail (alloc_params != NULL, NULL);
1011
1012 if (!gst_video_info_from_caps (&info, caps)) {
1013 GST_ERROR_OBJECT (device, "invalid caps");
1014 return NULL;
1015 }
1016
1017 pool = gst_d3d11_buffer_pool_new (device);
1018 config = gst_buffer_pool_get_config (pool);
1019 gst_buffer_pool_config_set_params (config,
1020 caps, GST_VIDEO_INFO_SIZE (&info), min_buffers, max_buffers);
1021
1022 gst_buffer_pool_config_set_d3d11_allocation_params (config, alloc_params);
1023
1024 gst_buffer_pool_config_add_option (config, GST_BUFFER_POOL_OPTION_VIDEO_META);
1025 if (!gst_buffer_pool_set_config (pool, config)) {
1026 GST_ERROR_OBJECT (pool, "Couldn't set config");
1027 gst_object_unref (pool);
1028 return NULL;
1029 }
1030
1031 return pool;
1032 }
1033