예제 #1
0
파일: gstclock.c 프로젝트: zsx/ossbuild
/**
 * gst_clock_id_get_time
 * @id: The #GstClockID to query
 *
 * Get the time of the clock ID
 *
 * Returns: the time of the given clock id.
 *
 * MT safe.
 */
GstClockTime
gst_clock_id_get_time (GstClockID id)
{
  g_return_val_if_fail (id != NULL, GST_CLOCK_TIME_NONE);

  return GST_CLOCK_ENTRY_TIME ((GstClockEntry *) id);
}
예제 #2
0
EXPORT_C
#endif

GstClockReturn
gst_clock_id_wait_async (GstClockID id,
    GstClockCallback func, gpointer user_data)
{
  GstClockEntry *entry;
  GstClock *clock;
  GstClockReturn res;
  GstClockClass *cclass;
  GstClockTime requested;

  g_return_val_if_fail (id != NULL, GST_CLOCK_ERROR);
  g_return_val_if_fail (func != NULL, GST_CLOCK_ERROR);

  entry = (GstClockEntry *) id;
  requested = GST_CLOCK_ENTRY_TIME (entry);
  clock = GST_CLOCK_ENTRY_CLOCK (entry);

  /* can't sync on invalid times */
  if (G_UNLIKELY (!GST_CLOCK_TIME_IS_VALID (requested)))
    goto invalid_time;

  /* a previously unscheduled entry cannot be scheduled again */
  if (G_UNLIKELY (entry->status == GST_CLOCK_UNSCHEDULED))
    goto unscheduled;

  cclass = GST_CLOCK_GET_CLASS (clock);

  if (G_UNLIKELY (cclass->wait_async == NULL))
    goto not_supported;

  entry->func = func;
  entry->user_data = user_data;

  res = cclass->wait_async (clock, entry);

  return res;

  /* ERRORS */
invalid_time:
  {
    (func) (clock, GST_CLOCK_TIME_NONE, id, user_data);
    GST_CAT_DEBUG_OBJECT (GST_CAT_CLOCK, clock,
        "invalid time requested, returning _BADTIME");
    return GST_CLOCK_BADTIME;
  }
unscheduled:
  {
    GST_CAT_DEBUG_OBJECT (GST_CAT_CLOCK, clock,
        "entry was unscheduled return _UNSCHEDULED");
    return GST_CLOCK_UNSCHEDULED;
  }
not_supported:
  {
    GST_CAT_DEBUG_OBJECT (GST_CAT_CLOCK, clock, "clock wait is not supported");
    return GST_CLOCK_UNSUPPORTED;
  }
}
예제 #3
0
파일: gstclock.c 프로젝트: zsx/ossbuild
/**
 * gst_clock_id_compare_func
 * @id1: A #GstClockID
 * @id2: A #GstClockID to compare with
 *
 * Compares the two #GstClockID instances. This function can be used
 * as a GCompareFunc when sorting ids.
 *
 * Returns: negative value if a < b; zero if a = b; positive value if a > b
 *
 * MT safe.
 */
