vaapisink: implement unlock/unlock_stop for wayland
authorMichael Olbrich <m.olbrich@pengutronix.de>
Thu, 7 May 2015 13:55:40 +0000 (15:55 +0200)
committerVíctor Manuel Jáquez Leal <victorx.jaquez@intel.com>
Fri, 15 May 2015 15:10:37 +0000 (17:10 +0200)
Otherwise wl_display_dispatch_queue() might prevent the pipeline from
shutting down. This can happen e.g. if the wayland compositor exits while
the pipeline is running.

Changes:
* renamed unlock()/unlock_stop() to unblock()/unblock_cancel() in gstvaapiwindow
* splitted the patch removing wl_display_dispatch_queue()

Signed-off-by: Víctor Manuel Jáquez Leal <victorx.jaquez@intel.com>
https://bugzilla.gnome.org/show_bug.cgi?id=747492

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

gst-libs/gst/vaapi/gstvaapiwindow.c
gst-libs/gst/vaapi/gstvaapiwindow.h
gst-libs/gst/vaapi/gstvaapiwindow_priv.h
gst-libs/gst/vaapi/gstvaapiwindow_wayland.c
gst/vaapi/gstvaapisink.c

index c895682..2480ee6 100644 (file)
@@ -509,3 +509,45 @@ gst_vaapi_window_reconfigure (GstVaapiWindow * window)
   window->check_geometry = TRUE;
   gst_vaapi_window_ensure_size (window);
 }
+
+/**
+ * gst_vaapi_window_unblock:
+ * @window: a #GstVaapiWindow
+ *
+ * Unblocks a rendering surface operation.
+ */
+gboolean
+gst_vaapi_window_unblock (GstVaapiWindow * window)
+{
+  const GstVaapiWindowClass *klass;
+
+  g_return_val_if_fail (window != NULL, FALSE);
+
+  klass = GST_VAAPI_WINDOW_GET_CLASS (window);
+
+  if (klass->unblock)
+    return klass->unblock (window);
+
+  return TRUE;
+}
+
+/**
+ * gst_vaapi_window_unblock_cancel:
+ * @window: a #GstVaapiWindow
+ *
+ * Cancels the previous unblock request.
+ */
+gboolean
+gst_vaapi_window_unblock_cancel (GstVaapiWindow * window)
+{
+  const GstVaapiWindowClass *klass;
+
+  g_return_val_if_fail (window != NULL, FALSE);
+
+  klass = GST_VAAPI_WINDOW_GET_CLASS (window);
+
+  if (klass->unblock_cancel)
+    return klass->unblock_cancel (window);
+
+  return TRUE;
+}
index 64ee3e5..c2d8954 100644 (file)
@@ -99,6 +99,12 @@ gst_vaapi_window_put_pixmap (GstVaapiWindow * window, GstVaapiPixmap * pixmap,
 void
 gst_vaapi_window_reconfigure (GstVaapiWindow * window);
 
+gboolean
+gst_vaapi_window_unblock (GstVaapiWindow * window);
+
+gboolean
+gst_vaapi_window_unblock_cancel (GstVaapiWindow * window);
+
 G_END_DECLS
 
 #endif /* GST_VAAPI_WINDOW_H */
index 08cd90c..3d0a596 100644 (file)
@@ -54,6 +54,8 @@ typedef gboolean (*GstVaapiWindowRenderPixmapFunc) (GstVaapiWindow * window,
     const GstVaapiRectangle * dst_rect);
 typedef guintptr (*GstVaapiWindowGetVisualIdFunc) (GstVaapiWindow * window);
 typedef guintptr (*GstVaapiWindowGetColormapFunc) (GstVaapiWindow * window);
+typedef gboolean (*GstVaapiWindowSetUnblockFunc) (GstVaapiWindow * window);
+typedef gboolean (*GstVaapiWindowSetUnblockCancelFunc) (GstVaapiWindow * window);
 
 /**
  * GstVaapiWindow:
@@ -88,6 +90,9 @@ struct _GstVaapiWindow
  *   create the window
  * @get_colormap: virtual function to get the desired colormap used to
  *   create the window, or the currently allocated one
+ * @unblock: virtual function to unblock a rendering surface operation
+ * @unblock_cancel: virtual function to cancel the previous unblock
+ *   request.
  *
  * Base class for system-dependent windows.
  */
@@ -107,6 +112,8 @@ struct _GstVaapiWindowClass
   GstVaapiWindowRenderPixmapFunc render_pixmap;
   GstVaapiWindowGetVisualIdFunc get_visual_id;
   GstVaapiWindowGetColormapFunc get_colormap;
+  GstVaapiWindowSetUnblockFunc unblock;
+  GstVaapiWindowSetUnblockCancelFunc unblock_cancel;
 };
 
 GstVaapiWindow *
index efb455c..00b5ef1 100644 (file)
@@ -104,6 +104,8 @@ struct _GstVaapiWindowWaylandPrivate
   GstVideoFormat surface_format;
   GstVaapiVideoPool *surface_pool;
   GstVaapiFilter *filter;
+  GstPoll *poll;
+  GstPollFD pollfd;
   guint is_shown:1;
   guint fullscreen_on_show:1;
   guint use_vpp:1;
@@ -158,6 +160,12 @@ gst_vaapi_window_wayland_sync (GstVaapiWindow * window)
   struct wl_display *const wl_display =
       GST_VAAPI_OBJECT_NATIVE_DISPLAY (window);
 
