msdk: vpp: Add deinterlacing support
authorSreerenj Balachandran <sreerenj.balachandran@intel.com>
Tue, 6 Mar 2018 13:52:04 +0000 (13:52 +0000)
committerSreerenj Balachandran <sreerenj.balachandran@intel.com>
Tue, 3 Apr 2018 18:38:52 +0000 (10:38 -0800)
https://bugzilla.gnome.org/show_bug.cgi?id=793705

sys/msdk/gstmsdkvpp.c
sys/msdk/gstmsdkvpp.h
sys/msdk/gstmsdkvpputil.c
sys/msdk/gstmsdkvpputil.h
sys/msdk/msdk-enums.c
sys/msdk/msdk-enums.h
sys/msdk/msdk.c

index b031a03..6b71e1e 100644 (file)
@@ -69,6 +69,8 @@ enum
   PROP_ASYNC_DEPTH,
   PROP_DENOISE,
   PROP_ROTATION,
+  PROP_DEINTERLACE_MODE,
+  PROP_DEINTERLACE_METHOD,
   PROP_N,
 };
 
@@ -76,6 +78,8 @@ enum
 #define PROP_ASYNC_DEPTH_DEFAULT         1
 #define PROP_DENOISE_DEFAULT             0
 #define PROP_ROTATION_DEFAULT            MFX_ANGLE_0
+#define PROP_DEINTERLACE_MODE_DEFAULT    GST_MSDKVPP_DEINTERLACE_MODE_AUTO
+#define PROP_DEINTERLACE_METHOD_DEFAULT  MFX_DEINTERLACING_BOB
 
 #define gst_msdkvpp_parent_class parent_class
 G_DEFINE_TYPE (GstMsdkVPP, gst_msdkvpp, GST_TYPE_BASE_TRANSFORM);
@@ -581,6 +585,7 @@ gst_msdkvpp_close (GstMsdkVPP * thiz)
     gst_object_unref (thiz->srcpad_buffer_pool);
   thiz->srcpad_buffer_pool = NULL;
 
+  thiz->field_duration = GST_CLOCK_TIME_NONE;
   gst_video_info_init (&thiz->sinkpad_info);
   gst_video_info_init (&thiz->srcpad_info);
 }
@@ -612,6 +617,17 @@ ensure_filters (GstMsdkVPP * thiz)
     n_filters++;
   }
 
