mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-12-18 06:16:36 +00:00
rtpbasepayload: add property for embedding twcc sequencenumbers
By setting the extension-ID for TWCC (Transport Wide Congestion Control), the payloader will embed sequencenumbers as a RTP header-extension according to https://tools.ietf.org/html/draft-holmer-rmcat-transport-wide-cc-extensions-01#section-2 The negotiation of this being enabled with downstream elements is done with caps reflecting the way this is communicated using SDP.
This commit is contained in:
parent
0e1f7f6e8d
commit
85e201fe30
2 changed files with 102 additions and 0 deletions
|
@ -47,6 +47,7 @@ struct _GstRTPBasePayloadPrivate
|
||||||
|
|
||||||
gboolean source_info;
|
gboolean source_info;
|
||||||
GstBuffer *input_meta_buffer;
|
GstBuffer *input_meta_buffer;
|
||||||
|
guint8 twcc_ext_id;
|
||||||
|
|
||||||
guint64 base_offset;
|
guint64 base_offset;
|
||||||
gint64 base_rtime;
|
gint64 base_rtime;
|
||||||
|
@ -92,6 +93,7 @@ enum
|
||||||
#define DEFAULT_RUNNING_TIME GST_CLOCK_TIME_NONE
|
#define DEFAULT_RUNNING_TIME GST_CLOCK_TIME_NONE
|
||||||
#define DEFAULT_SOURCE_INFO FALSE
|
#define DEFAULT_SOURCE_INFO FALSE
|
||||||
#define DEFAULT_ONVIF_NO_RATE_CONTROL FALSE
|
#define DEFAULT_ONVIF_NO_RATE_CONTROL FALSE
|
||||||
|
#define DEFAULT_TWCC_EXT_ID 0
|
||||||
|
|
||||||
enum
|
enum
|
||||||
{
|
{
|
||||||
|
@ -110,6 +112,7 @@ enum
|
||||||
PROP_STATS,
|
PROP_STATS,
|
||||||
PROP_SOURCE_INFO,
|
PROP_SOURCE_INFO,
|
||||||
PROP_ONVIF_NO_RATE_CONTROL,
|
PROP_ONVIF_NO_RATE_CONTROL,
|
||||||
|
PROP_TWCC_EXT_ID,
|
||||||
PROP_LAST
|
PROP_LAST
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -337,6 +340,28 @@ gst_rtp_base_payload_class_init (GstRTPBasePayloadClass * klass)
|
||||||
DEFAULT_ONVIF_NO_RATE_CONTROL,
|
DEFAULT_ONVIF_NO_RATE_CONTROL,
|
||||||
G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
|
G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
|
||||||
|
|
||||||
|
/**
|
||||||
|
* GstRTPBasePayload:twcc-ext-id:
|
||||||
|
*
|
||||||
|
* The RTP header-extension ID used for tagging buffers with Transport-Wide
|
||||||
|
* Congestion Control sequence-numbers.
|
||||||
|
*
|
||||||
|
* To use this across multiple bundled streams (transport wide), the
|
||||||
|
* GstRTPFunnel can mux TWCC sequence-numbers together.
|
||||||
|
*
|
||||||
|
* This is experimental, as it is still a draft and not yet a standard.
|
||||||
|
*
|
||||||
|
* Since: 1.18
|
||||||
|
*/
|
||||||
|
g_object_class_install_property (gobject_class, PROP_TWCC_EXT_ID,
|
||||||
|
g_param_spec_uint ("twcc-ext-id",
|
||||||
|
"Transport-wide Congestion Control Extension ID (experimental)",
|
||||||
|
"The RTP header-extension ID to use for tagging buffers with "
|
||||||
|
"Transport-wide Congestion Control sequencenumbers (0 = disable)",
|
||||||
|
0, 15, DEFAULT_TWCC_EXT_ID,
|
||||||
|
G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
|
||||||
|
|
||||||
|
|
||||||
gstelement_class->change_state = gst_rtp_base_payload_change_state;
|
gstelement_class->change_state = gst_rtp_base_payload_change_state;
|
||||||
|
|
||||||
klass->get_caps = gst_rtp_base_payload_getcaps_default;
|
klass->get_caps = gst_rtp_base_payload_getcaps_default;
|
||||||
|
@ -1115,6 +1140,16 @@ gst_rtp_base_payload_negotiate (GstRTPBasePayload * payload)
|
||||||
|
|
||||||
update_max_ptime (payload);
|
update_max_ptime (payload);
|
||||||
|
|
||||||
|
|
||||||
|
if (payload->priv->twcc_ext_id > 0) {
|
||||||
|
/* TODO: put this as a separate utility-function for RTP extensions */
|
||||||
|
gchar *name = g_strdup_printf ("extmap-%u", payload->priv->twcc_ext_id);
|
||||||
|
gst_caps_set_simple (srccaps, name, G_TYPE_STRING,
|
||||||
|
"http://www.ietf.org/id/draft-holmer-rmcat-transport-wide-cc-extensions-01",
|
||||||
|
NULL);
|
||||||
|
g_free (name);
|
||||||
|
}
|
||||||
|
|
||||||
res = gst_pad_set_caps (GST_RTP_BASE_PAYLOAD_SRCPAD (payload), srccaps);
|
res = gst_pad_set_caps (GST_RTP_BASE_PAYLOAD_SRCPAD (payload), srccaps);
|
||||||
gst_caps_unref (srccaps);
|
gst_caps_unref (srccaps);
|
||||||
gst_caps_unref (templ);
|
gst_caps_unref (templ);
|
||||||
|
@ -1162,6 +1197,7 @@ typedef struct
|
||||||
GstClockTime pts;
|
GstClockTime pts;
|
||||||
guint64 offset;
|
guint64 offset;
|
||||||
guint32 rtptime;
|
guint32 rtptime;
|
||||||
|
guint8 twcc_ext_id;
|
||||||
} HeaderData;
|
} HeaderData;
|
||||||
|
|
||||||
static gboolean
|
static gboolean
|
||||||
|
@ -1180,6 +1216,16 @@ find_timestamp (GstBuffer ** buffer, guint idx, gpointer user_data)
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
_set_twcc_seq (GstRTPBuffer * rtp, guint16 seq, guint8 ext_id)
|
||||||
|
{
|
||||||
|
guint16 data;
|
||||||
|
if (ext_id == 0 || ext_id > 14)
|
||||||
|
return;
|
||||||
|
GST_WRITE_UINT16_BE (&data, seq);
|
||||||
|
gst_rtp_buffer_add_extension_onebyte_header (rtp, ext_id, &data, 2);
|
||||||
|
}
|
||||||
|
|
||||||
static gboolean
|
static gboolean
|
||||||
set_headers (GstBuffer ** buffer, guint idx, gpointer user_data)
|
set_headers (GstBuffer ** buffer, guint idx, gpointer user_data)
|
||||||
{
|
{
|
||||||
|
@ -1193,6 +1239,7 @@ set_headers (GstBuffer ** buffer, guint idx, gpointer user_data)
|
||||||
gst_rtp_buffer_set_payload_type (&rtp, data->pt);
|
gst_rtp_buffer_set_payload_type (&rtp, data->pt);
|
||||||
gst_rtp_buffer_set_seq (&rtp, data->seqnum);
|
gst_rtp_buffer_set_seq (&rtp, data->seqnum);
|
||||||
gst_rtp_buffer_set_timestamp (&rtp, data->rtptime);
|
gst_rtp_buffer_set_timestamp (&rtp, data->rtptime);
|
||||||
|
_set_twcc_seq (&rtp, data->seqnum, data->twcc_ext_id);
|
||||||
gst_rtp_buffer_unmap (&rtp);
|
gst_rtp_buffer_unmap (&rtp);
|
||||||
|
|
||||||
/* increment the seqnum for each buffer */
|
/* increment the seqnum for each buffer */
|
||||||
|
@ -1249,6 +1296,7 @@ gst_rtp_base_payload_prepare_push (GstRTPBasePayload * payload,
|
||||||
data.seqnum = payload->seqnum;
|
data.seqnum = payload->seqnum;
|
||||||
data.ssrc = payload->current_ssrc;
|
data.ssrc = payload->current_ssrc;
|
||||||
data.pt = payload->pt;
|
data.pt = payload->pt;
|
||||||
|
data.twcc_ext_id = priv->twcc_ext_id;
|
||||||
|
|
||||||
/* find the first buffer with a timestamp */
|
/* find the first buffer with a timestamp */
|
||||||
if (is_list) {
|
if (is_list) {
|
||||||
|
@ -1566,6 +1614,9 @@ gst_rtp_base_payload_set_property (GObject * object, guint prop_id,
|
||||||
case PROP_ONVIF_NO_RATE_CONTROL:
|
case PROP_ONVIF_NO_RATE_CONTROL:
|
||||||
priv->onvif_no_rate_control = g_value_get_boolean (value);
|
priv->onvif_no_rate_control = g_value_get_boolean (value);
|
||||||
break;
|
break;
|
||||||
|
case PROP_TWCC_EXT_ID:
|
||||||
|
priv->twcc_ext_id = g_value_get_uint (value);
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||||
break;
|
break;
|
||||||
|
@ -1636,6 +1687,9 @@ gst_rtp_base_payload_get_property (GObject * object, guint prop_id,
|
||||||
case PROP_ONVIF_NO_RATE_CONTROL:
|
case PROP_ONVIF_NO_RATE_CONTROL:
|
||||||
g_value_set_boolean (value, priv->onvif_no_rate_control);
|
g_value_set_boolean (value, priv->onvif_no_rate_control);
|
||||||
break;
|
break;
|
||||||
|
case PROP_TWCC_EXT_ID:
|
||||||
|
g_value_set_uint (value, priv->twcc_ext_id);
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -1969,6 +1969,53 @@ GST_START_TEST (rtp_base_payload_segment_time)
|
||||||
|
|
||||||
GST_END_TEST;
|
GST_END_TEST;
|
||||||
|
|
||||||
|
#define TWCC_EXTMAP_STR "http://www.ietf.org/id/draft-holmer-rmcat-transport-wide-cc-extensions-01"
|
||||||
|
|
||||||
|
GST_START_TEST (rtp_base_payload_property_twcc_ext_id_test)
|
||||||
|
{
|
||||||
|
GstHarness *h;
|
||||||
|
GstRtpDummyPay *pay;
|
||||||
|
GstBuffer *buf;
|
||||||
|
GstRTPBuffer rtp = GST_RTP_BUFFER_INIT;
|
||||||
|
guint8 ext_id = 10;
|
||||||
|
gpointer data;
|
||||||
|
guint size;
|
||||||
|
guint16 seqnum, twcc_seqnum;
|
||||||
|
GstCaps *caps, *expected_caps;
|
||||||
|
|
||||||
|
pay = rtp_dummy_pay_new ();
|
||||||
|
g_object_set (pay, "twcc-ext-id", ext_id, NULL);
|
||||||
|
|
||||||
|
h = gst_harness_new_with_element (GST_ELEMENT_CAST (pay), "sink", "src");
|
||||||
|
gst_harness_set_src_caps_str (h, "application/x-rtp");
|
||||||
|
|
||||||
|
/* verify the presence of the twcc-seqnum */
|
||||||
|
buf = gst_harness_push_and_pull (h, gst_buffer_new ());
|
||||||
|
gst_rtp_buffer_map (buf, GST_MAP_READWRITE, &rtp);
|
||||||
|
fail_unless (gst_rtp_buffer_get_extension_onebyte_header (&rtp, ext_id,
|
||||||
|
0, &data, &size));
|
||||||
|
fail_unless_equals_int (2, size);
|
||||||
|
twcc_seqnum = GST_READ_UINT16_BE (data);
|
||||||
|
seqnum = gst_rtp_buffer_get_seq (&rtp);
|
||||||
|
fail_unless_equals_int (twcc_seqnum, seqnum);
|
||||||
|
gst_rtp_buffer_unmap (&rtp);
|
||||||
|
gst_buffer_unref (buf);
|
||||||
|
|
||||||
|
/* verify the presence of the twcc in caps */
|
||||||
|
caps = gst_pad_get_current_caps (GST_PAD_PEER (h->sinkpad));
|
||||||
|
expected_caps = gst_caps_from_string ("application/x-rtp, "
|
||||||
|
"extmap-10=" TWCC_EXTMAP_STR "");
|
||||||
|
fail_unless (gst_caps_is_subset (caps, expected_caps));
|
||||||
|
gst_caps_unref (caps);
|
||||||
|
gst_caps_unref (expected_caps);
|
||||||
|
|
||||||
|
g_object_unref (pay);
|
||||||
|
gst_harness_teardown (h);
|
||||||
|
}
|
||||||
|
|
||||||
|
GST_END_TEST;
|
||||||
|
|
||||||
|
|
||||||
static Suite *
|
static Suite *
|
||||||
rtp_basepayloading_suite (void)
|
rtp_basepayloading_suite (void)
|
||||||
{
|
{
|
||||||
|
@ -2003,6 +2050,7 @@ rtp_basepayloading_suite (void)
|
||||||
tcase_add_test (tc_chain, rtp_base_payload_property_ptime_multiple_test);
|
tcase_add_test (tc_chain, rtp_base_payload_property_ptime_multiple_test);
|
||||||
tcase_add_test (tc_chain, rtp_base_payload_property_stats_test);
|
tcase_add_test (tc_chain, rtp_base_payload_property_stats_test);
|
||||||
tcase_add_test (tc_chain, rtp_base_payload_property_source_info_test);
|
tcase_add_test (tc_chain, rtp_base_payload_property_source_info_test);
|
||||||
|
tcase_add_test (tc_chain, rtp_base_payload_property_twcc_ext_id_test);
|
||||||
|
|
||||||
tcase_add_test (tc_chain, rtp_base_payload_framerate_attribute);
|
tcase_add_test (tc_chain, rtp_base_payload_framerate_attribute);
|
||||||
tcase_add_test (tc_chain, rtp_base_payload_max_framerate_attribute);
|
tcase_add_test (tc_chain, rtp_base_payload_max_framerate_attribute);
|
||||||
|
|
Loading…
Reference in a new issue