+  if (priv->pollfd.fd < 0) {
+    priv->pollfd.fd = wl_display_get_fd (wl_display);
+    gst_poll_add_fd (priv->poll, &priv->pollfd);
+    gst_poll_fd_ctl_read (priv->poll, &priv->pollfd, TRUE);
+  }
+
   while (g_atomic_int_get (&priv->num_frames_pending) > 0) {
     while (wl_display_prepare_read_queue (wl_display, priv->event_queue) < 0) {
       if (wl_display_dispatch_queue_pending (wl_display, priv->event_queue) < 0)
@@ -166,6 +174,19 @@ gst_vaapi_window_wayland_sync (GstVaapiWindow * window)
 
     if (wl_display_flush (wl_display) < 0)
       goto error;
+
+  again:
+    if (gst_poll_wait (priv->poll, GST_CLOCK_TIME_NONE) < 0) {
+      int saved_errno = errno;
+      if (saved_errno == EAGAIN || saved_errno == EINTR)
+        goto again;
+      if (saved_errno == EBUSY) {       /* closing */
+        wl_display_cancel_read (wl_display);
+        break;
+      }
+      goto error;
+    }
+
     if (wl_display_read_events (wl_display) < 0)
       goto error;
     if (wl_display_dispatch_queue_pending (wl_display, priv->event_queue) < 0)
@@ -264,6 +285,9 @@ gst_vaapi_window_wayland_create (GstVaapiWindow * window,
       &shell_surface_listener, priv);
   wl_shell_surface_set_toplevel (priv->shell_surface);
 
+  priv->poll = gst_poll_new (TRUE);
+  gst_poll_fd_init (&priv->pollfd);
+
   if (priv->fullscreen_on_show)
     gst_vaapi_window_wayland_set_fullscreen (window, TRUE);
 
@@ -302,6 +326,8 @@ gst_vaapi_window_wayland_destroy (GstVaapiWindow * window)
 
   gst_vaapi_filter_replace (&priv->filter, NULL);
   gst_vaapi_video_pool_replace (&priv->surface_pool, NULL);
+
+  gst_poll_free (priv->poll);
 }
 
 static gboolean
@@ -521,6 +547,28 @@ gst_vaapi_window_wayland_render (GstVaapiWindow * window,
   return TRUE;
 }
 
+static gboolean
+gst_vaapi_window_wayland_unblock (GstVaapiWindow * window)
+{
+  GstVaapiWindowWaylandPrivate *const priv =
+      GST_VAAPI_WINDOW_WAYLAND_GET_PRIVATE (window);
+
+  gst_poll_set_flushing (priv->poll, TRUE);
+
+  return TRUE;
+}
+
+static gboolean
+gst_vaapi_window_wayland_unblock_cancel (GstVaapiWindow * window)
+{
+  GstVaapiWindowWaylandPrivate *const priv =
+      GST_VAAPI_WINDOW_WAYLAND_GET_PRIVATE (window);
+
+  gst_poll_set_flushing (priv->poll, FALSE);
+
+  return TRUE;
+}
+
 static void
 gst_vaapi_window_wayland_class_init (GstVaapiWindowWaylandClass * klass)
 {
@@ -536,6 +584,8 @@ gst_vaapi_window_wayland_class_init (GstVaapiWindowWaylandClass * klass)
   window_class->render = gst_vaapi_window_wayland_render;
   window_class->resize = gst_vaapi_window_wayland_resize;
   window_class->set_fullscreen = gst_vaapi_window_wayland_set_fullscreen;
+  window_class->unblock = gst_vaapi_window_wayland_unblock;
+  window_class->unblock_cancel = gst_vaapi_window_wayland_unblock_cancel;
 }
 
 #define gst_vaapi_window_wayland_finalize \
index a6a3ab5..bc89cff 100644 (file)
@@ -1550,6 +1550,28 @@ gst_vaapisink_get_property (GObject * object,
   }
 }
 
+static gboolean
+gst_vaapisink_unlock (GstBaseSink * base_sink)
+{
+  GstVaapiSink *const sink = GST_VAAPISINK_CAST (base_sink);
+
+  if (sink->window)
+    return gst_vaapi_window_unblock (sink->window);
+
+  return TRUE;
+}
+
+static gboolean
+gst_vaapisink_unlock_stop (GstBaseSink * base_sink)
+{
+  GstVaapiSink *const sink = GST_VAAPISINK_CAST (base_sink);
+
+  if (sink->window)
+    return gst_vaapi_window_unblock_cancel (sink->window);
+
+  return TRUE;
+}
+
 static void
 gst_vaapisink_set_bus (GstElement * element, GstBus * bus)
 {
@@ -1591,6 +1613,8 @@ gst_vaapisink_class_init (GstVaapiSinkClass * klass)
   basesink_class->set_caps = gst_vaapisink_set_caps;
   basesink_class->query = GST_DEBUG_FUNCPTR (gst_vaapisink_query);
   basesink_class->propose_allocation = gst_vaapisink_propose_allocation;
+  basesink_class->unlock = gst_vaapisink_unlock;
+  basesink_class->unlock_stop = gst_vaapisink_unlock_stop;
 
   videosink_class->show_frame = GST_DEBUG_FUNCPTR (gst_vaapisink_show_frame);