diff --git a/daemon/codec.c b/daemon/codec.c index d41697629..a91ad25ba 100644 --- a/daemon/codec.c +++ b/daemon/codec.c @@ -123,6 +123,8 @@ struct codec_ssrc_handler { // silence detection GQueue silence_events; + // DTMF audio suppression + unsigned long dtmf_start_ts; // DTMF send delay unsigned long dtmf_first_duration; @@ -2069,6 +2071,12 @@ static int packet_dtmf(struct codec_ssrc_handler *ch, struct transcode_packet *p if (ret == 1) { // END event ch->ts_in = packet->ts; + if (decoder_ch) + decoder_ch->dtmf_start_ts = 0; + } + else { + if (decoder_ch) + decoder_ch->dtmf_start_ts = packet->ts ? packet->ts : 1; } } @@ -2962,10 +2970,32 @@ static int packet_decode(struct codec_ssrc_handler *ch, struct transcode_packet { int ret = 0; + struct codec_ssrc_handler *decoder_ch = ch; + + if (ch->handler && ch->handler->source_pt.codec_def && ch->handler->source_pt.codec_def->supplemental) { + struct codec_handler *decoder_handler = __decoder_handler(ch->handler, mp); + decoder_ch = get_ssrc(mp->ssrc_in->parent->h.ssrc, + decoder_handler->ssrc_hash); + } + if (!ch->first_ts) ch->first_ts = packet->ts; ch->last_ts = packet->ts; + if (decoder_ch->dtmf_start_ts && !rtpe_config.dtmf_no_suppress) { + if ((packet->ts > decoder_ch->dtmf_start_ts && packet->ts - decoder_ch->dtmf_start_ts > 80000) || + (packet->ts < decoder_ch->dtmf_start_ts && decoder_ch->dtmf_start_ts - packet->ts > 80000)) { + ilogs(transcoding, LOG_DEBUG, "Resetting decoder DTMF state due to TS discrepancy"); + decoder_ch->dtmf_start_ts = 0; + } + else { + ilogs(transcoding, LOG_DEBUG, "Decoder is in DTMF state, discaring codec packet"); + if (mp->ssrc_out) + mp->ssrc_out->parent->seq_diff--; + goto out; + } + } + if (__buffer_dtx(ch->dtx_buffer, ch, packet, mp, __rtp_decode)) ret = 1; // consumed else { @@ -2974,6 +3004,9 @@ static int packet_decode(struct codec_ssrc_handler *ch, struct transcode_packet ret = ret ? -1 : 0; } +out: + if (decoder_ch != ch) + obj_put(&decoder_ch->h); return ret; } diff --git a/daemon/dtmf.c b/daemon/dtmf.c index 7a5df74e9..d2f61fba8 100644 --- a/daemon/dtmf.c +++ b/daemon/dtmf.c @@ -122,7 +122,7 @@ int dtmf_event(struct media_packet *mp, str *payload, int clockrate) { ilog(LOG_DEBUG, "DTMF event: event %u, volume %u, end %u, duration %u", dtmf->event, dtmf->volume, dtmf->end, dtmf->duration); - int ret = 0; + int ret = dtmf->end ? 1 : 0; GString *buf = NULL; @@ -140,8 +140,6 @@ int dtmf_event(struct media_packet *mp, str *payload, int clockrate) { if (rtpe_config.dtmf_via_ng) dtmf_bencode_and_notify(mp, dtmf, clockrate); g_string_free(buf, TRUE); - - ret = 1; // END event } return ret; diff --git a/daemon/main.c b/daemon/main.c index 76fcda607..79341fc24 100644 --- a/daemon/main.c +++ b/daemon/main.c @@ -432,6 +432,7 @@ static void options(int *argc, char ***argv) { { "log-facility-dtmf",0, 0, G_OPTION_ARG_STRING, &log_facility_dtmf_s, "Syslog facility to use for logging DTMF", "daemon|local0|...|local7"}, { "dtmf-log-dest", 0,0, G_OPTION_ARG_STRING, &dtmf_udp_ep, "Destination address for DTMF logging via UDP", "IP46|HOSTNAME:PORT" }, { "dtmf-log-ng-tcp", 0,0, G_OPTION_ARG_NONE, &rtpe_config.dtmf_via_ng, "DTMF logging via TCP NG protocol", NULL }, + { "dtmf-no-suppress", 0,0,G_OPTION_ARG_NONE, &rtpe_config.dtmf_no_suppress, "Disable audio suppression during DTMF events", NULL }, #endif { "log-format", 0, 0, G_OPTION_ARG_STRING, &log_format, "Log prefix format", "default|parsable"}, { "xmlrpc-format",'x', 0, G_OPTION_ARG_INT, &rtpe_config.fmt, "XMLRPC timeout request format to use. 0: SEMS DI, 1: call-id only, 2: Kamailio", "INT" }, diff --git a/daemon/rtpengine.pod b/daemon/rtpengine.pod index fb4d951a0..ba49fa7f3 100644 --- a/daemon/rtpengine.pod +++ b/daemon/rtpengine.pod @@ -279,6 +279,14 @@ given address as UDP packets. If B<--listen-tcp-ng> is enabled, this will send DTMF events to all connected cliens encoded in bencode format. +=item B<--dtmf-no-suppress> + +Some RTP clients continue to send audio RTP packets during a DTMF event, +resulting in both audio packets and DTMF packets appearing simultaneously. By +default, when transcoding, B suppresses audio packets during a DTMF +event and will only send DTMF packets until the DTMF event is over. Setting +this option disables this feature. + =item B<--log-srtp-keys> Write SRTP keys to error log instead of debug log. diff --git a/include/main.h b/include/main.h index c569f9d4f..280d09c5e 100644 --- a/include/main.h +++ b/include/main.h @@ -97,6 +97,7 @@ struct rtpengine_config { char *mysql_query; endpoint_t dtmf_udp_ep; int dtmf_via_ng; + int dtmf_no_suppress; enum endpoint_learning endpoint_learning; int jb_length; int jb_clock_drift;