summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorStian Selnes <stian@pexip.com>2016-10-03 18:43:24 +0200
committerTim-Philipp Müller <tim@centricular.com>2017-11-25 11:10:27 +0000
commitc9002e3dd52614a7df1a0992fe4a8453a74cda81 (patch)
tree46d0543e1e3b1c956dca469b126ae5193ec72f7c
parent531b1e326f06a75ac526d6f33dc20d7222472827 (diff)
downloadgstreamer-plugins-bad-c9002e3dd52614a7df1a0992fe4a8453a74cda81.tar.gz
netsim: Add gamma distribution for delay
This simulates the delay on wifi networks better.
-rw-r--r--gst/netsim/gstnetsim.c75
-rw-r--r--gst/netsim/gstnetsim.h3
2 files changed, 69 insertions, 9 deletions
diff --git a/gst/netsim/gstnetsim.c b/gst/netsim/gstnetsim.c
index d615ba0a6..29a2f7044 100644
--- a/gst/netsim/gstnetsim.c
+++ b/gst/netsim/gstnetsim.c
@@ -43,6 +43,7 @@ distribution_get_type (void)
static const GEnumValue values[] = {
{DISTRIBUTION_UNIFORM, "uniform", "uniform"},
{DISTRIBUTION_NORMAL, "normal", "normal"},
+ {DISTRIBUTION_GAMMA, "gamma", "gamma"},
{0, NULL, NULL}
};
GType g_define_type_id =
@@ -226,20 +227,17 @@ get_random_value_uniform (GRand * rand_seed, gint32 min_value, gint32 max_value)
return g_rand_int_range (rand_seed, min_value, max_value + 1);
}
-/* 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,
+/* Use the Box-Muller transform. */
+static gdouble
+random_value_normal (GRand * rand_seed, gdouble mu, gdouble sigma,
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);
+ return state->z1 * sigma + mu;
do {
u1 = g_rand_double (rand_seed);
@@ -251,7 +249,64 @@ get_random_value_normal (GRand * rand_seed, gint32 low, gint32 high,
state->z0 = t1 * cos (t2);
state->z1 = t1 * sin (t2);
- return round (state->z0 * sigma + mu);
+ return state->z0 * sigma + mu;
+}
+
+/* Generate a value from a normal distributation with 95% confidense interval
+ * between LOW and HIGH */
+static gint
+get_random_value_normal (GRand * rand_seed, gint32 low, gint32 high,
+ NormalDistributionState * state)
+{
+ gdouble mu = (high + low) / 2.0;
+ gdouble sigma = (high - low) / (2 * 1.96); /* 95% confidence interval */
+ gdouble z = random_value_normal (rand_seed, mu, sigma, state);
+
+ return round (z);
+}
+
+/* Marsaglia and Tsang's method */
+static gdouble
+random_value_gamma (GRand * rand_seed, gdouble a, gdouble b,
+ NormalDistributionState * state)
+{
+ const gdouble d = a - 1.0 / 3.0;
+ const gdouble c = 1.0 / sqrt (9 * d);
+ gdouble x, u, z, v;
+
+ if (a >= 1.0) {
+ while (TRUE) {
+ z = random_value_normal (rand_seed, 0.0, 1.0, state);
+ if (z > -1.0 / c) {
+ u = g_rand_double (rand_seed);
+ v = 1.0 + c * z;
+ v = v * v * v;
+ if (log (u) < (0.5 * z * z + d * (1 - v + log (v)))) {
+ x = d * v;
+ break;
+ }
+ }
+ }
+ } else {
+ u = g_rand_double (rand_seed);
+ x = random_value_gamma (rand_seed, a + 1, b, state) * pow (u, 1.0 / a);
+ }
+
+ return x * b;
+}
+
+static gint
+get_random_value_gamma (GRand * rand_seed, gint32 low, gint32 high,
+ NormalDistributionState * state)
+{
+ /* shape parameter 1.25 gives an OK simulation of wireless networks */
+ /* Find the scale parameter so that P(0 < x < high-low) < 0.95 */
+ /* We know: P(0 < x < R) < 0.95 for gamma(1.25, 1), R = 3.4640381 */
+ gdouble shape = 1.25;
+ gdouble scale = (high - low) / 3.4640381;
+ gdouble x = random_value_gamma (rand_seed, shape, scale, state);
+ /* Add offset so that low is the minimum possible value */
+ return round (x + low);
}
@@ -276,6 +331,10 @@ gst_net_sim_delay_buffer (GstNetSim * netsim, GstBuffer * buf)
delay = get_random_value_normal (netsim->rand_seed, netsim->min_delay,
netsim->max_delay, &netsim->delay_state);
break;
+ case DISTRIBUTION_GAMMA:
+ delay = get_random_value_gamma (netsim->rand_seed, netsim->min_delay,
+ netsim->max_delay, &netsim->delay_state);
+ break;
default:
g_assert_not_reached ();
break;
diff --git a/gst/netsim/gstnetsim.h b/gst/netsim/gstnetsim.h
index 8e4d75032..c9e32d8fd 100644
--- a/gst/netsim/gstnetsim.h
+++ b/gst/netsim/gstnetsim.h
@@ -49,7 +49,8 @@ typedef struct _GstNetSimClass GstNetSimClass;
typedef enum
{
DISTRIBUTION_UNIFORM,
- DISTRIBUTION_NORMAL
+ DISTRIBUTION_NORMAL,
+ DISTRIBUTION_GAMMA
} GstNetSimDistribution;
typedef struct