summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSebastian Dröge <sebastian@centricular.com>2017-02-25 12:18:14 +0200
committerSebastian Dröge <sebastian@centricular.com>2017-05-12 11:43:02 +0200
commit7d930b86930fbce5b6362e20c5d78073f24e3c8e (patch)
treec61b86695332fbe09694e99b03ed595faa5108df
parentda1d11be770a529b61b93bbc4cd3acbd5b7bc559 (diff)
buffer: Add GstReferenceTimestampMeta
This is a meta that generically allows to attach additional reference timestamps to a buffer, that don't have to relate to the pipeline clock in any way. Examples of this could be an NTP timestamp when the media was captured, a frame counter on the capture side or the (local) UNIX timestamp when the media was captured. https://bugzilla.gnome.org/show_bug.cgi?id=779213
-rw-r--r--docs/gst/gstreamer-sections.txt4
-rw-r--r--gst/gstbuffer.c169
-rw-r--r--gst/gstbuffer.h43
-rw-r--r--win32/common/libgstreamer.def4
4 files changed, 220 insertions, 0 deletions
diff --git a/docs/gst/gstreamer-sections.txt b/docs/gst/gstreamer-sections.txt
index 582157ab2..2efe9d216 100644
--- a/docs/gst/gstreamer-sections.txt
+++ b/docs/gst/gstreamer-sections.txt
@@ -263,6 +263,10 @@ GstParentBufferMeta
gst_buffer_add_parent_buffer_meta
gst_buffer_get_parent_buffer_meta
+GstReferenceTimestampMeta
+gst_buffer_add_reference_timestamp_meta
+gst_buffer_get_reference_timestamp_meta
+
gst_buffer_get_flags
gst_buffer_set_flags
gst_buffer_unset_flags
diff --git a/gst/gstbuffer.c b/gst/gstbuffer.c
index 7d51c6d2e..307754389 100644
--- a/gst/gstbuffer.c
+++ b/gst/gstbuffer.c
@@ -2538,3 +2538,172 @@ gst_parent_buffer_meta_get_info (void)
return meta_info;
}
+
+GST_DEBUG_CATEGORY_STATIC (gst_reference_timestamp_meta_debug);
+
+/**
+ * gst_buffer_add_reference_timestamp_meta:
+ * @buffer: (transfer none): a #GstBuffer
+ * @reference: (transfer none): identifier for the timestamp reference.
+ * @timestamp: timestamp
+ * @duration: duration, or %GST_CLOCK_TIME_NONE
+ *
+ * Add a #GstReferenceTimestampMeta to @buffer that holds a @timestamp and
+ * optionally @duration based on a specific timestamp @reference. See the
+ * documentation of #GstReferenceTimestampMeta for details.
+ *
+ * Returns: (transfer none): The #GstReferenceTimestampMeta that was added to the buffer
+ *
+ * Since: 1.14
+ */
+GstReferenceTimestampMeta *
+gst_buffer_add_reference_timestamp_meta (GstBuffer * buffer,
+ GstCaps * reference, GstClockTime timestamp, GstClockTime duration)
+{
+ GstReferenceTimestampMeta *meta;
+
+ g_return_val_if_fail (GST_IS_CAPS (reference), NULL);
+ g_return_val_if_fail (timestamp != GST_CLOCK_TIME_NONE, NULL);
+
+ meta =
+ (GstReferenceTimestampMeta *) gst_buffer_add_meta (buffer,
+ GST_REFERENCE_TIMESTAMP_META_INFO, NULL);
+
+ if (!meta)
+ return NULL;
+
+ meta->reference = gst_caps_ref (reference);
+ meta->timestamp = timestamp;
+ meta->duration = duration;
+
+ return meta;
+}
+
+/**
+ * gst_buffer_get_reference_timestamp_meta:
+ * @buffer: a #GstBuffer
+ * @reference: (allow-none): a reference #GstCaps
+ *
+ * Find the first #GstReferenceTimestampMeta on @buffer that conforms to
+ * @reference. Conformance is tested by checking if the meta's reference is a
+ * subset of @reference.
+ *
+ * Buffers can contain multiple #GstReferenceTimestampMeta metadata items.
+ *
+ * Returns: (transfer none): the #GstReferenceTimestampMeta or %NULL when there
+ * is no such metadata on @buffer.
+ *
+ * Since: 1.14
+ */
+GstReferenceTimestampMeta *
+gst_buffer_get_reference_timestamp_meta (GstBuffer * buffer,
+ GstCaps * reference)
+{
+ gpointer state = NULL;
+ GstMeta *meta;
+ const GstMetaInfo *info = GST_REFERENCE_TIMESTAMP_META_INFO;
+
+ while ((meta = gst_buffer_iterate_meta (buffer, &state))) {
+ if (meta->info->api == info->api) {
+ GstReferenceTimestampMeta *rmeta = (GstReferenceTimestampMeta *) meta;
+
+ if (!reference)
+ return rmeta;
+ if (gst_caps_is_subset (rmeta->reference, reference))
+ return rmeta;
+ }
+ }
+ return NULL;
+}
+
+static gboolean
+_gst_reference_timestamp_meta_transform (GstBuffer * dest, GstMeta * meta,
+ GstBuffer * buffer, GQuark type, gpointer data)
+{
+ GstReferenceTimestampMeta *dmeta, *smeta;
+
+ /* we copy over the reference timestamp meta, independent of transformation
+ * that happens. If it applied to the original buffer, it still applies to
+ * the new buffer as it refers to the time when the media was captured */
+ smeta = (GstReferenceTimestampMeta *) meta;
+ dmeta =
+ gst_buffer_add_reference_timestamp_meta (dest, smeta->reference,
+ smeta->timestamp, smeta->duration);
+ if (!dmeta)
+ return FALSE;
+
+ GST_CAT_DEBUG (gst_reference_timestamp_meta_debug,
+ "copy reference timestamp metadata from buffer %p to %p", buffer, dest);
+
+ return TRUE;
+}
+
+static void
+_gst_reference_timestamp_meta_free (GstReferenceTimestampMeta * meta,
+ GstBuffer * buffer)
+{
+ if (meta->reference)
+ gst_caps_unref (meta->reference);
+}
+
+static gboolean
+_gst_reference_timestamp_meta_init (GstReferenceTimestampMeta * meta,
+ gpointer params, GstBuffer * buffer)
+{
+ static volatile gsize _init;
+
+ if (g_once_init_enter (&_init)) {
+ GST_DEBUG_CATEGORY_INIT (gst_reference_timestamp_meta_debug,
+ "referencetimestampmeta", 0, "referencetimestampmeta");
+ g_once_init_leave (&_init, 1);
+ }
+
+ meta->reference = NULL;
+ meta->timestamp = GST_CLOCK_TIME_NONE;
+ meta->duration = GST_CLOCK_TIME_NONE;
+
+ return TRUE;
+}
+
+GType
+gst_reference_timestamp_meta_api_get_type (void)
+{
+ static volatile GType type = 0;
+ static const gchar *tags[] = { NULL };
+
+ if (g_once_init_enter (&type)) {
+ GType _type =
+ gst_meta_api_type_register ("GstReferenceTimestampMetaAPI", tags);
+ g_once_init_leave (&type, _type);
+ }
+
+ return type;
+}
+
+/**
+ * gst_reference_timestamp_meta_get_info:
+ *
+ * Get the global #GstMetaInfo describing the #GstReferenceTimestampMeta meta.
+ *
+ * Returns: (transfer none): The #GstMetaInfo
+ *
+ * Since: 1.14
+ */
+const GstMetaInfo *
+gst_reference_timestamp_meta_get_info (void)
+{
+ static const GstMetaInfo *meta_info = NULL;
+
+ if (g_once_init_enter ((GstMetaInfo **) & meta_info)) {
+ const GstMetaInfo *meta =
+ gst_meta_register (gst_reference_timestamp_meta_api_get_type (),
+ "GstReferenceTimestampMeta",
+ sizeof (GstReferenceTimestampMeta),
+ (GstMetaInitFunction) _gst_reference_timestamp_meta_init,
+ (GstMetaFreeFunction) _gst_reference_timestamp_meta_free,
+ _gst_reference_timestamp_meta_transform);
+ g_once_init_leave ((GstMetaInfo **) & meta_info, (GstMetaInfo *) meta);
+ }
+
+ return meta_info;
+}
diff --git a/gst/gstbuffer.h b/gst/gstbuffer.h
index 916f94726..40aaa12bd 100644
--- a/gst/gstbuffer.h
+++ b/gst/gstbuffer.h
@@ -27,6 +27,7 @@
#include <gst/gstminiobject.h>
#include <gst/gstclock.h>
#include <gst/gstallocator.h>
+#include <gst/gstcaps.h>
G_BEGIN_DECLS
@@ -632,6 +633,48 @@ const GstMetaInfo *gst_parent_buffer_meta_get_info (void);
GstParentBufferMeta *gst_buffer_add_parent_buffer_meta (GstBuffer *buffer,
GstBuffer *ref);
+typedef struct _GstReferenceTimestampMeta GstReferenceTimestampMeta;
+
+/**
+ * GstReferenceTimestampMeta:
+ * @parent: the parent #GstMeta structure
+ * @reference: identifier for the timestamp reference.
+ * @timestamp: timestamp
+ * @duration: duration, or %GST_CLOCK_TIME_NONE
+ *
+ * #GstReferenceTimestampMeta can be used to attach alternative timestamps and
+ * possibly durations to a #GstBuffer. These are generally not according to
+ * the pipeline clock and could be e.g. the NTP timestamp when the media was
+ * captured.
+ *
+ * The reference is stored as a #GstCaps in @reference. Examples of valid
+ * references would be "timestamp/x-drivername-stream" for timestamps that are locally
+ * generated by some driver named "drivername" when generating the stream,
+ * e.g. based on a frame counter, or "timestamp/x-ntp, host=pool.ntp.org,
+ * port=123" for timestamps based on a specific NTP server.
+ *
+ * Since: 1.14
+ */
+struct _GstReferenceTimestampMeta
+{
+ GstMeta parent;
+
+ /*< public >*/
+ GstCaps *reference;
+ GstClockTime timestamp, duration;
+};
+
+GType gst_reference_timestamp_meta_api_get_type (void);
+#define GST_REFERENCE_TIMESTAMP_META_API_TYPE (gst_reference_timestamp_meta_api_get_type())
+
+const GstMetaInfo *gst_reference_timestamp_meta_get_info (void);
+#define GST_REFERENCE_TIMESTAMP_META_INFO (gst_reference_timestamp_meta_get_info())
+
+/* implementation */
+GstReferenceTimestampMeta *gst_buffer_add_reference_timestamp_meta (GstBuffer *buffer,
+ GstCaps *reference, GstClockTime timestamp, GstClockTime duration);
+GstReferenceTimestampMeta *gst_buffer_get_reference_timestamp_meta (GstBuffer * buffer, GstCaps * reference);
+
#ifdef G_DEFINE_AUTOPTR_CLEANUP_FUNC
G_DEFINE_AUTOPTR_CLEANUP_FUNC(GstBuffer, gst_buffer_unref)
#endif
diff --git a/win32/common/libgstreamer.def b/win32/common/libgstreamer.def
index 389f52859..3fe1b4619 100644
--- a/win32/common/libgstreamer.def
+++ b/win32/common/libgstreamer.def
@@ -116,6 +116,7 @@ EXPORTS
gst_buffer_add_meta
gst_buffer_add_parent_buffer_meta
gst_buffer_add_protection_meta
+ gst_buffer_add_reference_timestamp_meta
gst_buffer_append
gst_buffer_append_memory
gst_buffer_append_region
@@ -135,6 +136,7 @@ EXPORTS
gst_buffer_get_memory
gst_buffer_get_memory_range
gst_buffer_get_meta
+ gst_buffer_get_reference_timestamp_meta
gst_buffer_get_size
gst_buffer_get_sizes
gst_buffer_get_sizes_range
@@ -1173,6 +1175,8 @@ EXPORTS
gst_query_type_to_quark
gst_query_writable_structure
gst_rank_get_type
+ gst_reference_timestamp_meta_api_get_type
+ gst_reference_timestamp_meta_get_info
gst_registry_add_feature
gst_registry_add_plugin
gst_registry_check_feature_version