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