urisourcebin: add a statistics property for queueing

It contains the minimum/maximum/average byte and time levels of the
queues inside this urisourcebin

https://gitlab.freedesktop.org/gstreamer/gst-plugins-base/issues/60
This commit is contained in:
Matthew Waters 2018-07-30 14:57:23 +10:00 committed by Edward Hervey
parent 81e00791bf
commit af166b5b22
5 changed files with 162 additions and 1 deletions

View file

@ -229,6 +229,7 @@ enum
PROP_RING_BUFFER_MAX_SIZE,
PROP_LOW_WATERMARK,
PROP_HIGH_WATERMARK,
PROP_STATISTICS,
};
#define CUSTOM_EOS_QUARK _custom_eos_quark_get ()
@ -279,6 +280,7 @@ static GstPad *create_output_pad (GstURISourceBin * urisrc, GstPad * pad);
static void remove_buffering_msgs (GstURISourceBin * bin, GstObject * src);
static void update_queue_values (GstURISourceBin * urisrc);
static GstStructure *get_queue_statistics (GstURISourceBin * urisrc);
static void
gst_uri_source_bin_class_init (GstURISourceBinClass * klass)
@ -384,6 +386,25 @@ gst_uri_source_bin_class_init (GstURISourceBinClass * klass)
0.0, 1.0, DEFAULT_HIGH_WATERMARK,
G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
/**
* GstURISourceBin::statistics
*
* A GStructure containing the following values based on the values from
* all the queue's contained in this urisourcebin.
*
* "minimum-byte-level" G_TYPE_UINT Minimum of the current byte levels
* "maximum-byte-level" G_TYPE_UINT Maximum of the current byte levels
* "average-byte-level" G_TYPE_UINT Average of the current byte levels
* "minimum-time-level" G_TYPE_UINT64 Minimum of the current time levels
* "maximum-time-level" G_TYPE_UINT64 Maximum of the current time levels
* "average-time-level" G_TYPE_UINT64 Average of the current time levels
*/
g_object_class_install_property (gobject_class, PROP_STATISTICS,
g_param_spec_boxed ("statistics", "Queue Statistics",
"A set of statistics over all the queue-like elements contained in "
"this element", GST_TYPE_STRUCTURE,
G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
/**
* GstURISourceBin::drained:
*
@ -580,6 +601,9 @@ gst_uri_source_bin_get_property (GObject * object, guint prop_id,
case PROP_HIGH_WATERMARK:
g_value_set_double (value, urisrc->high_watermark);
break;
case PROP_STATISTICS:
g_value_take_boxed (value, get_queue_statistics (dec));
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
@ -892,6 +916,53 @@ pre_queue_event_probe (GstPad * pad, GstPadProbeInfo * info, gpointer user_data)
return ret;
}
static GstStructure *
get_queue_statistics (GstURISourceBin * urisrc)
{
GstStructure *ret = NULL;
guint min_byte_level = 0, max_byte_level = 0;
guint64 min_time_level = 0, max_time_level = 0;
gdouble avg_byte_level = 0., avg_time_level = 0.;
guint i = 0;
GSList *cur;
GST_URI_SOURCE_BIN_LOCK (urisrc);
for (cur = urisrc->out_slots; cur != NULL; cur = g_slist_next (cur)) {
OutputSlotInfo *slot = (OutputSlotInfo *) (cur->data);
guint byte_limit = 0;
guint64 time_limit = 0;
g_object_get (slot->queue, "current-level-bytes", &byte_limit,
"current-level-time", &time_limit, NULL);
if (byte_limit < min_byte_level)
min_byte_level = byte_limit;
if (byte_limit > max_byte_level)
max_byte_level = byte_limit;
avg_byte_level = (avg_byte_level * i + byte_limit) / (gdouble) (i + 1);
if (time_limit < min_time_level)
min_time_level = time_limit;
if (time_limit > max_time_level)
max_time_level = time_limit;
avg_time_level = (avg_time_level * i + time_limit) / (gdouble) (i + 1);
i++;
}
GST_URI_SOURCE_BIN_UNLOCK (urisrc);
ret = gst_structure_new ("application/x-urisourcebin-stats",
"minimum-byte-level", G_TYPE_UINT, (guint) min_byte_level,
"maximum-byte-level", G_TYPE_UINT, (guint) max_byte_level,
"average-byte-level", G_TYPE_UINT, (guint) avg_byte_level,
"minimum-time-level", G_TYPE_UINT64, (guint64) min_time_level,
"maximum-time-level", G_TYPE_UINT64, (guint64) max_time_level,
"average-time-level", G_TYPE_UINT64, (guint64) avg_time_level, NULL);
return ret;
}
static void
update_queue_values (GstURISourceBin * urisrc)
{

View file

@ -103,7 +103,8 @@ endif
if USE_PLUGIN_PLAYBACK
check_playback = elements/decodebin elements/playbin \
elements/playbin-complex elements/streamsynchronizer \
elements/playsink
elements/playsink \
elements/urisourcebin
else
check_playback =
endif
@ -712,6 +713,9 @@ elements_playbin_CFLAGS = $(GST_BASE_CFLAGS) $(AM_CFLAGS)
elements_playbin_complex_LDADD = $(top_builddir)/gst-libs/gst/audio/libgstaudio-@GST_API_VERSION@.la $(top_builddir)/gst-libs/gst/video/libgstvideo-@GST_API_VERSION@.la $(GST_BASE_LIBS) $(LDADD)
elements_playbin_complex_CFLAGS = $(GST_PLUGINS_BASE_CFLAGS) $(GST_BASE_CFLAGS) $(AM_CFLAGS)
elements_urisourcebin_LDADD = $(GST_BASE_LIBS) $(LDADD)
elements_urisourcebin_CFLAGS = $(GST_BASE_CFLAGS) $(AM_CFLAGS)
elements_decodebin_LDADD = $(GST_BASE_LIBS) $(LDADD)
elements_decodebin_CFLAGS = $(GST_BASE_CFLAGS) $(AM_CFLAGS)

View file

@ -36,3 +36,4 @@ streamsynchronizer
subparse
rawaudioparse
rawvideoparse
urisourcebin

View file

@ -0,0 +1,84 @@
/* GStreamer unit tests for playsink
* Copyright (C) 2015 Matthew Waters <matthew@centricular.com>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
* Boston, MA 02110-1301, USA.
*/
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#include <gst/check/gstcheck.h>
GST_START_TEST (test_initial_statistics)
{
GstElement *urisrc;
GstStructure *stats = NULL;
guint min_bytes, max_bytes, avg_bytes;
guint64 min_time, max_time, avg_time;
urisrc = gst_element_factory_make ("urisourcebin", NULL);
fail_unless (urisrc != NULL);
g_object_get (urisrc, "statistics", &stats, NULL);
fail_unless (stats != NULL);
fail_unless (g_strcmp0 (gst_structure_get_name (stats),
"application/x-urisourcebin-stats") == 0);
fail_unless_equals_int (6, gst_structure_n_fields (stats));
fail_unless_equals_int (TRUE, gst_structure_get_uint (stats,
"minimum-byte-level", &min_bytes));
fail_unless_equals_int (0, min_bytes);
fail_unless_equals_int (TRUE, gst_structure_get_uint (stats,
"maximum-byte-level", &max_bytes));
fail_unless_equals_int (0, max_bytes);
fail_unless_equals_int (TRUE, gst_structure_get_uint (stats,
"average-byte-level", &avg_bytes));
fail_unless_equals_int (0, avg_bytes);
fail_unless_equals_int (TRUE, gst_structure_get_uint64 (stats,
"minimum-time-level", &min_time));
fail_unless_equals_int (0, min_time);
fail_unless_equals_int (TRUE, gst_structure_get_uint64 (stats,
"maximum-time-level", &max_time));
fail_unless_equals_int (0, max_time);
fail_unless_equals_int (TRUE, gst_structure_get_uint64 (stats,
"average-time-level", &avg_time));
fail_unless_equals_int (0, avg_time);
gst_structure_free (stats);
gst_object_unref (urisrc);
}
GST_END_TEST;
static Suite *
urisourcebin_suite (void)
{
Suite *s = suite_create ("urisourcebin");
TCase *tc_chain = tcase_create ("general");
suite_add_tcase (s, tc_chain);
tcase_add_test (tc_chain, test_initial_statistics);
return s;
}
GST_CHECK_MAIN (urisourcebin);

View file

@ -51,6 +51,7 @@ base_tests = [
[ 'elements/streamsynchronizer.c' ],
[ 'elements/subparse.c' ],
[ 'elements/textoverlay.c', not pango_dep.found() ],
[ 'elements/urisourcebin.c' ],
[ 'elements/videoconvert.c' ],
[ 'elements/videorate.c' ],
[ 'elements/videoscale.c' ],