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 #include <fcntl.h>
00027 #include <netinet/in.h>
00028 #include <stdio.h>
00029 #include <stdlib.h>
00030 #include <string.h>
00031 #include <unistd.h>
00032
00033 #include "asterisk.h"
00034
00035 ASTERISK_FILE_VERSION(__FILE__, "$Revision: 7221 $")
00036
00037 #include "asterisk/lock.h"
00038 #include "asterisk/logger.h"
00039 #include "asterisk/module.h"
00040 #include "asterisk/config.h"
00041 #include "asterisk/options.h"
00042 #include "asterisk/translate.h"
00043 #include "asterisk/channel.h"
00044 #include "asterisk/alaw.h"
00045
00046 #define BUFFER_SIZE 8096
00047
00048 AST_MUTEX_DEFINE_STATIC(localuser_lock);
00049 static int localusecnt = 0;
00050
00051 static char *tdesc = "A-law Coder/Decoder";
00052
00053 static int useplc = 0;
00054
00055
00056
00057 #include "slin_ulaw_ex.h"
00058 #include "ulaw_slin_ex.h"
00059
00060
00061
00062
00063 struct alaw_encoder_pvt
00064 {
00065 struct ast_frame f;
00066 char offset[AST_FRIENDLY_OFFSET];
00067 unsigned char outbuf[BUFFER_SIZE];
00068 int tail;
00069 };
00070
00071
00072
00073
00074 struct alaw_decoder_pvt
00075 {
00076 struct ast_frame f;
00077 char offset[AST_FRIENDLY_OFFSET];
00078 short outbuf[BUFFER_SIZE];
00079 int tail;
00080 plc_state_t plc;
00081 };
00082
00083
00084
00085
00086
00087
00088
00089
00090
00091
00092
00093
00094 static struct ast_translator_pvt * alawtolin_new (void)
00095 {
00096 struct alaw_decoder_pvt *tmp;
00097 tmp = malloc (sizeof (struct alaw_decoder_pvt));
00098 if (tmp)
00099 {
00100 memset(tmp, 0, sizeof(*tmp));
00101 tmp->tail = 0;
00102 plc_init(&tmp->plc);
00103 localusecnt++;
00104 ast_update_use_count ();
00105 }
00106 return (struct ast_translator_pvt *) tmp;
00107 }
00108
00109
00110
00111
00112
00113
00114
00115
00116
00117
00118
00119
00120 static struct ast_translator_pvt * lintoalaw_new (void)
00121 {
00122 struct alaw_encoder_pvt *tmp;
00123 tmp = malloc (sizeof (struct alaw_encoder_pvt));
00124 if (tmp)
00125 {
00126 memset(tmp, 0, sizeof(*tmp));
00127 localusecnt++;
00128 ast_update_use_count ();
00129 tmp->tail = 0;
00130 }
00131 return (struct ast_translator_pvt *) tmp;
00132 }
00133
00134
00135
00136
00137
00138
00139
00140
00141
00142
00143
00144
00145
00146 static int
00147 alawtolin_framein (struct ast_translator_pvt *pvt, struct ast_frame *f)
00148 {
00149 struct alaw_decoder_pvt *tmp = (struct alaw_decoder_pvt *) pvt;
00150 int x;
00151 unsigned char *b;
00152
00153 if(f->datalen == 0) {
00154 if((tmp->tail + 160) * 2 > sizeof(tmp->outbuf)) {
00155 ast_log(LOG_WARNING, "Out of buffer space\n");
00156 return -1;
00157 }
00158 if(useplc) {
00159 plc_fillin(&tmp->plc, tmp->outbuf+tmp->tail, 160);
00160 tmp->tail += 160;
00161 }
00162 return 0;
00163 }
00164
00165 if ((tmp->tail + f->datalen) * 2 > sizeof(tmp->outbuf)) {
00166 ast_log(LOG_WARNING, "Out of buffer space\n");
00167 return -1;
00168 }
00169
00170
00171 b = f->data;
00172 for (x=0;x<f->datalen;x++)
00173 tmp->outbuf[tmp->tail + x] = AST_ALAW(b[x]);
00174
00175 if(useplc) plc_rx(&tmp->plc, tmp->outbuf+tmp->tail, f->datalen);
00176
00177 tmp->tail += f->datalen;
00178 return 0;
00179 }
00180
00181
00182
00183
00184
00185
00186
00187
00188
00189
00190
00191
00192
00193 static struct ast_frame * alawtolin_frameout (struct ast_translator_pvt *pvt)
00194 {
00195 struct alaw_decoder_pvt *tmp = (struct alaw_decoder_pvt *) pvt;
00196
00197 if (!tmp->tail)
00198 return NULL;
00199
00200 tmp->f.frametype = AST_FRAME_VOICE;
00201 tmp->f.subclass = AST_FORMAT_SLINEAR;
00202 tmp->f.datalen = tmp->tail *2;
00203 tmp->f.samples = tmp->tail;
00204 tmp->f.mallocd = 0;
00205 tmp->f.offset = AST_FRIENDLY_OFFSET;
00206 tmp->f.src = __PRETTY_FUNCTION__;
00207 tmp->f.data = tmp->outbuf;
00208 tmp->tail = 0;
00209 return &tmp->f;
00210 }
00211
00212
00213
00214
00215
00216
00217
00218
00219
00220
00221
00222
00223 static int lintoalaw_framein (struct ast_translator_pvt *pvt, struct ast_frame *f)
00224 {
00225 struct alaw_encoder_pvt *tmp = (struct alaw_encoder_pvt *) pvt;
00226 int x;
00227 short *s;
00228 if (tmp->tail + f->datalen/2 >= sizeof(tmp->outbuf))
00229 {
00230 ast_log (LOG_WARNING, "Out of buffer space\n");
00231 return -1;
00232 }
00233 s = f->data;
00234 for (x=0;x<f->datalen/2;x++)
00235 tmp->outbuf[x+tmp->tail] = AST_LIN2A(s[x]);
00236 tmp->tail += f->datalen/2;
00237 return 0;
00238 }
00239
00240
00241
00242
00243
00244
00245
00246
00247
00248
00249
00250
00251
00252 static struct ast_frame * lintoalaw_frameout (struct ast_translator_pvt *pvt)
00253 {
00254 struct alaw_encoder_pvt *tmp = (struct alaw_encoder_pvt *) pvt;
00255
00256 if (tmp->tail) {
00257 tmp->f.frametype = AST_FRAME_VOICE;
00258 tmp->f.subclass = AST_FORMAT_ALAW;
00259 tmp->f.samples = tmp->tail;
00260 tmp->f.mallocd = 0;
00261 tmp->f.offset = AST_FRIENDLY_OFFSET;
00262 tmp->f.src = __PRETTY_FUNCTION__;
00263 tmp->f.data = tmp->outbuf;
00264 tmp->f.datalen = tmp->tail;
00265 tmp->tail = 0;
00266 return &tmp->f;
00267 } else return NULL;
00268 }
00269
00270
00271
00272
00273
00274
00275 static struct ast_frame * alawtolin_sample (void)
00276 {
00277 static struct ast_frame f;
00278 f.frametype = AST_FRAME_VOICE;
00279 f.subclass = AST_FORMAT_ALAW;
00280 f.datalen = sizeof (ulaw_slin_ex);
00281 f.samples = sizeof(ulaw_slin_ex);
00282 f.mallocd = 0;
00283 f.offset = 0;
00284 f.src = __PRETTY_FUNCTION__;
00285 f.data = ulaw_slin_ex;
00286 return &f;
00287 }
00288
00289
00290
00291
00292
00293 static struct ast_frame * lintoalaw_sample (void)
00294 {
00295 static struct ast_frame f;
00296 f.frametype = AST_FRAME_VOICE;
00297 f.subclass = AST_FORMAT_SLINEAR;
00298 f.datalen = sizeof (slin_ulaw_ex);
00299
00300 f.samples = sizeof (slin_ulaw_ex) / 2;
00301 f.mallocd = 0;
00302 f.offset = 0;
00303 f.src = __PRETTY_FUNCTION__;
00304 f.data = slin_ulaw_ex;
00305 return &f;
00306 }
00307
00308
00309
00310
00311
00312
00313
00314
00315
00316
00317
00318
00319 static void alaw_destroy (struct ast_translator_pvt *pvt)
00320 {
00321 free (pvt);
00322 localusecnt--;
00323 ast_update_use_count ();
00324 }
00325
00326
00327
00328
00329
00330 static struct ast_translator alawtolin = {
00331 "alawtolin",
00332 AST_FORMAT_ALAW,
00333 AST_FORMAT_SLINEAR,
00334 alawtolin_new,
00335 alawtolin_framein,
00336 alawtolin_frameout,
00337 alaw_destroy,
00338
00339 alawtolin_sample
00340 };
00341
00342
00343
00344
00345
00346 static struct ast_translator lintoalaw = {
00347 "lintoalaw",
00348 AST_FORMAT_SLINEAR,
00349 AST_FORMAT_ALAW,
00350 lintoalaw_new,
00351 lintoalaw_framein,
00352 lintoalaw_frameout,
00353 alaw_destroy,
00354
00355 lintoalaw_sample
00356 };
00357
00358 static void parse_config(void)
00359 {
00360 struct ast_config *cfg;
00361 struct ast_variable *var;
00362
00363 if ((cfg = ast_config_load("codecs.conf"))) {
00364 if ((var = ast_variable_browse(cfg, "plc"))) {
00365 while (var) {
00366 if (!strcasecmp(var->name, "genericplc")) {
00367 useplc = ast_true(var->value) ? 1 : 0;
00368 if (option_verbose > 2)
00369 ast_verbose(VERBOSE_PREFIX_3 "codec_alaw: %susing generic PLC\n", useplc ? "" : "not ");
00370 }
00371 var = var->next;
00372 }
00373 }
00374 ast_config_destroy(cfg);
00375 }
00376 }
00377
00378 int reload(void)
00379 {
00380 parse_config();
00381 return 0;
00382 }
00383
00384 int unload_module (void)
00385 {
00386 int res;
00387 ast_mutex_lock (&localuser_lock);
00388 res = ast_unregister_translator (&lintoalaw);
00389 if (!res)
00390 res = ast_unregister_translator (&alawtolin);
00391 if (localusecnt)
00392 res = -1;
00393 ast_mutex_unlock (&localuser_lock);
00394 return res;
00395 }
00396
00397 int load_module (void)
00398 {
00399 int res;
00400 parse_config();
00401 res = ast_register_translator (&alawtolin);
00402 if (!res)
00403 res = ast_register_translator (&lintoalaw);
00404 else
00405 ast_unregister_translator (&alawtolin);
00406 return res;
00407 }
00408
00409
00410
00411
00412
00413 char * description (void)
00414 {
00415 return tdesc;
00416 }
00417
00418 int usecount (void)
00419 {
00420 int res;
00421 STANDARD_USECOUNT (res);
00422 return res;
00423 }
00424
00425 char * key ()
00426 {
00427 return ASTERISK_GPL_KEY;
00428 }