]> 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 ccbc9f083078abc94f58aedc0004ab7d0e97b756..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)
+ */
+
+/* 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>
-
-#define DEFAULT_SIZEMIN                0
-#define DEFAULT_SIZEMAX                4096
-#define DEFAULT_PARENTSIZE     4096*10
-
-GstElementDetails gst_fakesrc_details = {
-  "Fake Source",
-  "Source",
-  "LGPL",
-  "Push empty (no data) buffers around",
-  VERSION,
-  "Erik Walthinsen <omega@cse.ogi.edu>\n"
-  "Wim Taymans <wim.taymans@chello.be>",
-  "(C) 1999",
-};
+#include "gstfakesrc.h"
+#include <gst/gstmarshal.h>
+
+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 {
+enum
+{
   /* FILL ME */
   SIGNAL_HANDOFF,
   LAST_SIGNAL
 };
 
-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_SILENT,
-  ARG_DUMP,
-  ARG_PARENTSIZE,
-  ARG_LAST_MESSAGE,
+#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
+{
+  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,
 };
 
-GST_PAD_TEMPLATE_FACTORY (fakesrc_src_factory,
-  "src%d",
-  GST_PAD_SRC,
-  GST_PAD_REQUEST,
-  NULL                  /* no caps */
-);
-
-#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},
   };
+
   if (!fakesrc_output_type) {
-    fakesrc_output_type = g_enum_register_static ("GstFakeSrcOutput", fakesrc_output);
+    fakesrc_output_type =
+        g_enum_register_static ("GstFakeSrcOutput", fakesrc_output);
   }
   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"},
-    { FAKESRC_DATA_BUFFERPOOL,                 "3", "Use the default buffer pool (forces sizetype=2)"},
+  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},
   };
+
   if (!fakesrc_sizetype_type) {
-    fakesrc_sizetype_type = g_enum_register_static ("GstFakeSrcSizeType", fakesrc_sizetype);
+    fakesrc_sizetype_type =
+        g_enum_register_static ("GstFakeSrcSizeType", fakesrc_sizetype);
   }
   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},
   };
+
   if (!fakesrc_filltype_type) {
-    fakesrc_filltype_type = g_enum_register_static ("GstFakeSrcFillType", fakesrc_filltype);
+    fakesrc_filltype_type =
+        g_enum_register_static ("GstFakeSrcFillType", fakesrc_filltype);
   }
   return fakesrc_filltype_type;
 }
 
-static void            gst_fakesrc_class_init          (GstFakeSrcClass *klass);
-static void            gst_fakesrc_init                (GstFakeSrc *fakesrc);
+#define _do_init(bla) \
+    GST_DEBUG_CATEGORY_INIT (gst_fake_src_debug, "fakesrc", 0, "fakesrc 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);
-static void            gst_fakesrc_update_functions    (GstFakeSrc *src);
-static void            gst_fakesrc_set_property        (GObject *object, guint prop_id, 
-                                                        const GValue *value, GParamSpec *pspec);
-static void            gst_fakesrc_get_property        (GObject *object, guint prop_id, 
-                                                        GValue *value, GParamSpec *pspec);
+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_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 GstBuffer*      gst_fakesrc_get                 (GstPad *pad);
-static void            gst_fakesrc_loop                (GstElement *element);
+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 GstElementClass *parent_class = NULL;
-static guint gst_fakesrc_signals[LAST_SIGNAL] = { 0 };
+static guint gst_fake_src_signals[LAST_SIGNAL] = { 0 };
 
-GType
-gst_fakesrc_get_type (void) 
+static GParamSpec *pspec_last_message = NULL;
+
+static void
+marshal_VOID__MINIOBJECT_OBJECT (GClosure * closure, GValue * return_value,
+    guint n_param_values, const GValue * param_values, gpointer invocation_hint,
+    gpointer marshal_data)
 {
-  static GType fakesrc_type = 0;
-
-  if (!fakesrc_type) {
-    static const GTypeInfo fakesrc_info = {
-      sizeof(GstFakeSrcClass),
-      NULL,
-      NULL,
-      (GClassInitFunc)gst_fakesrc_class_init,
-      NULL,
-      NULL,
-      sizeof(GstFakeSrc),
-      0,
-      (GInstanceInitFunc)gst_fakesrc_init,
-    };
-    fakesrc_type = g_type_register_static (GST_TYPE_ELEMENT, "GstFakeSrc", &fakesrc_info, 0);
+  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;
   }
-  return fakesrc_type;
+  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_fakesrc_class_init (GstFakeSrcClass *klass) 
+gst_fake_src_base_init (gpointer g_class)
 {
-  GObjectClass *gobject_class;
-  GstElementClass *gstelement_class;
-
-  gobject_class = (GObjectClass*)klass;
-  gstelement_class = (GstElementClass*)klass;
-
-  parent_class = g_type_class_ref (GST_TYPE_ELEMENT);
-
-  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,
-    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,
-    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,
-    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,
-    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_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_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,
-    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",
-                      G_MININT, 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,
-    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_DUMP,
-    g_param_spec_boolean ("dump", "Dump", "Dump produced bytes to stdout",
-                          FALSE, G_PARAM_READWRITE));
-
-  gst_fakesrc_signals[SIGNAL_HANDOFF] =
-    g_signal_new ("handoff", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST,
-                  G_STRUCT_OFFSET (GstFakeSrcClass, handoff), NULL, NULL,
-                  g_cclosure_marshal_VOID__POINTER, G_TYPE_NONE, 1,
-                  G_TYPE_POINTER);
-
-  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);
+  GstElementClass *gstelement_class = GST_ELEMENT_CLASS (g_class);
+
+  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 (&srctemplate));
 }
 
