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
00027
00028
00029
00030
00031
00032
00033 #include "asterisk.h"
00034
00035 ASTERISK_FILE_VERSION(__FILE__, "$Revision: 125386 $")
00036
00037 #include "asterisk/translate.h"
00038 #include "asterisk/config.h"
00039 #include "asterisk/module.h"
00040 #include "asterisk/utils.h"
00041
00042 #ifdef HAVE_GSM_HEADER
00043 #include "gsm.h"
00044 #elif defined(HAVE_GSM_GSM_HEADER)
00045 #include <gsm/gsm.h>
00046 #endif
00047
00048 #include "../formats/msgsm.h"
00049
00050
00051 #include "slin_gsm_ex.h"
00052 #include "gsm_slin_ex.h"
00053
00054 #define BUFFER_SAMPLES 8000
00055 #define GSM_SAMPLES 160
00056 #define GSM_FRAME_LEN 33
00057 #define MSGSM_FRAME_LEN 65
00058
00059 struct gsm_translator_pvt {
00060 gsm gsm;
00061 int16_t buf[BUFFER_SAMPLES];
00062 };
00063
00064 static int gsm_new(struct ast_trans_pvt *pvt)
00065 {
00066 struct gsm_translator_pvt *tmp = pvt->pvt;
00067
00068 return (tmp->gsm = gsm_create()) ? 0 : -1;
00069 }
00070
00071 static struct ast_frame *lintogsm_sample(void)
00072 {
00073 static struct ast_frame f;
00074 f.frametype = AST_FRAME_VOICE;
00075 f.subclass = AST_FORMAT_SLINEAR;
00076 f.datalen = sizeof(slin_gsm_ex);
00077
00078 f.samples = sizeof(slin_gsm_ex)/2;
00079 f.mallocd = 0;
00080 f.offset = 0;
00081 f.src = __PRETTY_FUNCTION__;
00082 f.data.ptr = slin_gsm_ex;
00083 return &f;
00084 }
00085
00086 static struct ast_frame *gsmtolin_sample(void)
00087 {
00088 static struct ast_frame f;
00089 f.frametype = AST_FRAME_VOICE;
00090 f.subclass = AST_FORMAT_GSM;
00091 f.datalen = sizeof(gsm_slin_ex);
00092
00093 f.samples = GSM_SAMPLES;
00094 f.mallocd = 0;
00095 f.offset = 0;
00096 f.src = __PRETTY_FUNCTION__;
00097 f.data.ptr = gsm_slin_ex;
00098 return &f;
00099 }
00100
00101
00102 static int gsmtolin_framein(struct ast_trans_pvt *pvt, struct ast_frame *f)
00103 {
00104 struct gsm_translator_pvt *tmp = pvt->pvt;
00105 int x;
00106 int16_t *dst = pvt->outbuf.i16;
00107
00108 int flen = (f->datalen % MSGSM_FRAME_LEN == 0) ?
00109 MSGSM_FRAME_LEN : GSM_FRAME_LEN;
00110
00111 for (x=0; x < f->datalen; x += flen) {
00112 unsigned char data[2 * GSM_FRAME_LEN];
00113 unsigned char *src;
00114 int len;
00115 if (flen == MSGSM_FRAME_LEN) {
00116 len = 2*GSM_SAMPLES;
00117 src = data;
00118
00119
00120
00121
00122 conv65(f->data.ptr + x, data);
00123 } else {
00124 len = GSM_SAMPLES;
00125 src = f->data.ptr + x;
00126 }
00127
00128 if (pvt->samples + len > BUFFER_SAMPLES) {
00129 ast_log(LOG_WARNING, "Out of buffer space\n");
00130 return -1;
00131 }
00132 if (gsm_decode(tmp->gsm, src, dst + pvt->samples)) {
00133 ast_log(LOG_WARNING, "Invalid GSM data (1)\n");
00134 return -1;
00135 }
00136 pvt->samples += GSM_SAMPLES;
00137 pvt->datalen += 2 * GSM_SAMPLES;
00138 if (flen == MSGSM_FRAME_LEN) {
00139 if (gsm_decode(tmp->gsm, data + GSM_FRAME_LEN, dst + pvt->samples)) {
00140 ast_log(LOG_WARNING, "Invalid GSM data (2)\n");
00141 return -1;
00142 }
00143 pvt->samples += GSM_SAMPLES;
00144 pvt->datalen += 2 * GSM_SAMPLES;
00145 }
00146 }
00147 return 0;
00148 }
00149
00150
00151 static int lintogsm_framein(struct ast_trans_pvt *pvt, struct ast_frame *f)
00152 {
00153 struct gsm_translator_pvt *tmp = pvt->pvt;
00154
00155
00156
00157
00158 if (pvt->samples + f->samples > BUFFER_SAMPLES) {
00159 ast_log(LOG_WARNING, "Out of buffer space\n");
00160 return -1;
00161 }
00162 memcpy(tmp->buf + pvt->samples, f->data.ptr, f->datalen);
00163 pvt->samples += f->samples;
00164 return 0;
00165 }
00166
00167
00168 static struct ast_frame *lintogsm_frameout(struct ast_trans_pvt *pvt)
00169 {
00170 struct gsm_translator_pvt *tmp = pvt->pvt;
00171 int datalen = 0;
00172 int samples = 0;
00173
00174
00175 if (pvt->samples < GSM_SAMPLES)
00176 return NULL;
00177 while (pvt->samples >= GSM_SAMPLES) {
00178
00179 gsm_encode(tmp->gsm, tmp->buf + samples, (gsm_byte *) pvt->outbuf.c + datalen);
00180 datalen += GSM_FRAME_LEN;
00181 samples += GSM_SAMPLES;
00182 pvt->samples -= GSM_SAMPLES;
00183 }
00184
00185
00186 if (pvt->samples)
00187 memmove(tmp->buf, tmp->buf + samples, pvt->samples * 2);
00188
00189 return ast_trans_frameout(pvt, datalen, samples);
00190 }
00191
00192 static void gsm_destroy_stuff(struct ast_trans_pvt *pvt)
00193 {
00194 struct gsm_translator_pvt *tmp = pvt->pvt;
00195 if (tmp->gsm)
00196 gsm_destroy(tmp->gsm);
00197 }
00198
00199 static struct ast_translator gsmtolin = {
00200 .name = "gsmtolin",
00201 .srcfmt = AST_FORMAT_GSM,
00202 .dstfmt = AST_FORMAT_SLINEAR,
00203 .newpvt = gsm_new,
00204 .framein = gsmtolin_framein,
00205 .destroy = gsm_destroy_stuff,
00206 .sample = gsmtolin_sample,
00207 .buffer_samples = BUFFER_SAMPLES,
00208 .buf_size = BUFFER_SAMPLES * 2,
00209 .desc_size = sizeof (struct gsm_translator_pvt ),
00210 .plc_samples = GSM_SAMPLES,
00211 };
00212
00213 static struct ast_translator lintogsm = {
00214 .name = "lintogsm",
00215 .srcfmt = AST_FORMAT_SLINEAR,
00216 .dstfmt = AST_FORMAT_GSM,
00217 .newpvt = gsm_new,
00218 .framein = lintogsm_framein,
00219 .frameout = lintogsm_frameout,
00220 .destroy = gsm_destroy_stuff,
00221 .sample = lintogsm_sample,
00222 .desc_size = sizeof (struct gsm_translator_pvt ),
00223 .buf_size = (BUFFER_SAMPLES * GSM_FRAME_LEN + GSM_SAMPLES - 1)/GSM_SAMPLES,
00224 };
00225
00226
00227 static int parse_config(int reload)
00228 {
00229 struct ast_variable *var;
00230 struct ast_flags config_flags = { reload ? CONFIG_FLAG_FILEUNCHANGED : 0 };
00231 struct ast_config *cfg = ast_config_load("codecs.conf", config_flags);
00232 if (cfg == NULL)
00233 return 0;
00234 if (cfg == CONFIG_STATUS_FILEUNCHANGED)
00235 return 0;
00236 for (var = ast_variable_browse(cfg, "plc"); var; var = var->next) {
00237 if (!strcasecmp(var->name, "genericplc")) {
00238 gsmtolin.useplc = ast_true(var->value) ? 1 : 0;
00239 ast_verb(3, "codec_gsm: %susing generic PLC\n", gsmtolin.useplc ? "" : "not ");
00240 }
00241 }
00242 ast_config_destroy(cfg);
00243 return 0;
00244 }
00245
00246
00247 static int reload(void)
00248 {
00249 if (parse_config(1)) {
00250 return AST_MODULE_LOAD_DECLINE;
00251 }
00252 return AST_MODULE_LOAD_SUCCESS;
00253 }
00254
00255 static int unload_module(void)
00256 {
00257 int res;
00258
00259 res = ast_unregister_translator(&lintogsm);
00260 if (!res)
00261 res = ast_unregister_translator(&gsmtolin);
00262
00263 return res;
00264 }
00265
00266 static int load_module(void)
00267 {
00268 int res;
00269
00270 if (parse_config(0))
00271 return AST_MODULE_LOAD_DECLINE;
00272 res = ast_register_translator(&gsmtolin);
00273 if (!res)
00274 res=ast_register_translator(&lintogsm);
00275 else
00276 ast_unregister_translator(&gsmtolin);
00277 if (res)
00278 return AST_MODULE_LOAD_FAILURE;
00279 return AST_MODULE_LOAD_SUCCESS;
00280 }
00281
00282 AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_DEFAULT, "GSM Coder/Decoder",
00283 .load = load_module,
00284 .unload = unload_module,
00285 .reload = reload,
00286 );