gst/elements/: Added datarate properties to limit the datarate.
authorWim Taymans <wim.taymans@gmail.com>
Fri, 3 Sep 2004 11:40:35 +0000 (11:40 +0000)
committerWim Taymans <wim.taymans@gmail.com>
Fri, 3 Sep 2004 11:40:35 +0000 (11:40 +0000)
Original commit message from CVS:
* gst/elements/gstfakesrc.c: (gst_fakesrc_class_init),
(gst_fakesrc_init), (gst_fakesrc_set_clock),
(gst_fakesrc_set_property), (gst_fakesrc_get_property),
(gst_fakesrc_get), (gst_fakesrc_change_state):
* gst/elements/gstfakesrc.h:
* gst/elements/gstidentity.c: (gst_identity_class_init),
(gst_identity_init), (gst_identity_chain),
(gst_identity_set_property), (gst_identity_get_property),
(gst_identity_change_state):
* gst/elements/gstidentity.h:
Added datarate properties to limit the datarate.

ChangeLog
gst/elements/gstfakesrc.c
gst/elements/gstfakesrc.h
gst/elements/gstidentity.c
gst/elements/gstidentity.h
plugins/elements/gstfakesrc.c
plugins/elements/gstfakesrc.h
plugins/elements/gstidentity.c
plugins/elements/gstidentity.h

index 7e5e132652227612637e20ac71f10c0c82f7c955..2b0b6ea9b525658b4e0c832de2822406bd2282a9 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,17 @@
+2004-09-03  Wim Taymans  <wim@fluendo.com>
+
+       * gst/elements/gstfakesrc.c: (gst_fakesrc_class_init),
+       (gst_fakesrc_init), (gst_fakesrc_set_clock),
+       (gst_fakesrc_set_property), (gst_fakesrc_get_property),
+       (gst_fakesrc_get), (gst_fakesrc_change_state):
+       * gst/elements/gstfakesrc.h:
+       * gst/elements/gstidentity.c: (gst_identity_class_init),
+       (gst_identity_init), (gst_identity_chain),
+       (gst_identity_set_property), (gst_identity_get_property),
+       (gst_identity_change_state):
+       * gst/elements/gstidentity.h:
+       Added datarate properties to limit the datarate.
+
 2004-08-25  Benjamin Otte  <in7y118@public.uni-hamburg.de>
 
        * gst/autoplug/gstspider.c: (plugin_init):
index 5184b9f2a20da80656fe424373537d3d144f52b0..3aad69584d4f20e4094619d325f60093c4cb5110 100644 (file)
@@ -34,6 +34,8 @@
 #define DEFAULT_SIZEMIN                0
 #define DEFAULT_SIZEMAX                4096
 #define DEFAULT_PARENTSIZE     4096*10
+#define DEFAULT_DATARATE       0
+#define DEFAULT_SYNC           FALSE
 
 static GstStaticPadTemplate srctemplate = GST_STATIC_PAD_TEMPLATE ("src",
     GST_PAD_SRC,
@@ -69,6 +71,8 @@ enum
   ARG_SIZEMIN,
   ARG_SIZEMAX,
   ARG_FILLTYPE,
+  ARG_DATARATE,
+  ARG_SYNC,
   ARG_PATTERN,
   ARG_NUM_BUFFERS,
   ARG_EOS,
@@ -180,6 +184,7 @@ 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_fakesrc_set_clock (GstElement * element, GstClock * clock);
 
 static GstElementStateReturn gst_fakesrc_change_state (GstElement * element);
 
@@ -240,13 +245,20 @@ gst_fakesrc_class_init (GstFakeSrcClass * klass)
       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_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_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,
       g_param_spec_string ("pattern", "pattern", "pattern", NULL,
           G_PARAM_READWRITE));
   g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_NUM_BUFFERS,
       g_param_spec_int ("num-buffers", "num-buffers",
-          "Number of buffers to output before sending EOS", -1, G_MAXINT,
-          0, G_PARAM_READWRITE));
+          "Number of buffers to output before sending EOS", -1, G_MAXINT, 0,
+          G_PARAM_READWRITE));
   g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_EOS,
       g_param_spec_boolean ("eos", "eos", "Send out the EOS event?", TRUE,
           G_PARAM_READWRITE));
@@ -275,6 +287,7 @@ gst_fakesrc_class_init (GstFakeSrcClass * klass)
   gstelement_class->request_new_pad =
       GST_DEBUG_FUNCPTR (gst_fakesrc_request_new_pad);
   gstelement_class->change_state = GST_DEBUG_FUNCPTR (gst_fakesrc_change_state);