-static void 
-gst_fakesrc_init (GstFakeSrc *fakesrc) 
+static void
+gst_fake_src_class_init (GstFakeSrcClass * klass)
 {
-  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);
+  GObjectClass *gobject_class;
+  GstBaseSrcClass *gstbase_src_class;
+
+  gobject_class = G_OBJECT_CLASS (klass);
+  gstbase_src_class = GST_BASE_SRC_CLASS (klass);
+
+  gobject_class->finalize = gst_fake_src_finalize;
+
+  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_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_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_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_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_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_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_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", 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", 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,
+      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);
+}
 
-  fakesrc->output = FAKESRC_FIRST_LAST_LOOP;
-  fakesrc->segment_start = -1;
-  fakesrc->segment_end = -1;
-  fakesrc->num_buffers = -1;
-  fakesrc->rt_num_buffers = -1;
+static void
+gst_fake_src_init (GstFakeSrc * fakesrc, GstFakeSrcClass * g_class)
+{
+  fakesrc->output = FAKE_SRC_FIRST_LAST_LOOP;
   fakesrc->buffer_count = 0;
-  fakesrc->silent = 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)
+static void
+gst_fake_src_finalize (GObject * object)
 {
-  gchar *name;
-  GstPad *srcpad;
-  GstFakeSrc *fakesrc;
+  GstFakeSrc *src;
 
-  g_return_val_if_fail (GST_IS_FAKESRC (element), NULL);
+  src = GST_FAKE_SRC (object);
 
-  if (templ->direction != GST_PAD_SRC) {
-    g_warning ("gstfakesrc: request new pad that is not a SRC pad\n");
-    return NULL;
+  g_free (src->last_message);
+  if (src->parent) {
+    gst_buffer_unref (src->parent);
+    src->parent = 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;
+  G_OBJECT_CLASS (parent_class)->finalize (object);
 }
 
-GST_PAD_FORMATS_FUNCTION (gst_fakesrc_get_formats,
-  GST_FORMAT_DEFAULT
-)
-
-GST_PAD_QUERY_TYPE_FUNCTION (gst_fakesrc_get_query_types,
-  GST_QUERY_TOTAL,
-  GST_QUERY_POSITION,
-  GST_QUERY_START,
-  GST_QUERY_SEGMENT_END
-) 
-
 static gboolean
-gst_fakesrc_query (GstPad *pad, GstQueryType type,
-                  GstFormat *format, gint64 *value)
-{
-  GstFakeSrc *src = GST_FAKESRC (GST_PAD_PARENT (pad));
-
-  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;
-  } 
-  return TRUE;
-}
-
-GST_PAD_EVENT_MASK_FUNCTION (gst_fakesrc_get_event_mask,
-  { GST_EVENT_SEEK, GST_SEEK_FLAG_FLUSH },
-  { GST_EVENT_SEEK_SEGMENT, GST_SEEK_FLAG_FLUSH | GST_SEEK_FLAG_SEGMENT_LOOP },
-  { GST_EVENT_FLUSH, 0 }
-)
-
-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);
-
-  return TRUE;
-}
+  if (!src->silent) {
+    const GstStructure *s;
+    gchar *sstr;
 
-static void
-gst_fakesrc_update_functions (GstFakeSrc *src)
-{
-  GList *pads;
+    GST_OBJECT_LOCK (src);
+    g_free (src->last_message);
 
-  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);
+    if ((s = gst_event_get_structure (event)))
+      sstr = gst_structure_to_string (s);
+    else
+      sstr = g_strdup ("");
+
+    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;
@@ -439,137 +476,152 @@ 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;
+
+  src = GST_FAKE_SRC (object);
+  basesrc = GST_BASE_SRC (object);
 
-  /* it's not null if we got it, but it might not be ours */
-  src = GST_FAKESRC (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);
           src->parent = NULL;
         }
       }
