예제 #1
0
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);
}
예제 #2
0
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);
}
예제 #3
0
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);
}
예제 #6
0
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;
  }
}
예제 #9
0
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);
  }
}
예제 #12
0
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 */
}