[Pkg-voip-commits] [janus] 263/282: Handle RTCP for all remote SSRCs, including video simulcast
Jonas Smedegaard
dr at jones.dk
Wed Dec 20 21:53:47 UTC 2017
This is an automated email from the git hooks/post-receive script.
js pushed a commit to annotated tag debian/0.2.6-1
in repository janus.
commit 05449073c9c4955425e7c144af13e1bba8ce8db5
Author: Lorenzo Miniero <lminiero at gmail.com>
Date: Fri Dec 15 19:17:53 2017 +0100
Handle RTCP for all remote SSRCs, including video simulcast
---
dtls.c | 4 +-
ice.c | 337 ++++++++++++++++++++++++++++++++--------------------------------
ice.h | 69 ++++++-------
janus.c | 167 ++++++++++++++++++--------------
rtcp.c | 12 +--
sdp.c | 36 ++++---
6 files changed, 325 insertions(+), 300 deletions(-)
diff --git a/dtls.c b/dtls.c
index 25a5aa1..8204066 100644
--- a/dtls.c
+++ b/dtls.c
@@ -872,8 +872,8 @@ void janus_dtls_fd_bridge(janus_dtls_srtp *dtls) {
/* Update stats (TODO Do the same for the last second window as well)
* FIXME: the Data stats includes the bytes used for the handshake */
if(bytes > 0) {
- component->out_stats.data_packets++;
- component->out_stats.data_bytes += bytes;
+ component->out_stats.data.packets++;
+ component->out_stats.data.bytes += bytes;
}
/* Check if there's anything left to send (e.g., fragmented packets) */
pending = BIO_ctrl_pending(dtls->filter_bio);
diff --git a/ice.c b/ice.c
index 42c69cd..6edba7b 100644
--- a/ice.c
+++ b/ice.c
@@ -988,25 +988,17 @@ static void janus_ice_stats_queue_free(gpointer data) {
void janus_ice_stats_reset(janus_ice_stats *stats) {
if(stats == NULL)
return;
- stats->audio_packets = 0;
- stats->audio_bytes = 0;
- if(stats->audio_bytes_lastsec)
- g_queue_free_full(stats->audio_bytes_lastsec, &janus_ice_stats_queue_free);
- stats->audio_bytes_lastsec = NULL;
- stats->audio_notified_lastsec = FALSE;
- stats->audio_nacks = 0;
- stats->video_packets = 0;
- stats->video_bytes = 0;
- if(stats->video_bytes_lastsec)
- g_queue_free_full(stats->video_bytes_lastsec, &janus_ice_stats_queue_free);
- stats->video_bytes_lastsec = NULL;
- stats->video_notified_lastsec = FALSE;
- stats->video_nacks = 0;
- stats->data_packets = 0;
- stats->data_bytes = 0;
- stats->last_slowlink_time = 0;
- stats->sl_nack_period_ts = 0;
- stats->sl_nack_recent_cnt = 0;
+ if(stats->audio.bytes_lastsec)
+ g_queue_free_full(stats->audio.bytes_lastsec, &janus_ice_stats_queue_free);
+ if(stats->video[0].bytes_lastsec)
+ g_queue_free_full(stats->video[0].bytes_lastsec, &janus_ice_stats_queue_free);
+ if(stats->video[1].bytes_lastsec)
+ g_queue_free_full(stats->video[1].bytes_lastsec, &janus_ice_stats_queue_free);
+ if(stats->video[2].bytes_lastsec)
+ g_queue_free_full(stats->video[2].bytes_lastsec, &janus_ice_stats_queue_free);
+ if(stats->data.bytes_lastsec)
+ g_queue_free_full(stats->data.bytes_lastsec, &janus_ice_stats_queue_free);
+ memset(stats, 0, sizeof(*stats));
}
@@ -1390,12 +1382,20 @@ void janus_ice_stream_free(GHashTable *streams, janus_ice_stream *stream) {
stream->video_payload_types = NULL;
g_free(stream->audio_rtcp_ctx);
stream->audio_rtcp_ctx = NULL;
- g_free(stream->video_rtcp_ctx);
- stream->video_rtcp_ctx = NULL;
+ g_free(stream->video_rtcp_ctx[0]);
+ stream->video_rtcp_ctx[0] = NULL;
+ g_free(stream->video_rtcp_ctx[1]);
+ stream->video_rtcp_ctx[1] = NULL;
+ g_free(stream->video_rtcp_ctx[2]);
+ stream->video_rtcp_ctx[2] = NULL;
stream->audio_first_ntp_ts = 0;
stream->audio_first_rtp_ts = 0;
- stream->video_first_ntp_ts = 0;
- stream->video_first_rtp_ts = 0;
+ stream->video_first_ntp_ts[0] = 0;
+ stream->video_first_ntp_ts[1] = 0;
+ stream->video_first_ntp_ts[2] = 0;
+ stream->video_first_rtp_ts[0] = 0;
+ stream->video_first_rtp_ts[1] = 0;
+ stream->video_first_rtp_ts[2] = 0;
stream->audio_last_ts = 0;
stream->video_last_ts = 0;
g_free(stream);
@@ -1482,8 +1482,12 @@ void janus_ice_component_free(GHashTable *components, janus_ice_component *compo
component->selected_pair = NULL;
if(component->last_seqs_audio)
janus_seq_list_free(&component->last_seqs_audio);
- if(component->last_seqs_video)
- janus_seq_list_free(&component->last_seqs_video);
+ if(component->last_seqs_video[0])
+ janus_seq_list_free(&component->last_seqs_video[0]);
+ if(component->last_seqs_video[1])
+ janus_seq_list_free(&component->last_seqs_video[1]);
+ if(component->last_seqs_video[2])
+ janus_seq_list_free(&component->last_seqs_video[2]);
janus_ice_stats_reset(&component->in_stats);
janus_ice_stats_reset(&component->out_stats);
g_free(component);
@@ -2006,8 +2010,8 @@ static void janus_ice_cb_nice_recv(NiceAgent *agent, guint stream_id, guint comp
JANUS_LOG(LOG_HUGE, "[%"SCNu64"] Looks like DTLS!\n", handle->handle_id);
janus_dtls_srtp_incoming_msg(component->dtls, buf, len);
/* Update stats (TODO Do the same for the last second window as well) */
- component->in_stats.data_packets++;
- component->in_stats.data_bytes += len;
+ component->in_stats.data.packets++;
+ component->in_stats.data.bytes += len;
return;
}
/* Not DTLS... RTP or RTCP? (http://tools.ietf.org/html/rfc5761#section-4) */
@@ -2023,19 +2027,19 @@ static void janus_ice_cb_nice_recv(NiceAgent *agent, guint stream_id, guint comp
janus_rtp_header *header = (janus_rtp_header *)buf;
guint32 packet_ssrc = ntohl(header->ssrc);
/* Is this audio or video? */
- int video = 0;
+ int video = 0, vindex = 0;
if(!janus_flags_is_set(&handle->webrtc_flags, JANUS_ICE_HANDLE_WEBRTC_BUNDLE)) {
/* Easy enough */
video = (stream->stream_id == handle->video_id ? 1 : 0);
} else {
/* Bundled streams, check SSRC */
- video = ((stream->video_ssrc_peer == packet_ssrc
+ video = ((stream->video_ssrc_peer[0] == packet_ssrc
|| stream->video_ssrc_peer_rtx == packet_ssrc
- || stream->video_ssrc_peer_sim_1 == packet_ssrc
- || stream->video_ssrc_peer_sim_2 == packet_ssrc) ? 1 : 0);
+ || stream->video_ssrc_peer[1] == packet_ssrc
+ || stream->video_ssrc_peer[2] == packet_ssrc) ? 1 : 0);
if(!video && stream->audio_ssrc_peer != packet_ssrc) {
/* FIXME In case it happens, we should check what it is */
- if(stream->audio_ssrc_peer == 0 || stream->video_ssrc_peer == 0) {
+ if(stream->audio_ssrc_peer == 0 || stream->video_ssrc_peer[0] == 0) {
/* Apparently we were not told the peer SSRCs, try to guess from the payload type */
gboolean found = FALSE;
guint16 pt = header->type;
@@ -2053,14 +2057,14 @@ static void janus_ice_cb_nice_recv(NiceAgent *agent, guint stream_id, guint comp
pts = pts->next;
}
}
- if(!found && stream->video_ssrc_peer == 0 && stream->video_payload_types) {
+ if(!found && stream->video_ssrc_peer[0] == 0 && stream->video_payload_types) {
GList *pts = stream->video_payload_types;
while(pts) {
guint16 video_pt = GPOINTER_TO_UINT(pts->data);
if(pt == video_pt) {
JANUS_LOG(LOG_VERB, "[%"SCNu64"] Unadvertized SSRC (%"SCNu32") is video! (payload type %"SCNu16")\n", handle->handle_id, packet_ssrc, pt);
video = 1;
- stream->video_ssrc_peer = packet_ssrc;
+ stream->video_ssrc_peer[0] = packet_ssrc;
found = TRUE;
break;
}
@@ -2073,19 +2077,22 @@ static void janus_ice_cb_nice_recv(NiceAgent *agent, guint stream_id, guint comp
return;
}
}
+ }
+ if(video) {
if(stream->video_ssrc_peer_rtx == packet_ssrc) {
- /* FIXME This is a video retransmission: set the regular peer SSRC so
- * that we avoid outgoing SRTP errors in case we got the packet already */
- header->ssrc = htonl(stream->video_ssrc_peer);
- } else if(stream->video_ssrc_peer_sim_1 == packet_ssrc) {
+ /* FIXME This is a video retransmission using RFC4588, but we don't support it yet,
+ * see https://tools.ietf.org/html/rfc4588#section-4 */
+ JANUS_LOG(LOG_WARN, "[%"SCNu64"] RFC4588 rtx packet, dropping (SSRC %"SCNu32")...\n", handle->handle_id, packet_ssrc);
+ return;
+ } else if(stream->video_ssrc_peer[1] == packet_ssrc) {
/* FIXME Simulcast (1) */
JANUS_LOG(LOG_HUGE, "[%"SCNu64"] Simulcast #1 (SSRC %"SCNu32")...\n", handle->handle_id, packet_ssrc);
- } else if(stream->video_ssrc_peer_sim_2 == packet_ssrc) {
+ vindex = 1;
+ } else if(stream->video_ssrc_peer[2] == packet_ssrc) {
/* FIXME Simulcast (2) */
JANUS_LOG(LOG_HUGE, "[%"SCNu64"] Simulcast #2 (SSRC %"SCNu32")...\n", handle->handle_id, packet_ssrc);
+ vindex = 2;
}
- //~ JANUS_LOG(LOG_VERB, "[RTP] Bundling: this is %s (video=%"SCNu64", audio=%"SCNu64", got %ld)\n",
- //~ video ? "video" : "audio", stream->video_ssrc_peer, stream->audio_ssrc_peer, ntohl(header->ssrc));
}
int buflen = len;
@@ -2100,9 +2107,9 @@ static void janus_ice_cb_nice_recv(NiceAgent *agent, guint stream_id, guint comp
}
} else {
if(video) {
- if(stream->video_ssrc_peer == 0) {
- stream->video_ssrc_peer = ntohl(header->ssrc);
- JANUS_LOG(LOG_VERB, "[%"SCNu64"] Peer video SSRC: %u\n", handle->handle_id, stream->video_ssrc_peer);
+ if(stream->video_ssrc_peer[0] == 0) {
+ stream->video_ssrc_peer[0] = ntohl(header->ssrc);
+ JANUS_LOG(LOG_VERB, "[%"SCNu64"] Peer video SSRC: %u\n", handle->handle_id, stream->video_ssrc_peer[0]);
}
} else {
if(stream->audio_ssrc_peer == 0) {
@@ -2126,45 +2133,41 @@ static void janus_ice_cb_nice_recv(NiceAgent *agent, guint stream_id, guint comp
s->when = janus_get_monotonic_time();
janus_mutex_lock(&component->mutex);
if(!video) {
- if(component->in_stats.audio_bytes == 0 || component->in_stats.audio_notified_lastsec) {
+ if(component->in_stats.audio.bytes == 0 || component->in_stats.audio.notified_lastsec) {
/* We either received our first audio packet, or we started receiving it again after missing more than a second */
- component->in_stats.audio_notified_lastsec = FALSE;
+ component->in_stats.audio.notified_lastsec = FALSE;
janus_ice_notify_media(handle, FALSE, TRUE);
}
- component->in_stats.audio_packets++;
- component->in_stats.audio_bytes += buflen;
- if(component->in_stats.audio_bytes_lastsec == NULL)
- component->in_stats.audio_bytes_lastsec = g_queue_new();
- g_queue_push_tail(component->in_stats.audio_bytes_lastsec, s);
- if(g_queue_get_length(component->in_stats.audio_bytes_lastsec) > 100) {
- s = (janus_ice_stats_item *)g_queue_pop_head(component->in_stats.audio_bytes_lastsec);
+ component->in_stats.audio.packets++;
+ component->in_stats.audio.bytes += buflen;
+ if(component->in_stats.audio.bytes_lastsec == NULL)
+ component->in_stats.audio.bytes_lastsec = g_queue_new();
+ g_queue_push_tail(component->in_stats.audio.bytes_lastsec, s);
+ if(g_queue_get_length(component->in_stats.audio.bytes_lastsec) > 100) {
+ s = (janus_ice_stats_item *)g_queue_pop_head(component->in_stats.audio.bytes_lastsec);
g_free(s);
}
} else {
- if(component->in_stats.video_bytes == 0 || component->in_stats.video_notified_lastsec) {
+ if(component->in_stats.video[vindex].bytes == 0 || component->in_stats.video[vindex].notified_lastsec) {
/* We either received our first video packet, or we started receiving it again after missing more than a second */
- component->in_stats.video_notified_lastsec = FALSE;
+ component->in_stats.video[vindex].notified_lastsec = FALSE;
janus_ice_notify_media(handle, TRUE, TRUE);
}
- component->in_stats.video_packets++;
- component->in_stats.video_bytes += buflen;
- if(component->in_stats.video_bytes_lastsec == NULL)
- component->in_stats.video_bytes_lastsec = g_queue_new();
- g_queue_push_tail(component->in_stats.video_bytes_lastsec, s);
- if(g_queue_get_length(component->in_stats.video_bytes_lastsec) > 100) {
- s = (janus_ice_stats_item *)g_queue_pop_head(component->in_stats.video_bytes_lastsec);
+ component->in_stats.video[vindex].packets++;
+ component->in_stats.video[vindex].bytes += buflen;
+ if(component->in_stats.video[vindex].bytes_lastsec == NULL)
+ component->in_stats.video[vindex].bytes_lastsec = g_queue_new();
+ g_queue_push_tail(component->in_stats.video[vindex].bytes_lastsec, s);
+ if(g_queue_get_length(component->in_stats.video[vindex].bytes_lastsec) > 100) {
+ s = (janus_ice_stats_item *)g_queue_pop_head(component->in_stats.video[vindex].bytes_lastsec);
g_free(s);
}
}
janus_mutex_unlock(&component->mutex);
}
- /* FIXME Don't handle RTCP or stats for the simulcasted SSRCs, for now */
- if(video && packet_ssrc != stream->video_ssrc_peer)
- return;
-
/* Update the RTCP context as well */
- rtcp_context *rtcp_ctx = video ? stream->video_rtcp_ctx : stream->audio_rtcp_ctx;
+ rtcp_context *rtcp_ctx = video ? stream->video_rtcp_ctx[vindex] : stream->audio_rtcp_ctx;
janus_rtcp_process_incoming_rtp(rtcp_ctx, buf, buflen);
/* Keep track of RTP sequence numbers, in case we need to NACK them */
@@ -2177,7 +2180,7 @@ static void janus_ice_cb_nice_recv(NiceAgent *agent, guint stream_id, guint comp
guint16 cur_seqn;
int last_seqs_len = 0;
janus_mutex_lock(&component->mutex);
- janus_seq_info **last_seqs = video ? &component->last_seqs_video : &component->last_seqs_audio;
+ janus_seq_info **last_seqs = video ? &component->last_seqs_video[vindex] : &component->last_seqs_audio;
janus_seq_info *cur_seq = *last_seqs;
if(cur_seq) {
cur_seq = cur_seq->prev;
@@ -2189,8 +2192,8 @@ static void janus_ice_cb_nice_recv(NiceAgent *agent, guint stream_id, guint comp
if(!janus_seq_in_range(new_seqn, cur_seqn, LAST_SEQS_MAX_LEN) &&
!janus_seq_in_range(cur_seqn, new_seqn, 1000)) {
/* Jump too big, start fresh */
- JANUS_LOG(LOG_WARN, "[%"SCNu64"] Big sequence number jump %hu -> %hu (%s stream)\n",
- handle->handle_id, cur_seqn, new_seqn, video ? "video" : "audio");
+ JANUS_LOG(LOG_WARN, "[%"SCNu64"] Big sequence number jump %hu -> %hu (%s stream #%d)\n",
+ handle->handle_id, cur_seqn, new_seqn, video ? "video" : "audio", vindex);
janus_seq_list_free(last_seqs);
cur_seq = NULL;
cur_seqn = new_seqn - (guint16)1;
@@ -2251,9 +2254,9 @@ static void janus_ice_cb_nice_recv(NiceAgent *agent, guint stream_id, guint comp
/* Update stats */
component->nack_sent_recent_cnt += nacks_count;
if(video) {
- component->out_stats.video_nacks += nacks_count;
+ component->out_stats.video[vindex].nacks += nacks_count;
} else {
- component->out_stats.audio_nacks += nacks_count;
+ component->out_stats.audio.nacks += nacks_count;
}
/* Inform the plugin about the slow downlink in case it's needed */
janus_slow_link_update(component, handle, nacks_count, video, 0, now);
@@ -2295,7 +2298,7 @@ static void janus_ice_cb_nice_recv(NiceAgent *agent, guint stream_id, guint comp
JANUS_LOG(LOG_VERB, "[%"SCNu64"] Got RTCP BYE on stream %"SCNu16" (component %"SCNu16")\n", handle->handle_id, stream->stream_id, component->component_id);
}
/* Is this audio or video? */
- int video = 0;
+ int video = 0, vindex = 0;
if(!janus_flags_is_set(&handle->webrtc_flags, JANUS_ICE_HANDLE_WEBRTC_BUNDLE)) {
/* Easy enough */
video = (stream->stream_id == handle->video_id ? 1 : 0);
@@ -2310,7 +2313,7 @@ static void janus_ice_cb_nice_recv(NiceAgent *agent, guint stream_id, guint comp
JANUS_LOG(LOG_HUGE, "[%"SCNu64"] Incoming RTCP, bundling: this is audio (no video has been negotiated)\n", handle->handle_id);
video = 0;
} else {
- if(stream->audio_ssrc_peer == 0 || stream->video_ssrc_peer == 0) {
+ if(stream->audio_ssrc_peer == 0 || stream->video_ssrc_peer[0] == 0) {
/* We don't know the remote SSRC: this can happen for recvonly clients
* (see https://groups.google.com/forum/#!topic/discuss-webrtc/5yuZjV7lkNc)
* Check the local SSRC, compare it to what we have */
@@ -2328,29 +2331,28 @@ static void janus_ice_cb_nice_recv(NiceAgent *agent, guint stream_id, guint comp
JANUS_LOG(LOG_HUGE, "[%"SCNu64"] Incoming RTCP, bundling: this is %s (local SSRC: video=%"SCNu32", audio=%"SCNu32", got %"SCNu32")\n",
handle->handle_id, video ? "video" : "audio", stream->video_ssrc, stream->audio_ssrc, rtcp_ssrc);
} else {
- /* Check the remote SSRC, compare it to what we have */
+ /* Check the remote SSRC, compare it to what we have: in case
+ * we're simulcasting, let's compare to the other SSRCs too */
guint32 rtcp_ssrc = janus_rtcp_get_sender_ssrc(buf, len);
if(rtcp_ssrc == stream->audio_ssrc_peer) {
video = 0;
- } else if(rtcp_ssrc == stream->video_ssrc_peer) {
+ } else if(rtcp_ssrc == stream->video_ssrc_peer[0]) {
video = 1;
- } else {
- /* If we're simulcasting, let's compare to the other SSRCs too */
- if((stream->video_ssrc_peer_sim_1 && rtcp_ssrc == stream->video_ssrc_peer_sim_1) ||
- (stream->video_ssrc_peer_sim_2 && rtcp_ssrc == stream->video_ssrc_peer_sim_2)) {
- /* FIXME RTCP for simulcasting SSRC, let's drop it for now... */
- JANUS_LOG(LOG_HUGE, "Dropping RTCP packet for SSRC %"SCNu32"\n", rtcp_ssrc);
- return;
- }
+ } else if(stream->video_ssrc_peer[1] && rtcp_ssrc == stream->video_ssrc_peer[1]) {
+ video = 1;
+ vindex = 1;
+ } else if(stream->video_ssrc_peer[2] && rtcp_ssrc == stream->video_ssrc_peer[2]) {
+ video = 1;
+ vindex = 2;
}
- JANUS_LOG(LOG_HUGE, "[%"SCNu64"] Incoming RTCP, bundling: this is %s (remote SSRC: video=%"SCNu32", audio=%"SCNu32", got %"SCNu32")\n",
- handle->handle_id, video ? "video" : "audio", stream->video_ssrc_peer, stream->audio_ssrc_peer, rtcp_ssrc);
+ JANUS_LOG(LOG_HUGE, "[%"SCNu64"] Incoming RTCP, bundling: this is %s (remote SSRC: video=%"SCNu32" #%d, audio=%"SCNu32", got %"SCNu32")\n",
+ handle->handle_id, video ? "video" : "audio", stream->video_ssrc_peer[vindex], vindex, stream->audio_ssrc_peer, rtcp_ssrc);
}
}
}
/* Let's process this RTCP (compound?) packet, and update the RTCP context for this stream in case */
- rtcp_context *rtcp_ctx = video ? stream->video_rtcp_ctx : stream->audio_rtcp_ctx;
+ rtcp_context *rtcp_ctx = video ? stream->video_rtcp_ctx[vindex] : stream->audio_rtcp_ctx;
janus_rtcp_parse(rtcp_ctx, buf, buflen);
/* Now let's see if there are any NACKs to handle */
@@ -2402,9 +2404,9 @@ static void janus_ice_cb_nice_recv(NiceAgent *agent, guint stream_id, guint comp
buflen = janus_rtcp_remove_nacks(buf, buflen);
/* Update stats */
if(video) {
- component->in_stats.video_nacks += nacks_count;
+ component->in_stats.video[vindex].nacks += nacks_count;
} else {
- component->in_stats.audio_nacks += nacks_count;
+ component->in_stats.audio.nacks += nacks_count;
}
/* Inform the plugin about the slow uplink in case it's needed */
janus_slow_link_update(component, handle, retransmits_cnt, video, 1, now);
@@ -2433,8 +2435,8 @@ static void janus_ice_cb_nice_recv(NiceAgent *agent, guint stream_id, guint comp
janus_dtls_srtp_incoming_msg(component->dtls, buf, len);
/* Update stats (TODO Do the same for the last second window as well) */
if(len > 0) {
- component->in_stats.data_packets++;
- component->in_stats.data_bytes += len;
+ component->in_stats.data.packets++;
+ component->in_stats.data.bytes += len;
}
return;
}
@@ -2988,20 +2990,14 @@ int janus_ice_setup_local(janus_ice_handle *handle, int offer, int audio, int vi
/* FIXME By default, if we're being called we're DTLS clients, but this may be changed by ICE... */
audio_stream->dtls_role = offer ? JANUS_DTLS_ROLE_CLIENT : JANUS_DTLS_ROLE_ACTPASS;
audio_stream->audio_ssrc = janus_random_uint32(); /* FIXME Should we look for conflicts? */
- audio_stream->audio_ssrc_peer = 0; /* FIXME Right now we don't know what this will be */
- audio_stream->video_ssrc = 0;
if(janus_flags_is_set(&handle->webrtc_flags, JANUS_ICE_HANDLE_WEBRTC_BUNDLE)) {
/* If we're bundling, this stream is going to be used for video as well */
audio_stream->video_ssrc = janus_random_uint32(); /* FIXME Should we look for conflicts? */
}
- audio_stream->video_ssrc_peer = 0; /* FIXME Right now we don't know what this will be */
- audio_stream->video_ssrc_peer_rtx = 0; /* FIXME Right now we don't know if and what this will be */
- audio_stream->video_ssrc_peer_sim_1 = 0; /* FIXME Right now we don't know if and what this will be */
- audio_stream->video_ssrc_peer_sim_2 = 0; /* FIXME Right now we don't know if and what this will be */
audio_stream->audio_rtcp_ctx = g_malloc0(sizeof(rtcp_context));
audio_stream->audio_rtcp_ctx->tb = 48000; /* May change later */
- audio_stream->video_rtcp_ctx = g_malloc0(sizeof(rtcp_context));
- audio_stream->video_rtcp_ctx->tb = 90000;
+ audio_stream->video_rtcp_ctx[0] = g_malloc0(sizeof(rtcp_context));
+ audio_stream->video_rtcp_ctx[0]->tb = 90000;
audio_stream->noerrorlog = FALSE;
janus_mutex_init(&audio_stream->mutex);
audio_stream->components = g_hash_table_new(NULL, NULL);
@@ -3061,7 +3057,7 @@ int janus_ice_setup_local(janus_ice_handle *handle, int offer, int audio, int vi
audio_rtp->nack_sent_log_ts = 0;
audio_rtp->nack_sent_recent_cnt = 0;
audio_rtp->last_seqs_audio = NULL;
- audio_rtp->last_seqs_video = NULL;
+ audio_rtp->last_seqs_video[0] = NULL;
janus_ice_stats_reset(&audio_rtp->in_stats);
janus_ice_stats_reset(&audio_rtp->out_stats);
janus_mutex_init(&audio_rtp->mutex);
@@ -3157,14 +3153,8 @@ int janus_ice_setup_local(janus_ice_handle *handle, int offer, int audio, int vi
/* FIXME By default, if we're being called we're DTLS clients, but this may be changed by ICE... */
video_stream->dtls_role = offer ? JANUS_DTLS_ROLE_CLIENT : JANUS_DTLS_ROLE_ACTPASS;
video_stream->video_ssrc = janus_random_uint32(); /* FIXME Should we look for conflicts? */
- video_stream->video_ssrc_peer = 0; /* FIXME Right now we don't know what this will be */
- video_stream->video_ssrc_peer_rtx = 0; /* FIXME Right now we don't know if and what this will be */
- video_stream->video_ssrc_peer_sim_1 = 0; /* FIXME Right now we don't know if and what this will be */
- video_stream->video_ssrc_peer_sim_2 = 0; /* FIXME Right now we don't know if and what this will be */
- video_stream->audio_ssrc = 0;
- video_stream->audio_ssrc_peer = 0;
- video_stream->video_rtcp_ctx = g_malloc0(sizeof(rtcp_context));
- video_stream->video_rtcp_ctx->tb = 90000;
+ video_stream->video_rtcp_ctx[0] = g_malloc0(sizeof(rtcp_context));
+ video_stream->video_rtcp_ctx[0]->tb = 90000;
video_stream->components = g_hash_table_new(NULL, NULL);
video_stream->noerrorlog = FALSE;
janus_mutex_init(&video_stream->mutex);
@@ -3224,7 +3214,7 @@ int janus_ice_setup_local(janus_ice_handle *handle, int offer, int audio, int vi
video_rtp->nack_sent_log_ts = 0;
video_rtp->nack_sent_recent_cnt = 0;
video_rtp->last_seqs_audio = NULL;
- video_rtp->last_seqs_video = NULL;
+ video_rtp->last_seqs_video[0] = NULL;
janus_ice_stats_reset(&video_rtp->in_stats);
janus_ice_stats_reset(&video_rtp->out_stats);
janus_mutex_init(&video_rtp->mutex);
@@ -3480,18 +3470,18 @@ void *janus_ice_send_thread(void *data) {
if(no_media_timer > 0 && now-before >= G_USEC_PER_SEC) {
if(handle->audio_stream && handle->audio_stream->rtp_component) {
janus_ice_component *component = handle->audio_stream->rtp_component;
- janus_ice_stats_item *last = (janus_ice_stats_item *)(component->in_stats.audio_bytes_lastsec ? g_queue_peek_tail(component->in_stats.audio_bytes_lastsec) : NULL);
- if(!component->in_stats.audio_notified_lastsec && last && now-last->when >= (gint64)no_media_timer*G_USEC_PER_SEC) {
+ janus_ice_stats_item *last = (janus_ice_stats_item *)(component->in_stats.audio.bytes_lastsec ? g_queue_peek_tail(component->in_stats.audio.bytes_lastsec) : NULL);
+ if(!component->in_stats.audio.notified_lastsec && last && now-last->when >= (gint64)no_media_timer*G_USEC_PER_SEC) {
/* We missed more than no_second_timer seconds of audio! */
- component->in_stats.audio_notified_lastsec = TRUE;
+ component->in_stats.audio.notified_lastsec = TRUE;
JANUS_LOG(LOG_WARN, "[%"SCNu64"] Didn't receive audio for more than %d seconds...\n", handle->handle_id, no_media_timer);
janus_ice_notify_media(handle, FALSE, FALSE);
}
- if(!component->in_stats.video_notified_lastsec && janus_flags_is_set(&handle->webrtc_flags, JANUS_ICE_HANDLE_WEBRTC_BUNDLE)) {
- last = (janus_ice_stats_item *)(component->in_stats.video_bytes_lastsec ? g_queue_peek_tail(component->in_stats.video_bytes_lastsec) : NULL);
+ if(!component->in_stats.video[0].notified_lastsec && janus_flags_is_set(&handle->webrtc_flags, JANUS_ICE_HANDLE_WEBRTC_BUNDLE)) {
+ last = (janus_ice_stats_item *)(component->in_stats.video[0].bytes_lastsec ? g_queue_peek_tail(component->in_stats.video[0].bytes_lastsec) : NULL);
if(last && now-last->when >= (gint64)no_media_timer*G_USEC_PER_SEC) {
/* We missed more than no_second_timer seconds of video! */
- component->in_stats.video_notified_lastsec = TRUE;
+ component->in_stats.video[0].notified_lastsec = TRUE;
JANUS_LOG(LOG_WARN, "[%"SCNu64"] Didn't receive video for more than %d seconds...\n", handle->handle_id, no_media_timer);
janus_ice_notify_media(handle, TRUE, FALSE);
}
@@ -3499,10 +3489,10 @@ void *janus_ice_send_thread(void *data) {
}
if(handle->video_stream && handle->video_stream->rtp_component) {
janus_ice_component *component = handle->video_stream->rtp_component;
- janus_ice_stats_item *last = (janus_ice_stats_item *)(component->in_stats.video_bytes_lastsec ? g_queue_peek_tail(component->in_stats.video_bytes_lastsec) : NULL);
- if(!component->in_stats.video_notified_lastsec && last && now-last->when >= (gint64)no_media_timer*G_USEC_PER_SEC) {
+ janus_ice_stats_item *last = (janus_ice_stats_item *)(component->in_stats.video[0].bytes_lastsec ? g_queue_peek_tail(component->in_stats.video[0].bytes_lastsec) : NULL);
+ if(!component->in_stats.video[0].notified_lastsec && last && now-last->when >= (gint64)no_media_timer*G_USEC_PER_SEC) {
/* We missed more than no_second_timer seconds of video! */
- component->in_stats.video_notified_lastsec = TRUE;
+ component->in_stats.video[0].notified_lastsec = TRUE;
JANUS_LOG(LOG_WARN, "[%"SCNu64"] Didn't receive video for more than a second...\n", handle->handle_id);
janus_ice_notify_media(handle, TRUE, FALSE);
}
@@ -3531,7 +3521,7 @@ void *janus_ice_send_thread(void *data) {
if(now-video_rtcp_last_rr >= 5*G_USEC_PER_SEC) {
janus_ice_stream *stream = janus_flags_is_set(&handle->webrtc_flags, JANUS_ICE_HANDLE_WEBRTC_BUNDLE) ? (handle->audio_stream ? handle->audio_stream : handle->video_stream) : (handle->video_stream);
if(stream) {
- if(stream->video_rtcp_ctx && stream->video_rtcp_ctx->rtp_recvd) {
+ if(stream->video_rtcp_ctx[0] && stream->video_rtcp_ctx[0]->rtp_recvd) {
/* Create a RR */
int rrlen = 32;
char rtcpbuf[32];
@@ -3541,7 +3531,7 @@ void *janus_ice_send_thread(void *data) {
rr->header.type = RTCP_RR;
rr->header.rc = 1;
rr->header.length = htons((rrlen/4)-1);
- janus_rtcp_report_block(stream->video_rtcp_ctx, &rr->rb[0]);
+ janus_rtcp_report_block(stream->video_rtcp_ctx[0], &rr->rb[0]);
/* Enqueue it, we'll send it later */
janus_ice_relay_rtcp_internal(handle, 1, rtcpbuf, 32, FALSE);
}
@@ -3551,7 +3541,7 @@ void *janus_ice_send_thread(void *data) {
/* Do the same with SR/SDES */
if(now-audio_rtcp_last_sr >= 5*G_USEC_PER_SEC) {
janus_ice_stream *stream = handle->audio_stream;
- if(stream && stream->rtp_component && stream->rtp_component->out_stats.audio_packets > 0) {
+ if(stream && stream->rtp_component && stream->rtp_component->out_stats.audio.packets > 0) {
/* Create a SR/SDES compound */
int srlen = 28;
int sdeslen = 20;
@@ -3578,8 +3568,8 @@ void *janus_ice_send_thread(void *data) {
uint32_t rtp_ts = ((ntp-stream->audio_first_ntp_ts)/1000)*(rtcp_ctx->tb/1000) + stream->audio_first_rtp_ts;
sr->si.rtp_ts = htonl(rtp_ts);
}
- sr->si.s_packets = htonl(stream->rtp_component->out_stats.audio_packets);
- sr->si.s_octets = htonl(stream->rtp_component->out_stats.audio_bytes);
+ sr->si.s_packets = htonl(stream->rtp_component->out_stats.audio.packets);
+ sr->si.s_octets = htonl(stream->rtp_component->out_stats.audio.bytes);
rtcp_sdes *sdes = (rtcp_sdes *)&rtcpbuf[28];
janus_rtcp_sdes((char *)sdes, sdeslen, "janusaudio", 10);
/* Enqueue it, we'll send it later */
@@ -3589,7 +3579,7 @@ void *janus_ice_send_thread(void *data) {
}
if(now-video_rtcp_last_sr >= 5*G_USEC_PER_SEC) {
janus_ice_stream *stream = janus_flags_is_set(&handle->webrtc_flags, JANUS_ICE_HANDLE_WEBRTC_BUNDLE) ? (handle->audio_stream ? handle->audio_stream : handle->video_stream) : (handle->video_stream);
- if(stream && stream->rtp_component && stream->rtp_component->out_stats.video_packets > 0) {
+ if(stream && stream->rtp_component && stream->rtp_component->out_stats.video[0].packets > 0) {
/* Create a SR/SDES compound */
int srlen = 28;
int sdeslen = 20;
@@ -3608,16 +3598,16 @@ void *janus_ice_send_thread(void *data) {
sr->si.ntp_ts_msw = htonl(s);
sr->si.ntp_ts_lsw = htonl(f);
/* Compute an RTP timestamp coherent with the NTP one */
- rtcp_context *rtcp_ctx = stream->video_rtcp_ctx;
+ rtcp_context *rtcp_ctx = stream->video_rtcp_ctx[0];
if(rtcp_ctx == NULL) {
sr->si.rtp_ts = htonl(stream->video_last_ts); /* FIXME */
} else {
int64_t ntp = tv.tv_sec*G_USEC_PER_SEC + tv.tv_usec;
- uint32_t rtp_ts = ((ntp-stream->video_first_ntp_ts)/1000)*(rtcp_ctx->tb/1000) + stream->video_first_rtp_ts;
+ uint32_t rtp_ts = ((ntp-stream->video_first_ntp_ts[0])/1000)*(rtcp_ctx->tb/1000) + stream->video_first_rtp_ts[0];
sr->si.rtp_ts = htonl(rtp_ts);
}
- sr->si.s_packets = htonl(stream->rtp_component->out_stats.video_packets);
- sr->si.s_octets = htonl(stream->rtp_component->out_stats.video_bytes);
+ sr->si.s_packets = htonl(stream->rtp_component->out_stats.video[0].packets);
+ sr->si.s_octets = htonl(stream->rtp_component->out_stats.video[0].bytes);
rtcp_sdes *sdes = (rtcp_sdes *)&rtcpbuf[28];
janus_rtcp_sdes((char *)sdes, sdeslen, "janusvideo", 10);
/* Enqueue it, we'll send it later */
@@ -3640,12 +3630,12 @@ void *janus_ice_send_thread(void *data) {
json_object_set_new(info, "jitter-local", json_integer(janus_rtcp_context_get_jitter(stream->audio_rtcp_ctx, FALSE)));
json_object_set_new(info, "jitter-remote", json_integer(janus_rtcp_context_get_jitter(stream->audio_rtcp_ctx, TRUE)));
if(stream->rtp_component) {
- json_object_set_new(info, "packets-received", json_integer(stream->rtp_component->in_stats.audio_packets));
- json_object_set_new(info, "packets-sent", json_integer(stream->rtp_component->out_stats.audio_packets));
- json_object_set_new(info, "bytes-received", json_integer(stream->rtp_component->in_stats.audio_bytes));
- json_object_set_new(info, "bytes-sent", json_integer(stream->rtp_component->out_stats.audio_bytes));
- json_object_set_new(info, "nacks-received", json_integer(stream->rtp_component->in_stats.audio_nacks));
- json_object_set_new(info, "nacks-sent", json_integer(stream->rtp_component->out_stats.audio_nacks));
+ json_object_set_new(info, "packets-received", json_integer(stream->rtp_component->in_stats.audio.packets));
+ json_object_set_new(info, "packets-sent", json_integer(stream->rtp_component->out_stats.audio.packets));
+ json_object_set_new(info, "bytes-received", json_integer(stream->rtp_component->in_stats.audio.bytes));
+ json_object_set_new(info, "bytes-sent", json_integer(stream->rtp_component->out_stats.audio.bytes));
+ json_object_set_new(info, "nacks-received", json_integer(stream->rtp_component->in_stats.audio.nacks));
+ json_object_set_new(info, "nacks-sent", json_integer(stream->rtp_component->out_stats.audio.nacks));
}
janus_events_notify_handlers(JANUS_EVENT_TYPE_MEDIA, session->session_id, handle->handle_id, info);
}
@@ -3655,24 +3645,33 @@ void *janus_ice_send_thread(void *data) {
if(janus_ice_event_stats_period > 0 && now-video_last_event >= (gint64)janus_ice_event_stats_period*G_USEC_PER_SEC) {
if(janus_events_is_enabled() && janus_flags_is_set(&handle->webrtc_flags, JANUS_ICE_HANDLE_WEBRTC_HAS_VIDEO)) {
janus_ice_stream *stream = janus_flags_is_set(&handle->webrtc_flags, JANUS_ICE_HANDLE_WEBRTC_BUNDLE) ? (handle->audio_stream ? handle->audio_stream : handle->video_stream) : (handle->video_stream);
- if(stream && stream->video_rtcp_ctx) {
- json_t *info = json_object();
- json_object_set_new(info, "media", json_string("video"));
- json_object_set_new(info, "base", json_integer(stream->video_rtcp_ctx->tb));
- json_object_set_new(info, "lsr", json_integer(janus_rtcp_context_get_lsr(stream->video_rtcp_ctx)));
- json_object_set_new(info, "lost", json_integer(janus_rtcp_context_get_lost_all(stream->video_rtcp_ctx, FALSE)));
- json_object_set_new(info, "lost-by-remote", json_integer(janus_rtcp_context_get_lost_all(stream->video_rtcp_ctx, TRUE)));
- json_object_set_new(info, "jitter-local", json_integer(janus_rtcp_context_get_jitter(stream->video_rtcp_ctx, FALSE)));
- json_object_set_new(info, "jitter-remote", json_integer(janus_rtcp_context_get_jitter(stream->video_rtcp_ctx, TRUE)));
- if(stream->rtp_component) {
- json_object_set_new(info, "packets-received", json_integer(stream->rtp_component->in_stats.video_packets));
- json_object_set_new(info, "packets-sent", json_integer(stream->rtp_component->out_stats.video_packets));
- json_object_set_new(info, "bytes-received", json_integer(stream->rtp_component->in_stats.video_bytes));
- json_object_set_new(info, "bytes-sent", json_integer(stream->rtp_component->out_stats.video_bytes));
- json_object_set_new(info, "nacks-received", json_integer(stream->rtp_component->in_stats.video_nacks));
- json_object_set_new(info, "nacks-sent", json_integer(stream->rtp_component->out_stats.video_nacks));
+ int vindex=0;
+ for(vindex=0; vindex<3; vindex++) {
+ if(stream && stream->video_rtcp_ctx[vindex]) {
+ json_t *info = json_object();
+ if(vindex == 0)
+ json_object_set_new(info, "media", json_string("video"));
+ else if(vindex == 1)
+ json_object_set_new(info, "media", json_string("video-sim1"));
+ else
+ json_object_set_new(info, "media", json_string("video-sim2"));
+ json_object_set_new(info, "media", json_string("video"));
+ json_object_set_new(info, "base", json_integer(stream->video_rtcp_ctx[vindex]->tb));
+ json_object_set_new(info, "lsr", json_integer(janus_rtcp_context_get_lsr(stream->video_rtcp_ctx[vindex])));
+ json_object_set_new(info, "lost", json_integer(janus_rtcp_context_get_lost_all(stream->video_rtcp_ctx[vindex], FALSE)));
+ json_object_set_new(info, "lost-by-remote", json_integer(janus_rtcp_context_get_lost_all(stream->video_rtcp_ctx[vindex], TRUE)));
+ json_object_set_new(info, "jitter-local", json_integer(janus_rtcp_context_get_jitter(stream->video_rtcp_ctx[vindex], FALSE)));
+ json_object_set_new(info, "jitter-remote", json_integer(janus_rtcp_context_get_jitter(stream->video_rtcp_ctx[vindex], TRUE)));
+ if(stream->rtp_component) {
+ json_object_set_new(info, "packets-received", json_integer(stream->rtp_component->in_stats.video[vindex].packets));
+ json_object_set_new(info, "packets-sent", json_integer(stream->rtp_component->out_stats.video[vindex].packets));
+ json_object_set_new(info, "bytes-received", json_integer(stream->rtp_component->in_stats.video[vindex].bytes));
+ json_object_set_new(info, "bytes-sent", json_integer(stream->rtp_component->out_stats.video[vindex].bytes));
+ json_object_set_new(info, "nacks-received", json_integer(stream->rtp_component->in_stats.video[vindex].nacks));
+ json_object_set_new(info, "nacks-sent", json_integer(stream->rtp_component->out_stats.video[vindex].nacks));
+ }
+ janus_events_notify_handlers(JANUS_EVENT_TYPE_MEDIA, session->session_id, handle->handle_id, info);
}
- janus_events_notify_handlers(JANUS_EVENT_TYPE_MEDIA, session->session_id, handle->handle_id, info);
}
}
video_last_event = now;
@@ -3767,19 +3766,19 @@ void *janus_ice_send_thread(void *data) {
rr->header.rc = 0;
rr->header.length = htons((rrlen/4)-1);
janus_ice_stream *stream = janus_flags_is_set(&handle->webrtc_flags, JANUS_ICE_HANDLE_WEBRTC_BUNDLE) ? (handle->audio_stream ? handle->audio_stream : handle->video_stream) : (handle->video_stream);
- if(stream && stream->video_rtcp_ctx && stream->video_rtcp_ctx->rtp_recvd) {
+ if(stream && stream->video_rtcp_ctx[0] && stream->video_rtcp_ctx[0]->rtp_recvd) {
rr->header.rc = 1;
- janus_rtcp_report_block(stream->video_rtcp_ctx, &rr->rb[0]);
+ janus_rtcp_report_block(stream->video_rtcp_ctx[0], &rr->rb[0]);
}
/* Append REMB */
memcpy(rtcpbuf+rrlen, pkt->data, pkt->length);
/* If we're simulcasting, set the extra SSRCs (the first one will be set by janus_rtcp_fix_ssrc) */
- if(stream->video_ssrc_peer_sim_1 && pkt->length >= 28) {
+ if(stream->video_ssrc_peer[1] && pkt->length >= 28) {
rtcp_fb *rtcpfb = (rtcp_fb *)(rtcpbuf+rrlen);
rtcp_remb *remb = (rtcp_remb *)rtcpfb->fci;
- remb->ssrc[1] = htonl(stream->video_ssrc_peer_sim_1);
- if(stream->video_ssrc_peer_sim_2 && pkt->length >= 32) {
- remb->ssrc[2] = htonl(stream->video_ssrc_peer_sim_2);
+ remb->ssrc[1] = htonl(stream->video_ssrc_peer[1]);
+ if(stream->video_ssrc_peer[2] && pkt->length >= 32) {
+ remb->ssrc[2] = htonl(stream->video_ssrc_peer[2]);
}
}
/* Free old packet and update */
@@ -3795,16 +3794,16 @@ void *janus_ice_send_thread(void *data) {
if(!janus_flags_is_set(&handle->webrtc_flags, JANUS_ICE_HANDLE_WEBRTC_PLAN_B)) {
JANUS_LOG(LOG_HUGE, "[%"SCNu64"] Fixing SSRCs (local %u, peer %u)\n", handle->handle_id,
video ? stream->video_ssrc : stream->audio_ssrc,
- video ? stream->video_ssrc_peer : stream->audio_ssrc_peer);
+ video ? stream->video_ssrc_peer[0] : stream->audio_ssrc_peer);
janus_rtcp_fix_ssrc(NULL, sbuf, pkt->length, 1,
video ? stream->video_ssrc : stream->audio_ssrc,
- video ? stream->video_ssrc_peer : stream->audio_ssrc_peer);
+ video ? stream->video_ssrc_peer[0] : stream->audio_ssrc_peer);
} else {
/* Plan B involved, we trust the plugin to set the right 'local' SSRC and we don't mess with it */
JANUS_LOG(LOG_HUGE, "[%"SCNu64"] Fixing peer SSRC (Plan B, peer %u)\n", handle->handle_id,
- video ? stream->video_ssrc_peer : stream->audio_ssrc_peer);
+ video ? stream->video_ssrc_peer[0] : stream->audio_ssrc_peer);
janus_rtcp_fix_ssrc(NULL, sbuf, pkt->length, 1, 0,
- video ? stream->video_ssrc_peer : stream->audio_ssrc_peer);
+ video ? stream->video_ssrc_peer[0] : stream->audio_ssrc_peer);
}
/* Do we need to dump this packet for debugging? */
if(g_atomic_int_get(&handle->dump_packets))
@@ -3928,8 +3927,8 @@ void *janus_ice_send_thread(void *data) {
janus_rtp_header *header = (janus_rtp_header *)sbuf;
guint32 timestamp = ntohl(header->timestamp);
if(pkt->type == JANUS_ICE_PACKET_AUDIO) {
- component->out_stats.audio_packets++;
- component->out_stats.audio_bytes += sent;
+ component->out_stats.audio.packets++;
+ component->out_stats.audio.bytes += sent;
stream->audio_last_ts = timestamp;
if(stream->audio_first_ntp_ts == 0) {
struct timeval tv;
@@ -3938,19 +3937,19 @@ void *janus_ice_send_thread(void *data) {
stream->audio_first_rtp_ts = timestamp;
}
/* Let's check if this was G.711: in case we may need to change the timestamp base */
- rtcp_context *rtcp_ctx = video ? stream->video_rtcp_ctx : stream->audio_rtcp_ctx;
+ rtcp_context *rtcp_ctx = video ? stream->video_rtcp_ctx[0] : stream->audio_rtcp_ctx;
int pt = header->type;
if((pt == 0 || pt == 8) && (rtcp_ctx->tb == 48000))
rtcp_ctx->tb = 8000;
} else if(pkt->type == JANUS_ICE_PACKET_VIDEO) {
- component->out_stats.video_packets++;
- component->out_stats.video_bytes += sent;
+ component->out_stats.video[0].packets++;
+ component->out_stats.video[0].bytes += sent;
stream->video_last_ts = timestamp;
- if(stream->video_first_ntp_ts == 0) {
+ if(stream->video_first_ntp_ts[0] == 0) {
struct timeval tv;
gettimeofday(&tv, NULL);
- stream->video_first_ntp_ts = (gint64)tv.tv_sec*G_USEC_PER_SEC + tv.tv_usec;
- stream->video_first_rtp_ts = timestamp;
+ stream->video_first_ntp_ts[0] = (gint64)tv.tv_sec*G_USEC_PER_SEC + tv.tv_usec;
+ stream->video_first_rtp_ts[0] = timestamp;
}
}
}
diff --git a/ice.h b/ice.h
index f7f1aee..2b78063 100644
--- a/ice.h
+++ b/ice.h
@@ -188,31 +188,28 @@ typedef struct janus_ice_trickle janus_ice_trickle;
/*! \brief Janus media statistics
* \note To improve with more stuff */
+typedef struct janus_ice_stats_info {
+ /*! \brief Packets sent or received */
+ guint32 packets;
+ /*! \brief Bytes sent or received */
+ guint64 bytes;
+ /*! \brief Bytes sent or received in the last second */
+ GQueue *bytes_lastsec;
+ /*! \brief Whether or not we notified about lastsec issues already */
+ gboolean notified_lastsec;
+ /*! \brief Number of NACKs sent or received */
+ guint32 nacks;
+} janus_ice_stats_info;
+
+/*! \brief Janus media statistics container
+ * \note To improve with more stuff */
typedef struct janus_ice_stats {
- /*! \brief Audio packets sent or received */
- guint32 audio_packets;
- /*! \brief Audio bytes sent or received */
- guint64 audio_bytes;
- /*! \brief Audio bytes sent or received in the last second */
- GQueue *audio_bytes_lastsec;
- /*! \brief Whether or not we notified about audio lastsec issues already */
- gboolean audio_notified_lastsec;
- /*! \brief Number of audio NACKs sent or received */
- guint32 audio_nacks;
- /*! \brief Video packets sent or received */
- guint32 video_packets;
- /*! \brief Video bytes sent or received */
- guint64 video_bytes;
- /*! \brief Video bytes sent or received in the last second */
- GQueue *video_bytes_lastsec;
- /*! \brief Whether or not we notified about video lastsec issues already */
- gboolean video_notified_lastsec;
- /*! \brief Number of video NACKs sent or received */
- guint32 video_nacks;
- /*! \brief Data packets sent or received */
- guint32 data_packets;
- /*! \brief Data bytes sent or received */
- guint64 data_bytes;
+ /*! \brief Audio info */
+ janus_ice_stats_info audio;
+ /*! \brief Video info (considering we may be simulcasting) */
+ janus_ice_stats_info video[3];
+ /*! \brief Data info */
+ janus_ice_stats_info data;
/*! \brief Last time the slow_link callback (of the plugin) was called */
gint64 last_slowlink_time;
/*! \brief Start time of recent NACKs (for slow_link) */
@@ -362,14 +359,10 @@ struct janus_ice_stream {
guint32 video_ssrc;
/*! \brief Audio SSRC of the peer for this stream (may be bundled) */
guint32 audio_ssrc_peer;
- /*! \brief Video SSRC of the peer for this stream (may be bundled) */
- guint32 video_ssrc_peer;
+ /*! \brief Video SSRC(s) of the peer for this stream (may be bundled, and simulcasting) */
+ guint32 video_ssrc_peer[3];
/*! \brief Video retransmissions SSRC of the peer for this stream (may be bundled) */
guint32 video_ssrc_peer_rtx;
- /*! \brief Video SSRC (simulcasted 1) of the peer for this stream (may be bundled) */
- guint32 video_ssrc_peer_sim_1;
- /*! \brief Video SSRC (simulcasted 2) of the peer for this stream (may be bundled) */
- guint32 video_ssrc_peer_sim_2;
/*! \brief Array of RTP Stream IDs (for Firefox simulcasting, if enabled) */
char *rid[3];
/*! \brief List of payload types we can expect for audio */
@@ -380,16 +373,16 @@ struct janus_ice_stream {
gint payload_type;
/*! \brief RTCP context for the audio stream (may be bundled) */
rtcp_context *audio_rtcp_ctx;
- /*! \brief RTCP context for the video stream (may be bundled) */
- rtcp_context *video_rtcp_ctx;
+ /*! \brief RTCP context(s) for the video stream (may be bundled, and simulcasting) */
+ rtcp_context *video_rtcp_ctx[3];
/*! \brief First received audio NTP timestamp */
gint64 audio_first_ntp_ts;
/*! \brief First received audio RTP timestamp */
guint32 audio_first_rtp_ts;
- /*! \brief First received video NTP timestamp */
- gint64 video_first_ntp_ts;
- /*! \brief First received video NTP RTP timestamp */
- guint32 video_first_rtp_ts;
+ /*! \brief First received video NTP timestamp (for all simulcast video streams) */
+ gint64 video_first_ntp_ts[3];
+ /*! \brief First received video NTP RTP timestamp (for all simulcast video streams) */
+ guint32 video_first_rtp_ts[3];
/*! \brief Last sent audio RTP timestamp */
guint32 audio_last_ts;
/*! \brief Last sent video RTP timestamp */
@@ -463,8 +456,8 @@ struct janus_ice_component {
guint nack_sent_recent_cnt;
/*! \brief List of recently received audio sequence numbers (as a support to NACK generation) */
janus_seq_info *last_seqs_audio;
- /*! \brief List of recently received video sequence numbers (as a support to NACK generation) */
- janus_seq_info *last_seqs_video;
+ /*! \brief List of recently received video sequence numbers (as a support to NACK generation, for each simulcast SSRC) */
+ janus_seq_info *last_seqs_video[3];
/*! \brief Stats for incoming data (audio/video/data) */
janus_ice_stats in_stats;
/*! \brief Stats for outgoing data (audio/video/data) */
diff --git a/janus.c b/janus.c
index 5de85dd..e507ae8 100644
--- a/janus.c
+++ b/janus.c
@@ -1130,10 +1130,10 @@ int janus_process_incoming_request(janus_request *request) {
if(handle->audio_stream->rtp_component && handle->video_stream->rtp_component)
handle->audio_stream->rtp_component->do_video_nacks = handle->video_stream->rtp_component->do_video_nacks;
handle->audio_stream->video_ssrc = handle->video_stream->video_ssrc;
- handle->audio_stream->video_ssrc_peer = handle->video_stream->video_ssrc_peer;
+ handle->audio_stream->video_ssrc_peer[0] = handle->video_stream->video_ssrc_peer[0];
handle->audio_stream->video_ssrc_peer_rtx = handle->video_stream->video_ssrc_peer_rtx;
- handle->audio_stream->video_ssrc_peer_sim_1 = handle->video_stream->video_ssrc_peer_sim_1;
- handle->audio_stream->video_ssrc_peer_sim_2 = handle->video_stream->video_ssrc_peer_sim_2;
+ handle->audio_stream->video_ssrc_peer[1] = handle->video_stream->video_ssrc_peer[1];
+ handle->audio_stream->video_ssrc_peer[2] = handle->video_stream->video_ssrc_peer[2];
nice_agent_attach_recv(handle->agent, handle->video_stream->stream_id, 1, g_main_loop_get_context (handle->iceloop), NULL, NULL);
if(!handle->force_rtcp_mux && !janus_ice_is_rtcpmux_forced())
nice_agent_attach_recv(handle->agent, handle->video_stream->stream_id, 2, g_main_loop_get_context (handle->iceloop), NULL, NULL);
@@ -1153,9 +1153,13 @@ int janus_process_incoming_request(janus_request *request) {
if(handle->audio_stream->rtp_component)
handle->audio_stream->rtp_component->do_video_nacks = FALSE;
handle->audio_stream->video_ssrc = 0;
- handle->audio_stream->video_ssrc_peer = 0;
- g_free(handle->audio_stream->video_rtcp_ctx);
- handle->audio_stream->video_rtcp_ctx = NULL;
+ handle->audio_stream->video_ssrc_peer[0] = 0;
+ g_free(handle->audio_stream->video_rtcp_ctx[0]);
+ handle->audio_stream->video_rtcp_ctx[0] = NULL;
+ g_free(handle->audio_stream->video_rtcp_ctx[1]);
+ handle->audio_stream->video_rtcp_ctx[1] = NULL;
+ g_free(handle->audio_stream->video_rtcp_ctx[2]);
+ handle->audio_stream->video_rtcp_ctx[2] = NULL;
}
} else if(video) {
/* Get rid of data, if present */
@@ -1367,19 +1371,19 @@ int janus_process_incoming_request(janus_request *request) {
body_jsep = json_pack("{ssss}", "type", jsep_type, "sdp", jsep_sdp_stripped);
/* Check if VP8 simulcasting is enabled */
if(janus_flags_is_set(&handle->webrtc_flags, JANUS_ICE_HANDLE_WEBRTC_HAS_VIDEO)) {
- if(handle->video_stream && handle->video_stream->video_ssrc_peer_sim_1) {
+ if(handle->video_stream && handle->video_stream->video_ssrc_peer[1]) {
json_t *simulcast = json_object();
- json_object_set(simulcast, "ssrc-0", json_integer(handle->video_stream->video_ssrc_peer));
- json_object_set(simulcast, "ssrc-1", json_integer(handle->video_stream->video_ssrc_peer_sim_1));
- if(handle->video_stream->video_ssrc_peer_sim_2)
- json_object_set(simulcast, "ssrc-2", json_integer(handle->video_stream->video_ssrc_peer_sim_2));
+ json_object_set(simulcast, "ssrc-0", json_integer(handle->video_stream->video_ssrc_peer[0]));
+ json_object_set(simulcast, "ssrc-1", json_integer(handle->video_stream->video_ssrc_peer[1]));
+ if(handle->video_stream->video_ssrc_peer[2])
+ json_object_set(simulcast, "ssrc-2", json_integer(handle->video_stream->video_ssrc_peer[2]));
json_object_set(body_jsep, "simulcast", simulcast);
- } else if(handle->audio_stream && handle->audio_stream->video_ssrc_peer_sim_1) {
+ } else if(handle->audio_stream && handle->audio_stream->video_ssrc_peer[1]) {
json_t *simulcast = json_object();
- json_object_set(simulcast, "ssrc-0", json_integer(handle->audio_stream->video_ssrc_peer));
- json_object_set(simulcast, "ssrc-1", json_integer(handle->audio_stream->video_ssrc_peer_sim_1));
- if(handle->audio_stream->video_ssrc_peer_sim_2)
- json_object_set(simulcast, "ssrc-2", json_integer(handle->audio_stream->video_ssrc_peer_sim_2));
+ json_object_set(simulcast, "ssrc-0", json_integer(handle->audio_stream->video_ssrc_peer[0]));
+ json_object_set(simulcast, "ssrc-1", json_integer(handle->audio_stream->video_ssrc_peer[1]));
+ if(handle->audio_stream->video_ssrc_peer[2])
+ json_object_set(simulcast, "ssrc-2", json_integer(handle->audio_stream->video_ssrc_peer[2]));
json_object_set(body_jsep, "simulcast", simulcast);
}
}
@@ -2440,14 +2444,14 @@ json_t *janus_admin_stream_summary(janus_ice_stream *stream) {
json_object_set_new(ss, "video", json_integer(stream->video_ssrc));
if(stream->audio_ssrc_peer)
json_object_set_new(ss, "audio-peer", json_integer(stream->audio_ssrc_peer));
- if(stream->video_ssrc_peer)
- json_object_set_new(ss, "video-peer", json_integer(stream->video_ssrc_peer));
+ if(stream->video_ssrc_peer[0])
+ json_object_set_new(ss, "video-peer", json_integer(stream->video_ssrc_peer[0]));
if(stream->video_ssrc_peer_rtx)
json_object_set_new(ss, "video-peer-rtx", json_integer(stream->video_ssrc_peer_rtx));
- if(stream->video_ssrc_peer_sim_1)
- json_object_set_new(ss, "video-peer-sim-1", json_integer(stream->video_ssrc_peer_sim_1));
- if(stream->video_ssrc_peer_sim_2)
- json_object_set_new(ss, "video-peer-sim-2", json_integer(stream->video_ssrc_peer_sim_2));
+ if(stream->video_ssrc_peer[1])
+ json_object_set_new(ss, "video-peer-sim-1", json_integer(stream->video_ssrc_peer[1]));
+ if(stream->video_ssrc_peer[2])
+ json_object_set_new(ss, "video-peer-sim-2", json_integer(stream->video_ssrc_peer[2]));
if(stream->rid[0]) {
json_t *rid = json_array();
json_array_append_new(rid, json_string(stream->rid[0]));
@@ -2481,17 +2485,25 @@ json_t *janus_admin_stream_summary(janus_ice_stream *stream) {
json_object_set_new(audio_rtcp_stats, "jitter-remote", json_integer(janus_rtcp_context_get_jitter(stream->audio_rtcp_ctx, TRUE)));
json_object_set_new(rtcp_stats, "audio", audio_rtcp_stats);
}
- if(stream->video_rtcp_ctx != NULL) {
- if(rtcp_stats == NULL)
- rtcp_stats = json_object();
- json_t *video_rtcp_stats = json_object();
- json_object_set_new(video_rtcp_stats, "base", json_integer(stream->video_rtcp_ctx->tb));
- json_object_set_new(video_rtcp_stats, "lsr", json_integer(janus_rtcp_context_get_lsr(stream->video_rtcp_ctx)));
- json_object_set_new(video_rtcp_stats, "lost", json_integer(janus_rtcp_context_get_lost_all(stream->video_rtcp_ctx, FALSE)));
- json_object_set_new(video_rtcp_stats, "lost-by-remote", json_integer(janus_rtcp_context_get_lost_all(stream->video_rtcp_ctx, TRUE)));
- json_object_set_new(video_rtcp_stats, "jitter-local", json_integer(janus_rtcp_context_get_jitter(stream->video_rtcp_ctx, FALSE)));
- json_object_set_new(video_rtcp_stats, "jitter-remote", json_integer(janus_rtcp_context_get_jitter(stream->video_rtcp_ctx, TRUE)));
- json_object_set_new(rtcp_stats, "video", video_rtcp_stats);
+ int vindex=0;
+ for(vindex=0; vindex<3; vindex++) {
+ if(stream->video_rtcp_ctx[vindex] != NULL) {
+ if(rtcp_stats == NULL)
+ rtcp_stats = json_object();
+ json_t *video_rtcp_stats = json_object();
+ json_object_set_new(video_rtcp_stats, "base", json_integer(stream->video_rtcp_ctx[vindex]->tb));
+ json_object_set_new(video_rtcp_stats, "lsr", json_integer(janus_rtcp_context_get_lsr(stream->video_rtcp_ctx[vindex])));
+ json_object_set_new(video_rtcp_stats, "lost", json_integer(janus_rtcp_context_get_lost_all(stream->video_rtcp_ctx[vindex], FALSE)));
+ json_object_set_new(video_rtcp_stats, "lost-by-remote", json_integer(janus_rtcp_context_get_lost_all(stream->video_rtcp_ctx[vindex], TRUE)));
+ json_object_set_new(video_rtcp_stats, "jitter-local", json_integer(janus_rtcp_context_get_jitter(stream->video_rtcp_ctx[vindex], FALSE)));
+ json_object_set_new(video_rtcp_stats, "jitter-remote", json_integer(janus_rtcp_context_get_jitter(stream->video_rtcp_ctx[vindex], TRUE)));
+ if(vindex == 0)
+ json_object_set_new(rtcp_stats, "video", video_rtcp_stats);
+ else if(vindex == 1)
+ json_object_set_new(rtcp_stats, "video-sim1", video_rtcp_stats);
+ else
+ json_object_set_new(rtcp_stats, "video-sim2", video_rtcp_stats);
+ }
}
if(rtcp_stats != NULL)
json_object_set_new(s, "rtcp_stats", rtcp_stats);
@@ -2553,16 +2565,16 @@ json_t *janus_admin_component_summary(janus_ice_component *component) {
if(dtls->dtls_connected > 0)
json_object_set_new(d, "connected", json_integer(dtls->dtls_connected));
if(handle && janus_flags_is_set(&handle->webrtc_flags, JANUS_ICE_HANDLE_WEBRTC_HAS_AUDIO)) {
- json_object_set_new(in_stats, "audio_packets", json_integer(component->in_stats.audio_packets));
- json_object_set_new(in_stats, "audio_bytes", json_integer(component->in_stats.audio_bytes));
+ json_object_set_new(in_stats, "audio_packets", json_integer(component->in_stats.audio.packets));
+ json_object_set_new(in_stats, "audio_bytes", json_integer(component->in_stats.audio.bytes));
json_object_set_new(in_stats, "do_audio_nacks", component->do_audio_nacks ? json_true() : json_false());
if(component->do_audio_nacks)
- json_object_set_new(in_stats, "audio_nacks", json_integer(component->in_stats.audio_nacks));
+ json_object_set_new(in_stats, "audio_nacks", json_integer(component->in_stats.audio.nacks));
/* Compute the last second stuff too */
gint64 now = janus_get_monotonic_time();
guint64 bytes = 0;
- if(component->in_stats.audio_bytes_lastsec) {
- GList *lastsec = g_queue_peek_head_link(component->in_stats.audio_bytes_lastsec);
+ if(component->in_stats.audio.bytes_lastsec) {
+ GList *lastsec = g_queue_peek_head_link(component->in_stats.audio.bytes_lastsec);
while(lastsec) {
janus_ice_stats_item *s = (janus_ice_stats_item *)lastsec->data;
if(s && now-s->when < G_USEC_PER_SEC)
@@ -2573,39 +2585,50 @@ json_t *janus_admin_component_summary(janus_ice_component *component) {
json_object_set_new(in_stats, "audio_bytes_lastsec", json_integer(bytes));
}
if(handle && janus_flags_is_set(&handle->webrtc_flags, JANUS_ICE_HANDLE_WEBRTC_HAS_VIDEO)) {
- json_object_set_new(in_stats, "video_packets", json_integer(component->in_stats.video_packets));
- json_object_set_new(in_stats, "video_bytes", json_integer(component->in_stats.video_bytes));
- json_object_set_new(in_stats, "do_video_nacks", component->do_video_nacks ? json_true() : json_false());
- if(component->do_video_nacks)
- json_object_set_new(in_stats, "video_nacks", json_integer(component->in_stats.video_nacks));
- /* Compute the last second stuff too */
- gint64 now = janus_get_monotonic_time();
- guint64 bytes = 0;
- if(component->in_stats.video_bytes_lastsec) {
- GList *lastsec = g_queue_peek_head_link(component->in_stats.video_bytes_lastsec);
- while(lastsec) {
- janus_ice_stats_item *s = (janus_ice_stats_item *)lastsec->data;
- if(s && now-s->when < G_USEC_PER_SEC)
- bytes += s->bytes;
- lastsec = lastsec->next;
+ int vindex=0;
+ for(vindex=0; vindex<3; vindex++) {
+ if(vindex > 0 && component->stream->video_ssrc_peer[vindex] == 0)
+ continue;
+ json_t *container = (vindex == 0 ? in_stats : json_object());
+ json_object_set_new(container, "video_packets", json_integer(component->in_stats.video[vindex].packets));
+ json_object_set_new(container, "video_bytes", json_integer(component->in_stats.video[vindex].bytes));
+ if(vindex == 0)
+ json_object_set_new(container, "do_video_nacks", component->do_video_nacks ? json_true() : json_false());
+ if(component->do_video_nacks)
+ json_object_set_new(container, "video_nacks", json_integer(component->in_stats.video[vindex].nacks));
+ /* Compute the last second stuff too */
+ gint64 now = janus_get_monotonic_time();
+ guint64 bytes = 0;
+ if(component->in_stats.video[vindex].bytes_lastsec) {
+ GList *lastsec = g_queue_peek_head_link(component->in_stats.video[vindex].bytes_lastsec);
+ while(lastsec) {
+ janus_ice_stats_item *s = (janus_ice_stats_item *)lastsec->data;
+ if(s && now-s->when < G_USEC_PER_SEC)
+ bytes += s->bytes;
+ lastsec = lastsec->next;
+ }
}
+ json_object_set_new(container, "video_bytes_lastsec", json_integer(bytes));
+ if(vindex == 1)
+ json_object_set_new(in_stats, "video-simulcast-1", container);
+ else if(vindex == 2)
+ json_object_set_new(in_stats, "video-simulcast-2", container);
}
- json_object_set_new(in_stats, "video_bytes_lastsec", json_integer(bytes));
}
- json_object_set_new(in_stats, "data_packets", json_integer(component->in_stats.data_packets));
- json_object_set_new(in_stats, "data_bytes", json_integer(component->in_stats.data_bytes));
+ json_object_set_new(in_stats, "data_packets", json_integer(component->in_stats.data.packets));
+ json_object_set_new(in_stats, "data_bytes", json_integer(component->in_stats.data.bytes));
if(handle && janus_flags_is_set(&handle->webrtc_flags, JANUS_ICE_HANDLE_WEBRTC_HAS_AUDIO)) {
- json_object_set_new(out_stats, "audio_packets", json_integer(component->out_stats.audio_packets));
- json_object_set_new(out_stats, "audio_bytes", json_integer(component->out_stats.audio_bytes));
- json_object_set_new(out_stats, "audio_nacks", json_integer(component->out_stats.audio_nacks));
+ json_object_set_new(out_stats, "audio_packets", json_integer(component->out_stats.audio.packets));
+ json_object_set_new(out_stats, "audio_bytes", json_integer(component->out_stats.audio.bytes));
+ json_object_set_new(out_stats, "audio_nacks", json_integer(component->out_stats.audio.nacks));
}
if(handle && janus_flags_is_set(&handle->webrtc_flags, JANUS_ICE_HANDLE_WEBRTC_HAS_VIDEO)) {
- json_object_set_new(out_stats, "video_packets", json_integer(component->out_stats.video_packets));
- json_object_set_new(out_stats, "video_bytes", json_integer(component->out_stats.video_bytes));
- json_object_set_new(out_stats, "video_nacks", json_integer(component->out_stats.video_nacks));
+ json_object_set_new(out_stats, "video_packets", json_integer(component->out_stats.video[0].packets));
+ json_object_set_new(out_stats, "video_bytes", json_integer(component->out_stats.video[0].bytes));
+ json_object_set_new(out_stats, "video_nacks", json_integer(component->out_stats.video[0].nacks));
}
- json_object_set_new(out_stats, "data_packets", json_integer(component->out_stats.data_packets));
- json_object_set_new(out_stats, "data_bytes", json_integer(component->out_stats.data_bytes));
+ json_object_set_new(out_stats, "data_packets", json_integer(component->out_stats.data.packets));
+ json_object_set_new(out_stats, "data_bytes", json_integer(component->out_stats.data.bytes));
#ifdef HAVE_SCTP
/* FIXME Actually check if this succeeded? */
json_object_set_new(d, "sctp-association", dtls->sctp ? json_true() : json_false());
@@ -3000,10 +3023,10 @@ json_t *janus_plugin_handle_sdp(janus_plugin_session *plugin_session, janus_plug
if(ice_handle->audio_stream->rtp_component && ice_handle->video_stream->rtp_component)
ice_handle->audio_stream->rtp_component->do_video_nacks = ice_handle->video_stream->rtp_component->do_video_nacks;
ice_handle->audio_stream->video_ssrc = ice_handle->video_stream->video_ssrc;
- ice_handle->audio_stream->video_ssrc_peer = ice_handle->video_stream->video_ssrc_peer;
+ ice_handle->audio_stream->video_ssrc_peer[0] = ice_handle->video_stream->video_ssrc_peer[0];
ice_handle->audio_stream->video_ssrc_peer_rtx = ice_handle->video_stream->video_ssrc_peer_rtx;
- ice_handle->audio_stream->video_ssrc_peer_sim_1 = ice_handle->video_stream->video_ssrc_peer_sim_1;
- ice_handle->audio_stream->video_ssrc_peer_sim_2 = ice_handle->video_stream->video_ssrc_peer_sim_2;
+ ice_handle->audio_stream->video_ssrc_peer[1] = ice_handle->video_stream->video_ssrc_peer[1];
+ ice_handle->audio_stream->video_ssrc_peer[2] = ice_handle->video_stream->video_ssrc_peer[2];
nice_agent_attach_recv(ice_handle->agent, ice_handle->video_stream->stream_id, 1, g_main_loop_get_context (ice_handle->iceloop), NULL, NULL);
if(!ice_handle->force_rtcp_mux && !janus_ice_is_rtcpmux_forced())
nice_agent_attach_recv(ice_handle->agent, ice_handle->video_stream->stream_id, 2, g_main_loop_get_context (ice_handle->iceloop), NULL, NULL);
@@ -3023,9 +3046,13 @@ json_t *janus_plugin_handle_sdp(janus_plugin_session *plugin_session, janus_plug
if(ice_handle->audio_stream->rtp_component)
ice_handle->audio_stream->rtp_component->do_video_nacks = FALSE;
ice_handle->audio_stream->video_ssrc = 0;
- ice_handle->audio_stream->video_ssrc_peer = 0;
- g_free(ice_handle->audio_stream->video_rtcp_ctx);
- ice_handle->audio_stream->video_rtcp_ctx = NULL;
+ ice_handle->audio_stream->video_ssrc_peer[0] = 0;
+ g_free(ice_handle->audio_stream->video_rtcp_ctx[0]);
+ ice_handle->audio_stream->video_rtcp_ctx[0] = NULL;
+ g_free(ice_handle->audio_stream->video_rtcp_ctx[1]);
+ ice_handle->audio_stream->video_rtcp_ctx[1] = NULL;
+ g_free(ice_handle->audio_stream->video_rtcp_ctx[2]);
+ ice_handle->audio_stream->video_rtcp_ctx[2] = NULL;
}
} else if(video) {
/* Get rid of data, if present */
diff --git a/rtcp.c b/rtcp.c
index 5507145..17fe671 100644
--- a/rtcp.c
+++ b/rtcp.c
@@ -162,8 +162,8 @@ int janus_rtcp_fix_ssrc(rtcp_context *ctx, char *packet, int len, int fixssrc, u
case RTCP_SR: {
/* SR, sender report */
JANUS_LOG(LOG_HUGE, " #%d SR (200)\n", pno);
- rtcp_sr *sr = (rtcp_sr*)rtcp;
- /* RTCP context provided, update it with info on this SR */
+ rtcp_sr *sr = (rtcp_sr *)rtcp;
+ /* If an RTCP context was provided, update it with info on this SR */
janus_rtcp_incoming_sr(ctx, sr);
if(fixssrc && newssrcl) {
sr->ssrc = htonl(newssrcl);
@@ -176,11 +176,9 @@ int janus_rtcp_fix_ssrc(rtcp_context *ctx, char *packet, int len, int fixssrc, u
case RTCP_RR: {
/* RR, receiver report */
JANUS_LOG(LOG_HUGE, " #%d RR (201)\n", pno);
- rtcp_rr *rr = (rtcp_rr*)rtcp;
- if(ctx != NULL) {
- /* RTCP context provided, update it with info on this SR */
- janus_rtcp_incoming_rr(ctx, rr);
- }
+ rtcp_rr *rr = (rtcp_rr *)rtcp;
+ /* If an RTCP context was provided, update it with info on this RR */
+ janus_rtcp_incoming_rr(ctx, rr);
if(fixssrc && newssrcl) {
rr->ssrc = htonl(newssrcl);
}
diff --git a/sdp.c b/sdp.c
index 1f13d91..d8de5d4 100644
--- a/sdp.c
+++ b/sdp.c
@@ -351,6 +351,14 @@ int janus_sdp_process(void *ice_handle, janus_sdp *remote_sdp) {
}
tempA = tempA->next;
}
+ if(stream->video_ssrc_peer[1] && stream->video_rtcp_ctx[1] == NULL) {
+ stream->video_rtcp_ctx[1] = g_malloc0(sizeof(rtcp_context));
+ stream->video_rtcp_ctx[1]->tb = 90000;
+ }
+ if(stream->video_ssrc_peer[2] && stream->video_rtcp_ctx[2] == NULL) {
+ stream->video_rtcp_ctx[2] = g_malloc0(sizeof(rtcp_context));
+ stream->video_rtcp_ctx[2]->tb = 90000;
+ }
temp = temp->next;
}
if(ruser)
@@ -605,16 +613,16 @@ int janus_sdp_parse_ssrc_group(void *ice_stream, const char *group_attr, int vid
ssrc = g_ascii_strtoull(index, NULL, 0);
switch(i) {
case 1:
- stream->video_ssrc_peer = ssrc;
- JANUS_LOG(LOG_VERB, "[%"SCNu64"] Peer video SSRC: %"SCNu32"\n", handle->handle_id, stream->video_ssrc_peer);
+ stream->video_ssrc_peer[0] = ssrc;
+ JANUS_LOG(LOG_VERB, "[%"SCNu64"] Peer video SSRC: %"SCNu32"\n", handle->handle_id, stream->video_ssrc_peer[0]);
break;
case 2:
if(fid) {
stream->video_ssrc_peer_rtx = ssrc;
JANUS_LOG(LOG_VERB, "[%"SCNu64"] Peer video SSRC (rtx): %"SCNu32"\n", handle->handle_id, stream->video_ssrc_peer_rtx);
} else if(sim) {
- stream->video_ssrc_peer_sim_1 = ssrc;
- JANUS_LOG(LOG_VERB, "[%"SCNu64"] Peer video SSRC (sim-1): %"SCNu32"\n", handle->handle_id, stream->video_ssrc_peer_sim_1);
+ stream->video_ssrc_peer[1] = ssrc;
+ JANUS_LOG(LOG_VERB, "[%"SCNu64"] Peer video SSRC (sim-1): %"SCNu32"\n", handle->handle_id, stream->video_ssrc_peer[1]);
} else {
JANUS_LOG(LOG_WARN, "[%"SCNu64"] Don't know what to do with SSRC: %"SCNu64"\n", handle->handle_id, ssrc);
}
@@ -623,8 +631,8 @@ int janus_sdp_parse_ssrc_group(void *ice_stream, const char *group_attr, int vid
if(fid) {
JANUS_LOG(LOG_WARN, "[%"SCNu64"] Found one too many retransmission SSRC (rtx): %"SCNu64"\n", handle->handle_id, ssrc);
} else if(sim) {
- stream->video_ssrc_peer_sim_2 = ssrc;
- JANUS_LOG(LOG_VERB, "[%"SCNu64"] Peer video SSRC (sim-2): %"SCNu32"\n", handle->handle_id, stream->video_ssrc_peer_sim_2);
+ stream->video_ssrc_peer[2] = ssrc;
+ JANUS_LOG(LOG_VERB, "[%"SCNu64"] Peer video SSRC (sim-2): %"SCNu32"\n", handle->handle_id, stream->video_ssrc_peer[2]);
} else {
JANUS_LOG(LOG_WARN, "[%"SCNu64"] Don't know what to do with SSRC: %"SCNu64"\n", handle->handle_id, ssrc);
}
@@ -654,17 +662,17 @@ int janus_sdp_parse_ssrc(void *ice_stream, const char *ssrc_attr, int video) {
return -3;
if(video) {
if(stream->video_ssrc_peer == 0) {
- stream->video_ssrc_peer = ssrc;
- JANUS_LOG(LOG_VERB, "[%"SCNu64"] Peer video SSRC: %"SCNu32"\n", handle->handle_id, stream->video_ssrc_peer);
+ stream->video_ssrc_peer[0] = ssrc;
+ JANUS_LOG(LOG_VERB, "[%"SCNu64"] Peer video SSRC: %"SCNu32"\n", handle->handle_id, stream->video_ssrc_peer[0]);
} else {
/* We already have a video SSRC: check if RID is involved, and we'll keep track of this for simulcasting */
if(stream->rid[0]) {
- if(stream->video_ssrc_peer_sim_1 == 0) {
- stream->video_ssrc_peer_sim_1 = ssrc;
- JANUS_LOG(LOG_VERB, "[%"SCNu64"] Peer video SSRC (sim-1): %"SCNu32"\n", handle->handle_id, stream->video_ssrc_peer_sim_1);
- } else if(stream->video_ssrc_peer_sim_2 == 0) {
- stream->video_ssrc_peer_sim_2 = ssrc;
- JANUS_LOG(LOG_VERB, "[%"SCNu64"] Peer video SSRC (sim-2): %"SCNu32"\n", handle->handle_id, stream->video_ssrc_peer_sim_2);
+ if(stream->video_ssrc_peer[1] == 0) {
+ stream->video_ssrc_peer[1] = ssrc;
+ JANUS_LOG(LOG_VERB, "[%"SCNu64"] Peer video SSRC (sim-1): %"SCNu32"\n", handle->handle_id, stream->video_ssrc_peer[1]);
+ } else if(stream->video_ssrc_peer[2] == 0) {
+ stream->video_ssrc_peer[2] = ssrc;
+ JANUS_LOG(LOG_VERB, "[%"SCNu64"] Peer video SSRC (sim-2): %"SCNu32"\n", handle->handle_id, stream->video_ssrc_peer[2]);
} else {
JANUS_LOG(LOG_WARN, "[%"SCNu64"] Don't know what to do with video SSRC: %"SCNu64"\n", handle->handle_id, ssrc);
}
--
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-voip/janus.git
More information about the Pkg-voip-commits
mailing list