From defff76a647c89be60c31a04a1c67819d77fdc9b Mon Sep 17 00:00:00 2001 From: Zhao Halley Date: Mon, 18 Mar 2013 17:10:31 +0800 Subject: [PATCH] support renders to Pixmap for vaapisink - supports render to Pixmap for vaapisink - supports multiple Pixmap with an array in vaapisink - add 'is-pixmap' attribute to vaapisink - reset sink->window when _stop --- gst-libs/gst/vaapi/gstvaapiwindow_x11.c | 50 ++++++++++++++++++--- gst-libs/gst/vaapi/gstvaapiwindow_x11.h | 2 +- gst/vaapi/gstvaapisink.c | 77 +++++++++++++++++++++++++++++---- gst/vaapi/gstvaapisink.h | 4 ++ tests/test-windows.c | 2 +- 5 files changed, 120 insertions(+), 15 deletions(-) mode change 100644 => 100755 gst-libs/gst/vaapi/gstvaapiwindow_x11.c mode change 100644 => 100755 gst-libs/gst/vaapi/gstvaapiwindow_x11.h mode change 100644 => 100755 gst/vaapi/gstvaapisink.c mode change 100644 => 100755 gst/vaapi/gstvaapisink.h mode change 100644 => 100755 tests/test-windows.c diff --git a/gst-libs/gst/vaapi/gstvaapiwindow_x11.c b/gst-libs/gst/vaapi/gstvaapiwindow_x11.c old mode 100644 new mode 100755 index 9a5db79..042e216 --- a/gst-libs/gst/vaapi/gstvaapiwindow_x11.c +++ b/gst-libs/gst/vaapi/gstvaapiwindow_x11.c @@ -51,7 +51,15 @@ struct _GstVaapiWindowX11Private { guint create_window : 1; guint is_mapped : 1; guint fullscreen_on_map : 1; + guint is_pixmap : 1; }; +/* + * is_pixmap will be used by _create(), but _new_with_xid() doesn't have + * a chance to set the flag, so add this flag here. + * TODO, we'd better add is_pixmap flag to base class: GstVaapiWindow +*/ + +static gboolean _is_pixmap = FALSE; #define _NET_WM_STATE_REMOVE 0 /* remove/unset property */ #define _NET_WM_STATE_ADD 1 /* add/set property */ @@ -235,8 +243,13 @@ gst_vaapi_window_x11_create(GstVaapiWindow *window, guint *width, guint *height) if (!priv->create_window && xid) { GST_VAAPI_OBJECT_LOCK_DISPLAY(window); - XGetWindowAttributes(dpy, xid, &wattr); - priv->is_mapped = wattr.map_state == IsViewable; + if (_is_pixmap) { + priv->is_mapped = TRUE; + } + else { + XGetWindowAttributes(dpy, xid, &wattr); + priv->is_mapped = wattr.map_state == IsViewable; + } ok = x11_get_geometry(dpy, xid, NULL, NULL, width, height); GST_VAAPI_OBJECT_UNLOCK_DISPLAY(window); return ok; @@ -493,6 +506,7 @@ gst_vaapi_window_x11_init(GstVaapiWindowX11 *window) priv->create_window = TRUE; priv->is_mapped = FALSE; priv->fullscreen_on_map = FALSE; + priv->is_pixmap = FALSE; } /** @@ -537,17 +551,26 @@ gst_vaapi_window_x11_new(GstVaapiDisplay *display, guint width, guint height) * Return value: the newly allocated #GstVaapiWindow object */ GstVaapiWindow * -gst_vaapi_window_x11_new_with_xid(GstVaapiDisplay *display, Window xid) +gst_vaapi_window_x11_new_with_xid(GstVaapiDisplay *display, Window xid, gboolean is_pixmap) { + GstVaapiWindow * window = NULL; GST_DEBUG("new window from xid 0x%08x", xid); g_return_val_if_fail(GST_VAAPI_IS_DISPLAY(display), NULL); g_return_val_if_fail(xid != None, NULL); - - return g_object_new(GST_VAAPI_TYPE_WINDOW_X11, + + _is_pixmap = is_pixmap; + window = g_object_new(GST_VAAPI_TYPE_WINDOW_X11, "display", display, "id", GST_VAAPI_ID(xid), NULL); + + if (window) { + GstVaapiWindowX11Private *priv = GST_VAAPI_WINDOW_X11_GET_PRIVATE(window); + priv->is_pixmap = is_pixmap; + } + + return window; } /** @@ -584,3 +607,20 @@ gst_vaapi_window_x11_is_foreign_xid(GstVaapiWindowX11 *window) return !window->priv->create_window; } + +/** + * gst_vaapi_window_x11_is_pixmap: + * @window: a #GstVaapiWindowX11 + * + * Checks whether the @window XID is Pixmap or Window + * + * Return value: %TRUE if the underlying X Drawble is Pixmap + */ +gboolean +gst_vaapi_window_x11_is_pixmap(GstVaapiWindowX11 *window) +{ + g_return_val_if_fail(GST_VAAPI_IS_WINDOW_X11(window), FALSE); + + return window->priv->is_pixmap; +} + diff --git a/gst-libs/gst/vaapi/gstvaapiwindow_x11.h b/gst-libs/gst/vaapi/gstvaapiwindow_x11.h old mode 100644 new mode 100755 index f1f22d4..b5ea9ff --- a/gst-libs/gst/vaapi/gstvaapiwindow_x11.h +++ b/gst-libs/gst/vaapi/gstvaapiwindow_x11.h @@ -101,7 +101,7 @@ GstVaapiWindow * gst_vaapi_window_x11_new(GstVaapiDisplay *display, guint width, guint height); GstVaapiWindow * -gst_vaapi_window_x11_new_with_xid(GstVaapiDisplay *display, Window xid); +gst_vaapi_window_x11_new_with_xid(GstVaapiDisplay *display, Window xid, gboolean is_pixmap); Window gst_vaapi_window_x11_get_xid(GstVaapiWindowX11 *window); diff --git a/gst/vaapi/gstvaapisink.c b/gst/vaapi/gstvaapisink.c old mode 100644 new mode 100755 index 7251398..e898d86 --- a/gst/vaapi/gstvaapisink.c +++ b/gst/vaapi/gstvaapisink.c @@ -107,6 +107,7 @@ enum { PROP_SYNCHRONOUS, PROP_USE_REFLECTION, PROP_ROTATION, + PROP_IS_PIXMAP, }; #define DEFAULT_DISPLAY_TYPE GST_VAAPI_DISPLAY_TYPE_ANY @@ -471,7 +472,7 @@ gst_vaapisink_ensure_window_xid(GstVaapiSink *sink, guintptr window_id) { Window rootwin; unsigned int width, height, border_width, depth; - int x, y; + int x, y, i; XID xid = window_id; if (!gst_vaapisink_ensure_display(sink)) @@ -494,11 +495,22 @@ gst_vaapisink_ensure_window_xid(GstVaapiSink *sink, guintptr window_id) sink->window_height = height; } - if (sink->window && - gst_vaapi_window_x11_get_xid(GST_VAAPI_WINDOW_X11(sink->window)) == xid) - return TRUE; - - g_clear_object(&sink->window); + if (sink->is_pixmap) { + for (i = 0; i < MAX_PIXMAP_COUNT; i++) { + if (sink->pixmap_pool[i]) + if (sink->pixmap_pool[i] && + gst_vaapi_window_x11_get_xid(GST_VAAPI_WINDOW_X11(sink->pixmap_pool[i])) == xid) { + sink->window = sink->pixmap_pool[i]; + return TRUE; + } + } + } + else { + if (sink->window && + gst_vaapi_window_x11_get_xid(GST_VAAPI_WINDOW_X11(sink->window)) == xid) + return TRUE; + g_clear_object(&sink->window); + } switch (sink->display_type) { #if USE_GLX @@ -507,12 +519,28 @@ gst_vaapisink_ensure_window_xid(GstVaapiSink *sink, guintptr window_id) break; #endif case GST_VAAPI_DISPLAY_TYPE_X11: - sink->window = gst_vaapi_window_x11_new_with_xid(sink->display, xid); + sink->window = gst_vaapi_window_x11_new_with_xid(sink->display, xid, sink->is_pixmap); break; default: GST_ERROR("unsupported display type %d", sink->display_type); return FALSE; } + + gboolean save_pixmap_to_pool = FALSE; + for (i = 0; i < MAX_PIXMAP_COUNT; i++) { + if (!sink->pixmap_pool[i]) { + sink->pixmap_pool[i] = sink->window; + save_pixmap_to_pool = TRUE; + break; + } + } + + if (!save_pixmap_to_pool) { + g_clear_object(&sink->pixmap_pool[MAX_PIXMAP_COUNT-1]); + sink->pixmap_pool[MAX_PIXMAP_COUNT-1] = sink->window; + GST_WARNING("exceed MAX_PIXMAP_COUNT: %d", MAX_PIXMAP_COUNT); + } + return sink->window != NULL; } #endif @@ -567,10 +595,21 @@ gst_vaapisink_start(GstBaseSink *base_sink) static gboolean gst_vaapisink_stop(GstBaseSink *base_sink) { + int i = 0; GstVaapiSink * const sink = GST_VAAPISINK(base_sink); gst_buffer_replace(&sink->video_buffer, NULL); - g_clear_object(&sink->window); + if (sink->is_pixmap) { + for (i=0; ipixmap_pool[i]) { + g_clear_object(&sink->pixmap_pool[i]); + } + } + } + else + g_clear_object(&sink->window); + sink->window = NULL; + g_clear_object(&sink->display); return TRUE; @@ -915,6 +954,9 @@ gst_vaapisink_set_property( case PROP_ROTATION: sink->rotation_req = g_value_get_enum(value); break; + case PROP_IS_PIXMAP: + sink->is_pixmap = g_value_get_boolean(value); + break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); break; @@ -947,6 +989,9 @@ gst_vaapisink_get_property( case PROP_ROTATION: g_value_set_enum(value, sink->rotation); break; + case PROP_IS_PIXMAP: + g_value_set_boolean(value, sink->is_pixmap); + break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); break; @@ -1046,11 +1091,22 @@ gst_vaapisink_class_init(GstVaapiSinkClass *klass) GST_VAAPI_TYPE_ROTATION, DEFAULT_ROTATION, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + + g_object_class_install_property + (object_class, + PROP_IS_PIXMAP, + g_param_spec_boolean("is-pixmap", + "IsPixmap", + "the X drawable is Pixmap or not", + FALSE, + G_PARAM_READWRITE)); + } static void gst_vaapisink_init(GstVaapiSink *sink) { + int i = 0; sink->caps = NULL; sink->display = NULL; sink->window = NULL; @@ -1071,4 +1127,9 @@ gst_vaapisink_init(GstVaapiSink *sink) sink->use_reflection = FALSE; sink->use_overlay = FALSE; sink->use_rotation = FALSE; + sink->is_pixmap = FALSE; + + for (i=0; ipixmap_pool[i] = NULL; + } } diff --git a/gst/vaapi/gstvaapisink.h b/gst/vaapi/gstvaapisink.h old mode 100644 new mode 100755 index a2e8bff..774bb40 --- a/gst/vaapi/gstvaapisink.h +++ b/gst/vaapi/gstvaapisink.h @@ -63,6 +63,8 @@ typedef struct _GstVaapiSinkClass GstVaapiSinkClass; typedef struct _GstVaapiTexture GstVaapiTexture; #endif +#define MAX_PIXMAP_COUNT 20 + struct _GstVaapiSink { /*< private >*/ GstVideoSink parent_instance; @@ -88,6 +90,8 @@ struct _GstVaapiSink { guint use_reflection : 1; guint use_overlay : 1; guint use_rotation : 1; + guint is_pixmap : 1; + GstVaapiWindow *pixmap_pool[MAX_PIXMAP_COUNT]; }; struct _GstVaapiSinkClass { diff --git a/tests/test-windows.c b/tests/test-windows.c old mode 100644 new mode 100755 index 8abc784..9e80a16 --- a/tests/test-windows.c +++ b/tests/test-windows.c @@ -181,7 +181,7 @@ main(int argc, char *argv[]) if (!win) g_error("could not create X window"); - window = gst_vaapi_window_x11_new_with_xid(display, win); + window = gst_vaapi_window_x11_new_with_xid(display, win, FALSE); if (!window) g_error("could not create window"); -- 2.7.4