};
#define DEFAULT_INTERNAL_SOURCE NULL
-#define DEFAULT_BANDWIDTH RTP_STATS_BANDWIDTH
-#define DEFAULT_RTCP_FRACTION (RTP_STATS_RTCP_FRACTION * RTP_STATS_BANDWIDTH)
+#define DEFAULT_BANDWIDTH 0.0
+#define DEFAULT_RTCP_FRACTION RTP_STATS_RTCP_FRACTION
#define DEFAULT_RTCP_RR_BANDWIDTH -1
#define DEFAULT_RTCP_RS_BANDWIDTH -1
#define DEFAULT_RTCP_MTU 1400
PROP_RTCP_FEEDBACK_RETENTION_WINDOW,
PROP_RTCP_IMMEDIATE_FEEDBACK_THRESHOLD,
PROP_PROBATION,
- PROP_STATS,
- PROP_LAST
+ PROP_STATS
};
/* update average packet size */
static void
rtp_session_init (RTPSession * sess)
{
+ gint i;
gchar *str;
g_mutex_init (&sess->lock);
sess->key = g_random_int ();
+ sess->mask_idx = 0;
+ sess->mask = 0;
- sess->ssrcs = g_hash_table_new_full (NULL, NULL, NULL,
- (GDestroyNotify) g_object_unref);
+ /* TODO: We currently only use the first hash table but this is the
+ * beginning of an implementation for RFC2762
+ for (i = 0; i < 32; i++) {
+ */
+ for (i = 0; i < 1; i++) {
+ sess->ssrcs[i] =
+ g_hash_table_new_full (NULL, NULL, NULL,
+ (GDestroyNotify) g_object_unref);
+ }
rtp_stats_init_defaults (&sess->stats);
INIT_AVG (sess->stats.avg_rtcp_packet_size, 100);
rtp_session_finalize (GObject * object)
{
RTPSession *sess;
+ gint i;
sess = RTP_SESSION_CAST (object);
g_list_free_full (sess->conflicting_addresses,
(GDestroyNotify) rtp_conflicting_address_free);
- g_hash_table_destroy (sess->ssrcs);
+ /* TODO: Change this again when implementing RFC 2762
+ * for (i = 0; i < 32; i++)
+ */
+ for (i = 0; i < 1; i++)
+ g_hash_table_destroy (sess->ssrcs[i]);
g_mutex_clear (&sess->lock);
RTP_SESSION_LOCK (sess);
/* get number of elements in the table */
- size = g_hash_table_size (sess->ssrcs);
+ size = g_hash_table_size (sess->ssrcs[sess->mask_idx]);
/* create the result value array */
res = g_value_array_new (size);
/* and copy all values into the array */
- g_hash_table_foreach (sess->ssrcs, (GHFunc) copy_source, res);
+ g_hash_table_foreach (sess->ssrcs[sess->mask_idx], (GHFunc) copy_source, res);
RTP_SESSION_UNLOCK (sess);
return res;
*/
data.is_doing_ptp = TRUE;
data.new_addr = NULL;
- g_hash_table_foreach (sess->ssrcs,
+ g_hash_table_foreach (sess->ssrcs[sess->mask_idx],
(GHFunc) compare_rtp_source_addr, (gpointer) & data);
is_doing_rtp_ptp = data.is_doing_ptp;
/* same but about rtcp */
data.is_doing_ptp = TRUE;
data.new_addr = NULL;
- g_hash_table_foreach (sess->ssrcs,
+ g_hash_table_foreach (sess->ssrcs[sess->mask_idx],
(GHFunc) compare_rtcp_source_addr, (gpointer) & data);
is_doing_rtcp_ptp = data.is_doing_ptp;
static void
add_source (RTPSession * sess, RTPSource * src)
{
- g_hash_table_insert (sess->ssrcs, GINT_TO_POINTER (src->ssrc), src);
+ g_hash_table_insert (sess->ssrcs[sess->mask_idx],
+ GINT_TO_POINTER (src->ssrc), src);
/* report the new source ASAP */
src->generation = sess->generation;
/* we have one more source now */
static RTPSource *
find_source (RTPSession * sess, guint32 ssrc)
{
- return g_hash_table_lookup (sess->ssrcs, GINT_TO_POINTER (ssrc));
+ return g_hash_table_lookup (sess->ssrcs[sess->mask_idx],
+ GINT_TO_POINTER (ssrc));
}
/* must be called with the session lock, the returned source needs to be
"RTT (%" GST_TIME_FORMAT " < %" GST_TIME_FORMAT ")",
fir ? "FIR" : "PLI",
GST_TIME_ARGS (current_time - sess->last_keyframe_request),
- GST_TIME_ARGS (round_trip_in_ns));;
+ GST_TIME_ARGS (round_trip_in_ns));
return FALSE;
}
}
return;
rtp_session_request_local_key_unit (sess, src, FALSE, current_time);
+
+ src->stats.recv_pli_count++;
}
static void
if (sess->stats.sender_sources > sess->stats.internal_sender_sources + 1)
return;
- g_hash_table_iter_init (&iter, sess->ssrcs);
+ g_hash_table_iter_init (&iter, sess->ssrcs[sess->mask_idx]);
while (g_hash_table_iter_next (&iter, NULL, (gpointer *) & src)) {
if (!src->internal && rtp_source_is_sender (src))
break;
return;
rtp_session_request_local_key_unit (sess, src, TRUE, current_time);
+ src->stats.recv_fir_count++;
}
static void
rtp_source_update_caps (source, caps);
g_object_unref (source);
}
+
+ if (gst_structure_get_uint (s, "rtx-ssrc", &ssrc)) {
+ source =
+ obtain_internal_source (sess, ssrc, &created, GST_CLOCK_TIME_NONE);
+ if (source) {
+ rtp_source_update_caps (source, caps);
+ g_object_unref (source);
+ }
+ }
RTP_SESSION_UNLOCK (sess);
}
}
/* If it is <= 0, then try to estimate the actual bandwidth */
bandwidth = 0;
- g_hash_table_foreach (sess->ssrcs, (GHFunc) add_bitrates, &bandwidth);
- bandwidth /= 8.0;
+ g_hash_table_foreach (sess->ssrcs[sess->mask_idx],
+ (GHFunc) add_bitrates, &bandwidth);
}
- if (bandwidth < 8000)
+ if (bandwidth < RTP_STATS_BANDWIDTH)
bandwidth = RTP_STATS_BANDWIDTH;
rtp_stats_set_bandwidths (&sess->stats, bandwidth,
g_return_if_fail (RTP_IS_SESSION (sess));
RTP_SESSION_LOCK (sess);
- g_hash_table_foreach (sess->ssrcs,
+ g_hash_table_foreach (sess->ssrcs[sess->mask_idx],
(GHFunc) source_mark_bye, (gpointer) reason);
RTP_SESSION_UNLOCK (sess);
}
fci_data[1] = fci_data[2] = fci_data[3] = 0;
source->send_fir = FALSE;
+ source->stats.sent_fir_count++;
}
static void
gst_rtcp_packet_fb_set_sender_ssrc (packet, data->source->ssrc);
gst_rtcp_packet_fb_set_media_ssrc (packet, 0);
- g_hash_table_foreach (sess->ssrcs, (GHFunc) session_add_fir, data);
+ g_hash_table_foreach (sess->ssrcs[sess->mask_idx],
+ (GHFunc) session_add_fir, data);
if (gst_rtcp_packet_fb_get_fci_length (packet) == 0)
gst_rtcp_packet_remove (packet);
source->send_pli = FALSE;
data->may_suppress = FALSE;
+
+ source->stats.sent_pli_count++;
}
/* construct NACK */
} else if (!data->is_early) {
/* loop over all known sources and add report blocks. If we are early, we
* just make a minimal RTCP packet and skip this step */
- g_hash_table_foreach (sess->ssrcs, (GHFunc) session_report_blocks, data);
+ g_hash_table_foreach (sess->ssrcs[sess->mask_idx],
+ (GHFunc) session_report_blocks, data);
}
if (!data->has_sdes)
session_sdes (sess, data);
session_fir (sess, data);
if (data->have_pli)
- g_hash_table_foreach (sess->ssrcs, (GHFunc) session_pli, data);
+ g_hash_table_foreach (sess->ssrcs[sess->mask_idx],
+ (GHFunc) session_pli, data);
if (data->have_nack)
- g_hash_table_foreach (sess->ssrcs, (GHFunc) session_nack, data);
+ g_hash_table_foreach (sess->ssrcs[sess->mask_idx],
+ (GHFunc) session_nack, data);
gst_rtcp_buffer_unmap (&data->rtcpbuf);
* cleanup stage below releases the session lock. */
table_copy = g_hash_table_new_full (NULL, NULL, NULL,
(GDestroyNotify) g_object_unref);
- g_hash_table_foreach (sess->ssrcs,
+ g_hash_table_foreach (sess->ssrcs[sess->mask_idx],
(GHFunc) clone_ssrcs_hashtable, table_copy);
/* Clean up the session, mark the source for removing, this might release the
g_hash_table_destroy (table_copy);
/* Now remove the marked sources */
- g_hash_table_foreach_remove (sess->ssrcs,
+ g_hash_table_foreach_remove (sess->ssrcs[sess->mask_idx],
(GHRFunc) remove_closing_sources, &data);
/* update point-to-point status */
sess->generation, data.num_to_report, data.is_early);
/* generate RTCP for all internal sources */
- g_hash_table_foreach (sess->ssrcs, (GHFunc) generate_rtcp, &data);
+ g_hash_table_foreach (sess->ssrcs[sess->mask_idx],
+ (GHFunc) generate_rtcp, &data);
/* update the generation for all the sources that have been reported */
- g_hash_table_foreach (sess->ssrcs, (GHFunc) update_generation, &data);
+ g_hash_table_foreach (sess->ssrcs[sess->mask_idx],
+ (GHFunc) update_generation, &data);
/* we keep track of the last report time in order to timeout inactive
* receivers or senders */
GST_TIME_ARGS (sess->next_rtcp_check_time));
ret = TRUE;
} else {
+ GST_LOG_OBJECT (sess,
+ "can't allow early feedback, next scheduled time is too late %"
+ GST_TIME_FORMAT " + %" GST_TIME_FORMAT " < %" GST_TIME_FORMAT,
+ GST_TIME_ARGS (current_time), GST_TIME_ARGS (max_delay),
+ GST_TIME_ARGS (sess->next_rtcp_check_time));
ret = FALSE;
}
goto end;
/* RFC 4585 section 3.5.2 step 3 */
if (current_time + T_dither_max > sess->next_rtcp_check_time) {
- GST_LOG_OBJECT (sess, "don't send because of dither");
- ret = FALSE;
+ GST_LOG_OBJECT (sess,
+ "don't send because of dither, next scheduled time is soon %"
+ GST_TIME_FORMAT " + %" GST_TIME_FORMAT " > %" GST_TIME_FORMAT,
+ GST_TIME_ARGS (current_time), GST_TIME_ARGS (T_dither_max),
+ GST_TIME_ARGS (sess->next_rtcp_check_time));
+ ret = TRUE;
goto end;
}
GST_TIME_ARGS (sess->next_rtcp_check_time));
ret = TRUE;
} else {
- GST_LOG_OBJECT (sess, "can't allow early feedback");
+ GST_LOG_OBJECT (sess,
+ "can't allow early feedback, next scheduled time is too late %"
+ GST_TIME_FORMAT " + %" GST_TIME_FORMAT " < %" GST_TIME_FORMAT,
+ GST_TIME_ARGS (current_time), GST_TIME_ARGS (max_delay),
+ GST_TIME_ARGS (sess->next_rtcp_check_time));
ret = FALSE;
}
goto end;
sess->next_rtcp_check_time = sess->last_rtcp_send_time + 2 * T_rr;
sess->last_rtcp_send_time += T_rr;
- GST_LOG_OBJECT (sess, "next early RTCP time %" GST_TIME_FORMAT,
- GST_TIME_ARGS (sess->next_early_rtcp_time));
+ GST_LOG_OBJECT (sess, "next early RTCP time %" GST_TIME_FORMAT
+ ", next regular RTCP time %" GST_TIME_FORMAT,
+ GST_TIME_ARGS (sess->next_early_rtcp_time),
+ GST_TIME_ARGS (sess->next_rtcp_check_time));
RTP_SESSION_UNLOCK (sess);
/* notify app of need to send packet early