Asterisk.org: Developer Documentation (28 Oct 2009)

Wed Oct 28 15:47:53 2009

## Asterisk developer's documentation

# codec_alaw.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_alaw.c - translate between signed linear and alaw
    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/alaw.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 = "A-law Coder/Decoder";
    00052
    00053 static int useplc = 0;
    00054
    00055 /* Sample frame data (Mu data is okay) */
    00056
    00057 #include "slin_ulaw_ex.h"
    00058 #include "ulaw_slin_ex.h"
    00059
    00060 /*!
    00061  * \brief Private workspace for translating signed linear signals to alaw.
    00062  */
    00063 struct alaw_encoder_pvt
    00064 {
    00065   struct ast_frame f;
    00066   char offset[AST_FRIENDLY_OFFSET];   /*!< Space to build offset */
    00067   unsigned char outbuf[BUFFER_SIZE];  /*!< Encoded alaw, two nibbles to a word */
    00068   int tail;
    00069 };
    00070
    00071 /*!
    00072  * \brief Private workspace for translating alaw signals to signed linear.
    00073  */
    00074 struct alaw_decoder_pvt
    00075 {
    00076   struct ast_frame f;
    00077   char offset[AST_FRIENDLY_OFFSET]; /* Space to build offset */
    00078   short outbuf[BUFFER_SIZE];  /* Decoded signed linear values */
    00079   int tail;
    00080   plc_state_t plc;
    00081 };
    00082
    00083 /*!
    00084  * \brief alawToLin_New
    00085  *  Create a new instance of alaw_decoder_pvt.
    00086  *
    00087  * Results:
    00088  *  Returns a pointer to the new instance.
    00089  *
    00090  * Side effects:
    00091  *  None.
    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  * \brief LinToalaw_New
    00111  *  Create a new instance of alaw_encoder_pvt.
    00112  *
    00113  * Results:
    00114  *  Returns a pointer to the new instance.
    00115  *
    00116  * Side effects:
    00117  *  None.
    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  * \brief alawToLin_FrameIn
    00136  *  Fill an input buffer with packed 4-bit alaw values if there is room
    00137  *  left.
    00138  *
    00139  * Results:
    00140  *  Foo
    00141  *
    00142  * Side effects:
    00143  *  tmp->tail is the number of packed values in the buffer.
    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) { /* perform PLC with nominal framesize of 20ms/160 samples */
    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   /* Reset ssindex and signal to frame's specified values */
    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  * \brief alawToLin_FrameOut
    00183  *  Convert 4-bit alaw encoded signals to 16-bit signed linear.
    00184  *
    00185  * Results:
    00186  *  Converted signals are placed in tmp->f.data, tmp->f.datalen
    00187  *  and tmp->f.samples are calculated.
    00188  *
    00189  * Side effects:
    00190  *  None.
    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  * \brief LinToalaw_FrameIn
    00214  *  Fill an input buffer with 16-bit signed linear PCM values.
    00215  *
    00216  * Results:
    00217  *  None.
    00218  *
    00219  * Side effects:
    00220  *  tmp->tail is number of signal values in the input buffer.
    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  * \brief LinToalaw_FrameOut
    00242  *  Convert a buffer of raw 16-bit signed linear PCM to a buffer
    00243  *  of 4-bit alaw packed two to a byte (Big Endian).
    00244  *
    00245  * Results:
    00246  *  Foo
    00247  *
    00248  * Side effects:
    00249  *  Leftover inbuf data gets packed, tail gets updated.
    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  * \brief alawToLin_Sample
    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  * \brief LinToalaw_Sample
    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   /* Assume 8000 Hz */
    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  * \brief alaw_Destroy
    00310  *  Destroys a private workspace.
    00311  *
    00312  * Results:
    00313  *  It's gone!
    00314  *
    00315  * Side effects:
    00316  *  None.
    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  * \brief The complete translator for alawToLin.
    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   /* NULL */
    00339   alawtolin_sample
    00340 };
    00341
    00342 /*!
    00343  * \brief The complete translator for LinToalaw.
    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   /* NULL */
    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  * Return a description of this module.
    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 }