mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-11-25 11:11:08 +00:00
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:
parent
da1d11be77
commit
7d930b8693
4 changed files with 220 additions and 0 deletions
|
@ -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
|
||||
|
|
169
gst/gstbuffer.c
169
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;
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in a new issue