docs: gst-launch -> gst-launch-1.0 and ffmpegcolorspace -> videoconvert
[platform/upstream/gstreamer.git] / sys / ximage / gstximagesrc.c
index 2c2106a..df43c08 100644 (file)
@@ -30,7 +30,7 @@
  * <refsect2>
  * <title>Example pipelines</title>
  * |[
- * gst-launch ximagesrc ! video/x-raw-rgb,framerate=5/1 ! ffmpegcolorspace ! theoraenc ! oggmux ! filesink location=desktop.ogg
+ * gst-launch-1.0 ximagesrc ! video/x-raw,framerate=5/1 ! videoconvert ! theoraenc ! oggmux ! filesink location=desktop.ogg
  * ]| Encodes your X display to an Ogg theora video at 5 frames per second.
  * </refsect2>
  */
 
 #include <gst/gst.h>
 #include <gst/gst-i18n-plugin.h>
+#include <gst/video/video.h>
+
+#include "gst/glib-compat-private.h"
 
 GST_DEBUG_CATEGORY_STATIC (gst_debug_ximage_src);
 #define GST_CAT_DEFAULT gst_debug_ximage_src
 
 static GstStaticPadTemplate t =
 GST_STATIC_PAD_TEMPLATE ("src", GST_PAD_SRC, GST_PAD_ALWAYS,
-    GST_STATIC_CAPS ("video/x-raw-rgb, "
+    GST_STATIC_CAPS ("video/x-raw, "
         "framerate = (fraction) [ 0, MAX ], "
         "width = (int) [ 1, MAX ], " "height = (int) [ 1, MAX ], "
         "pixel-aspect-ratio = (fraction) [ 0, MAX ]"));
@@ -71,11 +74,14 @@ enum
   PROP_ENDX,
   PROP_ENDY,
   PROP_REMOTE,
+  PROP_XID,
+  PROP_XNAME,
 };
 
-GST_BOILERPLATE (GstXImageSrc, gst_ximage_src, GstPushSrc, GST_TYPE_PUSH_SRC);
+#define gst_ximage_src_parent_class parent_class
+G_DEFINE_TYPE (GstXImageSrc, gst_ximage_src, GST_TYPE_PUSH_SRC);
 
-static void gst_ximage_src_fixate (GstPad * pad, GstCaps * caps);
+static GstCaps *gst_ximage_src_fixate (GstBaseSrc * bsrc, GstCaps * caps);
 static void gst_ximage_src_clear_bufpool (GstXImageSrc * ximagesrc);
 
 /* Called when a buffer is returned from the pipeline */
@@ -89,18 +95,48 @@ gst_ximage_src_return_buf (GstXImageSrc * ximagesrc, GstBuffer * ximage)
     GST_DEBUG_OBJECT (ximagesrc,
         "destroy image %p as its size changed %dx%d vs current %dx%d",
         ximage, meta->width, meta->height, ximagesrc->width, ximagesrc->height);
-    g_mutex_lock (ximagesrc->x_lock);
+    g_mutex_lock (&ximagesrc->x_lock);
     gst_ximageutil_ximage_destroy (ximagesrc->xcontext, ximage);
