};
/* ------------------------------------------------------------------------- */
+/* --- VPP Types --- */
+/* ------------------------------------------------------------------------- */
+
+GType
+gst_vaapi_deinterlace_method_get_type(void)
+{
+ static gsize g_type = 0;
+
+ static const GEnumValue enum_values[] = {
+ { GST_VAAPI_DEINTERLACE_METHOD_NONE,
+ "Disable deinterlacing", "none" },
+ { GST_VAAPI_DEINTERLACE_METHOD_BOB,
+ "Bob deinterlacing", "bob" },
+#if USE_VA_VPP
+ { GST_VAAPI_DEINTERLACE_METHOD_WEAVE,
+ "Weave deinterlacing", "weave" },
+ { GST_VAAPI_DEINTERLACE_METHOD_MOTION_ADAPTIVE,
+ "Motion adaptive deinterlacing", "motion-adaptive" },
+ { GST_VAAPI_DEINTERLACE_METHOD_MOTION_COMPENSATED,
+ "Motion compensated deinterlacing", "motion-compensated" },
+#endif
+ { 0, NULL, NULL },
+ };
+
+ if (g_once_init_enter(&g_type)) {
+ const GType type =
+ g_enum_register_static("GstVaapiDeinterlaceMethod", enum_values);
+ g_once_init_leave(&g_type, type);
+ }
+ return g_type;
+}
+
+GType
+gst_vaapi_deinterlace_flags_get_type(void)
+{
+ static gsize g_type = 0;
+
+ static const GEnumValue enum_values[] = {
+ { GST_VAAPI_DEINTERLACE_FLAG_TFF,
+ "Top-field first", "top-field-first" },
+ { GST_VAAPI_DEINTERLACE_FLAG_ONEFIELD,
+ "One field", "one-field" },
+ { 0, NULL, NULL }
+ };
+
+ if (g_once_init_enter(&g_type)) {
+ const GType type =
+ g_enum_register_static("GstVaapiDeinterlaceFlags", enum_values);
+ g_once_init_leave(&g_type, type);
+ }
+ return g_type;
+}
+
+/* ------------------------------------------------------------------------- */
/* --- VPP Helpers --- */
/* ------------------------------------------------------------------------- */
PROP_SATURATION = GST_VAAPI_FILTER_OP_SATURATION,
PROP_BRIGHTNESS = GST_VAAPI_FILTER_OP_BRIGHTNESS,
PROP_CONTRAST = GST_VAAPI_FILTER_OP_CONTRAST,
+ PROP_DEINTERLACING = GST_VAAPI_FILTER_OP_DEINTERLACING,
N_PROPERTIES
};
"The color contrast value",
0.0, 2.0, 1.0,
G_PARAM_READWRITE);
+
+ /**
+ * GstVaapiFilter:deinterlace-method:
+ *
+ * The deinterlacing algorithm to apply, expressed a an enum
+ * value. See #GstVaapiDeinterlaceMethod.
+ */
+ g_properties[PROP_DEINTERLACING] =
+ g_param_spec_enum("deinterlace",
+ "Deinterlacing Method",
+ "Deinterlacing method to apply",
+ GST_VAAPI_TYPE_DEINTERLACE_METHOD,
+ GST_VAAPI_DEINTERLACE_METHOD_NONE,
+ G_PARAM_READWRITE);
}
static void
op_data->va_cap_size = sizeof(VAProcFilterCapColorBalance);
op_data->va_buffer_size = sizeof(VAProcFilterParameterBufferColorBalance);
break;
+ case GST_VAAPI_FILTER_OP_DEINTERLACING:
+ op_data->va_type = VAProcFilterDeinterlacing;
+ op_data->va_cap_size = sizeof(VAProcFilterCapDeinterlacing);
+ op_data->va_buffer_size = sizeof(VAProcFilterParameterBufferDeinterlacing);
+ break;
default:
g_assert(0 && "unsupported operation");
goto error;
if (i == num_filter_caps)
return FALSE;
}
+
op_data->va_caps = g_memdup(filter_cap,
op_data->va_cap_size * num_filter_caps);
- return op_data->va_caps != NULL;
+ if (!op_data->va_caps)
+ return FALSE;
+
+ op_data->va_num_caps = num_filter_caps;
+ return TRUE;
}
/* Scale the filter value wrt. library spec and VA driver spec */
return success;
}
+/* Update deinterlace filter */
+#if USE_VA_VPP
+static gboolean
+op_set_deinterlace_unlocked(GstVaapiFilter *filter,
+ GstVaapiFilterOpData *op_data, GstVaapiDeinterlaceMethod method,
+ guint flags)
+{
+ VAProcFilterParameterBufferDeinterlacing *buf;
+ const VAProcFilterCapDeinterlacing *filter_caps;
+ VAProcDeinterlacingType algorithm;
+ guint i;
+
+ if (!op_data || !op_ensure_buffer(filter, op_data))
+ return FALSE;
+
+ op_data->is_enabled = (method != GST_VAAPI_DEINTERLACE_METHOD_NONE);
+ if (!op_data->is_enabled)
+ return TRUE;
+
+ algorithm = from_GstVaapiDeinterlaceMethod(method);
+ for (i = 0, filter_caps = op_data->va_caps; i < op_data->va_num_caps; i++) {
+ if (filter_caps[i].type == algorithm)
+ break;
+ }
+ if (i == op_data->va_num_caps)
+ return FALSE;
+
+ buf = vaapi_map_buffer(filter->va_display, op_data->va_buffer);
+ if (!buf)
+ return FALSE;
+
+ buf->type = op_data->va_type;
+ buf->algorithm = algorithm;
+ buf->flags = from_GstVaapiDeinterlaceFlags(flags);
+ vaapi_unmap_buffer(filter->va_display, op_data->va_buffer, NULL);
+ return TRUE;
+}
+#endif
+
+static inline gboolean
+op_set_deinterlace(GstVaapiFilter *filter, GstVaapiFilterOpData *op_data,
+ GstVaapiDeinterlaceMethod method, guint flags)
+{
+ gboolean success = FALSE;
+
+#if USE_VA_VPP
+ GST_VAAPI_DISPLAY_LOCK(filter->display);
+ success = op_set_deinterlace_unlocked(filter, op_data, method, flags);
+ GST_VAAPI_DISPLAY_UNLOCK(filter->display);
+#endif
+ return success;
+}
+
/* ------------------------------------------------------------------------- */
/* --- Surface Formats --- */
/* ------------------------------------------------------------------------- */
return op_set_color_balance(filter, op_data,
(value ? g_value_get_float(value) :
G_PARAM_SPEC_FLOAT(op_data->pspec)->default_value));
+ case GST_VAAPI_FILTER_OP_DEINTERLACING:
+ return op_set_deinterlace(filter, op_data,
+ (value ? g_value_get_enum(value) :
+ G_PARAM_SPEC_ENUM(op_data->pspec)->default_value), 0);
+ break;
default:
break;
}
return op_set_color_balance(filter,
find_operation(filter, GST_VAAPI_FILTER_OP_CONTRAST), value);
}
+
+/**
+ * gst_vaapi_filter_set_deinterlacing:
+ * @filter: a #GstVaapiFilter
+ * @method: the deinterlacing algorithm (see #GstVaapiDeinterlaceMethod)
+ * @flags: the additional flags
+ *
+ * Applies deinterlacing to the video processing pipeline. If @method
+ * is not @GST_VAAPI_DEINTERLACE_METHOD_NONE, then @flags could
+ * represent the initial picture structure of the source frame.
+ *
+ * Return value: %TRUE if the operation is supported, %FALSE otherwise.
+ */
+gboolean
+gst_vaapi_filter_set_deinterlacing(GstVaapiFilter *filter,
+ GstVaapiDeinterlaceMethod method, guint flags)
+{
+ g_return_val_if_fail(filter != NULL, FALSE);
+
+ return op_set_deinterlace(filter,
+ find_operation(filter, GST_VAAPI_FILTER_OP_DEINTERLACING), method,
+ flags);
+}
GST_VAAPI_FILTER_OP_SATURATION,
GST_VAAPI_FILTER_OP_BRIGHTNESS,
GST_VAAPI_FILTER_OP_CONTRAST,
+ GST_VAAPI_FILTER_OP_DEINTERLACING,
} GstVaapiFilterOp;
/**
GST_VAAPI_FILTER_STATUS_ERROR_UNSUPPORTED_FORMAT,
} GstVaapiFilterStatus;
+/**
+ * GstVaapiDeinterlaceMethod:
+ * @GST_VAAPI_DEINTERLACE_METHOD_NONE: No deinterlacing.
+ * @GST_VAAPI_DEINTERLACE_METHOD_BOB: Basic bob deinterlacing algorithm.
+ * @GST_VAAPI_DEINTERLACE_METHOD_WEAVE: Weave deinterlacing algorithm.
+ * @GST_VAAPI_DEINTERLACE_METHOD_MOTION_ADAPTIVE: Motion adaptive
+ * deinterlacing algorithm.
+ * @GST_VAAPI_DEINTERLACE_METHOD_MOTION_COMPENSATED: Motion compensated
+ * deinterlacing algorithm.
+ *
+ * Deinterlacing algorithms.
+ */
+typedef enum {
+ GST_VAAPI_DEINTERLACE_METHOD_NONE,
+ GST_VAAPI_DEINTERLACE_METHOD_BOB,
+ GST_VAAPI_DEINTERLACE_METHOD_WEAVE,
+ GST_VAAPI_DEINTERLACE_METHOD_MOTION_ADAPTIVE,
+ GST_VAAPI_DEINTERLACE_METHOD_MOTION_COMPENSATED,
+} GstVaapiDeinterlaceMethod;
+
+/**
+ * GstVaapiDeinterlaceFlags:
+ * @GST_VAAPI_DEINTERLACE_FLAG_TFF: Top-field first. If this flag is
+ * not set, then bottom-field first order is assumed.
+ * @GST_VAAPI_DEINTERLACE_FLAG_ONEFIELD: The input frame represents a
+ * single field. If this flag is not set, then the whole frame holds
+ * two fields.
+ *
+ * The set of gst_vaapi_filter_set_deinterlacing() flags.
+ */
+typedef enum {
+ GST_VAAPI_DEINTERLACE_FLAG_TFF = 1 << 31,
+ GST_VAAPI_DEINTERLACE_FLAG_ONEFIELD = 1 << 30,
+} GstVaapiDeinterlaceFlags;
+
+#define GST_VAAPI_TYPE_DEINTERLACE_METHOD \
+ gst_vaapi_deinterlace_method_get_type()
+
+#define GST_VAAPI_TYPE_DEINTERLACE_FLAGS \
+ gst_vaapi_deinterlace_flags_get_type()
+
+GType
+gst_vaapi_deinterlace_method_get_type(void) G_GNUC_CONST;
+
+GType
+gst_vaapi_deinterlace_flags_get_type(void) G_GNUC_CONST;
+
GstVaapiFilter *
gst_vaapi_filter_new(GstVaapiDisplay *display);
gboolean
gst_vaapi_filter_set_contrast(GstVaapiFilter *filter, gfloat value);
+gboolean
+gst_vaapi_filter_set_deinterlacing(GstVaapiFilter *filter,
+ GstVaapiDeinterlaceMethod method, guint flags);
+
#endif /* GST_VAAPI_FILTER_H */
#include "gstvaapiutils.h"
#include "gstvaapisurface.h"
#include "gstvaapisubpicture.h"
+#include "gstvaapifilter.h"
#include <stdio.h>
#include <stdarg.h>
+#if USE_VA_VPP
+# include <va/va_vpp.h>
+#endif
+
#define DEBUG 1
#include "gstvaapidebug.h"
GST_ERROR("unsupported VA-API rotation value %d", value);
return GST_VAAPI_ROTATION_0;
}
+
+/* VPP: translate GstVaapiDeinterlaceMethod to VA deinterlacing algorithm */
+guint
+from_GstVaapiDeinterlaceMethod(guint value)
+{
+ switch (value) {
+ case GST_VAAPI_DEINTERLACE_METHOD_NONE:
+ return 0;
+#if USE_VA_VPP
+ case GST_VAAPI_DEINTERLACE_METHOD_BOB:
+ return VAProcDeinterlacingBob;
+ case GST_VAAPI_DEINTERLACE_METHOD_WEAVE:
+ return VAProcDeinterlacingWeave;
+ case GST_VAAPI_DEINTERLACE_METHOD_MOTION_ADAPTIVE:
+ return VAProcDeinterlacingMotionAdaptive;
+ case GST_VAAPI_DEINTERLACE_METHOD_MOTION_COMPENSATED:
+ return VAProcDeinterlacingMotionCompensated;
+#endif
+ }
+ GST_ERROR("unsupported GstVaapiDeinterlaceMethod value %d", value);
+ return 0;
+}
+
+/* VPP: translate GstVaapiDeinterlaceFlags into VA deinterlacing flags */
+guint
+from_GstVaapiDeinterlaceFlags(guint flags)
+{
+ guint va_flags = 0;
+
+#if USE_VA_VPP
+ if (!(flags & GST_VAAPI_DEINTERLACE_FLAG_TFF))
+ va_flags |= VA_DEINTERLACING_BOTTOM_FIELD_FIRST;
+
+ if (flags & GST_VAAPI_DEINTERLACE_FLAG_ONEFIELD) {
+ va_flags |= VA_DEINTERLACING_ONE_FIELD;
+ if (!(flags & GST_VAAPI_DEINTERLACE_FLAG_TFF))
+ va_flags |= VA_DEINTERLACING_BOTTOM_FIELD;
+ }
+#endif
+ return va_flags;
+}