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 "gstvaapifilter.h"
25 #include "gstvaapiutils.h"
26 #include "gstvaapivalue.h"
27 #include "gstvaapiminiobject.h"
28 #include "gstvaapidisplay_priv.h"
29 #include "gstvaapisurface_priv.h"
32 # include <va/va_vpp.h>
36 #include "gstvaapidebug.h"
38 #define GST_VAAPI_FILTER(obj) \
39 ((GstVaapiFilter *)(obj))
41 typedef struct _GstVaapiFilterOpData GstVaapiFilterOpData;
42 struct _GstVaapiFilterOpData {
45 volatile gint ref_count;
56 struct _GstVaapiFilter {
58 GstVaapiMiniObject parent_instance;
60 GstVaapiDisplay *display;
63 VAContextID va_context;
64 GPtrArray *operations;
65 GstVideoFormat format;
67 GArray *forward_references;
68 GArray *backward_references;
69 GstVaapiRectangle crop_rect;
70 GstVaapiRectangle target_rect;
71 guint use_crop_rect : 1;
72 guint use_target_rect : 1;
75 /* ------------------------------------------------------------------------- */
76 /* --- VPP Types --- */
77 /* ------------------------------------------------------------------------- */
80 gst_vaapi_deinterlace_method_get_type(void)
82 static gsize g_type = 0;
84 static const GEnumValue enum_values[] = {
85 { GST_VAAPI_DEINTERLACE_METHOD_NONE,
86 "Disable deinterlacing", "none" },
87 { GST_VAAPI_DEINTERLACE_METHOD_BOB,
88 "Bob deinterlacing", "bob" },
90 { GST_VAAPI_DEINTERLACE_METHOD_WEAVE,
91 "Weave deinterlacing", "weave" },
92 { GST_VAAPI_DEINTERLACE_METHOD_MOTION_ADAPTIVE,
93 "Motion adaptive deinterlacing", "motion-adaptive" },
94 { GST_VAAPI_DEINTERLACE_METHOD_MOTION_COMPENSATED,
95 "Motion compensated deinterlacing", "motion-compensated" },
100 if (g_once_init_enter(&g_type)) {
102 g_enum_register_static("GstVaapiDeinterlaceMethod", enum_values);
103 g_once_init_leave(&g_type, type);
109 gst_vaapi_deinterlace_flags_get_type(void)
111 static gsize g_type = 0;
113 static const GEnumValue enum_values[] = {
114 { GST_VAAPI_DEINTERLACE_FLAG_TFF,
115 "Top-field first", "top-field-first" },
116 { GST_VAAPI_DEINTERLACE_FLAG_ONEFIELD,
117 "One field", "one-field" },
118 { GST_VAAPI_DEINTERLACE_FLAG_TOPFIELD,
119 "Top field", "top-field" },
123 if (g_once_init_enter(&g_type)) {
125 g_enum_register_static("GstVaapiDeinterlaceFlags", enum_values);
126 g_once_init_leave(&g_type, type);
131 /* ------------------------------------------------------------------------- */
132 /* --- VPP Helpers --- */
133 /* ------------------------------------------------------------------------- */
136 static VAProcFilterType *
137 vpp_get_filters_unlocked(GstVaapiFilter *filter, guint *num_filters_ptr)
139 VAProcFilterType *filters = NULL;
140 guint num_filters = 0;
143 num_filters = VAProcFilterCount;
144 filters = g_malloc_n(num_filters, sizeof(*filters));
148 va_status = vaQueryVideoProcFilters(filter->va_display, filter->va_context,
149 filters, &num_filters);
151 // Try to reallocate to the expected number of filters
152 if (va_status == VA_STATUS_ERROR_MAX_NUM_EXCEEDED) {
153 VAProcFilterType * const new_filters =
154 g_try_realloc_n(filters, num_filters, sizeof(*new_filters));
157 filters = new_filters;
159 va_status = vaQueryVideoProcFilters(filter->va_display,
160 filter->va_context, filters, &num_filters);
162 if (!vaapi_check_status(va_status, "vaQueryVideoProcFilters()"))
165 *num_filters_ptr = num_filters;
173 static VAProcFilterType *
174 vpp_get_filters(GstVaapiFilter *filter, guint *num_filters_ptr)
176 VAProcFilterType *filters;
178 GST_VAAPI_DISPLAY_LOCK(filter->display);
179 filters = vpp_get_filters_unlocked(filter, num_filters_ptr);
180 GST_VAAPI_DISPLAY_UNLOCK(filter->display);
185 vpp_get_filter_caps_unlocked(
186 GstVaapiFilter *filter, VAProcFilterType type,
187 guint cap_size, guint *num_caps_ptr)
193 caps = g_malloc(cap_size);
197 va_status = vaQueryVideoProcFilterCaps(filter->va_display,
198 filter->va_context, type, caps, &num_caps);
200 // Try to reallocate to the expected number of filters
201 if (va_status == VA_STATUS_ERROR_MAX_NUM_EXCEEDED) {
202 gpointer const new_caps = g_try_realloc_n(caps, num_caps, cap_size);
207 va_status = vaQueryVideoProcFilterCaps(filter->va_display,
208 filter->va_context, type, caps, &num_caps);
210 if (!vaapi_check_status(va_status, "vaQueryVideoProcFilterCaps()"))
213 *num_caps_ptr = num_caps;
222 vpp_get_filter_caps(GstVaapiFilter *filter, VAProcFilterType type,
223 guint cap_size, guint *num_caps_ptr)
227 GST_VAAPI_DISPLAY_LOCK(filter->display);
228 caps = vpp_get_filter_caps_unlocked(filter, type, cap_size, num_caps_ptr);
229 GST_VAAPI_DISPLAY_UNLOCK(filter->display);
234 /* ------------------------------------------------------------------------- */
235 /* --- VPP Operations --- */
236 /* ------------------------------------------------------------------------- */
239 #define DEFAULT_FORMAT GST_VIDEO_FORMAT_UNKNOWN
244 PROP_FORMAT = GST_VAAPI_FILTER_OP_FORMAT,
245 PROP_CROP = GST_VAAPI_FILTER_OP_CROP,
246 PROP_DENOISE = GST_VAAPI_FILTER_OP_DENOISE,
247 PROP_SHARPEN = GST_VAAPI_FILTER_OP_SHARPEN,
248 PROP_HUE = GST_VAAPI_FILTER_OP_HUE,
249 PROP_SATURATION = GST_VAAPI_FILTER_OP_SATURATION,
250 PROP_BRIGHTNESS = GST_VAAPI_FILTER_OP_BRIGHTNESS,
251 PROP_CONTRAST = GST_VAAPI_FILTER_OP_CONTRAST,
252 PROP_DEINTERLACING = GST_VAAPI_FILTER_OP_DEINTERLACING,
257 static GParamSpec *g_properties[N_PROPERTIES] = { NULL, };
258 static gsize g_properties_initialized = FALSE;
261 init_properties(void)
264 * GstVaapiFilter:format:
266 * The forced output pixel format, expressed as a #GstVideoFormat.
268 g_properties[PROP_FORMAT] =
269 g_param_spec_enum("format",
271 "The forced output pixel format",
272 GST_TYPE_VIDEO_FORMAT,
274 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
277 * GstVaapiFilter:crop-rect:
279 * The cropping rectangle, expressed as a #GstVaapiRectangle.
281 g_properties[PROP_CROP] =
282 g_param_spec_boxed("crop-rect",
283 "Cropping Rectangle",
284 "The cropping rectangle",
285 GST_VAAPI_TYPE_RECTANGLE,
286 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
289 * GstVaapiFilter:denoise:
291 * The level of noise reduction to apply.
293 g_properties[PROP_DENOISE] =
294 g_param_spec_float("denoise",
296 "The level of denoising to apply",
298 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
301 * GstVaapiFilter:sharpen:
303 * The level of sharpening to apply for positive values, or the
304 * level of blurring for negative values.
306 g_properties[PROP_SHARPEN] =
307 g_param_spec_float("sharpen",
309 "The level of sharpening/blurring to apply",
311 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
314 * GstVaapiFilter:hue:
316 * The color hue, expressed as a float value. Range is -180.0 to
317 * 180.0. Default value is 0.0 and represents no modification.
319 g_properties[PROP_HUE] =
320 g_param_spec_float("hue",
322 "The color hue value",
324 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
327 * GstVaapiFilter:saturation:
329 * The color saturation, expressed as a float value. Range is 0.0
330 * to 2.0. Default value is 1.0 and represents no modification.
332 g_properties[PROP_SATURATION] =
333 g_param_spec_float("saturation",
335 "The color saturation value",
337 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
340 * GstVaapiFilter:brightness:
342 * The color brightness, expressed as a float value. Range is -1.0
343 * to 1.0. Default value is 0.0 and represents no modification.
345 g_properties[PROP_BRIGHTNESS] =
346 g_param_spec_float("brightness",
348 "The color brightness value",
350 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
353 * GstVaapiFilter:contrast:
355 * The color contrast, expressed as a float value. Range is 0.0 to
356 * 2.0. Default value is 1.0 and represents no modification.
358 g_properties[PROP_CONTRAST] =
359 g_param_spec_float("contrast",
361 "The color contrast value",
363 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
366 * GstVaapiFilter:deinterlace-method:
368 * The deinterlacing algorithm to apply, expressed a an enum
369 * value. See #GstVaapiDeinterlaceMethod.
371 g_properties[PROP_DEINTERLACING] =
372 g_param_spec_enum("deinterlace",
373 "Deinterlacing Method",
374 "Deinterlacing method to apply",
375 GST_VAAPI_TYPE_DEINTERLACE_METHOD,
376 GST_VAAPI_DEINTERLACE_METHOD_NONE,
377 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
381 ensure_properties(void)
383 if (g_once_init_enter(&g_properties_initialized)) {
385 g_once_init_leave(&g_properties_initialized, TRUE);
390 op_data_free(GstVaapiFilterOpData *op_data)
392 g_free(op_data->va_caps);
393 g_slice_free(GstVaapiFilterOpData, op_data);
396 static inline gpointer
397 op_data_new(GstVaapiFilterOp op, GParamSpec *pspec)
399 GstVaapiFilterOpData *op_data;
401 op_data = g_slice_new0(GstVaapiFilterOpData);
406 op_data->pspec = pspec;
407 op_data->ref_count = 1;
408 op_data->va_buffer = VA_INVALID_ID;
411 case GST_VAAPI_FILTER_OP_FORMAT:
412 case GST_VAAPI_FILTER_OP_CROP:
413 op_data->va_type = VAProcFilterNone;
415 case GST_VAAPI_FILTER_OP_DENOISE:
416 op_data->va_type = VAProcFilterNoiseReduction;
417 op_data->va_cap_size = sizeof(VAProcFilterCap);
418 op_data->va_buffer_size = sizeof(VAProcFilterParameterBuffer);
420 case GST_VAAPI_FILTER_OP_SHARPEN:
421 op_data->va_type = VAProcFilterSharpening;
422 op_data->va_cap_size = sizeof(VAProcFilterCap);
423 op_data->va_buffer_size = sizeof(VAProcFilterParameterBuffer);
425 case GST_VAAPI_FILTER_OP_HUE:
426 op_data->va_subtype = VAProcColorBalanceHue;
427 goto op_colorbalance;
428 case GST_VAAPI_FILTER_OP_SATURATION:
429 op_data->va_subtype = VAProcColorBalanceSaturation;
430 goto op_colorbalance;
431 case GST_VAAPI_FILTER_OP_BRIGHTNESS:
432 op_data->va_subtype = VAProcColorBalanceBrightness;
433 goto op_colorbalance;
434 case GST_VAAPI_FILTER_OP_CONTRAST:
435 op_data->va_subtype = VAProcColorBalanceContrast;
437 op_data->va_type = VAProcFilterColorBalance;
438 op_data->va_cap_size = sizeof(VAProcFilterCapColorBalance);
439 op_data->va_buffer_size = sizeof(VAProcFilterParameterBufferColorBalance);
441 case GST_VAAPI_FILTER_OP_DEINTERLACING:
442 op_data->va_type = VAProcFilterDeinterlacing;
443 op_data->va_cap_size = sizeof(VAProcFilterCapDeinterlacing);
444 op_data->va_buffer_size = sizeof(VAProcFilterParameterBufferDeinterlacing);
447 g_assert(0 && "unsupported operation");
453 op_data_free(op_data);
457 static inline gpointer
458 op_data_ref(gpointer data)
460 GstVaapiFilterOpData * const op_data = data;
462 g_return_val_if_fail(op_data != NULL, NULL);
464 g_atomic_int_inc(&op_data->ref_count);
469 op_data_unref(gpointer data)
471 GstVaapiFilterOpData * const op_data = data;
473 g_return_if_fail(op_data != NULL);
474 g_return_if_fail(op_data->ref_count > 0);
476 if (g_atomic_int_dec_and_test(&op_data->ref_count))
477 op_data_free(op_data);
480 /* Ensure capability info is set up for the VA filter we are interested in */
482 op_data_ensure_caps(GstVaapiFilterOpData *op_data, gpointer filter_caps,
483 guint num_filter_caps)
485 guchar *filter_cap = filter_caps;
486 guint i, va_num_caps = num_filter_caps;
488 // Find the VA filter cap matching the op info sub-type
489 if (op_data->va_subtype) {
490 for (i = 0; i < num_filter_caps; i++) {
491 /* XXX: sub-type shall always be the first field */
492 if (op_data->va_subtype == *(guint *)filter_cap) {
496 filter_cap += op_data->va_cap_size;
498 if (i == num_filter_caps)
502 op_data->va_caps = g_memdup(filter_cap,
503 op_data->va_cap_size * va_num_caps);
504 if (!op_data->va_caps)
507 op_data->va_num_caps = va_num_caps;
511 /* Scale the filter value wrt. library spec and VA driver spec */
513 op_data_get_value_float(GstVaapiFilterOpData *op_data,
514 const VAProcFilterValueRange *range, gfloat value, gfloat *out_value_ptr)
516 GParamSpecFloat * const pspec = G_PARAM_SPEC_FLOAT(op_data->pspec);
519 g_return_val_if_fail(range != NULL, FALSE);
520 g_return_val_if_fail(out_value_ptr != NULL, FALSE);
522 if (value < pspec->minimum || value > pspec->maximum)
525 // Scale wrt. the medium ("default") value
526 out_value = range->default_value;
527 if (value > pspec->default_value)
528 out_value += ((value - pspec->default_value) /
529 (pspec->maximum - pspec->default_value) *
530 (range->max_value - range->default_value));
531 else if (value < pspec->default_value)
532 out_value -= ((pspec->default_value - value) /
533 (pspec->default_value - pspec->minimum) *
534 (range->default_value - range->min_value));
536 *out_value_ptr = out_value;
540 /* Get default list of operations supported by the library */
542 get_operations_default(void)
547 ops = g_ptr_array_new_full(N_PROPERTIES, op_data_unref);
553 for (i = 0; i < N_PROPERTIES; i++) {
554 GParamSpec * const pspec = g_properties[i];
558 GstVaapiFilterOpData * const op_data = op_data_new(i, pspec);
561 g_ptr_array_add(ops, op_data);
566 g_ptr_array_unref(ops);
570 /* Get the ordered list of operations, based on VA/VPP queries */
572 get_operations_ordered(GstVaapiFilter *filter, GPtrArray *default_ops)
575 VAProcFilterType *filters;
576 gpointer filter_caps = NULL;
577 guint i, j, num_filters, num_filter_caps = 0;
579 ops = g_ptr_array_new_full(default_ops->len, op_data_unref);
583 filters = vpp_get_filters(filter, &num_filters);
587 // Append virtual ops first, i.e. those without an associated VA filter
588 for (i = 0; i < default_ops->len; i++) {
589 GstVaapiFilterOpData * const op_data =
590 g_ptr_array_index(default_ops, i);
591 if (op_data->va_type == VAProcFilterNone)
592 g_ptr_array_add(ops, op_data_ref(op_data));
595 // Append ops, while preserving the VA filters ordering
596 for (i = 0; i < num_filters; i++) {
597 const VAProcFilterType va_type = filters[i];
598 if (va_type == VAProcFilterNone)
601 for (j = 0; j < default_ops->len; j++) {
602 GstVaapiFilterOpData * const op_data =
603 g_ptr_array_index(default_ops, j);
604 if (op_data->va_type != va_type)
608 filter_caps = vpp_get_filter_caps(filter, va_type,
609 op_data->va_cap_size, &num_filter_caps);
613 if (!op_data_ensure_caps(op_data, filter_caps, num_filter_caps))
615 g_ptr_array_add(ops, op_data_ref(op_data));
621 if (filter->operations)
622 g_ptr_array_unref(filter->operations);
623 filter->operations = g_ptr_array_ref(ops);
626 g_ptr_array_unref(default_ops);
632 g_ptr_array_unref(ops);
633 g_ptr_array_unref(default_ops);
638 /* Determine the set of supported VPP operations by the specific
639 filter, or known to this library if filter is NULL */
641 get_operations(GstVaapiFilter *filter)
646 if (filter && filter->operations)
647 return g_ptr_array_ref(filter->operations);
649 ops = get_operations_default();
652 return filter ? get_operations_ordered(filter, ops) : ops;
657 /* Ensure the set of supported VPP operations is cached into the
658 GstVaapiFilter::operations member */
659 static inline gboolean
660 ensure_operations(GstVaapiFilter *filter)
667 if (filter->operations)
670 ops = get_operations(filter);
674 g_ptr_array_unref(ops);
678 /* Find whether the VPP operation is supported or not */
679 GstVaapiFilterOpData *
680 find_operation(GstVaapiFilter *filter, GstVaapiFilterOp op)
684 if (!ensure_operations(filter))
687 for (i = 0; i < filter->operations->len; i++) {
688 GstVaapiFilterOpData * const op_data =
689 g_ptr_array_index(filter->operations, i);
690 if (op_data->op == op)
696 /* Ensure the operation's VA buffer is allocated */
698 static inline gboolean
699 op_ensure_buffer(GstVaapiFilter *filter, GstVaapiFilterOpData *op_data)
701 if (G_LIKELY(op_data->va_buffer != VA_INVALID_ID))
703 return vaapi_create_buffer(filter->va_display, filter->va_context,
704 VAProcFilterParameterBufferType, op_data->va_buffer_size, NULL,
705 &op_data->va_buffer, NULL);
709 /* Update a generic filter (float value) */
712 op_set_generic_unlocked(GstVaapiFilter *filter, GstVaapiFilterOpData *op_data,
715 VAProcFilterParameterBuffer *buf;
716 VAProcFilterCap *filter_cap;
719 if (!op_data || !op_ensure_buffer(filter, op_data))
722 op_data->is_enabled =
723 (value != G_PARAM_SPEC_FLOAT(op_data->pspec)->default_value);
724 if (!op_data->is_enabled)
727 filter_cap = op_data->va_caps;
728 if (!op_data_get_value_float(op_data, &filter_cap->range, value, &va_value))
731 buf = vaapi_map_buffer(filter->va_display, op_data->va_buffer);
735 buf->type = op_data->va_type;
736 buf->value = va_value;
737 vaapi_unmap_buffer(filter->va_display, op_data->va_buffer, NULL);
742 static inline gboolean
743 op_set_generic(GstVaapiFilter *filter, GstVaapiFilterOpData *op_data,
746 gboolean success = FALSE;
749 GST_VAAPI_DISPLAY_LOCK(filter->display);
750 success = op_set_generic_unlocked(filter, op_data, value);
751 GST_VAAPI_DISPLAY_UNLOCK(filter->display);
756 /* Update the color balance filter */
759 op_set_color_balance_unlocked(GstVaapiFilter *filter,
760 GstVaapiFilterOpData *op_data, gfloat value)
762 VAProcFilterParameterBufferColorBalance *buf;
763 VAProcFilterCapColorBalance *filter_cap;
766 if (!op_data || !op_ensure_buffer(filter, op_data))
769 op_data->is_enabled =
770 (value != G_PARAM_SPEC_FLOAT(op_data->pspec)->default_value);
771 if (!op_data->is_enabled)
774 filter_cap = op_data->va_caps;
775 if (!op_data_get_value_float(op_data, &filter_cap->range, value, &va_value))
778 buf = vaapi_map_buffer(filter->va_display, op_data->va_buffer);
782 buf->type = op_data->va_type;
783 buf->attrib = op_data->va_subtype;
784 buf->value = va_value;
785 vaapi_unmap_buffer(filter->va_display, op_data->va_buffer, NULL);
790 static inline gboolean
791 op_set_color_balance(GstVaapiFilter *filter, GstVaapiFilterOpData *op_data,
794 gboolean success = FALSE;
797 GST_VAAPI_DISPLAY_LOCK(filter->display);
798 success = op_set_color_balance_unlocked(filter, op_data, value);
799 GST_VAAPI_DISPLAY_UNLOCK(filter->display);
804 /* Update deinterlace filter */
807 op_set_deinterlace_unlocked(GstVaapiFilter *filter,
808 GstVaapiFilterOpData *op_data, GstVaapiDeinterlaceMethod method,
811 VAProcFilterParameterBufferDeinterlacing *buf;
812 const VAProcFilterCapDeinterlacing *filter_caps;
813 VAProcDeinterlacingType algorithm;
816 if (!op_data || !op_ensure_buffer(filter, op_data))
819 op_data->is_enabled = (method != GST_VAAPI_DEINTERLACE_METHOD_NONE);
820 if (!op_data->is_enabled)
823 algorithm = from_GstVaapiDeinterlaceMethod(method);
824 for (i = 0, filter_caps = op_data->va_caps; i < op_data->va_num_caps; i++) {
825 if (filter_caps[i].type == algorithm)
828 if (i == op_data->va_num_caps)
831 buf = vaapi_map_buffer(filter->va_display, op_data->va_buffer);
835 buf->type = op_data->va_type;
836 buf->algorithm = algorithm;
837 buf->flags = from_GstVaapiDeinterlaceFlags(flags);
838 vaapi_unmap_buffer(filter->va_display, op_data->va_buffer, NULL);
843 static inline gboolean
844 op_set_deinterlace(GstVaapiFilter *filter, GstVaapiFilterOpData *op_data,
845 GstVaapiDeinterlaceMethod method, guint flags)
847 gboolean success = FALSE;
850 GST_VAAPI_DISPLAY_LOCK(filter->display);
851 success = op_set_deinterlace_unlocked(filter, op_data, method, flags);
852 GST_VAAPI_DISPLAY_UNLOCK(filter->display);
858 deint_refs_set(GArray *refs, GstVaapiSurface **surfaces, guint num_surfaces)
862 if (num_surfaces > 0 && !surfaces)
865 for (i = 0; i < num_surfaces; i++)
866 g_array_append_val(refs, GST_VAAPI_OBJECT_ID(surfaces[i]));
871 deint_refs_clear(GArray *refs)
874 g_array_remove_range(refs, 0, refs->len);
878 deint_refs_clear_all(GstVaapiFilter *filter)
880 deint_refs_clear(filter->forward_references);
881 deint_refs_clear(filter->backward_references);
884 /* ------------------------------------------------------------------------- */
885 /* --- Surface Formats --- */
886 /* ------------------------------------------------------------------------- */
889 ensure_formats(GstVaapiFilter *filter)
891 #if VA_CHECK_VERSION(0,34,0)
892 VASurfaceAttrib *surface_attribs = NULL;
893 guint i, num_surface_attribs = 0;
896 if (G_LIKELY(filter->formats))
899 GST_VAAPI_DISPLAY_LOCK(filter->display);
900 va_status = vaQuerySurfaceAttributes(filter->va_display, filter->va_config,
901 NULL, &num_surface_attribs);
902 GST_VAAPI_DISPLAY_UNLOCK(filter->display);
903 if (!vaapi_check_status(va_status, "vaQuerySurfaceAttributes()"))
906 surface_attribs = g_malloc(num_surface_attribs * sizeof(*surface_attribs));
907 if (!surface_attribs)
910 GST_VAAPI_DISPLAY_LOCK(filter->display);
911 va_status = vaQuerySurfaceAttributes(filter->va_display, filter->va_config,
912 surface_attribs, &num_surface_attribs);
913 GST_VAAPI_DISPLAY_UNLOCK(filter->display);
914 if (!vaapi_check_status(va_status, "vaQuerySurfaceAttributes()"))
917 filter->formats = g_array_sized_new(FALSE, FALSE, sizeof(GstVideoFormat),
918 num_surface_attribs);
919 if (!filter->formats)
922 for (i = 0; i < num_surface_attribs; i++) {
923 const VASurfaceAttrib * const surface_attrib = &surface_attribs[i];
924 GstVideoFormat format;
926 if (surface_attrib->type != VASurfaceAttribPixelFormat)
928 if (!(surface_attrib->flags & VA_SURFACE_ATTRIB_SETTABLE))
931 format = gst_vaapi_video_format_from_va_fourcc(
932 surface_attrib->value.value.i);
933 if (format == GST_VIDEO_FORMAT_UNKNOWN)
935 g_array_append_val(filter->formats, format);
938 g_free(surface_attribs);
942 g_free(surface_attribs);
947 static inline gboolean
948 is_special_format(GstVideoFormat format)
950 return format == GST_VIDEO_FORMAT_UNKNOWN ||
951 format == GST_VIDEO_FORMAT_ENCODED;
955 find_format(GstVaapiFilter *filter, GstVideoFormat format)
959 if (is_special_format(format) || !filter->formats)
962 for (i = 0; i < filter->formats->len; i++) {
963 if (g_array_index(filter->formats, GstVideoFormat, i) == format)
969 /* ------------------------------------------------------------------------- */
970 /* --- Interface --- */
971 /* ------------------------------------------------------------------------- */
975 gst_vaapi_filter_init(GstVaapiFilter *filter, GstVaapiDisplay *display)
979 filter->display = gst_vaapi_display_ref(display);
980 filter->va_display = GST_VAAPI_DISPLAY_VADISPLAY(display);
981 filter->va_config = VA_INVALID_ID;
982 filter->va_context = VA_INVALID_ID;
983 filter->format = DEFAULT_FORMAT;
985 filter->forward_references =
986 g_array_sized_new(FALSE, FALSE, sizeof(VASurfaceID), 4);
987 if (!filter->forward_references)
990 filter->backward_references =
991 g_array_sized_new(FALSE, FALSE, sizeof(VASurfaceID), 4);
992 if (!filter->backward_references)
995 if (!GST_VAAPI_DISPLAY_HAS_VPP(display))
998 va_status = vaCreateConfig(filter->va_display, VAProfileNone,
999 VAEntrypointVideoProc, NULL, 0, &filter->va_config);
1000 if (!vaapi_check_status(va_status, "vaCreateConfig() [VPP]"))
1003 va_status = vaCreateContext(filter->va_display, filter->va_config, 0, 0, 0,
1004 NULL, 0, &filter->va_context);
1005 if (!vaapi_check_status(va_status, "vaCreateContext() [VPP]"))
1011 gst_vaapi_filter_finalize(GstVaapiFilter *filter)
1015 GST_VAAPI_DISPLAY_LOCK(filter->display);
1016 if (filter->operations) {
1017 for (i = 0; i < filter->operations->len; i++) {
1018 GstVaapiFilterOpData * const op_data =
1019 g_ptr_array_index(filter->operations, i);
1020 vaapi_destroy_buffer(filter->va_display, &op_data->va_buffer);
1022 g_ptr_array_unref(filter->operations);
1023 filter->operations = NULL;
1026 if (filter->va_context != VA_INVALID_ID) {
1027 vaDestroyContext(filter->va_display, filter->va_context);
1028 filter->va_context = VA_INVALID_ID;
1031 if (filter->va_config != VA_INVALID_ID) {
1032 vaDestroyConfig(filter->va_display, filter->va_config);
1033 filter->va_config = VA_INVALID_ID;
1035 GST_VAAPI_DISPLAY_UNLOCK(filter->display);
1036 gst_vaapi_display_replace(&filter->display, NULL);
1038 if (filter->forward_references) {
1039 g_array_unref(filter->forward_references);
1040 filter->forward_references = NULL;
1043 if (filter->backward_references) {
1044 g_array_unref(filter->backward_references);
1045 filter->backward_references = NULL;
1048 if (filter->formats) {
1049 g_array_unref(filter->formats);
1050 filter->formats = NULL;
1054 static inline const GstVaapiMiniObjectClass *
1055 gst_vaapi_filter_class(void)
1057 static const GstVaapiMiniObjectClass GstVaapiFilterClass = {
1058 sizeof(GstVaapiFilter),
1059 (GDestroyNotify)gst_vaapi_filter_finalize
1061 return &GstVaapiFilterClass;
1066 * gst_vaapi_filter_new:
1067 * @display: a #GstVaapiDisplay
1069 * Creates a new #GstVaapiFilter set up to operate in "identity"
1070 * mode. This means that no other operation than scaling is performed.
1072 * Return value: the newly created #GstVaapiFilter object
1075 gst_vaapi_filter_new(GstVaapiDisplay *display)
1078 GstVaapiFilter *filter;
1080 filter = (GstVaapiFilter *)
1081 gst_vaapi_mini_object_new0(gst_vaapi_filter_class());
1085 if (!gst_vaapi_filter_init(filter, display))
1090 gst_vaapi_filter_unref(filter);
1093 GST_WARNING("video processing is not supported, "
1094 "please consider an upgrade to VA-API >= 0.34");
1100 * gst_vaapi_filter_ref:
1101 * @filter: a #GstVaapiFilter
1103 * Atomically increases the reference count of the given @filter by one.
1105 * Returns: The same @filter argument
1108 gst_vaapi_filter_ref(GstVaapiFilter *filter)
1110 g_return_val_if_fail(filter != NULL, NULL);
1112 return GST_VAAPI_FILTER(gst_vaapi_mini_object_ref(
1113 GST_VAAPI_MINI_OBJECT(filter)));
1117 * gst_vaapi_filter_unref:
1118 * @filter: a #GstVaapiFilter
1120 * Atomically decreases the reference count of the @filter by one. If
1121 * the reference count reaches zero, the filter will be free'd.
1124 gst_vaapi_filter_unref(GstVaapiFilter *filter)
1126 g_return_if_fail(filter != NULL);
1128 gst_vaapi_mini_object_unref(GST_VAAPI_MINI_OBJECT(filter));
1132 * gst_vaapi_filter_replace:
1133 * @old_filter_ptr: a pointer to a #GstVaapiFilter
1134 * @new_filter: a #GstVaapiFilter
1136 * Atomically replaces the filter held in @old_filter_ptr with
1137 * @new_filter. This means that @old_filter_ptr shall reference a
1138 * valid filter. However, @new_filter can be NULL.
1141 gst_vaapi_filter_replace(GstVaapiFilter **old_filter_ptr,
1142 GstVaapiFilter *new_filter)
1144 g_return_if_fail(old_filter_ptr != NULL);
1146 gst_vaapi_mini_object_replace((GstVaapiMiniObject **)old_filter_ptr,
1147 GST_VAAPI_MINI_OBJECT(new_filter));
1151 * gst_vaapi_filter_get_operations:
1152 * @filter: a #GstVaapiFilter, or %NULL
1154 * Determines the set of supported operations for video processing.
1155 * The caller owns an extra reference to the resulting array of
1156 * #GstVaapiFilterOpInfo elements, so it shall be released with
1157 * g_ptr_array_unref() after usage.
1159 * If @filter is %NULL, then this function returns the video
1160 * processing operations supported by this library.
1162 * Return value: the set of supported operations, or %NULL if an error
1166 gst_vaapi_filter_get_operations(GstVaapiFilter *filter)
1168 return get_operations(filter);
1172 * gst_vaapi_filter_has_operation:
1173 * @filter: a #GstVaapiFilter
1174 * @op: a #GstVaapiFilterOp
1176 * Determines whether the underlying VA driver advertises support for
1177 * the supplied operation @op.
1179 * Return value: %TRUE if the specified operation may be supported by
1180 * the underlying hardware, %FALSE otherwise
1183 gst_vaapi_filter_has_operation(GstVaapiFilter *filter, GstVaapiFilterOp op)
1185 g_return_val_if_fail(filter != NULL, FALSE);
1187 return find_operation(filter, op) != NULL;
1191 * gst_vaapi_filter_use_operation:
1192 * @filter: a #GstVaapiFilter
1193 * @op: a #GstVaapiFilterOp
1195 * Determines whether the supplied operation @op was already enabled
1196 * through a prior call to gst_vaapi_filter_set_operation() or any
1197 * other operation-specific function.
1199 * Note: should an operation be set to its default value, this means
1200 * that it is actually not enabled.
1202 * Return value: %TRUE if the specified operation was already enabled,
1206 gst_vaapi_filter_use_operation(GstVaapiFilter *filter, GstVaapiFilterOp op)
1208 GstVaapiFilterOpData *op_data;
1210 g_return_val_if_fail(filter != NULL, FALSE);
1212 op_data = find_operation(filter, op);
1215 return op_data->is_enabled;
1219 * gst_vaapi_filter_set_operation:
1220 * @filter: a #GstVaapiFilter
1221 * @op: a #GstVaapiFilterOp
1222 * @value: the @op settings
1224 * Enable the specified operation @op to be performed during video
1225 * processing, i.e. in gst_vaapi_filter_process(). The @value argument
1226 * specifies the operation settings. e.g. deinterlacing method for
1227 * deinterlacing, denoising level for noise reduction, etc.
1229 * If @value is %NULL, then this function resets the operation
1230 * settings to their default values.
1232 * Return value: %TRUE if the specified operation may be supported,
1236 gst_vaapi_filter_set_operation(GstVaapiFilter *filter, GstVaapiFilterOp op,
1237 const GValue *value)
1240 GstVaapiFilterOpData *op_data;
1242 g_return_val_if_fail(filter != NULL, FALSE);
1244 op_data = find_operation(filter, op);
1248 if (value && !G_VALUE_HOLDS(value, G_PARAM_SPEC_VALUE_TYPE(op_data->pspec)))
1252 case GST_VAAPI_FILTER_OP_FORMAT:
1253 return gst_vaapi_filter_set_format(filter, value ?
1254 g_value_get_enum(value) : DEFAULT_FORMAT);
1255 case GST_VAAPI_FILTER_OP_CROP:
1256 return gst_vaapi_filter_set_cropping_rectangle(filter, value ?
1257 g_value_get_boxed(value) : NULL);
1258 case GST_VAAPI_FILTER_OP_DENOISE:
1259 case GST_VAAPI_FILTER_OP_SHARPEN:
1260 return op_set_generic(filter, op_data,
1261 (value ? g_value_get_float(value) :
1262 G_PARAM_SPEC_FLOAT(op_data->pspec)->default_value));
1263 case GST_VAAPI_FILTER_OP_HUE:
1264 case GST_VAAPI_FILTER_OP_SATURATION:
1265 case GST_VAAPI_FILTER_OP_BRIGHTNESS:
1266 case GST_VAAPI_FILTER_OP_CONTRAST:
1267 return op_set_color_balance(filter, op_data,
1268 (value ? g_value_get_float(value) :
1269 G_PARAM_SPEC_FLOAT(op_data->pspec)->default_value));
1270 case GST_VAAPI_FILTER_OP_DEINTERLACING:
1271 return op_set_deinterlace(filter, op_data,
1272 (value ? g_value_get_enum(value) :
1273 G_PARAM_SPEC_ENUM(op_data->pspec)->default_value), 0);
1283 * gst_vaapi_filter_process:
1284 * @filter: a #GstVaapiFilter
1285 * @src_surface: the source @GstVaapiSurface
1286 * @dst_surface: the destination @GstVaapiSurface
1287 * @flags: #GstVaapiSurfaceRenderFlags that apply to @src_surface
1289 * Applies the operations currently defined in the @filter to
1290 * @src_surface and return the output in @dst_surface. The order of
1291 * operations is determined in a way that suits best the underlying
1292 * hardware. i.e. the only guarantee held is the generated outcome,
1293 * not any specific order of operations.
1295 * Return value: a #GstVaapiFilterStatus
1297 static GstVaapiFilterStatus
1298 gst_vaapi_filter_process_unlocked(GstVaapiFilter *filter,
1299 GstVaapiSurface *src_surface, GstVaapiSurface *dst_surface, guint flags)
1302 VAProcPipelineParameterBuffer *pipeline_param = NULL;
1303 VABufferID pipeline_param_buf_id = VA_INVALID_ID;
1304 VABufferID filters[N_PROPERTIES];
1305 VAProcPipelineCaps pipeline_caps;
1306 guint i, num_filters = 0;
1308 VARectangle src_rect, dst_rect;
1310 if (!ensure_operations(filter))
1311 return GST_VAAPI_FILTER_STATUS_ERROR_ALLOCATION_FAILED;
1313 /* Build surface region (source) */
1314 if (filter->use_crop_rect) {
1315 const GstVaapiRectangle * const crop_rect = &filter->crop_rect;
1317 if ((crop_rect->x + crop_rect->width >
1318 GST_VAAPI_SURFACE_WIDTH(src_surface)) ||
1319 (crop_rect->y + crop_rect->height >
1320 GST_VAAPI_SURFACE_HEIGHT(src_surface)))
1323 src_rect.x = crop_rect->x;
1324 src_rect.y = crop_rect->y;
1325 src_rect.width = crop_rect->width;
1326 src_rect.height = crop_rect->height;
1331 src_rect.width = GST_VAAPI_SURFACE_WIDTH(src_surface);
1332 src_rect.height = GST_VAAPI_SURFACE_HEIGHT(src_surface);
1335 /* Build output region (target) */
1336 if (filter->use_target_rect) {
1337 const GstVaapiRectangle * const target_rect = &filter->target_rect;
1339 if ((target_rect->x + target_rect->width >
1340 GST_VAAPI_SURFACE_WIDTH(dst_surface)) ||
1341 (target_rect->y + target_rect->height >
1342 GST_VAAPI_SURFACE_HEIGHT(dst_surface)))
1345 dst_rect.x = target_rect->x;
1346 dst_rect.y = target_rect->y;
1347 dst_rect.width = target_rect->width;
1348 dst_rect.height = target_rect->height;
1353 dst_rect.width = GST_VAAPI_SURFACE_WIDTH(dst_surface);
1354 dst_rect.height = GST_VAAPI_SURFACE_HEIGHT(dst_surface);
1357 for (i = 0, num_filters = 0; i < filter->operations->len; i++) {
1358 GstVaapiFilterOpData * const op_data =
1359 g_ptr_array_index(filter->operations, i);
1360 if (!op_data->is_enabled)
1362 if (op_data->va_buffer == VA_INVALID_ID) {
1363 GST_ERROR("invalid VA buffer for operation %s",
1364 g_param_spec_get_name(op_data->pspec));
1367 filters[num_filters++] = op_data->va_buffer;
1370 /* Validate pipeline caps */
1371 va_status = vaQueryVideoProcPipelineCaps(filter->va_display,
1372 filter->va_context, filters, num_filters, &pipeline_caps);
1373 if (!vaapi_check_status(va_status, "vaQueryVideoProcPipelineCaps()"))
1376 if (!vaapi_create_buffer(filter->va_display, filter->va_context,
1377 VAProcPipelineParameterBufferType, sizeof(*pipeline_param),
1378 NULL, &pipeline_param_buf_id, (gpointer *)&pipeline_param))
1381 memset(pipeline_param, 0, sizeof(*pipeline_param));
1382 pipeline_param->surface = GST_VAAPI_OBJECT_ID(src_surface);
1383 pipeline_param->surface_region = &src_rect;
1384 pipeline_param->surface_color_standard = VAProcColorStandardNone;
1385 pipeline_param->output_region = &dst_rect;
1386 pipeline_param->output_color_standard = VAProcColorStandardNone;
1387 pipeline_param->output_background_color = 0xff000000;
1388 pipeline_param->filter_flags = from_GstVaapiSurfaceRenderFlags(flags);
1389 pipeline_param->filters = filters;
1390 pipeline_param->num_filters = num_filters;
1392 // Reference frames for advanced deinterlacing
1393 if (filter->forward_references->len > 0) {
1394 pipeline_param->forward_references = (VASurfaceID *)
1395 filter->forward_references->data;
1396 pipeline_param->num_forward_references =
1397 MIN(filter->forward_references->len,
1398 pipeline_caps.num_forward_references);
1401 pipeline_param->forward_references = NULL;
1402 pipeline_param->num_forward_references = 0;
1405 if (filter->backward_references->len > 0) {
1406 pipeline_param->backward_references = (VASurfaceID *)
1407 filter->backward_references->data;
1408 pipeline_param->num_backward_references =
1409 MIN(filter->backward_references->len,
1410 pipeline_caps.num_backward_references);
1413 pipeline_param->backward_references = NULL;
1414 pipeline_param->num_backward_references = 0;
1417 vaapi_unmap_buffer(filter->va_display, pipeline_param_buf_id, NULL);
1419 va_status = vaBeginPicture(filter->va_display, filter->va_context,
1420 GST_VAAPI_OBJECT_ID(dst_surface));
1421 if (!vaapi_check_status(va_status, "vaBeginPicture()"))
1424 va_status = vaRenderPicture(filter->va_display, filter->va_context,
1425 &pipeline_param_buf_id, 1);
1426 if (!vaapi_check_status(va_status, "vaRenderPicture()"))
1429 va_status = vaEndPicture(filter->va_display, filter->va_context);
1430 if (!vaapi_check_status(va_status, "vaEndPicture()"))
1433 deint_refs_clear_all(filter);
1434 vaapi_destroy_buffer(filter->va_display, &pipeline_param_buf_id);
1435 return GST_VAAPI_FILTER_STATUS_SUCCESS;
1438 deint_refs_clear_all(filter);
1439 vaapi_destroy_buffer(filter->va_display, &pipeline_param_buf_id);
1440 return GST_VAAPI_FILTER_STATUS_ERROR_OPERATION_FAILED;
1442 return GST_VAAPI_FILTER_STATUS_ERROR_UNSUPPORTED_OPERATION;
1445 GstVaapiFilterStatus
1446 gst_vaapi_filter_process(GstVaapiFilter *filter, GstVaapiSurface *src_surface,
1447 GstVaapiSurface *dst_surface, guint flags)
1449 GstVaapiFilterStatus status;
1451 g_return_val_if_fail(filter != NULL,
1452 GST_VAAPI_FILTER_STATUS_ERROR_INVALID_PARAMETER);
1453 g_return_val_if_fail(src_surface != NULL,
1454 GST_VAAPI_FILTER_STATUS_ERROR_INVALID_PARAMETER);
1455 g_return_val_if_fail(dst_surface != NULL,
1456 GST_VAAPI_FILTER_STATUS_ERROR_INVALID_PARAMETER);
1458 GST_VAAPI_DISPLAY_LOCK(filter->display);
1459 status = gst_vaapi_filter_process_unlocked(filter,
1460 src_surface, dst_surface, flags);
1461 GST_VAAPI_DISPLAY_UNLOCK(filter->display);
1466 * gst_vaapi_filter_get_formats:
1467 * @filter: a #GstVaapiFilter
1469 * Determines the set of supported source or target formats for video
1470 * processing. The caller owns an extra reference to the resulting
1471 * array of #GstVideoFormat elements, so it shall be released with
1472 * g_array_unref() after usage.
1474 * Return value: the set of supported target formats for video processing.
1477 gst_vaapi_filter_get_formats(GstVaapiFilter *filter)
1479 g_return_val_if_fail(filter != NULL, NULL);
1481 if (!ensure_formats(filter))
1483 return g_array_ref(filter->formats);
1487 * gst_vaapi_filter_set_format:
1488 * @filter: a #GstVaapiFilter
1489 * @format: the target surface format
1491 * Sets the desired pixel format of the resulting video processing
1494 * If @format is #GST_VIDEO_FORMAT_UNKNOWN, the filter will assume iso
1495 * format conversion, i.e. no color conversion at all and the target
1496 * surface format shall match the source surface format.
1498 * If @format is #GST_VIDEO_FORMAT_ENCODED, the filter will use the pixel
1499 * format of the target surface passed to gst_vaapi_filter_process().
1501 * Return value: %TRUE if the color conversion to the specified @format
1502 * may be supported, %FALSE otherwise.
1505 gst_vaapi_filter_set_format(GstVaapiFilter *filter, GstVideoFormat format)
1507 g_return_val_if_fail(filter != NULL, FALSE);
1509 if (!ensure_formats(filter))
1512 if (!is_special_format(format) && !find_format(filter, format))
1515 filter->format = format;
1520 * gst_vaapi_filter_set_cropping_rectangle:
1521 * @filter: a #GstVaapiFilter
1522 * @rect: the cropping region
1524 * Sets the source surface cropping rectangle to use during the video
1525 * processing. If @rect is %NULL, the whole source surface will be used.
1527 * Return value: %TRUE if the operation is supported, %FALSE otherwise.
1530 gst_vaapi_filter_set_cropping_rectangle(GstVaapiFilter *filter,
1531 const GstVaapiRectangle *rect)
1533 g_return_val_if_fail(filter != NULL, FALSE);
1535 filter->use_crop_rect = rect != NULL;
1536 if (filter->use_crop_rect)
1537 filter->crop_rect = *rect;
1542 * gst_vaapi_filter_set_target_rectangle:
1543 * @filter: a #GstVaapiFilter
1544 * @rect: the target render region
1546 * Sets the region within the target surface where the source surface
1547 * would be rendered. i.e. where the hardware accelerator would emit
1548 * the outcome of video processing. If @rect is %NULL, the whole
1549 * source surface will be used.
1551 * Return value: %TRUE if the operation is supported, %FALSE otherwise.
1554 gst_vaapi_filter_set_target_rectangle(GstVaapiFilter *filter,
1555 const GstVaapiRectangle *rect)
1557 g_return_val_if_fail(filter != NULL, FALSE);
1559 filter->use_target_rect = rect != NULL;
1560 if (filter->use_target_rect)
1561 filter->target_rect = *rect;
1566 * gst_vaapi_filter_set_denoising_level:
1567 * @filter: a #GstVaapiFilter
1568 * @level: the level of noise reduction to apply
1570 * Sets the noise reduction level to apply. If @level is 0.0f, this
1571 * corresponds to disabling the noise reduction algorithm.
1573 * Return value: %TRUE if the operation is supported, %FALSE otherwise.
1576 gst_vaapi_filter_set_denoising_level(GstVaapiFilter *filter, gfloat level)
1578 g_return_val_if_fail(filter != NULL, FALSE);
1580 return op_set_generic(filter,
1581 find_operation(filter, GST_VAAPI_FILTER_OP_DENOISE), level);
1585 * gst_vaapi_filter_set_sharpening_level:
1586 * @filter: a #GstVaapiFilter
1587 * @level: the sharpening factor
1589 * Enables noise reduction with the specified factor.
1591 * Return value: %TRUE if the operation is supported, %FALSE otherwise.
1594 gst_vaapi_filter_set_sharpening_level(GstVaapiFilter *filter, gfloat level)
1596 g_return_val_if_fail(filter != NULL, FALSE);
1598 return op_set_generic(filter,
1599 find_operation(filter, GST_VAAPI_FILTER_OP_SHARPEN), level);
1603 * gst_vaapi_filter_set_hue:
1604 * @filter: a #GstVaapiFilter
1605 * @value: the color hue value
1607 * Enables color hue adjustment to the specified value.
1609 * Return value: %TRUE if the operation is supported, %FALSE otherwise.
1612 gst_vaapi_filter_set_hue(GstVaapiFilter *filter, gfloat value)
1614 g_return_val_if_fail(filter != NULL, FALSE);
1616 return op_set_color_balance(filter,
1617 find_operation(filter, GST_VAAPI_FILTER_OP_HUE), value);
1621 * gst_vaapi_filter_set_saturation:
1622 * @filter: a #GstVaapiFilter
1623 * @value: the color saturation value
1625 * Enables color saturation adjustment to the specified value.
1627 * Return value: %TRUE if the operation is supported, %FALSE otherwise.
1630 gst_vaapi_filter_set_saturation(GstVaapiFilter *filter, gfloat value)
1632 g_return_val_if_fail(filter != NULL, FALSE);
1634 return op_set_color_balance(filter,
1635 find_operation(filter, GST_VAAPI_FILTER_OP_SATURATION), value);
1639 * gst_vaapi_filter_set_brightness:
1640 * @filter: a #GstVaapiFilter
1641 * @value: the color brightness value
1643 * Enables color brightness adjustment to the specified value.
1645 * Return value: %TRUE if the operation is supported, %FALSE otherwise.
1648 gst_vaapi_filter_set_brightness(GstVaapiFilter *filter, gfloat value)
1650 g_return_val_if_fail(filter != NULL, FALSE);
1652 return op_set_color_balance(filter,
1653 find_operation(filter, GST_VAAPI_FILTER_OP_BRIGHTNESS), value);
1657 * gst_vaapi_filter_set_contrast:
1658 * @filter: a #GstVaapiFilter
1659 * @value: the color contrast value
1661 * Enables color contrast adjustment to the specified value.
1663 * Return value: %TRUE if the operation is supported, %FALSE otherwise.
1666 gst_vaapi_filter_set_contrast(GstVaapiFilter *filter, gfloat value)
1668 g_return_val_if_fail(filter != NULL, FALSE);
1670 return op_set_color_balance(filter,
1671 find_operation(filter, GST_VAAPI_FILTER_OP_CONTRAST), value);
1675 * gst_vaapi_filter_set_deinterlacing:
1676 * @filter: a #GstVaapiFilter
1677 * @method: the deinterlacing algorithm (see #GstVaapiDeinterlaceMethod)
1678 * @flags: the additional flags
1680 * Applies deinterlacing to the video processing pipeline. If @method
1681 * is not @GST_VAAPI_DEINTERLACE_METHOD_NONE, then @flags could
1682 * represent the initial picture structure of the source frame.
1684 * Return value: %TRUE if the operation is supported, %FALSE otherwise.
1687 gst_vaapi_filter_set_deinterlacing(GstVaapiFilter *filter,
1688 GstVaapiDeinterlaceMethod method, guint flags)
1690 g_return_val_if_fail(filter != NULL, FALSE);
1692 return op_set_deinterlace(filter,
1693 find_operation(filter, GST_VAAPI_FILTER_OP_DEINTERLACING), method,
1698 * gst_vaapi_filter_set_deinterlacing_references:
1699 * @filter: a #GstVaapiFilter
1700 * @forward_references: the set of #GstVaapiSurface objects used as
1701 * forward references
1702 * @num_forward_references: the number of elements in the
1703 * @forward_references array
1704 * @backward_references: the set of #GstVaapiSurface objects used as
1705 * backward references
1706 * @num_backward_references: the number of elements in the
1707 * @backward_references array
1709 * Specifies the list of surfaces used for forward or backward reference in
1710 * advanced deinterlacing mode. The caller is responsible for maintaining
1711 * the associated surfaces live until gst_vaapi_filter_process() completes.
1712 * e.g. by holding an extra reference to the associated #GstVaapiSurfaceProxy.
1714 * Temporal ordering is maintained as follows: the shorter index in
1715 * either array is, the closest the matching surface is relatively to
1716 * the current source surface to process. e.g. surface in
1717 * @forward_references array index 0 represents the immediately
1718 * preceding surface in display order, surface at index 1 is the one
1719 * preceding surface at index 0, etc.
1721 * The video processing filter will only use the recommended number of
1722 * surfaces for backward and forward references.
1724 * Note: the supplied lists of reference surfaces are not sticky. This
1725 * means that they are only valid for the next gst_vaapi_filter_process()
1726 * call, and thus needs to be submitted again for subsequent calls.
1728 * Return value: %TRUE if the operation is supported, %FALSE otherwise.
1731 gst_vaapi_filter_set_deinterlacing_references(GstVaapiFilter *filter,
1732 GstVaapiSurface **forward_references, guint num_forward_references,
1733 GstVaapiSurface **backward_references, guint num_backward_references)
1735 g_return_val_if_fail(filter != NULL, FALSE);
1737 deint_refs_clear_all(filter);
1739 if (!deint_refs_set(filter->forward_references, forward_references,
1740 num_forward_references))
1743 if (!deint_refs_set(filter->backward_references, backward_references,
1744 num_backward_references))