-    g_mutex_unlock (ximagesrc->x_lock);
+    g_mutex_unlock (&ximagesrc->x_lock);
   } else {
     /* In that case we can reuse the image and add it to our image pool. */
     GST_LOG_OBJECT (ximagesrc, "recycling image %p in pool", ximage);
     /* need to increment the refcount again to recycle */
     gst_buffer_ref (ximage);
-    g_mutex_lock (ximagesrc->pool_lock);
+    g_mutex_lock (&ximagesrc->pool_lock);
+    GST_BUFFER_FLAGS (GST_BUFFER (ximage)) = 0; /* clear out any flags from the previous use */
     ximagesrc->buffer_pool = g_slist_prepend (ximagesrc->buffer_pool, ximage);
-    g_mutex_unlock (ximagesrc->pool_lock);
+    g_mutex_unlock (&ximagesrc->pool_lock);
+  }
+}
+
+static Window
+gst_ximage_src_find_window (GstXImageSrc * src, Window root, const char *name)
+{
+  Window *children;
+  Window window = 0, root_return, parent_return;
+  unsigned int nchildren;
+  char *tmpname;
+  int n, status;
+
+  status = XFetchName (src->xcontext->disp, root, &tmpname);
+  if (status && !strcmp (name, tmpname))
+    return root;
+
+  status =
+      XQueryTree (src->xcontext->disp, root, &root_return, &parent_return,
+      &children, &nchildren);
+  if (!status || !children)
+    return (Window) 0;
+
+  for (n = 0; n < nchildren; ++n) {
+    window = gst_ximage_src_find_window (src, children[n], name);
+    if (window != 0)
+      break;
   }
+
+  XFree (children);
+  return window;
 }
 
 static gboolean
@@ -111,10 +147,10 @@ gst_ximage_src_open_display (GstXImageSrc * s, const gchar * name)
   if (s->xcontext != NULL)
     return TRUE;
 
