summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorOlivier CrĂȘte <olivier.crete@collabora.com>2021-05-26 10:38:18 -0400
committerOlivier CrĂȘte <olivier.crete@collabora.com>2021-07-08 23:01:13 -0400
commit49f6d3bf33687661d5985aaf6fccc14271de0470 (patch)
tree3169ed22a76594bfc5661723b207fe7c55e2bb37
parentea516aee33fb27e698327cb6848fbb7143f6f0f4 (diff)
downloadgstreamer-plugins-base-49f6d3bf33687661d5985aaf6fccc14271de0470.tar.gz
audio aggregator: Post QoS message when dropping audio
Post a QoS message every time some audio samples are dropped. Also print log messages to make it easier to debug Part-of: <https://gitlab.freedesktop.org/gstreamer/gst-plugins-base/-/merge_requests/1209>
-rw-r--r--gst-libs/gst/audio/gstaudioaggregator.c101
1 files changed, 101 insertions, 0 deletions
diff --git a/gst-libs/gst/audio/gstaudioaggregator.c b/gst-libs/gst/audio/gstaudioaggregator.c
index 4187d1da4..7e5bfe911 100644
--- a/gst-libs/gst/audio/gstaudioaggregator.c
+++ b/gst-libs/gst/audio/gstaudioaggregator.c
@@ -478,6 +478,10 @@ struct _GstAudioAggregatorPrivate
/* info structure passed to selected-samples signal, must only be accessed
* from the aggregate thread */
GstStructure *selected_samples_info;
+
+ /* Only access from src thread */
+ /* Messages to post after releasing locks */
+ GQueue messages;
};
#define GST_AUDIO_AGGREGATOR_LOCK(self) g_mutex_lock (&(self)->priv->mutex);
@@ -713,6 +717,8 @@ gst_audio_aggregator_init (GstAudioAggregator * aagg)
aagg->priv->selected_samples_info =
gst_structure_new_empty ("GstAudioAggregatorSelectedSamplesInfo");
+
+ g_queue_init (&aagg->priv->messages);
}
static void
@@ -1637,6 +1643,74 @@ gst_audio_aggregator_do_clip (GstAggregator * agg,
return buffer;
}
+
+/* Called with the object lock for both the element and pad held,
+ * as well as the audio aggregator lock.
+ * Should only be called on the output queue.
+ */
+static GstClockTime
+gst_audio_aggregator_pad_enqueue_qos_message (GstAudioAggregatorPad * pad,
+ GstAudioAggregator * aagg, guint64 samples)
+{
+ GstAggregator *agg = GST_AGGREGATOR (aagg);
+ GstAggregatorPad *aggpad = GST_AGGREGATOR_PAD (pad);
+ GstAudioAggregatorPad *srcpad = GST_AUDIO_AGGREGATOR_PAD (agg->srcpad);
+
+ guint rate_output = GST_AUDIO_INFO_RATE (&srcpad->info);
+ GstClockTime offset = gst_util_uint64_scale (GST_SECOND, pad->priv->position,
+ rate_output);
+ GstClockTime timestamp = GST_BUFFER_PTS (pad->priv->buffer) + offset;
+ GstClockTime running_time =
+ gst_segment_to_running_time (&aggpad->segment, GST_FORMAT_TIME,
+ timestamp);
+ GstClockTime stream_time = gst_segment_to_stream_time (&aggpad->segment,
+ GST_FORMAT_TIME, timestamp);
+ GstClockTime duration;
+ guint rate_input;
+ guint64 processed, dropped;
+ GstMessage *msg;
+
+ if (GST_AUDIO_AGGREGATOR_PAD_GET_CLASS (pad)->convert_buffer)
+ rate_input = GST_AUDIO_INFO_RATE (&srcpad->info);
+ else
+ rate_input = GST_AUDIO_INFO_RATE (&pad->info);
+
+ duration = gst_util_uint64_scale (samples, GST_SECOND, rate_input);
+
+ processed = gst_util_uint64_scale (pad->priv->processed, rate_input,
+ rate_output);
+ dropped = gst_util_uint64_scale (pad->priv->dropped, rate_output,
+ rate_output);
+
+ msg = gst_message_new_qos (GST_OBJECT (aggpad), TRUE, running_time,
+ stream_time, timestamp, duration);
+ gst_message_set_qos_stats (msg, GST_FORMAT_DEFAULT, processed, dropped);
+
+ g_queue_push_tail (&aagg->priv->messages, msg);
+
+ return running_time;
+}
+
+static void
+gst_audio_aggregator_post_messages (GstAudioAggregator * aagg)
+{
+ if (g_queue_get_length (&aagg->priv->messages) != 0) {
+ GstClockTime latency = gst_aggregator_get_latency (GST_AGGREGATOR (aagg));
+ gboolean is_live = GST_CLOCK_TIME_IS_VALID (latency);
+ GstElement *e = GST_ELEMENT (aagg);
+ GstMessage *msg;
+
+ while ((msg = g_queue_pop_head (&aagg->priv->messages))) {
+ if (is_live) {
+ GstStructure *s = gst_message_writable_structure (msg);
+ gst_structure_set (s, "live", G_TYPE_BOOLEAN, TRUE, NULL);
+ }
+
+ gst_element_post_message (e, msg);
+ }
+ }
+}
+
/* Called with the object lock for both the element and pad held,
* as well as the aagg lock
*
@@ -1796,6 +1870,15 @@ gst_audio_aggregator_fill_buffer (GstAudioAggregator * aagg,
end_output_offset = start_output_offset + pad->priv->size;
if (end_output_offset < aagg->priv->offset) {
+ GstClockTime rt;
+
+ pad->priv->dropped += pad->priv->size;
+ rt = gst_audio_aggregator_pad_enqueue_qos_message (pad, aagg,
+ pad->priv->size);
+ GST_DEBUG_OBJECT (pad, "Dropped buffer of %u samples at running time %"
+ GST_TIME_FORMAT " because input buffer is entirely before current"
+ " output offset", pad->priv->size, GST_TIME_ARGS (rt));
+
pad->priv->position = 0;
pad->priv->size = 0;
GST_DEBUG_OBJECT (pad,
@@ -1827,6 +1910,14 @@ gst_audio_aggregator_fill_buffer (GstAudioAggregator * aagg,
}
pad->priv->dropped += MIN (diff, pad->priv->size);
+ if (diff != 0 && pad->priv->qos_messages) {
+ GstClockTime rt;
+
+ rt = gst_audio_aggregator_pad_enqueue_qos_message (pad, aagg, diff);
+ GST_DEBUG_OBJECT (pad, "Dropped %u samples at running time %"
+ GST_TIME_FORMAT " because input buffer starts before current"
+ " output offset", diff, GST_TIME_ARGS (rt));
+ }
pad->priv->position += diff;
if (pad->priv->position >= pad->priv->size) {
/* Empty buffer, drop */
@@ -2237,6 +2328,14 @@ gst_audio_aggregator_aggregate (GstAggregator * agg, gboolean timeout)
if (pad->priv->position + diff > pad->priv->size)
diff = pad->priv->size - pad->priv->position;
pad->priv->dropped += diff;
+ if (diff != 0 && pad->priv->qos_messages) {
+ GstClockTime rt;
+
+ rt = gst_audio_aggregator_pad_enqueue_qos_message (pad, aagg, diff);
+ GST_DEBUG_OBJECT (pad, "Dropped %" G_GINT64_FORMAT " samples at"
+ " running time %" GST_TIME_FORMAT " because input buffer is before"
+ " output offset", diff, GST_TIME_ARGS (rt));
+ }
pad->priv->position += diff;
pad->priv->output_offset += diff;
@@ -2259,6 +2358,8 @@ gst_audio_aggregator_aggregate (GstAggregator * agg, gboolean timeout)
}
GST_OBJECT_UNLOCK (agg);
+ gst_audio_aggregator_post_messages (aagg);
+
{
gst_structure_set (aagg->priv->selected_samples_info, "offset",
G_TYPE_UINT64, aagg->priv->offset, "frames", G_TYPE_UINT, blocksize,