Port gtk-doc comments to their equivalent markdown syntax
[platform/upstream/gstreamer.git] / libs / gst / net / gstptpclock.c
index eaee42a..79951a3 100644 (file)
@@ -19,6 +19,7 @@
  */
 /**
  * SECTION:gstptpclock
+ * @title: GstPtpClock
  * @short_description: Special clock that synchronizes to a remote time
  *                     provider via PTP (IEEE1588:2008).
  * @see_also: #GstClock, #GstNetClientClock, #GstPipeline
@@ -40,7 +41,6 @@
  * check this, you can use gst_clock_wait_for_sync(), the GstClock::synced
  * signal and gst_clock_is_synced().
  *
- *
  * To gather statistics about the PTP clock synchronization,
  * gst_ptp_statistics_callback_add() can be used. This gives the application
  * the possibility to collect all kinds of statistics from the clock
 
 #include "gstptpclock.h"
 
-#ifdef HAVE_PTP
-
 #include "gstptp_private.h"
 
+#ifdef HAVE_SYS_WAIT_H
 #include <sys/wait.h>
+#endif
+#ifdef G_OS_WIN32
+#define WIN32_LEAN_AND_MEAN
+#include <windows.h>
+#endif
 #include <sys/types.h>
+
+#ifdef HAVE_UNISTD_H
 #include <unistd.h>
+#elif defined(G_OS_WIN32)
+#include <io.h>
+#endif
 
 #include <gst/base/base.h>
 
@@ -226,7 +235,11 @@ typedef struct
 static GMutex ptp_lock;
 static GCond ptp_cond;
 static gboolean initted = FALSE;
+#ifdef HAVE_PTP
 static gboolean supported = TRUE;
+#else
+static gboolean supported = FALSE;
+#endif
 static GPid ptp_helper_pid;
 static GThread *ptp_helper_thread;
 static GMainContext *main_context;
@@ -954,6 +967,7 @@ send_delay_req_timeout (PtpPendingSync * sync)
       sizeof (header), &written, &err);
   if (status == G_IO_STATUS_ERROR) {
     g_warning ("Failed to write to stdout: %s", err->message);
+    g_clear_error (&err);
     return G_SOURCE_REMOVE;
   } else if (status == G_IO_STATUS_EOF) {
     g_message ("EOF on stdout");
@@ -977,6 +991,7 @@ send_delay_req_timeout (PtpPendingSync * sync)
       (const gchar *) delay_req, 44, &written, &err);
   if (status == G_IO_STATUS_ERROR) {
     g_warning ("Failed to write to stdout: %s", err->message);
+    g_clear_error (&err);
     g_main_loop_quit (main_loop);
     return G_SOURCE_REMOVE;
   } else if (status == G_IO_STATUS_EOF) {
@@ -1048,15 +1063,29 @@ update_ptp_time (PtpDomainData * domain, PtpPendingSync * sync)
 #endif
 
 #ifdef USE_ONLY_SYNC_WITH_DELAY
+  GstClockTime mean_path_delay;
+
   if (sync->delay_req_send_time_local == GST_CLOCK_TIME_NONE)
     return;
+
+  /* IEEE 1588 11.3 */
+  mean_path_delay =
+      (sync->delay_req_recv_time_remote - sync->sync_send_time_remote +
+      sync->sync_recv_time_local - sync->delay_req_send_time_local -
+      (sync->correction_field_sync + sync->correction_field_delay +
+          32768) / 65536) / 2;
 #endif
 
   /* IEEE 1588 11.2 */
   corrected_ptp_time =
       sync->sync_send_time_remote +
       (sync->correction_field_sync + 32768) / 65536;
+
+#ifdef USE_ONLY_SYNC_WITH_DELAY
+  corrected_local_time = sync->sync_recv_time_local - mean_path_delay;
+#else
   corrected_local_time = sync->sync_recv_time_local - domain->mean_path_delay;
