static void gst_net_client_clock_finalize (GObject * object) { GstNetClientClock *self = GST_NET_CLIENT_CLOCK (object); if (self->priv->thread) { gst_net_client_clock_stop (self); } g_free (self->priv->address); self->priv->address = NULL; if (self->priv->servaddr != NULL) { g_object_unref (self->priv->servaddr); self->priv->servaddr = NULL; } if (self->priv->socket != NULL) { g_socket_close (self->priv->socket, NULL); g_object_unref (self->priv->socket); self->priv->socket = NULL; } G_OBJECT_CLASS (parent_class)->finalize (object); }
static GstClockTime gst_net_client_clock_get_internal_time (GstClock * clock) { GstNetClientClock *self = GST_NET_CLIENT_CLOCK (clock); return gst_clock_get_time (self->priv->internal_clock); }
static void gst_net_client_clock_finalize (GObject * object) { GstNetClientClock *self = GST_NET_CLIENT_CLOCK (object); if (self->thread) { gst_net_client_clock_stop (self); g_assert (self->thread == NULL); } if (self->priv->fdset) { gst_poll_free (self->priv->fdset); self->priv->fdset = NULL; } g_free (self->address); self->address = NULL; g_free (self->servaddr); self->servaddr = NULL; #ifdef G_OS_WIN32 WSACleanup (); #endif G_OBJECT_CLASS (parent_class)->finalize (object); }
static void gst_net_client_clock_constructed (GObject * object) { GstNetClientClock *self = GST_NET_CLIENT_CLOCK (object); GstClock *internal_clock; GList *l; ClockCache *cache = NULL; G_OBJECT_CLASS (gst_net_client_clock_parent_class)->constructed (object); G_LOCK (clocks_lock); for (l = clocks; l; l = l->next) { ClockCache *tmp = l->data; GstNetClientInternalClock *internal_clock = GST_NET_CLIENT_INTERNAL_CLOCK (tmp->clock); if (strcmp (internal_clock->address, self->priv->address) == 0 && internal_clock->port == self->priv->port) { cache = tmp; if (cache->remove_id) { gst_clock_id_unschedule (cache->remove_id); cache->remove_id = NULL; } break; } } if (!cache) { cache = g_new0 (ClockCache, 1); cache->clock = g_object_new (GST_TYPE_NET_CLIENT_INTERNAL_CLOCK, "address", self->priv->address, "port", self->priv->port, "is-ntp", self->priv->is_ntp, NULL); clocks = g_list_prepend (clocks, cache); /* Not actually leaked but is cached for a while before being disposed, * see gst_net_client_clock_finalize, so pretend it is to not confuse * tests. */ GST_OBJECT_FLAG_SET (cache->clock, GST_OBJECT_FLAG_MAY_BE_LEAKED); } cache->clocks = g_list_prepend (cache->clocks, self); GST_OBJECT_LOCK (cache->clock); if (gst_clock_is_synced (cache->clock)) gst_clock_set_synced (GST_CLOCK (self), TRUE); self->priv->synced_id = g_signal_connect (cache->clock, "synced", G_CALLBACK (gst_net_client_clock_synced_cb), self); GST_OBJECT_UNLOCK (cache->clock); G_UNLOCK (clocks_lock); self->priv->internal_clock = internal_clock = cache->clock; /* all systems go, cap'n */ }
static GstClockTime gst_net_client_clock_get_internal_time (GstClock * clock) { GstNetClientClock *self = GST_NET_CLIENT_CLOCK (clock); if (!gst_clock_is_synced (self->priv->internal_clock)) { GstClockTime now = gst_clock_get_internal_time (self->priv->internal_clock); return gst_clock_adjust_with_calibration (self->priv->internal_clock, now, self->priv->internal_base_time, self->priv->base_time, 1, 1); } return gst_clock_get_time (self->priv->internal_clock); }
static void gst_net_client_clock_get_property (GObject * object, guint prop_id, GValue * value, GParamSpec * pspec) { GstNetClientClock *self = GST_NET_CLIENT_CLOCK (object); switch (prop_id) { case PROP_ADDRESS: g_value_set_string (value, self->priv->address); break; case PROP_PORT: g_value_set_int (value, self->priv->port); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; } }
static void gst_net_client_clock_finalize (GObject * object) { GstNetClientClock *self = GST_NET_CLIENT_CLOCK (object); GList *l; if (self->priv->synced_id) g_signal_handler_disconnect (self->priv->internal_clock, self->priv->synced_id); self->priv->synced_id = 0; G_LOCK (clocks_lock); for (l = clocks; l; l = l->next) { ClockCache *cache = l->data; if (cache->clock == self->priv->internal_clock) { cache->clocks = g_list_remove (cache->clocks, self); if (cache->clocks) { update_clock_cache (cache); } else { GstClock *sysclock = gst_system_clock_obtain (); GstClockTime time = gst_clock_get_time (sysclock) + 60 * GST_SECOND; cache->remove_id = gst_clock_new_single_shot_id (sysclock, time); gst_clock_id_wait_async (cache->remove_id, remove_clock_cache, cache, NULL); gst_object_unref (sysclock); } break; } } G_UNLOCK (clocks_lock); g_free (self->priv->address); self->priv->address = NULL; if (self->priv->bus != NULL) { gst_object_unref (self->priv->bus); self->priv->bus = NULL; } G_OBJECT_CLASS (gst_net_client_clock_parent_class)->finalize (object); }
static void gst_net_client_clock_get_property (GObject * object, guint prop_id, GValue * value, GParamSpec * pspec) { GstNetClientClock *self = GST_NET_CLIENT_CLOCK (object); switch (prop_id) { case PROP_ADDRESS: GST_OBJECT_LOCK (self); g_value_set_string (value, self->priv->address); GST_OBJECT_UNLOCK (self); break; case PROP_PORT: g_value_set_int (value, self->priv->port); break; case PROP_ROUNDTRIP_LIMIT: GST_OBJECT_LOCK (self); g_value_set_uint64 (value, self->priv->roundtrip_limit); GST_OBJECT_UNLOCK (self); break; case PROP_MINIMUM_UPDATE_INTERVAL: GST_OBJECT_LOCK (self); g_value_set_uint64 (value, self->priv->minimum_update_interval); GST_OBJECT_UNLOCK (self); break; case PROP_BUS: GST_OBJECT_LOCK (self); g_value_set_object (value, self->priv->bus); GST_OBJECT_UNLOCK (self); break; case PROP_BASE_TIME: g_value_set_uint64 (value, self->priv->base_time); break; case PROP_INTERNAL_CLOCK: g_value_set_object (value, self->priv->internal_clock); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; } }
static void gst_net_client_clock_set_property (GObject * object, guint prop_id, const GValue * value, GParamSpec * pspec) { GstNetClientClock *self = GST_NET_CLIENT_CLOCK (object); switch (prop_id) { case PROP_ADDRESS: g_free (self->priv->address); self->priv->address = g_value_dup_string (value); if (self->priv->address == NULL) self->priv->address = g_strdup (DEFAULT_ADDRESS); break; case PROP_PORT: self->priv->port = g_value_get_int (value); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; } }
static void gst_ntp_clock_init (GstNtpClock * self) { GST_NET_CLIENT_CLOCK (self)->priv->is_ntp = TRUE; }
static void gst_net_client_clock_set_property (GObject * object, guint prop_id, const GValue * value, GParamSpec * pspec) { GstNetClientClock *self = GST_NET_CLIENT_CLOCK (object); gboolean update = FALSE; switch (prop_id) { case PROP_ADDRESS: GST_OBJECT_LOCK (self); g_free (self->priv->address); self->priv->address = g_value_dup_string (value); if (self->priv->address == NULL) self->priv->address = g_strdup (DEFAULT_ADDRESS); GST_OBJECT_UNLOCK (self); break; case PROP_PORT: GST_OBJECT_LOCK (self); self->priv->port = g_value_get_int (value); GST_OBJECT_UNLOCK (self); break; case PROP_ROUNDTRIP_LIMIT: GST_OBJECT_LOCK (self); self->priv->roundtrip_limit = g_value_get_uint64 (value); GST_OBJECT_UNLOCK (self); update = TRUE; break; case PROP_MINIMUM_UPDATE_INTERVAL: GST_OBJECT_LOCK (self); self->priv->minimum_update_interval = g_value_get_uint64 (value); GST_OBJECT_UNLOCK (self); update = TRUE; break; case PROP_BUS: GST_OBJECT_LOCK (self); if (self->priv->bus) gst_object_unref (self->priv->bus); self->priv->bus = g_value_dup_object (value); GST_OBJECT_UNLOCK (self); update = TRUE; break; case PROP_BASE_TIME:{ GstClock *clock; self->priv->base_time = g_value_get_uint64 (value); clock = gst_system_clock_obtain (); self->priv->internal_base_time = gst_clock_get_time (clock); gst_object_unref (clock); break; } default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; } if (update && self->priv->internal_clock) { GList *l; G_LOCK (clocks_lock); for (l = clocks; l; l = l->next) { ClockCache *cache = l->data; if (cache->clock == self->priv->internal_clock) { update_clock_cache (cache); } } G_UNLOCK (clocks_lock); } }
static void gst_net_client_clock_constructed (GObject * object) { GstNetClientClock *self = GST_NET_CLIENT_CLOCK (object); GstClock *internal_clock; GstClockTime internal; GList *l; ClockCache *cache = NULL; G_OBJECT_CLASS (gst_net_client_clock_parent_class)->constructed (object); G_LOCK (clocks_lock); for (l = clocks; l; l = l->next) { ClockCache *tmp = l->data; GstNetClientInternalClock *internal_clock = GST_NET_CLIENT_INTERNAL_CLOCK (tmp->clock); if (strcmp (internal_clock->address, self->priv->address) == 0 && internal_clock->port == self->priv->port) { cache = tmp; if (cache->remove_id) { gst_clock_id_unschedule (cache->remove_id); cache->remove_id = NULL; } break; } } if (!cache) { cache = g_new0 (ClockCache, 1); cache->clock = g_object_new (GST_TYPE_NET_CLIENT_INTERNAL_CLOCK, "address", self->priv->address, "port", self->priv->port, "is-ntp", self->priv->is_ntp, NULL); clocks = g_list_prepend (clocks, cache); } cache->clocks = g_list_prepend (cache->clocks, self); GST_OBJECT_LOCK (cache->clock); if (gst_clock_is_synced (cache->clock)) gst_clock_set_synced (GST_CLOCK (self), TRUE); self->priv->synced_id = g_signal_connect (cache->clock, "synced", G_CALLBACK (gst_net_client_clock_synced_cb), self); GST_OBJECT_UNLOCK (cache->clock); G_UNLOCK (clocks_lock); self->priv->internal_clock = internal_clock = cache->clock; /* gst_clock_get_time() values are guaranteed to be increasing. because no one * has called get_time on this clock yet we are free to adjust to any value * without worrying about worrying about MAX() issues with the clock's * internal time. */ /* update our internal time so get_time() give something around base_time. assume that the rate is 1 in the beginning. */ internal = gst_clock_get_internal_time (internal_clock); gst_clock_set_calibration (internal_clock, internal, self->priv->base_time, 1, 1); { GstClockTime now = gst_clock_get_time (internal_clock); if (GST_CLOCK_DIFF (now, self->priv->base_time) > 0 || GST_CLOCK_DIFF (now, self->priv->base_time + GST_SECOND) < 0) { g_warning ("unable to set the base time, expect sync problems!"); } } /* all systems go, cap'n */ }