]> 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 b437fa3beca0fa5878c1d32447de71b5063d2fe8..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>
 
@@ -36,15 +59,8 @@ static GstStaticPadTemplate srctemplate = GST_STATIC_PAD_TEMPLATE ("src",
     GST_PAD_ALWAYS,
     GST_STATIC_CAPS_ANY);
 
-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>");
-
+GST_DEBUG_CATEGORY_STATIC (gst_fake_src_debug);
+#define GST_CAT_DEFAULT gst_fake_src_debug
 
 /* FakeSrc signals and args */
 enum
@@ -54,57 +70,64 @@ enum
   LAST_SIGNAL
 };
 
-#define DEFAULT_OUTPUT         FAKESRC_FIRST_LAST_LOOP
-#define DEFAULT_DATA           FAKESRC_DATA_ALLOCATE
-#define DEFAULT_SIZETYPE       FAKESRC_SIZETYPE_NULL
-#define DEFAULT_SIZEMIN                0
-#define DEFAULT_SIZEMAX                4096
-#define DEFAULT_FILLTYPE       FAKESRC_FILLTYPE_NULL
-#define DEFAULT_DATARATE       0
-#define DEFAULT_SYNC           FALSE
-#define DEFAULT_PATTERN                NULL
-#define DEFAULT_NUM_BUFFERS    -1
-#define DEFAULT_EOS            FALSE
+#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_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_OUTPUT,
-  ARG_DATA,
-  ARG_SIZETYPE,
-  ARG_SIZEMIN,
-  ARG_SIZEMAX,
-  ARG_FILLTYPE,
-  ARG_DATARATE,
-  ARG_SYNC,
-  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,
 };
 
-#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},
   };
 
@@ -114,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},
   };
 
@@ -152,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},
   };
 
@@ -175,134 +202,203 @@ 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, GstBaseSrc, GST_TYPE_BASESRC,
+GST_BOILERPLATE_FULL (GstFakeSrc, gst_fake_src, GstBaseSrc, GST_TYPE_BASE_SRC,
     _do_init);
 
-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 gboolean gst_fakesrc_start (GstBaseSrc * basesrc);
-static gboolean gst_fakesrc_stop (GstBaseSrc * basesrc);
+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_fakesrc_event_handler (GstBaseSrc * src, GstEvent * event);
-static GstFlowReturn gst_fakesrc_create (GstBaseSrc * src, guint64 offset,
+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 guint gst_fakesrc_signals[LAST_SIGNAL] = { 0 };
+static guint gst_fake_src_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_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));
-
-  gst_element_class_set_details (gstelement_class, &gst_fakesrc_details);
 }
 
 static void
