core/base: Only post latency messages if the latency values have actually changed
authorSebastian Dröge <sebastian@centricular.com>
Thu, 27 Oct 2022 12:13:36 +0000 (15:13 +0300)
committerGStreamer Marge Bot <gitlab-merge-bot@gstreamer-foundation.org>
Thu, 27 Oct 2022 15:25:22 +0000 (15:25 +0000)
Fixes https://gitlab.freedesktop.org/gstreamer/gstreamer/-/issues/1525

Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/3282>

subprojects/gst-plugins-base/gst-libs/gst/app/gstappsrc.c
subprojects/gst-plugins-base/gst-libs/gst/audio/gstaudiodecoder.c
subprojects/gst-plugins-base/gst-libs/gst/audio/gstaudioencoder.c
subprojects/gst-plugins-base/gst-libs/gst/video/gstvideoencoder.c
subprojects/gstreamer/libs/gst/base/gstaggregator.c
subprojects/gstreamer/libs/gst/base/gstbaseparse.c

index 1fb4674..add6a28 100644 (file)
@@ -183,6 +183,9 @@ struct _GstAppSrcPrivate
 
   guint64 min_latency;
   guint64 max_latency;
+  /* Tracks whether the latency message was posted at least once */
+  gboolean posted_latency_msg;
+
   gboolean emit_signals;
   guint min_percent;
   gboolean handle_segment_change;
@@ -1103,6 +1106,7 @@ gst_app_src_stop (GstBaseSrc * bsrc)
   priv->is_eos = FALSE;
   priv->flushing = TRUE;
   priv->started = FALSE;
+  priv->posted_latency_msg = FALSE;
   gst_app_src_flush_queued (appsrc, TRUE);
   g_cond_broadcast (&priv->cond);
   g_mutex_unlock (&priv->mutex);
@@ -2325,6 +2329,10 @@ gst_app_src_set_latencies (GstAppSrc * appsrc, gboolean do_min, guint64 min,
     priv->max_latency = max;
     changed = TRUE;
   }
