From 1944260c7be8732f0e6146fc4629e2a84114b5cf Mon Sep 17 00:00:00 2001 From: Andrey Volk Date: Tue, 27 Aug 2024 16:45:57 +0000 Subject: [PATCH] [mod_sangoma_codec] Remove from tree --- LICENSE | 3 +- build/modules.conf.in | 1 - build/modules.conf.most | 1 - ci.sh | 1 - .../autoload_configs/sangoma_codec.conf.xml | 37 - configure.ac | 3 +- debian/bootstrap.sh | 1 - debian/control-modules | 5 - debian/copyright | 6 - freeswitch.spec | 39 - src/mod/codecs/mod_sangoma_codec/Makefile.am | 8 - .../mod_sangoma_codec/mod_sangoma_codec.c | 1536 ----------------- 12 files changed, 2 insertions(+), 1639 deletions(-) mode change 100644 => 100755 build/modules.conf.in mode change 100644 => 100755 build/modules.conf.most delete mode 100644 conf/vanilla/autoload_configs/sangoma_codec.conf.xml mode change 100644 => 100755 configure.ac mode change 100644 => 100755 debian/control-modules mode change 100644 => 100755 debian/copyright mode change 100644 => 100755 freeswitch.spec delete mode 100644 src/mod/codecs/mod_sangoma_codec/Makefile.am delete mode 100644 src/mod/codecs/mod_sangoma_codec/mod_sangoma_codec.c diff --git a/LICENSE b/LICENSE index 7d64386fb2..d106a66b4f 100644 --- a/LICENSE +++ b/LICENSE @@ -1582,8 +1582,7 @@ Files: libs/libcodec2/src/pack.c Copyright: 2010 Perens LLC License: GPL-3+ -Files: src/mod/codecs/mod_sangoma_codec/mod_sangoma_codec.c - src/include/switch_profile.h +Files: src/include/switch_profile.h src/switch_profile.c Copyright: 2009,2010, Sangoma Technologies License: BSD-3-clause diff --git a/build/modules.conf.in b/build/modules.conf.in old mode 100644 new mode 100755 index d114df88f5..62156fa785 --- a/build/modules.conf.in +++ b/build/modules.conf.in @@ -75,7 +75,6 @@ codecs/mod_h26x #codecs/mod_isac #codecs/mod_mp4v codecs/mod_opus -#codecs/mod_sangoma_codec #codecs/mod_silk #codecs/mod_siren #codecs/mod_theora diff --git a/build/modules.conf.most b/build/modules.conf.most old mode 100644 new mode 100755 index 43a5290057..77cdfc346b --- a/build/modules.conf.most +++ b/build/modules.conf.most @@ -72,7 +72,6 @@ codecs/mod_ilbc codecs/mod_isac codecs/mod_mp4v codecs/mod_opus -codecs/mod_sangoma_codec codecs/mod_silk codecs/mod_siren codecs/mod_theora diff --git a/ci.sh b/ci.sh index e2ebe67ea1..d7322c4432 100755 --- a/ci.sh +++ b/ci.sh @@ -96,7 +96,6 @@ configure_freeswitch() -e '/mod_mp4/s/^/#/g' \ -e '/mod_mongo/s/^/#/g' \ -e '/mod_pocketsphinx/s/^/#/g' \ - -e '/mod_sangoma_codec/s/^/#/g' \ -e '/mod_siren/s/^/#/g' \ -e '/mod_avmd/s/^/#/g' \ -e '/mod_basic/s/^/#/g' \ diff --git a/conf/vanilla/autoload_configs/sangoma_codec.conf.xml b/conf/vanilla/autoload_configs/sangoma_codec.conf.xml deleted file mode 100644 index eed9d673e1..0000000000 --- a/conf/vanilla/autoload_configs/sangoma_codec.conf.xml +++ /dev/null @@ -1,37 +0,0 @@ - - - - - - - - - - - - - - diff --git a/configure.ac b/configure.ac old mode 100644 new mode 100755 index ed3eb4f32b..8de0226b7d --- a/configure.ac +++ b/configure.ac @@ -1079,7 +1079,7 @@ if test "x${ax_cv_c_compiler_vendor}" = "xclang" ; then fi # Tested and fixed lot of modules, but some are untested. Will be added back when the core team decide it ready -# Untested modules : mod_osp mod_soundtouch mod_sangoma_codec mod_opal mod_h323 mod_khomp +# Untested modules : mod_osp mod_soundtouch mod_opal mod_h323 mod_khomp # mod_cepstral mod_erlang_event mod_snmp mod_perl mod_java mod_managed # #saved_CFLAGS="$CFLAGS" @@ -2171,7 +2171,6 @@ AC_CONFIG_FILES([Makefile src/mod/codecs/mod_mp4v/Makefile src/mod/codecs/mod_opus/Makefile src/mod/codecs/mod_openh264/Makefile - src/mod/codecs/mod_sangoma_codec/Makefile src/mod/codecs/mod_silk/Makefile src/mod/codecs/mod_siren/Makefile src/mod/codecs/mod_skel_codec/Makefile diff --git a/debian/bootstrap.sh b/debian/bootstrap.sh index 484ba54555..05ee167c51 100755 --- a/debian/bootstrap.sh +++ b/debian/bootstrap.sh @@ -46,7 +46,6 @@ avoid_mods=( codecs/mod_com_g729 codecs/mod_openh264 codecs/mod_siren - codecs/mod_sangoma_codec codecs/mod_skel_codec endpoints/mod_h323 endpoints/mod_khomp diff --git a/debian/control-modules b/debian/control-modules old mode 100644 new mode 100755 index 291ffc1940..50880ae56c --- a/debian/control-modules +++ b/debian/control-modules @@ -360,11 +360,6 @@ Description: mod_opus Adds mod_opus. Build-Depends: libopus-dev -Module: codecs/mod_sangoma_codec -Description: mod_sangoma_codec - Adds mod_sangoma_codec. -Build-Depends: libsngtc-dev - Module: codecs/mod_silk Description: mod_silk Adds mod_silk. diff --git a/debian/copyright b/debian/copyright old mode 100644 new mode 100755 index a2860ea7b9..18b2f92ddc --- a/debian/copyright +++ b/debian/copyright @@ -1582,12 +1582,6 @@ Files: libs/libcodec2/src/pack.c Copyright: 2010 Perens LLC License: GPL-3+ -Files: src/mod/codecs/mod_sangoma_codec/mod_sangoma_codec.c - src/include/switch_profile.h - src/switch_profile.c -Copyright: 2009,2010, Sangoma Technologies -License: BSD-3-clause - Files: src/mod/codecs/mod_isac/* Copyright: 2011-2012 The WebRTC project authors License: BSD-3-clause diff --git a/freeswitch.spec b/freeswitch.spec old mode 100644 new mode 100755 index 9a28d21324..a3ddd6efc2 --- a/freeswitch.spec +++ b/freeswitch.spec @@ -29,17 +29,11 @@ # ###################################################################################################################### # Module build settings -%define build_sng_isdn 0 -%define build_sng_ss7 0 -%define build_sng_tc 0 %define build_py26_esl 0 %define build_timerfd 0 %define build_mod_esl 0 %define build_mod_v8 0 -%{?with_sang_tc:%define build_sng_tc 1 } -%{?with_sang_isdn:%define build_sng_isdn 1 } -%{?with_sang_ss7:%define build_sng_ss7 1 } %{?with_py26_esl:%define build_py26_esl 1 } %{?with_timerfd:%define build_timerfd 1 } %{?with_mod_esl:%define build_mod_esl 1 } @@ -746,19 +740,6 @@ BuildRequires: opus-devel >= 1.1 %description codec-opus OPUS Codec support for FreeSWITCH open source telephony platform -%if %{build_sng_tc} -%package sangoma-codec -Summary: Sangoma D100 and D500 Codec Card Support -Group: System/Libraries -Requires: %{name} = %{version}-%{release} -Requires: sng-tc-linux -BuildRequires: sng-tc-linux - -%description sangoma-codec -Sangoma D100 and D500 Codec Card Support - -%endif - %package codec-silk Summary: Silk Codec support for FreeSWITCH open source telephony platform Group: System/Libraries @@ -1394,9 +1375,6 @@ CODECS_MODULES="codecs/mod_amr codecs/mod_amrwb codecs/mod_bv codecs/mod_codec2 codecs/mod_g729 codecs/mod_h26x codecs/mod_ilbc codecs/mod_isac codecs/mod_mp4v codecs/mod_opus codecs/mod_silk \ codecs/mod_siren codecs/mod_theora" # -%if %{build_sng_tc} -CODECS_MODULES+="codecs/mod_sangoma_codec" -%endif ###################################################################################################################### # @@ -1648,17 +1626,6 @@ cd ../.. # ###################################################################################################################### -%if %{build_sng_ss7} -#do not delete a thing -%else -%{__rm} -f %{buildroot}/%{MODINSTDIR}/ftmod_sangoma_ss7* -%endif -%if %{build_sng_isdn} -#do not delete a thing -%else -%{__rm} -f %{buildroot}/%{MODINSTDIR}/ftmod_sangoma_isdn* -%endif - %{__rm} -f %{buildroot}/%{LIBDIR}/*.la %{__rm} -f %{buildroot}/%{MODINSTDIR}/*.la @@ -1886,7 +1853,6 @@ fi %config(noreplace) %attr(0640, freeswitch, daemon) %{sysconfdir}/autoload_configs/redis.conf.xml %config(noreplace) %attr(0640, freeswitch, daemon) %{sysconfdir}/autoload_configs/rss.conf.xml %config(noreplace) %attr(0640, freeswitch, daemon) %{sysconfdir}/autoload_configs/rtmp.conf.xml -%config(noreplace) %attr(0640, freeswitch, daemon) %{sysconfdir}/autoload_configs/sangoma_codec.conf.xml %config(noreplace) %attr(0640, freeswitch, daemon) %{sysconfdir}/autoload_configs/shout.conf.xml %config(noreplace) %attr(0640, freeswitch, daemon) %{sysconfdir}/autoload_configs/signalwire.conf.xml %config(noreplace) %attr(0640, freeswitch, daemon) %{sysconfdir}/autoload_configs/skinny.conf.xml @@ -2140,11 +2106,6 @@ fi %{MODINSTDIR}/mod_opus.so* %config(noreplace) %attr(0640, freeswitch, daemon) %{sysconfdir}/autoload_configs/opus.conf.xml -%if %{build_sng_tc} -%files sangoma-codec -%{MODINSTDIR}/mod_sangoma_codec.so* -%endif - %files codec-silk %{MODINSTDIR}/mod_silk.so* diff --git a/src/mod/codecs/mod_sangoma_codec/Makefile.am b/src/mod/codecs/mod_sangoma_codec/Makefile.am deleted file mode 100644 index eff90fe297..0000000000 --- a/src/mod/codecs/mod_sangoma_codec/Makefile.am +++ /dev/null @@ -1,8 +0,0 @@ -include $(top_srcdir)/build/modmake.rulesam -MODNAME=mod_sangoma_codec - -mod_LTLIBRARIES = mod_sangoma_codec.la -mod_sangoma_codec_la_SOURCES = mod_sangoma_codec.c -mod_sangoma_codec_la_CFLAGS = $(AM_CFLAGS) -mod_sangoma_codec_la_LIBADD = $(switch_builddir)/libfreeswitch.la -mod_sangoma_codec_la_LDFLAGS = -avoid-version -module -no-undefined -shared -lsngtc_node diff --git a/src/mod/codecs/mod_sangoma_codec/mod_sangoma_codec.c b/src/mod/codecs/mod_sangoma_codec/mod_sangoma_codec.c deleted file mode 100644 index 0eb9eac2fe..0000000000 --- a/src/mod/codecs/mod_sangoma_codec/mod_sangoma_codec.c +++ /dev/null @@ -1,1536 +0,0 @@ -/* - * Copyright (c) 2010, Sangoma Technologies - * Moises Silva - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * * Neither the name of the original author; nor the names of any contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER - * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include "switch.h" - -#include - -SWITCH_MODULE_LOAD_FUNCTION(mod_sangoma_codec_load); -SWITCH_MODULE_SHUTDOWN_FUNCTION(mod_sangoma_codec_shutdown); -SWITCH_MODULE_DEFINITION(mod_sangoma_codec, mod_sangoma_codec_load, mod_sangoma_codec_shutdown, NULL); - -#define SANGOMA_SESS_HASH_KEY_FORMAT "sngtc%lu" - -/* it seemed we need higher PTIME than the calling parties, so we assume nobody will use higher ptime than 40 */ -#define SANGOMA_DEFAULT_SAMPLING_RATE 80 -#define SANGOMA_TRANSCODE_CONFIG "sangoma_codec.conf" - -/* \brief vocallos configuration */ -static sngtc_init_cfg_t g_init_cfg; - -/* configured RTP IP */ -static int g_rtpip = 0; - -static char g_soap_url[255] = ""; - -/* \brief protect vocallo session creation and destroy */ -static switch_mutex_t *g_sessions_lock = NULL; - -/* \brief next unique session id (protected by g_sessions_lock) */ -unsigned long long g_next_session_id = 0; - -/* hash of sessions (I think a linked list suits better here, but FS does not have the data type) */ -static switch_hash_t *g_sessions_hash = NULL; - -typedef struct vocallo_codec_s { - int codec_id; /* vocallo codec ID */ - int iana; /* IANA code to register in FS */ - const char *iana_name; /* IANA name to register in FS */ - const char *fs_name; - int maxms; /* max supported ms (WARNING: codec impl from 10ms up to this value will be registered if autoinit=1) */ - int bps; /* bits per second */ - - /* following values must be set assuming frames of 10ms */ - int mpf; /* microseconds per frame */ - int spf; /* samples per frame */ - int bpfd; /* bytes per frame decompressed */ - int bpfc; /* bytes per frame compressed */ - - int sampling_rate; /* declared sampling rate */ - int actual_sampling_rate; /* true sampling rate */ - int autoinit; /* initialize on start loop or manually */ -} vocallo_codec_t; - -vocallo_codec_t g_codec_map[] = -{ - /* auto-init codecs */ - { SNGTC_CODEC_PCMU, IANA_PCMU_A_8000_1, "PCMU", "Sangoma PCMU", 40, 64000, 10000, 80, 160, 80, 8000, 8000, 1 }, - { SNGTC_CODEC_PCMA, IANA_PCMA_A_8000_1, "PCMA", "Sangoma PCMA", 40, 64000, 10000, 80, 160, 80, 8000, 8000, 1 }, - { SNGTC_CODEC_L16_1, IANA_L16_A_8000_1, "L16", "Sangoma L16", 40, 120000, 10000, 80, 160, 160, 8000, 8000, 0 }, - { SNGTC_CODEC_L16_2, IANA_L16_A_16000_1, "L16", "Sangoma L16 2", 40, 320000, 10000, 160, 320, 320, 16000, 16000, 0 }, - { SNGTC_CODEC_G726_32, IANA_G726_32_8000_1, "G726-32", "Sangoma G.726 32k", 40, 32000, 10000, 80, 160, 40, 8000, 8000, 1 }, - { SNGTC_CODEC_G722, IANA_G722_A_8000_1, "G722", "Sangoma G722", 20, 64000, 10000, 80, 160, 80, 8000, 8000, 1 }, - - /* manually initialized */ - { SNGTC_CODEC_GSM_FR, IANA_GSM_A_8000_1, "GSM", "Sangoma GSM", 20, 13200, 20000, 160, 320, 33, 8000, 8000, 0 }, - { SNGTC_CODEC_G723_1_63, IANA_G723_A_8000_1, "G723", "Sangoma G723", 90, 6300, 30000, 240, 480, 24, 8000, 8000, 0 }, - { SNGTC_CODEC_G729AB, IANA_G729_AB_8000_1, "G729", "Sangoma G729", 50, 8000, 10000, 80, 160, 10, 8000, 8000, 0 }, - { SNGTC_CODEC_AMR_1220, IANA_AMR_A_8000_1, "AMR", "Sangoma AMR", 20, 12200, 20000, 160, 320, 0, 8000, 8000, 0 }, - { SNGTC_CODEC_SIREN7_24, IANA_SIREN7, "G7221", "Sangoma G722.1", 20, 24000, 20000, 320, 640, 60, 16000, 16000, 0 }, - { SNGTC_CODEC_SIREN7_32, IANA_SIREN7, "G7221", "Sangoma G722.1", 20, 32000, 20000, 320, 640, 80, 16000, 16000, 0 }, - { SNGTC_CODEC_ILBC_133, IANA_ILBC_133_8000_1, "iLBC", "Sangoma iLBC", 30, 13330, 30000, 240, 480, 50, 8000, 8000, 0 }, - { SNGTC_CODEC_ILBC_152, IANA_ILBC_152_8000_1, "iLBC", "Sangoma iLBC", 20, 15200, 20000, 160, 320, 38, 8000, 8000, 0 }, - { -1, -1, NULL, NULL, -1, -1, -1, -1, -1, -1, -1, -1, 0 }, -}; - -/* RFC3389 RTP Payload for Comfort Noise */ -#define IANACODE_CN 13 - -/* default codec list to load, users may override, special codec 'all' registers everything available unless listed in noregister */ -static char g_codec_register_list[1024] = "G729"; - -/* default codec list to NOT load, users may override */ -static char g_codec_noregister_list[1024] = ""; - -#define SANGOMA_RTP_QUEUE_SIZE 4 -struct sangoma_rtp_payload { - uint8_t data[SWITCH_RECOMMENDED_BUFFER_SIZE]; - int32_t datalen; -}; - -struct codec_data { - /* sngtc request and reply */ - sngtc_codec_request_t request; - sngtc_codec_reply_t reply; - - /* rtp streams */ - void *txrtp; - void *rxrtp; - - /* packet counters */ - unsigned long tx; - unsigned long rx; - unsigned long ticks; - - /* Lost packets */ - long lastrxseqno; - unsigned long rxlost; - - /* discarded silence packets */ - unsigned long rxdiscarded; - - /* avg Rx time */ - switch_time_t avgrxus; - switch_time_t last_rx_time; - switch_time_t last_func_call_time; - - /* RTP queue. The bigger the queue, the bigger the possible delay */ - struct sangoma_rtp_payload rtp_queue[SANGOMA_RTP_QUEUE_SIZE]; - uint8_t queue_windex; - uint8_t queue_rindex; - uint8_t queue_size; - uint8_t queue_max_ever; - unsigned debug_timing:1; -}; - -struct sangoma_transcoding_session { - /* unique session id */ - unsigned long sessid; - char hashkey[25]; - - /* encoder and decoder */ - struct codec_data encoder; - struct codec_data decoder; - - /* codec implementation */ - const switch_codec_implementation_t *impl; - - /* memory pool */ - switch_memory_pool_t *pool; -}; - -static int codec_id_to_iana(int codec_id) -{ - int i; - for (i = 0; g_codec_map[i].codec_id != -1; i++) { - if (codec_id == g_codec_map[i].codec_id) { - return g_codec_map[i].iana; - } - } - return -1; -} - -static vocallo_codec_t *get_codec_from_iana(int iana, int bitrate) -{ - int i; - for (i = 0; g_codec_map[i].codec_id != -1; i++) { - if (iana == g_codec_map[i].iana && !bitrate) { - return &g_codec_map[i]; - } - if (iana == g_codec_map[i].iana && bitrate == g_codec_map[i].bps) { - return &g_codec_map[i]; - } - } - return NULL; -} - -static vocallo_codec_t *get_codec_from_id(int id) -{ - int i; - for (i = 0; g_codec_map[i].codec_id != -1; i++) { - if (id == g_codec_map[i].codec_id) { - return &g_codec_map[i]; - } - } - return NULL; -} - -static int sangoma_create_rtp_port(void *usr_priv, uint32_t host_ip, uint32_t *p_rtp_port, void **rtp_fd) -{ - struct in_addr local_ip_addr = { 0 }; - char local_ip[255]; - switch_port_t rtp_port; - - local_ip_addr.s_addr = htonl(host_ip); - - switch_inet_ntop(AF_INET, &local_ip_addr, local_ip, sizeof(local_ip)); - - /* request a port */ - if (!(rtp_port = switch_rtp_request_port(local_ip))) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Failed to allocate RTP port for IP %s\n", local_ip); - return -1; - } - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "New allocated port %d for IP %s/%d.%d.%d.%d\n", rtp_port, local_ip, - SNGTC_NIPV4(host_ip)); - *p_rtp_port = rtp_port; - *rtp_fd = NULL; - return 0; -} - -static int sangoma_release_rtp_port(void *usr_priv, uint32_t host_ip, uint32_t p_rtp_port, void *rtp_fd) -{ - struct in_addr local_ip_addr = { 0 }; - char local_ip[255]; - switch_port_t rtp_port = p_rtp_port; - - local_ip_addr.s_addr = htonl(host_ip); - - switch_inet_ntop(AF_INET, &local_ip_addr, local_ip, sizeof(local_ip)); - - /* release the port */ - switch_rtp_release_port(local_ip, rtp_port); - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Released port %d for IP %s/%d.%d.%d.%d\n", rtp_port, local_ip, - SNGTC_NIPV4(host_ip)); - return 0; -} - -static int sangoma_create_rtp(void *usr_priv, sngtc_codec_request_leg_t *codec_req_leg, sngtc_codec_reply_leg_t* codec_reply_leg, void **rtp_fd) -{ - switch_status_t status; - switch_memory_pool_t *sesspool = NULL; - switch_rtp_t *rtp_session = NULL; - char codec_ip[255]; - switch_rtp_flag_t flags[SWITCH_RTP_FLAG_INVALID] = {0}; - int iana = 0; - const char *err = NULL; - struct in_addr local_ip_addr = { 0 }; - char local_ip[255]; - switch_port_t rtp_port; - struct sangoma_transcoding_session *sess = usr_priv; - - rtp_port = codec_req_leg->host_udp_port; - *rtp_fd = NULL; - - /* - * We *MUST* use a new pool - * Do not use the session pool since the session may go away while the RTP socket should linger around - * until sangoma_transcode decides to kill it (possibly because the same RTP session is used for a different call) - * also do not use the module pool otherwise memory would keep growing because switch_rtp_destroy does not - * free the memory used (is assumed it'll be freed when the pool is destroyed) - */ - status = switch_core_new_memory_pool(&sesspool); - if (status != SWITCH_STATUS_SUCCESS) { - return -1; - } - - local_ip_addr.s_addr = htonl(codec_req_leg->host_ip); - switch_inet_ntop(AF_INET, &local_ip_addr, local_ip, sizeof(local_ip)); - sngtc_codec_ipv4_hex_to_str(codec_reply_leg->codec_ip, codec_ip); - - iana = codec_id_to_iana(codec_req_leg->codec_id); - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "Creating RTP session for host (%s/%d) vocallo(%s/%d) Iana=%d CodecId=%d ms=%d idx=%lu\n", - local_ip, rtp_port, codec_ip, codec_reply_leg->codec_udp_port, iana, codec_req_leg->codec_id, - codec_req_leg->ms*1000, sess->sessid); - - /* create the RTP socket */ - rtp_session = switch_rtp_new(local_ip, rtp_port, - codec_ip, codec_reply_leg->codec_udp_port, - iana, - sess->impl->samples_per_packet, - codec_req_leg->ms * 1000, /* microseconds per packet */ - flags, NULL, &err, sesspool, 0, 0); - - if (!rtp_session) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "failed to create switch rtp session: %s\n", err); - switch_core_destroy_memory_pool(&sesspool); - return -1; - } - switch_rtp_set_private(rtp_session, sesspool); - *rtp_fd = rtp_session; - - return 0; -} - -static int sangoma_destroy_rtp(void *usr_priv, void *fd) -{ - switch_memory_pool_t *sesspool; - switch_rtp_t *rtp = fd; - if (!rtp) { - return 0; - } - sesspool = switch_rtp_get_private(rtp); - switch_rtp_destroy(&rtp); - switch_core_destroy_memory_pool(&sesspool); - return 0; -} - -static switch_status_t switch_sangoma_init(switch_codec_t *codec, switch_codec_flag_t flags, const switch_codec_settings_t *codec_settings) -{ - uint32_t encoding, decoding; - struct sangoma_transcoding_session *sess = NULL; - vocallo_codec_t *vcodec; - - encoding = (flags & SWITCH_CODEC_FLAG_ENCODE); - decoding = (flags & SWITCH_CODEC_FLAG_DECODE); - - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Sangoma init called (encoding = %d, decoding = %d, iana = %d)\n", encoding ? 1 : 0, decoding ? 1 : 0, codec->implementation->ianacode); - - if (!(encoding || decoding)) { - return SWITCH_STATUS_FALSE; - } - - if (!(sess = switch_core_alloc(codec->memory_pool, sizeof(*sess)))) { - return SWITCH_STATUS_FALSE; - } - sess->encoder.lastrxseqno = -1; - sess->decoder.lastrxseqno = -1; - - sess->pool = codec->memory_pool; - sess->impl = codec->implementation; - switch_assert(sess->pool); - switch_assert(sess->impl); - - vcodec = get_codec_from_iana(codec->implementation->ianacode, codec->implementation->bits_per_second); - - if (encoding) { - sess->encoder.request.usr_priv = sess; - sess->encoder.request.a.host_ip = g_rtpip; - sess->encoder.request.a.codec_id = vcodec->actual_sampling_rate == 16000 - ? SNGTC_CODEC_L16_2 : SNGTC_CODEC_L16_1; - sess->encoder.request.a.ms = codec->implementation->microseconds_per_packet/1000; - - sess->encoder.request.b.host_ip = g_rtpip; - sess->encoder.request.b.codec_id = vcodec->codec_id; - sess->encoder.request.b.ms = codec->implementation->microseconds_per_packet/1000; - } - - if (decoding) { - sess->decoder.request.usr_priv = sess; - sess->decoder.request.a.host_ip = g_rtpip; - sess->decoder.request.a.codec_id = vcodec->codec_id; - sess->decoder.request.a.ms = codec->implementation->microseconds_per_packet/1000; - - sess->decoder.request.b.host_ip = g_rtpip; - sess->decoder.request.b.codec_id = vcodec->actual_sampling_rate == 16000 - ? SNGTC_CODEC_L16_2 : SNGTC_CODEC_L16_1; - sess->decoder.request.b.ms = codec->implementation->microseconds_per_packet/1000; - - } - - switch_mutex_lock(g_sessions_lock); - - sess->sessid = g_next_session_id++; - switch_snprintf(sess->hashkey, sizeof(sess->hashkey), SANGOMA_SESS_HASH_KEY_FORMAT, sess->sessid); - switch_core_hash_insert(g_sessions_hash, sess->hashkey, sess); - - switch_mutex_unlock(g_sessions_lock); - - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Sangoma init done for codec %s/%s, iana = %d\n", codec->implementation->iananame, vcodec->fs_name, codec->implementation->ianacode); - codec->private_info = sess; - - return SWITCH_STATUS_SUCCESS; -} - -static switch_status_t switch_sangoma_init_ilbc(switch_codec_t *codec, switch_codec_flag_t flags, const switch_codec_settings_t *codec_settings) -{ - int mode = codec->implementation->microseconds_per_packet / 1000; - if (codec->fmtp_in) { - int x, argc; - char *argv[10]; - argc = switch_separate_string(codec->fmtp_in, ';', argv, (sizeof(argv) / sizeof(argv[0]))); - for (x = 0; x < argc; x++) { - char *data = argv[x]; - char *arg; - switch_assert(data); - while (*data == ' ') { - data++; - } - if ((arg = strchr(data, '='))) { - *arg++ = '\0'; - if (!strcasecmp(data, "mode")) { - mode = atoi(arg); - } - } - } - } - codec->fmtp_out = switch_core_sprintf(codec->memory_pool, "mode=%d", mode); - return switch_sangoma_init(codec, flags, codec_settings); -} - -static switch_status_t switch_sangoma_init_siren7(switch_codec_t *codec, switch_codec_flag_t flags, const switch_codec_settings_t *codec_settings) -{ - int bit_rate = codec->implementation->bits_per_second; - codec->fmtp_out = switch_core_sprintf(codec->memory_pool, "bitrate=%d", bit_rate); - return switch_sangoma_init(codec, flags, codec_settings); -} - -static switch_status_t switch_sangoma_init_g729(switch_codec_t *codec, switch_codec_flag_t flags, const switch_codec_settings_t *codec_settings) -{ - if (codec->fmtp_in) { - codec->fmtp_out = switch_core_strdup(codec->memory_pool, codec->fmtp_in); - } - - return switch_sangoma_init(codec, flags, codec_settings); -} - -static void flush_rtp(switch_rtp_t *rtp) -{ - switch_status_t sres; - switch_frame_t read_frame; - int flushed = 0; - int sanity = 1000; - while (sanity--) { - sres = switch_rtp_zerocopy_read_frame(rtp, &read_frame, SWITCH_IO_FLAG_NOBLOCK); - if (sres == SWITCH_STATUS_GENERR) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Failed to read on Sangoma encoder RTP session while flushing: %d\n", sres); - return; - } - if (!read_frame.datalen) { - break; - } - flushed++; - } - if (!sanity) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Insanely big UDP queue!\n"); - } -} - -#define SAFE_INDEX_INC(array, index) \ - (index)++; \ - if ((index) == switch_arraylen((array))) { \ - (index) = 0; \ - } - -static switch_status_t switch_sangoma_encode(switch_codec_t *codec, switch_codec_t *other_codec, /* codec that was used by the other side */ - void *decoded_data, /* decoded data that we must encode */ - uint32_t decoded_data_len /* decoded data length */ , - uint32_t decoded_rate /* rate of the decoded data */ , - void *encoded_data, /* here we will store the encoded data */ - uint32_t *encoded_data_len, /* here we will set the length of the encoded data */ - uint32_t *encoded_rate /* here we will set the rate of the encoded data */ , - unsigned int *flag /* frame flag, see switch_frame_flag_enum_t */ ) -{ - /* FS core checks the actual samples per second and microseconds per packet to determine the buffer size in the worst case scenario, no need to check - * whether the buffer passed in by the core (encoded_data) will be big enough */ - switch_frame_t linear_frame; - switch_frame_t encoded_frame; - switch_status_t sres = SWITCH_STATUS_FALSE; - uint16_t decoded_byteswapped_data[SWITCH_RECOMMENDED_BUFFER_SIZE]; - uint16_t *decoded_data_linear = decoded_data; - switch_time_t now_time = 0, difftime = 0; - switch_time_t func_start_time = 0, func_end_time = 0; - int i = 0; - int res = 0; - int linear_payload = codec->implementation->actual_samples_per_second == 8000 ? IANA_L16_A_8000_1 : IANA_L16_A_16000_1; - struct sangoma_transcoding_session *sess = codec->private_info; - - if (sess->encoder.debug_timing) { - func_start_time = switch_micro_time_now(); - } - - sess->encoder.ticks++; - - /* start assuming we will not encode anything */ - *encoded_data_len = 0; - - /* initialize on first use */ - if (!sess->encoder.txrtp) { - int err = 0; - switch_mutex_lock(g_sessions_lock); - err = sngtc_create_transcoding_session(&sess->encoder.request, &sess->encoder.reply, 0); - if (err) { - memset(&sess->encoder, 0, sizeof(sess->encoder)); - switch_mutex_unlock(g_sessions_lock); - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Failed to create Sangoma encoding session.\n"); - return SWITCH_STATUS_FALSE; - } - sess->encoder.txrtp = sess->encoder.reply.tx_fd; - sess->encoder.rxrtp = sess->encoder.reply.rx_fd; - switch_mutex_unlock(g_sessions_lock); - flush_rtp(sess->encoder.rxrtp); - } - - if (sess->encoder.debug_timing && sess->encoder.last_func_call_time) { - difftime = func_start_time - sess->encoder.last_func_call_time; - if (difftime > 25000 || difftime < 15000) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "%ldus since last read on encoding session %lu\n", (long)difftime, sess->sessid); - } - } - - /* do the writing */ - memset(&linear_frame, 0, sizeof(linear_frame)); - linear_frame.source = __SWITCH_FUNC__; - linear_frame.data = decoded_byteswapped_data; - linear_frame.datalen = decoded_data_len; - linear_frame.payload = linear_payload; - - /* copy and byte-swap */ - for (i = 0; i < decoded_data_len/2; i++) { - decoded_byteswapped_data[i] = (decoded_data_linear[i] << 8) | (decoded_data_linear[i] >> 8); - } - - - res = switch_rtp_write_frame(sess->encoder.txrtp, &linear_frame); - if (-1 == res) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Failed to write to Sangoma encoder RTP session.\n"); - return SWITCH_STATUS_FALSE; - } - - if (res < i) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, - "Requested to write %d bytes to Sangoma encoder RTP session, but wrote %d bytes.\n", i, res); - return SWITCH_STATUS_FALSE; - } - sess->encoder.tx++; - - /* do the reading */ - for ( ; ; ) { -#if 0 - prevread_time = switch_micro_time_now(); -#endif - sres = switch_rtp_zerocopy_read_frame(sess->encoder.rxrtp, &encoded_frame, SWITCH_IO_FLAG_NOBLOCK); - if (sres == SWITCH_STATUS_GENERR) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Failed to read on Sangoma encoder RTP session: %d\n", sres); - return SWITCH_STATUS_FALSE; - } - -#if 0 - afterread_time = switch_micro_time_now(); - difftime = afterread_time - prevread_time; - if (difftime > 0) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "%ldus to read on encoding session %lu.\n", (long)difftime, sess->sessid); - } -#endif - if (0 == encoded_frame.datalen) { - break; - } - - if (encoded_frame.payload == IANACODE_CN) { - /* confort noise is treated as silence by us */ - continue; - } - - if (codec->implementation->encoded_bytes_per_packet && encoded_frame.datalen != codec->implementation->encoded_bytes_per_packet) { - /* seen when silence suppression is enabled */ - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Ignoring encoded frame of %d bytes intead of %d bytes\n", encoded_frame.datalen, codec->implementation->encoded_bytes_per_packet); - continue; - } - - if (encoded_frame.payload != codec->implementation->ianacode) { - if (sess->encoder.request.b.codec_id == SNGTC_CODEC_ILBC_152 || sess->encoder.request.b.codec_id == SNGTC_CODEC_ILBC_133) { - /* since we moved to SOAP based communications, the mapping between vocallo IANA and our IANA does not work, - * some codecs checks cannot be completely done, like iLBC */ - if (encoded_frame.payload != IANA_ILBC_152_8000_1 && encoded_frame.payload != IANA_ILBC_133_8000_1) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Read unexpected payload %d in Sangoma encoder RTP session, expecting either %d or %d\n", - encoded_frame.payload, IANA_ILBC_152_8000_1, IANA_ILBC_133_8000_1); - break; - } - } else { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Read unexpected payload %d in Sangoma encoder RTP session, expecting %d\n", - encoded_frame.payload, codec->implementation->ianacode); - break; - } - } - - if (sess->encoder.queue_windex == sess->encoder.queue_rindex) { - if (sess->encoder.rtp_queue[sess->encoder.queue_rindex].datalen) { - /* if there is something where we want to write, we're dropping it */ - sess->encoder.rxdiscarded++; -#if 0 - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Discarding encoded frame of %d bytes from RTP session %lu, windex = %d, rindex = %d\n", - sess->encoder.rtp_queue[sess->encoder.queue_rindex].datalen, sess->sessid, sess->encoder.queue_windex, sess->encoder.queue_rindex); -#endif - SAFE_INDEX_INC(sess->encoder.rtp_queue, sess->encoder.queue_rindex); - sess->encoder.queue_size--; - } - } - - memcpy(sess->encoder.rtp_queue[sess->encoder.queue_windex].data, encoded_frame.data, encoded_frame.datalen); - sess->encoder.rtp_queue[sess->encoder.queue_windex].datalen = encoded_frame.datalen; - SAFE_INDEX_INC(sess->encoder.rtp_queue, sess->encoder.queue_windex); - - /* monitor the queue size */ - sess->encoder.queue_size++; - if (sess->encoder.queue_size > sess->encoder.queue_max_ever) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Encoder Rx queue for RTP session %lu is now %d, windex = %d, rindex = %d\n", sess->sessid, sess->encoder.queue_size, - sess->encoder.queue_windex, sess->encoder.queue_rindex); - sess->encoder.queue_max_ever = sess->encoder.queue_size; - } - } - - /* update encoding stats if we have a frame to give */ - if (sess->encoder.rtp_queue[sess->encoder.queue_rindex].datalen) { - sess->encoder.rx++; - now_time = switch_micro_time_now(); - if (!sess->encoder.last_rx_time) { - sess->encoder.last_rx_time = now_time; - } else { - difftime = now_time - sess->encoder.last_rx_time; - sess->encoder.avgrxus = sess->encoder.avgrxus ? ((sess->encoder.avgrxus + difftime)/2) : difftime; - sess->encoder.last_rx_time = now_time; - } - - /* check sequence and bump lost rx packets count if needed */ - if (sess->encoder.lastrxseqno >= 0) { - if (encoded_frame.seq > (sess->encoder.lastrxseqno + 2) ) { - sess->encoder.rxlost += encoded_frame.seq - sess->encoder.lastrxseqno - 1; - } - } - sess->encoder.lastrxseqno = encoded_frame.seq; - - /* pop the data from the queue */ - *encoded_data_len = sess->encoder.rtp_queue[sess->encoder.queue_rindex].datalen; - memcpy(encoded_data, sess->encoder.rtp_queue[sess->encoder.queue_rindex].data, *encoded_data_len); - sess->encoder.rtp_queue[sess->encoder.queue_rindex].datalen = 0; - SAFE_INDEX_INC(sess->encoder.rtp_queue, sess->encoder.queue_rindex); - sess->encoder.queue_size--; - if (codec->implementation->encoded_bytes_per_packet && *encoded_data_len != codec->implementation->encoded_bytes_per_packet) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Returning odd encoded frame of %d bytes intead of %d bytes\n", *encoded_data_len, codec->implementation->encoded_bytes_per_packet); - } - } else { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "No output from sangoma encoder\n"); - } - - if (sess->encoder.debug_timing) { - func_end_time = switch_micro_time_now(); - difftime = func_end_time - func_start_time; - if (difftime > 5000) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "%ldus to execute encoding function in session %lu.\n", (long)difftime, sess->sessid); - } - sess->encoder.last_func_call_time = func_end_time; - } - return SWITCH_STATUS_SUCCESS; -} - -static switch_status_t switch_sangoma_decode(switch_codec_t *codec, /* codec session handle */ - switch_codec_t *other_codec, /* what is this? */ - void *encoded_data, /* data that we must decode into slinear and put it in decoded_data */ - uint32_t encoded_data_len, /* length in bytes of the encoded data */ - uint32_t encoded_rate, /* at which rate was the data encoded */ - void *decoded_data, /* buffer where we must put the decoded data */ - uint32_t *decoded_data_len, /* we must set this value to the size of the decoded data */ - uint32_t *decoded_rate, /* rate of the decoded data */ - unsigned int *flag /* frame flag, see switch_frame_flag_enum_t */ ) -{ - /* FS core checks the actual samples per second and microseconds per packet to determine the buffer size in the worst case scenario, no need to check - * whether the buffer passed in by the core will be enough */ - switch_frame_t encoded_frame; - switch_frame_t linear_frame; - switch_status_t sres = SWITCH_STATUS_FALSE; - switch_time_t now_time = 0, difftime = 0; - switch_time_t func_start_time = 0, func_end_time = 0; - uint16_t *dbuf_linear; - uint16_t *linear_frame_data; - uint16_t *rtp_data_linear; - int res = 0; - int i = 0; - int linear_payload = codec->implementation->actual_samples_per_second == 8000 ? IANA_L16_A_8000_1 : IANA_L16_A_16000_1; - struct sangoma_transcoding_session *sess = codec->private_info; - - if (sess->decoder.debug_timing) { - func_start_time = switch_micro_time_now(); - } - - dbuf_linear = decoded_data; - sess->decoder.ticks++; - - /* start assuming we will not decode anything */ - *decoded_data_len = 0; - if (*flag & SWITCH_CODEC_FLAG_SILENCE) { - memset(dbuf_linear, 0, codec->implementation->decoded_bytes_per_packet); - *decoded_data_len = codec->implementation->decoded_bytes_per_packet; - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Returned silence on request\n"); - return SWITCH_STATUS_SUCCESS; - } - - /* initialize on first use */ - if (!sess->decoder.txrtp) { - int err = 0; - switch_mutex_lock(g_sessions_lock); - err = sngtc_create_transcoding_session(&sess->decoder.request, &sess->decoder.reply, 0); - if (err) { - memset(&sess->decoder, 0, sizeof(sess->decoder)); - switch_mutex_unlock(g_sessions_lock); - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Failed to create Sangoma decoding session.\n"); - return SWITCH_STATUS_FALSE; - } - sess->decoder.txrtp = sess->decoder.reply.tx_fd; - sess->decoder.rxrtp = sess->decoder.reply.rx_fd; - switch_mutex_unlock(g_sessions_lock); - flush_rtp(sess->decoder.rxrtp); - } - - if (sess->decoder.debug_timing && sess->decoder.last_func_call_time) { - difftime = func_start_time - sess->decoder.last_func_call_time; - if (difftime > 25000 || difftime < 15000) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "%ldms since last read on decoding session %lu.\n", (long)difftime, sess->sessid); - } - } - - /* do the writing */ - memset(&encoded_frame, 0, sizeof(encoded_frame)); - encoded_frame.source = __SWITCH_FUNC__; - encoded_frame.data = encoded_data; - encoded_frame.datalen = encoded_data_len; - encoded_frame.payload = codec->implementation->ianacode; - - res = switch_rtp_write_frame(sess->decoder.txrtp, &encoded_frame); - if (-1 == res) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Failed to write to Sangoma decoder RTP session.\n"); - return SWITCH_STATUS_FALSE; - } - - if (res < encoded_data_len) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, - "Requested to write %d bytes to Sangoma decoder RTP session, but wrote %d bytes.\n", - encoded_data_len, res); - return SWITCH_STATUS_FALSE; - } - sess->decoder.tx++; - - /* do the reading */ - for ( ; ; ) { -#if 0 - prevread_time = switch_micro_time_now(); -#endif - sres = switch_rtp_zerocopy_read_frame(sess->decoder.rxrtp, &linear_frame, SWITCH_IO_FLAG_NOBLOCK); - if (sres == SWITCH_STATUS_GENERR) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Failed to read on Sangoma decoder RTP session: %d\n", sres); - return SWITCH_STATUS_FALSE; - } - -#if 0 - afterread_time = switch_micro_time_now(); - difftime = afterread_time - prevread_time; - if (difftime > 0) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "%ldus to read on decoding session %lu.\n", (long)difftime, sess->sessid); - } -#endif - if (0 == linear_frame.datalen) { - break; - } - - if (linear_frame.payload == IANACODE_CN) { - /* confort noise is treated as silence by us */ - continue; - } - - if (linear_frame.payload != linear_payload) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Read unexpected payload %d in Sangoma decoder RTP session, expecting %d\n", - linear_frame.payload, linear_payload); - break; - } - - - if (sess->decoder.queue_windex == sess->decoder.queue_rindex) { - if (sess->decoder.rtp_queue[sess->decoder.queue_rindex].datalen) { - /* if there is something where we want to write, we're dropping it */ - sess->decoder.rxdiscarded++; -#if 0 - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Discarding decoded frame of %d bytes from RTP session %lu, windex = %d, rindex = %d\n", - sess->decoder.rtp_queue[sess->decoder.queue_rindex].datalen, sess->sessid, sess->decoder.queue_windex, sess->decoder.queue_rindex); -#endif - SAFE_INDEX_INC(sess->decoder.rtp_queue, sess->decoder.queue_rindex); - sess->decoder.queue_size--; - } - } - - /* byteswap the received data */ - rtp_data_linear = (unsigned short *)sess->decoder.rtp_queue[sess->decoder.queue_windex].data; - linear_frame_data = linear_frame.data; - for (i = 0; i < linear_frame.datalen/2; i++) { - rtp_data_linear[i] = (linear_frame_data[i] << 8) | (linear_frame_data[i] >> 8); - } - sess->decoder.rtp_queue[sess->decoder.queue_windex].datalen = linear_frame.datalen; - - SAFE_INDEX_INC(sess->decoder.rtp_queue, sess->decoder.queue_windex); - - /* monitor the queue size */ - sess->decoder.queue_size++; - if (sess->decoder.queue_size > sess->decoder.queue_max_ever) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Encoder Rx queue for RTP session %lu is now %d, windex = %d, rindex = %d\n", sess->sessid, sess->decoder.queue_size, - sess->decoder.queue_windex, sess->decoder.queue_rindex); - sess->decoder.queue_max_ever = sess->decoder.queue_size; - } - } - - if (sess->decoder.rtp_queue[sess->decoder.queue_rindex].datalen) { - /* update decoding stats */ - sess->decoder.rx++; - - now_time = switch_micro_time_now(); - if (!sess->decoder.last_rx_time) { - sess->decoder.last_rx_time = now_time; - } else { - difftime = now_time - sess->decoder.last_rx_time; - sess->decoder.avgrxus = sess->decoder.avgrxus ? ((sess->decoder.avgrxus + difftime)/2) : difftime; - sess->decoder.last_rx_time = now_time; - } - - /* check sequence and bump lost rx packets count if needed */ - if (sess->decoder.lastrxseqno >= 0) { - if (linear_frame.seq > (sess->decoder.lastrxseqno + 2) ) { - sess->decoder.rxlost += linear_frame.seq - sess->decoder.lastrxseqno - 1; - } - } - sess->decoder.lastrxseqno = linear_frame.seq; - - /* pop the data from the queue */ - memcpy(dbuf_linear, sess->decoder.rtp_queue[sess->decoder.queue_rindex].data, sess->decoder.rtp_queue[sess->decoder.queue_rindex].datalen); - *decoded_data_len = sess->decoder.rtp_queue[sess->decoder.queue_rindex].datalen; - sess->decoder.rtp_queue[sess->decoder.queue_rindex].datalen = 0; - SAFE_INDEX_INC(sess->decoder.rtp_queue, sess->decoder.queue_rindex); - sess->decoder.queue_size--; - - if (*decoded_data_len != codec->implementation->decoded_bytes_per_packet) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Returning odd decoded frame of %d bytes intead of %d bytes\n", *decoded_data_len, codec->implementation->decoded_bytes_per_packet); - } - } else { - *decoded_data_len = codec->implementation->decoded_bytes_per_packet; - memset(dbuf_linear, 0, *decoded_data_len); - } - - if (sess->decoder.debug_timing) { - func_end_time = switch_micro_time_now(); - difftime = func_end_time - func_start_time; - if (difftime > 5000) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "%ldus to execute decoding function in session %lu.\n", (long)difftime, sess->sessid); - } - sess->decoder.last_func_call_time = func_end_time; - } - - return SWITCH_STATUS_SUCCESS; -} - -static switch_status_t switch_sangoma_destroy(switch_codec_t *codec) -{ - struct sangoma_transcoding_session *sess = codec->private_info; - /* things that you may do here is closing files, sockets or other resources used during the codec session - * no need to free memory allocated from the pool though, the owner of the pool takes care of that */ - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Sangoma destroy called.\n"); - - switch_mutex_lock(g_sessions_lock); - - if (sess->encoder.txrtp) { - sngtc_free_transcoding_session(&sess->encoder.reply); - } - if (sess->decoder.txrtp) { - sngtc_free_transcoding_session(&sess->decoder.reply); - } - - switch_core_hash_delete(g_sessions_hash, sess->hashkey); - memset(sess, 0, sizeof(*sess)); - - switch_mutex_unlock(g_sessions_lock); - return SWITCH_STATUS_SUCCESS; -} - -static struct sangoma_transcoding_session *sangoma_find_session(unsigned long sessid) -{ - char hashkey[50]; - snprintf(hashkey, sizeof(hashkey), SANGOMA_SESS_HASH_KEY_FORMAT, sessid); - return switch_core_hash_find(g_sessions_hash, hashkey); -} - -static void sangoma_print_stats(switch_stream_handle_t *stream, switch_rtp_numbers_t *stats) -{ - stream->write_function(stream, "Raw bytes: %lu\n", stats->raw_bytes); - stream->write_function(stream, "Media bytes: %lu\n", stats->media_bytes); - stream->write_function(stream, "Packet count: %lu\n", stats->packet_count); - stream->write_function(stream, "Media packet count: %lu\n", stats->media_packet_count); - stream->write_function(stream, "Skip packet count: %lu\n", stats->skip_packet_count); - stream->write_function(stream, "Jitter buffer packet count: %lu\n", stats->jb_packet_count); - stream->write_function(stream, "DTMF packet count: %lu\n", stats->dtmf_packet_count); - stream->write_function(stream, "CNG packet count: %lu\n", stats->cng_packet_count); - stream->write_function(stream, "Flush packet count: %lu\n\n\n", stats->flush_packet_count); -} - -#define SANGOMA_SYNTAX "settings|sessions|stats |debug |nodebug " -SWITCH_STANDARD_API(sangoma_function) -{ - char *argv[10] = { 0 }; - int argc = 0; - char *mycmd = NULL; - switch_bool_t locked = SWITCH_FALSE; - - if (zstr(cmd)) { - stream->write_function(stream, "%s", SANGOMA_SYNTAX); - return SWITCH_STATUS_SUCCESS; - } - - if (!(mycmd = strdup(cmd))) { - return SWITCH_STATUS_MEMERR; - } - - if (!(argc = switch_separate_string(mycmd, ' ', argv, (sizeof(argv) / sizeof(argv[0])))) || !argv[0]) { - stream->write_function(stream, "%s", SANGOMA_SYNTAX); - switch_safe_free(mycmd); - return SWITCH_STATUS_SUCCESS; - } - - /* Most operations in this API require the global session lock anyways since sessions can disappear at any moment ... */ - switch_mutex_lock(g_sessions_lock); - locked = SWITCH_TRUE; - - if (!strcasecmp(argv[0], "settings")) { - char addrbuff[50]; - int addr; - addr = htonl(g_rtpip); - stream->write_function(stream, "\tRTP IP Address: %s\n", - switch_inet_ntop(AF_INET, &addr, addrbuff, sizeof(addrbuff))); - } else if (!strcasecmp(argv[0], "sessions")) { - /* iterate over sessions hash */ - switch_hash_index_t *hi; - const void *var; - void *val; - unsigned totalsess = 0; -#define STATS_FORMAT "%-10.10s %-10.10s %-10.10s %-10.10s %-10.10s %-10.10s %-10.10s %-10.10s %-10.10s %-10.10s %-15.15s %-15.15s\n" - stream->write_function(stream, STATS_FORMAT, - "Session", "Codec", "Enc", "Dec", "Enc Tx", "Enc Rx", "Dec Tx", "Dec Rx", "Enc Lost", "Dec Lost", "Enc AvgRxMs", "Dec AvgRxMs"); - for (hi = switch_core_hash_first(g_sessions_hash); hi; hi = switch_core_hash_next(&hi)) { - struct sangoma_transcoding_session *sess; - char sessid_str[25]; - char encoder_tx_str[25]; - char encoder_rx_str[25]; - char decoder_tx_str[25]; - char decoder_rx_str[25]; - char encoder_lostrx_str[25]; - char decoder_lostrx_str[25]; - char encoder_avgrxus_str[25]; - char decoder_avgrxus_str[25]; - - switch_core_hash_this(hi, &var, NULL, &val); - sess = val; - - snprintf(sessid_str, sizeof(sessid_str), "%lu", sess->sessid); - snprintf(encoder_tx_str, sizeof(encoder_tx_str), "%lu", sess->encoder.tx); - snprintf(encoder_rx_str, sizeof(encoder_rx_str), "%lu", sess->encoder.rx); - snprintf(decoder_tx_str, sizeof(decoder_tx_str), "%lu", sess->decoder.tx); - snprintf(decoder_rx_str, sizeof(decoder_rx_str), "%lu", sess->decoder.rx); - snprintf(encoder_lostrx_str, sizeof(encoder_lostrx_str), "%lu", sess->encoder.rxlost); - snprintf(decoder_lostrx_str, sizeof(decoder_lostrx_str), "%lu", sess->decoder.rxlost); - snprintf(encoder_avgrxus_str, sizeof(encoder_avgrxus_str), "%ld", (long)(sess->encoder.avgrxus/1000)); - snprintf(decoder_avgrxus_str, sizeof(encoder_avgrxus_str), "%ld", (long)(sess->decoder.avgrxus/1000)); - - - stream->write_function(stream, STATS_FORMAT, - sessid_str, - sess->impl->iananame, - sess->encoder.txrtp ? "Yes" : "No", - sess->decoder.txrtp ? "Yes" : "No", - encoder_tx_str, - encoder_rx_str, - decoder_tx_str, - decoder_rx_str, - encoder_lostrx_str, - decoder_lostrx_str, - encoder_avgrxus_str, - decoder_avgrxus_str); - totalsess++; - } - stream->write_function(stream, "Total sessions: %d\n", totalsess); - } else if (!strcasecmp(argv[0], "stats")) { - struct sangoma_transcoding_session *sess; - unsigned long sessid = 0; - switch_rtp_stats_t *stats = NULL; - int ret = 0; - if (argc < 2) { - stream->write_function(stream, "%s", SANGOMA_SYNTAX); - goto done; - } - ret = sscanf(argv[1], "%lu", &sessid); - if (ret != 1) { - stream->write_function(stream, "%s", SANGOMA_SYNTAX); - goto done; - } - - sess = sangoma_find_session(sessid); - if (!sess) { - stream->write_function(stream, "Failed to find session %lu\n", sessid); - goto done; - } - stream->write_function(stream, "Stats for transcoding session: %lu\n", sessid); - - if (sess->encoder.rxrtp) { - stats = switch_rtp_get_stats(sess->encoder.rxrtp, NULL); - stream->write_function(stream, "=== %s Encoder ===\n", sess->impl->iananame); - - stream->write_function(stream, "Tx L16 from %d.%d.%d.%d:%d to %d.%d.%d.%d:%d\n\n", SNGTC_NIPV4(sess->encoder.reply.a.host_ip), sess->encoder.reply.a.host_udp_port, - SNGTC_NIPV4(sess->encoder.reply.a.codec_ip), sess->encoder.reply.a.codec_udp_port); - stream->write_function(stream, "Rx %s at %d.%d.%d.%d:%d from %d.%d.%d.%d:%d\n\n", sess->impl->iananame, SNGTC_NIPV4(sess->encoder.reply.b.host_ip), sess->encoder.reply.b.host_udp_port, - SNGTC_NIPV4(sess->encoder.reply.b.codec_ip), sess->encoder.reply.b.codec_udp_port); - - stream->write_function(stream, "Ticks: %lu\n", sess->encoder.ticks); - - stream->write_function(stream, "-- Inbound Stats --\n"); - stream->write_function(stream, "Rx Discarded: %lu\n", sess->encoder.rxdiscarded); - sangoma_print_stats(stream, &stats->inbound); - - - stats = switch_rtp_get_stats(sess->encoder.txrtp, NULL); - stream->write_function(stream, "-- Outbound Stats --\n"); - sangoma_print_stats(stream, &stats->outbound); - } - - if (sess->decoder.rxrtp) { - stats = switch_rtp_get_stats(sess->decoder.rxrtp, NULL); - - stream->write_function(stream, "=== %s Decoder ===\n", sess->impl->iananame); - stream->write_function(stream, "Tx %s from %d.%d.%d.%d:%d to %d.%d.%d.%d:%d\n\n", sess->impl->iananame, SNGTC_NIPV4(sess->decoder.reply.a.host_ip), sess->decoder.reply.a.host_udp_port, - SNGTC_NIPV4(sess->decoder.reply.a.codec_ip), sess->decoder.reply.a.codec_udp_port); - stream->write_function(stream, "Rx L16 at %d.%d.%d.%d:%d from %d.%d.%d.%d:%d\n\n", SNGTC_NIPV4(sess->decoder.reply.b.host_ip), sess->decoder.reply.b.host_udp_port, - SNGTC_NIPV4(sess->decoder.reply.b.codec_ip), sess->decoder.reply.b.codec_udp_port); - stream->write_function(stream, "Ticks: %lu\n", sess->decoder.ticks); - - stream->write_function(stream, "-- Inbound Stats --\n"); - stream->write_function(stream, "Rx Discarded: %lu\n", sess->decoder.rxdiscarded); - sangoma_print_stats(stream, &stats->inbound); - - stats = switch_rtp_get_stats(sess->decoder.txrtp, NULL); - stream->write_function(stream, "-- Outbound Stats --\n"); - sangoma_print_stats(stream, &stats->outbound); - } - } else if (!strcasecmp(argv[0], "debug")) { - struct sangoma_transcoding_session *sess; - unsigned long sessid = 0; - int ret = 0; - if (argc < 2) { - stream->write_function(stream, "%s", SANGOMA_SYNTAX); - goto done; - } - ret = sscanf(argv[1], "%lu", &sessid); - if (ret != 1) { - stream->write_function(stream, "%s", SANGOMA_SYNTAX); - goto done; - } - sess = sangoma_find_session(sessid); - if (!sess) { - stream->write_function(stream, "Failed to find session %lu\n", sessid); - goto done; - } - sess->encoder.debug_timing = 1; - sess->decoder.debug_timing = 1; - stream->write_function(stream, "Debug enabled for transcoding session: %lu\n", sessid); - } else if (!strcasecmp(argv[0], "nodebug")) { - struct sangoma_transcoding_session *sess; - unsigned long sessid = 0; - int ret = 0; - if (argc < 2) { - stream->write_function(stream, "%s", SANGOMA_SYNTAX); - goto done; - } - ret = sscanf(argv[1], "%lu", &sessid); - if (ret != 1) { - stream->write_function(stream, "%s", SANGOMA_SYNTAX); - goto done; - } - sess = sangoma_find_session(sessid); - if (!sess) { - stream->write_function(stream, "Failed to find session %lu\n", sessid); - goto done; - } - sess->encoder.debug_timing = 0; - sess->decoder.debug_timing = 0; - stream->write_function(stream, "Debug disabled for transcoding session: %lu\n", sessid); - } else { - stream->write_function(stream, "Unknown Command [%s]\n", argv[0]); - } - -done: - if (locked) { - switch_mutex_unlock(g_sessions_lock); - } - switch_safe_free(mycmd); - - return SWITCH_STATUS_SUCCESS; -} - -static int sangoma_logger(int level, char *fmt, ...) -{ - char *data; - int ret = 0; - va_list ap; - - va_start(ap, fmt); - ret = switch_vasprintf(&data, fmt, ap); - if (ret == -1) { - return -1; - } - va_end(ap); - - switch (level) { - case SNGTC_LOGLEVEL_DEBUG: - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "%s\n", data); - break; - case SNGTC_LOGLEVEL_WARN: - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "%s\n", data); - break; - case SNGTC_LOGLEVEL_INFO: - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "%s\n", data); - break; - case SNGTC_LOGLEVEL_STATS: - break; - case SNGTC_LOGLEVEL_ERROR: - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "%s\n", data); - break; - case SNGTC_LOGLEVEL_CRIT: - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "%s\n", data); - break; - default: - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Unexpected msg with loglevel %d: %s\n", level, data); - } - - free(data); - return 0; -} - -static int sangoma_parse_config(void) -{ - switch_xml_t cfg, settings, param, xml; - struct in_addr rtpaddr; - char localip[255]; - int mask = 0; - int rc = 0; - - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Reading sangoma codec configuration\n"); - if (!(xml = switch_xml_open_cfg(SANGOMA_TRANSCODE_CONFIG, &cfg, NULL))) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Failed to open sangoma codec configuration %s\n", SANGOMA_TRANSCODE_CONFIG); - return -1; - } - - memset(&g_init_cfg, 0, sizeof(g_init_cfg)); - - if ((settings = switch_xml_child(cfg, "settings"))) { - for (param = switch_xml_child(settings, "param"); param; param = param->next) { - char *var = (char *)switch_xml_attr_soft(param, "name"); - char *val = (char *)switch_xml_attr_soft(param, "value"); - - /* this parameter overrides the default list of codecs to load */ - if (!strcasecmp(var, "register")) { - strncpy(g_codec_register_list, val, sizeof(g_codec_register_list)-1); - g_codec_register_list[sizeof(g_codec_register_list)-1] = 0; - } else if (!strcasecmp(var, "noregister")) { - strncpy(g_codec_noregister_list, val, sizeof(g_codec_noregister_list)-1); - g_codec_noregister_list[sizeof(g_codec_noregister_list)-1] = 0; - } else if (!strcasecmp(var, "soapserver")) { - strncpy(g_soap_url, val, sizeof(g_soap_url)-1); - g_soap_url[sizeof(g_soap_url)-1] = 0; - } else if (!strcasecmp(var, "rtpip")) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Found Sangoma RTP IP %s\n", val); - if (switch_inet_pton(AF_INET, val, &rtpaddr) <= 0) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Invalid Sangoma RTP IP %s\n", val); - break; - } - g_rtpip = ntohl(rtpaddr.s_addr); - } else { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Ignored unknown Sangoma codec setting %s\n", var); - } - } - } - - if (!g_rtpip) { - if (SWITCH_STATUS_SUCCESS != switch_find_local_ip(localip, sizeof(localip), &mask, AF_INET)) { - rc = -1; - goto done; - } - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "No RTP IP specified, using %s\n", localip); - switch_inet_pton(AF_INET, localip, &rtpaddr); - g_rtpip = ntohl(rtpaddr.s_addr); - } - -done: - switch_xml_free(xml); - - g_init_cfg.host_nic_vocallo_sz = 0; - - return rc; -} - -SWITCH_MODULE_SHUTDOWN_FUNCTION(mod_sangoma_codec_shutdown) -{ - switch_core_hash_destroy(&g_sessions_hash); - return SWITCH_STATUS_SUCCESS; -} - -SWITCH_MODULE_LOAD_FUNCTION(mod_sangoma_codec_load) -{ - /* the codec interface that will be registered with the core */ - switch_codec_interface_t *codec_interface = NULL; - switch_api_interface_t *api_interface = NULL; - int i = 0, c = 0; - int ilbc_done = 0; - int siren_done = 0; - vocallo_codec_t *ilbc_codec = NULL; - vocallo_codec_t *siren_codec = NULL; - int detected = 0, activated = 0; - - /* make sure we have valid configuration */ - if (sangoma_parse_config()) { - return SWITCH_STATUS_FALSE; - } - - g_init_cfg.log = sangoma_logger; - g_init_cfg.create_rtp = sangoma_create_rtp; - g_init_cfg.create_rtp_port = sangoma_create_rtp_port; - g_init_cfg.destroy_rtp = sangoma_destroy_rtp; - g_init_cfg.release_rtp_port = sangoma_release_rtp_port; - - if (sngtc_detect_init_modules(&g_init_cfg, &detected)) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Failed to detect vocallo modules\n"); - return SWITCH_STATUS_FALSE; - } - - if (sngtc_activate_modules(&g_init_cfg, &activated)) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Failed to activate vocallo modules\n"); - return SWITCH_STATUS_FALSE; - } - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "Detected %d and activated %d Sangoma codec vocallo modules\n", detected, activated); - - if (strlen(g_soap_url)) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "Using %s SOAP server\n", g_soap_url); - sngtc_set_soap_server_url(g_soap_url); - } - - switch_mutex_init(&g_sessions_lock, SWITCH_MUTEX_UNNESTED, pool); - - switch_core_hash_init(&g_sessions_hash); - - *module_interface = switch_loadable_module_create_module_interface(pool, modname); - - - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Loading codecs, register='%s', noregister='%s'\n", g_codec_register_list, g_codec_noregister_list); - for (c = 0; g_codec_map[c].codec_id != -1; c++) { - - if (g_codec_map[c].codec_id == SNGTC_CODEC_L16_1 || g_codec_map[c].codec_id == SNGTC_CODEC_L16_2) { - /* registering L16 does not make any sense */ - continue; - } - - /* check if the codec is in the load list, otherwise skip it */ - if (strcasecmp(g_codec_register_list, "all") && !strcasestr(g_codec_register_list, g_codec_map[c].iana_name)) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Not loading codec %s because was not found in the load list\n", - g_codec_map[c].iana_name); - continue; - } - - /* load it unless is named in the noload list */ - if (strcasestr(g_codec_noregister_list, g_codec_map[c].iana_name)) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Not loading codec %s because was not found in the noload list\n", - g_codec_map[c].iana_name); - continue; - } - - /* special check for iLBC to add a single codec interface for both ILBC bitrate versions */ - if ((g_codec_map[c].codec_id == SNGTC_CODEC_ILBC_152 || g_codec_map[c].codec_id == SNGTC_CODEC_ILBC_133) && ilbc_done) { - continue; - } - - /* special check for siren to add a single codec interface for all siren bitrate versions */ - if ((g_codec_map[c].codec_id == SNGTC_CODEC_SIREN7_24 || g_codec_map[c].codec_id == SNGTC_CODEC_SIREN7_32) && siren_done) { - continue; - } - - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Registering implementations for codec %s\n", g_codec_map[c].iana_name); - - /* SWITCH_ADD_CODEC allocates a codec interface structure from the pool the core gave us and adds it to the internal interface - * list the core keeps, gets a codec id and set the given codec name to it. - * At this point there is an empty shell codec interface registered, but not yet implementations */ - SWITCH_ADD_CODEC(codec_interface, g_codec_map[c].fs_name); - - /* Now add as many codec implementations as needed, just up to 200ms for now */ - if (g_codec_map[c].autoinit) { - int ms = 0; - for (i = 1; i <= 20; i++) { - ms = i * 10; - if (g_codec_map[c].maxms < ms) { - break; - } - - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Adding %dms implementation of codec %s\n", ms, g_codec_map[c].fs_name); - switch_core_codec_add_implementation(pool, codec_interface, /* the codec interface we allocated and we want to register with the core */ - SWITCH_CODEC_TYPE_AUDIO, /* enumeration defining the type of the codec */ - g_codec_map[c].iana, /* the IANA code number, ie http://www.iana.org/assignments/rtp-parameters */ - g_codec_map[c].iana_name, /* the IANA code name */ - NULL, /* default fmtp to send (can be overridden by the init function), fmtp is used in SDP for format specific parameters */ - g_codec_map[c].sampling_rate, /* samples transferred per second */ - g_codec_map[c].actual_sampling_rate, /* actual samples transferred per second */ - g_codec_map[c].bps, /* bits transferred per second */ - g_codec_map[c].mpf * i, /* microseconds per frame */ - g_codec_map[c].spf * i, /* samples per frame */ - g_codec_map[c].bpfd * i, /* number of bytes per frame decompressed */ - g_codec_map[c].bpfc * i, /* number of bytes per frame compressed */ - 1, /* number of channels represented */ - g_codec_map[c].spf * i, /* number of frames per network packet (I dont think this is used at all) */ - switch_sangoma_init, /* function to initialize a codec session using this implementation */ - switch_sangoma_encode, /* function to encode slinear data into encoded data */ - switch_sangoma_decode, /* function to decode encoded data into slinear data */ - switch_sangoma_destroy); /* deinitalize a codec handle using this implementation */ - - } - } else { - - /* custom implementation for some codecs */ - switch (g_codec_map[c].codec_id) { - case SNGTC_CODEC_GSM_FR: - switch_core_codec_add_implementation(pool, codec_interface, /* the codec interface we allocated and we want to register with the core */ - SWITCH_CODEC_TYPE_AUDIO, /* enumeration defining the type of the codec */ - g_codec_map[c].iana, /* the IANA code number, ie http://www.iana.org/assignments/rtp-parameters */ - g_codec_map[c].iana_name, /* the IANA code name */ - NULL, /* default fmtp to send (can be overridden by the init function), fmtp is used in SDP for format specific parameters */ - 8000, /* samples transferred per second */ - 8000, /* actual samples transferred per second */ - g_codec_map[c].bps, /* bits transferred per second */ - g_codec_map[c].mpf, /* microseconds per frame */ - g_codec_map[c].spf, /* samples per frame */ - g_codec_map[c].bpfd, /* number of bytes per frame decompressed */ - g_codec_map[c].bpfc, /* number of bytes per frame compressed */ - 1, /* number of channels represented */ - g_codec_map[c].spf, /* number of frames per network packet (I dont think this is used at all) */ - switch_sangoma_init, /* function to initialize a codec session using this implementation */ - switch_sangoma_encode, /* function to encode slinear data into encoded data */ - switch_sangoma_decode, /* function to decode encoded data into slinear data */ - switch_sangoma_destroy); /* deinitalize a codec handle using this implementation */ - - break; - case SNGTC_CODEC_ILBC_133: - case SNGTC_CODEC_ILBC_152: - ilbc_codec = get_codec_from_id(SNGTC_CODEC_ILBC_152); - switch_core_codec_add_implementation(pool, codec_interface, /* the codec interface we allocated and we want to register with the core */ - SWITCH_CODEC_TYPE_AUDIO, /* enumeration defining the type of the codec */ - ilbc_codec->iana, /* the IANA code number, ie http://www.iana.org/assignments/rtp-parameters */ - ilbc_codec->iana_name, /* the IANA code name */ - "mode=20", /* default fmtp to send (can be overridden by the init function), fmtp is used in SDP for format specific parameters */ - 8000, /* samples transferred per second */ - 8000, /* actual samples transferred per second */ - 15200, /* bits transferred per second */ - 20000, /* microseconds per frame */ - 160, /* samples per frame */ - 320, /* number of bytes per frame decompressed */ - 38, /* number of bytes per frame compressed */ - 1, /* number of channels represented */ - 1, /* number of frames per network packet (I dont think this is used at all) */ - switch_sangoma_init_ilbc, /* function to initialize a codec session using this implementation */ - switch_sangoma_encode, /* function to encode slinear data into encoded data */ - switch_sangoma_decode, /* function to decode encoded data into slinear data */ - switch_sangoma_destroy); /* deinitalize a codec handle using this implementation */ - - ilbc_codec = get_codec_from_id(SNGTC_CODEC_ILBC_133); - switch_core_codec_add_implementation(pool, codec_interface, /* the codec interface we allocated and we want to register with the core */ - SWITCH_CODEC_TYPE_AUDIO, /* enumeration defining the type of the codec */ - ilbc_codec->iana, /* the IANA code number, ie http://www.iana.org/assignments/rtp-parameters */ - ilbc_codec->iana_name, /* the IANA code name */ - "mode=30", /* default fmtp to send (can be overridden by the init function), fmtp is used in SDP for format specific parameters */ - 8000, /* samples transferred per second */ - 8000, /* actual samples transferred per second */ - 13330, /* bits transferred per second */ - 30000, /* microseconds per frame */ - 240, /* samples per frame */ - 480, /* number of bytes per frame decompressed */ - 50, /* number of bytes per frame compressed */ - 1, /* number of channels represented */ - 1, /* number of frames per network packet (I dont think this is used at all) */ - switch_sangoma_init_ilbc, /* function to initialize a codec session using this implementation */ - switch_sangoma_encode, /* function to encode slinear data into encoded data */ - switch_sangoma_decode, /* function to decode encoded data into slinear data */ - switch_sangoma_destroy); /* deinitalize a codec handle using this implementation */ - ilbc_done = 1; - break; - - case SNGTC_CODEC_G723_1_63: - - for (i = 1; i <= 3; i++) { - switch_core_codec_add_implementation(pool, codec_interface, /* the codec interface we allocated and we want to register with the core */ - SWITCH_CODEC_TYPE_AUDIO, /* enumeration defining the type of the codec */ - g_codec_map[c].iana, /* the IANA code number, ie http://www.iana.org/assignments/rtp-parameters */ - g_codec_map[c].iana_name, /* the IANA code name */ - NULL, /* default fmtp to send (can be overridden by the init function), fmtp is used in SDP for format specific parameters */ - g_codec_map[c].sampling_rate, /* samples transferred per second */ - g_codec_map[c].actual_sampling_rate, /* actual samples transferred per second */ - g_codec_map[c].bps, /* bits transferred per second */ - g_codec_map[c].mpf * i, /* microseconds per frame */ - g_codec_map[c].spf * i, /* samples per frame */ - g_codec_map[c].bpfd * i, /* number of bytes per frame decompressed */ - g_codec_map[c].bpfc * i, /* number of bytes per frame compressed */ - 1, /* number of channels represented */ - g_codec_map[c].spf * i, /* number of frames per network packet (I dont think this is used at all) */ - switch_sangoma_init, /* function to initialize a codec session using this implementation */ - switch_sangoma_encode, /* function to encode slinear data into encoded data */ - switch_sangoma_decode, /* function to decode encoded data into slinear data */ - switch_sangoma_destroy); /* deinitalize a codec handle using this implementation */ - } - - break; - - case SNGTC_CODEC_AMR_1220: - switch_core_codec_add_implementation(pool, codec_interface, /* the codec interface we allocated and we want to register with the core */ - SWITCH_CODEC_TYPE_AUDIO, /* enumeration defining the type of the codec */ - g_codec_map[c].iana, /* the IANA code number, ie http://www.iana.org/assignments/rtp-parameters */ - g_codec_map[c].iana_name, /* the IANA code name */ - NULL, /* default fmtp to send (can be overridden by the init function), fmtp is used in SDP for format specific parameters */ - g_codec_map[c].sampling_rate, /* samples transferred per second */ - g_codec_map[c].actual_sampling_rate, /* actual samples transferred per second */ - g_codec_map[c].bps, /* bits transferred per second */ - g_codec_map[c].mpf, /* microseconds per frame */ - g_codec_map[c].spf, /* samples per frame */ - g_codec_map[c].bpfd, /* number of bytes per frame decompressed */ - g_codec_map[c].bpfc, /* number of bytes per frame compressed */ - 1, /* number of channels represented */ - g_codec_map[c].spf, /* number of frames per network packet (I dont think this is used at all) */ - switch_sangoma_init, /* function to initialize a codec session using this implementation */ - switch_sangoma_encode, /* function to encode slinear data into encoded data */ - switch_sangoma_decode, /* function to decode encoded data into slinear data */ - switch_sangoma_destroy); /* deinitalize a codec handle using this implementation */ - break; - - case SNGTC_CODEC_SIREN7_24: - case SNGTC_CODEC_SIREN7_32: - - siren_codec = get_codec_from_id(SNGTC_CODEC_SIREN7_24); - switch_core_codec_add_implementation(pool, codec_interface, /* the codec interface we allocated and we want to register with the core */ - SWITCH_CODEC_TYPE_AUDIO, /* enumeration defining the type of the codec */ - siren_codec->iana, /* the IANA code number, ie http://www.iana.org/assignments/rtp-parameters */ - siren_codec->iana_name, /* the IANA code name */ - "bitrate=24000", /* default fmtp to send (can be overridden by the init function), fmtp is used in SDP for format specific parameters */ - siren_codec->sampling_rate, /* samples transferred per second */ - siren_codec->actual_sampling_rate, /* actual samples transferred per second */ - siren_codec->bps, /* bits transferred per second */ - siren_codec->mpf, /* microseconds per frame */ - siren_codec->spf, /* samples per frame */ - siren_codec->bpfd, /* number of bytes per frame decompressed */ - siren_codec->bpfc, /* number of bytes per frame compressed */ - 1, /* number of channels represented */ - siren_codec->spf, /* number of frames per network packet (I dont think this is used at all) */ - switch_sangoma_init_siren7, /* function to initialize a codec session using this implementation */ - switch_sangoma_encode, /* function to encode slinear data into encoded data */ - switch_sangoma_decode, /* function to decode encoded data into slinear data */ - switch_sangoma_destroy); /* deinitalize a codec handle using this implementation */ - - siren_codec = get_codec_from_id(SNGTC_CODEC_SIREN7_32); - switch_core_codec_add_implementation(pool, codec_interface, /* the codec interface we allocated and we want to register with the core */ - SWITCH_CODEC_TYPE_AUDIO, /* enumeration defining the type of the codec */ - siren_codec->iana, /* the IANA code number, ie http://www.iana.org/assignments/rtp-parameters */ - siren_codec->iana_name, /* the IANA code name */ - "bitrate=32000", /* default fmtp to send (can be overridden by the init function), fmtp is used in SDP for format specific parameters */ - siren_codec->sampling_rate, /* samples transferred per second */ - siren_codec->actual_sampling_rate, /* actual samples transferred per second */ - siren_codec->bps, /* bits transferred per second */ - siren_codec->mpf, /* microseconds per frame */ - siren_codec->spf, /* samples per frame */ - siren_codec->bpfd, /* number of bytes per frame decompressed */ - siren_codec->bpfc, /* number of bytes per frame compressed */ - 1, /* number of channels represented */ - siren_codec->spf, /* number of frames per network packet (I dont think this is used at all) */ - switch_sangoma_init_siren7, /* function to initialize a codec session using this implementation */ - switch_sangoma_encode, /* function to encode slinear data into encoded data */ - switch_sangoma_decode, /* function to decode encoded data into slinear data */ - switch_sangoma_destroy); /* deinitalize a codec handle using this implementation */ - siren_done = 1; - break; - - case SNGTC_CODEC_G729AB: - for (i = 1; i <= 20; i++) { - if (g_codec_map[c].maxms < (i * 10)) { - break; - } - - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Adding %dms implementation of codec %s\n", (i * 10), g_codec_map[c].fs_name); - switch_core_codec_add_implementation(pool, codec_interface, /* the codec interface we allocated and we want to register with the core */ - SWITCH_CODEC_TYPE_AUDIO, /* enumeration defining the type of the codec */ - g_codec_map[c].iana, /* the IANA code number, ie http://www.iana.org/assignments/rtp-parameters */ - g_codec_map[c].iana_name, /* the IANA code name */ - NULL, /* default fmtp to send (can be overridden by the init function), fmtp is used in SDP for format specific parameters */ - g_codec_map[c].sampling_rate, /* samples transferred per second */ - g_codec_map[c].actual_sampling_rate, /* actual samples transferred per second */ - g_codec_map[c].bps, /* bits transferred per second */ - g_codec_map[c].mpf * i, /* microseconds per frame */ - g_codec_map[c].spf * i, /* samples per frame */ - g_codec_map[c].bpfd * i, /* number of bytes per frame decompressed */ - g_codec_map[c].bpfc * i, /* number of bytes per frame compressed */ - 1, /* number of channels represented */ - g_codec_map[c].spf * i, /* number of frames per network packet (I dont think this is used at all) */ - switch_sangoma_init_g729, /* function to initialize a codec session using this implementation */ - switch_sangoma_encode, /* function to encode slinear data into encoded data */ - switch_sangoma_decode, /* function to decode encoded data into slinear data */ - switch_sangoma_destroy); /* deinitalize a codec handle using this implementation */ - } - break; - - default: - break; - } - } - } - - - SWITCH_ADD_API(api_interface, "sangoma_codec", "Sangoma Codec Commands", sangoma_function, SANGOMA_SYNTAX); - switch_console_set_complete("add sangoma_codec"); - switch_console_set_complete("add sangoma_codec settings"); - switch_console_set_complete("add sangoma_codec sessions"); - switch_console_set_complete("add sangoma_codec stats"); - switch_console_set_complete("add sangoma_codec debug"); - switch_console_set_complete("add sangoma_codec nodebug"); - - return SWITCH_STATUS_SUCCESS; -} - -/* For Emacs: - * Local Variables: - * mode:c - * indent-tabs-mode:t - * tab-width:4 - * c-basic-offset:4 - * End: - * For VIM: - * vim:set softtabstop=4 shiftwidth=4 tabstop=4 noet: - */