fakesink: Add property to not drop out-of-segment buffers
authorJan Schmidt <jan@centricular.com>
Thu, 28 Apr 2016 16:38:49 +0000 (02:38 +1000)
committerJan Schmidt <jan@centricular.com>
Wed, 2 Nov 2016 00:21:37 +0000 (11:21 +1100)
Implement handling in basesink to not unconditionally discard
out-of-segment buffers and expose it as a new property on fakesink
(not unconditionally in all basesink based sinks).

The property defaults to FALSE.

https://bugzilla.gnome.org/show_bug.cgi?id=765734

libs/gst/base/gstbasesink.c
libs/gst/base/gstbasesink.h
plugins/elements/gstfakesink.c

index ac2390f..9f56e9f 100644 (file)
@@ -258,6 +258,8 @@ struct _GstBaseSinkPrivate
   GstClockTime rc_time;
   GstClockTime rc_next;
   gsize rc_accumulated;
+
+  gboolean drop_out_of_segment;
 };
 
 #define DO_RUNNING_AVG(avg,val,size) (((val) + ((size)-1) * (avg)) / (size))
@@ -286,6 +288,7 @@ struct _GstBaseSinkPrivate
 #define DEFAULT_ENABLE_LAST_SAMPLE  TRUE
 #define DEFAULT_THROTTLE_TIME       0
 #define DEFAULT_MAX_BITRATE         0
+#define DEFAULT_DROP_OUT_OF_SEGMENT TRUE
 
 enum
 {
@@ -655,6 +658,8 @@ gst_base_sink_init (GstBaseSink * basesink, gpointer g_class)
   priv->throttle_time = DEFAULT_THROTTLE_TIME;
   priv->max_bitrate = DEFAULT_MAX_BITRATE;
 
+  priv->drop_out_of_segment = DEFAULT_DROP_OUT_OF_SEGMENT;
+
   GST_OBJECT_FLAG_SET (basesink, GST_ELEMENT_FLAG_SINK);
 }
 
@@ -716,6 +721,57 @@ gst_base_sink_get_sync (GstBaseSink * sink)
 }
 
 /**
+ * gst_base_sink_set_drop_out_of_segment:
+ * @sink: the sink
+ *
+ * Checks if @sink is currently configured to synchronize against the
+ * clock.
+ *
+ * Returns: %TRUE if the sink is configured to synchronize against the clock.
+ */
+void
+gst_base_sink_set_drop_out_of_segment (GstBaseSink * sink,
+    gboolean drop_out_of_segment)
+{
+  GstBaseSinkPrivate *priv;
+
+  g_return_if_fail (GST_IS_BASE_SINK (sink));
+
+  priv = GST_BASE_SINK_GET_PRIVATE (sink);
+
+  GST_OBJECT_LOCK (sink);
+  priv->drop_out_of_segment = drop_out_of_segment;
+  GST_OBJECT_UNLOCK (sink);
+
+}
+
+/**
+ * gst_base_sink_get_drop_out_of_segment:
+ * @sink: the sink
+ *
+ * Checks if @sink is currently configured to drop buffers which are outside
+ * the current segment
+ *
+ * Returns: %TRUE if the sink is configured to synchronize against the clock.
+ */
+gboolean
+gst_base_sink_get_drop_out_of_segment (GstBaseSink * sink)
+{
+  GstBaseSinkPrivate *priv;
+  gboolean res;
+
+  g_return_val_if_fail (GST_IS_BASE_SINK (sink), FALSE);
+
+  priv = GST_BASE_SINK_GET_PRIVATE (sink);
+
+  GST_OBJECT_LOCK (sink);
+  res = priv->drop_out_of_segment;
+  GST_OBJECT_UNLOCK (sink);
+
+  return res;
+}
+
+/**
  * gst_base_sink_set_max_lateness:
  * @sink: the sink
  * @max_lateness: the new max lateness value.
@@ -3373,7 +3429,8 @@ gst_base_sink_chain_unlocked (GstBaseSink * basesink, GstPad * pad,
       pts_end = pts + (end - start);
 
     if (G_UNLIKELY (!gst_segment_clip (segment,
-                GST_FORMAT_TIME, pts, pts_end, NULL, NULL)))
+                GST_FORMAT_TIME, pts, pts_end, NULL, NULL)
+            && priv->drop_out_of_segment))
       goto out_of_segment;
   }
 
index 1df5d65..02c4a7a 100644 (file)
@@ -207,6 +207,10 @@ GstFlowReturn   gst_base_sink_wait_preroll      (GstBaseSink *sink);
 void            gst_base_sink_set_sync          (GstBaseSink *sink, gboolean sync);
 gboolean        gst_base_sink_get_sync          (GstBaseSink *sink);
 
+/* Drop buffers which are out of segment */
+void            gst_base_sink_set_drop_out_of_segment (GstBaseSink *sink, gboolean drop_clipped);
+gboolean        gst_base_sink_get_drop_out_of_segment (GstBaseSink *sink);
+
 /* dropping late buffers */
 void            gst_base_sink_set_max_lateness  (GstBaseSink *sink, gint64 max_lateness);
 gint64          gst_base_sink_get_max_lateness  (GstBaseSink *sink);
