identity: Fix the ts-offset property getter
[platform/upstream/gstreamer.git] / plugins / elements / gstidentity.c
index 119fb58..bf6ba40 100644 (file)
@@ -74,6 +74,8 @@ enum
 #define DEFAULT_CHECK_IMPERFECT_OFFSET    FALSE
 #define DEFAULT_SIGNAL_HANDOFFS           TRUE
 #define DEFAULT_TS_OFFSET               0
+#define DEFAULT_DROP_ALLOCATION         FALSE
+#define DEFAULT_EOS_AFTER               -1
 
 enum
 {
@@ -91,7 +93,9 @@ enum
   PROP_TS_OFFSET,
   PROP_CHECK_IMPERFECT_TIMESTAMP,
   PROP_CHECK_IMPERFECT_OFFSET,
-  PROP_SIGNAL_HANDOFFS
+  PROP_SIGNAL_HANDOFFS,
+  PROP_DROP_ALLOCATION,
+  PROP_EOS_AFTER
 };
 
 
@@ -157,7 +161,7 @@ gst_identity_class_init (GstIdentityClass * klass)
           DEFAULT_SLEEP_TIME, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
   g_object_class_install_property (gobject_class, PROP_ERROR_AFTER,
       g_param_spec_int ("error-after", "Error After", "Error after N buffers",
-          G_MININT, G_MAXINT, DEFAULT_ERROR_AFTER,
+          -1, G_MAXINT, DEFAULT_ERROR_AFTER,
           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
   g_object_class_install_property (gobject_class, PROP_DROP_PROBABILITY,
       g_param_spec_float ("drop-probability", "Drop Probability",
@@ -222,14 +226,31 @@ gst_identity_class_init (GstIdentityClass * klass)
   /**
    * GstIdentity:signal-handoffs
    *
-   * If set to #TRUE, the identity will emit a handoff signal when handling a buffer.
-   * When set to #FALSE, no signal will be emitted, which might improve performance.
+   * If set to %TRUE, the identity will emit a handoff signal when handling a buffer.
+   * When set to %FALSE, no signal will be emitted, which might improve performance.
    */
   g_object_class_install_property (gobject_class, PROP_SIGNAL_HANDOFFS,
       g_param_spec_boolean ("signal-handoffs",
           "Signal handoffs", "Send a signal before pushing the buffer",
           DEFAULT_SIGNAL_HANDOFFS, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
 
+  g_object_class_install_property (gobject_class, PROP_DROP_ALLOCATION,
+      g_param_spec_boolean ("drop-allocation", "Drop allocation query",
+          "Don't forward allocation queries", DEFAULT_DROP_ALLOCATION,
+          G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+
+  /**
+   * GstIdentity:eos-after
+   *
+   * EOS after N buffers.
+   *
+   * Since: 1.16
+   **/
+  g_object_class_install_property (gobject_class, PROP_EOS_AFTER,
+      g_param_spec_int ("eos-after", "EOS After", "EOS after N buffers",
+          -1, G_MAXINT, DEFAULT_EOS_AFTER,
+          G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+
   /**
    * GstIdentity::handoff:
    * @identity: the identity instance
@@ -271,6 +292,7 @@ gst_identity_init (GstIdentity * identity)
 {
   identity->sleep_time = DEFAULT_SLEEP_TIME;
   identity->error_after = DEFAULT_ERROR_AFTER;
+  identity->error_after_counter = DEFAULT_ERROR_AFTER;
   identity->drop_probability = DEFAULT_DROP_PROBABILITY;
   identity->drop_buffer_flags = DEFAULT_DROP_BUFFER_FLAGS;
   identity->datarate = DEFAULT_DATARATE;
@@ -284,6 +306,8 @@ gst_identity_init (GstIdentity * identity)
   identity->signal_handoffs = DEFAULT_SIGNAL_HANDOFFS;
   identity->ts_offset = DEFAULT_TS_OFFSET;
   g_cond_init (&identity->blocked_cond);
+  identity->eos_after = DEFAULT_EOS_AFTER;
+  identity->eos_after_counter = DEFAULT_EOS_AFTER;
 
   gst_base_transform_set_gap_aware (GST_BASE_TRANSFORM_CAST (identity), TRUE);
 }
@@ -305,9 +329,18 @@ gst_identity_do_sync (GstIdentity * identity, GstClockTime running_time)
 
     GST_OBJECT_LOCK (identity);
 
+    if (identity->flushing) {
+      GST_OBJECT_UNLOCK (identity);
+      return GST_FLOW_FLUSHING;
+    }
+
     while (identity->blocked)
       g_cond_wait (&identity->blocked_cond, GST_OBJECT_GET_LOCK (identity));
 
+    if (identity->flushing) {
+      GST_OBJECT_UNLOCK (identity);
+      return GST_FLOW_FLUSHING;
+    }
 
     if ((clock = GST_ELEMENT (identity)->clock)) {
       GstClockReturn cret;
@@ -336,8 +369,8 @@ gst_identity_do_sync (GstIdentity * identity, GstClockTime running_time)
         gst_clock_id_unref (identity->clock_id);
         identity->clock_id = NULL;
       }
-      if (cret == GST_CLOCK_UNSCHEDULED)
-        ret = GST_FLOW_EOS;
+      if (cret == GST_CLOCK_UNSCHEDULED || identity->flushing)
+        ret = GST_FLOW_FLUSHING;
     }
     GST_OBJECT_UNLOCK (identity);
   }
@@ -430,11 +463,16 @@ gst_identity_sink_event (GstBaseTransform * trans, GstEvent * event)
   } else {
     if (GST_EVENT_TYPE (event) == GST_EVENT_FLUSH_START) {
       GST_OBJECT_LOCK (identity);
+      identity->flushing = TRUE;
       if (identity->clock_id) {
         GST_DEBUG_OBJECT (identity, "unlock clock wait");
         gst_clock_id_unschedule (identity->clock_id);
       }
       GST_OBJECT_UNLOCK (identity);
+    } else if (GST_EVENT_TYPE (event) == GST_EVENT_FLUSH_STOP) {
+      GST_OBJECT_LOCK (identity);
+      identity->flushing = FALSE;
+      GST_OBJECT_UNLOCK (identity);
     }
 
     ret = GST_BASE_TRANSFORM_CLASS (parent_class)->sink_event (trans, event);
@@ -603,12 +641,18 @@ gst_identity_transform_ip (GstBaseTransform * trans, GstBuffer * buf)
   identity->prev_offset_end = GST_BUFFER_OFFSET_END (buf);
   identity->prev_offset = GST_BUFFER_OFFSET (buf);
 
-  if (identity->error_after >= 0) {
-    identity->error_after--;
-    if (identity->error_after == 0)
+  if (identity->error_after_counter >= 0) {
+    identity->error_after_counter--;
+    if (identity->error_after_counter == 0)
       goto error_after;
   }
 
+  if (identity->eos_after_counter >= 0) {
+    identity->eos_after_counter--;
+    if (identity->eos_after_counter == 0)
+      goto eos_after;
+  }
+
   if (identity->drop_probability > 0.0) {
     if ((gfloat) (1.0 * rand () / (RAND_MAX)) < identity->drop_probability)
       goto dropped;
@@ -678,6 +722,11 @@ error_after:
         (_("Failed after iterations as requested.")), (NULL));
     return GST_FLOW_ERROR;
   }
+eos_after:
+  {
+    GST_DEBUG_OBJECT (identity, "EOS after iterations as requested.");
+    return GST_FLOW_EOS;
+  }
 dropped:
   {
     if (!identity->silent) {
@@ -745,6 +794,12 @@ gst_identity_set_property (GObject * object, guint prop_id,
     case PROP_SIGNAL_HANDOFFS:
       identity->signal_handoffs = g_value_get_boolean (value);
       break;
+    case PROP_DROP_ALLOCATION:
+      identity->drop_allocation = g_value_get_boolean (value);
+      break;
+    case PROP_EOS_AFTER:
+      identity->eos_after = g_value_get_int (value);
+      break;
     default:
       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
       break;
@@ -797,7 +852,7 @@ gst_identity_get_property (GObject * object, guint prop_id, GValue * value,
       g_value_set_boolean (value, identity->sync);
       break;
     case PROP_TS_OFFSET:
-      identity->ts_offset = g_value_get_int64 (value);
+      g_value_set_int64 (value, identity->ts_offset);
       break;
     case PROP_CHECK_IMPERFECT_TIMESTAMP:
       g_value_set_boolean (value, identity->check_imperfect_timestamp);
@@ -808,6 +863,12 @@ gst_identity_get_property (GObject * object, guint prop_id, GValue * value,
     case PROP_SIGNAL_HANDOFFS:
       g_value_set_boolean (value, identity->signal_handoffs);
       break;
+    case PROP_DROP_ALLOCATION:
+      g_value_set_boolean (value, identity->drop_allocation);
+      break;
+    case PROP_EOS_AFTER:
+      g_value_set_int (value, identity->eos_after);
+      break;
     default:
       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
       break;
@@ -821,13 +882,27 @@ gst_identity_start (GstBaseTransform * trans)
 
   identity = GST_IDENTITY (trans);
 
+  if (identity->eos_after != DEFAULT_EOS_AFTER
+      && identity->error_after != DEFAULT_ERROR_AFTER)
+    goto both_afters_defined;
+
   identity->offset = 0;
   identity->prev_timestamp = GST_CLOCK_TIME_NONE;
   identity->prev_duration = GST_CLOCK_TIME_NONE;
   identity->prev_offset_end = GST_BUFFER_OFFSET_NONE;
   identity->prev_offset = GST_BUFFER_OFFSET_NONE;
+  identity->error_after_counter = identity->error_after;
+  identity->eos_after_counter = identity->eos_after;
 
   return TRUE;
+
+  /* ERROR */
+both_afters_defined:
+  {
+    GST_ELEMENT_ERROR (identity, CORE, FAILED,
+        (_("eos-after and error-after can't both be defined.")), (NULL));
+    return FALSE;
+  }
 }
 
 static gboolean
@@ -873,6 +948,12 @@ gst_identity_query (GstBaseTransform * base, GstPadDirection direction,
 
   identity = GST_IDENTITY (base);
 
+  if (GST_QUERY_TYPE (query) == GST_QUERY_ALLOCATION &&
+      identity->drop_allocation) {
+    GST_DEBUG_OBJECT (identity, "Dropping allocation query.");
+    return FALSE;
+  }
+
   ret = GST_BASE_TRANSFORM_CLASS (parent_class)->query (base, direction, query);
 
   if (GST_QUERY_TYPE (query) == GST_QUERY_LATENCY) {
@@ -917,6 +998,7 @@ gst_identity_change_state (GstElement * element, GstStateChange transition)
       break;
     case GST_STATE_CHANGE_READY_TO_PAUSED:
       GST_OBJECT_LOCK (identity);
+      identity->flushing = FALSE;
       identity->blocked = TRUE;
       GST_OBJECT_UNLOCK (identity);
       if (identity->sync)
@@ -930,6 +1012,7 @@ gst_identity_change_state (GstElement * element, GstStateChange transition)
       break;
     case GST_STATE_CHANGE_PAUSED_TO_READY:
       GST_OBJECT_LOCK (identity);
+      identity->flushing = TRUE;
       if (identity->clock_id) {
         GST_DEBUG_OBJECT (identity, "unlock clock wait");
         gst_clock_id_unschedule (identity->clock_id);