support renders to Pixmap for vaapisink
authorZhao Halley <halley.zhao@intel.com>
Mon, 18 Mar 2013 09:10:31 +0000 (17:10 +0800)
committerZhao Halley <halley.zhao@intel.com>
Thu, 21 Mar 2013 07:03:44 +0000 (15:03 +0800)
 - 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 [changed mode: 0644->0755]
gst-libs/gst/vaapi/gstvaapiwindow_x11.h [changed mode: 0644->0755]
gst/vaapi/gstvaapisink.c [changed mode: 0644->0755]
gst/vaapi/gstvaapisink.h [changed mode: 0644->0755]
tests/test-windows.c [changed mode: 0644->0755]

old mode 100644 (file)
new mode 100755 (executable)
index 9a5db79..042e216
@@ -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;
+}
+
old mode 100644 (file)
new mode 100755 (executable)
index f1f22d4..b5ea9ff
@@ -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);
old mode 100644 (file)
new mode 100755 (executable)
index 7251398..e898d86
@@ -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; i<MAX_PIXMAP_COUNT; i++) {
+            if (sink->pixmap_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; i<MAX_PIXMAP_COUNT; i++) {
+        sink->pixmap_pool[i] = NULL;
+    }
 }
old mode 100644 (file)
new mode 100755 (executable)
index a2e8bff..774bb40
@@ -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 {
old mode 100644 (file)
new mode 100755 (executable)
index 8abc784..9e80a16
@@ -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");