filter: add initial support for deinterlacing.
authorZhao Halley <halley.zhao@intel.com>
Mon, 29 Jul 2013 01:23:50 +0000 (09:23 +0800)
committerGwenole Beauchesne <gwenole.beauchesne@intel.com>
Fri, 23 Aug 2013 17:00:38 +0000 (19:00 +0200)
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 <gwenole.beauchesne@intel.com>
docs/reference/libs/libs-sections.txt
gst-libs/gst/vaapi/gstvaapifilter.c [changed mode: 0644->0755]
gst-libs/gst/vaapi/gstvaapifilter.h [changed mode: 0644->0755]
gst-libs/gst/vaapi/gstvaapiutils.c
gst-libs/gst/vaapi/gstvaapiutils.h
gst/vaapi/gstvaapipostproc.c [changed mode: 0644->0755]
gst/vaapi/gstvaapipostproc.h [changed mode: 0644->0755]

index 0aa1620..b70eaaa 100644 (file)
@@ -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
 <SUBSECTION Standard>
 GST_VAAPI_FILTER
 </SECTION>
old mode 100644 (file)
new mode 100755 (executable)
index 4ac3c22..78ab107
@@ -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);
+}
old mode 100644 (file)
new mode 100755 (executable)
index 8da28d4..bd77077
@@ -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 */
index aec68ff..a0b0d0a 100644 (file)
 #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"
 
@@ -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;
+}
index a0a84b4..0ab132b 100644 (file)
@@ -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 */
old mode 100644 (file)
new mode 100755 (executable)
index 944e11f..2504fb6
@@ -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)
 {
old mode 100644 (file)
new mode 100755 (executable)
index e983a31..b33e724
@@ -26,6 +26,7 @@
 #include <gst/vaapi/gstvaapidisplay.h>
 #include <gst/vaapi/gstvaapisurface.h>
 #include <gst/vaapi/gstvaapisurfacepool.h>
+#include <gst/vaapi/gstvaapifilter.h>
 
 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;