Asterisk.org: Developer Documentation (28 Oct 2009)

Wed Oct 28 15:47:53 2009

## Asterisk developer's documentation

# codec_ulaw.c

Go to the documentation of this file.

    00001 /*
    00002  * Asterisk -- An open source telephony toolkit.
    00003  *
    00004  * Copyright (C) 1999 - 2005, Digium, Inc.
    00005  *
    00006  * Mark Spencer <markster@digium.com>
    00007  *
    00008  * See http://www.asterisk.org for more information about
    00009  * the Asterisk project. Please do not directly contact
    00010  * any of the maintainers of this project for assistance;
    00011  * the project provides a web site, mailing lists and IRC
    00012  * channels for your use.
    00013  *
    00014  * This program is free software, distributed under the terms of
    00015  * the GNU General Public License Version 2. See the LICENSE file
    00016  * at the top of the source tree.
    00017  */
    00018
    00019 /*! \file
    00020  *
    00021  * \brief codec_ulaw.c - translate between signed linear and ulaw
    00022  *
    00023  * \ingroup codecs
    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/ulaw.h"
    00045
    00046 #define BUFFER_SIZE   8096 /* size for the translation buffers */
    00047
    00048 AST_MUTEX_DEFINE_STATIC(localuser_lock);
    00049 static int localusecnt = 0;
    00050
    00051 static char *tdesc = "Mu-law Coder/Decoder";
    00052
    00053 static int useplc = 0;
    00054
    00055 /* Sample frame data */
    00056
    00057 #include "slin_ulaw_ex.h"
    00058 #include "ulaw_slin_ex.h"
    00059
    00060 /*
    00061  * Private workspace for translating signed linear signals to ulaw.
    00062  */
    00063
    00064 struct ulaw_encoder_pvt
    00065 {
    00066   struct ast_frame f;
    00067   char offset[AST_FRIENDLY_OFFSET];   /* Space to build offset */
    00068   unsigned char outbuf[BUFFER_SIZE];  /* Encoded ulaw, two nibbles to a word */
    00069   int tail;
    00070 };
    00071
    00072 /*
    00073  * Private workspace for translating ulaw signals to signed linear.
    00074  */
    00075
    00076 struct ulaw_decoder_pvt
    00077 {
    00078   struct ast_frame f;
    00079   char offset[AST_FRIENDLY_OFFSET]; /* Space to build offset */
    00080   short outbuf[BUFFER_SIZE];  /* Decoded signed linear values */
    00081   int tail;
    00082   plc_state_t plc;
    00083 };
    00084
    00085 /*
    00086  * ulawToLin_New
    00087  *  Create a new instance of ulaw_decoder_pvt.
    00088  *
    00089  * Results:
    00090  *  Returns a pointer to the new instance.
    00091  *
    00092  * Side effects:
    00093  *  None.
    00094  */
    00095
    00096 static struct ast_translator_pvt *
    00097 ulawtolin_new (void)
    00098 {
    00099   struct ulaw_decoder_pvt *tmp;
    00100   tmp = malloc (sizeof (struct ulaw_decoder_pvt));
    00101   if (tmp)
    00102     {
    00103      memset(tmp, 0, sizeof(*tmp));
    00104       tmp->tail = 0;
    00105       plc_init(&tmp->plc);
    00106       localusecnt++;
    00107       ast_update_use_count ();
    00108     }
    00109   return (struct ast_translator_pvt *) tmp;
    00110 }
    00111
    00112 /*
    00113  * LinToulaw_New
    00114  *  Create a new instance of ulaw_encoder_pvt.
    00115  *
    00116  * Results:
    00117  *  Returns a pointer to the new instance.
    00118  *
    00119  * Side effects:
    00120  *  None.
    00121  */
    00122
    00123 static struct ast_translator_pvt *
    00124 lintoulaw_new (void)
    00125 {
    00126   struct ulaw_encoder_pvt *tmp;
    00127   tmp = malloc (sizeof (struct ulaw_encoder_pvt));
    00128   if (tmp)
    00129     {
    00130      memset(tmp, 0, sizeof(*tmp));
    00131       localusecnt++;
    00132       ast_update_use_count ();
    00133       tmp->tail = 0;
    00134     }
    00135   return (struct ast_translator_pvt *) tmp;
    00136 }
    00137
    00138 /*
    00139  * ulawToLin_FrameIn
    00140  *  Fill an input buffer with packed 4-bit ulaw values if there is room
    00141  *  left.
    00142  *
    00143  * Results:
    00144  *  Foo
    00145  *
    00146  * Side effects:
    00147  *  tmp->tail is the number of packed values in the buffer.
    00148  */
    00149
    00150 static int
    00151 ulawtolin_framein (struct ast_translator_pvt *pvt, struct ast_frame *f)
    00152 {
    00153   struct ulaw_decoder_pvt *tmp = (struct ulaw_decoder_pvt *) pvt;
    00154   int x;
    00155   unsigned char *b;
    00156
    00157   if(f->datalen == 0) { /* perform PLC with nominal framesize of 20ms/160 samples */
    00158    if((tmp->tail + 160)  * 2 > sizeof(tmp->outbuf)) {
    00159        ast_log(LOG_WARNING, "Out of buffer space\n");
    00160        return -1;
    00161    }
    00162    if(useplc) {
    00163        plc_fillin(&tmp->plc, tmp->outbuf+tmp->tail, 160);
    00164        tmp->tail += 160;
    00165    }
    00166    return 0;
    00167   }
    00168
    00169   if ((tmp->tail + f->datalen) * 2 > sizeof(tmp->outbuf)) {
    00170    ast_log(LOG_WARNING, "Out of buffer space\n");
    00171    return -1;
    00172   }
    00173
    00174   /* Reset ssindex and signal to frame's specified values */
    00175   b = f->data;
    00176   for (x=0;x<f->datalen;x++)
    00177    tmp->outbuf[tmp->tail + x] = AST_MULAW(b[x]);
    00178
    00179   if(useplc) plc_rx(&tmp->plc, tmp->outbuf+tmp->tail, f->datalen);
    00180
    00181   tmp->tail += f->datalen;
    00182   return 0;
    00183 }
    00184
    00185 /*
    00186  * ulawToLin_FrameOut
    00187  *  Convert 4-bit ulaw encoded signals to 16-bit signed linear.
    00188  *
    00189  * Results:
    00190  *  Converted signals are placed in tmp->f.data, tmp->f.datalen
    00191  *  and tmp->f.samples are calculated.
    00192  *
    00193  * Side effects:
    00194  *  None.
    00195  */
    00196
    00197 static struct ast_frame *
    00198 ulawtolin_frameout (struct ast_translator_pvt *pvt)
    00199 {
    00200   struct ulaw_decoder_pvt *tmp = (struct ulaw_decoder_pvt *) pvt;
    00201
    00202   if (!tmp->tail)
    00203     return NULL;
    00204
    00205   tmp->f.frametype = AST_FRAME_VOICE;
    00206   tmp->f.subclass = AST_FORMAT_SLINEAR;
    00207   tmp->f.datalen = tmp->tail *2;
    00208   tmp->f.samples = tmp->tail;
    00209   tmp->f.mallocd = 0;
    00210   tmp->f.offset = AST_FRIENDLY_OFFSET;
    00211   tmp->f.src = __PRETTY_FUNCTION__;
    00212   tmp->f.data = tmp->outbuf;
    00213   tmp->tail = 0;
    00214   return &tmp->f;
    00215 }
    00216
    00217 /*
    00218  * LinToulaw_FrameIn
    00219  *  Fill an input buffer with 16-bit signed linear PCM values.
    00220  *
    00221  * Results:
    00222  *  None.
    00223  *
    00224  * Side effects:
    00225  *  tmp->tail is number of signal values in the input buffer.
    00226  */
    00227
    00228 static int
    00229 lintoulaw_framein (struct ast_translator_pvt *pvt, struct ast_frame *f)
    00230 {
    00231   struct ulaw_encoder_pvt *tmp = (struct ulaw_encoder_pvt *) pvt;
    00232   int x;
    00233   short *s;
    00234   if (tmp->tail + f->datalen/2 >= sizeof(tmp->outbuf))
    00235     {
    00236       ast_log (LOG_WARNING, "Out of buffer space\n");
    00237       return -1;
    00238     }
    00239   s = f->data;
    00240   for (x=0;x<f->datalen/2;x++)
    00241    tmp->outbuf[x+tmp->tail] = AST_LIN2MU(s[x]);
    00242   tmp->tail += f->datalen/2;
    00243   return 0;
    00244 }
    00245
    00246 /*
    00247  * LinToulaw_FrameOut
    00248  *  Convert a buffer of raw 16-bit signed linear PCM to a buffer
    00249  *  of 4-bit ulaw packed two to a byte (Big Endian).
    00250  *
    00251  * Results:
    00252  *  Foo
    00253  *
    00254  * Side effects:
    00255  *  Leftover inbuf data gets packed, tail gets updated.
    00256  */
    00257
    00258 static struct ast_frame *
    00259 lintoulaw_frameout (struct ast_translator_pvt *pvt)
    00260 {
    00261   struct ulaw_encoder_pvt *tmp = (struct ulaw_encoder_pvt *) pvt;
    00262
    00263   if (tmp->tail) {
    00264      tmp->f.frametype = AST_FRAME_VOICE;
    00265      tmp->f.subclass = AST_FORMAT_ULAW;
    00266      tmp->f.samples = tmp->tail;
    00267      tmp->f.mallocd = 0;
    00268      tmp->f.offset = AST_FRIENDLY_OFFSET;
    00269      tmp->f.src = __PRETTY_FUNCTION__;
    00270      tmp->f.data = tmp->outbuf;
    00271      tmp->f.datalen = tmp->tail;
    00272      tmp->tail = 0;
    00273      return &tmp->f;
    00274    } else return NULL;
    00275 }
    00276
    00277
    00278 /*
    00279  * ulawToLin_Sample
    00280  */
    00281
    00282 static struct ast_frame *
    00283 ulawtolin_sample (void)
    00284 {
    00285   static struct ast_frame f;
    00286   f.frametype = AST_FRAME_VOICE;
    00287   f.subclass = AST_FORMAT_ULAW;
    00288   f.datalen = sizeof (ulaw_slin_ex);
    00289   f.samples = sizeof(ulaw_slin_ex);
    00290   f.mallocd = 0;
    00291   f.offset = 0;
    00292   f.src = __PRETTY_FUNCTION__;
    00293   f.data = ulaw_slin_ex;
    00294   return &f;
    00295 }
    00296
    00297 /*
    00298  * LinToulaw_Sample
    00299  */
    00300
    00301 static struct ast_frame *
    00302 lintoulaw_sample (void)
    00303 {
    00304   static struct ast_frame f;
    00305   f.frametype = AST_FRAME_VOICE;
    00306   f.subclass = AST_FORMAT_SLINEAR;
    00307   f.datalen = sizeof (slin_ulaw_ex);
    00308   /* Assume 8000 Hz */
    00309   f.samples = sizeof (slin_ulaw_ex) / 2;
    00310   f.mallocd = 0;
    00311   f.offset = 0;
    00312   f.src = __PRETTY_FUNCTION__;
    00313   f.data = slin_ulaw_ex;
    00314   return &f;
    00315 }
    00316
    00317 /*
    00318  * ulaw_Destroy
    00319  *  Destroys a private workspace.
    00320  *
    00321  * Results:
    00322  *  It's gone!
    00323  *
    00324  * Side effects:
    00325  *  None.
    00326  */
    00327
    00328 static void
    00329 ulaw_destroy (struct ast_translator_pvt *pvt)
    00330 {
    00331   free (pvt);
    00332   localusecnt--;
    00333   ast_update_use_count ();
    00334 }
    00335
    00336 /*
    00337  * The complete translator for ulawToLin.
    00338  */
    00339
    00340 static struct ast_translator ulawtolin = {
    00341   "ulawtolin",
    00342   AST_FORMAT_ULAW,
    00343   AST_FORMAT_SLINEAR,
    00344   ulawtolin_new,
    00345   ulawtolin_framein,
    00346   ulawtolin_frameout,
    00347   ulaw_destroy,
    00348   /* NULL */
    00349   ulawtolin_sample
    00350 };
    00351
    00352 /*
    00353  * The complete translator for LinToulaw.
    00354  */
    00355
    00356 static struct ast_translator lintoulaw = {
    00357   "lintoulaw",
    00358   AST_FORMAT_SLINEAR,
    00359   AST_FORMAT_ULAW,
    00360   lintoulaw_new,
    00361   lintoulaw_framein,
    00362   lintoulaw_frameout,
    00363   ulaw_destroy,
    00364   /* NULL */
    00365   lintoulaw_sample
    00366 };
    00367
    00368 static void
    00369 parse_config(void)
    00370 {
    00371   struct ast_config *cfg;
    00372   struct ast_variable *var;
    00373   if ((cfg = ast_config_load("codecs.conf"))) {
    00374     if ((var = ast_variable_browse(cfg, "plc"))) {
    00375       while (var) {
    00376    if (!strcasecmp(var->name, "genericplc")) {
    00377      useplc = ast_true(var->value) ? 1 : 0;
    00378      if (option_verbose > 2)
    00379        ast_verbose(VERBOSE_PREFIX_3 "codec_ulaw: %susing generic PLC\n", useplc ? "" : "not ");
    00380    }
    00381    var = var->next;
    00382       }
    00383     }
    00384     ast_config_destroy(cfg);
    00385   }
    00386 }
    00387
    00388 int
    00389 reload(void)
    00390 {
    00391   parse_config();
    00392   return 0;
    00393 }
    00394
    00395
    00396 int
    00397 unload_module (void)
    00398 {
    00399   int res;
    00400   ast_mutex_lock (&localuser_lock);
    00401   res = ast_unregister_translator (&lintoulaw);
    00402   if (!res)
    00403     res = ast_unregister_translator (&ulawtolin);
    00404   if (localusecnt)
    00405     res = -1;
    00406   ast_mutex_unlock (&localuser_lock);
    00407   return res;
    00408 }
    00409
    00410 int
    00411 load_module (void)
    00412 {
    00413   int res;
    00414   parse_config();
    00415   res = ast_register_translator (&ulawtolin);
    00416   if (!res)
    00417     res = ast_register_translator (&lintoulaw);
    00418   else
    00419     ast_unregister_translator (&ulawtolin);
    00420   return res;
    00421 }
    00422
    00423 /*
    00424  * Return a description of this module.
    00425  */
    00426
    00427 char *
    00428 description (void)
    00429 {
    00430   return tdesc;
    00431 }
    00432
    00433 int
    00434 usecount (void)
    00435 {
    00436   int res;
    00437   STANDARD_USECOUNT (res);
    00438   return res;
    00439 }
    00440
    00441 char *
    00442 key ()
    00443 {
    00444   return ASTERISK_GPL_KEY;
    00445 }