]> Gitweb @ Texas Instruments - Open Source Git Repositories - git.TI.com/gitweb - glsdk/gstreamer0-10.git/blobdiff - plugins/elements/gstfakesrc.c
fakesrc: Make event/buffer verbose output consistent with identity and print buffer...
[glsdk/gstreamer0-10.git] / plugins / elements / gstfakesrc.c
index fcb00366760efce7165e7d6ddf1dad4e0f8b1e19..8ba1b0998be9aa888223f88f76140e5986ffb8d7 100644 (file)
@@ -1,8 +1,8 @@
 /* GStreamer
  * Copyright (C) 1999,2000 Erik Walthinsen <omega@cse.ogi.edu>
- *                    2000 Wim Taymans <wtay@chello.be>
+ *                    2000 Wim Taymans <wim@fluendo.com>
  *
- * gstfakesrc.c: 
+ * gstfakesrc.c:
  *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Library General Public
  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
  * Boston, MA 02111-1307, USA.
  */
+/**
+ * SECTION:element-fakesrc
+ * @see_also: #GstFakeSink
+ *
+ * The fakesrc element is a multipurpose element that can generate
+ * a wide range of buffers and can operate in various scheduling modes.
+ *
+ * It is mostly used as a testing element, one trivial example for testing
+ * basic <application>GStreamer</application> core functionality is:
+ *
+ * <refsect2>
+ * <title>Example launch line</title>
+ * |[
+ * gst-launch -v fakesrc num-buffers=5 ! fakesink
+ * ]| This pipeline will push 5 empty buffers to the fakesink element and then
+ * sends an EOS.
+ * </refsect2>
+ *
+ * Last reviewed on 2008-06-20 (0.10.21)
+ */
 
-
-#include <stdlib.h>
-#include <string.h>
+/* FIXME: this ignores basesrc::blocksize property, which could be used as an
+ * alias to ::sizemax (see gst_base_src_get_blocksize()).
+ */
 
 #ifdef HAVE_CONFIG_H
 #  include "config.h"
 #endif
 
+#include <stdlib.h>
+#include <string.h>
+
 #include "gstfakesrc.h"
 #include <gst/gstmarshal.h>
 
-#define DEFAULT_SIZEMIN                0
-#define DEFAULT_SIZEMAX                4096
-#define DEFAULT_PARENTSIZE     4096*10
-
-GST_DEBUG_CATEGORY_STATIC (gst_fakesrc_debug);
-#define GST_CAT_DEFAULT gst_fakesrc_debug
-
-GstElementDetails gst_fakesrc_details = GST_ELEMENT_DETAILS ("Fake Source",
-    "Source",
-    "Push empty (no data) buffers around",
-    "Erik Walthinsen <omega@cse.ogi.edu>, "
-    "Wim Taymans <wim.taymans@chello.be>");
+static GstStaticPadTemplate srctemplate = GST_STATIC_PAD_TEMPLATE ("src",
+    GST_PAD_SRC,
+    GST_PAD_ALWAYS,
+    GST_STATIC_CAPS_ANY);
 
+GST_DEBUG_CATEGORY_STATIC (gst_fake_src_debug);
+#define GST_CAT_DEFAULT gst_fake_src_debug
 
 /* FakeSrc signals and args */
 enum
@@ -53,46 +70,64 @@ enum
   LAST_SIGNAL
 };
 
+#define DEFAULT_OUTPUT          FAKE_SRC_FIRST_LAST_LOOP
+#define DEFAULT_DATA            FAKE_SRC_DATA_ALLOCATE
+#define DEFAULT_SIZETYPE        FAKE_SRC_SIZETYPE_EMPTY
+#define DEFAULT_SIZEMIN         0
+#define DEFAULT_SIZEMAX         4096
+#define DEFAULT_FILLTYPE        FAKE_SRC_FILLTYPE_ZERO
+#define DEFAULT_DATARATE        0
+#define DEFAULT_SYNC            FALSE
+#define DEFAULT_PATTERN         NULL
+#define DEFAULT_EOS             FALSE
+#define DEFAULT_SIGNAL_HANDOFFS FALSE
+#define DEFAULT_SILENT          FALSE
+#define DEFAULT_DUMP            FALSE
+#define DEFAULT_PARENTSIZE      4096*10
+#define DEFAULT_CAN_ACTIVATE_PULL TRUE
+#define DEFAULT_CAN_ACTIVATE_PUSH TRUE
+#define DEFAULT_FORMAT          GST_FORMAT_BYTES
+
 enum
 {
-  ARG_0,
-  ARG_NUM_SOURCES,
-  ARG_LOOP_BASED,
-  ARG_OUTPUT,
-  ARG_DATA,
-  ARG_SIZETYPE,
-  ARG_SIZEMIN,
-  ARG_SIZEMAX,
-  ARG_FILLTYPE,
-  ARG_PATTERN,
-  ARG_NUM_BUFFERS,
-  ARG_EOS,
-  ARG_SIGNAL_HANDOFFS,
-  ARG_SILENT,
-  ARG_DUMP,
-  ARG_PARENTSIZE,
-  ARG_LAST_MESSAGE
+  PROP_0,
+  PROP_OUTPUT,
+  PROP_DATA,
+  PROP_SIZETYPE,
+  PROP_SIZEMIN,
+  PROP_SIZEMAX,
+  PROP_FILLTYPE,
+  PROP_DATARATE,
+  PROP_SYNC,
+  PROP_PATTERN,
+  PROP_EOS,
+  PROP_SIGNAL_HANDOFFS,
+  PROP_SILENT,
+  PROP_DUMP,
+  PROP_PARENTSIZE,
+  PROP_LAST_MESSAGE,
+  PROP_CAN_ACTIVATE_PULL,
+  PROP_CAN_ACTIVATE_PUSH,
+  PROP_IS_LIVE,
+  PROP_FORMAT,
+  PROP_LAST,
 };
 
-GstStaticPadTemplate fakesrc_src_template = GST_STATIC_PAD_TEMPLATE ("src%d",
-    GST_PAD_SRC,
-    GST_PAD_REQUEST,
-    GST_STATIC_CAPS_ANY);
-
-#define GST_TYPE_FAKESRC_OUTPUT (gst_fakesrc_output_get_type())
+/* not implemented
+#define GST_TYPE_FAKE_SRC_OUTPUT (gst_fake_src_output_get_type())
 static GType
-gst_fakesrc_output_get_type (void)
+gst_fake_src_output_get_type (void)
 {
   static GType fakesrc_output_type = 0;
-  static GEnumValue fakesrc_output[] = {
-    {FAKESRC_FIRST_LAST_LOOP, "1", "First-Last loop"},
-    {FAKESRC_LAST_FIRST_LOOP, "2", "Last-First loop"},
-    {FAKESRC_PING_PONG, "3", "Ping-Pong"},
-    {FAKESRC_ORDERED_RANDOM, "4", "Ordered Random"},
-    {FAKESRC_RANDOM, "5", "Random"},
-    {FAKESRC_PATTERN_LOOP, "6", "Patttern loop"},
-    {FAKESRC_PING_PONG_PATTERN, "7", "Ping-Pong Pattern"},
-    {FAKESRC_GET_ALWAYS_SUCEEDS, "8", "'_get' Always succeeds"},
+  static const GEnumValue fakesrc_output[] = {
+    {FAKE_SRC_FIRST_LAST_LOOP, "1", "First-Last loop"},
+    {FAKE_SRC_LAST_FIRST_LOOP, "2", "Last-First loop"},
+    {FAKE_SRC_PING_PONG, "3", "Ping-Pong"},
+    {FAKE_SRC_ORDERED_RANDOM, "4", "Ordered Random"},
+    {FAKE_SRC_RANDOM, "5", "Random"},
+    {FAKE_SRC_PATTERN_LOOP, "6", "Patttern loop"},
+    {FAKE_SRC_PING_PONG_PATTERN, "7", "Ping-Pong Pattern"},
+    {FAKE_SRC_GET_ALWAYS_SUCEEDS, "8", "'_get' Always succeeds"},
     {0, NULL, NULL},
   };
 
@@ -102,34 +137,36 @@ gst_fakesrc_output_get_type (void)
   }
   return fakesrc_output_type;
 }
+*/
 