gint
gst_clock_id_compare_func (gconstpointer id1, gconstpointer id2)
{
  GstClockEntry *entry1, *entry2;

  entry1 = (GstClockEntry *) id1;
  entry2 = (GstClockEntry *) id2;

  if (GST_CLOCK_ENTRY_TIME (entry1) > GST_CLOCK_ENTRY_TIME (entry2)) {
    return 1;
  }
  if (GST_CLOCK_ENTRY_TIME (entry1) < GST_CLOCK_ENTRY_TIME (entry2)) {
    return -1;
  }
  return 0;
}
static void
process_entry_context_unlocked (GstTestClock * test_clock,
    GstClockEntryContext * ctx)
{
  GstTestClockPrivate *priv = GST_TEST_CLOCK_GET_PRIVATE (test_clock);
  GstClockEntry *entry = ctx->clock_entry;

  if (ctx->time_diff >= 0)
    GST_CLOCK_ENTRY_STATUS (entry) = GST_CLOCK_OK;
  else
    GST_CLOCK_ENTRY_STATUS (entry) = GST_CLOCK_EARLY;

  if (entry->func != NULL) {
    GST_OBJECT_UNLOCK (test_clock);
    entry->func (GST_CLOCK (test_clock), priv->internal_time, entry,
        entry->user_data);
    GST_OBJECT_LOCK (test_clock);
  }

  gst_test_clock_remove_entry (test_clock, entry);

  if (GST_CLOCK_ENTRY_TYPE (entry) == GST_CLOCK_ENTRY_PERIODIC) {
    GST_CLOCK_ENTRY_TIME (entry) += GST_CLOCK_ENTRY_INTERVAL (entry);

    if (entry->func != NULL)
      gst_test_clock_add_entry (test_clock, entry, NULL);
  }
}
static GstClockReturn
gst_test_clock_wait_async (GstClock * clock, GstClockEntry * entry)
{
  GstTestClock *test_clock = GST_TEST_CLOCK (clock);

  GST_OBJECT_LOCK (test_clock);

  if (GST_CLOCK_ENTRY_STATUS (entry) == GST_CLOCK_UNSCHEDULED)
    goto was_unscheduled;

  GST_CAT_DEBUG_OBJECT (GST_CAT_TEST_CLOCK, test_clock,
      "requesting asynchronous clock notification at %" GST_TIME_FORMAT,
      GST_TIME_ARGS (GST_CLOCK_ENTRY_TIME (entry)));

  gst_test_clock_add_entry (test_clock, entry, NULL);

  GST_OBJECT_UNLOCK (test_clock);

  return GST_CLOCK_OK;

  /* ERRORS */
was_unscheduled:
  {
    GST_CAT_DEBUG_OBJECT (GST_CAT_TEST_CLOCK, test_clock,
        "entry was unscheduled");
    GST_OBJECT_UNLOCK (test_clock);
    return GST_CLOCK_UNSCHEDULED;
  }
}
예제 #6
0
/**
 * gst_clock_id_wait:
 * @id: The #GstClockID to wait on
 * @jitter: (out) (allow-none): a pointer that will contain the jitter,
 *     can be %NULL.
 *
 * Perform a blocking wait on @id. 
 * @id should have been created with gst_clock_new_single_shot_id()
 * or gst_clock_new_periodic_id() and should not have been unscheduled
 * with a call to gst_clock_id_unschedule(). 
 *
 * If the @jitter argument is not %NULL and this function returns #GST_CLOCK_OK
 * or #GST_CLOCK_EARLY, it will contain the difference
 * against the clock and the time of @id when this method was
 * called. 
 * Positive values indicate how late @id was relative to the clock
 * (in which case this function will return #GST_CLOCK_EARLY). 
 * Negative values indicate how much time was spent waiting on the clock 
 * before this function returned.
 *
 * Returns: the result of the blocking wait. #GST_CLOCK_EARLY will be returned
 * if the current clock time is past the time of @id, #GST_CLOCK_OK if 
 * @id was scheduled in time. #GST_CLOCK_UNSCHEDULED if @id was 
 * unscheduled with gst_clock_id_unschedule().
 *
 * MT safe.
 */
GstClockReturn
gst_clock_id_wait (GstClockID id, GstClockTimeDiff * jitter)
{
  GstClockEntry *entry;
  GstClock *clock;
  GstClockReturn res;
  GstClockTime requested;
  GstClockClass *cclass;

  g_return_val_if_fail (id != NULL, GST_CLOCK_ERROR);

  entry = (GstClockEntry *) id;
  requested = GST_CLOCK_ENTRY_TIME (entry);

  clock = GST_CLOCK_ENTRY_CLOCK (entry);

  /* can't sync on invalid times */
  if (G_UNLIKELY (!GST_CLOCK_TIME_IS_VALID (requested)))
    goto invalid_time;

  cclass = GST_CLOCK_GET_CLASS (clock);

  GST_CAT_DEBUG_OBJECT (GST_CAT_CLOCK, clock, "waiting on clock entry %p", id);

  /* if we have a wait_jitter function, use that */
  if (G_UNLIKELY (cclass->wait == NULL))
    goto not_supported;

  res = cclass->wait (clock, entry, jitter);

  GST_CAT_DEBUG_OBJECT (GST_CAT_CLOCK, clock,
      "done waiting entry %p, res: %d (%s)", id, res,
      gst_clock_return_get_name (res));

  if (entry->type == GST_CLOCK_ENTRY_PERIODIC)
    entry->time = requested + entry->interval;

  return res;

  /* ERRORS */
invalid_time:
  {
    GST_CAT_DEBUG_OBJECT (GST_CAT_CLOCK, clock,
        "invalid time requested, returning _BADTIME");
    return GST_CLOCK_BADTIME;
  }
not_supported:
  {
    GST_CAT_DEBUG_OBJECT (GST_CAT_CLOCK, clock, "clock wait is not supported");
    return GST_CLOCK_UNSUPPORTED;
  }
}
static void
gst_test_clock_add_entry (GstTestClock * test_clock,
    GstClockEntry * entry, GstClockTimeDiff * jitter)
{
  GstTestClockPrivate *priv = GST_TEST_CLOCK_GET_PRIVATE (test_clock);
  GstClockTime now;
  GstClockEntryContext *ctx;

  now = gst_clock_adjust_unlocked (GST_CLOCK (test_clock), priv->internal_time);

  if (jitter != NULL)
    *jitter = GST_CLOCK_DIFF (GST_CLOCK_ENTRY_TIME (entry), now);

  ctx = g_slice_new (GstClockEntryContext);
  ctx->clock_entry = GST_CLOCK_ENTRY (gst_clock_id_ref (entry));
  ctx->time_diff = GST_CLOCK_DIFF (now, GST_CLOCK_ENTRY_TIME (entry));

  priv->entry_contexts = g_list_insert_sorted (priv->entry_contexts, ctx,
      gst_clock_entry_context_compare_func);

  g_cond_broadcast (&priv->entry_added_cond);
}
예제 #8
0
/**
 * gst_clock_id_wait_async:
 * @id: a #GstClockID to wait on
 * @func: The callback function
 * @user_data: User data passed in the callback
 * @destroy_data: #GDestroyNotify for user_data
 *
 * Register a callback on the given #GstClockID @id with the given
 * function and user_data. When passing a #GstClockID with an invalid
 * time to this function, the callback will be called immediately
 * with  a time set to GST_CLOCK_TIME_NONE. The callback will
 * be called when the time of @id has been reached.
 *
 * The callback @func can be invoked from any thread, either provided by the
 * core or from a streaming thread. The application should be prepared for this.
 *
 * Returns: the result of the non blocking wait.
 *
 * MT safe.
 */
