summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--apps/app_mp3.c52
-rw-r--r--build_tools/menuselect-deps.in1
-rw-r--r--codecs/codec_codec2.c222
-rw-r--r--codecs/ex_codec2.h32
-rw-r--r--configs/samples/alsa.conf.sample4
-rw-r--r--configs/samples/ccss.conf.sample16
-rw-r--r--configs/samples/chan_dahdi.conf.sample4
-rw-r--r--configs/samples/console.conf.sample4
-rw-r--r--configs/samples/mgcp.conf.sample6
-rw-r--r--configs/samples/minivm.conf.sample14
-rw-r--r--configs/samples/misdn.conf.sample4
-rw-r--r--configs/samples/oss.conf.sample4
-rw-r--r--configs/samples/queues.conf.sample4
-rw-r--r--configs/samples/res_snmp.conf.sample2
-rw-r--r--configs/samples/sip.conf.sample44
-rw-r--r--configs/samples/skinny.conf.sample20
-rw-r--r--configs/samples/unistim.conf.sample4
-rw-r--r--configs/samples/vpb.conf.sample2
-rwxr-xr-xconfigure143
-rw-r--r--configure.ac3
-rwxr-xr-xcontrib/scripts/sip_to_pjsip/sip_to_pjsip.py6
-rw-r--r--include/asterisk/astobj2.h27
-rw-r--r--include/asterisk/autoconfig.h.in3
-rw-r--r--include/asterisk/format_cache.h5
-rw-r--r--include/asterisk/named_locks.h10
-rw-r--r--include/asterisk/sorcery.h20
-rw-r--r--main/astobj2.c75
-rw-r--r--main/codec_builtin.c25
-rw-r--r--main/format_cache.c10
-rw-r--r--main/format_cap.c2
-rw-r--r--main/named_locks.c83
-rw-r--r--main/sorcery.c19
-rw-r--r--makeopts.in3
-rw-r--r--res/res_pjsip/location.c36
-rw-r--r--res/res_pjsip_registrar.c14
35 files changed, 770 insertions, 153 deletions
diff --git a/apps/app_mp3.c b/apps/app_mp3.c
index 5712cfe33..05afe54b1 100644
--- a/apps/app_mp3.c
+++ b/apps/app_mp3.c
@@ -77,9 +77,10 @@ ASTERISK_REGISTER_FILE()
***/
static char *app = "MP3Player";
-static int mp3play(const char *filename, int fd)
+static int mp3play(const char *filename, unsigned int sampling_rate, int fd)
{
int res;
+ char sampling_rate_str[8];
res = ast_safe_fork(0);
if (res < 0)
@@ -93,30 +94,44 @@ static int mp3play(const char *filename, int fd)
dup2(fd, STDOUT_FILENO);
ast_close_fds_above_n(STDERR_FILENO);
+ snprintf(sampling_rate_str, 8, "%u", sampling_rate);
+
/* Execute mpg123, but buffer if it's a net connection */
- if (!strncasecmp(filename, "http://", 7)) {
+ if (!strncasecmp(filename, "http://", 7) && strstr(filename, ".m3u")) {
+ char buffer_size_str[8];
+ snprintf(buffer_size_str, 8, "%u", (int) 0.5*2*sampling_rate/1000); // 0.5 seconds for a live stream
+ /* Most commonly installed in /usr/local/bin */
+ execl(LOCAL_MPG_123, "mpg123", "-q", "-s", "-b", buffer_size_str, "-f", "8192", "--mono", "-r", sampling_rate_str, "-@", filename, (char *)NULL);
+ /* But many places has it in /usr/bin */
+ execl(MPG_123, "mpg123", "-q", "-s", "-b", buffer_size_str, "-f", "8192", "--mono", "-r", sampling_rate_str, "-@", filename, (char *)NULL);
+ /* As a last-ditch effort, try to use PATH */
+ execlp("mpg123", "mpg123", "-q", "-s", "-b", buffer_size_str, "-f", "8192", "--mono", "-r", sampling_rate_str, "-@", filename, (char *)NULL);
+ }
+ else if (!strncasecmp(filename, "http://", 7)) {
+ char buffer_size_str[8];
+ snprintf(buffer_size_str, 8, "%u", 6*2*sampling_rate/1000); // 6 seconds for a remote MP3 file
/* Most commonly installed in /usr/local/bin */
- execl(LOCAL_MPG_123, "mpg123", "-q", "-s", "-b", "1024", "-f", "8192", "--mono", "-r", "8000", filename, (char *)NULL);
+ execl(LOCAL_MPG_123, "mpg123", "-q", "-s", "-b", buffer_size_str, "-f", "8192", "--mono", "-r", sampling_rate_str, filename, (char *)NULL);
/* But many places has it in /usr/bin */
- execl(MPG_123, "mpg123", "-q", "-s", "-b", "1024","-f", "8192", "--mono", "-r", "8000", filename, (char *)NULL);
+ execl(MPG_123, "mpg123", "-q", "-s", "-b", buffer_size_str, "-f", "8192", "--mono", "-r", sampling_rate_str, filename, (char *)NULL);
/* As a last-ditch effort, try to use PATH */
- execlp("mpg123", "mpg123", "-q", "-s", "-b", "1024", "-f", "8192", "--mono", "-r", "8000", filename, (char *)NULL);
+ execlp("mpg123", "mpg123", "-q", "-s", "-b", buffer_size_str, "-f", "8192", "--mono", "-r", sampling_rate_str, filename, (char *)NULL);
}
else if (strstr(filename, ".m3u")) {
/* Most commonly installed in /usr/local/bin */
- execl(LOCAL_MPG_123, "mpg123", "-q", "-z", "-s", "-b", "1024", "-f", "8192", "--mono", "-r", "8000", "-@", filename, (char *)NULL);
+ execl(LOCAL_MPG_123, "mpg123", "-q", "-z", "-s", "-f", "8192", "--mono", "-r", sampling_rate_str, "-@", filename, (char *)NULL);
/* But many places has it in /usr/bin */
- execl(MPG_123, "mpg123", "-q", "-z", "-s", "-b", "1024","-f", "8192", "--mono", "-r", "8000", "-@", filename, (char *)NULL);
+ execl(MPG_123, "mpg123", "-q", "-z", "-s", "-f", "8192", "--mono", "-r", sampling_rate_str, "-@", filename, (char *)NULL);
/* As a last-ditch effort, try to use PATH */
- execlp("mpg123", "mpg123", "-q", "-z", "-s", "-b", "1024", "-f", "8192", "--mono", "-r", "8000", "-@", filename, (char *)NULL);
+ execlp("mpg123", "mpg123", "-q", "-z", "-s", "-f", "8192", "--mono", "-r", sampling_rate_str, "-@", filename, (char *)NULL);
}
else {
/* Most commonly installed in /usr/local/bin */
- execl(MPG_123, "mpg123", "-q", "-s", "-f", "8192", "--mono", "-r", "8000", filename, (char *)NULL);
+ execl(MPG_123, "mpg123", "-q", "-s", "-f", "8192", "--mono", "-r", sampling_rate_str, filename, (char *)NULL);
/* But many places has it in /usr/bin */
- execl(LOCAL_MPG_123, "mpg123", "-q", "-s", "-f", "8192", "--mono", "-r", "8000", filename, (char *)NULL);
+ execl(LOCAL_MPG_123, "mpg123", "-q", "-s", "-f", "8192", "--mono", "-r", sampling_rate_str, filename, (char *)NULL);
/* As a last-ditch effort, try to use PATH */
- execlp("mpg123", "mpg123", "-q", "-s", "-f", "8192", "--mono", "-r", "8000", filename, (char *)NULL);
+ execlp("mpg123", "mpg123", "-q", "-s", "-f", "8192", "--mono", "-r", sampling_rate_str, filename, (char *)NULL);
}
/* Can't use ast_log since FD's are closed */
fprintf(stderr, "Execute of mpg123 failed\n");
@@ -155,6 +170,9 @@ static int mp3_exec(struct ast_channel *chan, const char *data)
} myf = {
.f = { 0, },
};
+ struct ast_format * native_format;
+ unsigned int sampling_rate;
+ struct ast_format * write_format;
if (ast_strlen_zero(data)) {
ast_log(LOG_WARNING, "MP3 Playback requires an argument (filename)\n");
@@ -168,15 +186,19 @@ static int mp3_exec(struct ast_channel *chan, const char *data)
ast_stopstream(chan);
+ native_format = ast_format_cap_get_format(ast_channel_nativeformats(chan), 0);
+ sampling_rate = ast_format_get_sample_rate(native_format);
+ write_format = ast_format_cache_get_slin_by_rate(sampling_rate);
+
owriteformat = ao2_bump(ast_channel_writeformat(chan));
- res = ast_set_write_format(chan, ast_format_slin);
+ res = ast_set_write_format(chan, write_format);
if (res < 0) {
ast_log(LOG_WARNING, "Unable to set write format to signed linear\n");
return -1;
}
myf.f.frametype = AST_FRAME_VOICE;
- myf.f.subclass.format = ast_format_slin;
+ myf.f.subclass.format = write_format;
myf.f.mallocd = 0;
myf.f.offset = AST_FRIENDLY_OFFSET;
myf.f.src = __PRETTY_FUNCTION__;
@@ -184,7 +206,7 @@ static int mp3_exec(struct ast_channel *chan, const char *data)
myf.f.delivery.tv_usec = 0;
myf.f.data.ptr = myf.frdata;
- res = mp3play(data, fds[1]);
+ res = mp3play(data, sampling_rate, fds[1]);
if (!strncasecmp(data, "http://", 7)) {
timeout = 10000;
}
@@ -211,7 +233,7 @@ static int mp3_exec(struct ast_channel *chan, const char *data)
res = 0;
break;
}
- next = ast_tvadd(next, ast_samp2tv(myf.f.samples, 8000));
+ next = ast_tvadd(next, ast_samp2tv(myf.f.samples, sampling_rate));
} else {
ms = ast_waitfor(chan, ms);
if (ms < 0) {
diff --git a/build_tools/menuselect-deps.in b/build_tools/menuselect-deps.in
index f194482e9..a04440955 100644
--- a/build_tools/menuselect-deps.in
+++ b/build_tools/menuselect-deps.in
@@ -4,6 +4,7 @@ COROSYNC=@PBX_COROSYNC@
CRYPTO=@PBX_CRYPTO@
BFD=@PBX_BFD@
BISON=@PBX_BISON@
+CODEC2=@PBX_CODEC2@
CURL=@PBX_CURL@
DAHDI=@PBX_DAHDI@
DLADDR=@PBX_DLADDR@
diff --git a/codecs/codec_codec2.c b/codecs/codec_codec2.c
new file mode 100644
index 000000000..e446854c3
--- /dev/null
+++ b/codecs/codec_codec2.c
@@ -0,0 +1,222 @@
+/*
+ * Asterisk -- An open source telephony toolkit.
+ *
+ * Copyright (C) 2016, Alexander Traud
+ *
+ * Alexander Traud <pabstraud@compuserve.com>
+ *
+ * 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 Translate between signed linear and Codec 2
+ *
+ * \author Alexander Traud <pabstraud@compuserve.com>
+ *
+ * \note http://www.rowetel.com/codec2.html
+ *
+ * \ingroup codecs
+ */
+
+/*** MODULEINFO
+ <depend>codec2</depend>
+ <support_level>core</support_level>
+ ***/
+
+#include "asterisk.h"
+
+#include "asterisk/codec.h" /* for AST_MEDIA_TYPE_AUDIO */
+#include "asterisk/frame.h" /* for ast_frame */
+#include "asterisk/linkedlists.h" /* for AST_LIST_NEXT, etc */
+#include "asterisk/logger.h" /* for ast_log, etc */
+#include "asterisk/module.h"
+#include "asterisk/rtp_engine.h" /* ast_rtp_engine_(un)load_format */
+#include "asterisk/translate.h" /* for ast_trans_pvt, etc */
+
+#include <codec2/codec2.h>
+
+#define BUFFER_SAMPLES 8000
+#define CODEC2_SAMPLES 160 /* consider codec2_samples_per_frame(.) */
+#define CODEC2_FRAME_LEN 6 /* consider codec2_bits_per_frame(.) */
+
+/* Sample frame data */
+#include "asterisk/slin.h"
+#include "ex_codec2.h"
+
+struct codec2_translator_pvt {
+ struct CODEC2 *state; /* May be encoder or decoder */
+ int16_t buf[BUFFER_SAMPLES];
+};
+
+static int codec2_new(struct ast_trans_pvt *pvt)
+{
+ struct codec2_translator_pvt *tmp = pvt->pvt;
+
+ tmp->state = codec2_create(CODEC2_MODE_2400);
+
+ if (!tmp->state) {
+ ast_log(LOG_ERROR, "Error creating Codec 2 conversion\n");
+ return -1;
+ }
+
+ return 0;
+}
+
+/*! \brief decode and store in outbuf. */
+static int codec2tolin_framein(struct ast_trans_pvt *pvt, struct ast_frame *f)
+{
+ struct codec2_translator_pvt *tmp = pvt->pvt;
+ int x;
+
+ for (x = 0; x < f->datalen; x += CODEC2_FRAME_LEN) {
+ unsigned char *src = f->data.ptr + x;
+ int16_t *dst = pvt->outbuf.i16 + pvt->samples;
+
+ codec2_decode(tmp->state, dst, src);
+
+ pvt->samples += CODEC2_SAMPLES;
+ pvt->datalen += CODEC2_SAMPLES * 2;
+ }
+
+ return 0;
+}
+
+/*! \brief store samples into working buffer for later decode */
+static int lintocodec2_framein(struct ast_trans_pvt *pvt, struct ast_frame *f)
+{
+ struct codec2_translator_pvt *tmp = pvt->pvt;
+
+ memcpy(tmp->buf + pvt->samples, f->data.ptr, f->datalen);
+ pvt->samples += f->samples;
+
+ return 0;
+}
+
+/*! \brief encode and produce a frame */
+static struct ast_frame *lintocodec2_frameout(struct ast_trans_pvt *pvt)
+{
+ struct codec2_translator_pvt *tmp = pvt->pvt;
+ struct ast_frame *result = NULL;
+ struct ast_frame *last = NULL;
+ int samples = 0; /* output samples */
+
+ while (pvt->samples >= CODEC2_SAMPLES) {
+ struct ast_frame *current;
+
+ /* Encode a frame of data */
+ codec2_encode(tmp->state, pvt->outbuf.uc, tmp->buf + samples);
+
+ samples += CODEC2_SAMPLES;
+ pvt->samples -= CODEC2_SAMPLES;
+
+ current = ast_trans_frameout(pvt, CODEC2_FRAME_LEN, CODEC2_SAMPLES);
+
+ if (!current) {
+ continue;
+ } else if (last) {
+ AST_LIST_NEXT(last, frame_list) = current;
+ } else {
+ result = current;
+ }
+ last = current;
+ }
+
+ /* Move the data at the end of the buffer to the front */
+ if (samples) {
+ memmove(tmp->buf, tmp->buf + samples, pvt->samples * 2);
+ }
+
+ return result;
+}
+
+static void codec2_destroy_stuff(struct ast_trans_pvt *pvt)
+{
+ struct codec2_translator_pvt *tmp = pvt->pvt;
+
+ if (tmp->state) {
+ codec2_destroy(tmp->state);
+ }
+}
+
+static struct ast_translator codec2tolin = {
+ .name = "codec2tolin",
+ .src_codec = {
+ .name = "codec2",
+ .type = AST_MEDIA_TYPE_AUDIO,
+ .sample_rate = 8000,
+ },
+ .dst_codec = {
+ .name = "slin",
+ .type = AST_MEDIA_TYPE_AUDIO,
+ .sample_rate = 8000,
+ },
+ .format = "slin",
+ .newpvt = codec2_new,
+ .framein = codec2tolin_framein,
+ .destroy = codec2_destroy_stuff,
+ .sample = codec2_sample,
+ .desc_size = sizeof(struct codec2_translator_pvt),
+ .buffer_samples = BUFFER_SAMPLES,
+ .buf_size = BUFFER_SAMPLES * 2,
+};
+
+static struct ast_translator lintocodec2 = {
+ .name = "lintocodec2",
+ .src_codec = {
+ .name = "slin",
+ .type = AST_MEDIA_TYPE_AUDIO,
+ .sample_rate = 8000,
+ },
+ .dst_codec = {
+ .name = "codec2",
+ .type = AST_MEDIA_TYPE_AUDIO,
+ .sample_rate = 8000,
+ },
+ .format = "codec2",
+ .newpvt = codec2_new,
+ .framein = lintocodec2_framein,
+ .frameout = lintocodec2_frameout,
+ .destroy = codec2_destroy_stuff,
+ .sample = slin8_sample,
+ .desc_size = sizeof(struct codec2_translator_pvt),
+ .buffer_samples = BUFFER_SAMPLES,
+ .buf_size = (BUFFER_SAMPLES * CODEC2_FRAME_LEN + CODEC2_SAMPLES - 1) / CODEC2_SAMPLES,
+};
+
+static int unload_module(void)
+{
+ int res = 0;
+
+ res |= ast_rtp_engine_unload_format(ast_format_codec2);
+ res |= ast_unregister_translator(&lintocodec2);
+ res |= ast_unregister_translator(&codec2tolin);
+
+ return res;
+}
+
+static int load_module(void)
+{
+ int res = 0;
+
+ res |= ast_register_translator(&codec2tolin);
+ res |= ast_register_translator(&lintocodec2);
+ res |= ast_rtp_engine_load_format(ast_format_codec2);
+
+ if (res) {
+ unload_module();
+ return AST_MODULE_LOAD_FAILURE;
+ }
+
+ return AST_MODULE_LOAD_SUCCESS;
+}
+
+AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "Codec 2 Coder/Decoder");
diff --git a/codecs/ex_codec2.h b/codecs/ex_codec2.h
new file mode 100644
index 000000000..f2f4c9723
--- /dev/null
+++ b/codecs/ex_codec2.h
@@ -0,0 +1,32 @@
+/*! \file
+ * \brief 8-bit raw data
+ *
+ * Copyright (C) 2016, Alexander Traud
+ *
+ * Distributed under the terms of the GNU General Public License
+ *
+ */
+
+#include "asterisk/format_cache.h" /* for ast_format_codec2 */
+#include "asterisk/frame.h" /* for ast_frame, etc */
+
+static uint8_t ex_codec2[] = {
+ 0xea, 0xca, 0x14, 0x85, 0x91, 0x78,
+};
+
+static struct ast_frame *codec2_sample(void)
+{
+ static struct ast_frame f = {
+ .frametype = AST_FRAME_VOICE,
+ .datalen = sizeof(ex_codec2),
+ .samples = CODEC2_SAMPLES,
+ .mallocd = 0,
+ .offset = 0,
+ .src = __PRETTY_FUNCTION__,
+ .data.ptr = ex_codec2,
+ };
+
+ f.subclass.format = ast_format_codec2;
+
+ return &f;
+}
diff --git a/configs/samples/alsa.conf.sample b/configs/samples/alsa.conf.sample
index ced5b4485..23aac4e10 100644
--- a/configs/samples/alsa.conf.sample
+++ b/configs/samples/alsa.conf.sample
@@ -46,7 +46,7 @@ extension=s
; systems where there will be no return audio path, such as overhead pagers.
;noaudiocapture=true
-;------------------------------ JITTER BUFFER CONFIGURATION --------------------------
+; ----------------------------- JITTER BUFFER CONFIGURATION --------------------------
; jbenable = yes ; Enables the use of a jitterbuffer on the receiving side of an
; ALSA channel. Defaults to "no". An enabled jitterbuffer will
; be used only if the sending side can create and the receiving
@@ -74,5 +74,5 @@ extension=s
; network normally has low jitter, but occasionally has spikes.
; jblog = no ; Enables jitterbuffer frame logging. Defaults to "no".
-;-----------------------------------------------------------------------------------
+; ----------------------------------------------------------------------------------
diff --git a/configs/samples/ccss.conf.sample b/configs/samples/ccss.conf.sample
index 21b0b0668..7b3fe7d23 100644
--- a/configs/samples/ccss.conf.sample
+++ b/configs/samples/ccss.conf.sample
@@ -64,9 +64,9 @@
; PLEASE READ THIS!!!
;===========================================
;
-;---------------------------------------------------------------------
+; --------------------------------------------------------------------
; Timers
-;---------------------------------------------------------------------
+; --------------------------------------------------------------------
;There are three configurable timers for all types of CC: the
;cc_offer_timer, the ccbs_available_timer, and the ccnr_available_timer.
;In addition, when using a generic agent, there is a fourth timer,
@@ -98,9 +98,9 @@
; only affects operation when using a generic agent.
;
;cc_recall_timer = 20
-;---------------------------------------------------------------------
+; --------------------------------------------------------------------
; Policies
-;---------------------------------------------------------------------
+; --------------------------------------------------------------------
; Policy settings tell Asterisk how to behave and what sort of
; resources to allocate in order to facilitate CC. There are two
; settings to control the actions Asterisk will take.
@@ -153,9 +153,9 @@
;cc_monitor_policy=never
;
;
-;---------------------------------------------------------------------
+; --------------------------------------------------------------------
; Limits
-;---------------------------------------------------------------------
+; --------------------------------------------------------------------
;
; The use of CC requires Asterisk to potentially use more memory than
; some administrators would like. As such, it is a good idea to limit
@@ -175,9 +175,9 @@
;
;cc_max_monitors = 5
;
-;---------------------------------------------------------------------
+; --------------------------------------------------------------------
; Other
-;---------------------------------------------------------------------
+; --------------------------------------------------------------------
;
; When using a generic CC agent, the caller who requested CC will be
; called back when a called party becomes available. When the caller
diff --git a/configs/samples/chan_dahdi.conf.sample b/configs/samples/chan_dahdi.conf.sample
index a0c729c11..e70a2a138 100644
--- a/configs/samples/chan_dahdi.conf.sample
+++ b/configs/samples/chan_dahdi.conf.sample
@@ -1220,7 +1220,7 @@ pickupgroup=1
;
;jitterbuffers=4
;
-;------------------------------ JITTER BUFFER CONFIGURATION --------------------------
+; ----------------------------- JITTER BUFFER CONFIGURATION --------------------------
; jbenable = yes ; Enables the use of a jitterbuffer on the receiving side of a
; DAHDI channel. Defaults to "no". An enabled jitterbuffer will
; be used only if the sending side can create and the receiving
@@ -1248,7 +1248,7 @@ pickupgroup=1
; network normally has low jitter, but occasionally has spikes.
; jblog = no ; Enables jitterbuffer frame logging. Defaults to "no".
-;-----------------------------------------------------------------------------------
+; ----------------------------------------------------------------------------------
;
; You can define your own custom ring cadences here. You can define up to 8
; pairs. If the silence is negative, it indicates where the caller ID spill is
diff --git a/configs/samples/console.conf.sample b/configs/samples/console.conf.sample
index 606254eee..aad306ed5 100644
--- a/configs/samples/console.conf.sample
+++ b/configs/samples/console.conf.sample
@@ -44,7 +44,7 @@
;
;mohinterpret=default
-;------------------------------ JITTER BUFFER CONFIGURATION --------------------------
+; ----------------------------- JITTER BUFFER CONFIGURATION --------------------------
; jbenable = yes ; Enables the use of a jitterbuffer on the receiving side of an
; Console channel. Defaults to "no". An enabled jitterbuffer will
; be used only if the sending side can create and the receiving
@@ -72,7 +72,7 @@
; network normally has low jitter, but occasionally has spikes.
; jblog = no ; Enables jitterbuffer frame logging. Defaults to "no".
-;-----------------------------------------------------------------------------------
+; ----------------------------------------------------------------------------------
;
diff --git a/configs/samples/mgcp.conf.sample b/configs/samples/mgcp.conf.sample
index 7c725bc3d..f4bc0dbf2 100644
--- a/configs/samples/mgcp.conf.sample
+++ b/configs/samples/mgcp.conf.sample
@@ -11,12 +11,12 @@
;cos=3 ; Sets 802.1p priority for signaling packets.
;cos_audio=5 ; Sets 802.1p priority for RTP audio packets.
-;---------------------- DIGIT TIMEOUTS ----------------------------
+; --------------------- DIGIT TIMEOUTS ----------------------------
firstdigittimeout = 30000 ; default 16000 = 16s
gendigittimeout = 10000 ; default 8000 = 8s
matchdigittimeout = 5000 ; defaults 3000 = 3s
-;------------------------------ JITTER BUFFER CONFIGURATION --------------------------
+; ----------------------------- JITTER BUFFER CONFIGURATION --------------------------
; jbenable = yes ; Enables the use of a jitterbuffer on the receiving side of a
; MGCP channel. Defaults to "no". An enabled jitterbuffer will
; be used only if the sending side can create and the receiving
@@ -48,7 +48,7 @@ matchdigittimeout = 5000 ; defaults 3000 = 3s
; network normally has low jitter, but occasionally has spikes.
; jblog = no ; Enables jitterbuffer frame logging. Defaults to "no".
-;-----------------------------------------------------------------------------------
+; ----------------------------------------------------------------------------------
;[dlinkgw]
;host = 192.168.0.64
diff --git a/configs/samples/minivm.conf.sample b/configs/samples/minivm.conf.sample
index 55a39c869..2df3449d1 100644
--- a/configs/samples/minivm.conf.sample
+++ b/configs/samples/minivm.conf.sample
@@ -12,7 +12,7 @@
; this configuration file or realtime. The idea is to build voicemail as building blocks so that
; a complete and adaptive voicemail system can be built in the dialplan
;
-;------------------------------ Variables to use in subject, from and message body ------------------
+; ----------------------------- Variables to use in subject, from and message body ------------------
; Change the from, body and/or subject, variables:
; MVM_NAME, MVM_DUR, MVM_MSGNUM, VM_MAILBOX, MVM_CALLERID, MVM_CIDNUM,
; MVM_CIDNAME, MVM_DATE
@@ -24,7 +24,7 @@
; Note: The emailbody config row can only be up to 512 characters due to a
; limitation in the Asterisk configuration subsystem.
; To create longer mails, use the templatefile option when creating the template
-;----------------------------------------------------------------------------------------------------
+; ---------------------------------------------------------------------------------------------------
[general]
; Default format for storing and sending voicemail
@@ -64,7 +64,7 @@ silencethreshold=128
; This is used both for e-mail and pager messages
;mailcmd=/usr/sbin/sendmail -t
;
-;--------------Default e-mail message template (used if no templates are used) ------
+; -------------Default e-mail message template (used if no templates are used) ------
;fromstring=The Asterisk PBX
;
@@ -82,7 +82,7 @@ emaildateformat=%A, %B %d, %Y at %r
; 24h date format
;emaildateformat=%A, %d %B %Y at %H:%M:%S
;
-;--------------Default pager message template (used if no templates are used) ------
+; -------------Default pager message template (used if no templates are used) ------
; You can also change the Pager From: string, the pager body and/or subject.
; The above defined variables also can be used here
;pagerfromstring=The Asterisk PBX
@@ -90,7 +90,7 @@ emaildateformat=%A, %B %d, %Y at %r
;pagerbody=New ${MVM_DUR} long msg in box ${MVM_MAILBOX}\nfrom ${MVM_CALLERID}, on ${MVM_DATE}
;
;
-;--------------Timezone definitions (used in voicemail accounts) -------------------
+; -------------Timezone definitions (used in voicemail accounts) -------------------
;
; Users may be located in different timezones, or may have different
; message announcements for their introductory message when they enter
@@ -133,7 +133,7 @@ central=America/Chicago|'vm-received' Q 'digits/at' IMp
central24=America/Chicago|'vm-received' q 'digits/at' H N 'hours'
military=Zulu|'vm-received' q 'digits/at' H N 'hours' 'phonetic/z_p'
-;----------------------- Message body templates---------------------
+; ---------------------- Message body templates---------------------
; [template-name] ; "template-" is a verbatim marker
; fromaddress = Your Friendly Asterisk Server
; fromemail = asteriskvm@digium.com
@@ -187,7 +187,7 @@ dateformat=%A, %B %d, %Y at %r
;subject = Dear old chap, you've got an electronic communique
;charset=ascii
-;----------------------- Mailbox accounts --------------------------
+; ---------------------- Mailbox accounts --------------------------
;Template for mailbox definition - all options
;
; [username@domain] ; Has to be unique within domain (MWM_USERNAME, MWM_DOMAIN)
diff --git a/configs/samples/misdn.conf.sample b/configs/samples/misdn.conf.sample
index ac54dbc5a..ca27c03bd 100644
--- a/configs/samples/misdn.conf.sample
+++ b/configs/samples/misdn.conf.sample
@@ -109,7 +109,7 @@ crypt_prefix=**
;
crypt_keys=test,muh
-;------------------------------ JITTER BUFFER CONFIGURATION --------------------------
+; ----------------------------- JITTER BUFFER CONFIGURATION --------------------------
; jbenable = yes ; Enables the use of a jitterbuffer on the receiving side of a
; SIP channel. Defaults to "no". An enabled jitterbuffer will
; be used only if the sending side can create and the receiving
@@ -140,7 +140,7 @@ crypt_keys=test,muh
; network normally has low jitter, but occasionally has spikes.
; jblog = no ; Enables jitterbuffer frame logging. Defaults to "no".
-;-----------------------------------------------------------------------------------
+; ----------------------------------------------------------------------------------
; users sections:
;
diff --git a/configs/samples/oss.conf.sample b/configs/samples/oss.conf.sample
index c3781a2a2..ee169209f 100644
--- a/configs/samples/oss.conf.sample
+++ b/configs/samples/oss.conf.sample
@@ -46,7 +46,7 @@
; queuesize = 10 ; frames in device driver
; frags = 8 ; argument to SETFRAGMENT
- ;------------------------------ JITTER BUFFER CONFIGURATION --------------------------
+ ; ----------------------------- JITTER BUFFER CONFIGURATION --------------------------
; jbenable = yes ; Enables the use of a jitterbuffer on the receiving side of an
; OSS channel. Defaults to "no". An enabled jitterbuffer will
; be used only if the sending side can create and the receiving
@@ -74,7 +74,7 @@
; network normally has low jitter, but occasionally has spikes.
; jblog = no ; Enables jitterbuffer frame logging. Defaults to "no".
- ;-----------------------------------------------------------------------------------
+ ; ----------------------------------------------------------------------------------
; below is an entry for a second console channel
; [card1]
diff --git a/configs/samples/queues.conf.sample b/configs/samples/queues.conf.sample
index 85cf9e40f..8a9c88402 100644
--- a/configs/samples/queues.conf.sample
+++ b/configs/samples/queues.conf.sample
@@ -129,7 +129,7 @@ monitor-type = MixMonitor
;
;penaltymemberslimit = 5
;
-;----------------------QUEUE TIMING OPTIONS------------------------------------
+; ---------------------QUEUE TIMING OPTIONS------------------------------------
; A Queue has two different "timeout" values associated with it. One is the
; timeout parameter configured in queues.conf. This timeout specifies the
; amount of time to try ringing a member's phone before considering the
@@ -181,7 +181,7 @@ monitor-type = MixMonitor
;retry = 5
;timeoutpriority = app|conf
;
-;-----------------------END QUEUE TIMING OPTIONS---------------------------------
+; ----------------------END QUEUE TIMING OPTIONS---------------------------------
; Weight of queue - when compared to other queues, higher weights get
; first shot at available channels when the same channel is included in
; more than one queue.
diff --git a/configs/samples/res_snmp.conf.sample b/configs/samples/res_snmp.conf.sample
index a6e40c8e2..7f3734910 100644
--- a/configs/samples/res_snmp.conf.sample
+++ b/configs/samples/res_snmp.conf.sample
@@ -1,6 +1,6 @@
;
; Configuration file for res_snmp
-;---------------------------------
+; --------------------------------
;
; Res_snmp can run as a subagent or standalone SNMP agent. The standalone snmp
; agent is based on net-snmp and will read a configuration file called
diff --git a/configs/samples/sip.conf.sample b/configs/samples/sip.conf.sample
index da176b4d6..916e2d671 100644
--- a/configs/samples/sip.conf.sample
+++ b/configs/samples/sip.conf.sample
@@ -15,7 +15,7 @@
; - context - Which set of services you offer various users
;
; SIP dial strings
-;-----------------------------------------------------------
+; ----------------------------------------------------------
; In the dialplan (extensions.conf) you can use several
; syntaxes for dialing SIP devices.
; SIP/devicename
@@ -87,7 +87,7 @@
; sip reload Reload configuration file
; sip show settings Show the current channel configuration
;
-;------- Naming devices ------------------------------------------------------
+; ------ Naming devices ------------------------------------------------------
;
; When naming devices, make sure you understand how Asterisk matches calls
; that come in.
@@ -111,7 +111,7 @@
; not needed at all. Check below. In later releases, it's renamed
; to "defaultuser" which is a better name, since it is used in
; combination with the "defaultip" setting.
-;-----------------------------------------------------------------------------
+; ----------------------------------------------------------------------------
; ** Old configuration options **
; The "call-limit" configuation option is considered old is replaced
@@ -573,7 +573,7 @@ srvlookup=yes ; Enable DNS SRV lookups on outbound calls
; are not purged during SIP reloads.
;
-;------------------------ TLS settings ------------------------------------------------------------
+; ----------------------- TLS settings ------------------------------------------------------------
;tlscertfile=</path/to/certificate.pem> ; Certificate chain (*.pem format only) to use for TLS connections
; The certificates must be sorted starting with the subject's certificate
; and followed by intermediate CA certificates if applicable. If the
@@ -622,7 +622,7 @@ srvlookup=yes ; Enable DNS SRV lookups on outbound calls
; Your distribution might have changed that list
; further.
;
-;--------------------------- SIP timers ----------------------------------------------------
+; -------------------------- SIP timers ----------------------------------------------------
; These timers are used primarily in INVITE transactions.
; The default for Timer T1 is 500 ms or the measured run-trip time between
; Asterisk and the device if you have qualify=yes for the device.
@@ -636,7 +636,7 @@ srvlookup=yes ; Enable DNS SRV lookups on outbound calls
; in this amount of time, the call will autocongest
; Defaults to 64*timert1
-;--------------------------- RTP timers ----------------------------------------------------
+; -------------------------- RTP timers ----------------------------------------------------
; These timers are currently used for both audio and video streams. The RTP timeouts
; are only applied to the audio channel.
; The settings are settable in the global section as well as per device
@@ -652,7 +652,7 @@ srvlookup=yes ; Enable DNS SRV lookups on outbound calls
;rtpkeepalive=<secs> ; Send keepalives in the RTP stream to keep NAT open
; (default is off - zero)
-;--------------------------- SIP Session-Timers (RFC 4028)------------------------------------
+; -------------------------- 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
; signaling procedures. Session-Timers can be configured globally or at a user/peer level.
@@ -681,7 +681,7 @@ srvlookup=yes ; Enable DNS SRV lookups on outbound calls
;session-minse=90
;session-refresher=uac
;
-;--------------------------- SIP DEBUGGING ---------------------------------------------------
+; -------------------------- SIP DEBUGGING ---------------------------------------------------
;sipdebug = yes ; Turn on SIP debugging by default, from
; the moment the channel loads this configuration.
; NOTE: You cannot use the CLI to turn it off. You'll
@@ -692,7 +692,7 @@ srvlookup=yes ; Enable DNS SRV lookups on outbound calls
; SIP history is output to the DEBUG logging channel
-;--------------------------- STATUS NOTIFICATIONS (SUBSCRIPTIONS) ----------------------------
+; -------------------------- STATUS NOTIFICATIONS (SUBSCRIPTIONS) ----------------------------
; You can subscribe to the status of extensions with a "hint" priority
; (See extensions.conf.sample for examples)
; chan_sip support two major formats for notifications: dialog-info and SIMPLE
@@ -741,7 +741,7 @@ srvlookup=yes ; Enable DNS SRV lookups on outbound calls
;callcounter = yes ; Enable call counters on devices. This can be set per
; device too.
-;----------------------------------------- T.38 FAX SUPPORT ----------------------------------
+; ---------------------------------------- T.38 FAX SUPPORT ----------------------------------
;
; This setting is available in the [general] section as well as in device configurations.
; Setting this to yes enables T.38 FAX (UDPTL) on SIP calls; it defaults to off.
@@ -774,7 +774,7 @@ srvlookup=yes ; Enable DNS SRV lookups on outbound calls
; faxdetect = cng ; Enables only CNG detection
; faxdetect = t38 ; Enables only T.38 detection
;
-;----------------------------------------- OUTBOUND SIP REGISTRATIONS ------------------------
+; ---------------------------------------- OUTBOUND SIP REGISTRATIONS ------------------------
; Asterisk can register as a SIP user agent to a SIP proxy (provider)
; Format for the register statement is:
; register => [peer?][transport://]user[@domain][:secret[:authuser]]@host[:port][/extension][~expiry]
@@ -851,7 +851,7 @@ srvlookup=yes ; Enable DNS SRV lookups on outbound calls
; 401 responses and continue retrying according to normal
; retry rules.
-;----------------------------------------- OUTBOUND MWI SUBSCRIPTIONS -------------------------
+; ---------------------------------------- OUTBOUND MWI SUBSCRIPTIONS -------------------------
; Asterisk can subscribe to receive the MWI from another SIP server and store it locally for retrieval
; by other phones. At this time, you can only subscribe using UDP as the transport.
; Format for the mwi register statement is:
@@ -866,7 +866,7 @@ srvlookup=yes ; Enable DNS SRV lookups on outbound calls
; MWI received will be stored in the 1234 mailbox of the SIP_Remote context.
; It can be used by other phones by following the below:
; mailbox=1234@SIP_Remote
-;----------------------------------------- NAT SUPPORT ------------------------
+; ---------------------------------------- NAT SUPPORT ------------------------
;
; WARNING: SIP operation behind a NAT is tricky and you really need
; to read and understand well the following section.
@@ -1008,7 +1008,7 @@ srvlookup=yes ; Enable DNS SRV lookups on outbound calls
;
; icesupport = yes
-;----------------------------------- MEDIA HANDLING --------------------------------
+; ---------------------------------- MEDIA HANDLING --------------------------------
; By default, Asterisk tries to re-invite media streams to an optimal path. If there's
; no reason for Asterisk to stay in the media path, the media will be redirected.
; This does not really work well in the case where Asterisk is outside and the
@@ -1090,7 +1090,7 @@ srvlookup=yes ; Enable DNS SRV lookups on outbound calls
; option may be specified at the global or peer scope.
;force_avp=yes ; Force 'RTP/AVP', 'RTP/AVPF', 'RTP/SAVP', and 'RTP/SAVPF' to be used for
; media streams when appropriate, even if a DTLS stream is present.
-;----------------------------------------- REALTIME SUPPORT ------------------------
+; ---------------------------------------- REALTIME SUPPORT ------------------------
; For additional information on ARA, the Asterisk Realtime Architecture,
; please read https://wiki.asterisk.org/wiki/display/AST/Realtime+Database+Configuration
;
@@ -1128,7 +1128,7 @@ srvlookup=yes ; Enable DNS SRV lookups on outbound calls
; is still in memory (due to caching or other reasons), the
; information will not be removed from realtime storage
-;----------------------------------------- SIP DOMAIN SUPPORT ------------------------
+; ---------------------------------------- SIP DOMAIN SUPPORT ------------------------
; Incoming INVITE and REFER messages can be matched against a list of 'allowed'
; domains, each of which can direct the call to a specific context if desired.
; By default, all domains are accepted and sent to the default context or the
@@ -1167,13 +1167,13 @@ srvlookup=yes ; Enable DNS SRV lookups on outbound calls
; destinations which do not have a prior
; account relationship with your server.
-;------------------------------ Advice of Charge CONFIGURATION --------------------------
+; ----------------------------- Advice of Charge CONFIGURATION --------------------------
; snom_aoc_enabled = yes; ; This options turns on and off support for sending AOC-D and
; AOC-E to snom endpoints. This option can be used both in the
; peer and global scope. The default for this option is off.
-;------------------------------ JITTER BUFFER CONFIGURATION --------------------------
+; ----------------------------- JITTER BUFFER CONFIGURATION --------------------------
; jbenable = yes ; Enables the use of a jitterbuffer on the receiving side of a
; SIP channel. Defaults to "no". An enabled jitterbuffer will
; be used only if the sending side can create and the receiving
@@ -1205,7 +1205,7 @@ srvlookup=yes ; Enable DNS SRV lookups on outbound calls
; jblog = no ; Enables jitterbuffer frame logging. Defaults to "no".
-;-----------------------------------------------------------------------------------
+; ----------------------------------------------------------------------------------
[authentication]
; Global credentials for outbound calls, i.e. when a proxy challenges your
@@ -1224,7 +1224,7 @@ srvlookup=yes ; Enable DNS SRV lookups on outbound calls
; You may also add auth= statements to [peer] definitions
; Peer auth= override all other authentication settings if we match on realm
-;------------------------------------------------------------------------------
+; -----------------------------------------------------------------------------
; DEVICE CONFIGURATION
;
; SIP entities have a 'type' which determines their roles within Asterisk.
@@ -1351,7 +1351,7 @@ srvlookup=yes ; Enable DNS SRV lookups on outbound calls
; ; from the peer's configuration.
;
-;------------------------------------------------------------------------------
+; -----------------------------------------------------------------------------
; DTLS-SRTP CONFIGURATION
;
; DTLS-SRTP support is available if the underlying RTP engine in use supports it.
@@ -1409,7 +1409,7 @@ srvlookup=yes ; Enable DNS SRV lookups on outbound calls
;port=80 ; The port number we want to connect to on the remote side
; Also used as "defaultport" in combination with "defaultip" settings
-;--- sample definition for a provider
+; -- sample definition for a provider
;[provider1]
;type=peer
;host=sip.provider1.com
diff --git a/configs/samples/skinny.conf.sample b/configs/samples/skinny.conf.sample
index be88dc230..2bf06fbc8 100644
--- a/configs/samples/skinny.conf.sample
+++ b/configs/samples/skinny.conf.sample
@@ -54,7 +54,7 @@ keepalive=120
;cos_audio=5 ; Sets 802.1p priority for RTP audio packets.
;cos_video=4 ; Sets 802.1p priority for RTP video packets.
-;------------------------------ JITTER BUFFER CONFIGURATION --------------------------
+; ----------------------------- JITTER BUFFER CONFIGURATION --------------------------
;jbenable = yes ; Enables the use of a jitterbuffer on the receiving side of a
; skinny channel. Defaults to "no". An enabled jitterbuffer will
; be used only if the sending side can create and the receiving
@@ -79,10 +79,10 @@ keepalive=120
; Defaults to fixed.
;jblog = no ; Enables jitterbuffer frame logging. Defaults to "no".
-;-----------------------------------------------------------------------------------
+; ----------------------------------------------------------------------------------
[lines]
-;----------------------------------- LINES SECTION --------------------------------
+; ---------------------------------- LINES SECTION --------------------------------
; Options set under [lines] apply to all lines unless explicitly set for a particular
; device. The options that can be set under lines are specified in GENERAL LINE OPTIONS.
; These options can also be set for each individual device as well as those under SPECIFIC
@@ -95,15 +95,15 @@ keepalive=120
; Where options are common to both lines and devices, the results typically take that of
; the least permission. ie if a no is set for either line or device, the call will not be
; able to use that permission
-;-------------------------------- GENERAL LINE OPTIONS -----------------------------
+; ------------------------------- GENERAL LINE OPTIONS -----------------------------
;earlyrtp=1 ; whether audio signalling should be provided by asterisk
; ; (earlyrtp=1) or device generated (earlyrtp=0). default=yes
;transfer=1 ; whether the device is allowed to transfer. default=yes
;context=default ; context to use for this line.
;callfwdtimeout=20000 ; ms before cfwd_noans occurs (default 20 secs)
-;------------------------------- SPECIFIC LINE OPTIONS -----------------------------
+; ------------------------------ SPECIFIC LINE OPTIONS -----------------------------
;setvar= ; allows for the setting of chanvars.
-;-----------------------------------------------------------------------------------
+; ----------------------------------------------------------------------------------
;[100]
;nat=yes
@@ -149,7 +149,7 @@ keepalive=120
[devices]
-;---------------------------------- DEVICES SECTION -------------------------------
+; --------------------------------- DEVICES SECTION -------------------------------
; Options set under [devices] apply to all devices unless explicitly set for a particular
; device. The options that can be set under devices are specified in GENERAL DEVICE OPTIONS.
; These options can also be set for each individual device as well as those under SPECIFIC
@@ -162,16 +162,16 @@ keepalive=120
; Where options are common to both lines and devices, the results typically take that of
; the least permission. ie if a no is set for either line or device, the call will not be
; able to use that permission
-;------------------------------- GENERAL DEVICE OPTIONS ----------------------------
+; ------------------------------ GENERAL DEVICE OPTIONS ----------------------------
;earlyrtp=1 ; whether audio signalling should be provided by asterisk
; ; (earlyrtp=1) or device generated (earlyrtp=0). default=yes
;transfer=1 ; whether the device is allowed to transfer. default=yes
-;------------------------------ SPECIFIC DEVICE OPTIONS ----------------------------
+; ----------------------------- SPECIFIC DEVICE OPTIONS ----------------------------
;device="SEPxxxxxxxxxxxx ; id of the device. Must be set.
;version=P002G204 ; firmware version to be loaded. If this version is different
; ; to the one on the device, the device will try to load this
; ; version from the tftp server. Set to device firmware version.
-;-----------------------------------------------------------------------------------
+; ----------------------------------------------------------------------------------
; Typical config for 12SP+
;[florian]
diff --git a/configs/samples/unistim.conf.sample b/configs/samples/unistim.conf.sample
index c33426b0c..a09642796 100644
--- a/configs/samples/unistim.conf.sample
+++ b/configs/samples/unistim.conf.sample
@@ -17,7 +17,7 @@ port=5000 ; UDP port
;autoprovisioning=no ; Allow undeclared phones to register an extension. See README for important
; informations. no (default), yes, tn.
;mohsuggest=default
-;------------------------------ JITTER BUFFER CONFIGURATION --------------------------
+; ----------------------------- JITTER BUFFER CONFIGURATION --------------------------
; jbenable = yes ; Enables the use of a jitterbuffer on the receiving side of a
; SIP channel. Defaults to "no". An enabled jitterbuffer will
; be used only if the sending side can create and the receiving
@@ -41,7 +41,7 @@ port=5000 ; UDP port
; variable size, actually the new jb of IAX2). Defaults to fixed.
; jblog = no ; Enables jitterbuffer frame logging. Defaults to "no".
-;-----------------------------------------------------------------------------------
+; ----------------------------------------------------------------------------------
;[black] ; name of the device
diff --git a/configs/samples/vpb.conf.sample b/configs/samples/vpb.conf.sample
index fecb3ec59..bdc89dff5 100644
--- a/configs/samples/vpb.conf.sample
+++ b/configs/samples/vpb.conf.sample
@@ -199,7 +199,7 @@ grunttimeout=3600
;
mode=immediate
-;-------------------------------------------------------------------------
+; ------------------------------------------------------------------------
; Channel definitions
;
; Each channel inherits the settings specified above, unless the are
diff --git a/configure b/configure
index 43114a359..3e5140ddb 100755
--- a/configure
+++ b/configure
@@ -1164,6 +1164,10 @@ PBX_COROSYNC
COROSYNC_DIR
COROSYNC_INCLUDE
COROSYNC_LIB
+PBX_CODEC2
+CODEC2_DIR
+CODEC2_INCLUDE
+CODEC2_LIB
PBX_CAP
CAP_DIR
CAP_INCLUDE
@@ -1338,6 +1342,7 @@ with_bfd
with_execinfo
with_bluetooth
with_cap
+with_codec2
with_cpg
with_curses
with_crypt
@@ -2077,6 +2082,7 @@ Optional Packages:
--with-execinfo=PATH use Stack Backtrace files in PATH
--with-bluetooth=PATH use Bluetooth files in PATH
--with-cap=PATH use POSIX 1.e capabilities files in PATH
+ --with-codec2=PATH use Codec 2 Audio Decoder/Encoder files in PATH
--with-cpg=PATH use Corosync files in PATH
--with-curses=PATH use curses files in PATH
--with-crypt=PATH use password and data encryption files in PATH
@@ -9000,6 +9006,38 @@ fi
+ CODEC2_DESCRIP="Codec 2 Audio Decoder/Encoder"
+ CODEC2_OPTION="codec2"
+ PBX_CODEC2=0
+
+# Check whether --with-codec2 was given.
+if test "${with_codec2+set}" = set; then :
+ withval=$with_codec2;
+ case ${withval} in
+ n|no)
+ USE_CODEC2=no
+ # -1 is a magic value used by menuselect to know that the package
+ # was disabled, other than 'not found'
+ PBX_CODEC2=-1
+ ;;
+ y|ye|yes)
+ ac_mandatory_list="${ac_mandatory_list} CODEC2"
+ ;;
+ *)
+ CODEC2_DIR="${withval}"
+ ac_mandatory_list="${ac_mandatory_list} CODEC2"
+ ;;
+ esac
+
+fi
+
+
+
+
+
+
+
+
COROSYNC_DESCRIP="Corosync"
COROSYNC_OPTION="cpg"
PBX_COROSYNC=0
@@ -30531,6 +30569,111 @@ fi
fi
+if test "x${PBX_CODEC2}" != "x1" -a "${USE_CODEC2}" != "no"; then
+ pbxlibdir=""
+ # if --with-CODEC2=DIR has been specified, use it.
+ if test "x${CODEC2_DIR}" != "x"; then
+ if test -d ${CODEC2_DIR}/lib; then
+ pbxlibdir="-L${CODEC2_DIR}/lib"
+ else
+ pbxlibdir="-L${CODEC2_DIR}"
+ fi
+ fi
+ pbxfuncname="codec2_create"
+ if test "x${pbxfuncname}" = "x" ; then # empty lib, assume only headers
+ AST_CODEC2_FOUND=yes
+ else
+ ast_ext_lib_check_save_CFLAGS="${CFLAGS}"
+ CFLAGS="${CFLAGS} "
+ as_ac_Lib=`$as_echo "ac_cv_lib_codec2_${pbxfuncname}" | $as_tr_sh`
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for ${pbxfuncname} in -lcodec2" >&5
+$as_echo_n "checking for ${pbxfuncname} in -lcodec2... " >&6; }
+if eval \${$as_ac_Lib+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ ac_check_lib_save_LIBS=$LIBS
+LIBS="-lcodec2 ${pbxlibdir} $LIBS"
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+/* Override any GCC internal prototype to avoid an error.
+ Use char because int might match the return type of a GCC
+ builtin and then its argument prototype would still apply. */
+#ifdef __cplusplus
+extern "C"
+#endif
+char ${pbxfuncname} ();
+int
+main ()
+{
+return ${pbxfuncname} ();
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+ eval "$as_ac_Lib=yes"
+else
+ eval "$as_ac_Lib=no"
+fi
+rm -f core conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+eval ac_res=\$$as_ac_Lib
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
+$as_echo "$ac_res" >&6; }
+if eval test \"x\$"$as_ac_Lib"\" = x"yes"; then :
+ AST_CODEC2_FOUND=yes
+else
+ AST_CODEC2_FOUND=no
+fi
+
+ CFLAGS="${ast_ext_lib_check_save_CFLAGS}"
+ fi
+
+ # now check for the header.
+ if test "${AST_CODEC2_FOUND}" = "yes"; then
+ CODEC2_LIB="${pbxlibdir} -lcodec2 "
+ # if --with-CODEC2=DIR has been specified, use it.
+ if test "x${CODEC2_DIR}" != "x"; then
+ CODEC2_INCLUDE="-I${CODEC2_DIR}/include"
+ fi
+ CODEC2_INCLUDE="${CODEC2_INCLUDE} "
+ if test "xcodec2/codec2.h" = "x" ; then # no header, assume found
+ CODEC2_HEADER_FOUND="1"
+ else # check for the header
+ ast_ext_lib_check_saved_CPPFLAGS="${CPPFLAGS}"
+ CPPFLAGS="${CPPFLAGS} ${CODEC2_INCLUDE}"
+ ac_fn_c_check_header_mongrel "$LINENO" "codec2/codec2.h" "ac_cv_header_codec2_codec2_h" "$ac_includes_default"
+if test "x$ac_cv_header_codec2_codec2_h" = xyes; then :
+ CODEC2_HEADER_FOUND=1
+else
+ CODEC2_HEADER_FOUND=0
+fi
+
+
+ CPPFLAGS="${ast_ext_lib_check_saved_CPPFLAGS}"
+ fi
+ if test "x${CODEC2_HEADER_FOUND}" = "x0" ; then
+ CODEC2_LIB=""
+ CODEC2_INCLUDE=""
+ else
+ if test "x${pbxfuncname}" = "x" ; then # only checking headers -> no library
+ CODEC2_LIB=""
+ fi
+ PBX_CODEC2=1
+ cat >>confdefs.h <<_ACEOF
+#define HAVE_CODEC2 1
+_ACEOF
+
+ fi
+ fi
+fi
+
+
+
+
if test "x${PBX_COROSYNC}" != "x1" -a "${USE_COROSYNC}" != "no"; then
pbxlibdir=""
# if --with-COROSYNC=DIR has been specified, use it.
diff --git a/configure.ac b/configure.ac
index ba13bf46d..950cfc5a1 100644
--- a/configure.ac
+++ b/configure.ac
@@ -407,6 +407,7 @@ AST_EXT_LIB_SETUP([BFD], [Debug symbol decoding], [bfd])
AST_EXT_LIB_SETUP([BKTR], [Stack Backtrace], [execinfo])
AST_EXT_LIB_SETUP([BLUETOOTH], [Bluetooth], [bluetooth])
AST_EXT_LIB_SETUP([CAP], [POSIX 1.e capabilities], [cap])
+AST_EXT_LIB_SETUP([CODEC2], [Codec 2 Audio Decoder/Encoder], [codec2])
AST_EXT_LIB_SETUP([COROSYNC], [Corosync], [cpg])
AST_EXT_LIB_SETUP_OPTIONAL([COROSYNC_CFG_STATE_TRACK], [A callback only in corosync 1.x], [COROSYNC], [cfg])
AST_EXT_LIB_SETUP([CURSES], [curses], [curses])
@@ -2341,6 +2342,8 @@ else
AST_EXT_LIB_CHECK([RADIUS], [radiusclient-ng], [rc_read_config], [radiusclient-ng.h])
fi
+AST_EXT_LIB_CHECK([CODEC2], [codec2], [codec2_create], [codec2/codec2.h])
+
AST_EXT_LIB_CHECK([COROSYNC], [cpg], [cpg_join], [corosync/cpg.h], [-lcfg])
AST_EXT_LIB_CHECK([COROSYNC_CFG_STATE_TRACK], [cfg], [corosync_cfg_state_track], [corosync/cfg.h], [-lcfg])
diff --git a/contrib/scripts/sip_to_pjsip/sip_to_pjsip.py b/contrib/scripts/sip_to_pjsip/sip_to_pjsip.py
index 437386a67..4da31cb59 100755
--- a/contrib/scripts/sip_to_pjsip/sip_to_pjsip.py
+++ b/contrib/scripts/sip_to_pjsip/sip_to_pjsip.py
@@ -17,7 +17,7 @@ PREFIX = 'pjsip_'
def section_by_type(section, pjsip, type):
"""Finds a section based upon the given type, adding it if not found."""
def __find_dict(mdicts, key, val):
- """Given a list of mult-dicts, return the multi-dict that contains
+ """Given a list of multi-dicts, return the multi-dict that contains
the given key/value pair."""
def found(d):
@@ -1021,7 +1021,7 @@ class Registration:
if self.outbound_proxy:
set_value('outboundproxy', self.outbound_proxy, section, pjsip,
- nmapped, 'registartion')
+ nmapped, 'registration')
def map_registrations(sip, pjsip, nmapped):
@@ -1182,7 +1182,7 @@ def cli_options():
"""
global PREFIX
usage = "usage: %prog [options] [input-file [output-file]]\n\n" \
- "Converts the chan_sip configuration input-file to the chan_pjsip output-file.\n"\
+ "Converts the chan_sip configuration input-file to the chan_pjsip output-file.\n" \
"The input-file defaults to 'sip.conf'.\n" \
"The output-file defaults to 'pjsip.conf'."
parser = optparse.OptionParser(usage=usage)
diff --git a/include/asterisk/astobj2.h b/include/asterisk/astobj2.h
index 0472c1b37..28ae73e87 100644
--- a/include/asterisk/astobj2.h
+++ b/include/asterisk/astobj2.h
@@ -368,6 +368,13 @@ enum ao2_alloc_opts {
AO2_ALLOC_OPT_LOCK_NOLOCK = (2 << 0),
/*! The ao2 object locking option field mask. */
AO2_ALLOC_OPT_LOCK_MASK = (3 << 0),
+ /*!
+ * \internal The ao2 object uses a separate object for locking.
+ *
+ * \note This option is used internally by ao2_alloc_with_lockobj and
+ * should never be passed directly to ao2_alloc.
+ */
+ AO2_ALLOC_OPT_LOCK_OBJ = AO2_ALLOC_OPT_LOCK_MASK,
};
/*!
@@ -408,6 +415,26 @@ void *__ao2_alloc(size_t data_size, ao2_destructor_fn destructor_fn, unsigned in
/*! @} */
+/*!
+ * \since 14.1.0
+ * \brief Allocate and initialize an object with separate locking.
+ *
+ * \param data_size The sizeof() of the user-defined structure.
+ * \param destructor_fn The destructor function (can be NULL)
+ * \param lockobj A separate ao2 object that will provide locking.
+ * \param debug_msg An ao2 object debug tracing message.
+ * \return A pointer to user-data.
+ *
+ * \see \ref ao2_alloc for additional details.
+ *
+ * \note lockobj must be a valid AO2 object.
+ */
+#define ao2_alloc_with_lockobj(data_size, destructor_fn, lockobj, tag) \
+ __ao2_alloc_with_lockobj((data_size), (destructor_fn), (lockobj), (tag), __FILE__, __LINE__, __PRETTY_FUNCTION__)
+
+void *__ao2_alloc_with_lockobj(size_t data_size, ao2_destructor_fn destructor_fn, void *lockobj,
+ const char *tag, const char *file, int line, const char *func) attribute_warn_unused_result;
+
/*! \brief
* Reference/unreference an object and return the old refcount.
*
diff --git a/include/asterisk/autoconfig.h.in b/include/asterisk/autoconfig.h.in
index bdd93bb64..f9a6b46e4 100644
--- a/include/asterisk/autoconfig.h.in
+++ b/include/asterisk/autoconfig.h.in
@@ -145,6 +145,9 @@
/* Define to 1 if you have the `closefrom' function. */
#undef HAVE_CLOSEFROM
+/* Define to 1 if you have the Codec 2 Audio Decoder/Encoder library. */
+#undef HAVE_CODEC2
+
/* Define to 1 if you have the Corosync library. */
#undef HAVE_COROSYNC
diff --git a/include/asterisk/format_cache.h b/include/asterisk/format_cache.h
index 3894ad21b..6099c59ea 100644
--- a/include/asterisk/format_cache.h
+++ b/include/asterisk/format_cache.h
@@ -209,6 +209,11 @@ extern struct ast_format *ast_format_siren7;
extern struct ast_format *ast_format_opus;
/*!
+ * \brief Built-in cached Codec 2 format.
+ */
+extern struct ast_format *ast_format_codec2;
+
+/*!
* \brief Built-in cached t140 format.
*/
extern struct ast_format *ast_format_t140;
diff --git a/include/asterisk/named_locks.h b/include/asterisk/named_locks.h
index 0fe07d992..1959841d0 100644
--- a/include/asterisk/named_locks.h
+++ b/include/asterisk/named_locks.h
@@ -48,7 +48,7 @@
* To use a named lock:
* Call ast_named_lock_get with the appropriate keyspace and key.
* Use the standard ao2 lock/unlock functions as needed.
- * Call ast_named_lock_put when you're finished with it.
+ * Call ao2_cleanup when you're finished with it.
*/
/*!
@@ -66,9 +66,6 @@ struct ast_named_lock;
struct ast_named_lock *__ast_named_lock_get(const char *filename, int lineno, const char *func,
enum ast_named_lock_type lock_type, const char *keyspace, const char *key);
-int __ast_named_lock_put(const char *filename, int lineno, const char *func,
- struct ast_named_lock *lock);
-
/*!
* \brief Geta named lock handle
* \since 13.9.0
@@ -92,11 +89,8 @@ int __ast_named_lock_put(const char *filename, int lineno, const char *func,
* \since 13.9.0
*
* \param lock The pointer to the ast_named_lock structure returned by ast_named_lock_get
- * \retval 0 Success
- * \retval -1 Failure
*/
-#define ast_named_lock_put(lock) \
- __ast_named_lock_put(__FILE__, __LINE__, __PRETTY_FUNCTION__, lock)
+#define ast_named_lock_put(lock) ao2_cleanup(lock)
/*!
* @}
diff --git a/include/asterisk/sorcery.h b/include/asterisk/sorcery.h
index 23219ec41..896633816 100644
--- a/include/asterisk/sorcery.h
+++ b/include/asterisk/sorcery.h
@@ -988,10 +988,30 @@ int ast_sorcery_changeset_create(const struct ast_variable *original, const stru
*
* \retval non-NULL success
* \retval NULL failure
+ *
+ * \note The returned object does not support AO2 locking.
*/
void *ast_sorcery_generic_alloc(size_t size, ao2_destructor_fn destructor);
/*!
+ * \since 14.1.0
+ * \brief Allocate a generic sorcery capable object with locking.
+ *
+ * \details Sorcery objects may be replaced with new allocations during reloads.
+ * If locking is required on sorcery objects it must be shared between the old
+ * object and the new one. lockobj can be any AO2 object with locking enabled,
+ * but in most cases named locks should be used to provide stable locking.
+ *
+ * \param size Size of the object
+ * \param destructor Optional destructor function
+ * \param lockobj An AO2 object that will provide locking.
+ *
+ * \retval non-NULL success
+ * \retval NULL failure
+ */
+void *ast_sorcery_lockable_alloc(size_t size, ao2_destructor_fn destructor, void *lockobj);
+
+/*!
* \brief Allocate an object
*
* \param sorcery Pointer to a sorcery structure
diff --git a/main/astobj2.c b/main/astobj2.c
index 5c92f263f..604e6a1ae 100644
--- a/main/astobj2.c
+++ b/main/astobj2.c
@@ -108,6 +108,17 @@ struct astobj2_rwlock {
void *user_data[0];
};
+struct ao2_lockobj_priv {
+ void *lock;
+};
+
+/* AstObj2 with locking provided by a separate object. */
+struct astobj2_lockobj {
+ struct ao2_lockobj_priv lockobj;
+ struct __priv_data priv_data;
+ void *user_data[0];
+};
+
#ifdef AO2_DEBUG
struct ao2_stats ao2;
#endif
@@ -118,6 +129,9 @@ struct ao2_stats ao2;
#define INTERNAL_OBJ_RWLOCK(user_data) \
((struct astobj2_rwlock *) (((char *) (user_data)) - sizeof(struct astobj2_rwlock)))
+#define INTERNAL_OBJ_LOCKOBJ(user_data) \
+ ((struct astobj2_lockobj *) (((char *) (user_data)) - sizeof(struct astobj2_lockobj)))
+
#define INTERNAL_OBJ(user_data) \
(struct astobj2 *) ((char *) user_data - sizeof(struct astobj2))
@@ -187,6 +201,7 @@ int __ao2_lock(void *user_data, enum ao2_lock_req lock_how, const char *file, co
struct astobj2 *obj = __INTERNAL_OBJ_CHECK(user_data, file, line, func);
struct astobj2_lock *obj_mutex;
struct astobj2_rwlock *obj_rwlock;
+ struct astobj2_lockobj *obj_lockobj;
int res = 0;
if (obj == NULL) {
@@ -231,6 +246,10 @@ int __ao2_lock(void *user_data, enum ao2_lock_req lock_how, const char *file, co
case AO2_ALLOC_OPT_LOCK_NOLOCK:
/* The ao2 object has no lock. */
break;
+ case AO2_ALLOC_OPT_LOCK_OBJ:
+ obj_lockobj = INTERNAL_OBJ_LOCKOBJ(user_data);
+ res = __ao2_lock(obj_lockobj->lockobj.lock, lock_how, file, func, line, var);
+ break;
default:
ast_log(__LOG_ERROR, file, line, func, "Invalid lock option on ao2 object %p\n",
user_data);
@@ -245,6 +264,7 @@ int __ao2_unlock(void *user_data, const char *file, const char *func, int line,
struct astobj2 *obj = __INTERNAL_OBJ_CHECK(user_data, file, line, func);
struct astobj2_lock *obj_mutex;
struct astobj2_rwlock *obj_rwlock;
+ struct astobj2_lockobj *obj_lockobj;
int res = 0;
int current_value;
@@ -281,6 +301,10 @@ int __ao2_unlock(void *user_data, const char *file, const char *func, int line,
case AO2_ALLOC_OPT_LOCK_NOLOCK:
/* The ao2 object has no lock. */
break;
+ case AO2_ALLOC_OPT_LOCK_OBJ:
+ obj_lockobj = INTERNAL_OBJ_LOCKOBJ(user_data);
+ res = __ao2_unlock(obj_lockobj->lockobj.lock, file, func, line, var);
+ break;
default:
ast_log(__LOG_ERROR, file, line, func, "Invalid lock option on ao2 object %p\n",
user_data);
@@ -295,6 +319,7 @@ int __ao2_trylock(void *user_data, enum ao2_lock_req lock_how, const char *file,
struct astobj2 *obj = __INTERNAL_OBJ_CHECK(user_data, file, line, func);
struct astobj2_lock *obj_mutex;
struct astobj2_rwlock *obj_rwlock;
+ struct astobj2_lockobj *obj_lockobj;
int res = 0;
if (obj == NULL) {
@@ -339,6 +364,10 @@ int __ao2_trylock(void *user_data, enum ao2_lock_req lock_how, const char *file,
case AO2_ALLOC_OPT_LOCK_NOLOCK:
/* The ao2 object has no lock. */
return 0;
+ case AO2_ALLOC_OPT_LOCK_OBJ:
+ obj_lockobj = INTERNAL_OBJ_LOCKOBJ(user_data);
+ res = __ao2_trylock(obj_lockobj->lockobj.lock, lock_how, file, func, line, var);
+ break;
default:
ast_log(__LOG_ERROR, file, line, func, "Invalid lock option on ao2 object %p\n",
user_data);
@@ -370,6 +399,7 @@ enum ao2_lock_req __adjust_lock(void *user_data, enum ao2_lock_req lock_how, int
{
struct astobj2 *obj = INTERNAL_OBJ(user_data);
struct astobj2_rwlock *obj_rwlock;
+ struct astobj2_lockobj *obj_lockobj;
enum ao2_lock_req orig_lock;
switch (obj->priv_data.options & AO2_ALLOC_OPT_LOCK_MASK) {
@@ -400,6 +430,10 @@ enum ao2_lock_req __adjust_lock(void *user_data, enum ao2_lock_req lock_how, int
break;
}
break;
+ case AO2_ALLOC_OPT_LOCK_OBJ:
+ obj_lockobj = INTERNAL_OBJ_LOCKOBJ(user_data);
+ orig_lock = __adjust_lock(obj_lockobj->lockobj.lock, lock_how, keep_stronger);
+ break;
default:
ast_log(LOG_ERROR, "Invalid lock option on ao2 object %p\n", user_data);
/* Fall through */
@@ -441,6 +475,7 @@ int __ao2_ref(void *user_data, int delta,
struct astobj2 *obj = __INTERNAL_OBJ_CHECK(user_data, file, line, func);
struct astobj2_lock *obj_mutex;
struct astobj2_rwlock *obj_rwlock;
+ struct astobj2_lockobj *obj_lockobj;
int current_value;
int ret;
void *weakproxy = NULL;
@@ -552,6 +587,12 @@ int __ao2_ref(void *user_data, int delta,
case AO2_ALLOC_OPT_LOCK_NOLOCK:
ast_free(obj);
break;
+ case AO2_ALLOC_OPT_LOCK_OBJ:
+ obj_lockobj = INTERNAL_OBJ_LOCKOBJ(user_data);
+ ao2_t_ref(obj_lockobj->lockobj.lock, -1, "release lockobj");
+
+ ast_free(obj_lockobj);
+ break;
default:
ast_log(__LOG_ERROR, file, line, func,
"Invalid lock option on ao2 object %p\n", user_data);
@@ -581,13 +622,14 @@ void __ao2_cleanup(void *obj)
}
}
-void *__ao2_alloc(size_t data_size, ao2_destructor_fn destructor_fn, unsigned int options,
- const char *tag, const char *file, int line, const char *func)
+static void *internal_ao2_alloc(size_t data_size, ao2_destructor_fn destructor_fn, unsigned int options,
+ void *lockobj, const char *tag, const char *file, int line, const char *func)
{
/* allocation */
struct astobj2 *obj;
struct astobj2_lock *obj_mutex;
struct astobj2_rwlock *obj_rwlock;
+ struct astobj2_lockobj *obj_lockobj;
switch (options & AO2_ALLOC_OPT_LOCK_MASK) {
case AO2_ALLOC_OPT_LOCK_MUTEX:
@@ -614,6 +656,22 @@ void *__ao2_alloc(size_t data_size, ao2_destructor_fn destructor_fn, unsigned in
return NULL;
}
break;
+ case AO2_ALLOC_OPT_LOCK_OBJ:
+ lockobj = ao2_t_bump(lockobj, "set lockobj");
+ if (!lockobj) {
+ ast_log(__LOG_ERROR, file, line, func, "AO2_ALLOC_OPT_LOCK_OBJ requires a non-NULL lockobj.\n");
+ return NULL;
+ }
+
+ obj_lockobj = __ast_calloc(1, sizeof(*obj_lockobj) + data_size, file, line, func);
+ if (obj_lockobj == NULL) {
+ ao2_t_ref(lockobj, -1, "release lockobj for failed alloc");
+ return NULL;
+ }
+
+ obj_lockobj->lockobj.lock = lockobj;
+ obj = (struct astobj2 *) &obj_lockobj->priv_data;
+ break;
default:
/* Invalid option value. */
ast_log(__LOG_DEBUG, file, line, func, "Invalid lock option requested\n");
@@ -643,6 +701,19 @@ void *__ao2_alloc(size_t data_size, ao2_destructor_fn destructor_fn, unsigned in
return EXTERNAL_OBJ(obj);
}
+void *__ao2_alloc(size_t data_size, ao2_destructor_fn destructor_fn, unsigned int options,
+ const char *tag, const char *file, int line, const char *func)
+{
+ return internal_ao2_alloc(data_size, destructor_fn, options, NULL, tag, file, line, func);
+}
+
+void *__ao2_alloc_with_lockobj(size_t data_size, ao2_destructor_fn destructor_fn, void *lockobj,
+ const char *tag, const char *file, int line, const char *func)
+{
+ return internal_ao2_alloc(data_size, destructor_fn, AO2_ALLOC_OPT_LOCK_OBJ, lockobj,
+ tag, file, line, func);
+}
+
unsigned int ao2_options_get(void *obj)
{
struct astobj2 *orig_obj;
diff --git a/main/codec_builtin.c b/main/codec_builtin.c
index 15147980d..facb5a84c 100644
--- a/main/codec_builtin.c
+++ b/main/codec_builtin.c
@@ -108,6 +108,30 @@ static struct ast_codec g723 = {
.get_length = g723_length,
};
+static int codec2_samples(struct ast_frame *frame)
+{
+ return 160 * (frame->datalen / 6);
+}
+
+static int codec2_length(unsigned int samples)
+{
+ return (samples / 160) * 6;
+}
+
+static struct ast_codec codec2 = {
+ .name = "codec2",
+ .description = "Codec 2",
+ .type = AST_MEDIA_TYPE_AUDIO,
+ .sample_rate = 8000,
+ .minimum_ms = 20,
+ .maximum_ms = 300,
+ .default_ms = 20,
+ .minimum_bytes = 6,
+ .samples_count = codec2_samples,
+ .get_length = codec2_length,
+ .smooth = 1,
+};
+
static int none_samples(struct ast_frame *frame)
{
return frame->datalen;
@@ -869,6 +893,7 @@ int ast_codec_builtin_init(void)
{
int res = 0;
+ res |= CODEC_REGISTER_AND_CACHE(codec2);
res |= CODEC_REGISTER_AND_CACHE(g723);
res |= CODEC_REGISTER_AND_CACHE(ulaw);
res |= CODEC_REGISTER_AND_CACHE(alaw);
diff --git a/main/format_cache.c b/main/format_cache.c
index b4d426092..c704f1c37 100644
--- a/main/format_cache.c
+++ b/main/format_cache.c
@@ -218,6 +218,11 @@ struct ast_format *ast_format_siren7;
struct ast_format *ast_format_opus;
/*!
+ * \brief Built-in cached codec2 format.
+ */
+struct ast_format *ast_format_codec2;
+
+/*!
* \brief Built-in cached t140 format.
*/
struct ast_format *ast_format_t140;
@@ -328,6 +333,7 @@ static void format_cache_shutdown(void)
ao2_replace(ast_format_testlaw, NULL);
ao2_replace(ast_format_g719, NULL);
ao2_replace(ast_format_opus, NULL);
+ ao2_replace(ast_format_codec2, NULL);
ao2_replace(ast_format_jpeg, NULL);
ao2_replace(ast_format_png, NULL);
ao2_replace(ast_format_h261, NULL);
@@ -360,7 +366,9 @@ int ast_format_cache_init(void)
static void set_cached_format(const char *name, struct ast_format *format)
{
- if (!strcmp(name, "g723")) {
+ if (!strcmp(name, "codec2")) {
+ ao2_replace(ast_format_codec2, format);
+ } else if (!strcmp(name, "g723")) {
ao2_replace(ast_format_g723, format);
} else if (!strcmp(name, "ulaw")) {
ao2_replace(ast_format_ulaw, format);
diff --git a/main/format_cap.c b/main/format_cap.c
index 2b3e6cd5f..013b7bea1 100644
--- a/main/format_cap.c
+++ b/main/format_cap.c
@@ -703,7 +703,7 @@ const char *ast_format_cap_get_names(struct ast_format_cap *cap, struct ast_str
ast_str_set(buf, 0, "(");
- if (!AST_VECTOR_SIZE(&cap->preference_order)) {
+ if (!cap || !AST_VECTOR_SIZE(&cap->preference_order)) {
ast_str_append(buf, 0, "nothing)");
return ast_str_buffer(*buf);
}
diff --git a/main/named_locks.c b/main/named_locks.c
index 596048388..c71f3b579 100644
--- a/main/named_locks.c
+++ b/main/named_locks.c
@@ -35,13 +35,17 @@ ASTERISK_REGISTER_FILE()
struct ao2_container *named_locks;
#define NAMED_LOCKS_BUCKETS 101
-struct ast_named_lock {
+struct named_lock_proxy {
+ AO2_WEAKPROXY();
char key[0];
};
+struct ast_named_lock {
+};
+
static int named_locks_hash(const void *obj, const int flags)
{
- const struct ast_named_lock *lock = obj;
+ const struct named_lock_proxy *lock = obj;
switch (flags & OBJ_SEARCH_MASK) {
case OBJ_SEARCH_KEY:
@@ -57,8 +61,8 @@ static int named_locks_hash(const void *obj, const int flags)
static int named_locks_cmp(void *obj_left, void *obj_right, int flags)
{
- const struct ast_named_lock *object_left = obj_left;
- const struct ast_named_lock *object_right = obj_right;
+ const struct named_lock_proxy *object_left = obj_left;
+ const struct named_lock_proxy *object_right = obj_right;
const char *right_key = obj_right;
int cmp;
@@ -98,45 +102,72 @@ int ast_named_locks_init(void)
return 0;
}
+static void named_lock_proxy_cb(void *weakproxy, void *data)
+{
+ ao2_unlink(named_locks, weakproxy);
+}
+
struct ast_named_lock *__ast_named_lock_get(const char *filename, int lineno, const char *func,
enum ast_named_lock_type lock_type, const char *keyspace, const char *key)
{
+ struct named_lock_proxy *proxy = NULL;
struct ast_named_lock *lock = NULL;
- int concat_key_buff_len = strlen(keyspace) + strlen(key) + 2;
- char *concat_key = ast_alloca(concat_key_buff_len);
+ int keylen = strlen(keyspace) + strlen(key) + 2;
+ char *concat_key = ast_alloca(keylen);
sprintf(concat_key, "%s-%s", keyspace, key); /* Safe */
ao2_lock(named_locks);
- lock = ao2_find(named_locks, concat_key, OBJ_SEARCH_KEY | OBJ_NOLOCK);
- if (lock) {
+ proxy = ao2_find(named_locks, concat_key, OBJ_SEARCH_KEY | OBJ_NOLOCK);
+ if (proxy) {
ao2_unlock(named_locks);
- ast_assert((ao2_options_get(lock) & AO2_ALLOC_OPT_LOCK_MASK) == lock_type);
- return lock;
- }
+ lock = __ao2_weakproxy_get_object(proxy, 0, __PRETTY_FUNCTION__, filename, lineno, func);
+
+ if (lock) {
+ /* We have an existing lock and it's not being destroyed. */
+ ao2_ref(proxy, -1);
+ ast_assert((ao2_options_get(lock) & AO2_ALLOC_OPT_LOCK_MASK) == lock_type);
+
+ return lock;
+ }
- lock = ao2_alloc_options(sizeof(*lock) + concat_key_buff_len, NULL, lock_type);
- if (lock) {
- strcpy(lock->key, concat_key); /* Safe */
- ao2_link_flags(named_locks, lock, OBJ_NOLOCK);
+ /* the old proxy is being destroyed, clean list before creating/adding new one */
+ ao2_lock(named_locks);
+ ao2_unlink_flags(named_locks, proxy, OBJ_NOLOCK);
+ ao2_ref(proxy, -1);
}
- ao2_unlock(named_locks);
- return lock;
-}
+ proxy = ao2_t_weakproxy_alloc(sizeof(*proxy) + keylen, NULL, concat_key);
+ if (!proxy) {
+ goto failure_cleanup;
+ }
-int __ast_named_lock_put(const char *filename, int lineno, const char *func,
- struct ast_named_lock *lock)
-{
+ lock = __ao2_alloc(sizeof(*lock) + keylen, NULL, lock_type, concat_key, filename, lineno, func);
if (!lock) {
- return -1;
+ goto failure_cleanup;
}
- ao2_lock(named_locks);
- if (ao2_ref(lock, -1) == 2) {
- ao2_unlink_flags(named_locks, lock, OBJ_NOLOCK);
+ /* We have exclusive access to proxy and lock, no need for locking here. */
+ if (ao2_weakproxy_set_object(proxy, lock, OBJ_NOLOCK)) {
+ goto failure_cleanup;
}
+
+ if (ao2_weakproxy_subscribe(proxy, named_lock_proxy_cb, NULL, OBJ_NOLOCK)) {
+ goto failure_cleanup;
+ }
+
+ strcpy(proxy->key, concat_key); /* Safe */
+ ao2_link_flags(named_locks, proxy, OBJ_NOLOCK);
ao2_unlock(named_locks);
+ ao2_t_ref(proxy, -1, "Release allocation reference");
- return 0;
+ return lock;
+
+failure_cleanup:
+ ao2_unlock(named_locks);
+
+ ao2_cleanup(proxy);
+ ao2_cleanup(lock);
+
+ return NULL;
}
diff --git a/main/sorcery.c b/main/sorcery.c
index 55ee830b7..9f8c35c3b 100644
--- a/main/sorcery.c
+++ b/main/sorcery.c
@@ -1736,9 +1736,26 @@ static void sorcery_object_destructor(void *object)
ast_free(details->object->id);
}
+void *ast_sorcery_lockable_alloc(size_t size, ao2_destructor_fn destructor, void *lockobj)
+{
+ void *object = ao2_alloc_with_lockobj(size + sizeof(struct ast_sorcery_object),
+ sorcery_object_destructor, lockobj, "");
+ struct ast_sorcery_object_details *details = object;
+
+ if (!object) {
+ return NULL;
+ }
+
+ details->object = object + size;
+ details->object->destructor = destructor;
+
+ return object;
+}
+
void *ast_sorcery_generic_alloc(size_t size, ao2_destructor_fn destructor)
{
- void *object = ao2_alloc_options(size + sizeof(struct ast_sorcery_object), sorcery_object_destructor, AO2_ALLOC_OPT_LOCK_NOLOCK);
+ void *object = ao2_alloc_options(size + sizeof(struct ast_sorcery_object),
+ sorcery_object_destructor, AO2_ALLOC_OPT_LOCK_NOLOCK);
struct ast_sorcery_object_details *details = object;
if (!object) {
diff --git a/makeopts.in b/makeopts.in
index d4347daf1..f0b0d0ef5 100644
--- a/makeopts.in
+++ b/makeopts.in
@@ -126,6 +126,9 @@ BFD_LIB=@BFD_LIB@
BLUETOOTH_INCLUDE=@BLUETOOTH_INCLUDE@
BLUETOOTH_LIB=@BLUETOOTH_LIB@
+CODEC2_INCLUDE=@CODEC2_INCLUDE@
+CODEC2_LIB=@CODEC2_LIB@
+
CURL_INCLUDE=@CURL_INCLUDE@
CURL_LIB=@CURL_LIB@
diff --git a/res/res_pjsip/location.c b/res/res_pjsip/location.c
index 0ab69ec5b..5abfcabad 100644
--- a/res/res_pjsip/location.c
+++ b/res/res_pjsip/location.c
@@ -49,11 +49,22 @@ static void aor_destroy(void *obj)
/*! \brief Allocator for AOR */
static void *aor_alloc(const char *name)
{
- struct ast_sip_aor *aor = ast_sorcery_generic_alloc(sizeof(struct ast_sip_aor), aor_destroy);
+ void *lock;
+ struct ast_sip_aor *aor;
+
+ lock = ast_named_lock_get(AST_NAMED_LOCK_TYPE_MUTEX, "aor", name);
+ if (!lock) {
+ return NULL;
+ }
+
+ aor = ast_sorcery_lockable_alloc(sizeof(struct ast_sip_aor), aor_destroy, lock);
+ ao2_ref(lock, -1);
+
if (!aor) {
return NULL;
}
ast_string_field_init(aor, 128);
+
return aor;
}
@@ -206,17 +217,11 @@ struct ao2_container *ast_sip_location_retrieve_aor_contacts_nolock(const struct
struct ao2_container *ast_sip_location_retrieve_aor_contacts(const struct ast_sip_aor *aor)
{
struct ao2_container *contacts;
- struct ast_named_lock *lock;
- lock = ast_named_lock_get(AST_NAMED_LOCK_TYPE_MUTEX, "aor", ast_sorcery_object_get_id(aor));
- if (!lock) {
- return NULL;
- }
-
- ao2_lock(lock);
+ /* ao2_lock / ao2_unlock do not actually write aor since it has an ao2 lockobj. */
+ ao2_lock((void*)aor);
contacts = ast_sip_location_retrieve_aor_contacts_nolock(aor);
- ao2_unlock(lock);
- ast_named_lock_put(lock);
+ ao2_unlock((void*)aor);
return contacts;
}
@@ -369,19 +374,12 @@ int ast_sip_location_add_contact(struct ast_sip_aor *aor, const char *uri,
struct ast_sip_endpoint *endpoint)
{
int res;
- struct ast_named_lock *lock;
-
- lock = ast_named_lock_get(AST_NAMED_LOCK_TYPE_MUTEX, "aor", ast_sorcery_object_get_id(aor));
- if (!lock) {
- return -1;
- }
- ao2_lock(lock);
+ ao2_lock(aor);
res = ast_sip_location_add_contact_nolock(aor, uri, expiration_time, path_info, user_agent,
via_addr, via_port, call_id,
endpoint);
- ao2_unlock(lock);
- ast_named_lock_put(lock);
+ ao2_unlock(aor);
return res;
}
diff --git a/res/res_pjsip_registrar.c b/res/res_pjsip_registrar.c
index f99a3b84d..47d5991e4 100644
--- a/res/res_pjsip_registrar.c
+++ b/res/res_pjsip_registrar.c
@@ -523,25 +523,17 @@ static int register_aor(pjsip_rx_data *rdata,
{
int res;
struct ao2_container *contacts = NULL;
- struct ast_named_lock *lock;
- lock = ast_named_lock_get(AST_NAMED_LOCK_TYPE_MUTEX, "aor", aor_name);
- if (!lock) {
- return PJ_TRUE;
- }
-
- ao2_lock(lock);
+ ao2_lock(aor);
contacts = ast_sip_location_retrieve_aor_contacts_nolock(aor);
if (!contacts) {
- ao2_unlock(lock);
- ast_named_lock_put(lock);
+ ao2_unlock(aor);
return PJ_TRUE;
}
res = register_aor_core(rdata, endpoint, aor, aor_name, contacts);
ao2_cleanup(contacts);
- ao2_unlock(lock);
- ast_named_lock_put(lock);
+ ao2_unlock(aor);
return res;
}