-  g_mutex_lock (s->x_lock);
+  g_mutex_lock (&s->x_lock);
   s->xcontext = ximageutil_xcontext_get (GST_ELEMENT (s), name);
   if (s->xcontext == NULL) {
-    g_mutex_unlock (s->x_lock);
+    g_mutex_unlock (&s->x_lock);
     GST_ELEMENT_ERROR (s, RESOURCE, OPEN_READ,
         ("Could not open X display for reading"),
         ("NULL returned from getting xcontext"));
@@ -123,8 +159,51 @@ gst_ximage_src_open_display (GstXImageSrc * s, const gchar * name)
   s->width = s->xcontext->width;
   s->height = s->xcontext->height;
 
-  /* Always capture root window, for now */
   s->xwindow = s->xcontext->root;
+  if (s->xid != 0 || s->xname) {
+    int status;
+    XWindowAttributes attrs;
+    Window window;
+
+    if (s->xid != 0) {
+      status = XGetWindowAttributes (s->xcontext->disp, s->xid, &attrs);
+      if (status) {
+        GST_DEBUG_OBJECT (s, "Found window XID %" G_GUINT64_FORMAT, s->xid);
+        s->xwindow = s->xid;
+        goto window_found;
+      } else {
+        GST_WARNING_OBJECT (s, "Failed to get window %" G_GUINT64_FORMAT
+            " attributes", s->xid);
+      }
+    }
+
+    if (s->xname) {
+      GST_DEBUG_OBJECT (s, "Looking for window %s", s->xname);
+      window = gst_ximage_src_find_window (s, s->xcontext->root, s->xname);
+      if (window != 0) {
+        GST_DEBUG_OBJECT (s, "Found window named %s, ", s->xname);
+        status = XGetWindowAttributes (s->xcontext->disp, window, &attrs);
+        if (status) {
+          s->xwindow = window;
+          goto window_found;
+        } else {
+          GST_WARNING_OBJECT (s, "Failed to get window attributes for "
+              "window named %s", s->xname);
+        }
+      }
+    }
+
+    GST_INFO_OBJECT (s, "Using root window");
+    goto use_root_window;
+
+  window_found:
+    g_assert (s->xwindow != 0);
+    s->width = attrs.width;
+    s->height = attrs.height;
+    GST_INFO_OBJECT (s, "Using default window size of %dx%d",
+        s->width, s->height);
+  }
+use_root_window:
 
 #ifdef HAVE_XFIXES
   /* check if xfixes supported */
@@ -181,7 +260,7 @@ gst_ximage_src_open_display (GstXImageSrc * s, const gchar * name)
 #endif
 #endif
 
-  g_mutex_unlock (s->x_lock);
+  g_mutex_unlock (&s->x_lock);
 
   if (s->xcontext == NULL)
     return FALSE;
@@ -223,7 +302,7 @@ gst_ximage_src_stop (GstBaseSrc * basesrc)
 #endif
 
   if (src->xcontext) {
-    g_mutex_lock (src->x_lock);
+    g_mutex_lock (&src->x_lock);
 
 #ifdef HAVE_XDAMAGE
     if (src->damage_copy_gc != None) {
@@ -242,7 +321,7 @@ gst_ximage_src_stop (GstBaseSrc * basesrc)
 
     ximageutil_xcontext_clear (src->xcontext);
     src->xcontext = NULL;
-    g_mutex_unlock (src->x_lock);
+    g_mutex_unlock (&src->x_lock);
   }
 
   return TRUE;
@@ -355,6 +434,18 @@ composite_pixel (GstXContext * xcontext, guchar * dest, guchar * src)
 }
 #endif
 
+#ifdef HAVE_XDAMAGE
+static void
+copy_buffer (GstBuffer * dest, GstBuffer * src)
+{
+  GstMapInfo map;
+
+  gst_buffer_map (src, &map, GST_MAP_READ);
+  gst_buffer_fill (dest, 0, map.data, map.size);
+  gst_buffer_unmap (src, &map);
+}
+#endif
+
 /* Retrieve an XImageSrcBuffer, preferably from our
  * pool of existing images and populate it from the window */
 static GstBuffer *
@@ -363,7 +454,7 @@ gst_ximage_src_ximage_get (GstXImageSrc * ximagesrc)
   GstBuffer *ximage = NULL;
   GstMetaXImage *meta;
 
-  g_mutex_lock (ximagesrc->pool_lock);
+  g_mutex_lock (&ximagesrc->pool_lock);
   while (ximagesrc->buffer_pool != NULL) {
     ximage = ximagesrc->buffer_pool->data;
 
@@ -377,16 +468,13 @@ gst_ximage_src_ximage_get (GstXImageSrc * ximagesrc)
     ximagesrc->buffer_pool = g_slist_delete_link (ximagesrc->buffer_pool,
         ximagesrc->buffer_pool);
   }
-  g_mutex_unlock (ximagesrc->pool_lock);
+  g_mutex_unlock (&ximagesrc->pool_lock);
 
   if (ximage == NULL) {
-    GstXContext *xcontext;
-    GstCaps *caps = NULL;
-
     GST_DEBUG_OBJECT (ximagesrc, "creating image (%dx%d)",
         ximagesrc->width, ximagesrc->height);
 
-    g_mutex_lock (ximagesrc->x_lock);
+    g_mutex_lock (&ximagesrc->x_lock);
     ximage = gst_ximageutil_ximage_new (ximagesrc->xcontext,
         GST_ELEMENT (ximagesrc), ximagesrc->width, ximagesrc->height,
         (BufferReturnFunc) (gst_ximage_src_return_buf));
@@ -394,31 +482,11 @@ gst_ximage_src_ximage_get (GstXImageSrc * ximagesrc)
       GST_ELEMENT_ERROR (ximagesrc, RESOURCE, WRITE, (NULL),
           ("could not create a %dx%d ximage", ximagesrc->width,
               ximagesrc->height));
-      g_mutex_unlock (ximagesrc->x_lock);
+      g_mutex_unlock (&ximagesrc->x_lock);
       return NULL;
     }
 
-    xcontext = ximagesrc->xcontext;
-
-
-    caps = gst_caps_new_simple ("video/x-raw-rgb",
-        "bpp", G_TYPE_INT, xcontext->bpp,
-        "depth", G_TYPE_INT, xcontext->depth,
-        "endianness", G_TYPE_INT, xcontext->endianness,
-        "red_mask", G_TYPE_INT, xcontext->r_mask_output,
-        "green_mask", G_TYPE_INT, xcontext->g_mask_output,
-        "blue_mask", G_TYPE_INT, xcontext->b_mask_output,
-        "width", G_TYPE_INT, ximagesrc->width,
-        "height", G_TYPE_INT, ximagesrc->height,
-        "framerate", GST_TYPE_FRACTION, ximagesrc->fps_n, ximagesrc->fps_d,
-        "pixel-aspect-ratio", GST_TYPE_FRACTION,
-        gst_value_get_fraction_numerator (xcontext->par),
-        gst_value_get_fraction_denominator (xcontext->par), NULL);
-
-    gst_buffer_set_caps (ximage, caps);
-    g_mutex_unlock (ximagesrc->x_lock);
-
-    gst_caps_unref (caps);
+    g_mutex_unlock (&ximagesrc->x_lock);
   }
 
   g_return_val_if_fail (GST_IS_XIMAGE_SRC (ximagesrc), NULL);
