vaapisink: implement unlock/unlock_stop for wayland

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
This commit is contained in:
Michael Olbrich 2015-05-07 15:55:40 +02:00 committed by Víctor Manuel Jáquez Leal
parent 522ec79d2e
commit 11b9260b6c
5 changed files with 129 additions and 0 deletions

View 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;
}

View 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 */

View 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 *

View 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 \

View 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);