summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHavard Graff <havard.graff@gmail.com>2020-11-19 23:50:23 +0100
committerGStreamer Marge Bot <gitlab-merge-bot@gstreamer-foundation.org>2021-08-25 08:36:06 +0000
commitbe5fab15e00162a3cb0eb6f84e3bfdecb01c8869 (patch)
treeb665d02c027f82d3109325b4ddfc08f44c4bc41f
parentddcde96efef752aafca9eef329714114c28b71ae (diff)
downloadgstreamer-plugins-good-be5fab15e00162a3cb0eb6f84e3bfdecb01c8869.tar.gz
rtptwcc: add feedback-interval
To allow RTCP TWCC reports to be scheduled on a timer instead of per marker-bit. Part-of: <https://gitlab.freedesktop.org/gstreamer/gst-plugins-good/-/merge_requests/927>
-rw-r--r--gst/rtpmanager/rtpsession.c29
-rw-r--r--gst/rtpmanager/rtptwcc.c34
-rw-r--r--gst/rtpmanager/rtptwcc.h3
-rw-r--r--tests/check/elements/rtpsession.c45
4 files changed, 109 insertions, 2 deletions
diff --git a/gst/rtpmanager/rtpsession.c b/gst/rtpmanager/rtpsession.c
index 5c52766e0..b8429a1a3 100644
--- a/gst/rtpmanager/rtpsession.c
+++ b/gst/rtpmanager/rtpsession.c
@@ -78,6 +78,7 @@ enum
#define DEFAULT_RTP_PROFILE GST_RTP_PROFILE_AVP
#define DEFAULT_RTCP_REDUCED_SIZE FALSE
#define DEFAULT_RTCP_DISABLE_SR_TIMESTAMP FALSE
+#define DEFAULT_TWCC_FEEDBACK_INTERVAL GST_CLOCK_TIME_NONE
enum
{
@@ -103,7 +104,8 @@ enum
PROP_STATS,
PROP_RTP_PROFILE,
PROP_RTCP_REDUCED_SIZE,
- PROP_RTCP_DISABLE_SR_TIMESTAMP
+ PROP_RTCP_DISABLE_SR_TIMESTAMP,
+ PROP_TWCC_FEEDBACK_INTERVAL,
};
/* update average packet size */
@@ -629,6 +631,23 @@ rtp_session_class_init (RTPSessionClass * klass)
DEFAULT_RTCP_DISABLE_SR_TIMESTAMP,
G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+ /**
+ * RTPSession::twcc-feedback-interval:
+ *
+ * The interval to send TWCC reports on.
+ * This overrides the default behavior of sending reports
+ * based on marker-bits.
+ *
+ * Since: 1.20
+ */
+ g_object_class_install_property (gobject_class,
+ PROP_TWCC_FEEDBACK_INTERVAL,
+ g_param_spec_uint64 ("twcc-feedback-interval",
+ "TWCC Feedback Interval",
+ "The interval to send TWCC reports on",
+ 0, G_MAXUINT64, DEFAULT_TWCC_FEEDBACK_INTERVAL,
+ G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+
klass->get_source_by_ssrc =
GST_DEBUG_FUNCPTR (rtp_session_get_source_by_ssrc);
klass->send_rtcp = GST_DEBUG_FUNCPTR (rtp_session_send_rtcp);
@@ -907,6 +926,10 @@ rtp_session_set_property (GObject * object, guint prop_id,
case PROP_RTCP_DISABLE_SR_TIMESTAMP:
sess->timestamp_sender_reports = !g_value_get_boolean (value);
break;
+ case PROP_TWCC_FEEDBACK_INTERVAL:
+ rtp_twcc_manager_set_feedback_interval (sess->twcc,
+ g_value_get_uint64 (value));
+ break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
@@ -989,6 +1012,10 @@ rtp_session_get_property (GObject * object, guint prop_id,
case PROP_RTCP_DISABLE_SR_TIMESTAMP:
g_value_set_boolean (value, !sess->timestamp_sender_reports);
break;
+ case PROP_TWCC_FEEDBACK_INTERVAL:
+ g_value_set_uint64 (value,
+ rtp_twcc_manager_get_feedback_interval (sess->twcc));
+ break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
diff --git a/gst/rtpmanager/rtptwcc.c b/gst/rtpmanager/rtptwcc.c
index 8a7e879f6..d5039d4fc 100644
--- a/gst/rtpmanager/rtptwcc.c
+++ b/gst/rtpmanager/rtptwcc.c
@@ -87,6 +87,9 @@ struct _RTPTWCCManager
gboolean first_fci_parse;
guint16 expected_parsed_seqnum;
guint8 expected_parsed_fb_pkt_count;
+
+ GstClockTime next_feedback_send_time;
+ GstClockTime feedback_interval;
};
G_DEFINE_TYPE (RTPTWCCManager, rtp_twcc_manager, G_TYPE_OBJECT);
@@ -105,6 +108,9 @@ rtp_twcc_manager_init (RTPTWCCManager * twcc)
twcc->recv_sender_ssrc = -1;
twcc->first_fci_parse = TRUE;
+
+ twcc->feedback_interval = GST_CLOCK_TIME_NONE;
+ twcc->next_feedback_send_time = GST_CLOCK_TIME_NONE;
}
static void
@@ -157,6 +163,19 @@ rtp_twcc_manager_set_mtu (RTPTWCCManager * twcc, guint mtu)
twcc->max_packets_per_rtcp = ((twcc->mtu - 32) * 7) / (2 + 14);
}
+void
+rtp_twcc_manager_set_feedback_interval (RTPTWCCManager * twcc,
+ GstClockTime feedback_interval)
+{
+ twcc->feedback_interval = feedback_interval;
+}
+
+GstClockTime
+rtp_twcc_manager_get_feedback_interval (RTPTWCCManager * twcc)
+{
+ return twcc->feedback_interval;
+}
+
static gint
_twcc_seqnum_sort (gconstpointer a, gconstpointer b)
{
@@ -609,7 +628,20 @@ rtp_twcc_manager_recv_packet (RTPTWCCManager * twcc,
GST_LOG ("Receive: twcc-seqnum: %u, marker: %d, ts: %" GST_TIME_FORMAT,
seqnum, pinfo->marker, GST_TIME_ARGS (pinfo->running_time));
- if (pinfo->marker || _many_packets_some_lost (twcc, seqnum)) {
+ /* are we sending on an interval, or based on marker bit */
+ if (GST_CLOCK_TIME_IS_VALID (twcc->feedback_interval)) {
+ if (!GST_CLOCK_TIME_IS_VALID (twcc->next_feedback_send_time))
+ twcc->next_feedback_send_time =
+ pinfo->running_time + twcc->feedback_interval;
+
+ if (pinfo->running_time >= twcc->next_feedback_send_time) {
+ rtp_twcc_manager_create_feedback (twcc);
+ send_feedback = TRUE;
+
+ while (pinfo->running_time >= twcc->next_feedback_send_time)
+ twcc->next_feedback_send_time += twcc->feedback_interval;
+ }
+ } else if (pinfo->marker || _many_packets_some_lost (twcc, seqnum)) {
rtp_twcc_manager_create_feedback (twcc);
send_feedback = TRUE;
}
diff --git a/gst/rtpmanager/rtptwcc.h b/gst/rtpmanager/rtptwcc.h
index 2342ef83f..bb14dbad2 100644
--- a/gst/rtpmanager/rtptwcc.h
+++ b/gst/rtpmanager/rtptwcc.h
@@ -54,6 +54,9 @@ struct _RTPTWCCPacket
RTPTWCCManager * rtp_twcc_manager_new (guint mtu);
void rtp_twcc_manager_set_mtu (RTPTWCCManager * twcc, guint mtu);
+void rtp_twcc_manager_set_feedback_interval (RTPTWCCManager * twcc,
+ GstClockTime feedback_interval);
+GstClockTime rtp_twcc_manager_get_feedback_interval (RTPTWCCManager * twcc);
gboolean rtp_twcc_manager_recv_packet (RTPTWCCManager * twcc,
guint16 seqnum, RTPPacketInfo * pinfo);
diff --git a/tests/check/elements/rtpsession.c b/tests/check/elements/rtpsession.c
index d3de55373..d87de24bf 100644
--- a/tests/check/elements/rtpsession.c
+++ b/tests/check/elements/rtpsession.c
@@ -3685,6 +3685,48 @@ GST_START_TEST (test_twcc_send_and_recv)
GST_END_TEST;
+typedef struct
+{
+ GstClockTime interval;
+ guint num_packets;
+ GstClockTime ts_delta;
+ guint num_feedback;
+} TWCCFeedbackIntervalCtx;
+
+static TWCCFeedbackIntervalCtx test_twcc_feedback_interval_ctx[] = {
+ {50 * GST_MSECOND, 21, 10 * GST_MSECOND, 4},
+ {50 * GST_MSECOND, 16, 7 * GST_MSECOND, 2},
+ {50 * GST_MSECOND, 16, 66 * GST_MSECOND, 15},
+ {50 * GST_MSECOND, 15, 33 * GST_MSECOND, 9},
+};
+
+GST_START_TEST (test_twcc_feedback_interval)
+{
+ SessionHarness *h = session_harness_new ();
+ GstBuffer *buf;
+ TWCCFeedbackIntervalCtx *ctx = &test_twcc_feedback_interval_ctx[__i__];
+
+ session_harness_set_twcc_recv_ext_id (h, TEST_TWCC_EXT_ID);
+ g_object_set (h->internal_session, "twcc-feedback-interval", ctx->interval,
+ NULL);
+
+ for (guint i = 0; i < ctx->num_packets; i++) {
+ GstClockTime ts = i * ctx->ts_delta;
+ gst_test_clock_set_time ((h->testclock), ts);
+ fail_unless_equals_int (GST_FLOW_OK,
+ session_harness_recv_rtp (h, generate_twcc_recv_buffer (i, ts, FALSE)));
+ }
+
+ for (guint i = 0; i < ctx->num_feedback; i++) {
+ buf = session_harness_produce_twcc (h);
+ gst_buffer_unref (buf);
+ }
+
+ session_harness_free (h);
+}
+
+GST_END_TEST;
+
static Suite *
rtpsession_suite (void)
{
@@ -3749,6 +3791,9 @@ rtpsession_suite (void)
tcase_add_test (tc_chain, test_twcc_recv_rtcp_reordered);
tcase_add_test (tc_chain, test_twcc_no_exthdr_in_buffer);
tcase_add_test (tc_chain, test_twcc_send_and_recv);
+ tcase_add_loop_test (tc_chain, test_twcc_feedback_interval, 0,
+ G_N_ELEMENTS (test_twcc_feedback_interval_ctx));
+
return s;
}