Wed Jan 8 2020 09:49:46

Asterisk developer's documentation


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 ASTERISK_FILE_VERSION(__FILE__, "$Revision: 328209 $")
37 
38 #include "asterisk/translate.h"
39 #include "asterisk/config.h"
40 #include "asterisk/module.h"
41 #include "asterisk/utils.h"
42 
43 #ifdef HAVE_GSM_HEADER
44 #include "gsm.h"
45 #elif defined(HAVE_GSM_GSM_HEADER)
46 #include <gsm/gsm.h>
47 #endif
48 
49 #include "../formats/msgsm.h"
50 
51 #define BUFFER_SAMPLES 8000
52 #define GSM_SAMPLES 160
53 #define GSM_FRAME_LEN 33
54 #define MSGSM_FRAME_LEN 65
55 
56 /* Sample frame data */
57 #include "asterisk/slin.h"
58 #include "ex_gsm.h"
59 
60 struct gsm_translator_pvt { /* both gsm2lin and lin2gsm */
62  int16_t buf[BUFFER_SAMPLES]; /* lin2gsm, temporary storage */
63 };
64 
65 static int gsm_new(struct ast_trans_pvt *pvt)
66 {
67  struct gsm_translator_pvt *tmp = pvt->pvt;
68 
69  return (tmp->gsm = gsm_create()) ? 0 : -1;
70 }
71 
72 /*! \brief decode and store in outbuf. */
73 static int gsmtolin_framein(struct ast_trans_pvt *pvt, struct ast_frame *f)
74 {
75  struct gsm_translator_pvt *tmp = pvt->pvt;
76  int x;
77  int16_t *dst = pvt->outbuf.i16;
78  /* guess format from frame len. 65 for MSGSM, 33 for regular GSM */
79  int flen = (f->datalen % MSGSM_FRAME_LEN == 0) ?
81 
82  for (x=0; x < f->datalen; x += flen) {
83  unsigned char data[2 * GSM_FRAME_LEN];
84  unsigned char *src;
85  int len;
86  if (flen == MSGSM_FRAME_LEN) {
87  len = 2*GSM_SAMPLES;
88  src = data;
89  /* Translate MSGSM format to Real GSM format before feeding in */
90  /* XXX what's the point here! we should just work
91  * on the full format.
92  */
93  conv65(f->data.ptr + x, data);
94  } else {
95  len = GSM_SAMPLES;
96  src = f->data.ptr + x;
97  }
98  /* XXX maybe we don't need to check */
99  if (pvt->samples + len > BUFFER_SAMPLES) {
100  ast_log(LOG_WARNING, "Out of buffer space\n");
101  return -1;
102  }
103  if (gsm_decode(tmp->gsm, src, dst + pvt->samples)) {
104  ast_log(LOG_WARNING, "Invalid GSM data (1)\n");
105  return -1;
106  }
107  pvt->samples += GSM_SAMPLES;
108  pvt->datalen += 2 * GSM_SAMPLES;
109  if (flen == MSGSM_FRAME_LEN) {
110  if (gsm_decode(tmp->gsm, data + GSM_FRAME_LEN, dst + pvt->samples)) {
111  ast_log(LOG_WARNING, "Invalid GSM data (2)\n");
112  return -1;
113  }
114  pvt->samples += GSM_SAMPLES;
115  pvt->datalen += 2 * GSM_SAMPLES;
116  }
117  }
118  return 0;
119 }
120 
121 /*! \brief store samples into working buffer for later decode */
122 static int lintogsm_framein(struct ast_trans_pvt *pvt, struct ast_frame *f)
123 {
124  struct gsm_translator_pvt *tmp = pvt->pvt;
125 
126  /* XXX We should look at how old the rest of our stream is, and if it
127  is too old, then we should overwrite it entirely, otherwise we can
128  get artifacts of earlier talk that do not belong */
129  if (pvt->samples + f->samples > BUFFER_SAMPLES) {
130  ast_log(LOG_WARNING, "Out of buffer space\n");
131  return -1;
132  }
133  memcpy(tmp->buf + pvt->samples, f->data.ptr, f->datalen);
134  pvt->samples += f->samples;
135  return 0;
136 }
137 
138 /*! \brief encode and produce a frame */
139 static struct ast_frame *lintogsm_frameout(struct ast_trans_pvt *pvt)
140 {
141  struct gsm_translator_pvt *tmp = pvt->pvt;
142  int datalen = 0;
143  int samples = 0;
144 
145  /* We can't work on anything less than a frame in size */
146  if (pvt->samples < GSM_SAMPLES)
147  return NULL;
148  while (pvt->samples >= GSM_SAMPLES) {
149  /* Encode a frame of data */
150  gsm_encode(tmp->gsm, tmp->buf + samples, (gsm_byte *) pvt->outbuf.c + datalen);
151  datalen += GSM_FRAME_LEN;
152  samples += GSM_SAMPLES;
153  pvt->samples -= GSM_SAMPLES;
154  }
155 
156  /* Move the data at the end of the buffer to the front */
157  if (pvt->samples)
158  memmove(tmp->buf, tmp->buf + samples, pvt->samples * 2);
159 
160  return ast_trans_frameout(pvt, datalen, samples);
161 }
162 
163 static void gsm_destroy_stuff(struct ast_trans_pvt *pvt)
164 {
165  struct gsm_translator_pvt *tmp = pvt->pvt;
166  if (tmp->gsm)
167  gsm_destroy(tmp->gsm);
168 }
169 
170 static struct ast_translator gsmtolin = {
171  .name = "gsmtolin",
172  .srcfmt = AST_FORMAT_GSM,
173  .dstfmt = AST_FORMAT_SLINEAR,
174  .newpvt = gsm_new,
175  .framein = gsmtolin_framein,
176  .destroy = gsm_destroy_stuff,
177  .sample = gsm_sample,
178  .buffer_samples = BUFFER_SAMPLES,
179  .buf_size = BUFFER_SAMPLES * 2,
180  .desc_size = sizeof (struct gsm_translator_pvt ),
181 };
182 
183 static struct ast_translator lintogsm = {
184  .name = "lintogsm",
185  .srcfmt = AST_FORMAT_SLINEAR,
186  .dstfmt = AST_FORMAT_GSM,
187  .newpvt = gsm_new,
188  .framein = lintogsm_framein,
189  .frameout = lintogsm_frameout,
190  .destroy = gsm_destroy_stuff,
191  .sample = slin8_sample,
192  .desc_size = sizeof (struct gsm_translator_pvt ),
193  .buf_size = (BUFFER_SAMPLES * GSM_FRAME_LEN + GSM_SAMPLES - 1)/GSM_SAMPLES,
194 };
195 
196 /*! \brief standard module glue */
197 static int reload(void)
198 {
200 }
201 
202 static int unload_module(void)
203 {
204  int res;
205 
206  res = ast_unregister_translator(&lintogsm);
207  if (!res)
208  res = ast_unregister_translator(&gsmtolin);
209 
210  return res;
211 }
212 
213 static int load_module(void)
214 {
215  int res;
216 
217  res = ast_register_translator(&gsmtolin);
218  if (!res)
219  res=ast_register_translator(&lintogsm);
220  else
221  ast_unregister_translator(&gsmtolin);
222  if (res)
225 }
226 
228  .load = load_module,
229  .unload = unload_module,
230  .reload = reload,
231  );
struct ast_frame * ast_trans_frameout(struct ast_trans_pvt *pvt, int datalen, int samples)
generic frameout function
Definition: translate.c:235
int datalen
actual space used in outbuf
Definition: translate.h:140
Asterisk main include file. File version handling, generic pbx functions.
union ast_trans_pvt::@213 outbuf
int16_t buf[BUFFER_SAMPLES]
Definition: codec_gsm.c:62
Descriptor of a translator.
Definition: translate.h:71
static struct ast_translator lintogsm
Definition: codec_gsm.c:183
void * ptr
Definition: frame.h:160
#define LOG_WARNING
Definition: logger.h:144
#define GSM_FRAME_LEN
Definition: codec_gsm.c:53
static int unload_module(void)
Definition: codec_gsm.c:202
static struct ast_frame * lintogsm_frameout(struct ast_trans_pvt *pvt)
encode and produce a frame
Definition: codec_gsm.c:139
Configuration File Parser.
const char name[80]
Definition: translate.h:72
static void gsm_destroy_stuff(struct ast_trans_pvt *pvt)
Definition: codec_gsm.c:163
#define AST_MODULE_INFO(keystr, flags_to_set, desc, fields...)
Definition: module.h:374
static struct ast_frame * slin8_sample(void)
Definition: slin.h:61
void * pvt
Definition: translate.h:141
static int gsmtolin_framein(struct ast_trans_pvt *pvt, struct ast_frame *f)
decode and store in outbuf.
Definition: codec_gsm.c:73
int16_t * i16
Definition: translate.h:145
Utility functions.
static struct ast_translator gsmtolin
Definition: codec_gsm.c:170
#define MSGSM_FRAME_LEN
Definition: codec_gsm.c:54
int datalen
Definition: frame.h:148
#define ast_register_translator(t)
See __ast_register_translator()
Definition: translate.h:170
int ast_unregister_translator(struct ast_translator *t)
Unregister a translator Unregisters the given tranlator.
Definition: translate.c:942
static void conv65(wav_byte *c, gsm_byte *d)
Definition: msgsm.h:455
Default structure for translators, with the basic fields and buffers, all allocated as part of the sa...
Definition: translate.h:135
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:65
#define GSM_SAMPLES
Definition: codec_gsm.c:52
void ast_log(int level, const char *file, int line, const char *function, const char *fmt,...)
Used for sending a log message This is the standard logger function. Probably the only way you will i...
Definition: logger.c:1207
#define BUFFER_SAMPLES
Definition: codec_gsm.c:51
static struct ast_format f[]
Definition: format_g726.c:181
static int reload(void)
standard module glue
Definition: codec_gsm.c:197
unsigned char gsm_byte
Definition: msgsm.h:6
#define AST_FORMAT_SLINEAR
Definition: frame.h:254
Data structure associated with a single frame of data.
Definition: frame.h:142
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:122
8-bit raw data
static int load_module(void)
Definition: codec_gsm.c:213
#define ASTERISK_GPL_KEY
The text the key() function should return.
Definition: module.h:38
Asterisk module definitions.
union ast_frame::@172 data
#define AST_FORMAT_GSM
Definition: frame.h:244
#define ASTERISK_FILE_VERSION(file, version)
Register/unregister a source code file with the core.
Definition: asterisk.h:180
int samples
Definition: frame.h:150
static struct ast_frame * gsm_sample(void)
Definition: ex_gsm.h:17