-      
-      if (src->data == FAKESRC_DATA_BUFFERPOOL) {
-        if (src->sizetype != FAKESRC_SIZETYPE_FIXED)
-          g_object_set (src, "sizetype", FAKESRC_SIZETYPE_FIXED, NULL);
-        
-        if (!src->pool) 
-          src->pool = gst_buffer_pool_get_default (src->sizemax, 10);
-      } else {
-        if (src->pool) {
-          gst_buffer_pool_free (src->pool);
-          src->pool = NULL;
-        }
-      }
       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 (0, "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_DUMP:
+    case PROP_SIGNAL_HANDOFFS:
+      src->signal_handoffs = g_value_get_boolean (value);
+      break;
+    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;
   }
 }
 
-static void 
-gst_fakesrc_get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec)
+static void
+gst_fake_src_get_property (GObject * object, guint prop_id, GValue * value,
+    GParamSpec * pspec)
 {
   GstFakeSrc *src;
-   
-  /* it's not null if we got it, but it might not be ours */
-  g_return_if_fail (GST_IS_FAKESRC (object));
-  
-  src = GST_FAKESRC (object);
-   
+  GstBaseSrc *basesrc;
+
+  g_return_if_fail (GST_IS_FAKE_SRC (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_DUMP:
+    case PROP_SIGNAL_HANDOFFS:
+      g_value_set_boolean (value, src->signal_handoffs);
+      break;
+    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);
@@ -578,65 +630,68 @@ gst_fakesrc_get_property (GObject *object, guint prop_id, GValue *value, GParamS
 }
 
 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) 
+  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);
 
       for (i = GST_BUFFER_SIZE (buf); i; i--) {
-       *ptr++ = src->pattern_byte++;
+        *ptr++ = src->pattern_byte++;
       }
       break;
     }
-    case FAKESRC_FILLTYPE_NOTHING:
+    case FAKE_SRC_FILLTYPE_NOTHING:
     default:
       break;
   }
 }
 
-static GstBuffer*
-gst_fakesrc_alloc_buffer (GstFakeSrc *src, guint size)
+static GstBuffer *
+gst_fake_src_alloc_buffer (GstFakeSrc * src, guint size)
 {
   GstBuffer *buf;
 
   buf = gst_buffer_new ();
-  GST_BUFFER_SIZE(buf) = size;
+  GST_BUFFER_SIZE (buf) = size;
 
-  if (size != 0) { 
+  if (size != 0) {
     switch (src->filltype) {
-      case FAKESRC_FILLTYPE_NOTHING:
-        GST_BUFFER_DATA(buf) = g_malloc (size);
+      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:
-        GST_BUFFER_DATA(buf) = g_malloc0 (size);
+      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_DATA (buf) = g_malloc (size);
+        GST_BUFFER_MALLOCDATA (buf) = GST_BUFFER_DATA (buf);
+        gst_fake_src_prepare_buffer (src, buf);
         break;
     }
   }
@@ -645,20 +700,20 @@ 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; 
+      size = 0;
       break;
   }
 
@@ -666,47 +721,38 @@ 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);
-       g_assert (src->parent);
+        gst_fake_src_alloc_parent (src);
+        g_assert (src->parent);
       }
       /* see if it's large enough */
       if ((GST_BUFFER_SIZE (src->parent) - src->parentoffset) >= size) {
-        buf = gst_buffer_create_sub (src->parent, src->parentoffset, size);
-        src->parentoffset += size;
-      }
-      else {
-       /* the parent is useless now */
-       gst_buffer_unref (src->parent);
-       src->parent = NULL;
-       /* try again (this will allocate a new parent) */
-        return gst_fakesrc_create_buffer (src);
+        buf = gst_buffer_create_sub (src->parent, src->parentoffset, size);
+        src->parentoffset += size;
+      } else {
+        /* the parent is useless now */
+        gst_buffer_unref (src->parent);
+        src->parent = NULL;
+        /* try again (this will allocate a new parent) */
+        return gst_fake_src_create_buffer (src);
       }
-      gst_fakesrc_prepare_buffer (src, buf);
-      break;
-    case FAKESRC_DATA_BUFFERPOOL:
-      buf = gst_buffer_new_from_pool (src->pool, 0, 0);
-      gst_fakesrc_prepare_buffer (src, buf);
+      gst_fake_src_prepare_buffer (src, buf);
       break;
     default:
       g_warning ("fakesrc: dunno how to allocate buffers !");
