mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-10-03 01:02:19 +00:00
session: handle partial RTCP report blocks
When we have more SSRCs to report than what fit in an RTCP packet, use a generation counter to make sure all of them end up in a packet eventually.
This commit is contained in:
parent
6cce6fb04c
commit
e0abd2e9b5
3 changed files with 35 additions and 4 deletions
|
@ -1289,6 +1289,8 @@ add_source (RTPSession * sess, RTPSource * src)
|
||||||
{
|
{
|
||||||
g_hash_table_insert (sess->ssrcs[sess->mask_idx],
|
g_hash_table_insert (sess->ssrcs[sess->mask_idx],
|
||||||
GINT_TO_POINTER (src->ssrc), src);
|
GINT_TO_POINTER (src->ssrc), src);
|
||||||
|
/* report the new source ASAP */
|
||||||
|
src->generation = sess->generation;
|
||||||
/* we have one more source now */
|
/* we have one more source now */
|
||||||
sess->total_sources++;
|
sess->total_sources++;
|
||||||
if (RTP_SOURCE_IS_ACTIVE (src))
|
if (RTP_SOURCE_IS_ACTIVE (src))
|
||||||
|
@ -2744,6 +2746,7 @@ typedef struct
|
||||||
GstRTCPBuffer rtcpbuf;
|
GstRTCPBuffer rtcpbuf;
|
||||||
RTPSession *sess;
|
RTPSession *sess;
|
||||||
RTPSource *source;
|
RTPSource *source;
|
||||||
|
guint num_to_report;
|
||||||
GstBuffer *rtcp;
|
GstBuffer *rtcp;
|
||||||
GstClockTime current_time;
|
GstClockTime current_time;
|
||||||
guint64 ntpnstime;
|
guint64 ntpnstime;
|
||||||
|
@ -2799,15 +2802,23 @@ session_start_rtcp (RTPSession * sess, ReportData * data)
|
||||||
static void
|
static void
|
||||||
session_report_blocks (const gchar * key, RTPSource * source, ReportData * data)
|
session_report_blocks (const gchar * key, RTPSource * source, ReportData * data)
|
||||||
{
|
{
|
||||||
|
RTPSession *sess = data->sess;
|
||||||
GstRTCPPacket *packet = &data->packet;
|
GstRTCPPacket *packet = &data->packet;
|
||||||
guint8 fractionlost;
|
guint8 fractionlost;
|
||||||
gint32 packetslost;
|
gint32 packetslost;
|
||||||
guint32 exthighestseq, jitter;
|
guint32 exthighestseq, jitter;
|
||||||
guint32 lsr, dlsr;
|
guint32 lsr, dlsr;
|
||||||
|
|
||||||
|
/* don't report for sources in future generations */
|
||||||
|
if (((gint16) (source->generation - sess->generation)) > 0) {
|
||||||
|
GST_DEBUG ("source %08x generation %u > %u", source->ssrc,
|
||||||
|
source->generation, sess->generation);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
/* only report about other sender */
|
/* only report about other sender */
|
||||||
if (source == data->source)
|
if (source == data->source)
|
||||||
return;
|
goto reported;
|
||||||
|
|
||||||
if (gst_rtcp_packet_get_rb_count (packet) == GST_RTCP_MAX_RB_COUNT) {
|
if (gst_rtcp_packet_get_rb_count (packet) == GST_RTCP_MAX_RB_COUNT) {
|
||||||
GST_DEBUG ("max RB count reached");
|
GST_DEBUG ("max RB count reached");
|
||||||
|
@ -2816,7 +2827,7 @@ session_report_blocks (const gchar * key, RTPSource * source, ReportData * data)
|
||||||
|
|
||||||
if (!RTP_SOURCE_IS_SENDER (source)) {
|
if (!RTP_SOURCE_IS_SENDER (source)) {
|
||||||
GST_DEBUG ("source %08x not sender", source->ssrc);
|
GST_DEBUG ("source %08x not sender", source->ssrc);
|
||||||
return;
|
goto reported;
|
||||||
}
|
}
|
||||||
|
|
||||||
GST_DEBUG ("create RB for SSRC %08x", source->ssrc);
|
GST_DEBUG ("create RB for SSRC %08x", source->ssrc);
|
||||||
|
@ -2837,6 +2848,16 @@ session_report_blocks (const gchar * key, RTPSource * source, ReportData * data)
|
||||||
/* packet is not yet filled, add report block for this source. */
|
/* packet is not yet filled, add report block for this source. */
|
||||||
gst_rtcp_packet_add_rb (packet, source->ssrc, fractionlost, packetslost,
|
gst_rtcp_packet_add_rb (packet, source->ssrc, fractionlost, packetslost,
|
||||||
exthighestseq, jitter, lsr, dlsr);
|
exthighestseq, jitter, lsr, dlsr);
|
||||||
|
|
||||||
|
reported:
|
||||||
|
/* source is reported, move to next generation */
|
||||||
|
source->generation = sess->generation + 1;
|
||||||
|
|
||||||
|
/* if we reported all sources in this generation, move to next */
|
||||||
|
if (--data->num_to_report == 0) {
|
||||||
|
sess->generation++;
|
||||||
|
GST_DEBUG ("all reported, generation now %u", sess->generation);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* perform cleanup of sources that timed out */
|
/* perform cleanup of sources that timed out */
|
||||||
|
@ -2851,6 +2872,8 @@ session_cleanup (const gchar * key, RTPSource * source, ReportData * data)
|
||||||
GstClockTime interval, binterval;
|
GstClockTime interval, binterval;
|
||||||
GstClockTime btime;
|
GstClockTime btime;
|
||||||
|
|
||||||
|
GST_DEBUG ("look at %08x, generation %u", source->ssrc, source->generation);
|
||||||
|
|
||||||
/* check for outdated collisions */
|
/* check for outdated collisions */
|
||||||
if (source->internal) {
|
if (source->internal) {
|
||||||
GST_DEBUG ("Timing out collisions for %x", source->ssrc);
|
GST_DEBUG ("Timing out collisions for %x", source->ssrc);
|
||||||
|
@ -2963,8 +2986,10 @@ session_cleanup (const gchar * key, RTPSource * source, ReportData * data)
|
||||||
|
|
||||||
on_sender_timeout (sess, source);
|
on_sender_timeout (sess, source);
|
||||||
}
|
}
|
||||||
|
/* count how many source to report in this generation */
|
||||||
|
if (((gint16) (source->generation - sess->generation)) <= 0)
|
||||||
|
data->num_to_report++;
|
||||||
}
|
}
|
||||||
|
|
||||||
source->closing = remove;
|
source->closing = remove;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3166,7 +3191,7 @@ generate_rtcp (const gchar * key, RTPSource * source, ReportData * data)
|
||||||
make_source_bye (sess, source, data);
|
make_source_bye (sess, source, data);
|
||||||
is_bye = TRUE;
|
is_bye = TRUE;
|
||||||
} else if (!data->is_early) {
|
} else if (!data->is_early) {
|
||||||
/* loop over all known sources and add report blocks. If we are ealy, we
|
/* loop over all known sources and add report blocks. If we are early, we
|
||||||
* just make a minimal RTCP packet and skip this step */
|
* just make a minimal RTCP packet and skip this step */
|
||||||
g_hash_table_foreach (sess->ssrcs[sess->mask_idx],
|
g_hash_table_foreach (sess->ssrcs[sess->mask_idx],
|
||||||
(GHFunc) session_report_blocks, data);
|
(GHFunc) session_report_blocks, data);
|
||||||
|
@ -3221,6 +3246,7 @@ rtp_session_on_timeout (RTPSession * sess, GstClockTime current_time,
|
||||||
data.current_time = current_time;
|
data.current_time = current_time;
|
||||||
data.ntpnstime = ntpnstime;
|
data.ntpnstime = ntpnstime;
|
||||||
data.running_time = running_time;
|
data.running_time = running_time;
|
||||||
|
data.num_to_report = 0;
|
||||||
data.may_suppress = FALSE;
|
data.may_suppress = FALSE;
|
||||||
g_queue_init (&data.output);
|
g_queue_init (&data.output);
|
||||||
|
|
||||||
|
@ -3257,6 +3283,9 @@ rtp_session_on_timeout (RTPSession * sess, GstClockTime current_time,
|
||||||
if (!is_rtcp_time (sess, current_time, &data))
|
if (!is_rtcp_time (sess, current_time, &data))
|
||||||
goto done;
|
goto done;
|
||||||
|
|
||||||
|
GST_DEBUG ("doing RTCP generation %u for %u sources", sess->generation,
|
||||||
|
data.num_to_report);
|
||||||
|
|
||||||
/* generate RTCP for all internal sources */
|
/* generate RTCP for all internal sources */
|
||||||
g_hash_table_foreach (sess->ssrcs[sess->mask_idx],
|
g_hash_table_foreach (sess->ssrcs[sess->mask_idx],
|
||||||
(GHFunc) generate_rtcp, &data);
|
(GHFunc) generate_rtcp, &data);
|
||||||
|
|
|
@ -207,6 +207,7 @@ struct _RTPSession {
|
||||||
GHashTable *ssrcs[32];
|
GHashTable *ssrcs[32];
|
||||||
guint total_sources;
|
guint total_sources;
|
||||||
|
|
||||||
|
guint16 generation;
|
||||||
GstClockTime next_rtcp_check_time;
|
GstClockTime next_rtcp_check_time;
|
||||||
GstClockTime last_rtcp_send_time;
|
GstClockTime last_rtcp_send_time;
|
||||||
GstClockTime start_time;
|
GstClockTime start_time;
|
||||||
|
|
|
@ -135,6 +135,7 @@ struct _RTPSource {
|
||||||
/*< private >*/
|
/*< private >*/
|
||||||
guint32 ssrc;
|
guint32 ssrc;
|
||||||
|
|
||||||
|
guint16 generation;
|
||||||
guint probation;
|
guint probation;
|
||||||
guint curr_probation;
|
guint curr_probation;
|
||||||
gboolean validated;
|
gboolean validated;
|
||||||
|
|
Loading…
Reference in a new issue