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 #include <gst/allocators/allocators.h>
35 /* Default debug category is from the subclass */
36 #define GST_CAT_DEFAULT (plugin->debug_category)
38 /* GstVideoContext interface */
40 plugin_set_display (GstVaapiPluginBase * plugin, GstVaapiDisplay * display)
42 const gchar *const display_name =
43 gst_vaapi_display_get_display_name (display);
45 if (plugin->display_name && g_strcmp0 (plugin->display_name, display_name)) {
46 GST_DEBUG_OBJECT (plugin, "incompatible display name '%s', requested '%s'",
47 display_name, plugin->display_name);
48 gst_vaapi_display_replace (&plugin->display, NULL);
50 GST_INFO_OBJECT (plugin, "set display %p", display);
51 gst_vaapi_display_replace (&plugin->display, display);
52 plugin->display_type = gst_vaapi_display_get_display_type (display);
53 gst_vaapi_plugin_base_set_display_name (plugin, display_name);
55 gst_vaapi_display_unref (display);
59 plugin_set_context (GstElement * element, GstContext * context)
61 GstVaapiPluginBase *const plugin = GST_VAAPI_PLUGIN_BASE (element);
62 GstVaapiDisplay *display = NULL;
64 if (gst_vaapi_video_context_get_display (context, &display))
65 plugin_set_display (plugin, display);
69 gst_vaapi_plugin_base_init_interfaces (GType g_define_type_id)
74 default_has_interface (GstVaapiPluginBase * plugin, GType type)
80 default_display_changed (GstVaapiPluginBase * plugin)
85 plugin_update_sinkpad_info_from_buffer (GstVaapiPluginBase * plugin,
88 GstVideoInfo *const vip = &plugin->sinkpad_info;
92 vmeta = gst_buffer_get_video_meta (buf);
96 if (GST_VIDEO_INFO_FORMAT (vip) != vmeta->format ||
97 GST_VIDEO_INFO_WIDTH (vip) != vmeta->width ||
98 GST_VIDEO_INFO_HEIGHT (vip) != vmeta->height ||
99 GST_VIDEO_INFO_N_PLANES (vip) != vmeta->n_planes)
102 for (i = 0; i < GST_VIDEO_INFO_N_PLANES (vip); ++i) {
103 GST_VIDEO_INFO_PLANE_OFFSET (vip, i) = vmeta->offset[i];
104 GST_VIDEO_INFO_PLANE_STRIDE (vip, i) = vmeta->stride[i];
106 GST_VIDEO_INFO_SIZE (vip) = gst_buffer_get_size (buf);
111 is_dma_buffer (GstBuffer * buf)
115 if (gst_buffer_n_memory (buf) < 1)
118 mem = gst_buffer_peek_memory (buf, 0);
119 if (!mem || !gst_is_dmabuf_memory (mem))
125 plugin_bind_dma_to_vaapi_buffer (GstVaapiPluginBase * plugin,
126 GstBuffer * inbuf, GstBuffer * outbuf)
128 GstVideoInfo *const vip = &plugin->sinkpad_info;
129 GstVaapiVideoMeta *meta;
130 GstVaapiSurface *surface;
131 GstVaapiSurfaceProxy *proxy;
134 fd = gst_dmabuf_memory_get_fd (gst_buffer_peek_memory (inbuf, 0));
138 if (!plugin_update_sinkpad_info_from_buffer (plugin, inbuf))
139 goto error_update_sinkpad_info;
141 meta = gst_buffer_get_vaapi_video_meta (outbuf);
142 g_return_val_if_fail (meta != NULL, FALSE);
144 surface = gst_vaapi_surface_new_with_dma_buf_handle (plugin->display, fd,
145 GST_VIDEO_INFO_SIZE (vip), GST_VIDEO_INFO_FORMAT (vip),
146 GST_VIDEO_INFO_WIDTH (vip), GST_VIDEO_INFO_HEIGHT (vip),
147 vip->offset, vip->stride);
149 goto error_create_surface;
151 proxy = gst_vaapi_surface_proxy_new (surface);
152 gst_vaapi_object_unref (surface);
154 goto error_create_proxy;
156 gst_vaapi_surface_proxy_set_destroy_notify (proxy,
157 (GDestroyNotify) gst_buffer_unref, (gpointer) gst_buffer_ref (inbuf));
158 gst_vaapi_video_meta_set_surface_proxy (meta, proxy);
159 gst_vaapi_surface_proxy_unref (proxy);
163 error_update_sinkpad_info:
164 GST_ERROR ("failed to update sink pad video info from video meta");
166 error_create_surface:
167 GST_ERROR ("failed to create VA surface from dma_buf handle");
170 GST_ERROR ("failed to create VA surface proxy from wrapped VA surface");
175 gst_vaapi_plugin_base_class_init (GstVaapiPluginBaseClass * klass)
177 klass->has_interface = default_has_interface;
178 klass->display_changed = default_display_changed;
180 GstElementClass *const element_class = GST_ELEMENT_CLASS (klass);
181 element_class->set_context = GST_DEBUG_FUNCPTR (plugin_set_context);
185 gst_vaapi_plugin_base_init (GstVaapiPluginBase * plugin,
186 GstDebugCategory * debug_category)
188 plugin->debug_category = debug_category;
189 plugin->display_type = GST_VAAPI_DISPLAY_TYPE_ANY;
190 plugin->display_type_req = GST_VAAPI_DISPLAY_TYPE_ANY;
193 plugin->sinkpad = gst_element_get_static_pad (GST_ELEMENT (plugin), "sink");
194 plugin->sinkpad_query = GST_PAD_QUERYFUNC (plugin->sinkpad);
195 gst_video_info_init (&plugin->sinkpad_info);
198 if (!(GST_OBJECT_FLAGS (plugin) & GST_ELEMENT_FLAG_SINK)) {
199 plugin->srcpad = gst_element_get_static_pad (GST_ELEMENT (plugin), "src");
200 plugin->srcpad_query = GST_PAD_QUERYFUNC (plugin->srcpad);
202 gst_video_info_init (&plugin->srcpad_info);
206 gst_vaapi_plugin_base_finalize (GstVaapiPluginBase * plugin)
208 gst_vaapi_plugin_base_close (plugin);
209 g_free (plugin->display_name);
211 gst_object_unref (plugin->sinkpad);
213 gst_object_unref (plugin->srcpad);
217 * gst_vaapi_plugin_base_open:
218 * @plugin: a #GstVaapiPluginBase
220 * Allocates any internal resources needed for correct operation from
223 * Returns: %TRUE if successful, %FALSE otherwise.
226 gst_vaapi_plugin_base_open (GstVaapiPluginBase * plugin)
232 * gst_vaapi_plugin_base_close:
233 * @plugin: a #GstVaapiPluginBase
235 * Deallocates all internal resources that were allocated so
236 * far. i.e. put the base plugin object into a clean state.
239 gst_vaapi_plugin_base_close (GstVaapiPluginBase * plugin)
241 g_clear_object (&plugin->uploader);
242 gst_vaapi_display_replace (&plugin->display, NULL);
243 gst_object_replace (&plugin->gl_context, NULL);
245 gst_caps_replace (&plugin->sinkpad_caps, NULL);
246 plugin->sinkpad_caps_changed = FALSE;
247 gst_video_info_init (&plugin->sinkpad_info);
248 if (plugin->sinkpad_buffer_pool) {
249 gst_object_unref (plugin->sinkpad_buffer_pool);
250 plugin->sinkpad_buffer_pool = NULL;
252 g_clear_object (&plugin->srcpad_buffer_pool);
254 gst_caps_replace (&plugin->srcpad_caps, NULL);
255 plugin->srcpad_caps_changed = FALSE;
256 gst_video_info_init (&plugin->srcpad_info);
260 * gst_vaapi_plugin_base_has_display_type:
261 * @plugin: a #GstVaapiPluginBase
262 * @display_type_req: the desired #GstVaapiDisplayType
264 * Checks whether the @plugin elements already has a #GstVaapiDisplay
265 * instance compatible with type @display_type_req.
267 * Return value: %TRUE if @plugin has a compatible display, %FALSE otherwise
270 gst_vaapi_plugin_base_has_display_type (GstVaapiPluginBase * plugin,
271 GstVaapiDisplayType display_type_req)
273 GstVaapiDisplayType display_type;
275 if (!plugin->display)
278 display_type = plugin->display_type;
279 if (gst_vaapi_display_type_is_compatible (display_type, display_type_req))
282 display_type = gst_vaapi_display_get_class_type (plugin->display);
283 if (gst_vaapi_display_type_is_compatible (display_type, display_type_req))
289 * gst_vaapi_plugin_base_set_display_type:
290 * @plugin: a #GstVaapiPluginBase
291 * @display_type: the new request #GstVaapiDisplayType
293 * Requests a new display type. The change is effective at the next
294 * call to gst_vaapi_plugin_base_ensure_display().
297 gst_vaapi_plugin_base_set_display_type (GstVaapiPluginBase * plugin,
298 GstVaapiDisplayType display_type)
300 plugin->display_type_req = display_type;
304 * gst_vaapi_plugin_base_set_display_name:
305 * @plugin: a #GstVaapiPluginBase
306 * @display_name: the new display name to match
308 * Sets the name of the display to look for. The change is effective
309 * at the next call to gst_vaapi_plugin_base_ensure_display().
312 gst_vaapi_plugin_base_set_display_name (GstVaapiPluginBase * plugin,
313 const gchar * display_name)
315 g_free (plugin->display_name);
316 plugin->display_name = g_strdup (display_name);
320 * gst_vaapi_plugin_base_ensure_display:
321 * @plugin: a #GstVaapiPluginBase
323 * Ensures the display stored in @plugin complies with the requested
324 * display type constraints.
326 * Returns: %TRUE if the display was created to match the requested
327 * type, %FALSE otherwise.
330 gst_vaapi_plugin_base_ensure_display (GstVaapiPluginBase * plugin)
332 if (gst_vaapi_plugin_base_has_display_type (plugin, plugin->display_type_req))
334 gst_vaapi_display_replace (&plugin->display, NULL);
336 if (!gst_vaapi_ensure_display (plugin, plugin->display_type_req))
338 plugin->display_type = gst_vaapi_display_get_display_type (plugin->display);
340 GST_VAAPI_PLUGIN_BASE_GET_CLASS (plugin)->display_changed (plugin);
345 * gst_vaapi_plugin_base_ensure_uploader:
346 * @plugin: a #GstVaapiPluginBase
348 * Makes sure the built-in #GstVaapiUploader object is created, or
349 * that it was successfully notified of any VA display change.
351 * Returns: %TRUE if the uploader was successfully created, %FALSE otherwise.
354 gst_vaapi_plugin_base_ensure_uploader (GstVaapiPluginBase * plugin)
356 if (plugin->uploader) {
357 if (!gst_vaapi_uploader_ensure_display (plugin->uploader, plugin->display))
360 plugin->uploader = gst_vaapi_uploader_new (plugin->display);
361 if (!plugin->uploader)
367 /* Checks whether the supplied pad peer element supports DMABUF sharing */
368 /* XXX: this is a workaround to the absence of any proposer way to
369 specify DMABUF memory capsfeatures or bufferpool option to downstream */
371 has_dmabuf_capable_peer (GstVaapiPluginBase * plugin, GstPad * pad)
373 GstPad *other_pad = NULL;
374 GstElement *element = NULL;
375 gchar *element_name = NULL;
376 gboolean is_dmabuf_capable = FALSE;
379 gst_object_ref (pad);
382 other_pad = gst_pad_get_peer (pad);
383 gst_object_unref (pad);
387 element = gst_pad_get_parent_element (other_pad);
388 gst_object_unref (other_pad);
392 if (GST_IS_PUSH_SRC (element)) {
393 element_name = gst_element_get_name (element);
394 if (!element_name || sscanf (element_name, "v4l2src%d", &v) != 1)
398 g_object_get (element, "io-mode", &v, NULL);
399 is_dmabuf_capable = v == 5; /* "dmabuf-import" enum value */
401 } else if (GST_IS_BASE_TRANSFORM (element)) {
402 element_name = gst_element_get_name (element);
403 if (!element_name || sscanf (element_name, "capsfilter%d", &v) != 1)
406 pad = gst_element_get_static_pad (element, "sink");
412 g_free (element_name);
414 g_clear_object (&element);
417 g_free (element_name);
418 g_clear_object (&element);
419 return is_dmabuf_capable;
423 * ensure_sinkpad_buffer_pool:
424 * @plugin: a #GstVaapiPluginBase
425 * @caps: the initial #GstCaps for the resulting buffer pool
427 * Makes sure the sink pad video buffer pool is created with the
430 * Returns: %TRUE if successful, %FALSE otherwise.
433 ensure_sinkpad_buffer_pool (GstVaapiPluginBase * plugin, GstCaps * caps)
437 GstStructure *config;
441 if (!gst_vaapi_plugin_base_ensure_display (plugin))
444 if (plugin->sinkpad_buffer_pool) {
445 config = gst_buffer_pool_get_config (plugin->sinkpad_buffer_pool);
446 gst_buffer_pool_config_get_params (config, &pool_caps, NULL, NULL, NULL);
447 need_pool = !gst_caps_is_equal (caps, pool_caps);
448 gst_structure_free (config);
451 g_clear_object (&plugin->sinkpad_buffer_pool);
452 plugin->sinkpad_buffer_size = 0;
455 pool = gst_vaapi_video_buffer_pool_new (plugin->display);
457 goto error_create_pool;
459 gst_video_info_init (&vi);
460 gst_video_info_from_caps (&vi, caps);
461 if (GST_VIDEO_INFO_FORMAT (&vi) == GST_VIDEO_FORMAT_ENCODED) {
462 GST_DEBUG ("assume video buffer pool format is NV12");
463 gst_video_info_set_format (&vi, GST_VIDEO_FORMAT_NV12,
464 GST_VIDEO_INFO_WIDTH (&vi), GST_VIDEO_INFO_HEIGHT (&vi));
466 plugin->sinkpad_buffer_size = vi.size;
468 config = gst_buffer_pool_get_config (pool);
469 gst_buffer_pool_config_set_params (config, caps,
470 plugin->sinkpad_buffer_size, 0, 0);
471 gst_buffer_pool_config_add_option (config,
472 GST_BUFFER_POOL_OPTION_VAAPI_VIDEO_META);
473 gst_buffer_pool_config_add_option (config, GST_BUFFER_POOL_OPTION_VIDEO_META);
474 if (!gst_buffer_pool_set_config (pool, config))
475 goto error_pool_config;
476 plugin->sinkpad_buffer_pool = pool;
482 GST_ERROR ("failed to create buffer pool");
487 GST_ERROR ("failed to reset buffer pool config");
488 gst_object_unref (pool);
494 * gst_vaapi_plugin_base_set_caps:
495 * @plugin: a #GstVaapiPluginBase
496 * @incaps: the sink pad (input) caps
497 * @outcaps: the src pad (output) caps
499 * Notifies the base plugin object of the new input and output caps,
500 * obtained from the subclass.
502 * Returns: %TRUE if the update of caps was successful, %FALSE otherwise.
505 gst_vaapi_plugin_base_set_caps (GstVaapiPluginBase * plugin, GstCaps * incaps,
508 if (incaps && incaps != plugin->sinkpad_caps) {
509 gst_caps_replace (&plugin->sinkpad_caps, incaps);
510 if (!gst_video_info_from_caps (&plugin->sinkpad_info, incaps))
512 plugin->sinkpad_caps_changed = TRUE;
513 plugin->sinkpad_caps_is_raw = !gst_caps_has_vaapi_surface (incaps);
516 if (outcaps && outcaps != plugin->srcpad_caps) {
517 gst_caps_replace (&plugin->srcpad_caps, outcaps);
518 if (!gst_video_info_from_caps (&plugin->srcpad_info, outcaps))
520 plugin->srcpad_caps_changed = TRUE;
523 if (plugin->uploader && plugin->sinkpad_caps_is_raw) {
524 if (!gst_vaapi_uploader_ensure_display (plugin->uploader, plugin->display))
526 if (!gst_vaapi_uploader_ensure_caps (plugin->uploader,
527 plugin->sinkpad_caps, plugin->srcpad_caps))
531 if (!ensure_sinkpad_buffer_pool (plugin, plugin->sinkpad_caps))
537 * gst_vaapi_plugin_base_propose_allocation:
538 * @plugin: a #GstVaapiPluginBase
539 * @query: the allocation query to configure
541 * Proposes allocation parameters to the upstream elements.
543 * Returns: %TRUE if successful, %FALSE otherwise.
546 gst_vaapi_plugin_base_propose_allocation (GstVaapiPluginBase * plugin,
549 GstCaps *caps = NULL;
552 gst_query_parse_allocation (query, &caps, &need_pool);
557 if (!ensure_sinkpad_buffer_pool (plugin, caps))
559 gst_query_add_allocation_pool (query, plugin->sinkpad_buffer_pool,
560 plugin->sinkpad_buffer_size, 0, 0);
562 if (has_dmabuf_capable_peer (plugin, plugin->sinkpad)) {
563 GstStructure *const config =
564 gst_buffer_pool_get_config (plugin->sinkpad_buffer_pool);
566 gst_buffer_pool_config_add_option (config,
567 GST_BUFFER_POOL_OPTION_DMABUF_MEMORY);
568 if (!gst_buffer_pool_set_config (plugin->sinkpad_buffer_pool, config))
569 goto error_pool_config;
573 gst_query_add_allocation_meta (query, GST_VAAPI_VIDEO_META_API_TYPE, NULL);
574 gst_query_add_allocation_meta (query, GST_VIDEO_META_API_TYPE, NULL);
580 GST_ERROR ("no caps specified");
585 GST_ERROR ("failed to reset buffer pool config");
591 * gst_vaapi_plugin_base_decide_allocation:
592 * @plugin: a #GstVaapiPluginBase
593 * @query: the allocation query to parse
594 * @feature: the desired #GstVaapiCapsFeature, or zero to find the
597 * Decides allocation parameters for the downstream elements.
599 * Returns: %TRUE if successful, %FALSE otherwise.
602 gst_vaapi_plugin_base_decide_allocation (GstVaapiPluginBase * plugin,
603 GstQuery * query, guint feature)
605 GstCaps *caps = NULL;
607 GstStructure *config;
609 guint size, min, max;
610 gboolean need_pool, update_pool;
611 gboolean has_video_meta = FALSE;
612 gboolean has_video_alignment = FALSE;
613 #if (USE_GLX || USE_EGL)
614 gboolean has_texture_upload_meta = FALSE;
618 g_return_val_if_fail (plugin->display != NULL, FALSE);
620 gst_query_parse_allocation (query, &caps, &need_pool);
622 /* We don't need any GL context beyond this point if not requested
623 so explicitly through GstVideoGLTextureUploadMeta */
624 gst_object_replace (&plugin->gl_context, NULL);
631 gst_vaapi_find_preferred_caps_feature (plugin->srcpad,
632 GST_VIDEO_FORMAT_ENCODED, NULL);
634 has_video_meta = gst_query_find_allocation_meta (query,
635 GST_VIDEO_META_API_TYPE, NULL);
637 #if (USE_GLX || USE_EGL)
638 has_texture_upload_meta = gst_query_find_allocation_meta (query,
639 GST_VIDEO_GL_TEXTURE_UPLOAD_META_API_TYPE, &idx) &&
640 (feature == GST_VAAPI_CAPS_FEATURE_GL_TEXTURE_UPLOAD_META);
642 #if USE_GST_GL_HELPERS
643 if (has_texture_upload_meta) {
644 const GstStructure *params;
645 GstObject *gl_context;
647 gst_query_parse_nth_allocation_meta (query, idx, ¶ms);
649 if (gst_structure_get (params, "gst.gl.GstGLContext", GST_GL_TYPE_CONTEXT,
650 &gl_context, NULL) && gl_context) {
651 gst_vaapi_plugin_base_set_gl_context (plugin, gl_context);
652 gst_object_unref (gl_context);
659 /* Make sure the display we pass down to the buffer pool is actually
660 the expected one, especially when the downstream element requires
661 a GLX or EGL display */
662 if (!gst_vaapi_plugin_base_ensure_display (plugin))
663 goto error_ensure_display;
665 gst_video_info_init (&vi);
666 gst_video_info_from_caps (&vi, caps);
667 if (GST_VIDEO_INFO_FORMAT (&vi) == GST_VIDEO_FORMAT_ENCODED)
668 gst_video_info_set_format (&vi, GST_VIDEO_FORMAT_I420,
669 GST_VIDEO_INFO_WIDTH (&vi), GST_VIDEO_INFO_HEIGHT (&vi));
671 if (gst_query_get_n_allocation_pools (query) > 0) {
672 gst_query_parse_nth_allocation_pool (query, 0, &pool, &size, &min, &max);
674 size = MAX (size, vi.size);
677 /* Check whether downstream element proposed a bufferpool but did
678 not provide a correct propose_allocation() implementation */
679 has_video_alignment = gst_buffer_pool_has_option (pool,
680 GST_BUFFER_POOL_OPTION_VIDEO_ALIGNMENT);
689 /* GstVaapiVideoMeta is mandatory, and this implies VA surface memory */
690 if (!pool || !gst_buffer_pool_has_option (pool,
691 GST_BUFFER_POOL_OPTION_VAAPI_VIDEO_META)) {
692 GST_INFO_OBJECT (plugin, "no pool or doesn't support GstVaapiVideoMeta, "
695 gst_object_unref (pool);
696 pool = gst_vaapi_video_buffer_pool_new (plugin->display);
698 goto error_create_pool;
700 config = gst_buffer_pool_get_config (pool);
701 gst_buffer_pool_config_set_params (config, caps, size, min, max);
702 gst_buffer_pool_config_add_option (config,
703 GST_BUFFER_POOL_OPTION_VAAPI_VIDEO_META);
704 gst_buffer_pool_set_config (pool, config);
707 /* Check whether GstVideoMeta, or GstVideoAlignment, is needed (raw video) */
708 if (has_video_meta) {
709 config = gst_buffer_pool_get_config (pool);
710 gst_buffer_pool_config_add_option (config,
711 GST_BUFFER_POOL_OPTION_VIDEO_META);
712 gst_buffer_pool_set_config (pool, config);
713 } else if (has_video_alignment) {
714 config = gst_buffer_pool_get_config (pool);
715 gst_buffer_pool_config_add_option (config,
716 GST_BUFFER_POOL_OPTION_VIDEO_ALIGNMENT);
717 gst_buffer_pool_set_config (pool, config);
720 /* GstVideoGLTextureUploadMeta (OpenGL) */
721 #if (USE_GLX || USE_EGL)
722 if (has_texture_upload_meta) {
723 config = gst_buffer_pool_get_config (pool);
724 gst_buffer_pool_config_add_option (config,
725 GST_BUFFER_POOL_OPTION_VIDEO_GL_TEXTURE_UPLOAD_META);
726 gst_buffer_pool_set_config (pool, config);
731 gst_query_set_nth_allocation_pool (query, 0, pool, size, min, max);
733 gst_query_add_allocation_pool (query, pool, size, min, max);
735 g_clear_object (&plugin->srcpad_buffer_pool);
736 plugin->srcpad_buffer_pool = pool;
742 GST_ERROR_OBJECT (plugin, "no caps specified");
745 error_ensure_display:
747 GST_ERROR_OBJECT (plugin, "failed to ensure display of type %d",
748 plugin->display_type_req);
753 GST_ERROR_OBJECT (plugin, "failed to create buffer pool");
759 * gst_vaapi_plugin_base_allocate_input_buffer:
760 * @plugin: a #GstVaapiPluginBase
761 * @caps: the buffer caps constraints to honour
762 * @outbuf_ptr: the pointer location to the newly allocated buffer
764 * Creates a buffer that holds a VA surface memory for the sink pad to
765 * use it as the result for buffer_alloc() impementations.
767 * Return: #GST_FLOW_OK if the buffer could be created.
770 gst_vaapi_plugin_base_allocate_input_buffer (GstVaapiPluginBase * plugin,
771 GstCaps * caps, GstBuffer ** outbuf_ptr)
777 if (!plugin->sinkpad_caps_changed) {
778 if (!gst_video_info_from_caps (&plugin->sinkpad_info, caps))
779 return GST_FLOW_NOT_SUPPORTED;
780 plugin->sinkpad_caps_changed = TRUE;
783 if (!plugin->sinkpad_caps_is_raw)
786 if (!gst_vaapi_uploader_ensure_display (plugin->uploader, plugin->display))
787 return GST_FLOW_NOT_SUPPORTED;
788 if (!gst_vaapi_uploader_ensure_caps (plugin->uploader, caps, NULL))
789 return GST_FLOW_NOT_SUPPORTED;
791 outbuf = gst_vaapi_uploader_get_buffer (plugin->uploader);
793 GST_WARNING ("failed to allocate resources for raw YUV buffer");
794 return GST_FLOW_NOT_SUPPORTED;
797 *outbuf_ptr = outbuf;
802 * gst_vaapi_plugin_base_get_input_buffer:
803 * @plugin: a #GstVaapiPluginBase
804 * @incaps: the sink pad (input) buffer
805 * @outbuf_ptr: the pointer to location to the VA surface backed buffer
807 * Acquires the sink pad (input) buffer as a VA surface backed
808 * buffer. This is mostly useful for raw YUV buffers, as source
809 * buffers that are already backed as a VA surface are passed
812 * Returns: #GST_FLOW_OK if the buffer could be acquired
815 gst_vaapi_plugin_base_get_input_buffer (GstVaapiPluginBase * plugin,
816 GstBuffer * inbuf, GstBuffer ** outbuf_ptr)
818 GstVaapiVideoMeta *meta;
820 GstVideoFrame src_frame, out_frame;
823 g_return_val_if_fail (inbuf != NULL, GST_FLOW_ERROR);
824 g_return_val_if_fail (outbuf_ptr != NULL, GST_FLOW_ERROR);
826 meta = gst_buffer_get_vaapi_video_meta (inbuf);
828 *outbuf_ptr = gst_buffer_ref (inbuf);
832 if (!plugin->sinkpad_caps_is_raw)
833 goto error_invalid_buffer;
835 if (!plugin->sinkpad_buffer_pool)
838 if (!gst_buffer_pool_set_active (plugin->sinkpad_buffer_pool, TRUE))
839 goto error_active_pool;
842 if (gst_buffer_pool_acquire_buffer (plugin->sinkpad_buffer_pool,
843 &outbuf, NULL) != GST_FLOW_OK)
844 goto error_create_buffer;
846 if (is_dma_buffer (inbuf)) {
847 if (!plugin_bind_dma_to_vaapi_buffer (plugin, inbuf, outbuf))
848 goto error_bind_dma_buffer;
852 if (!gst_video_frame_map (&src_frame, &plugin->sinkpad_info, inbuf,
854 goto error_map_src_buffer;
856 if (!gst_video_frame_map (&out_frame, &plugin->sinkpad_info, outbuf,
858 goto error_map_dst_buffer;
860 success = gst_video_frame_copy (&out_frame, &src_frame);
861 gst_video_frame_unmap (&out_frame);
862 gst_video_frame_unmap (&src_frame);
864 goto error_copy_buffer;
867 gst_buffer_copy_into (outbuf, inbuf, GST_BUFFER_COPY_FLAGS |
868 GST_BUFFER_COPY_TIMESTAMPS, 0, -1);
869 *outbuf_ptr = outbuf;
875 GST_ELEMENT_ERROR (plugin, STREAM, FAILED,
876 ("no buffer pool was negotiated"),
877 ("no buffer pool was negotiated"));
878 return GST_FLOW_ERROR;
882 GST_ELEMENT_ERROR (plugin, STREAM, FAILED,
883 ("failed to activate buffer pool"),
884 ("failed to activate buffer pool"));
885 return GST_FLOW_ERROR;
887 error_map_dst_buffer:
889 gst_video_frame_unmap (&src_frame);
892 error_map_src_buffer:
894 GST_WARNING ("failed to map buffer");
895 gst_buffer_unref (outbuf);
896 return GST_FLOW_NOT_SUPPORTED;
900 error_invalid_buffer:
902 GST_ELEMENT_ERROR (plugin, STREAM, FAILED,
903 ("failed to validate source buffer"),
904 ("failed to validate source buffer"));
905 return GST_FLOW_ERROR;
909 GST_ELEMENT_ERROR (plugin, STREAM, FAILED, ("Allocation failed"),
910 ("failed to create buffer"));
911 return GST_FLOW_ERROR;
913 error_bind_dma_buffer:
915 GST_ELEMENT_ERROR (plugin, STREAM, FAILED, ("Allocation failed"),
916 ("failed to bind dma_buf to VA surface buffer"));
917 gst_buffer_unref (outbuf);
918 return GST_FLOW_ERROR;
922 GST_WARNING ("failed to upload buffer to VA surface");
923 gst_buffer_unref (outbuf);
924 return GST_FLOW_NOT_SUPPORTED;
929 * gst_vaapi_plugin_base_set_gl_context:
930 * @plugin: a #GstVaapiPluginBase
931 * @object: the new GL context from downstream
933 * Registers the new GL context. The change is effective at the next
934 * call to gst_vaapi_plugin_base_ensure_display(), where the
935 * underlying display object could be re-allocated to fit the GL
939 gst_vaapi_plugin_base_set_gl_context (GstVaapiPluginBase * plugin,
942 #if USE_GST_GL_HELPERS
943 GstGLContext *const gl_context = GST_GL_CONTEXT (object);
944 GstVaapiDisplayType display_type;
946 gst_object_replace (&plugin->gl_context, object);
948 switch (gst_gl_context_get_gl_platform (gl_context)) {
950 case GST_GL_PLATFORM_GLX:
951 display_type = GST_VAAPI_DISPLAY_TYPE_GLX;
955 case GST_GL_PLATFORM_EGL:
956 display_type = GST_VAAPI_DISPLAY_TYPE_EGL;
960 display_type = plugin->display_type;
963 gst_vaapi_plugin_base_set_display_type (plugin, display_type);