+  gstelement_class->set_clock = GST_DEBUG_FUNCPTR (gst_fakesrc_set_clock);
 }
 
 static void
@@ -310,8 +323,21 @@ gst_fakesrc_init (GstFakeSrc * fakesrc)
   fakesrc->parent = NULL;
   fakesrc->parentsize = DEFAULT_PARENTSIZE;
   fakesrc->last_message = NULL;
+  fakesrc->datarate = DEFAULT_DATARATE;
+  fakesrc->sync = DEFAULT_SYNC;
+}
+
+static void
+gst_fakesrc_set_clock (GstElement * element, GstClock * clock)
+{
+  GstFakeSrc *src;
+
+  src = GST_FAKESRC (element);
+
+  src->clock = clock;
 }
 
+
 static GstPad *
 gst_fakesrc_request_new_pad (GstElement * element, GstPadTemplate * templ,
     const gchar * unused)
@@ -525,6 +551,12 @@ gst_fakesrc_set_property (GObject * object, guint prop_id, const GValue * value,
     case ARG_FILLTYPE:
       src->filltype = g_value_get_enum (value);
       break;
+    case ARG_DATARATE:
+      src->datarate = g_value_get_int (value);
+      break;
+    case ARG_SYNC:
+      src->sync = g_value_get_boolean (value);
+      break;
     case ARG_PATTERN:
       break;
     case ARG_NUM_BUFFERS:
@@ -588,6 +620,12 @@ gst_fakesrc_get_property (GObject * object, guint prop_id, GValue * value,
     case ARG_FILLTYPE:
       g_value_set_enum (value, src->filltype);
       break;
+    case ARG_DATARATE:
+      g_value_set_int (value, src->datarate);
+      break;
+    case ARG_SYNC:
+      g_value_set_boolean (value, src->sync);
+      break;
     case ARG_PATTERN:
       g_value_set_string (value, src->pattern);
       break;
@@ -792,7 +830,20 @@ gst_fakesrc_get (GstPad * pad)
   }
 
   buf = gst_fakesrc_create_buffer (src);
-  GST_BUFFER_TIMESTAMP (buf) = src->buffer_count++;
+  GST_BUFFER_OFFSET (buf) = src->buffer_count++;
+
+  GstClockTime time = GST_CLOCK_TIME_NONE;
+
+  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;
+  }
+  GST_BUFFER_TIMESTAMP (buf) = time;
 
   if (!src->silent) {
     g_free (src->last_message);
@@ -812,6 +863,8 @@ gst_fakesrc_get (GstPad * pad)
     GST_LOG_OBJECT (src, "post handoff emit");
   }
 
+  src->bytes_sent += GST_BUFFER_SIZE (buf);
+
   return GST_DATA (buf);
 }
 
@@ -866,6 +919,7 @@ gst_fakesrc_change_state (GstElement * element)
       fakesrc->pattern_byte = 0x00;
       fakesrc->need_flush = FALSE;
       fakesrc->eos = FALSE;
+      fakesrc->bytes_sent = 0;
       fakesrc->rt_num_buffers = fakesrc->num_buffers;
       break;
     case GST_STATE_PAUSED_TO_PLAYING:
index abe93f21ae33c8d3c144cac26266e9cca62c940c..5214f0bb7c506583d6bf741d93ad777456e276da 100644 (file)
@@ -92,6 +92,9 @@ struct _GstFakeSrc {
   guint8        pattern_byte;
   gchar        *pattern;
   GList        *patternlist;
+  gint          datarate;
+  gboolean      sync;
+  GstClock     *clock;
   gint64        segment_start;
   gint64        segment_end;
   gboolean      segment_loop;
@@ -103,6 +106,8 @@ struct _GstFakeSrc {
   gboolean      dump;
   gboolean      need_flush;
 
+  guint64        bytes_sent;
+
   gchar                *last_message;
 };
 
index 49ec840ee497ec86a82a0fa87eaef530585d6411..9e416cd5446742ed80c8189a8c546bcf1467b9ea 100644 (file)
@@ -58,6 +58,17 @@ enum
   LAST_SIGNAL
 };
 