-      buf = gst_buffer_new();
+      buf = gst_buffer_new ();
       break;
   }
   if (dump) {
@@ -716,153 +762,180 @@ gst_fakesrc_create_buffer (GstFakeSrc *src)
   return buf;
 }
 
-static GstBuffer *
-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_FAKESRC (gst_pad_get_parent (pad));
+  src = GST_FAKE_SRC (basesrc);
 
-  g_return_val_if_fail (GST_IS_FAKESRC (src), NULL);
+  /* sync on the timestamp of the buffer if requested. */
+  if (src->sync) {
+    GstClockTime timestamp = GST_BUFFER_TIMESTAMP (buffer);
 
-  if (src->need_flush) {
-    src->need_flush = FALSE;
-    return GST_BUFFER(gst_event_new (GST_EVENT_FLUSH));
-  }
+    if (GST_CLOCK_TIME_IS_VALID (timestamp)) {
+      /* get duration to calculate end time */
+      GstClockTime duration = GST_BUFFER_DURATION (buffer);
 
-  if (src->buffer_count == src->segment_end) {
-    if (src->segment_loop) {
-      return GST_BUFFER(gst_event_new (GST_EVENT_SEGMENT_DONE));
-    }
-    else {
-      gst_element_set_eos (GST_ELEMENT (src));
-      return GST_BUFFER(gst_event_new (GST_EVENT_EOS));
+      if (GST_CLOCK_TIME_IS_VALID (duration)) {
+        *end = timestamp + duration;
+      }
+      *start = timestamp;
     }
+  } else {
+    *start = -1;
+    *end = -1;
   }
+}
 
-  if (src->rt_num_buffers == 0) {
-    gst_element_set_eos (GST_ELEMENT (src));
-    return GST_BUFFER(gst_event_new (GST_EVENT_EOS));
-  }
-  else {
-    if (src->rt_num_buffers > 0)
-      src->rt_num_buffers--;
-  }
+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);
 
-  if (src->eos) {
-    GST_INFO (0, "fakesrc is setting eos on pad");
-    return GST_BUFFER(gst_event_new (GST_EVENT_EOS));
+  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 {
+      /* not an error not to have a clock */
+      time = GST_CLOCK_TIME_NONE;
+    }
+  } else {
+    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, %llu) %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));
+    }
+
+    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
+  }
 
-    g_object_notify (G_OBJECT (src), "last_message");
+  if (src->signal_handoffs) {
+    GST_LOG_OBJECT (src, "pre handoff emit");
+    g_signal_emit (src, gst_fake_src_signals[SIGNAL_HANDOFF], 0, buf,
+        basesrc->srcpad);
+    GST_LOG_OBJECT (src, "post handoff emit");
   }
 
-  GST_DEBUG_ELEMENT (GST_CAT_DATAFLOW, src, "pre handoff emit");
-  g_signal_emit (G_OBJECT (src), gst_fakesrc_signals[SIGNAL_HANDOFF], 0,
-                   buf, pad);
-  GST_DEBUG_ELEMENT (GST_CAT_DATAFLOW, src, "post handoff emit");
+  src->bytes_sent += GST_BUFFER_SIZE (buf);
 
-  return 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);
 
-  pads = gst_element_get_pad_list (element);
+  src = GST_FAKE_SRC (basesrc);
 
-  while (pads) {
-    GstPad *pad = GST_PAD (pads->data);
-    GstBuffer *buf;
+  src->buffer_count = 0;
+  src->pattern_byte = 0x00;
+  src->bytes_sent = 0;
 
-    buf = gst_fakesrc_get (pad);
-    gst_pad_push (pad, buf);
-
-    if (src->eos) {
-      return;
-    }
+  gst_base_src_set_format (basesrc, src->format);
 
-    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;
-      }
-      if (fakesrc->pool) {
-        gst_buffer_pool_unref (fakesrc->pool);
-        fakesrc->pool = 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 GST_STATE_SUCCESS;
+  return TRUE;
 }
 
-gboolean
-gst_fakesrc_factory_init (GstElementFactory *factory)
+static gboolean
+gst_fake_src_is_seekable (GstBaseSrc * basesrc)
 {
-  gst_element_factory_add_pad_template (factory, GST_PAD_TEMPLATE_GET (fakesrc_src_factory));
+  GstFakeSrc *src = GST_FAKE_SRC (basesrc);
 
-  return TRUE;
+  return src->can_activate_pull;
 }
-