index c9c3e3a..9f75e48 100644 (file)
@@ -59,6 +59,7 @@ enum
 };
 
 #define DEFAULT_SYNC FALSE
+#define DEFAULT_DROP_OUT_OF_SEGMENT TRUE
 
 #define DEFAULT_STATE_ERROR FAKE_SINK_STATE_ERROR_NONE
 #define DEFAULT_SILENT TRUE
@@ -76,6 +77,7 @@ enum
   PROP_SILENT,
   PROP_DUMP,
   PROP_SIGNAL_HANDOFFS,
+  PROP_DROP_OUT_OF_SEGMENT,
   PROP_LAST_MESSAGE,
   PROP_CAN_ACTIVATE_PUSH,
   PROP_CAN_ACTIVATE_PULL,
@@ -165,6 +167,12 @@ gst_fake_sink_class_init (GstFakeSinkClass * klass)
       g_param_spec_boolean ("signal-handoffs", "Signal handoffs",
           "Send a signal before unreffing the buffer", DEFAULT_SIGNAL_HANDOFFS,
           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+  g_object_class_install_property (gobject_class, PROP_DROP_OUT_OF_SEGMENT,
+      g_param_spec_boolean ("drop-out-of-segment",
+          "Drop out-of-segment buffers",
+          "Drop and don't render / hand off out-of-segment buffers",
+          DEFAULT_DROP_OUT_OF_SEGMENT,
+          G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
   g_object_class_install_property (gobject_class, PROP_SILENT,
       g_param_spec_boolean ("silent", "Silent",
           "Don't produce last_message events", DEFAULT_SILENT,
@@ -172,15 +180,14 @@ gst_fake_sink_class_init (GstFakeSinkClass * klass)
           G_PARAM_STATIC_STRINGS));
   g_object_class_install_property (gobject_class, PROP_DUMP,
       g_param_spec_boolean ("dump", "Dump", "Dump buffer contents to stdout",
-          DEFAULT_DUMP, G_PARAM_READWRITE | GST_PARAM_MUTABLE_PLAYING |
+          DEFAULT_DUMP,
+          G_PARAM_READWRITE | GST_PARAM_MUTABLE_PLAYING |
           G_PARAM_STATIC_STRINGS));
-  g_object_class_install_property (gobject_class,
-      PROP_CAN_ACTIVATE_PUSH,
+  g_object_class_install_property (gobject_class, PROP_CAN_ACTIVATE_PUSH,
       g_param_spec_boolean ("can-activate-push", "Can activate push",
           "Can activate in push mode", DEFAULT_CAN_ACTIVATE_PUSH,
           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
-  g_object_class_install_property (gobject_class,
-      PROP_CAN_ACTIVATE_PULL,
+  g_object_class_install_property (gobject_class, PROP_CAN_ACTIVATE_PULL,
       g_param_spec_boolean ("can-activate-pull", "Can activate pull",
           "Can activate in pull mode", DEFAULT_CAN_ACTIVATE_PULL,
           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
@@ -247,6 +254,8 @@ gst_fake_sink_init (GstFakeSink * fakesink)
   fakesink->num_buffers = DEFAULT_NUM_BUFFERS;
 
   gst_base_sink_set_sync (GST_BASE_SINK (fakesink), DEFAULT_SYNC);
+  gst_base_sink_set_drop_out_of_segment (GST_BASE_SINK (fakesink),
+      DEFAULT_DROP_OUT_OF_SEGMENT);
 }
 
 static void
@@ -276,6 +285,10 @@ gst_fake_sink_set_property (GObject * object, guint prop_id,
     case PROP_SIGNAL_HANDOFFS:
       sink->signal_handoffs = g_value_get_boolean (value);
       break;
+    case PROP_DROP_OUT_OF_SEGMENT:
+      gst_base_sink_set_drop_out_of_segment (GST_BASE_SINK (object),
+          g_value_get_boolean (value));
+      break;
     case PROP_CAN_ACTIVATE_PUSH:
       GST_BASE_SINK (sink)->can_activate_push = g_value_get_boolean (value);
       break;
@@ -312,6 +325,10 @@ gst_fake_sink_get_property (GObject * object, guint prop_id, GValue * value,
     case PROP_SIGNAL_HANDOFFS:
       g_value_set_boolean (value, sink->signal_handoffs);
       break;
+    case PROP_DROP_OUT_OF_SEGMENT:
+      g_value_set_boolean (value,
+          gst_base_sink_get_drop_out_of_segment (GST_BASE_SINK (object)));
+      break;
     case PROP_LAST_MESSAGE:
       GST_OBJECT_LOCK (sink);
       g_value_set_string (value, sink->last_message);