GST_META_TAG_MEMORY_STR
gst_meta_register
gst_meta_get_info
+gst_meta_get_seqnum
+gst_meta_compare_seqnum
<SUBSECTION Standard>
GST_META_CAST
<SUBSECTION Private>
GstStructure *cache_data;
};
+/* Needed by GstMeta (to access meta seq) and GstBuffer (create/free/iterate) */
+typedef struct _GstMetaItem GstMetaItem;
+struct _GstMetaItem {
+ GstMetaItem *next;
+ guint64 seq_num;
+ GstMeta meta;
+};
+
/* FIXME: could rename all priv_gst_* functions to __gst_* now */
G_GNUC_INTERNAL gboolean priv_gst_plugin_loading_have_whitelist (void);
GType _gst_buffer_type = 0;
-typedef struct _GstMetaItem GstMetaItem;
-
-struct _GstMetaItem
-{
- GstMetaItem *next;
- GstMeta meta;
-};
-
/* info->size will be sizeof(FooMeta) which contains a GstMeta at the beginning
* too, and then there is again a GstMeta in GstMetaItem, so subtract one. */
#define ITEM_SIZE(info) ((info)->size + sizeof (GstMetaItem) - sizeof (GstMeta))
GstMetaItem *item;
} GstBufferImpl;
+static gint64 meta_seq; /* 0 *//* ATOMIC */
+
+/* TODO: use GLib's once https://gitlab.gnome.org/GNOME/glib/issues/1076 lands */
+#if defined(__GCC_HAVE_SYNC_COMPARE_AND_SWAP_8)
+static inline gint64
+gst_atomic_int64_inc (volatile gint64 * atomic)
+{
+ return __sync_fetch_and_add (atomic, 1);
+}
+#elif defined (G_PLATFORM_WIN32)
+#include <windows.h>
+static inline gint64
+gst_atomic_int64_inc (volatile gint64 * atomic)
+{
+ InterlockedExchangeAdd (atomic, 1);
+}
+#else
+#warning No 64-bit atomic int defined for this platform/toolchain!
+#define NO_64BIT_ATOMIC_INT_FOR_PLATFORM
+G_LOCK_DEFINE_STATIC (meta_seq);
+static inline gint64
+gst_atomic_int64_inc (volatile gint64 * atomic)
+{
+ gint64 ret;
+
+ G_LOCK (meta_seq);
+ ret = *atomic++;
+ G_UNLOCK (meta_seq);
+
+ return ret;
+}
+#endif
static gboolean
_is_span (GstMemory ** mem, gsize len, gsize * poffset, GstMemory ** parent)
_priv_gst_buffer_initialize (void)
{
_gst_buffer_type = gst_buffer_get_type ();
+
+#ifdef NO_64BIT_ATOMIC_INT_FOR_PLATFORM
+ GST_CAT_WARNING (GST_CAT_PERFORMANCE,
+ "No 64-bit atomic int defined for this platform/toolchain!");
+#endif
}
/**
if (!info->init_func (result, params, buffer))
goto init_failed;
+ item->seq_num = gst_atomic_int64_inc (&meta_seq);
+
/* and add to the list of metadata */
item->next = GST_BUFFER_META (buffer);
GST_BUFFER_META (buffer) = item;
return info;
}
+
+/**
+ * gst_meta_get_seqnum:
+ * @meta: a #GstMeta
+ *
+ * Gets seqnum for this meta.
+ *
+ * Since: 1.16
+ */
+guint64
+gst_meta_get_seqnum (const GstMeta * meta)
+{
+ GstMetaItem *meta_item;
+ guint8 *p;
+
+ g_return_val_if_fail (meta != NULL, 0);
+
+ p = (guint8 *) meta;
+ p -= G_STRUCT_OFFSET (GstMetaItem, meta);
+ meta_item = (GstMetaItem *) p;
+ return meta_item->seq_num;
+}
+
+/**
+ * gst_meta_compare_seqnum:
+ * @meta1: a #GstMeta
+ * @meta2: a #GstMeta
+ *
+ * Meta sequence number compare function. Can be used as #GCompareFunc
+ * or a #GCompareDataFunc.
+ *
+ * Returns: a negative number if @meta1 comes before @meta2, 0 if both metas
+ * have an equal sequence number, or a positive integer if @meta1 comes
+ * after @meta2.
+ *
+ * Since: 1.16
+ */
+gint
+gst_meta_compare_seqnum (const GstMeta * meta1, const GstMeta * meta2)
+{
+ guint64 seqnum1 = gst_meta_get_seqnum (meta1);
+ guint64 seqnum2 = gst_meta_get_seqnum (meta2);
+
+ if (seqnum1 == seqnum2)
+ return 0;
+
+ return (seqnum1 < seqnum2) ? -1 : 1;
+}
GST_API
const gchar* const* gst_meta_api_type_get_tags (GType api);
+GST_API
+guint64 gst_meta_get_seqnum (const GstMeta * meta);
+
+GST_API
+gint gst_meta_compare_seqnum (const GstMeta * meta1,
+ const GstMeta * meta2);
+
/* some default tags */
GST_API GQuark _gst_meta_tag_memory;
GST_END_TEST;
+#define test_meta_compare_seqnum(a,b) \
+ gst_meta_compare_seqnum((GstMeta*)(a),(GstMeta*)(b))
+
+GST_START_TEST (test_meta_seqnum)
+{
+ GstMetaTest *meta1, *meta2, *meta3;
+ GstBuffer *buffer;
+
+ buffer = gst_buffer_new_and_alloc (4);
+ fail_unless (buffer != NULL);
+
+ /* add some metadata */
+ meta1 = GST_META_TEST_ADD (buffer);
+ fail_unless (meta1 != NULL);
+ meta2 = GST_META_TEST_ADD (buffer);
+ fail_unless (meta2 != NULL);
+ meta3 = GST_META_TEST_ADD (buffer);
+ fail_unless (meta3 != NULL);
+
+ fail_unless (test_meta_compare_seqnum (meta1, meta2) < 0);
+ fail_unless (test_meta_compare_seqnum (meta2, meta3) < 0);
+ fail_unless (test_meta_compare_seqnum (meta1, meta3) < 0);
+
+ fail_unless_equals_int (test_meta_compare_seqnum (meta1, meta1), 0);
+ fail_unless_equals_int (test_meta_compare_seqnum (meta2, meta2), 0);
+ fail_unless_equals_int (test_meta_compare_seqnum (meta3, meta3), 0);
+
+ fail_unless (test_meta_compare_seqnum (meta2, meta1) > 0);
+ fail_unless (test_meta_compare_seqnum (meta3, meta2) > 0);
+ fail_unless (test_meta_compare_seqnum (meta3, meta1) > 0);
+
+ /* Check that gst_meta_compare_seqnum() works correctly as a GCompareFunc */
+ {
+ GList *list;
+
+ /* Make list: 3, 1, 2 */
+ list = g_list_prepend (NULL, meta2);
+ list = g_list_prepend (list, meta1);
+ list = g_list_prepend (list, meta3);
+
+ list = g_list_sort (list, (GCompareFunc) gst_meta_compare_seqnum);
+
+ fail_unless (g_list_nth_data (list, 0) == meta1);
+ fail_unless (g_list_nth_data (list, 1) == meta2);
+ fail_unless (g_list_nth_data (list, 2) == meta3);
+
+ g_list_free (list);
+ }
+
+ /* clean up */
+ gst_buffer_unref (buffer);
+}
+
+GST_END_TEST;
+
static Suite *
gst_buffermeta_suite (void)
{
tcase_add_test (tc_chain, test_meta_foreach_remove_head_and_tail_of_three);
tcase_add_test (tc_chain, test_meta_foreach_remove_several);
tcase_add_test (tc_chain, test_meta_iterate);
+ tcase_add_test (tc_chain, test_meta_seqnum);
return s;
}