From 8c26e33f2003629b765af92f0d2ddf516959c597 Mon Sep 17 00:00:00 2001 From: Antonio Ospite Date: Wed, 13 Mar 2019 13:03:44 +0100 Subject: [PATCH] imagefreeze: add a num-buffers property The imagefreeze element can be handy for benchmarking downstream elements because it re-uses the same buffer memory and introduces less overhead compared to always creating new frames with videotestsrc. However it's not possible to make imagefreeze send EOS when using gst-launch-1.0. Add a num-buffers property to make it look more like a source in the above scenario. --- gst/imagefreeze/gstimagefreeze.c | 73 ++++++++++++++++++++++++++++++++ gst/imagefreeze/gstimagefreeze.h | 3 ++ 2 files changed, 76 insertions(+) diff --git a/gst/imagefreeze/gstimagefreeze.c b/gst/imagefreeze/gstimagefreeze.c index 00876da49d..35cd1f70a8 100644 --- a/gst/imagefreeze/gstimagefreeze.c +++ b/gst/imagefreeze/gstimagefreeze.c @@ -45,6 +45,14 @@ #include "gstimagefreeze.h" +#define DEFAULT_NUM_BUFFERS -1 + +enum +{ + PROP_0, + PROP_NUM_BUFFERS +}; + static void gst_image_freeze_finalize (GObject * object); static void gst_image_freeze_reset (GstImageFreeze * self); @@ -52,6 +60,10 @@ static void gst_image_freeze_reset (GstImageFreeze * self); static GstStateChangeReturn gst_image_freeze_change_state (GstElement * element, GstStateChange transition); +static void gst_image_freeze_set_property (GObject * object, guint prop_id, + const GValue * value, GParamSpec * pspec); +static void gst_image_freeze_get_property (GObject * object, guint prop_id, + GValue * value, GParamSpec * pspec); static GstFlowReturn gst_image_freeze_sink_chain (GstPad * pad, GstObject * parent, GstBuffer * buffer); static gboolean gst_image_freeze_sink_event (GstPad * pad, GstObject * parent, @@ -91,6 +103,14 @@ gst_image_freeze_class_init (GstImageFreezeClass * klass) GstElementClass *gstelement_class = GST_ELEMENT_CLASS (klass); gobject_class->finalize = gst_image_freeze_finalize; + gobject_class->set_property = gst_image_freeze_set_property; + gobject_class->get_property = gst_image_freeze_get_property; + + g_object_class_install_property (gobject_class, PROP_NUM_BUFFERS, + g_param_spec_int ("num-buffers", "num-buffers", + "Number of buffers to output before sending EOS (-1 = unlimited)", + -1, G_MAXINT, DEFAULT_NUM_BUFFERS, G_PARAM_READWRITE | + G_PARAM_STATIC_STRINGS)); gstelement_class->change_state = GST_DEBUG_FUNCPTR (gst_image_freeze_change_state); @@ -130,6 +150,8 @@ gst_image_freeze_init (GstImageFreeze * self) g_mutex_init (&self->lock); + self->num_buffers = DEFAULT_NUM_BUFFERS; + gst_image_freeze_reset (self); } @@ -138,6 +160,8 @@ gst_image_freeze_finalize (GObject * object) { GstImageFreeze *self = GST_IMAGE_FREEZE (object); + self->num_buffers = DEFAULT_NUM_BUFFERS; + gst_image_freeze_reset (self); g_mutex_clear (&self->lock); @@ -152,6 +176,7 @@ gst_image_freeze_reset (GstImageFreeze * self) g_mutex_lock (&self->lock); gst_buffer_replace (&self->buffer, NULL); + self->num_buffers_left = self->num_buffers; gst_segment_init (&self->segment, GST_FORMAT_TIME); self->need_segment = TRUE; @@ -670,6 +695,42 @@ gst_image_freeze_src_event (GstPad * pad, GstObject * parent, GstEvent * event) return ret; } +static void +gst_image_freeze_set_property (GObject * object, guint prop_id, + const GValue * value, GParamSpec * pspec) +{ + GstImageFreeze *self; + + self = GST_IMAGE_FREEZE (object); + + switch (prop_id) { + case PROP_NUM_BUFFERS: + self->num_buffers = g_value_get_int (value); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +gst_image_freeze_get_property (GObject * object, guint prop_id, GValue * value, + GParamSpec * pspec) +{ + GstImageFreeze *self; + + self = GST_IMAGE_FREEZE (object); + + switch (prop_id) { + case PROP_NUM_BUFFERS: + g_value_set_int (value, self->num_buffers); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + static GstFlowReturn gst_image_freeze_sink_chain (GstPad * pad, GstObject * parent, GstBuffer * buffer) @@ -717,6 +778,18 @@ gst_image_freeze_src_loop (GstPad * pad) g_mutex_unlock (&self->lock); goto pause_task; } + + /* normally we don't count buffers */ + if (G_UNLIKELY (self->num_buffers_left >= 0)) { + GST_DEBUG_OBJECT (pad, "Buffers left %d", self->num_buffers_left); + if (self->num_buffers_left == 0) { + flow_ret = GST_FLOW_EOS; + g_mutex_unlock (&self->lock); + goto pause_task; + } else { + self->num_buffers_left--; + } + } buffer = gst_buffer_copy (self->buffer); g_mutex_unlock (&self->lock); diff --git a/gst/imagefreeze/gstimagefreeze.h b/gst/imagefreeze/gstimagefreeze.h index 19e803bbe8..4d03118e9e 100644 --- a/gst/imagefreeze/gstimagefreeze.h +++ b/gst/imagefreeze/gstimagefreeze.h @@ -55,6 +55,9 @@ struct _GstImageFreeze gboolean need_segment; guint seqnum; + gint num_buffers; + gint num_buffers_left; + guint64 offset; /* TRUE if currently doing a flushing seek, protected