After an evaluation, GNOME has moved from Bugzilla to GitLab. Learn more about GitLab.
No new issues can be reported in GNOME Bugzilla anymore.
To report an issue in a GNOME project, go to GNOME GitLab.
Do not go to GNOME Gitlab for: Bluefish, Doxygen, GnuCash, GStreamer, java-gnome, LDTP, NetworkManager, Tomboy.
Bug 787358 - debugutils: Added new jitterer element
debugutils: Added new jitterer element
Status: RESOLVED OBSOLETE
Product: GStreamer
Classification: Platform
Component: gst-plugins-bad
unspecified
Other All
: Normal enhancement
: git master
Assigned To: GStreamer Maintainers
GStreamer Maintainers
Depends on:
Blocks:
 
 
Reported: 2017-09-06 11:59 UTC by Vivia Nikolaidou
Modified: 2018-11-03 14:13 UTC
See Also:
GNOME target: ---
GNOME version: ---


Attachments
debugutils: Added new jitterer element (15.50 KB, patch)
2017-09-06 11:59 UTC, Vivia Nikolaidou
none Details | Review
debugutils: Added new jitterer element (17.79 KB, patch)
2017-10-27 15:03 UTC, Vivia Nikolaidou
none Details | Review
debugutils: Added new jitterer element (17.70 KB, patch)
2018-05-06 15:19 UTC, Vivia Nikolaidou
none Details | Review

Description Vivia Nikolaidou 2017-09-06 11:59:51 UTC
See commit message
Comment 1 Vivia Nikolaidou 2017-09-06 11:59:55 UTC
Created attachment 359260 [details] [review]
debugutils: Added new jitterer element

This element can be configured to add jitter and/or drift to incoming
buffers' PTS, DTS, or both. Amplitude and average of jitter and drift
are configurable.
Comment 2 Tim-Philipp Müller 2017-09-06 12:16:29 UTC
How does this differ from the functionality provided by or use case targeted by the netsim element?
Comment 3 Vivia Nikolaidou 2017-09-06 12:20:52 UTC
Functionality:
This can provide both jitter and drift - so there can be either per-buffer jitter or accumulated drift, or both. Plus, jitterer can be configured to change only PTS or only DTS.

Use case:
The netsim element seems to focus on network-induced problems. In jitterer we are emulating problems caused usually by faulty drivers.
Comment 4 Nicolas Dufresne (ndufresne) 2017-09-06 12:55:38 UTC
I think netsim would ideally be able to affect the TS (just like this element). Real network jitter will affect the TS since we use do-timestamp as an approximation of the arrival time (we don't have HW timestamps). Though I agree netsim is not really about drift.
Comment 5 Sebastian Dröge (slomo) 2017-09-07 10:32:51 UTC
Review of attachment 359260 [details] [review]:

I think this element is useful and different enough from netsim. It has a different use case

::: gst/debugutils/gstjitterer.c
@@ +119,3 @@
+          "Average of the drift to apply",
+          -G_MAXINT64 / 2, G_MAXINT64 / 2, 0,
+          G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));

This is drift per buffer, which seems a bit difficult to control. Better would be something like drift per second, but not sure how to implement that easily just from the buffer timestamps. One could calculate a running average of buffer durations (as calculated from timestamps) probably and base it on that.

@@ +247,3 @@
+    highrand = g_rand_int_range (rand, highmin, highmax);
+    lowrand = g_rand_int (rand);
+    return ((((gint64) highrand) << 32) | lowrand);

