Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

PLI dilution (Multistream) #3423

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
86 changes: 46 additions & 40 deletions src/plugins/janus_videoroom.c
Original file line number Diff line number Diff line change
Expand Up @@ -2903,13 +2903,22 @@ static void janus_videoroom_codecstr(janus_videoroom *videoroom, char *audio_cod
}
}

/* Helper method to send an RTCP PLI to a remote publisher */
static void janus_videoroom_rtcp_pli_send(janus_videoroom_publisher_stream *ps) {
if(ps == NULL || ps->publisher == NULL)
return;
janus_videoroom_publisher *publisher = ps->publisher;
if(publisher->remote_rtcp_fd < 0 || publisher->rtcp_addr.ss_family == 0)
/* Helper method to send PLI to publishers.
* Send an PLI to local publisher and RTCP PLI to a remote publishers */
static void janus_videoroom_reqpli(janus_videoroom_publisher_stream *ps, const char *reason) {
if (ps == NULL || g_atomic_int_get(&ps->destroyed))
return;

janus_videoroom_publisher *remote_publisher = NULL;

if(ps->publisher->remote) {
if(ps->publisher == NULL || g_atomic_int_get(&ps->publisher->destroyed))
return;
remote_publisher = ps->publisher;
if(remote_publisher->remote_rtcp_fd < 0 || remote_publisher->rtcp_addr.ss_family == 0)
return;
}

if(!g_atomic_int_compare_and_exchange(&ps->sending_pli, 0, 1))
return;
gint64 now = janus_get_monotonic_time();
Expand All @@ -2919,44 +2928,38 @@ static void janus_videoroom_rtcp_pli_send(janus_videoroom_publisher_stream *ps)
g_atomic_int_set(&ps->sending_pli, 0);
return;
}

JANUS_LOG(LOG_VERB, "%s, sending PLI to %s (#%d, %s)\n", reason,
ps->publisher->user_id_str, ps->mindex, ps->publisher->display ? ps->publisher->display : "??");

/* Update the time of when we last sent a keyframe request */
g_atomic_int_set(&ps->need_pli, 0);
ps->pli_latest = janus_get_monotonic_time();
JANUS_LOG(LOG_HUGE, "Sending PLI\n");
/* Generate a PLI */
char rtcp_buf[12];
int rtcp_len = 12;
janus_rtcp_pli((char *)&rtcp_buf, rtcp_len);
uint32_t ssrc = REMOTE_PUBLISHER_BASE_SSRC + (ps->mindex*REMOTE_PUBLISHER_SSRC_STEP);
janus_rtcp_fix_ssrc(NULL, rtcp_buf, rtcp_len, 1, 1, ssrc);
/* Send the packet */
socklen_t addrlen = publisher->rtcp_addr.ss_family == AF_INET ? sizeof(struct sockaddr_in) : sizeof(struct sockaddr_in6);
int sent = 0;
if((sent = sendto(publisher->remote_rtcp_fd, rtcp_buf, rtcp_len, 0,
(struct sockaddr *)&publisher->rtcp_addr, addrlen)) < 0) {
JANUS_LOG(LOG_ERR, "Error in sendto... %d (%s)\n", errno, g_strerror(errno));
} else {
JANUS_LOG(LOG_HUGE, "Sent %d/%d bytes\n", sent, rtcp_len);
}
g_atomic_int_set(&ps->sending_pli, 0);
}
/* Update the time of when we last sent a keyframe request */
ps->fir_latest = ps->pli_latest;