+#define DEFAULT_LOOP_BASED             FALSE
+#define DEFAULT_SLEEP_TIME             0
+#define DEFAULT_DUPLICATE              1
+#define DEFAULT_ERROR_AFTER            -1
+#define DEFAULT_DROP_PROBABILITY       0.0
+#define DEFAULT_DATARATE               0
+#define DEFAULT_SILENT                 FALSE
+#define DEFAULT_DUMP                   FALSE
+#define DEFAULT_SYNC                   FALSE
+#define DEFAULT_CHECK_PERFECT          FALSE
+
 enum
 {
   ARG_0,
@@ -66,6 +77,7 @@ enum
   ARG_DUPLICATE,
   ARG_ERROR_AFTER,
   ARG_DROP_PROBABILITY,
+  ARG_DATARATE,
   ARG_SILENT,
   ARG_LAST_MESSAGE,
   ARG_DUMP,
@@ -85,6 +97,7 @@ static void gst_identity_set_property (GObject * object, guint prop_id,
     const GValue * value, GParamSpec * pspec);
 static void gst_identity_get_property (GObject * object, guint prop_id,
     GValue * value, GParamSpec * pspec);
+static GstElementStateReturn gst_identity_change_state (GstElement * element);
 
 static void gst_identity_chain (GstPad * pad, GstData * _data);
 static void gst_identity_set_clock (GstElement * element, GstClock * clock);
@@ -128,37 +141,42 @@ gst_identity_class_init (GstIdentityClass * klass)
   g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_LOOP_BASED,
       g_param_spec_boolean ("loop-based", "Loop-based",
           "Set to TRUE to use loop-based rather than chain-based scheduling",
-          TRUE, G_PARAM_READWRITE));
+          DEFAULT_LOOP_BASED, G_PARAM_READWRITE));
   g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_SLEEP_TIME,
       g_param_spec_uint ("sleep-time", "Sleep time",
-          "Microseconds to sleep between processing", 0, G_MAXUINT, 0,
-          G_PARAM_READWRITE));
+          "Microseconds to sleep between processing", 0, G_MAXUINT,
+          DEFAULT_SLEEP_TIME, G_PARAM_READWRITE));
   g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_DUPLICATE,
       g_param_spec_uint ("duplicate", "Duplicate Buffers",
-          "Push the buffers N times", 0, G_MAXUINT, 1, G_PARAM_READWRITE));
+          "Push the buffers N times", 0, G_MAXUINT, DEFAULT_DUPLICATE,
+          G_PARAM_READWRITE));
   g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_ERROR_AFTER,
       g_param_spec_int ("error_after", "Error After", "Error after N buffers",
-          G_MININT, G_MAXINT, -1, G_PARAM_READWRITE));
+          G_MININT, G_MAXINT, DEFAULT_ERROR_AFTER, G_PARAM_READWRITE));
   g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_DROP_PROBABILITY,
       g_param_spec_float ("drop_probability", "Drop Probability",
-          "The Probability a buffer is dropped", 0.0, 1.0, 0.0,
-          G_PARAM_READWRITE));
+          "The Probability a buffer is dropped", 0.0, 1.0,
+          DEFAULT_DROP_PROBABILITY, G_PARAM_READWRITE));
+  g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_DATARATE,
+      g_param_spec_int ("datarate", "Datarate",
+          "(Re)timestamps buffers with number of bytes per second (0 = inactive)",
+          0, G_MAXINT, DEFAULT_DATARATE, G_PARAM_READWRITE));
   g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_SILENT,
-      g_param_spec_boolean ("silent", "silent", "silent", FALSE,
+      g_param_spec_boolean ("silent", "silent", "silent", DEFAULT_SILENT,
           G_PARAM_READWRITE));
   g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_LAST_MESSAGE,
       g_param_spec_string ("last-message", "last-message", "last-message", NULL,
           G_PARAM_READABLE));
   g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_DUMP,
-      g_param_spec_boolean ("dump", "Dump", "Dump buffer contents", FALSE,
-          G_PARAM_READWRITE));
+      g_param_spec_boolean ("dump", "Dump", "Dump buffer contents",
+          DEFAULT_DUMP, G_PARAM_READWRITE));
   g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_SYNC,
       g_param_spec_boolean ("sync", "Synchronize",
-          "Synchronize to pipeline clock", FALSE, G_PARAM_READWRITE));
+          "Synchronize to pipeline clock", DEFAULT_SYNC, G_PARAM_READWRITE));
   g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_CHECK_PERFECT,
       g_param_spec_boolean ("check-perfect", "Check For Perfect Stream",
-          "Verify that the stream is time- and data-contiguous", FALSE,
-          G_PARAM_READWRITE));
+          "Verify that the stream is time- and data-contiguous",
+          DEFAULT_CHECK_PERFECT, G_PARAM_READWRITE));
 
   gst_identity_signals[SIGNAL_HANDOFF] =
       g_signal_new ("handoff", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST,
@@ -170,6 +188,8 @@ gst_identity_class_init (GstIdentityClass * klass)
   gobject_class->get_property = GST_DEBUG_FUNCPTR (gst_identity_get_property);
 
   gstelement_class->set_clock = GST_DEBUG_FUNCPTR (gst_identity_set_clock);
+  gstelement_class->change_state =
+      GST_DEBUG_FUNCPTR (gst_identity_change_state);
 
 }
 
