netclientclock: Preparation for NTPv4 support

We extend our calculations to work with local send time, remote receive time,
remote send time and local receive time. For the netclientclock protocol,
remote receive and send time are assumed to be the same value.

For the results, this modified calculation makes absolutely no difference
unless the two remote times are different.
This commit is contained in:
Sebastian Dröge 2015-06-06 20:39:47 +02:00
parent 8d6837edf5
commit cc15f68b6a

View file

@ -384,11 +384,12 @@ compare_clock_time (const GstClockTime * a, const GstClockTime * b)
static void static void
gst_net_client_clock_observe_times (GstNetClientClock * self, gst_net_client_clock_observe_times (GstNetClientClock * self,
GstClockTime local_1, GstClockTime remote, GstClockTime local_2) GstClockTime local_1, GstClockTime remote_1, GstClockTime remote_2,
GstClockTime local_2)
{ {
GstNetClientClockPrivate *priv = self->priv; GstNetClientClockPrivate *priv = self->priv;
GstClockTime current_timeout = 0; GstClockTime current_timeout = 0;
GstClockTime local_avg; GstClockTime local_avg, remote_avg;
gdouble r_squared; gdouble r_squared;
GstClock *clock; GstClock *clock;
GstClockTime rtt, rtt_limit, min_update_interval; GstClockTime rtt, rtt_limit, min_update_interval;
@ -420,7 +421,19 @@ gst_net_client_clock_observe_times (GstNetClientClock * self,
goto bogus_observation; goto bogus_observation;
} }
rtt = GST_CLOCK_DIFF (local_1, local_2); if (remote_2 < remote_1) {
GST_LOG_OBJECT (self,
"Dropping observation: remote receive time %" GST_TIME_FORMAT
" < send time %" GST_TIME_FORMAT, GST_TIME_ARGS (remote_1),
GST_TIME_ARGS (remote_2));
goto bogus_observation;
}
/* The round trip time is (assuming symmetric path delays)
* delta = (local_2 - local_1) - (remote_2 - remote_1)
*/
rtt = GST_CLOCK_DIFF (local_1, local_2) - GST_CLOCK_DIFF (remote_1, remote_2);
if ((rtt_limit > 0) && (rtt > rtt_limit)) { if ((rtt_limit > 0) && (rtt > rtt_limit)) {
GST_LOG_OBJECT (self, GST_LOG_OBJECT (self,
@ -473,11 +486,46 @@ gst_net_client_clock_observe_times (GstNetClientClock * self,
goto bogus_observation; goto bogus_observation;
} }
local_avg = (local_2 + local_1) / 2; /* The difference between the local and remote clock (again assuming
* symmetric path delays):
*
* local_1 + delta / 2 - remote_1 = theta
* or
* local_2 - delta / 2 - remote_2 = theta
*
* which gives after some simple algebraic transformations:
*
* (remote_1 - local_1) + (remote_2 - local_2)
* theta = -------------------------------------------
* 2
*
*
* Thus remote time at local_avg is equal to:
*
* local_avg + theta =
*
* local_1 + local_2 (remote_1 - local_1) + (remote_2 - local_2)
* ----------------- + -------------------------------------------
* 2 2
*
* =
*
* remote_1 + remote_2
* ------------------- = remote_avg
* 2
*
* We use this for our clock estimation, i.e. local_avg at remote clock
* being the same as remote_avg.
*/
GST_LOG_OBJECT (self, "local1 %" G_GUINT64_FORMAT " remote %" G_GUINT64_FORMAT local_avg = (local_2 + local_1) / 2;
" localavg %" G_GUINT64_FORMAT " local2 %" G_GUINT64_FORMAT, remote_avg = (remote_2 + remote_1) / 2;
local_1, remote, local_avg, local_2);
GST_LOG_OBJECT (self,
"local1 %" G_GUINT64_FORMAT " remote1 %" G_GUINT64_FORMAT " remote2 %"
G_GUINT64_FORMAT " remoteavg %" G_GUINT64_FORMAT " localavg %"
G_GUINT64_FORMAT " local2 %" G_GUINT64_FORMAT, local_1, remote_1,
remote_2, remote_avg, local_avg, local_2);
clock = GST_CLOCK_CAST (self); clock = GST_CLOCK_CAST (self);
@ -502,12 +550,13 @@ gst_net_client_clock_observe_times (GstNetClientClock * self,
/* If the remote observation was within a max_discont window around our min/max estimates, we're synched */ /* If the remote observation was within a max_discont window around our min/max estimates, we're synched */
synched = synched =
(GST_CLOCK_DIFF (remote, min_guess) < (GstClockTimeDiff) (max_discont) (GST_CLOCK_DIFF (remote_avg, min_guess) < (GstClockTimeDiff) (max_discont)
&& GST_CLOCK_DIFF (time_before, && GST_CLOCK_DIFF (time_before,
remote) < (GstClockTimeDiff) (max_discont)); remote_avg) < (GstClockTimeDiff) (max_discont));
if (gst_clock_add_observation_unapplied (GST_CLOCK (self), local_avg, remote, if (gst_clock_add_observation_unapplied (GST_CLOCK (self), local_avg,
&r_squared, &internal_time, &external_time, &rate_num, &rate_den)) { remote_avg, &r_squared, &internal_time, &external_time, &rate_num,
&rate_den)) {
/* Now compare the difference (discont) in the clock /* Now compare the difference (discont) in the clock
* after this observation */ * after this observation */
@ -539,13 +588,13 @@ gst_net_client_clock_observe_times (GstNetClientClock * self,
/* Check if the new clock params would have made our observation within range */ /* Check if the new clock params would have made our observation within range */
now_synched = now_synched =
(GST_CLOCK_DIFF (remote, (GST_CLOCK_DIFF (remote_avg,
gst_clock_adjust_with_calibration (GST_CLOCK (self), local_1, gst_clock_adjust_with_calibration (GST_CLOCK (self), local_1,
internal_time, external_time, rate_num, internal_time, external_time, rate_num,
rate_den)) < (GstClockTimeDiff) (max_discont)) rate_den)) < (GstClockTimeDiff) (max_discont))
&& (GST_CLOCK_DIFF (gst_clock_adjust_with_calibration (GST_CLOCK (self), && (GST_CLOCK_DIFF (gst_clock_adjust_with_calibration (GST_CLOCK (self),
local_2, internal_time, external_time, rate_num, rate_den), local_2, internal_time, external_time, rate_num, rate_den),
remote) < (GstClockTimeDiff) (max_discont)); remote_avg) < (GstClockTimeDiff) (max_discont));
/* Only update the clock if we had synch or just gained it */ /* Only update the clock if we had synch or just gained it */
if (synched || now_synched || priv->skipped_updates > MAX_SKIPPED_UPDATES) { if (synched || now_synched || priv->skipped_updates > MAX_SKIPPED_UPDATES) {
@ -580,23 +629,20 @@ gst_net_client_clock_observe_times (GstNetClientClock * self,
"rtt", G_TYPE_UINT64, rtt, "rtt", G_TYPE_UINT64, rtt,
"rtt-average", G_TYPE_UINT64, priv->rtt_avg, "rtt-average", G_TYPE_UINT64, priv->rtt_avg,
"local", G_TYPE_UINT64, local_avg, "local", G_TYPE_UINT64, local_avg,
"remote", G_TYPE_UINT64, remote, "remote", G_TYPE_UINT64, remote_avg,
"discontinuity", G_TYPE_INT64, time_discont, "discontinuity", G_TYPE_INT64, time_discont,
"remote-min-estimate", G_TYPE_UINT64, min_guess, "remote-min-estimate", G_TYPE_UINT64, min_guess,
"remote-max-estimate", G_TYPE_UINT64, time_before, "remote-max-estimate", G_TYPE_UINT64, time_before,
"remote-min-error", G_TYPE_INT64, GST_CLOCK_DIFF (remote, min_guess), "remote-min-error", G_TYPE_INT64, GST_CLOCK_DIFF (remote_avg,
"remote-max-error", G_TYPE_INT64, GST_CLOCK_DIFF (remote, time_before), min_guess), "remote-max-error", G_TYPE_INT64,
"request-send", G_TYPE_UINT64, local_1, GST_CLOCK_DIFF (remote_avg, time_before), "request-send", G_TYPE_UINT64,
"request-receive", G_TYPE_UINT64, local_2, local_1, "request-receive", G_TYPE_UINT64, local_2, "r-squared",
"r-squared", G_TYPE_DOUBLE, r_squared, G_TYPE_DOUBLE, r_squared, "timeout", G_TYPE_UINT64, current_timeout,
"timeout", G_TYPE_UINT64, current_timeout, "internal-time", G_TYPE_UINT64, internal_time, "external-time",
"internal-time", G_TYPE_UINT64, internal_time, G_TYPE_UINT64, external_time, "rate-num", G_TYPE_UINT64, rate_num,
"external-time", G_TYPE_UINT64, external_time, "rate-den", G_TYPE_UINT64, rate_den, "rate", G_TYPE_DOUBLE,
"rate-num", G_TYPE_UINT64, rate_num, (gdouble) (rate_num) / rate_den, "local-clock-offset", G_TYPE_INT64,
"rate-den", G_TYPE_UINT64, rate_den, GST_CLOCK_DIFF (internal_time, external_time), NULL);
"rate", G_TYPE_DOUBLE, (gdouble) (rate_num) / rate_den,
"local-clock-offset", G_TYPE_INT64, GST_CLOCK_DIFF (internal_time,
external_time), NULL);
msg = gst_message_new_element (GST_OBJECT (self), s); msg = gst_message_new_element (GST_OBJECT (self), s);
gst_bus_post (bus, msg); gst_bus_post (bus, msg);
} }
@ -695,7 +741,7 @@ gst_net_client_clock_thread (gpointer data)
/* observe_times will reset the timeout */ /* observe_times will reset the timeout */
gst_net_client_clock_observe_times (self, packet->local_time, gst_net_client_clock_observe_times (self, packet->local_time,
packet->remote_time, new_local); packet->remote_time, packet->remote_time, new_local);
g_free (packet); g_free (packet);
} else if (err != NULL) { } else if (err != NULL) {