d3d11: Update build-time dependency
[platform/upstream/gstreamer.git] / subprojects / gst-plugins-bad / 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 gboolean
137 gst_d3d11_hdr_meta_data_to_dxgi (GstVideoMasteringDisplayInfo * minfo,
138     GstVideoContentLightLevel * cll, DXGI_HDR_METADATA_HDR10 * dxgi_hdr10)
139 {
140   g_return_val_if_fail (dxgi_hdr10 != NULL, FALSE);
141
142   memset (dxgi_hdr10, 0, sizeof (DXGI_HDR_METADATA_HDR10));
143
144   if (minfo) {
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;
151
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;
156   }
157
158   if (cll) {
159     dxgi_hdr10->MaxContentLightLevel = cll->max_content_light_level;
160     dxgi_hdr10->MaxFrameAverageLightLevel = cll->max_frame_average_light_level;
161   }
162
163   return TRUE;
164 }
165
166 typedef enum
167 {
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;
195
196 /* https://docs.microsoft.com/en-us/windows/win32/api/dxgicommon/ne-dxgicommon-dxgi_color_space_type */
197
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 }
202
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
213    *
214    * NOTE: if G24 (Gamma 2.4, SRGB) transfer is not defined,
215    * it will be approximated as G22.
216    * NOTE: BT470BG ~= BT709
217    */
218
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),
228
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),
232
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),
236
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,
245       BT470BG),
246   MAKE_COLOR_MAP (RGB_STUDIO_G22_NONE_P709, _16_235, UNKNOWN, BT2020_12,
247       BT470BG),
248
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),
252
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,
257       BT2020),
258   MAKE_COLOR_MAP (RGB_STUDIO_G22_NONE_P2020, _16_235, UNKNOWN, BT2020_12,
259       BT2020),
260
261   /* 5) RGB_FULL_G2084_NONE_P2020 */
262   MAKE_COLOR_MAP (RGB_FULL_G2084_NONE_P2020, _0_255, UNKNOWN, SMPTE2084,
263       BT2020),
264
265   /* 6) RGB_STUDIO_G2084_NONE_P2020 */
266   MAKE_COLOR_MAP (RGB_STUDIO_G2084_NONE_P2020, _16_235, UNKNOWN, SMPTE2084,
267       BT2020),
268
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),
274
275   /* 7-1) Approximation for RGB_FULL_G22_NONE_P2020 */
276   MAKE_COLOR_MAP (RGB_FULL_G22_NONE_P2020, _0_255, UNKNOWN, SRGB, BT2020),
277
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),
281
282   /* 9) RGB_STUDIO_G24_NONE_P2020 */
283   MAKE_COLOR_MAP (RGB_STUDIO_G24_NONE_P2020, _16_235, UNKNOWN, SRGB, BT2020),
284 };
285
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
302    *
303    * NOTE: BT470BG ~= BT709
304    */
305
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,
310       BT709),
311   MAKE_COLOR_MAP (YCBCR_FULL_G22_NONE_P709_X601, _0_255, BT601, BT2020_12,
312       BT709),
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,
316       BT470BG),
317   MAKE_COLOR_MAP (YCBCR_FULL_G22_NONE_P709_X601, _0_255, BT601, BT2020_12,
318       BT470BG),
319
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,
324       SMPTE170M),
325   MAKE_COLOR_MAP (YCBCR_STUDIO_G22_LEFT_P601, _16_235, BT601, BT2020_12,
326       SMPTE170M),
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,
330       SMPTE240M),
331   MAKE_COLOR_MAP (YCBCR_STUDIO_G22_LEFT_P601, _16_235, BT601, BT2020_12,
332       SMPTE240M),
333
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,
338       SMPTE170M),
339   MAKE_COLOR_MAP (YCBCR_FULL_G22_LEFT_P601, _0_255, BT601, BT2020_12,
340       SMPTE170M),
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,
344       SMPTE240M),
345   MAKE_COLOR_MAP (YCBCR_FULL_G22_LEFT_P601, _0_255, BT601, BT2020_12,
346       SMPTE240M),
347
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,
352       BT709),
353   MAKE_COLOR_MAP (YCBCR_STUDIO_G22_LEFT_P709, _16_235, BT709, BT2020_12,
354       BT709),
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,
358       BT470BG),
359   MAKE_COLOR_MAP (YCBCR_STUDIO_G22_LEFT_P709, _16_235, BT709, BT2020_12,
360       BT470BG),
361
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),
371
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,
376       BT2020),
377   MAKE_COLOR_MAP (YCBCR_STUDIO_G22_LEFT_P2020, _16_235, BT2020, BT2020_12,
378       BT2020),
379
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,
384       BT2020),
385   MAKE_COLOR_MAP (YCBCR_FULL_G22_LEFT_P2020, _0_255, BT2020, BT2020_12,
386       BT2020),
387
388   /* 8) YCBCR_STUDIO_G2084_LEFT_P2020 */
389   MAKE_COLOR_MAP (YCBCR_STUDIO_G2084_LEFT_P2020, _16_235, BT2020, SMPTE2084,
390       BT2020),
391
392   /* 9) YCBCR_STUDIO_G22_TOPLEFT_P2020 */
393   MAKE_COLOR_MAP (YCBCR_STUDIO_G22_TOPLEFT_P2020, _16_235, BT2020, BT2020_10,
394       BT2020),
395   MAKE_COLOR_MAP (YCBCR_STUDIO_G22_TOPLEFT_P2020, _16_235, BT2020, BT2020_12,
396       BT2020),
397
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,
402       BT2020),
403
404   /* 11) YCBCR_STUDIO_GHLG_TOPLEFT_P2020 */
405   MAKE_COLOR_MAP (YCBCR_STUDIO_GHLG_TOPLEFT_P2020, _16_235, BT2020,
406       ARIB_STD_B67, BT2020),
407
408   /* 12) YCBCR_FULL_GHLG_TOPLEFT_P2020 */
409   MAKE_COLOR_MAP (YCBCR_FULL_GHLG_TOPLEFT_P2020, _0_255, BT2020, ARIB_STD_B67,
410       BT2020),
411
412   /* 13) YCBCR_STUDIO_G24_LEFT_P709 */
413   MAKE_COLOR_MAP (YCBCR_STUDIO_G24_LEFT_P709, _16_235, BT709, SRGB, BT709),
414
415   /* 14) YCBCR_STUDIO_G24_LEFT_P2020 */
416   MAKE_COLOR_MAP (YCBCR_STUDIO_G24_LEFT_P2020, _16_235, BT2020, SRGB, BT2020),
417
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,
422       BT2020),
423 };
424
425 #define SCORE_RANGE_MISMATCH 5
426 #define SCORE_MATRIX_MISMATCH 5
427 #define SCORE_TRANSFER_MISMATCH 5
428 #define SCORE_PRIMARY_MISMATCH 10
429
430 static gint
431 get_score (GstVideoInfo * info, const GstDxgiColorSpace * color_map,
432     gboolean is_yuv)
433 {
434   gint loss = 0;
435   GstVideoColorimetry *color = &info->colorimetry;
436
437   if (color->range != color_map->range)
438     loss += SCORE_RANGE_MISMATCH;
439
440   if (is_yuv && color->matrix != color_map->matrix)
441     loss += SCORE_MATRIX_MISMATCH;
442
443   if (color->transfer != color_map->transfer)
444     loss += SCORE_TRANSFER_MISMATCH;
445
446   if (color->primaries != color_map->primaries)
447     loss += SCORE_PRIMARY_MISMATCH;
448
449   return loss;
450 }
451
452 static const GstDxgiColorSpace *
453 gst_d3d11_video_info_to_dxgi_color_space_rgb (GstVideoInfo * info)
454 {
455   gint best_score = G_MAXINT;
456   gint score;
457   guint i;
458   const GstDxgiColorSpace *colorspace = NULL;
459
460   for (i = 0; i < G_N_ELEMENTS (rgb_colorspace_map); i++) {
461     score = get_score (info, &rgb_colorspace_map[i], FALSE);
462
463     if (score < best_score) {
464       best_score = score;
465       colorspace = &rgb_colorspace_map[i];
466
467       if (score == 0)
468         break;
469     }
470   }
471
472   return colorspace;
473 }
474
475 static const GstDxgiColorSpace *
476 gst_d3d11_video_info_to_dxgi_color_space_yuv (GstVideoInfo * info)
477 {
478   gint best_score = G_MAXINT;
479   gint score;
480   guint i;
481   const GstDxgiColorSpace *colorspace = NULL;
482
483   for (i = 0; i < G_N_ELEMENTS (yuv_colorspace_map); i++) {
484     score = get_score (info, &yuv_colorspace_map[i], TRUE);
485
486     if (score < best_score) {
487       best_score = score;
488       colorspace = &yuv_colorspace_map[i];
489
490       if (score == 0)
491         break;
492     }
493   }
494
495   return colorspace;
496 }
497
498 const GstDxgiColorSpace *
499 gst_d3d11_video_info_to_dxgi_color_space (GstVideoInfo * info)
500 {
501   g_return_val_if_fail (info != NULL, NULL);
502
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);
507   }
508
509   return NULL;
510 }
511
512 const GstDxgiColorSpace *
513 gst_d3d11_find_swap_chain_color_space (GstVideoInfo * info,
514     IDXGISwapChain3 * swapchain)
515 {
516   const GstDxgiColorSpace *colorspace = NULL;
517   gint best_score = G_MAXINT;
518   guint i;
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,
524   };
525
526   g_return_val_if_fail (info != NULL, FALSE);
527   g_return_val_if_fail (swapchain != NULL, FALSE);
528
529   if (!GST_VIDEO_INFO_IS_RGB (info)) {
530     GST_WARNING ("Swapchain colorspace should be RGB format");
531     return FALSE;
532   }
533
534   for (i = 0; i < G_N_ELEMENTS (rgb_colorspace_map); i++) {
535     UINT can_support = 0;
536     HRESULT hr;
537     gint score;
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;
541
542     for (guint j = 0; j < G_N_ELEMENTS (whitelist); j++) {
543       if (whitelist[j] == cur_type) {
544         valid = TRUE;
545         break;
546       }
547     }
548
549     if (!valid)
550       continue;
551
552     hr = swapchain->CheckColorSpaceSupport ((DXGI_COLOR_SPACE_TYPE) cur_type,
553         &can_support);
554
555     if (FAILED (hr))
556       continue;
557
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);
561
562       GST_DEBUG ("colorspace %d supported, score %d", cur_type, score);
563
564       if (score < best_score) {
565         best_score = score;
566         colorspace = &rgb_colorspace_map[i];
567       }
568     }
569   }
570
571   return colorspace;
572 }
573
574 static void
575 fill_staging_desc (const D3D11_TEXTURE2D_DESC * ref,
576     D3D11_TEXTURE2D_DESC * staging)
577 {
578   memset (staging, 0, sizeof (D3D11_TEXTURE2D_DESC));
579
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);
588 }
589
590 GstBuffer *
591 gst_d3d11_allocate_staging_buffer_for (GstBuffer * buffer,
592     const GstVideoInfo * info, gboolean add_videometa)
593 {
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, };
600   guint i;
601   gsize size = 0;
602   const GstD3D11Format *format;
603   D3D11_TEXTURE2D_DESC desc;
604
605   for (i = 0; i < gst_buffer_n_memory (buffer); i++) {
606     GstMemory *mem = gst_buffer_peek_memory (buffer, i);
607
608     if (!gst_is_d3d11_memory (mem)) {
609       GST_DEBUG ("Not a d3d11 memory");
610
611       return NULL;
612     }
613   }
614
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));
619   if (!format) {
620     GST_ERROR ("Unknown d3d11 format");
621     return NULL;
622   }
623
624   alloc = (GstD3D11Allocator *) gst_allocator_find (GST_D3D11_MEMORY_NAME);
625   if (!alloc) {
626     GST_ERROR ("D3D11 allocator is not available");
627     return NULL;
628   }
629
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;
635
636     guint cur_stride = 0;
637
638     gst_d3d11_memory_get_texture_desc (mem, &desc);
639     fill_staging_desc (&desc, &staging_desc);
640
641     new_mem = (GstD3D11Memory *)
642         gst_d3d11_allocator_alloc (alloc, mem->device, &staging_desc);
643     if (!new_mem) {
644       GST_ERROR ("Failed to allocate memory");
645       goto error;
646     }
647
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));
652       goto error;
653     }
654
655     offset[i] = size;
656     stride[i] = cur_stride;
657     size += GST_MEMORY_CAST (new_mem)->size;
658
659     gst_buffer_append_memory (staging_buffer, GST_MEMORY_CAST (new_mem));
660   }
661
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;
667   }
668
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),
672       offset, stride);
673
674   if (alloc)
675     gst_object_unref (alloc);
676
677   return staging_buffer;
678
679 error:
680   gst_clear_buffer (&staging_buffer);
681   gst_clear_object (&alloc);
682
683   return NULL;
684 }
685
686 static gboolean
687 gst_d3d11_buffer_copy_into_fallback (GstBuffer * dst, GstBuffer * src,
688     const GstVideoInfo * info)
689 {
690   GstVideoFrame in_frame, out_frame;
691   gboolean ret;
692
693   if (!gst_video_frame_map (&in_frame, (GstVideoInfo *) info, src,
694           (GstMapFlags) (GST_MAP_READ | GST_VIDEO_FRAME_MAP_FLAG_NO_REF)))
695     goto invalid_buffer;
696
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);
700     goto invalid_buffer;
701   }
702
703   ret = gst_video_frame_copy (&out_frame, &in_frame);
704
705   gst_video_frame_unmap (&in_frame);
706   gst_video_frame_unmap (&out_frame);
707
708   return ret;
709
710   /* ERRORS */
711 invalid_buffer:
712   {
713     GST_ERROR ("Invalid video buffer");
714     return FALSE;
715   }
716 }
717
718 gboolean
719 gst_d3d11_buffer_copy_into (GstBuffer * dst, GstBuffer * src,
720     const GstVideoInfo * info)
721 {
722   guint i;
723
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);
727
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);
731   }
732
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);
736   }
737
738   for (i = 0; i < gst_buffer_n_memory (dst); i++) {
739     GstMemory *dst_mem, *src_mem;
740     GstD3D11Memory *dst_dmem, *src_dmem;
741     GstMapInfo dst_info;
742     GstMapInfo src_info;
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;
749
750     dst_mem = gst_buffer_peek_memory (dst, i);
751     src_mem = gst_buffer_peek_memory (src, i);
752
753     dst_dmem = (GstD3D11Memory *) dst_mem;
754     src_dmem = (GstD3D11Memory *) src_mem;
755
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);
760     }
761
762     gst_d3d11_memory_get_texture_desc (dst_dmem, &dst_desc);
763     gst_d3d11_memory_get_texture_desc (src_dmem, &src_desc);
764
765     if (dst_desc.Format != src_desc.Format) {
766       GST_WARNING ("different dxgi format");
767       return FALSE;
768     }
769
770     device_context = gst_d3d11_device_get_device_context_handle (device);
771
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");
775       return FALSE;
776     }
777
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);
782       return FALSE;
783     }
784
785     dst_texture = (ID3D11Resource *) dst_info.data;
786     src_texture = (ID3D11Resource *) src_info.data;
787
788     /* src/dst texture size might be different if padding was used.
789      * select smaller size */
790     src_box.left = 0;
791     src_box.top = 0;
792     src_box.front = 0;
793     src_box.back = 1;
794     src_box.right = MIN (src_desc.Width, dst_desc.Width);
795     src_box.bottom = MIN (src_desc.Height, dst_desc.Height);
796
797     dst_subidx = gst_d3d11_memory_get_subresource_index (dst_dmem);
798     src_subidx = gst_d3d11_memory_get_subresource_index (src_dmem);
799
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);
804
805     gst_memory_unmap (src_mem, &src_info);
806     gst_memory_unmap (dst_mem, &dst_info);
807   }
808
809   return TRUE;
810 }
811
812 gboolean
813 gst_is_d3d11_buffer (GstBuffer * buffer)
814 {
815   guint i;
816   guint size;
817
818   g_return_val_if_fail (GST_IS_BUFFER (buffer), FALSE);
819
820   size = gst_buffer_n_memory (buffer);
821   if (size == 0)
822     return FALSE;
823
824   for (i = 0; i < size; i++) {
825     GstMemory *mem = gst_buffer_peek_memory (buffer, i);
826
827     if (!gst_is_d3d11_memory (mem))
828       return FALSE;
829   }
830
831   return TRUE;
832 }
833
834 gboolean
835 gst_d3d11_buffer_can_access_device (GstBuffer * buffer, ID3D11Device * device)
836 {
837   guint i;
838
839   g_return_val_if_fail (GST_IS_BUFFER (buffer), FALSE);
840   g_return_val_if_fail (device != NULL, FALSE);
841
842   if (!gst_is_d3d11_buffer (buffer)) {
843     GST_LOG ("Not a d3d11 buffer");
844     return FALSE;
845   }
846
847   for (i = 0; i < gst_buffer_n_memory (buffer); i++) {
848     GstD3D11Memory *mem = (GstD3D11Memory *) gst_buffer_peek_memory (buffer, i);
849     ID3D11Device *handle;
850
851     handle = gst_d3d11_device_get_device_handle (mem->device);
852     if (handle != device) {
853       GST_LOG ("D3D11 device is incompatible");
854       return FALSE;
855     }
856   }
857
858   return TRUE;
859 }
860
861 gboolean
862 gst_d3d11_buffer_map (GstBuffer * buffer, ID3D11Device * device,
863     GstMapInfo info[GST_VIDEO_MAX_PLANES], GstMapFlags flags)
864 {
865   GstMapFlags map_flags;
866   guint num_mapped = 0;
867
868   g_return_val_if_fail (GST_IS_BUFFER (buffer), FALSE);
869   g_return_val_if_fail (info != NULL, FALSE);
870
871   if (!gst_d3d11_buffer_can_access_device (buffer, device))
872     return FALSE;
873
874   map_flags = (GstMapFlags) (flags | GST_MAP_D3D11);
875
876   for (num_mapped = 0; num_mapped < gst_buffer_n_memory (buffer); num_mapped++) {
877     GstMemory *mem = gst_buffer_peek_memory (buffer, num_mapped);
878
879     if (!gst_memory_map (mem, &info[num_mapped], map_flags)) {
880       GST_ERROR ("Couldn't map memory");
881       goto error;
882     }
883   }
884
885   return TRUE;
886
887 error:
888   {
889     guint i;
890     for (i = 0; i < num_mapped; i++) {
891       GstMemory *mem = gst_buffer_peek_memory (buffer, i);
892       gst_memory_unmap (mem, &info[i]);
893     }
894
895     return FALSE;
896   }
897 }
898
899 gboolean
900 gst_d3d11_buffer_unmap (GstBuffer * buffer,
901     GstMapInfo info[GST_VIDEO_MAX_PLANES])
902 {
903   guint i;
904
905   g_return_val_if_fail (GST_IS_BUFFER (buffer), FALSE);
906   g_return_val_if_fail (info != NULL, FALSE);
907
908   for (i = 0; i < gst_buffer_n_memory (buffer); i++) {
909     GstMemory *mem = gst_buffer_peek_memory (buffer, i);
910
911     gst_memory_unmap (mem, &info[i]);
912   }
913
914   return TRUE;
915 }
916
917 guint
918 gst_d3d11_buffer_get_shader_resource_view (GstBuffer * buffer,
919     ID3D11ShaderResourceView * view[GST_VIDEO_MAX_PLANES])
920 {
921   guint i;
922   guint num_views = 0;
923
924   g_return_val_if_fail (GST_IS_BUFFER (buffer), 0);
925   g_return_val_if_fail (view != NULL, 0);
926
927   if (!gst_is_d3d11_buffer (buffer)) {
928     GST_ERROR ("Buffer contains non-d3d11 memory");
929     return 0;
930   }
931
932   for (i = 0; i < gst_buffer_n_memory (buffer); i++) {
933     GstD3D11Memory *mem = (GstD3D11Memory *) gst_buffer_peek_memory (buffer, i);
934     guint view_size;
935     guint j;
936
937     view_size = gst_d3d11_memory_get_shader_resource_view_size (mem);
938     if (!view_size) {
939       GST_LOG ("SRV is unavailable for memory index %d", i);
940       return 0;
941     }
942
943     for (j = 0; j < view_size; j++) {
944       if (num_views >= GST_VIDEO_MAX_PLANES) {
945         GST_ERROR ("Too many SRVs");
946         return 0;
947       }
948
949       view[num_views++] = gst_d3d11_memory_get_shader_resource_view (mem, j);
950     }
951   }
952
953   return num_views;
954 }
955
956 guint
957 gst_d3d11_buffer_get_render_target_view (GstBuffer * buffer,
958     ID3D11RenderTargetView * view[GST_VIDEO_MAX_PLANES])
959 {
960   guint i;
961   guint num_views = 0;
962
963   g_return_val_if_fail (GST_IS_BUFFER (buffer), 0);
964   g_return_val_if_fail (view != NULL, 0);
965
966   if (!gst_is_d3d11_buffer (buffer)) {
967     GST_ERROR ("Buffer contains non-d3d11 memory");
968     return 0;
969   }
970
971   for (i = 0; i < gst_buffer_n_memory (buffer); i++) {
972     GstD3D11Memory *mem = (GstD3D11Memory *) gst_buffer_peek_memory (buffer, i);
973     guint view_size;
974     guint j;
975
976     view_size = gst_d3d11_memory_get_render_target_view_size (mem);
977     if (!view_size) {
978       GST_LOG ("RTV is unavailable for memory index %d", i);
979       return 0;
980     }
981
982     for (j = 0; j < view_size; j++) {
983       if (num_views >= GST_VIDEO_MAX_PLANES) {
984         GST_ERROR ("Too many RTVs");
985         return 0;
986       }
987
988       view[num_views++] = gst_d3d11_memory_get_render_target_view (mem, j);
989     }
990   }
991
992   return num_views;
993 }
994
995 GstBufferPool *
996 gst_d3d11_buffer_pool_new_with_options (GstD3D11Device * device,
997     GstCaps * caps, GstD3D11AllocationParams * alloc_params,
998     guint min_buffers, guint max_buffers)
999 {
1000   GstBufferPool *pool;
1001   GstStructure *config;
1002   GstVideoInfo info;
1003
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);
1007
1008   if (!gst_video_info_from_caps (&info, caps)) {
1009     GST_ERROR_OBJECT (device, "invalid caps");
1010     return NULL;
1011   }
1012
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);
1017
1018   gst_buffer_pool_config_set_d3d11_allocation_params (config, alloc_params);
1019
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);
1024     return NULL;
1025   }
1026
1027   return pool;
1028 }