mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-12-30 04:00:37 +00:00
validate: allow config to check for minimum buffer frequency on pads
This change allow tests to check performance of elements by checking the frequency at which buffers are pushed on src pads. I re-used most of the logic from fpsdisplaysink to compute the frequency. We can now uses something like: GST_VALIDATE_CONFIG='core,min-buffer-frequency=60,target-element-factory-name=v4l2src' The 'buffer-frequency-start' optional field can be used to ignore the frequency during the start of the pipeline. This is useful when testing live pipelines where configuring and setting up elements can take some time slowing down the first buffers.
This commit is contained in:
parent
40f263e857
commit
b20f73099f
5 changed files with 169 additions and 0 deletions
|
@ -116,6 +116,44 @@
|
||||||
Note that you will still need to set <envar>GST_DEBUG_DUMP_DOT_DIR</envar>.
|
Note that you will still need to set <envar>GST_DEBUG_DUMP_DOT_DIR</envar>.
|
||||||
</informalexample>
|
</informalexample>
|
||||||
|
|
||||||
|
<informalexample>
|
||||||
|
You can also check that a src pad is pushing buffers at a
|
||||||
|
minimum frequency. For example to check if <literal>v4l2src</literal> is
|
||||||
|
producing at least 60 frames per second you can do:
|
||||||
|
<programlisting>
|
||||||
|
core,min-buffer-frequency=60,target-element-factory-name=v4l2src
|
||||||
|
</programlisting>
|
||||||
|
|
||||||
|
This config accepts the following fields:
|
||||||
|
<itemizedlist>
|
||||||
|
<listitem>
|
||||||
|
<para><literal>min-buffer-frequency</literal>: the expected minimum
|
||||||
|
rate, in buffers per second, at which buffers are pushed on the pad
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
<listitem>
|
||||||
|
<para><literal>target-element-{factory-name,name,klass}</literal>:
|
||||||
|
the factory-name, object name or class of the element to check
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
<listitem>
|
||||||
|
<para><literal>name</literal>: (optional) only check the frequency if
|
||||||
|
the src pad has this name
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
<listitem>
|
||||||
|
<para><literal>buffer-frequency-start</literal>: (optional) if defined,
|
||||||
|
validate will ignore the frequency of the pad during the time specified
|
||||||
|
in this field, in ns.
|
||||||
|
This can be useful when testing live pipelines where
|
||||||
|
configuring and setting up elements can take some time slowing
|
||||||
|
down the first buffers until the pipeline reaches its cruising
|
||||||
|
speed.
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
</itemizedlist>
|
||||||
|
</informalexample>
|
||||||
|
|
||||||
<para>
|
<para>
|
||||||
For more examples you can look at the ssim GstValidate plugin documentation to
|
For more examples you can look at the ssim GstValidate plugin documentation to
|
||||||
see how to configure that plugin.
|
see how to configure that plugin.
|
||||||
|
|
|
@ -30,6 +30,8 @@
|
||||||
#include "gst-validate-element-monitor.h"
|
#include "gst-validate-element-monitor.h"
|
||||||
#include "gst-validate-pipeline-monitor.h"
|
#include "gst-validate-pipeline-monitor.h"
|
||||||
#include "gst-validate-reporter.h"
|
#include "gst-validate-reporter.h"
|
||||||
|
#include "gst-validate-utils.h"
|
||||||
|
#include "validate.h"
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <stdarg.h>
|
#include <stdarg.h>
|
||||||
|
|
||||||
|
@ -970,6 +972,13 @@ gst_validate_pad_monitor_reset (GstValidatePadMonitor * pad_monitor)
|
||||||
|
|
||||||
/* FIXME : Why BYTES and not UNDEFINED ? */
|
/* FIXME : Why BYTES and not UNDEFINED ? */
|
||||||
gst_segment_init (&pad_monitor->segment, GST_FORMAT_BYTES);
|
gst_segment_init (&pad_monitor->segment, GST_FORMAT_BYTES);
|
||||||
|
|
||||||
|
pad_monitor->min_buf_freq = 0;
|
||||||
|
pad_monitor->buffers_pushed = 0;
|
||||||
|
pad_monitor->last_buffers_pushed = 0;
|
||||||
|
pad_monitor->min_buf_freq_interval_ts = GST_CLOCK_TIME_NONE;
|
||||||
|
pad_monitor->min_buf_freq_first_buffer_ts = GST_CLOCK_TIME_NONE;
|
||||||
|
pad_monitor->min_buf_freq_start = GST_CLOCK_TIME_NONE;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
@ -2440,6 +2449,62 @@ gst_validate_pad_monitor_activatemode_func (GstPad * pad, GstObject * parent,
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* The interval between two buffer frequency checks */
|
||||||
|
#define BUF_FREQ_CHECK_INTERVAL (GST_SECOND)
|
||||||
|
|
||||||
|
static void
|
||||||
|
gst_validate_pad_monitor_check_buffer_freq (GstValidatePadMonitor * monitor,
|
||||||
|
GstPad * pad)
|
||||||
|
{
|
||||||
|
GstClockTime ts;
|
||||||
|
|
||||||
|
if (!GST_PAD_IS_SRC (pad))
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (!monitor->min_buf_freq)
|
||||||
|
return;
|
||||||
|
|
||||||
|
ts = gst_util_get_timestamp ();
|
||||||
|
monitor->buffers_pushed++;
|
||||||
|
|
||||||
|
/* Same logic as in fpsdisplaysink to compute the buffer frequency */
|
||||||
|
if (G_UNLIKELY (!GST_CLOCK_TIME_IS_VALID
|
||||||
|
(monitor->min_buf_freq_first_buffer_ts))) {
|
||||||
|
monitor->min_buf_freq_first_buffer_ts = ts;
|
||||||
|
monitor->min_buf_freq_interval_ts = ts;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (GST_CLOCK_DIFF (monitor->min_buf_freq_interval_ts,
|
||||||
|
ts) > BUF_FREQ_CHECK_INTERVAL) {
|
||||||
|
guint time_diff;
|
||||||
|
gdouble fps;
|
||||||
|
|
||||||
|
time_diff = (gdouble) (ts - monitor->min_buf_freq_interval_ts) / GST_SECOND;
|
||||||
|
fps =
|
||||||
|
(gdouble) (monitor->buffers_pushed -
|
||||||
|
monitor->last_buffers_pushed) / time_diff;
|
||||||
|
|
||||||
|
if (fps < monitor->min_buf_freq) {
|
||||||
|
if (GST_CLOCK_TIME_IS_VALID (monitor->min_buf_freq_start) &&
|
||||||
|
GST_CLOCK_DIFF (monitor->min_buf_freq_first_buffer_ts,
|
||||||
|
ts) < monitor->min_buf_freq_start) {
|
||||||
|
GST_DEBUG_OBJECT (pad,
|
||||||
|
"buffer frequency is too low (%.2f) but ignore for now (buffer-frequency-start =%"
|
||||||
|
GST_TIME_FORMAT ")", fps,
|
||||||
|
GST_TIME_ARGS (monitor->min_buf_freq_start));
|
||||||
|
} else {
|
||||||
|
GST_VALIDATE_REPORT (monitor, CONFIG_BUFFER_FREQUENCY_TOO_LOW,
|
||||||
|
"Buffers are not pushed fast enough on this pad: %.2f/sec (minimum: %.2f)",
|
||||||
|
fps, monitor->min_buf_freq);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
monitor->last_buffers_pushed = monitor->buffers_pushed;
|
||||||
|
monitor->min_buf_freq_interval_ts = ts;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static gboolean
|
static gboolean
|
||||||
gst_validate_pad_monitor_buffer_probe (GstPad * pad, GstBuffer * buffer,
|
gst_validate_pad_monitor_buffer_probe (GstPad * pad, GstBuffer * buffer,
|
||||||
gpointer udata, gboolean pull_mode)
|
gpointer udata, gboolean pull_mode)
|
||||||
|
@ -2496,6 +2561,8 @@ gst_validate_pad_monitor_buffer_probe (GstPad * pad, GstBuffer * buffer,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
gst_validate_pad_monitor_check_buffer_freq (monitor, pad);
|
||||||
|
|
||||||
GST_VALIDATE_MONITOR_UNLOCK (monitor);
|
GST_VALIDATE_MONITOR_UNLOCK (monitor);
|
||||||
GST_VALIDATE_PAD_MONITOR_PARENT_UNLOCK (monitor);
|
GST_VALIDATE_PAD_MONITOR_PARENT_UNLOCK (monitor);
|
||||||
gst_validate_pad_monitor_buffer_probe_overrides (monitor, buffer);
|
gst_validate_pad_monitor_buffer_probe_overrides (monitor, buffer);
|
||||||
|
@ -2748,6 +2815,55 @@ gst_validate_pad_monitor_setcaps_post (GstValidatePadMonitor * pad_monitor,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gst_validate_pad_monitor_get_min_buffer_frequency (GstValidatePadMonitor *
|
||||||
|
monitor, GstPad * pad)
|
||||||
|
{
|
||||||
|
GList *config, *l;
|
||||||
|
|
||||||
|
if (!GST_PAD_IS_SRC (pad))
|
||||||
|
return;
|
||||||
|
|
||||||
|
config = gst_validate_plugin_get_config (NULL);
|
||||||
|
for (l = config; l != NULL; l = g_list_next (l)) {
|
||||||
|
GstStructure *s = l->data;
|
||||||
|
gdouble min_buf_freq;
|
||||||
|
const gchar *pad_name;
|
||||||
|
GstElement *element = NULL;
|
||||||
|
|
||||||
|
if (!gst_structure_get_double (s, "min-buffer-frequency", &min_buf_freq)) {
|
||||||
|
gint max_int;
|
||||||
|
|
||||||
|
if (!gst_structure_get_int (s, "min-buffer-frequency", &max_int))
|
||||||
|
goto next;
|
||||||
|
|
||||||
|
min_buf_freq = max_int;
|
||||||
|
}
|
||||||
|
|
||||||
|
pad_name = gst_structure_get_string (s, "name");
|
||||||
|
if (!pad_name)
|
||||||
|
pad_name = "src";
|
||||||
|
|
||||||
|
if (g_strcmp0 (GST_PAD_NAME (pad), pad_name))
|
||||||
|
goto next;
|
||||||
|
|
||||||
|
element = gst_pad_get_parent_element (pad);
|
||||||
|
|
||||||
|
if (!gst_validate_element_matches_target (element, s))
|
||||||
|
goto next;
|
||||||
|
|
||||||
|
monitor->min_buf_freq = min_buf_freq;
|
||||||
|
|
||||||
|
gst_validate_utils_get_clocktime (s, "buffer-frequency-start",
|
||||||
|
&monitor->min_buf_freq_start);
|
||||||
|
|
||||||
|
GST_DEBUG_OBJECT (pad, "pad has a minimum buffer frequency of %f",
|
||||||
|
min_buf_freq);
|
||||||
|
next:
|
||||||
|
g_clear_object (&element);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static gboolean
|
static gboolean
|
||||||
gst_validate_pad_monitor_do_setup (GstValidateMonitor * monitor)
|
gst_validate_pad_monitor_do_setup (GstValidateMonitor * monitor)
|
||||||
{
|
{
|
||||||
|
@ -2807,6 +2923,8 @@ gst_validate_pad_monitor_do_setup (GstValidateMonitor * monitor)
|
||||||
if (G_UNLIKELY (GST_PAD_PARENT (pad) == NULL))
|
if (G_UNLIKELY (GST_PAD_PARENT (pad) == NULL))
|
||||||
GST_FIXME ("Saw a pad not belonging to any object");
|
GST_FIXME ("Saw a pad not belonging to any object");
|
||||||
|
|
||||||
|
gst_validate_pad_monitor_get_min_buffer_frequency (pad_monitor, pad);
|
||||||
|
|
||||||
gst_object_unref (pad);
|
gst_object_unref (pad);
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
|
@ -124,6 +124,14 @@ struct _GstValidatePadMonitor {
|
||||||
/* The GstBuffer that should arrive next in a GList */
|
/* The GstBuffer that should arrive next in a GList */
|
||||||
GList *current_buf;
|
GList *current_buf;
|
||||||
gboolean check_buffers;
|
gboolean check_buffers;
|
||||||
|
|
||||||
|
/* 'min-buffer-frequency' config check */
|
||||||
|
gdouble min_buf_freq;
|
||||||
|
gint buffers_pushed;
|
||||||
|
gint last_buffers_pushed;
|
||||||
|
GstClockTime min_buf_freq_interval_ts;
|
||||||
|
GstClockTime min_buf_freq_first_buffer_ts;
|
||||||
|
GstClockTime min_buf_freq_start;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -404,6 +404,10 @@ gst_validate_report_load_issues (void)
|
||||||
_
|
_
|
||||||
("The number of dropped buffers is higher than the maximum allowed by the scenario"),
|
("The number of dropped buffers is higher than the maximum allowed by the scenario"),
|
||||||
NULL);
|
NULL);
|
||||||
|
REGISTER_VALIDATE_ISSUE (CRITICAL, CONFIG_BUFFER_FREQUENCY_TOO_LOW,
|
||||||
|
_
|
||||||
|
("Pad buffers push frequency is lower than the minimum required by the config"),
|
||||||
|
NULL);
|
||||||
REGISTER_VALIDATE_ISSUE (WARNING, G_LOG_WARNING, _("We got a g_log warning"),
|
REGISTER_VALIDATE_ISSUE (WARNING, G_LOG_WARNING, _("We got a g_log warning"),
|
||||||
NULL);
|
NULL);
|
||||||
REGISTER_VALIDATE_ISSUE (CRITICAL, G_LOG_CRITICAL,
|
REGISTER_VALIDATE_ISSUE (CRITICAL, G_LOG_CRITICAL,
|
||||||
|
|
|
@ -123,6 +123,7 @@ typedef enum {
|
||||||
|
|
||||||
#define CONFIG_LATENCY_TOO_HIGH _QUARK("config::latency-too-high")
|
#define CONFIG_LATENCY_TOO_HIGH _QUARK("config::latency-too-high")
|
||||||
#define CONFIG_TOO_MANY_BUFFERS_DROPPED _QUARK("config::too-many-buffers-dropped")
|
#define CONFIG_TOO_MANY_BUFFERS_DROPPED _QUARK("config::too-many-buffers-dropped")
|
||||||
|
#define CONFIG_BUFFER_FREQUENCY_TOO_LOW _QUARK("config::buffer-frequency-too-low")
|
||||||
|
|
||||||
#define G_LOG_ISSUE _QUARK("g-log::issue")
|
#define G_LOG_ISSUE _QUARK("g-log::issue")
|
||||||
#define G_LOG_WARNING _QUARK("g-log::warning")
|
#define G_LOG_WARNING _QUARK("g-log::warning")
|
||||||
|
|
Loading…
Reference in a new issue