+#endif
 
 #ifdef USE_MEASUREMENT_FILTERING
   /* We check this here and when updating the mean path delay, because
@@ -1069,6 +1098,8 @@ update_ptp_time (PtpDomainData * domain, PtpPendingSync * sync)
         GST_TIME_ARGS (sync->follow_up_recv_time_local),
         GST_TIME_ARGS (domain->mean_path_delay));
     synced = FALSE;
+    gst_clock_get_calibration (GST_CLOCK_CAST (domain->domain_clock),
+        &internal_time, &external_time, &rate_num, &rate_den);
     goto out;
   }
 #endif
@@ -1260,7 +1291,7 @@ static gboolean
 update_mean_path_delay (PtpDomainData * domain, PtpPendingSync * sync)
 {
 #ifdef USE_MEDIAN_PRE_FILTERING
-  GstClockTime last_path_delays[G_N_ELEMENTS (domain->last_path_delays)];
+  GstClockTime last_path_delays[MEDIAN_PRE_FILTERING_WINDOW];
   GstClockTime median;
   gint i;
 #endif
@@ -1276,7 +1307,7 @@ update_mean_path_delay (PtpDomainData * domain, PtpPendingSync * sync)
           32768) / 65536) / 2;
 
 #ifdef USE_MEDIAN_PRE_FILTERING
-  for (i = 1; i < G_N_ELEMENTS (domain->last_path_delays); i++)
+  for (i = 1; i < MEDIAN_PRE_FILTERING_WINDOW; i++)
     domain->last_path_delays[i - 1] = domain->last_path_delays[i];
   domain->last_path_delays[i - 1] = mean_path_delay;
 
@@ -1286,10 +1317,10 @@ update_mean_path_delay (PtpDomainData * domain, PtpPendingSync * sync)
     memcpy (&last_path_delays, &domain->last_path_delays,
         sizeof (last_path_delays));
     g_qsort_with_data (&last_path_delays,
-        G_N_ELEMENTS (domain->last_path_delays), sizeof (GstClockTime),
+        MEDIAN_PRE_FILTERING_WINDOW, sizeof (GstClockTime),
         (GCompareDataFunc) compare_clock_time, NULL);
 
-    median = last_path_delays[G_N_ELEMENTS (last_path_delays) / 2];
+    median = last_path_delays[MEDIAN_PRE_FILTERING_WINDOW / 2];
 
     /* FIXME: We might want to use something else here, like only allowing
      * things in the interquartile range, or also filtering away delays that
@@ -1725,6 +1756,7 @@ have_stdin_data_cb (GIOChannel * channel, GIOCondition condition,
       &read, &err);
   if (status == G_IO_STATUS_ERROR) {
     GST_ERROR ("Failed to read from stdin: %s", err->message);
+    g_clear_error (&err);
     g_main_loop_quit (main_loop);
     return G_SOURCE_REMOVE;
   } else if (status == G_IO_STATUS_EOF) {
@@ -1748,6 +1780,7 @@ have_stdin_data_cb (GIOChannel * channel, GIOCondition condition,
   status = g_io_channel_read_chars (channel, buffer, header.size, &read, &err);
   if (status == G_IO_STATUS_ERROR) {
     GST_ERROR ("Failed to read from stdin: %s", err->message);
+    g_clear_error (&err);
     g_main_loop_quit (main_loop);
     return G_SOURCE_REMOVE;
   } else if (status == G_IO_STATUS_EOF) {
@@ -1949,7 +1982,7 @@ gst_ptp_is_initialized (void)
 /**
  * gst_ptp_init:
  * @clock_id: PTP clock id of this process' clock or %GST_PTP_CLOCK_ID_NONE
- * @interfaces: (transfer none) (array zero-terminated=1): network interfaces to run the clock on
+ * @interfaces: (transfer none) (array zero-terminated=1) (allow-none): network interfaces to run the clock on
  *
  * Initialize the GStreamer PTP subsystem and create a PTP ordinary clock in
  * slave-only mode for all domains on the given @interfaces with the
@@ -1958,7 +1991,6 @@ gst_ptp_is_initialized (void)
  * If @clock_id is %GST_PTP_CLOCK_ID_NONE, a clock id is automatically
  * generated from the MAC address of the first network interface.
  *
- *
  * This function is automatically called by gst_ptp_clock_new() with default
  * parameters if it wasn't called before.
  *
@@ -2102,8 +2134,13 @@ done:
 
   if (!ret) {
     if (ptp_helper_pid) {
+#ifndef G_OS_WIN32
       kill (ptp_helper_pid, SIGKILL);
       waitpid (ptp_helper_pid, NULL, 0);
+#else
+      TerminateProcess (ptp_helper_pid, 1);
+      WaitForSingleObject (ptp_helper_pid, INFINITE);
+#endif
       g_spawn_close_pid (ptp_helper_pid);
     }
     ptp_helper_pid = 0;
@@ -2158,8 +2195,13 @@ gst_ptp_deinit (void)
   g_mutex_lock (&ptp_lock);
 
   if (ptp_helper_pid) {
+#ifndef G_OS_WIN32
     kill (ptp_helper_pid, SIGKILL);
     waitpid (ptp_helper_pid, NULL, 0);
+#else
+    TerminateProcess (ptp_helper_pid, 1);
+    WaitForSingleObject (ptp_helper_pid, INFINITE);
+#endif
     g_spawn_close_pid (ptp_helper_pid);
   }
   ptp_helper_pid = 0;
@@ -2231,7 +2273,9 @@ enum
 {
   PROP_0,
   PROP_DOMAIN,
-  PROP_INTERNAL_CLOCK
+  PROP_INTERNAL_CLOCK,
+  PROP_MASTER_CLOCK_ID,
+  PROP_GRANDMASTER_CLOCK_ID
 };
 
 #define GST_PTP_CLOCK_GET_PRIVATE(obj)  \
@@ -2281,6 +2325,16 @@ gst_ptp_clock_class_init (GstPtpClockClass * klass)
           "Internal clock", GST_TYPE_CLOCK,
           G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
 
+  g_object_class_install_property (gobject_class, PROP_MASTER_CLOCK_ID,
+      g_param_spec_uint64 ("master-clock-id", "Master Clock ID",
+          "Master Clock ID", 0, G_MAXUINT64, 0,
+          G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
+
+  g_object_class_install_property (gobject_class, PROP_GRANDMASTER_CLOCK_ID,
+      g_param_spec_uint64 ("grandmaster-clock-id", "Grand Master Clock ID",
+          "Grand Master Clock ID", 0, G_MAXUINT64, 0,
+          G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
+
   clock_class->get_internal_time = gst_ptp_clock_get_internal_time;
 }
 
@@ -2384,6 +2438,28 @@ gst_ptp_clock_get_property (GObject * object, guint prop_id,
       gst_ptp_clock_ensure_domain_clock (self);
       g_value_set_object (value, self->priv->domain_clock);
       break;
+    case PROP_MASTER_CLOCK_ID:
+    case PROP_GRANDMASTER_CLOCK_ID:{
+      GList *l;
+
+      g_mutex_lock (&domain_clocks_lock);
+      g_value_set_uint64 (value, 0);
+
+      for (l = domain_clocks; l; l = l->next) {
+        PtpDomainData *clock_data = l->data;
+
+        if (clock_data->domain == self->priv->domain) {
+          if (prop_id == PROP_MASTER_CLOCK_ID)
+            g_value_set_uint64 (value,
+                clock_data->master_clock_identity.clock_identity);
+          else
+            g_value_set_uint64 (value, clock_data->grandmaster_identity);
+          break;
+        }
+      }
+      g_mutex_unlock (&domain_clocks_lock);
+      break;
+    }
     default:
       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
       break;
@@ -2428,7 +2504,6 @@ gst_ptp_clock_get_internal_time (GstClock * clock)
  * If gst_ptp_init() was not called before, this will call gst_ptp_init() with
  * default parameters.
  *
- *
  * This clock only returns valid timestamps after it received the first
  * times from the PTP master clock on the network. Once this happens the
  * GstPtpClock::internal-clock property will become non-NULL. You can
@@ -2534,55 +2609,3 @@ gst_ptp_statistics_callback_remove (gulong id)
     g_atomic_int_add (&domain_stats_n_hooks, -1);
   g_mutex_unlock (&ptp_lock);
 }
-
-#else /* HAVE_PTP */
-
-GType
-gst_ptp_clock_get_type (void)
-{
-  return G_TYPE_INVALID;
-}
-
-gboolean
-gst_ptp_is_supported (void)
-{
-  return FALSE;
-}
-
-gboolean
-gst_ptp_is_initialized (void)
-{
-  return FALSE;
-}
-
-gboolean
-gst_ptp_init (guint64 clock_id, gchar ** interfaces)
-{
-  return FALSE;
-}
-
-void
-gst_ptp_deinit (void)
-{
-}
-
-GstClock *
-gst_ptp_clock_new (const gchar * name, guint domain)
-{
-  return NULL;
-}
-
-gulong
-gst_ptp_statistics_callback_add (GstPtpStatisticsCallback callback,
-    gpointer user_data, GDestroyNotify destroy_data)
-{
-  return 0;
-}
-
-void
-gst_ptp_statistics_callback_remove (gulong id)
-{
-  return;
-}
-
-#endif