2 * Copyright (C) 2021 Igalia, S.L.
3 * Author: Víctor Jáquez <vjaquez@igalia.com>
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.
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.
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.
25 #include "gstvabasetransform.h"
27 #include "gstvaallocator.h"
28 #include "gstvacaps.h"
29 #include "gstvapool.h"
31 #define GST_CAT_DEFAULT gst_va_base_transform_debug
32 GST_DEBUG_CATEGORY_STATIC (GST_CAT_DEFAULT);
40 static GParamSpec *properties[N_PROPERTIES];
42 struct _GstVaBaseTransformPrivate
44 GstVideoInfo srcpad_info;
46 GstBufferPool *other_pool;
48 GstCaps *sinkpad_caps;
49 GstVideoInfo sinkpad_info;
50 GstBufferPool *sinkpad_pool;
58 * A base class implementation for VA-API filters.
62 #define gst_va_base_transform_parent_class parent_class
63 G_DEFINE_TYPE_WITH_CODE (GstVaBaseTransform, gst_va_base_transform,
64 GST_TYPE_BASE_TRANSFORM, G_ADD_PRIVATE (GstVaBaseTransform)
65 GST_DEBUG_CATEGORY_INIT (gst_va_base_transform_debug,
66 "vabasetransform", 0, "vabasetransform element");
69 extern GRecMutex GST_VA_SHARED_LOCK;
72 gst_va_base_transform_get_property (GObject * object, guint prop_id,
73 GValue * value, GParamSpec * pspec)
75 GstVaBaseTransform *self = GST_VA_BASE_TRANSFORM (object);
78 case PROP_DEVICE_PATH:{
79 if (!(self->display && GST_IS_VA_DISPLAY_DRM (self->display))) {
80 g_value_set_string (value, NULL);
83 g_object_get_property (G_OBJECT (self->display), "path", value);
87 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
92 gst_va_base_transform_dispose (GObject * object)
94 GstVaBaseTransform *self = GST_VA_BASE_TRANSFORM (object);
96 if (self->priv->other_pool) {
97 gst_buffer_pool_set_active (self->priv->other_pool, FALSE);
98 gst_clear_object (&self->priv->other_pool);
101 gst_clear_caps (&self->out_caps);
102 gst_clear_caps (&self->in_caps);
104 gst_clear_caps (&self->priv->filter_caps);
106 gst_clear_object (&self->filter);
107 gst_clear_object (&self->display);
109 if (self->priv->sinkpad_pool) {
110 gst_buffer_pool_set_active (self->priv->sinkpad_pool, FALSE);
111 gst_clear_object (&self->priv->sinkpad_pool);
114 gst_clear_caps (&self->priv->sinkpad_caps);
116 G_OBJECT_CLASS (parent_class)->dispose (object);
120 gst_va_base_transform_init (GstVaBaseTransform * self)
122 gst_base_transform_set_qos_enabled (GST_BASE_TRANSFORM (self), TRUE);
124 self->priv = gst_va_base_transform_get_instance_private (self);
128 gst_va_base_transform_query (GstBaseTransform * trans,
129 GstPadDirection direction, GstQuery * query)
131 GstVaBaseTransform *self = GST_VA_BASE_TRANSFORM (trans);
132 gboolean ret = FALSE;
134 switch (GST_QUERY_TYPE (query)) {
135 case GST_QUERY_CONTEXT:
137 GstVaDisplay *display = NULL;
139 gst_object_replace ((GstObject **) & display,
140 (GstObject *) self->display);
141 ret = gst_va_handle_context_query (GST_ELEMENT_CAST (self), query,
143 gst_clear_object (&display);
147 ret = GST_BASE_TRANSFORM_CLASS (parent_class)->query (trans, direction,
156 gst_va_base_transform_set_caps (GstBaseTransform * trans, GstCaps * incaps,
159 GstVaBaseTransform *self = GST_VA_BASE_TRANSFORM (trans);
160 GstVaBaseTransformClass *fclass;
161 GstVideoInfo in_info, out_info;
165 if (!gst_video_info_from_caps (&in_info, incaps))
169 if (!gst_video_info_from_caps (&out_info, outcaps))
172 fclass = GST_VA_BASE_TRANSFORM_GET_CLASS (self);
173 if (fclass->set_info)
174 res = fclass->set_info (self, incaps, &in_info, outcaps, &out_info);
178 self->negotiated = res;
181 gst_caps_replace (&self->in_caps, incaps);
182 gst_caps_replace (&self->out_caps, outcaps);
184 self->in_info = in_info;
185 self->out_info = out_info;
188 if (self->priv->sinkpad_pool) {
189 gst_buffer_pool_set_active (self->priv->sinkpad_pool, FALSE);
190 gst_clear_object (&self->priv->sinkpad_pool);
193 if (self->priv->other_pool) {
194 gst_buffer_pool_set_active (self->priv->other_pool, FALSE);
195 gst_clear_object (&self->priv->other_pool);
203 GST_ERROR_OBJECT (self, "invalid caps");
204 self->negotiated = FALSE;
209 /* Answer upstream allocation query. */
211 gst_va_base_transform_propose_allocation (GstBaseTransform * trans,
212 GstQuery * decide_query, GstQuery * query)
214 GstVaBaseTransform *self = GST_VA_BASE_TRANSFORM (trans);
215 GstAllocator *allocator = NULL;
216 GstAllocationParams params = { 0, };
220 gboolean update_allocator = FALSE;
221 guint size, usage_hint = VA_SURFACE_ATTRIB_USAGE_HINT_GENERIC; /* it migth be
225 gst_clear_caps (&self->priv->sinkpad_caps);
227 if (!GST_BASE_TRANSFORM_CLASS (parent_class)->propose_allocation (trans,
228 decide_query, query))
231 /* passthrough, we're done */
235 if (gst_query_get_n_allocation_pools (query) > 0)
238 gst_query_parse_allocation (query, &caps, NULL);
241 if (!gst_video_info_from_caps (&info, caps)) {
242 GST_ERROR_OBJECT (self, "Cannot parse caps %" GST_PTR_FORMAT, caps);
246 size = GST_VIDEO_INFO_SIZE (&info);
248 if (gst_query_get_n_allocation_params (query) > 0) {
249 gst_query_parse_nth_allocation_param (query, 0, &allocator, ¶ms);
250 if (!GST_IS_VA_DMABUF_ALLOCATOR (allocator)
251 && !GST_IS_VA_ALLOCATOR (allocator))
252 gst_clear_object (&allocator);
253 update_allocator = TRUE;
255 gst_allocation_params_init (¶ms);
259 if (!(allocator = gst_va_base_transform_allocator_from_caps (self, caps)))
263 pool = gst_va_pool_new_with_config (caps, size, 1 + self->extra_min_buffers,
264 0, usage_hint, allocator, ¶ms);
266 gst_object_unref (allocator);
270 if (update_allocator)
271 gst_query_set_nth_allocation_param (query, 0, allocator, ¶ms);
273 gst_query_add_allocation_param (query, allocator, ¶ms);
275 gst_query_add_allocation_pool (query, pool, size, 1 + self->extra_min_buffers,
278 GST_DEBUG_OBJECT (self,
279 "proposing %" GST_PTR_FORMAT " with allocator %" GST_PTR_FORMAT,
282 gst_object_unref (allocator);
283 gst_object_unref (pool);
285 gst_query_add_allocation_meta (query, GST_VIDEO_META_API_TYPE, NULL);
287 self->priv->sinkpad_caps = gst_caps_ref (caps);
294 GST_ERROR_OBJECT (self, "failed to set config");
299 static GstBufferPool *
300 _create_other_pool (GstAllocator * allocator,
301 GstAllocationParams * params, GstCaps * caps, guint size)
303 GstBufferPool *pool = NULL;
304 GstStructure *config;
306 pool = gst_video_buffer_pool_new ();
307 config = gst_buffer_pool_get_config (pool);
309 gst_buffer_pool_config_set_params (config, caps, size, 0, 0);
310 gst_buffer_pool_config_set_allocator (config, allocator, params);
311 if (!gst_buffer_pool_set_config (pool, config)) {
312 gst_clear_object (&pool);
318 /* configure the allocation query that was answered downstream, we can
319 * configure some properties on it. Only it's called when not in
320 * passthrough mode. */
322 gst_va_base_transform_decide_allocation (GstBaseTransform * trans,
325 GstVaBaseTransform *self = GST_VA_BASE_TRANSFORM (trans);
326 GstAllocator *allocator = NULL, *other_allocator = NULL;
327 GstAllocationParams params, other_params;
328 GstBufferPool *pool = NULL, *other_pool = NULL;
329 GstCaps *outcaps = NULL;
330 GstStructure *config;
332 guint min, max, size = 0, usage_hint = VA_SURFACE_ATTRIB_USAGE_HINT_VPP_WRITE;
333 gboolean update_pool, update_allocator, has_videometa, copy_frames;
335 gst_query_parse_allocation (query, &outcaps, NULL);
337 gst_allocation_params_init (&other_params);
338 gst_allocation_params_init (¶ms);
340 if (!gst_video_info_from_caps (&vinfo, outcaps)) {
341 GST_ERROR_OBJECT (self, "Cannot parse caps %" GST_PTR_FORMAT, outcaps);
345 if (gst_query_get_n_allocation_params (query) > 0) {
346 gst_query_parse_nth_allocation_param (query, 0, &allocator, &other_params);
347 if (allocator && !(GST_IS_VA_DMABUF_ALLOCATOR (allocator)
348 || GST_IS_VA_ALLOCATOR (allocator))) {
349 /* save the allocator for the other pool */
350 other_allocator = allocator;
353 update_allocator = TRUE;
355 update_allocator = FALSE;
358 if (gst_query_get_n_allocation_pools (query) > 0) {
359 gst_query_parse_nth_allocation_pool (query, 0, &pool, &size, &min, &max);
362 if (!GST_IS_VA_POOL (pool)) {
363 GST_DEBUG_OBJECT (self,
364 "may need other pool for copy frames %" GST_PTR_FORMAT, pool);
372 size = GST_VIDEO_INFO_SIZE (&vinfo);
379 /* XXX(victor): USAGE_HINT_VPP_WRITE creates tiled dmabuf frames
381 if (gst_caps_is_dmabuf (outcaps) && GST_VIDEO_INFO_IS_RGB (&vinfo))
382 usage_hint = VA_SURFACE_ATTRIB_USAGE_HINT_GENERIC;
384 gst_va_base_transform_allocator_from_caps (self, outcaps)))
389 pool = gst_va_pool_new ();
391 config = gst_buffer_pool_get_config (pool);
392 gst_buffer_pool_config_set_allocator (config, allocator, ¶ms);
393 gst_buffer_pool_config_add_option (config, GST_BUFFER_POOL_OPTION_VIDEO_META);
394 gst_buffer_pool_config_set_params (config, outcaps, size, min, max);
395 gst_buffer_pool_config_set_va_allocation_params (config, usage_hint);
396 if (!gst_buffer_pool_set_config (pool, config)) {
397 gst_object_unref (allocator);
398 gst_object_unref (pool);
402 if (GST_IS_VA_DMABUF_ALLOCATOR (allocator)) {
403 gst_va_dmabuf_allocator_get_format (allocator, &self->priv->srcpad_info,
405 } else if (GST_IS_VA_ALLOCATOR (allocator)) {
406 gst_va_allocator_get_format (allocator, &self->priv->srcpad_info, NULL);
409 if (update_allocator)
410 gst_query_set_nth_allocation_param (query, 0, allocator, ¶ms);
412 gst_query_add_allocation_param (query, allocator, ¶ms);
415 gst_query_set_nth_allocation_pool (query, 0, pool, size, min, max);
417 gst_query_add_allocation_pool (query, pool, size, min, max);
419 has_videometa = gst_query_find_allocation_meta (query,
420 GST_VIDEO_META_API_TYPE, NULL);
422 copy_frames = (!has_videometa && gst_va_pool_requires_video_meta (pool)
423 && gst_caps_is_raw (outcaps));
426 gst_object_replace ((GstObject **) & self->priv->other_pool,
427 (GstObject *) other_pool);
429 self->priv->other_pool =
430 _create_other_pool (other_allocator, &other_params, outcaps, size);
432 GST_DEBUG_OBJECT (self, "Use the other pool for copy %" GST_PTR_FORMAT,
433 self->priv->other_pool);
435 gst_clear_object (&self->priv->other_pool);
438 GST_DEBUG_OBJECT (self,
439 "decided pool %" GST_PTR_FORMAT " with allocator %" GST_PTR_FORMAT,
442 gst_object_unref (allocator);
443 gst_object_unref (pool);
444 gst_clear_object (&other_allocator);
445 gst_clear_object (&other_pool);
447 /* removes allocation metas */
448 return GST_BASE_TRANSFORM_CLASS (parent_class)->decide_allocation (trans,
453 /* output buffers must be from our VA-based pool, they cannot be
454 * system-allocated */
456 gst_va_base_transform_transform_size (GstBaseTransform * trans,
457 GstPadDirection direction, GstCaps * caps, gsize size,
458 GstCaps * othercaps, gsize * othersize)
464 gst_va_base_transform_generate_output (GstBaseTransform * trans,
467 GstVaBaseTransform *self = GST_VA_BASE_TRANSFORM (trans);
468 GstVideoFrame src_frame;
469 GstVideoFrame dest_frame;
470 GstBuffer *buffer = NULL;
473 ret = GST_BASE_TRANSFORM_CLASS (parent_class)->generate_output (trans,
476 if (ret != GST_FLOW_OK || *outbuf == NULL)
479 if (!self->priv->other_pool)
482 /* Now need to copy the output buffer */
483 ret = GST_FLOW_ERROR;
485 if (!gst_buffer_pool_set_active (self->priv->other_pool, TRUE)) {
486 GST_WARNING_OBJECT (self, "failed to active the other pool %"
487 GST_PTR_FORMAT, self->priv->other_pool);
491 ret = gst_buffer_pool_acquire_buffer (self->priv->other_pool, &buffer, NULL);
492 if (ret != GST_FLOW_OK)
495 if (!gst_video_frame_map (&src_frame, &self->priv->srcpad_info, *outbuf,
499 if (!gst_video_frame_map (&dest_frame, &self->out_info, buffer,
501 gst_video_frame_unmap (&src_frame);
505 if (!gst_video_frame_copy (&dest_frame, &src_frame)) {
506 gst_video_frame_unmap (&src_frame);
507 gst_video_frame_unmap (&dest_frame);
511 gst_video_frame_unmap (&src_frame);
512 gst_video_frame_unmap (&dest_frame);
514 gst_buffer_replace (outbuf, buffer);
518 gst_clear_buffer (&buffer);
522 static GstStateChangeReturn
523 gst_va_base_transform_change_state (GstElement * element,
524 GstStateChange transition)
526 GstVaBaseTransform *self = GST_VA_BASE_TRANSFORM (element);
527 GstVaBaseTransformClass *klass = GST_VA_BASE_TRANSFORM_GET_CLASS (element);
528 GstStateChangeReturn ret;
530 switch (transition) {
531 case GST_STATE_CHANGE_NULL_TO_READY:
532 if (!gst_va_ensure_element_data (element, klass->render_device_path,
535 g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_DEVICE_PATH]);
536 gst_clear_caps (&self->priv->filter_caps);
537 gst_clear_object (&self->filter);
538 self->filter = gst_va_filter_new (self->display);
539 if (!gst_va_filter_open (self->filter))
541 if (klass->update_properties)
542 klass->update_properties (self);
548 ret = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition);
550 switch (transition) {
551 case GST_STATE_CHANGE_PAUSED_TO_READY:
552 gst_va_filter_close (self->filter);
554 case GST_STATE_CHANGE_READY_TO_NULL:
555 gst_clear_caps (&self->priv->filter_caps);
556 gst_clear_object (&self->filter);
557 gst_clear_object (&self->display);
558 g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_DEVICE_PATH]);
569 GST_ELEMENT_ERROR (self, LIBRARY, INIT, (NULL), ("Failed to open VPP"));
570 return GST_STATE_CHANGE_FAILURE;
575 gst_va_base_transform_set_context (GstElement * element, GstContext * context)
577 GstVaDisplay *old_display, *new_display;
578 GstVaBaseTransform *self = GST_VA_BASE_TRANSFORM (element);
579 GstVaBaseTransformClass *klass = GST_VA_BASE_TRANSFORM_GET_CLASS (self);
582 old_display = self->display ? gst_object_ref (self->display) : NULL;
583 ret = gst_va_handle_set_context (element, context, klass->render_device_path,
585 new_display = self->display ? gst_object_ref (self->display) : NULL;
588 || (old_display && new_display && old_display != new_display
590 GST_ELEMENT_WARNING (element, RESOURCE, BUSY,
591 ("Can't replace VA display while operating"), (NULL));
594 gst_clear_object (&old_display);
595 gst_clear_object (&new_display);
597 GST_ELEMENT_CLASS (parent_class)->set_context (element, context);
601 gst_va_base_transform_class_init (GstVaBaseTransformClass * klass)
603 GObjectClass *gobject_class;
604 GstElementClass *element_class;
605 GstBaseTransformClass *trans_class;
607 gobject_class = G_OBJECT_CLASS (klass);
608 element_class = GST_ELEMENT_CLASS (klass);
609 trans_class = GST_BASE_TRANSFORM_CLASS (klass);
611 gobject_class->dispose = gst_va_base_transform_dispose;
612 gobject_class->get_property = gst_va_base_transform_get_property;
614 trans_class->query = GST_DEBUG_FUNCPTR (gst_va_base_transform_query);
615 trans_class->set_caps = GST_DEBUG_FUNCPTR (gst_va_base_transform_set_caps);
616 trans_class->propose_allocation =
617 GST_DEBUG_FUNCPTR (gst_va_base_transform_propose_allocation);
618 trans_class->decide_allocation =
619 GST_DEBUG_FUNCPTR (gst_va_base_transform_decide_allocation);
620 trans_class->transform_size =
621 GST_DEBUG_FUNCPTR (gst_va_base_transform_transform_size);
622 trans_class->generate_output =
623 GST_DEBUG_FUNCPTR (gst_va_base_transform_generate_output);
625 element_class->set_context =
626 GST_DEBUG_FUNCPTR (gst_va_base_transform_set_context);
627 element_class->change_state =
628 GST_DEBUG_FUNCPTR (gst_va_base_transform_change_state);
630 properties[PROP_DEVICE_PATH] = g_param_spec_string ("device-path",
631 "Device Path", "DRM device path", NULL,
632 G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
634 g_object_class_install_properties (gobject_class, N_PROPERTIES, properties);
636 gst_type_mark_as_plugin_api (GST_TYPE_VA_BASE_TRANSFORM, 0);
640 gst_va_base_transform_allocator_from_caps (GstVaBaseTransform * self,
643 GstAllocator *allocator = NULL;
645 if (gst_caps_is_dmabuf (caps)) {
646 allocator = gst_va_dmabuf_allocator_new (self->display);
648 GArray *surface_formats = gst_va_filter_get_surface_formats (self->filter);
649 allocator = gst_va_allocator_new (self->display, surface_formats);
656 _get_plane_data_size (GstVideoInfo * info, guint plane)
658 gint comp[GST_VIDEO_MAX_COMPONENTS];
659 gint height, padded_height;
661 gst_video_format_info_component (info->finfo, plane, comp);
663 height = GST_VIDEO_INFO_HEIGHT (info);
665 GST_VIDEO_FORMAT_INFO_SCALE_HEIGHT (info->finfo, comp[0], height);
667 return GST_VIDEO_INFO_PLANE_STRIDE (info, plane) * padded_height;
671 _try_import_dmabuf_unlocked (GstVaBaseTransform * self, GstBuffer * inbuf)
673 GstVaBaseTransform *btrans = GST_VA_BASE_TRANSFORM (self);
675 GstVideoInfo in_info = btrans->in_info;
676 GstMemory *mems[GST_VIDEO_MAX_PLANES];
677 guint i, n_mem, n_planes;
678 gsize offset[GST_VIDEO_MAX_PLANES];
679 uintptr_t fd[GST_VIDEO_MAX_PLANES];
681 n_planes = GST_VIDEO_INFO_N_PLANES (&in_info);
682 n_mem = gst_buffer_n_memory (inbuf);
683 meta = gst_buffer_get_video_meta (inbuf);
685 /* This will eliminate most non-dmabuf out there */
686 if (!gst_is_dmabuf_memory (gst_buffer_peek_memory (inbuf, 0)))
689 /* We cannot have multiple dmabuf per plane */
690 if (n_mem > n_planes)
693 /* Update video info based on video meta */
695 GST_VIDEO_INFO_WIDTH (&in_info) = meta->width;
696 GST_VIDEO_INFO_HEIGHT (&in_info) = meta->height;
698 for (i = 0; i < meta->n_planes; i++) {
699 GST_VIDEO_INFO_PLANE_OFFSET (&in_info, i) = meta->offset[i];
700 GST_VIDEO_INFO_PLANE_STRIDE (&in_info, i) = meta->stride[i];
704 /* Find and validate all memories */
705 for (i = 0; i < n_planes; i++) {
711 plane_size = _get_plane_data_size (&in_info, i);
713 if (!gst_buffer_find_memory (inbuf, in_info.offset[i], plane_size,
714 &mem_idx, &length, &mem_skip))
717 /* We can't have more then one dmabuf per plane */
721 mems[i] = gst_buffer_peek_memory (inbuf, mem_idx);
723 /* And all memory found must be dmabuf */
724 if (!gst_is_dmabuf_memory (mems[i]))
727 offset[i] = mems[i]->offset + mem_skip;
728 fd[i] = gst_dmabuf_memory_get_fd (mems[i]);
731 /* Now create a VASurfaceID for the buffer */
732 return gst_va_dmabuf_memories_setup (btrans->display, &in_info, n_planes,
733 mems, fd, offset, VA_SURFACE_ATTRIB_USAGE_HINT_VPP_READ);
736 static GstBufferPool *
737 _get_sinkpad_pool (GstVaBaseTransform * self)
739 GstAllocator *allocator;
740 GstAllocationParams params = { 0, };
742 GstVideoInfo in_info;
743 guint size, usage_hint = VA_SURFACE_ATTRIB_USAGE_HINT_VPP_READ;
745 if (self->priv->sinkpad_pool)
746 return self->priv->sinkpad_pool;
748 gst_allocation_params_init (¶ms);
750 if (self->priv->sinkpad_caps) {
751 caps = self->priv->sinkpad_caps;
752 gst_video_info_from_caps (&in_info, caps);
754 caps = self->in_caps;
755 in_info = self->in_info;
758 size = GST_VIDEO_INFO_SIZE (&in_info);
760 allocator = gst_va_base_transform_allocator_from_caps (self, caps);
761 self->priv->sinkpad_pool = gst_va_pool_new_with_config (caps, size, 1, 0,
762 usage_hint, allocator, ¶ms);
763 if (!self->priv->sinkpad_pool) {
764 gst_object_unref (allocator);
768 if (GST_IS_VA_DMABUF_ALLOCATOR (allocator)) {
769 gst_va_dmabuf_allocator_get_format (allocator, &self->priv->sinkpad_info,
771 } else if (GST_IS_VA_ALLOCATOR (allocator)) {
772 gst_va_allocator_get_format (allocator, &self->priv->sinkpad_info, NULL);
775 gst_object_unref (allocator);
777 if (!gst_buffer_pool_set_active (self->priv->sinkpad_pool, TRUE)) {
778 GST_WARNING_OBJECT (self, "failed to active the sinkpad pool %"
779 GST_PTR_FORMAT, self->priv->sinkpad_pool);
783 return self->priv->sinkpad_pool;
787 _try_import_buffer (GstVaBaseTransform * self, GstBuffer * inbuf)
792 surface = gst_va_buffer_get_surface (inbuf);
793 if (surface != VA_INVALID_ID)
796 g_rec_mutex_lock (&GST_VA_SHARED_LOCK);
797 ret = _try_import_dmabuf_unlocked (self, inbuf);
798 g_rec_mutex_unlock (&GST_VA_SHARED_LOCK);
804 gst_va_base_transform_import_buffer (GstVaBaseTransform * self,
805 GstBuffer * inbuf, GstBuffer ** buf)
807 GstBuffer *buffer = NULL;
810 GstVideoFrame in_frame, out_frame;
811 gboolean imported, copied;
813 g_return_val_if_fail (GST_IS_VA_BASE_TRANSFORM (self), GST_FLOW_ERROR);
815 imported = _try_import_buffer (self, inbuf);
817 *buf = gst_buffer_ref (inbuf);
821 /* input buffer doesn't come from a vapool, thus it is required to
822 * have a pool, grab from it a new buffer and copy the input
823 * buffer to the new one */
824 if (!(pool = _get_sinkpad_pool (self)))
825 return GST_FLOW_ERROR;
827 ret = gst_buffer_pool_acquire_buffer (pool, &buffer, NULL);
828 if (ret != GST_FLOW_OK)
831 GST_LOG_OBJECT (self, "copying input frame");
833 if (!gst_video_frame_map (&in_frame, &self->in_info, inbuf, GST_MAP_READ))
836 if (!gst_video_frame_map (&out_frame, &self->priv->sinkpad_info, buffer,
838 gst_video_frame_unmap (&in_frame);
842 copied = gst_video_frame_copy (&out_frame, &in_frame);
844 gst_video_frame_unmap (&out_frame);
845 gst_video_frame_unmap (&in_frame);
850 /* copy metadata, default implemenation of baseclass will copy everything
852 GST_BASE_TRANSFORM_CLASS (parent_class)->copy_metadata
853 (GST_BASE_TRANSFORM_CAST (self), inbuf, buffer);
861 GST_ELEMENT_WARNING (self, CORE, NOT_IMPLEMENTED, (NULL),
862 ("invalid video buffer received"));
864 gst_buffer_unref (buffer);
870 gst_va_base_transform_get_filter_caps (GstVaBaseTransform * self)
872 g_return_val_if_fail (GST_IS_VA_BASE_TRANSFORM (self), NULL);
874 GST_OBJECT_LOCK (self);
875 if (self->priv->filter_caps) {
876 GST_OBJECT_UNLOCK (self);
877 return self->priv->filter_caps;
879 GST_OBJECT_UNLOCK (self);
884 GST_OBJECT_LOCK (self);
885 self->priv->filter_caps = gst_va_filter_get_caps (self->filter);
886 GST_OBJECT_UNLOCK (self);
887 return self->priv->filter_caps;