-gst_fakesrc_class_init (GstFakeSrcClass * klass)
+gst_fake_src_class_init (GstFakeSrcClass * klass)
 {
   GObjectClass *gobject_class;
-  GstElementClass *gstelement_class;
-  GstBaseSrcClass *gstbasesrc_class;
+  GstBaseSrcClass *gstbase_src_class;
+
+  gobject_class = G_OBJECT_CLASS (klass);
+  gstbase_src_class = GST_BASE_SRC_CLASS (klass);
 
-  gobject_class = (GObjectClass *) klass;
-  gstelement_class = (GstElementClass *) klass;
-  gstbasesrc_class = (GstBaseSrcClass *) klass;
+  gobject_class->finalize = gst_fake_src_finalize;
 
-  gobject_class->set_property = GST_DEBUG_FUNCPTR (gst_fakesrc_set_property);
-  gobject_class->get_property = GST_DEBUG_FUNCPTR (gst_fakesrc_get_property);
+  gobject_class->set_property = gst_fake_src_set_property;
+  gobject_class->get_property = gst_fake_src_get_property;
 
-  g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_OUTPUT,
+/*
+  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, DEFAULT_OUTPUT, 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, DEFAULT_DATA, 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,
-          DEFAULT_SIZETYPE, 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,
-          DEFAULT_FILLTYPE, G_PARAM_READWRITE));
-  g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_DATARATE,
+          "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_object_class_install_property (G_OBJECT_CLASS (klass), ARG_SYNC,
+          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_object_class_install_property (G_OBJECT_CLASS (klass), ARG_PATTERN,
+          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_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,
-          DEFAULT_NUM_BUFFERS, 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?",
-          DEFAULT_EOS, 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_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_object_class_install_property (G_OBJECT_CLASS (klass), ARG_SIGNAL_HANDOFFS,
+          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_object_class_install_property (G_OBJECT_CLASS (klass), ARG_DUMP,
-      g_param_spec_boolean ("dump", "Dump", "Dump produced bytes to stdout",
-          DEFAULT_DUMP, G_PARAM_READWRITE));
-
-  gst_fakesrc_signals[SIGNAL_HANDOFF] =
+          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__BOXED_OBJECT, G_TYPE_NONE, 1,
-      GST_TYPE_BUFFER | G_SIGNAL_TYPE_STATIC_SCOPE);
-
-  gstbasesrc_class->start = GST_DEBUG_FUNCPTR (gst_fakesrc_start);
-  gstbasesrc_class->stop = GST_DEBUG_FUNCPTR (gst_fakesrc_stop);
-  gstbasesrc_class->event = GST_DEBUG_FUNCPTR (gst_fakesrc_event_handler);
-  gstbasesrc_class->create = GST_DEBUG_FUNCPTR (gst_fakesrc_create);
+      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)
 {
-  fakesrc->output = FAKESRC_FIRST_LAST_LOOP;
-  fakesrc->segment_start = -1;
-  fakesrc->segment_end = -1;
-  fakesrc->num_buffers = DEFAULT_NUM_BUFFERS;
-  fakesrc->rt_num_buffers = -1;
+  fakesrc->output = FAKE_SRC_FIRST_LAST_LOOP;
   fakesrc->buffer_count = 0;
   fakesrc->silent = DEFAULT_SILENT;
   fakesrc->signal_handoffs = DEFAULT_SIGNAL_HANDOFFS;
   fakesrc->dump = DEFAULT_DUMP;
   fakesrc->pattern_byte = 0x00;
-  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;
@@ -310,36 +406,69 @@ gst_fakesrc_init (GstFakeSrc * fakesrc)
   fakesrc->last_message = NULL;
   fakesrc->datarate = DEFAULT_DATARATE;
   fakesrc->sync = DEFAULT_SYNC;
+  fakesrc->format = DEFAULT_FORMAT;
+}
+
+static void
+gst_fake_src_finalize (GObject * object)
+{
+  GstFakeSrc *src;
+
+  src = GST_FAKE_SRC (object);
+
+  g_free (src->last_message);
+  if (src->parent) {
+    gst_buffer_unref (src->parent);
+    src->parent = NULL;
+  }
+
+  G_OBJECT_CLASS (parent_class)->finalize (object);
 }
 
 static gboolean
-gst_fakesrc_event_handler (GstBaseSrc * basesrc, GstEvent * event)
+gst_fake_src_event_handler (GstBaseSrc * basesrc, GstEvent * event)
 {
   GstFakeSrc *src;
 
-  src = GST_FAKESRC (basesrc);
+  src = GST_FAKE_SRC (basesrc);
 
   if (!src->silent) {
+    const GstStructure *s;
+    gchar *sstr;
+
+    GST_OBJECT_LOCK (src);
     g_free (src->last_message);
 
-    src->last_message =
-        g_strdup_printf ("event   ******* E (type: %d) %p",
-        GST_EVENT_TYPE (event), event);
+    if ((s = gst_event_get_structure (event)))
+      sstr = gst_structure_to_string (s);
+    else
+      sstr = g_strdup ("");
 
-    g_object_notify (G_OBJECT (src), "last_message");
+    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
   }
 
-
-  return TRUE;
+  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;
@@ -347,23 +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;
 
-  src = GST_FAKESRC (object);
+  src = GST_FAKE_SRC (object);
+  basesrc = GST_BASE_SRC (object);
 
   switch (prop_id) {
-    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);
@@ -371,45 +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_DATARATE:
+    case PROP_DATARATE:
       src->datarate = g_value_get_int (value);
       break;
-    case ARG_SYNC:
+    case PROP_SYNC:
       src->sync = g_value_get_boolean (value);
       break;
-    case ARG_PATTERN:
-      break;
-    case ARG_NUM_BUFFERS:
-      src->num_buffers = g_value_get_int (value);
+    case PROP_PATTERN:
       break;
-    case ARG_EOS:
-      src->eos = g_value_get_boolean (value);
-      GST_INFO ("will EOS on next buffer");
-      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;
@@ -417,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_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_DATARATE:
+    case PROP_DATARATE:
       g_value_set_int (value, src->datarate);
       break;
-    case ARG_SYNC:
+    case PROP_SYNC:
       g_value_set_boolean (value, src->sync);
       break;
-    case ARG_PATTERN:
+    case PROP_PATTERN:
       g_value_set_string (value, src->pattern);
       break;
-    case ARG_NUM_BUFFERS:
-      g_value_set_int (value, src->num_buffers);
-      break;
-    case ARG_EOS:
-      g_value_set_boolean (value, src->eos);
-      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);
@@ -483,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);
@@ -514,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;
 
@@ -530,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;
     }
   }
@@ -550,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;
@@ -574,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 */
@@ -603,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 !");
@@ -619,64 +762,132 @@ gst_fakesrc_create_buffer (GstFakeSrc * src)
   return buf;
 }
 
