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
This commit is contained in:
Sebastian Dröge 2017-02-25 12:18:14 +02:00
parent da1d11be77
commit 7d930b8693
4 changed files with 220 additions and 0 deletions

View file

@ -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

View file

@ -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;
}

View file

@ -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

View file

@ -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