static gboolean _latency_query (GstAggregator * self, GstPad * pad, gpointer user_data) { LatencyData *data = user_data; GstClockTime min, max; GstQuery *query; gboolean live, res; query = gst_query_new_latency (); res = gst_pad_peer_query (pad, query); if (res) { gst_query_parse_latency (query, &live, &min, &max); GST_LOG_OBJECT (self, "got latency live:%s min:%" G_GINT64_FORMAT " max:%" G_GINT64_FORMAT, live ? "true" : "false", min, max); if (min > data->min) data->min = min; if (max != GST_CLOCK_TIME_NONE && ((data->max != GST_CLOCK_TIME_NONE && max < data->max) || (data->max == GST_CLOCK_TIME_NONE))) data->max = max; data->live |= live; } gst_query_unref (query); return TRUE; }
static VALUE latency_initialize(VALUE self) { GstQuery *query; query = gst_query_new_latency(); G_INITIALIZE(self, query); return Qnil; }
uint64_t ofGstUtils::getMaxLatencyNanos(){ GstClockTime minlat=0, maxlat=0; GstQuery * q = gst_query_new_latency(); if (gst_element_query (gstPipeline, q)) { gboolean live; gst_query_parse_latency (q, &live, &minlat, &maxlat); } gst_query_unref (q); return maxlat; }
static void query_upstream_latency (MpegTSBase * base) { GstQuery *query; query = gst_query_new_latency (); if (gst_pad_peer_query (base->sinkpad, query)) { gst_query_parse_latency (query, &base->upstream_live, NULL, NULL); GST_DEBUG_OBJECT (base, "Upstream is %s", base->upstream_live ? "LIVE" : "NOT LIVE"); } else GST_WARNING_OBJECT (base, "Failed to query upstream latency"); gst_query_unref (query); base->queried_latency = TRUE; }
static gboolean gst_webrtc_echo_probe_src_event (GstBaseTransform * btrans, GstEvent * event) { GstBaseTransformClass *klass; GstWebrtcEchoProbe *self = GST_WEBRTC_ECHO_PROBE (btrans); GstClockTime latency; GstClockTime upstream_latency = 0; GstQuery *query; klass = GST_BASE_TRANSFORM_CLASS (gst_webrtc_echo_probe_parent_class); switch (GST_EVENT_TYPE (event)) { case GST_EVENT_LATENCY: gst_event_parse_latency (event, &latency); query = gst_query_new_latency (); if (gst_pad_query (btrans->srcpad, query)) { gst_query_parse_latency (query, NULL, &upstream_latency, NULL); if (!GST_CLOCK_TIME_IS_VALID (upstream_latency)) upstream_latency = 0; } GST_WEBRTC_ECHO_PROBE_LOCK (self); self->latency = latency; self->delay = upstream_latency / GST_MSECOND; GST_WEBRTC_ECHO_PROBE_UNLOCK (self); GST_DEBUG_OBJECT (self, "We have a latency of %" GST_TIME_FORMAT " and delay of %ims", GST_TIME_ARGS (latency), (gint) (upstream_latency / GST_MSECOND)); break; default: break; } return klass->src_event (btrans, event); }
static gboolean gst_adder_query_latency (GstAdder * adder, GstQuery * query) { GstClockTime min, max; gboolean live; gboolean res; GstIterator *it; gboolean done; res = TRUE; done = FALSE; live = FALSE; min = 0; max = GST_CLOCK_TIME_NONE; /* Take maximum of all latency values */ it = gst_element_iterate_sink_pads (GST_ELEMENT_CAST (adder)); while (!done) { GstIteratorResult ires; gpointer item; ires = gst_iterator_next (it, &item); switch (ires) { case GST_ITERATOR_DONE: done = TRUE; break; case GST_ITERATOR_OK: { GstPad *pad = GST_PAD_CAST (item); GstQuery *peerquery; GstClockTime min_cur, max_cur; gboolean live_cur; peerquery = gst_query_new_latency (); /* Ask peer for latency */ res &= gst_pad_peer_query (pad, peerquery); /* take max from all valid return values */ if (res) { gst_query_parse_latency (peerquery, &live_cur, &min_cur, &max_cur); if (min_cur > min) min = min_cur; if (max_cur != GST_CLOCK_TIME_NONE && ((max != GST_CLOCK_TIME_NONE && max_cur > max) || (max == GST_CLOCK_TIME_NONE))) max = max_cur; live = live || live_cur; } gst_query_unref (peerquery); gst_object_unref (pad); break; } case GST_ITERATOR_RESYNC: live = FALSE; min = 0; max = GST_CLOCK_TIME_NONE; res = TRUE; gst_iterator_resync (it); break; default: res = FALSE; done = TRUE; break; } } gst_iterator_free (it); if (res) { /* store the results */ GST_DEBUG_OBJECT (adder, "Calculated total latency: live %s, min %" GST_TIME_FORMAT ", max %" GST_TIME_FORMAT, (live ? "yes" : "no"), GST_TIME_ARGS (min), GST_TIME_ARGS (max)); gst_query_set_latency (query, live, min, max); } return res; }
static gboolean gst_pipeline_do_latency (GstBin * bin) { GstPipeline *pipeline = GST_PIPELINE (bin); GstQuery *query; GstClockTime latency; GstClockTime min_latency, max_latency; gboolean res; GST_OBJECT_LOCK (pipeline); latency = pipeline->priv->latency; GST_OBJECT_UNLOCK (pipeline); if (latency == GST_CLOCK_TIME_NONE) return GST_BIN_CLASS (parent_class)->do_latency (bin); GST_DEBUG_OBJECT (pipeline, "querying latency"); query = gst_query_new_latency (); if ((res = gst_element_query (GST_ELEMENT_CAST (pipeline), query))) { gboolean live; gst_query_parse_latency (query, &live, &min_latency, &max_latency); GST_DEBUG_OBJECT (pipeline, "got min latency %" GST_TIME_FORMAT ", max latency %" GST_TIME_FORMAT ", live %d", GST_TIME_ARGS (min_latency), GST_TIME_ARGS (max_latency), live); if (max_latency < min_latency) { /* this is an impossible situation, some parts of the pipeline might not * work correctly. We post a warning for now. */ GST_ELEMENT_WARNING (pipeline, CORE, CLOCK, (NULL), ("Impossible to configure latency: max %" GST_TIME_FORMAT " < min %" GST_TIME_FORMAT ". Add queues or other buffering elements.", GST_TIME_ARGS (max_latency), GST_TIME_ARGS (min_latency))); } if (latency < min_latency) { /* This is a problematic situation as we will most likely drop lots of * data if we configure a too low latency */ GST_ELEMENT_WARNING (pipeline, CORE, CLOCK, (NULL), ("Configured latency is lower than detected minimum latency: configured %" GST_TIME_FORMAT " < min %" GST_TIME_FORMAT, GST_TIME_ARGS (latency), GST_TIME_ARGS (min_latency))); } } else { /* this is not a real problem, we just don't configure any latency. */ GST_WARNING_OBJECT (pipeline, "failed to query latency"); } gst_query_unref (query); /* configure latency on elements */ res = gst_element_send_event (GST_ELEMENT_CAST (pipeline), gst_event_new_latency (latency)); if (res) { GST_INFO_OBJECT (pipeline, "configured latency of %" GST_TIME_FORMAT, GST_TIME_ARGS (latency)); } else { GST_WARNING_OBJECT (pipeline, "did not really configure latency of %" GST_TIME_FORMAT, GST_TIME_ARGS (latency)); } return res; }
static gboolean hls_test_bus_message (InsanityGstPipelineTest * ptest, GstMessage * msg) { switch (GST_MESSAGE_TYPE (msg)) { case GST_MESSAGE_BUFFERING: { gint per; gst_message_parse_buffering (msg, &per); /* First buffering happend properly, this is requiered to be able to * start seeking */ if (G_UNLIKELY (glob_buffered == FALSE)) { if (per == 100) { insanity_test_validate_checklist_item (INSANITY_TEST (ptest), "done-buffering", TRUE, NULL); glob_buffered = TRUE; if (glob_buffering_timeout != 0) { g_source_remove (glob_buffering_timeout); glob_buffering_timeout = 0; } } else { glob_buffering_timeout = g_timeout_add (250, (GSourceFunc) buffering_timeout, INSANITY_TEST (ptest)); } } break; } case GST_MESSAGE_STATE_CHANGED: if (GST_MESSAGE_SRC (msg) == GST_OBJECT (glob_pipeline)) { const char *validate_checklist_item = glob_validate_on_playing; GstState oldstate, newstate, pending; gst_message_parse_state_changed (msg, &oldstate, &newstate, &pending); if (newstate == GST_STATE_PAUSED && oldstate == GST_STATE_READY) { GstIterator *it; GValue v = { 0, }; gboolean queried; InsanityTest *test = INSANITY_TEST (ptest); GstQuery *query = gst_query_new_latency (); const gchar *step_message = "Could not query seeking\n"; if ((queried = gst_element_query (glob_pipeline, query))) { gst_query_parse_latency (query, &glob_is_live, NULL, NULL); step_message = NULL; } else insanity_test_printf (test, "Could not query\n"); insanity_gst_pipeline_test_set_live (ptest, glob_is_live); insanity_test_validate_checklist_item (test, "queried-live", queried, step_message); gst_query_unref (query); step_message = "Could not query seekable\n"; query = gst_query_new_seeking (GST_FORMAT_TIME); if ((queried = gst_element_query (glob_pipeline, query))) { gst_query_parse_seeking (query, NULL, &glob_is_seekable, NULL, NULL); step_message = NULL; } else insanity_test_printf (test, "Could not query\n"); insanity_test_validate_checklist_item (test, "queried-seekable", queried, step_message); gst_query_unref (query); /* Iterate over the bins to find a hlsdemux */ it = gst_bin_iterate_recurse (GST_BIN (glob_pipeline)); if (gst_iterator_find_custom (it, (GCompareFunc) find_hlsdemux, &v, NULL)) { glob_hlsdemux = g_value_dup_object (&v); } g_value_unset (&v); gst_iterator_free (it); if (glob_hlsdemux != NULL) { insanity_test_validate_checklist_item (test, "protocol-is-hls", TRUE, "HLS protocol in use"); gst_object_unref (glob_hlsdemux); } else { insanity_test_validate_checklist_item (test, "protocol-is-hls", FALSE, "HLS protocol in use"); insanity_test_done (test); } /* Watch pipeline only if seekable */ if (glob_is_seekable) watch_pipeline (ptest); } else if (newstate == GST_STATE_PLAYING && pending == GST_STATE_VOID_PENDING && validate_checklist_item) { glob_validate_on_playing = NULL; insanity_test_validate_checklist_item (INSANITY_TEST (ptest), validate_checklist_item, TRUE, NULL); /* let it run a couple seconds */ glob_wait_time = hls_test_get_wait_time (INSANITY_TEST (ptest)); glob_timer_id = g_timeout_add (250, (GSourceFunc) & wait_and_end_step, INSANITY_TEST (ptest)); } } break; case GST_MESSAGE_EOS: return FALSE; default: break; } return TRUE; }
LatencyQueryPtr LatencyQuery::create() { return LatencyQueryPtr::wrap(gst_query_new_latency(), false); }