diff --git a/docs/gst/gstreamer-sections.txt b/docs/gst/gstreamer-sections.txt index 582157ab28..2efe9d216f 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 7d51c6d2ed..3077543899 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 916f947267..40aaa12bde 100644 --- a/gst/gstbuffer.h +++ b/gst/gstbuffer.h @@ -27,6 +27,7 @@ #include #include #include +#include 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 389f528591..3fe1b4619d 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