rtpbasepayload: add extensions property

Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/5694>
This commit is contained in:
Maksym Khomenko 2023-11-28 16:54:59 +02:00 committed by GStreamer Marge Bot
parent 4eff26ee1c
commit 20f48f0fd0
3 changed files with 134 additions and 0 deletions

View file

@ -3146,6 +3146,19 @@ the need to handle these extensions manually using the
GstRTPBasePayload::request-extension: signal.</doc>
<type name="gboolean" c:type="gboolean"/>
</property>
<property name="extensions" version="1.24" transfer-ownership="none">
<doc xml:space="preserve" filename="../subprojects/gst-plugins-base/gst-libs/gst/rtp/gstrtpbasepayload.c">A list of already enabled RTP header extensions. This may be useful for finding
out which extensions are already enabled (with add-extension signal) and picking a non-conflicting
ID for a new extension that needs to be added on top of the existing ones.
Note that the value returned by reading this property is not dynamically updated when the set of
enabled extensions changes by any of existing action signals. Rather, it represents the current state
at the time the property is read.
Dynamic updates of this property can be received by subscribing to its corresponding "notify" signal, i.e.
"notify::extensions".</doc>
<type name="Gst.ValueArray"/>
</property>
<property name="max-ptime" writable="1" transfer-ownership="none">
<type name="gint64" c:type="gint64"/>
</property>

View file

