[asterisk-commits] oej: branch oej/roibos-cng-support-1.8 r411924 - in /team/oej/roibos-cng-supp...
SVN commits to the Asterisk project
asterisk-commits at lists.digium.com
Tue Apr 8 09:23:29 CDT 2014
Author: oej
Date: Tue Apr 8 09:23:25 2014
New Revision: 411924
URL: http://svnview.digium.com/svn/asterisk?view=rev&rev=411924
Log:
Let the fun begin!
Added:
team/oej/roibos-cng-support-1.8/include/asterisk/silencedetection.h (with props)
team/oej/roibos-cng-support-1.8/main/silencedetection.c (with props)
Modified:
team/oej/roibos-cng-support-1.8/channels/chan_sip.c
team/oej/roibos-cng-support-1.8/channels/sip/include/sip.h
team/oej/roibos-cng-support-1.8/configs/sip.conf.sample
team/oej/roibos-cng-support-1.8/include/asterisk/audiohook.h
team/oej/roibos-cng-support-1.8/include/asterisk/frame.h
team/oej/roibos-cng-support-1.8/main/audiohook.c
team/oej/roibos-cng-support-1.8/patches/silence-detection-games-1.8.diff
Modified: team/oej/roibos-cng-support-1.8/channels/chan_sip.c
URL: http://svnview.digium.com/svn/asterisk/team/oej/roibos-cng-support-1.8/channels/chan_sip.c?view=diff&rev=411924&r1=411923&r2=411924
==============================================================================
--- team/oej/roibos-cng-support-1.8/channels/chan_sip.c (original)
+++ team/oej/roibos-cng-support-1.8/channels/chan_sip.c Tue Apr 8 09:23:25 2014
@@ -273,6 +273,7 @@
#include "sip/include/sdp_crypto.h"
#include "asterisk/ccss.h"
#include "asterisk/xml.h"
+#include "asterisk/silencedetection.h"
#include "sip/include/dialog.h"
#include "sip/include/dialplan_functions.h"
@@ -6923,6 +6924,11 @@
struct sip_pvt *p = ast->tech_pvt;
int res = 0;
+ if (frame == &ast_null_frame) {
+ /* We do not send null frames. Sorry */
+ return 1;
+ }
+
switch (frame->frametype) {
case AST_FRAME_VOICE:
if (!(frame->subclass.codec & ast->nativeformats)) {
@@ -7466,6 +7472,38 @@
return res;
}
+
+/*! \brief Activates a DSP to detect silence, something we can use to suppress silent RTP packets
+ and send CNG (comfort noise generation) requests instead */
+static int activate_silence_detection(struct sip_pvt *dialog)
+{
+ int res = 0;
+ ast_debug(3, "SILDET: Checking if we need silence detection on %s\n", dialog->callid);
+
+ /* Check if we really want silence suppression */
+ if (!dialog || !dialog->rtp || !dialog->owner || !ast_test_flag(&dialog->flags[2], SIP_PAGE3_SILENCE_DETECTION)) {
+ ast_debug(3, "SILDET: Channel does not need silence suppression on %s\n", dialog->callid);
+ return FALSE;
+ }
+
+ if(ast_sildet_activate(dialog->owner, dialog->silencelevel, dialog->silenceframes)) {
+
+ /* We now have a call where we have a DSP. The rest of the magic is happening somewhere else in chan_sip. */
+ ast_debug(3, "SILDET: Activated silence suppression on call %s\n", dialog->callid);
+#ifdef ISTHISNEEDED
+ if ((res = ast_set_read_format(dialog->owner, AST_FORMAT_SLINEAR)) < 0) {
+ /* Put channel in the right codec mode: SLINEAR */
+ ast_log(LOG_WARNING, "Unable to set channel to linear mode, giving up\n");
+ ast_sildet_deactivate(dialog->owner);
+ return FALSE;
+ }
+#endif
+ } else {
+ ast_debug(3, "SILDET: Failed to activate silence detection on call %s\n", dialog->callid);
+ }
+ return TRUE;
+}
+
/*!
* \brief Initiate a call in the SIP channel
*
@@ -7684,6 +7722,8 @@
manager_event(EVENT_FLAG_SYSTEM, "ChannelUpdate",
"Channel: %s\r\nUniqueid: %s\r\nChanneltype: %s\r\nSIPcallid: %s\r\nSIPfullcontact: %s\r\n",
tmp->name, tmp->uniqueid, "SIP", i->callid, i->fullcontact);
+
+ activate_silence_detection(i);
return tmp;
}
@@ -7981,7 +8021,6 @@
ast_frfree(fr);
fr = &ast_null_frame;
}
-
sip_pvt_unlock(p);
return fr;
@@ -8236,6 +8275,8 @@
ast_string_field_set(p, mohinterpret, default_mohinterpret);
ast_string_field_set(p, mohsuggest, default_mohsuggest);
p->capability = sip_cfg.capability;
+ p->silencelevel = sip_cfg.silencelevel;
+ p->silenceframes = sip_cfg.silenceframes;
p->allowtransfer = sip_cfg.allowtransfer;
if ((ast_test_flag(&p->flags[0], SIP_DTMF) == SIP_DTMF_RFC2833) ||
(ast_test_flag(&p->flags[0], SIP_DTMF) == SIP_DTMF_AUTO)) {
@@ -18324,7 +18365,7 @@
ast_cli(fd, " Codec Order : (");
print_codec_to_cli(fd, &peer->prefs);
ast_cli(fd, ")\n");
-
+ ast_cli(fd, " Silence Det. : %s\n", AST_CLI_YESNO(ast_test_flag(&peer->flags[2], SIP_PAGE3_SILENCE_DETECTION)));
ast_cli(fd, " Auto-Framing : %s\n", AST_CLI_YESNO(peer->autoframing));
ast_cli(fd, " Status : ");
peer_status(peer, status, sizeof(status));
@@ -19008,6 +19049,9 @@
ast_cli(a->fd, " DTMF: %s\n", dtmfmode2str(ast_test_flag(&global_flags[0], SIP_DTMF)));
ast_cli(a->fd, " Qualify: %d\n", default_qualify);
ast_cli(a->fd, " Use ClientCode: %s\n", AST_CLI_YESNO(ast_test_flag(&global_flags[0], SIP_USECLIENTCODE)));
+ ast_cli(a->fd, " Silence detection: %s\n", AST_CLI_YESNO(ast_test_flag(&global_flags[2], SIP_PAGE3_SILENCE_DETECTION)));
+ ast_cli(a->fd, " Silence level: %d\n", sip_cfg.silencelevel);
+ ast_cli(a->fd, " Silence frames: %d\n", sip_cfg.silenceframes);
ast_cli(a->fd, " Progress inband: %s\n", (ast_test_flag(&global_flags[0], SIP_PROG_INBAND) == SIP_PROG_INBAND_NEVER) ? "Never" : (AST_CLI_YESNO(ast_test_flag(&global_flags[0], SIP_PROG_INBAND) != SIP_PROG_INBAND_NO)));
ast_cli(a->fd, " Language: %s\n", default_language);
ast_cli(a->fd, " MOH Interpret: %s\n", default_mohinterpret);
@@ -19404,6 +19448,9 @@
ast_cli(a->fd, " Promiscuous Redir: %s\n", AST_CLI_YESNO(ast_test_flag(&cur->flags[0], SIP_PROMISCREDIR)));
ast_cli(a->fd, " Route: %s\n", cur->route ? cur->route->hop : "N/A");
ast_cli(a->fd, " DTMF Mode: %s\n", dtmfmode2str(ast_test_flag(&cur->flags[0], SIP_DTMF)));
+ ast_cli(a->fd, " Silence Detection: %s\n", AST_CLI_YESNO(ast_test_flag(&cur->flags[2], SIP_PAGE3_SILENCE_DETECTION)));
+ ast_cli(a->fd, " Silence level: %d\n", cur->silencelevel);
+ ast_cli(a->fd, " Silence frames: %d\n", cur->silenceframes);
ast_cli(a->fd, " SIP Options: ");
if (cur->sipoptions) {
int x;
@@ -27808,6 +27855,9 @@
} else if (!strcasecmp(v->name, "buggymwi")) {
ast_set_flag(&mask[1], SIP_PAGE2_BUGGY_MWI);
ast_set2_flag(&flags[1], ast_true(v->value), SIP_PAGE2_BUGGY_MWI);
+ } else if (!strcasecmp(v->name, "silencedetection")) {
+ ast_set_flag(&mask[2], SIP_PAGE3_SILENCE_DETECTION);
+ ast_set2_flag(&flags[2], ast_true(v->value), SIP_PAGE3_SILENCE_DETECTION);
} else if (!strcasecmp(v->name, "comfort-noise")) {
ast_set_flag(&mask[1], SIP_PAGE2_ALLOW_CN);
ast_set2_flag(&flags[1], ast_true(v->value), SIP_PAGE2_ALLOW_CN);
@@ -29033,6 +29083,8 @@
ast_copy_string(default_callerid, DEFAULT_CALLERID, sizeof(default_callerid));
ast_copy_string(default_mwi_from, DEFAULT_MWI_FROM, sizeof(default_mwi_from));
sip_cfg.compactheaders = DEFAULT_COMPACTHEADERS;
+ sip_cfg.silencelevel = DEFAULT_SILENCELEVEL;
+ sip_cfg.silenceframes = DEFAULT_SILENCEFRAMES;
global_reg_timeout = DEFAULT_REGISTRATION_TIMEOUT;
global_regattempts_max = 0;
global_reg_retry_403 = 0;
@@ -29581,6 +29633,18 @@
}
} else if (!strcasecmp(v->name, "use_q850_reason")) {
ast_set2_flag(&global_flags[1], ast_true(v->value), SIP_PAGE2_Q850_REASON);
+ } else if (!strcasecmp(v->name, "silencelevel")) {
+ if (sscanf(v->value, "%30d", &sip_cfg.silencelevel) != 1
+ || sip_cfg.silencelevel < 1 ) {
+ ast_log(LOG_WARNING, "'%s' is not a valid silencelevel value at line %d. Using default.\n", v->value, v->lineno);
+ sip_cfg.silencelevel = DEFAULT_SILENCELEVEL;
+ }
+ } else if (!strcasecmp(v->name, "silenceframes")) {
+ if (sscanf(v->value, "%30d", &sip_cfg.silenceframes) != 1
+ || sip_cfg.silenceframes < 0 || sip_cfg.silenceframes > 150) {
+ ast_log(LOG_WARNING, "'%s' is not a valid silencelevel value at line %d. Using default.\n", v->value, v->lineno);
+ sip_cfg.silenceframes = DEFAULT_SILENCEFRAMES;
+ }
} else if (!strcasecmp(v->name, "maxforwards")) {
if (sscanf(v->value, "%30d", &sip_cfg.default_max_forwards) != 1
|| sip_cfg.default_max_forwards < 1 || 255 < sip_cfg.default_max_forwards) {
Modified: team/oej/roibos-cng-support-1.8/channels/sip/include/sip.h
URL: http://svnview.digium.com/svn/asterisk/team/oej/roibos-cng-support-1.8/channels/sip/include/sip.h?view=diff&rev=411924&r1=411923&r2=411924
==============================================================================
--- team/oej/roibos-cng-support-1.8/channels/sip/include/sip.h (original)
+++ team/oej/roibos-cng-support-1.8/channels/sip/include/sip.h Tue Apr 8 09:23:25 2014
@@ -61,6 +61,8 @@
#define DEFAULT_AUTHLIMIT 100
#define DEFAULT_AUTHTIMEOUT 30
+#define DEFAULT_SILENCELEVEL 100
+#define DEFAULT_SILENCEFRAMES 7 /* Number of frames of silence to let through before we start suppressing it */
/* guard limit must be larger than guard secs */
/* guard min must be < 1000, and should be >= 250 */
@@ -361,9 +363,10 @@
#define SIP_PAGE3_SNOM_AOC (1 << 0) /*!< DPG: Allow snom aoc messages */
#define SIP_PAGE3_DIRECT_MEDIA_OUTGOING (1 << 1) /*!< DP: Only send direct media reinvites on outgoing calls */
+#define SIP_PAGE3_SILENCE_DETECTION (1 << 21) /*!< DPG: Enable silence detection? */
#define SIP_PAGE3_FLAGS_TO_COPY \
- (SIP_PAGE3_SNOM_AOC | SIP_PAGE3_DIRECT_MEDIA_OUTGOING)
+ (SIP_PAGE3_SNOM_AOC | SIP_PAGE3_DIRECT_MEDIA_OUTGOING | SIP_PAGE3_SILENCE_DETECTION)
/*@}*/
@@ -718,6 +721,8 @@
format_t capability; /*!< Supported codecs */
int tcp_enabled;
int default_max_forwards; /*!< Default max forwards (SIP Anti-loop) */
+ unsigned int silencelevel; /*!< Default silence treshold for silence detection */
+ unsigned int silenceframes; /*!< Default silence period - how many frames to wait before suppressing silence */
};
/*! \brief The SIP socket definition */
@@ -1090,6 +1095,10 @@
uint32_t dialogver; /*!< SUBSCRIBE: Version for subscription dialog-info */
struct ast_dsp *dsp; /*!< Inband DTMF or Fax CNG tone Detection dsp */
+ unsigned int silencelevel; /*!< Silence treshold */
+ unsigned int silenceframes; /*!< How many frames to wait for silence before activating silence
+ support and sending CNG */
+ unsigned int silencecounter; /*!< Frame Counter used for silence detection. */
struct sip_peer *relatedpeer; /*!< If this dialog is related to a peer, which one
Used in peerpoke, mwi subscriptions */
Modified: team/oej/roibos-cng-support-1.8/configs/sip.conf.sample
URL: http://svnview.digium.com/svn/asterisk/team/oej/roibos-cng-support-1.8/configs/sip.conf.sample?view=diff&rev=411924&r1=411923&r2=411924
==============================================================================
--- team/oej/roibos-cng-support-1.8/configs/sip.conf.sample (original)
+++ team/oej/roibos-cng-support-1.8/configs/sip.conf.sample Tue Apr 8 09:23:25 2014
@@ -543,6 +543,21 @@
; when we're on hold (must be > rtptimeout)
;rtpkeepalive=<secs> ; Send keepalives in the RTP stream to keep NAT open
; (default is off - zero)
+
+;--------------------------- SIP Silence detection/suppression for RTP ------------------------------------
+; The silence detection assigns a software DSP to each channel and converts all audio into
+; signed linear in order to be able to detect silence. This will require a lot of CPU
+; per channel including transcoding.
+; This is only settable in [general] right now, but should be settable per channel
+;silencedetection = YES ; Enable silence detection - by default turned off.
+; ; settable per device too
+; ; You want to enable comfort noise too
+;silencelevel = 850 ; Silence detection noise level - below this is considered silent.
+ ; Default = 850
+;silenceperiod = 2 ; How many frames of silence should we get before we supress
+ ; audio. Consider packetization. A normal ALAW stream has 20 ms audio
+ ; per RTP packet. 2 means we will start sending CNG at the third silent
+ ; packet, after 40 ms of silence.
;--------------------------- SIP Session-Timers (RFC 4028)------------------------------------
; SIP Session-Timers provide an end-to-end keep-alive mechanism for active SIP sessions.
Modified: team/oej/roibos-cng-support-1.8/include/asterisk/audiohook.h
URL: http://svnview.digium.com/svn/asterisk/team/oej/roibos-cng-support-1.8/include/asterisk/audiohook.h?view=diff&rev=411924&r1=411923&r2=411924
==============================================================================
--- team/oej/roibos-cng-support-1.8/include/asterisk/audiohook.h (original)
+++ team/oej/roibos-cng-support-1.8/include/asterisk/audiohook.h Tue Apr 8 09:23:25 2014
@@ -37,6 +37,7 @@
AST_AUDIOHOOK_TYPE_SPY = 0, /*!< Audiohook wants to receive audio */
AST_AUDIOHOOK_TYPE_WHISPER, /*!< Audiohook wants to provide audio to be mixed with existing audio */
AST_AUDIOHOOK_TYPE_MANIPULATE, /*!< Audiohook wants to manipulate the audio */
+ AST_AUDIOHOOK_TYPE_SILDET, /*!< Audiohook to detect silence. That's all */
};
enum ast_audiohook_status {
Modified: team/oej/roibos-cng-support-1.8/include/asterisk/frame.h
URL: http://svnview.digium.com/svn/asterisk/team/oej/roibos-cng-support-1.8/include/asterisk/frame.h?view=diff&rev=411924&r1=411923&r2=411924
==============================================================================
--- team/oej/roibos-cng-support-1.8/include/asterisk/frame.h (original)
+++ team/oej/roibos-cng-support-1.8/include/asterisk/frame.h Tue Apr 8 09:23:25 2014
@@ -124,6 +124,8 @@
AST_FRAME_MODEM,
/*! DTMF begin event, subclass is the digit */
AST_FRAME_DTMF_BEGIN,
+ /*! A frame that needs to be killed, dropped or just silently ignored */
+ AST_FRAME_DROP,
};
#define AST_FRAME_DTMF AST_FRAME_DTMF_END
Added: team/oej/roibos-cng-support-1.8/include/asterisk/silencedetection.h
URL: http://svnview.digium.com/svn/asterisk/team/oej/roibos-cng-support-1.8/include/asterisk/silencedetection.h?view=auto&rev=411924
==============================================================================
--- team/oej/roibos-cng-support-1.8/include/asterisk/silencedetection.h (added)
+++ team/oej/roibos-cng-support-1.8/include/asterisk/silencedetection.h Tue Apr 8 09:23:25 2014
@@ -1,0 +1,49 @@
+/*
+ * Asterisk -- An open source telephony toolkit.
+ *
+ * Copyright (C) 2014, Olle E. Johansson
+ *
+ * Olle E. Johansson <oej at edvina.net>
+ *
+ * See http://www.asterisk.org for more information about
+ * the Asterisk project. Please do not directly contact
+ * any of the maintainers of this project for assistance;
+ * the project provides a web site, mailing lists and IRC
+ * channels for your use.
+ *
+ * This program is free software, distributed under the terms of
+ * the GNU General Public License Version 2. See the LICENSE file
+ * at the top of the source tree.
+ */
+
+/*! \file
+ * \brief Audiohook for silnce detection
+ */
+
+#ifndef _ASTERISK_SILENCEDETECTION_H
+#define _ASTERISK_SILENCEDETECTION_H
+
+#if defined(__cplusplus) || defined(c_plusplus)
+extern "C" {
+#endif
+
+/*! \brief Activation of silence detection
+ \param chan The channel
+ \param silencelevel Audio treshold for silence
+ \param silenceframes Number of frames before we react
+
+ \note That this function assumes the channel is set to read signed linear audio
+
+*/
+int ast_sildet_activate(struct ast_channel *chan, unsigned int silencelevel, unsigned int silenceframes);
+
+/*! \brief Deactivation of silence detection
+ \param chan The channel
+*/
+int ast_sildet_deactivate(struct ast_channel *chan);
+
+#if defined(__cplusplus) || defined(c_plusplus)
+}
+#endif
+
+#endif /* _ASTERISK_SILENCEDETECTION_H */
Propchange: team/oej/roibos-cng-support-1.8/include/asterisk/silencedetection.h
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: team/oej/roibos-cng-support-1.8/include/asterisk/silencedetection.h
------------------------------------------------------------------------------
svn:keywords = Author Date Id Revision
Propchange: team/oej/roibos-cng-support-1.8/include/asterisk/silencedetection.h
------------------------------------------------------------------------------
svn:mime-type = text/plain
Modified: team/oej/roibos-cng-support-1.8/main/audiohook.c
URL: http://svnview.digium.com/svn/asterisk/team/oej/roibos-cng-support-1.8/main/audiohook.c?view=diff&rev=411924&r1=411923&r2=411924
==============================================================================
--- team/oej/roibos-cng-support-1.8/main/audiohook.c (original)
+++ team/oej/roibos-cng-support-1.8/main/audiohook.c Tue Apr 8 09:23:25 2014
@@ -79,6 +79,9 @@
case AST_AUDIOHOOK_TYPE_WHISPER:
ast_slinfactory_init(&audiohook->write_factory);
break;
+ case AST_AUDIOHOOK_TYPE_SILDET:
+ ast_slinfactory_init(&audiohook->read_factory); /* We read and forget. */
+ break;
default:
break;
}
@@ -102,6 +105,9 @@
/* Fall through intentionally */
case AST_AUDIOHOOK_TYPE_WHISPER:
ast_slinfactory_destroy(&audiohook->write_factory);
+ break;
+ case AST_AUDIOHOOK_TYPE_SILDET:
+ ast_slinfactory_destroy(&audiohook->read_factory);
break;
default:
break;
@@ -626,6 +632,7 @@
struct ast_frame *start_frame = frame, *middle_frame = frame, *end_frame = frame;
struct ast_audiohook *audiohook = NULL;
int samples = frame->samples;
+ int needsdrop = 0;
/* ---Part_1. translate start_frame to SLINEAR if necessary. */
/* If the frame coming in is not signed linear we have to send it through the in_translate path */
@@ -705,15 +712,25 @@
* be taken here to exit early. */
}
ast_audiohook_unlock(audiohook);
+ if (middle_frame->frametype == AST_FRAME_DROP) {
+ /* This frame is going nowhere after this */
+ needsdrop = 1;
+ }
}
AST_LIST_TRAVERSE_SAFE_END;
end_frame = middle_frame;
}
/* ---Part_3: Decide what to do with the end_frame (whether to transcode or not) */
+ if (needsdrop) {
+ /* The frame needs to go away badly */
+ ast_frfree(middle_frame);
+ return &ast_null_frame;
+ }
+
if (middle_frame == end_frame) {
/* Middle frame was modified and became the end frame... let's see if we need to transcode */
- if (end_frame->subclass.codec != start_frame->subclass.codec) {
+ if (end_frame->frametype == AST_FRAME_AUDIO && end_frame->subclass.codec != start_frame->subclass.codec) {
if (out_translate->format != start_frame->subclass.codec) {
if (out_translate->trans_pvt)
ast_translator_free_path(out_translate->trans_pvt);
Added: team/oej/roibos-cng-support-1.8/main/silencedetection.c
URL: http://svnview.digium.com/svn/asterisk/team/oej/roibos-cng-support-1.8/main/silencedetection.c?view=auto&rev=411924
==============================================================================
--- team/oej/roibos-cng-support-1.8/main/silencedetection.c (added)
+++ team/oej/roibos-cng-support-1.8/main/silencedetection.c Tue Apr 8 09:23:25 2014
@@ -1,0 +1,315 @@
+/*
+ * Asterisk -- An open source telephony toolkit.
+ *
+ * Copyright (C) 2014, Olle E. Johansson
+ *
+ * Olle E. Johansson <oej at edvina.net>
+ *
+ * See http://www.asterisk.org for more information about
+ * the Asterisk project. Please do not directly contact
+ * any of the maintainers of this project for assistance;
+ * the project provides a web site, mailing lists and IRC
+ * channels for your use.
+ *
+ * This program is free software, distributed under the terms of
+ * the GNU General Public License Version 2. See the LICENSE file
+ * at the top of the source tree.
+ */
+
+/*! \file
+ *
+ * \brief Silence Detection and suppression audiohooks
+ *
+ * \author Olle E. Johansson <oej at edvina.net>
+ *
+ *
+ * This is an internal API and have no functions, applications or other cool stuff to expose to the admin.
+ *
+ * If this audiohook is applied, we listen for silence and when silence has been detected for a certain
+ * number of frames in a row, we replace the frame with a CNG frame and then (want to) drop frames until
+ * we have audio again. Right now the code just clears the frame.
+ *
+ * \note This code only handles audio streams
+ * For silence in video, check Ingmar Bergman movies on Wikipedia. We have
+ * no current way to detect video "silence" so we can't optimize that type of movies.
+ */
+
+/*** MODULEINFO
+ <support_level>core</support_level>
+ ***/
+
+#include "asterisk.h"
+
+ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
+
+#include "asterisk/options.h"
+#include "asterisk/logger.h"
+#include "asterisk/channel.h"
+#include "asterisk/config.h"
+#include "asterisk/file.h"
+#include "asterisk/pbx.h"
+#include "asterisk/frame.h"
+#include "asterisk/utils.h"
+#include "asterisk/audiohook.h"
+#include "asterisk/dsp.h"
+#include "asterisk/silencedetection.h"
+
+
+/*! Our own datastore */
+struct silence_detection_info {
+ struct ast_audiohook audiohook;
+ struct ast_dsp *dsp; /*!< DSP used for silence detection */
+ unsigned int silencelevel; /*!< Silence treshold */
+ unsigned int silenceframes; /*!< How many frames to wait for silence before activating silence
+ support and sending CNG */
+ unsigned int silencecounter; /*!< Frame Counter used for silence detection. */
+ int detect; /*!< Silence detected */
+ int active;
+};
+
+
+#define TRUE 1
+#define FALSE 0
+
+/*! Datastore destroy audiohook callback */
+static void destroy_callback(void *data)
+{
+ struct silence_detection_info *sildet = data;
+
+ ast_dsp_free(sildet->dsp);
+ sildet->dsp = NULL;
+
+ /* Destroy the audiohook, and destroy ourselves */
+ ast_audiohook_destroy(&sildet->audiohook);
+ ast_free(sildet);
+
+ return;
+}
+
+/*! \brief Static structure for datastore information */
+static const struct ast_datastore_info sildet_datastore = {
+ .type = "sildet",
+ .destroy = destroy_callback
+};
+
+/*! \brief The callback from the audiohook subsystem. We basically get a frame to have fun with
+ Return TRUE to keep original packet
+ Return FALSE to use our packet
+*/
+static int silence_detection_callback(struct ast_audiohook *audiohook, struct ast_channel *chan, struct ast_frame *frame, enum ast_audiohook_direction direction)
+{
+ struct ast_datastore *datastore = NULL;
+ struct silence_detection_info *sildet = NULL;
+
+ if (direction != AST_AUDIOHOOK_DIRECTION_WRITE) {
+ return 1;
+ }
+
+ /* If the audiohook is stopping it means the channel is shutting down.... but we let the datastore destroy take care of it */
+ if (audiohook->status == AST_AUDIOHOOK_STATUS_DONE) {
+ ast_debug(7, "Audiohook giving up - STATUS_DONE \n");
+ return 1;
+ }
+
+ ast_channel_lock(chan);
+ /* Grab datastore which contains our mute information */
+ if (!(datastore = ast_channel_datastore_find(chan, &sildet_datastore, NULL))) {
+ ast_channel_unlock(chan);
+ ast_debug(2, "Can't find any datastore to use. Bad. \n");
+ return 1;
+ }
+
+ sildet = datastore->data;
+ if (!sildet || !sildet->dsp) {
+ ast_channel_unlock(chan);
+ ast_debug(2, "Can't find any DSP to use. Bad. \n");
+ return 1;
+ }
+
+ /* If this is audio then allow them to increase/decrease the gains */
+ if (frame->frametype == AST_FRAME_VOICE) {
+ int dsptime = 0;
+
+ /* Based on direction of frame grab the gain, and confirm it is applicable */
+ if (direction == AST_AUDIOHOOK_DIRECTION_WRITE) {
+ ast_dsp_silence(sildet->dsp, frame, &dsptime); /* Checking for silence */
+ if (!dsptime) {
+ if (option_debug && sildet->silencecounter > 0) {
+ ast_debug(8, " ++++ Silence stopped ++++ on chan %s\n", chan->name);
+ }
+ if (sildet->silencecounter > 0) {
+ sildet->silencecounter = 0; /* No more silence */
+ sildet->detect = 0; /* No more silence */
+ }
+ ast_debug(9, " ++++ We are not silent on write to %s (dsptime %d)\n", chan->name, dsptime);
+ } else {
+ if (option_debug && sildet->silencecounter == 0) {
+ ast_debug(9, " ++++ Silence starts here %d ++++ on chan %s dsptime %d\n", sildet->silencecounter, chan->name, dsptime);
+ }
+ if (option_debug && sildet->silencecounter > 0) {
+ ast_debug(9, " ++++ Silence continues %d ++++ on chan %s dsptime %d\n", sildet->silencecounter, chan->name, dsptime);
+ }
+ sildet->silencecounter++;
+ if (sildet->detect == 1 && sildet->silencecounter > sildet->silenceframes) {
+ ast_frame_clear(frame); /* Should really be dropped. */
+ frame->samples = 0;
+ frame->datalen = 0;
+
+ frame->frametype = AST_FRAME_DROP;
+ ast_channel_unlock(chan);
+ return 0; /* Return TRUE since we manipulated the frame */
+ }
+ }
+ if (sildet->detect == 0 && sildet->silencecounter > sildet->silenceframes) {
+ ast_debug(8, "++++ Silence suppression should start now ++++ on chan %s\n", chan->name);
+ sildet->detect = 1;
+ ast_frame_clear(frame);
+ frame->frametype = AST_FRAME_CNG;
+ frame->subclass.integer = 0x7f;
+ frame->samples = 0;
+ ast_channel_unlock(chan);
+ return 0; /* Return TRUE since we manipulated the frame */
+ }
+ /* Do not touch the frame yet */
+ }
+ }
+ ast_channel_unlock(chan);
+
+ return 1;
+}
+
+/*! \brief Initialize mute hook on channel, but don't activate it
+ \pre Assumes that the channel is locked
+*/
+static struct ast_datastore *initialize_sildethook(struct ast_channel *chan)
+{
+ struct ast_datastore *datastore = NULL;
+ struct silence_detection_info *sildet = NULL;
+
+ ast_debug(2, "Initializing new Silence Detection Audiohook \n");
+
+ /* Allocate a new datastore to hold the reference to this sildet_datastore and audiohook information */
+ if (!(datastore = ast_datastore_alloc(&sildet_datastore, NULL))) {
+ return NULL;
+ }
+
+ if (!(sildet = ast_calloc(1, sizeof(*sildet)))) {
+ ast_datastore_free(datastore);
+ return NULL;
+ }
+ if (!(sildet->dsp = ast_dsp_new())) {
+ /* We failed to create a DSP */
+ ast_log(LOG_WARNING, "Unable to create silence detector :(\n");
+ ast_free(sildet);
+ ast_datastore_free(datastore);
+ return NULL;
+ }
+ ast_audiohook_init(&sildet->audiohook, AST_AUDIOHOOK_TYPE_MANIPULATE, "Sildet");
+ sildet->audiohook.manipulate_callback = silence_detection_callback;
+ sildet->active = 1;
+ sildet->silencecounter = 0;
+ sildet->detect = 0;
+ datastore->data = sildet;
+ return datastore;
+}
+
+/*! \brief Add or activate mute audiohook on channel
+ Assumes channel is locked
+*/
+static int sildet_add_audiohook(struct ast_channel *chan, struct silence_detection_info *sildet, struct ast_datastore *datastore)
+{
+ /* Activate the settings */
+ ast_channel_datastore_add(chan, datastore);
+ if (ast_audiohook_attach(chan, &sildet->audiohook)) {
+ ast_log(LOG_ERROR, "Failed to attach audiohook for silence detection on channel %s\n", chan->name);
+ return -1;
+ }
+ ast_debug(2, "Initialized audiohook for silence detection on channel %s\n", chan->name);
+ return 0;
+}
+
+/*! \brief Activation of silence detection */
+int ast_sildet_activate(struct ast_channel *chan, unsigned int silencelevel, unsigned int silenceframes)
+{
+ struct ast_datastore *datastore = NULL;
+ struct silence_detection_info *sildet = NULL;
+
+ int is_new = 0;
+
+ if (!chan) {
+ ast_log(LOG_WARNING, "No channel was provided.\n" );
+ return -1;
+ }
+ if (silenceframes < 3) {
+ ast_log(LOG_WARNING, "Silenceframes is set very low. Are you sure? Value=%d\n", silenceframes);
+ }
+ ast_debug(4, "----> Setting up silence detection/suppression with silence level %d and silence frames %d for chan %s\n", silencelevel, silenceframes, chan->name);
+
+ ast_channel_lock(chan);
+ ast_debug(4, "----> Looking for silence detection datastore for %s\n", chan->name);
+ if (!(datastore = ast_channel_datastore_find(chan, &sildet_datastore, NULL))) {
+ if (!(datastore = initialize_sildethook(chan))) {
+ ast_debug(4, "----> Failed to initialize hook for silence detection for %s\n", chan->name);
+ ast_channel_unlock(chan);
+ return 0;
+ }
+ is_new = 1;
+ }
+
+ /* Configure the silence detection */
+ sildet = datastore->data;
+ if (!sildet) {
+ ast_debug(4, "----> No datastore data for silence detection for %s\n", chan->name);
+ ast_channel_unlock(chan);
+ return 0;
+ }
+ if (!sildet->dsp) {
+ ast_debug(4, "----> No datastore dsp for silence detection for %s\n", chan->name);
+ ast_channel_unlock(chan);
+ return 0;
+ }
+ ast_debug(4, "----> Looking for silence detection datastore for %s\n", chan->name);
+ ast_dsp_set_threshold(sildet->dsp, silencelevel);
+ sildet->silencelevel = silencelevel;
+ sildet->silenceframes = silenceframes;
+ sildet->active = 1;
+ sildet->silencecounter = 0;
+ sildet->detect = 0;
+
+ if (is_new) {
+ if (sildet_add_audiohook(chan, sildet, datastore)) {
+ /* Can't add audiohook - already printed error message */
+ ast_datastore_free(datastore);
+ ast_free(sildet);
+ }
+ }
+ ast_channel_unlock(chan);
+
+ return 1;
+}
+
+int ast_sildet_deactivate(struct ast_channel *chan)
+{
+ struct ast_datastore *datastore = NULL;
+ struct silence_detection_info *sildet = NULL;
+ if (!chan) {
+ ast_log(LOG_WARNING, "No channel was provided.\n" );
+ return -1;
+ }
+ ast_channel_lock(chan);
+ if (!(datastore = ast_channel_datastore_find(chan, &sildet_datastore, NULL))) {
+ ast_debug(4, "----> No silence detection datastore for %s\n", chan->name);
+ ast_channel_unlock(chan);
+ return 0;
+ }
+ sildet = datastore->data;
+ if (!sildet) {
+ ast_debug(4, "----> No datastore data for silence detection for %s\n", chan->name);
+ ast_channel_unlock(chan);
+ return 0;
+ }
+ sildet->active = 0;
+ ast_audiohook_detach(&sildet->audiohook);
+ ast_channel_unlock(chan);
+ return 1;
+}
Propchange: team/oej/roibos-cng-support-1.8/main/silencedetection.c
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: team/oej/roibos-cng-support-1.8/main/silencedetection.c
------------------------------------------------------------------------------
svn:keywords = Author Date Id Revision
Propchange: team/oej/roibos-cng-support-1.8/main/silencedetection.c
------------------------------------------------------------------------------
svn:mime-type = text/plain
Modified: team/oej/roibos-cng-support-1.8/patches/silence-detection-games-1.8.diff
URL: http://svnview.digium.com/svn/asterisk/team/oej/roibos-cng-support-1.8/patches/silence-detection-games-1.8.diff?view=diff&rev=411924&r1=411923&r2=411924
==============================================================================
--- team/oej/roibos-cng-support-1.8/patches/silence-detection-games-1.8.diff (original)
+++ team/oej/roibos-cng-support-1.8/patches/silence-detection-games-1.8.diff Tue Apr 8 09:23:25 2014
@@ -737,53 +737,3 @@
;--------------------------- SIP Session-Timers (RFC 4028)------------------------------------
; SIP Session-Timers provide an end-to-end keep-alive mechanism for active SIP sessions.
; This mechanism can detect and reclaim SIP channels that do not terminate through normal
-Index: res/res_rtp_asterisk.c
-===================================================================
---- res/res_rtp_asterisk.c (.../branches/1.8) (revision 411922)
-+++ res/res_rtp_asterisk.c (.../team/oej/silence-detection-games-1.8) (revision 411922)
-@@ -1753,9 +1753,11 @@
- /* Convert comfort noise into audio with various codecs. Unfortunately this doesn't
- totally help us out becuase we don't have an engine to keep it going and we are not
- guaranteed to have it every 20ms or anything */
-- if (rtpdebug)
-+ if (rtpdebug) {
- ast_debug(0, "- RTP 3389 Comfort noise event: Level %" PRId64 " (len = %d)\n", rtp->lastrxformat, len);
-+ }
-
-+#ifdef OLD
- if (ast_test_flag(rtp, FLAG_3389_WARNING)) {
- struct ast_sockaddr remote_address = { {0,} };
-
-@@ -1765,10 +1767,12 @@
- ast_sockaddr_stringify(&remote_address));
- ast_set_flag(rtp, FLAG_3389_WARNING);
- }
-+#endif
-
- /* Must have at least one byte */
-- if (!len)
-+ if (!len) {
- return NULL;
-+ }
- if (len < 24) {
- rtp->f.data.ptr = rtp->rawdata + AST_FRIENDLY_OFFSET;
- rtp->f.datalen = len - 1;
-Index: .
-===================================================================
---- . (.../branches/1.8) (revision 411922)
-+++ . (.../team/oej/silence-detection-games-1.8) (revision 411922)
-
-Property changes on: .
-___________________________________________________________________
-Added: svnmerge-integrated
-## -0,0 +1 ##
-+/branches/1.8:1-411860
-\ No newline at end of property
-Added: automerge-email
-## -0,0 +1 ##
-+oej at edvina.net
-\ No newline at end of property
-Added: automerge
-## -0,0 +1 ##
-+*
-\ No newline at end of property
More information about the asterisk-commits
mailing list