+  /* Deinterlace */
+  if (thiz->flags & GST_MSDK_FLAG_DEINTERLACE) {
+    mfxExtVPPDeinterlacing *mfx_deinterlace = &thiz->mfx_deinterlace;
+    mfx_deinterlace->Header.BufferId = MFX_EXTBUFF_VPP_DEINTERLACING;
+    mfx_deinterlace->Header.BufferSz = sizeof (mfxExtVPPDeinterlacing);
+    mfx_deinterlace->Mode = thiz->deinterlace_method;
+    gst_msdkvpp_add_extra_param (thiz, (mfxExtBuffer *) mfx_deinterlace);
+    thiz->max_filter_algorithms[n_filters] = MFX_EXTBUFF_VPP_DEINTERLACING;
+    n_filters++;
+  }
+
   /* mfxExtVPPDoUse */
   if (n_filters) {
     mfxExtVPPDoUse *mfx_vpp_douse = &thiz->mfx_vpp_douse;
@@ -682,6 +698,10 @@ gst_msdkvpp_initialize (GstMsdkVPP * thiz)
   thiz->param.vpp.Out.FrameRateExtD =
       GST_VIDEO_INFO_FPS_D (&thiz->sinkpad_info);
 
+  /* set vpp out picstruct as progressive if deinterlacing enabled */
+  if (thiz->flags & GST_MSDK_FLAG_DEINTERLACE)
+    thiz->param.vpp.Out.PicStruct = MFX_PICSTRUCT_PROGRESSIVE;
+
   /* validate parameters and allow the Media SDK to make adjustments */
   status = MFXVideoVPP_Query (session, &thiz->param, &thiz->param);
   if (status < MFX_ERR_NONE) {
@@ -753,6 +773,7 @@ gst_msdkvpp_set_caps (GstBaseTransform * trans, GstCaps * caps,
   GstVideoInfo in_info, out_info;
   gboolean sinkpad_info_changed = FALSE;
   gboolean srcpad_info_changed = FALSE;
+  gboolean deinterlace;
 
   gst_video_info_from_caps (&in_info, caps);
   gst_video_info_from_caps (&out_info, out_caps);
@@ -773,6 +794,14 @@ gst_msdkvpp_set_caps (GstBaseTransform * trans, GstCaps * caps,
   if (!sinkpad_info_changed && !srcpad_info_changed)
     return TRUE;
 
+  /* check for deinterlace requirement */
+  deinterlace = gst_msdkvpp_is_deinterlace_enabled (thiz, &in_info);
+  if (deinterlace)
+    thiz->flags |= GST_MSDK_FLAG_DEINTERLACE;
+  thiz->field_duration = GST_VIDEO_INFO_FPS_N (&in_info) > 0 ?
+      gst_util_uint64_scale (GST_SECOND, GST_VIDEO_INFO_FPS_D (&in_info),
+      (1 + deinterlace) * GST_VIDEO_INFO_FPS_N (&in_info)) : 0;
+
   if (!gst_msdkvpp_initialize (thiz))
     return FALSE;
 
@@ -880,6 +909,12 @@ gst_msdkvpp_set_property (GObject * object, guint prop_id,
       thiz->rotation = g_value_get_enum (value);
       thiz->flags |= GST_MSDK_FLAG_ROTATION;
       break;
+    case PROP_DEINTERLACE_MODE:
+      thiz->deinterlace_mode = g_value_get_enum (value);
+      break;
+    case PROP_DEINTERLACE_METHOD:
+      thiz->deinterlace_method = g_value_get_enum (value);
+      break;
     default:
       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
       break;
@@ -905,6 +940,12 @@ gst_msdkvpp_get_property (GObject * object, guint prop_id,
     case PROP_ROTATION:
       g_value_set_enum (value, thiz->rotation);
       break;
+    case PROP_DEINTERLACE_MODE:
+      g_value_set_enum (value, thiz->deinterlace_mode);
+      break;
+    case PROP_DEINTERLACE_METHOD:
+      g_value_set_enum (value, thiz->deinterlace_method);
+      break;
     default:
       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
       break;
@@ -995,6 +1036,18 @@ gst_msdkvpp_class_init (GstMsdkVPPClass * klass)
       "Rotation Angle", gst_msdkvpp_rotation_get_type (),
       PROP_ROTATION_DEFAULT, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
 
+  obj_properties[PROP_DEINTERLACE_MODE] =
+      g_param_spec_enum ("deinterlace-mode", "Deinterlace Mode",
+      "Deinterlace mode to use", gst_msdkvpp_deinterlace_mode_get_type (),
+      PROP_DEINTERLACE_MODE_DEFAULT,
+      G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
+
+  obj_properties[PROP_DEINTERLACE_METHOD] =
+      g_param_spec_enum ("deinterlace-method", "Deinterlace Method",
+      "Deinterlace method to use", gst_msdkvpp_deinterlace_method_get_type (),
+      PROP_DEINTERLACE_METHOD_DEFAULT,
+      G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
+
   g_object_class_install_properties (gobject_class, PROP_N, obj_properties);
 }
 
@@ -1005,6 +1058,9 @@ gst_msdkvpp_init (GstMsdkVPP * thiz)
   thiz->async_depth = PROP_ASYNC_DEPTH_DEFAULT;
   thiz->denoise_factor = PROP_DENOISE_DEFAULT;
   thiz->rotation = PROP_ROTATION_DEFAULT;
+  thiz->deinterlace_mode = PROP_DEINTERLACE_MODE_DEFAULT;
+  thiz->deinterlace_method = PROP_DEINTERLACE_METHOD_DEFAULT;
+  thiz->field_duration = GST_CLOCK_TIME_NONE;
   gst_video_info_init (&thiz->sinkpad_info);
   gst_video_info_init (&thiz->srcpad_info);
 }
index b4c68ff..ca3d21a 100644 (file)
@@ -61,8 +61,9 @@ typedef struct _GstMsdkVPP GstMsdkVPP;
 typedef struct _GstMsdkVPPClass GstMsdkVPPClass;
 
 typedef enum {
-  GST_MSDK_FLAG_DENOISE  = 1 << 0,
-  GST_MSDK_FLAG_ROTATION = 1 << 1,
+  GST_MSDK_FLAG_DENOISE     = 1 << 0,
+  GST_MSDK_FLAG_ROTATION    = 1 << 1,
+  GST_MSDK_FLAG_DEINTERLACE = 1 << 2,
 } GstMsdkVppFlags;
 
 struct _GstMsdkVPP
@@ -99,12 +100,16 @@ struct _GstMsdkVPP
   guint async_depth;
   guint denoise_factor;
   guint rotation;
+  guint deinterlace_mode;
+  guint deinterlace_method;
+  GstClockTime field_duration;
 
   /* MFX Filters */
   mfxExtVPPDoUse mfx_vpp_douse;
   mfxU32 max_filter_algorithms [MAX_FILTER_ALGORITHMS];
   mfxExtVPPDenoise mfx_denoise;
   mfxExtVPPRotation mfx_rotation;
+  mfxExtVPPDeinterlacing mfx_deinterlace;
 
   /* Extended buffers */
   mfxExtBuffer *extra_params[MAX_EXTRA_PARAMS];
index bc337ea..82695aa 100644 (file)
  */
 
 #include "gstmsdkvpputil.h"
+#include "msdk-enums.h"
+
+gboolean
+gst_msdkvpp_is_deinterlace_enabled (GstMsdkVPP * msdkvpp, GstVideoInfo * vip)
+{
+  gboolean deinterlace;
+
+  switch (msdkvpp->deinterlace_mode) {
+    case GST_MSDKVPP_DEINTERLACE_MODE_AUTO:
+      deinterlace = GST_VIDEO_INFO_IS_INTERLACED (vip);
+      break;
+    case GST_MSDKVPP_DEINTERLACE_MODE_INTERLACED:
+      deinterlace = TRUE;
+      break;
+    default:
+      deinterlace = FALSE;
+      break;
+  }
+  return deinterlace;
+}
 
 static gboolean
 fixate_output_frame_size (GstMsdkVPP * thiz, GstVideoInfo * vinfo,
@@ -407,6 +427,31 @@ overflow_error:
 }
 
 static gboolean
+fixate_frame_rate (GstMsdkVPP * thiz, GstVideoInfo * vinfo, GstStructure * outs)
+{
+  gint fps_n, fps_d;
+
+  fps_n = GST_VIDEO_INFO_FPS_N (vinfo);
+  fps_d = GST_VIDEO_INFO_FPS_D (vinfo);
+  if (gst_msdkvpp_is_deinterlace_enabled (thiz, vinfo)) {
+    /* Fixme: set double framerate?:
+     * msdk is not outputting double framerate for bob or adv deinterlace */
+    if (!gst_util_fraction_multiply (fps_n, fps_d, 1, 1, &fps_n, &fps_d))
+      goto overflow_error;
+  }
+  gst_structure_set (outs, "framerate", GST_TYPE_FRACTION, fps_n, fps_d, NULL);
+  return TRUE;
+
+  /* ERRORS */
+overflow_error:
+  {
+    GST_ELEMENT_ERROR (thiz, CORE, NEGOTIATION, (NULL),
+        ("Error calculating the output framerate - integer overflow"));
+    return FALSE;
+  }
+}
+
+static gboolean
 set_multiview_mode (GstMsdkVPP * thiz, GstVideoInfo * vinfo,
     GstStructure * outs)
 {
@@ -429,6 +474,28 @@ set_multiview_mode (GstMsdkVPP * thiz, GstVideoInfo * vinfo,
   return TRUE;
 }
 
+static gboolean
+set_interlace_mode (GstMsdkVPP * thiz, GstVideoInfo * vinfo,
+    GstStructure * outs)
+{
+  const gchar *interlace_mode = NULL;
+
+  if (gst_msdkvpp_is_deinterlace_enabled (thiz, vinfo)) {
+    interlace_mode = "progressive";
+  } else {
+    interlace_mode =
+        gst_video_interlace_mode_to_string (GST_VIDEO_INFO_INTERLACE_MODE
+        (vinfo));
+  }
+
+  if (!interlace_mode)
+    return FALSE;
+
+  gst_structure_set (outs, "interlace-mode", G_TYPE_STRING, interlace_mode,
+      NULL);
+  return TRUE;
+}
+
 static GstCaps *
 _get_preferred_src_caps (GstMsdkVPP * thiz, GstVideoInfo * vinfo,
     GstCaps * srccaps)
@@ -450,14 +517,18 @@ _get_preferred_src_caps (GstMsdkVPP * thiz, GstVideoInfo * vinfo,
     goto fixate_failed;
 
   /* Fixate the framerate */
-  gst_structure_set (structure, "framerate", GST_TYPE_FRACTION,
-      GST_VIDEO_INFO_FPS_N (vinfo), GST_VIDEO_INFO_FPS_D (vinfo), NULL);
+  if (!fixate_frame_rate (thiz, vinfo, structure))
+    goto fixate_failed;
 
   /* set multiview mode based on input caps */
   if (!set_multiview_mode (thiz, vinfo, structure))
     goto fixate_failed;
 
-  /*Fixme: Set colorimetry and interlace mode */
+  /*Fixme: Set colorimetry */
+
+  /* set interlace mode */
+  if (!set_interlace_mode (thiz, vinfo, structure))
+    goto interlace_mode_failed;
 
   outcaps = gst_caps_new_empty ();
   gst_caps_append_structure (outcaps, structure);
@@ -471,6 +542,11 @@ fixate_failed:
     gst_structure_free (structure);
     return NULL;
   }
+interlace_mode_failed:
+  {
+    GST_WARNING_OBJECT (thiz, "Invalid sink caps interlace mode");
+    return NULL;
+  }
 }
 
 /**
index ab6abe5..560ea94 100644 (file)
@@ -33,6 +33,10 @@ G_BEGIN_DECLS
 GstCaps *gst_msdkvpp_fixate_srccaps (GstMsdkVPP * msdkvpp,
     GstCaps * sinkcaps, GstCaps * srccaps);
 
+gboolean
+gst_msdkvpp_is_deinterlace_enabled (GstMsdkVPP * msdkvpp,
+    GstVideoInfo * vip);
+
 G_END_DECLS
 
 #endif /* GST_MSDKVPPUTIL_H */
index 1479715..51dd7cc 100644 (file)
@@ -176,3 +176,69 @@ gst_msdkvpp_rotation_get_type (void)
   }
   return type;
 }
+
+GType
+gst_msdkvpp_deinterlace_mode_get_type (void)
+{
+  static GType type = 0;
+
+  static const GEnumValue values[] = {
+    {GST_MSDKVPP_DEINTERLACE_MODE_AUTO,
+        "Auto detection", "auto"},
+    {GST_MSDKVPP_DEINTERLACE_MODE_INTERLACED,
+        "Force deinterlacing", "interlaced"},
+    {GST_MSDKVPP_DEINTERLACE_MODE_DISABLED,
+        "Never deinterlace", "disabled"},
+    {0, NULL, NULL},
+  };
+
+  if (!type) {
+    type = g_enum_register_static ("GstMsdkVPPDeinterlaceMode", values);
+  }
+  return type;
+}
+
+GType
+gst_msdkvpp_deinterlace_method_get_type (void)
+{
+  static GType type = 0;
+
+  static const GEnumValue values[] = {
+    {_MFX_DEINTERLACE_METHOD_NONE,
+        "Disable deinterlacing", "none"},
+    {MFX_DEINTERLACING_BOB, "Bob deinterlacing", "bob"},
+    {MFX_DEINTERLACING_ADVANCED, "Advanced deinterlacing (Motion adaptive)",
+        "advanced"},
+#if 0
+    {MFX_DEINTERLACING_AUTO_DOUBLE,
+          "Auto mode with deinterlacing double framerate output",
+        "auto-double"},
+    {MFX_DEINTERLACING_AUTO_SINGLE,
+          "Auto mode with deinterlacing single framerate output",
+        "auto-single"},
+    {MFX_DEINTERLACING_FULL_FR_OUT,
+        "Deinterlace only mode with full framerate output", "full-fr"},
+    {MFX_DEINTERLACING_HALF_FR_OUT,
+        "Deinterlace only Mode with half framerate output", "half-fr"},
+    {MFX_DEINTERLACING_24FPS_OUT, "24 fps fixed output mode", "24-fps"},
+    {MFX_DEINTERLACING_FIXED_TELECINE_PATTERN,
+        "Fixed telecine pattern removal mode", "fixed-telecine-removal"},
+    {MFX_DEINTERLACING_30FPS_OUT, "30 fps fixed output mode", "30-fps"},
+    {MFX_DEINTERLACING_DETECT_INTERLACE, "Only interlace detection",
+        "only-detect"},
+#endif
+    {MFX_DEINTERLACING_ADVANCED_NOREF,
+          "Advanced deinterlacing mode without using of reference frames",
+        "advanced-no-ref"},
+    {MFX_DEINTERLACING_ADVANCED_SCD,
+          "Advanced deinterlacing mode with scene change detection",
+        "advanced-scd"},
+    {MFX_DEINTERLACING_FIELD_WEAVING, "Field weaving", "field-weave"},
+    {0, NULL, NULL},
+  };
+
+  if (!type) {
+    type = g_enum_register_static ("GstMsdkVPPDeinterlaceMethod", values);
+  }
+  return type;
+}
index dde0cc5..14c7d46 100644 (file)
@@ -60,8 +60,23 @@ GType
 gst_msdkenc_adaptive_b_get_type (void);
 
 /*========= MSDK VPP Enums =========================*/
+
 GType
 gst_msdkvpp_rotation_get_type (void);
 
+typedef enum
+{
+  GST_MSDKVPP_DEINTERLACE_MODE_AUTO = 0,
+  GST_MSDKVPP_DEINTERLACE_MODE_INTERLACED,
+  GST_MSDKVPP_DEINTERLACE_MODE_DISABLED,
+} GstMskdVPPDeinterlaceMode;
+
+GType
+gst_msdkvpp_deinterlace_mode_get_type (void);
+
+#define _MFX_DEINTERLACE_METHOD_NONE 0
+GType
+gst_msdkvpp_deinterlace_method_get_type (void);
+
 G_END_DECLS
 #endif
index aaeffc4..e2c80bf 100644 (file)
@@ -265,7 +265,9 @@ gst_msdk_set_mfx_frame_info_from_video_info (mfxFrameInfo * mfx_info,
   mfx_info->FrameRateExtD = GST_VIDEO_INFO_FPS_D (info);
   mfx_info->AspectRatioW = GST_VIDEO_INFO_PAR_N (info);
   mfx_info->AspectRatioH = GST_VIDEO_INFO_PAR_D (info);
-  mfx_info->PicStruct = MFX_PICSTRUCT_PROGRESSIVE;      /* this is by default */
+  mfx_info->PicStruct =
+      !GST_VIDEO_INFO_IS_INTERLACED (info) ? MFX_PICSTRUCT_PROGRESSIVE :
+      MFX_PICSTRUCT_UNKNOWN;
   mfx_info->FourCC =
       gst_msdk_get_mfx_fourcc_from_format (GST_VIDEO_INFO_FORMAT (info));
   mfx_info->ChromaFormat =