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
310 #define DEFAULT_SCALING GST_VAAPI_SCALE_METHOD_DEFAULT
311 #define DEFAULT_VIDEO_DIRECTION GST_VIDEO_ORIENTATION_IDENTITY
322 PROP_FORMAT = GST_VAAPI_FILTER_OP_FORMAT,
323 PROP_CROP = GST_VAAPI_FILTER_OP_CROP,
324 PROP_DENOISE = GST_VAAPI_FILTER_OP_DENOISE,
325 PROP_SHARPEN = GST_VAAPI_FILTER_OP_SHARPEN,
326 PROP_HUE = GST_VAAPI_FILTER_OP_HUE,
327 PROP_SATURATION = GST_VAAPI_FILTER_OP_SATURATION,
328 PROP_BRIGHTNESS = GST_VAAPI_FILTER_OP_BRIGHTNESS,
329 PROP_CONTRAST = GST_VAAPI_FILTER_OP_CONTRAST,
330 PROP_DEINTERLACING = GST_VAAPI_FILTER_OP_DEINTERLACING,
331 PROP_SCALING = GST_VAAPI_FILTER_OP_SCALING,
332 PROP_VIDEO_DIRECTION = GST_VAAPI_FILTER_OP_VIDEO_DIRECTION,
333 PROP_SKINTONE = GST_VAAPI_FILTER_OP_SKINTONE,
338 static GParamSpec *g_properties[N_PROPERTIES] = { NULL, };
340 static gsize g_properties_initialized = FALSE;
343 init_properties (void)
346 * GstVaapiFilter:format:
348 * The forced output pixel format, expressed as a #GstVideoFormat.
350 g_properties[PROP_FORMAT] = g_param_spec_enum ("format",
352 "The forced output pixel format",
353 GST_TYPE_VIDEO_FORMAT,
354 DEFAULT_FORMAT, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
357 * GstVaapiFilter:crop-rect:
359 * The cropping rectangle, expressed as a #GstVaapiRectangle.
361 g_properties[PROP_CROP] = g_param_spec_boxed ("crop-rect",
362 "Cropping Rectangle",
363 "The cropping rectangle",
364 GST_VAAPI_TYPE_RECTANGLE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
367 * GstVaapiFilter:denoise:
369 * The level of noise reduction to apply.
371 g_properties[PROP_DENOISE] = g_param_spec_float ("denoise",
373 "The level of denoising to apply",
374 0.0, 1.0, 0.0, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
377 * GstVaapiFilter:sharpen:
379 * The level of sharpening to apply for positive values, or the
380 * level of blurring for negative values.
382 g_properties[PROP_SHARPEN] = g_param_spec_float ("sharpen",
384 "The level of sharpening/blurring to apply",
385 -1.0, 1.0, 0.0, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
388 * GstVaapiFilter:hue:
390 * The color hue, expressed as a float value. Range is -180.0 to
391 * 180.0. Default value is 0.0 and represents no modification.
393 g_properties[PROP_HUE] = g_param_spec_float ("hue",
395 "The color hue value",
396 -180.0, 180.0, 0.0, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
399 * GstVaapiFilter:saturation:
401 * The color saturation, expressed as a float value. Range is 0.0 to
402 * 2.0. Default value is 1.0 and represents no modification.
404 g_properties[PROP_SATURATION] = g_param_spec_float ("saturation",
406 "The color saturation value",
407 0.0, 2.0, 1.0, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
410 * GstVaapiFilter:brightness:
412 * The color brightness, expressed as a float value. Range is -1.0
413 * to 1.0. Default value is 0.0 and represents no modification.
415 g_properties[PROP_BRIGHTNESS] = g_param_spec_float ("brightness",
417 "The color brightness value",
418 -1.0, 1.0, 0.0, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
421 * GstVaapiFilter:contrast:
423 * The color contrast, expressed as a float value. Range is 0.0 to
424 * 2.0. Default value is 1.0 and represents no modification.
426 g_properties[PROP_CONTRAST] = g_param_spec_float ("contrast",
428 "The color contrast value",
429 0.0, 2.0, 1.0, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
432 * GstVaapiFilter:deinterlace-method:
434 * The deinterlacing algorithm to apply, expressed a an enum
435 * value. See #GstVaapiDeinterlaceMethod.
437 g_properties[PROP_DEINTERLACING] = g_param_spec_enum ("deinterlace",
438 "Deinterlacing Method",
439 "Deinterlacing method to apply",
440 GST_VAAPI_TYPE_DEINTERLACE_METHOD,
441 GST_VAAPI_DEINTERLACE_METHOD_NONE,
442 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
445 * GstVaapiFilter:scale-method:
447 * The scaling method to use, expressed as an enum value. See
448 * #GstVaapiScaleMethod.
450 g_properties[PROP_SCALING] = g_param_spec_enum ("scale-method",
452 "Scaling method to use",
453 GST_VAAPI_TYPE_SCALE_METHOD,
454 DEFAULT_SCALING, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
457 * GstVaapiFilter:video-direction:
459 * The video-direction to use, expressed as an enum value. See
460 * #GstVideoOrientationMethod.
462 g_properties[PROP_VIDEO_DIRECTION] = g_param_spec_enum ("video-direction",
464 "Video direction: rotation and flipping",
465 GST_TYPE_VIDEO_ORIENTATION_METHOD,
466 DEFAULT_VIDEO_DIRECTION, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
469 * GstVaapiFilter:skin-tone-enhancement:
471 * Apply the skin tone enhancement algorithm.
473 g_properties[PROP_SKINTONE] = g_param_spec_boolean ("skin-tone-enhancement",
474 "Skin tone enhancement",
475 "Apply the skin tone enhancement algorithm",
476 FALSE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
480 ensure_properties (void)
482 if (g_once_init_enter (&g_properties_initialized)) {
484 g_once_init_leave (&g_properties_initialized, TRUE);
489 op_data_free (GstVaapiFilterOpData * op_data)
491 g_free (op_data->va_caps);
492 g_slice_free (GstVaapiFilterOpData, op_data);
495 static inline gpointer
496 op_data_new (GstVaapiFilterOp op, GParamSpec * pspec)
498 GstVaapiFilterOpData *op_data;
500 op_data = g_slice_new0 (GstVaapiFilterOpData);
505 op_data->pspec = pspec;
506 op_data->ref_count = 1;
507 op_data->va_buffer = VA_INVALID_ID;
510 case GST_VAAPI_FILTER_OP_FORMAT:
511 case GST_VAAPI_FILTER_OP_CROP:
512 case GST_VAAPI_FILTER_OP_SCALING:
513 case GST_VAAPI_FILTER_OP_VIDEO_DIRECTION:
514 op_data->va_type = VAProcFilterNone;
516 case GST_VAAPI_FILTER_OP_DENOISE:
517 op_data->va_type = VAProcFilterNoiseReduction;
518 op_data->va_cap_size = sizeof (VAProcFilterCap);
519 op_data->va_buffer_size = sizeof (VAProcFilterParameterBuffer);
521 case GST_VAAPI_FILTER_OP_SHARPEN:
522 op_data->va_type = VAProcFilterSharpening;
523 op_data->va_cap_size = sizeof (VAProcFilterCap);
524 op_data->va_buffer_size = sizeof (VAProcFilterParameterBuffer);
526 case GST_VAAPI_FILTER_OP_SKINTONE:
527 op_data->va_type = VAProcFilterSkinToneEnhancement;
528 op_data->va_buffer_size = sizeof (VAProcFilterParameterBuffer);
530 case GST_VAAPI_FILTER_OP_HUE:
531 op_data->va_subtype = VAProcColorBalanceHue;
532 goto op_colorbalance;
533 case GST_VAAPI_FILTER_OP_SATURATION:
534 op_data->va_subtype = VAProcColorBalanceSaturation;
535 goto op_colorbalance;
536 case GST_VAAPI_FILTER_OP_BRIGHTNESS:
537 op_data->va_subtype = VAProcColorBalanceBrightness;
538 goto op_colorbalance;
539 case GST_VAAPI_FILTER_OP_CONTRAST:
540 op_data->va_subtype = VAProcColorBalanceContrast;
542 op_data->va_type = VAProcFilterColorBalance;
543 op_data->va_cap_size = sizeof (VAProcFilterCapColorBalance);
544 op_data->va_buffer_size =
545 sizeof (VAProcFilterParameterBufferColorBalance);
547 case GST_VAAPI_FILTER_OP_DEINTERLACING:
548 op_data->va_type = VAProcFilterDeinterlacing;
549 op_data->va_cap_size = sizeof (VAProcFilterCapDeinterlacing);
550 op_data->va_buffer_size =
551 sizeof (VAProcFilterParameterBufferDeinterlacing);
554 g_assert (0 && "unsupported operation");
562 op_data_free (op_data);
567 static inline gpointer
568 op_data_ref (gpointer data)
570 GstVaapiFilterOpData *const op_data = data;
572 g_return_val_if_fail (op_data != NULL, NULL);
574 g_atomic_int_inc (&op_data->ref_count);
579 op_data_unref (gpointer data)
581 GstVaapiFilterOpData *const op_data = data;
583 g_return_if_fail (op_data != NULL);
584 g_return_if_fail (op_data->ref_count > 0);
586 if (g_atomic_int_dec_and_test (&op_data->ref_count))
587 op_data_free (op_data);
590 /* Ensure capability info is set up for the VA filter we are interested in */
592 op_data_ensure_caps (GstVaapiFilterOpData * op_data, gpointer filter_caps,
593 guint num_filter_caps)
595 guchar *filter_cap = filter_caps;
596 guint i, va_num_caps = num_filter_caps;
598 // Find the VA filter cap matching the op info sub-type
599 if (op_data->va_subtype) {
600 for (i = 0; i < num_filter_caps; i++) {
601 /* XXX: sub-type shall always be the first field */
602 if (op_data->va_subtype == *(guint *) filter_cap) {
606 filter_cap += op_data->va_cap_size;
608 if (i == num_filter_caps)
612 op_data->va_caps = g_memdup (filter_cap, op_data->va_cap_size * va_num_caps);
613 if (!op_data->va_caps)
616 op_data->va_num_caps = va_num_caps;
620 /* Scale the filter value wrt. library spec and VA driver spec */
622 op_data_get_value_float (GstVaapiFilterOpData * op_data,
623 const VAProcFilterValueRange * range, gfloat value, gfloat * out_value_ptr)
625 GParamSpecFloat *const pspec = G_PARAM_SPEC_FLOAT (op_data->pspec);
628 g_return_val_if_fail (range != NULL, FALSE);
629 g_return_val_if_fail (out_value_ptr != NULL, FALSE);
631 if (value < pspec->minimum || value > pspec->maximum)
634 // Scale wrt. the medium ("default") value
635 out_value = range->default_value;
636 if (value > pspec->default_value)
637 out_value += ((value - pspec->default_value) /
638 (pspec->maximum - pspec->default_value) *
639 (range->max_value - range->default_value));
640 else if (value < pspec->default_value)
641 out_value -= ((pspec->default_value - value) /
642 (pspec->default_value - pspec->minimum) *
643 (range->default_value - range->min_value));
645 *out_value_ptr = out_value;
649 /* Get default list of operations supported by the library */
651 get_operations_default (void)
656 ops = g_ptr_array_new_full (N_PROPERTIES, op_data_unref);
660 ensure_properties ();
662 for (i = 0; i < N_PROPERTIES; i++) {
663 GstVaapiFilterOpData *op_data;
664 GParamSpec *const pspec = g_properties[i];
668 op_data = op_data_new (i, pspec);
671 g_ptr_array_add (ops, op_data);
678 g_ptr_array_unref (ops);
683 /* Get the ordered list of operations, based on VA/VPP queries */
685 get_operations_ordered (GstVaapiFilter * filter, GPtrArray * default_ops)
688 VAProcFilterType *filters;
689 gpointer filter_caps = NULL;
690 guint i, j, num_filters, num_filter_caps = 0;
692 ops = g_ptr_array_new_full (default_ops->len, op_data_unref);
696 filters = vpp_get_filters (filter, &num_filters);
700 // Append virtual ops first, i.e. those without an associated VA filter
701 for (i = 0; i < default_ops->len; i++) {
702 GstVaapiFilterOpData *const op_data = g_ptr_array_index (default_ops, i);
703 if (op_data->va_type == VAProcFilterNone)
704 g_ptr_array_add (ops, op_data_ref (op_data));
707 // Append ops, while preserving the VA filters ordering
708 for (i = 0; i < num_filters; i++) {
709 const VAProcFilterType va_type = filters[i];
710 if (va_type == VAProcFilterNone)
713 for (j = 0; j < default_ops->len; j++) {
714 GstVaapiFilterOpData *const op_data = g_ptr_array_index (default_ops, j);
715 if (op_data->va_type != va_type)
718 if (op_data->va_cap_size == 0) { /* no caps, like skintone */
719 g_ptr_array_add (ops, op_data_ref (op_data));
724 filter_caps = vpp_get_filter_caps (filter, va_type,
725 op_data->va_cap_size, &num_filter_caps);
729 if (!op_data_ensure_caps (op_data, filter_caps, num_filter_caps))
731 g_ptr_array_add (ops, op_data_ref (op_data));
737 vpp_get_pipeline_caps (filter);
739 if (filter->operations)
740 g_ptr_array_unref (filter->operations);
741 filter->operations = g_ptr_array_ref (ops);
744 g_ptr_array_unref (default_ops);
750 g_free (filter_caps);
752 g_ptr_array_unref (ops);
753 g_ptr_array_unref (default_ops);
758 /* Determine the set of supported VPP operations by the specific
759 filter, or known to this library if filter is NULL */
761 get_operations (GstVaapiFilter * filter)
765 if (filter && filter->operations)
766 return g_ptr_array_ref (filter->operations);
768 ops = get_operations_default ();
771 return filter ? get_operations_ordered (filter, ops) : ops;
774 /* Ensure the set of supported VPP operations is cached into the
775 GstVaapiFilter::operations member */
776 static inline gboolean
777 ensure_operations (GstVaapiFilter * filter)
784 if (filter->operations)
787 ops = get_operations (filter);
791 g_ptr_array_unref (ops);
795 /* Find whether the VPP operation is supported or not */
796 static GstVaapiFilterOpData *
797 find_operation (GstVaapiFilter * filter, GstVaapiFilterOp op)
801 if (!ensure_operations (filter))
804 for (i = 0; i < filter->operations->len; i++) {
805 GstVaapiFilterOpData *const op_data =
806 g_ptr_array_index (filter->operations, i);
807 if (op_data->op == op)
813 /* Ensure the operation's VA buffer is allocated */
814 static inline gboolean
815 op_ensure_n_elements_buffer (GstVaapiFilter * filter,
816 GstVaapiFilterOpData * op_data, gint op_num)
818 if (G_LIKELY (op_data->va_buffer != VA_INVALID_ID))
820 return vaapi_create_n_elements_buffer (filter->va_display, filter->va_context,
821 VAProcFilterParameterBufferType, op_data->va_buffer_size, NULL,
822 &op_data->va_buffer, NULL, op_num);
825 static inline gboolean
826 op_ensure_buffer (GstVaapiFilter * filter, GstVaapiFilterOpData * op_data)
828 return op_ensure_n_elements_buffer (filter, op_data, 1);
831 /* Update a generic filter (float value) */
833 op_set_generic_unlocked (GstVaapiFilter * filter,
834 GstVaapiFilterOpData * op_data, gfloat value)
836 VAProcFilterParameterBuffer *buf;
837 VAProcFilterCap *filter_cap;
840 if (!op_data || !op_ensure_buffer (filter, op_data))
843 op_data->is_enabled =
844 (value != G_PARAM_SPEC_FLOAT (op_data->pspec)->default_value);
845 if (!op_data->is_enabled)
848 filter_cap = op_data->va_caps;
849 if (!op_data_get_value_float (op_data, &filter_cap->range, value, &va_value))
852 buf = vaapi_map_buffer (filter->va_display, op_data->va_buffer);
856 buf->type = op_data->va_type;
857 buf->value = va_value;
858 vaapi_unmap_buffer (filter->va_display, op_data->va_buffer, NULL);
862 static inline gboolean
863 op_set_generic (GstVaapiFilter * filter, GstVaapiFilterOpData * op_data,
866 gboolean success = FALSE;
868 GST_VAAPI_DISPLAY_LOCK (filter->display);
869 success = op_set_generic_unlocked (filter, op_data, value);
870 GST_VAAPI_DISPLAY_UNLOCK (filter->display);
874 /* Update the color balance filter */
875 #define COLOR_BALANCE_NUM \
876 GST_VAAPI_FILTER_OP_CONTRAST - GST_VAAPI_FILTER_OP_HUE + 1
879 op_set_color_balance_unlocked (GstVaapiFilter * filter,
880 GstVaapiFilterOpData * op_data, gfloat value)
882 VAProcFilterParameterBufferColorBalance *buf;
883 VAProcFilterCapColorBalance *filter_cap;
886 GstVaapiFilterOpData *color_data[COLOR_BALANCE_NUM];
887 GstVaapiFilterOpData *enabled_data = NULL;
893 /* collect all the Color Balance operators and find the first
895 for (i = 0; i < COLOR_BALANCE_NUM; i++) {
896 color_data[i] = find_operation (filter, GST_VAAPI_FILTER_OP_HUE + i);
900 if (!enabled_data && color_data[i]->is_enabled)
901 enabled_data = color_data[i];
904 /* If there's no enabled operators let's enable this one.
906 * HACK: This operator will be the only one with an allocated buffer
907 * which will store all the color balance operators.
910 if (value == G_PARAM_SPEC_FLOAT (op_data->pspec)->default_value)
913 if (!op_ensure_n_elements_buffer (filter, op_data, COLOR_BALANCE_NUM))
916 enabled_data = op_data;
918 buf = vaapi_map_buffer (filter->va_display, enabled_data->va_buffer);
922 /* Write all the color balance operator values in the buffer. --
923 * Use the default value for all the operators except the set
925 for (i = 0; i < COLOR_BALANCE_NUM; i++) {
926 buf[i].type = color_data[i]->va_type;
927 buf[i].attrib = color_data[i]->va_subtype;
929 va_value = G_PARAM_SPEC_FLOAT (color_data[i]->pspec)->default_value;
930 if (color_data[i]->op == op_data->op) {
931 filter_cap = color_data[i]->va_caps;
932 /* fail but ignore current value and set default one */
933 if (!op_data_get_value_float (color_data[i], &filter_cap->range, value,
938 buf[i].value = va_value;
941 enabled_data->is_enabled = 1;
943 /* There's already one operator enabled, *in theory* with a
944 * buffer associated. */
945 if (G_UNLIKELY (enabled_data->va_buffer == VA_INVALID_ID))
948 filter_cap = op_data->va_caps;
949 if (!op_data_get_value_float (op_data, &filter_cap->range, value,
953 buf = vaapi_map_buffer (filter->va_display, enabled_data->va_buffer);
957 buf[op_data->op - GST_VAAPI_FILTER_OP_HUE].value = va_value;
960 vaapi_unmap_buffer (filter->va_display, enabled_data->va_buffer, NULL);
965 static inline gboolean
966 op_set_color_balance (GstVaapiFilter * filter, GstVaapiFilterOpData * op_data,
969 gboolean success = FALSE;
971 GST_VAAPI_DISPLAY_LOCK (filter->display);
972 success = op_set_color_balance_unlocked (filter, op_data, value);
973 GST_VAAPI_DISPLAY_UNLOCK (filter->display);
977 /* Update deinterlace filter */
979 op_set_deinterlace_unlocked (GstVaapiFilter * filter,
980 GstVaapiFilterOpData * op_data, GstVaapiDeinterlaceMethod method,
983 VAProcFilterParameterBufferDeinterlacing *buf;
984 const VAProcFilterCapDeinterlacing *filter_caps;
985 VAProcDeinterlacingType algorithm;
988 if (!op_data || !op_ensure_buffer (filter, op_data))
991 op_data->is_enabled = (method != GST_VAAPI_DEINTERLACE_METHOD_NONE);
992 if (!op_data->is_enabled)
995 algorithm = from_GstVaapiDeinterlaceMethod (method);
996 for (i = 0, filter_caps = op_data->va_caps; i < op_data->va_num_caps; i++) {
997 if (filter_caps[i].type == algorithm)
1000 if (i == op_data->va_num_caps)
1003 buf = vaapi_map_buffer (filter->va_display, op_data->va_buffer);
1007 buf->type = op_data->va_type;
1008 buf->algorithm = algorithm;
1009 buf->flags = from_GstVaapiDeinterlaceFlags (flags);
1010 vaapi_unmap_buffer (filter->va_display, op_data->va_buffer, NULL);
1014 static inline gboolean
1015 op_set_deinterlace (GstVaapiFilter * filter, GstVaapiFilterOpData * op_data,
1016 GstVaapiDeinterlaceMethod method, guint flags)
1018 gboolean success = FALSE;
1020 GST_VAAPI_DISPLAY_LOCK (filter->display);
1021 success = op_set_deinterlace_unlocked (filter, op_data, method, flags);
1022 GST_VAAPI_DISPLAY_UNLOCK (filter->display);
1026 /* Update skin tone enhancement */
1028 op_set_skintone_unlocked (GstVaapiFilter * filter,
1029 GstVaapiFilterOpData * op_data, gboolean value)
1031 VAProcFilterParameterBuffer *buf;
1033 if (!op_data || !op_ensure_buffer (filter, op_data))
1036 op_data->is_enabled = value;
1037 if (!op_data->is_enabled)
1040 buf = vaapi_map_buffer (filter->va_display, op_data->va_buffer);
1043 buf->type = op_data->va_type;
1045 vaapi_unmap_buffer (filter->va_display, op_data->va_buffer, NULL);
1049 static inline gboolean
1050 op_set_skintone (GstVaapiFilter * filter, GstVaapiFilterOpData * op_data,
1053 gboolean success = FALSE;
1055 GST_VAAPI_DISPLAY_LOCK (filter->display);
1056 success = op_set_skintone_unlocked (filter, op_data, enhance);
1057 GST_VAAPI_DISPLAY_UNLOCK (filter->display);
1062 deint_refs_set (GArray * refs, GstVaapiSurface ** surfaces, guint num_surfaces)
1066 if (num_surfaces > 0 && !surfaces)
1069 for (i = 0; i < num_surfaces; i++)
1070 g_array_append_val (refs, GST_VAAPI_OBJECT_ID (surfaces[i]));
1075 deint_refs_clear (GArray * refs)
1078 g_array_remove_range (refs, 0, refs->len);
1082 deint_refs_clear_all (GstVaapiFilter * filter)
1084 deint_refs_clear (filter->forward_references);
1085 deint_refs_clear (filter->backward_references);
1088 /* ------------------------------------------------------------------------- */
1089 /* --- Surface Attribs --- */
1090 /* ------------------------------------------------------------------------- */
1093 ensure_attributes (GstVaapiFilter * filter)
1095 if (G_LIKELY (filter->attribs))
1098 filter->attribs = gst_vaapi_config_surface_attributes_get (filter->display,
1100 return (filter->attribs != NULL);
1103 static inline gboolean
1104 is_special_format (GstVideoFormat format)
1106 return format == GST_VIDEO_FORMAT_UNKNOWN ||
1107 format == GST_VIDEO_FORMAT_ENCODED;
1111 find_format (GstVaapiFilter * filter, GstVideoFormat format)
1116 formats = filter->attribs->formats;
1117 if (is_special_format (format) || !formats)
1120 for (i = 0; i < formats->len; i++) {
1121 if (g_array_index (formats, GstVideoFormat, i) == format)
1127 /* ------------------------------------------------------------------------- */
1128 /* --- Interface --- */
1129 /* ------------------------------------------------------------------------- */
1132 gst_vaapi_filter_init (GstVaapiFilter * filter)
1134 filter->va_config = VA_INVALID_ID;
1135 filter->va_context = VA_INVALID_ID;
1136 filter->format = DEFAULT_FORMAT;
1138 filter->forward_references =
1139 g_array_sized_new (FALSE, FALSE, sizeof (VASurfaceID), 4);
1141 filter->backward_references =
1142 g_array_sized_new (FALSE, FALSE, sizeof (VASurfaceID), 4);
1146 gst_vaapi_filter_initialize (GstVaapiFilter * filter)
1150 if (!filter->display)
1153 va_status = vaCreateConfig (filter->va_display, VAProfileNone,
1154 VAEntrypointVideoProc, NULL, 0, &filter->va_config);
1155 if (!vaapi_check_status (va_status, "vaCreateConfig() [VPP]"))
1158 va_status = vaCreateContext (filter->va_display, filter->va_config, 0, 0, 0,
1159 NULL, 0, &filter->va_context);
1160 if (!vaapi_check_status (va_status, "vaCreateContext() [VPP]"))
1166 gst_vaapi_filter_finalize (GObject * object)
1168 GstVaapiFilter *const filter = GST_VAAPI_FILTER (object);
1171 GST_VAAPI_DISPLAY_LOCK (filter->display);
1172 if (filter->operations) {
1173 for (i = 0; i < filter->operations->len; i++) {
1174 GstVaapiFilterOpData *const op_data =
1175 g_ptr_array_index (filter->operations, i);
1176 vaapi_destroy_buffer (filter->va_display, &op_data->va_buffer);
1178 g_ptr_array_unref (filter->operations);
1179 filter->operations = NULL;
1182 if (filter->va_context != VA_INVALID_ID) {
1183 vaDestroyContext (filter->va_display, filter->va_context);
1184 filter->va_context = VA_INVALID_ID;
1187 if (filter->va_config != VA_INVALID_ID) {
1188 vaDestroyConfig (filter->va_display, filter->va_config);
1189 filter->va_config = VA_INVALID_ID;
1191 GST_VAAPI_DISPLAY_UNLOCK (filter->display);
1192 gst_vaapi_display_replace (&filter->display, NULL);
1194 if (filter->forward_references) {
1195 g_array_unref (filter->forward_references);
1196 filter->forward_references = NULL;
1199 if (filter->backward_references) {
1200 g_array_unref (filter->backward_references);
1201 filter->backward_references = NULL;
1204 if (filter->attribs) {
1205 gst_vaapi_config_surface_attributes_free (filter->attribs);
1206 filter->attribs = NULL;
1209 G_OBJECT_CLASS (gst_vaapi_filter_parent_class)->finalize (object);
1213 gst_vaapi_filter_set_property (GObject * object, guint property_id,
1214 const GValue * value, GParamSpec * pspec)
1216 GstVaapiFilter *const filter = GST_VAAPI_FILTER (object);
1218 switch (property_id) {
1220 GstVaapiDisplay *display = g_value_get_object (value);;
1223 if (GST_VAAPI_DISPLAY_HAS_VPP (display)) {
1224 filter->display = gst_object_ref (display);
1225 filter->va_display = GST_VAAPI_DISPLAY_VADISPLAY (filter->display);
1227 GST_WARNING_OBJECT (filter, "VA display doesn't support VPP");
1233 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
1238 gst_vaapi_filter_get_property (GObject * object, guint property_id,
1239 GValue * value, GParamSpec * pspec)
1241 GstVaapiFilter *const filter = GST_VAAPI_FILTER (object);
1243 switch (property_id) {
1245 g_value_set_object (value, filter->display);
1248 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
1253 gst_vaapi_filter_class_init (GstVaapiFilterClass * klass)
1255 GObjectClass *const object_class = G_OBJECT_CLASS (klass);
1257 object_class->set_property = gst_vaapi_filter_set_property;
1258 object_class->get_property = gst_vaapi_filter_get_property;
1259 object_class->finalize = gst_vaapi_filter_finalize;
1262 * GstVaapiFilter:display:
1264 * #GstVaapiDisplay to be used.
1266 g_object_class_install_property (object_class, PROP_DISPLAY,
1267 g_param_spec_object ("display", "Gst VA-API Display",
1268 "The VA-API display object to use", GST_TYPE_VAAPI_DISPLAY,
1269 G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_NAME));
1273 * gst_vaapi_filter_new:
1274 * @display: a #GstVaapiDisplay
1276 * Creates a new #GstVaapiFilter set up to operate in "identity"
1277 * mode. This means that no other operation than scaling is performed.
1279 * Return value: the newly created #GstVaapiFilter object
1282 gst_vaapi_filter_new (GstVaapiDisplay * display)
1284 GstVaapiFilter *filter;
1286 filter = g_object_new (GST_TYPE_VAAPI_FILTER, "display", display, NULL);
1287 if (!gst_vaapi_filter_initialize (filter))
1294 gst_object_unref (filter);
1300 * gst_vaapi_filter_replace:
1301 * @old_filter_ptr: a pointer to a #GstVaapiFilter
1302 * @new_filter: a #GstVaapiFilter
1304 * Atomically replaces the filter held in @old_filter_ptr with
1305 * @new_filter. This means that @old_filter_ptr shall reference a
1306 * valid filter. However, @new_filter can be NULL.
1309 gst_vaapi_filter_replace (GstVaapiFilter ** old_filter_ptr,
1310 GstVaapiFilter * new_filter)
1312 g_return_if_fail (old_filter_ptr != NULL);
1314 gst_object_replace ((GstObject **) old_filter_ptr, GST_OBJECT (new_filter));
1318 * gst_vaapi_filter_get_operations:
1319 * @filter: a #GstVaapiFilter, or %NULL
1321 * Determines the set of supported operations for video processing.
1322 * The caller owns an extra reference to the resulting array of
1323 * #GstVaapiFilterOpInfo elements, so it shall be released with
1324 * g_ptr_array_unref() after usage.
1326 * If @filter is %NULL, then this function returns the video
1327 * processing operations supported by this library.
1329 * Return value: the set of supported operations, or %NULL if an error
1333 gst_vaapi_filter_get_operations (GstVaapiFilter * filter)
1335 return get_operations (filter);
1339 * gst_vaapi_filter_has_operation:
1340 * @filter: a #GstVaapiFilter
1341 * @op: a #GstVaapiFilterOp
1343 * Determines whether the underlying VA driver advertises support for
1344 * the supplied operation @op.
1346 * Return value: %TRUE if the specified operation may be supported by
1347 * the underlying hardware, %FALSE otherwise
1350 gst_vaapi_filter_has_operation (GstVaapiFilter * filter, GstVaapiFilterOp op)
1352 g_return_val_if_fail (filter != NULL, FALSE);
1354 return find_operation (filter, op) != NULL;
1358 * gst_vaapi_filter_use_operation:
1359 * @filter: a #GstVaapiFilter
1360 * @op: a #GstVaapiFilterOp
1362 * Determines whether the supplied operation @op was already enabled
1363 * through a prior call to gst_vaapi_filter_set_operation() or any
1364 * other operation-specific function.
1366 * Note: should an operation be set to its default value, this means
1367 * that it is actually not enabled.
1369 * Return value: %TRUE if the specified operation was already enabled,
1373 gst_vaapi_filter_use_operation (GstVaapiFilter * filter, GstVaapiFilterOp op)
1375 GstVaapiFilterOpData *op_data;
1377 g_return_val_if_fail (filter != NULL, FALSE);
1379 op_data = find_operation (filter, op);
1382 return op_data->is_enabled;
1386 * gst_vaapi_filter_set_operation:
1387 * @filter: a #GstVaapiFilter
1388 * @op: a #GstVaapiFilterOp
1389 * @value: the @op settings
1391 * Enable the specified operation @op to be performed during video
1392 * processing, i.e. in gst_vaapi_filter_process(). The @value argument
1393 * specifies the operation settings. e.g. deinterlacing method for
1394 * deinterlacing, denoising level for noise reduction, etc.
1396 * If @value is %NULL, then this function resets the operation
1397 * settings to their default values.
1399 * Return value: %TRUE if the specified operation may be supported,
1403 gst_vaapi_filter_set_operation (GstVaapiFilter * filter, GstVaapiFilterOp op,
1404 const GValue * value)
1406 GstVaapiFilterOpData *op_data;
1408 g_return_val_if_fail (filter != NULL, FALSE);
1410 op_data = find_operation (filter, op);
1414 if (value && !G_VALUE_HOLDS (value, G_PARAM_SPEC_VALUE_TYPE (op_data->pspec)))
1418 case GST_VAAPI_FILTER_OP_FORMAT:
1419 return gst_vaapi_filter_set_format (filter, value ?
1420 g_value_get_enum (value) : DEFAULT_FORMAT);
1421 case GST_VAAPI_FILTER_OP_CROP:
1422 return gst_vaapi_filter_set_cropping_rectangle (filter, value ?
1423 g_value_get_boxed (value) : NULL);
1424 case GST_VAAPI_FILTER_OP_DENOISE:
1425 case GST_VAAPI_FILTER_OP_SHARPEN:
1426 return op_set_generic (filter, op_data,
1427 (value ? g_value_get_float (value) :
1428 G_PARAM_SPEC_FLOAT (op_data->pspec)->default_value));
1429 case GST_VAAPI_FILTER_OP_HUE:
1430 case GST_VAAPI_FILTER_OP_SATURATION:
1431 case GST_VAAPI_FILTER_OP_BRIGHTNESS:
1432 case GST_VAAPI_FILTER_OP_CONTRAST:
1433 return op_set_color_balance (filter, op_data,
1434 (value ? g_value_get_float (value) :
1435 G_PARAM_SPEC_FLOAT (op_data->pspec)->default_value));
1436 case GST_VAAPI_FILTER_OP_DEINTERLACING:
1437 return op_set_deinterlace (filter, op_data,
1438 (value ? g_value_get_enum (value) :
1439 G_PARAM_SPEC_ENUM (op_data->pspec)->default_value), 0);
1441 case GST_VAAPI_FILTER_OP_SCALING:
1442 return gst_vaapi_filter_set_scaling (filter, value ?
1443 g_value_get_enum (value) : DEFAULT_SCALING);
1444 case GST_VAAPI_FILTER_OP_SKINTONE:
1445 return op_set_skintone (filter, op_data,
1446 (value ? g_value_get_boolean (value) :
1447 G_PARAM_SPEC_BOOLEAN (op_data->pspec)->default_value));
1448 case GST_VAAPI_FILTER_OP_VIDEO_DIRECTION:
1449 return gst_vaapi_filter_set_video_direction (filter, value ?
1450 g_value_get_enum (value) : DEFAULT_VIDEO_DIRECTION);
1458 * gst_vaapi_filter_process:
1459 * @filter: a #GstVaapiFilter
1460 * @src_surface: the source @GstVaapiSurface
1461 * @dst_surface: the destination @GstVaapiSurface
1462 * @flags: #GstVaapiSurfaceRenderFlags that apply to @src_surface
1464 * Applies the operations currently defined in the @filter to
1465 * @src_surface and return the output in @dst_surface. The order of
1466 * operations is determined in a way that suits best the underlying
1467 * hardware. i.e. the only guarantee held is the generated outcome,
1468 * not any specific order of operations.
1470 * Return value: a #GstVaapiFilterStatus
1472 static GstVaapiFilterStatus
1473 gst_vaapi_filter_process_unlocked (GstVaapiFilter * filter,
1474 GstVaapiSurface * src_surface, GstVaapiSurface * dst_surface, guint flags)
1476 VAProcPipelineParameterBuffer *pipeline_param = NULL;
1477 VABufferID pipeline_param_buf_id = VA_INVALID_ID;
1478 VABufferID filters[N_PROPERTIES];
1479 VAProcPipelineCaps pipeline_caps;
1480 guint i, num_filters = 0;
1482 VARectangle src_rect, dst_rect;
1483 guint va_mirror = 0, va_rotation = 0;
1485 if (!ensure_operations (filter))
1486 return GST_VAAPI_FILTER_STATUS_ERROR_ALLOCATION_FAILED;
1488 /* Build surface region (source) */
1489 if (filter->use_crop_rect) {
1490 const GstVaapiRectangle *const crop_rect = &filter->crop_rect;
1492 if ((crop_rect->x + crop_rect->width >
1493 GST_VAAPI_SURFACE_WIDTH (src_surface)) ||
1494 (crop_rect->y + crop_rect->height >
1495 GST_VAAPI_SURFACE_HEIGHT (src_surface)))
1498 src_rect.x = crop_rect->x;
1499 src_rect.y = crop_rect->y;
1500 src_rect.width = crop_rect->width;
1501 src_rect.height = crop_rect->height;
1505 src_rect.width = GST_VAAPI_SURFACE_WIDTH (src_surface);
1506 src_rect.height = GST_VAAPI_SURFACE_HEIGHT (src_surface);
1509 /* Build output region (target) */
1510 if (filter->use_target_rect) {
1511 const GstVaapiRectangle *const target_rect = &filter->target_rect;
1513 if ((target_rect->x + target_rect->width >
1514 GST_VAAPI_SURFACE_WIDTH (dst_surface)) ||
1515 (target_rect->y + target_rect->height >
1516 GST_VAAPI_SURFACE_HEIGHT (dst_surface)))
1519 dst_rect.x = target_rect->x;
1520 dst_rect.y = target_rect->y;
1521 dst_rect.width = target_rect->width;
1522 dst_rect.height = target_rect->height;
1526 dst_rect.width = GST_VAAPI_SURFACE_WIDTH (dst_surface);
1527 dst_rect.height = GST_VAAPI_SURFACE_HEIGHT (dst_surface);
1530 for (i = 0, num_filters = 0; i < filter->operations->len; i++) {
1531 GstVaapiFilterOpData *const op_data =
1532 g_ptr_array_index (filter->operations, i);
1533 if (!op_data->is_enabled)
1535 if (op_data->va_buffer == VA_INVALID_ID) {
1536 GST_ERROR ("invalid VA buffer for operation %s",
1537 g_param_spec_get_name (op_data->pspec));
1540 filters[num_filters++] = op_data->va_buffer;
1543 /* Validate pipeline caps */
1544 va_status = vaQueryVideoProcPipelineCaps (filter->va_display,
1545 filter->va_context, filters, num_filters, &pipeline_caps);
1546 if (!vaapi_check_status (va_status, "vaQueryVideoProcPipelineCaps()"))
1549 if (!vaapi_create_buffer (filter->va_display, filter->va_context,
1550 VAProcPipelineParameterBufferType, sizeof (*pipeline_param),
1551 NULL, &pipeline_param_buf_id, (gpointer *) & pipeline_param))
1554 memset (pipeline_param, 0, sizeof (*pipeline_param));
1555 pipeline_param->surface = GST_VAAPI_OBJECT_ID (src_surface);
1556 pipeline_param->surface_region = &src_rect;
1557 pipeline_param->surface_color_standard = VAProcColorStandardNone;
1558 pipeline_param->output_region = &dst_rect;
1559 pipeline_param->output_color_standard = VAProcColorStandardNone;
1560 pipeline_param->output_background_color = 0xff000000;
1561 pipeline_param->filter_flags = from_GstVaapiSurfaceRenderFlags (flags) |
1562 from_GstVaapiScaleMethod (filter->scale_method);
1563 pipeline_param->filters = filters;
1564 pipeline_param->num_filters = num_filters;
1566 from_GstVideoOrientationMethod (filter->video_direction, &va_mirror,
1569 #if VA_CHECK_VERSION(1,1,0)
1570 pipeline_param->mirror_state = va_mirror;
1571 pipeline_param->rotation_state = va_rotation;
1574 // Reference frames for advanced deinterlacing
1575 if (filter->forward_references->len > 0) {
1576 pipeline_param->forward_references = (VASurfaceID *)
1577 filter->forward_references->data;
1578 pipeline_param->num_forward_references =
1579 MIN (filter->forward_references->len,
1580 pipeline_caps.num_forward_references);
1582 pipeline_param->forward_references = NULL;
1583 pipeline_param->num_forward_references = 0;
1586 if (filter->backward_references->len > 0) {
1587 pipeline_param->backward_references = (VASurfaceID *)
1588 filter->backward_references->data;
1589 pipeline_param->num_backward_references =
1590 MIN (filter->backward_references->len,
1591 pipeline_caps.num_backward_references);
1593 pipeline_param->backward_references = NULL;
1594 pipeline_param->num_backward_references = 0;
1597 vaapi_unmap_buffer (filter->va_display, pipeline_param_buf_id, NULL);
1599 va_status = vaBeginPicture (filter->va_display, filter->va_context,
1600 GST_VAAPI_OBJECT_ID (dst_surface));
1601 if (!vaapi_check_status (va_status, "vaBeginPicture()"))
1604 va_status = vaRenderPicture (filter->va_display, filter->va_context,
1605 &pipeline_param_buf_id, 1);
1606 if (!vaapi_check_status (va_status, "vaRenderPicture()"))
1609 va_status = vaEndPicture (filter->va_display, filter->va_context);
1610 if (!vaapi_check_status (va_status, "vaEndPicture()"))
1613 deint_refs_clear_all (filter);
1614 vaapi_destroy_buffer (filter->va_display, &pipeline_param_buf_id);
1615 return GST_VAAPI_FILTER_STATUS_SUCCESS;
1620 deint_refs_clear_all (filter);
1621 vaapi_destroy_buffer (filter->va_display, &pipeline_param_buf_id);
1622 return GST_VAAPI_FILTER_STATUS_ERROR_OPERATION_FAILED;
1626 GstVaapiFilterStatus
1627 gst_vaapi_filter_process (GstVaapiFilter * filter,
1628 GstVaapiSurface * src_surface, GstVaapiSurface * dst_surface, guint flags)
1630 GstVaapiFilterStatus status;
1632 g_return_val_if_fail (filter != NULL,
1633 GST_VAAPI_FILTER_STATUS_ERROR_INVALID_PARAMETER);
1634 g_return_val_if_fail (src_surface != NULL,
1635 GST_VAAPI_FILTER_STATUS_ERROR_INVALID_PARAMETER);
1636 g_return_val_if_fail (dst_surface != NULL,
1637 GST_VAAPI_FILTER_STATUS_ERROR_INVALID_PARAMETER);
1639 GST_VAAPI_DISPLAY_LOCK (filter->display);
1640 status = gst_vaapi_filter_process_unlocked (filter,
1641 src_surface, dst_surface, flags);
1642 GST_VAAPI_DISPLAY_UNLOCK (filter->display);
1647 * gst_vaapi_filter_get_formats:
1648 * @filter: a #GstVaapiFilter
1650 * Determines the set of supported source or target formats for video
1651 * processing. The caller owns an extra reference to the resulting
1652 * array of #GstVideoFormat elements, so it shall be released with
1653 * g_array_unref() after usage.
1655 * Return value: the set of supported target formats for video processing.
1658 gst_vaapi_filter_get_formats (GstVaapiFilter * filter)
1660 g_return_val_if_fail (filter != NULL, NULL);
1662 if (!ensure_attributes (filter))
1664 if (filter->attribs->formats)
1665 return g_array_ref (filter->attribs->formats);
1670 * gst_vaapi_filter_set_format:
1671 * @filter: a #GstVaapiFilter
1672 * @format: the target surface format
1674 * Sets the desired pixel format of the resulting video processing
1677 * If @format is #GST_VIDEO_FORMAT_UNKNOWN, the filter will assume iso
1678 * format conversion, i.e. no color conversion at all and the target
1679 * surface format shall match the source surface format.
1681 * If @format is #GST_VIDEO_FORMAT_ENCODED, the filter will use the pixel
1682 * format of the target surface passed to gst_vaapi_filter_process().
1684 * Return value: %TRUE if the color conversion to the specified @format
1685 * may be supported, %FALSE otherwise.
1688 gst_vaapi_filter_set_format (GstVaapiFilter * filter, GstVideoFormat format)
1690 g_return_val_if_fail (filter != NULL, FALSE);
1692 if (!ensure_attributes (filter))
1695 if (!is_special_format (format) && !find_format (filter, format))
1698 filter->format = format;
1703 * gst_vaapi_filter_append_caps:
1704 * @filter: a #GstVaapiFilter
1705 * @structure: a #GstStructure from #GstCaps
1707 * Extracts the config's surface attributes, from @filter's context,
1708 * and transforms it into a caps formats and appended them into
1711 * Returns: %TRUE if the capabilities could be extracted and appended
1712 * into @structure; otherwise %FALSE
1715 gst_vaapi_filter_append_caps (GstVaapiFilter * filter, GstStructure * structure)
1717 GstVaapiConfigSurfaceAttributes *attribs;
1719 g_return_val_if_fail (filter != NULL, FALSE);
1720 g_return_val_if_fail (structure != NULL, FALSE);
1722 if (!ensure_attributes (filter))
1725 attribs = filter->attribs;
1727 if (attribs->min_width >= attribs->max_width ||
1728 attribs->min_height >= attribs->max_height)
1731 gst_structure_set (structure, "width", GST_TYPE_INT_RANGE, attribs->min_width,
1732 attribs->max_width, "height", GST_TYPE_INT_RANGE, attribs->min_height,
1733 attribs->max_height, NULL);
1740 * gst_vaapi_filter_set_cropping_rectangle:
1741 * @filter: a #GstVaapiFilter
1742 * @rect: the cropping region
1744 * Sets the source surface cropping rectangle to use during the video
1745 * processing. If @rect is %NULL, the whole source surface will be used.
1747 * Return value: %TRUE if the operation is supported, %FALSE otherwise.
1750 gst_vaapi_filter_set_cropping_rectangle (GstVaapiFilter * filter,
1751 const GstVaapiRectangle * rect)
1753 g_return_val_if_fail (filter != NULL, FALSE);
1755 filter->use_crop_rect = rect != NULL;
1756 if (filter->use_crop_rect)
1757 filter->crop_rect = *rect;
1762 * gst_vaapi_filter_set_target_rectangle:
1763 * @filter: a #GstVaapiFilter
1764 * @rect: the target render region
1766 * Sets the region within the target surface where the source surface
1767 * would be rendered. i.e. where the hardware accelerator would emit
1768 * the outcome of video processing. If @rect is %NULL, the whole
1769 * source surface will be used.
1771 * Return value: %TRUE if the operation is supported, %FALSE otherwise.
1774 gst_vaapi_filter_set_target_rectangle (GstVaapiFilter * filter,
1775 const GstVaapiRectangle * rect)
1777 g_return_val_if_fail (filter != NULL, FALSE);
1779 filter->use_target_rect = rect != NULL;
1780 if (filter->use_target_rect)
1781 filter->target_rect = *rect;
1786 * gst_vaapi_filter_set_denoising_level:
1787 * @filter: a #GstVaapiFilter
1788 * @level: the level of noise reduction to apply
1790 * Sets the noise reduction level to apply. If @level is 0.0f, this
1791 * corresponds to disabling the noise reduction algorithm.
1793 * Return value: %TRUE if the operation is supported, %FALSE otherwise.
1796 gst_vaapi_filter_set_denoising_level (GstVaapiFilter * filter, gfloat level)
1798 g_return_val_if_fail (filter != NULL, FALSE);
1800 return op_set_generic (filter,
1801 find_operation (filter, GST_VAAPI_FILTER_OP_DENOISE), level);
1805 * gst_vaapi_filter_set_sharpening_level:
1806 * @filter: a #GstVaapiFilter
1807 * @level: the sharpening factor
1809 * Enables noise reduction with the specified factor.
1811 * Return value: %TRUE if the operation is supported, %FALSE otherwise.
1814 gst_vaapi_filter_set_sharpening_level (GstVaapiFilter * filter, gfloat level)
1816 g_return_val_if_fail (filter != NULL, FALSE);
1818 return op_set_generic (filter,
1819 find_operation (filter, GST_VAAPI_FILTER_OP_SHARPEN), level);
1823 * gst_vaapi_filter_set_hue:
1824 * @filter: a #GstVaapiFilter
1825 * @value: the color hue value
1827 * Enables color hue adjustment to the specified value.
1829 * Return value: %TRUE if the operation is supported, %FALSE otherwise.
1832 gst_vaapi_filter_set_hue (GstVaapiFilter * filter, gfloat value)
1834 g_return_val_if_fail (filter != NULL, FALSE);
1836 return op_set_color_balance (filter,
1837 find_operation (filter, GST_VAAPI_FILTER_OP_HUE), value);
1841 * gst_vaapi_filter_set_saturation:
1842 * @filter: a #GstVaapiFilter
1843 * @value: the color saturation value
1845 * Enables color saturation adjustment to the specified value.
1847 * Return value: %TRUE if the operation is supported, %FALSE otherwise.
1850 gst_vaapi_filter_set_saturation (GstVaapiFilter * filter, gfloat value)
1852 g_return_val_if_fail (filter != NULL, FALSE);
1854 return op_set_color_balance (filter,
1855 find_operation (filter, GST_VAAPI_FILTER_OP_SATURATION), value);
1859 * gst_vaapi_filter_set_brightness:
1860 * @filter: a #GstVaapiFilter
1861 * @value: the color brightness value
1863 * Enables color brightness adjustment to the specified value.
1865 * Return value: %TRUE if the operation is supported, %FALSE otherwise.
1868 gst_vaapi_filter_set_brightness (GstVaapiFilter * filter, gfloat value)
1870 g_return_val_if_fail (filter != NULL, FALSE);
1872 return op_set_color_balance (filter,
1873 find_operation (filter, GST_VAAPI_FILTER_OP_BRIGHTNESS), value);
1877 * gst_vaapi_filter_set_contrast:
1878 * @filter: a #GstVaapiFilter
1879 * @value: the color contrast value
1881 * Enables color contrast adjustment to the specified value.
1883 * Return value: %TRUE if the operation is supported, %FALSE otherwise.
1886 gst_vaapi_filter_set_contrast (GstVaapiFilter * filter, gfloat value)
1888 g_return_val_if_fail (filter != NULL, FALSE);
1890 return op_set_color_balance (filter,
1891 find_operation (filter, GST_VAAPI_FILTER_OP_CONTRAST), value);
1895 * gst_vaapi_filter_set_deinterlacing:
1896 * @filter: a #GstVaapiFilter
1897 * @method: the deinterlacing algorithm (see #GstVaapiDeinterlaceMethod)
1898 * @flags: the additional flags
1900 * Applies deinterlacing to the video processing pipeline. If @method
1901 * is not @GST_VAAPI_DEINTERLACE_METHOD_NONE, then @flags could
1902 * represent the initial picture structure of the source frame.
1904 * Return value: %TRUE if the operation is supported, %FALSE otherwise.
1907 gst_vaapi_filter_set_deinterlacing (GstVaapiFilter * filter,
1908 GstVaapiDeinterlaceMethod method, guint flags)
1910 g_return_val_if_fail (filter != NULL, FALSE);
1912 return op_set_deinterlace (filter,
1913 find_operation (filter, GST_VAAPI_FILTER_OP_DEINTERLACING), method,
1918 * gst_vaapi_filter_set_deinterlacing_references:
1919 * @filter: a #GstVaapiFilter
1920 * @forward_references: the set of #GstVaapiSurface objects used as
1921 * forward references
1922 * @num_forward_references: the number of elements in the
1923 * @forward_references array
1924 * @backward_references: the set of #GstVaapiSurface objects used as
1925 * backward references
1926 * @num_backward_references: the number of elements in the
1927 * @backward_references array
1929 * Specifies the list of surfaces used for forward or backward reference in
1930 * advanced deinterlacing mode. The caller is responsible for maintaining
1931 * the associated surfaces live until gst_vaapi_filter_process() completes.
1932 * e.g. by holding an extra reference to the associated #GstVaapiSurfaceProxy.
1934 * Temporal ordering is maintained as follows: the shorter index in
1935 * either array is, the closest the matching surface is relatively to
1936 * the current source surface to process. e.g. surface in
1937 * @forward_references array index 0 represents the immediately
1938 * preceding surface in display order, surface at index 1 is the one
1939 * preceding surface at index 0, etc.
1941 * The video processing filter will only use the recommended number of
1942 * surfaces for backward and forward references.
1944 * Note: the supplied lists of reference surfaces are not sticky. This
1945 * means that they are only valid for the next gst_vaapi_filter_process()
1946 * call, and thus needs to be submitted again for subsequent calls.
1948 * Return value: %TRUE if the operation is supported, %FALSE otherwise.
1951 gst_vaapi_filter_set_deinterlacing_references (GstVaapiFilter * filter,
1952 GstVaapiSurface ** forward_references, guint num_forward_references,
1953 GstVaapiSurface ** backward_references, guint num_backward_references)
1955 g_return_val_if_fail (filter != NULL, FALSE);
1957 deint_refs_clear_all (filter);
1959 if (!deint_refs_set (filter->forward_references, forward_references,
1960 num_forward_references))
1963 if (!deint_refs_set (filter->backward_references, backward_references,
1964 num_backward_references))
1970 * gst_vaapi_filter_set_scaling:
1971 * @filter: a #GstVaapiFilter
1972 * @method: the scaling algorithm (see #GstVaapiScaleMethod)
1974 * Applies scaling algorithm to the video processing pipeline.
1976 * Return value: %TRUE if the operation is supported, %FALSE otherwise.
1979 gst_vaapi_filter_set_scaling (GstVaapiFilter * filter,
1980 GstVaapiScaleMethod method)
1982 g_return_val_if_fail (filter != NULL, FALSE);
1984 filter->scale_method = method;
1989 * gst_vaapi_filter_set_skintone:
1990 * @filter: a #GstVaapiFilter
1991 * @enhance: %TRUE if enable the skin tone enhancement algorithm
1993 * Applies the skin tone enhancement algorithm.
1995 * Return value: %TRUE if the operation is supported, %FALSE
1999 gst_vaapi_filter_set_skintone (GstVaapiFilter * filter, gboolean enhance)
2001 g_return_val_if_fail (filter != NULL, FALSE);
2003 return op_set_skintone (filter,
2004 find_operation (filter, GST_VAAPI_FILTER_OP_SKINTONE), enhance);
2008 * gst_vaapi_filter_set_video_direction:
2009 * @filter: a #GstVaapiFilter
2010 * @method: the video direction (see #GstVideoOrientationMethod)
2012 * Applies mirror/rotation to the video processing pipeline.
2014 * Return value: %TRUE if the operation is supported, %FALSE otherwise.
2017 gst_vaapi_filter_set_video_direction (GstVaapiFilter * filter,
2018 GstVideoOrientationMethod method)
2020 g_return_val_if_fail (filter != NULL, FALSE);
2022 #if VA_CHECK_VERSION(1,1,0)
2024 guint32 va_mirror = VA_MIRROR_NONE;
2025 guint32 va_rotation = VA_ROTATION_NONE;
2027 from_GstVideoOrientationMethod (method, &va_mirror, &va_rotation);
2029 if (va_mirror != VA_MIRROR_NONE && !(filter->mirror_flags & va_mirror))
2032 if (va_rotation != VA_ROTATION_NONE
2033 && !(filter->rotation_flags & (1 << va_rotation)))
2040 filter->video_direction = method;
2045 * gst_vaapi_filter_get_video_direction:
2046 * @filter: a #GstVaapiFilter
2048 * Return value: the currently applied video direction (see #GstVideoOrientationMethod)
2050 GstVideoOrientationMethod
2051 gst_vaapi_filter_get_video_direction (GstVaapiFilter * filter)
2053 g_return_val_if_fail (filter != NULL, GST_VIDEO_ORIENTATION_IDENTITY);
2054 return filter->video_direction;
2057 static inline gfloat
2058 op_get_float_default_value (GstVaapiFilter * filter,
2059 GstVaapiFilterOpData * op_data)
2061 GParamSpecFloat *const pspec = G_PARAM_SPEC_FLOAT (op_data->pspec);
2062 return pspec->default_value;
2066 gst_vaapi_filter_get_denoising_level_default (GstVaapiFilter * filter)
2068 g_return_val_if_fail (filter != NULL, FALSE);
2070 return op_get_float_default_value (filter,
2071 find_operation (filter, GST_VAAPI_FILTER_OP_DENOISE));
2075 gst_vaapi_filter_get_sharpening_level_default (GstVaapiFilter * filter)
2077 g_return_val_if_fail (filter != NULL, FALSE);
2079 return op_get_float_default_value (filter,
2080 find_operation (filter, GST_VAAPI_FILTER_OP_SHARPEN));
2084 gst_vaapi_filter_get_hue_default (GstVaapiFilter * filter)
2086 g_return_val_if_fail (filter != NULL, FALSE);
2088 return op_get_float_default_value (filter,
2089 find_operation (filter, GST_VAAPI_FILTER_OP_HUE));
2093 gst_vaapi_filter_get_saturation_default (GstVaapiFilter * filter)
2095 g_return_val_if_fail (filter != NULL, FALSE);
2097 return op_get_float_default_value (filter,
2098 find_operation (filter, GST_VAAPI_FILTER_OP_SATURATION));
2102 gst_vaapi_filter_get_brightness_default (GstVaapiFilter * filter)
2104 g_return_val_if_fail (filter != NULL, FALSE);
2106 return op_get_float_default_value (filter,
2107 find_operation (filter, GST_VAAPI_FILTER_OP_BRIGHTNESS));
2111 gst_vaapi_filter_get_contrast_default (GstVaapiFilter * filter)
2113 g_return_val_if_fail (filter != NULL, FALSE);
2115 return op_get_float_default_value (filter,
2116 find_operation (filter, GST_VAAPI_FILTER_OP_CONTRAST));
2120 gst_vaapi_filter_get_scaling_default (GstVaapiFilter * filter)
2122 g_return_val_if_fail (filter != NULL, FALSE);
2124 return DEFAULT_SCALING;
2128 gst_vaapi_filter_get_skintone_default (GstVaapiFilter * filter)
2130 g_return_val_if_fail (filter != NULL, FALSE);
2135 GstVideoOrientationMethod
2136 gst_vaapi_filter_get_video_direction_default (GstVaapiFilter * filter)
2138 g_return_val_if_fail (filter != NULL, FALSE);
2140 return DEFAULT_VIDEO_DIRECTION;