diff --git a/gst-libs/gst/vaapi/gstvaapiwindow.c b/gst-libs/gst/vaapi/gstvaapiwindow.c index c8956826a5..2480ee63bf 100644 --- a/gst-libs/gst/vaapi/gstvaapiwindow.c +++ b/gst-libs/gst/vaapi/gstvaapiwindow.c @@ -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; +} diff --git a/gst-libs/gst/vaapi/gstvaapiwindow.h b/gst-libs/gst/vaapi/gstvaapiwindow.h index 64ee3e50e4..c2d895441f 100644 --- a/gst-libs/gst/vaapi/gstvaapiwindow.h +++ b/gst-libs/gst/vaapi/gstvaapiwindow.h @@ -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 */ diff --git a/gst-libs/gst/vaapi/gstvaapiwindow_priv.h b/gst-libs/gst/vaapi/gstvaapiwindow_priv.h index 08cd90c3c5..3d0a59639e 100644 --- a/gst-libs/gst/vaapi/gstvaapiwindow_priv.h +++ b/gst-libs/gst/vaapi/gstvaapiwindow_priv.h @@ -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 * diff --git a/gst-libs/gst/vaapi/gstvaapiwindow_wayland.c b/gst-libs/gst/vaapi/gstvaapiwindow_wayland.c index efb455ca3c..00b5ef115a 100644 --- a/gst-libs/gst/vaapi/gstvaapiwindow_wayland.c +++ b/gst-libs/gst/vaapi/gstvaapiwindow_wayland.c @@ -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 \ diff --git a/gst/vaapi/gstvaapisink.c b/gst/vaapi/gstvaapisink.c index a6a3ab5e15..bc89cff7c5 100644 --- a/gst/vaapi/gstvaapisink.c +++ b/gst/vaapi/gstvaapisink.c @@ -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);