translate: Fix transcoding while different in frame size.
[asterisk/asterisk.git] / codecs / codec_ilbc.c
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 <markster@digium.com>
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 ASTERISK_REGISTER_FILE()
36
37 #include "asterisk/translate.h"
38 #include "asterisk/module.h"
39 #include "asterisk/utils.h"
40 #include "asterisk/linkedlists.h"
41
42 #ifdef ILBC_WEBRTC
43 #include <ilbc.h>
44 typedef WebRtc_UWord16 ilbc_bytes;
45 typedef WebRtc_Word16  ilbc_block;
46 #define BUF_TYPE i16
47 #else
48 #include "ilbc/iLBC_encode.h"
49 #include "ilbc/iLBC_decode.h"
50 typedef unsigned char ilbc_bytes;
51 typedef float         ilbc_block;
52 #define BUF_TYPE uc
53 #endif
54
55 #define USE_ILBC_ENHANCER       0
56 #define ILBC_MS                         30
57 /* #define ILBC_MS                      20 */
58
59 #define ILBC_FRAME_LEN  50      /* apparently... */
60 #define ILBC_SAMPLES    240     /* 30ms at 8000 hz */
61 #define BUFFER_SAMPLES  8000
62
63 /* Sample frame data */
64 #include "asterisk/slin.h"
65 #include "ex_ilbc.h"
66
67 struct ilbc_coder_pvt {
68         iLBC_Enc_Inst_t enc;
69         iLBC_Dec_Inst_t dec;
70         /* Enough to store a full second */
71         int16_t buf[BUFFER_SAMPLES];
72 };
73
74 static int lintoilbc_new(struct ast_trans_pvt *pvt)
75 {
76         struct ilbc_coder_pvt *tmp = pvt->pvt;
77
78         initEncode(&tmp->enc, ILBC_MS);
79
80         return 0;
81 }
82
83 static int ilbctolin_new(struct ast_trans_pvt *pvt)
84 {
85         struct ilbc_coder_pvt *tmp = pvt->pvt;
86
87         initDecode(&tmp->dec, ILBC_MS, USE_ILBC_ENHANCER);
88
89         return 0;
90 }
91
92 /*! \brief decode a frame and store in outbuf */
93 static int ilbctolin_framein(struct ast_trans_pvt *pvt, struct ast_frame *f)
94 {
95         struct ilbc_coder_pvt *tmp = pvt->pvt;
96         int plc_mode = 1; /* 1 = normal data, 0 = plc */
97         /* Assuming there's space left, decode into the current buffer at
98            the tail location.  Read in as many frames as there are */
99         int x,i;
100         int datalen = f->datalen;
101         int16_t *dst = pvt->outbuf.i16;
102         ilbc_block tmpf[ILBC_SAMPLES];
103
104         if (!f->data.ptr && datalen) {
105                 ast_debug(1, "issue 16070, ILIB ERROR. data = NULL datalen = %d src = %s\n", datalen, f->src ? f->src : "no src set");
106                 f->datalen = 0;
107                 datalen = 0;
108         }
109
110         if (datalen == 0) { /* native PLC, set fake datalen and clear plc_mode */
111                 datalen = ILBC_FRAME_LEN;
112                 f->samples = ILBC_SAMPLES;
113                 plc_mode = 0;   /* do native plc */
114                 pvt->samples += ILBC_SAMPLES;
115         }
116
117         if (datalen % ILBC_FRAME_LEN) {
118                 ast_log(LOG_WARNING, "Huh?  An ilbc frame that isn't a multiple of 50 bytes long from %s (%d)?\n", f->src, datalen);
119                 return -1;
120         }
121
122         for (x=0; x < datalen ; x += ILBC_FRAME_LEN) {
123                 if (pvt->samples + ILBC_SAMPLES > BUFFER_SAMPLES) {
124                         ast_log(LOG_WARNING, "Out of buffer space\n");
125                         return -1;
126                 }
127                 iLBC_decode(tmpf, plc_mode ? f->data.ptr + x : NULL, &tmp->dec, plc_mode);
128                 for ( i=0; i < ILBC_SAMPLES; i++)
129                         dst[pvt->samples + i] = tmpf[i];
130                 pvt->samples += ILBC_SAMPLES;
131                 pvt->datalen += 2*ILBC_SAMPLES;
132         }
133         return 0;
134 }
135
136 /*! \brief store a frame into a temporary buffer, for later decoding */
137 static int lintoilbc_framein(struct ast_trans_pvt *pvt, struct ast_frame *f)
138 {
139         struct ilbc_coder_pvt *tmp = pvt->pvt;
140
141         /* Just add the frames to our stream */
142         /* XXX We should look at how old the rest of our stream is, and if it
143            is too old, then we should overwrite it entirely, otherwise we can
144            get artifacts of earlier talk that do not belong */
145         memcpy(tmp->buf + pvt->samples, f->data.ptr, f->datalen);
146         pvt->samples += f->samples;
147         return 0;
148 }
149
150 /*! \brief encode the temporary buffer and generate a frame */
151 static struct ast_frame *lintoilbc_frameout(struct ast_trans_pvt *pvt)
152 {
153         struct ilbc_coder_pvt *tmp = pvt->pvt;
154         struct ast_frame *result = NULL;
155         struct ast_frame *last = NULL;
156         int samples = 0; /* output samples */
157
158         while (pvt->samples >= ILBC_SAMPLES) {
159                 struct ast_frame *current;
160                 ilbc_block tmpf[ILBC_SAMPLES];
161                 int i;
162
163                 /* Encode a frame of data */
164                 for (i = 0 ; i < ILBC_SAMPLES ; i++)
165                         tmpf[i] = tmp->buf[samples + i];
166                 iLBC_encode((ilbc_bytes *) pvt->outbuf.BUF_TYPE, tmpf, &tmp->enc);
167
168                 samples += ILBC_SAMPLES;
169                 pvt->samples -= ILBC_SAMPLES;
170
171                 current = ast_trans_frameout(pvt, ILBC_FRAME_LEN, ILBC_SAMPLES);
172                 if (!current) {
173                         continue;
174                 } else if (last) {
175                         AST_LIST_NEXT(last, frame_list) = current;
176                 } else {
177                         result = current;
178                 }
179                 last = current;
180         }
181
182         /* Move the data at the end of the buffer to the front */
183         if (samples) {
184                 memmove(tmp->buf, tmp->buf + samples, pvt->samples * 2);
185         }
186
187         return result;
188 }
189
190 static struct ast_translator ilbctolin = {
191         .name = "ilbctolin",
192         .src_codec = {
193                 .name = "ilbc",
194                 .type = AST_MEDIA_TYPE_AUDIO,
195                 .sample_rate = 8000,
196         },
197         .dst_codec = {
198                 .name = "slin",
199                 .type = AST_MEDIA_TYPE_AUDIO,
200                 .sample_rate = 8000,
201         },
202         .format = "slin",
203         .newpvt = ilbctolin_new,
204         .framein = ilbctolin_framein,
205         .sample = ilbc_sample,
206         .desc_size = sizeof(struct ilbc_coder_pvt),
207         .buf_size = BUFFER_SAMPLES * 2,
208         .native_plc = 1,
209 };
210
211 static struct ast_translator lintoilbc = {
212         .name = "lintoilbc",
213         .src_codec = {
214                 .name = "slin",
215                 .type = AST_MEDIA_TYPE_AUDIO,
216                 .sample_rate = 8000,
217         },
218         .dst_codec = {
219                 .name = "ilbc",
220                 .type = AST_MEDIA_TYPE_AUDIO,
221                 .sample_rate = 8000,
222         },
223         .format = "ilbc",
224         .newpvt = lintoilbc_new,
225         .framein = lintoilbc_framein,
226         .frameout = lintoilbc_frameout,
227         .sample = slin8_sample,
228         .desc_size = sizeof(struct ilbc_coder_pvt),
229         .buf_size = (BUFFER_SAMPLES * ILBC_FRAME_LEN + ILBC_SAMPLES - 1) / ILBC_SAMPLES,
230 };
231
232 static int unload_module(void)
233 {
234         int res;
235
236         res = ast_unregister_translator(&lintoilbc);
237         res |= ast_unregister_translator(&ilbctolin);
238
239         return res;
240 }
241
242 static int load_module(void)
243 {
244         int res;
245
246         res = ast_register_translator(&ilbctolin);
247         res |= ast_register_translator(&lintoilbc);
248
249         if (res) {
250                 unload_module();
251                 return AST_MODULE_LOAD_FAILURE;
252         }
253
254         return AST_MODULE_LOAD_SUCCESS;
255 }
256
257 AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "iLBC Coder/Decoder");