2 * gstvaapipluginbase.c - Base GStreamer VA-API Plugin element
4 * Copyright (C) 2010-2011 Splitted-Desktop Systems
5 * Author: Gwenole Beauchesne <gwenole.beauchesne@splitted-desktop.com>
6 * Copyright (C) 2011-2014 Intel Corporation
7 * Author: Gwenole Beauchesne <gwenole.beauchesne@intel.com>
9 * This library is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU Lesser General Public License
11 * as published by the Free Software Foundation; either version 2.1
12 * of the License, or (at your option) any later version.
14 * This library is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * Lesser General Public License for more details.
19 * You should have received a copy of the GNU Lesser General Public
20 * License along with this library; if not, write to the Free
21 * Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
22 * Boston, MA 02110-1301 USA
25 #include "gstcompat.h"
26 #include <gst/vaapi/gstvaapisurface_drm.h>
27 #include <gst/base/gstpushsrc.h>
28 #include "gstvaapipluginbase.h"
29 #include "gstvaapipluginutil.h"
30 #include "gstvaapivideocontext.h"
31 #include "gstvaapivideometa.h"
32 #include "gstvaapivideobufferpool.h"
33 #if USE_GST_GL_HELPERS
34 # include <gst/gl/gl.h>
37 GST_DEBUG_CATEGORY_STATIC (CAT_PERFORMANCE);
38 /* Default debug category is from the subclass */
39 #define GST_CAT_DEFAULT (plugin->debug_category)
41 #define BUFFER_POOL_SINK_MIN_BUFFERS 2
43 #define GST_VAAPI_PAD_PRIVATE(pad) \
44 (GST_VAAPI_PLUGIN_BASE_GET_CLASS(plugin)->get_vaapi_pad_private(plugin, pad))
47 gst_vaapi_pad_private_new (void)
49 GstVaapiPadPrivate *priv = g_new0 (GstVaapiPadPrivate, 1);
51 gst_video_info_init (&priv->info);
57 gst_vaapi_pad_private_reset (GstVaapiPadPrivate * priv)
61 gst_caps_replace (&priv->caps, NULL);
62 gst_video_info_init (&priv->info);
64 g_clear_object (&priv->buffer_pool);
65 g_clear_object (&priv->allocator);
67 priv->buffer_size = 0;
68 priv->caps_is_raw = FALSE;
70 g_clear_object (&priv->other_allocator);
71 priv->can_dmabuf = FALSE;
75 gst_vaapi_pad_private_finalize (GstVaapiPadPrivate * priv)
77 gst_vaapi_pad_private_reset (priv);
81 /* GstVideoContext interface */
83 plugin_set_display (GstVaapiPluginBase * plugin, GstVaapiDisplay * display)
85 const gchar *const display_name =
86 gst_vaapi_display_get_display_name (display);
88 if (plugin->display_name && g_strcmp0 (plugin->display_name, display_name)) {
89 GST_DEBUG_OBJECT (plugin, "incompatible display name '%s', requested '%s'",
90 display_name, plugin->display_name);
91 gst_vaapi_display_replace (&plugin->display, NULL);
93 GST_INFO_OBJECT (plugin, "set display %" GST_PTR_FORMAT, display);
94 gst_vaapi_display_replace (&plugin->display, display);
95 plugin->display_type = gst_vaapi_display_get_display_type (display);
96 gst_vaapi_plugin_base_set_display_name (plugin, display_name);
98 gst_object_unref (display);
102 * gst_vaapi_plugin_base_set_context:
103 * @plugin: a #GstVaapiPluginBase instance
104 * @context: a #GstContext to set
106 * This is a common set_context() element's vmethod for all the
107 * GStreamer VA-API elements.
109 * It normally should be used through the macro
110 * #GST_VAAPI_PLUGIN_BASE_DEFINE_SET_CONTEXT()
113 gst_vaapi_plugin_base_set_context (GstVaapiPluginBase * plugin,
114 GstContext * context)
116 GstVaapiDisplay *display = NULL;
118 /* gst.vaapi.app.Display is only attended _if_ the element is
119 * vaapisink and it doesn't have a display set yet */
120 if (gst_vaapi_video_context_get_display (context,
121 GST_IS_VIDEO_SINK (plugin) && !plugin->display, &display)) {
122 plugin_set_display (plugin, display);
124 #if USE_GST_GL_HELPERS
125 gst_gl_handle_set_context (GST_ELEMENT_CAST (plugin), context,
126 (GstGLDisplay **) & plugin->gl_display,
127 (GstGLContext **) & plugin->gl_other_context);
132 gst_vaapi_plugin_base_init_interfaces (GType g_define_type_id)
137 default_has_interface (GstVaapiPluginBase * plugin, GType type)
143 default_display_changed (GstVaapiPluginBase * plugin)
147 static GstVaapiSurface *
148 _get_cached_surface (GstBuffer * buf)
150 return gst_mini_object_get_qdata (GST_MINI_OBJECT (buf),
151 g_quark_from_static_string ("GstVaapiDMABufSurface"));
155 _set_cached_surface (GstBuffer * buf, GstVaapiSurface * surface)
157 return gst_mini_object_set_qdata (GST_MINI_OBJECT (buf),
158 g_quark_from_static_string ("GstVaapiDMABufSurface"), surface,
159 (GDestroyNotify) gst_vaapi_object_unref);
163 plugin_update_sinkpad_info_from_buffer (GstVaapiPluginBase * plugin,
166 GstVaapiPadPrivate *sinkpriv = GST_VAAPI_PAD_PRIVATE (plugin->sinkpad);
167 GstVideoInfo *const vip = &sinkpriv->info;
171 vmeta = gst_buffer_get_video_meta (buf);
175 if (GST_VIDEO_INFO_FORMAT (vip) != vmeta->format ||
176 GST_VIDEO_INFO_WIDTH (vip) != vmeta->width ||
177 GST_VIDEO_INFO_HEIGHT (vip) != vmeta->height ||
178 GST_VIDEO_INFO_N_PLANES (vip) != vmeta->n_planes)
181 for (i = 0; i < GST_VIDEO_INFO_N_PLANES (vip); ++i) {
182 GST_VIDEO_INFO_PLANE_OFFSET (vip, i) = vmeta->offset[i];
183 GST_VIDEO_INFO_PLANE_STRIDE (vip, i) = vmeta->stride[i];
185 GST_VIDEO_INFO_SIZE (vip) = gst_buffer_get_size (buf);
190 is_dma_buffer (GstBuffer * buf)
194 if (gst_buffer_n_memory (buf) < 1)
197 mem = gst_buffer_peek_memory (buf, 0);
198 if (!mem || !gst_is_dmabuf_memory (mem))
204 plugin_bind_dma_to_vaapi_buffer (GstVaapiPluginBase * plugin,
205 GstBuffer * inbuf, GstBuffer * outbuf)
207 GstVaapiPadPrivate *sinkpriv = GST_VAAPI_PAD_PRIVATE (plugin->sinkpad);
208 GstVideoInfo *const vip = &sinkpriv->info;
209 GstVaapiVideoMeta *meta;
210 GstVaapiSurface *surface;
211 GstVaapiSurfaceProxy *proxy;
214 fd = gst_dmabuf_memory_get_fd (gst_buffer_peek_memory (inbuf, 0));
218 if (!plugin_update_sinkpad_info_from_buffer (plugin, inbuf))
219 goto error_update_sinkpad_info;
221 meta = gst_buffer_get_vaapi_video_meta (outbuf);
222 g_return_val_if_fail (meta != NULL, FALSE);
224 /* Check for a VASurface cached in the buffer */
225 surface = _get_cached_surface (inbuf);
227 /* otherwise create one and cache it */
229 gst_vaapi_surface_new_with_dma_buf_handle (plugin->display, fd, vip);
231 goto error_create_surface;
232 _set_cached_surface (inbuf, surface);
235 proxy = gst_vaapi_surface_proxy_new (surface);
237 goto error_create_proxy;
238 gst_vaapi_video_meta_set_surface_proxy (meta, proxy);
239 gst_vaapi_surface_proxy_unref (proxy);
240 gst_buffer_add_parent_buffer_meta (outbuf, inbuf);
244 error_update_sinkpad_info:
246 GST_ERROR_OBJECT (plugin,
247 "failed to update sink pad video info from video meta");
250 error_create_surface:
252 GST_ERROR_OBJECT (plugin,
253 "failed to create VA surface from dma_buf handle");
258 GST_ERROR_OBJECT (plugin,
259 "failed to create VA surface proxy from wrapped VA surface");
265 plugin_reset_texture_map (GstVaapiPluginBase * plugin)
268 gst_vaapi_display_reset_texture_map (plugin->display);
271 static GstVaapiPadPrivate *
272 default_get_vaapi_pad_private (GstVaapiPluginBase * plugin, GstPad * pad)
274 if (plugin->sinkpad == pad)
275 return plugin->sinkpriv;
277 g_assert (plugin->srcpad == pad);
278 return plugin->srcpriv;
282 gst_vaapi_plugin_base_class_init (GstVaapiPluginBaseClass * klass)
284 klass->has_interface = default_has_interface;
285 klass->display_changed = default_display_changed;
286 klass->get_vaapi_pad_private = default_get_vaapi_pad_private;
290 gst_vaapi_plugin_base_init (GstVaapiPluginBase * plugin,
291 GstDebugCategory * debug_category)
293 plugin->debug_category = debug_category;
294 plugin->display_type = GST_VAAPI_DISPLAY_TYPE_ANY;
295 plugin->display_type_req = GST_VAAPI_DISPLAY_TYPE_ANY;
298 plugin->sinkpad = gst_element_get_static_pad (GST_ELEMENT (plugin), "sink");
301 plugin->sinkpriv = gst_vaapi_pad_private_new ();
304 if (!(GST_OBJECT_FLAGS (plugin) & GST_ELEMENT_FLAG_SINK))
305 plugin->srcpad = gst_element_get_static_pad (GST_ELEMENT (plugin), "src");
308 plugin->srcpriv = gst_vaapi_pad_private_new ();
310 plugin->enable_direct_rendering =
311 (g_getenv ("GST_VAAPI_ENABLE_DIRECT_RENDERING") != NULL);
315 gst_vaapi_plugin_base_finalize (GstVaapiPluginBase * plugin)
317 gst_vaapi_plugin_base_close (plugin);
318 g_free (plugin->display_name);
320 if (plugin->sinkpriv)
321 gst_vaapi_pad_private_finalize (plugin->sinkpriv);
323 gst_vaapi_pad_private_finalize (plugin->srcpriv);
326 gst_object_unref (plugin->sinkpad);
328 gst_object_unref (plugin->srcpad);
332 * gst_vaapi_plugin_base_open:
333 * @plugin: a #GstVaapiPluginBase
335 * Allocates any internal resources needed for correct operation from
338 * Returns: %TRUE if successful, %FALSE otherwise.
341 gst_vaapi_plugin_base_open (GstVaapiPluginBase * plugin)
347 * gst_vaapi_plugin_base_close:
348 * @plugin: a #GstVaapiPluginBase
350 * Deallocates all internal resources that were allocated so
351 * far. i.e. put the base plugin object into a clean state.
354 gst_vaapi_plugin_base_close (GstVaapiPluginBase * plugin)
356 /* Release vaapi textures first if exist, which refs display object */
357 plugin_reset_texture_map (plugin);
359 gst_vaapi_display_replace (&plugin->display, NULL);
360 gst_object_replace (&plugin->gl_context, NULL);
361 gst_object_replace (&plugin->gl_display, NULL);
362 gst_object_replace (&plugin->gl_other_context, NULL);
364 gst_caps_replace (&plugin->allowed_raw_caps, NULL);
366 if (plugin->sinkpriv)
367 gst_vaapi_pad_private_reset (plugin->sinkpriv);
369 gst_vaapi_pad_private_reset (plugin->srcpriv);
373 * gst_vaapi_plugin_base_has_display_type:
374 * @plugin: a #GstVaapiPluginBase
375 * @display_type_req: the desired #GstVaapiDisplayType
377 * Checks whether the @plugin elements already has a #GstVaapiDisplay
378 * instance compatible with type @display_type_req.
380 * Return value: %TRUE if @plugin has a compatible display, %FALSE otherwise
383 gst_vaapi_plugin_base_has_display_type (GstVaapiPluginBase * plugin,
384 GstVaapiDisplayType display_type_req)
386 GstVaapiDisplayType display_type;
388 if (!plugin->display)
391 display_type = plugin->display_type;
392 if (gst_vaapi_display_type_is_compatible (display_type, display_type_req))
395 display_type = gst_vaapi_display_get_class_type (plugin->display);
396 if (gst_vaapi_display_type_is_compatible (display_type, display_type_req))
402 * gst_vaapi_plugin_base_set_display_type:
403 * @plugin: a #GstVaapiPluginBase
404 * @display_type: the new request #GstVaapiDisplayType
406 * Requests a new display type. The change is effective at the next
407 * call to gst_vaapi_plugin_base_ensure_display().
410 gst_vaapi_plugin_base_set_display_type (GstVaapiPluginBase * plugin,
411 GstVaapiDisplayType display_type)
413 plugin->display_type_req = display_type;
417 * gst_vaapi_plugin_base_set_display_name:
418 * @plugin: a #GstVaapiPluginBase
419 * @display_name: the new display name to match
421 * Sets the name of the display to look for. The change is effective
422 * at the next call to gst_vaapi_plugin_base_ensure_display().
425 gst_vaapi_plugin_base_set_display_name (GstVaapiPluginBase * plugin,
426 const gchar * display_name)
428 g_free (plugin->display_name);
429 plugin->display_name = g_strdup (display_name);
433 * gst_vaapi_plugin_base_ensure_display:
434 * @plugin: a #GstVaapiPluginBase
436 * Ensures the display stored in @plugin complies with the requested
437 * display type constraints.
439 * Returns: %TRUE if the display was created to match the requested
440 * type, %FALSE otherwise.
443 gst_vaapi_plugin_base_ensure_display (GstVaapiPluginBase * plugin)
445 if (gst_vaapi_plugin_base_has_display_type (plugin, plugin->display_type_req))
447 gst_vaapi_display_replace (&plugin->display, NULL);
449 if (!gst_vaapi_ensure_display (GST_ELEMENT (plugin),
450 plugin->display_type_req))
452 plugin->display_type = gst_vaapi_display_get_display_type (plugin->display);
454 GST_VAAPI_PLUGIN_BASE_GET_CLASS (plugin)->display_changed (plugin);
459 gst_vaapi_buffer_pool_caps_is_equal (GstBufferPool * pool, GstCaps * newcaps)
461 GstStructure *config;
467 config = gst_buffer_pool_get_config (pool);
468 if (gst_buffer_pool_config_get_params (config, &caps, NULL, NULL, NULL))
469 ret = gst_caps_is_equal (newcaps, caps);
470 gst_structure_free (config);
475 static inline gboolean
476 reset_allocator (GstAllocator * allocator, GstVideoInfo * vinfo)
478 const GstVideoInfo *orig_vi;
483 orig_vi = gst_allocator_get_vaapi_video_info (allocator, NULL);
484 if (!gst_video_info_changed (orig_vi, vinfo))
487 gst_object_unref (allocator);
492 ensure_sinkpad_allocator (GstVaapiPluginBase * plugin, GstCaps * caps,
495 GstVaapiPadPrivate *sinkpriv = GST_VAAPI_PAD_PRIVATE (plugin->sinkpad);
497 const GstVideoInfo *image_info;
498 GstVaapiImageUsageFlags usage_flag =
499 GST_VAAPI_IMAGE_USAGE_FLAG_NATIVE_FORMATS;
501 if (!gst_video_info_from_caps (&vinfo, caps))
502 goto error_invalid_caps;
504 if (!reset_allocator (sinkpriv->allocator, &vinfo))
507 /* enable direct upload if upstream requests raw video */
508 if (gst_caps_is_video_raw (caps)) {
509 usage_flag = GST_VAAPI_IMAGE_USAGE_FLAG_DIRECT_UPLOAD;
510 GST_INFO_OBJECT (plugin, "enabling direct upload in sink allocator");
512 sinkpriv->allocator =
513 gst_vaapi_video_allocator_new (plugin->display, &vinfo, 0, usage_flag);
516 if (!sinkpriv->allocator)
517 goto error_create_allocator;
519 image_info = gst_allocator_get_vaapi_video_info (sinkpriv->allocator, NULL);
520 g_assert (image_info); /* allocator ought set its image info */
522 /* update the size with the one generated by the allocator */
523 *size = GST_VIDEO_INFO_SIZE (image_info);
530 GST_ERROR_OBJECT (plugin, "invalid caps %" GST_PTR_FORMAT, caps);
533 error_create_allocator:
535 GST_ERROR_OBJECT (plugin, "failed to create sink pad's allocator");
541 get_dmabuf_surface_allocation_flags (void)
543 /* @FIXME: fetch the real devices ids */
544 /* Pair vendor/device identifies an unique physical device. */
545 guint va_vendor_id = 0x00;
546 guint va_device_id = 0x00;
547 guint gl_vendor_id = 0x00;
548 guint gl_device_id = 0x00;
550 /* Requires linear memory only if fd export is done on a different
551 * device than the device where the fd is imported. */
552 gboolean same_physical_device = va_vendor_id == gl_vendor_id
553 && va_device_id == gl_device_id;
555 if (same_physical_device)
557 return GST_VAAPI_SURFACE_ALLOC_FLAG_LINEAR_STORAGE;
560 static inline GstAllocator *
561 create_dmabuf_srcpad_allocator (GstVaapiPluginBase * plugin,
562 GstVideoInfo * vinfo, gboolean check_for_map)
564 GstAllocator *allocator;
566 if (!GST_IS_VIDEO_DECODER (plugin) && !GST_IS_BASE_TRANSFORM (plugin))
569 allocator = gst_vaapi_dmabuf_allocator_new (plugin->display, vinfo,
570 get_dmabuf_surface_allocation_flags (), GST_PAD_SRC);
571 if (!allocator || !check_for_map)
574 /* the dmabuf allocator *must* be capable to map a buffer with raw
575 * caps and the there's no evidence of downstream dmabuf
577 if (!gst_vaapi_dmabuf_can_map (plugin->display, allocator)) {
578 GST_INFO_OBJECT (plugin, "dmabuf allocator generates unmappable buffers");
579 gst_object_replace ((GstObject **) & allocator, NULL);
586 ensure_srcpad_allocator (GstVaapiPluginBase * plugin, GstVideoInfo * vinfo,
589 GstVaapiPadPrivate *srcpriv = GST_VAAPI_PAD_PRIVATE (plugin->srcpad);
590 const GstVideoInfo *image_info;
592 if (!reset_allocator (srcpriv->allocator, vinfo))
593 goto valid_allocator;
595 srcpriv->allocator = NULL;
596 if (caps && gst_caps_is_video_raw (caps)) {
597 GstAllocator *allocator = create_dmabuf_srcpad_allocator (plugin, vinfo,
598 !srcpriv->can_dmabuf);
599 srcpriv->allocator = allocator;
600 } else if (caps && gst_vaapi_caps_feature_contains (caps,
601 GST_VAAPI_CAPS_FEATURE_DMABUF)) {
602 srcpriv->allocator = create_dmabuf_srcpad_allocator (plugin, vinfo, FALSE);
603 if (!srcpriv->allocator)
604 goto error_create_allocator;
607 if (!srcpriv->allocator) {
608 GstVaapiImageUsageFlags usage_flag =
609 GST_VAAPI_IMAGE_USAGE_FLAG_NATIVE_FORMATS;
611 if (plugin->enable_direct_rendering) {
612 usage_flag = GST_VAAPI_IMAGE_USAGE_FLAG_DIRECT_RENDER;
613 GST_INFO_OBJECT (plugin, "enabling direct rendering in source allocator");
617 gst_vaapi_video_allocator_new (plugin->display, vinfo, 0, usage_flag);
620 if (!srcpriv->allocator)
621 goto error_create_allocator;
624 image_info = gst_allocator_get_vaapi_video_info (srcpriv->allocator, NULL);
625 g_assert (image_info); /* both allocators ought set its image
628 /* update the size with the one generated by the allocator */
629 GST_VIDEO_INFO_SIZE (vinfo) = GST_VIDEO_INFO_SIZE (image_info);
631 if (GST_IS_VIDEO_DECODER (plugin)) {
632 /* the received caps are the "allocation caps" which may be
633 * different from the "negotiation caps". In this case, we should
634 * indicate the allocator to store the negotiation caps since they
635 * are the one should be used for frame mapping with GstVideoMeta */
636 gboolean different_caps = srcpriv->caps &&
637 !gst_caps_is_strictly_equal (srcpriv->caps, caps);
638 const GstVideoInfo *previous_negotiated =
639 gst_allocator_get_vaapi_negotiated_video_info (srcpriv->allocator);
641 if (different_caps) {
643 GstVideoInfo vi = srcpriv->info;
645 /* update the planes and the size with the allocator image/surface
646 * info, but not the resolution */
647 for (i = 0; i < GST_VIDEO_INFO_N_PLANES (image_info); i++) {
648 GST_VIDEO_INFO_PLANE_OFFSET (&vi, i) =
649 GST_VIDEO_INFO_PLANE_OFFSET (image_info, i);
650 GST_VIDEO_INFO_PLANE_STRIDE (&vi, i) =
651 GST_VIDEO_INFO_PLANE_STRIDE (image_info, i);
653 GST_VIDEO_INFO_SIZE (&vi) = GST_VIDEO_INFO_SIZE (image_info);
654 gst_allocator_set_vaapi_negotiated_video_info (srcpriv->allocator, &vi);
655 } else if (previous_negotiated) {
656 gst_allocator_set_vaapi_negotiated_video_info (srcpriv->allocator, NULL);
662 error_create_allocator:
664 GST_ERROR_OBJECT (plugin, "failed to create src pad's allocator");
670 * gst_vaapi_plugin_base_create_pool:
671 * @plugin: a #GstVaapiPluginBase
672 * @caps: the initial #GstCaps for the resulting buffer pool
673 * @size: the size of each buffer, not including prefix and padding
674 * @options: a set of #GstVaapiVideoBufferPoolOption encoded as bit-wise
675 * @allocator: (allow-none): the #GstAllocator to use or %NULL
677 * Create an instance of #GstVaapiVideoBufferPool
679 * Returns: (transfer full): a new allocated #GstBufferPool
681 static GstBufferPool *
682 gst_vaapi_plugin_base_create_pool (GstVaapiPluginBase * plugin, GstCaps * caps,
683 gsize size, guint min_buffers, guint max_buffers, guint options,
684 GstAllocator * allocator)
687 GstStructure *config;
689 if (!(pool = gst_vaapi_video_buffer_pool_new (plugin->display)))
690 goto error_create_pool;
692 config = gst_buffer_pool_get_config (pool);
693 gst_buffer_pool_config_set_params (config, caps, size, min_buffers,
695 gst_buffer_pool_config_add_option (config,
696 GST_BUFFER_POOL_OPTION_VAAPI_VIDEO_META);
697 if (options & GST_VAAPI_VIDEO_BUFFER_POOL_OPTION_VIDEO_META) {
698 gst_buffer_pool_config_add_option (config,
699 GST_BUFFER_POOL_OPTION_VIDEO_META);
701 if (options & GST_VAAPI_VIDEO_BUFFER_POOL_OPTION_VIDEO_ALIGNMENT) {
702 gst_buffer_pool_config_add_option (config,
703 GST_BUFFER_POOL_OPTION_VIDEO_ALIGNMENT);
705 #if (USE_GLX || USE_EGL)
706 if (options & GST_VAAPI_VIDEO_BUFFER_POOL_OPTION_GL_TEXTURE_UPLOAD) {
707 gst_buffer_pool_config_add_option (config,
708 GST_BUFFER_POOL_OPTION_VIDEO_GL_TEXTURE_UPLOAD_META);
712 gst_buffer_pool_config_set_allocator (config, allocator, NULL);
713 if (!gst_buffer_pool_set_config (pool, config)) {
714 config = gst_buffer_pool_get_config (pool);
716 if (!gst_buffer_pool_config_validate_params (config, caps, size,
717 min_buffers, max_buffers)) {
718 gst_structure_free (config);
719 goto error_pool_config;
722 if (!gst_buffer_pool_set_config (pool, config))
723 goto error_pool_config;
730 GST_ERROR_OBJECT (plugin, "failed to create buffer pool");
735 gst_object_unref (pool);
736 GST_ELEMENT_ERROR (plugin, RESOURCE, SETTINGS,
737 ("Failed to configure the buffer pool"),
738 ("Configuration is most likely invalid, please report this issue."));
744 * ensure_sinkpad_buffer_pool:
745 * @plugin: a #GstVaapiPluginBase
746 * @caps: the initial #GstCaps for the resulting buffer pool
748 * Makes sure the sink pad video buffer pool is created with the
751 * Returns: %TRUE if successful, %FALSE otherwise.
754 ensure_sinkpad_buffer_pool (GstVaapiPluginBase * plugin, GstCaps * caps)
756 GstVaapiPadPrivate *sinkpriv = GST_VAAPI_PAD_PRIVATE (plugin->sinkpad);
760 /* video decoders don't use a buffer pool in the sink pad */
761 if (GST_IS_VIDEO_DECODER (plugin))
764 if (!gst_vaapi_plugin_base_ensure_display (plugin))
767 if (sinkpriv->buffer_pool) {
768 if (gst_vaapi_buffer_pool_caps_is_equal (sinkpriv->buffer_pool, caps))
770 gst_buffer_pool_set_active (sinkpriv->buffer_pool, FALSE);
771 g_clear_object (&sinkpriv->buffer_pool);
772 g_clear_object (&sinkpriv->allocator);
773 sinkpriv->buffer_size = 0;
776 if (!ensure_sinkpad_allocator (plugin, caps, &size))
780 gst_vaapi_plugin_base_create_pool (plugin, caps, size,
781 BUFFER_POOL_SINK_MIN_BUFFERS, 0,
782 GST_VAAPI_VIDEO_BUFFER_POOL_OPTION_VIDEO_META, sinkpriv->allocator);
786 sinkpriv->buffer_pool = pool;
787 sinkpriv->buffer_size = size;
792 * gst_vaapi_plugin_base_set_caps:
793 * @plugin: a #GstVaapiPluginBase
794 * @incaps: the sink pad (input) caps
795 * @outcaps: the src pad (output) caps
797 * Notifies the base plugin object of the new input and output caps,
798 * obtained from the subclass.
800 * Returns: %TRUE if the update of caps was successful, %FALSE otherwise.
803 gst_vaapi_plugin_base_set_caps (GstVaapiPluginBase * plugin, GstCaps * incaps,
806 GstVaapiPadPrivate *sinkpriv = NULL;
807 GstVaapiPadPrivate *srcpriv = NULL;
810 g_assert (plugin->sinkpad);
811 sinkpriv = GST_VAAPI_PAD_PRIVATE (plugin->sinkpad);
814 if (incaps && incaps != sinkpriv->caps) {
815 if (!gst_video_info_from_caps (&sinkpriv->info, incaps))
817 gst_caps_replace (&sinkpriv->caps, incaps);
818 sinkpriv->caps_is_raw = !gst_caps_has_vaapi_surface (incaps);
822 g_assert (plugin->srcpad);
823 srcpriv = GST_VAAPI_PAD_PRIVATE (plugin->srcpad);
826 if (outcaps && outcaps != srcpriv->caps) {
827 if (!gst_video_info_from_caps (&srcpriv->info, outcaps))
829 if (srcpriv->buffer_pool
830 && !gst_vaapi_buffer_pool_caps_is_equal (srcpriv->buffer_pool,
832 gst_buffer_pool_set_active (srcpriv->buffer_pool, FALSE);
833 g_clear_object (&srcpriv->buffer_pool);
834 g_clear_object (&srcpriv->allocator);
835 plugin_reset_texture_map (plugin);
837 gst_caps_replace (&srcpriv->caps, outcaps);
840 if (incaps && !ensure_sinkpad_buffer_pool (plugin, sinkpriv->caps))
846 * gst_vaapi_plugin_base_propose_allocation:
847 * @plugin: a #GstVaapiPluginBase
848 * @query: the allocation query to configure
850 * Proposes allocation parameters to the upstream elements.
852 * Returns: %TRUE if successful, %FALSE otherwise.
855 gst_vaapi_plugin_base_propose_allocation (GstVaapiPluginBase * plugin,
858 GstVaapiPadPrivate *sinkpriv = GST_VAAPI_PAD_PRIVATE (plugin->sinkpad);
859 GstCaps *caps = NULL;
860 GstBufferPool *pool = NULL;
862 guint size = 0, n_allocators;
864 gst_query_parse_allocation (query, &caps, &need_pool);
868 if (!ensure_sinkpad_allocator (plugin, caps, &size))
872 pool = gst_vaapi_plugin_base_create_pool (plugin, caps, size,
873 BUFFER_POOL_SINK_MIN_BUFFERS, 0,
874 GST_VAAPI_VIDEO_BUFFER_POOL_OPTION_VIDEO_META, sinkpriv->allocator);
879 /* Set sinkpad allocator as the last allocation param.
881 * If there's none, set system's allocator first and VAAPI allocator
884 n_allocators = gst_query_get_n_allocation_params (query);
885 if (n_allocators == 0) {
886 GstAllocator *allocator;
888 allocator = gst_allocator_find (GST_ALLOCATOR_SYSMEM);
889 gst_query_add_allocation_param (query, allocator, NULL);
890 gst_object_unref (allocator);
892 gst_query_add_allocation_param (query, sinkpriv->allocator, NULL);
894 gst_query_add_allocation_pool (query, pool, size,
895 BUFFER_POOL_SINK_MIN_BUFFERS, 0);
897 gst_object_unref (pool);
899 gst_query_add_allocation_meta (query, GST_VAAPI_VIDEO_META_API_TYPE, NULL);
900 gst_query_add_allocation_meta (query, GST_VIDEO_META_API_TYPE, NULL);
906 GST_INFO_OBJECT (plugin, "no caps specified");
912 * gst_vaapi_plugin_base_decide_allocation:
913 * @plugin: a #GstVaapiPluginBase
914 * @query: the allocation query to parse
915 * @feature: the desired #GstVaapiCapsFeature, or zero to find the
918 * Decides allocation parameters for the downstream elements.
920 * Returns: %TRUE if successful, %FALSE otherwise.
923 gst_vaapi_plugin_base_decide_allocation (GstVaapiPluginBase * plugin,
926 GstVaapiPadPrivate *srcpriv = GST_VAAPI_PAD_PRIVATE (plugin->srcpad);
927 GstCaps *caps = NULL;
930 guint i, size, min, max, pool_options, num_allocators;
931 gint index_allocator;
932 gboolean update_pool = FALSE;
933 #if (USE_GLX || USE_EGL)
937 gst_query_parse_allocation (query, &caps, NULL);
942 if (gst_query_find_allocation_meta (query, GST_VIDEO_META_API_TYPE, NULL))
943 pool_options |= GST_VAAPI_VIDEO_BUFFER_POOL_OPTION_VIDEO_META;
945 #if (USE_GLX || USE_EGL)
946 if (gst_query_find_allocation_meta (query,
947 GST_VIDEO_GL_TEXTURE_UPLOAD_META_API_TYPE, &idx) &&
948 gst_vaapi_caps_feature_contains (caps,
949 GST_VAAPI_CAPS_FEATURE_GL_TEXTURE_UPLOAD_META))
950 pool_options |= GST_VAAPI_VIDEO_BUFFER_POOL_OPTION_GL_TEXTURE_UPLOAD;
952 #if USE_GST_GL_HELPERS
953 if (!plugin->gl_context &&
954 (pool_options & GST_VAAPI_VIDEO_BUFFER_POOL_OPTION_GL_TEXTURE_UPLOAD)) {
955 const GstStructure *params;
956 GstObject *gl_context;
958 gst_query_parse_nth_allocation_meta (query, idx, ¶ms);
960 if (gst_structure_get (params, "gst.gl.GstGLContext", GST_TYPE_GL_CONTEXT,
961 &gl_context, NULL) && gl_context) {
962 gst_vaapi_plugin_base_set_gl_context (plugin, gl_context);
963 gst_vaapi_plugin_base_set_srcpad_can_dmabuf (plugin, gl_context);
964 gst_object_unref (gl_context);
971 /* Make sure the display we pass down to the buffer pool is actually
972 the expected one, especially when the downstream element requires
973 a GLX or EGL display */
974 if (!gst_vaapi_plugin_base_ensure_display (plugin))
975 goto error_ensure_display;
977 if (!gst_video_info_from_caps (&vi, caps))
978 goto error_invalid_caps;
979 gst_video_info_force_nv12_if_encoded (&vi);
981 index_allocator = -1;
982 num_allocators = gst_query_get_n_allocation_params (query);
983 for (i = 0; i < num_allocators; i++) {
984 GstAllocator *allocator = NULL;
985 GstAllocationParams params;
987 gst_query_parse_nth_allocation_param (query, i, &allocator, ¶ms);
991 /* Let's keep the the first allocator if it is not VA-API. It
992 * might be used if it is required to copy the output frame to a
995 && g_strcmp0 (allocator->mem_type, GST_VAAPI_VIDEO_MEMORY_NAME) != 0) {
996 if (srcpriv->other_allocator)
997 gst_object_unref (srcpriv->other_allocator);
998 srcpriv->other_allocator = allocator;
999 srcpriv->other_allocator_params = params;
1003 if (g_strcmp0 (allocator->mem_type, GST_VAAPI_VIDEO_MEMORY_NAME) == 0) {
1004 GST_DEBUG_OBJECT (plugin, "found vaapi allocator in query %"
1005 GST_PTR_FORMAT, allocator);
1006 index_allocator = i;
1007 if (srcpriv->allocator)
1008 gst_object_unref (srcpriv->allocator);
1009 srcpriv->allocator = allocator;
1012 gst_object_unref (allocator);
1015 if (gst_query_get_n_allocation_pools (query) > 0) {
1016 gst_query_parse_nth_allocation_pool (query, 0, &pool, &size, &min, &max);
1018 size = MAX (size, GST_VIDEO_INFO_SIZE (&vi));
1020 /* Check whether downstream element proposed a bufferpool but did
1021 not provide a correct propose_allocation() implementation */
1022 if (gst_buffer_pool_has_option (pool,
1023 GST_BUFFER_POOL_OPTION_VIDEO_ALIGNMENT))
1024 pool_options |= GST_VAAPI_VIDEO_BUFFER_POOL_OPTION_VIDEO_ALIGNMENT;
1026 /* GstVaapiVideoMeta is mandatory, and this implies VA surface memory */
1027 if (!gst_buffer_pool_has_option (pool,
1028 GST_BUFFER_POOL_OPTION_VAAPI_VIDEO_META)) {
1029 GST_INFO_OBJECT (plugin, "ignoring non-VAAPI pool: %" GST_PTR_FORMAT,
1031 g_clear_object (&pool);
1036 size = GST_VIDEO_INFO_SIZE (&vi);
1041 if (!ensure_srcpad_allocator (plugin, &vi, caps))
1043 size = GST_VIDEO_INFO_SIZE (&vi); /* size might be updated by
1045 pool = gst_vaapi_plugin_base_create_pool (plugin, caps, size, min, max,
1046 pool_options, srcpriv->allocator);
1052 gst_query_set_nth_allocation_pool (query, 0, pool, size, min, max);
1054 gst_query_add_allocation_pool (query, pool, size, min, max);
1056 /* allocator might be updated by ensure_srcpad_allocator() */
1057 if (srcpriv->allocator) {
1058 if (index_allocator > 0) {
1059 gst_query_set_nth_allocation_param (query, index_allocator,
1060 srcpriv->allocator, NULL);
1062 GST_DEBUG_OBJECT (plugin, "adding allocator in query %" GST_PTR_FORMAT,
1063 srcpriv->allocator);
1064 gst_query_add_allocation_param (query, srcpriv->allocator, NULL);
1068 g_clear_object (&srcpriv->buffer_pool);
1069 srcpriv->buffer_pool = pool;
1071 /* if downstream doesn't support GstVideoMeta, and the negotiated
1072 * caps are raw video, and the used allocator is the VA-API one, we
1073 * should copy the VA-API frame into a dumb buffer */
1074 plugin->copy_output_frame = gst_vaapi_video_buffer_pool_copy_buffer (pool);
1081 GST_ERROR_OBJECT (plugin, "no caps specified");
1086 GST_ERROR_OBJECT (plugin, "invalid caps %" GST_PTR_FORMAT, caps);
1089 error_ensure_display:
1091 GST_ERROR_OBJECT (plugin, "failed to ensure display of type %d",
1092 plugin->display_type_req);
1097 /* error message already sent */
1103 * gst_vaapi_plugin_base_get_input_buffer:
1104 * @plugin: a #GstVaapiPluginBase
1105 * @inbuf: the sink pad (input) buffer
1106 * @outbuf_ptr: the pointer to location to the VA surface backed buffer
1108 * Acquires the sink pad (input) buffer as a VA surface backed
1109 * buffer. This is mostly useful for raw YUV buffers, as source
1110 * buffers that are already backed as a VA surface are passed
1113 * Returns: #GST_FLOW_OK if the buffer could be acquired
1116 gst_vaapi_plugin_base_get_input_buffer (GstVaapiPluginBase * plugin,
1117 GstBuffer * inbuf, GstBuffer ** outbuf_ptr)
1119 GstVaapiPadPrivate *sinkpriv = GST_VAAPI_PAD_PRIVATE (plugin->sinkpad);
1120 GstVaapiVideoMeta *meta;
1122 GstVideoFrame src_frame, out_frame;
1125 g_return_val_if_fail (inbuf != NULL, GST_FLOW_ERROR);
1126 g_return_val_if_fail (outbuf_ptr != NULL, GST_FLOW_ERROR);
1128 meta = gst_buffer_get_vaapi_video_meta (inbuf);
1130 *outbuf_ptr = gst_buffer_ref (inbuf);
1134 if (!sinkpriv->caps_is_raw)
1135 goto error_invalid_buffer;
1137 if (!sinkpriv->buffer_pool)
1140 if (!gst_buffer_pool_is_active (sinkpriv->buffer_pool) &&
1141 !gst_buffer_pool_set_active (sinkpriv->buffer_pool, TRUE))
1142 goto error_active_pool;
1145 if (gst_buffer_pool_acquire_buffer (sinkpriv->buffer_pool,
1146 &outbuf, NULL) != GST_FLOW_OK)
1147 goto error_create_buffer;
1149 if (is_dma_buffer (inbuf)) {
1150 if (!plugin_bind_dma_to_vaapi_buffer (plugin, inbuf, outbuf))
1151 goto error_bind_dma_buffer;
1155 if (!gst_video_frame_map (&src_frame, &sinkpriv->info, inbuf, GST_MAP_READ))
1156 goto error_map_src_buffer;
1158 if (!gst_video_frame_map (&out_frame, &sinkpriv->info, outbuf, GST_MAP_WRITE))
1159 goto error_map_dst_buffer;
1161 success = gst_video_frame_copy (&out_frame, &src_frame);
1162 gst_video_frame_unmap (&out_frame);
1163 gst_video_frame_unmap (&src_frame);
1165 goto error_copy_buffer;
1168 if (!gst_buffer_copy_into (outbuf, inbuf, GST_BUFFER_COPY_FLAGS |
1169 GST_BUFFER_COPY_TIMESTAMPS | GST_BUFFER_COPY_META, 0, -1))
1170 return GST_FLOW_ERROR;
1171 *outbuf_ptr = outbuf;
1177 GST_ELEMENT_ERROR (plugin, STREAM, FAILED,
1178 ("no buffer pool was negotiated"), ("no buffer pool was negotiated"));
1179 return GST_FLOW_ERROR;
1183 GST_ELEMENT_ERROR (plugin, STREAM, FAILED,
1184 ("failed to activate buffer pool"), ("failed to activate buffer pool"));
1185 return GST_FLOW_ERROR;
1187 error_map_dst_buffer:
1189 gst_video_frame_unmap (&src_frame);
1192 error_map_src_buffer:
1194 GST_WARNING ("failed to map buffer");
1195 gst_buffer_unref (outbuf);
1196 return GST_FLOW_NOT_SUPPORTED;
1200 error_invalid_buffer:
1202 GST_ELEMENT_ERROR (plugin, STREAM, FAILED,
1203 ("failed to validate source buffer"),
1204 ("failed to validate source buffer"));
1205 return GST_FLOW_ERROR;
1207 error_create_buffer:
1209 GST_ELEMENT_ERROR (plugin, STREAM, FAILED, ("Allocation failed"),
1210 ("failed to create buffer"));
1211 return GST_FLOW_ERROR;
1213 error_bind_dma_buffer:
1215 GST_ELEMENT_ERROR (plugin, STREAM, FAILED, ("Allocation failed"),
1216 ("failed to bind dma_buf to VA surface buffer"));
1217 gst_buffer_unref (outbuf);
1218 return GST_FLOW_ERROR;
1222 GST_WARNING_OBJECT (plugin, "failed to upload buffer to VA surface");
1223 gst_buffer_unref (outbuf);
1224 return GST_FLOW_NOT_SUPPORTED;
1229 * gst_vaapi_plugin_base_set_gl_context:
1230 * @plugin: a #GstVaapiPluginBase
1231 * @object: the new GL context from downstream
1233 * Registers the new GL context. The change is effective at the next
1234 * call to gst_vaapi_plugin_base_ensure_display(), where the
1235 * underlying display object could be re-allocated to fit the GL
1239 gst_vaapi_plugin_base_set_gl_context (GstVaapiPluginBase * plugin,
1242 #if USE_GST_GL_HELPERS
1243 GstGLContext *const gl_context = GST_GL_CONTEXT (object);
1244 GstVaapiDisplayType display_type;
1246 if (plugin->gl_context == object)
1249 gst_object_replace (&plugin->gl_context, object);
1251 switch (gst_gl_context_get_gl_platform (gl_context)) {
1253 case GST_GL_PLATFORM_GLX:
1254 display_type = GST_VAAPI_DISPLAY_TYPE_GLX;
1257 case GST_GL_PLATFORM_EGL:
1259 display_type = GST_VAAPI_DISPLAY_TYPE_EGL;
1263 display_type = plugin->display_type;
1266 GST_INFO_OBJECT (plugin, "GL context: %" GST_PTR_FORMAT, plugin->gl_context);
1267 gst_vaapi_plugin_base_set_display_type (plugin, display_type);
1272 * gst_vaapi_plugin_base_create_gl_context:
1273 * @plugin: a #GstVaapiPluginBase
1275 * It queries downstream and upstream for a #GstGLDisplay and a other
1276 * #GstGLContext. If not found, a new #GstGLDisplay and #GstGLContext
1277 * are created, if it is possible.
1279 * Returns: (transfer full) a new created #GstGLContext or %NULL
1282 gst_vaapi_plugin_base_create_gl_context (GstVaapiPluginBase * plugin)
1284 #if USE_GST_GL_HELPERS
1285 GstGLContext *gl_other_context = NULL, *gl_context = NULL;
1286 GstGLDisplay *gl_display = NULL;
1288 if (!plugin->gl_display)
1291 gl_display = (GstGLDisplay *) plugin->gl_display;
1292 if (gst_gl_display_get_handle_type (gl_display) == GST_GL_DISPLAY_TYPE_ANY)
1293 goto no_valid_gl_display;
1294 gl_other_context = (GstGLContext *) plugin->gl_other_context;
1296 GST_INFO_OBJECT (plugin, "creating a new GstGL context");
1298 GST_OBJECT_LOCK (gl_display);
1301 gst_object_unref (gl_context);
1302 gl_context = gst_gl_display_get_gl_context_for_thread (gl_display, NULL);
1304 if (!gst_gl_display_create_context (gl_display, gl_other_context,
1308 } while (!gst_gl_display_add_context (gl_display, gl_context));
1309 GST_OBJECT_UNLOCK (gl_display);
1311 return GST_OBJECT_CAST (gl_context);
1314 no_valid_gl_display:
1316 GST_INFO_OBJECT (plugin, "No valid GL display found");
1317 gst_object_replace (&plugin->gl_display, NULL);
1318 gst_object_replace (&plugin->gl_other_context, NULL);
1327 extract_allowed_surface_formats (GstVaapiDisplay * display,
1328 GArray * img_formats, GstVideoFormat specified_format,
1329 GstPadDirection direction)
1332 GArray *out_formats;
1333 GstVaapiSurface *surface = NULL;
1335 g_assert (direction == GST_PAD_SRC || direction == GST_PAD_SINK);
1338 g_array_sized_new (FALSE, FALSE, sizeof (GstVideoFormat),
1343 for (i = 0; i < img_formats->len; i++) {
1344 const GstVideoFormat img_format =
1345 g_array_index (img_formats, GstVideoFormat, i);
1346 GstVaapiImage *image;
1348 GstVideoFormat surface_format;
1351 if (img_format == GST_VIDEO_FORMAT_UNKNOWN)
1355 (specified_format == GST_VIDEO_FORMAT_UNKNOWN) ?
1356 img_format : specified_format;
1358 gst_video_info_set_format (&vi, surface_format, 64, 64);
1359 surface = gst_vaapi_surface_new_full (display, &vi, 0);
1364 image = gst_vaapi_image_new (display, img_format, 64, 64);
1366 /* Just reuse the surface if the format is specified */
1367 if (specified_format == GST_VIDEO_FORMAT_UNKNOWN)
1368 gst_vaapi_object_replace (&surface, NULL);
1374 if (direction == GST_PAD_SRC) {
1375 res = gst_vaapi_surface_get_image (surface, image);
1377 res = gst_vaapi_surface_put_image (surface, image);
1380 g_array_append_val (out_formats, img_format);
1382 gst_vaapi_object_unref (image);
1383 /* Just reuse the surface if the format is specified */
1384 if (specified_format == GST_VIDEO_FORMAT_UNKNOWN)
1385 gst_vaapi_object_replace (&surface, NULL);
1389 gst_vaapi_object_unref (surface);
1391 if (out_formats->len == 0) {
1392 g_array_unref (out_formats);
1399 ensure_allowed_raw_caps (GstVaapiPluginBase * plugin, GstVideoFormat format,
1400 GstPadDirection direction)
1402 GArray *formats, *out_formats;
1403 GstVaapiDisplay *display;
1405 gboolean ret = FALSE;
1407 if (plugin->allowed_raw_caps)
1411 display = gst_object_ref (plugin->display);
1412 formats = gst_vaapi_display_get_image_formats (display);
1416 extract_allowed_surface_formats (display, formats, format, direction);
1419 out_caps = gst_vaapi_video_format_new_template_caps_from_list (out_formats);
1423 gst_caps_replace (&plugin->allowed_raw_caps, out_caps);
1424 gst_caps_unref (out_caps);
1429 g_array_unref (formats);
1431 g_array_unref (out_formats);
1432 gst_object_unref (display);
1438 * gst_vaapi_plugin_base_get_allowed_sinkpad_raw_caps:
1439 * @plugin: a #GstVaapiPluginBase
1441 * Returns the raw #GstCaps allowed by the element.
1443 * Returns: the allowed raw #GstCaps or %NULL
1446 gst_vaapi_plugin_base_get_allowed_sinkpad_raw_caps (GstVaapiPluginBase * plugin)
1448 if (!ensure_allowed_raw_caps (plugin, GST_VIDEO_FORMAT_UNKNOWN, GST_PAD_SINK))
1450 return plugin->allowed_raw_caps;
1454 * gst_vaapi_plugin_base_get_allowed_srcpad_raw_caps:
1455 * @plugin: a #GstVaapiPluginBase
1456 * @format: a #GstVideoFormat, the format we need to check
1458 * Returns the raw #GstCaps allowed by the element.
1460 * Returns: the allowed raw #GstCaps or %NULL
1463 gst_vaapi_plugin_base_get_allowed_srcpad_raw_caps (GstVaapiPluginBase *
1464 plugin, GstVideoFormat format)
1466 if (!ensure_allowed_raw_caps (plugin, format, GST_PAD_SRC))
1468 return plugin->allowed_raw_caps;
1472 * gst_vaapi_plugin_base_set_srcpad_can_dmabuf:
1473 * @plugin: a #GstVaapiPluginBase
1474 * @object: the GL context from gst-gl
1476 * This function will determine if @object supports dmabuf
1479 * Please note that the context @object should come from downstream.
1482 gst_vaapi_plugin_base_set_srcpad_can_dmabuf (GstVaapiPluginBase * plugin,
1485 #if USE_EGL && USE_GST_GL_HELPERS
1486 GstVaapiPadPrivate *srcpriv = GST_VAAPI_PAD_PRIVATE (plugin->srcpad);
1487 GstGLContext *const gl_context = GST_GL_CONTEXT (object);
1489 srcpriv->can_dmabuf =
1490 (!(gst_gl_context_get_gl_api (gl_context) & GST_GL_API_GLES1)
1491 && gst_gl_context_check_feature (gl_context,
1492 "EGL_EXT_image_dma_buf_import"));
1497 _init_performance_debug (void)
1499 #ifndef GST_DISABLE_GST_DEBUG
1500 static volatile gsize _init = 0;
1502 if (g_once_init_enter (&_init)) {
1503 GST_DEBUG_CATEGORY_GET (CAT_PERFORMANCE, "GST_PERFORMANCE");
1504 g_once_init_leave (&_init, 1);
1510 * gst_vaapi_plugin_copy_va_buffer:
1511 * @plugin: a #GstVaapiPluginBase
1512 * @inbuf: a #GstBuffer with VA memory type
1513 * @outbuf: a #GstBuffer with system allocated memory
1515 * Copy @inbuf to @outbuf. This if required when downstream doesn't
1516 * support GstVideoMeta, and since VA memory may have custom strides a
1517 * frame copy is required.
1519 * Returns: %FALSE if the copy failed, otherwise %TRUE. Also returns
1520 * %TRUE if it is not required to do the copy
1523 gst_vaapi_plugin_copy_va_buffer (GstVaapiPluginBase * plugin,
1524 GstBuffer * inbuf, GstBuffer * outbuf)
1526 GstVaapiPadPrivate *srcpriv = GST_VAAPI_PAD_PRIVATE (plugin->srcpad);
1527 GstVideoMeta *vmeta;
1528 GstVideoFrame src_frame, dst_frame;
1531 if (!plugin->copy_output_frame)
1534 /* inbuf shall have video meta */
1535 vmeta = gst_buffer_get_video_meta (inbuf);
1539 _init_performance_debug ();
1540 GST_CAT_INFO (CAT_PERFORMANCE, "copying VA buffer to system memory buffer");
1542 if (!gst_video_frame_map (&src_frame, &srcpriv->info, inbuf, GST_MAP_READ))
1544 if (!gst_video_frame_map (&dst_frame, &srcpriv->info, outbuf, GST_MAP_WRITE)) {
1545 gst_video_frame_unmap (&src_frame);
1548 success = gst_video_frame_copy (&dst_frame, &src_frame);
1549 gst_video_frame_unmap (&dst_frame);
1550 gst_video_frame_unmap (&src_frame);
1553 gst_buffer_copy_into (outbuf, inbuf, GST_BUFFER_COPY_TIMESTAMPS
1554 | GST_BUFFER_COPY_FLAGS, 0, -1);