@@ -192,18 +212,16 @@ gst_identity_init (GstIdentity * identity)
   gst_pad_set_link_function (identity->srcpad, gst_pad_proxy_pad_link);
   gst_pad_set_getcaps_function (identity->srcpad, gst_pad_proxy_getcaps);
 
-  identity->loop_based = FALSE;
-  identity->sleep_time = 0;
-  identity->duplicate = 1;
-  identity->error_after = -1;
-  identity->drop_probability = 0.0;
-  identity->silent = FALSE;
-  identity->sync = FALSE;
-  identity->check_perfect = FALSE;
-  identity->prev_timestamp = GST_CLOCK_TIME_NONE;
-  identity->prev_duration = GST_CLOCK_TIME_NONE;
-  identity->prev_offset_end = -1;
-  identity->dump = FALSE;
+  identity->loop_based = DEFAULT_LOOP_BASED;
+  identity->sleep_time = DEFAULT_SLEEP_TIME;
+  identity->duplicate = DEFAULT_DUPLICATE;
+  identity->error_after = DEFAULT_ERROR_AFTER;
+  identity->drop_probability = DEFAULT_DROP_PROBABILITY;
+  identity->datarate = DEFAULT_DATARATE;
+  identity->silent = DEFAULT_SILENT;
+  identity->sync = DEFAULT_SYNC;
+  identity->check_perfect = DEFAULT_CHECK_PERFECT;
+  identity->dump = DEFAULT_DUMP;
   identity->last_message = NULL;
   identity->srccaps = NULL;
 
@@ -321,6 +339,16 @@ gst_identity_chain (GstPad * pad, GstData * _data)
       g_object_notify (G_OBJECT (identity), "last-message");
     }
 
+    GstClockTime time = GST_BUFFER_TIMESTAMP (buf);
+
+    if (identity->datarate > 0) {
+      time = identity->bytes_handled * GST_SECOND / identity->datarate;
+
+      GST_BUFFER_TIMESTAMP (buf) = time;
+      GST_BUFFER_DURATION (buf) =
+          GST_BUFFER_SIZE (buf) * GST_SECOND / identity->datarate;
+    }
+
     g_signal_emit (G_OBJECT (identity), gst_identity_signals[SIGNAL_HANDOFF], 0,
         buf);
 
@@ -329,9 +357,11 @@ gst_identity_chain (GstPad * pad, GstData * _data)
 
     if (identity->sync) {
       if (identity->clock) {
-        gst_element_wait (GST_ELEMENT (identity), GST_BUFFER_TIMESTAMP (buf));
+        gst_element_wait (GST_ELEMENT (identity), time);
       }
     }
+
+    identity->bytes_handled += GST_BUFFER_SIZE (buf);
     gst_pad_push (identity->srcpad, GST_DATA (buf));
 
     if (identity->sleep_time)
