Asterisk.org: Developer Documentation (28 Oct 2009)

Wed Oct 28 15:48:43 2009

## Asterisk developer's documentation

# codec_gsm.c File Reference

Translate between signed linear and Global System for Mobile Communications (GSM). More...

`#include <fcntl.h>`
`#include <stdlib.h>`
`#include <unistd.h>`
`#include <netinet/in.h>`
`#include <string.h>`
`#include <stdio.h>`
`#include "asterisk.h"`
`#include "asterisk/lock.h"`
`#include "asterisk/translate.h"`
`#include "asterisk/config.h"`
`#include "asterisk/options.h"`
`#include "asterisk/module.h"`
`#include "asterisk/logger.h"`
`#include "asterisk/channel.h"`
`#include "gsm/inc/gsm.h"`
`#include "../formats/msgsm.h"`
`#include "slin_gsm_ex.h"`
`#include "gsm_slin_ex.h"`

Include dependency graph for codec_gsm.c:

Go to the source code of this file.

## Data Structures

struct | ast_translator_pvt

## Defines

#define | gsm_coder_pvt ast_translator_pvt

## Functions

| AST_MUTEX_DEFINE_STATIC (localuser_lock)
char * | description (void)
| Provides a description of the module.
static void | gsm_destroy_stuff (struct ast_translator_pvt *pvt)
static struct ast_translator_pvt * | gsm_new (void)
static int | gsmtolin_framein (struct ast_translator_pvt *tmp, struct ast_frame *f)
static struct ast_frame * | gsmtolin_frameout (struct ast_translator_pvt *tmp)
static struct ast_frame * | gsmtolin_sample (void)
char * | key ()
| Returns the ASTERISK_GPL_KEY.
static int | lintogsm_framein (struct ast_translator_pvt *tmp, struct ast_frame *f)
static struct ast_frame * | lintogsm_frameout (struct ast_translator_pvt *tmp)
static struct ast_frame * | lintogsm_sample (void)
int | load_module (void)
| Initialize the module.
static void | parse_config (void)
int | reload (void)
| Reload stuff.
int | unload_module (void)
| Cleanup all module structures, sockets, etc.
int | usecount (void)
| Provides a usecount.

## Variables

static struct ast_translator | gsmtolin
static struct ast_translator | lintogsm
static int | localusecnt = 0
static char * | tdesc = "GSM/PCM16 (signed linear) Codec Translator"
static int | useplc = 0

## Detailed Description

Translate between signed linear and Global System for Mobile Communications (GSM).

Definition in file codec_gsm.c.

## Define Documentation

#define gsm_coder_pvt ast_translator_pvt

Definition at line 75 of file codec_gsm.c.

Referenced by gsm_new().

## Function Documentation

AST_MUTEX_DEFINE_STATIC | ( | localuser_lock |  | ) |

char* description | ( | void |  | ) |

Provides a description of the module.

Returns:
  a short description of your module

Definition at line 337 of file codec_gsm.c.

    00338 {
    00339    return tdesc;
    00340 }

static void gsm_destroy_stuff | ( | struct ast_translator_pvt * | pvt | ) | `[static]`

Definition at line 258 of file codec_gsm.c.

References free, and ast_translator_pvt::gsm.

    00259 {
    00260    if (pvt->gsm)
    00261       gsm_destroy(pvt->gsm);
    00262    free(pvt);
    00263    localusecnt--;
    00264 }

static struct ast_translator_pvt* gsm_new | ( | void |  | ) | `[static, read]`

Definition at line 77 of file codec_gsm.c.

References free, gsm_coder_pvt, malloc, and plc_init().

    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 }

static int gsmtolin_framein | ( | struct ast_translator_pvt * | tmp,
|  | struct ast_frame * | f |
| ) |  |  | `[static]`

Definition at line 144 of file codec_gsm.c.

