mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-12-24 01:00:37 +00:00
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.
This commit is contained in:
parent
3eb733d95f
commit
9416d36463
4 changed files with 116 additions and 7 deletions
|
@ -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
|
||||
|
|
|
@ -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",
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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,
|
||||
)
|
||||
|
|
Loading…
Reference in a new issue