@@ -454,11 +522,9 @@ gst_ximage_src_ximage_get (GstXImageSrc * ximagesrc)
 
           if (!have_frame) {
             GST_LOG_OBJECT (ximagesrc,
-                "Copying from last frame ximage->size: %d",
-                GST_BUFFER_SIZE (GST_BUFFER (ximage)));
-            memcpy (GST_BUFFER_DATA (GST_BUFFER (ximage)),
-                GST_BUFFER_DATA (GST_BUFFER (ximagesrc->last_ximage)),
-                GST_BUFFER_SIZE (GST_BUFFER (ximage)));
+                "Copying from last frame ximage->size: %" G_GSIZE_FORMAT,
+                gst_buffer_get_size (ximage));
+            copy_buffer (ximage, ximagesrc->last_ximage);
             have_frame = TRUE;
           }
           for (i = 0; i < nrects; i++) {
@@ -518,11 +584,9 @@ gst_ximage_src_ximage_get (GstXImageSrc * ximagesrc)
     } while (XPending (ximagesrc->xcontext->disp));
     if (!have_frame) {
       GST_LOG_OBJECT (ximagesrc,
-          "Copying from last frame ximage->size: %d",
-          GST_BUFFER_SIZE (GST_BUFFER (ximage)));
-      memcpy (GST_BUFFER_DATA (GST_BUFFER (ximage)),
-          GST_BUFFER_DATA (GST_BUFFER (ximagesrc->last_ximage)),
-          GST_BUFFER_SIZE (GST_BUFFER (ximage)));
+          "Copying from last frame ximage->size: %" G_GSIZE_FORMAT,
+          gst_buffer_get_size (ximage));
+      copy_buffer (ximage, ximagesrc->last_ximage);
     }
 #ifdef HAVE_XFIXES
     /* re-get area where last mouse pointer was  but only if in our clipping
@@ -698,9 +762,9 @@ gst_ximage_src_ximage_get (GstXImageSrc * ximagesrc)
 #ifdef HAVE_XDAMAGE
   if (ximagesrc->have_xdamage && ximagesrc->use_damage) {
     /* need to ref ximage to put in last_ximage */
-    gst_buffer_ref (GST_BUFFER (ximage));
+    gst_buffer_ref (ximage);
     if (ximagesrc->last_ximage) {
-      gst_buffer_unref (GST_BUFFER (ximagesrc->last_ximage));
+      gst_buffer_unref (ximagesrc->last_ximage);
     }
     ximagesrc->last_ximage = ximage;
     GST_LOG_OBJECT (ximagesrc, "reffing current buffer for last_ximage");
@@ -775,7 +839,7 @@ gst_ximage_src_create (GstPushSrc * bs, GstBuffer ** buf)
     if (ret == GST_CLOCK_UNSCHEDULED) {
       /* Got woken up by the unlock function */
       GST_OBJECT_UNLOCK (s);
-      return GST_FLOW_WRONG_STATE;
+      return GST_FLOW_FLUSHING;
     }
     /* Duration is a complete 1/fps frame duration */
     dur = gst_util_uint64_scale_int (GST_SECOND, s->fps_d, s->fps_n);
