Merging gst-plugins-bad
[platform/upstream/gstreamer.git] / sys / d3d11 / gstd3d11pluginutils.cpp
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
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 *
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
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
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
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
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 *
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 *
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 *
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 *
516 gst_d3d11_find_swap_chain_color_space (GstVideoInfo * info,
517     IDXGISwapChain3 * swapchain, gboolean use_hdr10)
518 {
519   const GstDxgiColorSpace *colorspace = NULL;
520   gint best_score = G_MAXINT;
521   guint i;
522
523   g_return_val_if_fail (info != NULL, FALSE);
524   g_return_val_if_fail (swapchain != NULL, FALSE);
525
526   if (!GST_VIDEO_INFO_IS_RGB (info)) {
527     GST_WARNING ("Swapchain colorspace should be RGB format");
528     return FALSE;
529   }
530
531   for (i = 0; i < G_N_ELEMENTS (rgb_colorspace_map); i++) {
532     UINT can_support = 0;
533     HRESULT hr;
534     gint score;
535     DXGI_COLOR_SPACE_TYPE cur_type =
536         (DXGI_COLOR_SPACE_TYPE) rgb_colorspace_map[i].dxgi_color_space_type;
537
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.
541      */
542     if (!use_hdr10 &&
543         rgb_colorspace_map[i].primaries == GST_VIDEO_COLOR_PRIMARIES_BT2020)
544       continue;
545
546     hr = swapchain->CheckColorSpaceSupport (cur_type, &can_support);
547
548     if (FAILED (hr))
549       continue;
550
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);
554
555       GST_DEBUG ("colorspace %d supported, score %d", cur_type, score);
556
557       if (score < best_score) {
558         best_score = score;
559         colorspace = &rgb_colorspace_map[i];
560       }
561     }
562   }
563
564   return colorspace;
565 }
566 #endif
567
568 static void
569 fill_staging_desc (const D3D11_TEXTURE2D_DESC * ref,
570     D3D11_TEXTURE2D_DESC * staging)
571 {
572   memset (staging, 0, sizeof (D3D11_TEXTURE2D_DESC));
573
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);
582 }
583
584 GstBuffer *
585 gst_d3d11_allocate_staging_buffer_for (GstBuffer * buffer,
586     const GstVideoInfo * info, gboolean add_videometa)
587 {
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, };
594   guint i;
595   gsize size = 0;
596   const GstD3D11Format *format;
597   D3D11_TEXTURE2D_DESC desc;
598
599   for (i = 0; i < gst_buffer_n_memory (buffer); i++) {
600     GstMemory *mem = gst_buffer_peek_memory (buffer, i);
601
602     if (!gst_is_d3d11_memory (mem)) {
603       GST_DEBUG ("Not a d3d11 memory");
604
605       return NULL;
606     }
607   }
608
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));
613   if (!format) {
614     GST_ERROR ("Unknown d3d11 format");
615     return NULL;
616   }
617
618   alloc = (GstD3D11Allocator *) gst_allocator_find (GST_D3D11_MEMORY_NAME);
619   if (!alloc) {
620     GST_ERROR ("D3D11 allocator is not available");
621     return NULL;
622   }
623
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;
629
630     guint cur_stride = 0;
631
632     gst_d3d11_memory_get_texture_desc (mem, &desc);
633     fill_staging_desc (&desc, &staging_desc);
634
635     new_mem = (GstD3D11Memory *)
636         gst_d3d11_allocator_alloc (alloc, mem->device, &staging_desc);
637     if (!new_mem) {
638       GST_ERROR ("Failed to allocate memory");
639       goto error;
640     }
641
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));
646       goto error;
647     }
648
649     offset[i] = size;
650     stride[i] = cur_stride;
651     size += GST_MEMORY_CAST (new_mem)->size;
652
653     gst_buffer_append_memory (staging_buffer, GST_MEMORY_CAST (new_mem));
654   }
655
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;
661   }
662
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),
666       offset, stride);
667
668   if (alloc)
669     gst_object_unref (alloc);
670
671   return staging_buffer;
672
673 error:
674   gst_clear_buffer (&staging_buffer);
675   gst_clear_object (&alloc);
676
677   return NULL;
678 }
679
680 static gboolean
681 gst_d3d11_buffer_copy_into_fallback (GstBuffer * dst, GstBuffer * src,
682     const GstVideoInfo * info)
683 {
684   GstVideoFrame in_frame, out_frame;
685   gboolean ret;
686
687   if (!gst_video_frame_map (&in_frame, (GstVideoInfo *) info, src,
688           (GstMapFlags) (GST_MAP_READ | GST_VIDEO_FRAME_MAP_FLAG_NO_REF)))
689     goto invalid_buffer;
690
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);
694     goto invalid_buffer;
695   }
696
697   ret = gst_video_frame_copy (&out_frame, &in_frame);
698
699   gst_video_frame_unmap (&in_frame);
700   gst_video_frame_unmap (&out_frame);
701
702   return ret;
703
704   /* ERRORS */
705 invalid_buffer:
706   {
707     GST_ERROR ("Invalid video buffer");
708     return FALSE;
709   }
710 }
711
712 gboolean
713 gst_d3d11_buffer_copy_into (GstBuffer * dst, GstBuffer * src,
714     const GstVideoInfo * info)
715 {
716   guint i;
717
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);
721
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);
725   }
726
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);
730   }
731
732   for (i = 0; i < gst_buffer_n_memory (dst); i++) {
733     GstMemory *dst_mem, *src_mem;
734     GstD3D11Memory *dst_dmem, *src_dmem;
735     GstMapInfo dst_info;
736     GstMapInfo src_info;
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;
743
744     dst_mem = gst_buffer_peek_memory (dst, i);
745     src_mem = gst_buffer_peek_memory (src, i);
746
747     dst_dmem = (GstD3D11Memory *) dst_mem;
748     src_dmem = (GstD3D11Memory *) src_mem;
749
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);
754     }
755
756     gst_d3d11_memory_get_texture_desc (dst_dmem, &dst_desc);
757     gst_d3d11_memory_get_texture_desc (src_dmem, &src_desc);
758
759     if (dst_desc.Format != src_desc.Format) {
760       GST_WARNING ("different dxgi format");
761       return FALSE;
762     }
763
764     device_context = gst_d3d11_device_get_device_context_handle (device);
765
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");
769       return FALSE;
770     }
771
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);
776       return FALSE;
777     }
778
779     dst_texture = (ID3D11Resource *) dst_info.data;
780     src_texture = (ID3D11Resource *) src_info.data;
781
782     /* src/dst texture size might be different if padding was used.
783      * select smaller size */
784     src_box.left = 0;
785     src_box.top = 0;
786     src_box.front = 0;
787     src_box.back = 1;
788     src_box.right = MIN (src_desc.Width, dst_desc.Width);
789     src_box.bottom = MIN (src_desc.Height, dst_desc.Height);
790
791     dst_subidx = gst_d3d11_memory_get_subresource_index (dst_dmem);
792     src_subidx = gst_d3d11_memory_get_subresource_index (src_dmem);
793
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);
798
799     gst_memory_unmap (src_mem, &src_info);
800     gst_memory_unmap (dst_mem, &dst_info);
801   }
802
803   return TRUE;
804 }
805
806 gboolean
807 gst_is_d3d11_buffer (GstBuffer * buffer)
808 {
809   guint i;
810   guint size;
811
812   g_return_val_if_fail (GST_IS_BUFFER (buffer), FALSE);
813
814   size = gst_buffer_n_memory (buffer);
815   if (size == 0)
816     return FALSE;
817
818   for (i = 0; i < size; i++) {
819     GstMemory *mem = gst_buffer_peek_memory (buffer, i);
820
821     if (!gst_is_d3d11_memory (mem))
822       return FALSE;
823   }
824
825   return TRUE;
826 }
827
828 gboolean
829 gst_d3d11_buffer_can_access_device (GstBuffer * buffer, ID3D11Device * device)
830 {
831   guint i;
832
833   g_return_val_if_fail (GST_IS_BUFFER (buffer), FALSE);
834   g_return_val_if_fail (device != NULL, FALSE);
835
836   if (!gst_is_d3d11_buffer (buffer)) {
837     GST_LOG ("Not a d3d11 buffer");
838     return FALSE;
839   }
840
841   for (i = 0; i < gst_buffer_n_memory (buffer); i++) {
842     GstD3D11Memory *mem = (GstD3D11Memory *) gst_buffer_peek_memory (buffer, i);
843     ID3D11Device *handle;
844
845     handle = gst_d3d11_device_get_device_handle (mem->device);
846     if (handle != device) {
847       GST_LOG ("D3D11 device is incompatible");
848       return FALSE;
849     }
850   }
851
852   return TRUE;
853 }
854
855 gboolean
856 gst_d3d11_buffer_map (GstBuffer * buffer, ID3D11Device * device,
857     GstMapInfo info[GST_VIDEO_MAX_PLANES], GstMapFlags flags)
858 {
859   GstMapFlags map_flags;
860   guint num_mapped = 0;
861
862   g_return_val_if_fail (GST_IS_BUFFER (buffer), FALSE);
863   g_return_val_if_fail (info != NULL, FALSE);
864
865   if (!gst_d3d11_buffer_can_access_device (buffer, device))
866     return FALSE;
867
868   map_flags = (GstMapFlags) (flags | GST_MAP_D3D11);
869
870   for (num_mapped = 0; num_mapped < gst_buffer_n_memory (buffer); num_mapped++) {
871     GstMemory *mem = gst_buffer_peek_memory (buffer, num_mapped);
872
873     if (!gst_memory_map (mem, &info[num_mapped], map_flags)) {
874       GST_ERROR ("Couldn't map memory");
875       goto error;
876     }
877   }
878
879   return TRUE;
880
881 error:
882   {
883     guint i;
884     for (i = 0; i < num_mapped; i++) {
885       GstMemory *mem = gst_buffer_peek_memory (buffer, i);
886       gst_memory_unmap (mem, &info[i]);
887     }
888
889     return FALSE;
890   }
891 }
892
893 gboolean
894 gst_d3d11_buffer_unmap (GstBuffer * buffer,
895     GstMapInfo info[GST_VIDEO_MAX_PLANES])
896 {
897   guint i;
898
899   g_return_val_if_fail (GST_IS_BUFFER (buffer), FALSE);
900   g_return_val_if_fail (info != NULL, FALSE);
901
902   for (i = 0; i < gst_buffer_n_memory (buffer); i++) {
903     GstMemory *mem = gst_buffer_peek_memory (buffer, i);
904
905     gst_memory_unmap (mem, &info[i]);
906   }
907
908   return TRUE;
909 }
910
911 guint
912 gst_d3d11_buffer_get_shader_resource_view (GstBuffer * buffer,
913     ID3D11ShaderResourceView * view[GST_VIDEO_MAX_PLANES])
914 {
915   guint i;
916   guint num_views = 0;
917
918   g_return_val_if_fail (GST_IS_BUFFER (buffer), 0);
919   g_return_val_if_fail (view != NULL, 0);
920
921   if (!gst_is_d3d11_buffer (buffer)) {
922     GST_ERROR ("Buffer contains non-d3d11 memory");
923     return 0;
924   }
925
926   for (i = 0; i < gst_buffer_n_memory (buffer); i++) {
927     GstD3D11Memory *mem = (GstD3D11Memory *) gst_buffer_peek_memory (buffer, i);
928     guint view_size;
929     guint j;
930
931     view_size = gst_d3d11_memory_get_shader_resource_view_size (mem);
932     if (!view_size) {
933       GST_LOG ("SRV is unavailable for memory index %d", i);
934       return 0;
935     }
936
937     for (j = 0; j < view_size; j++) {
938       if (num_views >= GST_VIDEO_MAX_PLANES) {
939         GST_ERROR ("Too many SRVs");
940         return 0;
941       }
942
943       view[num_views++] = gst_d3d11_memory_get_shader_resource_view (mem, j);
944     }
945   }
946
947   return num_views;
948 }
949
950 guint
951 gst_d3d11_buffer_get_render_target_view (GstBuffer * buffer,
952     ID3D11RenderTargetView * view[GST_VIDEO_MAX_PLANES])
953 {
954   guint i;
955   guint num_views = 0;
956
957   g_return_val_if_fail (GST_IS_BUFFER (buffer), 0);
958   g_return_val_if_fail (view != NULL, 0);
959
960   if (!gst_is_d3d11_buffer (buffer)) {
961     GST_ERROR ("Buffer contains non-d3d11 memory");
962     return 0;
963   }
964
965   for (i = 0; i < gst_buffer_n_memory (buffer); i++) {
966     GstD3D11Memory *mem = (GstD3D11Memory *) gst_buffer_peek_memory (buffer, i);
967     guint view_size;
968     guint j;
969
970     view_size = gst_d3d11_memory_get_render_target_view_size (mem);
971     if (!view_size) {
972       GST_LOG ("RTV is unavailable for memory index %d", i);
973       return 0;
974     }
975
976     for (j = 0; j < view_size; j++) {
977       if (num_views >= GST_VIDEO_MAX_PLANES) {
978         GST_ERROR ("Too many RTVs");
979         return 0;
980       }
981
982       view[num_views++] = gst_d3d11_memory_get_render_target_view (mem, j);
983     }
984   }
985
986   return num_views;
987 }
988
989 GstBufferPool *
990 gst_d3d11_buffer_pool_new_with_options (GstD3D11Device * device,
991     GstCaps * caps, GstD3D11AllocationParams * alloc_params,
992     guint min_buffers, guint max_buffers)
993 {
994   GstBufferPool *pool;
995   GstStructure *config;
996   GstVideoInfo info;
997
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);
1001
1002   if (!gst_video_info_from_caps (&info, caps)) {
1003     GST_ERROR_OBJECT (device, "invalid caps");
1004     return NULL;
1005   }
1006
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);
1011
1012   gst_buffer_pool_config_set_d3d11_allocation_params (config, alloc_params);
1013
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);
1018     return NULL;
1019   }
1020
1021   return pool;
1022 }