buffer: Add optional info structure to GstReferenceTimestampMeta
This allows carrying additional per-timestamp information if needed. Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/9245>
This commit is contained in:
parent
f40726597e
commit
4bd4c4d4f7
@ -40524,7 +40524,14 @@ references would be
|
||||
the local clock.
|
||||
|
||||
Since 1.24 it can be serialized using gst_meta_serialize() and
|
||||
gst_meta_deserialize().</doc>
|
||||
gst_meta_deserialize().
|
||||
|
||||
Since 1.28 additional information about the timestamp can be provided via the
|
||||
optional @info structure. This should only be used for information about the
|
||||
timestamp and not for information about the clock source. The latter should
|
||||
be stored in the @reference instead.
|
||||
|
||||
Interpretation of the fields of @info depends on the @reference.</doc>
|
||||
<source-position filename="../subprojects/gstreamer/gst/gstbuffer.h"/>
|
||||
<field name="parent" writable="1">
|
||||
<doc xml:space="preserve" filename="../subprojects/gstreamer/gst/gstbuffer.h">the parent #GstMeta structure</doc>
|
||||
@ -40542,6 +40549,10 @@ gst_meta_deserialize().</doc>
|
||||
<doc xml:space="preserve" filename="../subprojects/gstreamer/gst/gstbuffer.h">duration, or %GST_CLOCK_TIME_NONE</doc>
|
||||
<type name="ClockTime" c:type="GstClockTime"/>
|
||||
</field>
|
||||
<field name="info" version="1.28" writable="1">
|
||||
<doc xml:space="preserve" filename="../subprojects/gstreamer/gst/gstbuffer.h">Additional information about the timestamp.</doc>
|
||||
<type name="Structure" c:type="GstStructure*"/>
|
||||
</field>
|
||||
<function name="get_info" c:identifier="gst_reference_timestamp_meta_get_info" version="1.14">
|
||||
<doc xml:space="preserve" filename="../subprojects/gstreamer/gst/gstbuffer.c">Gets the global #GstMetaInfo describing the #GstReferenceTimestampMeta meta.</doc>
|
||||
<source-position filename="../subprojects/gstreamer/gst/gstbuffer.h"/>
|
||||
|
@ -2763,6 +2763,7 @@ gst_buffer_add_reference_timestamp_meta (GstBuffer * buffer,
|
||||
meta->reference = gst_caps_ref (reference);
|
||||
meta->timestamp = timestamp;
|
||||
meta->duration = duration;
|
||||
meta->info = NULL;
|
||||
|
||||
return meta;
|
||||
}
|
||||
@ -2770,7 +2771,7 @@ gst_buffer_add_reference_timestamp_meta (GstBuffer * buffer,
|
||||
/**
|
||||
* gst_buffer_get_reference_timestamp_meta:
|
||||
* @buffer: a #GstBuffer
|
||||
* @reference: (allow-none): a reference #GstCaps
|
||||
* @reference: (nullable): a reference #GstCaps
|
||||
*
|
||||
* Finds the first #GstReferenceTimestampMeta on @buffer that conforms to
|
||||
* @reference. Conformance is tested by checking if the meta's reference is a
|
||||
@ -2822,7 +2823,11 @@ _gst_reference_timestamp_meta_transform (GstBuffer * dest, GstMeta * meta,
|
||||
GST_REFERENCE_TIMESTAMP_META_API_TYPE))) {
|
||||
if (ometa->timestamp == smeta->timestamp
|
||||
&& ometa->duration == smeta->duration
|
||||
&& gst_caps_is_equal (ometa->reference, smeta->reference)) {
|
||||
&& gst_caps_is_equal (ometa->reference, smeta->reference)
|
||||
&& ((ometa->info == NULL && smeta->info == NULL) ||
|
||||
(ometa->info != NULL && smeta->info != NULL
|
||||
&& gst_structure_is_equal (ometa->info, smeta->info))
|
||||
)) {
|
||||
GST_CAT_TRACE (gst_reference_timestamp_meta_debug,
|
||||
"Not copying reference timestamp metadata from buffer %p to %p because equal meta already exists",
|
||||
buffer, dest);
|
||||
@ -2835,6 +2840,8 @@ _gst_reference_timestamp_meta_transform (GstBuffer * dest, GstMeta * meta,
|
||||
smeta->timestamp, smeta->duration);
|
||||
if (!dmeta)
|
||||
return FALSE;
|
||||
if (smeta->info)
|
||||
dmeta->info = gst_structure_copy (smeta->info);
|
||||
|
||||
GST_CAT_DEBUG (gst_reference_timestamp_meta_debug,
|
||||
"copy reference timestamp metadata from buffer %p to %p", buffer, dest);
|
||||
@ -2848,6 +2855,8 @@ _gst_reference_timestamp_meta_free (GstReferenceTimestampMeta * meta,
|
||||
{
|
||||
if (meta->reference)
|
||||
gst_caps_unref (meta->reference);
|
||||
if (meta->info)
|
||||
gst_structure_free (meta->info);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
@ -2865,6 +2874,7 @@ _gst_reference_timestamp_meta_init (GstReferenceTimestampMeta * meta,
|
||||
meta->reference = NULL;
|
||||
meta->timestamp = GST_CLOCK_TIME_NONE;
|
||||
meta->duration = GST_CLOCK_TIME_NONE;
|
||||
meta->info = NULL;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
@ -2893,13 +2903,23 @@ timestamp_meta_serialize (const GstMeta * meta, GstByteArrayInterface * data,
|
||||
{
|
||||
const GstReferenceTimestampMeta *rtmeta =
|
||||
(const GstReferenceTimestampMeta *) meta;
|
||||
gchar *info_str = rtmeta->info ? gst_structure_serialize_full (rtmeta->info,
|
||||
GST_SERIALIZE_FLAG_STRICT) : NULL;
|
||||
gsize info_str_len = info_str ? strlen (info_str) : 0;
|
||||
|
||||
if (rtmeta->info && !info_str) {
|
||||
GST_WARNING ("Failed serializing GstReferenceTimestampMeta");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
gchar *caps_str = gst_caps_to_string (rtmeta->reference);
|
||||
gsize caps_str_len = strlen (caps_str);
|
||||
|
||||
gsize size = 16 + caps_str_len + 1;
|
||||
gsize size = 16 + caps_str_len + 1 + (info_str ? info_str_len + 1 : 0);
|
||||
guint8 *ptr = gst_byte_array_interface_append (data, size);
|
||||
if (ptr == NULL) {
|
||||
g_free (caps_str);
|
||||
g_free (info_str);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
@ -2907,6 +2927,9 @@ timestamp_meta_serialize (const GstMeta * meta, GstByteArrayInterface * data,
|
||||
GST_WRITE_UINT64_LE (ptr + 8, rtmeta->duration);
|
||||
memcpy (ptr + 16, caps_str, caps_str_len + 1);
|
||||
g_free (caps_str);
|
||||
if (info_str)
|
||||
memcpy (ptr + 16 + caps_str_len + 1, info_str, info_str_len + 1);
|
||||
g_free (info_str);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
@ -2915,19 +2938,31 @@ static GstMeta *
|
||||
timestamp_meta_deserialize (const GstMetaInfo * info, GstBuffer * buffer,
|
||||
const guint8 * data, gsize size, guint8 version)
|
||||
{
|
||||
/* Sanity check: caps_str must be 0-terminated. */
|
||||
/* Sanity check: caps_str / info_str must be 0-terminated. */
|
||||
if (version != 0 || size < 2 * sizeof (guint64) + 1 || data[size - 1] != '\0')
|
||||
return NULL;
|
||||
|
||||
guint64 timestamp = GST_READ_UINT64_LE (data);
|
||||
guint64 duration = GST_READ_UINT64_LE (data + 8);
|
||||
const gchar *caps_str = (const gchar *) data + 16;
|
||||
gsize caps_str_len = strlen (caps_str);
|
||||
GstCaps *reference = gst_caps_from_string (caps_str);
|
||||
GstMeta *meta = (GstMeta *) gst_buffer_add_reference_timestamp_meta (buffer,
|
||||
|
||||
/* Have additional data afterward the reference, which is for the optional
|
||||
* info structure */
|
||||
GstStructure *rtinfo = NULL;
|
||||
if (size > 16 + caps_str_len + 1) {
|
||||
const gchar *info_str = (const gchar *) data + 16 + caps_str_len + 1;
|
||||
rtinfo = gst_structure_from_string (info_str, NULL);
|
||||
}
|
||||
|
||||
GstReferenceTimestampMeta *meta =
|
||||
gst_buffer_add_reference_timestamp_meta (buffer,
|
||||
reference, timestamp, duration);
|
||||
gst_caps_unref (reference);
|
||||
meta->info = rtinfo;
|
||||
|
||||
return meta;
|
||||
return (GstMeta *) meta;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -743,6 +743,7 @@ typedef struct _GstReferenceTimestampMeta GstReferenceTimestampMeta;
|
||||
* @reference: identifier for the timestamp reference.
|
||||
* @timestamp: timestamp
|
||||
* @duration: duration, or %GST_CLOCK_TIME_NONE
|
||||
* @info: (nullable): optional additional information about the timestamp
|
||||
*
|
||||
* #GstReferenceTimestampMeta can be used to attach alternative timestamps and
|
||||
* possibly durations to a #GstBuffer. These are generally not according to
|
||||
@ -766,6 +767,13 @@ typedef struct _GstReferenceTimestampMeta GstReferenceTimestampMeta;
|
||||
* Since 1.24 it can be serialized using gst_meta_serialize() and
|
||||
* gst_meta_deserialize().
|
||||
*
|
||||
* Since 1.28 additional information about the timestamp can be provided via the
|
||||
* optional @info structure. This should only be used for information about the
|
||||
* timestamp and not for information about the clock source. The latter should
|
||||
* be stored in the @reference instead.
|
||||
*
|
||||
* Interpretation of the fields of @info depends on the @reference.
|
||||
*
|
||||
* Since: 1.14
|
||||
*/
|
||||
struct _GstReferenceTimestampMeta
|
||||
@ -775,6 +783,15 @@ struct _GstReferenceTimestampMeta
|
||||
/*< public >*/
|
||||
GstCaps *reference;
|
||||
GstClockTime timestamp, duration;
|
||||
|
||||
/**
|
||||
* GstReferenceTimestampMeta.info:
|
||||
*
|
||||
* Additional information about the timestamp.
|
||||
*
|
||||
* Since: 1.28
|
||||
*/
|
||||
GstStructure *info;
|
||||
};
|
||||
|
||||
GST_API
|
||||
|
@ -1001,6 +1001,45 @@ GST_START_TEST (test_reference_timestamp_meta_serialization)
|
||||
|
||||
GST_END_TEST;
|
||||
|
||||
GST_START_TEST (test_reference_timestamp_meta_with_info_serialization)
|
||||
{
|
||||
GstCaps *reference =
|
||||
gst_caps_new_simple ("timestamp/x-unix", NULL, NULL, NULL);
|
||||
GstStructure *info =
|
||||
gst_structure_new ("info", "field1", G_TYPE_INT, 123, "field2",
|
||||
G_TYPE_STRING, "hello", NULL);
|
||||
|
||||
/* Serialize */
|
||||
GstBuffer *buffer = gst_buffer_new ();
|
||||
GstReferenceTimestampMeta *meta =
|
||||
gst_buffer_add_reference_timestamp_meta (buffer, reference, 1, 2);
|
||||
meta->info = gst_structure_copy (info);
|
||||
GByteArray *data = g_byte_array_new ();
|
||||
fail_unless (gst_meta_serialize_simple ((GstMeta *) meta, data));
|
||||
gst_buffer_unref (buffer);
|
||||
|
||||
/* Deserialize */
|
||||
buffer = gst_buffer_new ();
|
||||
guint32 consumed;
|
||||
meta = (GstReferenceTimestampMeta *) gst_meta_deserialize (buffer, data->data,
|
||||
data->len, &consumed);
|
||||
fail_unless (meta);
|
||||
fail_unless (consumed == data->len);
|
||||
fail_unless (GST_IS_CAPS (meta->reference));
|
||||
fail_unless (gst_caps_is_equal (meta->reference, reference));
|
||||
fail_unless_equals_uint64 (meta->timestamp, 1);
|
||||
fail_unless_equals_uint64 (meta->duration, 2);
|
||||
fail_unless (GST_IS_STRUCTURE (meta->info));
|
||||
fail_unless (gst_structure_is_equal (meta->info, info));
|
||||
gst_buffer_unref (buffer);
|
||||
|
||||
gst_caps_unref (reference);
|
||||
gst_structure_free (info);
|
||||
g_byte_array_unref (data);
|
||||
}
|
||||
|
||||
GST_END_TEST;
|
||||
|
||||
static Suite *
|
||||
gst_buffer_suite (void)
|
||||
{
|
||||
@ -1029,6 +1068,8 @@ gst_buffer_suite (void)
|
||||
tcase_add_test (tc_chain, test_new_memdup);
|
||||
tcase_add_test (tc_chain, test_auto_unmap);
|
||||
tcase_add_test (tc_chain, test_reference_timestamp_meta_serialization);
|
||||
tcase_add_test (tc_chain,
|
||||
test_reference_timestamp_meta_with_info_serialization);
|
||||
|
||||
return s;
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user