vaapidecodebin: ensure VPP before going to READY
authorVíctor Manuel Jáquez Leal <victorx.jaquez@intel.com>
Thu, 6 Aug 2015 16:48:13 +0000 (18:48 +0200)
committerVíctor Manuel Jáquez Leal <victorx.jaquez@intel.com>
Thu, 13 Aug 2015 15:34:42 +0000 (17:34 +0200)
There are sometimes that the VA-API display context is not shared among the
pipeline, but it is important to know it before going to READY state (when the
pipeline is already linked).

One instance of this case is this:

gst-launch-1.0 filesrc location=media ! decodebin ! vaapipostproc ! vaapisink

This patch adds a new function in gstvaapipluginutil called
gst_vaapi_create_test_display(). Its purpose is to create a disposable VA-API
display, which only will be used for verify if the VAEntrypointVideoProc is
available by the hardware. Afterwards, it should be unrefed.

If the vaapidecodebin is going to READY state, and the element still doesn't
know if VPP is available, the last resort is to create a new instance of the
VA-API display and test for it.

https://bugzilla.gnome.org/show_bug.cgi?id=749554

gst/vaapi/gstvaapidecodebin.c
gst/vaapi/gstvaapipluginutil.c
gst/vaapi/gstvaapipluginutil.h

index 1e72278..121bda7 100644 (file)
@@ -176,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)
@@ -293,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)
 {
@@ -307,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);
 
index c23cd16..ef3c6cf 100644 (file)
@@ -634,3 +634,18 @@ gst_video_info_change_format (GstVideoInfo * vip, GstVideoFormat format,
   vip->fps_n = vi.fps_n;
   vip->fps_d = vi.fps_d;
 }
+
+/**
+ * gst_vaapi_create_test_display:
+ *
+ * Creates a temporal #GstVaapiDisplay instance, just for testing the
+ * supported features.
+ *
+ * Returns: a new #GstVaapiDisplay instances. Free with
+ * gst_vaapi_display_unref () after use.
+ **/
+GstVaapiDisplay *
+gst_vaapi_create_test_display ()
+{
+  return gst_vaapi_create_display (GST_VAAPI_DISPLAY_TYPE_ANY, NULL);
+}
index 3decd05..94050fb 100644 (file)
@@ -122,4 +122,8 @@ void
 gst_video_info_change_format (GstVideoInfo * vip, GstVideoFormat format,
     guint width, guint height);
 
+G_GNUC_INTERNAL
+GstVaapiDisplay *
+gst_vaapi_create_test_display (void);
+
 #endif /* GST_VAAPI_PLUGIN_UTIL_H */