vaapipostproc: add mirror support
authorU. Artie Eoff <ullysses.a.eoff@intel.com>
Mon, 13 May 2019 23:39:33 +0000 (16:39 -0700)
committerVíctor Manuel Jáquez Leal <vjaquez@igalia.com>
Wed, 29 May 2019 09:06:27 +0000 (09:06 +0000)
Adds vpp mirroring support to vaapipostproc.  Use
property video-direction.  Valid values are identity,
horiz or vert.  Default is identity (no mirror).

Closes #89

v2: Use GstVideoOrientationMethod enum
v3: Don't warn for VA_MIRROR_NONE.
    Use GST_TYPE_VIDEO_ORIENTATION_METHOD type.
v4: Query VAAPI caps when setting mirror value
    instead of during per-frame processing.
v5: Return TRUE in warning cases when setting mirror value.

gst-libs/gst/vaapi/gstvaapifilter.c
gst-libs/gst/vaapi/gstvaapifilter.h
gst-libs/gst/vaapi/gstvaapiutils.c
gst-libs/gst/vaapi/gstvaapiutils.h
gst/vaapi/gstvaapipostproc.c
gst/vaapi/gstvaapipostproc.h

index 5f25b37..f715851 100644 (file)
@@ -61,6 +61,7 @@ struct _GstVaapiFilter
   GPtrArray *operations;
   GstVideoFormat format;
   GstVaapiScaleMethod scale_method;
+  GstVideoOrientationMethod video_direction;
   GArray *formats;
   GArray *forward_references;
   GArray *backward_references;
@@ -115,6 +116,17 @@ gst_vaapi_scale_method_get_type (void)
   return g_type;
 }
 
