summaryrefslogtreecommitdiff
path: root/gst/netsim
diff options
context:
space:
mode:
authorStian Selnes <stian@pexip.com>2016-08-01 20:27:03 +0200
committerTim-Philipp Müller <tim@centricular.com>2017-11-25 11:10:27 +0000
commit9416d364631de23ff88dd679c8cdcb95f40d9c8a (patch)
treedd063b4f282361c6a49f9fbd666e945e6dfdd752 /gst/netsim
parent3eb733d95fc800a9aace8a73dd678b5242566830 (diff)
downloadgstreamer-plugins-bad-9416d364631de23ff88dd679c8cdcb95f40d9c8a.tar.gz
netsim: Add "delay-distribution" property plus normal distribution
By using the property "delay-distribution" the user can control how the delay applied to delayed packets is distributed. This is either the uniform distribution (as before) or the normal distribution. "min-delay" and "max-delay" control both distributions. For the normal distribution it defines the bounds of the 95% confidence interval.
Diffstat (limited to 'gst/netsim')
-rw-r--r--gst/netsim/Makefile.am2
-rw-r--r--gst/netsim/gstnetsim.c104
-rw-r--r--gst/netsim/gstnetsim.h15
-rw-r--r--gst/netsim/meson.build2
4 files changed, 116 insertions, 7 deletions
diff --git a/gst/netsim/Makefile.am b/gst/netsim/Makefile.am
index 22c2002f0..102843a3c 100644
--- a/gst/netsim/Makefile.am
+++ b/gst/netsim/Makefile.am
@@ -2,7 +2,7 @@ plugin_LTLIBRARIES = libgstnetsim.la
libgstnetsim_la_SOURCES = gstnetsim.c
libgstnetsim_la_CFLAGS = $(GST_PLUGINS_BASE_CFLAGS) $(GST_BASE_CFLAGS) $(GST_CFLAGS)
-libgstnetsim_la_LIBADD = $(GST_PLUGINS_BASE_LIBS) $(GST_BASE_LIBS) $(GST_LIBS)
+libgstnetsim_la_LIBADD = $(GST_PLUGINS_BASE_LIBS) $(GST_BASE_LIBS) $(GST_LIBS) $(LIBM)
libgstnetsim_la_LDFLAGS = $(GST_PLUGIN_LDFLAGS)
noinst_HEADERS = gstnetsim.h
diff --git a/gst/netsim/gstnetsim.c b/gst/netsim/gstnetsim.c
index c95e1d73a..44aa1d20a 100644
--- a/gst/netsim/gstnetsim.c
+++ b/gst/netsim/gstnetsim.c
@@ -27,17 +27,37 @@
#include "config.h"
#endif
-#include <string.h>
#include "gstnetsim.h"
+#include <string.h>
+#include <math.h>
+#include <float.h>
GST_DEBUG_CATEGORY (netsim_debug);
#define GST_CAT_DEFAULT (netsim_debug)
+static GType
+distribution_get_type (void)
+{
+ static volatile gsize g_define_type_id__volatile = 0;
+ if (g_once_init_enter (&g_define_type_id__volatile)) {
+ static const GEnumValue values[] = {
+ {DISTRIBUTION_UNIFORM, "uniform", "uniform"},
+ {DISTRIBUTION_NORMAL, "normal", "normal"},
+ {0, NULL, NULL}
+ };
+ GType g_define_type_id =
+ g_enum_register_static ("GstNetSimDistribution", values);
+ g_once_init_leave (&g_define_type_id__volatile, g_define_type_id);
+ }
+ return g_define_type_id__volatile;
+}
+
enum
{
PROP_0,
PROP_MIN_DELAY,
PROP_MAX_DELAY,
+ PROP_DELAY_DISTRIBUTION,
PROP_DELAY_PROBABILITY,
PROP_DROP_PROBABILITY,
PROP_DUPLICATE_PROBABILITY,
@@ -49,6 +69,7 @@ enum
/* these numbers are nothing but wild guesses and dont reflect any reality */
#define DEFAULT_MIN_DELAY 200
#define DEFAULT_MAX_DELAY 400
+#define DEFAULT_DELAY_DISTRIBUTION DISTRIBUTION_UNIFORM
#define DEFAULT_DELAY_PROBABILITY 0.0
#define DEFAULT_DROP_PROBABILITY 0.0
#define DEFAULT_DUPLICATE_PROBABILITY 0.0
@@ -199,6 +220,41 @@ push_buffer_ctx_push (PushBufferCtx * ctx)
return FALSE;
}
+static gint
+get_random_value_uniform (GRand * rand_seed, gint32 min_value, gint32 max_value)
+{
+ return g_rand_int_range (rand_seed, min_value, max_value);
+}
+
+/* Generate a value from a normal distributation with 95% confidense interval
+ * between LOW and HIGH, using the Box-Muller transform. */
+static gint
+get_random_value_normal (GRand * rand_seed, gint32 low, gint32 high,
+ NormalDistributionState * state)
+{
+ gdouble u1, u2, t1, t2;
+ gdouble mu = (high + low) / 2.0;
+ gdouble sigma = (high - low) / (2 * 1.96); /* 95% confidence interval */
+
+ state->generate = !state->generate;
+
+ if (!state->generate)
+ return round (state->z1 * sigma + mu);
+
+ do {
+ u1 = g_rand_double (rand_seed);
+ u2 = g_rand_double (rand_seed);
+ } while (u1 <= DBL_EPSILON);
+
+ t1 = sqrt (-2.0 * log (u1));
+ t2 = 2.0 * G_PI * u2;
+ state->z0 = t1 * cos (t2);
+ state->z1 = t1 * sin (t2);
+
+ return round (state->z0 * sigma + mu);
+}
+
+
static GstFlowReturn
gst_net_sim_delay_buffer (GstNetSim * netsim, GstBuffer * buf)
{
@@ -207,10 +263,29 @@ gst_net_sim_delay_buffer (GstNetSim * netsim, GstBuffer * buf)
g_mutex_lock (&netsim->loop_mutex);
if (netsim->main_loop != NULL && netsim->delay_probability > 0 &&
g_rand_double (netsim->rand_seed) < netsim->delay_probability) {
- PushBufferCtx *ctx = push_buffer_ctx_new (netsim->srcpad, buf);
- gint delay = g_rand_int_range (netsim->rand_seed,
- netsim->min_delay, netsim->max_delay);
- GSource *source = g_timeout_source_new (delay);
+ gint delay;
+ PushBufferCtx *ctx;
+ GSource *source;
+
+ switch (netsim->delay_distribution) {
+ case DISTRIBUTION_UNIFORM:
+ delay = get_random_value_uniform (netsim->rand_seed, netsim->min_delay,
+ netsim->max_delay);
+ break;
+ case DISTRIBUTION_NORMAL:
+ delay = get_random_value_normal (netsim->rand_seed, netsim->min_delay,
+ netsim->max_delay, &netsim->delay_state);
+ break;
+ default:
+ g_assert_not_reached ();
+ break;
+ }
+
+ if (delay < 0)
+ delay = 0;
+
+ ctx = push_buffer_ctx_new (netsim->srcpad, buf);
+ source = g_timeout_source_new (delay);
GST_DEBUG_OBJECT (netsim, "Delaying packet by %d", delay);
g_source_set_callback (source, (GSourceFunc) push_buffer_ctx_push,
@@ -361,6 +436,9 @@ gst_net_sim_set_property (GObject * object,
case PROP_MAX_DELAY:
netsim->max_delay = g_value_get_int (value);
break;
+ case PROP_DELAY_DISTRIBUTION:
+ netsim->delay_distribution = g_value_get_enum (value);
+ break;
case PROP_DELAY_PROBABILITY:
netsim->delay_probability = g_value_get_float (value);
break;
@@ -400,6 +478,9 @@ gst_net_sim_get_property (GObject * object,
case PROP_MAX_DELAY:
g_value_set_int (value, netsim->max_delay);
break;
+ case PROP_DELAY_DISTRIBUTION:
+ g_value_set_enum (value, netsim->delay_distribution);
+ break;
case PROP_DELAY_PROBABILITY:
g_value_set_float (value, netsim->delay_probability);
break;
@@ -510,6 +591,19 @@ gst_net_sim_class_init (GstNetSimClass * klass)
G_MININT, G_MAXINT, DEFAULT_MAX_DELAY,
G_PARAM_READWRITE | G_PARAM_CONSTRUCT | G_PARAM_STATIC_STRINGS));
+ /**
+ * GstNetSim:delay-distribution:
+ *
+ * Distribution for the amount of delay.
+ *
+ * Since: 1.14
+ */
+ g_object_class_install_property (gobject_class, PROP_DELAY_DISTRIBUTION,
+ g_param_spec_enum ("delay-distribution", "Delay Distribution",
+ "Distribution for the amount of delay",
+ distribution_get_type (), DEFAULT_DELAY_DISTRIBUTION,
+ G_PARAM_READWRITE | G_PARAM_CONSTRUCT | G_PARAM_STATIC_STRINGS));
+
g_object_class_install_property (gobject_class, PROP_DELAY_PROBABILITY,
g_param_spec_float ("delay-probability", "Delay Probability",
"The Probability a buffer is delayed",
diff --git a/gst/netsim/gstnetsim.h b/gst/netsim/gstnetsim.h
index c066774dc..8e4d75032 100644
--- a/gst/netsim/gstnetsim.h
+++ b/gst/netsim/gstnetsim.h
@@ -46,6 +46,19 @@ G_BEGIN_DECLS
typedef struct _GstNetSim GstNetSim;
typedef struct _GstNetSimClass GstNetSimClass;
+typedef enum
+{
+ DISTRIBUTION_UNIFORM,
+ DISTRIBUTION_NORMAL
+} GstNetSimDistribution;
+
+typedef struct
+{
+ gboolean generate;
+ gdouble z0;
+ gdouble z1;
+} NormalDistributionState;
+
struct _GstNetSim
{
GstElement parent;
@@ -60,10 +73,12 @@ struct _GstNetSim
GRand *rand_seed;
gsize bucket_size;
GstClockTime prev_time;
+ NormalDistributionState delay_state;
/* properties */
gint min_delay;
gint max_delay;
+ GstNetSimDistribution delay_distribution;
gfloat delay_probability;
gfloat drop_probability;
gfloat duplicate_probability;
diff --git a/gst/netsim/meson.build b/gst/netsim/meson.build
index d2cc1d322..2cd65db75 100644
--- a/gst/netsim/meson.build
+++ b/gst/netsim/meson.build
@@ -6,7 +6,7 @@ gstnetsim = library('gstnetsim',
netsim_sources,
c_args : gst_plugins_bad_args,
include_directories : [configinc],
- dependencies : [gstbase_dep],
+ dependencies : [gstbase_dep, libm],
install : true,
install_dir : plugins_install_dir,
)