From 5d2684999f93dbcaa95645fddc531137d6c028a5 Mon Sep 17 00:00:00 2001 From: Wim Taymans Date: Fri, 3 Sep 2004 11:40:35 +0000 Subject: [PATCH] gst/elements/: Added datarate properties to limit the datarate. 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 | 14 +++++ gst/elements/gstfakesrc.c | 60 +++++++++++++++++++- gst/elements/gstfakesrc.h | 5 ++ gst/elements/gstidentity.c | 125 ++++++++++++++++++++++++++++++++--------- gst/elements/gstidentity.h | 3 + plugins/elements/gstfakesrc.c | 60 +++++++++++++++++++- plugins/elements/gstfakesrc.h | 5 ++ plugins/elements/gstidentity.c | 125 ++++++++++++++++++++++++++++++++--------- plugins/elements/gstidentity.h | 3 + 9 files changed, 342 insertions(+), 58 deletions(-) diff --git a/ChangeLog b/ChangeLog index 7e5e132..2b0b6ea 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,17 @@ +2004-09-03 Wim Taymans + + * 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 * gst/autoplug/gstspider.c: (plugin_init): diff --git a/gst/elements/gstfakesrc.c b/gst/elements/gstfakesrc.c index 5184b9f..3aad6958 100644 --- a/gst/elements/gstfakesrc.c +++ b/gst/elements/gstfakesrc.c @@ -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: diff --git a/gst/elements/gstfakesrc.h b/gst/elements/gstfakesrc.h index abe93f2..5214f0b 100644 --- a/gst/elements/gstfakesrc.h +++ b/gst/elements/gstfakesrc.h @@ -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; }; diff --git a/gst/elements/gstidentity.c b/gst/elements/gstidentity.c index 49ec840..9e416cd 100644 --- a/gst/elements/gstidentity.c +++ b/gst/elements/gstidentity.c @@ -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; +} diff --git a/gst/elements/gstidentity.h b/gst/elements/gstidentity.h index 6520039..00203be 100644 --- a/gst/elements/gstidentity.h +++ b/gst/elements/gstidentity.h @@ -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 { diff --git a/plugins/elements/gstfakesrc.c b/plugins/elements/gstfakesrc.c index 5184b9f..3aad6958 100644 --- a/plugins/elements/gstfakesrc.c +++ b/plugins/elements/gstfakesrc.c @@ -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: diff --git a/plugins/elements/gstfakesrc.h b/plugins/elements/gstfakesrc.h index abe93f2..5214f0b 100644 --- a/plugins/elements/gstfakesrc.h +++ b/plugins/elements/gstfakesrc.h @@ -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; }; diff --git a/plugins/elements/gstidentity.c b/plugins/elements/gstidentity.c index 49ec840..9e416cd 100644 --- a/plugins/elements/gstidentity.c +++ b/plugins/elements/gstidentity.c @@ -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; +} diff --git a/plugins/elements/gstidentity.h b/plugins/elements/gstidentity.h index 6520039..00203be 100644 --- a/plugins/elements/gstidentity.h +++ b/plugins/elements/gstidentity.h @@ -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 { -- 2.7.4