From 30c59af0a012ce2c75ce45bbe47b303f40f04ebe Mon Sep 17 00:00:00 2001 From: Gwenole Beauchesne Date: Wed, 30 Jul 2014 17:27:50 +0200 Subject: [PATCH] vaapisink: introduce separate backends. Introduce new backends vtable so that to have clean separation between display dependent code and common base code. That's a "soft" separation, we don't really need dedicated objects. https://bugzilla.gnome.org/show_bug.cgi?id=722248 --- gst/vaapi/gstvaapisink.c | 591 +++++++++++++++++++++------------------ gst/vaapi/gstvaapisink.h | 25 ++ 2 files changed, 345 insertions(+), 271 deletions(-) diff --git a/gst/vaapi/gstvaapisink.c b/gst/vaapi/gstvaapisink.c index 7f6f2e59c5..fd2e3813e1 100644 --- a/gst/vaapi/gstvaapisink.c +++ b/gst/vaapi/gstvaapisink.c @@ -36,17 +36,6 @@ #include #include -#if USE_DRM -# include -#endif -#if USE_X11 -# include -# include -#endif -#if USE_WAYLAND -# include -# include -#endif /* Supported interfaces */ #if GST_CHECK_VERSION(1,0,0) @@ -142,10 +131,8 @@ gst_vaapisink_ensure_display(GstVaapiSink *sink); static void gst_vaapisink_video_overlay_expose(GstVideoOverlay *overlay); -#if USE_X11 static gboolean -gst_vaapisink_ensure_window_xid(GstVaapiSink *sink, guintptr window_id); -#endif +gst_vaapisink_reconfigure_window(GstVaapiSink * sink); static void gst_vaapisink_set_event_handling(GstVideoOverlay *overlay, gboolean handle_events); @@ -153,18 +140,298 @@ gst_vaapisink_set_event_handling(GstVideoOverlay *overlay, gboolean handle_event static GstFlowReturn gst_vaapisink_show_frame(GstBaseSink *base_sink, GstBuffer *buffer); +static gboolean +gst_vaapisink_put_surface(GstVaapiSink *sink, GstVaapiSurface *surface, + const GstVaapiRectangle *surface_rect, guint flags); + static gboolean gst_vaapisink_ensure_render_rect(GstVaapiSink *sink, guint width, guint height); +/* ------------------------------------------------------------------------ */ +/* --- DRM Backend --- */ +/* ------------------------------------------------------------------------ */ + +#if USE_DRM +#include + +static gboolean +gst_vaapisink_drm_create_window(GstVaapiSink *sink, guint width, guint height) +{ + g_return_val_if_fail(sink->window == NULL, FALSE); + + GST_ERROR("failed to create a window for VA/DRM display"); + return FALSE; +} + +static gboolean +gst_vaapisink_drm_render_surface(GstVaapiSink *sink, GstVaapiSurface *surface, + const GstVaapiRectangle *surface_rect, guint flags) +{ + return TRUE; +} + +static const inline GstVaapiSinkBackend * +gst_vaapisink_backend_drm(void) +{ + static const GstVaapiSinkBackend GstVaapiSinkBackendDRM = { + .create_window = gst_vaapisink_drm_create_window, + .render_surface = gst_vaapisink_drm_render_surface, + }; + return &GstVaapiSinkBackendDRM; +} +#endif + +/* ------------------------------------------------------------------------ */ +/* --- X11 Backend --- */ +/* ------------------------------------------------------------------------ */ + +#if USE_X11 +#include +#include + +/* Checks whether a ConfigureNotify event is in the queue */ +typedef struct _ConfigureNotifyEventPendingArgs ConfigureNotifyEventPendingArgs; +struct _ConfigureNotifyEventPendingArgs { + Window window; + guint width; + guint height; + gboolean match; +}; + +static Bool +configure_notify_event_pending_cb(Display *dpy, XEvent *xev, XPointer arg) +{ + ConfigureNotifyEventPendingArgs * const args = + (ConfigureNotifyEventPendingArgs *)arg; + + if (xev->type == ConfigureNotify && + xev->xconfigure.window == args->window && + xev->xconfigure.width == args->width && + xev->xconfigure.height == args->height) + args->match = TRUE; + + /* XXX: this is a hack to traverse the whole queue because we + can't use XPeekIfEvent() since it could block */ + return False; +} + +static gboolean +configure_notify_event_pending(GstVaapiSink *sink, Window window, + guint width, guint height) +{ + GstVaapiDisplayX11 * const display = + GST_VAAPI_DISPLAY_X11(GST_VAAPI_PLUGIN_BASE_DISPLAY(sink)); + ConfigureNotifyEventPendingArgs args; + XEvent xev; + + args.window = window; + args.width = width; + args.height = height; + args.match = FALSE; + + /* XXX: don't use XPeekIfEvent() because it might block */ + XCheckIfEvent( + gst_vaapi_display_x11_get_display(display), + &xev, + configure_notify_event_pending_cb, (XPointer)&args + ); + return args.match; +} + +static gboolean +gst_vaapisink_x11_create_window(GstVaapiSink *sink, guint width, guint height) +{ + GstVaapiDisplay * const display = GST_VAAPI_PLUGIN_BASE_DISPLAY(sink); + + g_return_val_if_fail(sink->window == NULL, FALSE); + + sink->window = gst_vaapi_window_x11_new(display, width, height); + if (!sink->window) + return FALSE; + + gst_video_overlay_got_window_handle(GST_VIDEO_OVERLAY(sink), + gst_vaapi_window_x11_get_xid(GST_VAAPI_WINDOW_X11(sink->window))); + return TRUE; +} + +static gboolean +gst_vaapisink_x11_create_window_from_handle(GstVaapiSink *sink, guintptr window) +{ + GstVaapiDisplay *display; + Window rootwin; + unsigned int width, height, border_width, depth; + int x, y; + XID xid = window; + + if (!gst_vaapisink_ensure_display(sink)) + return FALSE; + display = GST_VAAPI_PLUGIN_BASE_DISPLAY(sink); + + gst_vaapi_display_lock(display); + XGetGeometry( + gst_vaapi_display_x11_get_display(GST_VAAPI_DISPLAY_X11(display)), + xid, + &rootwin, + &x, &y, &width, &height, &border_width, &depth + ); + gst_vaapi_display_unlock(display); + + if ((width != sink->window_width || height != sink->window_height) && + !configure_notify_event_pending(sink, xid, width, height)) { + if (!gst_vaapisink_ensure_render_rect(sink, width, height)) + return FALSE; + sink->window_width = width; + sink->window_height = height; + } + + if (!sink->window || gst_vaapi_window_x11_get_xid( + GST_VAAPI_WINDOW_X11(sink->window)) != xid) { + gst_vaapi_window_replace(&sink->window, NULL); + sink->window = gst_vaapi_window_x11_new_with_xid(display, xid); + if (!sink->window) + return FALSE; + } + + gst_vaapisink_set_event_handling(GST_VIDEO_OVERLAY(sink), + sink->handle_events); + return TRUE; +} + +static gboolean +gst_vaapisink_x11_handle_events(GstVaapiSink *sink) +{ + GstVaapiDisplay * const display = GST_VAAPI_PLUGIN_BASE_DISPLAY(sink); + gboolean has_events, do_expose = FALSE; + XEvent e; + + if (sink->window) { + Display * const x11_dpy = + gst_vaapi_display_x11_get_display(GST_VAAPI_DISPLAY_X11(display)); + Window x11_win = + gst_vaapi_window_x11_get_xid(GST_VAAPI_WINDOW_X11(sink->window)); + + /* Handle Expose + ConfigureNotify */ + /* Need to lock whole loop or we corrupt the XEvent queue: */ + for (;;) { + gst_vaapi_display_lock(display); + has_events = XCheckWindowEvent(x11_dpy, x11_win, + StructureNotifyMask | ExposureMask, &e); + gst_vaapi_display_unlock(display); + if (!has_events) + break; + + switch (e.type) { + case Expose: + do_expose = TRUE; + break; + case ConfigureNotify: + if (gst_vaapisink_reconfigure_window(sink)) + do_expose = TRUE; + break; + default: + break; + } + } + if (do_expose) + gst_vaapisink_video_overlay_expose(GST_VIDEO_OVERLAY(sink)); + /* FIXME: handle mouse and key events */ + } + return TRUE; +} + +static gboolean +gst_vaapisink_x11_pre_start_event_thread(GstVaapiSink *sink) +{ + GstVaapiDisplayX11 * const display = + GST_VAAPI_DISPLAY_X11(GST_VAAPI_PLUGIN_BASE_DISPLAY(sink)); + + if (sink->window) { + XSelectInput(gst_vaapi_display_x11_get_display(display), + gst_vaapi_window_x11_get_xid(GST_VAAPI_WINDOW_X11(sink->window)), + StructureNotifyMask | ExposureMask); + } + return TRUE; +} + +static gboolean +gst_vaapisink_x11_pre_stop_event_thread(GstVaapiSink *sink) +{ + GstVaapiDisplayX11 * const display = + GST_VAAPI_DISPLAY_X11(GST_VAAPI_PLUGIN_BASE_DISPLAY(sink)); + + if (sink->window) { + XSelectInput(gst_vaapi_display_x11_get_display(display), + gst_vaapi_window_x11_get_xid(GST_VAAPI_WINDOW_X11(sink->window)), + 0); + } + return TRUE; +} + +static const inline GstVaapiSinkBackend * +gst_vaapisink_backend_x11(void) +{ + static const GstVaapiSinkBackend GstVaapiSinkBackendX11 = { + .create_window = gst_vaapisink_x11_create_window, + .create_window_from_handle = gst_vaapisink_x11_create_window_from_handle, + .render_surface = gst_vaapisink_put_surface, + + .event_thread_needed = TRUE, + .handle_events = gst_vaapisink_x11_handle_events, + .pre_start_event_thread = gst_vaapisink_x11_pre_start_event_thread, + .pre_stop_event_thread = gst_vaapisink_x11_pre_stop_event_thread, + }; + return &GstVaapiSinkBackendX11; +} +#endif + +/* ------------------------------------------------------------------------ */ +/* --- Wayland Backend --- */ +/* ------------------------------------------------------------------------ */ + +#if USE_WAYLAND +#include +#include + +static gboolean +gst_vaapisink_wayland_create_window(GstVaapiSink *sink, guint width, + guint height) +{ + GstVaapiDisplay * const display = GST_VAAPI_PLUGIN_BASE_DISPLAY(sink); + + g_return_val_if_fail(sink->window == NULL, FALSE); + + sink->window = gst_vaapi_window_wayland_new(display, width, height); + if (!sink->window) + return FALSE; + return TRUE; +} + +static const inline GstVaapiSinkBackend * +gst_vaapisink_backend_wayland(void) +{ + static const GstVaapiSinkBackend GstVaapiSinkBackendWayland = { + .create_window = gst_vaapisink_wayland_create_window, + .render_surface = gst_vaapisink_put_surface, + }; + return &GstVaapiSinkBackendWayland; +} +#endif + +/* ------------------------------------------------------------------------ */ +/* --- Common implementation --- */ +/* ------------------------------------------------------------------------ */ + static void gst_vaapisink_video_overlay_set_window_handle(GstVideoOverlay *overlay, guintptr window) { GstVaapiSink * const sink = GST_VAAPISINK(overlay); + const GstVaapiSinkBackend * const backend = sink->backend; GstVaapiDisplayType display_type; if (!gst_vaapisink_ensure_display(sink)) return; + display_type = GST_VAAPI_PLUGIN_BASE_DISPLAY_TYPE(sink); /* Disable GLX rendering when vaapisink is using a foreign X @@ -176,17 +443,8 @@ gst_vaapisink_video_overlay_set_window_handle(GstVideoOverlay *overlay, } sink->foreign_window = TRUE; - - switch (display_type) { -#if USE_X11 - case GST_VAAPI_DISPLAY_TYPE_X11: - gst_vaapisink_ensure_window_xid(sink, window); - gst_vaapisink_set_event_handling(GST_VIDEO_OVERLAY(sink), sink->handle_events); - break; -#endif - default: - break; - } + if (backend->create_window_from_handle) + backend->create_window_from_handle(sink, window); } static void @@ -230,75 +488,13 @@ gst_vaapisink_reconfigure_window(GstVaapiSink * sink) return FALSE; } -#if USE_X11 -static void -gst_vaapisink_event_thread_loop_x11(GstVaapiSink *sink) -{ - GstVaapiDisplay * const display = GST_VAAPI_PLUGIN_BASE_DISPLAY(sink); - gboolean has_events, do_expose = FALSE; - XEvent e; - - if (sink->window) { - Display * const x11_dpy = - gst_vaapi_display_x11_get_display(GST_VAAPI_DISPLAY_X11(display)); - Window x11_win = - gst_vaapi_window_x11_get_xid(GST_VAAPI_WINDOW_X11(sink->window)); - - /* Handle Expose + ConfigureNotify */ - /* Need to lock whole loop or we corrupt the XEvent queue: */ - for (;;) { - gst_vaapi_display_lock(display); - has_events = XCheckWindowEvent(x11_dpy, x11_win, - StructureNotifyMask | ExposureMask, &e); - gst_vaapi_display_unlock(display); - if (!has_events) - break; - - switch (e.type) { - case Expose: - do_expose = TRUE; - break; - case ConfigureNotify: - if (gst_vaapisink_reconfigure_window(sink)) - do_expose = TRUE; - break; - default: - break; - } - } - if (do_expose) - gst_vaapisink_video_overlay_expose(GST_VIDEO_OVERLAY(sink)); - /* FIXME: handle mouse and key events */ - } -} -#endif - -static void -gst_vaapisink_event_thread_loop_default(GstVaapiSink *sink) -{ -} - static gpointer gst_vaapisink_event_thread (GstVaapiSink *sink) { - void (*thread_loop)(GstVaapiSink *sink); - - switch (GST_VAAPI_PLUGIN_BASE_DISPLAY_TYPE(sink)) { -#if USE_X11 - case GST_VAAPI_DISPLAY_TYPE_X11: - case GST_VAAPI_DISPLAY_TYPE_GLX: - thread_loop = gst_vaapisink_event_thread_loop_x11; - break; -#endif - default: - thread_loop = gst_vaapisink_event_thread_loop_default; - break; - } - GST_OBJECT_LOCK(sink); while (!sink->event_thread_cancel) { GST_OBJECT_UNLOCK(sink); - thread_loop(sink); + sink->backend->handle_events(sink); g_usleep(G_USEC_PER_SEC / 20); GST_OBJECT_LOCK(sink); } @@ -324,28 +520,17 @@ gst_vaapisink_set_event_handling(GstVideoOverlay *overlay, { GThread *thread = NULL; GstVaapiSink * const sink = GST_VAAPISINK(overlay); -#if USE_X11 - GstVaapiDisplayX11 * const display = - GST_VAAPI_DISPLAY_X11(GST_VAAPI_PLUGIN_BASE_DISPLAY(sink)); -#endif + + if (!sink->backend->event_thread_needed) + return; GST_OBJECT_LOCK(sink); sink->handle_events = handle_events; if (handle_events && !sink->event_thread) { /* Setup our event listening thread */ GST_DEBUG("starting xevent thread"); - switch (GST_VAAPI_PLUGIN_BASE_DISPLAY_TYPE(sink)) { -#if USE_X11 - case GST_VAAPI_DISPLAY_TYPE_X11: - case GST_VAAPI_DISPLAY_TYPE_GLX: - XSelectInput(gst_vaapi_display_x11_get_display(display), - gst_vaapi_window_x11_get_xid(GST_VAAPI_WINDOW_X11(sink->window)), - StructureNotifyMask | ExposureMask); - break; -#endif - default: - break; - } + if (sink->backend->pre_start_event_thread) + sink->backend->pre_start_event_thread(sink); sink->event_thread_cancel = FALSE; sink->event_thread = g_thread_try_new("vaapisink-events", @@ -353,20 +538,8 @@ gst_vaapisink_set_event_handling(GstVideoOverlay *overlay, } else if (!handle_events && sink->event_thread) { GST_DEBUG("stopping xevent thread"); - if (sink->window) { - switch (GST_VAAPI_PLUGIN_BASE_DISPLAY_TYPE(sink)) { -#if USE_X11 - case GST_VAAPI_DISPLAY_TYPE_X11: - case GST_VAAPI_DISPLAY_TYPE_GLX: - XSelectInput(gst_vaapi_display_x11_get_display(display), - gst_vaapi_window_x11_get_xid(GST_VAAPI_WINDOW_X11(sink->window)), - 0); - break; -#endif - default: - break; - } - } + if (sink->backend->pre_stop_event_thread) + sink->backend->pre_stop_event_thread(sink); /* grab thread and mark it as NULL */ thread = sink->event_thread; @@ -400,61 +573,6 @@ gst_vaapisink_destroy(GstVaapiSink *sink) gst_caps_replace(&sink->caps, NULL); } -#if USE_X11 -/* Checks whether a ConfigureNotify event is in the queue */ -typedef struct _ConfigureNotifyEventPendingArgs ConfigureNotifyEventPendingArgs; -struct _ConfigureNotifyEventPendingArgs { - Window window; - guint width; - guint height; - gboolean match; -}; - -static Bool -configure_notify_event_pending_cb(Display *dpy, XEvent *xev, XPointer arg) -{ - ConfigureNotifyEventPendingArgs * const args = - (ConfigureNotifyEventPendingArgs *)arg; - - if (xev->type == ConfigureNotify && - xev->xconfigure.window == args->window && - xev->xconfigure.width == args->width && - xev->xconfigure.height == args->height) - args->match = TRUE; - - /* XXX: this is a hack to traverse the whole queue because we - can't use XPeekIfEvent() since it could block */ - return False; -} - -static gboolean -configure_notify_event_pending( - GstVaapiSink *sink, - Window window, - guint width, - guint height -) -{ - GstVaapiDisplayX11 * const display = - GST_VAAPI_DISPLAY_X11(GST_VAAPI_PLUGIN_BASE_DISPLAY(sink)); - ConfigureNotifyEventPendingArgs args; - XEvent xev; - - args.window = window; - args.width = width; - args.height = height; - args.match = FALSE; - - /* XXX: don't use XPeekIfEvent() because it might block */ - XCheckIfEvent( - gst_vaapi_display_x11_get_display(display), - &xev, - configure_notify_event_pending_cb, (XPointer)&args - ); - return args.match; -} -#endif - static const gchar * get_display_type_name(GstVaapiDisplayType display_type) { @@ -481,6 +599,33 @@ gst_vaapisink_display_changed(GstVaapiPluginBase *plugin) GST_INFO("created %s %p", get_display_type_name(plugin->display_type), plugin->display); + switch (GST_VAAPI_PLUGIN_BASE_DISPLAY_TYPE(sink)) { +#if USE_DRM + case GST_VAAPI_DISPLAY_TYPE_DRM: + sink->backend = gst_vaapisink_backend_drm(); + break; +#endif +#if USE_X11 + case GST_VAAPI_DISPLAY_TYPE_X11: + sink->backend = gst_vaapisink_backend_x11(); + break; +#endif +#if USE_GLX + case GST_VAAPI_DISPLAY_TYPE_GLX: + sink->backend = gst_vaapisink_backend_x11(); + break; +#endif +#if USE_WAYLAND + case GST_VAAPI_DISPLAY_TYPE_WAYLAND: + sink->backend = gst_vaapisink_backend_wayland(); + break; +#endif + default: + GST_ERROR("failed to initialize GstVaapiSink backend"); + g_assert_not_reached(); + break; + } + sink->use_overlay = gst_vaapi_display_get_render_mode(plugin->display, &render_mode) && render_mode == GST_VAAPI_RENDER_MODE_OVERLAY; @@ -624,79 +769,9 @@ gst_vaapisink_ensure_window_size(GstVaapiSink *sink, guint *pwidth, guint *pheig static inline gboolean gst_vaapisink_ensure_window(GstVaapiSink *sink, guint width, guint height) { - GstVaapiDisplay * const display = GST_VAAPI_PLUGIN_BASE_DISPLAY(sink); - - if (!sink->window) { - const GstVaapiDisplayType display_type = - GST_VAAPI_PLUGIN_BASE_DISPLAY_TYPE(sink); - switch (display_type) { -#if USE_X11 - case GST_VAAPI_DISPLAY_TYPE_GLX: - case GST_VAAPI_DISPLAY_TYPE_X11: - sink->window = gst_vaapi_window_x11_new(display, width, height); - if (!sink->window) - break; - gst_video_overlay_got_window_handle( - GST_VIDEO_OVERLAY(sink), - gst_vaapi_window_x11_get_xid(GST_VAAPI_WINDOW_X11(sink->window)) - ); - break; -#endif -#if USE_WAYLAND - case GST_VAAPI_DISPLAY_TYPE_WAYLAND: - sink->window = gst_vaapi_window_wayland_new(display, width, height); - break; -#endif - default: - GST_ERROR("unsupported display type %d", display_type); - return FALSE; - } - } - return sink->window != NULL; + return sink->window || sink->backend->create_window(sink, width, height); } -#if USE_X11 -static gboolean -gst_vaapisink_ensure_window_xid(GstVaapiSink *sink, guintptr window_id) -{ - GstVaapiDisplay *display; - Window rootwin; - unsigned int width, height, border_width, depth; - int x, y; - XID xid = window_id; - - if (!gst_vaapisink_ensure_display(sink)) - return FALSE; - display = GST_VAAPI_PLUGIN_BASE_DISPLAY(sink); - - gst_vaapi_display_lock(display); - XGetGeometry( - gst_vaapi_display_x11_get_display(GST_VAAPI_DISPLAY_X11(display)), - xid, - &rootwin, - &x, &y, &width, &height, &border_width, &depth - ); - gst_vaapi_display_unlock(display); - - if ((width != sink->window_width || height != sink->window_height) && - !configure_notify_event_pending(sink, xid, width, height)) { - if (!gst_vaapisink_ensure_render_rect(sink, width, height)) - return FALSE; - sink->window_width = width; - sink->window_height = height; - } - - if (sink->window && - gst_vaapi_window_x11_get_xid(GST_VAAPI_WINDOW_X11(sink->window)) == xid) - return TRUE; - - gst_vaapi_window_replace(&sink->window, NULL); - - sink->window = gst_vaapi_window_x11_new_with_xid(display, xid); - return sink->window != NULL; -} -#endif - static gboolean gst_vaapisink_ensure_rotation(GstVaapiSink *sink, gboolean recalc_display_rect) { @@ -836,10 +911,8 @@ gst_vaapisink_set_caps(GstBaseSink *base_sink, GstCaps *caps) return FALSE; display = GST_VAAPI_PLUGIN_BASE_DISPLAY(sink); -#if USE_DRM if (GST_VAAPI_PLUGIN_BASE_DISPLAY_TYPE(sink) == GST_VAAPI_DISPLAY_TYPE_DRM) return TRUE; -#endif if (!gst_vaapi_plugin_base_set_caps(plugin, caps, NULL)) return FALSE; @@ -908,7 +981,6 @@ gst_vaapisink_show_frame_unlocked(GstVaapiSink *sink, GstBuffer *src_buffer) GstVaapiSurface *surface; GstBuffer *buffer; guint flags; - gboolean success; GstVaapiRectangle *surface_rect = NULL; #if GST_CHECK_VERSION(1,0,0) GstVaapiRectangle tmp_rect; @@ -978,30 +1050,7 @@ gst_vaapisink_show_frame_unlocked(GstVaapiSink *sink, GstBuffer *src_buffer) if (!gst_vaapi_apply_composition(surface, src_buffer)) GST_WARNING("could not update subtitles"); - switch (GST_VAAPI_PLUGIN_BASE_DISPLAY_TYPE(sink)) { -#if USE_DRM - case GST_VAAPI_DISPLAY_TYPE_DRM: - success = TRUE; - break; -#endif -#if USE_X11 - case GST_VAAPI_DISPLAY_TYPE_GLX: - case GST_VAAPI_DISPLAY_TYPE_X11: - success = gst_vaapisink_put_surface(sink, surface, surface_rect, flags); - break; -#endif -#if USE_WAYLAND - case GST_VAAPI_DISPLAY_TYPE_WAYLAND: - success = gst_vaapisink_put_surface(sink, surface, surface_rect, flags); - break; -#endif - default: - GST_ERROR("unsupported display type %d", - GST_VAAPI_PLUGIN_BASE_DISPLAY_TYPE(sink)); - success = FALSE; - break; - } - if (!success) + if (!sink->backend->render_surface(sink, surface, surface_rect, flags)) goto error; /* Retain VA surface until the next one is displayed */ diff --git a/gst/vaapi/gstvaapisink.h b/gst/vaapi/gstvaapisink.h index 5dc51012e8..f55dbf53db 100644 --- a/gst/vaapi/gstvaapisink.h +++ b/gst/vaapi/gstvaapisink.h @@ -57,11 +57,36 @@ G_BEGIN_DECLS typedef struct _GstVaapiSink GstVaapiSink; typedef struct _GstVaapiSinkClass GstVaapiSinkClass; +typedef struct _GstVaapiSinkBackend GstVaapiSinkBackend; + +typedef gboolean (*GstVaapiSinkCreateWindowFunc)(GstVaapiSink *sink, + guint width, guint height); +typedef gboolean (*GstVaapiSinkCreateWindowFromHandleFunc)(GstVaapiSink *sink, + guintptr window); +typedef gboolean (*GstVaapiSinkRenderSurfaceFunc)(GstVaapiSink *sink, + GstVaapiSurface *surface, const GstVaapiRectangle *surface_rect, guint flags); +typedef gboolean (*GstVaapiSinkHandleEventsFunc)(GstVaapiSink *sink); +typedef gboolean (*GstVaapiSinkPreStartEventThreadFunc)(GstVaapiSink *sink); +typedef gboolean (*GstVaapiSinkPreStopEventThreadFunc)(GstVaapiSink *sink); + +struct _GstVaapiSinkBackend { + GstVaapiSinkCreateWindowFunc create_window; + GstVaapiSinkCreateWindowFromHandleFunc create_window_from_handle; + GstVaapiSinkRenderSurfaceFunc render_surface; + + /* Event threads handling */ + gboolean event_thread_needed; + GstVaapiSinkHandleEventsFunc handle_events; + GstVaapiSinkPreStartEventThreadFunc pre_start_event_thread; + GstVaapiSinkPreStopEventThreadFunc pre_stop_event_thread; +}; struct _GstVaapiSink { /*< private >*/ GstVaapiPluginBase parent_instance; + const GstVaapiSinkBackend *backend; + GstCaps *caps; GstVaapiWindow *window; guint window_width;