gboolean synced;
};
+typedef struct
+{
+ GstClockEntry entry;
+ GWeakRef clock;
+} GstClockEntryImpl;
+
+#define GST_CLOCK_ENTRY_CLOCK_WEAK_REF(entry) (&((GstClockEntryImpl *)(entry))->clock)
+
/* seqlocks */
#define read_seqbegin(clock) \
g_atomic_int_get (&clock->priv->post_count);
{
GstClockEntry *entry;
- entry = g_slice_new (GstClockEntry);
+ entry = (GstClockEntry *) g_slice_new (GstClockEntryImpl);
/* FIXME: add tracer hook for struct allocations such as clock entries */
"created entry %p, time %" GST_TIME_FORMAT, entry, GST_TIME_ARGS (time));
entry->refcount = 1;
+#ifndef GST_REMOVE_DEPRECATED
+#ifndef GST_DISABLE_DEPRECATED
entry->clock = clock;
+#else
+ entry->_clock = clock;
+#endif
+#endif
+ g_weak_ref_init (GST_CLOCK_ENTRY_CLOCK_WEAK_REF (entry), clock);
entry->type = type;
entry->time = time;
entry->interval = interval;
GstClockTime time, GstClockTime interval, GstClockEntryType type)
{
g_return_val_if_fail (entry->status != GST_CLOCK_BUSY, FALSE);
- g_return_val_if_fail (entry->clock == clock, FALSE);
+ g_return_val_if_fail (gst_clock_id_uses_clock ((GstClockID) entry, clock),
+ FALSE);
entry->type = type;
entry->time = time;
if (entry->destroy_data)
entry->destroy_data (entry->user_data);
+ g_weak_ref_clear (GST_CLOCK_ENTRY_CLOCK_WEAK_REF (entry));
+
/* FIXME: add tracer hook for struct allocations such as clock entries */
- g_slice_free (GstClockEntry, id);
+ g_slice_free (GstClockEntryImpl, (GstClockEntryImpl *) id);
}
/**
entry = (GstClockEntry *) id;
requested = GST_CLOCK_ENTRY_TIME (entry);
- clock = GST_CLOCK_ENTRY_CLOCK (entry);
+ clock = g_weak_ref_get (GST_CLOCK_ENTRY_CLOCK_WEAK_REF (entry));
+ if (G_UNLIKELY (clock == NULL))
+ goto invalid_entry;
/* can't sync on invalid times */
if (G_UNLIKELY (!GST_CLOCK_TIME_IS_VALID (requested)))
if (entry->type == GST_CLOCK_ENTRY_PERIODIC)
entry->time = requested + entry->interval;
+ gst_object_unref (clock);
return res;
/* ERRORS */
{
GST_CAT_DEBUG_OBJECT (GST_CAT_CLOCK, clock,
"invalid time requested, returning _BADTIME");
+ gst_object_unref (clock);
return GST_CLOCK_BADTIME;
}
not_supported:
{
GST_CAT_DEBUG_OBJECT (GST_CAT_CLOCK, clock, "clock wait is not supported");
+ gst_object_unref (clock);
return GST_CLOCK_UNSUPPORTED;
}
+invalid_entry:
+ {
+ GST_CAT_DEBUG (GST_CAT_CLOCK, "clock entry %p lost its clock", id);
+ return GST_CLOCK_ERROR;
+ }
}
/**
entry = (GstClockEntry *) id;
requested = GST_CLOCK_ENTRY_TIME (entry);
- clock = GST_CLOCK_ENTRY_CLOCK (entry);
+ clock = g_weak_ref_get (GST_CLOCK_ENTRY_CLOCK_WEAK_REF (entry));
+ if (G_UNLIKELY (clock == NULL))
+ goto invalid_entry;
/* can't sync on invalid times */
if (G_UNLIKELY (!GST_CLOCK_TIME_IS_VALID (requested)))
res = cclass->wait_async (clock, entry);
+ gst_object_unref (clock);
return res;
/* ERRORS */
(func) (clock, GST_CLOCK_TIME_NONE, id, user_data);
GST_CAT_DEBUG_OBJECT (GST_CAT_CLOCK, clock,
"invalid time requested, returning _BADTIME");
+ gst_object_unref (clock);
return GST_CLOCK_BADTIME;
}
not_supported:
{
GST_CAT_DEBUG_OBJECT (GST_CAT_CLOCK, clock, "clock wait is not supported");
+ gst_object_unref (clock);
return GST_CLOCK_UNSUPPORTED;
}
+invalid_entry:
+ {
+ GST_CAT_DEBUG (GST_CAT_CLOCK, "clock entry %p lost its clock", id);
+ return GST_CLOCK_ERROR;
+ }
}
/**
g_return_if_fail (id != NULL);
entry = (GstClockEntry *) id;
- clock = entry->clock;
+ clock = g_weak_ref_get (GST_CLOCK_ENTRY_CLOCK_WEAK_REF (entry));
+ if (G_UNLIKELY (clock == NULL))
+ goto invalid_entry;
cclass = GST_CLOCK_GET_CLASS (clock);
if (G_LIKELY (cclass->unschedule))
cclass->unschedule (clock, entry);
+
+ gst_object_unref (clock);
+ return;
+
+invalid_entry:
+ {
+ GST_CAT_DEBUG (GST_CAT_CLOCK, "clock entry %p lost its clock", id);
+ return;
+ }
}
}
/**
+ * gst_clock_id_get_clock:
+ * @id: a #GstClockID
+ *
+ * This function returns the underlying clock.
+ *
+ * Returns: (transfer full) (nullable): a #GstClock or %NULL when the
+ * underlying clock has been freed. Unref after usage.
+ *
+ * MT safe.
+ *
+ * Since: 1.16
+ */
+GstClock *
+gst_clock_id_get_clock (GstClockID id)
+{
+ GstClockEntry *entry;
+
+ g_return_val_if_fail (id != NULL, NULL);
+
+ entry = (GstClockEntry *) id;
+ return g_weak_ref_get (GST_CLOCK_ENTRY_CLOCK_WEAK_REF (entry));
+}
+
+/**
+ * gst_clock_id_uses_clock:
+ * @id: a #GstClockID to check
+ * @clock: a #GstClock to compare against
+ *
+ * This function returns whether @id uses @clock as the underlying clock.
+ * @clock can be NULL, in which case the return value indicates whether
+ * the underlying clock has been freed. If this is the case, the @id is
+ * no longer usable and should be freed.
+ *
+ * Returns: whether the clock @id uses the same underlying #GstClock @clock.
+ *
+ * MT safe.
+ *
+ * Since: 1.16
+ */
+gboolean
+gst_clock_id_uses_clock (GstClockID id, GstClock * clock)
+{
+ GstClockEntry *entry;
+ GstClock *entry_clock;
+ gboolean ret = FALSE;
+
+ g_return_val_if_fail (id != NULL, FALSE);
+ g_return_val_if_fail (clock != NULL, FALSE);
+
+ entry = (GstClockEntry *) id;
+ entry_clock = g_weak_ref_get (GST_CLOCK_ENTRY_CLOCK_WEAK_REF (entry));
+ if (entry_clock == clock)
+ ret = TRUE;
+
+ if (G_LIKELY (entry_clock != NULL))
+ gst_object_unref (entry_clock);
+
+ return ret;
+}
+
+
+/**
* gst_clock_add_observation:
* @clock: a #GstClock
* @slave: a time on the slave