#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/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 |
Definition in file codec_gsm.c.
#define gsm_coder_pvt ast_translator_pvt |
AST_MUTEX_DEFINE_STATIC | ( | localuser_lock | ) |
char* description | ( | void | ) |
Provides a description of the 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] |
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] |
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] |
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; }
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] |
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] |
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.
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.
Definition at line 325 of file codec_gsm.c.
References ast_register_translator(), ast_unregister_translator(), gsmtolin, lintogsm, 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, option_verbose, 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.
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).
Definition at line 312 of file codec_gsm.c.
References ast_mutex_lock(), ast_mutex_unlock(), ast_unregister_translator(), gsmtolin, and lintogsm.
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.
Definition at line 342 of file codec_gsm.c.
References STANDARD_USECOUNT.
00343 { 00344 int res; 00345 STANDARD_USECOUNT(res); 00346 return res; 00347 }
struct ast_translator gsmtolin [static] |
struct ast_translator lintogsm [static] |
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.