vaapidecodebin: ensure VPP before going to READY
[platform/upstream/gstreamer.git] / gst / vaapi / gstvaapidecodebin.c
index f147f1c..121bda7 100644 (file)
@@ -47,12 +47,18 @@ enum
   PROP_MAX_SIZE_BYTES,
   PROP_MAX_SIZE_TIME,
   PROP_DEINTERLACE_METHOD,
-  PROP_DISABLE_VPP
+  PROP_DISABLE_VPP,
+  PROP_LAST
 };
 
-#define GST_VAAPI_DECODE_BIN_SURFACE_CAPS \
-    GST_VIDEO_CAPS_MAKE_WITH_FEATURES(  \
-        GST_CAPS_FEATURE_MEMORY_VAAPI_SURFACE, "{ ENCODED, I420, YV12, NV12 }")
+enum
+{
+  HAS_VPP_UNKNOWN,
+  HAS_VPP_NO,
+  HAS_VPP_YES
+};
+
+static GParamSpec *properties[PROP_LAST];
 
 /* Default templates */
 #define GST_CAPS_CODEC(CODEC) CODEC "; "
@@ -79,10 +85,9 @@ static const char gst_vaapi_decode_bin_sink_caps_str[] =
 
 /* *INDENT-OFF* */
 static const char gst_vaapi_decode_bin_src_caps_str[] =
-  GST_VAAPI_DECODE_BIN_SURFACE_CAPS ", "
+  GST_VAAPI_MAKE_SURFACE_CAPS ", "
   GST_CAPS_INTERLACED_FALSE "; "
-  GST_VIDEO_CAPS_MAKE_WITH_FEATURES (
-      GST_CAPS_FEATURE_META_GST_VIDEO_GL_TEXTURE_UPLOAD_META, "{ RGBA, BGRA }") ", "
+  GST_VAAPI_MAKE_GLTEXUPLOAD_CAPS ", "
   GST_CAPS_INTERLACED_FALSE "; "
   GST_VIDEO_CAPS_MAKE (GST_VIDEO_FORMATS_ALL) ", "
   GST_CAPS_INTERLACED_FALSE;
@@ -124,7 +129,7 @@ activate_vpp (GstVaapiDecodeBin * vaapidecbin)
   if (vaapidecbin->ghost_pad_src || vaapidecbin->postproc)
     return TRUE;
 
-  if (!vaapidecbin->has_vpp || vaapidecbin->disable_vpp) {
+  if (vaapidecbin->has_vpp != HAS_VPP_YES || vaapidecbin->disable_vpp) {
     src = vaapidecbin->queue;
     goto connect_src_ghost_pad;
   }
@@ -171,6 +176,30 @@ connect_src_ghost_pad:
   }
 }
 
+static gboolean
+ensure_vpp (GstVaapiDecodeBin * vaapidecbin)
+{
+  GstVaapiDisplay *display;
+
+  if (vaapidecbin->has_vpp != HAS_VPP_UNKNOWN)
+    return TRUE;
+
+  GST_DEBUG_OBJECT (vaapidecbin, "Creating a dummy display to test for vpp");
+  display = gst_vaapi_create_test_display ();
+  if (!display)
+    return FALSE;
+
+  vaapidecbin->has_vpp = gst_vaapi_display_has_video_processing (display) ?
+    HAS_VPP_YES : HAS_VPP_NO;
+
+  gst_vaapi_display_unref (display);
+
+  if (!activate_vpp (vaapidecbin))
+    return FALSE;
+
+  return TRUE;
+}
+
 static void
 gst_vaapi_decode_bin_set_property (GObject * object,
     guint prop_id, const GValue * value, GParamSpec * pspec)
@@ -267,14 +296,17 @@ gst_vaapi_decode_bin_handle_message (GstBin * bin, GstMessage * message)
   if (!gst_vaapi_video_context_get_display (context, &display))
     goto bail;
 
-  vaapidecbin->has_vpp = gst_vaapi_display_has_video_processing (display);
+  vaapidecbin->has_vpp = gst_vaapi_display_has_video_processing (display) ?
+    HAS_VPP_YES : HAS_VPP_NO;
 
   /* the underlying VA driver implementation doesn't support video
    * post-processing, hence we have to disable it */
-  if (!vaapidecbin->has_vpp) {
+  if (vaapidecbin->has_vpp != HAS_VPP_YES) {
     GST_WARNING_OBJECT (vaapidecbin, "VA driver doesn't support VPP");
     if (!vaapidecbin->disable_vpp) {
       vaapidecbin->disable_vpp = TRUE;
+      g_object_notify_by_pspec (G_OBJECT (vaapidecbin),
+          properties[PROP_DISABLE_VPP]);
     }
   }
 
@@ -285,6 +317,35 @@ bail:
       message);
 }
 
