~ubuntu-branches/ubuntu/trusty/gstreamer1.0/trusty-proposed

« back to all changes in this revision

Viewing changes to libs/gst/net/gstnetclientclock.c

  • Committer: Package Import Robot
  • Author(s): Sebastian Dröge
  • Date: 2012-08-10 12:59:53 UTC
  • Revision ID: package-import@ubuntu.com-20120810125953-bry2kkn7l230l2gm
Tags: 0.11.93-2
* debian/control.in:
  + Build-depend on GLIB >= 2.23.
* debian/patches/0001-netclientclock-simplify-by-using-g_socket_condition_.patch:
  + Fix unit test hang that causes the build to fail sometimes.

Show diffs side-by-side

added added

removed removed

Lines of Context:
248
248
  }
249
249
}
250
250
 
251
 
typedef struct
252
 
{
253
 
  GSource source;
254
 
  GstNetClientClock *clock;
255
 
  gboolean *p_timeout;
256
 
} GstNetClientClockTimeoutSource;
257
 
 
258
 
static gboolean
259
 
gst_net_client_clock_timeout_source_prepare (GSource * s, gint * p_timeout)
260
 
{
261
 
  GstNetClientClockTimeoutSource *source = (GstNetClientClockTimeoutSource *) s;
262
 
  GstClockTime expiration_time = source->clock->priv->timeout_expiration;
263
 
  GstClockTime now = gst_util_get_timestamp ();
264
 
 
265
 
  if (now >= expiration_time || (expiration_time - now) <= GST_MSECOND) {
266
 
    *p_timeout = 0;
267
 
    return TRUE;
268
 
  }
269
 
 
270
 
  *p_timeout = (expiration_time - now) / GST_MSECOND;
271
 
  GST_TRACE_OBJECT (source->clock, "time out in %d ms please", *p_timeout);
272
 
  return FALSE;
273
 
}
274
 
 
275
 
static gboolean
276
 
gst_net_client_clock_timeout_source_check (GSource * s)
277
 
{
278
 
  GstNetClientClockTimeoutSource *source = (GstNetClientClockTimeoutSource *) s;
279
 
 
280
 
  return (gst_util_get_timestamp () >= source->clock->priv->timeout_expiration);
281
 
}
282
 
 
283
 
static gboolean
284
 
gst_net_client_clock_timeout_source_dispatch (GSource * s, GSourceFunc cb,
285
 
    gpointer data)
286
 
{
287
 
  GstNetClientClockTimeoutSource *source = (GstNetClientClockTimeoutSource *) s;
288
 
 
289
 
  GST_TRACE_OBJECT (source->clock, "timed out");
290
 
  *source->p_timeout = TRUE;
291
 
  return TRUE;
292
 
}
293
 
 
294
 
static gboolean
295
 
gst_net_client_clock_socket_cb (GSocket * socket, GIOCondition condition,
296
 
    gpointer user_data)
297
 
