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.
This commit is contained in:
Antonio Ospite 2019-03-13 13:03:44 +01:00
parent fcd568dd56
commit 8c26e33f20
2 changed files with 76 additions and 0 deletions

View file

@ -45,6 +45,14 @@
#include "gstimagefreeze.h" #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_finalize (GObject * object);
static void gst_image_freeze_reset (GstImageFreeze * self); 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, static GstStateChangeReturn gst_image_freeze_change_state (GstElement * element,
GstStateChange transition); 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, static GstFlowReturn gst_image_freeze_sink_chain (GstPad * pad,
GstObject * parent, GstBuffer * buffer); GstObject * parent, GstBuffer * buffer);
static gboolean gst_image_freeze_sink_event (GstPad * pad, GstObject * parent, 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); GstElementClass *gstelement_class = GST_ELEMENT_CLASS (klass);
gobject_class->finalize = gst_image_freeze_finalize; 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 = gstelement_class->change_state =
GST_DEBUG_FUNCPTR (gst_image_freeze_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); g_mutex_init (&self->lock);
self->num_buffers = DEFAULT_NUM_BUFFERS;
gst_image_freeze_reset (self); gst_image_freeze_reset (self);
} }
@ -138,6 +160,8 @@ gst_image_freeze_finalize (GObject * object)
{ {
GstImageFreeze *self = GST_IMAGE_FREEZE (object); GstImageFreeze *self = GST_IMAGE_FREEZE (object);
self->num_buffers = DEFAULT_NUM_BUFFERS;
gst_image_freeze_reset (self); gst_image_freeze_reset (self);
g_mutex_clear (&self->lock); g_mutex_clear (&self->lock);
@ -152,6 +176,7 @@ gst_image_freeze_reset (GstImageFreeze * self)
g_mutex_lock (&self->lock); g_mutex_lock (&self->lock);
gst_buffer_replace (&self->buffer, NULL); gst_buffer_replace (&self->buffer, NULL);
self->num_buffers_left = self->num_buffers;
gst_segment_init (&self->segment, GST_FORMAT_TIME); gst_segment_init (&self->segment, GST_FORMAT_TIME);
self->need_segment = TRUE; self->need_segment = TRUE;
@ -670,6 +695,42 @@ gst_image_freeze_src_event (GstPad * pad, GstObject * parent, GstEvent * event)
return ret; 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 static GstFlowReturn
gst_image_freeze_sink_chain (GstPad * pad, GstObject * parent, gst_image_freeze_sink_chain (GstPad * pad, GstObject * parent,
GstBuffer * buffer) GstBuffer * buffer)
@ -717,6 +778,18 @@ gst_image_freeze_src_loop (GstPad * pad)
g_mutex_unlock (&self->lock); g_mutex_unlock (&self->lock);
goto pause_task; 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); buffer = gst_buffer_copy (self->buffer);
g_mutex_unlock (&self->lock); g_mutex_unlock (&self->lock);

View file

@ -55,6 +55,9 @@ struct _GstImageFreeze
gboolean need_segment; gboolean need_segment;
guint seqnum; guint seqnum;
gint num_buffers;
gint num_buffers_left;
guint64 offset; guint64 offset;
/* TRUE if currently doing a flushing seek, protected /* TRUE if currently doing a flushing seek, protected