imagefreeze: add a num-buffers property
authorAntonio Ospite <antonio.ospite@collabora.com>
Wed, 13 Mar 2019 12:03:44 +0000 (13:03 +0100)
committerAntonio Ospite <antonio.ospite@collabora.com>
Thu, 14 Mar 2019 08:12:28 +0000 (09:12 +0100)
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
gst/imagefreeze/gstimagefreeze.h

index 00876da..35cd1f7 100644 (file)
 
 #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);
index 19e803b..4d03118 100644 (file)
@@ -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