[Pkg-voip-commits] [janus] 22/163: Some fixes and enhancements in VideoRoom simulcasting
Jonas Smedegaard
dr at jones.dk
Sat Oct 28 01:22:05 UTC 2017
This is an automated email from the git hooks/post-receive script.
js pushed a commit to annotated tag debian/0.2.5-1
in repository janus.
commit 50162f9e7b4ffb7d9733bf1465051ee69792c0d1
Author: Lorenzo Miniero <lminiero at gmail.com>
Date: Mon Jul 10 19:42:26 2017 +0200
Some fixes and enhancements in VideoRoom simulcasting
---
html/videoroomtest.js | 1 +
plugins/janus_videoroom.c | 155 +++++++++++++++++++---------------------------
2 files changed, 66 insertions(+), 90 deletions(-)
diff --git a/html/videoroomtest.js b/html/videoroomtest.js
index a241145..d14c15f 100644
--- a/html/videoroomtest.js
+++ b/html/videoroomtest.js
@@ -568,6 +568,7 @@ function newRemoteFeed(id, display) {
if(bitrateTimer[remoteFeed.rfindex] !== null && bitrateTimer[remoteFeed.rfindex] !== null)
clearInterval(bitrateTimer[remoteFeed.rfindex]);
bitrateTimer[remoteFeed.rfindex] = null;
+ remoteFeed.simulcastStarted = false;
$('#simulcast'+remoteFeed.rfindex).remove();
}
});
diff --git a/plugins/janus_videoroom.c b/plugins/janus_videoroom.c
index 7bfb9a3..0de7cfe 100644
--- a/plugins/janus_videoroom.c
+++ b/plugins/janus_videoroom.c
@@ -539,7 +539,7 @@ typedef struct janus_videoroom_participant {
gboolean recording_active; /* Whether this publisher has to be recorded or not */
gchar *recording_base; /* Base name for the recording (e.g., /path/to/filename, will generate /path/to/filename-audio.mjr and/or /path/to/filename-video.mjr */
janus_recorder *arc; /* The Janus recorder instance for this publisher's audio, if enabled */
- janus_recorder *vrc[3]; /* The Janus recorder instance for this user's video, if enabled (there may be more if we're simulcasting) */
+ janus_recorder *vrc; /* The Janus recorder instance for this user's video, if enabled */
janus_recorder *drc; /* The Janus recorder instance for this publisher's data, if enabled */
janus_mutex rec_mutex; /* Mutex to protect the recorders from race conditions */
GSList *listeners; /* Subscriptions to this publisher (who's watching this publisher) */
@@ -565,6 +565,7 @@ typedef struct janus_videoroom_listener {
int substream_target; /* As above, but to handle transitions (e.g., wait for keyframe) */
int templayer; /* Which simulcast temporal layer we should forward, in case the publisher is simulcasting */
int templayer_target; /* As above, but to handle transitions (e.g., wait for keyframe) */
+ gint64 last_relayed; /* When we relayed the last packet (used to detect when substreams become unavailable) */
janus_vp8_simulcast_context simulcast_context;
gboolean audio, video, data; /* Whether audio, video and/or data must be sent to this publisher */
gboolean paused;
@@ -1165,16 +1166,12 @@ json_t *janus_videoroom_query_session(janus_plugin_session *handle) {
json_object_set_new(info, "bitrate", json_integer(participant->bitrate));
if(participant->ssrc[0] != 0)
json_object_set_new(info, "simulcast", json_true());
- if(participant->arc || participant->vrc[0] || participant->drc) {
+ if(participant->arc || participant->vrc || participant->drc) {
json_t *recording = json_object();
if(participant->arc && participant->arc->filename)
json_object_set_new(recording, "audio", json_string(participant->arc->filename));
- if(participant->vrc[0] && participant->vrc[0]->filename)
- json_object_set_new(recording, "video", json_string(participant->vrc[0]->filename));
- if(participant->vrc[1] && participant->vrc[1]->filename)
- json_object_set_new(recording, "video-sim1", json_string(participant->vrc[1]->filename));
- if(participant->vrc[2] && participant->vrc[2]->filename)
- json_object_set_new(recording, "video-sim2", json_string(participant->vrc[2]->filename));
+ if(participant->vrc && participant->vrc->filename)
+ json_object_set_new(recording, "video", json_string(participant->vrc->filename));
if(participant->drc && participant->drc->filename)
json_object_set_new(recording, "data", json_string(participant->drc->filename));
json_object_set_new(info, "recording", recording);
@@ -2430,9 +2427,9 @@ void janus_videoroom_incoming_rtp(janus_plugin_session *handle, int video, char
rtp->ssrc = htonl(ssrc);
}
janus_mutex_unlock(&participant->rtp_forwarders_mutex);
+ /* Save the frame if we're recording */
+ janus_recorder_save_frame(video ? participant->vrc : participant->arc, buf, len);
}
- /* Save the frame if we're recording */
- janus_recorder_save_frame(video ? (sc < 0 ? participant->vrc[0] : participant->vrc[sc]) : participant->arc, buf, len);
/* Done, relay it */
janus_videoroom_rtp_relay_packet packet;
packet.data = rtp;
@@ -2646,52 +2643,20 @@ static void janus_videoroom_recorder_create(janus_videoroom_participant *partici
if(participant->recording_base) {
/* Use the filename and path we have been provided */
g_snprintf(filename, 255, "%s-video", participant->recording_base);
- participant->vrc[0] = janus_recorder_create(participant->room->rec_dir,
+ participant->vrc = janus_recorder_create(participant->room->rec_dir,
janus_videoroom_videocodec_name(participant->room->vcodec), filename);
- if(participant->vrc[0] == NULL) {
+ if(participant->vrc == NULL) {
JANUS_LOG(LOG_ERR, "Couldn't open an video recording file for this publisher!\n");
}
- if(participant->ssrc[0] != 0) {
- /* Create recordings for the other layers as well */
- g_snprintf(filename, 255, "%s-video-sim1", participant->recording_base);
- participant->vrc[1] = janus_recorder_create(participant->room->rec_dir,
- janus_videoroom_videocodec_name(participant->room->vcodec), filename);
- if(participant->vrc[1] == NULL) {
- JANUS_LOG(LOG_ERR, "Couldn't open an video recording file (simulcasting #1) for this publisher!\n");
- }
- g_snprintf(filename, 255, "%s-video-sim2", participant->recording_base);
- participant->vrc[2] = janus_recorder_create(participant->room->rec_dir,
- janus_videoroom_videocodec_name(participant->room->vcodec), filename);
- if(participant->vrc[2] == NULL) {
- JANUS_LOG(LOG_ERR, "Couldn't open an video recording file (simulcasting #2) for this publisher!\n");
- }
- }
} else {
/* Build a filename */
g_snprintf(filename, 255, "videoroom-%"SCNu64"-user-%"SCNu64"-%"SCNi64"-video",
participant->room->room_id, participant->user_id, now);
- participant->vrc[0] = janus_recorder_create(participant->room->rec_dir,
+ participant->vrc = janus_recorder_create(participant->room->rec_dir,
janus_videoroom_videocodec_name(participant->room->vcodec), filename);
- if(participant->vrc[0] == NULL) {
+ if(participant->vrc == NULL) {
JANUS_LOG(LOG_ERR, "Couldn't open an video recording file for this publisher!\n");
}
- if(participant->ssrc[0] != 0) {
- /* Create recordings for the other layers as well */
- g_snprintf(filename, 255, "videoroom-%"SCNu64"-user-%"SCNu64"-%"SCNi64"-video-sim1",
- participant->room->room_id, participant->user_id, now);
- participant->vrc[1] = janus_recorder_create(participant->room->rec_dir,
- janus_videoroom_videocodec_name(participant->room->vcodec), filename);
- if(participant->vrc[1] == NULL) {
- JANUS_LOG(LOG_ERR, "Couldn't open an video recording file (simulcasting #1) for this publisher!\n");
- }
- g_snprintf(filename, 255, "videoroom-%"SCNu64"-user-%"SCNu64"-%"SCNi64"-video-sim2",
- participant->room->room_id, participant->user_id, now);
- participant->vrc[2] = janus_recorder_create(participant->room->rec_dir,
- janus_videoroom_videocodec_name(participant->room->vcodec), filename);
- if(participant->vrc[2] == NULL) {
- JANUS_LOG(LOG_ERR, "Couldn't open an video recording file (simulcasting #2) for this publisher!\n");
- }
- }
}
}
if(data) {
@@ -2724,24 +2689,12 @@ static void janus_videoroom_recorder_close(janus_videoroom_participant *particip
janus_recorder_free(participant->arc);
}
participant->arc = NULL;
- if(participant->vrc[0]) {
- janus_recorder_close(participant->vrc[0]);
- JANUS_LOG(LOG_INFO, "Closed video recording %s\n", participant->vrc[0]->filename ? participant->vrc[0]->filename : "??");
- janus_recorder_free(participant->vrc[0]);
+ if(participant->vrc) {
+ janus_recorder_close(participant->vrc);
+ JANUS_LOG(LOG_INFO, "Closed video recording %s\n", participant->vrc->filename ? participant->vrc->filename : "??");
+ janus_recorder_free(participant->vrc);
}
- participant->vrc[0] = NULL;
- if(participant->vrc[1]) {
- janus_recorder_close(participant->vrc[1]);
- JANUS_LOG(LOG_INFO, "Closed video recording %s (simulcasting #1)\n", participant->vrc[1]->filename ? participant->vrc[1]->filename : "??");
- janus_recorder_free(participant->vrc[1]);
- }
- participant->vrc[1] = NULL;
- if(participant->vrc[2]) {
- janus_recorder_close(participant->vrc[2]);
- JANUS_LOG(LOG_INFO, "Closed video recording %s (simulcasting #2)\n", participant->vrc[2]->filename ? participant->vrc[2]->filename : "??");
- janus_recorder_free(participant->vrc[2]);
- }
- participant->vrc[2] = NULL;
+ participant->vrc = NULL;
if(participant->drc) {
janus_recorder_close(participant->drc);
JANUS_LOG(LOG_INFO, "Closed data recording %s\n", participant->drc->filename ? participant->drc->filename : "??");
@@ -2985,9 +2938,7 @@ static void *janus_videoroom_handler(void *data) {
publisher->recording_active = FALSE;
publisher->recording_base = NULL;
publisher->arc = NULL;
- publisher->vrc[0] = NULL;
- publisher->vrc[1] = NULL;
- publisher->vrc[2] = NULL;
+ publisher->vrc = NULL;
publisher->drc = NULL;
janus_mutex_init(&publisher->rec_mutex);
publisher->firefox = FALSE;
@@ -3178,9 +3129,10 @@ static void *janus_videoroom_handler(void *data) {
listener->data = FALSE; /* ... unless the publisher isn't sending any data */
listener->paused = TRUE; /* We need an explicit start from the listener */
listener->substream = -1;
- listener->substream_target = 0;
+ listener->substream_target = 2;
listener->templayer = -1;
listener->templayer_target = 2;
+ listener->last_relayed = 0;
janus_vp8_simulcast_context_reset(&listener->simulcast_context);
session->participant = listener;
janus_mutex_lock(&publisher->listeners_mutex);
@@ -3387,16 +3339,12 @@ static void *janus_videoroom_handler(void *data) {
json_object_set_new(info, "video_active", participant->video_active ? json_true() : json_false());
json_object_set_new(info, "data_active", participant->data_active ? json_true() : json_false());
json_object_set_new(info, "bitrate", json_integer(participant->bitrate));
- if(participant->arc || participant->vrc[0] || participant->drc) {
+ if(participant->arc || participant->vrc || participant->drc) {
json_t *recording = json_object();
if(participant->arc && participant->arc->filename)
json_object_set_new(recording, "audio", json_string(participant->arc->filename));
- if(participant->vrc[0] && participant->vrc[0]->filename)
- json_object_set_new(recording, "video", json_string(participant->vrc[0]->filename));
- if(participant->vrc[1] && participant->vrc[1]->filename)
- json_object_set_new(recording, "video-sim1", json_string(participant->vrc[1]->filename));
- if(participant->vrc[2] && participant->vrc[2]->filename)
- json_object_set_new(recording, "video-sim2", json_string(participant->vrc[2]->filename));
+ if(participant->vrc && participant->vrc->filename)
+ json_object_set_new(recording, "video", json_string(participant->vrc->filename));
if(participant->drc && participant->drc->filename)
json_object_set_new(recording, "data", json_string(participant->drc->filename));
json_object_set_new(info, "recording", recording);
@@ -4046,13 +3994,14 @@ static void janus_videoroom_relay_rtp_packet(gpointer data, gpointer user_data)
gboolean switched = FALSE;
if(listener->substream != listener->substream_target) {
/* There has been a change: let's wait for a keyframe on the target */
- if(ssrc == packet->ssrc[listener->substream_target]) {
- if(janus_vp8_is_keyframe(payload, plen)) {
+ int step = (listener->substream < 1 && listener->substream_target == 2);
+ if(ssrc == packet->ssrc[listener->substream_target] || (step && ssrc == packet->ssrc[step])) {
+ //~ if(janus_vp8_is_keyframe(payload, plen)) {
uint32_t ssrc_old = 0;
if(listener->substream != -1)
ssrc_old = packet->ssrc[listener->substream];
JANUS_LOG(LOG_WARN, "Received keyframe on SSRC %"SCNu32", switching (was %"SCNu32")\n", ssrc, ssrc_old);
- listener->substream = listener->substream_target;
+ listener->substream = (ssrc == packet->ssrc[listener->substream_target] ? listener->substream_target : step);;
switched = TRUE;
/* Notify the viewer */
json_t *event = json_object();
@@ -4061,8 +4010,41 @@ static void janus_videoroom_relay_rtp_packet(gpointer data, gpointer user_data)
json_object_set_new(event, "substream", json_integer(listener->substream));
gateway->push_event(listener->session->handle, &janus_videoroom_plugin, NULL, event, NULL);
json_decref(event);
- } else {
- JANUS_LOG(LOG_WARN, "Not a keyframe on SSRC %"SCNu32" yet, waiting before switching\n", ssrc);
+ //~ } else {
+ //~ JANUS_LOG(LOG_WARN, "Not a keyframe on SSRC %"SCNu32" yet, waiting before switching\n", ssrc);
+ //~ }
+ }
+ }
+ /* If we haven't received our desired substream yet, let's drop temporarily */
+ if(listener->last_relayed == 0) {
+ /* Let's start slow */
+ listener->last_relayed = janus_get_monotonic_time();
+ } else {
+ /* Check if 250ms went by with no packet relayed */
+ gint64 now = janus_get_monotonic_time();
+ if(now-listener->last_relayed >= 250000) {
+ listener->last_relayed = now;
+ int substream = listener->substream-1;
+ if(substream < 0)
+ substream = 0;
+ if(listener->substream != substream) {
+ JANUS_LOG(LOG_WARN, "No packet received on substream %d for a while, falling back to %d\n",
+ listener->substream, substream);
+ listener->substream = substream;
+ /* Send a PLI */
+ JANUS_LOG(LOG_VERB, "Just (re-)enabled video, sending a PLI to recover it\n");
+ char rtcpbuf[12];
+ memset(rtcpbuf, 0, 12);
+ janus_rtcp_pli((char *)&rtcpbuf, 12);
+ if(listener->feed && listener->feed->session && listener->feed->session->handle)
+ gateway->relay_rtcp(listener->feed->session->handle, 1, rtcpbuf, 12);
+ /* Notify the viewer */
+ json_t *event = json_object();
+ json_object_set_new(event, "videoroom", json_string("event"));
+ json_object_set_new(event, "room", json_integer(listener->room->room_id));
+ json_object_set_new(event, "substream", json_integer(listener->substream));
+ gateway->push_event(listener->session->handle, &janus_videoroom_plugin, NULL, event, NULL);
+ json_decref(event);
}
}
}
@@ -4071,6 +4053,7 @@ static void janus_videoroom_relay_rtp_packet(gpointer data, gpointer user_data)
ssrc, packet->ssrc[listener->substream]);
return;
}
+ listener->last_relayed = janus_get_monotonic_time();
/* Check if there's any temporal scalability to take into account */
uint16_t picid = 0;
uint8_t tlzi = 0;
@@ -4192,17 +4175,9 @@ static void janus_videoroom_participant_free(janus_videoroom_participant *p) {
janus_recorder_free(p->arc);
p->arc = NULL;
}
- if(p->vrc[0]) {
- janus_recorder_free(p->vrc[0]);
- p->vrc[0] = NULL;
- }
- if(p->vrc[1]) {
- janus_recorder_free(p->vrc[1]);
- p->vrc[1] = NULL;
- }
- if(p->vrc[2]) {
- janus_recorder_free(p->vrc[2]);
- p->vrc[2] = NULL;
+ if(p->vrc) {
+ janus_recorder_free(p->vrc);
+ p->vrc = NULL;
}
if(p->drc) {
janus_recorder_free(p->drc);
--
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