diff --git a/gst/elements/gstfakesrc.c b/gst/elements/gstfakesrc.c index cae36ea6b3..7a543c17bf 100644 --- a/gst/elements/gstfakesrc.c +++ b/gst/elements/gstfakesrc.c @@ -21,6 +21,7 @@ */ +#include #include @@ -47,10 +48,17 @@ enum { ARG_NUM_SOURCES, ARG_LOOP_BASED, ARG_OUTPUT, + ARG_DATA, + ARG_SIZETYPE, + ARG_SIZEMIN, + ARG_SIZEMAX, + ARG_FILLTYPE, ARG_PATTERN, ARG_NUM_BUFFERS, ARG_EOS, - ARG_SILENT + ARG_SILENT, + ARG_DUMP, + ARG_PARENTSIZE }; GST_PADTEMPLATE_FACTORY (fakesrc_src_factory, @@ -82,6 +90,58 @@ gst_fakesrc_output_get_type (void) return fakesrc_output_type; } +#define GST_TYPE_FAKESRC_DATA (gst_fakesrc_data_get_type()) +static GType +gst_fakesrc_data_get_type (void) +{ + static GType fakesrc_data_type = 0; + static GEnumValue fakesrc_data[] = { + { FAKESRC_DATA_ALLOCATE, "2", "Allocate data"}, + { FAKESRC_DATA_SUBBUFFER, "3", "Subbuffer data"}, + {0, NULL, NULL}, + }; + if (!fakesrc_data_type) { + fakesrc_data_type = g_enum_register_static ("GstFakeSrcData", fakesrc_data); + } + return fakesrc_data_type; +} + +#define GST_TYPE_FAKESRC_SIZETYPE (gst_fakesrc_sizetype_get_type()) +static GType +gst_fakesrc_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)"}, + {0, NULL, NULL}, + }; + if (!fakesrc_sizetype_type) { + fakesrc_sizetype_type = g_enum_register_static ("GstFakeSrcSizeType", fakesrc_sizetype); + } + return fakesrc_sizetype_type; +} + +#define GST_TYPE_FAKESRC_FILLTYPE (gst_fakesrc_filltype_get_type()) +static GType +gst_fakesrc_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"}, + {0, NULL, NULL}, + }; + if (!fakesrc_filltype_type) { + fakesrc_filltype_type = g_enum_register_static ("GstFakeSrcFillType", fakesrc_filltype); + } + return fakesrc_filltype_type; +} + static void gst_fakesrc_class_init (GstFakeSrcClass *klass); static void gst_fakesrc_init (GstFakeSrc *fakesrc); @@ -138,6 +198,24 @@ gst_fakesrc_class_init (GstFakeSrcClass *klass) g_object_class_install_property(G_OBJECT_CLASS(klass), ARG_OUTPUT, g_param_spec_enum("output","output","output", GST_TYPE_FAKESRC_OUTPUT,FAKESRC_FIRST_LAST_LOOP,G_PARAM_READWRITE)); // CHECKME! + g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_DATA, + g_param_spec_enum ("data", "data", "data", + GST_TYPE_FAKESRC_DATA, FAKESRC_DATA_ALLOCATE, G_PARAM_READWRITE)); + g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_SIZETYPE, + g_param_spec_enum ("sizetype", "sizetype", "sizetype", + GST_TYPE_FAKESRC_SIZETYPE, FAKESRC_SIZETYPE_NULL, G_PARAM_READWRITE)); + g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_SIZEMIN, + g_param_spec_int ("sizemin","sizemin","sizemin", + 0, G_MAXINT, 0, G_PARAM_READWRITE)); + g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_SIZEMAX, + g_param_spec_int ("sizemax","sizemax","sizemax", + 0, G_MAXINT, 4096, G_PARAM_READWRITE)); + g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_PARENTSIZE, + g_param_spec_int ("parentsize","parentsize","parentsize", + 0, G_MAXINT, 4096 * 10, G_PARAM_READWRITE)); + g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_FILLTYPE, + g_param_spec_enum ("filltype", "filltype", "filltype", + GST_TYPE_FAKESRC_FILLTYPE, FAKESRC_FILLTYPE_NULL, G_PARAM_READWRITE)); g_object_class_install_property(G_OBJECT_CLASS(klass), ARG_PATTERN, g_param_spec_string("pattern","pattern","pattern", NULL, G_PARAM_READWRITE)); // CHECKME @@ -150,6 +228,9 @@ gst_fakesrc_class_init (GstFakeSrcClass *klass) g_object_class_install_property(G_OBJECT_CLASS(klass), ARG_SILENT, g_param_spec_boolean("silent","silent","silent", FALSE, G_PARAM_READWRITE)); // CHECKME + g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_DUMP, + g_param_spec_boolean ("dump","dump","dump", + FALSE, G_PARAM_READWRITE)); gst_fakesrc_signals[SIGNAL_HANDOFF] = g_signal_new ("handoff", G_TYPE_FROM_CLASS(klass), G_SIGNAL_RUN_LAST, @@ -182,7 +263,16 @@ gst_fakesrc_init (GstFakeSrc *fakesrc) fakesrc->num_buffers = -1; fakesrc->buffer_count = 0; fakesrc->silent = FALSE; + fakesrc->dump = FALSE; + fakesrc->pattern_byte = 0x00; fakesrc->need_flush = FALSE; + fakesrc->data = FAKESRC_DATA_ALLOCATE; + fakesrc->sizetype = FAKESRC_SIZETYPE_NULL; + fakesrc->filltype = FAKESRC_FILLTYPE_NOTHING; + fakesrc->sizemin = 0; + fakesrc->sizemax = 4096; + fakesrc->parent = NULL; + fakesrc->parentsize = 4096 * 10; } static GstPad* @@ -236,6 +326,8 @@ gst_fakesrc_event_handler (GstPad *pad, GstEvent *event) g_print("fakesrc: have unhandled event\n"); break; } + + return TRUE; } static void @@ -266,6 +358,19 @@ gst_fakesrc_update_functions (GstFakeSrc *src) } } +static void +gst_fakesrc_alloc_parent (GstFakeSrc *src) +{ + GstBuffer *buf; + + buf = gst_buffer_new (); + GST_BUFFER_DATA (buf) = g_malloc (src->parentsize); + GST_BUFFER_SIZE (buf) = src->parentsize; + + src->parent = buf; + src->parentoffset = 0; +} + static void gst_fakesrc_set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec) { @@ -281,6 +386,35 @@ gst_fakesrc_set_property (GObject *object, guint prop_id, const GValue *value, G break; case ARG_OUTPUT: break; + case ARG_DATA: + src->data = g_value_get_int (value); + switch (src->data) { + case FAKESRC_DATA_ALLOCATE: + gst_buffer_unref (src->parent); + src->parent = NULL; + break; + case FAKESRC_DATA_SUBBUFFER: + if (!src->parent) + gst_fakesrc_alloc_parent (src); + default: + break; + } + break; + case ARG_SIZETYPE: + src->sizetype = g_value_get_int (value); + break; + case ARG_SIZEMIN: + src->sizemin = g_value_get_int (value); + break; + case ARG_SIZEMAX: + src->sizemax = g_value_get_int (value); + break; + case ARG_PARENTSIZE: + src->parentsize = g_value_get_int (value); + break; + case ARG_FILLTYPE: + src->filltype = g_value_get_int (value); + break; case ARG_PATTERN: break; case ARG_NUM_BUFFERS: @@ -293,6 +427,9 @@ GST_INFO (0, "will EOS on next buffer"); case ARG_SILENT: src->silent = g_value_get_boolean (value); break; + case ARG_DUMP: + src->dump = g_value_get_boolean (value); + break; default: break; } @@ -318,6 +455,24 @@ gst_fakesrc_get_property (GObject *object, guint prop_id, GValue *value, GParamS case ARG_OUTPUT: g_value_set_int (value, src->output); break; + case ARG_DATA: + g_value_set_int (value, src->data); + break; + case ARG_SIZETYPE: + g_value_set_int (value, src->sizetype); + break; + case ARG_SIZEMIN: + g_value_set_int (value, src->sizemin); + break; + case ARG_SIZEMAX: + g_value_set_int (value, src->sizemax); + break; + case ARG_PARENTSIZE: + g_value_set_int (value, src->parentsize); + break; + case ARG_FILLTYPE: + g_value_set_int (value, src->filltype); + break; case ARG_PATTERN: g_value_set_string (value, src->pattern); break; @@ -330,21 +485,150 @@ gst_fakesrc_get_property (GObject *object, guint prop_id, GValue *value, GParamS case ARG_SILENT: g_value_set_boolean (value, src->silent); break; + case ARG_DUMP: + g_value_set_boolean (value, src->dump); + break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; } } +static void +gst_fakesrc_prepare_buffer (GstFakeSrc *src, GstBuffer *buf) +{ + if (GST_BUFFER_SIZE (buf) == 0) + return; + + switch (src->filltype) { + case FAKESRC_FILLTYPE_NULL: + memset (GST_BUFFER_DATA (buf), 0, GST_BUFFER_SIZE (buf)); + break; + case FAKESRC_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)); + } + break; + } + case FAKESRC_FILLTYPE_PATTERN: + src->pattern_byte = 0x00; + case FAKESRC_FILLTYPE_PATTERN_CONT: + { + gint i; + guint8 *ptr = GST_BUFFER_DATA (buf); + + for (i = GST_BUFFER_SIZE (buf); i; i--) { + *ptr++ = src->pattern_byte++; + } + break; + } + case FAKESRC_FILLTYPE_NOTHING: + default: + break; + } +} + +static GstBuffer* +gst_fakesrc_alloc_buffer (GstFakeSrc *src, guint size) +{ + GstBuffer *buf; + + buf = gst_buffer_new (); + GST_BUFFER_SIZE(buf) = size; + + if (size != 0) { + switch (src->filltype) { + case FAKESRC_FILLTYPE_NOTHING: + GST_BUFFER_DATA(buf) = g_malloc (size); + break; + case FAKESRC_FILLTYPE_NULL: + GST_BUFFER_DATA(buf) = g_malloc0 (size); + break; + case FAKESRC_FILLTYPE_RANDOM: + case FAKESRC_FILLTYPE_PATTERN: + case FAKESRC_FILLTYPE_PATTERN_CONT: + default: + GST_BUFFER_DATA(buf) = g_malloc (size); + gst_fakesrc_prepare_buffer (src, buf); + break; + } + } + + return buf; +} + +static guint +gst_fakesrc_get_size (GstFakeSrc *src) +{ + guint size; + + switch (src->sizetype) { + case FAKESRC_SIZETYPE_FIXED: + size = src->sizemax; + break; + case FAKESRC_SIZETYPE_RANDOM: + size = src->sizemin + (guint8)(((gfloat)src->sizemax)*rand()/(RAND_MAX + (gfloat)src->sizemin)); + break; + case FAKESRC_SIZETYPE_NULL: + default: + size = 0; + break; + } + + return size; +} + +static GstBuffer * +gst_fakesrc_create_buffer (GstFakeSrc *src) +{ + GstBuffer *buf; + guint size; + 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); + break; + case FAKESRC_DATA_SUBBUFFER: + // see if we have a parent to subbuffer + if (!src->parent) { + gst_fakesrc_alloc_parent (src); + g_assert (src->parent); + } + // see if it's large enough + if ((GST_BUFFER_SIZE (src->parent) - src->parentoffset) >= size) { + buf = gst_buffer_create_sub (src->parent, src->parentoffset, size); + src->parentoffset += size; + } + else { + // the parent is useless now + gst_buffer_unref (src->parent); + src->parent = NULL; + // try again (this will allocate a new parent) + return gst_fakesrc_create_buffer (src); + } + gst_fakesrc_prepare_buffer (src, buf); + break; + default: + g_warning ("fakesrc: dunno how to allocate buffers !"); + buf = gst_buffer_new(); + break; + } + if (dump) { + gst_util_dump_mem (GST_BUFFER_DATA (buf), GST_BUFFER_SIZE (buf)); + } + + return buf; +} -/** - * gst_fakesrc_get: - * @src: the faksesrc to get - * - * generate an empty buffer and return it - * - * Returns: a new empty buffer - */ static GstBuffer * gst_fakesrc_get(GstPad *pad) { @@ -379,7 +663,7 @@ gst_fakesrc_get(GstPad *pad) return GST_BUFFER(gst_event_new (GST_EVENT_EOS)); } - buf = gst_buffer_new(); + buf = gst_fakesrc_create_buffer (src); GST_BUFFER_TIMESTAMP (buf) = src->buffer_count++; if (!src->silent) @@ -431,7 +715,7 @@ gst_fakesrc_loop(GstElement *element) return; } - buf = gst_buffer_new(); + buf = gst_fakesrc_create_buffer (src); GST_BUFFER_TIMESTAMP (buf) = src->buffer_count++; if (!src->silent) diff --git a/gst/elements/gstfakesrc.h b/gst/elements/gstfakesrc.h index d9bcc5dfd5..550015b2af 100644 --- a/gst/elements/gstfakesrc.h +++ b/gst/elements/gstfakesrc.h @@ -47,6 +47,25 @@ typedef enum { FAKESRC_GET_ALWAYS_SUCEEDS, } GstFakeSrcOutputType; +typedef enum { + FAKESRC_DATA_ALLOCATE = 1, + FAKESRC_DATA_SUBBUFFER, +} GstFakeSrcDataType; + +typedef enum { + FAKESRC_SIZETYPE_NULL = 1, + FAKESRC_SIZETYPE_FIXED, + FAKESRC_SIZETYPE_RANDOM +} GstFakeSrcSizeType; + +typedef enum { + FAKESRC_FILLTYPE_NOTHING = 1, + FAKESRC_FILLTYPE_NULL, + FAKESRC_FILLTYPE_RANDOM, + FAKESRC_FILLTYPE_PATTERN, + FAKESRC_FILLTYPE_PATTERN_CONT +} GstFakeSrcFillType; + #define GST_TYPE_FAKESRC \ (gst_fakesrc_get_type()) #define GST_FAKESRC(obj) \ @@ -64,17 +83,29 @@ typedef struct _GstFakeSrcClass GstFakeSrcClass; struct _GstFakeSrc { GstElement element; - gboolean loop_based; - gboolean eos; - gint numsrcpads; - GSList *srcpads; + gboolean loop_based; + gboolean eos; + gint numsrcpads; + GSList *srcpads; + GstFakeSrcOutputType output; - gchar *pattern; - GList *patternlist; - gint num_buffers; - guint64 buffer_count; - gboolean silent; - gboolean need_flush; + GstFakeSrcDataType data; + GstFakeSrcSizeType sizetype; + GstFakeSrcFillType filltype; + + guint sizemin; + guint sizemax; + GstBuffer *parent; + guint parentsize; + guint parentoffset; + guint8 pattern_byte; + gchar *pattern; + GList *patternlist; + gint num_buffers; + guint64 buffer_count; + gboolean silent; + gboolean dump; + gboolean need_flush; }; struct _GstFakeSrcClass { diff --git a/plugins/elements/gstfakesrc.c b/plugins/elements/gstfakesrc.c index cae36ea6b3..7a543c17bf 100644 --- a/plugins/elements/gstfakesrc.c +++ b/plugins/elements/gstfakesrc.c @@ -21,6 +21,7 @@ */ +#include #include @@ -47,10 +48,17 @@ enum { ARG_NUM_SOURCES, ARG_LOOP_BASED, ARG_OUTPUT, + ARG_DATA, + ARG_SIZETYPE, + ARG_SIZEMIN, + ARG_SIZEMAX, + ARG_FILLTYPE, ARG_PATTERN, ARG_NUM_BUFFERS, ARG_EOS, - ARG_SILENT + ARG_SILENT, + ARG_DUMP, + ARG_PARENTSIZE }; GST_PADTEMPLATE_FACTORY (fakesrc_src_factory, @@ -82,6 +90,58 @@ gst_fakesrc_output_get_type (void) return fakesrc_output_type; } +#define GST_TYPE_FAKESRC_DATA (gst_fakesrc_data_get_type()) +static GType +gst_fakesrc_data_get_type (void) +{ + static GType fakesrc_data_type = 0; + static GEnumValue fakesrc_data[] = { + { FAKESRC_DATA_ALLOCATE, "2", "Allocate data"}, + { FAKESRC_DATA_SUBBUFFER, "3", "Subbuffer data"}, + {0, NULL, NULL}, + }; + if (!fakesrc_data_type) { + fakesrc_data_type = g_enum_register_static ("GstFakeSrcData", fakesrc_data); + } + return fakesrc_data_type; +} + +#define GST_TYPE_FAKESRC_SIZETYPE (gst_fakesrc_sizetype_get_type()) +static GType +gst_fakesrc_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)"}, + {0, NULL, NULL}, + }; + if (!fakesrc_sizetype_type) { + fakesrc_sizetype_type = g_enum_register_static ("GstFakeSrcSizeType", fakesrc_sizetype); + } + return fakesrc_sizetype_type; +} + +#define GST_TYPE_FAKESRC_FILLTYPE (gst_fakesrc_filltype_get_type()) +static GType +gst_fakesrc_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"}, + {0, NULL, NULL}, + }; + if (!fakesrc_filltype_type) { + fakesrc_filltype_type = g_enum_register_static ("GstFakeSrcFillType", fakesrc_filltype); + } + return fakesrc_filltype_type; +} + static void gst_fakesrc_class_init (GstFakeSrcClass *klass); static void gst_fakesrc_init (GstFakeSrc *fakesrc); @@ -138,6 +198,24 @@ gst_fakesrc_class_init (GstFakeSrcClass *klass) g_object_class_install_property(G_OBJECT_CLASS(klass), ARG_OUTPUT, g_param_spec_enum("output","output","output", GST_TYPE_FAKESRC_OUTPUT,FAKESRC_FIRST_LAST_LOOP,G_PARAM_READWRITE)); // CHECKME! + g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_DATA, + g_param_spec_enum ("data", "data", "data", + GST_TYPE_FAKESRC_DATA, FAKESRC_DATA_ALLOCATE, G_PARAM_READWRITE)); + g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_SIZETYPE, + g_param_spec_enum ("sizetype", "sizetype", "sizetype", + GST_TYPE_FAKESRC_SIZETYPE, FAKESRC_SIZETYPE_NULL, G_PARAM_READWRITE)); + g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_SIZEMIN, + g_param_spec_int ("sizemin","sizemin","sizemin", + 0, G_MAXINT, 0, G_PARAM_READWRITE)); + g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_SIZEMAX, + g_param_spec_int ("sizemax","sizemax","sizemax", + 0, G_MAXINT, 4096, G_PARAM_READWRITE)); + g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_PARENTSIZE, + g_param_spec_int ("parentsize","parentsize","parentsize", + 0, G_MAXINT, 4096 * 10, G_PARAM_READWRITE)); + g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_FILLTYPE, + g_param_spec_enum ("filltype", "filltype", "filltype", + GST_TYPE_FAKESRC_FILLTYPE, FAKESRC_FILLTYPE_NULL, G_PARAM_READWRITE)); g_object_class_install_property(G_OBJECT_CLASS(klass), ARG_PATTERN, g_param_spec_string("pattern","pattern","pattern", NULL, G_PARAM_READWRITE)); // CHECKME @@ -150,6 +228,9 @@ gst_fakesrc_class_init (GstFakeSrcClass *klass) g_object_class_install_property(G_OBJECT_CLASS(klass), ARG_SILENT, g_param_spec_boolean("silent","silent","silent", FALSE, G_PARAM_READWRITE)); // CHECKME + g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_DUMP, + g_param_spec_boolean ("dump","dump","dump", + FALSE, G_PARAM_READWRITE)); gst_fakesrc_signals[SIGNAL_HANDOFF] = g_signal_new ("handoff", G_TYPE_FROM_CLASS(klass), G_SIGNAL_RUN_LAST, @@ -182,7 +263,16 @@ gst_fakesrc_init (GstFakeSrc *fakesrc) fakesrc->num_buffers = -1; fakesrc->buffer_count = 0; fakesrc->silent = FALSE; + fakesrc->dump = FALSE; + fakesrc->pattern_byte = 0x00; fakesrc->need_flush = FALSE; + fakesrc->data = FAKESRC_DATA_ALLOCATE; + fakesrc->sizetype = FAKESRC_SIZETYPE_NULL; + fakesrc->filltype = FAKESRC_FILLTYPE_NOTHING; + fakesrc->sizemin = 0; + fakesrc->sizemax = 4096; + fakesrc->parent = NULL; + fakesrc->parentsize = 4096 * 10; } static GstPad* @@ -236,6 +326,8 @@ gst_fakesrc_event_handler (GstPad *pad, GstEvent *event) g_print("fakesrc: have unhandled event\n"); break; } + + return TRUE; } static void @@ -266,6 +358,19 @@ gst_fakesrc_update_functions (GstFakeSrc *src) } } +static void +gst_fakesrc_alloc_parent (GstFakeSrc *src) +{ + GstBuffer *buf; + + buf = gst_buffer_new (); + GST_BUFFER_DATA (buf) = g_malloc (src->parentsize); + GST_BUFFER_SIZE (buf) = src->parentsize; + + src->parent = buf; + src->parentoffset = 0; +} + static void gst_fakesrc_set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec) { @@ -281,6 +386,35 @@ gst_fakesrc_set_property (GObject *object, guint prop_id, const GValue *value, G break; case ARG_OUTPUT: break; + case ARG_DATA: + src->data = g_value_get_int (value); + switch (src->data) { + case FAKESRC_DATA_ALLOCATE: + gst_buffer_unref (src->parent); + src->parent = NULL; + break; + case FAKESRC_DATA_SUBBUFFER: + if (!src->parent) + gst_fakesrc_alloc_parent (src); + default: + break; + } + break; + case ARG_SIZETYPE: + src->sizetype = g_value_get_int (value); + break; + case ARG_SIZEMIN: + src->sizemin = g_value_get_int (value); + break; + case ARG_SIZEMAX: + src->sizemax = g_value_get_int (value); + break; + case ARG_PARENTSIZE: + src->parentsize = g_value_get_int (value); + break; + case ARG_FILLTYPE: + src->filltype = g_value_get_int (value); + break; case ARG_PATTERN: break; case ARG_NUM_BUFFERS: @@ -293,6 +427,9 @@ GST_INFO (0, "will EOS on next buffer"); case ARG_SILENT: src->silent = g_value_get_boolean (value); break; + case ARG_DUMP: + src->dump = g_value_get_boolean (value); + break; default: break; } @@ -318,6 +455,24 @@ gst_fakesrc_get_property (GObject *object, guint prop_id, GValue *value, GParamS case ARG_OUTPUT: g_value_set_int (value, src->output); break; + case ARG_DATA: + g_value_set_int (value, src->data); + break; + case ARG_SIZETYPE: + g_value_set_int (value, src->sizetype); + break; + case ARG_SIZEMIN: + g_value_set_int (value, src->sizemin); + break; + case ARG_SIZEMAX: + g_value_set_int (value, src->sizemax); + break; + case ARG_PARENTSIZE: + g_value_set_int (value, src->parentsize); + break; + case ARG_FILLTYPE: + g_value_set_int (value, src->filltype); + break; case ARG_PATTERN: g_value_set_string (value, src->pattern); break; @@ -330,21 +485,150 @@ gst_fakesrc_get_property (GObject *object, guint prop_id, GValue *value, GParamS case ARG_SILENT: g_value_set_boolean (value, src->silent); break; + case ARG_DUMP: + g_value_set_boolean (value, src->dump); + break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; } } +static void +gst_fakesrc_prepare_buffer (GstFakeSrc *src, GstBuffer *buf) +{ + if (GST_BUFFER_SIZE (buf) == 0) + return; + + switch (src->filltype) { + case FAKESRC_FILLTYPE_NULL: + memset (GST_BUFFER_DATA (buf), 0, GST_BUFFER_SIZE (buf)); + break; + case FAKESRC_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)); + } + break; + } + case FAKESRC_FILLTYPE_PATTERN: + src->pattern_byte = 0x00; + case FAKESRC_FILLTYPE_PATTERN_CONT: + { + gint i; + guint8 *ptr = GST_BUFFER_DATA (buf); + + for (i = GST_BUFFER_SIZE (buf); i; i--) { + *ptr++ = src->pattern_byte++; + } + break; + } + case FAKESRC_FILLTYPE_NOTHING: + default: + break; + } +} + +static GstBuffer* +gst_fakesrc_alloc_buffer (GstFakeSrc *src, guint size) +{ + GstBuffer *buf; + + buf = gst_buffer_new (); + GST_BUFFER_SIZE(buf) = size; + + if (size != 0) { + switch (src->filltype) { + case FAKESRC_FILLTYPE_NOTHING: + GST_BUFFER_DATA(buf) = g_malloc (size); + break; + case FAKESRC_FILLTYPE_NULL: + GST_BUFFER_DATA(buf) = g_malloc0 (size); + break; + case FAKESRC_FILLTYPE_RANDOM: + case FAKESRC_FILLTYPE_PATTERN: + case FAKESRC_FILLTYPE_PATTERN_CONT: + default: + GST_BUFFER_DATA(buf) = g_malloc (size); + gst_fakesrc_prepare_buffer (src, buf); + break; + } + } + + return buf; +} + +static guint +gst_fakesrc_get_size (GstFakeSrc *src) +{ + guint size; + + switch (src->sizetype) { + case FAKESRC_SIZETYPE_FIXED: + size = src->sizemax; + break; + case FAKESRC_SIZETYPE_RANDOM: + size = src->sizemin + (guint8)(((gfloat)src->sizemax)*rand()/(RAND_MAX + (gfloat)src->sizemin)); + break; + case FAKESRC_SIZETYPE_NULL: + default: + size = 0; + break; + } + + return size; +} + +static GstBuffer * +gst_fakesrc_create_buffer (GstFakeSrc *src) +{ + GstBuffer *buf; + guint size; + 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); + break; + case FAKESRC_DATA_SUBBUFFER: + // see if we have a parent to subbuffer + if (!src->parent) { + gst_fakesrc_alloc_parent (src); + g_assert (src->parent); + } + // see if it's large enough + if ((GST_BUFFER_SIZE (src->parent) - src->parentoffset) >= size) { + buf = gst_buffer_create_sub (src->parent, src->parentoffset, size); + src->parentoffset += size; + } + else { + // the parent is useless now + gst_buffer_unref (src->parent); + src->parent = NULL; + // try again (this will allocate a new parent) + return gst_fakesrc_create_buffer (src); + } + gst_fakesrc_prepare_buffer (src, buf); + break; + default: + g_warning ("fakesrc: dunno how to allocate buffers !"); + buf = gst_buffer_new(); + break; + } + if (dump) { + gst_util_dump_mem (GST_BUFFER_DATA (buf), GST_BUFFER_SIZE (buf)); + } + + return buf; +} -/** - * gst_fakesrc_get: - * @src: the faksesrc to get - * - * generate an empty buffer and return it - * - * Returns: a new empty buffer - */ static GstBuffer * gst_fakesrc_get(GstPad *pad) { @@ -379,7 +663,7 @@ gst_fakesrc_get(GstPad *pad) return GST_BUFFER(gst_event_new (GST_EVENT_EOS)); } - buf = gst_buffer_new(); + buf = gst_fakesrc_create_buffer (src); GST_BUFFER_TIMESTAMP (buf) = src->buffer_count++; if (!src->silent) @@ -431,7 +715,7 @@ gst_fakesrc_loop(GstElement *element) return; } - buf = gst_buffer_new(); + buf = gst_fakesrc_create_buffer (src); GST_BUFFER_TIMESTAMP (buf) = src->buffer_count++; if (!src->silent) diff --git a/plugins/elements/gstfakesrc.h b/plugins/elements/gstfakesrc.h index d9bcc5dfd5..550015b2af 100644 --- a/plugins/elements/gstfakesrc.h +++ b/plugins/elements/gstfakesrc.h @@ -47,6 +47,25 @@ typedef enum { FAKESRC_GET_ALWAYS_SUCEEDS, } GstFakeSrcOutputType; +typedef enum { + FAKESRC_DATA_ALLOCATE = 1, + FAKESRC_DATA_SUBBUFFER, +} GstFakeSrcDataType; + +typedef enum { + FAKESRC_SIZETYPE_NULL = 1, + FAKESRC_SIZETYPE_FIXED, + FAKESRC_SIZETYPE_RANDOM +} GstFakeSrcSizeType; + +typedef enum { + FAKESRC_FILLTYPE_NOTHING = 1, + FAKESRC_FILLTYPE_NULL, + FAKESRC_FILLTYPE_RANDOM, + FAKESRC_FILLTYPE_PATTERN, + FAKESRC_FILLTYPE_PATTERN_CONT +} GstFakeSrcFillType; + #define GST_TYPE_FAKESRC \ (gst_fakesrc_get_type()) #define GST_FAKESRC(obj) \ @@ -64,17 +83,29 @@ typedef struct _GstFakeSrcClass GstFakeSrcClass; struct _GstFakeSrc { GstElement element; - gboolean loop_based; - gboolean eos; - gint numsrcpads; - GSList *srcpads; + gboolean loop_based; + gboolean eos; + gint numsrcpads; + GSList *srcpads; + GstFakeSrcOutputType output; - gchar *pattern; - GList *patternlist; - gint num_buffers; - guint64 buffer_count; - gboolean silent; - gboolean need_flush; + GstFakeSrcDataType data; + GstFakeSrcSizeType sizetype; + GstFakeSrcFillType filltype; + + guint sizemin; + guint sizemax; + GstBuffer *parent; + guint parentsize; + guint parentoffset; + guint8 pattern_byte; + gchar *pattern; + GList *patternlist; + gint num_buffers; + guint64 buffer_count; + gboolean silent; + gboolean dump; + gboolean need_flush; }; struct _GstFakeSrcClass {