From bd5a4d321bc67fd78fc5684939856b05db49a297 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20Dr=C3=B6ge?= Date: Mon, 3 Oct 2022 20:28:47 +0300 Subject: [PATCH] rtpsource: Don't do probation for RTX sources Disable probation for RTX sources as packets will arrive very irregularly and waiting for a second packet usually exceeds the deadline of the retransmission. Fixes https://gitlab.freedesktop.org/gstreamer/gst-plugins-good/-/issues/181 Part-of: --- .../gst/rtpmanager/gstrtpsession.c | 41 +++------------ .../gst/rtpmanager/rtpsession.c | 37 ++++++------- .../gst/rtpmanager/rtpsession.h | 16 +++--- .../gst/rtpmanager/rtpsource.c | 52 ++++++++++++++----- .../gst/rtpmanager/rtpsource.h | 14 ++--- 5 files changed, 76 insertions(+), 84 deletions(-) diff --git a/subprojects/gst-plugins-good/gst/rtpmanager/gstrtpsession.c b/subprojects/gst-plugins-good/gst/rtpmanager/gstrtpsession.c index f87f78f0d9..3d38e14736 100644 --- a/subprojects/gst-plugins-good/gst/rtpmanager/gstrtpsession.c +++ b/subprojects/gst-plugins-good/gst/rtpmanager/gstrtpsession.c @@ -298,7 +298,7 @@ static GstFlowReturn gst_rtp_session_send_rtcp (RTPSession * sess, RTPSource * src, GstBuffer * buffer, gboolean eos, gpointer user_data); static GstFlowReturn gst_rtp_session_sync_rtcp (RTPSession * sess, GstBuffer * buffer, gpointer user_data); -static gint gst_rtp_session_clock_rate (RTPSession * sess, guint8 payload, +static GstCaps *gst_rtp_session_caps (RTPSession * sess, guint8 payload, gpointer user_data); static void gst_rtp_session_reconsider (RTPSession * sess, gpointer user_data); static void gst_rtp_session_request_key_unit (RTPSession * sess, guint32 ssrc, @@ -328,7 +328,7 @@ static RTPSessionCallbacks callbacks = { gst_rtp_session_send_rtp, gst_rtp_session_sync_rtcp, gst_rtp_session_send_rtcp, - gst_rtp_session_clock_rate, + gst_rtp_session_caps, gst_rtp_session_reconsider, gst_rtp_session_request_key_unit, gst_rtp_session_request_time, @@ -1678,41 +1678,12 @@ no_caps: } /* called when the session manager needs the clock rate */ -static gint -gst_rtp_session_clock_rate (RTPSession * sess, guint8 payload, - gpointer user_data) +static GstCaps * +gst_rtp_session_caps (RTPSession * sess, guint8 payload, gpointer user_data) { - gint result = -1; - GstRtpSession *rtpsession; - GstCaps *caps; - const GstStructure *s; + GstRtpSession *rtpsession = GST_RTP_SESSION_CAST (user_data); - rtpsession = GST_RTP_SESSION_CAST (user_data); - - caps = gst_rtp_session_get_caps_for_pt (rtpsession, payload); - - if (!caps) - goto done; - - s = gst_caps_get_structure (caps, 0); - if (!gst_structure_get_int (s, "clock-rate", &result)) - goto no_clock_rate; - - gst_caps_unref (caps); - - GST_DEBUG_OBJECT (rtpsession, "parsed clock-rate %d", result); - -done: - - return result; - - /* ERRORS */ -no_clock_rate: - { - gst_caps_unref (caps); - GST_DEBUG_OBJECT (rtpsession, "No clock-rate in caps!"); - goto done; - } + return gst_rtp_session_get_caps_for_pt (rtpsession, payload); } /* called when the session manager asks us to reconsider the timeout */ diff --git a/subprojects/gst-plugins-good/gst/rtpmanager/rtpsession.c b/subprojects/gst-plugins-good/gst/rtpmanager/rtpsession.c index 48ef879b3b..7a2042426b 100644 --- a/subprojects/gst-plugins-good/gst/rtpmanager/rtpsession.c +++ b/subprojects/gst-plugins-good/gst/rtpmanager/rtpsession.c @@ -1224,9 +1224,9 @@ rtp_session_set_callbacks (RTPSession * sess, RTPSessionCallbacks * callbacks, sess->callbacks.sync_rtcp = callbacks->sync_rtcp; sess->sync_rtcp_user_data = user_data; } - if (callbacks->clock_rate) { - sess->callbacks.clock_rate = callbacks->clock_rate; - sess->clock_rate_user_data = user_data; + if (callbacks->caps) { + sess->callbacks.caps = callbacks->caps; + sess->caps_user_data = user_data; } if (callbacks->reconsider) { sess->callbacks.reconsider = callbacks->reconsider; @@ -1331,7 +1331,7 @@ rtp_session_set_sync_rtcp_callback (RTPSession * sess, } /** - * rtp_session_set_clock_rate_callback: + * rtp_session_set_caps_callback: * @sess: an #RTPSession * @callback: callback to set * @user_data: user data passed in the callback @@ -1339,13 +1339,13 @@ rtp_session_set_sync_rtcp_callback (RTPSession * sess, * Configure only the clock_rate callback to be notified of the clock_rate action. */ void -rtp_session_set_clock_rate_callback (RTPSession * sess, - RTPSessionClockRate callback, gpointer user_data) +rtp_session_set_caps_callback (RTPSession * sess, + RTPSessionCaps callback, gpointer user_data) { g_return_if_fail (RTP_IS_SESSION (sess)); - sess->callbacks.clock_rate = callback; - sess->clock_rate_user_data = user_data; + sess->callbacks.caps = callback; + sess->caps_user_data = user_data; } /** @@ -1549,30 +1549,26 @@ source_push_rtp (RTPSource * source, gpointer data, RTPSession * session) return result; } -static gint -source_clock_rate (RTPSource * source, guint8 pt, RTPSession * session) +static GstCaps * +source_caps (RTPSource * source, guint8 pt, RTPSession * session) { - gint result; + GstCaps *result = NULL; RTP_SESSION_UNLOCK (session); - if (session->callbacks.clock_rate) - result = - session->callbacks.clock_rate (session, pt, - session->clock_rate_user_data); - else - result = -1; + if (session->callbacks.caps) + result = session->callbacks.caps (session, pt, session->caps_user_data); RTP_SESSION_LOCK (session); - GST_DEBUG ("got clock-rate %d for pt %d", result, pt); + GST_DEBUG ("got caps %" GST_PTR_FORMAT " for pt %d", result, pt); return result; } static RTPSourceCallbacks callbacks = { (RTPSourcePushRTP) source_push_rtp, - (RTPSourceClockRate) source_clock_rate, + (RTPSourceCaps) source_caps, }; @@ -1924,7 +1920,8 @@ obtain_internal_source (RTPSession * sess, guint32 ssrc, gboolean * created, source->validated = TRUE; source->internal = TRUE; - source->probation = FALSE; + source->probation = 0; + source->curr_probation = 0; rtp_source_set_sdes_struct (source, gst_structure_copy (sess->sdes)); rtp_source_set_callbacks (source, &callbacks, sess); diff --git a/subprojects/gst-plugins-good/gst/rtpmanager/rtpsession.h b/subprojects/gst-plugins-good/gst/rtpmanager/rtpsession.h index 0af06d02e4..eb512c78f3 100644 --- a/subprojects/gst-plugins-good/gst/rtpmanager/rtpsession.h +++ b/subprojects/gst-plugins-good/gst/rtpmanager/rtpsession.h @@ -97,16 +97,16 @@ typedef GstFlowReturn (*RTPSessionSendRTCP) (RTPSession *sess, RTPSource *src, G typedef GstFlowReturn (*RTPSessionSyncRTCP) (RTPSession *sess, GstBuffer *buffer, gpointer user_data); /** - * RTPSessionClockRate: + * RTPSessionCaps: * @sess: an #RTPSession * @payload: the payload * @user_data: user data specified when registering * - * This callback will be called when @sess needs the clock-rate of @payload. + * This callback will be called when @sess needs the caps of @payload. * - * Returns: the clock-rate of @pt. + * Returns: the caps of @pt. */ -typedef gint (*RTPSessionClockRate) (RTPSession *sess, guint8 payload, gpointer user_data); +typedef GstCaps * (*RTPSessionCaps) (RTPSession *sess, guint8 payload, gpointer user_data); /** * RTPSessionReconsider: @@ -209,7 +209,7 @@ typedef struct { RTPSessionSendRTP send_rtp; RTPSessionSyncRTCP sync_rtcp; RTPSessionSendRTCP send_rtcp; - RTPSessionClockRate clock_rate; + RTPSessionCaps caps; RTPSessionReconsider reconsider; RTPSessionRequestKeyUnit request_key_unit; RTPSessionRequestTime request_time; @@ -288,7 +288,7 @@ struct _RTPSession { gpointer send_rtp_user_data; gpointer send_rtcp_user_data; gpointer sync_rtcp_user_data; - gpointer clock_rate_user_data; + gpointer caps_user_data; gpointer reconsider_user_data; gpointer request_key_unit_user_data; gpointer request_time_user_data; @@ -375,8 +375,8 @@ void rtp_session_set_send_rtcp_callback (RTPSession * sess, void rtp_session_set_sync_rtcp_callback (RTPSession * sess, RTPSessionSyncRTCP callback, gpointer user_data); -void rtp_session_set_clock_rate_callback (RTPSession * sess, - RTPSessionClockRate callback, +void rtp_session_set_caps_callback (RTPSession * sess, + RTPSessionCaps callback, gpointer user_data); void rtp_session_set_reconsider_callback (RTPSession * sess, RTPSessionReconsider callback, diff --git a/subprojects/gst-plugins-good/gst/rtpmanager/rtpsource.c b/subprojects/gst-plugins-good/gst/rtpmanager/rtpsource.c index 0a0d858c4b..d7f2a015e5 100644 --- a/subprojects/gst-plugins-good/gst/rtpmanager/rtpsource.c +++ b/subprojects/gst-plugins-good/gst/rtpmanager/rtpsource.c @@ -345,7 +345,7 @@ rtp_source_finalize (GObject * object) g_free (src->bye_reason); - gst_caps_replace (&src->send_caps, NULL); + gst_caps_replace (&src->caps, NULL); g_list_free_full (src->conflicting_addresses, (GDestroyNotify) rtp_conflicting_address_free); @@ -649,7 +649,7 @@ rtp_source_set_callbacks (RTPSource * src, RTPSourceCallbacks * cb, g_return_if_fail (RTP_IS_SOURCE (src)); src->callbacks.push_rtp = cb->push_rtp; - src->callbacks.clock_rate = cb->clock_rate; + src->callbacks.caps = cb->caps; src->user_data = user_data; } @@ -829,7 +829,7 @@ rtp_source_update_send_caps (RTPSource * src, GstCaps * caps) gboolean rtx; /* nothing changed, return */ - if (caps == NULL || src->send_caps == caps) + if (caps == NULL || src->caps == caps) return; s = gst_caps_get_structure (caps, 0); @@ -869,7 +869,7 @@ rtp_source_update_send_caps (RTPSource * src, GstCaps * caps) GST_DEBUG ("got %sseqnum-offset %" G_GINT32_FORMAT, rtx ? "rtx " : "", src->seqnum_offset); - gst_caps_replace (&src->send_caps, caps); + gst_caps_replace (&src->caps, caps); if (rtx) { src->media_ssrc = ssrc; @@ -940,7 +940,7 @@ push_packet (RTPSource * src, GstBuffer * buffer) } static void -fetch_clock_rate_from_payload (RTPSource * src, guint8 payload) +fetch_caps_for_payload (RTPSource * src, guint8 payload) { if (src->payload == -1) { /* first payload received, nothing was in the caps, lock on to this payload */ @@ -954,16 +954,40 @@ fetch_clock_rate_from_payload (RTPSource * src, guint8 payload) src->stats.transit = -1; } - if (src->clock_rate == -1) { - gint clock_rate = -1; + if (src->clock_rate == -1 || !src->caps) { + GstCaps *caps = NULL; - if (src->callbacks.clock_rate) - clock_rate = src->callbacks.clock_rate (src, payload, src->user_data); + if (src->callbacks.caps) { + caps = src->callbacks.caps (src, payload, src->user_data); + } - GST_DEBUG ("got clock-rate %d", clock_rate); + GST_DEBUG ("got caps %" GST_PTR_FORMAT, caps); - src->clock_rate = clock_rate; - gst_rtp_packet_rate_ctx_reset (&src->packet_rate_ctx, clock_rate); + if (caps) { + const GstStructure *s; + gint clock_rate = -1; + const gchar *encoding_name; + + s = gst_caps_get_structure (caps, 0); + + if (gst_structure_get_int (s, "clock-rate", &clock_rate)) { + src->clock_rate = clock_rate; + gst_rtp_packet_rate_ctx_reset (&src->packet_rate_ctx, clock_rate); + } else { + GST_DEBUG ("No clock-rate in caps!"); + } + + encoding_name = gst_structure_get_string (s, "encoding-name"); + /* Disable probation for RTX sources as packets will arrive very + * irregularly and waiting for a second packet usually exceeds the + * deadline of the retransmission */ + if (g_strcmp0 (encoding_name, "rtx") == 0) { + src->probation = src->curr_probation = 0; + } + } + + gst_caps_replace (&src->caps, caps); + gst_clear_caps (&caps); } } @@ -1280,7 +1304,7 @@ rtp_source_process_rtp (RTPSource * src, RTPPacketInfo * pinfo) g_return_val_if_fail (RTP_IS_SOURCE (src), GST_FLOW_ERROR); g_return_val_if_fail (pinfo != NULL, GST_FLOW_ERROR); - fetch_clock_rate_from_payload (src, pinfo->pt); + fetch_caps_for_payload (src, pinfo->pt); if (!update_receiver_stats (src, pinfo, TRUE)) return GST_FLOW_OK; @@ -1572,7 +1596,7 @@ rtp_source_get_new_sr (RTPSource * src, guint64 ntpnstime, if (src->clock_rate == -1 && src->pt_set) { GST_INFO ("no clock-rate, getting for pt %u and SSRC %u", src->pt, src->ssrc); - fetch_clock_rate_from_payload (src, src->pt); + fetch_caps_for_payload (src, src->pt); } if (src->clock_rate != -1) { diff --git a/subprojects/gst-plugins-good/gst/rtpmanager/rtpsource.h b/subprojects/gst-plugins-good/gst/rtpmanager/rtpsource.h index e23d53700d..f099e4b792 100644 --- a/subprojects/gst-plugins-good/gst/rtpmanager/rtpsource.h +++ b/subprojects/gst-plugins-good/gst/rtpmanager/rtpsource.h @@ -86,29 +86,29 @@ typedef GstFlowReturn (*RTPSourcePushRTP) (RTPSource *src, gpointer data, gpointer user_data); /** - * RTPSourceClockRate: + * RTPSourceCaps: * @src: an #RTPSource * @payload: a payload type * @user_data: user data specified when registering * - * This callback will be called when @src needs the clock-rate of the + * This callback will be called when @src needs the caps of the * @payload. * - * Returns: a clock-rate for @payload. + * Returns: a caps for @payload. */ -typedef gint (*RTPSourceClockRate) (RTPSource *src, guint8 payload, gpointer user_data); +typedef GstCaps * (*RTPSourceCaps) (RTPSource *src, guint8 payload, gpointer user_data); /** * RTPSourceCallbacks: * @push_rtp: a packet becomes available for handling - * @clock_rate: a clock-rate is requested + * @caps: a caps is requested * @get_time: the current clock time is requested * * Callbacks performed by #RTPSource when actions need to be performed. */ typedef struct { RTPSourcePushRTP push_rtp; - RTPSourceClockRate clock_rate; + RTPSourceCaps caps; } RTPSourceCallbacks; /** @@ -161,7 +161,7 @@ struct _RTPSource { GSocketAddress *rtcp_from; gint payload; - GstCaps *send_caps; + GstCaps *caps; gint clock_rate; gint32 seqnum_offset;