References ast_log(), ast_translator_pvt::buf, conv65(), ast_frame::data, ast_frame::datalen, ast_translator_pvt::gsm, LOG_WARNING, ast_translator_pvt::plc, plc_fillin(), plc_rx(), ast_frame::src, and ast_translator_pvt::tail.

    00145 {
    00146    /* Assuming there's space left, decode into the current buffer at
    00147       the tail location.  Read in as many frames as there are */
    00148    int x;
    00149    unsigned char data[66];
    00150    int msgsm=0;
    00151
    00152    if(f->datalen == 0) { /* perform PLC with nominal framesize of 20ms/160 samples */
    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          /* Translate MSGSM format to Real GSM format before feeding in */
    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    /* just add the last 20ms frame; there must have been at least one */
    00206    if(useplc) plc_rx(&tmp->plc, tmp->buf+tmp->tail-160, 160);
    00207
    00208    return 0;
    00209 }

static struct ast_frame* gsmtolin_frameout | ( | struct ast_translator_pvt * | tmp | ) | `[static, read]`

Definition at line 123 of file codec_gsm.c.

References AST_FORMAT_SLINEAR, AST_FRAME_VOICE, AST_FRIENDLY_OFFSET, ast_translator_pvt::buf, ast_frame::data, ast_frame::datalen, ast_translator_pvt::f, ast_frame::frametype, ast_frame::mallocd, ast_frame::offset, ast_frame::samples, ast_frame::src, ast_frame::subclass, and ast_translator_pvt::tail.

    00124 {
    00125    if (!tmp->tail)
    00126       return NULL;
    00127    /* Signed linear is no particular frame size, so just send whatever
    00128       we have in the buffer in one lump sum */
    00129    tmp->f.frametype = AST_FRAME_VOICE;
    00130    tmp->f.subclass = AST_FORMAT_SLINEAR;
    00131    tmp->f.datalen = tmp->tail * 2;
    00132    /* Assume 8000 Hz */
    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    /* Reset tail pointer */
    00139    tmp->tail = 0;
    00140
    00141    return &tmp->f;
    00142 }

static struct ast_frame* gsmtolin_sample | ( | void |  | ) | `[static, read]`

Definition at line 108 of file codec_gsm.c.

References AST_FORMAT_GSM, AST_FRAME_VOICE, ast_frame::data, ast_frame::datalen, ast_frame::frametype, gsm_slin_ex, ast_frame::mallocd, ast_frame::offset, ast_frame::samples, ast_frame::src, and ast_frame::subclass.

    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    /* All frames are 20 ms long */
    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 }

char* key | ( | void |  | ) |

Returns the ASTERISK_GPL_KEY.

This returns the ASTERISK_GPL_KEY, signifiying that you agree to the terms of the GPL stated in the ASTERISK_GPL_KEY. Your module will not load if it does not return the EXACT message:

     char *key(void) {
             return ASTERISK_GPL_KEY;
     }

Returns:
  ASTERISK_GPL_KEY

Definition at line 349 of file codec_gsm.c.

References ASTERISK_GPL_KEY.

    00350 {
    00351    return ASTERISK_GPL_KEY;
    00352 }

static int lintogsm_framein | ( | struct ast_translator_pvt * | tmp,
|  | struct ast_frame * | f |
| ) |  |  | `[static]`

Definition at line 211 of file codec_gsm.c.

References ast_log(), ast_translator_pvt::buf, ast_frame::data, ast_frame::datalen, LOG_WARNING, and ast_translator_pvt::tail.

    00212 {
    00213    /* Just add the frames to our stream */
    00214    /* XXX We should look at how old the rest of our stream is, and if it
    00215       is too old, then we should overwrite it entirely, otherwise we can
    00216       get artifacts of earlier talk that do not belong */
    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 }

static struct ast_frame* lintogsm_frameout | ( | struct ast_translator_pvt * | tmp | ) | `[static, read]`

Definition at line 227 of file codec_gsm.c.

