From 944a7bd077fdc77c7383f975af45f0db262bff77 Mon Sep 17 00:00:00 2001 From: Zhao Halley Date: Mon, 29 Jul 2013 09:23:50 +0800 Subject: [PATCH] filter: add initial support for deinterlacing. Add basic deinterlacing support, i.e. bob-deinterlacing whereby only the selected field from the input surface is kept for the target surface. Setting gst_vaapi_filter_set_deinterlacing() method argument to GST_VAAPI_DEINTERLACE_METHOD_NONE means to disable deinterlacing. Also move GstVaapiDeinterlaceMethod definition from vaapipostproc plug-in to libgstvaapi core library. Signed-off-by: Gwenole Beauchesne --- docs/reference/libs/libs-sections.txt | 1 + gst-libs/gst/vaapi/gstvaapifilter.c | 162 +++++++++++++++++++++++++++++++++- gst-libs/gst/vaapi/gstvaapifilter.h | 52 +++++++++++ gst-libs/gst/vaapi/gstvaapiutils.c | 46 ++++++++++ gst-libs/gst/vaapi/gstvaapiutils.h | 8 ++ gst/vaapi/gstvaapipostproc.c | 30 ------- gst/vaapi/gstvaapipostproc.h | 15 +--- 7 files changed, 269 insertions(+), 45 deletions(-) mode change 100644 => 100755 gst-libs/gst/vaapi/gstvaapifilter.c mode change 100644 => 100755 gst-libs/gst/vaapi/gstvaapifilter.h mode change 100644 => 100755 gst/vaapi/gstvaapipostproc.c mode change 100644 => 100755 gst/vaapi/gstvaapipostproc.h diff --git a/docs/reference/libs/libs-sections.txt b/docs/reference/libs/libs-sections.txt index 0aa1620..b70eaaa 100644 --- a/docs/reference/libs/libs-sections.txt +++ b/docs/reference/libs/libs-sections.txt @@ -393,6 +393,7 @@ gst_vaapi_filter_set_hue gst_vaapi_filter_set_saturation gst_vaapi_filter_set_brightness gst_vaapi_filter_set_saturation +gst_vaapi_filter_set_deinterlacing GST_VAAPI_FILTER diff --git a/gst-libs/gst/vaapi/gstvaapifilter.c b/gst-libs/gst/vaapi/gstvaapifilter.c old mode 100644 new mode 100755 index 4ac3c22..78ab107 --- a/gst-libs/gst/vaapi/gstvaapifilter.c +++ b/gst-libs/gst/vaapi/gstvaapifilter.c @@ -68,6 +68,60 @@ struct _GstVaapiFilter { }; /* ------------------------------------------------------------------------- */ +/* --- 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 --- */ /* ------------------------------------------------------------------------- */ @@ -188,6 +242,7 @@ enum { 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 }; @@ -299,6 +354,20 @@ init_properties(void) "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 @@ -354,6 +423,11 @@ op_data_new(GstVaapiFilterOp op, GParamSpec *pspec) 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; @@ -409,9 +483,14 @@ op_data_ensure_caps(GstVaapiFilterOpData *op_data, gpointer filter_caps, 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 */ @@ -681,6 +760,59 @@ op_set_color_balance(GstVaapiFilter *filter, GstVaapiFilterOpData *op_data, 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 --- */ /* ------------------------------------------------------------------------- */ @@ -1004,6 +1136,11 @@ gst_vaapi_filter_set_operation(GstVaapiFilter *filter, GstVaapiFilterOp op, 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; } @@ -1322,3 +1459,26 @@ gst_vaapi_filter_set_contrast(GstVaapiFilter *filter, gfloat value) 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); +} diff --git a/gst-libs/gst/vaapi/gstvaapifilter.h b/gst-libs/gst/vaapi/gstvaapifilter.h old mode 100644 new mode 100755 index 8da28d4..bd77077 --- a/gst-libs/gst/vaapi/gstvaapifilter.h +++ b/gst-libs/gst/vaapi/gstvaapifilter.h @@ -51,6 +51,7 @@ typedef enum { GST_VAAPI_FILTER_OP_SATURATION, GST_VAAPI_FILTER_OP_BRIGHTNESS, GST_VAAPI_FILTER_OP_CONTRAST, + GST_VAAPI_FILTER_OP_DEINTERLACING, } GstVaapiFilterOp; /** @@ -85,6 +86,53 @@ typedef enum { 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); @@ -137,4 +185,8 @@ gst_vaapi_filter_set_brightness(GstVaapiFilter *filter, gfloat value); 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 */ diff --git a/gst-libs/gst/vaapi/gstvaapiutils.c b/gst-libs/gst/vaapi/gstvaapiutils.c index aec68ff..a0b0d0a 100644 --- a/gst-libs/gst/vaapi/gstvaapiutils.c +++ b/gst-libs/gst/vaapi/gstvaapiutils.c @@ -25,9 +25,14 @@ #include "gstvaapiutils.h" #include "gstvaapisurface.h" #include "gstvaapisubpicture.h" +#include "gstvaapifilter.h" #include #include +#if USE_VA_VPP +# include +#endif + #define DEBUG 1 #include "gstvaapidebug.h" @@ -433,3 +438,44 @@ to_GstVaapiRotation(guint value) 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; +} diff --git a/gst-libs/gst/vaapi/gstvaapiutils.h b/gst-libs/gst/vaapi/gstvaapiutils.h index a0a84b4..0ab132b 100644 --- a/gst-libs/gst/vaapi/gstvaapiutils.h +++ b/gst-libs/gst/vaapi/gstvaapiutils.h @@ -109,4 +109,12 @@ G_GNUC_INTERNAL guint to_GstVaapiRotation(guint value); +G_GNUC_INTERNAL +guint +from_GstVaapiDeinterlaceMethod(guint value); + +G_GNUC_INTERNAL +guint +from_GstVaapiDeinterlaceFlags(guint flags); + #endif /* GST_VAAPI_UTILS_H */ diff --git a/gst/vaapi/gstvaapipostproc.c b/gst/vaapi/gstvaapipostproc.c old mode 100644 new mode 100755 index 944e11f..2504fb6 --- a/gst/vaapi/gstvaapipostproc.c +++ b/gst/vaapi/gstvaapipostproc.c @@ -149,36 +149,6 @@ gst_vaapi_deinterlace_mode_get_type(void) return deinterlace_mode_type; } -#define GST_VAAPI_TYPE_DEINTERLACE_METHOD \ - gst_vaapi_deinterlace_method_get_type() - -static GType -gst_vaapi_deinterlace_method_get_type(void) -{ - static GType deinterlace_method_type = 0; - - static const GEnumValue method_types[] = { - { GST_VAAPI_DEINTERLACE_METHOD_BOB, - "Bob deinterlacing", "bob" }, -#if 0 - /* 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 (!deinterlace_method_type) { - deinterlace_method_type = - g_enum_register_static("GstVaapiDeinterlaceMethod", method_types); - } - return deinterlace_method_type; -} - static inline GstVaapiPostproc * get_vaapipostproc_from_pad(GstPad *pad) { diff --git a/gst/vaapi/gstvaapipostproc.h b/gst/vaapi/gstvaapipostproc.h old mode 100644 new mode 100755 index e983a31..b33e724 --- a/gst/vaapi/gstvaapipostproc.h +++ b/gst/vaapi/gstvaapipostproc.h @@ -26,6 +26,7 @@ #include #include #include +#include G_BEGIN_DECLS @@ -68,20 +69,6 @@ typedef enum { GST_VAAPI_DEINTERLACE_MODE_DISABLED, } GstVaapiDeinterlaceMode; -/** - * GstVaapiDeinterlaceMethod: - * @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. - */ -typedef enum { - GST_VAAPI_DEINTERLACE_METHOD_BOB = 1, - GST_VAAPI_DEINTERLACE_METHOD_WEAVE, - GST_VAAPI_DEINTERLACE_METHOD_MOTION_ADAPTIVE, - GST_VAAPI_DEINTERLACE_METHOD_MOTION_COMPENSATED, -} GstVaapiDeinterlaceMethod; - struct _GstVaapiPostproc { /*< private >*/ GstElement parent_instance; -- 2.7.4