+static const gchar *
+gst_vaapi_get_video_direction_nick (GstVideoOrientationMethod method)
+{
+  gpointer const klass = g_type_class_peek (GST_TYPE_VIDEO_ORIENTATION_METHOD);
+  GEnumValue *const e = g_enum_get_value (klass, method);
+
+  if (e)
+    return e->value_nick;
+  return "<unknown>";
+}
+
 GType
 gst_vaapi_deinterlace_method_get_type (void)
 {
@@ -277,6 +289,7 @@ vpp_get_filter_caps (GstVaapiFilter * filter, VAProcFilterType type,
 
 #define DEFAULT_FORMAT  GST_VIDEO_FORMAT_UNKNOWN
 #define DEFAULT_SCALING GST_VAAPI_SCALE_METHOD_DEFAULT
+#define DEFAULT_VIDEO_DIRECTION GST_VIDEO_ORIENTATION_IDENTITY
 
 enum
 {
@@ -297,6 +310,7 @@ enum
   PROP_CONTRAST = GST_VAAPI_FILTER_OP_CONTRAST,
   PROP_DEINTERLACING = GST_VAAPI_FILTER_OP_DEINTERLACING,
   PROP_SCALING = GST_VAAPI_FILTER_OP_SCALING,
+  PROP_VIDEO_DIRECTION = GST_VAAPI_FILTER_OP_VIDEO_DIRECTION,
   PROP_SKINTONE = GST_VAAPI_FILTER_OP_SKINTONE,
 
   N_PROPERTIES
@@ -421,6 +435,18 @@ init_properties (void)
       DEFAULT_SCALING, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
 
   /**
+   * GstVaapiFilter:video-direction:
+   *
+   * The video-direction to use, expressed as an enum value. See
+   * #GstVideoOrientationMethod.
+   */
+  g_properties[PROP_VIDEO_DIRECTION] = g_param_spec_enum ("video-direction",
+      "Video Direction",
+      "Video direction: rotation and flipping",
+      GST_TYPE_VIDEO_ORIENTATION_METHOD,
+      DEFAULT_VIDEO_DIRECTION, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
+
+  /**
    * GstVaapiFilter:skin-tone-enhancement:
    *
    * Apply the skin tone enhancement algorithm.
@@ -465,6 +491,7 @@ op_data_new (GstVaapiFilterOp op, GParamSpec * pspec)
     case GST_VAAPI_FILTER_OP_FORMAT:
     case GST_VAAPI_FILTER_OP_CROP:
     case GST_VAAPI_FILTER_OP_SCALING:
+    case GST_VAAPI_FILTER_OP_VIDEO_DIRECTION:
       op_data->va_type = VAProcFilterNone;
       break;
     case GST_VAAPI_FILTER_OP_DENOISE:
@@ -1330,6 +1357,9 @@ gst_vaapi_filter_set_operation (GstVaapiFilter * filter, GstVaapiFilterOp op,
       return op_set_skintone (filter, op_data,
           (value ? g_value_get_boolean (value) :
               G_PARAM_SPEC_BOOLEAN (op_data->pspec)->default_value));
+    case GST_VAAPI_FILTER_OP_VIDEO_DIRECTION:
+      return gst_vaapi_filter_set_video_direction (filter, value ?
+          g_value_get_enum (value) : DEFAULT_VIDEO_DIRECTION);
     default:
       break;
   }
@@ -1362,6 +1392,7 @@ gst_vaapi_filter_process_unlocked (GstVaapiFilter * filter,
   guint i, num_filters = 0;
   VAStatus va_status;
   VARectangle src_rect, dst_rect;
+  guint va_mirror = from_GstVideoOrientationMethod (filter->video_direction);
 
   if (!ensure_operations (filter))
     return GST_VAAPI_FILTER_STATUS_ERROR_ALLOCATION_FAILED;
@@ -1444,6 +1475,10 @@ gst_vaapi_filter_process_unlocked (GstVaapiFilter * filter,
   pipeline_param->filters = filters;
   pipeline_param->num_filters = num_filters;
 
+#if VA_CHECK_VERSION(1,1,0)
+  pipeline_param->mirror_state = va_mirror;
+#endif
+
   // Reference frames for advanced deinterlacing
   if (filter->forward_references->len > 0) {
     pipeline_param->forward_references = (VASurfaceID *)
@@ -1838,6 +1873,58 @@ gst_vaapi_filter_set_skintone (GstVaapiFilter * filter, gboolean enhance)
       find_operation (filter, GST_VAAPI_FILTER_OP_SKINTONE), enhance);
 }
 
+/**
+ * gst_vaapi_filter_set_video_direction:
+ * @filter: a #GstVaapiFilter
+ * @method: the video direction (see #GstVideoOrientationMethod)
+ *
+ * Applies mirror/rotation to the video processing pipeline.
+ *
+ * Return value: %TRUE if the operation is supported, %FALSE otherwise.
+ */
+gboolean
+gst_vaapi_filter_set_video_direction (GstVaapiFilter * filter,
+    GstVideoOrientationMethod method)
+{
+  g_return_val_if_fail (filter != NULL, FALSE);
+
+  switch (method) {
+    case GST_VIDEO_ORIENTATION_IDENTITY:
+      break;
+    case GST_VIDEO_ORIENTATION_HORIZ:
+    case GST_VIDEO_ORIENTATION_VERT:
+    {
+#if VA_CHECK_VERSION(1,1,0)
+      VAProcPipelineCaps pipeline_caps;
+      guint va_mirror = from_GstVideoOrientationMethod (method);
+
+      VAStatus va_status = vaQueryVideoProcPipelineCaps (filter->va_display,
+          filter->va_context, NULL, 0, &pipeline_caps);
+      if (!vaapi_check_status (va_status, "vaQueryVideoProcPipelineCaps()"))
+        return FALSE;
+
+      if (!(pipeline_caps.mirror_flags & va_mirror)) {
+        GST_WARNING ("%s video-direction unsupported",
+            gst_vaapi_get_video_direction_nick (method));
+        return TRUE;
+      }
+#else
+      GST_WARNING ("%s video-direction unsupported",
+          gst_vaapi_get_video_direction_nick (method));
+      return TRUE;
+#endif
+      break;
+    }
+    default:
+      GST_WARNING ("%s video-direction unsupported or unimplemented",
+          gst_vaapi_get_video_direction_nick (method));
+      return TRUE;
+  }
+
+  filter->video_direction = method;
+  return TRUE;
+}
+
 static inline gfloat
 op_get_float_default_value (GstVaapiFilter * filter,
     GstVaapiFilterOpData * op_data)
@@ -1915,3 +2002,11 @@ gst_vaapi_filter_get_skintone_default (GstVaapiFilter * filter)
 
   return FALSE;
 }
+
+GstVideoOrientationMethod
+gst_vaapi_filter_get_video_direction_default (GstVaapiFilter * filter)
+{
+  g_return_val_if_fail (filter != NULL, FALSE);
+
+  return DEFAULT_VIDEO_DIRECTION;
+}
index 98798c9..491f459 100644 (file)
@@ -48,6 +48,8 @@ typedef struct _GstVaapiFilterOpInfo            GstVaapiFilterOpInfo;
  * @GST_VAAPI_FILTER_OP_BRIGHTNESS: Change brightness (float).
  * @GST_VAAPI_FILTER_OP_CONTRAST: Change contrast (float).
  * @GST_VAAPI_FILTER_OP_SCALING: Change scaling method (#GstVaapiScaleMethod).
+ * @GST_VAAPI_FILTER_OP_VIDEO_DIRECTION: Change video direction
+ *   (#GstVideoOrientationMethod).
  * @GST_VAAPI_FILTER_OP_SKINTONE: Skin tone enhancement (bool).
  *
  * The set of operations that could be applied to the filter.
@@ -63,6 +65,7 @@ typedef enum {
   GST_VAAPI_FILTER_OP_CONTRAST,
   GST_VAAPI_FILTER_OP_DEINTERLACING,
   GST_VAAPI_FILTER_OP_SCALING,
+  GST_VAAPI_FILTER_OP_VIDEO_DIRECTION,
   GST_VAAPI_FILTER_OP_SKINTONE,
 } GstVaapiFilterOp;
 
@@ -247,6 +250,10 @@ gst_vaapi_filter_set_scaling (GstVaapiFilter * filter,
     GstVaapiScaleMethod method);
 
 gboolean
+gst_vaapi_filter_set_video_direction (GstVaapiFilter * filter,
+    GstVideoOrientationMethod method);
+
+gboolean
 gst_vaapi_filter_set_skintone (GstVaapiFilter * filter,
     gboolean enhance);
 
@@ -271,6 +278,9 @@ gst_vaapi_filter_get_contrast_default (GstVaapiFilter * filter);
 GstVaapiScaleMethod
 gst_vaapi_filter_get_scaling_default (GstVaapiFilter * filter);
 
+GstVideoOrientationMethod
+gst_vaapi_filter_get_video_direction_default (GstVaapiFilter * filter);
+
 gboolean
 gst_vaapi_filter_get_skintone_default (GstVaapiFilter * filter);
 
index 7f9b9ca..4e3fc2f 100644 (file)
@@ -828,3 +828,27 @@ to_GstVaapiScaleMethod (guint flags)
   }
   return method;
 }
+
+/* VPP: translate GstVideoOrientationMethod into VA mirror flags */
+guint
+from_GstVideoOrientationMethod (guint value)
+{
+  guint va_flags = 0;
+
+  switch (value) {
+#if VA_CHECK_VERSION(1,1,0)
+    case GST_VIDEO_ORIENTATION_IDENTITY:
+      va_flags = VA_MIRROR_NONE;
+      break;
+    case GST_VIDEO_ORIENTATION_HORIZ:
+      va_flags = VA_MIRROR_HORIZONTAL;
+      break;
+    case GST_VIDEO_ORIENTATION_VERT:
+      va_flags = VA_MIRROR_VERTICAL;
+      break;
+#endif
+    default:
+      break;
+  }
+  return va_flags;
+}
index 680fc17..cf12051 100644 (file)
@@ -147,4 +147,8 @@ G_GNUC_INTERNAL
 guint
 to_GstVaapiScaleMethod (guint flags);
 
+G_GNUC_INTERNAL
+guint
+from_GstVideoOrientationMethod (guint value);
+
 #endif /* GST_VAAPI_UTILS_H */
index 55e3a56..d89804a 100644 (file)
@@ -121,6 +121,7 @@ enum
   PROP_BRIGHTNESS,
   PROP_CONTRAST,
   PROP_SCALE_METHOD,
+  PROP_VIDEO_DIRECTION,
   PROP_SKIN_TONE_ENHANCEMENT,
 };
 
@@ -593,6 +594,16 @@ update_filter (GstVaapiPostproc * postproc)
       postproc->flags &= ~(GST_VAAPI_POSTPROC_FLAG_SCALE);
   }
 
+  if (postproc->flags & GST_VAAPI_POSTPROC_FLAG_VIDEO_DIRECTION) {
+    if (!gst_vaapi_filter_set_video_direction (postproc->filter,
+            postproc->video_direction))
+      return FALSE;
+
+    if (gst_vaapi_filter_get_video_direction_default (postproc->filter) ==
+        postproc->video_direction)
+      postproc->flags &= ~(GST_VAAPI_POSTPROC_FLAG_VIDEO_DIRECTION);
+  }
+
   if (postproc->flags & GST_VAAPI_POSTPROC_FLAG_SKINTONE) {
     if (!gst_vaapi_filter_set_skintone (postproc->filter,
             postproc->skintone_enhance))
@@ -1613,6 +1624,10 @@ gst_vaapipostproc_set_property (GObject * object,
       postproc->scale_method = g_value_get_enum (value);
       postproc->flags |= GST_VAAPI_POSTPROC_FLAG_SCALE;
       break;
+    case PROP_VIDEO_DIRECTION:
+      postproc->video_direction = g_value_get_enum (value);
+      postproc->flags |= GST_VAAPI_POSTPROC_FLAG_VIDEO_DIRECTION;
+      break;
     case PROP_SKIN_TONE_ENHANCEMENT:
       postproc->skintone_enhance = g_value_get_boolean (value);
       postproc->flags |= GST_VAAPI_POSTPROC_FLAG_SKINTONE;
@@ -1674,6 +1689,9 @@ gst_vaapipostproc_get_property (GObject * object,
     case PROP_SCALE_METHOD:
       g_value_set_enum (value, postproc->scale_method);
       break;
+    case PROP_VIDEO_DIRECTION:
+      g_value_set_enum (value, postproc->video_direction);
+      break;
     case PROP_SKIN_TONE_ENHANCEMENT:
       g_value_set_boolean (value, postproc->skintone_enhance);
       break;
@@ -1895,6 +1913,17 @@ gst_vaapipostproc_class_init (GstVaapiPostprocClass * klass)
         PROP_SCALE_METHOD, filter_op->pspec);
 
   /**
+   * GstVaapiPostproc:video-direction:
+   *
+   * The video-direction to use, expressed as an enum value. See
+   * #GstVideoDirectionMethod.
+   */
+  filter_op = find_filter_op (filter_ops, GST_VAAPI_FILTER_OP_VIDEO_DIRECTION);
+  if (filter_op)
+    g_object_class_install_property (object_class,
+        PROP_VIDEO_DIRECTION, filter_op->pspec);
+
+  /**
    * GstVaapiPostproc:skin-tone-enhancement:
    *
    * Apply the skin tone enhancement algorithm.
index 3c4232c..9e73002 100644 (file)
@@ -86,6 +86,7 @@ typedef enum
  * @GST_VAAPI_POSTPROC_FLAG_DEINTERLACE: Deinterlacing.
  * @GST_VAAPI_POSTPROC_FLAG_SIZE: Video scaling.
  * @GST_VAAPI_POSTPROC_FLAG_SCALE: Video scaling mode.
+ * @GST_VAAPI_POSTPROC_FLAG_VIDEO_DIRECTION: Video rotation and flip/mirroring.
  * @GST_VAAPI_POSTPROC_FLAG_SKINTONE: Skin tone enhancement.
  *
  * The set of operations that are to be performed for each frame.
@@ -101,6 +102,8 @@ typedef enum
   GST_VAAPI_POSTPROC_FLAG_CONTRAST    = 1 << GST_VAAPI_FILTER_OP_CONTRAST,
   GST_VAAPI_POSTPROC_FLAG_DEINTERLACE = 1 << GST_VAAPI_FILTER_OP_DEINTERLACING,
   GST_VAAPI_POSTPROC_FLAG_SCALE       = 1 << GST_VAAPI_FILTER_OP_SCALING,
+  GST_VAAPI_POSTPROC_FLAG_VIDEO_DIRECTION =
+      1 << GST_VAAPI_FILTER_OP_VIDEO_DIRECTION,
   GST_VAAPI_POSTPROC_FLAG_SKINTONE    = 1 << GST_VAAPI_FILTER_OP_SKINTONE,
 
   /* Additional custom flags */
@@ -160,8 +163,11 @@ struct _GstVaapiPostproc
   gfloat denoise_level;
   gfloat sharpen_level;
 
-  /* Color balance filter values */
   GstVaapiScaleMethod scale_method;
+
+  GstVideoOrientationMethod video_direction;
+
+  /* Color balance filter values */
   gfloat hue;
   gfloat saturation;
   gfloat brightness;