-#define GST_TYPE_FAKESRC_DATA (gst_fakesrc_data_get_type())
+#define GST_TYPE_FAKE_SRC_DATA (gst_fake_src_data_get_type())
 static GType
-gst_fakesrc_data_get_type (void)
+gst_fake_src_data_get_type (void)
 {
   static GType fakesrc_data_type = 0;
-  static GEnumValue fakesrc_data[] = {
-    {FAKESRC_DATA_ALLOCATE, "1", "Allocate data"},
-    {FAKESRC_DATA_SUBBUFFER, "2", "Subbuffer data"},
+  static const GEnumValue fakesrc_data[] = {
+    {FAKE_SRC_DATA_ALLOCATE, "Allocate data", "allocate"},
+    {FAKE_SRC_DATA_SUBBUFFER, "Subbuffer data", "subbuffer"},
     {0, NULL, NULL},
   };
 
   if (!fakesrc_data_type) {
-    fakesrc_data_type = g_enum_register_static ("GstFakeSrcData", fakesrc_data);
+    fakesrc_data_type =
+        g_enum_register_static ("GstFakeSrcDataType", fakesrc_data);
   }
   return fakesrc_data_type;
 }
 
-#define GST_TYPE_FAKESRC_SIZETYPE (gst_fakesrc_sizetype_get_type())
+#define GST_TYPE_FAKE_SRC_SIZETYPE (gst_fake_src_sizetype_get_type())
 static GType
-gst_fakesrc_sizetype_get_type (void)
+gst_fake_src_sizetype_get_type (void)
 {
   static GType fakesrc_sizetype_type = 0;
-  static GEnumValue fakesrc_sizetype[] = {
-    {FAKESRC_SIZETYPE_NULL, "1", "Send empty buffers"},
-    {FAKESRC_SIZETYPE_FIXED, "2", "Fixed size buffers (sizemax sized)"},
-    {FAKESRC_SIZETYPE_RANDOM, "3",
-        "Random sized buffers (sizemin <= size <= sizemax)"},
+  static const GEnumValue fakesrc_sizetype[] = {
+    {FAKE_SRC_SIZETYPE_EMPTY, "Send empty buffers", "empty"},
+    {FAKE_SRC_SIZETYPE_FIXED, "Fixed size buffers (sizemax sized)", "fixed"},
+    {FAKE_SRC_SIZETYPE_RANDOM,
+        "Random sized buffers (sizemin <= size <= sizemax)", "random"},
     {0, NULL, NULL},
   };
 
@@ -140,18 +177,20 @@ gst_fakesrc_sizetype_get_type (void)
   return fakesrc_sizetype_type;
 }
 
-#define GST_TYPE_FAKESRC_FILLTYPE (gst_fakesrc_filltype_get_type())
+#define GST_TYPE_FAKE_SRC_FILLTYPE (gst_fake_src_filltype_get_type())
 static GType
-gst_fakesrc_filltype_get_type (void)
+gst_fake_src_filltype_get_type (void)
 {
   static GType fakesrc_filltype_type = 0;
-  static GEnumValue fakesrc_filltype[] = {
-    {FAKESRC_FILLTYPE_NOTHING, "1", "Leave data as malloced"},
-    {FAKESRC_FILLTYPE_NULL, "2", "Fill buffers with zeros"},
-    {FAKESRC_FILLTYPE_RANDOM, "3", "Fill buffers with random crap"},
-    {FAKESRC_FILLTYPE_PATTERN, "4", "Fill buffers with pattern 0x00 -> 0xff"},
-    {FAKESRC_FILLTYPE_PATTERN_CONT, "5",
-        "Fill buffers with pattern 0x00 -> 0xff that spans buffers"},
+  static const GEnumValue fakesrc_filltype[] = {
+    {FAKE_SRC_FILLTYPE_NOTHING, "Leave data as malloced", "nothing"},
+    {FAKE_SRC_FILLTYPE_ZERO, "Fill buffers with zeros", "zero"},
+    {FAKE_SRC_FILLTYPE_RANDOM, "Fill buffers with random crap", "random"},
+    {FAKE_SRC_FILLTYPE_PATTERN, "Fill buffers with pattern 0x00 -> 0xff",
+        "pattern"},
+    {FAKE_SRC_FILLTYPE_PATTERN_CONT,
+          "Fill buffers with pattern 0x00 -> 0xff that spans buffers",
+        "pattern-span"},
     {0, NULL, NULL},
   };
 
@@ -163,308 +202,273 @@ gst_fakesrc_filltype_get_type (void)
 }
 
 #define _do_init(bla) \
-    GST_DEBUG_CATEGORY_INIT (gst_fakesrc_debug, "fakesrc", 0, "fakesrc element");
+    GST_DEBUG_CATEGORY_INIT (gst_fake_src_debug, "fakesrc", 0, "fakesrc element");
 
-GST_BOILERPLATE_FULL (GstFakeSrc, gst_fakesrc, GstElement, GST_TYPE_ELEMENT,
+GST_BOILERPLATE_FULL (GstFakeSrc, gst_fake_src, GstBaseSrc, GST_TYPE_BASE_SRC,
     _do_init);
 
-static GstPad *gst_fakesrc_request_new_pad (GstElement * element,
-    GstPadTemplate * templ, const gchar * unused);
-static void gst_fakesrc_update_functions (GstFakeSrc * src);
-static void gst_fakesrc_set_property (GObject * object, guint prop_id,
+static void gst_fake_src_finalize (GObject * object);
+static void gst_fake_src_set_property (GObject * object, guint prop_id,
     const GValue * value, GParamSpec * pspec);
-static void gst_fakesrc_get_property (GObject * object, guint prop_id,
+static void gst_fake_src_get_property (GObject * object, guint prop_id,
     GValue * value, GParamSpec * pspec);
 
-static GstElementStateReturn gst_fakesrc_change_state (GstElement * element);
+static gboolean gst_fake_src_start (GstBaseSrc * basesrc);
+static gboolean gst_fake_src_stop (GstBaseSrc * basesrc);
+static gboolean gst_fake_src_is_seekable (GstBaseSrc * basesrc);
+
+static gboolean gst_fake_src_event_handler (GstBaseSrc * src, GstEvent * event);
+static void gst_fake_src_get_times (GstBaseSrc * basesrc, GstBuffer * buffer,
+    GstClockTime * start, GstClockTime * end);
+static GstFlowReturn gst_fake_src_create (GstBaseSrc * src, guint64 offset,
+    guint length, GstBuffer ** buf);
 
-static GstData *gst_fakesrc_get (GstPad * pad);
-static void gst_fakesrc_loop (GstElement * element);
+static guint gst_fake_src_signals[LAST_SIGNAL] = { 0 };
 
-static guint gst_fakesrc_signals[LAST_SIGNAL] = { 0 };
+static GParamSpec *pspec_last_message = NULL;
 
 static void
-gst_fakesrc_base_init (gpointer g_class)
+marshal_VOID__MINIOBJECT_OBJECT (GClosure * closure, GValue * return_value,
+    guint n_param_values, const GValue * param_values, gpointer invocation_hint,
+    gpointer marshal_data)
+{
+  typedef void (*marshalfunc_VOID__MINIOBJECT_OBJECT) (gpointer obj,
+      gpointer arg1, gpointer arg2, gpointer data2);
+  register marshalfunc_VOID__MINIOBJECT_OBJECT callback;
+  register GCClosure *cc = (GCClosure *) closure;
+  register gpointer data1, data2;
+
+  g_return_if_fail (n_param_values == 3);
+
+  if (G_CCLOSURE_SWAP_DATA (closure)) {
+    data1 = closure->data;
+    data2 = g_value_peek_pointer (param_values + 0);
+  } else {
+    data1 = g_value_peek_pointer (param_values + 0);
+    data2 = closure->data;
+  }
+  callback =
+      (marshalfunc_VOID__MINIOBJECT_OBJECT) (marshal_data ? marshal_data :
+      cc->callback);
+
+  callback (data1, gst_value_get_mini_object (param_values + 1),
+      g_value_get_object (param_values + 2), data2);
+}
+
+static void
+gst_fake_src_base_init (gpointer g_class)
 {
   GstElementClass *gstelement_class = GST_ELEMENT_CLASS (g_class);
 
-  gst_element_class_set_details (gstelement_class, &gst_fakesrc_details);
+  gst_element_class_set_details_simple (gstelement_class,
+      "Fake Source",
+      "Source",
+      "Push empty (no data) buffers around",
+      "Erik Walthinsen <omega@cse.ogi.edu>, " "Wim Taymans <wim@fluendo.com>");
   gst_element_class_add_pad_template (gstelement_class,
-      gst_static_pad_template_get (&fakesrc_src_template));
+      gst_static_pad_template_get (&srctemplate));
 }
 
 static void
-gst_fakesrc_class_init (GstFakeSrcClass * klass)
+gst_fake_src_class_init (GstFakeSrcClass * klass)
 {
   GObjectClass *gobject_class;
-  GstElementClass *gstelement_class;
+  GstBaseSrcClass *gstbase_src_class;
 
-  gobject_class = (GObjectClass *) klass;
-  gstelement_class = (GstElementClass *) klass;
+  gobject_class = G_OBJECT_CLASS (klass);
+  gstbase_src_class = GST_BASE_SRC_CLASS (klass);
 
+  gobject_class->finalize = gst_fake_src_finalize;
 
-  g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_NUM_SOURCES,
-      g_param_spec_int ("num-sources", "num-sources", "Number of sources",
-          1, G_MAXINT, 1, G_PARAM_READABLE));
-  g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_LOOP_BASED,
-      g_param_spec_boolean ("loop-based", "loop-based",
-          "Enable loop-based operation", FALSE, G_PARAM_READWRITE));
-  g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_OUTPUT,
+  gobject_class->set_property = gst_fake_src_set_property;
+  gobject_class->get_property = gst_fake_src_get_property;
+
+/*
+  FIXME: this is not implemented; would make sense once basesrc and fakesrc
+  support multiple pads
+  g_object_class_install_property (gobject_class, PROP_OUTPUT,
       g_param_spec_enum ("output", "output", "Output method (currently unused)",
-          GST_TYPE_FAKESRC_OUTPUT, FAKESRC_FIRST_LAST_LOOP, G_PARAM_READWRITE));
-  g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_DATA,
+          GST_TYPE_FAKE_SRC_OUTPUT, DEFAULT_OUTPUT, G_PARAM_READWRITE));
+*/
+  g_object_class_install_property (gobject_class, PROP_DATA,
       g_param_spec_enum ("data", "data", "Data allocation method",
-          GST_TYPE_FAKESRC_DATA, FAKESRC_DATA_ALLOCATE, G_PARAM_READWRITE));
-  g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_SIZETYPE,
+          GST_TYPE_FAKE_SRC_DATA, DEFAULT_DATA,
+          G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+  g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_SIZETYPE,
       g_param_spec_enum ("sizetype", "sizetype",
-          "How to determine buffer sizes", GST_TYPE_FAKESRC_SIZETYPE,
-          FAKESRC_SIZETYPE_NULL, G_PARAM_READWRITE));
-  g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_SIZEMIN,
+          "How to determine buffer sizes", GST_TYPE_FAKE_SRC_SIZETYPE,
+          DEFAULT_SIZETYPE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+  g_object_class_install_property (gobject_class, PROP_SIZEMIN,
       g_param_spec_int ("sizemin", "sizemin", "Minimum buffer size", 0,
-          G_MAXINT, DEFAULT_SIZEMIN, G_PARAM_READWRITE));
-  g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_SIZEMAX,
+          G_MAXINT, DEFAULT_SIZEMIN,
+          G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+  g_object_class_install_property (gobject_class, PROP_SIZEMAX,
       g_param_spec_int ("sizemax", "sizemax", "Maximum buffer size", 0,
-          G_MAXINT, DEFAULT_SIZEMAX, G_PARAM_READWRITE));
-  g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_PARENTSIZE,
+          G_MAXINT, DEFAULT_SIZEMAX,
+          G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+  g_object_class_install_property (gobject_class, PROP_PARENTSIZE,
       g_param_spec_int ("parentsize", "parentsize",
           "Size of parent buffer for sub-buffered allocation", 0, G_MAXINT,
-          DEFAULT_PARENTSIZE, G_PARAM_READWRITE));
-  g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_FILLTYPE,
+          DEFAULT_PARENTSIZE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+  g_object_class_install_property (gobject_class, PROP_FILLTYPE,
       g_param_spec_enum ("filltype", "filltype",
-          "How to fill the buffer, if at all", GST_TYPE_FAKESRC_FILLTYPE,
-          FAKESRC_FILLTYPE_NULL, G_PARAM_READWRITE));
-  g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_PATTERN,
-      g_param_spec_string ("pattern", "pattern", "pattern", NULL,
-          G_PARAM_READWRITE));
-  g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_NUM_BUFFERS,
-      g_param_spec_int ("num-buffers", "num-buffers",
-          "Number of buffers to output before sending EOS", -1, G_MAXINT,
-          0, G_PARAM_READWRITE));
-  g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_EOS,
-      g_param_spec_boolean ("eos", "eos", "Send out the EOS event?", TRUE,
-          G_PARAM_READWRITE));
-  g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_LAST_MESSAGE,
-      g_param_spec_string ("last-message", "last-message",
-          "The last status message", NULL, G_PARAM_READABLE));
-  g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_SILENT,
+          "How to fill the buffer, if at all", GST_TYPE_FAKE_SRC_FILLTYPE,
+          DEFAULT_FILLTYPE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+  g_object_class_install_property (gobject_class, PROP_DATARATE,
+      g_param_spec_int ("datarate", "Datarate",
+          "Timestamps buffers with number of bytes per second (0 = none)", 0,
+          G_MAXINT, DEFAULT_DATARATE,
+          G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+  g_object_class_install_property (gobject_class, PROP_SYNC,
+      g_param_spec_boolean ("sync", "Sync", "Sync to the clock to the datarate",
+          DEFAULT_SYNC, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+  g_object_class_install_property (gobject_class, PROP_PATTERN,
+      g_param_spec_string ("pattern", "pattern", "pattern", DEFAULT_PATTERN,
+          G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+  pspec_last_message = g_param_spec_string ("last-message", "last-message",
+      "The last status message", NULL,
+      G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
+  g_object_class_install_property (gobject_class, PROP_LAST_MESSAGE,
+      pspec_last_message);
+  g_object_class_install_property (gobject_class, PROP_SILENT,
       g_param_spec_boolean ("silent", "Silent",
-          "Don't produce last_message events", FALSE, G_PARAM_READWRITE));
-  g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_SIGNAL_HANDOFFS,
+          "Don't produce last_message events", DEFAULT_SILENT,
+          G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+  g_object_class_install_property (gobject_class, PROP_SIGNAL_HANDOFFS,
       g_param_spec_boolean ("signal-handoffs", "Signal handoffs",
-          "Send a signal before pushing the buffer", FALSE, G_PARAM_READWRITE));
-  g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_DUMP,
-      g_param_spec_boolean ("dump", "Dump", "Dump produced bytes to stdout",
-          FALSE, G_PARAM_READWRITE));
-
-  gst_fakesrc_signals[SIGNAL_HANDOFF] =
+          "Send a signal before pushing the buffer", DEFAULT_SIGNAL_HANDOFFS,
+          G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+  g_object_class_install_property (gobject_class, PROP_DUMP,
+      g_param_spec_boolean ("dump", "Dump", "Dump buffer contents to stdout",
+          DEFAULT_DUMP, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+  g_object_class_install_property (gobject_class, PROP_CAN_ACTIVATE_PUSH,
+      g_param_spec_boolean ("can-activate-push", "Can activate push",
+          "Can activate in push mode", DEFAULT_CAN_ACTIVATE_PUSH,
+          G_PARAM_READWRITE | G_PARAM_CONSTRUCT | G_PARAM_STATIC_STRINGS));
+  g_object_class_install_property (gobject_class, PROP_CAN_ACTIVATE_PULL,
+      g_param_spec_boolean ("can-activate-pull", "Can activate pull",
+          "Can activate in pull mode", DEFAULT_CAN_ACTIVATE_PULL,
+          G_PARAM_READWRITE | G_PARAM_CONSTRUCT | G_PARAM_STATIC_STRINGS));
+  g_object_class_install_property (gobject_class, PROP_IS_LIVE,
+      g_param_spec_boolean ("is-live", "Is this a live source",
+          "True if the element cannot produce data in PAUSED", FALSE,
+          G_PARAM_READWRITE | G_PARAM_CONSTRUCT | G_PARAM_STATIC_STRINGS));
+  /**
+   * GstFakeSrc:format
+   *
+   * Set the format of the newsegment events to produce.
+   *
+   * Since: 0.10.20
+   */
+  g_object_class_install_property (gobject_class, PROP_FORMAT,
+      g_param_spec_enum ("format", "Format",
+          "The format of the segment events", GST_TYPE_FORMAT,
+          DEFAULT_FORMAT, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+
+  /**
+   * GstFakeSrc::handoff:
+   * @fakesrc: the fakesrc instance
+   * @buffer: the buffer that will be pushed
+   * @pad: the pad that will sent it
+   *
+   * This signal gets emitted before sending the buffer.
+   */
+  gst_fake_src_signals[SIGNAL_HANDOFF] =
       g_signal_new ("handoff", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST,
       G_STRUCT_OFFSET (GstFakeSrcClass, handoff), NULL, NULL,
-      gst_marshal_VOID__POINTER_OBJECT, G_TYPE_NONE, 2,
-      GST_TYPE_BUFFER | G_SIGNAL_TYPE_STATIC_SCOPE, GST_TYPE_PAD);
-
-  gobject_class->set_property = GST_DEBUG_FUNCPTR (gst_fakesrc_set_property);
-  gobject_class->get_property = GST_DEBUG_FUNCPTR (gst_fakesrc_get_property);
-
-  gstelement_class->request_new_pad =
-      GST_DEBUG_FUNCPTR (gst_fakesrc_request_new_pad);
-  gstelement_class->change_state = GST_DEBUG_FUNCPTR (gst_fakesrc_change_state);
+      marshal_VOID__MINIOBJECT_OBJECT, G_TYPE_NONE, 2, GST_TYPE_BUFFER,
+      GST_TYPE_PAD);
+
+  gstbase_src_class->is_seekable = GST_DEBUG_FUNCPTR (gst_fake_src_is_seekable);
+  gstbase_src_class->start = GST_DEBUG_FUNCPTR (gst_fake_src_start);
+  gstbase_src_class->stop = GST_DEBUG_FUNCPTR (gst_fake_src_stop);
+  gstbase_src_class->event = GST_DEBUG_FUNCPTR (gst_fake_src_event_handler);
+  gstbase_src_class->get_times = GST_DEBUG_FUNCPTR (gst_fake_src_get_times);
+  gstbase_src_class->create = GST_DEBUG_FUNCPTR (gst_fake_src_create);
 }
 
 static void
-gst_fakesrc_init (GstFakeSrc * fakesrc)
+gst_fake_src_init (GstFakeSrc * fakesrc, GstFakeSrcClass * g_class)
 {
-  GstPad *pad;
-
-  /* create our first output pad */
-  pad = gst_pad_new ("src", GST_PAD_SRC);
-  gst_element_add_pad (GST_ELEMENT (fakesrc), pad);
-
-  fakesrc->loop_based = FALSE;
-  gst_fakesrc_update_functions (fakesrc);
-
-  fakesrc->output = FAKESRC_FIRST_LAST_LOOP;
-  fakesrc->segment_start = -1;
-  fakesrc->segment_end = -1;
-  fakesrc->num_buffers = -1;
-  fakesrc->rt_num_buffers = -1;
+  fakesrc->output = FAKE_SRC_FIRST_LAST_LOOP;
   fakesrc->buffer_count = 0;
-  fakesrc->silent = FALSE;
-  fakesrc->signal_handoffs = FALSE;
-  fakesrc->dump = FALSE;
+  fakesrc->silent = DEFAULT_SILENT;
+  fakesrc->signal_handoffs = DEFAULT_SIGNAL_HANDOFFS;
+  fakesrc->dump = DEFAULT_DUMP;
   fakesrc->pattern_byte = 0x00;
-  fakesrc->need_flush = FALSE;
-  fakesrc->data = FAKESRC_DATA_ALLOCATE;
-  fakesrc->sizetype = FAKESRC_SIZETYPE_NULL;
-  fakesrc->filltype = FAKESRC_FILLTYPE_NOTHING;
+  fakesrc->data = FAKE_SRC_DATA_ALLOCATE;
+  fakesrc->sizetype = FAKE_SRC_SIZETYPE_EMPTY;
+  fakesrc->filltype = FAKE_SRC_FILLTYPE_NOTHING;
   fakesrc->sizemin = DEFAULT_SIZEMIN;
   fakesrc->sizemax = DEFAULT_SIZEMAX;
   fakesrc->parent = NULL;
   fakesrc->parentsize = DEFAULT_PARENTSIZE;
   fakesrc->last_message = NULL;
+  fakesrc->datarate = DEFAULT_DATARATE;
+  fakesrc->sync = DEFAULT_SYNC;
+  fakesrc->format = DEFAULT_FORMAT;
 }
 
-static GstPad *
-gst_fakesrc_request_new_pad (GstElement * element, GstPadTemplate * templ,
-    const gchar * unused)
-{
-  gchar *name;
-  GstPad *srcpad;
-  GstFakeSrc *fakesrc;
-
-  g_return_val_if_fail (GST_IS_FAKESRC (element), NULL);
-
-  if (templ->direction != GST_PAD_SRC) {
-    g_warning ("gstfakesrc: request new pad that is not a SRC pad\n");
-    return NULL;
-  }
-
-  fakesrc = GST_FAKESRC (element);
-
-  name = g_strdup_printf ("src%d", GST_ELEMENT (fakesrc)->numsrcpads);
-
-  srcpad = gst_pad_new_from_template (templ, name);
-  gst_element_add_pad (GST_ELEMENT (fakesrc), srcpad);
-  gst_fakesrc_update_functions (fakesrc);
-
-  g_free (name);
-
-  return srcpad;
-}
-
-static const GstFormat *
-gst_fakesrc_get_formats (GstPad * pad)
-{
-  static const GstFormat formats[] = {
-    GST_FORMAT_DEFAULT,
-    0,
-  };
-
-  return formats;
-}
-
-static const GstQueryType *
-gst_fakesrc_get_query_types (GstPad * pad)
+static void
+gst_fake_src_finalize (GObject * object)
 {
-  static const GstQueryType types[] = {
-    GST_QUERY_TOTAL,
-    GST_QUERY_POSITION,
-    GST_QUERY_START,
-    GST_QUERY_SEGMENT_END,
-    0,
-  };
-
-  return types;
-}
+  GstFakeSrc *src;
 
-static gboolean
-gst_fakesrc_query (GstPad * pad, GstQueryType type,
-    GstFormat * format, gint64 * value)
-{
-  GstFakeSrc *src = GST_FAKESRC (GST_PAD_PARENT (pad));
+  src = GST_FAKE_SRC (object);
 
-  switch (type) {
-    case GST_QUERY_TOTAL:
-      *value = src->num_buffers;
-      break;
-    case GST_QUERY_POSITION:
-      *value = src->buffer_count;
-      break;
-    case GST_QUERY_START:
-      *value = src->segment_start;
-      break;
-    case GST_QUERY_SEGMENT_END:
-      *value = src->segment_end;
-      break;
-    default:
-      return FALSE;
+  g_free (src->last_message);
+  if (src->parent) {
+    gst_buffer_unref (src->parent);
+    src->parent = NULL;
   }
-  return TRUE;
-}
 
-static const GstEventMask *
-gst_fakesrc_get_event_mask (GstPad * pad)
-{
-  static const GstEventMask masks[] = {
-    {GST_EVENT_SEEK, GST_SEEK_FLAG_FLUSH},
-    {GST_EVENT_SEEK_SEGMENT, GST_SEEK_FLAG_FLUSH | GST_SEEK_FLAG_SEGMENT_LOOP},
-    {GST_EVENT_FLUSH, 0},
-    {0, 0},
-  };
-
-  return masks;
+  G_OBJECT_CLASS (parent_class)->finalize (object);
 }
 
 static gboolean
-gst_fakesrc_event_handler (GstPad * pad, GstEvent * event)
+gst_fake_src_event_handler (GstBaseSrc * basesrc, GstEvent * event)
 {
   GstFakeSrc *src;
 
-  src = GST_FAKESRC (gst_pad_get_parent (pad));
-
-  switch (GST_EVENT_TYPE (event)) {
-    case GST_EVENT_SEEK:
-      src->buffer_count = GST_EVENT_SEEK_OFFSET (event);
+  src = GST_FAKE_SRC (basesrc);
 
-      if (!GST_EVENT_SEEK_FLAGS (event) & GST_SEEK_FLAG_FLUSH) {
-        break;
-      }
-      /* else we do a flush too */
-    case GST_EVENT_SEEK_SEGMENT:
-      src->segment_start = GST_EVENT_SEEK_OFFSET (event);
-      src->segment_end = GST_EVENT_SEEK_ENDOFFSET (event);
-      src->buffer_count = src->segment_start;
-      src->segment_loop =
-          GST_EVENT_SEEK_FLAGS (event) & GST_SEEK_FLAG_SEGMENT_LOOP;
-      break;
-    case GST_EVENT_FLUSH:
-      src->need_flush = TRUE;
-      break;
-    default:
-      break;
-  }
-  gst_event_unref (event);
+  if (!src->silent) {
+    const GstStructure *s;
+    gchar *sstr;
 
-  return TRUE;
-}
+    GST_OBJECT_LOCK (src);
+    g_free (src->last_message);
 
-static void
-gst_fakesrc_update_functions (GstFakeSrc * src)
-{
-  GList *pads;
+    if ((s = gst_event_get_structure (event)))
+      sstr = gst_structure_to_string (s);
+    else
+      sstr = g_strdup ("");
 
-  if (src->loop_based) {
-    gst_element_set_loop_function (GST_ELEMENT (src),
-        GST_DEBUG_FUNCPTR (gst_fakesrc_loop));
-  } else {
-    gst_element_set_loop_function (GST_ELEMENT (src), NULL);
+    src->last_message =
+        g_strdup_printf ("event   ******* (%s:%s) E (type: %d, %s) %p",
+        GST_DEBUG_PAD_NAME (GST_BASE_SRC_CAST (src)->srcpad),
+        GST_EVENT_TYPE (event), sstr, event);
+    g_free (sstr);
+    GST_OBJECT_UNLOCK (src);
+
+#if !GLIB_CHECK_VERSION(2,26,0)
+    g_object_notify ((GObject *) src, "last-message");
+#else
+    g_object_notify_by_pspec ((GObject *) src, pspec_last_message);
+#endif
   }
 
-  pads = GST_ELEMENT (src)->pads;
-  while (pads) {
-    GstPad *pad = GST_PAD (pads->data);
-
-    if (src->loop_based) {
-      gst_pad_set_get_function (pad, NULL);
-    } else {
-      gst_pad_set_get_function (pad, GST_DEBUG_FUNCPTR (gst_fakesrc_get));
-    }
-
-    gst_pad_set_event_function (pad, gst_fakesrc_event_handler);
-    gst_pad_set_event_mask_function (pad, gst_fakesrc_get_event_mask);
-    gst_pad_set_query_function (pad, gst_fakesrc_query);
-    gst_pad_set_query_type_function (pad, gst_fakesrc_get_query_types);
-    gst_pad_set_formats_function (pad, gst_fakesrc_get_formats);
-    pads = g_list_next (pads);
-  }
+  return GST_BASE_SRC_CLASS (parent_class)->event (basesrc, event);
 }
 
 static void
-gst_fakesrc_alloc_parent (GstFakeSrc * src)
+gst_fake_src_alloc_parent (GstFakeSrc * src)
 {
   GstBuffer *buf;
 
   buf = gst_buffer_new ();
   GST_BUFFER_DATA (buf) = g_malloc (src->parentsize);
+  GST_BUFFER_MALLOCDATA (buf) = GST_BUFFER_DATA (buf);
   GST_BUFFER_SIZE (buf) = src->parentsize;
 
   src->parent = buf;
@@ -472,28 +476,25 @@ gst_fakesrc_alloc_parent (GstFakeSrc * src)
 }
 
 static void
-gst_fakesrc_set_property (GObject * object, guint prop_id, const GValue * value,
-    GParamSpec * pspec)
+gst_fake_src_set_property (GObject * object, guint prop_id,
+    const GValue * value, GParamSpec * pspec)
 {
   GstFakeSrc *src;
+  GstBaseSrc *basesrc;
 
-  /* it's not null if we got it, but it might not be ours */
-  src = GST_FAKESRC (object);
+  src = GST_FAKE_SRC (object);
+  basesrc = GST_BASE_SRC (object);
 
   switch (prop_id) {
-    case ARG_LOOP_BASED:
-      src->loop_based = g_value_get_boolean (value);
-      gst_fakesrc_update_functions (src);
-      break;
-    case ARG_OUTPUT:
+    case PROP_OUTPUT:
       g_warning ("not yet implemented");
       break;
-    case ARG_DATA:
+    case PROP_DATA:
       src->data = g_value_get_enum (value);
 
-      if (src->data == FAKESRC_DATA_SUBBUFFER) {
+      if (src->data == FAKE_SRC_DATA_SUBBUFFER) {
         if (!src->parent)
-          gst_fakesrc_alloc_parent (src);
+          gst_fake_src_alloc_parent (src);
       } else {
         if (src->parent) {
           gst_buffer_unref (src->parent);
@@ -501,39 +502,52 @@ gst_fakesrc_set_property (GObject * object, guint prop_id, const GValue * value,
         }
       }
       break;
-    case ARG_SIZETYPE:
+    case PROP_SIZETYPE:
       src->sizetype = g_value_get_enum (value);
       break;
-    case ARG_SIZEMIN:
+    case PROP_SIZEMIN:
       src->sizemin = g_value_get_int (value);
       break;
-    case ARG_SIZEMAX:
+    case PROP_SIZEMAX:
       src->sizemax = g_value_get_int (value);
       break;
-    case ARG_PARENTSIZE:
+    case PROP_PARENTSIZE:
       src->parentsize = g_value_get_int (value);
       break;
-    case ARG_FILLTYPE:
+    case PROP_FILLTYPE:
       src->filltype = g_value_get_enum (value);
       break;
-    case ARG_PATTERN:
+    case PROP_DATARATE:
+      src->datarate = g_value_get_int (value);
       break;
-    case ARG_NUM_BUFFERS:
-      src->num_buffers = g_value_get_int (value);
+    case PROP_SYNC:
+      src->sync = g_value_get_boolean (value);
       break;
-    case ARG_EOS:
-      src->eos = g_value_get_boolean (value);
-      GST_INFO ("will EOS on next buffer");
+    case PROP_PATTERN:
       break;
-    case ARG_SILENT:
+    case PROP_SILENT:
       src->silent = g_value_get_boolean (value);
       break;
-    case ARG_SIGNAL_HANDOFFS:
+    case PROP_SIGNAL_HANDOFFS:
       src->signal_handoffs = g_value_get_boolean (value);
       break;
-    case ARG_DUMP:
+    case PROP_DUMP:
       src->dump = g_value_get_boolean (value);
       break;
+    case PROP_CAN_ACTIVATE_PUSH:
+      g_return_if_fail (!GST_OBJECT_FLAG_IS_SET (object, GST_BASE_SRC_STARTED));
+      GST_BASE_SRC (src)->can_activate_push = g_value_get_boolean (value);
+      break;
+    case PROP_CAN_ACTIVATE_PULL:
+      g_return_if_fail (!GST_OBJECT_FLAG_IS_SET (object, GST_BASE_SRC_STARTED));
+      src->can_activate_pull = g_value_get_boolean (value);
+      break;
+    case PROP_IS_LIVE:
+      gst_base_src_set_live (basesrc, g_value_get_boolean (value));
+      break;
+    case PROP_FORMAT:
+      src->format = g_value_get_enum (value);
+      break;
     default:
       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
       break;
@@ -541,64 +555,73 @@ gst_fakesrc_set_property (GObject * object, guint prop_id, const GValue * value,
 }
 
 static void
-gst_fakesrc_get_property (GObject * object, guint prop_id, GValue * value,
+gst_fake_src_get_property (GObject * object, guint prop_id, GValue * value,
     GParamSpec * pspec)
 {
   GstFakeSrc *src;
+  GstBaseSrc *basesrc;
 
-  /* it's not null if we got it, but it might not be ours */
-  g_return_if_fail (GST_IS_FAKESRC (object));
+  g_return_if_fail (GST_IS_FAKE_SRC (object));
 
-  src = GST_FAKESRC (object);
+  src = GST_FAKE_SRC (object);
+  basesrc = GST_BASE_SRC (object);
 
   switch (prop_id) {
-    case ARG_NUM_SOURCES:
-      g_value_set_int (value, GST_ELEMENT (src)->numsrcpads);
-      break;
-    case ARG_LOOP_BASED:
-      g_value_set_boolean (value, src->loop_based);
-      break;
-    case ARG_OUTPUT:
+    case PROP_OUTPUT:
       g_value_set_enum (value, src->output);
       break;
-    case ARG_DATA:
+    case PROP_DATA:
       g_value_set_enum (value, src->data);
       break;
-    case ARG_SIZETYPE:
+    case PROP_SIZETYPE:
       g_value_set_enum (value, src->sizetype);
       break;
-    case ARG_SIZEMIN:
+    case PROP_SIZEMIN:
       g_value_set_int (value, src->sizemin);
       break;
-    case ARG_SIZEMAX:
+    case PROP_SIZEMAX:
       g_value_set_int (value, src->sizemax);
       break;
-    case ARG_PARENTSIZE:
+    case PROP_PARENTSIZE:
       g_value_set_int (value, src->parentsize);
       break;
-    case ARG_FILLTYPE:
+    case PROP_FILLTYPE:
       g_value_set_enum (value, src->filltype);
       break;
-    case ARG_PATTERN:
-      g_value_set_string (value, src->pattern);
+    case PROP_DATARATE:
+      g_value_set_int (value, src->datarate);
       break;
-    case ARG_NUM_BUFFERS:
-      g_value_set_int (value, src->num_buffers);
+    case PROP_SYNC:
+      g_value_set_boolean (value, src->sync);
       break;
-    case ARG_EOS:
-      g_value_set_boolean (value, src->eos);
+    case PROP_PATTERN:
+      g_value_set_string (value, src->pattern);
       break;
-    case ARG_SILENT:
+    case PROP_SILENT:
       g_value_set_boolean (value, src->silent);
       break;
-    case ARG_SIGNAL_HANDOFFS:
+    case PROP_SIGNAL_HANDOFFS:
       g_value_set_boolean (value, src->signal_handoffs);
       break;
-    case ARG_DUMP:
+    case PROP_DUMP:
       g_value_set_boolean (value, src->dump);
       break;
-    case ARG_LAST_MESSAGE:
+    case PROP_LAST_MESSAGE:
+      GST_OBJECT_LOCK (src);
       g_value_set_string (value, src->last_message);
+      GST_OBJECT_UNLOCK (src);
+      break;
+    case PROP_CAN_ACTIVATE_PUSH:
+      g_value_set_boolean (value, GST_BASE_SRC (src)->can_activate_push);
+      break;
+    case PROP_CAN_ACTIVATE_PULL:
+      g_value_set_boolean (value, src->can_activate_pull);
+      break;
+    case PROP_IS_LIVE:
+      g_value_set_boolean (value, gst_base_src_is_live (basesrc));
+      break;
+    case PROP_FORMAT:
+      g_value_set_enum (value, src->format);
       break;
     default:
       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
@@ -607,28 +630,28 @@ gst_fakesrc_get_property (GObject * object, guint prop_id, GValue * value,
 }
 
 static void
-gst_fakesrc_prepare_buffer (GstFakeSrc * src, GstBuffer * buf)
+gst_fake_src_prepare_buffer (GstFakeSrc * src, GstBuffer * buf)
 {
   if (GST_BUFFER_SIZE (buf) == 0)
     return;
 
   switch (src->filltype) {
-    case FAKESRC_FILLTYPE_NULL:
+    case FAKE_SRC_FILLTYPE_ZERO:
       memset (GST_BUFFER_DATA (buf), 0, GST_BUFFER_SIZE (buf));
       break;
-    case FAKESRC_FILLTYPE_RANDOM:
+    case FAKE_SRC_FILLTYPE_RANDOM:
     {
       gint i;
       guint8 *ptr = GST_BUFFER_DATA (buf);
 
       for (i = GST_BUFFER_SIZE (buf); i; i--) {
-        *ptr++ = (gint8) ((255.0) * rand () / (RAND_MAX));
+        *ptr++ = g_random_int_range (0, 256);
       }
       break;
     }
-    case FAKESRC_FILLTYPE_PATTERN:
+    case FAKE_SRC_FILLTYPE_PATTERN:
       src->pattern_byte = 0x00;
-    case FAKESRC_FILLTYPE_PATTERN_CONT:
+    case FAKE_SRC_FILLTYPE_PATTERN_CONT:
     {
       gint i;
       guint8 *ptr = GST_BUFFER_DATA (buf);
@@ -638,14 +661,14 @@ gst_fakesrc_prepare_buffer (GstFakeSrc * src, GstBuffer * buf)
       }
       break;
     }
-    case FAKESRC_FILLTYPE_NOTHING:
+    case FAKE_SRC_FILLTYPE_NOTHING:
     default:
       break;
   }
 }
 
 static GstBuffer *
-gst_fakesrc_alloc_buffer (GstFakeSrc * src, guint size)
+gst_fake_src_alloc_buffer (GstFakeSrc * src, guint size)
 {
   GstBuffer *buf;
 
@@ -654,18 +677,21 @@ gst_fakesrc_alloc_buffer (GstFakeSrc * src, guint size)
 
   if (size != 0) {
     switch (src->filltype) {
-      case FAKESRC_FILLTYPE_NOTHING:
+      case FAKE_SRC_FILLTYPE_NOTHING:
         GST_BUFFER_DATA (buf) = g_malloc (size);
+        GST_BUFFER_MALLOCDATA (buf) = GST_BUFFER_DATA (buf);
         break;
-      case FAKESRC_FILLTYPE_NULL:
+      case FAKE_SRC_FILLTYPE_ZERO:
         GST_BUFFER_DATA (buf) = g_malloc0 (size);
+        GST_BUFFER_MALLOCDATA (buf) = GST_BUFFER_DATA (buf);
         break;
-      case FAKESRC_FILLTYPE_RANDOM:
-      case FAKESRC_FILLTYPE_PATTERN:
-      case FAKESRC_FILLTYPE_PATTERN_CONT:
+      case FAKE_SRC_FILLTYPE_RANDOM:
+      case FAKE_SRC_FILLTYPE_PATTERN:
+      case FAKE_SRC_FILLTYPE_PATTERN_CONT:
       default:
         GST_BUFFER_DATA (buf) = g_malloc (size);
-        gst_fakesrc_prepare_buffer (src, buf);
+        GST_BUFFER_MALLOCDATA (buf) = GST_BUFFER_DATA (buf);
+        gst_fake_src_prepare_buffer (src, buf);
         break;
     }
   }
@@ -674,21 +700,18 @@ gst_fakesrc_alloc_buffer (GstFakeSrc * src, guint size)
 }
 
 static guint
-gst_fakesrc_get_size (GstFakeSrc * src)
+gst_fake_src_get_size (GstFakeSrc * src)
 {
   guint size;
 
   switch (src->sizetype) {
-    case FAKESRC_SIZETYPE_FIXED:
+    case FAKE_SRC_SIZETYPE_FIXED:
       size = src->sizemax;
       break;
-    case FAKESRC_SIZETYPE_RANDOM:
-      size =
-          src->sizemin +
-          (guint8) (((gfloat) src->sizemax) * rand () / (RAND_MAX +
-              (gfloat) src->sizemin));
+    case FAKE_SRC_SIZETYPE_RANDOM:
+      size = g_random_int_range (src->sizemin, src->sizemax);
       break;
-    case FAKESRC_SIZETYPE_NULL:
+    case FAKE_SRC_SIZETYPE_EMPTY:
     default:
       size = 0;
       break;
@@ -698,24 +721,20 @@ gst_fakesrc_get_size (GstFakeSrc * src)
 }
 
 static GstBuffer *
-gst_fakesrc_create_buffer (GstFakeSrc * src)
+gst_fake_src_create_buffer (GstFakeSrc * src)
 {
   GstBuffer *buf;
-  guint size;
+  guint size = gst_fake_src_get_size (src);
   gboolean dump = src->dump;
 
-  size = gst_fakesrc_get_size (src);
-  if (size == 0)
-    return gst_buffer_new ();
-
   switch (src->data) {
-    case FAKESRC_DATA_ALLOCATE:
-      buf = gst_fakesrc_alloc_buffer (src, size);
+    case FAKE_SRC_DATA_ALLOCATE:
+      buf = gst_fake_src_alloc_buffer (src, size);
       break;
-    case FAKESRC_DATA_SUBBUFFER:
+    case FAKE_SRC_DATA_SUBBUFFER:
       /* see if we have a parent to subbuffer */
       if (!src->parent) {
-        gst_fakesrc_alloc_parent (src);
+        gst_fake_src_alloc_parent (src);
         g_assert (src->parent);
       }
       /* see if it's large enough */
@@ -727,9 +746,9 @@ gst_fakesrc_create_buffer (GstFakeSrc * src)
         gst_buffer_unref (src->parent);
         src->parent = NULL;
         /* try again (this will allocate a new parent) */
-        return gst_fakesrc_create_buffer (src);
+        return gst_fake_src_create_buffer (src);
       }
-      gst_fakesrc_prepare_buffer (src, buf);
+      gst_fake_src_prepare_buffer (src, buf);
       break;
     default:
       g_warning ("fakesrc: dunno how to allocate buffers !");
@@ -743,142 +762,180 @@ gst_fakesrc_create_buffer (GstFakeSrc * src)
   return buf;
 }
 
-static GstData *
-gst_fakesrc_get (GstPad * pad)
+static void
+gst_fake_src_get_times (GstBaseSrc * basesrc, GstBuffer * buffer,
+    GstClockTime * start, GstClockTime * end)
 {
   GstFakeSrc *src;
-  GstBuffer *buf;
 
-  g_return_val_if_fail (pad != NULL, NULL);
+  src = GST_FAKE_SRC (basesrc);
 
-  src = GST_FAKESRC (GST_OBJECT_PARENT (pad));
+  /* sync on the timestamp of the buffer if requested. */
+  if (src->sync) {
+    GstClockTime timestamp = GST_BUFFER_TIMESTAMP (buffer);
 
-  g_return_val_if_fail (GST_IS_FAKESRC (src), NULL);
+    if (GST_CLOCK_TIME_IS_VALID (timestamp)) {
+      /* get duration to calculate end time */
+      GstClockTime duration = GST_BUFFER_DURATION (buffer);
 
-  if (src->need_flush) {
-    src->need_flush = FALSE;
-    return GST_DATA (gst_event_new (GST_EVENT_FLUSH));
+      if (GST_CLOCK_TIME_IS_VALID (duration)) {
+        *end = timestamp + duration;
+      }
+      *start = timestamp;
+    }
+  } else {
+    *start = -1;
+    *end = -1;
   }
+}
 
-  if (src->buffer_count == src->segment_end) {
-    if (src->segment_loop) {
-      return GST_DATA (gst_event_new (GST_EVENT_SEGMENT_DONE));
+static GstFlowReturn
+gst_fake_src_create (GstBaseSrc * basesrc, guint64 offset, guint length,
+    GstBuffer ** ret)
+{
+  GstFakeSrc *src;
+  GstBuffer *buf;
+  GstClockTime time;
+
+  src = GST_FAKE_SRC (basesrc);
+
+  buf = gst_fake_src_create_buffer (src);
+  GST_BUFFER_OFFSET (buf) = src->buffer_count++;
+
+  if (src->datarate > 0) {
+    time = (src->bytes_sent * GST_SECOND) / src->datarate;
+
+    GST_BUFFER_DURATION (buf) =
+        GST_BUFFER_SIZE (buf) * GST_SECOND / src->datarate;
+  } else if (gst_base_src_is_live (basesrc)) {
+    GstClock *clock;
+
+    clock = gst_element_get_clock (GST_ELEMENT (src));
+
+    if (clock) {
+      time = gst_clock_get_time (clock);
+      time -= gst_element_get_base_time (GST_ELEMENT (src));
+      gst_object_unref (clock);
     } else {
-      gst_element_set_eos (GST_ELEMENT (src));
-      return GST_DATA (gst_event_new (GST_EVENT_EOS));
+      /* not an error not to have a clock */
+      time = GST_CLOCK_TIME_NONE;
     }
-  }
-
-  if (src->rt_num_buffers == 0) {
-    gst_element_set_eos (GST_ELEMENT (src));
-    return GST_DATA (gst_event_new (GST_EVENT_EOS));
   } else {
-    if (src->rt_num_buffers > 0)
-      src->rt_num_buffers--;
-  }
-
-  if (src->eos) {
-    GST_INFO ("fakesrc is setting eos on pad");
-    return GST_DATA (gst_event_new (GST_EVENT_EOS));
+    time = GST_CLOCK_TIME_NONE;
   }
 
-  buf = gst_fakesrc_create_buffer (src);
-  GST_BUFFER_TIMESTAMP (buf) = src->buffer_count++;
+  GST_BUFFER_TIMESTAMP (buf) = time;
 
   if (!src->silent) {
+    gchar ts_str[64], dur_str[64];
+    gchar flag_str[100];
+
+    GST_OBJECT_LOCK (src);
     g_free (src->last_message);
 
-    src->last_message =
-        g_strdup_printf ("get      ******* (%s:%s)> (%d bytes, %"
-        G_GUINT64_FORMAT " ) %p", GST_DEBUG_PAD_NAME (pad),
-        GST_BUFFER_SIZE (buf), GST_BUFFER_TIMESTAMP (buf), buf);
+    if (GST_BUFFER_TIMESTAMP (buf) != GST_CLOCK_TIME_NONE) {
+      g_snprintf (ts_str, sizeof (ts_str), "%" GST_TIME_FORMAT,
+          GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (buf)));
+    } else {
+      g_strlcpy (ts_str, "none", sizeof (ts_str));
+    }
 
-    g_object_notify (G_OBJECT (src), "last_message");
+    if (GST_BUFFER_DURATION (buf) != GST_CLOCK_TIME_NONE) {
+      g_snprintf (dur_str, sizeof (dur_str), "%" GST_TIME_FORMAT,
+          GST_TIME_ARGS (GST_BUFFER_DURATION (buf)));
+    } else {
+      g_strlcpy (dur_str, "none", sizeof (dur_str));
+    }
+
+    {
+      const char *flag_list[12] = {
+        "ro", "media4", "", "",
+        "preroll", "discont", "incaps", "gap",
+        "delta_unit", "media1", "media2", "media3"
+      };
+      int i;
+      char *end = flag_str;
+      end[0] = '\0';
+      for (i = 0; i < 12; i++) {
+        if (GST_MINI_OBJECT_CAST (buf)->flags & (1 << i)) {
+          strcpy (end, flag_list[i]);
+          end += strlen (end);
+          end[0] = ' ';
+          end[1] = '\0';
+          end++;
+        }
+      }
+    }
+
+    src->last_message =
+        g_strdup_printf ("create   ******* (%s:%s) (%u bytes, timestamp: %s"
+        ", duration: %s, offset: %" G_GINT64_FORMAT ", offset_end: %"
+        G_GINT64_FORMAT ", flags: %d %s) %p",
+        GST_DEBUG_PAD_NAME (GST_BASE_SRC_CAST (src)->srcpad),
+        GST_BUFFER_SIZE (buf), ts_str, dur_str, GST_BUFFER_OFFSET (buf),
+        GST_BUFFER_OFFSET_END (buf), GST_MINI_OBJECT (buf)->flags, flag_str,
+        buf);
+    GST_OBJECT_UNLOCK (src);
+
+#if !GLIB_CHECK_VERSION(2,26,0)
+    g_object_notify ((GObject *) src, "last-message");
+#else
+    g_object_notify_by_pspec ((GObject *) src, pspec_last_message);
+#endif
   }
 
   if (src->signal_handoffs) {
     GST_LOG_OBJECT (src, "pre handoff emit");
-    g_signal_emit (G_OBJECT (src), gst_fakesrc_signals[SIGNAL_HANDOFF], 0,
-        buf, pad);
+    g_signal_emit (src, gst_fake_src_signals[SIGNAL_HANDOFF], 0, buf,
+        basesrc->srcpad);
     GST_LOG_OBJECT (src, "post handoff emit");
   }
 
-  return GST_DATA (buf);
+  src->bytes_sent += GST_BUFFER_SIZE (buf);
+
+  *ret = buf;
+  return GST_FLOW_OK;
 }
 
-/**
- * gst_fakesrc_loop:
- * @element: the faksesrc to loop
- * 
- * generate an empty buffer and push it to the next element.
- */
-static void
-gst_fakesrc_loop (GstElement * element)
+static gboolean
+gst_fake_src_start (GstBaseSrc * basesrc)
 {
   GstFakeSrc *src;
-  const GList *pads;
-
-  g_return_if_fail (element != NULL);
-  g_return_if_fail (GST_IS_FAKESRC (element));
 
-  src = GST_FAKESRC (element);
+  src = GST_FAKE_SRC (basesrc);
 
-  pads = gst_element_get_pad_list (element);
+  src->buffer_count = 0;
+  src->pattern_byte = 0x00;
+  src->bytes_sent = 0;
 
-  while (pads) {
-    GstPad *pad = GST_PAD (pads->data);
-    GstData *data;
+  gst_base_src_set_format (basesrc, src->format);
 
-    data = gst_fakesrc_get (pad);
-    gst_pad_push (pad, data);
-
-    if (src->eos) {
-      return;
-    }
-
-    pads = g_list_next (pads);
-  }
+  return TRUE;
 }
 
-static GstElementStateReturn
-gst_fakesrc_change_state (GstElement * element)
+static gboolean
+gst_fake_src_stop (GstBaseSrc * basesrc)
 {
-  GstFakeSrc *fakesrc;
-
-  g_return_val_if_fail (GST_IS_FAKESRC (element), GST_STATE_FAILURE);
+  GstFakeSrc *src;
 
-  fakesrc = GST_FAKESRC (element);
+  src = GST_FAKE_SRC (basesrc);
 
-  switch (GST_STATE_TRANSITION (element)) {
-    case GST_STATE_NULL_TO_READY:
-      break;
-    case GST_STATE_READY_TO_PAUSED:
-      fakesrc->buffer_count = 0;
-      fakesrc->pattern_byte = 0x00;
-      fakesrc->need_flush = FALSE;
-      fakesrc->eos = FALSE;
-      fakesrc->rt_num_buffers = fakesrc->num_buffers;
-      break;
-    case GST_STATE_PAUSED_TO_PLAYING:
-    case GST_STATE_PLAYING_TO_PAUSED:
-      break;
-    case GST_STATE_PAUSED_TO_READY:
-      if (fakesrc->parent) {
-        gst_buffer_unref (fakesrc->parent);
-        fakesrc->parent = NULL;
-      }
-      g_free (fakesrc->last_message);
-      fakesrc->last_message = NULL;
-      break;
-    case GST_STATE_READY_TO_NULL:
-      break;
-    default:
-      g_assert_not_reached ();
-      break;
+  GST_OBJECT_LOCK (src);
+  if (src->parent) {
+    gst_buffer_unref (src->parent);
+    src->parent = NULL;
   }
+  g_free (src->last_message);
+  src->last_message = NULL;
+  GST_OBJECT_UNLOCK (src);
 
-  if (GST_ELEMENT_CLASS (parent_class)->change_state)
-    return GST_ELEMENT_CLASS (parent_class)->change_state (element);
+  return TRUE;
+}
+
+static gboolean
+gst_fake_src_is_seekable (GstBaseSrc * basesrc)
+{
+  GstFakeSrc *src = GST_FAKE_SRC (basesrc);
 
-  return GST_STATE_SUCCESS;
+  return src->can_activate_pull;
 }