{
298
 
  GIOCondition *p_cond = user_data;
299
 
 
300
 
  GST_TRACE ("socket %p I/O condition: 0x%02x", socket, condition);
301
 
  *p_cond = condition;
302
 
  return TRUE;
303
 
}
304
 
 
305
251
static gpointer
306
252
gst_net_client_clock_thread (gpointer data)
307
253
{
308
254
  GstNetClientClock *self = data;
309
255
  GstNetTimePacket *packet;
310
 
  GMainContext *ctx;
311
 
  GSourceFuncs funcs = { NULL, };
312
 
  GSource *source;
313
 
  GIOCondition cond;
314
 
  gboolean timeout;
315
256
  GSocket *socket = self->priv->socket;
316
257
  GError *err = NULL;
317
258
  GstClock *clock = data;
321
262
  g_socket_set_blocking (socket, TRUE);
322
263
  g_socket_set_timeout (socket, 0);
323
264
 
324
 
  ctx = g_main_context_new ();
325
 
 
326
 
  source = g_socket_create_source (socket, G_IO_IN, self->priv->cancel);
327
 
  g_source_set_name (source, "GStreamer net client clock thread socket");
328
 
  g_source_set_callback (source, (GSourceFunc) gst_net_client_clock_socket_cb,
329
 
      &cond, NULL);
330
 
  g_source_attach (source, ctx);
331
 
  g_source_unref (source);
332
 
 
333
 
  /* GSocket only support second granularity for timeouts, so roll our own
334
 
   * timeout source (so we don't have to create a new source whenever the
335
 
   * timeout changes, as we would have to do with the default timeout source) */
336
 
  funcs.prepare = gst_net_client_clock_timeout_source_prepare;
337
 
  funcs.check = gst_net_client_clock_timeout_source_check;
338
 
  funcs.dispatch = gst_net_client_clock_timeout_source_dispatch;
339
 
  funcs.finalize = NULL;
340
 
  source = g_source_new (&funcs, sizeof (GstNetClientClockTimeoutSource));
341
 
  ((GstNetClientClockTimeoutSource *) source)->clock = self;
342
 
  ((GstNetClientClockTimeoutSource *) source)->p_timeout = &timeout;
343
 
  g_source_set_name (source, "GStreamer net client clock timeout");
344
 
  g_source_attach (source, ctx);
345
 
  g_source_unref (source);
346
 
 
347
265
  while (!g_cancellable_is_cancelled (self->priv->cancel)) {
348
 
    cond = 0;
349
 
    timeout = FALSE;
350
 
    g_main_context_iteration (ctx, TRUE);
351
 
 
352
 
    if (g_cancellable_is_cancelled (self->priv->cancel))
353
 
      break;
354
 
 
355
 
    if (timeout) {
356
 
      /* timed out, let's send another packet */
357
 
      GST_DEBUG_OBJECT (self, "timed out");
358
 
 
359
 
      packet = gst_net_time_packet_new (NULL);
360
 
 
361
 
      packet->local_time = gst_clock_get_internal_time (GST_CLOCK (self));
362
 
 
363
 
      GST_DEBUG_OBJECT (self, "sending packet, local time = %" GST_TIME_FORMAT,
364
 
          GST_TIME_ARGS (packet->local_time));
365
 
 
366
 
      gst_net_time_packet_send (packet, self->priv->socket,
367
 
          self->priv->servaddr, NULL);
368
 
 
369
 
      g_free (packet);
370
 
 
371
 
      /* reset timeout (but are expecting a response sooner anyway) */
372
 
      self->priv->timeout_expiration =
373
 
          gst_util_get_timestamp () + gst_clock_get_timeout (clock);
374
 
      continue;
 
266
    GstClockTime expiration_time = self->priv->timeout_expiration;
 
267
    GstClockTime now = gst_util_get_timestamp ();
 
268
    gint64 socket_timeout;
 
269
 
 
270
    if (now >= expiration_time || (expiration_time - now) <= GST_MSECOND) {
 
271
      socket_timeout = 0;
 
272
    } else {
 
273
      socket_timeout = (expiration_time - now) / GST_USECOND;
375
274
    }
376
275
 
377
 
    /* got data to read? */
378
 
    if ((cond & G_IO_IN)) {
 
276
    GST_TRACE_OBJECT (self, "time out in %d microsecs please", socket_timeout);
 
277
 
 
278
    if (!g_socket_condition_timed_wait (socket, G_IO_IN, socket_timeout,
 
279
            self->priv->cancel, &err)) {
 
280
      /* cancelled, timeout or error */
 
281
      if (err->code == G_IO_ERROR_CANCELLED) {
 
282
        GST_INFO_OBJECT (self, "cancelled");
 
283
        g_clear_error (&err);
 
284
        break;
 
285
      } else if (err->code == G_IO_ERROR_TIMED_OUT) {
 
286
        /* timed out, let's send another packet */
 
287
        GST_DEBUG_OBJECT (self, "timed out");
 
288
 
 
289
        packet = gst_net_time_packet_new (NULL);
 
290
 
 
291
        packet->local_time = gst_clock_get_internal_time (GST_CLOCK (self));
 
292
 
 
293
        GST_DEBUG_OBJECT (self,
 
294
            "sending packet, local time = %" GST_TIME_FORMAT,
 
295
            GST_TIME_ARGS (packet->local_time));
 
296
 
 
297
        gst_net_time_packet_send (packet, self->priv->socket,
 
298
            self->priv->servaddr, NULL);
 
299
 
 
300
        g_free (packet);
 
301
 
 
302
        /* reset timeout (but are expecting a response sooner anyway) */
 
303
        self->priv->timeout_expiration =
 
304
            gst_util_get_timestamp () + gst_clock_get_timeout (clock);
 
305
      } else {
 
306
        GST_DEBUG_OBJECT (self, "socket error: %s", err->message);
 
307
        g_usleep (G_USEC_PER_SEC / 10); /* throttle */
 
308
      }
 
309
      g_clear_error (&err);
 
310
    } else {
379
311
      GstClockTime new_local;
380
312
 
 
313
      /* got packet */
 
314
 
381
315
      new_local = gst_clock_get_internal_time (GST_CLOCK (self));
382
316
 
383
317
      packet = gst_net_time_packet_receive (socket, NULL, &err);
384
318
 
385
 
      if (err != NULL) {
 
319
      if (packet != NULL) {
 
320
        GST_LOG_OBJECT (self, "got packet back");
 
321
        GST_LOG_OBJECT (self, "local_1 = %" GST_TIME_FORMAT,
 
322
            GST_TIME_ARGS (packet->local_time));
 
323
        GST_LOG_OBJECT (self, "remote = %" GST_TIME_FORMAT,
 
324
            GST_TIME_ARGS (packet->remote_time));
 
325
        GST_LOG_OBJECT (self, "local_2 = %" GST_TIME_FORMAT,
 
326
            GST_TIME_ARGS (new_local));
 
327
 
 
328
        /* observe_times will reset the timeout */
 
329
        gst_net_client_clock_observe_times (self, packet->local_time,
 
330
            packet->remote_time, new_local);
 
331
 
 
332
        g_free (packet);
 
333
      } else if (err != NULL) {
386
334
        GST_WARNING_OBJECT (self, "receive error: %s", err->message);
387
 
        g_error_free (err);
388
 
        err = NULL;
389
 
        continue;
 
335
        g_clear_error (&err);
390
336
      }
391
 
 
392
 
      GST_LOG_OBJECT (self, "got packet back");
393
 
      GST_LOG_OBJECT (self, "local_1 = %" GST_TIME_FORMAT,
394
 
          GST_TIME_ARGS (packet->local_time));
395
 
      GST_LOG_OBJECT (self, "remote = %" GST_TIME_FORMAT,
396
 
          GST_TIME_ARGS (packet->remote_time));
397
 
      GST_LOG_OBJECT (self, "local_2 = %" GST_TIME_FORMAT,
398
 
          GST_TIME_ARGS (new_local));
399
 
 
400
 
      /* observe_times will reset the timeout */
401
 
      gst_net_client_clock_observe_times (self, packet->local_time,
402
 
          packet->remote_time, new_local);
403
 
 
404
 
      g_free (packet);
405
 
      continue;
406
 
    }
407
 
 
408
 
    if ((cond & (G_IO_ERR | G_IO_HUP))) {
409
 
      GST_DEBUG_OBJECT (self, "socket error?! %s", g_strerror (errno));
410
 
      g_usleep (G_USEC_PER_SEC / 10);
411
 
      continue;
412
337
    }
413
338
  }
414
339
 
415
340
  GST_INFO_OBJECT (self, "shutting down net client clock thread");
416
 
  g_main_context_unref (ctx);
417
341
  return NULL;
418
342
}
419
343