GstClockReturn
gst_clock_id_wait_async (GstClockID id,
    GstClockCallback func, gpointer user_data, GDestroyNotify destroy_data)
{
  GstClockEntry *entry;
  GstClock *clock;
  GstClockReturn res;
  GstClockClass *cclass;
  GstClockTime requested;

  g_return_val_if_fail (id != NULL, GST_CLOCK_ERROR);
  g_return_val_if_fail (func != NULL, GST_CLOCK_ERROR);

  entry = (GstClockEntry *) id;
  requested = GST_CLOCK_ENTRY_TIME (entry);
  clock = GST_CLOCK_ENTRY_CLOCK (entry);

  /* can't sync on invalid times */
  if (G_UNLIKELY (!GST_CLOCK_TIME_IS_VALID (requested)))
    goto invalid_time;

  cclass = GST_CLOCK_GET_CLASS (clock);

  if (G_UNLIKELY (cclass->wait_async == NULL))
    goto not_supported;

  entry->func = func;
  entry->user_data = user_data;
  entry->destroy_data = destroy_data;

  res = cclass->wait_async (clock, entry);

  return res;

  /* ERRORS */
invalid_time:
  {
    (func) (clock, GST_CLOCK_TIME_NONE, id, user_data);
    GST_CAT_DEBUG_OBJECT (GST_CAT_CLOCK, clock,
        "invalid time requested, returning _BADTIME");
    return GST_CLOCK_BADTIME;
  }
not_supported:
  {
    GST_CAT_DEBUG_OBJECT (GST_CAT_CLOCK, clock, "clock wait is not supported");
    return GST_CLOCK_UNSUPPORTED;
  }
}
static void
gst_test_clock_unschedule (GstClock * clock, GstClockEntry * entry)
{
  GstTestClock *test_clock = GST_TEST_CLOCK (clock);

  GST_OBJECT_LOCK (test_clock);

  GST_CAT_DEBUG_OBJECT (GST_CAT_TEST_CLOCK, test_clock,
      "unscheduling requested clock notification at %" GST_TIME_FORMAT,
      GST_TIME_ARGS (GST_CLOCK_ENTRY_TIME (entry)));

  GST_CLOCK_ENTRY_STATUS (entry) = GST_CLOCK_UNSCHEDULED;
  gst_test_clock_remove_entry (test_clock, entry);

  GST_OBJECT_UNLOCK (test_clock);
}
static GstClockReturn
gst_test_clock_wait (GstClock * clock,
    GstClockEntry * entry, GstClockTimeDiff * jitter)
{
  GstTestClock *test_clock = GST_TEST_CLOCK (clock);
  GstTestClockPrivate *priv = GST_TEST_CLOCK_GET_PRIVATE (test_clock);

  GST_OBJECT_LOCK (test_clock);

  GST_CAT_DEBUG_OBJECT (GST_CAT_TEST_CLOCK, test_clock,
      "requesting synchronous clock notification at %" GST_TIME_FORMAT,
      GST_TIME_ARGS (GST_CLOCK_ENTRY_TIME (entry)));

  if (GST_CLOCK_ENTRY_STATUS (entry) == GST_CLOCK_UNSCHEDULED)
    goto was_unscheduled;

  if (gst_test_clock_lookup_entry_context (test_clock, entry) == NULL)
    gst_test_clock_add_entry (test_clock, entry, jitter);

  GST_CLOCK_ENTRY_STATUS (entry) = GST_CLOCK_BUSY;

  while (GST_CLOCK_ENTRY_STATUS (entry) == GST_CLOCK_BUSY)
    g_cond_wait (&priv->entry_processed_cond, GST_OBJECT_GET_LOCK (test_clock));

  GST_OBJECT_UNLOCK (test_clock);

  return GST_CLOCK_ENTRY_STATUS (entry);

  /* ERRORS */
was_unscheduled:
  {
    GST_CAT_DEBUG_OBJECT (GST_CAT_TEST_CLOCK, test_clock,
        "entry was unscheduled");
    GST_OBJECT_UNLOCK (test_clock);
    return GST_CLOCK_UNSCHEDULED;
  }
}
예제 #11
0
/* Method: time
 * Returns: the requested time of the entry, in nanoseconds.
 */