static void janus_videoroom_reqpli(janus_videoroom_publisher_stream *ps, const char *reason) {
if(ps == NULL || g_atomic_int_get(&ps->destroyed) || ps->publisher == NULL || g_atomic_int_get(&ps->publisher->destroyed))
return;
/* Send a PLI */
JANUS_LOG(LOG_VERB, "%s sending PLI to %s (#%d, %s)\n", reason,
ps->publisher->user_id_str, ps->mindex, ps->publisher->display ? ps->publisher->display : "??");
if(!ps->publisher->remote) {
/* Easy enough, local publisher so we ask the Janus core to send a PLI */
if (!remote_publisher) {
/* local publisher so we ask the Janus core to send a PLI */
gateway->send_pli_stream(ps->publisher->session->handle, ps->mindex);
} else {
/* This is a remote publisher, so we'll need to send a PLI to the remote RTCP address */
JANUS_LOG(LOG_VERB, "Sending PLI to remote publisher\n");
janus_videoroom_rtcp_pli_send(ps);
/* Generate a PLI */
char rtcp_buf[12];
int rtcp_len = 12;
janus_rtcp_pli((char *)&rtcp_buf, rtcp_len);
uint32_t ssrc = REMOTE_PUBLISHER_BASE_SSRC + (ps->mindex*REMOTE_PUBLISHER_SSRC_STEP);
janus_rtcp_fix_ssrc(NULL, rtcp_buf, rtcp_len, 1, 1, ssrc);
/* Send the packet */
socklen_t addrlen = remote_publisher->rtcp_addr.ss_family == AF_INET ? sizeof(struct sockaddr_in) : sizeof(struct sockaddr_in6);
int sent = 0;
if((sent = sendto(remote_publisher->remote_rtcp_fd, rtcp_buf, rtcp_len, 0,
(struct sockaddr *)&remote_publisher->rtcp_addr, addrlen)) < 0) {
JANUS_LOG(LOG_ERR, "Error in sendto... %d (%s)\n", errno, g_strerror(errno));
} else {
JANUS_LOG(LOG_HUGE, "Sent %d/%d bytes\n", sent, rtcp_len);
}
}
/* Update the time of when we last sent a keyframe request */
ps->fir_latest = janus_get_monotonic_time();

g_atomic_int_set(&ps->sending_pli, 0);
}

/* Error codes */
Expand Down Expand Up @@ -10004,9 +10007,12 @@ static void *janus_videoroom_handler(void *data) {
json_t *sc_substream = json_object_get(s, "substream");
if(json_integer_value(spatial) < 0 || json_integer_value(spatial) > 2 ||
json_integer_value(sc_substream) < 0 || json_integer_value(sc_substream) > 2) {
JANUS_LOG(LOG_ERR, "Invalid element (substream/spatial_layer should be 0, 1 or 2)\n");
/*JANUS_LOG(LOG_ERR, "Invalid element (substream/spatial_layer should be 0, 1 or 2)\n");*/
error_code = JANUS_VIDEOROOM_ERROR_INVALID_ELEMENT;
g_snprintf(error_cause, 512, "Invalid value (substream/spatial_layer should be 0, 1 or 2)");
/* g_snprintf(error_cause, 512, "Invalid value (substream/spatial_layer should be 0, 1 or 2)"); */
g_snprintf(error_cause, 512, "Invalid value (substream(%lld)/spatial_layer(%lld) should be 0, 1 or 2)",
json_integer_value(sc_substream), json_integer_value(spatial));
JANUS_LOG(LOG_ERR, "Invalid element, %s\n", error_cause);
janus_mutex_unlock(&videoroom->mutex);
/* Unref publishers we may have taken note of so far */
while(publishers) {
Expand Down Expand Up @@ -13552,7 +13558,7 @@ static void *janus_videoroom_remote_publisher_thread(void *user_data) {
ps = (janus_videoroom_publisher_stream *)temp->data;
/* Any PLI and/or REMB we should send back to the source? */
if(ps->type == JANUS_VIDEOROOM_MEDIA_VIDEO && g_atomic_int_get(&ps->need_pli))
janus_videoroom_rtcp_pli_send(ps);
janus_videoroom_reqpli(ps, "Delayed PLI request");
temp = temp->next;
}
janus_mutex_unlock(&publisher->streams_mutex);
Expand Down
9 changes: 6 additions & 3 deletions src/rtp.c
Original file line number Diff line number Diff line change
Expand Up @@ -1218,7 +1218,8 @@ gboolean janus_rtp_simulcasting_context_process_rtp(janus_rtp_simulcasting_conte
context->last_relayed = now;
} else if(context->substream > 0) {
/* Check if too much time went by with no packet relayed */
if((now - context->last_relayed) > (context->drop_trigger ? context->drop_trigger : 250000)) {
gint64 delayMicrosec = (now - context->last_relayed);
if(delayMicrosec > (context->drop_trigger ? context->drop_trigger : 250000)) {
context->last_relayed = now;
if(context->substream != substream && context->substream_target_temp != 0) {
if(context->substream_target > substream) {
Expand All @@ -1230,8 +1231,10 @@ gboolean janus_rtp_simulcasting_context_process_rtp(janus_rtp_simulcasting_conte
if(context->substream_target_temp < 0)
context->substream_target_temp = 0;
if(context->substream_target_temp != prev_target) {
JANUS_LOG(LOG_WARN, "No packet received on substream %d for a while, falling back to %d\n",
context->substream, context->substream_target_temp);

JANUS_LOG(LOG_WARN, "No packet received on substream %d for %"SCNi64" Milliseconds, falling back to %d\n",
context->substream, (delayMicrosec / 1000), context->substream_target_temp);

/* Notify the caller that we (still) need a PLI */
context->need_pli = TRUE;
}
Expand Down