@@ -405,6 +435,9 @@ gst_identity_set_property (GObject * object, guint prop_id,
     case ARG_DROP_PROBABILITY:
       identity->drop_probability = g_value_get_float (value);
       break;
+    case ARG_DATARATE:
+      identity->datarate = g_value_get_int (value);
+      break;
     case ARG_SYNC:
       identity->sync = g_value_get_boolean (value);
       break;
@@ -444,6 +477,9 @@ gst_identity_get_property (GObject * object, guint prop_id, GValue * value,
     case ARG_DROP_PROBABILITY:
       g_value_set_float (value, identity->drop_probability);
       break;
+    case ARG_DATARATE:
+      g_value_set_int (value, identity->datarate);
+      break;
     case ARG_SILENT:
       g_value_set_boolean (value, identity->silent);
       break;
@@ -464,3 +500,40 @@ gst_identity_get_property (GObject * object, guint prop_id, GValue * value,
       break;
   }
 }
+
+static GstElementStateReturn
+gst_identity_change_state (GstElement * element)
+{
+  GstIdentity *identity;
+
+  g_return_val_if_fail (GST_IS_IDENTITY (element), GST_STATE_FAILURE);
+
+  identity = GST_IDENTITY (element);
+
+  switch (GST_STATE_TRANSITION (element)) {
+    case GST_STATE_NULL_TO_READY:
+      break;
+    case GST_STATE_READY_TO_PAUSED:
+      identity->bytes_handled = 0;
+      identity->prev_timestamp = GST_CLOCK_TIME_NONE;
+      identity->prev_duration = GST_CLOCK_TIME_NONE;
+      identity->prev_offset_end = -1;
+      break;
+    case GST_STATE_PAUSED_TO_PLAYING:
+    case GST_STATE_PLAYING_TO_PAUSED:
+      break;
+    case GST_STATE_PAUSED_TO_READY:
+      g_free (identity->last_message);
+      identity->last_message = NULL;
+      break;
+    case GST_STATE_READY_TO_NULL:
+      break;
+    default:
+      break;
+  }
+
+  if (GST_ELEMENT_CLASS (parent_class)->change_state)
+    return GST_ELEMENT_CLASS (parent_class)->change_state (element);
+
+  return GST_STATE_SUCCESS;
+}
index 652003985819fdc793b588671a168bfa246c5155..00203beed590aedc1792fdde2edef807f5351fbb 100644 (file)
@@ -54,6 +54,7 @@ struct _GstIdentity {
   guint         duplicate;
   gint                  error_after;
   gfloat        drop_probability;
+  gint          datarate;
   guint         sleep_time;
   gboolean      silent;
   gboolean      dump;
@@ -65,6 +66,8 @@ struct _GstIdentity {
   GstClock     *clock;
   gchar        *last_message;
   GstCaps      *srccaps;
+
+  guint64       bytes_handled;
 };
 
 struct _GstIdentityClass {
index 5184b9f2a20da80656fe424373537d3d144f52b0..3aad69584d4f20e4094619d325f60093c4cb5110 100644 (file)
@@ -34,6 +34,8 @@
 #define DEFAULT_SIZEMIN                0
 #define DEFAULT_SIZEMAX                4096
 #define DEFAULT_PARENTSIZE     4096*10
+#define DEFAULT_DATARATE       0
+#define DEFAULT_SYNC           FALSE
 
 static GstStaticPadTemplate srctemplate = GST_STATIC_PAD_TEMPLATE ("src",
     GST_PAD_SRC,
@@ -69,6 +71,8 @@ enum
   ARG_SIZEMIN,
   ARG_SIZEMAX,
   ARG_FILLTYPE,
+  ARG_DATARATE,
+  ARG_SYNC,
   ARG_PATTERN,
   ARG_NUM_BUFFERS,
   ARG_EOS,
@@ -180,6 +184,7 @@ 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_fakesrc_set_clock (GstElement * element, GstClock * clock);
 
 static GstElementStateReturn gst_fakesrc_change_state (GstElement * element);
 
@@ -240,13 +245,20 @@ gst_fakesrc_class_init (GstFakeSrcClass * klass)
       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_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_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,
       g_param_spec_string ("pattern", "pattern", "pattern", NULL,
           G_PARAM_READWRITE));
   g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_NUM_BUFFERS,
       g_param_spec_int ("num-buffers", "num-buffers",
-          "Number of buffers to output before sending EOS", -1, G_MAXINT,
-          0, G_PARAM_READWRITE));
+          "Number of buffers to output before sending EOS", -1, G_MAXINT, 0,
+          G_PARAM_READWRITE));
   g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_EOS,
       g_param_spec_boolean ("eos", "eos", "Send out the EOS event?", TRUE,
           G_PARAM_READWRITE));
@@ -275,6 +287,7 @@ gst_fakesrc_class_init (GstFakeSrcClass * klass)
   gstelement_class->request_new_pad =
       GST_DEBUG_FUNCPTR (gst_fakesrc_request_new_pad);
   gstelement_class->change_state = GST_DEBUG_FUNCPTR (gst_fakesrc_change_state);
+  gstelement_class->set_clock = GST_DEBUG_FUNCPTR (gst_fakesrc_set_clock);
 }
 
 static void
@@ -310,8 +323,21 @@ gst_fakesrc_init (GstFakeSrc * fakesrc)
   fakesrc->parent = NULL;
   fakesrc->parentsize = DEFAULT_PARENTSIZE;
   fakesrc->last_message = NULL;
+  fakesrc->datarate = DEFAULT_DATARATE;
+  fakesrc->sync = DEFAULT_SYNC;
+}
+
+static void
+gst_fakesrc_set_clock (GstElement * element, GstClock * clock)
+{
+  GstFakeSrc *src;
+
+  src = GST_FAKESRC (element);
+
+  src->clock = clock;
 }
 
+
 static GstPad *
 gst_fakesrc_request_new_pad (GstElement * element, GstPadTemplate * templ,
     const gchar * unused)
