From b94a89d20ed40f273a1bb84a838388fba1474ce5 Mon Sep 17 00:00:00 2001 From: Lorenzo Miniero Date: Wed, 3 Nov 2021 10:20:36 +0100 Subject: [PATCH] Initial support for DTX (EchoTest, VideoRoom) (#2789) --- conf/janus.plugin.videoroom.jcfg.sample | 5 +- html/echotest.js | 8 +++ html/videoroomtest.js | 15 ++++++ plugins/janus_echotest.c | 36 ++++++++++--- plugins/janus_videoroom.c | 70 +++++++++++++++++++++++-- postprocessing/janus-pp-rec.1 | 3 ++ postprocessing/janus-pp-rec.c | 20 ++++--- postprocessing/janus-pp-rec.ggo | 1 + 8 files changed, 138 insertions(+), 20 deletions(-) diff --git a/conf/janus.plugin.videoroom.jcfg.sample b/conf/janus.plugin.videoroom.jcfg.sample index 4c6d2e1e03..e0f8a54ec0 100644 --- a/conf/janus.plugin.videoroom.jcfg.sample +++ b/conf/janus.plugin.videoroom.jcfg.sample @@ -3,7 +3,7 @@ # is_private = true|false (whether this room should be in the public list, default=true) # secret = # pin = -# require_pvtid = true|false (whether subscriptions are required to provide a valid private_id +# require_pvtid = true|false (whether subscriptions are required to provide a valid private_id # to associate with a publisher, default=false) # publishers = (e.g., 6 for a video # conference or 1 for a webinar) @@ -17,7 +17,8 @@ # can be a comma separated list in order of preference, e.g., vp9,vp8,h264) # vp9_profile = VP9-specific profile to prefer (e.g., "2" for "profile-id=2") # h264_profile = H.264-specific profile to prefer (e.g., "42e01f" for "profile-level-id=42e01f") -# opus_fec = true|false (whether inband FEC must be negotiated; only works for Opus, default=false) +# opus_fec = true|false (whether inband FEC must be negotiated; only works for Opus, default=true) +# opus_dtx = true|false (whether DTX must be negotiated; only works for Opus, default=false) # video_svc = true|false (whether SVC support must be enabled; only works for VP9, default=false) # audiolevel_ext = true|false (whether the ssrc-audio-level RTP extension must # be negotiated/used or not for new publishers, default=true) diff --git a/html/echotest.js b/html/echotest.js index 410d5be71a..2e9874c6ca 100644 --- a/html/echotest.js +++ b/html/echotest.js @@ -63,6 +63,7 @@ var doSimulcast2 = (getQueryStringValue("simulcast2") === "yes" || getQueryStrin var acodec = (getQueryStringValue("acodec") !== "" ? getQueryStringValue("acodec") : null); var vcodec = (getQueryStringValue("vcodec") !== "" ? getQueryStringValue("vcodec") : null); var vprofile = (getQueryStringValue("vprofile") !== "" ? getQueryStringValue("vprofile") : null); +var doDtx = (getQueryStringValue("dtx") === "yes" || getQueryStringValue("dtx") === "true"); var simulcastStarted = false; $(document).ready(function() { @@ -123,6 +124,13 @@ $(document).ready(function() { // the following 'simulcast' property to pass to janus.js to true simulcast: doSimulcast, simulcast2: doSimulcast2, + customizeSdp: function(jsep) { + // If DTX is enabled, munge the SDP + if(doDtx) { + jsep.sdp = jsep.sdp + .replace("useinbandfec=1", "useinbandfec=1;usedtx=1") + } + }, success: function(jsep) { Janus.debug("Got SDP!", jsep); echotest.send({ message: body, jsep: jsep }); diff --git a/html/videoroomtest.js b/html/videoroomtest.js index 72f9a2bf4a..6a566891d8 100644 --- a/html/videoroomtest.js +++ b/html/videoroomtest.js @@ -68,6 +68,7 @@ var doSimulcast = (getQueryStringValue("simulcast") === "yes" || getQueryStringV var doSimulcast2 = (getQueryStringValue("simulcast2") === "yes" || getQueryStringValue("simulcast2") === "true"); var acodec = (getQueryStringValue("acodec") !== "" ? getQueryStringValue("acodec") : null); var vcodec = (getQueryStringValue("vcodec") !== "" ? getQueryStringValue("vcodec") : null); +var doDtx = (getQueryStringValue("dtx") === "yes" || getQueryStringValue("dtx") === "true"); var subscriber_mode = (getQueryStringValue("subscriber-mode") === "yes" || getQueryStringValue("subscriber-mode") === "true"); $(document).ready(function() { @@ -416,6 +417,13 @@ function publishOwnFeed(useAudio) { // the following 'simulcast' property to pass to janus.js to true simulcast: doSimulcast, simulcast2: doSimulcast2, + customizeSdp: function(jsep) { + // If DTX is enabled, munge the SDP + if(doDtx) { + jsep.sdp = jsep.sdp + .replace("useinbandfec=1", "useinbandfec=1;usedtx=1") + } + }, success: function(jsep) { Janus.debug("Got publisher SDP!", jsep); var publish = { request: "configure", audio: useAudio, video: true }; @@ -550,6 +558,7 @@ function newRemoteFeed(id, display, audio, video) { } if(jsep) { Janus.debug("Handling SDP as well...", jsep); + var stereo = (jsep.sdp.indexOf("stereo=1") !== -1); // Answer and attach remoteFeed.createAnswer( { @@ -557,6 +566,12 @@ function newRemoteFeed(id, display, audio, video) { // Add data:true here if you want to subscribe to datachannels as well // (obviously only works if the publisher offered them in the first place) media: { audioSend: false, videoSend: false }, // We want recvonly audio/video + customizeSdp: function(jsep) { + if(stereo && jsep.sdp.indexOf("stereo=1") == -1) { + // Make sure that our offer contains stereo too + jsep.sdp = jsep.sdp.replace("useinbandfec=1", "useinbandfec=1;stereo=1"); + } + }, success: function(jsep) { Janus.debug("Got SDP!", jsep); var body = { request: "start", room: myroom }; diff --git a/plugins/janus_echotest.c b/plugins/janus_echotest.c index ff599ff3b1..809007771a 100644 --- a/plugins/janus_echotest.c +++ b/plugins/janus_echotest.c @@ -1065,8 +1065,10 @@ static void *janus_echotest_handler(void *data) { g_snprintf(error_cause, 512, "Error parsing offer: %s", error_str); goto error; } - /* Check if we need to negotiate Opus FEC */ - gboolean opus_fec = FALSE; + /* Check if we need to negotiate Opus FEC and/or DTX */ + gboolean opus_fec = FALSE, opus_dtx = FALSE; + char custom_fmtp[256]; + custom_fmtp[0] = '\0'; GList *temp = offer->m_lines; while(temp) { /* Which media are available? */ @@ -1077,9 +1079,31 @@ static void *janus_echotest_handler(void *data) { while(ma) { janus_sdp_attribute *a = (janus_sdp_attribute *)ma->data; if(a->value) { - if(m->type == JANUS_SDP_AUDIO && !strcasecmp(a->name, "fmtp") && - strstr(a->value, "useinbandfec=1")) { - opus_fec = TRUE; + if(m->type == JANUS_SDP_AUDIO && !strcasecmp(a->name, "fmtp")) { + if(strstr(a->value, "useinbandfec=1")) { + opus_fec = TRUE; + if(strlen(custom_fmtp) == 0) { + g_snprintf(custom_fmtp, sizeof(custom_fmtp), "useinbandfec=1"); + } else { + g_strlcat(custom_fmtp, ";useinbandfec=1", sizeof(custom_fmtp)); + } + } + if(strstr(a->value, "usedtx=1")) { + opus_dtx = TRUE; + if(strlen(custom_fmtp) == 0) { + g_snprintf(custom_fmtp, sizeof(custom_fmtp), "usedtx=1"); + } else { + g_strlcat(custom_fmtp, ";usedtx=1", sizeof(custom_fmtp)); + } + } + if(strstr(a->value, "stereo=1")) { + opus_dtx = TRUE; + if(strlen(custom_fmtp) == 0) { + g_snprintf(custom_fmtp, sizeof(custom_fmtp), "usedtx=1"); + } else { + g_strlcat(custom_fmtp, ";usedtx=1", sizeof(custom_fmtp)); + } + } } } ma = ma->next; @@ -1089,7 +1113,7 @@ static void *janus_echotest_handler(void *data) { } janus_sdp *answer = janus_sdp_generate_answer(offer, JANUS_SDP_OA_AUDIO_CODEC, json_string_value(audiocodec), - JANUS_SDP_OA_AUDIO_FMTP, opus_fec ? "useinbandfec=1" : NULL, + JANUS_SDP_OA_AUDIO_FMTP, (opus_fec || opus_dtx ? custom_fmtp : NULL), JANUS_SDP_OA_VIDEO_CODEC, json_string_value(videocodec), JANUS_SDP_OA_VP9_PROFILE, json_string_value(videoprofile), JANUS_SDP_OA_H264_PROFILE, json_string_value(videoprofile), diff --git a/plugins/janus_videoroom.c b/plugins/janus_videoroom.c index d6ec731cf0..d7651f6602 100644 --- a/plugins/janus_videoroom.c +++ b/plugins/janus_videoroom.c @@ -67,7 +67,8 @@ room-: { can be a comma separated list in order of preference, e.g., vp9,vp8,h264) vp9_profile = VP9-specific profile to prefer (e.g., "2" for "profile-id=2") h264_profile = H.264-specific profile to prefer (e.g., "42e01f" for "profile-level-id=42e01f") - opus_fec = true|false (whether inband FEC must be negotiated; only works for Opus, default=false) + opus_fec = true|false (whether inband FEC must be negotiated; only works for Opus, default=true) + opus_dtx = true|false (whether DTX must be negotiated; only works for Opus, default=false) video_svc = true|false (whether SVC support must be enabled; only works for VP9, default=false) audiolevel_ext = true|false (whether the ssrc-audio-level RTP extension must be negotiated/used or not for new publishers, default=true) @@ -387,6 +388,7 @@ room-: { "audiocodec" : "", "videocodec" : "", "opus_fec": , + "opus_dtx": , "video_svc": , "record" : , "rec_dir" : "", @@ -1267,6 +1269,7 @@ static struct janus_json_parameter create_parameters[] = { {"vp9_profile", JSON_STRING, 0}, {"h264_profile", JSON_STRING, 0}, {"opus_fec", JANUS_JSON_BOOL, 0}, + {"opus_dtx", JANUS_JSON_BOOL, 0}, {"video_svc", JANUS_JSON_BOOL, 0}, {"audiolevel_ext", JANUS_JSON_BOOL, 0}, {"audiolevel_event", JANUS_JSON_BOOL, 0}, @@ -1491,6 +1494,7 @@ typedef struct janus_videoroom { char *vp9_profile; /* VP9 codec profile to prefer, if more are negotiated */ char *h264_profile; /* H.264 codec profile to prefer, if more are negotiated */ gboolean do_opusfec; /* Whether inband FEC must be negotiated (note: only available for Opus) */ + gboolean do_opusdtx; /* Whether DTX must be negotiated (note: only available for Opus) */ gboolean do_svc; /* Whether SVC must be done for video (note: only available for VP9 right now) */ gboolean audiolevel_ext; /* Whether the ssrc-audio-level extension must be negotiated or not for new publishers */ gboolean audiolevel_event; /* Whether to emit event to other users about audiolevel */ @@ -1633,6 +1637,7 @@ typedef struct janus_videoroom_publisher { guint32 audio_ssrc; /* Audio SSRC of this publisher */ guint32 video_ssrc; /* Video SSRC of this publisher */ gboolean do_opusfec; /* Whether this publisher is sending inband Opus FEC */ + gboolean do_opusdtx; /* Whether this publisher is using Opus DTX (Discontinuous Transmission) */ uint32_t ssrc[3]; /* Only needed in case VP8 (or H.264) simulcasting is involved */ char *rid[3]; /* Only needed if simulcasting is rid-based */ int rid_extmap_id; /* rid extmap ID */ @@ -2254,6 +2259,7 @@ int janus_videoroom_init(janus_callbacks *callback, const char *config_path) { janus_config_item *vp9profile = janus_config_get(config, cat, janus_config_type_item, "vp9_profile"); janus_config_item *h264profile = janus_config_get(config, cat, janus_config_type_item, "h264_profile"); janus_config_item *fec = janus_config_get(config, cat, janus_config_type_item, "opus_fec"); + janus_config_item *dtx = janus_config_get(config, cat, janus_config_type_item, "opus_dtx"); janus_config_item *svc = janus_config_get(config, cat, janus_config_type_item, "video_svc"); janus_config_item *audiolevel_ext = janus_config_get(config, cat, janus_config_type_item, "audiolevel_ext"); janus_config_item *audiolevel_event = janus_config_get(config, cat, janus_config_type_item, "audiolevel_event"); @@ -2395,6 +2401,7 @@ int janus_videoroom_init(janus_callbacks *callback, const char *config_path) { videoroom->vcodec[4] == JANUS_VIDEOCODEC_H264)) { videoroom->h264_profile = g_strdup(h264profile->value); } + videoroom->do_opusfec = TRUE; if(fec && fec->value) { videoroom->do_opusfec = janus_is_true(fec->value); if(videoroom->acodec[0] != JANUS_AUDIOCODEC_OPUS && @@ -2406,6 +2413,17 @@ int janus_videoroom_init(janus_callbacks *callback, const char *config_path) { JANUS_LOG(LOG_WARN, "Inband FEC is only supported for rooms that allow Opus: disabling it...\n"); } } + if(dtx && dtx->value) { + videoroom->do_opusdtx = janus_is_true(dtx->value); + if(videoroom->acodec[0] != JANUS_AUDIOCODEC_OPUS && + videoroom->acodec[1] != JANUS_AUDIOCODEC_OPUS && + videoroom->acodec[2] != JANUS_AUDIOCODEC_OPUS && + videoroom->acodec[3] != JANUS_AUDIOCODEC_OPUS && + videoroom->acodec[4] != JANUS_AUDIOCODEC_OPUS) { + videoroom->do_opusdtx = FALSE; + JANUS_LOG(LOG_WARN, "DTX is only supported for rooms that allow Opus: disabling it...\n"); + } + } if(svc && svc->value && janus_is_true(svc->value)) { if(videoroom->vcodec[0] == JANUS_VIDEOCODEC_VP9 && videoroom->vcodec[1] == JANUS_VIDEOCODEC_NONE && @@ -3096,6 +3114,7 @@ static json_t *janus_videoroom_process_synchronous_request(janus_videoroom_sessi json_t *vp9profile = json_object_get(root, "vp9_profile"); json_t *h264profile = json_object_get(root, "h264_profile"); json_t *fec = json_object_get(root, "opus_fec"); + json_t *dtx = json_object_get(root, "opus_dtx"); json_t *svc = json_object_get(root, "video_svc"); json_t *audiolevel_ext = json_object_get(root, "audiolevel_ext"); json_t *audiolevel_event = json_object_get(root, "audiolevel_event"); @@ -3287,6 +3306,7 @@ static json_t *janus_videoroom_process_synchronous_request(janus_videoroom_sessi videoroom->vcodec[4] == JANUS_VIDEOCODEC_H264)) { videoroom->h264_profile = g_strdup(h264_profile); } + videoroom->do_opusfec = TRUE; if(fec) { videoroom->do_opusfec = json_is_true(fec); if(videoroom->acodec[0] != JANUS_AUDIOCODEC_OPUS && @@ -3298,6 +3318,17 @@ static json_t *janus_videoroom_process_synchronous_request(janus_videoroom_sessi JANUS_LOG(LOG_WARN, "Inband FEC is only supported for rooms that allow Opus: disabling it...\n"); } } + if(dtx) { + videoroom->do_opusdtx = json_is_true(dtx); + if(videoroom->acodec[0] != JANUS_AUDIOCODEC_OPUS && + videoroom->acodec[1] != JANUS_AUDIOCODEC_OPUS && + videoroom->acodec[2] != JANUS_AUDIOCODEC_OPUS && + videoroom->acodec[3] != JANUS_AUDIOCODEC_OPUS && + videoroom->acodec[4] != JANUS_AUDIOCODEC_OPUS) { + videoroom->do_opusdtx = FALSE; + JANUS_LOG(LOG_WARN, "DTX is only supported for rooms that allow Opus: disabling it...\n"); + } + } if(svc && json_is_true(svc)) { if(videoroom->vcodec[0] == JANUS_VIDEOCODEC_VP9 && videoroom->vcodec[1] == JANUS_VIDEOCODEC_NONE && @@ -3413,6 +3444,8 @@ static json_t *janus_videoroom_process_synchronous_request(janus_videoroom_sessi janus_config_add(config, c, janus_config_item_create("h264_profile", videoroom->h264_profile)); if(videoroom->do_opusfec) janus_config_add(config, c, janus_config_item_create("opus_fec", "yes")); + if(videoroom->do_opusdtx) + janus_config_add(config, c, janus_config_item_create("opus_dtx", "yes")); if(videoroom->do_svc) janus_config_add(config, c, janus_config_item_create("video_svc", "yes")); if(videoroom->room_secret) @@ -3595,6 +3628,8 @@ static json_t *janus_videoroom_process_synchronous_request(janus_videoroom_sessi janus_config_add(config, c, janus_config_item_create("h264_profile", videoroom->h264_profile)); if(videoroom->do_opusfec) janus_config_add(config, c, janus_config_item_create("opus_fec", "yes")); + if(videoroom->do_opusdtx) + janus_config_add(config, c, janus_config_item_create("opus_dtx", "yes")); if(videoroom->do_svc) janus_config_add(config, c, janus_config_item_create("video_svc", "yes")); if(videoroom->room_secret) @@ -3797,6 +3832,8 @@ static json_t *janus_videoroom_process_synchronous_request(janus_videoroom_sessi json_object_set_new(rl, "videocodec", json_string(video_codecs)); if(room->do_opusfec) json_object_set_new(rl, "opus_fec", json_true()); + if(room->do_opusdtx) + json_object_set_new(rl, "opus_dtx", json_true()); if(room->do_svc) json_object_set_new(rl, "video_svc", json_true()); json_object_set_new(rl, "record", room->record ? json_true() : json_false()); @@ -7540,6 +7577,8 @@ static void *janus_videoroom_handler(void *data) { goto error; } char *audio_fmtp = NULL; + char custom_fmtp[256]; + custom_fmtp[0] = '\0'; GList *temp = offer->m_lines; while(temp) { /* Which media are available? */ @@ -7569,8 +7608,29 @@ static void *janus_videoroom_handler(void *data) { if(janus_string_to_uint8(a->value, &participant->playout_delay_extmap_id) < 0) JANUS_LOG(LOG_WARN, "Invalid playout-delay extension ID: %s\n", a->value); } else if(m->type == JANUS_SDP_AUDIO && !strcasecmp(a->name, "fmtp")) { - if(strstr(a->value, "useinbandfec=1")) - participant->do_opusfec = videoroom->do_opusfec; + if(strstr(a->value, "useinbandfec=1") && videoroom->do_opusfec) { + participant->do_opusfec = TRUE; + if(strlen(custom_fmtp) == 0) { + g_snprintf(custom_fmtp, sizeof(custom_fmtp), "useinbandfec=1"); + } else { + g_strlcat(custom_fmtp, ";useinbandfec=1", sizeof(custom_fmtp)); + } + } + if(strstr(a->value, "usedtx=1") && videoroom->do_opusdtx) { + participant->do_opusdtx = TRUE; + if(strlen(custom_fmtp) == 0) { + g_snprintf(custom_fmtp, sizeof(custom_fmtp), "usedtx=1"); + } else { + g_strlcat(custom_fmtp, ";usedtx=1", sizeof(custom_fmtp)); + } + } + if(strstr(a->value, "stereo=1")) { + if(strlen(custom_fmtp) == 0) { + g_snprintf(custom_fmtp, sizeof(custom_fmtp), "stereo=1"); + } else { + g_strlcat(custom_fmtp, ";stereo=1", sizeof(custom_fmtp)); + } + } char *tmp = strchr(a->value, ' '); if(tmp && strlen(tmp) > 1) { tmp++; @@ -7646,7 +7706,7 @@ static void *janus_videoroom_handler(void *data) { janus_sdp *answer = janus_sdp_generate_answer(offer, JANUS_SDP_OA_AUDIO_CODEC, janus_audiocodec_name(participant->acodec), JANUS_SDP_OA_AUDIO_DIRECTION, JANUS_SDP_RECVONLY, - JANUS_SDP_OA_AUDIO_FMTP, audio_fmtp ? audio_fmtp : (participant->do_opusfec ? "useinbandfec=1" : NULL), + JANUS_SDP_OA_AUDIO_FMTP, audio_fmtp ? audio_fmtp : (strlen(custom_fmtp) > 0 ? custom_fmtp : NULL), JANUS_SDP_OA_VIDEO_CODEC, janus_videocodec_name(participant->vcodec), JANUS_SDP_OA_VP9_PROFILE, vp9_profile, JANUS_SDP_OA_H264_PROFILE, h264_profile, @@ -7744,7 +7804,7 @@ static void *janus_videoroom_handler(void *data) { JANUS_SDP_OA_AUDIO_CODEC, janus_audiocodec_name(participant->acodec), JANUS_SDP_OA_AUDIO_PT, janus_audiocodec_pt(participant->acodec), JANUS_SDP_OA_AUDIO_DIRECTION, JANUS_SDP_SENDONLY, - JANUS_SDP_OA_AUDIO_FMTP, audio_fmtp ? audio_fmtp : (participant->do_opusfec ? "useinbandfec=1" : NULL), + JANUS_SDP_OA_AUDIO_FMTP, audio_fmtp ? audio_fmtp : (strlen(custom_fmtp) > 0 ? custom_fmtp : NULL), JANUS_SDP_OA_AUDIO_EXTENSION, JANUS_RTP_EXTMAP_AUDIO_LEVEL, participant->audio_level_extmap_id > 0 ? participant->audio_level_extmap_id : 0, JANUS_SDP_OA_AUDIO_EXTENSION, JANUS_RTP_EXTMAP_MID, mid_ext_id, diff --git a/postprocessing/janus-pp-rec.1 b/postprocessing/janus-pp-rec.1 index a6771051ca..f8546dceac 100644 --- a/postprocessing/janus-pp-rec.1 +++ b/postprocessing/janus-pp-rec.1 @@ -66,6 +66,9 @@ Time threshold to trigger an audio skew compensation, disabled if 0 (default=0) .BR \-C ", " \-\-silence-distance=count RTP packets distance used to detect RTP silence suppression, disabled if 0 (default=100) .TP +.BR \-X ", " \-\-dtx +Enable DTX mode (disables code to handle silence suppression) (default=off) +.TP .BR \-r ", " \-\-restamp=count If the latency of a packet is bigger than the `moving_average_latency * (/1000)` the timestamps will be corrected, disabled if 0 (default=0) .TP diff --git a/postprocessing/janus-pp-rec.c b/postprocessing/janus-pp-rec.c index 7275578b3f..dcc3f8c0a1 100644 --- a/postprocessing/janus-pp-rec.c +++ b/postprocessing/janus-pp-rec.c @@ -80,6 +80,8 @@ Usage: janus-pp-rec [OPTIONS] source.mjr compensation, disabled if 0 (default=0) -C, --silence-distance=count RTP packets distance used to detect RTP silence suppression, disabled if 0 (default=100) + -X, --dtx Enable DTX mode (disables code to handle + silence suppression) (default=off) -r, --restamp=count If the latency of a packet is bigger than the `moving_average_latency * (/1000)` the timestamps will be corrected, disabled if @@ -312,6 +314,8 @@ int main(int argc, char *argv[]) if(val >= 0) silence_distance = val; } + if(args_info.dtx_given) + silence_distance = 0; if(args_info.restamp_given || (g_getenv("JANUS_PPREC_RESTAMP") != NULL)) { int val = args_info.restamp_given ? args_info.restamp_arg : atoi(g_getenv("JANUS_PPREC_RESTAMP")); if(val >= 0) @@ -803,8 +807,8 @@ int main(int argc, char *argv[]) int ignored = 0; offset = 0; gboolean started = FALSE; - /* DTX stuff */ - gboolean dtx_on = FALSE; + /* Silence suppression stuff */ + gboolean ssup_on = FALSE; /* Extensions, if any */ int audiolevel = 0, rotation = 0, last_rotation = -1, rotated = -1; uint16_t rtp_header_len, rtp_read_n; @@ -989,9 +993,11 @@ int main(int argc, char *argv[]) p->ts = (times_resetted*max32)+rtp_ts; } else { if(!video && !data) { - if(dtx_on) { - /* Leaving DTX mode (RTP started flowing again) */ - dtx_on = FALSE; + /* Check if we need to handle the SIP silence suppression mode, + * see https://github.com/meetecho/janus-gateway/pull/2328 */ + if(ssup_on) { + /* Leaving silence suppression mode (RTP started flowing again) */ + ssup_on = FALSE; JANUS_LOG(LOG_WARN, "Leaving RTP silence suppression (seq=%"SCNu16", rtp_ts=%"SCNu32")\n", ntohs(rtp->seq_number), rtp_ts); } else if(rtp->markerbit == 1) { /* Try to detect RTP silence suppression */ @@ -1002,8 +1008,8 @@ int main(int argc, char *argv[]) int32_t expected_rtp_distance = inter_rtp_ts * seq_distance; int32_t rtp_distance = abs((int32_t)(rtp_ts - highest_rtp_ts)); if(rtp_distance > 10 * expected_rtp_distance) { - /* Entering DTX mode (RTP will stop) */ - dtx_on = TRUE; + /* Entering silence suppression mode (RTP will stop) */ + ssup_on = TRUE; /* This is a close packet with not coherent RTP ts -> silence suppression */ JANUS_LOG(LOG_WARN, "Dropping audio RTP silence suppression (seq_distance=%d, rtp_distance=%d)\n", seq_distance, rtp_distance); /* Skip data */ diff --git a/postprocessing/janus-pp-rec.ggo b/postprocessing/janus-pp-rec.ggo index 80f78a4c7c..c02cbc862a 100644 --- a/postprocessing/janus-pp-rec.ggo +++ b/postprocessing/janus-pp-rec.ggo @@ -16,6 +16,7 @@ option "format" f "Specifies the output format (overrides the format from the de option "faststart" t "For mp4 files write the MOOV atom at the head of the file" flag off option "audioskew" S "Time threshold to trigger an audio skew compensation, disabled if 0 (default=0)" int typestr="milliseconds" optional option "silence-distance" C "RTP packets distance used to detect RTP silence suppression, disabled if 0 (default=100)" int typestr="count" optional +option "dtx" X "Enable DTX mode (disables code to handle silence suppression)" flag off option "restamp" r "If the latency of a packet is bigger than the `moving_average_latency * (/1000)` the timestamps will be corrected, disabled if 0 (default=0)" int typestr="count" optional option "restamp-packets" c "Number of packets used for calculating moving average latency for timestamp correction (default=10)" int typestr="count" optional option "restamp-min-th" n "Minimum latency of moving average to reach before starting to correct timestamps. (default=500)" int typestr="milliseconds" optional