References AST_FORMAT_GSM, AST_FRAME_VOICE, AST_FRIENDLY_OFFSET, ast_log(), ast_translator_pvt::buf, ast_frame::data, ast_frame::datalen, ast_translator_pvt::f, ast_frame::frametype, ast_translator_pvt::gsm, LOG_WARNING, ast_frame::mallocd, ast_frame::offset, ast_translator_pvt::outbuf, ast_frame::samples, ast_frame::src, ast_frame::subclass, and ast_translator_pvt::tail.

    00228 {
    00229    int x=0;
    00230    /* We can't work on anything less than a frame in size */
    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       /* Encode a frame of data */
    00245       gsm_encode(tmp->gsm, tmp->buf, ((gsm_byte *) tmp->outbuf) + (x * 33));
    00246       /* Assume 8000 Hz -- 20 ms */
    00247       tmp->tail -= 160;
    00248       /* Move the data at the end of the buffer to the front */
    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 }

static struct ast_frame* lintogsm_sample | ( | void |  | ) | `[static, read]`

Definition at line 93 of file codec_gsm.c.

References AST_FORMAT_SLINEAR, AST_FRAME_VOICE, ast_frame::data, ast_frame::datalen, ast_frame::frametype, ast_frame::mallocd, ast_frame::offset, ast_frame::samples, slin_gsm_ex, ast_frame::src, and ast_frame::subclass.

    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    /* Assume 8000 Hz */
    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 }

int load_module | ( | void |  | ) |

Initialize the module.

This function is called at module load time. Put all code in here that needs to set up your module's hardware, software, registrations, etc.

Returns:
  This function should return 0 on success and non-zero on failure. If the module is not loaded successfully, Asterisk will call its unload_module() function.

Initialize the Agents module. This function is being called by Asterisk when loading the module. Among other thing it registers applications, cli commands and reads the cofiguration file.

Returns:
  int Always 0.

TE STUFF END

Definition at line 325 of file codec_gsm.c.

References ast_register_translator(), ast_unregister_translator(), and parse_config().

    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 }

static void parse_config | ( | void |  | ) | `[static]`

Definition at line 287 of file codec_gsm.c.

References ast_config_destroy(), ast_config_load(), ast_true(), ast_variable_browse(), ast_verbose(), cfg, ast_variable::name, ast_variable::next, option_verbose, ast_variable::value, var, and VERBOSE_PREFIX_3.

    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 }

int reload | ( | void |  | ) |

Reload stuff.

This function is where any reload routines take place. Re-read config files, change signalling, whatever is appropriate on a reload.

Returns:
  The return value is not used.

Definition at line 306 of file codec_gsm.c.

References parse_config().

    00307 {
    00308    parse_config();
    00309    return 0;
    00310 }

int unload_module | ( | void |  | ) |

Cleanup all module structures, sockets, etc.

This is called at exit. Any registrations and memory allocations need to be unregistered and free'd here. Nothing else will do these for you (until exit).

Returns:
  Zero on success, or non-zero on error.

Definition at line 312 of file codec_gsm.c.

References ast_mutex_lock(), ast_mutex_unlock(), and ast_unregister_translator().

    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 }

int usecount | ( | void |  | ) |

Provides a usecount.

This function will be called by various parts of asterisk. Basically, all it has to do is to return a usecount when called. You will need to maintain your usecount within the module somewhere. The usecount should be how many channels provided by this module are in use.

Returns:
  The module's usecount.

Definition at line 342 of file codec_gsm.c.

References STANDARD_USECOUNT.

    00343 {
    00344    int res;
    00345    STANDARD_USECOUNT(res);
    00346    return res;
    00347 }

## Variable Documentation

struct ast_translator gsmtolin`[static]`

Definition at line 266 of file codec_gsm.c.

struct ast_translator lintogsm`[static]`

Definition at line 276 of file codec_gsm.c.

int localusecnt = 0`[static]`

Definition at line 56 of file codec_gsm.c.

char* tdesc = "GSM/PCM16 (signed linear) Codec Translator"`[static]`

Definition at line 58 of file codec_gsm.c.

int useplc = 0`[static]`

Definition at line 60 of file codec_gsm.c.