@@ -525,6 +551,12 @@ gst_fakesrc_set_property (GObject * object, guint prop_id, const GValue * value,
     case ARG_FILLTYPE:
       src->filltype = g_value_get_enum (value);
       break;
+    case ARG_DATARATE:
+      src->datarate = g_value_get_int (value);
+      break;
+    case ARG_SYNC:
+      src->sync = g_value_get_boolean (value);
+      break;
     case ARG_PATTERN:
       break;
     case ARG_NUM_BUFFERS:
@@ -588,6 +620,12 @@ gst_fakesrc_get_property (GObject * object, guint prop_id, GValue * value,
     case ARG_FILLTYPE:
       g_value_set_enum (value, src->filltype);
       break;
+    case ARG_DATARATE:
+      g_value_set_int (value, src->datarate);
+      break;
+    case ARG_SYNC:
+      g_value_set_boolean (value, src->sync);
+      break;
     case ARG_PATTERN:
       g_value_set_string (value, src->pattern);
       break;
@@ -792,7 +830,20 @@ gst_fakesrc_get (GstPad * pad)
   }
 
   buf = gst_fakesrc_create_buffer (src);
-  GST_BUFFER_TIMESTAMP (buf) = src->buffer_count++;
+  GST_BUFFER_OFFSET (buf) = src->buffer_count++;
+
+  GstClockTime time = GST_CLOCK_TIME_NONE;
+
+  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;
+  }
+  GST_BUFFER_TIMESTAMP (buf) = time;
 
   if (!src->silent) {
     g_free (src->last_message);
@@ -812,6 +863,8 @@ gst_fakesrc_get (GstPad * pad)
     GST_LOG_OBJECT (src, "post handoff emit");
   }
 
+  src->bytes_sent += GST_BUFFER_SIZE (buf);
+
   return GST_DATA (buf);
 }
 
@@ -866,6 +919,7 @@ gst_fakesrc_change_state (GstElement * element)
       fakesrc->pattern_byte = 0x00;
       fakesrc->need_flush = FALSE;
       fakesrc->eos = FALSE;
+      fakesrc->bytes_sent = 0;
       fakesrc->rt_num_buffers = fakesrc->num_buffers;
       break;
     case GST_STATE_PAUSED_TO_PLAYING:
index abe93f21ae33c8d3c144cac26266e9cca62c940c..5214f0bb7c506583d6bf741d93ad777456e276da 100644 (file)
@@ -92,6 +92,9 @@ struct _GstFakeSrc {
   guint8        pattern_byte;
   gchar        *pattern;
   GList        *patternlist;
+  gint          datarate;
+  gboolean      sync;
+  GstClock     *clock;
   gint64        segment_start;
   gint64        segment_end;
   gboolean      segment_loop;
@@ -103,6 +106,8 @@ struct _GstFakeSrc {
   gboolean      dump;
   gboolean      need_flush;
 
+  guint64        bytes_sent;
+
   gchar                *last_message;
 };
 
index 49ec840ee497ec86a82a0fa87eaef530585d6411..9e416cd5446742ed80c8189a8c546bcf1467b9ea 100644 (file)
@@ -58,6 +58,17 @@ enum
   LAST_SIGNAL
 };
 
+#define DEFAULT_LOOP_BASED             FALSE
+#define DEFAULT_SLEEP_TIME             0
+#define DEFAULT_DUPLICATE              1
+#define DEFAULT_ERROR_AFTER            -1
+#define DEFAULT_DROP_PROBABILITY       0.0
+#define DEFAULT_DATARATE               0
+#define DEFAULT_SILENT                 FALSE
+#define DEFAULT_DUMP                   FALSE
+#define DEFAULT_SYNC                   FALSE
+#define DEFAULT_CHECK_PERFECT          FALSE
+
 enum
 {
   ARG_0,
@@ -66,6 +77,7 @@ enum
   ARG_DUPLICATE,
   ARG_ERROR_AFTER,
   ARG_DROP_PROBABILITY,
+  ARG_DATARATE,
   ARG_SILENT,
   ARG_LAST_MESSAGE,
   ARG_DUMP,
@@ -85,6 +97,7 @@ static void gst_identity_set_property (GObject * object, guint prop_id,
     const GValue * value, GParamSpec * pspec);
 static void gst_identity_get_property (GObject * object, guint prop_id,
     GValue * value, GParamSpec * pspec);
+static GstElementStateReturn gst_identity_change_state (GstElement * element);
 
 static void gst_identity_chain (GstPad * pad, GstData * _data);
 static void gst_identity_set_clock (GstElement * element, GstClock * clock);
@@ -128,37 +141,42 @@ gst_identity_class_init (GstIdentityClass * klass)
   g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_LOOP_BASED,
       g_param_spec_boolean ("loop-based", "Loop-based",
           "Set to TRUE to use loop-based rather than chain-based scheduling",
-          TRUE, G_PARAM_READWRITE));
+          DEFAULT_LOOP_BASED, G_PARAM_READWRITE));
   g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_SLEEP_TIME,
       g_param_spec_uint ("sleep-time", "Sleep time",
-          "Microseconds to sleep between processing", 0, G_MAXUINT, 0,
-          G_PARAM_READWRITE));
+          "Microseconds to sleep between processing", 0, G_MAXUINT,
+          DEFAULT_SLEEP_TIME, G_PARAM_READWRITE));
   g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_DUPLICATE,
       g_param_spec_uint ("duplicate", "Duplicate Buffers",
-          "Push the buffers N times", 0, G_MAXUINT, 1, G_PARAM_READWRITE));
+          "Push the buffers N times", 0, G_MAXUINT, DEFAULT_DUPLICATE,
+          G_PARAM_READWRITE));
   g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_ERROR_AFTER,
       g_param_spec_int ("error_after", "Error After", "Error after N buffers",
-          G_MININT, G_MAXINT, -1, G_PARAM_READWRITE));
+          G_MININT, G_MAXINT, DEFAULT_ERROR_AFTER, G_PARAM_READWRITE));
   g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_DROP_PROBABILITY,
       g_param_spec_float ("drop_probability", "Drop Probability",
-          "The Probability a buffer is dropped", 0.0, 1.0, 0.0,
-          G_PARAM_READWRITE));
+          "The Probability a buffer is dropped", 0.0, 1.0,
+          DEFAULT_DROP_PROBABILITY, G_PARAM_READWRITE));
+  g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_DATARATE,
+      g_param_spec_int ("datarate", "Datarate",
+          "(Re)timestamps buffers with number of bytes per second (0 = inactive)",
+          0, G_MAXINT, DEFAULT_DATARATE, G_PARAM_READWRITE));
   g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_SILENT,