@ -137,9 +137,12 @@ enum
PROP_ONVIF_NO_RATE_CONTROL,
PROP_SCALE_RTPTIME,
PROP_AUTO_HEADER_EXTENSION,
PROP_EXTENSIONS,
PROP_LAST
};
static GParamSpec *gst_rtp_base_payload_extensions_pspec;
static void gst_rtp_base_payload_class_init (GstRTPBasePayloadClass * klass);
static void gst_rtp_base_payload_init (GstRTPBasePayload * rtpbasepayload,
gpointer g_class);
@ -176,6 +179,8 @@ static gboolean gst_rtp_base_payload_negotiate (GstRTPBasePayload * payload);
static void gst_rtp_base_payload_add_extension (GstRTPBasePayload * payload,
GstRTPHeaderExtension * ext);
static void gst_rtp_base_payload_clear_extensions (GstRTPBasePayload * payload);
static void gst_rtp_base_payload_get_extensions (GstRTPBasePayload * payload,
GValue * out_value);
static GstElementClass *parent_class = NULL;
static gint private_offset = 0;
@ -442,6 +447,33 @@ gst_rtp_base_payload_class_init (GstRTPBasePayloadClass * klass)
DEFAULT_AUTO_HEADER_EXTENSION,
G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
gst_rtp_base_payload_extensions_pspec = gst_param_spec_array ("extensions",
"RTP header extensions",
"A list of already enabled RTP header extensions",
g_param_spec_object ("extension", "RTP header extension",
"An already enabled RTP extension", GST_TYPE_RTP_HEADER_EXTENSION,
G_PARAM_READABLE | G_PARAM_STATIC_STRINGS),
G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
/**
* GstRTPBasePayload:extensions:
*
* A list of already enabled RTP header extensions. This may be useful for finding
* out which extensions are already enabled (with add-extension signal) and picking a non-conflicting
* ID for a new extension that needs to be added on top of the existing ones.
*
* Note that the value returned by reading this property is not dynamically updated when the set of
* enabled extensions changes by any of existing action signals. Rather, it represents the current state
* at the time the property is read.
*
* Dynamic updates of this property can be received by subscribing to its corresponding "notify" signal, i.e.
* "notify::extensions".
*
* Since: 1.24
*/
g_object_class_install_property (G_OBJECT_CLASS (klass),
PROP_EXTENSIONS, gst_rtp_base_payload_extensions_pspec);
/**
* GstRTPBasePayload::add-extension:
* @object: the #GstRTPBasePayload
@ -1589,6 +1621,9 @@ gst_rtp_base_payload_add_extension (GstRTPBasePayload * payload,
g_ptr_array_add (payload->priv->header_exts, gst_object_ref (ext));
gst_pad_mark_reconfigure (GST_RTP_BASE_PAYLOAD_SRCPAD (payload));
GST_OBJECT_UNLOCK (payload);
g_object_notify_by_pspec (G_OBJECT (payload),
gst_rtp_base_payload_extensions_pspec);
}
static void
@ -1597,6 +1632,32 @@ gst_rtp_base_payload_clear_extensions (GstRTPBasePayload * payload)
GST_OBJECT_LOCK (payload);
g_ptr_array_set_size (payload->priv->header_exts, 0);
GST_OBJECT_UNLOCK (payload);
g_object_notify_by_pspec (G_OBJECT (payload),
gst_rtp_base_payload_extensions_pspec);
}
static void
gst_rtp_base_payload_get_extensions (GstRTPBasePayload * payload,
GValue * out_value)
{
GPtrArray *extensions;
guint i;
GST_OBJECT_LOCK (payload);
extensions = payload->priv->header_exts;
for (i = 0; i < extensions->len; ++i) {
GValue value = G_VALUE_INIT;
g_value_init (&value, GST_TYPE_RTP_HEADER_EXTENSION);
g_value_set_object (&value, g_ptr_array_index (extensions, i));
gst_value_array_append_value (out_value, &value);
g_value_unset (&value);
}
GST_OBJECT_UNLOCK (payload);
}
typedef struct
@ -2248,6 +2309,9 @@ gst_rtp_base_payload_get_property (GObject * object, guint prop_id,
case PROP_AUTO_HEADER_EXTENSION:
g_value_set_boolean (value, priv->auto_hdr_ext);
break;
case PROP_EXTENSIONS:
gst_rtp_base_payload_get_extensions (rtpbasepayload, value);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;

View file

@ -2310,6 +2310,61 @@ GST_START_TEST (rtp_base_payload_extensions_shrink_ext_data)
}
GST_END_TEST;
GST_START_TEST (rtp_base_payload_extensions_get_enabled)
{
GstElement *pay = GST_ELEMENT (rtp_dummy_pay_new ());
GstRTPHeaderExtension *ext = rtp_dummy_hdr_ext_new ();
GValue extensions = G_VALUE_INIT;
const GValue *returned_ext;
g_signal_emit_by_name (pay, "add-extension", ext, NULL);
g_object_get_property (G_OBJECT (pay), "extensions", &extensions);
fail_unless_equals_int (gst_value_array_get_size (&extensions), 1);
returned_ext = gst_value_array_get_value (&extensions, 0);
fail_unless (G_VALUE_HOLDS (returned_ext, GST_TYPE_RTP_HEADER_EXTENSION));
fail_unless (g_value_get_object (returned_ext) == ext);
g_value_unset (&extensions);
gst_object_unref (ext);
gst_object_unref (pay);
}
GST_END_TEST;
static void
on_extensions_changed (GObject * sender, GParamSpec * pspec,
guint * invocation_count)
{
(void) sender;
(void) pspec;
(*invocation_count)++;
}
GST_START_TEST (rtp_base_payload_extensions_notify_on_change)
{
GstElement *pay = GST_ELEMENT (rtp_dummy_pay_new ());
GstRTPHeaderExtension *ext = rtp_dummy_hdr_ext_new ();
guint invocation_count = 0;
g_signal_connect (pay, "notify::extensions",
G_CALLBACK (on_extensions_changed), &invocation_count);
g_signal_emit_by_name (pay, "add-extension", ext, NULL);
fail_unless_equals_int (invocation_count, 1);
g_signal_emit_by_name (pay, "clear-extensions", NULL);
fail_unless_equals_int (invocation_count, 2);
gst_object_unref (ext);
gst_object_unref (pay);
}
GST_END_TEST;
static Suite *
rtp_basepayloading_suite (void)
{
@ -2358,6 +2413,8 @@ rtp_basepayloading_suite (void)
tcase_add_test (tc_chain, rtp_base_payload_caps_request_ignored);
tcase_add_test (tc_chain, rtp_base_payload_extensions_in_output_caps);
tcase_add_test (tc_chain, rtp_base_payload_extensions_shrink_ext_data);
tcase_add_test (tc_chain, rtp_base_payload_extensions_get_enabled);
tcase_add_test (tc_chain, rtp_base_payload_extensions_notify_on_change);
return s;
}