00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029 #include <fcntl.h>
00030 #include <stdlib.h>
00031 #include <unistd.h>
00032 #include <netinet/in.h>
00033 #include <string.h>
00034 #include <stdio.h>
00035
00036 #include "asterisk.h"
00037
00038 ASTERISK_FILE_VERSION(__FILE__, "$Revision: 7221 $")
00039
00040 #include "asterisk/lock.h"
00041 #include "asterisk/translate.h"
00042 #include "asterisk/config.h"
00043 #include "asterisk/options.h"
00044 #include "asterisk/module.h"
00045 #include "asterisk/logger.h"
00046 #include "asterisk/channel.h"
00047
00048 #include <gsm/gsm.h>
00049 #include "../formats/msgsm.h"
00050
00051
00052 #include "slin_gsm_ex.h"
00053 #include "gsm_slin_ex.h"
00054
00055 AST_MUTEX_DEFINE_STATIC(localuser_lock);
00056 static int localusecnt=0;
00057
00058 static char *tdesc = "GSM/PCM16 (signed linear) Codec Translator";
00059
00060 static int useplc = 0;
00061
00062 struct ast_translator_pvt {
00063 gsm gsm;
00064 struct ast_frame f;
00065
00066 char offset[AST_FRIENDLY_OFFSET];
00067
00068 short outbuf[8000];
00069
00070 short buf[8000];
00071 int tail;
00072 plc_state_t plc;
00073 };
00074
00075 #define gsm_coder_pvt ast_translator_pvt
00076
00077 static struct ast_translator_pvt *gsm_new(void)
00078 {
00079 struct gsm_coder_pvt *tmp;
00080 tmp = malloc(sizeof(struct gsm_coder_pvt));
00081 if (tmp) {
00082 if (!(tmp->gsm = gsm_create())) {
00083 free(tmp);
00084 tmp = NULL;
00085 }
00086 tmp->tail = 0;
00087 plc_init(&tmp->plc);
00088 localusecnt++;
00089 }
00090 return tmp;
00091 }
00092
00093 static struct ast_frame *lintogsm_sample(void)
00094 {
00095 static struct ast_frame f;
00096 f.frametype = AST_FRAME_VOICE;
00097 f.subclass = AST_FORMAT_SLINEAR;
00098 f.datalen = sizeof(slin_gsm_ex);
00099
00100 f.samples = sizeof(slin_gsm_ex)/2;
00101 f.mallocd = 0;
00102 f.offset = 0;
00103 f.src = __PRETTY_FUNCTION__;
00104 f.data = slin_gsm_ex;
00105 return &f;
00106 }
00107
00108 static struct ast_frame *gsmtolin_sample(void)
00109 {
00110 static struct ast_frame f;
00111 f.frametype = AST_FRAME_VOICE;
00112 f.subclass = AST_FORMAT_GSM;
00113 f.datalen = sizeof(gsm_slin_ex);
00114
00115 f.samples = 160;
00116 f.mallocd = 0;
00117 f.offset = 0;
00118 f.src = __PRETTY_FUNCTION__;
00119 f.data = gsm_slin_ex;
00120 return &f;
00121 }
00122
00123 static struct ast_frame *gsmtolin_frameout(struct ast_translator_pvt *tmp)
00124 {
00125 if (!tmp->tail)
00126 return NULL;
00127
00128
00129 tmp->f.frametype = AST_FRAME_VOICE;
00130 tmp->f.subclass = AST_FORMAT_SLINEAR;
00131 tmp->f.datalen = tmp->tail * 2;
00132
00133 tmp->f.samples = tmp->tail;
00134 tmp->f.mallocd = 0;
00135 tmp->f.offset = AST_FRIENDLY_OFFSET;
00136 tmp->f.src = __PRETTY_FUNCTION__;
00137 tmp->f.data = tmp->buf;
00138
00139 tmp->tail = 0;
00140
00141 return &tmp->f;
00142 }
00143
00144 static int gsmtolin_framein(struct ast_translator_pvt *tmp, struct ast_frame *f)
00145 {
00146
00147
00148 int x;
00149 unsigned char data[66];
00150 int msgsm=0;
00151
00152 if(f->datalen == 0) {
00153 if((tmp->tail + 160) > sizeof(tmp->buf) / 2) {
00154 ast_log(LOG_WARNING, "Out of buffer space\n");
00155 return -1;
00156 }
00157 if(useplc) {
00158 plc_fillin(&tmp->plc, tmp->buf+tmp->tail, 160);
00159 tmp->tail += 160;
00160 }
00161 return 0;
00162 }
00163
00164 if ((f->datalen % 33) && (f->datalen % 65)) {
00165 ast_log(LOG_WARNING, "Huh? A GSM frame that isn't a multiple of 33 or 65 bytes long from %s (%d)?\n", f->src, f->datalen);
00166 return -1;
00167 }
00168
00169 if (f->datalen % 65 == 0)
00170 msgsm = 1;
00171
00172 for (x=0;x<f->datalen;x+=(msgsm ? 65 : 33)) {
00173 if (msgsm) {
00174
00175 conv65(f->data + x, data);
00176 if (tmp->tail + 320 < sizeof(tmp->buf)/2) {
00177 if (gsm_decode(tmp->gsm, data, tmp->buf + tmp->tail)) {
00178 ast_log(LOG_WARNING, "Invalid GSM data (1)\n");
00179 return -1;
00180 }
00181 tmp->tail+=160;
00182 if (gsm_decode(tmp->gsm, data + 33, tmp->buf + tmp->tail)) {
00183 ast_log(LOG_WARNING, "Invalid GSM data (2)\n");
00184 return -1;
00185 }
00186 tmp->tail+=160;
00187 } else {
00188 ast_log(LOG_WARNING, "Out of (MS) buffer space\n");
00189 return -1;
00190 }
00191 } else {
00192 if (tmp->tail + 160 < sizeof(tmp->buf)/2) {
00193 if (gsm_decode(tmp->gsm, f->data + x, tmp->buf + tmp->tail)) {
00194 ast_log(LOG_WARNING, "Invalid GSM data\n");
00195 return -1;
00196 }
00197 tmp->tail+=160;
00198 } else {
00199 ast_log(LOG_WARNING, "Out of buffer space\n");
00200 return -1;
00201 }
00202 }
00203 }
00204
00205
00206 if(useplc) plc_rx(&tmp->plc, tmp->buf+tmp->tail-160, 160);
00207
00208 return 0;
00209 }
00210
00211 static int lintogsm_framein(struct ast_translator_pvt *tmp, struct ast_frame *f)
00212 {
00213
00214
00215
00216
00217 if (tmp->tail + f->datalen/2 < sizeof(tmp->buf) / 2) {
00218 memcpy((tmp->buf + tmp->tail), f->data, f->datalen);
00219 tmp->tail += f->datalen/2;
00220 } else {
00221 ast_log(LOG_WARNING, "Out of buffer space\n");
00222 return -1;
00223 }
00224 return 0;
00225 }
00226
00227 static struct ast_frame *lintogsm_frameout(struct ast_translator_pvt *tmp)
00228 {
00229 int x=0;
00230
00231 if (tmp->tail < 160)
00232 return NULL;
00233 tmp->f.frametype = AST_FRAME_VOICE;
00234 tmp->f.subclass = AST_FORMAT_GSM;
00235 tmp->f.mallocd = 0;
00236 tmp->f.offset = AST_FRIENDLY_OFFSET;
00237 tmp->f.src = __PRETTY_FUNCTION__;
00238 tmp->f.data = tmp->outbuf;
00239 while(tmp->tail >= 160) {
00240 if ((x+1) * 33 >= sizeof(tmp->outbuf)) {
00241 ast_log(LOG_WARNING, "Out of buffer space\n");
00242 break;
00243 }
00244
00245 gsm_encode(tmp->gsm, tmp->buf, ((gsm_byte *) tmp->outbuf) + (x * 33));
00246
00247 tmp->tail -= 160;
00248
00249 if (tmp->tail)
00250 memmove(tmp->buf, tmp->buf + 160, tmp->tail * 2);
00251 x++;
00252 }
00253 tmp->f.datalen = x * 33;
00254 tmp->f.samples = x * 160;
00255 return &tmp->f;
00256 }
00257
00258 static void gsm_destroy_stuff(struct ast_translator_pvt *pvt)
00259 {
00260 if (pvt->gsm)
00261 gsm_destroy(pvt->gsm);
00262 free(pvt);
00263 localusecnt--;
00264 }
00265
00266 static struct ast_translator gsmtolin =
00267 { "gsmtolin",
00268 AST_FORMAT_GSM, AST_FORMAT_SLINEAR,
00269 gsm_new,
00270 gsmtolin_framein,
00271 gsmtolin_frameout,
00272 gsm_destroy_stuff,
00273 gsmtolin_sample
00274 };
00275
00276 static struct ast_translator lintogsm =
00277 { "lintogsm",
00278 AST_FORMAT_SLINEAR, AST_FORMAT_GSM,
00279 gsm_new,
00280 lintogsm_framein,
00281 lintogsm_frameout,
00282 gsm_destroy_stuff,
00283 lintogsm_sample
00284 };
00285
00286
00287 static void parse_config(void)
00288 {
00289 struct ast_config *cfg;
00290 struct ast_variable *var;
00291 if ((cfg = ast_config_load("codecs.conf"))) {
00292 if ((var = ast_variable_browse(cfg, "plc"))) {
00293 while (var) {
00294 if (!strcasecmp(var->name, "genericplc")) {
00295 useplc = ast_true(var->value) ? 1 : 0;
00296 if (option_verbose > 2)
00297 ast_verbose(VERBOSE_PREFIX_3 "codec_gsm: %susing generic PLC\n", useplc ? "" : "not ");
00298 }
00299 var = var->next;
00300 }
00301 }
00302 ast_config_destroy(cfg);
00303 }
00304 }
00305
00306 int reload(void)
00307 {
00308 parse_config();
00309 return 0;
00310 }
00311
00312 int unload_module(void)
00313 {
00314 int res;
00315 ast_mutex_lock(&localuser_lock);
00316 res = ast_unregister_translator(&lintogsm);
00317 if (!res)
00318 res = ast_unregister_translator(&gsmtolin);
00319 if (localusecnt)
00320 res = -1;
00321 ast_mutex_unlock(&localuser_lock);
00322 return res;
00323 }
00324
00325 int load_module(void)
00326 {
00327 int res;
00328 parse_config();
00329 res=ast_register_translator(&gsmtolin);
00330 if (!res)
00331 res=ast_register_translator(&lintogsm);
00332 else
00333 ast_unregister_translator(&gsmtolin);
00334 return res;
00335 }
00336
00337 char *description(void)
00338 {
00339 return tdesc;
00340 }
00341
00342 int usecount(void)
00343 {
00344 int res;
00345 STANDARD_USECOUNT(res);
00346 return res;
00347 }
00348
00349 char *key()
00350 {
00351 return ASTERISK_GPL_KEY;
00352 }