-      g_param_spec_boolean ("silent", "silent", "silent", FALSE,
+      g_param_spec_boolean ("silent", "silent", "silent", DEFAULT_SILENT,
           G_PARAM_READWRITE));
   g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_LAST_MESSAGE,
       g_param_spec_string ("last-message", "last-message", "last-message", NULL,
           G_PARAM_READABLE));
   g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_DUMP,
-      g_param_spec_boolean ("dump", "Dump", "Dump buffer contents", FALSE,
-          G_PARAM_READWRITE));
+      g_param_spec_boolean ("dump", "Dump", "Dump buffer contents",
+          DEFAULT_DUMP, G_PARAM_READWRITE));
   g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_SYNC,
       g_param_spec_boolean ("sync", "Synchronize",
-          "Synchronize to pipeline clock", FALSE, G_PARAM_READWRITE));
+          "Synchronize to pipeline clock", DEFAULT_SYNC, G_PARAM_READWRITE));
   g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_CHECK_PERFECT,
       g_param_spec_boolean ("check-perfect", "Check For Perfect Stream",
-          "Verify that the stream is time- and data-contiguous", FALSE,
-          G_PARAM_READWRITE));
+          "Verify that the stream is time- and data-contiguous",
+          DEFAULT_CHECK_PERFECT, G_PARAM_READWRITE));
 
   gst_identity_signals[SIGNAL_HANDOFF] =
       g_signal_new ("handoff", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST,
@@ -170,6 +188,8 @@ gst_identity_class_init (GstIdentityClass * klass)
   gobject_class->get_property = GST_DEBUG_FUNCPTR (gst_identity_get_property);
 
   gstelement_class->set_clock = GST_DEBUG_FUNCPTR (gst_identity_set_clock);
+  gstelement_class->change_state =
+      GST_DEBUG_FUNCPTR (gst_identity_change_state);
 
 }
 
@@ -192,18 +212,16 @@ gst_identity_init (GstIdentity * identity)
   gst_pad_set_link_function (identity->srcpad, gst_pad_proxy_pad_link);
   gst_pad_set_getcaps_function (identity->srcpad, gst_pad_proxy_getcaps);
 
-  identity->loop_based = FALSE;
-  identity->sleep_time = 0;
-  identity->duplicate = 1;
-  identity->error_after = -1;
-  identity->drop_probability = 0.0;
-  identity->silent = FALSE;
-  identity->sync = FALSE;
-  identity->check_perfect = FALSE;
-  identity->prev_timestamp = GST_CLOCK_TIME_NONE;
-  identity->prev_duration = GST_CLOCK_TIME_NONE;
-  identity->prev_offset_end = -1;
-  identity->dump = FALSE;
+  identity->loop_based = DEFAULT_LOOP_BASED;
+  identity->sleep_time = DEFAULT_SLEEP_TIME;
+  identity->duplicate = DEFAULT_DUPLICATE;
+  identity->error_after = DEFAULT_ERROR_AFTER;
+  identity->drop_probability = DEFAULT_DROP_PROBABILITY;
+  identity->datarate = DEFAULT_DATARATE;
+  identity->silent = DEFAULT_SILENT;
+  identity->sync = DEFAULT_SYNC;
+  identity->check_perfect = DEFAULT_CHECK_PERFECT;
+  identity->dump = DEFAULT_DUMP;
   identity->last_message = NULL;
   identity->srccaps = NULL;
 
