1 /*
2 * CELT Codec Plugin for Opal
3 *
4 * Based on the GSM-AMR one
5 */
6
7 #define _CRT_NONSTDC_NO_DEPRECATE 1
8 #define _CRT_SECURE_NO_WARNINGS 1
9
10 #include <stdio.h>
11 #include <stdlib.h>
12 #include <string.h>
13
14 #include "plugin-config.h"
15
16 #include <codec/opalplugin.h>
17 #include <celt/celt.h>
18
19 #ifndef FALSE
20 #define FALSE 0
21 #endif
22
23 #ifndef TRUE
24 #define TRUE (!FALSE)
25 #endif
26
27 #if defined(_WIN32) || defined(_WIN32_WCE)
28 #define STRCMPI _strcmpi
29 #else
30 #define STRCMPI strcasecmp
31 #endif
32
33 /*Disable some warnings on VC++*/
34 #ifdef _MSC_VER
35 #pragma warning(disable : 4100)
36 #endif
37
38 // this is what we hand back when we are asked to create an encoder
39 typedef struct
40 {
41 CELTDecoder *decoder_state;
42 CELTEncoder *encoder_state;
43 CELTMode *mode;
44 int frame_size;
45 int bytes_per_packet;
46 } CELTContext;
47
48
49 /////////////////////////////////////////////////////////////////////////////
50
init_mode(CELTContext * celt,const struct PluginCodec_Definition * codec)51 static int init_mode(CELTContext *celt, const struct PluginCodec_Definition * codec)
52 {
53 int error = 0;
54
55 celt->mode = celt_mode_create(codec->sampleRate, 1, codec->parm.audio.samplesPerFrame, &error);
56 if (celt->mode == NULL) {
57 return FALSE;
58 }
59
60 celt_mode_info(celt->mode, CELT_GET_FRAME_SIZE, &celt->frame_size);
61 celt->bytes_per_packet = (codec->bitsPerSec * celt->frame_size/codec->sampleRate + 4) / 8;
62
63 return TRUE;
64 }
65
celt_create_encoder(const struct PluginCodec_Definition * codec)66 static void * celt_create_encoder(const struct PluginCodec_Definition * codec)
67 {
68 CELTContext * celt = malloc(sizeof(CELTContext));
69 if (celt == NULL)
70 return NULL;
71
72 if (init_mode(celt, codec) == FALSE) {
73 free(celt);
74 return NULL;
75 }
76
77 celt->encoder_state = celt_encoder_create(celt->mode);
78 if (celt->encoder_state == NULL ) {
79 celt_mode_destroy(celt->mode);
80 free(celt);
81 return NULL;
82 }
83
84 return celt;
85 }
86
87
celt_create_decoder(const struct PluginCodec_Definition * codec)88 static void * celt_create_decoder(const struct PluginCodec_Definition * codec)
89 {
90 CELTContext * celt = malloc(sizeof(CELTContext));
91 if (celt == NULL)
92 return NULL;
93
94 if (init_mode(celt, codec) == FALSE) {
95 free(celt);
96 return NULL;
97 }
98
99 celt->decoder_state = celt_decoder_create(celt->mode);
100 if (celt->decoder_state == NULL ) {
101 celt_mode_destroy(celt->mode);
102 free(celt);
103 return NULL;
104 }
105
106 return celt;
107 }
108
109
celt_destroy_encoder(const struct PluginCodec_Definition * codec,void * context)110 static void celt_destroy_encoder(const struct PluginCodec_Definition * codec, void * context)
111 {
112 CELTContext * celt = (CELTContext *)context;
113 celt_encoder_destroy(celt->encoder_state);
114 celt_mode_destroy(celt->mode);
115 free(celt);
116 }
117
118
celt_destroy_decoder(const struct PluginCodec_Definition * codec,void * context)119 static void celt_destroy_decoder(const struct PluginCodec_Definition * codec, void * context)
120 {
121 CELTContext * celt = (CELTContext *)context;
122 celt_decoder_destroy(celt->decoder_state);
123 celt_mode_destroy(celt->mode);
124 free(celt);
125 }
126
127
celt_codec_encoder(const struct PluginCodec_Definition * codec,void * context,const void * fromPtr,unsigned * fromLen,void * toPtr,unsigned * toLen,unsigned int * flag)128 static int celt_codec_encoder(const struct PluginCodec_Definition * codec,
129 void * context,
130 const void * fromPtr,
131 unsigned * fromLen,
132 void * toPtr,
133 unsigned * toLen,
134 unsigned int * flag)
135 {
136 CELTContext *celt = (CELTContext *)context;
137 unsigned byteCount;
138
139 if (*fromLen < codec->parm.audio.samplesPerFrame*sizeof(short))
140 return FALSE;
141
142 if (*toLen < celt->bytes_per_packet)
143 return FALSE;
144
145 #ifdef HAVE_CELT_0_5_0_OR_LATER
146 byteCount = celt_encode(celt->encoder_state, (celt_int16_t *)fromPtr, NULL, (char *)toPtr, celt->bytes_per_packet);
147 #else
148 byteCount = celt_encode(celt->encoder_state, (celt_int16_t *)fromPtr, (char *)toPtr, celt->bytes_per_packet);
149 #endif
150 if (byteCount < 0) {
151 return 0;
152 }
153 *toLen = byteCount;
154 *fromLen = codec->parm.audio.samplesPerFrame*sizeof(short);
155
156 return TRUE;
157 }
158
159
celt_codec_decoder(const struct PluginCodec_Definition * codec,void * context,const void * fromPtr,unsigned * fromLen,void * toPtr,unsigned * toLen,unsigned int * flag)160 static int celt_codec_decoder(const struct PluginCodec_Definition * codec,
161 void * context,
162 const void * fromPtr,
163 unsigned * fromLen,
164 void * toPtr,
165 unsigned * toLen,
166 unsigned int * flag)
167 {
168 CELTContext *celt = (CELTContext *)context;
169
170 if (*toLen < codec->parm.audio.samplesPerFrame*sizeof(short))
171 return FALSE;
172
173 if (*fromLen == 0)
174 return FALSE;
175
176 if (celt_decode(celt->decoder_state, (char *)fromPtr, *fromLen, (short *)toPtr) < 0) {
177 return 0;
178 }
179
180 *toLen = codec->parm.audio.samplesPerFrame*sizeof(short);
181
182 return TRUE;
183 }
184
185 /* taken from Speex */
valid_for_sip(const struct PluginCodec_Definition * codec,void * context,const char * key,void * parm,unsigned * parmLen)186 static int valid_for_sip(
187 const struct PluginCodec_Definition * codec,
188 void * context,
189 const char * key,
190 void * parm,
191 unsigned * parmLen)
192 {
193 if (parmLen == NULL || parm == NULL || *parmLen != sizeof(char *))
194 return 0;
195
196 return (STRCMPI((const char *)parm, "sip") == 0) ? 1 : 0;
197 }
198
199 /////////////////////////////////////////////////////////////////////////////
200
201 static struct PluginCodec_ControlDefn celt_codec_controls[] = {
202 { "valid_for_protocol", valid_for_sip },
203 { NULL }
204 };
205
206 static struct PluginCodec_information licenseInfo = {
207 // Fri Dec 13 2008, 23:37:31 CET =
208 1229729851,
209
210 "Stefan Knoblich, axsentis GmbH", // source code author
211 "0.1", // source code version
212 "s.knoblich@axsentis.de", // source code email
213 "http://oss.axsentis.de/", // source code URL
214 "Copyright (C) 2008 axsentis GmbH", // source code copyright
215 "BSD license", // source code license
216 PluginCodec_License_BSD, // source code license
217
218 "CELT (ultra-low delay audio codec)", // codec description
219 "Jean-Marc Valin, Xiph Foundation.", // codec author
220 "", // codec version
221 "jean-marc.valin@hermes.usherb.ca", // codec email
222 "http://www.celt-codec.org", // codec URL
223 "(C) 2008 Xiph.Org Foundation, All Rights Reserved", // codec copyright information
224 "Xiph BSD license", // codec license
225 PluginCodec_License_BSD // codec license code
226 };
227
228 static struct PluginCodec_Definition celtCodecDefn[] = {
229 /* 32KHz */
230 {
231 // encoder
232 PLUGIN_CODEC_VERSION_OPTIONS, // codec API version
233 &licenseInfo, // license information
234
235 PluginCodec_MediaTypeAudio | // audio codec
236 PluginCodec_InputTypeRaw | // raw input data
237 PluginCodec_OutputTypeRaw | // raw output data
238 PluginCodec_RTPTypeShared |
239 PluginCodec_RTPTypeDynamic, // dynamic RTP type
240
241 "CELT-32K", // text decription
242 "L16", // source format
243 "CELT-32K", // destination format
244
245 NULL, // user data
246
247 32000, // samples per second
248 32000, // raw bits per second
249 10000, // microseconds per frame
250 {{
251 320, // samples per frame
252 40, // bytes per frame
253 1, // recommended number of frames per packet
254 1, // maximum number of frames per packet
255 }},
256 0, // IANA RTP payload code
257 "CELT", // RTP payload name
258
259 celt_create_encoder, // create codec function
260 celt_destroy_encoder, // destroy codec
261 celt_codec_encoder, // encode/decode
262 celt_codec_controls, // codec controls
263
264 PluginCodec_H323Codec_NoH323,
265 NULL
266 },
267 {
268 // decoder
269 PLUGIN_CODEC_VERSION_OPTIONS, // codec API version
270 &licenseInfo, // license information
271
272 PluginCodec_MediaTypeAudio | // audio codec
273 PluginCodec_InputTypeRaw | // raw input data
274 PluginCodec_OutputTypeRaw | // raw output data
275 PluginCodec_RTPTypeShared |
276 PluginCodec_RTPTypeDynamic, // dynamic RTP type
277
278 #if 0 /* supported ???*/
279 PluginCodec_DecodeSilence, // Can accept missing (empty) frames and generate silence
280 #endif
281
282 "CELT-32K", // text decription
283 "CELT-32K", // source format
284 "L16", // destination format
285
286 NULL, // user data
287
288 32000, // samples per second
289 32000, // raw bits per second
290 10000, // microseconds per frame
291 {{
292 320, // samples per frame
293 40, // bytes per frame
294 1, // recommended number of frames per packet
295 1, // maximum number of frames per packet
296 }},
297 0, // IANA RTP payload code
298 "CELT", // RTP payload name
299
300 celt_create_decoder, // create codec function
301 celt_destroy_decoder, // destroy codec
302 celt_codec_decoder, // encode/decode
303 celt_codec_controls, // codec controls
304
305 PluginCodec_H323Codec_NoH323,
306 NULL
307 },
308
309 /* 48 KHz */
310 {
311 // encoder
312 PLUGIN_CODEC_VERSION_OPTIONS, // codec API version
313 &licenseInfo, // license information
314
315 PluginCodec_MediaTypeAudio | // audio codec
316 PluginCodec_InputTypeRaw | // raw input data
317 PluginCodec_OutputTypeRaw | // raw output data
318 PluginCodec_RTPTypeShared |
319 PluginCodec_RTPTypeDynamic, // dynamic RTP type
320
321 "CELT-48K", // text decription
322 "L16", // source format
323 "CELT-48K", // destination format
324
325 NULL, // user data
326
327 48000, // samples per second
328 48000, // raw bits per second
329 10000, // microseconds per frame
330 {{
331 480, // samples per frame
332 60, // bytes per frame
333 1, // recommended number of frames per packet
334 1, // maximum number of frames per packet
335 }},
336 0, // IANA RTP payload code
337 "CELT", // RTP payload name
338
339 celt_create_encoder, // create codec function
340 celt_destroy_encoder, // destroy codec
341 celt_codec_encoder, // encode/decode
342 celt_codec_controls, // codec controls
343
344 PluginCodec_H323Codec_NoH323,
345 NULL
346 },
347 {
348 // decoder
349 PLUGIN_CODEC_VERSION_OPTIONS, // codec API version
350 &licenseInfo, // license information
351
352 PluginCodec_MediaTypeAudio | // audio codec
353 PluginCodec_InputTypeRaw | // raw input data
354 PluginCodec_OutputTypeRaw | // raw output data
355 PluginCodec_RTPTypeShared |
356 PluginCodec_RTPTypeDynamic, // dynamic RTP type
357
358 #if 0 /* supported ???*/
359 PluginCodec_DecodeSilence, // Can accept missing (empty) frames and generate silence
360 #endif
361
362 "CELT-48K", // text decription
363 "CELT-48K", // source format
364 "L16", // destination format
365
366 NULL, // user data
367
368 48000, // samples per second
369 48000, // raw bits per second
370 10000, // microseconds per frame
371 {{
372 480, // samples per frame
373 60, // bytes per frame
374 1, // recommended number of frames per packet
375 1, // maximum number of frames per packet
376 }},
377 0, // IANA RTP payload code
378 "CELT", // RTP payload name
379
380 celt_create_decoder, // create codec function
381 celt_destroy_decoder, // destroy codec
382 celt_codec_decoder, // encode/decode
383 celt_codec_controls, // codec controls
384
385 PluginCodec_H323Codec_NoH323,
386 NULL
387 }
388 };
389
390
391 PLUGIN_CODEC_IMPLEMENT_ALL(CELT, celtCodecDefn, PLUGIN_CODEC_VERSION_OPTIONS)
392
393 /////////////////////////////////////////////////////////////////////////////
394