• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /* GStreamer
2  * Copyright (C) <2019> Seungha Yang <seungha.yang@navercorp.com>
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Library General Public
6  * License as published by the Free Software Foundation; either
7  * version 2 of the License, or (at your option) any later version.
8  *
9  * This library is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * Library General Public License for more details.
13  *
14  * You should have received a copy of the GNU Library General Public
15  * License along with this library; if not, write to the
16  * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
17  * Boston, MA 02110-1301, USA.
18  */
19 
20 /**
21  * SECTION:element-d3d11upload
22  * @title: d3d11upload
23  *
24  * Upload video frame to Direct3D11 texture memory
25  *
26  * ## Example launch line
27  * ```
28  * gst-launch-1.0 videotestsrc ! d3d11upload ! d3d11videosinkelement
29  * ```
30  *   This pipeline will upload video test frame (system memory) into Direct3D11
31  * textures and d3d11videosinkelement will display frames on screen.
32  *
33  * Since: 1.18
34  *
35  */
36 
37 #ifdef HAVE_CONFIG_H
38 #  include <config.h>
39 #endif
40 
41 #include "gstd3d11upload.h"
42 
43 #include <string.h>
44 
45 GST_DEBUG_CATEGORY_STATIC (gst_d3d11_upload_debug);
46 #define GST_CAT_DEFAULT gst_d3d11_upload_debug
47 
48 static GstStaticCaps sink_template_caps =
49     GST_STATIC_CAPS (GST_VIDEO_CAPS_MAKE (GST_D3D11_ALL_FORMATS) "; "
50     GST_VIDEO_CAPS_MAKE_WITH_FEATURES
51     (GST_CAPS_FEATURE_MEMORY_SYSTEM_MEMORY ","
52         GST_CAPS_FEATURE_META_GST_VIDEO_OVERLAY_COMPOSITION,
53         GST_D3D11_ALL_FORMATS) "; "
54     GST_VIDEO_CAPS_MAKE_WITH_FEATURES (GST_CAPS_FEATURE_MEMORY_D3D11_MEMORY,
55         GST_D3D11_ALL_FORMATS) ";"
56     GST_VIDEO_CAPS_MAKE_WITH_FEATURES (GST_CAPS_FEATURE_MEMORY_D3D11_MEMORY
57         "," GST_CAPS_FEATURE_META_GST_VIDEO_OVERLAY_COMPOSITION,
58         GST_D3D11_ALL_FORMATS));
59 
60 static GstStaticCaps src_template_caps =
61     GST_STATIC_CAPS (GST_VIDEO_CAPS_MAKE_WITH_FEATURES
62     (GST_CAPS_FEATURE_MEMORY_D3D11_MEMORY, GST_D3D11_ALL_FORMATS) "; "
63     GST_VIDEO_CAPS_MAKE_WITH_FEATURES
64     (GST_CAPS_FEATURE_MEMORY_D3D11_MEMORY ","
65         GST_CAPS_FEATURE_META_GST_VIDEO_OVERLAY_COMPOSITION,
66         GST_D3D11_ALL_FORMATS) ";"
67     GST_VIDEO_CAPS_MAKE (GST_D3D11_ALL_FORMATS) "; "
68     GST_VIDEO_CAPS_MAKE_WITH_FEATURES
69     (GST_CAPS_FEATURE_MEMORY_SYSTEM_MEMORY ","
70         GST_CAPS_FEATURE_META_GST_VIDEO_OVERLAY_COMPOSITION,
71         GST_D3D11_ALL_FORMATS));
72 
73 struct _GstD3D11Upload
74 {
75   GstD3D11BaseFilter parent;
76 
77   GstBuffer *staging_buffer;
78 };
79 
80 #define gst_d3d11_upload_parent_class parent_class
81 G_DEFINE_TYPE (GstD3D11Upload, gst_d3d11_upload, GST_TYPE_D3D11_BASE_FILTER);
82 
83 static void gst_d3d11_upload_dispose (GObject * object);
84 static gboolean gst_d3d11_upload_stop (GstBaseTransform * trans);
85 static gboolean gst_d3d11_upload_sink_event (GstBaseTransform * trans,
86     GstEvent * event);
87 static GstCaps *gst_d3d11_upload_transform_caps (GstBaseTransform * trans,
88     GstPadDirection direction, GstCaps * caps, GstCaps * filter);
89 static gboolean gst_d3d11_upload_propose_allocation (GstBaseTransform * trans,
90     GstQuery * decide_query, GstQuery * query);
91 static gboolean gst_d3d11_upload_decide_allocation (GstBaseTransform * trans,
92     GstQuery * query);
93 static GstFlowReturn gst_d3d11_upload_transform (GstBaseTransform * trans,
94     GstBuffer * inbuf, GstBuffer * outbuf);
95 static gboolean gst_d3d11_upload_set_info (GstD3D11BaseFilter * filter,
96     GstCaps * incaps, GstVideoInfo * in_info, GstCaps * outcaps,
97     GstVideoInfo * out_info);
98 
99 static void
gst_d3d11_upload_class_init(GstD3D11UploadClass * klass)100 gst_d3d11_upload_class_init (GstD3D11UploadClass * klass)
101 {
102   GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
103   GstElementClass *element_class = GST_ELEMENT_CLASS (klass);
104   GstBaseTransformClass *trans_class = GST_BASE_TRANSFORM_CLASS (klass);
105   GstD3D11BaseFilterClass *bfilter_class = GST_D3D11_BASE_FILTER_CLASS (klass);
106   GstCaps *caps;
107 
108   gobject_class->dispose = gst_d3d11_upload_dispose;
109 
110   caps = gst_d3d11_get_updated_template_caps (&sink_template_caps);
111   gst_element_class_add_pad_template (element_class,
112       gst_pad_template_new ("sink", GST_PAD_SINK, GST_PAD_ALWAYS, caps));
113   gst_caps_unref (caps);
114 
115   caps = gst_d3d11_get_updated_template_caps (&src_template_caps);
116   gst_element_class_add_pad_template (element_class,
117       gst_pad_template_new ("src", GST_PAD_SRC, GST_PAD_ALWAYS, caps));
118   gst_caps_unref (caps);
119 
120   gst_element_class_set_static_metadata (element_class,
121       "Direct3D11 uploader", "Filter/Video",
122       "Uploads data into Direct3D11 texture memory",
123       "Seungha Yang <seungha.yang@navercorp.com>");
124 
125   trans_class->passthrough_on_same_caps = TRUE;
126 
127   trans_class->stop = GST_DEBUG_FUNCPTR (gst_d3d11_upload_stop);
128   trans_class->sink_event = GST_DEBUG_FUNCPTR (gst_d3d11_upload_sink_event);
129   trans_class->transform_caps =
130       GST_DEBUG_FUNCPTR (gst_d3d11_upload_transform_caps);
131   trans_class->propose_allocation =
132       GST_DEBUG_FUNCPTR (gst_d3d11_upload_propose_allocation);
133   trans_class->decide_allocation =
134       GST_DEBUG_FUNCPTR (gst_d3d11_upload_decide_allocation);
135   trans_class->transform = GST_DEBUG_FUNCPTR (gst_d3d11_upload_transform);
136 
137   bfilter_class->set_info = GST_DEBUG_FUNCPTR (gst_d3d11_upload_set_info);
138 
139   GST_DEBUG_CATEGORY_INIT (gst_d3d11_upload_debug,
140       "d3d11upload", 0, "d3d11upload Element");
141 }
142 
143 static void
gst_d3d11_upload_init(GstD3D11Upload * upload)144 gst_d3d11_upload_init (GstD3D11Upload * upload)
145 {
146 }
147 
148 static void
gst_d3d11_upload_dispose(GObject * object)149 gst_d3d11_upload_dispose (GObject * object)
150 {
151   GstD3D11Upload *self = GST_D3D11_UPLOAD (object);
152 
153   gst_clear_buffer (&self->staging_buffer);
154 
155   G_OBJECT_CLASS (parent_class)->dispose (object);
156 }
157 
158 static gboolean
gst_d3d11_upload_stop(GstBaseTransform * trans)159 gst_d3d11_upload_stop (GstBaseTransform * trans)
160 {
161   GstD3D11Upload *self = GST_D3D11_UPLOAD (trans);
162 
163   gst_clear_buffer (&self->staging_buffer);
164 
165   return GST_BASE_TRANSFORM_CLASS (parent_class)->stop (trans);
166 }
167 
168 static gboolean
gst_d3d11_upload_sink_event(GstBaseTransform * trans,GstEvent * event)169 gst_d3d11_upload_sink_event (GstBaseTransform * trans, GstEvent * event)
170 {
171   GstD3D11Upload *self = GST_D3D11_UPLOAD (trans);
172 
173   switch (GST_EVENT_TYPE (event)) {
174     case GST_EVENT_EOS:
175       /* We don't need to hold this staging buffer after eos */
176       gst_clear_buffer (&self->staging_buffer);
177       break;
178     default:
179       break;
180   }
181 
182   return GST_BASE_TRANSFORM_CLASS (parent_class)->sink_event (trans, event);
183 }
184 
185 static GstCaps *
_set_caps_features(const GstCaps * caps,const gchar * feature_name)186 _set_caps_features (const GstCaps * caps, const gchar * feature_name)
187 {
188   guint i, j, m, n;
189   GstCaps *tmp;
190   GstCapsFeatures *overlay_feature =
191       gst_caps_features_from_string
192       (GST_CAPS_FEATURE_META_GST_VIDEO_OVERLAY_COMPOSITION);
193 
194   tmp = gst_caps_new_empty ();
195 
196   n = gst_caps_get_size (caps);
197   for (i = 0; i < n; i++) {
198     GstCapsFeatures *features, *orig_features;
199     GstStructure *s = gst_caps_get_structure (caps, i);
200 
201     orig_features = gst_caps_get_features (caps, i);
202     features = gst_caps_features_new (feature_name, NULL);
203 
204     if (gst_caps_features_is_any (orig_features)) {
205       gst_caps_append_structure_full (tmp, gst_structure_copy (s),
206           gst_caps_features_copy (features));
207 
208       if (!gst_caps_features_contains (features,
209               GST_CAPS_FEATURE_META_GST_VIDEO_OVERLAY_COMPOSITION))
210         gst_caps_features_add (features,
211             GST_CAPS_FEATURE_META_GST_VIDEO_OVERLAY_COMPOSITION);
212     } else {
213       m = gst_caps_features_get_size (orig_features);
214       for (j = 0; j < m; j++) {
215         const gchar *feature = gst_caps_features_get_nth (orig_features, j);
216 
217         /* if we already have the features */
218         if (gst_caps_features_contains (features, feature))
219           continue;
220 
221         if (g_strcmp0 (feature, GST_CAPS_FEATURE_MEMORY_SYSTEM_MEMORY) == 0)
222           continue;
223 
224         if (gst_caps_features_contains (overlay_feature, feature)) {
225           gst_caps_features_add (features, feature);
226         }
227       }
228     }
229 
230     gst_caps_append_structure_full (tmp, gst_structure_copy (s), features);
231   }
232 
233   gst_caps_features_free (overlay_feature);
234 
235   return tmp;
236 }
237 
238 static GstCaps *
gst_d3d11_upload_transform_caps(GstBaseTransform * trans,GstPadDirection direction,GstCaps * caps,GstCaps * filter)239 gst_d3d11_upload_transform_caps (GstBaseTransform * trans,
240     GstPadDirection direction, GstCaps * caps, GstCaps * filter)
241 {
242   GstCaps *result, *tmp;
243 
244   GST_DEBUG_OBJECT (trans,
245       "Transforming caps %" GST_PTR_FORMAT " in direction %s", caps,
246       (direction == GST_PAD_SINK) ? "sink" : "src");
247 
248   if (direction == GST_PAD_SINK) {
249     tmp = _set_caps_features (caps, GST_CAPS_FEATURE_MEMORY_D3D11_MEMORY);
250     tmp = gst_caps_merge (gst_caps_ref (caps), tmp);
251   } else {
252     GstCaps *newcaps;
253     tmp = gst_caps_ref (caps);
254     newcaps = _set_caps_features (caps, GST_CAPS_FEATURE_MEMORY_SYSTEM_MEMORY);
255     tmp = gst_caps_merge (tmp, newcaps);
256   }
257 
258   if (filter) {
259     result = gst_caps_intersect_full (filter, tmp, GST_CAPS_INTERSECT_FIRST);
260     gst_caps_unref (tmp);
261   } else {
262     result = tmp;
263   }
264 
265   GST_DEBUG_OBJECT (trans, "returning caps: %" GST_PTR_FORMAT, result);
266 
267   return result;
268 }
269 
270 static gboolean
gst_d3d11_upload_propose_allocation(GstBaseTransform * trans,GstQuery * decide_query,GstQuery * query)271 gst_d3d11_upload_propose_allocation (GstBaseTransform * trans,
272     GstQuery * decide_query, GstQuery * query)
273 {
274   GstD3D11BaseFilter *filter = GST_D3D11_BASE_FILTER (trans);
275   GstVideoInfo info;
276   GstBufferPool *pool;
277   GstCaps *caps;
278   guint size;
279 
280   if (!GST_BASE_TRANSFORM_CLASS (parent_class)->propose_allocation (trans,
281           decide_query, query))
282     return FALSE;
283 
284   /* passthrough, we're done */
285   if (decide_query == NULL)
286     return TRUE;
287 
288   gst_query_parse_allocation (query, &caps, NULL);
289 
290   if (caps == NULL)
291     return FALSE;
292 
293   if (!gst_video_info_from_caps (&info, caps))
294     return FALSE;
295 
296   if (gst_query_get_n_allocation_pools (query) == 0) {
297     GstCapsFeatures *features;
298     GstStructure *config;
299     gboolean is_d3d11 = FALSE;
300 
301     features = gst_caps_get_features (caps, 0);
302 
303     if (features && gst_caps_features_contains (features,
304             GST_CAPS_FEATURE_MEMORY_D3D11_MEMORY)) {
305       GST_DEBUG_OBJECT (filter, "upstream support d3d11 memory");
306       pool = gst_d3d11_buffer_pool_new (filter->device);
307       is_d3d11 = TRUE;
308     } else {
309       pool = gst_video_buffer_pool_new ();
310     }
311 
312     config = gst_buffer_pool_get_config (pool);
313 
314     gst_buffer_pool_config_add_option (config,
315         GST_BUFFER_POOL_OPTION_VIDEO_META);
316 
317     /* d3d11 pool does not support video alignment */
318     if (!is_d3d11) {
319       gst_buffer_pool_config_add_option (config,
320           GST_BUFFER_POOL_OPTION_VIDEO_ALIGNMENT);
321     }
322 
323     size = GST_VIDEO_INFO_SIZE (&info);
324     gst_buffer_pool_config_set_params (config, caps, size, 0, 0);
325 
326     if (!gst_buffer_pool_set_config (pool, config))
327       goto config_failed;
328 
329     /* d3d11 buffer pool will update buffer size based on allocated texture,
330      * get size from config again */
331     if (is_d3d11) {
332       config = gst_buffer_pool_get_config (pool);
333       gst_buffer_pool_config_get_params (config,
334           nullptr, &size, nullptr, nullptr);
335       gst_structure_free (config);
336     }
337 
338     gst_query_add_allocation_pool (query, pool, size, 0, 0);
339     gst_object_unref (pool);
340   }
341 
342   gst_query_add_allocation_meta (query, GST_VIDEO_META_API_TYPE, NULL);
343   gst_query_add_allocation_meta (query,
344       GST_VIDEO_OVERLAY_COMPOSITION_META_API_TYPE, NULL);
345 
346   return TRUE;
347 
348   /* ERRORS */
349 config_failed:
350   {
351     GST_ERROR_OBJECT (filter, "failed to set config");
352     gst_object_unref (pool);
353     return FALSE;
354   }
355 }
356 
357 static gboolean
gst_d3d11_upload_decide_allocation(GstBaseTransform * trans,GstQuery * query)358 gst_d3d11_upload_decide_allocation (GstBaseTransform * trans, GstQuery * query)
359 {
360   GstD3D11BaseFilter *filter = GST_D3D11_BASE_FILTER (trans);
361   GstCaps *outcaps = NULL;
362   GstBufferPool *pool = NULL;
363   guint size, min, max;
364   GstStructure *config;
365   gboolean update_pool = FALSE;
366   GstVideoInfo vinfo;
367   const GstD3D11Format *d3d11_format;
368   GstD3D11AllocationParams *d3d11_params;
369   guint bind_flags = 0;
370   guint i;
371   DXGI_FORMAT dxgi_format = DXGI_FORMAT_UNKNOWN;
372   UINT supported = 0;
373   HRESULT hr;
374   ID3D11Device *device_handle;
375 
376   gst_query_parse_allocation (query, &outcaps, NULL);
377 
378   if (!outcaps)
379     return FALSE;
380 
381   gst_video_info_from_caps (&vinfo, outcaps);
382 
383   d3d11_format = gst_d3d11_device_format_from_gst (filter->device,
384       GST_VIDEO_INFO_FORMAT (&vinfo));
385   if (!d3d11_format) {
386     GST_ERROR_OBJECT (filter, "Unknown format caps %" GST_PTR_FORMAT, outcaps);
387     return FALSE;
388   }
389 
390   if (d3d11_format->dxgi_format == DXGI_FORMAT_UNKNOWN) {
391     dxgi_format = d3d11_format->resource_format[0];
392   } else {
393     dxgi_format = d3d11_format->dxgi_format;
394   }
395 
396   device_handle = gst_d3d11_device_get_device_handle (filter->device);
397   hr = device_handle->CheckFormatSupport (dxgi_format, &supported);
398   if (gst_d3d11_result (hr, filter->device)) {
399     if ((supported & D3D11_FORMAT_SUPPORT_SHADER_SAMPLE) ==
400         D3D11_FORMAT_SUPPORT_SHADER_SAMPLE) {
401       bind_flags |= D3D11_BIND_SHADER_RESOURCE;
402     }
403 
404     if ((supported & D3D11_FORMAT_SUPPORT_RENDER_TARGET) ==
405         D3D11_FORMAT_SUPPORT_RENDER_TARGET) {
406       bind_flags |= D3D11_BIND_RENDER_TARGET;
407     }
408   }
409 
410   if (gst_query_get_n_allocation_pools (query) > 0) {
411     gst_query_parse_nth_allocation_pool (query, 0, &pool, &size, &min, &max);
412     if (pool) {
413       if (!GST_IS_D3D11_BUFFER_POOL (pool)) {
414         gst_clear_object (&pool);
415       } else {
416         GstD3D11BufferPool *dpool = GST_D3D11_BUFFER_POOL (pool);
417         if (dpool->device != filter->device)
418           gst_clear_object (&pool);
419       }
420     }
421 
422     update_pool = TRUE;
423   } else {
424     size = GST_VIDEO_INFO_SIZE (&vinfo);
425     min = max = 0;
426   }
427 
428   if (!pool) {
429     GST_DEBUG_OBJECT (trans, "create our pool");
430 
431     pool = gst_d3d11_buffer_pool_new (filter->device);
432   }
433 
434   config = gst_buffer_pool_get_config (pool);
435   gst_buffer_pool_config_add_option (config, GST_BUFFER_POOL_OPTION_VIDEO_META);
436   gst_buffer_pool_config_set_params (config, outcaps, size, min, max);
437 
438   d3d11_params = gst_buffer_pool_config_get_d3d11_allocation_params (config);
439   if (!d3d11_params) {
440     d3d11_params = gst_d3d11_allocation_params_new (filter->device, &vinfo,
441         (GstD3D11AllocationFlags) 0, bind_flags);
442   } else {
443     /* Set bind flag */
444     for (i = 0; i < GST_VIDEO_INFO_N_PLANES (&vinfo); i++) {
445       d3d11_params->desc[i].BindFlags |= bind_flags;
446     }
447   }
448 
449   gst_buffer_pool_config_set_d3d11_allocation_params (config, d3d11_params);
450   gst_d3d11_allocation_params_free (d3d11_params);
451 
452   gst_buffer_pool_set_config (pool, config);
453 
454   /* d3d11 buffer pool will update buffer size based on allocated texture,
455    * get size from config again */
456   config = gst_buffer_pool_get_config (pool);
457   gst_buffer_pool_config_get_params (config, nullptr, &size, nullptr, nullptr);
458   gst_structure_free (config);
459 
460   if (update_pool)
461     gst_query_set_nth_allocation_pool (query, 0, pool, size, min, max);
462   else
463     gst_query_add_allocation_pool (query, pool, size, min, max);
464 
465   gst_object_unref (pool);
466 
467   return GST_BASE_TRANSFORM_CLASS (parent_class)->decide_allocation (trans,
468       query);
469 }
470 
471 static gboolean
gst_d3d11_upload_can_use_staging_buffer(GstD3D11Upload * self,GstBuffer * outbuf)472 gst_d3d11_upload_can_use_staging_buffer (GstD3D11Upload * self,
473     GstBuffer * outbuf)
474 {
475   GstD3D11BaseFilter *filter = GST_D3D11_BASE_FILTER (self);
476   ID3D11Device *device_handle =
477       gst_d3d11_device_get_device_handle (filter->device);
478 
479   if (!gst_d3d11_buffer_can_access_device (outbuf, device_handle))
480     return FALSE;
481 
482   if (self->staging_buffer)
483     return TRUE;
484 
485   self->staging_buffer = gst_d3d11_allocate_staging_buffer_for (outbuf,
486       &filter->out_info, TRUE);
487 
488   if (!self->staging_buffer) {
489     GST_WARNING_OBJECT (self, "Couldn't allocate staging buffer");
490     return FALSE;
491   }
492 
493   return TRUE;
494 }
495 
496 static GstFlowReturn
gst_d3d11_upload_transform(GstBaseTransform * trans,GstBuffer * inbuf,GstBuffer * outbuf)497 gst_d3d11_upload_transform (GstBaseTransform * trans, GstBuffer * inbuf,
498     GstBuffer * outbuf)
499 {
500   GstD3D11BaseFilter *filter = GST_D3D11_BASE_FILTER (trans);
501   GstD3D11Upload *self = GST_D3D11_UPLOAD (trans);
502   GstVideoFrame in_frame, out_frame;
503   GstFlowReturn ret = GST_FLOW_OK;
504   gboolean use_staging_buf;
505   GstBuffer *target_outbuf = outbuf;
506   guint i;
507 
508   use_staging_buf = gst_d3d11_upload_can_use_staging_buffer (self, outbuf);
509 
510   if (use_staging_buf) {
511     GST_TRACE_OBJECT (self, "Copy input buffer to staging buffer");
512     target_outbuf = self->staging_buffer;
513   }
514 
515   if (!gst_video_frame_map (&in_frame, &filter->in_info, inbuf,
516           (GstMapFlags) (GST_MAP_READ | GST_VIDEO_FRAME_MAP_FLAG_NO_REF)))
517     goto invalid_buffer;
518 
519   if (!gst_video_frame_map (&out_frame, &filter->out_info, target_outbuf,
520           (GstMapFlags) (GST_MAP_WRITE | GST_VIDEO_FRAME_MAP_FLAG_NO_REF))) {
521     gst_video_frame_unmap (&in_frame);
522     goto invalid_buffer;
523   }
524 
525   for (i = 0; i < GST_VIDEO_FRAME_N_PLANES (&in_frame); i++) {
526     if (!gst_video_frame_copy_plane (&out_frame, &in_frame, i)) {
527       GST_ERROR_OBJECT (filter, "Couldn't copy plane %d", i);
528       ret = GST_FLOW_ERROR;
529       break;
530     }
531   }
532 
533   gst_video_frame_unmap (&out_frame);
534   gst_video_frame_unmap (&in_frame);
535 
536   /* Copy staging texture to d3d11 texture */
537   if (use_staging_buf) {
538     if (!gst_d3d11_buffer_copy_into (outbuf,
539             self->staging_buffer, &filter->out_info)) {
540       GST_ERROR_OBJECT (self, "Cannot copy staging texture into texture");
541       return GST_FLOW_ERROR;
542     }
543   }
544 
545   return ret;
546 
547   /* ERRORS */
548 invalid_buffer:
549   {
550     GST_ELEMENT_WARNING (filter, CORE, NOT_IMPLEMENTED, (NULL),
551         ("invalid video buffer received"));
552     return GST_FLOW_ERROR;
553   }
554 }
555 
556 static gboolean
gst_d3d11_upload_set_info(GstD3D11BaseFilter * filter,GstCaps * incaps,GstVideoInfo * in_info,GstCaps * outcaps,GstVideoInfo * out_info)557 gst_d3d11_upload_set_info (GstD3D11BaseFilter * filter,
558     GstCaps * incaps, GstVideoInfo * in_info, GstCaps * outcaps,
559     GstVideoInfo * out_info)
560 {
561   GstD3D11Upload *self = GST_D3D11_UPLOAD (filter);
562 
563   gst_clear_buffer (&self->staging_buffer);
564 
565   return TRUE;
566 }
567