static VALUE
rg_time (VALUE self)
{
    return ULL2NUM (GST_CLOCK_ENTRY_TIME (RGST_CLOCK_ENTRY (self)));
}
예제 #12
0
파일: gstclock.c 프로젝트: zsx/ossbuild
/**
 * gst_clock_id_wait
 * @id: The #GstClockID to wait on
 * @jitter: A pointer that will contain the jitter, can be %NULL.
 *
 * Perform a blocking wait on @id. 
 * @id should have been created with gst_clock_new_single_shot_id()
 * or gst_clock_new_periodic_id() and should not have been unscheduled
 * with a call to gst_clock_id_unschedule(). 
 *
 * If the @jitter argument is not %NULL and this function returns #GST_CLOCK_OK
 * or #GST_CLOCK_EARLY, it will contain the difference
 * against the clock and the time of @id when this method was
 * called. 
 * Positive values indicate how late @id was relative to the clock
 * (in which case this function will return #GST_CLOCK_EARLY). 
 * Negative values indicate how much time was spent waiting on the clock 
 * before this function returned.
 *
 * Returns: the result of the blocking wait. #GST_CLOCK_EARLY will be returned
 * if the current clock time is past the time of @id, #GST_CLOCK_OK if 
 * @id was scheduled in time. #GST_CLOCK_UNSCHEDULED if @id was 
 * unscheduled with gst_clock_id_unschedule().
 *
 * MT safe.
 */
GstClockReturn
gst_clock_id_wait (GstClockID id, GstClockTimeDiff * jitter)
{
  GstClockEntry *entry;
  GstClock *clock;
  GstClockReturn res;
  GstClockTime requested;
  GstClockClass *cclass;

  g_return_val_if_fail (id != NULL, GST_CLOCK_ERROR);

  entry = (GstClockEntry *) id;
  requested = GST_CLOCK_ENTRY_TIME (entry);

  clock = GST_CLOCK_ENTRY_CLOCK (entry);

  /* can't sync on invalid times */
  if (G_UNLIKELY (!GST_CLOCK_TIME_IS_VALID (requested)))
    goto invalid_time;

  cclass = GST_CLOCK_GET_CLASS (clock);

  GST_CAT_DEBUG_OBJECT (GST_CAT_CLOCK, clock, "waiting on clock entry %p", id);

  /* if we have a wait_jitter function, use that */
  if (G_LIKELY (cclass->wait_jitter)) {
    res = cclass->wait_jitter (clock, entry, jitter);
  } else {
    /* check if we have a simple _wait function otherwise. The function without
     * the jitter arg is less optimal as we need to do an additional _get_time()
     * which is not atomic with the _wait() and a typical _wait() function does
     * yet another _get_time() anyway. */
    if (G_UNLIKELY (cclass->wait == NULL))
      goto not_supported;

    if (jitter) {
      GstClockTime now = gst_clock_get_time (clock);

      /* jitter is the diff against the clock when this entry is scheduled. Negative
       * values mean that the entry was in time, a positive value means that the
       * entry was too late. */
      *jitter = GST_CLOCK_DIFF (requested, now);
    }
    res = cclass->wait (clock, entry);
  }

  GST_CAT_DEBUG_OBJECT (GST_CAT_CLOCK, clock,
      "done waiting entry %p, res: %d", id, res);

  if (entry->type == GST_CLOCK_ENTRY_PERIODIC)
    entry->time = requested + entry->interval;

  if (G_UNLIKELY (clock->stats))
    gst_clock_update_stats (clock);

  return res;

  /* ERRORS */
invalid_time:
  {
    GST_CAT_DEBUG_OBJECT (GST_CAT_CLOCK, clock,
        "invalid time requested, returning _BADTIME");
    return GST_CLOCK_BADTIME;
  }
not_supported:
  {
    GST_CAT_DEBUG_OBJECT (GST_CAT_CLOCK, clock, "clock wait is not supported");
    return GST_CLOCK_UNSUPPORTED;
  }
}