@@ -797,7 +861,7 @@ gst_ximage_src_create (GstPushSrc * bs, GstBuffer ** buf)
   if (!image)
     return GST_FLOW_ERROR;
 
-  *buf = GST_BUFFER (image);
+  *buf = image;
   GST_BUFFER_TIMESTAMP (*buf) = next_capture_ts;
   GST_BUFFER_DURATION (*buf) = dur;
 
@@ -840,6 +904,21 @@ gst_ximage_src_set_property (GObject * object, guint prop_id,
     case PROP_REMOTE:
       src->remote = g_value_get_boolean (value);
       break;
+    case PROP_XID:
+      if (src->xcontext != NULL) {
+        g_warning ("ximagesrc window ID must be set before opening display");
+        break;
+      }
+      src->xid = g_value_get_uint64 (value);
+      break;
+    case PROP_XNAME:
+      if (src->xcontext != NULL) {
+        g_warning ("ximagesrc window name must be set before opening display");
+        break;
+      }
+      g_free (src->xname);
+      src->xname = g_strdup (g_value_get_string (value));
+      break;
     default:
       break;
   }
@@ -883,6 +962,12 @@ gst_ximage_src_get_property (GObject * object, guint prop_id, GValue * value,
     case PROP_REMOTE:
       g_value_set_boolean (value, src->remote);
       break;
+    case PROP_XID:
+      g_value_set_uint64 (value, src->xid);
+      break;
+    case PROP_XNAME:
+      g_value_set_string (value, src->xname);
+      break;
     default:
       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
       break;
@@ -892,7 +977,7 @@ gst_ximage_src_get_property (GObject * object, guint prop_id, GValue * value,
 static void
 gst_ximage_src_clear_bufpool (GstXImageSrc * ximagesrc)
 {
-  g_mutex_lock (ximagesrc->pool_lock);
+  g_mutex_lock (&ximagesrc->pool_lock);
   while (ximagesrc->buffer_pool != NULL) {
     GstBuffer *ximage = ximagesrc->buffer_pool->data;
 
@@ -901,21 +986,7 @@ gst_ximage_src_clear_bufpool (GstXImageSrc * ximagesrc)
     ximagesrc->buffer_pool = g_slist_delete_link (ximagesrc->buffer_pool,
         ximagesrc->buffer_pool);
   }
-  g_mutex_unlock (ximagesrc->pool_lock);
-}
-
-static void
-gst_ximage_src_base_init (gpointer g_class)
-{
-  GstElementClass *ec = GST_ELEMENT_CLASS (g_class);
-
-  gst_element_class_set_details_simple (ec, "Ximage video source",
-      "Source/Video",
-      "Creates a screenshot video stream",
-      "Lutz Mueller <lutz@users.sourceforge.net>, "
-      "Jan Schmidt <thaytan@mad.scientist.com>, "
-      "Zaheer Merali <zaheerabbas at merali dot org>");
-  gst_element_class_add_pad_template (ec, gst_static_pad_template_get (&t));
+  g_mutex_unlock (&ximagesrc->pool_lock);
 }
 
 static void
@@ -935,33 +1006,38 @@ gst_ximage_src_finalize (GObject * object)
   if (src->xcontext)
     ximageutil_xcontext_clear (src->xcontext);
 
-  g_mutex_free (src->pool_lock);
-  g_mutex_free (src->x_lock);
+  g_free (src->xname);
+  g_mutex_clear (&src->pool_lock);
+  g_mutex_clear (&src->x_lock);
 
   G_OBJECT_CLASS (parent_class)->finalize (object);
 }
 
 static GstCaps *
-gst_ximage_src_get_caps (GstBaseSrc * bs)
+gst_ximage_src_get_caps (GstBaseSrc * bs, GstCaps * filter)
 {
   GstXImageSrc *s = GST_XIMAGE_SRC (bs);
   GstXContext *xcontext;
   gint width, height;
+  GstVideoFormat format;
 
   if ((!s->xcontext) && (!gst_ximage_src_open_display (s, s->display_name)))
-    return
-        gst_caps_copy (gst_pad_get_pad_template_caps (GST_BASE_SRC
-            (s)->srcpad));
+    return gst_pad_get_pad_template_caps (GST_BASE_SRC (s)->srcpad);
 
   if (!gst_ximage_src_recalc (s))
-    return
-        gst_caps_copy (gst_pad_get_pad_template_caps (GST_BASE_SRC
-            (s)->srcpad));
+    return gst_pad_get_pad_template_caps (GST_BASE_SRC (s)->srcpad);
 
   xcontext = s->xcontext;
-
-  width = xcontext->width;
-  height = xcontext->height;
+  width = s->xcontext->width;
+  height = s->xcontext->height;
+  if (s->xwindow != 0) {
+    XWindowAttributes attrs;
+    int status = XGetWindowAttributes (s->xcontext->disp, s->xwindow, &attrs);
+    if (status) {
+      width = attrs.width;
+      height = attrs.height;
+    }
+  }
 
   /* property comments say 0 means right/bottom, means we can't capture
      the top left pixel alone */
@@ -973,8 +1049,7 @@ gst_ximage_src_get_caps (GstBaseSrc * bs)
   if (s->endx >= s->startx && s->endy >= s->starty) {
     /* this means user has put in values */
     if (s->startx < xcontext->width && s->endx < xcontext->width &&
-        s->starty < xcontext->height && s->endy < xcontext->height &&
-        s->startx >= 0 && s->starty >= 0) {
+        s->starty < xcontext->height && s->endy < xcontext->height) {
       /* values are fine */
       s->width = width = s->endx - s->startx + 1;
       s->height = height = s->endy - s->starty + 1;
@@ -994,13 +1069,14 @@ gst_ximage_src_get_caps (GstBaseSrc * bs)
     s->endy = height - 1;
   }
   GST_DEBUG ("width = %d, height=%d", width, height);
-  return gst_caps_new_simple ("video/x-raw-rgb",
-      "bpp", G_TYPE_INT, xcontext->bpp,
-      "depth", G_TYPE_INT, xcontext->depth,
-      "endianness", G_TYPE_INT, xcontext->endianness,
-      "red_mask", G_TYPE_INT, xcontext->r_mask_output,
-      "green_mask", G_TYPE_INT, xcontext->g_mask_output,
-      "blue_mask", G_TYPE_INT, xcontext->b_mask_output,
+
+  format =
+      gst_video_format_from_masks (xcontext->depth, xcontext->bpp,
+      xcontext->endianness, xcontext->r_mask_output, xcontext->g_mask_output,
+      xcontext->b_mask_output, 0);
+
+  return gst_caps_new_simple ("video/x-raw",
+      "format", G_TYPE_STRING, gst_video_format_to_string (format),
       "width", G_TYPE_INT, width,
       "height", G_TYPE_INT, height,
       "framerate", GST_TYPE_FRACTION_RANGE, 1, G_MAXINT, G_MAXINT, 1,
@@ -1034,23 +1110,29 @@ gst_ximage_src_set_caps (GstBaseSrc * bs, GstCaps * caps)
   return TRUE;
 }
 
-static void
-gst_ximage_src_fixate (GstPad * pad, GstCaps * caps)
+static GstCaps *
+gst_ximage_src_fixate (GstBaseSrc * bsrc, GstCaps * caps)
 {
   gint i;
   GstStructure *structure;
 
+  caps = gst_caps_make_writable (caps);
+
   for (i = 0; i < gst_caps_get_size (caps); ++i) {
     structure = gst_caps_get_structure (caps, i);
 
     gst_structure_fixate_field_nearest_fraction (structure, "framerate", 25, 1);
   }
+  caps = GST_BASE_SRC_CLASS (parent_class)->fixate (bsrc, caps);
+
+  return caps;
 }
 
 static void
 gst_ximage_src_class_init (GstXImageSrcClass * klass)
 {
   GObjectClass *gc = G_OBJECT_CLASS (klass);
+  GstElementClass *ec = GST_ELEMENT_CLASS (klass);
   GstBaseSrcClass *bc = GST_BASE_SRC_CLASS (klass);
   GstPushSrcClass *push_class = GST_PUSH_SRC_CLASS (klass);
 
@@ -1141,27 +1223,54 @@ gst_ximage_src_class_init (GstXImageSrcClass * klass)
       g_param_spec_boolean ("remote", "Remote dispay",
           "Whether the display is remote", FALSE,
           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+  /**
+   * GstXImageSrc:xid
+   *
+   * The XID of the window to capture. 0 for the root window (default).
+   *
+   * Since: 0.10.31
+   **/
+  g_object_class_install_property (gc, PROP_XID,
+      g_param_spec_uint64 ("xid", "Window XID",
+          "Window XID to capture from", 0, G_MAXUINT64, 0,
+          G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+  /**
+   * GstXImageSrc:xname
+   *
+   * The name of the window to capture, if any.
+   *
+   * Since: 0.10.31
+   **/
+  g_object_class_install_property (gc, PROP_XNAME,
+      g_param_spec_string ("xname", "Window name",
+          "Window name to capture from", NULL,
+          G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
 
-  parent_class = g_type_class_peek_parent (klass);
+  gst_element_class_set_static_metadata (ec, "Ximage video source",
+      "Source/Video",
+      "Creates a screenshot video stream",
+      "Lutz Mueller <lutz@users.sourceforge.net>, "
+      "Jan Schmidt <thaytan@mad.scientist.com>, "
+      "Zaheer Merali <zaheerabbas at merali dot org>");
+  gst_element_class_add_pad_template (ec, gst_static_pad_template_get (&t));
 
-  push_class->create = gst_ximage_src_create;
+  bc->fixate = gst_ximage_src_fixate;
   bc->get_caps = gst_ximage_src_get_caps;
   bc->set_caps = gst_ximage_src_set_caps;
   bc->start = gst_ximage_src_start;
   bc->stop = gst_ximage_src_stop;
   bc->unlock = gst_ximage_src_unlock;
+  push_class->create = gst_ximage_src_create;
 }
 
 static void
-gst_ximage_src_init (GstXImageSrc * ximagesrc, GstXImageSrcClass * klass)
+gst_ximage_src_init (GstXImageSrc * ximagesrc)
 {
   gst_base_src_set_format (GST_BASE_SRC (ximagesrc), GST_FORMAT_TIME);
   gst_base_src_set_live (GST_BASE_SRC (ximagesrc), TRUE);
-  gst_pad_set_fixatecaps_function (GST_BASE_SRC_PAD (ximagesrc),
-      gst_ximage_src_fixate);
 
-  ximagesrc->pool_lock = g_mutex_new ();
-  ximagesrc->x_lock = g_mutex_new ();
+  g_mutex_init (&ximagesrc->pool_lock);
+  g_mutex_init (&ximagesrc->x_lock);
   ximagesrc->show_pointer = TRUE;
   ximagesrc->use_damage = TRUE;
   ximagesrc->startx = 0;
@@ -1187,6 +1296,6 @@ plugin_init (GstPlugin * plugin)
 
 GST_PLUGIN_DEFINE (GST_VERSION_MAJOR,
     GST_VERSION_MINOR,
-    "ximagesrc",
+    ximagesrc,
     "X11 video input plugin using standard Xlib calls",
     plugin_init, VERSION, GST_LICENSE, GST_PACKAGE_NAME, GST_PACKAGE_ORIGIN);