Asterisk - The Open Source Telephony Project  18.5.0
codec_ilbc.c
Go to the documentation of this file.
1 /*
2  * Asterisk -- An open source telephony toolkit.
3  *
4  * The iLBC code is from The IETF code base and is copyright The Internet Society (2004)
5  *
6  * Copyright (C) 1999 - 2005, Digium, Inc.
7  *
8  * Mark Spencer <[email protected]>
9  *
10  * See http://www.asterisk.org for more information about
11  * the Asterisk project. Please do not directly contact
12  * any of the maintainers of this project for assistance;
13  * the project provides a web site, mailing lists and IRC
14  * channels for your use.
15  *
16  * This program is free software, distributed under the terms of
17  * the GNU General Public License Version 2. See the LICENSE file
18  * at the top of the source tree.
19  */
20 
21 /*! \file
22  *
23  * \brief Translate between signed linear and Internet Low Bitrate Codec
24  *
25  * \ingroup codecs
26  */
27 
28 /*** MODULEINFO
29  <use>ilbc</use>
30  <support_level>core</support_level>
31  ***/
32 
33 #include "asterisk.h"
34 
35 #include "asterisk/codec.h" /* for AST_MEDIA_TYPE_AUDIO */
36 #include "asterisk/format.h" /* for ast_format_get_attribute_data */
37 #include "asterisk/frame.h" /* for ast_frame, etc */
38 #include "asterisk/linkedlists.h" /* for AST_LIST_NEXT, etc */
39 #include "asterisk/logger.h" /* for ast_log, ast_debug, etc */
40 #include "asterisk/module.h"
41 #include "asterisk/translate.h" /* for ast_trans_pvt, etc */
42 
43 #ifdef ILBC_WEBRTC
44 #include <ilbc.h>
45 typedef uint16_t ilbc_bytes;
46 typedef int16_t ilbc_block;
47 #define BUF_TYPE i16
48 #else
49 #include "ilbc/iLBC_encode.h"
50 #include "ilbc/iLBC_decode.h"
51 typedef unsigned char ilbc_bytes;
52 typedef float ilbc_block;
53 #define BUF_TYPE uc
54 #endif
55 
56 #include "asterisk/ilbc.h"
57 
58 #define USE_ILBC_ENHANCER 0
59 #define BUFFER_SAMPLES 8000
60 
61 /* Sample frame data */
62 #include "asterisk/slin.h"
63 #include "ex_ilbc.h"
64 
68  /* Enough to store a full second */
71 };
72 
73 static int lintoilbc_new(struct ast_trans_pvt *pvt)
74 {
75  struct ilbc_coder_pvt *tmp = pvt->pvt;
77  const unsigned int mode = attr ? attr->mode : 30;
78 
79  initEncode(&tmp->enc, mode);
80 
81  return 0;
82 }
83 
84 static int ilbctolin_new(struct ast_trans_pvt *pvt)
85 {
86  struct ilbc_coder_pvt *tmp = pvt->pvt;
87 
88  tmp->inited = 0; /* we do not know the iLBC mode, yet */
89 
90  return 0;
91 }
92 
93 /*! \brief decode a frame and store in outbuf */
94 static int ilbctolin_framein(struct ast_trans_pvt *pvt, struct ast_frame *f)
95 {
96  struct ilbc_coder_pvt *tmp = pvt->pvt;
98  const unsigned int mode = attr ? attr->mode : 30;
99  const unsigned int sample_rate = pvt->t->dst_codec.sample_rate;
100  const unsigned int samples_per_frame = mode * sample_rate / 1000;
101  const unsigned int octets_per_frame = (mode == 20) ? 38 : 50;
102 
103  int plc_mode = 1; /* 1 = normal data, 0 = plc */
104  /* Assuming there's space left, decode into the current buffer at
105  the tail location. Read in as many frames as there are */
106  int x,i;
107  int datalen = f->datalen;
108  int16_t *dst = pvt->outbuf.i16;
109  ilbc_block tmpf[samples_per_frame];
110 
111  if (!f->data.ptr && datalen) {
112  ast_debug(1, "issue 16070, ILIB ERROR. data = NULL datalen = %d src = %s\n", datalen, f->src ? f->src : "no src set");
113  f->datalen = 0;
114  datalen = 0;
115  }
116 
117  if (datalen == 0) { /* native PLC, set fake datalen and clear plc_mode */
118  datalen = octets_per_frame;
119  f->samples = samples_per_frame;
120  plc_mode = 0; /* do native plc */
121  pvt->samples += samples_per_frame;
122  }
123 
124  if (datalen % octets_per_frame) {
125  ast_log(LOG_WARNING, "Huh? An ilbc frame that isn't a multiple of %u bytes long from %s (%d)?\n", octets_per_frame, f->src, datalen);
126  return -1;
127  }
128 
129  if (!tmp->inited) {
130  initDecode(&tmp->dec, mode, USE_ILBC_ENHANCER);
131  tmp->inited = 1;
132  }
133 
134  for (x = 0; x < datalen; x += octets_per_frame) {
135  if (pvt->samples + samples_per_frame > BUFFER_SAMPLES) {
136  ast_log(LOG_WARNING, "Out of buffer space\n");
137  return -1;
138  }
139  iLBC_decode(tmpf, plc_mode ? f->data.ptr + x : NULL, &tmp->dec, plc_mode);
140  for (i = 0; i < samples_per_frame; i++)
141  dst[pvt->samples + i] = tmpf[i];
142  pvt->samples += samples_per_frame;
143  pvt->datalen += samples_per_frame * 2;
144  }
145  return 0;
146 }
147 
148 /*! \brief store a frame into a temporary buffer, for later decoding */
149 static int lintoilbc_framein(struct ast_trans_pvt *pvt, struct ast_frame *f)
150 {
151  struct ilbc_coder_pvt *tmp = pvt->pvt;
152 
153  /* Just add the frames to our stream */
154  /* XXX We should look at how old the rest of our stream is, and if it
155  is too old, then we should overwrite it entirely, otherwise we can
156  get artifacts of earlier talk that do not belong */
157  memcpy(tmp->buf + pvt->samples, f->data.ptr, f->datalen);
158  pvt->samples += f->samples;
159  return 0;
160 }
161 
162 /*! \brief encode the temporary buffer and generate a frame */
163 static struct ast_frame *lintoilbc_frameout(struct ast_trans_pvt *pvt)
164 {
165  struct ilbc_coder_pvt *tmp = pvt->pvt;
166  struct ast_frame *result = NULL;
167  struct ast_frame *last = NULL;
168  int samples = 0; /* output samples */
169 
171  const unsigned int mode = attr ? attr->mode : 30;
172  const unsigned int sample_rate = pvt->t->dst_codec.sample_rate;
173  const unsigned int samples_per_frame = mode * sample_rate / 1000;
174  const unsigned int octets_per_frame = (mode == 20) ? 38 : 50;
175 
176  while (pvt->samples >= samples_per_frame) {
177  struct ast_frame *current;
178  ilbc_block tmpf[samples_per_frame];
179  int i;
180 
181  /* Encode a frame of data */
182  for (i = 0; i < samples_per_frame; i++)
183  tmpf[i] = tmp->buf[samples + i];
184  iLBC_encode((ilbc_bytes *) pvt->outbuf.BUF_TYPE, tmpf, &tmp->enc);
185 
186  samples += samples_per_frame;
187  pvt->samples -= samples_per_frame;
188 
189  current = ast_trans_frameout(pvt, octets_per_frame, samples_per_frame);
190  if (!current) {
191  continue;
192  } else if (last) {
193  AST_LIST_NEXT(last, frame_list) = current;
194  } else {
195  result = current;
196  }
197  last = current;
198  }
199 
200  /* Move the data at the end of the buffer to the front */
201  if (samples) {
202  memmove(tmp->buf, tmp->buf + samples, pvt->samples * 2);
203  }
204 
205  return result;
206 }
207 
208 static struct ast_translator ilbctolin = {
209  .name = "ilbctolin",
210  .src_codec = {
211  .name = "ilbc",
212  .type = AST_MEDIA_TYPE_AUDIO,
213  .sample_rate = 8000,
214  },
215  .dst_codec = {
216  .name = "slin",
217  .type = AST_MEDIA_TYPE_AUDIO,
218  .sample_rate = 8000,
219  },
220  .format = "slin",
221  .newpvt = ilbctolin_new,
222  .framein = ilbctolin_framein,
223  .sample = ilbc_sample,
224  .desc_size = sizeof(struct ilbc_coder_pvt),
225  .buf_size = BUFFER_SAMPLES * 2,
226  .native_plc = 1,
227 };
228 
229 static struct ast_translator lintoilbc = {
230  .name = "lintoilbc",
231  .src_codec = {
232  .name = "slin",
233  .type = AST_MEDIA_TYPE_AUDIO,
234  .sample_rate = 8000,
235  },
236  .dst_codec = {
237  .name = "ilbc",
238  .type = AST_MEDIA_TYPE_AUDIO,
239  .sample_rate = 8000,
240  },
241  .format = "ilbc",
242  .newpvt = lintoilbc_new,
243  .framein = lintoilbc_framein,
244  .frameout = lintoilbc_frameout,
245  .sample = slin8_sample,
246  .desc_size = sizeof(struct ilbc_coder_pvt),
247  /* frame len (38 bytes), frame size (160 samples), ceil (+ 160 - 1) */
248  .buf_size = (BUFFER_SAMPLES * 38 + 160 - 1) / 160,
249 };
250 
251 static int unload_module(void)
252 {
253  int res;
254 
255  res = ast_unregister_translator(&lintoilbc);
256  res |= ast_unregister_translator(&ilbctolin);
257 
258  return res;
259 }
260 
261 static int load_module(void)
262 {
263  int res;
264 
265  res = ast_register_translator(&ilbctolin);
266  res |= ast_register_translator(&lintoilbc);
267 
268  if (res) {
269  unload_module();
271  }
272 
274 }
275 
struct ast_frame * ast_trans_frameout(struct ast_trans_pvt *pvt, int datalen, int samples)
generic frameout function
Definition: translate.c:438
int datalen
actual space used in outbuf
Definition: translate.h:218
#define AST_MODULE_INFO_STANDARD(keystr, desc)
Definition: module.h:567
static int ilbctolin_new(struct ast_trans_pvt *pvt)
Definition: codec_ilbc.c:84
Asterisk main include file. File version handling, generic pbx functions.
iLBC_Enc_Inst_t enc
Definition: codec_ilbc.c:66
Definition: ilbc.h:4
Descriptor of a translator.
Definition: translate.h:137
short int16_t
Definition: db.h:59
Support for translation of data formats. translate.c.
float ilbc_block
Definition: codec_ilbc.c:52
void iLBC_decode(float *decblock, unsigned char *bytes, iLBC_Dec_Inst_t *iLBCdec_inst, int mode)
Definition: iLBC_decode.c:326
static struct ast_translator ilbctolin
Definition: codec_ilbc.c:208
struct ast_frame f
Definition: translate.h:215
#define LOG_WARNING
Definition: logger.h:274
int16_t inited
Definition: codec_ilbc.c:70
static struct ast_translator lintoilbc
Definition: codec_ilbc.c:229
static int tmp()
Definition: bt_open.c:389
#define AST_LIST_NEXT(elm, field)
Returns the next entry in the list after the given entry.
Definition: linkedlists.h:438
Codec API.
void * ast_format_get_attribute_data(const struct ast_format *format)
Get the attribute data on a format.
Definition: format.c:125
static struct ast_frame * slin8_sample(void)
Definition: slin.h:64
#define NULL
Definition: resample.c:96
static int load_module(void)
Definition: codec_ilbc.c:261
void * pvt
Definition: translate.h:219
void iLBC_encode(unsigned char *bytes, float *block, iLBC_Enc_Inst_t *iLBCenc_inst)
Definition: iLBC_encode.c:89
struct ast_frame_subclass subclass
int16_t * i16
Definition: translate.h:223
Media Format API.
static struct ast_frame * ilbc_sample(void)
Definition: ex_ilbc.h:21
short initDecode(iLBC_Dec_Inst_t *iLBCdec_inst, int mode, int use_enhancer)
Definition: iLBC_decode.c:33
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:452
#define ast_log
Definition: astobj2.c:42
const char * src
struct sla_ringing_trunk * last
Definition: app_meetme.c:1092
#define ast_register_translator(t)
See __ast_register_translator()
Definition: translate.h:257
Asterisk internal frame definitions.
int ast_unregister_translator(struct ast_translator *t)
Unregister a translator Unregisters the given tranlator.
Definition: translate.c:1333
unsigned char ilbc_bytes
Definition: codec_ilbc.c:51
A set of macros to manage forward-linked lists.
static int ilbctolin_framein(struct ast_trans_pvt *pvt, struct ast_frame *f)
decode a frame and store in outbuf
Definition: codec_ilbc.c:94
int16_t buf[BUFFER_SAMPLES]
Definition: codec_ilbc.c:69
union ast_trans_pvt::@327 outbuf
struct ast_codec dst_codec
Definition: translate.h:140
struct ast_format * explicit_dst
Definition: translate.h:237
Default structure for translators, with the basic fields and buffers, all allocated as part of the sa...
Definition: translate.h:213
short initEncode(iLBC_Enc_Inst_t *iLBCenc_inst, int mode)
Definition: iLBC_encode.c:35
iLBC_Dec_Inst_t dec
Definition: codec_ilbc.c:67
unsigned int mode
Definition: ilbc.h:5
static int unload_module(void)
Definition: codec_ilbc.c:251
#define BUFFER_SAMPLES
Definition: codec_ilbc.c:59
Module has failed to load, may be in an inconsistent state.
Definition: module.h:78
unsigned int sample_rate
Sample rate (number of samples carried in a second)
Definition: codec.h:52
Support for logging to various files, console and syslog Configuration in file logger.conf.
Raw 8-bit data.
static struct ast_frame * lintoilbc_frameout(struct ast_trans_pvt *pvt)
encode the temporary buffer and generate a frame
Definition: codec_ilbc.c:163
#define USE_ILBC_ENHANCER
Definition: codec_ilbc.c:58
static PGresult * result
Definition: cel_pgsql.c:88
Data structure associated with a single frame of data.
static int lintoilbc_framein(struct ast_trans_pvt *pvt, struct ast_frame *f)
store a frame into a temporary buffer, for later decoding
Definition: codec_ilbc.c:149
struct ast_translator * t
Definition: translate.h:214
union ast_frame::@263 data
struct ast_format * format
static int lintoilbc_new(struct ast_trans_pvt *pvt)
Definition: codec_ilbc.c:73
#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