From c342003d845fa1cac5dd01023eef1a45b7b1c553 Mon Sep 17 00:00:00 2001 From: drowe67 Date: Thu, 3 Apr 2014 21:22:19 +0000 Subject: [PATCH] asterisk 11 driver patch, Thanks Antonio git-svn-id: https://svn.code.sf.net/p/freetel/code@1486 01035d8c-6547-0410-b346-abe4f91aad63 --- codec2-dev/asterisk-11/README.md | 19 + .../asterisk-11/asterisk-11.8.1-codec2.patch | 384 ++++++++++++++++++ .../asterisk-11.8.1-opus-codec2.patch | 384 ++++++++++++++++++ 3 files changed, 787 insertions(+) create mode 100644 codec2-dev/asterisk-11/README.md create mode 100644 codec2-dev/asterisk-11/asterisk-11.8.1-codec2.patch create mode 100644 codec2-dev/asterisk-11/asterisk-11.8.1-opus-codec2.patch diff --git a/codec2-dev/asterisk-11/README.md b/codec2-dev/asterisk-11/README.md new file mode 100644 index 00000000..6f5b2442 --- /dev/null +++ b/codec2-dev/asterisk-11/README.md @@ -0,0 +1,19 @@ +#Asterisk 11 Codec 2 support +=========================== + +##Description +These patches add Codec 2 2400 support to Asterisk 11. +The following patches are provided: + +* asterisk-11.8.1-codec2.patch: plain Asterisk 11. +* asterisk-11.8.1-opus-codec2.patch: Asterisk patched with Meetecho's Opus codec support. + +##Building +Building and installing are integrated within Asterisk building environment. libcodec2 must be installed beforehand. + +##Credits +I've followed the example of [asterisk-opus](https://github.com/meetecho/asterisk-opus), by [@meetecho](https://github.com/meetecho), to adapt Codec2 Asterisk 1.8 patch to version 11. + +Many thanks to the [Codec2](http://www.rowetel.com/blog/codec2.html) team for developing such great codec! + +Developed by [Antonio Eugenio Burriel](https://github.com/aeburriel) diff --git a/codec2-dev/asterisk-11/asterisk-11.8.1-codec2.patch b/codec2-dev/asterisk-11/asterisk-11.8.1-codec2.patch new file mode 100644 index 00000000..a2fa0db0 --- /dev/null +++ b/codec2-dev/asterisk-11/asterisk-11.8.1-codec2.patch @@ -0,0 +1,384 @@ +diff -urN asterisk-11.8.1-orig/build_tools/menuselect-deps.in asterisk-11.8.1-codec2/build_tools/menuselect-deps.in +--- asterisk-11.8.1-orig/build_tools/menuselect-deps.in 2013-04-11 21:59:35.000000000 +0200 ++++ asterisk-11.8.1-codec2/build_tools/menuselect-deps.in 2014-04-01 10:24:29.368859813 +0200 +@@ -4,6 +4,7 @@ + CRYPTO=@PBX_CRYPTO@ + BFD=@PBX_BFD@ + BISON=@PBX_BISON@ ++CODEC2=@PBX_CODEC2@ + CURL=@PBX_CURL@ + DAHDI=@PBX_DAHDI@ + DLADDR=@PBX_DLADDR@ +diff -urN asterisk-11.8.1-orig/codecs/codec_codec2.c asterisk-11.8.1-codec2/codecs/codec_codec2.c +--- asterisk-11.8.1-orig/codecs/codec_codec2.c 1970-01-01 01:00:00.000000000 +0100 ++++ asterisk-11.8.1-codec2/codecs/codec_codec2.c 2014-04-01 01:28:47.000000000 +0200 +@@ -0,0 +1,190 @@ ++/* ++ * Codec 2 module for Asterisk. ++ * ++ * Credit: codec_gsm.c used as a starting point. ++ * ++ * Copyright (C) 2012 Ed W and David Rowe ++ * ++ * 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 ++ * ++ * \ingroup codecs ++ */ ++ ++/*** MODULEINFO ++ codec2 ++ core ++ ***/ ++ ++#include "asterisk.h" ++ ++#include "asterisk/translate.h" ++#include "asterisk/config.h" ++#include "asterisk/module.h" ++#include "asterisk/utils.h" ++ ++#include ++ ++#define BUFFER_SAMPLES 8000 ++#define CODEC2_SAMPLES 160 ++#define CODEC2_FRAME_LEN 6 ++ ++/* Sample frame data */ ++ ++#include "asterisk/slin.h" ++#include "ex_codec2.h" ++ ++struct codec2_translator_pvt { /* both codec2tolin and codec2togsm */ ++ struct CODEC2 *codec2; ++ int16_t buf[BUFFER_SAMPLES]; /* lintocodec2, temporary storage */ ++}; ++ ++static int codec2_new(struct ast_trans_pvt *pvt) ++{ ++ struct codec2_translator_pvt *tmp = pvt->pvt; ++ ++ tmp->codec2 = codec2_create(CODEC2_MODE_2400); ++ if (!tmp) ++ 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; ++ int16_t *dst = pvt->outbuf.i16; ++ int flen = CODEC2_FRAME_LEN; ++ ++ for (x=0; x < f->datalen; x += flen) { ++ unsigned char *src; ++ int len; ++ len = CODEC2_SAMPLES; ++ src = f->data.ptr + x; ++ ++ codec2_decode(tmp->codec2, dst + pvt->samples, src); ++ ++ pvt->samples += CODEC2_SAMPLES; ++ pvt->datalen += 2 * CODEC2_SAMPLES; ++ } ++ 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; ++ ++ if (pvt->samples + f->samples > BUFFER_SAMPLES) { ++ ast_log(LOG_WARNING, "Out of buffer space\n"); ++ return -1; ++ } ++ 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; ++ int datalen = 0; ++ int samples = 0; ++ ++ /* We can't work on anything less than a frame in size */ ++ if (pvt->samples < CODEC2_SAMPLES) ++ return NULL; ++ while (pvt->samples >= CODEC2_SAMPLES) { ++ /* Encode a frame of data */ ++ codec2_encode(tmp->codec2, (unsigned char*)(pvt->outbuf.c + datalen), tmp->buf + samples); ++ datalen += CODEC2_FRAME_LEN; ++ samples += CODEC2_SAMPLES; ++ pvt->samples -= CODEC2_SAMPLES; ++ } ++ ++ /* Move the data at the end of the buffer to the front */ ++ if (pvt->samples) ++ memmove(tmp->buf, tmp->buf + samples, pvt->samples * 2); ++ ++ return ast_trans_frameout(pvt, datalen, samples); ++} ++ ++static void codec2_destroy_stuff(struct ast_trans_pvt *pvt) ++{ ++ struct codec2_translator_pvt *tmp = pvt->pvt; ++ if (tmp->codec2) ++ codec2_destroy(tmp->codec2); ++} ++ ++static struct ast_translator codec2tolin = { ++ .name = "codec2tolin", ++ .newpvt = codec2_new, ++ .framein = codec2tolin_framein, ++ .destroy = codec2_destroy_stuff, ++ .sample = codec2_sample, ++ .buffer_samples = BUFFER_SAMPLES, ++ .buf_size = BUFFER_SAMPLES * 2, ++ .desc_size = sizeof (struct codec2_translator_pvt ), ++}; ++ ++static struct ast_translator lintocodec2 = { ++ .name = "lintocodec2", ++ .newpvt = codec2_new, ++ .framein = lintocodec2_framein, ++ .frameout = lintocodec2_frameout, ++ .destroy = codec2_destroy_stuff, ++ .sample = slin8_sample, ++ .desc_size = sizeof (struct codec2_translator_pvt ), ++ .buf_size = (BUFFER_SAMPLES * CODEC2_FRAME_LEN + CODEC2_SAMPLES - 1)/CODEC2_SAMPLES, ++}; ++ ++/*! \brief standard module glue */ ++static int reload(void) ++{ ++ return AST_MODULE_LOAD_SUCCESS; ++} ++ ++static int unload_module(void) ++{ ++ int res; ++ ++ res = ast_unregister_translator(&lintocodec2); ++ if (!res) ++ res = ast_unregister_translator(&codec2tolin); ++ ++ return res; ++} ++ ++static int load_module(void) ++{ ++ int res; ++ ++ ast_format_set(&codec2tolin.src_format, AST_FORMAT_CODEC2, 0); ++ ast_format_set(&codec2tolin.dst_format, AST_FORMAT_SLINEAR, 0); ++ ++ ast_format_set(&lintocodec2.src_format, AST_FORMAT_SLINEAR, 0); ++ ast_format_set(&lintocodec2.dst_format, AST_FORMAT_CODEC2, 0); ++ ++ res = ast_register_translator(&codec2tolin); ++ if (!res) ++ res=ast_register_translator(&lintocodec2); ++ else ++ ast_unregister_translator(&codec2tolin); ++ if (res) ++ return AST_MODULE_LOAD_FAILURE; ++ return AST_MODULE_LOAD_SUCCESS; ++} ++ ++AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_DEFAULT, "Codec 2 Coder/Decoder", ++ .load = load_module, ++ .unload = unload_module, ++ .reload = reload, ++ ); +diff -urN asterisk-11.8.1-orig/codecs/ex_codec2.h asterisk-11.8.1-codec2/codecs/ex_codec2.h +--- asterisk-11.8.1-orig/codecs/ex_codec2.h 1970-01-01 01:00:00.000000000 +0100 ++++ asterisk-11.8.1-codec2/codecs/ex_codec2.h 2014-04-01 01:30:29.000000000 +0200 +@@ -0,0 +1,29 @@ ++/*! \file ++ * \brief 8-bit raw data ++ * ++ * Copyright (C) 2012, 2012 Ed W and David Rowe ++ * ++ * Distributed under the terms of the GNU General Public License ++ * ++ */ ++ ++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, ++ }; ++ ++ ast_format_set(&f.subclass.format, AST_FORMAT_CODEC2, 0); ++ ++ return &f; ++} +diff -urN asterisk-11.8.1-orig/configure.ac asterisk-11.8.1-codec2/configure.ac +--- asterisk-11.8.1-orig/configure.ac 2014-01-08 17:17:32.000000000 +0100 ++++ asterisk-11.8.1-codec2/configure.ac 2014-04-01 10:27:08.503390997 +0200 +@@ -384,6 +384,7 @@ + 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], [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]) +@@ -2116,6 +2117,8 @@ + + AST_EXT_LIB_CHECK([RADIUS], [radiusclient-ng], [rc_read_config], [radiusclient-ng.h]) + ++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 -urN asterisk-11.8.1-orig/include/asterisk/format.h asterisk-11.8.1-codec2/include/asterisk/format.h +--- asterisk-11.8.1-orig/include/asterisk/format.h 2012-07-13 20:41:07.000000000 +0200 ++++ asterisk-11.8.1-codec2/include/asterisk/format.h 2014-04-01 10:03:16.120355835 +0200 +@@ -101,6 +101,7 @@ + AST_FORMAT_SLINEAR192 = 27 + AST_FORMAT_TYPE_AUDIO, + AST_FORMAT_SPEEX32 = 28 + AST_FORMAT_TYPE_AUDIO, + AST_FORMAT_CELT = 29 + AST_FORMAT_TYPE_AUDIO, ++ AST_FORMAT_CODEC2 = 31 + AST_FORMAT_TYPE_AUDIO, + + /*! H.261 Video */ + AST_FORMAT_H261 = 1 + AST_FORMAT_TYPE_VIDEO, +diff -urN asterisk-11.8.1-orig/main/channel.c asterisk-11.8.1-codec2/main/channel.c +--- asterisk-11.8.1-orig/main/channel.c 2013-12-31 00:16:04.000000000 +0100 ++++ asterisk-11.8.1-codec2/main/channel.c 2014-04-01 10:06:55.659929991 +0200 +@@ -918,6 +918,8 @@ + AST_FORMAT_SILK, + /*! CELT supports crazy high sample rates */ + AST_FORMAT_CELT, ++ /* Codec 2 */ ++ AST_FORMAT_CODEC2, + /*! Ick, LPC10 sounds terrible, but at least we have code for it, if you're tacky enough + to use it */ + AST_FORMAT_LPC10, +diff -urN asterisk-11.8.1-orig/main/format.c asterisk-11.8.1-codec2/main/format.c +--- asterisk-11.8.1-orig/main/format.c 2013-06-12 04:25:23.000000000 +0200 ++++ asterisk-11.8.1-codec2/main/format.c 2014-04-01 10:11:05.319972320 +0200 +@@ -430,6 +430,9 @@ + /*! SpeeX Wideband (16kHz) Free Compression */ + case AST_FORMAT_SPEEX16: + return (1ULL << 33); ++ /*! Codec 2 (8KHz) */ ++ case AST_FORMAT_CODEC2: ++ return (1ULL << 35); + /*! Raw mu-law data (G.711) */ + case AST_FORMAT_TESTLAW: + return (1ULL << 47); +@@ -532,6 +535,9 @@ + /*! SpeeX Wideband (16kHz) Free Compression */ + case (1ULL << 33): + return ast_format_set(dst, AST_FORMAT_SPEEX16, 0); ++ /*! Codec 2 (8KHz) */ ++ case (1ULL << 35): ++ return ast_format_set(dst, AST_FORMAT_CODEC2, 0); + /*! Raw mu-law data (G.711) */ + case (1ULL << 47): + return ast_format_set(dst, AST_FORMAT_TESTLAW, 0); +@@ -1071,6 +1077,8 @@ + format_list_add_static(ast_format_set(&tmpfmt, AST_FORMAT_SLINEAR48, 0), "slin48", 48000, "16 bit Signed Linear PCM (48kHz)", 960, 10, 70, 10, 20, AST_SMOOTHER_FLAG_BE, 0);/*!< Signed linear (48kHz) */ + format_list_add_static(ast_format_set(&tmpfmt, AST_FORMAT_SLINEAR96, 0), "slin96", 96000, "16 bit Signed Linear PCM (96kHz)", 1920, 10, 70, 10, 20, AST_SMOOTHER_FLAG_BE, 0);/*!< Signed linear (96kHz) */ + format_list_add_static(ast_format_set(&tmpfmt, AST_FORMAT_SLINEAR192, 0), "slin192", 192000, "16 bit Signed Linear PCM (192kHz)", 3840, 10, 70, 10, 20, AST_SMOOTHER_FLAG_BE, 0);/*!< Signed linear (192kHz) */ ++ /* Codec 2 */ ++ format_list_add_static(ast_format_set(&tmpfmt, AST_FORMAT_CODEC2, 0), "codec2", 8000, "Codec 2", 6, 20, 20, 20, 20, 0, 0); /*!< codec_codec2.c */ + + return 0; + } +diff -urN asterisk-11.8.1-orig/main/frame.c asterisk-11.8.1-codec2/main/frame.c +--- asterisk-11.8.1-orig/main/frame.c 2012-07-24 18:54:26.000000000 +0200 ++++ asterisk-11.8.1-codec2/main/frame.c 2014-04-01 10:13:35.626395684 +0200 +@@ -1083,6 +1083,10 @@ + /* TODO The assumes 20ms delivery right now, which is incorrect */ + samples = ast_format_rate(&f->subclass.format) / 50; + break; ++ /* Codec 2 */ ++ case AST_FORMAT_CODEC2: ++ samples = 160 * (f->datalen / 6); ++ break; + default: + ast_log(LOG_WARNING, "Unable to calculate samples for format %s\n", ast_getformatname(&f->subclass.format)); + } +@@ -1134,6 +1138,10 @@ + /* 48,000 samples per second at 64kbps is 8,000 bytes per second */ + len = (int) samples / ((float) 48000 / 8000); + break; ++ /* Codec 2 */ ++ case AST_FORMAT_CODEC2: ++ len = (samples / 160) * 6; ++ break; + default: + ast_log(LOG_WARNING, "Unable to calculate sample length for format %s\n", ast_getformatname(format)); + } +diff -urN asterisk-11.8.1-orig/main/rtp_engine.c asterisk-11.8.1-codec2/main/rtp_engine.c +--- asterisk-11.8.1-orig/main/rtp_engine.c 2013-12-18 00:35:07.000000000 +0100 ++++ asterisk-11.8.1-codec2/main/rtp_engine.c 2014-04-01 10:17:00.121681465 +0200 +@@ -2289,6 +2289,8 @@ + set_next_mime_type(ast_format_set(&tmpfmt, AST_FORMAT_SIREN7, 0), 0, "audio", "G7221", 16000); + set_next_mime_type(ast_format_set(&tmpfmt, AST_FORMAT_SIREN14, 0), 0, "audio", "G7221", 32000); + set_next_mime_type(ast_format_set(&tmpfmt, AST_FORMAT_G719, 0), 0, "audio", "G719", 48000); ++ /* Codec 2 */ ++ set_next_mime_type(ast_format_set(&tmpfmt, AST_FORMAT_CODEC2, 0), 0, "audio", "CODEC2", 8000); + + /* Define the static rtp payload mappings */ + add_static_payload(0, ast_format_set(&tmpfmt, AST_FORMAT_ULAW, 0), 0); +@@ -2330,6 +2332,8 @@ + add_static_payload(118, ast_format_set(&tmpfmt, AST_FORMAT_SLINEAR16, 0), 0); /* 16 Khz signed linear */ + add_static_payload(119, ast_format_set(&tmpfmt, AST_FORMAT_SPEEX32, 0), 0); + add_static_payload(121, NULL, AST_RTP_CISCO_DTMF); /* Must be type 121 */ ++ /* Codec 2 */ ++ add_static_payload(121, ast_format_set(&tmpfmt, AST_FORMAT_CODEC2, 0), 0); + + return 0; + } +diff -urN asterisk-11.8.1-orig/makeopts.in asterisk-11.8.1-codec2/makeopts.in +--- asterisk-11.8.1-orig/makeopts.in 2013-04-11 21:59:35.000000000 +0200 ++++ asterisk-11.8.1-codec2/makeopts.in 2014-04-01 10:28:49.424993462 +0200 +@@ -120,6 +120,9 @@ + 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 -urN asterisk-11.8.1-orig/res/res_rtp_asterisk.c asterisk-11.8.1-codec2/res/res_rtp_asterisk.c +--- asterisk-11.8.1-orig/res/res_rtp_asterisk.c 2014-02-27 22:39:30.000000000 +0100 ++++ asterisk-11.8.1-codec2/res/res_rtp_asterisk.c 2014-04-01 10:19:18.727901747 +0200 +@@ -2738,6 +2738,8 @@ + case AST_FORMAT_SIREN7: + case AST_FORMAT_SIREN14: + case AST_FORMAT_G719: ++ /* Codec 2 */ ++ case AST_FORMAT_CODEC2: + /* these are all frame-based codecs and cannot be safely run through + a smoother */ + break; diff --git a/codec2-dev/asterisk-11/asterisk-11.8.1-opus-codec2.patch b/codec2-dev/asterisk-11/asterisk-11.8.1-opus-codec2.patch new file mode 100644 index 00000000..a90d3d60 --- /dev/null +++ b/codec2-dev/asterisk-11/asterisk-11.8.1-opus-codec2.patch @@ -0,0 +1,384 @@ +diff -urN asterisk-11.8.1-opus/build_tools/menuselect-deps.in asterisk-11.8.1-opus-codec2/build_tools/menuselect-deps.in +--- asterisk-11.8.1-opus/build_tools/menuselect-deps.in 2014-04-01 10:58:52.127106070 +0200 ++++ asterisk-11.8.1-opus-codec2/build_tools/menuselect-deps.in 2014-04-01 10:50:21.490079146 +0200 +@@ -4,6 +4,7 @@ + CRYPTO=@PBX_CRYPTO@ + BFD=@PBX_BFD@ + BISON=@PBX_BISON@ ++CODEC2=@PBX_CODEC2@ + CURL=@PBX_CURL@ + DAHDI=@PBX_DAHDI@ + DLADDR=@PBX_DLADDR@ +diff -urN asterisk-11.8.1-opus/codecs/codec_codec2.c asterisk-11.8.1-opus-codec2/codecs/codec_codec2.c +--- asterisk-11.8.1-opus/codecs/codec_codec2.c 1970-01-01 01:00:00.000000000 +0100 ++++ asterisk-11.8.1-opus-codec2/codecs/codec_codec2.c 2014-04-01 10:50:21.490079146 +0200 +@@ -0,0 +1,190 @@ ++/* ++ * Codec 2 module for Asterisk. ++ * ++ * Credit: codec_gsm.c used as a starting point. ++ * ++ * Copyright (C) 2012 Ed W and David Rowe ++ * ++ * 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 ++ * ++ * \ingroup codecs ++ */ ++ ++/*** MODULEINFO ++ codec2 ++ core ++ ***/ ++ ++#include "asterisk.h" ++ ++#include "asterisk/translate.h" ++#include "asterisk/config.h" ++#include "asterisk/module.h" ++#include "asterisk/utils.h" ++ ++#include ++ ++#define BUFFER_SAMPLES 8000 ++#define CODEC2_SAMPLES 160 ++#define CODEC2_FRAME_LEN 6 ++ ++/* Sample frame data */ ++ ++#include "asterisk/slin.h" ++#include "ex_codec2.h" ++ ++struct codec2_translator_pvt { /* both codec2tolin and codec2togsm */ ++ struct CODEC2 *codec2; ++ int16_t buf[BUFFER_SAMPLES]; /* lintocodec2, temporary storage */ ++}; ++ ++static int codec2_new(struct ast_trans_pvt *pvt) ++{ ++ struct codec2_translator_pvt *tmp = pvt->pvt; ++ ++ tmp->codec2 = codec2_create(CODEC2_MODE_2400); ++ if (!tmp) ++ 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; ++ int16_t *dst = pvt->outbuf.i16; ++ int flen = CODEC2_FRAME_LEN; ++ ++ for (x=0; x < f->datalen; x += flen) { ++ unsigned char *src; ++ int len; ++ len = CODEC2_SAMPLES; ++ src = f->data.ptr + x; ++ ++ codec2_decode(tmp->codec2, dst + pvt->samples, src); ++ ++ pvt->samples += CODEC2_SAMPLES; ++ pvt->datalen += 2 * CODEC2_SAMPLES; ++ } ++ 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; ++ ++ if (pvt->samples + f->samples > BUFFER_SAMPLES) { ++ ast_log(LOG_WARNING, "Out of buffer space\n"); ++ return -1; ++ } ++ 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; ++ int datalen = 0; ++ int samples = 0; ++ ++ /* We can't work on anything less than a frame in size */ ++ if (pvt->samples < CODEC2_SAMPLES) ++ return NULL; ++ while (pvt->samples >= CODEC2_SAMPLES) { ++ /* Encode a frame of data */ ++ codec2_encode(tmp->codec2, (unsigned char*)(pvt->outbuf.c + datalen), tmp->buf + samples); ++ datalen += CODEC2_FRAME_LEN; ++ samples += CODEC2_SAMPLES; ++ pvt->samples -= CODEC2_SAMPLES; ++ } ++ ++ /* Move the data at the end of the buffer to the front */ ++ if (pvt->samples) ++ memmove(tmp->buf, tmp->buf + samples, pvt->samples * 2); ++ ++ return ast_trans_frameout(pvt, datalen, samples); ++} ++ ++static void codec2_destroy_stuff(struct ast_trans_pvt *pvt) ++{ ++ struct codec2_translator_pvt *tmp = pvt->pvt; ++ if (tmp->codec2) ++ codec2_destroy(tmp->codec2); ++} ++ ++static struct ast_translator codec2tolin = { ++ .name = "codec2tolin", ++ .newpvt = codec2_new, ++ .framein = codec2tolin_framein, ++ .destroy = codec2_destroy_stuff, ++ .sample = codec2_sample, ++ .buffer_samples = BUFFER_SAMPLES, ++ .buf_size = BUFFER_SAMPLES * 2, ++ .desc_size = sizeof (struct codec2_translator_pvt ), ++}; ++ ++static struct ast_translator lintocodec2 = { ++ .name = "lintocodec2", ++ .newpvt = codec2_new, ++ .framein = lintocodec2_framein, ++ .frameout = lintocodec2_frameout, ++ .destroy = codec2_destroy_stuff, ++ .sample = slin8_sample, ++ .desc_size = sizeof (struct codec2_translator_pvt ), ++ .buf_size = (BUFFER_SAMPLES * CODEC2_FRAME_LEN + CODEC2_SAMPLES - 1)/CODEC2_SAMPLES, ++}; ++ ++/*! \brief standard module glue */ ++static int reload(void) ++{ ++ return AST_MODULE_LOAD_SUCCESS; ++} ++ ++static int unload_module(void) ++{ ++ int res; ++ ++ res = ast_unregister_translator(&lintocodec2); ++ if (!res) ++ res = ast_unregister_translator(&codec2tolin); ++ ++ return res; ++} ++ ++static int load_module(void) ++{ ++ int res; ++ ++ ast_format_set(&codec2tolin.src_format, AST_FORMAT_CODEC2, 0); ++ ast_format_set(&codec2tolin.dst_format, AST_FORMAT_SLINEAR, 0); ++ ++ ast_format_set(&lintocodec2.src_format, AST_FORMAT_SLINEAR, 0); ++ ast_format_set(&lintocodec2.dst_format, AST_FORMAT_CODEC2, 0); ++ ++ res = ast_register_translator(&codec2tolin); ++ if (!res) ++ res=ast_register_translator(&lintocodec2); ++ else ++ ast_unregister_translator(&codec2tolin); ++ if (res) ++ return AST_MODULE_LOAD_FAILURE; ++ return AST_MODULE_LOAD_SUCCESS; ++} ++ ++AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_DEFAULT, "Codec 2 Coder/Decoder", ++ .load = load_module, ++ .unload = unload_module, ++ .reload = reload, ++ ); +diff -urN asterisk-11.8.1-opus/codecs/ex_codec2.h asterisk-11.8.1-opus-codec2/codecs/ex_codec2.h +--- asterisk-11.8.1-opus/codecs/ex_codec2.h 1970-01-01 01:00:00.000000000 +0100 ++++ asterisk-11.8.1-opus-codec2/codecs/ex_codec2.h 2014-04-01 10:50:21.490079146 +0200 +@@ -0,0 +1,29 @@ ++/*! \file ++ * \brief 8-bit raw data ++ * ++ * Copyright (C) 2012, 2012 Ed W and David Rowe ++ * ++ * Distributed under the terms of the GNU General Public License ++ * ++ */ ++ ++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, ++ }; ++ ++ ast_format_set(&f.subclass.format, AST_FORMAT_CODEC2, 0); ++ ++ return &f; ++} +diff -urN asterisk-11.8.1-opus/configure.ac asterisk-11.8.1-opus-codec2/configure.ac +--- asterisk-11.8.1-opus/configure.ac 2014-04-01 10:58:52.143106352 +0200 ++++ asterisk-11.8.1-opus-codec2/configure.ac 2014-04-01 10:50:21.494079217 +0200 +@@ -384,6 +384,7 @@ + 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], [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]) +@@ -2117,6 +2118,8 @@ + + AST_EXT_LIB_CHECK([RADIUS], [radiusclient-ng], [rc_read_config], [radiusclient-ng.h]) + ++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 -urN asterisk-11.8.1-opus/include/asterisk/format.h asterisk-11.8.1-opus-codec2/include/asterisk/format.h +--- asterisk-11.8.1-opus/include/asterisk/format.h 2014-04-01 10:58:52.143106352 +0200 ++++ asterisk-11.8.1-opus-codec2/include/asterisk/format.h 2014-04-01 10:53:25.961351185 +0200 +@@ -103,6 +103,7 @@ + AST_FORMAT_CELT = 29 + AST_FORMAT_TYPE_AUDIO, + /*! Opus */ + AST_FORMAT_OPUS = 30 + AST_FORMAT_TYPE_AUDIO, ++ AST_FORMAT_CODEC2 = 31 + AST_FORMAT_TYPE_AUDIO, + + /*! H.261 Video */ + AST_FORMAT_H261 = 1 + AST_FORMAT_TYPE_VIDEO, +diff -urN asterisk-11.8.1-opus/main/channel.c asterisk-11.8.1-opus-codec2/main/channel.c +--- asterisk-11.8.1-opus/main/channel.c 2014-04-01 10:58:52.147106422 +0200 ++++ asterisk-11.8.1-opus-codec2/main/channel.c 2014-04-01 10:50:21.498079289 +0200 +@@ -920,6 +920,8 @@ + AST_FORMAT_SILK, + /*! CELT supports crazy high sample rates */ + AST_FORMAT_CELT, ++ /* Codec 2 */ ++ AST_FORMAT_CODEC2, + /*! Ick, LPC10 sounds terrible, but at least we have code for it, if you're tacky enough + to use it */ + AST_FORMAT_LPC10, +diff -urN asterisk-11.8.1-opus/main/format.c asterisk-11.8.1-opus-codec2/main/format.c +--- asterisk-11.8.1-opus/main/format.c 2014-04-01 10:58:52.147106422 +0200 ++++ asterisk-11.8.1-opus-codec2/main/format.c 2014-04-01 10:52:23.820250398 +0200 +@@ -433,6 +433,9 @@ + /*! Opus audio (8kHz, 16kHz, 24kHz, 48Khz) */ + case AST_FORMAT_OPUS: + return (1ULL << 34); ++ /*! Codec 2 (8KHz) */ ++ case AST_FORMAT_CODEC2: ++ return (1ULL << 35); + /*! Raw mu-law data (G.711) */ + case AST_FORMAT_TESTLAW: + return (1ULL << 47); +@@ -541,6 +544,9 @@ + /*! Opus audio (8kHz, 16kHz, 24kHz, 48Khz) */ + case (1ULL << 34): + return ast_format_set(dst, AST_FORMAT_OPUS, 0); ++ /*! Codec 2 (8KHz) */ ++ case (1ULL << 35): ++ return ast_format_set(dst, AST_FORMAT_CODEC2, 0); + /*! Raw mu-law data (G.711) */ + case (1ULL << 47): + return ast_format_set(dst, AST_FORMAT_TESTLAW, 0); +@@ -1090,6 +1096,8 @@ + format_list_add_static(ast_format_set(&tmpfmt, AST_FORMAT_OPUS, 0), "opus", 48000, "Opus Codec", 10, 20, 60, 20, 20, 0, 0); /*!< codec_opus.c */ + /* VP8 (passthrough) */ + format_list_add_static(ast_format_set(&tmpfmt, AST_FORMAT_VP8, 0), "vp8", 0, "VP8 Video", 0, 0, 0, 0 ,0 ,0, 0); /*!< Passthrough support, see format_h263.c */ ++ /* Codec 2 */ ++ format_list_add_static(ast_format_set(&tmpfmt, AST_FORMAT_CODEC2, 0), "codec2", 8000, "Codec 2", 6, 20, 20, 20, 20, 0, 0); /*!< codec_codec2.c */ + + return 0; + } +diff -urN asterisk-11.8.1-opus/main/frame.c asterisk-11.8.1-opus-codec2/main/frame.c +--- asterisk-11.8.1-opus/main/frame.c 2014-04-01 10:58:52.151106493 +0200 ++++ asterisk-11.8.1-opus-codec2/main/frame.c 2014-04-01 10:50:21.502079360 +0200 +@@ -1121,6 +1121,10 @@ + case AST_FORMAT_OPUS: + samples = opus_samples(f->data.ptr, f->datalen); + break; ++ /* Codec 2 */ ++ case AST_FORMAT_CODEC2: ++ samples = 160 * (f->datalen / 6); ++ break; + default: + ast_log(LOG_WARNING, "Unable to calculate samples for format %s\n", ast_getformatname(&f->subclass.format)); + } +@@ -1172,6 +1176,10 @@ + /* 48,000 samples per second at 64kbps is 8,000 bytes per second */ + len = (int) samples / ((float) 48000 / 8000); + break; ++ /* Codec 2 */ ++ case AST_FORMAT_CODEC2: ++ len = (samples / 160) * 6; ++ break; + default: + ast_log(LOG_WARNING, "Unable to calculate sample length for format %s\n", ast_getformatname(format)); + } +diff -urN asterisk-11.8.1-opus/main/rtp_engine.c asterisk-11.8.1-opus-codec2/main/rtp_engine.c +--- asterisk-11.8.1-opus/main/rtp_engine.c 2014-04-01 10:58:52.151106493 +0200 ++++ asterisk-11.8.1-opus-codec2/main/rtp_engine.c 2014-04-01 10:51:17.367071621 +0200 +@@ -2292,6 +2292,8 @@ + /* Opus and VP8 */ + set_next_mime_type(ast_format_set(&tmpfmt, AST_FORMAT_OPUS, 0), 0, "audio", "opus", 48000); + set_next_mime_type(ast_format_set(&tmpfmt, AST_FORMAT_VP8, 0), 0, "video", "VP8", 90000); ++ /* Codec 2 */ ++ set_next_mime_type(ast_format_set(&tmpfmt, AST_FORMAT_CODEC2, 0), 0, "audio", "CODEC2", 8000); + + /* Define the static rtp payload mappings */ + add_static_payload(0, ast_format_set(&tmpfmt, AST_FORMAT_ULAW, 0), 0); +@@ -2336,6 +2338,8 @@ + /* Opus and VP8 */ + add_static_payload(100, ast_format_set(&tmpfmt, AST_FORMAT_VP8, 0), 0); + add_static_payload(107, ast_format_set(&tmpfmt, AST_FORMAT_OPUS, 0), 0); ++ /* Codec 2 */ ++ add_static_payload(121, ast_format_set(&tmpfmt, AST_FORMAT_CODEC2, 0), 0); + + return 0; + } +diff -urN asterisk-11.8.1-opus/makeopts.in asterisk-11.8.1-opus-codec2/makeopts.in +--- asterisk-11.8.1-opus/makeopts.in 2014-04-01 10:58:52.151106493 +0200 ++++ asterisk-11.8.1-opus-codec2/makeopts.in 2014-04-01 10:50:21.538079999 +0200 +@@ -120,6 +120,9 @@ + 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 -urN asterisk-11.8.1-opus/res/res_rtp_asterisk.c asterisk-11.8.1-opus-codec2/res/res_rtp_asterisk.c +--- asterisk-11.8.1-opus/res/res_rtp_asterisk.c 2014-04-01 10:58:52.151106493 +0200 ++++ asterisk-11.8.1-opus-codec2/res/res_rtp_asterisk.c 2014-04-01 10:53:02.292932085 +0200 +@@ -2780,6 +2780,8 @@ + case AST_FORMAT_G719: + /* Opus */ + case AST_FORMAT_OPUS: ++ /* Codec 2 */ ++ case AST_FORMAT_CODEC2: + /* these are all frame-based codecs and cannot be safely run through + a smoother */ + break; -- 2.25.1