This does not allow to get a range between e.g. [2**32, and 2**32 + 5]. Best to take the code from GLib here and adjust the types
Comment 6 Tim-Philipp Müller 2017-09-07 10:39:52 UTC
I don't mind another element for similar functionality. Jumping straight to the most difficult problem in software engineering: would 'jittersim' be a better name? ;) (I'm undecided myself)
Comment 7 Sebastian Dröge (slomo) 2017-09-07 10:47:02 UTC
(In reply to Sebastian Dröge (slomo) from comment #5)

> ::: gst/debugutils/gstjitterer.c
> @@ +119,3 @@
> +          "Average of the drift to apply",
> +          -G_MAXINT64 / 2, G_MAXINT64 / 2, 0,
> +          G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
> 
> This is drift per buffer, which seems a bit difficult to control. Better
> would be something like drift per second, but not sure how to implement that
> easily just from the buffer timestamps. One could calculate a running
> average of buffer durations (as calculated from timestamps) probably and
> base it on that.

Even easier actually. No drift on first buffer, drift on second buffer is scaled by the timestamp diff between current and previous buffer, drift on third by current and previous again, etc. Just need to remember the last buffer timestamp for this.
Comment 8 Vivia Nikolaidou 2017-10-27 15:03:58 UTC
Created attachment 362417 [details] [review]
debugutils: Added new jitterer element

This element can be configured to add jitter and/or drift to incoming
buffers' PTS, DTS, or both. Amplitude and average of jitter and drift
are configurable.
Comment 9 Vivia Nikolaidou 2017-10-27 15:05:14 UTC
Thanks, fixed. Please review again.
Comment 10 Nicolas Dufresne (ndufresne) 2017-10-30 18:49:03 UTC
Review of attachment 362417 [details] [review]:

::: gst/debugutils/gstjitterer.c
@@ +70,3 @@
+
+#define parent_class gst_jitterer_parent_class
+G_DEFINE_TYPE (GstJitterer, gst_jitterer, GST_TYPE_ELEMENT);

I think this should be a GstBaseTransform running "in-place" mode. This way everything will be properly forwarded. It's far in my memory, but I think there is strong motivation why "identity" element is base on that too.

@@ +103,3 @@
+  g_object_class_install_property (object_class, PROP_JITTER_AMPL,
+      g_param_spec_uint64 ("jitter-amplitude", "Jitter amplitude",
+          "Amplitude of the jitter to apply",

For extra clarity, can you add the time unit, I assume it's nanosecond all over right ?

@@ +158,3 @@
+  self->jitter_avg = 0;
+  self->drift_ampl = 0;
+  self->drift_avg = 0;

Note, this was optional, gobjects allocation is set to zero. (informative comment)

@@ +183,3 @@
+{
+  GstJitterer *self = GST_JITTERER (object);
+

Take the object lock here maybe ?

@@ +241,3 @@
+
+static gint64
+gst_jitterer_rand_uint64_range (GRand * rand, gint64 min, gint64 max)

For readability, this function could benefit some white lines.

@@ +250,3 @@
+  if (G_LIKELY (dist < G_MAXINT32)) {
+    return g_rand_int_range (rand, 0, dist) + min;
+  } else {

Drop this else here please, it's not needed, previous case has a return statement.

@@ +251,3 @@
+    return g_rand_int_range (rand, 0, dist) + min;
+  } else {
+    /* This code is based on g_rand_int_range source */

Worth bringing over some copyright ?

@@ +272,3 @@
+      lowrand = g_rand_int (rand);
+      ret = ((((gint64) highrand) << 32) | lowrand);
+    } while (ret > maxvalue);

I'm not fan of this pattern, if unlucky, this can spin and waste a lot of CPU. Why not scaling down the highrand to the appropriate range ?

@@ +298,3 @@
+{
+  GstJitterer *self = GST_JITTERER (parent);
+

I think object lock would be appropriate, so that we don't get mixed property values being used.

@@ +306,3 @@
+    max = self->jitter_avg + self->jitter_ampl / 2;
+
+    if (self->change_pts && GST_BUFFER_PTS (inbuf) != GST_CLOCK_TIME_NONE) {

Maybe you could use GST_CLOCK_TIME_IS_VALID() instead of != GST_CLOCK_TIME_NONE. This is repeated.

@@ +309,3 @@
+      jitter = gst_jitterer_rand_uint64_range (self->rand, min, max);
+      if (GST_BUFFER_PTS (inbuf) + jitter > 0)
+        GST_BUFFER_PTS (inbuf) = GST_BUFFER_PTS (inbuf) + jitter;

You didn't call gst_buffer_make_writable(), yet you modify the buffer.

@@ +325,3 @@
+  if (self->prev_pts != GST_CLOCK_TIME_NONE) {
+    GstClockTimeDiff drift_avg_per_frame;
+    GstClockTime pts_diff = GST_BUFFER_PTS (inbuf) - self->prev_pts;

You are assuming PTS is monotonic, which may lead to overflow. You should check the prev_pts is smaller, or use GStClockTimeDiff and the associated DIFF macro. Then you have to deal with positive and negative values later.
Comment 11 Vivia Nikolaidou 2018-05-06 15:19:37 UTC
Created attachment 371754 [details] [review]
debugutils: Added new jitterer element

This element can be configured to add jitter and/or drift to incoming
buffers' PTS, DTS, or both. Amplitude and average of jitter and drift
are configurable.
Comment 12 Vivia Nikolaidou 2018-05-06 15:22:49 UTC
Thanks for the review! Implemented your review comments except :

(In reply to Nicolas Dufresne (ndufresne) from comment #10)
> Review of attachment 362417 [details] [review] [review]:
> 
> ::: gst/debugutils/gstjitterer.c
> @@ +70,3 @@
> +
> +#define parent_class gst_jitterer_parent_class
> +G_DEFINE_TYPE (GstJitterer, gst_jitterer, GST_TYPE_ELEMENT);
> 
> I think this should be a GstBaseTransform running "in-place" mode. This way
> everything will be properly forwarded. It's far in my memory, but I think
> there is strong motivation why "identity" element is base on that too.

Not worth it for this specific simple element, as discussed in person during the hackfest.


> @@ +251,3 @@
> +    return g_rand_int_range (rand, 0, dist) + min;
> +  } else {
> +    /* This code is based on g_rand_int_range source */
> 
> Worth bringing over some copyright ?

Not anymore after revamping the function, see point below
 
> @@ +272,3 @@
> +      lowrand = g_rand_int (rand);
> +      ret = ((((gint64) highrand) << 32) | lowrand);
> +    } while (ret > maxvalue);
> 
> I'm not fan of this pattern, if unlucky, this can spin and waste a lot of
> CPU. Why not scaling down the highrand to the appropriate range ?

Refactored this by creating a random integer from 0 to G_MAXUINT64 and scaling+moving it to the appropriate range.
 
> @@ +325,3 @@
> +  if (self->prev_pts != GST_CLOCK_TIME_NONE) {
> +    GstClockTimeDiff drift_avg_per_frame;
> +    GstClockTime pts_diff = GST_BUFFER_PTS (inbuf) - self->prev_pts;
> 
> You are assuming PTS is monotonic, which may lead to overflow. You should
> check the prev_pts is smaller, or use GStClockTimeDiff and the associated
> DIFF macro. Then you have to deal with positive and negative values later.

Oops, forgot this point. Feel free to review the rest of the patch if you want, I'll work on this when we're not getting kicked out of the hackfest room. :)
Comment 13 GStreamer system administrator 2018-11-03 14:13:05 UTC
-- GitLab Migration Automatic Message --

This bug has been migrated to freedesktop.org's GitLab instance and has been closed from further activity.

You can subscribe and participate further through the new bug through this link to our GitLab instance: https://gitlab.freedesktop.org/gstreamer/gst-plugins-bad/issues/606.