mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-11-26 19:51:11 +00:00
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>
This commit is contained in:
parent
ddcde96efe
commit
be5fab15e0
4 changed files with 109 additions and 2 deletions
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue