2 * gstvaapifilter.c - Video processing abstraction
4 * Copyright (C) 2013-2014 Intel Corporation
5 * Author: Gwenole Beauchesne <gwenole.beauchesne@intel.com>
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public License
9 * as published by the Free Software Foundation; either version 2.1
10 * of the License, or (at your option) any later version.
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free
19 * Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
20 * Boston, MA 02110-1301 USA
24 #include "gstvaapicompat.h"
25 #include "gstvaapifilter.h"
26 #include "gstvaapiutils.h"
27 #include "gstvaapivalue.h"
28 #include "gstvaapiminiobject.h"
29 #include "gstvaapidisplay_priv.h"
30 #include "gstvaapisurface_priv.h"
31 #include "gstvaapiutils_core.h"
33 #define GST_VAAPI_FILTER_CAST(obj) \
34 ((GstVaapiFilter *)(obj))
36 typedef struct _GstVaapiFilterOpData GstVaapiFilterOpData;
37 struct _GstVaapiFilterOpData
41 volatile gint ref_count;
52 struct _GstVaapiFilter
55 GstObject parent_instance;
57 GstVaapiDisplay *display;
60 VAContextID va_context;
61 GPtrArray *operations;
62 GstVideoFormat format;
63 GstVaapiScaleMethod scale_method;
64 GstVideoOrientationMethod video_direction;
65 GstVaapiConfigSurfaceAttributes *attribs;
66 GArray *forward_references;
67 GArray *backward_references;
68 GstVaapiRectangle crop_rect;
69 GstVaapiRectangle target_rect;
70 guint use_crop_rect:1;
71 guint use_target_rect:1;
73 guint32 rotation_flags;
76 typedef struct _GstVaapiFilterClass GstVaapiFilterClass;
77 struct _GstVaapiFilterClass
80 GstObjectClass parent_class;
83 /* Debug category for VaapiFilter */
84 GST_DEBUG_CATEGORY (gst_debug_vaapi_filter);
85 #define GST_CAT_DEFAULT gst_debug_vaapi_filter
88 GST_DEBUG_CATEGORY_INIT (gst_debug_vaapi_filter, "vaapifilter", 0, \
91 G_DEFINE_TYPE_WITH_CODE (GstVaapiFilter, gst_vaapi_filter, GST_TYPE_OBJECT,
94 /* ------------------------------------------------------------------------- */
95 /* --- VPP Types --- */
96 /* ------------------------------------------------------------------------- */
99 gst_vaapi_scale_method_get_type (void)
101 static gsize g_type = 0;
103 static const GEnumValue enum_values[] = {
104 {GST_VAAPI_SCALE_METHOD_DEFAULT,
105 "Default scaling mode", "default"},
106 {GST_VAAPI_SCALE_METHOD_FAST,
107 "Fast scaling mode", "fast"},
108 {GST_VAAPI_SCALE_METHOD_HQ,
109 "High quality scaling mode", "hq"},
113 if (g_once_init_enter (&g_type)) {
115 g_enum_register_static ("GstVaapiScaleMethod", enum_values);
116 g_once_init_leave (&g_type, type);
122 gst_vaapi_deinterlace_method_get_type (void)
124 static gsize g_type = 0;
126 static const GEnumValue enum_values[] = {
127 {GST_VAAPI_DEINTERLACE_METHOD_NONE,
128 "Disable deinterlacing", "none"},
129 {GST_VAAPI_DEINTERLACE_METHOD_BOB,
130 "Bob deinterlacing", "bob"},
131 {GST_VAAPI_DEINTERLACE_METHOD_WEAVE,
132 "Weave deinterlacing", "weave"},
133 {GST_VAAPI_DEINTERLACE_METHOD_MOTION_ADAPTIVE,
134 "Motion adaptive deinterlacing", "motion-adaptive"},
135 {GST_VAAPI_DEINTERLACE_METHOD_MOTION_COMPENSATED,
136 "Motion compensated deinterlacing", "motion-compensated"},
140 if (g_once_init_enter (&g_type)) {
142 g_enum_register_static ("GstVaapiDeinterlaceMethod", enum_values);
143 g_once_init_leave (&g_type, type);
149 gst_vaapi_deinterlace_flags_get_type (void)
151 static gsize g_type = 0;
153 static const GEnumValue enum_values[] = {
154 {GST_VAAPI_DEINTERLACE_FLAG_TFF,
155 "Top-field first", "top-field-first"},
156 {GST_VAAPI_DEINTERLACE_FLAG_ONEFIELD,
157 "One field", "one-field"},
158 {GST_VAAPI_DEINTERLACE_FLAG_TOPFIELD,
159 "Top field", "top-field"},
163 if (g_once_init_enter (&g_type)) {
165 g_enum_register_static ("GstVaapiDeinterlaceFlags", enum_values);
166 g_once_init_leave (&g_type, type);
171 /* ------------------------------------------------------------------------- */
172 /* --- VPP Helpers --- */
173 /* ------------------------------------------------------------------------- */
175 static VAProcFilterType *
176 vpp_get_filters_unlocked (GstVaapiFilter * filter, guint * num_filters_ptr)
178 VAProcFilterType *filters = NULL;
179 guint num_filters = 0;
182 num_filters = VAProcFilterCount;
183 filters = g_malloc_n (num_filters, sizeof (*filters));
187 va_status = vaQueryVideoProcFilters (filter->va_display, filter->va_context,
188 filters, &num_filters);
190 // Try to reallocate to the expected number of filters
191 if (va_status == VA_STATUS_ERROR_MAX_NUM_EXCEEDED) {
192 VAProcFilterType *const new_filters =
193 g_try_realloc_n (filters, num_filters, sizeof (*new_filters));
196 filters = new_filters;
198 va_status = vaQueryVideoProcFilters (filter->va_display,
199 filter->va_context, filters, &num_filters);
201 if (!vaapi_check_status (va_status, "vaQueryVideoProcFilters()"))
204 *num_filters_ptr = num_filters;
215 static VAProcFilterType *
216 vpp_get_filters (GstVaapiFilter * filter, guint * num_filters_ptr)
218 VAProcFilterType *filters;
220 GST_VAAPI_DISPLAY_LOCK (filter->display);
221 filters = vpp_get_filters_unlocked (filter, num_filters_ptr);
222 GST_VAAPI_DISPLAY_UNLOCK (filter->display);
227 vpp_get_filter_caps_unlocked (GstVaapiFilter * filter, VAProcFilterType type,
228 guint cap_size, guint * num_caps_ptr)
234 caps = g_malloc (cap_size);
238 va_status = vaQueryVideoProcFilterCaps (filter->va_display,
239 filter->va_context, type, caps, &num_caps);
241 // Try to reallocate to the expected number of filters
242 if (va_status == VA_STATUS_ERROR_MAX_NUM_EXCEEDED) {
243 gpointer const new_caps = g_try_realloc_n (caps, num_caps, cap_size);
248 va_status = vaQueryVideoProcFilterCaps (filter->va_display,
249 filter->va_context, type, caps, &num_caps);
251 if (!vaapi_check_status (va_status, "vaQueryVideoProcFilterCaps()"))
254 *num_caps_ptr = num_caps;
266 vpp_get_filter_caps (GstVaapiFilter * filter, VAProcFilterType type,
267 guint cap_size, guint * num_caps_ptr)
271 GST_VAAPI_DISPLAY_LOCK (filter->display);
272 caps = vpp_get_filter_caps_unlocked (filter, type, cap_size, num_caps_ptr);
273 GST_VAAPI_DISPLAY_UNLOCK (filter->display);
278 vpp_get_pipeline_caps_unlocked (GstVaapiFilter * filter)
280 #if VA_CHECK_VERSION(1,1,0)
281 VAProcPipelineCaps pipeline_caps = { 0, };
283 VAStatus va_status = vaQueryVideoProcPipelineCaps (filter->va_display,
284 filter->va_context, NULL, 0, &pipeline_caps);
286 if (vaapi_check_status (va_status, "vaQueryVideoProcPipelineCaps()")) {
287 filter->mirror_flags = pipeline_caps.mirror_flags;
288 filter->rotation_flags = pipeline_caps.rotation_flags;
293 filter->mirror_flags = 0;
294 filter->rotation_flags = 0;
298 vpp_get_pipeline_caps (GstVaapiFilter * filter)
300 GST_VAAPI_DISPLAY_LOCK (filter->display);
301 vpp_get_pipeline_caps_unlocked (filter);
302 GST_VAAPI_DISPLAY_UNLOCK (filter->display);
305 /* ------------------------------------------------------------------------- */
306 /* --- VPP Operations --- */
307 /* ------------------------------------------------------------------------- */
309 #define DEFAULT_FORMAT GST_VIDEO_FORMAT_UNKNOWN
320 PROP_FORMAT = GST_VAAPI_FILTER_OP_FORMAT,
321 PROP_CROP = GST_VAAPI_FILTER_OP_CROP,
322 PROP_DENOISE = GST_VAAPI_FILTER_OP_DENOISE,
323 PROP_SHARPEN = GST_VAAPI_FILTER_OP_SHARPEN,
324 PROP_HUE = GST_VAAPI_FILTER_OP_HUE,
325 PROP_SATURATION = GST_VAAPI_FILTER_OP_SATURATION,
326 PROP_BRIGHTNESS = GST_VAAPI_FILTER_OP_BRIGHTNESS,
327 PROP_CONTRAST = GST_VAAPI_FILTER_OP_CONTRAST,
328 PROP_DEINTERLACING = GST_VAAPI_FILTER_OP_DEINTERLACING,
329 PROP_SCALING = GST_VAAPI_FILTER_OP_SCALING,
330 PROP_VIDEO_DIRECTION = GST_VAAPI_FILTER_OP_VIDEO_DIRECTION,
331 #ifndef GST_REMOVE_DEPRECATED
332 PROP_SKINTONE = GST_VAAPI_FILTER_OP_SKINTONE,
334 PROP_SKINTONE_LEVEL = GST_VAAPI_FILTER_OP_SKINTONE_LEVEL,
339 static GParamSpec *g_properties[N_PROPERTIES] = { NULL, };
341 static gsize g_properties_initialized = FALSE;
344 init_properties (void)
347 * GstVaapiFilter:format:
349 * The forced output pixel format, expressed as a #GstVideoFormat.
351 g_properties[PROP_FORMAT] = g_param_spec_enum ("format",
353 "The forced output pixel format",
354 GST_TYPE_VIDEO_FORMAT,
355 DEFAULT_FORMAT, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
358 * GstVaapiFilter:crop-rect:
360 * The cropping rectangle, expressed as a #GstVaapiRectangle.
362 g_properties[PROP_CROP] = g_param_spec_boxed ("crop-rect",
363 "Cropping Rectangle",
364 "The cropping rectangle",
365 GST_VAAPI_TYPE_RECTANGLE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
368 * GstVaapiFilter:denoise:
370 * The level of noise reduction to apply.
372 g_properties[PROP_DENOISE] = g_param_spec_float ("denoise",
374 "The level of denoising to apply",
375 0.0, 1.0, 0.0, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
378 * GstVaapiFilter:sharpen:
380 * The level of sharpening to apply for positive values, or the
381 * level of blurring for negative values.
383 g_properties[PROP_SHARPEN] = g_param_spec_float ("sharpen",
385 "The level of sharpening/blurring to apply",
386 -1.0, 1.0, 0.0, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
389 * GstVaapiFilter:hue:
391 * The color hue, expressed as a float value. Range is -180.0 to
392 * 180.0. Default value is 0.0 and represents no modification.
394 g_properties[PROP_HUE] = g_param_spec_float ("hue",
396 "The color hue value",
397 -180.0, 180.0, 0.0, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
400 * GstVaapiFilter:saturation:
402 * The color saturation, expressed as a float value. Range is 0.0 to
403 * 2.0. Default value is 1.0 and represents no modification.
405 g_properties[PROP_SATURATION] = g_param_spec_float ("saturation",
407 "The color saturation value",
408 0.0, 2.0, 1.0, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
411 * GstVaapiFilter:brightness:
413 * The color brightness, expressed as a float value. Range is -1.0
414 * to 1.0. Default value is 0.0 and represents no modification.
416 g_properties[PROP_BRIGHTNESS] = g_param_spec_float ("brightness",
418 "The color brightness value",
419 -1.0, 1.0, 0.0, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
422 * GstVaapiFilter:contrast:
424 * The color contrast, expressed as a float value. Range is 0.0 to
425 * 2.0. Default value is 1.0 and represents no modification.
427 g_properties[PROP_CONTRAST] = g_param_spec_float ("contrast",
429 "The color contrast value",
430 0.0, 2.0, 1.0, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
433 * GstVaapiFilter:deinterlace-method:
435 * The deinterlacing algorithm to apply, expressed a an enum
436 * value. See #GstVaapiDeinterlaceMethod.
438 g_properties[PROP_DEINTERLACING] = g_param_spec_enum ("deinterlace",
439 "Deinterlacing Method",
440 "Deinterlacing method to apply",
441 GST_VAAPI_TYPE_DEINTERLACE_METHOD,
442 GST_VAAPI_DEINTERLACE_METHOD_NONE,
443 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
446 * GstVaapiFilter:scale-method:
448 * The scaling method to use, expressed as an enum value. See
449 * #GstVaapiScaleMethod.
451 g_properties[PROP_SCALING] = g_param_spec_enum ("scale-method",
453 "Scaling method to use",
454 GST_VAAPI_TYPE_SCALE_METHOD,
455 GST_VAAPI_SCALE_METHOD_DEFAULT,
456 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
459 * GstVaapiFilter:video-direction:
461 * The video-direction to use, expressed as an enum value. See
462 * #GstVideoOrientationMethod.
464 g_properties[PROP_VIDEO_DIRECTION] = g_param_spec_enum ("video-direction",
466 "Video direction: rotation and flipping",
467 GST_TYPE_VIDEO_ORIENTATION_METHOD,
468 GST_VIDEO_ORIENTATION_IDENTITY,
469 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
471 #ifndef GST_REMOVE_DEPRECATED
473 * GstVaapiFilter:skin-tone-enhancement:
475 * Apply the skin tone enhancement algorithm.
477 g_properties[PROP_SKINTONE] = g_param_spec_boolean ("skin-tone-enhancement",
478 "Skin tone enhancement",
479 "Apply the skin tone enhancement algorithm",
480 FALSE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
484 * GstVaapiFilter:skin-tone-enhancement-level:
486 * Apply the skin tone enhancement algorithm with specified value.
488 g_properties[PROP_SKINTONE_LEVEL] =
489 g_param_spec_uint ("skin-tone-enhancement-level",
490 "Skin tone enhancement level",
491 "Apply the skin tone enhancement algorithm with specified level", 0, 9, 3,
492 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
496 ensure_properties (void)
498 if (g_once_init_enter (&g_properties_initialized)) {
500 g_once_init_leave (&g_properties_initialized, TRUE);
505 op_data_free (GstVaapiFilterOpData * op_data)
507 g_free (op_data->va_caps);
508 g_slice_free (GstVaapiFilterOpData, op_data);
511 static inline gpointer
512 op_data_new (GstVaapiFilterOp op, GParamSpec * pspec)
514 GstVaapiFilterOpData *op_data;
516 op_data = g_slice_new0 (GstVaapiFilterOpData);
521 op_data->pspec = pspec;
522 op_data->ref_count = 1;
523 op_data->va_buffer = VA_INVALID_ID;
526 case GST_VAAPI_FILTER_OP_FORMAT:
527 case GST_VAAPI_FILTER_OP_CROP:
528 case GST_VAAPI_FILTER_OP_SCALING:
529 case GST_VAAPI_FILTER_OP_VIDEO_DIRECTION:
530 op_data->va_type = VAProcFilterNone;
532 case GST_VAAPI_FILTER_OP_DENOISE:
533 op_data->va_type = VAProcFilterNoiseReduction;
534 op_data->va_cap_size = sizeof (VAProcFilterCap);
535 op_data->va_buffer_size = sizeof (VAProcFilterParameterBuffer);
537 case GST_VAAPI_FILTER_OP_SHARPEN:
538 op_data->va_type = VAProcFilterSharpening;
539 op_data->va_cap_size = sizeof (VAProcFilterCap);
540 op_data->va_buffer_size = sizeof (VAProcFilterParameterBuffer);
542 #ifndef GST_REMOVE_DEPRECATED
543 case GST_VAAPI_FILTER_OP_SKINTONE:
545 case GST_VAAPI_FILTER_OP_SKINTONE_LEVEL:
546 op_data->va_type = VAProcFilterSkinToneEnhancement;
547 op_data->va_buffer_size = sizeof (VAProcFilterParameterBuffer);
549 case GST_VAAPI_FILTER_OP_HUE:
550 op_data->va_subtype = VAProcColorBalanceHue;
551 goto op_colorbalance;
552 case GST_VAAPI_FILTER_OP_SATURATION:
553 op_data->va_subtype = VAProcColorBalanceSaturation;
554 goto op_colorbalance;
555 case GST_VAAPI_FILTER_OP_BRIGHTNESS:
556 op_data->va_subtype = VAProcColorBalanceBrightness;
557 goto op_colorbalance;
558 case GST_VAAPI_FILTER_OP_CONTRAST:
559 op_data->va_subtype = VAProcColorBalanceContrast;
561 op_data->va_type = VAProcFilterColorBalance;
562 op_data->va_cap_size = sizeof (VAProcFilterCapColorBalance);
563 op_data->va_buffer_size =
564 sizeof (VAProcFilterParameterBufferColorBalance);
566 case GST_VAAPI_FILTER_OP_DEINTERLACING:
567 op_data->va_type = VAProcFilterDeinterlacing;
568 op_data->va_cap_size = sizeof (VAProcFilterCapDeinterlacing);
569 op_data->va_buffer_size =
570 sizeof (VAProcFilterParameterBufferDeinterlacing);
573 g_assert (0 && "unsupported operation");
581 op_data_free (op_data);
586 static inline gpointer
587 op_data_ref (gpointer data)
589 GstVaapiFilterOpData *const op_data = data;
591 g_return_val_if_fail (op_data != NULL, NULL);
593 g_atomic_int_inc (&op_data->ref_count);
598 op_data_unref (gpointer data)
600 GstVaapiFilterOpData *const op_data = data;
602 g_return_if_fail (op_data != NULL);
603 g_return_if_fail (op_data->ref_count > 0);
605 if (g_atomic_int_dec_and_test (&op_data->ref_count))
606 op_data_free (op_data);
609 /* Ensure capability info is set up for the VA filter we are interested in */
611 op_data_ensure_caps (GstVaapiFilterOpData * op_data, gpointer filter_caps,
612 guint num_filter_caps)
614 guchar *filter_cap = filter_caps;
615 guint i, va_num_caps = num_filter_caps;
617 // Find the VA filter cap matching the op info sub-type
618 if (op_data->va_subtype) {
619 for (i = 0; i < num_filter_caps; i++) {
620 /* XXX: sub-type shall always be the first field */
621 if (op_data->va_subtype == *(guint *) filter_cap) {
625 filter_cap += op_data->va_cap_size;
627 if (i == num_filter_caps)
631 op_data->va_caps = g_memdup (filter_cap, op_data->va_cap_size * va_num_caps);
632 if (!op_data->va_caps)
635 op_data->va_num_caps = va_num_caps;
639 /* Scale the filter value wrt. library spec and VA driver spec */
641 op_data_get_value_float (GstVaapiFilterOpData * op_data,
642 const VAProcFilterValueRange * range, gfloat value, gfloat * out_value_ptr)
644 GParamSpecFloat *const pspec = G_PARAM_SPEC_FLOAT (op_data->pspec);
647 g_return_val_if_fail (range != NULL, FALSE);
648 g_return_val_if_fail (out_value_ptr != NULL, FALSE);
650 if (value < pspec->minimum || value > pspec->maximum)
653 // Scale wrt. the medium ("default") value
654 out_value = range->default_value;
655 if (value > pspec->default_value)
656 out_value += ((value - pspec->default_value) /
657 (pspec->maximum - pspec->default_value) *
658 (range->max_value - range->default_value));
659 else if (value < pspec->default_value)
660 out_value -= ((pspec->default_value - value) /
661 (pspec->default_value - pspec->minimum) *
662 (range->default_value - range->min_value));
664 *out_value_ptr = out_value;
668 /* Get default list of operations supported by the library */
670 get_operations_default (void)
675 ops = g_ptr_array_new_full (N_PROPERTIES, op_data_unref);
679 ensure_properties ();
681 for (i = 0; i < N_PROPERTIES; i++) {
682 GstVaapiFilterOpData *op_data;
683 GParamSpec *const pspec = g_properties[i];
687 op_data = op_data_new (i, pspec);
690 g_ptr_array_add (ops, op_data);
697 g_ptr_array_unref (ops);
702 /* Get the ordered list of operations, based on VA/VPP queries */
704 get_operations_ordered (GstVaapiFilter * filter, GPtrArray * default_ops)
707 VAProcFilterType *filters;
708 gpointer filter_caps = NULL;
709 guint i, j, num_filters, num_filter_caps = 0;
711 ops = g_ptr_array_new_full (default_ops->len, op_data_unref);
715 filters = vpp_get_filters (filter, &num_filters);
719 // Append virtual ops first, i.e. those without an associated VA filter
720 for (i = 0; i < default_ops->len; i++) {
721 GstVaapiFilterOpData *const op_data = g_ptr_array_index (default_ops, i);
722 if (op_data->va_type == VAProcFilterNone)
723 g_ptr_array_add (ops, op_data_ref (op_data));
726 // Append ops, while preserving the VA filters ordering
727 for (i = 0; i < num_filters; i++) {
728 const VAProcFilterType va_type = filters[i];
729 if (va_type == VAProcFilterNone)
732 for (j = 0; j < default_ops->len; j++) {
733 GstVaapiFilterOpData *const op_data = g_ptr_array_index (default_ops, j);
734 if (op_data->va_type != va_type)
737 if (op_data->va_cap_size == 0) { /* no caps, like skintone */
738 g_ptr_array_add (ops, op_data_ref (op_data));
743 filter_caps = vpp_get_filter_caps (filter, va_type,
744 op_data->va_cap_size, &num_filter_caps);
748 if (!op_data_ensure_caps (op_data, filter_caps, num_filter_caps))
750 g_ptr_array_add (ops, op_data_ref (op_data));
756 vpp_get_pipeline_caps (filter);
758 if (filter->operations)
759 g_ptr_array_unref (filter->operations);
760 filter->operations = g_ptr_array_ref (ops);
763 g_ptr_array_unref (default_ops);
769 g_free (filter_caps);
771 g_ptr_array_unref (ops);
772 g_ptr_array_unref (default_ops);
777 /* Determine the set of supported VPP operations by the specific
778 filter, or known to this library if filter is NULL */
780 get_operations (GstVaapiFilter * filter)
784 if (filter && filter->operations)
785 return g_ptr_array_ref (filter->operations);
787 ops = get_operations_default ();
790 return filter ? get_operations_ordered (filter, ops) : ops;
793 /* Ensure the set of supported VPP operations is cached into the
794 GstVaapiFilter::operations member */
795 static inline gboolean
796 ensure_operations (GstVaapiFilter * filter)
803 if (filter->operations)
806 ops = get_operations (filter);
810 g_ptr_array_unref (ops);
814 /* Find whether the VPP operation is supported or not */
815 static GstVaapiFilterOpData *
816 find_operation (GstVaapiFilter * filter, GstVaapiFilterOp op)
820 if (!ensure_operations (filter))
823 for (i = 0; i < filter->operations->len; i++) {
824 GstVaapiFilterOpData *const op_data =
825 g_ptr_array_index (filter->operations, i);
826 if (op_data->op == op)
832 /* Ensure the operation's VA buffer is allocated */
833 static inline gboolean
834 op_ensure_n_elements_buffer (GstVaapiFilter * filter,
835 GstVaapiFilterOpData * op_data, gint op_num)
837 if (G_LIKELY (op_data->va_buffer != VA_INVALID_ID))
839 return vaapi_create_n_elements_buffer (filter->va_display, filter->va_context,
840 VAProcFilterParameterBufferType, op_data->va_buffer_size, NULL,
841 &op_data->va_buffer, NULL, op_num);
844 static inline gboolean
845 op_ensure_buffer (GstVaapiFilter * filter, GstVaapiFilterOpData * op_data)
847 return op_ensure_n_elements_buffer (filter, op_data, 1);
850 /* Update a generic filter (float value) */
852 op_set_generic_unlocked (GstVaapiFilter * filter,
853 GstVaapiFilterOpData * op_data, gfloat value)
855 VAProcFilterParameterBuffer *buf;
856 VAProcFilterCap *filter_cap;
859 if (!op_data || !op_ensure_buffer (filter, op_data))
862 op_data->is_enabled =
863 (value != G_PARAM_SPEC_FLOAT (op_data->pspec)->default_value);
864 if (!op_data->is_enabled)
867 filter_cap = op_data->va_caps;
868 if (!op_data_get_value_float (op_data, &filter_cap->range, value, &va_value))
871 buf = vaapi_map_buffer (filter->va_display, op_data->va_buffer);
875 buf->type = op_data->va_type;
876 buf->value = va_value;
877 vaapi_unmap_buffer (filter->va_display, op_data->va_buffer, NULL);
881 static inline gboolean
882 op_set_generic (GstVaapiFilter * filter, GstVaapiFilterOpData * op_data,
885 gboolean success = FALSE;
887 GST_VAAPI_DISPLAY_LOCK (filter->display);
888 success = op_set_generic_unlocked (filter, op_data, value);
889 GST_VAAPI_DISPLAY_UNLOCK (filter->display);
893 /* Update the color balance filter */
894 #define COLOR_BALANCE_NUM \
895 GST_VAAPI_FILTER_OP_CONTRAST - GST_VAAPI_FILTER_OP_HUE + 1
898 op_set_color_balance_unlocked (GstVaapiFilter * filter,
899 GstVaapiFilterOpData * op_data, gfloat value)
901 VAProcFilterParameterBufferColorBalance *buf;
902 VAProcFilterCapColorBalance *filter_cap;
905 GstVaapiFilterOpData *color_data[COLOR_BALANCE_NUM];
906 GstVaapiFilterOpData *enabled_data = NULL;
912 /* collect all the Color Balance operators and find the first
914 for (i = 0; i < COLOR_BALANCE_NUM; i++) {
915 color_data[i] = find_operation (filter, GST_VAAPI_FILTER_OP_HUE + i);
919 if (!enabled_data && color_data[i]->is_enabled)
920 enabled_data = color_data[i];
923 /* If there's no enabled operators let's enable this one.
925 * HACK: This operator will be the only one with an allocated buffer
926 * which will store all the color balance operators.
929 if (value == G_PARAM_SPEC_FLOAT (op_data->pspec)->default_value)
932 if (!op_ensure_n_elements_buffer (filter, op_data, COLOR_BALANCE_NUM))
935 enabled_data = op_data;
937 buf = vaapi_map_buffer (filter->va_display, enabled_data->va_buffer);
941 /* Write all the color balance operator values in the buffer. --
942 * Use the default value for all the operators except the set
944 for (i = 0; i < COLOR_BALANCE_NUM; i++) {
945 buf[i].type = color_data[i]->va_type;
946 buf[i].attrib = color_data[i]->va_subtype;
948 va_value = G_PARAM_SPEC_FLOAT (color_data[i]->pspec)->default_value;
949 if (color_data[i]->op == op_data->op) {
950 filter_cap = color_data[i]->va_caps;
951 /* fail but ignore current value and set default one */
952 if (!op_data_get_value_float (color_data[i], &filter_cap->range, value,
957 buf[i].value = va_value;
960 enabled_data->is_enabled = 1;
962 /* There's already one operator enabled, *in theory* with a
963 * buffer associated. */
964 if (G_UNLIKELY (enabled_data->va_buffer == VA_INVALID_ID))
967 filter_cap = op_data->va_caps;
968 if (!op_data_get_value_float (op_data, &filter_cap->range, value,
972 buf = vaapi_map_buffer (filter->va_display, enabled_data->va_buffer);
976 buf[op_data->op - GST_VAAPI_FILTER_OP_HUE].value = va_value;
979 vaapi_unmap_buffer (filter->va_display, enabled_data->va_buffer, NULL);
984 static inline gboolean
985 op_set_color_balance (GstVaapiFilter * filter, GstVaapiFilterOpData * op_data,
988 gboolean success = FALSE;
990 GST_VAAPI_DISPLAY_LOCK (filter->display);
991 success = op_set_color_balance_unlocked (filter, op_data, value);
992 GST_VAAPI_DISPLAY_UNLOCK (filter->display);
996 /* Update deinterlace filter */
998 op_set_deinterlace_unlocked (GstVaapiFilter * filter,
999 GstVaapiFilterOpData * op_data, GstVaapiDeinterlaceMethod method,
1002 VAProcFilterParameterBufferDeinterlacing *buf;
1003 const VAProcFilterCapDeinterlacing *filter_caps;
1004 VAProcDeinterlacingType algorithm;
1007 if (!op_data || !op_ensure_buffer (filter, op_data))
1010 op_data->is_enabled = (method != GST_VAAPI_DEINTERLACE_METHOD_NONE);
1011 if (!op_data->is_enabled)
1014 algorithm = from_GstVaapiDeinterlaceMethod (method);
1015 for (i = 0, filter_caps = op_data->va_caps; i < op_data->va_num_caps; i++) {
1016 if (filter_caps[i].type == algorithm)
1019 if (i == op_data->va_num_caps)
1022 buf = vaapi_map_buffer (filter->va_display, op_data->va_buffer);
1026 buf->type = op_data->va_type;
1027 buf->algorithm = algorithm;
1028 buf->flags = from_GstVaapiDeinterlaceFlags (flags);
1029 vaapi_unmap_buffer (filter->va_display, op_data->va_buffer, NULL);
1033 static inline gboolean
1034 op_set_deinterlace (GstVaapiFilter * filter, GstVaapiFilterOpData * op_data,
1035 GstVaapiDeinterlaceMethod method, guint flags)
1037 gboolean success = FALSE;
1039 GST_VAAPI_DISPLAY_LOCK (filter->display);
1040 success = op_set_deinterlace_unlocked (filter, op_data, method, flags);
1041 GST_VAAPI_DISPLAY_UNLOCK (filter->display);
1045 /* Update skin tone enhancement level */
1047 op_set_skintone_level_unlocked (GstVaapiFilter * filter,
1048 GstVaapiFilterOpData * op_data, guint value)
1050 VAProcFilterParameterBuffer *buf;
1052 if (!op_data || !op_ensure_buffer (filter, op_data))
1055 op_data->is_enabled = 1;
1057 buf = vaapi_map_buffer (filter->va_display, op_data->va_buffer);
1060 buf->type = op_data->va_type;
1062 vaapi_unmap_buffer (filter->va_display, op_data->va_buffer, NULL);
1066 static inline gboolean
1067 op_set_skintone_level (GstVaapiFilter * filter,
1068 GstVaapiFilterOpData * op_data, guint value)
1070 gboolean success = FALSE;
1072 GST_VAAPI_DISPLAY_LOCK (filter->display);
1073 success = op_set_skintone_level_unlocked (filter, op_data, value);
1074 GST_VAAPI_DISPLAY_UNLOCK (filter->display);
1078 #ifndef GST_REMOVE_DEPRECATED
1079 /* Update skin tone enhancement */
1081 op_set_skintone_unlocked (GstVaapiFilter * filter,
1082 GstVaapiFilterOpData * op_data, gboolean value)
1088 op_data->is_enabled = 0;
1092 return op_set_skintone_level_unlocked (filter, op_data, 3);
1095 static inline gboolean
1096 op_set_skintone (GstVaapiFilter * filter, GstVaapiFilterOpData * op_data,
1099 gboolean success = FALSE;
1101 GST_VAAPI_DISPLAY_LOCK (filter->display);
1102 success = op_set_skintone_unlocked (filter, op_data, enhance);
1103 GST_VAAPI_DISPLAY_UNLOCK (filter->display);
1109 deint_refs_set (GArray * refs, GstVaapiSurface ** surfaces, guint num_surfaces)
1113 if (num_surfaces > 0 && !surfaces)
1116 for (i = 0; i < num_surfaces; i++)
1117 g_array_append_val (refs, GST_VAAPI_OBJECT_ID (surfaces[i]));
1122 deint_refs_clear (GArray * refs)
1125 g_array_remove_range (refs, 0, refs->len);
1129 deint_refs_clear_all (GstVaapiFilter * filter)
1131 deint_refs_clear (filter->forward_references);
1132 deint_refs_clear (filter->backward_references);
1135 /* ------------------------------------------------------------------------- */
1136 /* --- Surface Attribs --- */
1137 /* ------------------------------------------------------------------------- */
1140 ensure_attributes (GstVaapiFilter * filter)
1142 if (G_LIKELY (filter->attribs))
1145 filter->attribs = gst_vaapi_config_surface_attributes_get (filter->display,
1147 return (filter->attribs != NULL);
1150 static inline gboolean
1151 is_special_format (GstVideoFormat format)
1153 return format == GST_VIDEO_FORMAT_UNKNOWN ||
1154 format == GST_VIDEO_FORMAT_ENCODED;
1158 find_format (GstVaapiFilter * filter, GstVideoFormat format)
1163 formats = filter->attribs->formats;
1164 if (is_special_format (format) || !formats)
1167 for (i = 0; i < formats->len; i++) {
1168 if (g_array_index (formats, GstVideoFormat, i) == format)
1174 /* ------------------------------------------------------------------------- */
1175 /* --- Interface --- */
1176 /* ------------------------------------------------------------------------- */
1179 gst_vaapi_filter_init (GstVaapiFilter * filter)
1181 filter->va_config = VA_INVALID_ID;
1182 filter->va_context = VA_INVALID_ID;
1183 filter->format = DEFAULT_FORMAT;
1185 filter->forward_references =
1186 g_array_sized_new (FALSE, FALSE, sizeof (VASurfaceID), 4);
1188 filter->backward_references =
1189 g_array_sized_new (FALSE, FALSE, sizeof (VASurfaceID), 4);
1193 gst_vaapi_filter_initialize (GstVaapiFilter * filter)
1197 if (!filter->display)
1200 va_status = vaCreateConfig (filter->va_display, VAProfileNone,
1201 VAEntrypointVideoProc, NULL, 0, &filter->va_config);
1202 if (!vaapi_check_status (va_status, "vaCreateConfig() [VPP]"))
1205 va_status = vaCreateContext (filter->va_display, filter->va_config, 0, 0, 0,
1206 NULL, 0, &filter->va_context);
1207 if (!vaapi_check_status (va_status, "vaCreateContext() [VPP]"))
1213 gst_vaapi_filter_finalize (GObject * object)
1215 GstVaapiFilter *const filter = GST_VAAPI_FILTER (object);
1218 GST_VAAPI_DISPLAY_LOCK (filter->display);
1219 if (filter->operations) {
1220 for (i = 0; i < filter->operations->len; i++) {
1221 GstVaapiFilterOpData *const op_data =
1222 g_ptr_array_index (filter->operations, i);
1223 vaapi_destroy_buffer (filter->va_display, &op_data->va_buffer);
1225 g_ptr_array_unref (filter->operations);
1226 filter->operations = NULL;
1229 if (filter->va_context != VA_INVALID_ID) {
1230 vaDestroyContext (filter->va_display, filter->va_context);
1231 filter->va_context = VA_INVALID_ID;
1234 if (filter->va_config != VA_INVALID_ID) {
1235 vaDestroyConfig (filter->va_display, filter->va_config);
1236 filter->va_config = VA_INVALID_ID;
1238 GST_VAAPI_DISPLAY_UNLOCK (filter->display);
1239 gst_vaapi_display_replace (&filter->display, NULL);
1241 if (filter->forward_references) {
1242 g_array_unref (filter->forward_references);
1243 filter->forward_references = NULL;
1246 if (filter->backward_references) {
1247 g_array_unref (filter->backward_references);
1248 filter->backward_references = NULL;
1251 if (filter->attribs) {
1252 gst_vaapi_config_surface_attributes_free (filter->attribs);
1253 filter->attribs = NULL;
1256 G_OBJECT_CLASS (gst_vaapi_filter_parent_class)->finalize (object);
1260 gst_vaapi_filter_set_property (GObject * object, guint property_id,
1261 const GValue * value, GParamSpec * pspec)
1263 GstVaapiFilter *const filter = GST_VAAPI_FILTER (object);
1265 switch (property_id) {
1267 GstVaapiDisplay *display = g_value_get_object (value);;
1270 if (GST_VAAPI_DISPLAY_HAS_VPP (display)) {
1271 filter->display = gst_object_ref (display);
1272 filter->va_display = GST_VAAPI_DISPLAY_VADISPLAY (filter->display);
1274 GST_WARNING_OBJECT (filter, "VA display doesn't support VPP");
1280 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
1285 gst_vaapi_filter_get_property (GObject * object, guint property_id,
1286 GValue * value, GParamSpec * pspec)
1288 GstVaapiFilter *const filter = GST_VAAPI_FILTER (object);
1290 switch (property_id) {
1292 g_value_set_object (value, filter->display);
1295 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
1300 gst_vaapi_filter_class_init (GstVaapiFilterClass * klass)
1302 GObjectClass *const object_class = G_OBJECT_CLASS (klass);
1304 object_class->set_property = gst_vaapi_filter_set_property;
1305 object_class->get_property = gst_vaapi_filter_get_property;
1306 object_class->finalize = gst_vaapi_filter_finalize;
1309 * GstVaapiFilter:display:
1311 * #GstVaapiDisplay to be used.
1313 g_object_class_install_property (object_class, PROP_DISPLAY,
1314 g_param_spec_object ("display", "Gst VA-API Display",
1315 "The VA-API display object to use", GST_TYPE_VAAPI_DISPLAY,
1316 G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_NAME));
1320 * gst_vaapi_filter_new:
1321 * @display: a #GstVaapiDisplay
1323 * Creates a new #GstVaapiFilter set up to operate in "identity"
1324 * mode. This means that no other operation than scaling is performed.
1326 * Return value: the newly created #GstVaapiFilter object
1329 gst_vaapi_filter_new (GstVaapiDisplay * display)
1331 GstVaapiFilter *filter;
1333 filter = g_object_new (GST_TYPE_VAAPI_FILTER, "display", display, NULL);
1334 if (!gst_vaapi_filter_initialize (filter))
1341 gst_object_unref (filter);
1347 * gst_vaapi_filter_replace:
1348 * @old_filter_ptr: a pointer to a #GstVaapiFilter
1349 * @new_filter: a #GstVaapiFilter
1351 * Atomically replaces the filter held in @old_filter_ptr with
1352 * @new_filter. This means that @old_filter_ptr shall reference a
1353 * valid filter. However, @new_filter can be NULL.
1356 gst_vaapi_filter_replace (GstVaapiFilter ** old_filter_ptr,
1357 GstVaapiFilter * new_filter)
1359 g_return_if_fail (old_filter_ptr != NULL);
1361 gst_object_replace ((GstObject **) old_filter_ptr, GST_OBJECT (new_filter));
1365 * gst_vaapi_filter_get_operations:
1366 * @filter: a #GstVaapiFilter, or %NULL
1368 * Determines the set of supported operations for video processing.
1369 * The caller owns an extra reference to the resulting array of
1370 * #GstVaapiFilterOpInfo elements, so it shall be released with
1371 * g_ptr_array_unref() after usage.
1373 * If @filter is %NULL, then this function returns the video
1374 * processing operations supported by this library.
1376 * Return value: the set of supported operations, or %NULL if an error
1380 gst_vaapi_filter_get_operations (GstVaapiFilter * filter)
1382 return get_operations (filter);
1386 * gst_vaapi_filter_has_operation:
1387 * @filter: a #GstVaapiFilter
1388 * @op: a #GstVaapiFilterOp
1390 * Determines whether the underlying VA driver advertises support for
1391 * the supplied operation @op.
1393 * Return value: %TRUE if the specified operation may be supported by
1394 * the underlying hardware, %FALSE otherwise
1397 gst_vaapi_filter_has_operation (GstVaapiFilter * filter, GstVaapiFilterOp op)
1399 g_return_val_if_fail (filter != NULL, FALSE);
1401 return find_operation (filter, op) != NULL;
1405 * gst_vaapi_filter_use_operation:
1406 * @filter: a #GstVaapiFilter
1407 * @op: a #GstVaapiFilterOp
1409 * Determines whether the supplied operation @op was already enabled
1410 * through a prior call to gst_vaapi_filter_set_operation() or any
1411 * other operation-specific function.
1413 * Note: should an operation be set to its default value, this means
1414 * that it is actually not enabled.
1416 * Return value: %TRUE if the specified operation was already enabled,
1420 gst_vaapi_filter_use_operation (GstVaapiFilter * filter, GstVaapiFilterOp op)
1422 GstVaapiFilterOpData *op_data;
1424 g_return_val_if_fail (filter != NULL, FALSE);
1426 op_data = find_operation (filter, op);
1429 return op_data->is_enabled;
1433 * gst_vaapi_filter_set_operation:
1434 * @filter: a #GstVaapiFilter
1435 * @op: a #GstVaapiFilterOp
1436 * @value: the @op settings
1438 * Enable the specified operation @op to be performed during video
1439 * processing, i.e. in gst_vaapi_filter_process(). The @value argument
1440 * specifies the operation settings. e.g. deinterlacing method for
1441 * deinterlacing, denoising level for noise reduction, etc.
1443 * If @value is %NULL, then this function resets the operation
1444 * settings to their default values.
1446 * Return value: %TRUE if the specified operation may be supported,
1450 gst_vaapi_filter_set_operation (GstVaapiFilter * filter, GstVaapiFilterOp op,
1451 const GValue * value)
1453 GstVaapiFilterOpData *op_data;
1455 g_return_val_if_fail (filter != NULL, FALSE);
1457 op_data = find_operation (filter, op);
1461 if (value && !G_VALUE_HOLDS (value, G_PARAM_SPEC_VALUE_TYPE (op_data->pspec)))
1465 case GST_VAAPI_FILTER_OP_FORMAT:
1466 return gst_vaapi_filter_set_format (filter, value ?
1467 g_value_get_enum (value) : DEFAULT_FORMAT);
1468 case GST_VAAPI_FILTER_OP_CROP:
1469 return gst_vaapi_filter_set_cropping_rectangle (filter, value ?
1470 g_value_get_boxed (value) : NULL);
1471 case GST_VAAPI_FILTER_OP_DENOISE:
1472 case GST_VAAPI_FILTER_OP_SHARPEN:
1473 return op_set_generic (filter, op_data,
1474 (value ? g_value_get_float (value) :
1475 G_PARAM_SPEC_FLOAT (op_data->pspec)->default_value));
1476 case GST_VAAPI_FILTER_OP_HUE:
1477 case GST_VAAPI_FILTER_OP_SATURATION:
1478 case GST_VAAPI_FILTER_OP_BRIGHTNESS:
1479 case GST_VAAPI_FILTER_OP_CONTRAST:
1480 return op_set_color_balance (filter, op_data,
1481 (value ? g_value_get_float (value) :
1482 G_PARAM_SPEC_FLOAT (op_data->pspec)->default_value));
1483 case GST_VAAPI_FILTER_OP_DEINTERLACING:
1484 return op_set_deinterlace (filter, op_data,
1485 (value ? g_value_get_enum (value) :
1486 G_PARAM_SPEC_ENUM (op_data->pspec)->default_value), 0);
1488 case GST_VAAPI_FILTER_OP_SCALING:
1489 return gst_vaapi_filter_set_scaling (filter,
1490 (value ? g_value_get_enum (value) :
1491 G_PARAM_SPEC_ENUM (op_data->pspec)->default_value));
1492 #ifndef GST_REMOVE_DEPRECATED
1493 case GST_VAAPI_FILTER_OP_SKINTONE:
1494 return op_set_skintone (filter, op_data,
1495 (value ? g_value_get_boolean (value) :
1496 G_PARAM_SPEC_BOOLEAN (op_data->pspec)->default_value));
1498 case GST_VAAPI_FILTER_OP_SKINTONE_LEVEL:
1499 return op_set_skintone_level (filter, op_data,
1500 (value ? g_value_get_uint (value) :
1501 G_PARAM_SPEC_UINT (op_data->pspec)->default_value));
1502 case GST_VAAPI_FILTER_OP_VIDEO_DIRECTION:
1503 return gst_vaapi_filter_set_video_direction (filter,
1504 (value ? g_value_get_enum (value) :
1505 G_PARAM_SPEC_ENUM (op_data->pspec)->default_value));
1513 * gst_vaapi_filter_process:
1514 * @filter: a #GstVaapiFilter
1515 * @src_surface: the source @GstVaapiSurface
1516 * @dst_surface: the destination @GstVaapiSurface
1517 * @flags: #GstVaapiSurfaceRenderFlags that apply to @src_surface
1519 * Applies the operations currently defined in the @filter to
1520 * @src_surface and return the output in @dst_surface. The order of
1521 * operations is determined in a way that suits best the underlying
1522 * hardware. i.e. the only guarantee held is the generated outcome,
1523 * not any specific order of operations.
1525 * Return value: a #GstVaapiFilterStatus
1527 static GstVaapiFilterStatus
1528 gst_vaapi_filter_process_unlocked (GstVaapiFilter * filter,
1529 GstVaapiSurface * src_surface, GstVaapiSurface * dst_surface, guint flags)
1531 VAProcPipelineParameterBuffer *pipeline_param = NULL;
1532 VABufferID pipeline_param_buf_id = VA_INVALID_ID;
1533 VABufferID filters[N_PROPERTIES];
1534 VAProcPipelineCaps pipeline_caps;
1535 guint i, num_filters = 0;
1537 VARectangle src_rect, dst_rect;
1538 guint va_mirror = 0, va_rotation = 0;
1540 if (!ensure_operations (filter))
1541 return GST_VAAPI_FILTER_STATUS_ERROR_ALLOCATION_FAILED;
1543 /* Build surface region (source) */
1544 if (filter->use_crop_rect) {
1545 const GstVaapiRectangle *const crop_rect = &filter->crop_rect;
1547 if ((crop_rect->x + crop_rect->width >
1548 GST_VAAPI_SURFACE_WIDTH (src_surface)) ||
1549 (crop_rect->y + crop_rect->height >
1550 GST_VAAPI_SURFACE_HEIGHT (src_surface)))
1553 src_rect.x = crop_rect->x;
1554 src_rect.y = crop_rect->y;
1555 src_rect.width = crop_rect->width;
1556 src_rect.height = crop_rect->height;
1560 src_rect.width = GST_VAAPI_SURFACE_WIDTH (src_surface);
1561 src_rect.height = GST_VAAPI_SURFACE_HEIGHT (src_surface);
1564 /* Build output region (target) */
1565 if (filter->use_target_rect) {
1566 const GstVaapiRectangle *const target_rect = &filter->target_rect;
1568 if ((target_rect->x + target_rect->width >
1569 GST_VAAPI_SURFACE_WIDTH (dst_surface)) ||
1570 (target_rect->y + target_rect->height >
1571 GST_VAAPI_SURFACE_HEIGHT (dst_surface)))
1574 dst_rect.x = target_rect->x;
1575 dst_rect.y = target_rect->y;
1576 dst_rect.width = target_rect->width;
1577 dst_rect.height = target_rect->height;
1581 dst_rect.width = GST_VAAPI_SURFACE_WIDTH (dst_surface);
1582 dst_rect.height = GST_VAAPI_SURFACE_HEIGHT (dst_surface);
1585 for (i = 0, num_filters = 0; i < filter->operations->len; i++) {
1586 GstVaapiFilterOpData *const op_data =
1587 g_ptr_array_index (filter->operations, i);
1588 if (!op_data->is_enabled)
1590 if (op_data->va_buffer == VA_INVALID_ID) {
1591 GST_ERROR ("invalid VA buffer for operation %s",
1592 g_param_spec_get_name (op_data->pspec));
1595 filters[num_filters++] = op_data->va_buffer;
1598 /* Validate pipeline caps */
1599 va_status = vaQueryVideoProcPipelineCaps (filter->va_display,
1600 filter->va_context, filters, num_filters, &pipeline_caps);
1601 if (!vaapi_check_status (va_status, "vaQueryVideoProcPipelineCaps()"))
1604 if (!vaapi_create_buffer (filter->va_display, filter->va_context,
1605 VAProcPipelineParameterBufferType, sizeof (*pipeline_param),
1606 NULL, &pipeline_param_buf_id, (gpointer *) & pipeline_param))
1609 memset (pipeline_param, 0, sizeof (*pipeline_param));
1610 pipeline_param->surface = GST_VAAPI_OBJECT_ID (src_surface);
1611 pipeline_param->surface_region = &src_rect;
1612 pipeline_param->surface_color_standard = VAProcColorStandardNone;
1613 pipeline_param->output_region = &dst_rect;
1614 pipeline_param->output_color_standard = VAProcColorStandardNone;
1615 pipeline_param->output_background_color = 0xff000000;
1616 pipeline_param->filter_flags = from_GstVaapiSurfaceRenderFlags (flags) |
1617 from_GstVaapiScaleMethod (filter->scale_method);
1618 pipeline_param->filters = filters;
1619 pipeline_param->num_filters = num_filters;
1621 from_GstVideoOrientationMethod (filter->video_direction, &va_mirror,
1624 #if VA_CHECK_VERSION(1,1,0)
1625 pipeline_param->mirror_state = va_mirror;
1626 pipeline_param->rotation_state = va_rotation;
1629 // Reference frames for advanced deinterlacing
1630 if (filter->forward_references->len > 0) {
1631 pipeline_param->forward_references = (VASurfaceID *)
1632 filter->forward_references->data;
1633 pipeline_param->num_forward_references =
1634 MIN (filter->forward_references->len,
1635 pipeline_caps.num_forward_references);
1637 pipeline_param->forward_references = NULL;
1638 pipeline_param->num_forward_references = 0;
1641 if (filter->backward_references->len > 0) {
1642 pipeline_param->backward_references = (VASurfaceID *)
1643 filter->backward_references->data;
1644 pipeline_param->num_backward_references =
1645 MIN (filter->backward_references->len,
1646 pipeline_caps.num_backward_references);
1648 pipeline_param->backward_references = NULL;
1649 pipeline_param->num_backward_references = 0;
1652 vaapi_unmap_buffer (filter->va_display, pipeline_param_buf_id, NULL);
1654 va_status = vaBeginPicture (filter->va_display, filter->va_context,
1655 GST_VAAPI_OBJECT_ID (dst_surface));
1656 if (!vaapi_check_status (va_status, "vaBeginPicture()"))
1659 va_status = vaRenderPicture (filter->va_display, filter->va_context,
1660 &pipeline_param_buf_id, 1);
1661 if (!vaapi_check_status (va_status, "vaRenderPicture()"))
1664 va_status = vaEndPicture (filter->va_display, filter->va_context);
1665 if (!vaapi_check_status (va_status, "vaEndPicture()"))
1668 deint_refs_clear_all (filter);
1669 vaapi_destroy_buffer (filter->va_display, &pipeline_param_buf_id);
1670 return GST_VAAPI_FILTER_STATUS_SUCCESS;
1675 deint_refs_clear_all (filter);
1676 vaapi_destroy_buffer (filter->va_display, &pipeline_param_buf_id);
1677 return GST_VAAPI_FILTER_STATUS_ERROR_OPERATION_FAILED;
1681 GstVaapiFilterStatus
1682 gst_vaapi_filter_process (GstVaapiFilter * filter,
1683 GstVaapiSurface * src_surface, GstVaapiSurface * dst_surface, guint flags)
1685 GstVaapiFilterStatus status;
1687 g_return_val_if_fail (filter != NULL,
1688 GST_VAAPI_FILTER_STATUS_ERROR_INVALID_PARAMETER);
1689 g_return_val_if_fail (src_surface != NULL,
1690 GST_VAAPI_FILTER_STATUS_ERROR_INVALID_PARAMETER);
1691 g_return_val_if_fail (dst_surface != NULL,
1692 GST_VAAPI_FILTER_STATUS_ERROR_INVALID_PARAMETER);
1694 GST_VAAPI_DISPLAY_LOCK (filter->display);
1695 status = gst_vaapi_filter_process_unlocked (filter,
1696 src_surface, dst_surface, flags);
1697 GST_VAAPI_DISPLAY_UNLOCK (filter->display);
1702 * gst_vaapi_filter_get_formats:
1703 * @filter: a #GstVaapiFilter
1705 * Determines the set of supported source or target formats for video
1706 * processing. The caller owns an extra reference to the resulting
1707 * array of #GstVideoFormat elements, so it shall be released with
1708 * g_array_unref() after usage.
1710 * Return value: the set of supported target formats for video processing.
1713 gst_vaapi_filter_get_formats (GstVaapiFilter * filter)
1715 g_return_val_if_fail (filter != NULL, NULL);
1717 if (!ensure_attributes (filter))
1719 if (filter->attribs->formats)
1720 return g_array_ref (filter->attribs->formats);
1725 * gst_vaapi_filter_set_format:
1726 * @filter: a #GstVaapiFilter
1727 * @format: the target surface format
1729 * Sets the desired pixel format of the resulting video processing
1732 * If @format is #GST_VIDEO_FORMAT_UNKNOWN, the filter will assume iso
1733 * format conversion, i.e. no color conversion at all and the target
1734 * surface format shall match the source surface format.
1736 * If @format is #GST_VIDEO_FORMAT_ENCODED, the filter will use the pixel
1737 * format of the target surface passed to gst_vaapi_filter_process().
1739 * Return value: %TRUE if the color conversion to the specified @format
1740 * may be supported, %FALSE otherwise.
1743 gst_vaapi_filter_set_format (GstVaapiFilter * filter, GstVideoFormat format)
1745 g_return_val_if_fail (filter != NULL, FALSE);
1747 if (!ensure_attributes (filter))
1750 if (!is_special_format (format) && !find_format (filter, format))
1753 filter->format = format;
1758 * gst_vaapi_filter_append_caps:
1759 * @filter: a #GstVaapiFilter
1760 * @structure: a #GstStructure from #GstCaps
1762 * Extracts the config's surface attributes, from @filter's context,
1763 * and transforms it into a caps formats and appended them into
1766 * Returns: %TRUE if the capabilities could be extracted and appended
1767 * into @structure; otherwise %FALSE
1770 gst_vaapi_filter_append_caps (GstVaapiFilter * filter, GstStructure * structure)
1772 GstVaapiConfigSurfaceAttributes *attribs;
1774 g_return_val_if_fail (filter != NULL, FALSE);
1775 g_return_val_if_fail (structure != NULL, FALSE);
1777 if (!ensure_attributes (filter))
1780 attribs = filter->attribs;
1782 if (attribs->min_width >= attribs->max_width ||
1783 attribs->min_height >= attribs->max_height)
1786 gst_structure_set (structure, "width", GST_TYPE_INT_RANGE, attribs->min_width,
1787 attribs->max_width, "height", GST_TYPE_INT_RANGE, attribs->min_height,
1788 attribs->max_height, NULL);
1795 * gst_vaapi_filter_set_cropping_rectangle:
1796 * @filter: a #GstVaapiFilter
1797 * @rect: the cropping region
1799 * Sets the source surface cropping rectangle to use during the video
1800 * processing. If @rect is %NULL, the whole source surface will be used.
1802 * Return value: %TRUE if the operation is supported, %FALSE otherwise.
1805 gst_vaapi_filter_set_cropping_rectangle (GstVaapiFilter * filter,
1806 const GstVaapiRectangle * rect)
1808 g_return_val_if_fail (filter != NULL, FALSE);
1810 filter->use_crop_rect = rect != NULL;
1811 if (filter->use_crop_rect)
1812 filter->crop_rect = *rect;
1817 * gst_vaapi_filter_set_target_rectangle:
1818 * @filter: a #GstVaapiFilter
1819 * @rect: the target render region
1821 * Sets the region within the target surface where the source surface
1822 * would be rendered. i.e. where the hardware accelerator would emit
1823 * the outcome of video processing. If @rect is %NULL, the whole
1824 * source surface will be used.
1826 * Return value: %TRUE if the operation is supported, %FALSE otherwise.
1829 gst_vaapi_filter_set_target_rectangle (GstVaapiFilter * filter,
1830 const GstVaapiRectangle * rect)
1832 g_return_val_if_fail (filter != NULL, FALSE);
1834 filter->use_target_rect = rect != NULL;
1835 if (filter->use_target_rect)
1836 filter->target_rect = *rect;
1841 * gst_vaapi_filter_set_denoising_level:
1842 * @filter: a #GstVaapiFilter
1843 * @level: the level of noise reduction to apply
1845 * Sets the noise reduction level to apply. If @level is 0.0f, this
1846 * corresponds to disabling the noise reduction algorithm.
1848 * Return value: %TRUE if the operation is supported, %FALSE otherwise.
1851 gst_vaapi_filter_set_denoising_level (GstVaapiFilter * filter, gfloat level)
1853 g_return_val_if_fail (filter != NULL, FALSE);
1855 return op_set_generic (filter,
1856 find_operation (filter, GST_VAAPI_FILTER_OP_DENOISE), level);
1860 * gst_vaapi_filter_set_sharpening_level:
1861 * @filter: a #GstVaapiFilter
1862 * @level: the sharpening factor
1864 * Enables noise reduction with the specified factor.
1866 * Return value: %TRUE if the operation is supported, %FALSE otherwise.
1869 gst_vaapi_filter_set_sharpening_level (GstVaapiFilter * filter, gfloat level)
1871 g_return_val_if_fail (filter != NULL, FALSE);
1873 return op_set_generic (filter,
1874 find_operation (filter, GST_VAAPI_FILTER_OP_SHARPEN), level);
1878 * gst_vaapi_filter_set_hue:
1879 * @filter: a #GstVaapiFilter
1880 * @value: the color hue value
1882 * Enables color hue adjustment to the specified value.
1884 * Return value: %TRUE if the operation is supported, %FALSE otherwise.
1887 gst_vaapi_filter_set_hue (GstVaapiFilter * filter, gfloat value)
1889 g_return_val_if_fail (filter != NULL, FALSE);
1891 return op_set_color_balance (filter,
1892 find_operation (filter, GST_VAAPI_FILTER_OP_HUE), value);
1896 * gst_vaapi_filter_set_saturation:
1897 * @filter: a #GstVaapiFilter
1898 * @value: the color saturation value
1900 * Enables color saturation adjustment to the specified value.
1902 * Return value: %TRUE if the operation is supported, %FALSE otherwise.
1905 gst_vaapi_filter_set_saturation (GstVaapiFilter * filter, gfloat value)
1907 g_return_val_if_fail (filter != NULL, FALSE);
1909 return op_set_color_balance (filter,
1910 find_operation (filter, GST_VAAPI_FILTER_OP_SATURATION), value);
1914 * gst_vaapi_filter_set_brightness:
1915 * @filter: a #GstVaapiFilter
1916 * @value: the color brightness value
1918 * Enables color brightness adjustment to the specified value.
1920 * Return value: %TRUE if the operation is supported, %FALSE otherwise.
1923 gst_vaapi_filter_set_brightness (GstVaapiFilter * filter, gfloat value)
1925 g_return_val_if_fail (filter != NULL, FALSE);
1927 return op_set_color_balance (filter,
1928 find_operation (filter, GST_VAAPI_FILTER_OP_BRIGHTNESS), value);
1932 * gst_vaapi_filter_set_contrast:
1933 * @filter: a #GstVaapiFilter
1934 * @value: the color contrast value
1936 * Enables color contrast adjustment to the specified value.
1938 * Return value: %TRUE if the operation is supported, %FALSE otherwise.
1941 gst_vaapi_filter_set_contrast (GstVaapiFilter * filter, gfloat value)
1943 g_return_val_if_fail (filter != NULL, FALSE);
1945 return op_set_color_balance (filter,
1946 find_operation (filter, GST_VAAPI_FILTER_OP_CONTRAST), value);
1950 * gst_vaapi_filter_set_deinterlacing:
1951 * @filter: a #GstVaapiFilter
1952 * @method: the deinterlacing algorithm (see #GstVaapiDeinterlaceMethod)
1953 * @flags: the additional flags
1955 * Applies deinterlacing to the video processing pipeline. If @method
1956 * is not @GST_VAAPI_DEINTERLACE_METHOD_NONE, then @flags could
1957 * represent the initial picture structure of the source frame.
1959 * Return value: %TRUE if the operation is supported, %FALSE otherwise.
1962 gst_vaapi_filter_set_deinterlacing (GstVaapiFilter * filter,
1963 GstVaapiDeinterlaceMethod method, guint flags)
1965 g_return_val_if_fail (filter != NULL, FALSE);
1967 return op_set_deinterlace (filter,
1968 find_operation (filter, GST_VAAPI_FILTER_OP_DEINTERLACING), method,
1973 * gst_vaapi_filter_set_deinterlacing_references:
1974 * @filter: a #GstVaapiFilter
1975 * @forward_references: the set of #GstVaapiSurface objects used as
1976 * forward references
1977 * @num_forward_references: the number of elements in the
1978 * @forward_references array
1979 * @backward_references: the set of #GstVaapiSurface objects used as
1980 * backward references
1981 * @num_backward_references: the number of elements in the
1982 * @backward_references array
1984 * Specifies the list of surfaces used for forward or backward reference in
1985 * advanced deinterlacing mode. The caller is responsible for maintaining
1986 * the associated surfaces live until gst_vaapi_filter_process() completes.
1987 * e.g. by holding an extra reference to the associated #GstVaapiSurfaceProxy.
1989 * Temporal ordering is maintained as follows: the shorter index in
1990 * either array is, the closest the matching surface is relatively to
1991 * the current source surface to process. e.g. surface in
1992 * @forward_references array index 0 represents the immediately
1993 * preceding surface in display order, surface at index 1 is the one
1994 * preceding surface at index 0, etc.
1996 * The video processing filter will only use the recommended number of
1997 * surfaces for backward and forward references.
1999 * Note: the supplied lists of reference surfaces are not sticky. This
2000 * means that they are only valid for the next gst_vaapi_filter_process()
2001 * call, and thus needs to be submitted again for subsequent calls.
2003 * Return value: %TRUE if the operation is supported, %FALSE otherwise.
2006 gst_vaapi_filter_set_deinterlacing_references (GstVaapiFilter * filter,
2007 GstVaapiSurface ** forward_references, guint num_forward_references,
2008 GstVaapiSurface ** backward_references, guint num_backward_references)
2010 g_return_val_if_fail (filter != NULL, FALSE);
2012 deint_refs_clear_all (filter);
2014 if (!deint_refs_set (filter->forward_references, forward_references,
2015 num_forward_references))
2018 if (!deint_refs_set (filter->backward_references, backward_references,
2019 num_backward_references))
2025 * gst_vaapi_filter_set_scaling:
2026 * @filter: a #GstVaapiFilter
2027 * @method: the scaling algorithm (see #GstVaapiScaleMethod)
2029 * Applies scaling algorithm to the video processing pipeline.
2031 * Return value: %TRUE if the operation is supported, %FALSE otherwise.
2034 gst_vaapi_filter_set_scaling (GstVaapiFilter * filter,
2035 GstVaapiScaleMethod method)
2037 g_return_val_if_fail (filter != NULL, FALSE);
2039 filter->scale_method = method;
2043 #ifndef GST_REMOVE_DEPRECATED
2045 * gst_vaapi_filter_set_skintone:
2046 * @filter: a #GstVaapiFilter
2047 * @enhance: %TRUE if enable the skin tone enhancement algorithm
2049 * Applies the skin tone enhancement algorithm.
2051 * Return value: %TRUE if the operation is supported, %FALSE
2055 gst_vaapi_filter_set_skintone (GstVaapiFilter * filter, gboolean enhance)
2057 g_return_val_if_fail (filter != NULL, FALSE);
2059 return op_set_skintone (filter,
2060 find_operation (filter, GST_VAAPI_FILTER_OP_SKINTONE), enhance);
2065 * gst_vaapi_filter_set_skintone_level:
2066 * @filter: a #GstVaapiFilter
2067 * @value: the value if enable the skin tone enhancement algorithm
2069 * Applies the skin tone enhancement algorithm with specifled value.
2071 * Return value: %TRUE if the operation is supported, %FALSE
2075 gst_vaapi_filter_set_skintone_level (GstVaapiFilter * filter, guint value)
2077 g_return_val_if_fail (filter != NULL, FALSE);
2079 return op_set_skintone_level (filter,
2080 find_operation (filter, GST_VAAPI_FILTER_OP_SKINTONE_LEVEL), value);
2084 * gst_vaapi_filter_set_video_direction:
2085 * @filter: a #GstVaapiFilter
2086 * @method: the video direction (see #GstVideoOrientationMethod)
2088 * Applies mirror/rotation to the video processing pipeline.
2090 * Return value: %TRUE if the operation is supported, %FALSE otherwise.
2093 gst_vaapi_filter_set_video_direction (GstVaapiFilter * filter,
2094 GstVideoOrientationMethod method)
2096 g_return_val_if_fail (filter != NULL, FALSE);
2098 #if VA_CHECK_VERSION(1,1,0)
2100 guint32 va_mirror = VA_MIRROR_NONE;
2101 guint32 va_rotation = VA_ROTATION_NONE;
2103 from_GstVideoOrientationMethod (method, &va_mirror, &va_rotation);
2105 if (va_mirror != VA_MIRROR_NONE && !(filter->mirror_flags & va_mirror))
2108 if (va_rotation != VA_ROTATION_NONE
2109 && !(filter->rotation_flags & (1 << va_rotation)))
2116 filter->video_direction = method;
2121 * gst_vaapi_filter_get_video_direction:
2122 * @filter: a #GstVaapiFilter
2124 * Return value: the currently applied video direction (see #GstVideoOrientationMethod)
2126 GstVideoOrientationMethod
2127 gst_vaapi_filter_get_video_direction (GstVaapiFilter * filter)
2129 g_return_val_if_fail (filter != NULL, GST_VIDEO_ORIENTATION_IDENTITY);
2130 return filter->video_direction;
2133 static inline gfloat
2134 op_get_float_default_value (GstVaapiFilter * filter,
2135 GstVaapiFilterOpData * op_data)
2137 GParamSpecFloat *const pspec = G_PARAM_SPEC_FLOAT (op_data->pspec);
2138 return pspec->default_value;
2142 op_get_enum_default_value (GstVaapiFilter * filter,
2143 GstVaapiFilterOpData * op_data)
2145 GParamSpecEnum *const pspec = G_PARAM_SPEC_ENUM (op_data->pspec);
2146 return pspec->default_value;
2150 op_get_uint_default_value (GstVaapiFilter * filter,
2151 GstVaapiFilterOpData * op_data)
2153 GParamSpecUInt *const pspec = G_PARAM_SPEC_UINT (op_data->pspec);
2154 return pspec->default_value;
2157 static inline gboolean
2158 op_get_bool_default_value (GstVaapiFilter * filter,
2159 GstVaapiFilterOpData * op_data)
2161 GParamSpecBoolean *const pspec = G_PARAM_SPEC_BOOLEAN (op_data->pspec);
2162 return pspec->default_value;
2166 gst_vaapi_filter_get_denoising_level_default (GstVaapiFilter * filter)
2168 g_return_val_if_fail (filter != NULL, FALSE);
2170 return op_get_float_default_value (filter,
2171 find_operation (filter, GST_VAAPI_FILTER_OP_DENOISE));
2175 gst_vaapi_filter_get_sharpening_level_default (GstVaapiFilter * filter)
2177 g_return_val_if_fail (filter != NULL, FALSE);
2179 return op_get_float_default_value (filter,
2180 find_operation (filter, GST_VAAPI_FILTER_OP_SHARPEN));
2184 gst_vaapi_filter_get_hue_default (GstVaapiFilter * filter)
2186 g_return_val_if_fail (filter != NULL, FALSE);
2188 return op_get_float_default_value (filter,
2189 find_operation (filter, GST_VAAPI_FILTER_OP_HUE));
2193 gst_vaapi_filter_get_saturation_default (GstVaapiFilter * filter)
2195 g_return_val_if_fail (filter != NULL, FALSE);
2197 return op_get_float_default_value (filter,
2198 find_operation (filter, GST_VAAPI_FILTER_OP_SATURATION));
2202 gst_vaapi_filter_get_brightness_default (GstVaapiFilter * filter)
2204 g_return_val_if_fail (filter != NULL, FALSE);
2206 return op_get_float_default_value (filter,
2207 find_operation (filter, GST_VAAPI_FILTER_OP_BRIGHTNESS));
2211 gst_vaapi_filter_get_contrast_default (GstVaapiFilter * filter)
2213 g_return_val_if_fail (filter != NULL, FALSE);
2215 return op_get_float_default_value (filter,
2216 find_operation (filter, GST_VAAPI_FILTER_OP_CONTRAST));
2220 gst_vaapi_filter_get_scaling_default (GstVaapiFilter * filter)
2222 g_return_val_if_fail (filter != NULL, FALSE);
2224 return op_get_enum_default_value (filter,
2225 find_operation (filter, GST_VAAPI_FILTER_OP_SCALING));
2228 #ifndef GST_REMOVE_DEPRECATED
2230 gst_vaapi_filter_get_skintone_default (GstVaapiFilter * filter)
2232 g_return_val_if_fail (filter != NULL, FALSE);
2234 return op_get_bool_default_value (filter,
2235 find_operation (filter, GST_VAAPI_FILTER_OP_SKINTONE));
2240 gst_vaapi_filter_get_skintone_level_default (GstVaapiFilter * filter)
2242 g_return_val_if_fail (filter != NULL, FALSE);
2244 return op_get_uint_default_value (filter,
2245 find_operation (filter, GST_VAAPI_FILTER_OP_SKINTONE_LEVEL));
2248 GstVideoOrientationMethod
2249 gst_vaapi_filter_get_video_direction_default (GstVaapiFilter * filter)
2251 g_return_val_if_fail (filter != NULL, FALSE);
2253 return op_get_enum_default_value (filter,
2254 find_operation (filter, GST_VAAPI_FILTER_OP_VIDEO_DIRECTION));