+static GstStateChangeReturn
+gst_vaapi_decode_bin_change_state (GstElement * element,
+    GstStateChange transition)
+{
+  GstVaapiDecodeBin *vaapidecbin = GST_VAAPI_DECODE_BIN (element);
+  GstStateChangeReturn ret;
+
+  switch (transition) {
+    default:
+      break;
+  }
+
+  ret = GST_ELEMENT_CLASS (gst_vaapi_decode_bin_parent_class)->change_state
+    (element, transition);
+  if (ret == GST_STATE_CHANGE_FAILURE)
+    return ret;
+
+  switch (transition) {
+    case GST_STATE_CHANGE_NULL_TO_READY:
+      if (!ensure_vpp (vaapidecbin))
+        return GST_STATE_CHANGE_FAILURE;
+      break;
+    default:
+      break;
+  }
+
+  return ret;
+}
+
 static void
 gst_vaapi_decode_bin_class_init (GstVaapiDecodeBinClass * klass)
 {
@@ -299,6 +360,9 @@ gst_vaapi_decode_bin_class_init (GstVaapiDecodeBinClass * klass)
   gobject_class->set_property = gst_vaapi_decode_bin_set_property;
   gobject_class->get_property = gst_vaapi_decode_bin_get_property;
 
+  element_class->change_state =
+      GST_DEBUG_FUNCPTR (gst_vaapi_decode_bin_change_state);
+
   bin_class->handle_message =
       GST_DEBUG_FUNCPTR (gst_vaapi_decode_bin_handle_message);
 
@@ -308,31 +372,28 @@ gst_vaapi_decode_bin_class_init (GstVaapiDecodeBinClass * klass)
       GST_PLUGIN_DESC,
       "Sreerenj Balachandran <sreerenj.balachandran@intel.com>");
 
-  g_object_class_install_property (gobject_class, PROP_MAX_SIZE_BYTES,
-      g_param_spec_uint ("max-size-bytes", "Max. size (kB)",
-          "Max. amount of data in the queue (bytes, 0=disable)",
-          0, G_MAXUINT, DEFAULT_QUEUE_MAX_SIZE_BYTES,
-          G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
-  g_object_class_install_property (gobject_class, PROP_MAX_SIZE_BUFFERS,
-      g_param_spec_uint ("max-size-buffers", "Max. size (buffers)",
-          "Max. number of buffers in the queue (0=disable)", 0, G_MAXUINT,
-          DEFAULT_QUEUE_MAX_SIZE_BUFFERS,
-          G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
-  g_object_class_install_property (gobject_class, PROP_MAX_SIZE_TIME,
-      g_param_spec_uint64 ("max-size-time", "Max. size (ns)",
-          "Max. amount of data in the queue (in ns, 0=disable)", 0, G_MAXUINT64,
-          DEFAULT_QUEUE_MAX_SIZE_TIME,
-          G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
-  g_object_class_install_property (gobject_class, PROP_DEINTERLACE_METHOD,
-      g_param_spec_enum ("deinterlace-method", "Deinterlace method",
-          "Deinterlace method to use", GST_VAAPI_TYPE_DEINTERLACE_METHOD,
-          DEFAULT_DEINTERLACE_METHOD,
-          G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
-  g_object_class_install_property (gobject_class, PROP_DISABLE_VPP,
-      g_param_spec_boolean ("disable-vpp",
-          "Disable VPP",
-          "Disable Video Post Processing(No support for run time disabling)",
-          FALSE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+  properties[PROP_MAX_SIZE_BYTES] = g_param_spec_uint ("max-size-bytes",
+      "Max. size (kB)", "Max. amount of data in the queue (bytes, 0=disable)",
+      0, G_MAXUINT, DEFAULT_QUEUE_MAX_SIZE_BYTES,
+      G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
+  properties[PROP_MAX_SIZE_BUFFERS] = g_param_spec_uint ("max-size-buffers",
+      "Max. size (buffers)", "Max. number of buffers in the queue (0=disable)",
+      0, G_MAXUINT, DEFAULT_QUEUE_MAX_SIZE_BUFFERS,
+      G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
+  properties[PROP_MAX_SIZE_TIME] = g_param_spec_uint64 ("max-size-time",
+      "Max. size (ns)", "Max. amount of data in the queue (in ns, 0=disable)",
+      0, G_MAXUINT64, DEFAULT_QUEUE_MAX_SIZE_TIME,
+      G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
+  properties[PROP_DEINTERLACE_METHOD] = g_param_spec_enum ("deinterlace-method",
+      "Deinterlace method", "Deinterlace method to use",
+      GST_VAAPI_TYPE_DEINTERLACE_METHOD, DEFAULT_DEINTERLACE_METHOD,
+      G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
+  properties[PROP_DISABLE_VPP] = g_param_spec_boolean ("disable-vpp",
+      "Disable VPP",
+      "Disable Video Post Processing (No support for run time disabling)",
+      FALSE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
+
+  g_object_class_install_properties (gobject_class, PROP_LAST, properties);
 
   gst_element_class_add_pad_template (element_class,
       gst_static_pad_template_get (&gst_vaapi_decode_bin_sink_factory));
@@ -384,7 +445,8 @@ error_element_missing:
   }
 error_link_pad:
   {
-    GST_ERROR_OBJECT (vaapidecbin, "Failed to link the child elements");
+    GST_ELEMENT_ERROR (vaapidecbin, CORE, PAD,
+        (NULL), ("Failed to configure the vaapidecodebin."));
     return FALSE;
   }
 }
@@ -394,8 +456,7 @@ gst_vaapi_decode_bin_init (GstVaapiDecodeBin * vaapidecbin)
 {
   GstPad *element_pad, *ghost_pad;
 
-  /* let's assume we have VPP until we prove the opposite */
-  vaapidecbin->has_vpp = TRUE;
+  vaapidecbin->has_vpp = HAS_VPP_UNKNOWN;
 
   if (!gst_vaapi_decode_bin_configure (vaapidecbin))
     return;