Asterisk - The Open Source Telephony Project  GIT-master-0190e70
codec_gsm.c
Go to the documentation of this file.
1 /*
2  * Asterisk -- An open source telephony toolkit.
3  *
4  * The GSM code is from TOAST. Copyright information for that package is available
5  * in the GSM directory.
6  *
7  * Copyright (C) 1999 - 2005, Digium, Inc.
8  *
9  * Mark Spencer <markster@digium.com>
10  *
11  * See http://www.asterisk.org for more information about
12  * the Asterisk project. Please do not directly contact
13  * any of the maintainers of this project for assistance;
14  * the project provides a web site, mailing lists and IRC
15  * channels for your use.
16  *
17  * This program is free software, distributed under the terms of
18  * the GNU General Public License Version 2. See the LICENSE file
19  * at the top of the source tree.
20  */
21 
22 /*! \file
23  *
24  * \brief Translate between signed linear and Global System for Mobile Communications (GSM)
25  *
26  * \ingroup codecs
27  */
28 
29 /*** MODULEINFO
30  <depend>gsm</depend>
31  <support_level>core</support_level>
32  ***/
33 
34 #include "asterisk.h"
35 
36 #include "asterisk/translate.h"
37 #include "asterisk/config.h"
38 #include "asterisk/module.h"
39 #include "asterisk/utils.h"
40 #include "asterisk/linkedlists.h"
41 
42 #ifdef HAVE_GSM_HEADER
43 #include "gsm.h"
44 #elif defined(HAVE_GSM_GSM_HEADER)
45 #include <gsm/gsm.h>
46 #endif
47 
48 #include "../formats/msgsm.h"
49 
50 #define BUFFER_SAMPLES 8000
51 #define GSM_SAMPLES 160
52 #define GSM_FRAME_LEN 33
53 #define MSGSM_FRAME_LEN 65
54 
55 /* Sample frame data */
56 #include "asterisk/slin.h"
57 #include "ex_gsm.h"
58 
59 struct gsm_translator_pvt { /* both gsm2lin and lin2gsm */
61  int16_t buf[BUFFER_SAMPLES]; /* lin2gsm, temporary storage */
62 };
63 
64 static int gsm_new(struct ast_trans_pvt *pvt)
65 {
66  struct gsm_translator_pvt *tmp = pvt->pvt;
67 
68  return (tmp->gsm = gsm_create()) ? 0 : -1;
69 }
70 
71 /*! \brief decode and store in outbuf. */
72 static int gsmtolin_framein(struct ast_trans_pvt *pvt, struct ast_frame *f)
73 {
74  struct gsm_translator_pvt *tmp = pvt->pvt;
75  int x;
76  int16_t *dst = pvt->outbuf.i16;
77  /* guess format from frame len. 65 for MSGSM, 33 for regular GSM */
78  int flen = (f->datalen % MSGSM_FRAME_LEN == 0) ?
80 
81  for (x=0; x < f->datalen; x += flen) {
82  unsigned char data[2 * GSM_FRAME_LEN];
83  unsigned char *src;
84  int len;
85  if (flen == MSGSM_FRAME_LEN) {
86  len = 2*GSM_SAMPLES;
87  src = data;
88  /* Translate MSGSM format to Real GSM format before feeding in */
89  /* XXX what's the point here! we should just work
90  * on the full format.
91  */
92  conv65(f->data.ptr + x, data);
93  } else {
94  len = GSM_SAMPLES;
95  src = f->data.ptr + x;
96  }
97  /* XXX maybe we don't need to check */
98  if (pvt->samples + len > BUFFER_SAMPLES) {
99  ast_log(LOG_WARNING, "Out of buffer space\n");
100  return -1;
101  }
102  if (gsm_decode(tmp->gsm, src, dst + pvt->samples)) {
103  ast_log(LOG_WARNING, "Invalid GSM data (1)\n");
104  return -1;
105  }
106  pvt->samples += GSM_SAMPLES;
107  pvt->datalen += 2 * GSM_SAMPLES;
108  if (flen == MSGSM_FRAME_LEN) {
109  if (gsm_decode(tmp->gsm, data + GSM_FRAME_LEN, dst + pvt->samples)) {
110  ast_log(LOG_WARNING, "Invalid GSM data (2)\n");
111  return -1;
112  }
113  pvt->samples += GSM_SAMPLES;
114  pvt->datalen += 2 * GSM_SAMPLES;
115  }
116  }
117  return 0;
118 }
119 
120 /*! \brief store samples into working buffer for later decode */
121 static int lintogsm_framein(struct ast_trans_pvt *pvt, struct ast_frame *f)
122 {
123  struct gsm_translator_pvt *tmp = pvt->pvt;
124 
125  /* XXX We should look at how old the rest of our stream is, and if it
126  is too old, then we should overwrite it entirely, otherwise we can
127  get artifacts of earlier talk that do not belong */
128  if (pvt->samples + f->samples > BUFFER_SAMPLES) {
129  ast_log(LOG_WARNING, "Out of buffer space\n");
130  return -1;
131  }
132  memcpy(tmp->buf + pvt->samples, f->data.ptr, f->datalen);
133  pvt->samples += f->samples;
134  return 0;
135 }
136 
137 /*! \brief encode and produce a frame */
138 static struct ast_frame *lintogsm_frameout(struct ast_trans_pvt *pvt)
139 {
140  struct gsm_translator_pvt *tmp = pvt->pvt;
141  struct ast_frame *result = NULL;
142  struct ast_frame *last = NULL;
143  int samples = 0; /* output samples */
144 
145  while (pvt->samples >= GSM_SAMPLES) {
146  struct ast_frame *current;
147 
148  /* Encode a frame of data */
149  gsm_encode(tmp->gsm, tmp->buf + samples, (gsm_byte *) pvt->outbuf.c);
150  samples += GSM_SAMPLES;
151  pvt->samples -= GSM_SAMPLES;
152 
154  if (!current) {
155  continue;
156  } else if (last) {
157  AST_LIST_NEXT(last, frame_list) = current;
158  } else {
159  result = current;
160  }
161  last = current;
162  }
163 
164  /* Move the data at the end of the buffer to the front */
165  if (samples) {
166  memmove(tmp->buf, tmp->buf + samples, pvt->samples * 2);
167  }
168 
169  return result;
170 }
171 
172 static void gsm_destroy_stuff(struct ast_trans_pvt *pvt)
173 {
174  struct gsm_translator_pvt *tmp = pvt->pvt;
175  if (tmp->gsm)
176  gsm_destroy(tmp->gsm);
177 }
178 
179 static struct ast_translator gsmtolin = {
180  .name = "gsmtolin",
181  .src_codec = {
182  .name = "gsm",
183  .type = AST_MEDIA_TYPE_AUDIO,
184  .sample_rate = 8000,
185  },
186  .dst_codec = {
187  .name = "slin",
188  .type = AST_MEDIA_TYPE_AUDIO,
189  .sample_rate = 8000,
190  },
191  .format = "slin",
192  .newpvt = gsm_new,
193  .framein = gsmtolin_framein,
194  .destroy = gsm_destroy_stuff,
195  .sample = gsm_sample,
196  .buffer_samples = BUFFER_SAMPLES,
197  .buf_size = BUFFER_SAMPLES * 2,
198  .desc_size = sizeof (struct gsm_translator_pvt ),
199 };
200 
201 static struct ast_translator lintogsm = {
202  .name = "lintogsm",
203  .src_codec = {
204  .name = "slin",
205  .type = AST_MEDIA_TYPE_AUDIO,
206  .sample_rate = 8000,
207  },
208  .dst_codec = {
209  .name = "gsm",
210  .type = AST_MEDIA_TYPE_AUDIO,
211  .sample_rate = 8000,
212  },
213  .format = "gsm",
214  .newpvt = gsm_new,
215  .framein = lintogsm_framein,
216  .frameout = lintogsm_frameout,
217  .destroy = gsm_destroy_stuff,
218  .sample = slin8_sample,
219  .desc_size = sizeof (struct gsm_translator_pvt ),
220  .buf_size = (BUFFER_SAMPLES * GSM_FRAME_LEN + GSM_SAMPLES - 1)/GSM_SAMPLES,
221 };
222 
223 static int unload_module(void)
224 {
225  int res;
226 
227  res = ast_unregister_translator(&lintogsm);
228  res |= ast_unregister_translator(&gsmtolin);
229 
230  return res;
231 }
232 
233 static int load_module(void)
234 {
235  int res;
236 
237  res = ast_register_translator(&gsmtolin);
238  res |= ast_register_translator(&lintogsm);
239 
240  if (res) {
241  unload_module();
243  }
244 
246 }
247 
249  .support_level = AST_MODULE_SUPPORT_CORE,
250  .load = load_module,
251  .unload = unload_module,
252 );
struct ast_frame * ast_trans_frameout(struct ast_trans_pvt *pvt, int datalen, int samples)
generic frameout function
Definition: translate.c:432
int datalen
actual space used in outbuf
Definition: translate.h:218
Asterisk main include file. File version handling, generic pbx functions.
int16_t buf[BUFFER_SAMPLES]
Definition: codec_gsm.c:61
Descriptor of a translator.
Definition: translate.h:137
short int16_t
Definition: db.h:59
union ast_trans_pvt::@321 outbuf
static struct ast_translator lintogsm
Definition: codec_gsm.c:201
Support for translation of data formats. translate.c.
#define LOG_WARNING
Definition: logger.h:274
union ast_frame::@257 data
static int tmp()
Definition: bt_open.c:389
#define GSM_FRAME_LEN
Definition: codec_gsm.c:52
#define AST_LIST_NEXT(elm, field)
Returns the next entry in the list after the given entry.
Definition: linkedlists.h:438
static int unload_module(void)
Definition: codec_gsm.c:223
static struct ast_frame * lintogsm_frameout(struct ast_trans_pvt *pvt)
encode and produce a frame
Definition: codec_gsm.c:138
unsigned char gsm_byte
Definition: gsm.h:41
static void gsm_destroy_stuff(struct ast_trans_pvt *pvt)
Definition: codec_gsm.c:172
static struct ast_frame * slin8_sample(void)
Definition: slin.h:64
#define NULL
Definition: resample.c:96
void * pvt
Definition: translate.h:219
static int gsmtolin_framein(struct ast_trans_pvt *pvt, struct ast_frame *f)
decode and store in outbuf.
Definition: codec_gsm.c:72
int16_t * i16
Definition: translate.h:223
Utility functions.
Configuration File Parser.
static struct ast_translator gsmtolin
Definition: codec_gsm.c:179
#define ast_log
Definition: astobj2.c:42
#define MSGSM_FRAME_LEN
Definition: codec_gsm.c:53
struct sla_ringing_trunk * last
Definition: app_meetme.c:1092
#define ast_register_translator(t)
See __ast_register_translator()
Definition: translate.h:257
int ast_unregister_translator(struct ast_translator *t)
Unregister a translator Unregisters the given tranlator.
Definition: translate.c:1327
A set of macros to manage forward-linked lists.
static void conv65(wav_byte *c, gsm_byte *d)
Definition: msgsm.h:457
Default structure for translators, with the basic fields and buffers, all allocated as part of the sa...
Definition: translate.h:213
static int len(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t buflen)
static int gsm_new(struct ast_trans_pvt *pvt)
Definition: codec_gsm.c:64
#define GSM_SAMPLES
Definition: codec_gsm.c:51
#define BUFFER_SAMPLES
Definition: codec_gsm.c:50
Module has failed to load, may be in an inconsistent state.
Definition: module.h:78
AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_GLOBAL_SYMBOLS|AST_MODFLAG_LOAD_ORDER, "HTTP Phone Provisioning",.support_level=AST_MODULE_SUPPORT_EXTENDED,.load=load_module,.unload=unload_module,.reload=reload,.load_pri=AST_MODPRI_CHANNEL_DEPEND,.requires="http",)
static PGresult * result
Definition: cel_pgsql.c:88
Data structure associated with a single frame of data.
static int lintogsm_framein(struct ast_trans_pvt *pvt, struct ast_frame *f)
store samples into working buffer for later decode
Definition: codec_gsm.c:121
8-bit raw data
static int load_module(void)
Definition: codec_gsm.c:233
#define ASTERISK_GPL_KEY
The text the key() function should return.
Definition: module.h:46
Asterisk module definitions.
char name[80]
Definition: translate.h:138
static struct ast_frame * gsm_sample(void)
Definition: ex_gsm.h:17