+  if (!priv->posted_latency_msg) {
+    priv->posted_latency_msg = TRUE;
+    changed = TRUE;
+  }
   g_mutex_unlock (&priv->mutex);
 
   if (changed) {
index 8b00138..9396a9f 100644 (file)
@@ -180,6 +180,8 @@ typedef struct _GstAudioDecoderContext
   /* MT-protected (with LOCK) */
   GstClockTime min_latency;
   GstClockTime max_latency;
+  /* Tracks whether the latency message was posted at least once */
+  gboolean posted_latency_msg;
 
   GstAllocator *allocator;
   GstAllocationParams params;
@@ -555,6 +557,7 @@ gst_audio_decoder_reset (GstAudioDecoder * dec, gboolean full)
     memset (&dec->priv->ctx, 0, sizeof (dec->priv->ctx));
 
     gst_audio_info_init (&dec->priv->ctx.info);
+    dec->priv->ctx.posted_latency_msg = FALSE;
     GST_OBJECT_UNLOCK (dec);
     dec->priv->ctx.had_output_data = FALSE;
     dec->priv->ctx.had_input_data = FALSE;
@@ -3391,24 +3394,43 @@ gst_audio_decoder_get_max_errors (GstAudioDecoder * dec)
  * @min: minimum latency
  * @max: maximum latency
  *
- * Sets decoder latency.
+ * Sets decoder latency. If the provided values changed from
+ * previously provided ones, this will also post a LATENCY message on the bus
+ * so the pipeline can reconfigure its global latency.
  */
 void
 gst_audio_decoder_set_latency (GstAudioDecoder * dec,
     GstClockTime min, GstClockTime max)
 {
+  gboolean post_message = FALSE;
+
   g_return_if_fail (GST_IS_AUDIO_DECODER (dec));
   g_return_if_fail (GST_CLOCK_TIME_IS_VALID (min));
   g_return_if_fail (min <= max);
 
+  GST_DEBUG_OBJECT (dec,
+      "min_latency:%" GST_TIME_FORMAT " max_latency:%" GST_TIME_FORMAT,
+      GST_TIME_ARGS (min), GST_TIME_ARGS (max));
+
   GST_OBJECT_LOCK (dec);
-  dec->priv->ctx.min_latency = min;
-  dec->priv->ctx.max_latency = max;
+  if (dec->priv->ctx.min_latency != min) {
+    dec->priv->ctx.min_latency = min;
+    post_message = TRUE;
+  }
+  if (dec->priv->ctx.max_latency != max) {
+    dec->priv->ctx.max_latency = max;
+    post_message = TRUE;
+  }
+  if (!dec->priv->ctx.posted_latency_msg) {
+    dec->priv->ctx.posted_latency_msg = TRUE;
+    post_message = TRUE;
+  }
   GST_OBJECT_UNLOCK (dec);
 
   /* post latency message on the bus */
-  gst_element_post_message (GST_ELEMENT (dec),
-      gst_message_new_latency (GST_OBJECT (dec)));
+  if (post_message)
+    gst_element_post_message (GST_ELEMENT (dec),
+        gst_message_new_latency (GST_OBJECT (dec)));
 }
 
 /**
index a2fa472..f772167 100644 (file)
@@ -171,6 +171,9 @@ typedef struct _GstAudioEncoderContext
   /* MT-protected (with LOCK) */
   GstClockTime min_latency;
   GstClockTime max_latency;
+  /* Tracks whether the latency message was posted at least once */
+  gboolean posted_latency_msg;
+
   gboolean negotiated;
 
   GList *headers;
@@ -493,6 +496,7 @@ gst_audio_encoder_reset (GstAudioEncoder * enc, gboolean full)
 
     memset (&enc->priv->ctx, 0, sizeof (enc->priv->ctx));
     gst_audio_info_init (&enc->priv->ctx.info);
+    enc->priv->ctx.posted_latency_msg = FALSE;
     GST_OBJECT_UNLOCK (enc);
 
     if (enc->priv->upstream_tags) {
@@ -2346,27 +2350,43 @@ gst_audio_encoder_get_lookahead (GstAudioEncoder * enc)
  * @min: minimum latency
  * @max: maximum latency
  *
- * Sets encoder latency.
+ * Sets encoder latency. If the provided values changed from
+ * previously provided ones, this will also post a LATENCY message on the bus
+ * so the pipeline can reconfigure its global latency.
  */
 void
 gst_audio_encoder_set_latency (GstAudioEncoder * enc,
     GstClockTime min, GstClockTime max)
 {
+  gboolean post_message = FALSE;
+
   g_return_if_fail (GST_IS_AUDIO_ENCODER (enc));
   g_return_if_fail (GST_CLOCK_TIME_IS_VALID (min));
   g_return_if_fail (min <= max);
 
+  GST_DEBUG_OBJECT (enc,
+      "min_latency:%" GST_TIME_FORMAT " max_latency:%" GST_TIME_FORMAT,
+      GST_TIME_ARGS (min), GST_TIME_ARGS (max));
+
   GST_OBJECT_LOCK (enc);
-  enc->priv->ctx.min_latency = min;
-  enc->priv->ctx.max_latency = max;
+  if (enc->priv->ctx.min_latency != min) {
+    enc->priv->ctx.min_latency = min;
+    post_message = TRUE;
+  }
+  if (enc->priv->ctx.max_latency != max) {
+    enc->priv->ctx.max_latency = max;
+    post_message = TRUE;
+  }
+  if (!enc->priv->ctx.posted_latency_msg) {
+    enc->priv->ctx.posted_latency_msg = TRUE;
+    post_message = TRUE;
+  }
   GST_OBJECT_UNLOCK (enc);
 
-  GST_LOG_OBJECT (enc, "set to %" GST_TIME_FORMAT "-%" GST_TIME_FORMAT,
-      GST_TIME_ARGS (min), GST_TIME_ARGS (max));
-
   /* post latency message on the bus */
-  gst_element_post_message (GST_ELEMENT (enc),
-      gst_message_new_latency (GST_OBJECT (enc)));
+  if (post_message)
+    gst_element_post_message (GST_ELEMENT (enc),
+        gst_message_new_latency (GST_OBJECT (enc)));
 }
 
 /**
index 2f814ad..fcfb15b 100644 (file)
@@ -134,6 +134,9 @@ struct _GstVideoEncoderPrivate
   gint64 min_latency;
   gint64 max_latency;
 
+  /* Tracks whether the latency message was posted at least once */
+  gboolean posted_latency_msg;
+
   /* FIXME 2.0: Use a GQueue or similar, see GstVideoCodecFrame::events */
   GList *current_frame_events;
 
@@ -512,6 +515,8 @@ gst_video_encoder_reset (GstVideoEncoder * encoder, gboolean hard)
 
     priv->dropped = 0;
     priv->processed = 0;
+
+    priv->posted_latency_msg = FALSE;
   } else {
     GList *l;
 
@@ -2853,22 +2858,41 @@ gst_video_encoder_set_output_state (GstVideoEncoder * encoder, GstCaps * caps,
  * @min_latency: minimum latency
  * @max_latency: maximum latency
  *
- * Informs baseclass of encoding latency.
+ * Informs baseclass of encoding latency. If the provided values changed from
+ * previously provided ones, this will also post a LATENCY message on the bus
+ * so the pipeline can reconfigure its global latency.
  */
 void
 gst_video_encoder_set_latency (GstVideoEncoder * encoder,
     GstClockTime min_latency, GstClockTime max_latency)
 {
+  gboolean post_message = FALSE;
+
   g_return_if_fail (GST_CLOCK_TIME_IS_VALID (min_latency));
   g_return_if_fail (max_latency >= min_latency);
 
+  GST_DEBUG_OBJECT (encoder,
+      "min_latency:%" GST_TIME_FORMAT " max_latency:%" GST_TIME_FORMAT,
+      GST_TIME_ARGS (min_latency), GST_TIME_ARGS (max_latency));
+
   GST_OBJECT_LOCK (encoder);
-  encoder->priv->min_latency = min_latency;
-  encoder->priv->max_latency = max_latency;
+  if (encoder->priv->min_latency != min_latency) {
+    encoder->priv->min_latency = min_latency;
+    post_message = TRUE;
+  }
+  if (encoder->priv->max_latency != max_latency) {
+    encoder->priv->max_latency = max_latency;
+    post_message = TRUE;
+  }
+  if (!encoder->priv->posted_latency_msg) {
+    encoder->priv->posted_latency_msg = TRUE;
+    post_message = TRUE;
+  }
   GST_OBJECT_UNLOCK (encoder);
 
-  gst_element_post_message (GST_ELEMENT_CAST (encoder),
-      gst_message_new_latency (GST_OBJECT_CAST (encoder)));
+  if (post_message)
+    gst_element_post_message (GST_ELEMENT_CAST (encoder),
+        gst_message_new_latency (GST_OBJECT_CAST (encoder)));
 }
 
 /**
index 3e7d12a..d51ac56 100644 (file)
@@ -384,6 +384,8 @@ struct _GstAggregatorPrivate
 
   GstClockTime sub_latency_min; /* protected by src_lock */
   GstClockTime sub_latency_max; /* protected by src_lock */
+  /* Tracks whether the latency message was posted at least once */
+  gboolean posted_latency_msg;
 
   GstClockTime upstream_latency_min;    /* protected by src_lock */
 
@@ -1914,6 +1916,7 @@ gst_aggregator_stop (GstAggregator * agg)
   agg->priv->has_peer_latency = FALSE;
   agg->priv->peer_latency_live = FALSE;
   agg->priv->peer_latency_min = agg->priv->peer_latency_max = 0;
+  agg->priv->posted_latency_msg = FALSE;
 
   if (agg->priv->tags)
     gst_tag_list_unref (agg->priv->tags);
@@ -3699,7 +3702,7 @@ gst_aggregator_merge_tags (GstAggregator * self,
  *
  * Lets #GstAggregator sub-classes tell the baseclass what their internal
  * latency is. Will also post a LATENCY message on the bus so the pipeline
- * can reconfigure its global latency.
+ * can reconfigure its global latency if the values changed.
  */
 void
 gst_aggregator_set_latency (GstAggregator * self,
@@ -3720,6 +3723,10 @@ gst_aggregator_set_latency (GstAggregator * self,
     self->priv->sub_latency_max = max_latency;
     changed = TRUE;
   }
+  if (!self->priv->posted_latency_msg) {
+    self->priv->posted_latency_msg = TRUE;
+    changed = TRUE;
+  }
 
   if (changed)
     SRC_BROADCAST (self);
index e1920a9..4e7c46e 100644 (file)
@@ -231,6 +231,8 @@ struct _GstBaseParsePrivate
   guint lead_in, lead_out;
   GstClockTime lead_in_ts, lead_out_ts;
   GstClockTime min_latency, max_latency;
+  /* Tracks whether the latency message was posted at least once */
+  gboolean posted_latency_msg;
 
   gboolean discont;
   gboolean flushing;
@@ -899,6 +901,7 @@ gst_base_parse_reset (GstBaseParse * parse)
   parse->priv->detect_buffers_size = 0;
 
   parse->priv->segment_seqnum = GST_SEQNUM_INVALID;
+  parse->priv->posted_latency_msg = FALSE;
   GST_OBJECT_UNLOCK (parse);
 }
 
@@ -4081,23 +4084,44 @@ gst_base_parse_set_infer_ts (GstBaseParse * parse, gboolean infer_ts)
  * @max_latency: maximum parse latency
  *
  * Sets the minimum and maximum (which may likely be equal) latency introduced
- * by the parsing process.  If there is such a latency, which depends on the
+ * by the parsing process. If there is such a latency, which depends on the
  * particular parsing of the format, it typically corresponds to 1 frame duration.
+ *
+ * If the provided values changed from previously provided ones, this will
+ * also post a LATENCY message on the bus so the pipeline can reconfigure its
+ * global latency.
  */
 void
 gst_base_parse_set_latency (GstBaseParse * parse, GstClockTime min_latency,
     GstClockTime max_latency)
 {
+  gboolean post_message = FALSE;
+
   g_return_if_fail (GST_CLOCK_TIME_IS_VALID (min_latency));
   g_return_if_fail (min_latency <= max_latency);
 
-  GST_OBJECT_LOCK (parse);
-  parse->priv->min_latency = min_latency;
-  parse->priv->max_latency = max_latency;
-  GST_OBJECT_UNLOCK (parse);
   GST_INFO_OBJECT (parse, "min/max latency %" GST_TIME_FORMAT ", %"
       GST_TIME_FORMAT, GST_TIME_ARGS (min_latency),
       GST_TIME_ARGS (max_latency));
+
+  GST_OBJECT_LOCK (parse);
+  if (parse->priv->min_latency != min_latency) {
+    parse->priv->min_latency = min_latency;
+    post_message = TRUE;
+  }
+  if (parse->priv->max_latency != max_latency) {
+    parse->priv->max_latency = max_latency;
+    post_message = TRUE;
+  }
+  if (!parse->priv->posted_latency_msg) {
+    parse->priv->posted_latency_msg = TRUE;
+    post_message = TRUE;
+  }
+  GST_OBJECT_UNLOCK (parse);
+
+  if (post_message)
+    gst_element_post_message (GST_ELEMENT_CAST (parse),
+        gst_message_new_latency (GST_OBJECT_CAST (parse)));
 }
 
 static gboolean