@@ -321,6 +339,16 @@ gst_identity_chain (GstPad * pad, GstData * _data)
       g_object_notify (G_OBJECT (identity), "last-message");
     }
 
+    GstClockTime time = GST_BUFFER_TIMESTAMP (buf);
+
+    if (identity->datarate > 0) {
+      time = identity->bytes_handled * GST_SECOND / identity->datarate;
+
+      GST_BUFFER_TIMESTAMP (buf) = time;
+      GST_BUFFER_DURATION (buf) =
+          GST_BUFFER_SIZE (buf) * GST_SECOND / identity->datarate;
+    }
+
     g_signal_emit (G_OBJECT (identity), gst_identity_signals[SIGNAL_HANDOFF], 0,
         buf);
 
@@ -329,9 +357,11 @@ gst_identity_chain (GstPad * pad, GstData * _data)
 
     if (identity->sync) {
       if (identity->clock) {
-        gst_element_wait (GST_ELEMENT (identity), GST_BUFFER_TIMESTAMP (buf));
+        gst_element_wait (GST_ELEMENT (identity), time);
       }
     }
+
+    identity->bytes_handled += GST_BUFFER_SIZE (buf);
     gst_pad_push (identity->srcpad, GST_DATA (buf));
 
     if (identity->sleep_time)
@@ -405,6 +435,9 @@ gst_identity_set_property (GObject * object, guint prop_id,
     case ARG_DROP_PROBABILITY:
       identity->drop_probability = g_value_get_float (value);
       break;
+    case ARG_DATARATE:
+      identity->datarate = g_value_get_int (value);
+      break;
     case ARG_SYNC:
       identity->sync = g_value_get_boolean (value);
       break;
@@ -444,6 +477,9 @@ gst_identity_get_property (GObject * object, guint prop_id, GValue * value,
     case ARG_DROP_PROBABILITY:
       g_value_set_float (value, identity->drop_probability);
       break;
+    case ARG_DATARATE:
+      g_value_set_int (value, identity->datarate);
+      break;
     case ARG_SILENT:
       g_value_set_boolean (value, identity->silent);
       break;
@@ -464,3 +500,40 @@ gst_identity_get_property (GObject * object, guint prop_id, GValue * value,
       break;
   }
 }
+
+static GstElementStateReturn
+gst_identity_change_state (GstElement * element)
+{
+  GstIdentity *identity;
+
+  g_return_val_if_fail (GST_IS_IDENTITY (element), GST_STATE_FAILURE);
+
+  identity = GST_IDENTITY (element);
+
+  switch (GST_STATE_TRANSITION (element)) {
+    case GST_STATE_NULL_TO_READY:
+      break;
+    case GST_STATE_READY_TO_PAUSED:
+      identity->bytes_handled = 0;
+      identity->prev_timestamp = GST_CLOCK_TIME_NONE;
+      identity->prev_duration = GST_CLOCK_TIME_NONE;
+      identity->prev_offset_end = -1;
+      break;
+    case GST_STATE_PAUSED_TO_PLAYING:
+    case GST_STATE_PLAYING_TO_PAUSED:
+      break;
+    case GST_STATE_PAUSED_TO_READY:
+      g_free (identity->last_message);
+      identity->last_message = NULL;
+      break;
+    case GST_STATE_READY_TO_NULL:
+      break;
+    default:
+      break;
+  }
+
+  if (GST_ELEMENT_CLASS (parent_class)->change_state)
+    return GST_ELEMENT_CLASS (parent_class)->change_state (element);
+
+  return GST_STATE_SUCCESS;
+}
index 652003985819fdc793b588671a168bfa246c5155..00203beed590aedc1792fdde2edef807f5351fbb 100644 (file)
@@ -54,6 +54,7 @@ struct _GstIdentity {
   guint         duplicate;
   gint                  error_after;
   gfloat        drop_probability;
+  gint          datarate;
   guint         sleep_time;
   gboolean      silent;
   gboolean      dump;
@@ -65,6 +66,8 @@ struct _GstIdentity {
   GstClock     *clock;
   gchar        *last_message;
   GstCaps      *srccaps;
+
+  guint64       bytes_handled;
 };
 
 struct _GstIdentityClass {