-static GstFlowReturn
-gst_fakesrc_create (GstBaseSrc * basesrc, guint64 offset, guint length,
-    GstBuffer ** ret)
+static void
+gst_fake_src_get_times (GstBaseSrc * basesrc, GstBuffer * buffer,
+    GstClockTime * start, GstClockTime * end)
 {
   GstFakeSrc *src;
-  GstBuffer *buf;
-  GstClockTime time;
 
-  src = GST_FAKESRC (basesrc);
+  src = GST_FAKE_SRC (basesrc);
 
-  if (src->buffer_count == src->segment_end) {
-    GST_INFO ("buffer_count reaches segment_end %d %d", src->buffer_count,
-        src->segment_end);
-    return GST_FLOW_UNEXPECTED;
-  }
+  /* sync on the timestamp of the buffer if requested. */
+  if (src->sync) {
+    GstClockTime timestamp = GST_BUFFER_TIMESTAMP (buffer);
+
+    if (GST_CLOCK_TIME_IS_VALID (timestamp)) {
+      /* get duration to calculate end time */
+      GstClockTime duration = GST_BUFFER_DURATION (buffer);
 
-  if (src->rt_num_buffers == 0) {
-    return GST_FLOW_UNEXPECTED;
+      if (GST_CLOCK_TIME_IS_VALID (duration)) {
+        *end = timestamp + duration;
+      }
+      *start = timestamp;
+    }
   } else {
-    if (src->rt_num_buffers > 0)
-      src->rt_num_buffers--;
+    *start = -1;
+    *end = -1;
   }
+}
 
-  if (src->eos) {
-    GST_INFO ("fakesrc is setting eos on pad");
-    return GST_FLOW_UNEXPECTED;
-  }
+static GstFlowReturn
+gst_fake_src_create (GstBaseSrc * basesrc, guint64 offset, guint length,
+    GstBuffer ** ret)
+{
+  GstFakeSrc *src;
+  GstBuffer *buf;
+  GstClockTime time;
 
-  buf = gst_fakesrc_create_buffer (src);
-  GST_BUFFER_OFFSET (buf) = src->buffer_count++;
+  src = GST_FAKE_SRC (basesrc);
 
-  time = GST_CLOCK_TIME_NONE;
+  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;
-    if (src->sync) {
-      /* gst_element_wait (GST_ELEMENT (src), time); */
-    }
 
     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;
   }
+
   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      ******* > (%d bytes, %"
-        G_GUINT64_FORMAT " ) %p",
-        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);
+    g_signal_emit (src, gst_fake_src_signals[SIGNAL_HANDOFF], 0, buf,
+        basesrc->srcpad);
     GST_LOG_OBJECT (src, "post handoff emit");
   }
 
@@ -687,34 +898,44 @@ gst_fakesrc_create (GstBaseSrc * basesrc, guint64 offset, guint length,
 }
 
 static gboolean
-gst_fakesrc_start (GstBaseSrc * basesrc)
+gst_fake_src_start (GstBaseSrc * basesrc)
 {
   GstFakeSrc *src;
 
-  src = GST_FAKESRC (basesrc);
+  src = GST_FAKE_SRC (basesrc);
 
   src->buffer_count = 0;
   src->pattern_byte = 0x00;
-  src->eos = FALSE;
   src->bytes_sent = 0;
-  src->rt_num_buffers = src->num_buffers;
+
+  gst_base_src_set_format (basesrc, src->format);
 
   return TRUE;
 }
 
 static gboolean
-gst_fakesrc_stop (GstBaseSrc * basesrc)
+gst_fake_src_stop (GstBaseSrc * basesrc)
 {
   GstFakeSrc *src;
 
-  src = GST_FAKESRC (basesrc);
+  src = GST_FAKE_SRC (basesrc);
 
+  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);
 
   return TRUE;
 }
+
+static gboolean
+gst_fake_src_is_seekable (GstBaseSrc * basesrc)
+{
+  GstFakeSrc *src = GST_FAKE_SRC (basesrc);
+
+  return src->can_activate_pull;
+}