1 /* $Id$ */
2 /*
3 * Copyright (C) 2008-2011 Teluu Inc. (http://www.teluu.com)
4 * Copyright (C) 2003-2008 Benny Prijono <benny@prijono.org>
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 */
20 #include <pjmedia-codec/ilbc.h>
21 #include <pjmedia-codec/types.h>
22 #include <pjmedia/codec.h>
23 #include <pjmedia/errno.h>
24 #include <pjmedia/endpoint.h>
25 #include <pjmedia/plc.h>
26 #include <pjmedia/port.h>
27 #include <pjmedia/silencedet.h>
28 #include <pj/assert.h>
29 #include <pj/log.h>
30 #include <pj/pool.h>
31 #include <pj/string.h>
32 #include <pj/os.h>
33
34 #if defined(PJMEDIA_ILBC_CODEC_USE_COREAUDIO)&& PJMEDIA_ILBC_CODEC_USE_COREAUDIO
35 #include <AudioToolbox/AudioToolbox.h>
36 #define iLBC_Enc_Inst_t AudioConverterRef
37 #define iLBC_Dec_Inst_t AudioConverterRef
38 #define BLOCKL_MAX 1
39 #else
40 #include "../../third_party/ilbc/iLBC_encode.h"
41 #include "../../third_party/ilbc/iLBC_decode.h"
42 #endif
43
44 /*
45 * Only build this file if PJMEDIA_HAS_ILBC_CODEC != 0
46 */
47 #if defined(PJMEDIA_HAS_ILBC_CODEC) && PJMEDIA_HAS_ILBC_CODEC != 0
48
49
50 #define THIS_FILE "ilbc.c"
51 #define CLOCK_RATE 8000
52 #define DEFAULT_MODE 30
53
54
55 /* Prototypes for iLBC factory */
56 static pj_status_t ilbc_test_alloc(pjmedia_codec_factory *factory,
57 const pjmedia_codec_info *id );
58 static pj_status_t ilbc_default_attr(pjmedia_codec_factory *factory,
59 const pjmedia_codec_info *id,
60 pjmedia_codec_param *attr );
61 static pj_status_t ilbc_enum_codecs(pjmedia_codec_factory *factory,
62 unsigned *count,
63 pjmedia_codec_info codecs[]);
64 static pj_status_t ilbc_alloc_codec(pjmedia_codec_factory *factory,
65 const pjmedia_codec_info *id,
66 pjmedia_codec **p_codec);
67 static pj_status_t ilbc_dealloc_codec(pjmedia_codec_factory *factory,
68 pjmedia_codec *codec );
69
70 /* Prototypes for iLBC implementation. */
71 static pj_status_t ilbc_codec_init(pjmedia_codec *codec,
72 pj_pool_t *pool );
73 static pj_status_t ilbc_codec_open(pjmedia_codec *codec,
74 pjmedia_codec_param *attr );
75 static pj_status_t ilbc_codec_close(pjmedia_codec *codec );
76 static pj_status_t ilbc_codec_modify(pjmedia_codec *codec,
77 const pjmedia_codec_param *attr );
78 static pj_status_t ilbc_codec_parse(pjmedia_codec *codec,
79 void *pkt,
80 pj_size_t pkt_size,
81 const pj_timestamp *ts,
82 unsigned *frame_cnt,
83 pjmedia_frame frames[]);
84 static pj_status_t ilbc_codec_encode(pjmedia_codec *codec,
85 const struct pjmedia_frame *input,
86 unsigned output_buf_len,
87 struct pjmedia_frame *output);
88 static pj_status_t ilbc_codec_decode(pjmedia_codec *codec,
89 const struct pjmedia_frame *input,
90 unsigned output_buf_len,
91 struct pjmedia_frame *output);
92 static pj_status_t ilbc_codec_recover(pjmedia_codec *codec,
93 unsigned output_buf_len,
94 struct pjmedia_frame *output);
95
96 /* Definition for iLBC codec operations. */
97 static pjmedia_codec_op ilbc_op =
98 {
99 &ilbc_codec_init,
100 &ilbc_codec_open,
101 &ilbc_codec_close,
102 &ilbc_codec_modify,
103 &ilbc_codec_parse,
104 &ilbc_codec_encode,
105 &ilbc_codec_decode,
106 &ilbc_codec_recover
107 };
108
109 /* Definition for iLBC codec factory operations. */
110 static pjmedia_codec_factory_op ilbc_factory_op =
111 {
112 &ilbc_test_alloc,
113 &ilbc_default_attr,
114 &ilbc_enum_codecs,
115 &ilbc_alloc_codec,
116 &ilbc_dealloc_codec,
117 &pjmedia_codec_ilbc_deinit
118 };
119
120 /* iLBC factory */
121 static struct ilbc_factory
122 {
123 pjmedia_codec_factory base;
124 pjmedia_endpt *endpt;
125
126 int mode;
127 int bps;
128 } ilbc_factory;
129
130
131 /* iLBC codec private data. */
132 struct ilbc_codec
133 {
134 pjmedia_codec base;
135 pj_pool_t *pool;
136 char obj_name[PJ_MAX_OBJ_NAME];
137 pjmedia_silence_det *vad;
138 pj_bool_t vad_enabled;
139 pj_bool_t plc_enabled;
140 pj_timestamp last_tx;
141
142
143 pj_bool_t enc_ready;
144 iLBC_Enc_Inst_t enc;
145 unsigned enc_frame_size;
146 unsigned enc_samples_per_frame;
147 float enc_block[BLOCKL_MAX];
148
149 pj_bool_t dec_ready;
150 iLBC_Dec_Inst_t dec;
151 unsigned dec_frame_size;
152 unsigned dec_samples_per_frame;
153 float dec_block[BLOCKL_MAX];
154
155 #if defined(PJMEDIA_ILBC_CODEC_USE_COREAUDIO)&& PJMEDIA_ILBC_CODEC_USE_COREAUDIO
156 unsigned enc_total_packets;
157 char *enc_buffer;
158 unsigned enc_buffer_offset;
159
160 unsigned dec_total_packets;
161 char *dec_buffer;
162 unsigned dec_buffer_offset;
163 #endif
164 };
165
166 static pj_str_t STR_MODE = {"mode", 4};
167
168 /*
169 * Initialize and register iLBC codec factory to pjmedia endpoint.
170 */
pjmedia_codec_ilbc_init(pjmedia_endpt * endpt,int mode)171 PJ_DEF(pj_status_t) pjmedia_codec_ilbc_init( pjmedia_endpt *endpt,
172 int mode )
173 {
174 pjmedia_codec_mgr *codec_mgr;
175 pj_status_t status;
176
177 PJ_ASSERT_RETURN(endpt != NULL, PJ_EINVAL);
178 PJ_ASSERT_RETURN(mode==0 || mode==20 || mode==30, PJ_EINVAL);
179
180 if (ilbc_factory.endpt != NULL) {
181 /* Already initialized. */
182 return PJ_SUCCESS;
183 }
184
185 /* Create iLBC codec factory. */
186 ilbc_factory.base.op = &ilbc_factory_op;
187 ilbc_factory.base.factory_data = NULL;
188 ilbc_factory.endpt = endpt;
189
190 if (mode == 0)
191 mode = DEFAULT_MODE;
192
193 ilbc_factory.mode = mode;
194
195 if (mode == 20) {
196 ilbc_factory.bps = 15200;
197 } else {
198 ilbc_factory.bps = 13333;
199 }
200
201 /* Get the codec manager. */
202 codec_mgr = pjmedia_endpt_get_codec_mgr(endpt);
203 if (!codec_mgr) {
204 ilbc_factory.endpt = NULL;
205 return PJ_EINVALIDOP;
206 }
207
208 /* Register codec factory to endpoint. */
209 status = pjmedia_codec_mgr_register_factory(codec_mgr,
210 &ilbc_factory.base);
211 if (status != PJ_SUCCESS) {
212 ilbc_factory.endpt = NULL;
213 return status;
214 }
215
216 /* Done. */
217 return PJ_SUCCESS;
218 }
219
220
221
222 /*
223 * Unregister iLBC codec factory from pjmedia endpoint and deinitialize
224 * the iLBC codec library.
225 */
pjmedia_codec_ilbc_deinit(void)226 PJ_DEF(pj_status_t) pjmedia_codec_ilbc_deinit(void)
227 {
228 pjmedia_codec_mgr *codec_mgr;
229 pj_status_t status;
230
231 if (ilbc_factory.endpt == NULL) {
232 /* Not registered. */
233 return PJ_SUCCESS;
234 }
235
236 /* Get the codec manager. */
237 codec_mgr = pjmedia_endpt_get_codec_mgr(ilbc_factory.endpt);
238 if (!codec_mgr)
239 return PJ_EINVALIDOP;
240
241 /* Unregister iLBC codec factory. */
242 status = pjmedia_codec_mgr_unregister_factory(codec_mgr,
243 &ilbc_factory.base);
244 ilbc_factory.endpt = NULL;
245
246 return status;
247 }
248
249 /*
250 * Check if factory can allocate the specified codec.
251 */
ilbc_test_alloc(pjmedia_codec_factory * factory,const pjmedia_codec_info * info)252 static pj_status_t ilbc_test_alloc( pjmedia_codec_factory *factory,
253 const pjmedia_codec_info *info )
254 {
255 const pj_str_t ilbc_tag = { "iLBC", 4};
256
257 PJ_UNUSED_ARG(factory);
258 PJ_ASSERT_RETURN(factory==&ilbc_factory.base, PJ_EINVAL);
259
260
261 /* Type MUST be audio. */
262 if (info->type != PJMEDIA_TYPE_AUDIO)
263 return PJMEDIA_CODEC_EUNSUP;
264
265 /* Check encoding name. */
266 if (pj_stricmp(&info->encoding_name, &ilbc_tag) != 0)
267 return PJMEDIA_CODEC_EUNSUP;
268
269 /* Check clock-rate */
270 if (info->clock_rate != CLOCK_RATE)
271 return PJMEDIA_CODEC_EUNSUP;
272
273 /* Channel count must be one */
274 if (info->channel_cnt != 1)
275 return PJMEDIA_CODEC_EUNSUP;
276
277 /* Yes, this should be iLBC! */
278 return PJ_SUCCESS;
279 }
280
281
282 /*
283 * Generate default attribute.
284 */
ilbc_default_attr(pjmedia_codec_factory * factory,const pjmedia_codec_info * id,pjmedia_codec_param * attr)285 static pj_status_t ilbc_default_attr (pjmedia_codec_factory *factory,
286 const pjmedia_codec_info *id,
287 pjmedia_codec_param *attr )
288 {
289 PJ_UNUSED_ARG(factory);
290 PJ_ASSERT_RETURN(factory==&ilbc_factory.base, PJ_EINVAL);
291
292 PJ_UNUSED_ARG(id);
293 PJ_ASSERT_RETURN(pj_stricmp2(&id->encoding_name, "iLBC")==0, PJ_EINVAL);
294
295 pj_bzero(attr, sizeof(pjmedia_codec_param));
296
297 attr->info.clock_rate = CLOCK_RATE;
298 attr->info.channel_cnt = 1;
299 attr->info.avg_bps = ilbc_factory.bps;
300 attr->info.max_bps = 15200;
301 attr->info.pcm_bits_per_sample = 16;
302 attr->info.frm_ptime = (short)ilbc_factory.mode;
303 attr->info.pt = PJMEDIA_RTP_PT_ILBC;
304
305 attr->setting.frm_per_pkt = 1;
306 attr->setting.vad = 1;
307 attr->setting.plc = 1;
308 attr->setting.penh = 1;
309 attr->setting.dec_fmtp.cnt = 1;
310 attr->setting.dec_fmtp.param[0].name = STR_MODE;
311 if (ilbc_factory.mode == 30)
312 attr->setting.dec_fmtp.param[0].val = pj_str("30");
313 else
314 attr->setting.dec_fmtp.param[0].val = pj_str("20");
315
316 return PJ_SUCCESS;
317 }
318
319 /*
320 * Enum codecs supported by this factory (i.e. only iLBC!).
321 */
ilbc_enum_codecs(pjmedia_codec_factory * factory,unsigned * count,pjmedia_codec_info codecs[])322 static pj_status_t ilbc_enum_codecs(pjmedia_codec_factory *factory,
323 unsigned *count,
324 pjmedia_codec_info codecs[])
325 {
326 PJ_UNUSED_ARG(factory);
327 PJ_ASSERT_RETURN(factory==&ilbc_factory.base, PJ_EINVAL);
328
329 PJ_ASSERT_RETURN(codecs && *count > 0, PJ_EINVAL);
330
331 pj_bzero(&codecs[0], sizeof(pjmedia_codec_info));
332
333 codecs[0].encoding_name = pj_str("iLBC");
334 codecs[0].pt = PJMEDIA_RTP_PT_ILBC;
335 codecs[0].type = PJMEDIA_TYPE_AUDIO;
336 codecs[0].clock_rate = 8000;
337 codecs[0].channel_cnt = 1;
338
339 *count = 1;
340
341 return PJ_SUCCESS;
342 }
343
344 /*
345 * Allocate a new iLBC codec instance.
346 */
ilbc_alloc_codec(pjmedia_codec_factory * factory,const pjmedia_codec_info * id,pjmedia_codec ** p_codec)347 static pj_status_t ilbc_alloc_codec(pjmedia_codec_factory *factory,
348 const pjmedia_codec_info *id,
349 pjmedia_codec **p_codec)
350 {
351 pj_pool_t *pool;
352 struct ilbc_codec *codec;
353
354 PJ_ASSERT_RETURN(factory && id && p_codec, PJ_EINVAL);
355 PJ_ASSERT_RETURN(factory == &ilbc_factory.base, PJ_EINVAL);
356
357 pool = pjmedia_endpt_create_pool(ilbc_factory.endpt, "iLBC%p",
358 2000, 2000);
359 PJ_ASSERT_RETURN(pool != NULL, PJ_ENOMEM);
360
361 codec = PJ_POOL_ZALLOC_T(pool, struct ilbc_codec);
362 codec->base.op = &ilbc_op;
363 codec->base.factory = factory;
364 codec->pool = pool;
365
366 pj_ansi_snprintf(codec->obj_name, sizeof(codec->obj_name),
367 "ilbc%p", codec);
368
369 *p_codec = &codec->base;
370 return PJ_SUCCESS;
371 }
372
373
374 /*
375 * Free codec.
376 */
ilbc_dealloc_codec(pjmedia_codec_factory * factory,pjmedia_codec * codec)377 static pj_status_t ilbc_dealloc_codec( pjmedia_codec_factory *factory,
378 pjmedia_codec *codec )
379 {
380 struct ilbc_codec *ilbc_codec;
381
382 PJ_ASSERT_RETURN(factory && codec, PJ_EINVAL);
383 PJ_UNUSED_ARG(factory);
384 PJ_ASSERT_RETURN(factory == &ilbc_factory.base, PJ_EINVAL);
385
386 ilbc_codec = (struct ilbc_codec*) codec;
387
388 #if defined(PJMEDIA_ILBC_CODEC_USE_COREAUDIO)&& PJMEDIA_ILBC_CODEC_USE_COREAUDIO
389 if (ilbc_codec->enc) {
390 AudioConverterDispose(ilbc_codec->enc);
391 ilbc_codec->enc = NULL;
392 }
393 if (ilbc_codec->dec) {
394 AudioConverterDispose(ilbc_codec->dec);
395 ilbc_codec->dec = NULL;
396 }
397 #endif
398
399 pj_pool_release(ilbc_codec->pool);
400
401 return PJ_SUCCESS;
402 }
403
404 /*
405 * Init codec.
406 */
ilbc_codec_init(pjmedia_codec * codec,pj_pool_t * pool)407 static pj_status_t ilbc_codec_init(pjmedia_codec *codec,
408 pj_pool_t *pool )
409 {
410 PJ_UNUSED_ARG(codec);
411 PJ_UNUSED_ARG(pool);
412 return PJ_SUCCESS;
413 }
414
415 /*
416 * Open codec.
417 */
ilbc_codec_open(pjmedia_codec * codec,pjmedia_codec_param * attr)418 static pj_status_t ilbc_codec_open(pjmedia_codec *codec,
419 pjmedia_codec_param *attr )
420 {
421 struct ilbc_codec *ilbc_codec = (struct ilbc_codec*)codec;
422 pj_status_t status;
423 unsigned i;
424 pj_uint16_t dec_fmtp_mode = DEFAULT_MODE,
425 enc_fmtp_mode = DEFAULT_MODE;
426
427 #if defined(PJMEDIA_ILBC_CODEC_USE_COREAUDIO)&& PJMEDIA_ILBC_CODEC_USE_COREAUDIO
428 AudioStreamBasicDescription srcFormat, dstFormat;
429 UInt32 size;
430
431 srcFormat.mSampleRate = attr->info.clock_rate;
432 srcFormat.mFormatID = kAudioFormatLinearPCM;
433 srcFormat.mFormatFlags = kLinearPCMFormatFlagIsSignedInteger
434 | kLinearPCMFormatFlagIsPacked;
435 srcFormat.mBitsPerChannel = attr->info.pcm_bits_per_sample;
436 srcFormat.mChannelsPerFrame = attr->info.channel_cnt;
437 srcFormat.mBytesPerFrame = srcFormat.mChannelsPerFrame
438 * srcFormat.mBitsPerChannel >> 3;
439 srcFormat.mFramesPerPacket = 1;
440 srcFormat.mBytesPerPacket = srcFormat.mBytesPerFrame *
441 srcFormat.mFramesPerPacket;
442
443 memset(&dstFormat, 0, sizeof(dstFormat));
444 dstFormat.mSampleRate = attr->info.clock_rate;
445 dstFormat.mFormatID = kAudioFormatiLBC;
446 dstFormat.mChannelsPerFrame = attr->info.channel_cnt;
447 #endif
448
449 pj_assert(ilbc_codec != NULL);
450 pj_assert(ilbc_codec->enc_ready == PJ_FALSE &&
451 ilbc_codec->dec_ready == PJ_FALSE);
452
453 /* Get decoder mode */
454 for (i = 0; i < attr->setting.dec_fmtp.cnt; ++i) {
455 if (pj_stricmp(&attr->setting.dec_fmtp.param[i].name, &STR_MODE) == 0)
456 {
457 dec_fmtp_mode = (pj_uint16_t)
458 pj_strtoul(&attr->setting.dec_fmtp.param[i].val);
459 break;
460 }
461 }
462
463 /* Decoder mode must be set */
464 PJ_ASSERT_RETURN(dec_fmtp_mode == 20 || dec_fmtp_mode == 30,
465 PJMEDIA_CODEC_EINMODE);
466
467 /* Get encoder mode */
468 for (i = 0; i < attr->setting.enc_fmtp.cnt; ++i) {
469 if (pj_stricmp(&attr->setting.enc_fmtp.param[i].name, &STR_MODE) == 0)
470 {
471 enc_fmtp_mode = (pj_uint16_t)
472 pj_strtoul(&attr->setting.enc_fmtp.param[i].val);
473 break;
474 }
475 }
476
477 PJ_ASSERT_RETURN(enc_fmtp_mode==20 || enc_fmtp_mode==30,
478 PJMEDIA_CODEC_EINMODE);
479
480 /* Both sides of a bi-directional session MUST use the same "mode" value.
481 * In this point, possible values are only 20 or 30, so when encoder and
482 * decoder modes are not same, just use the default mode, it is 30.
483 */
484 if (enc_fmtp_mode != dec_fmtp_mode) {
485 enc_fmtp_mode = dec_fmtp_mode = DEFAULT_MODE;
486 PJ_LOG(4,(ilbc_codec->obj_name,
487 "Normalized iLBC encoder and decoder modes to %d",
488 DEFAULT_MODE));
489 }
490
491 /* Update some attributes based on negotiated mode. */
492 attr->info.avg_bps = (dec_fmtp_mode == 30? 13333 : 15200);
493 attr->info.frm_ptime = dec_fmtp_mode;
494
495 /* Create encoder */
496 #if defined(PJMEDIA_ILBC_CODEC_USE_COREAUDIO)&& PJMEDIA_ILBC_CODEC_USE_COREAUDIO
497 dstFormat.mFramesPerPacket = CLOCK_RATE * enc_fmtp_mode / 1000;
498 dstFormat.mBytesPerPacket = (enc_fmtp_mode == 20? 38 : 50);
499
500 /* Use AudioFormat API to fill out the rest of the description */
501 size = sizeof(dstFormat);
502 AudioFormatGetProperty(kAudioFormatProperty_FormatInfo,
503 0, NULL, &size, &dstFormat);
504
505 if (AudioConverterNew(&srcFormat, &dstFormat, &ilbc_codec->enc) != noErr)
506 return PJMEDIA_CODEC_EFAILED;
507 ilbc_codec->enc_frame_size = (enc_fmtp_mode == 20? 38 : 50);
508 #else
509 ilbc_codec->enc_frame_size = initEncode(&ilbc_codec->enc, enc_fmtp_mode);
510 #endif
511 ilbc_codec->enc_samples_per_frame = CLOCK_RATE * enc_fmtp_mode / 1000;
512 ilbc_codec->enc_ready = PJ_TRUE;
513
514 /* Create decoder */
515 #if defined(PJMEDIA_ILBC_CODEC_USE_COREAUDIO)&& PJMEDIA_ILBC_CODEC_USE_COREAUDIO
516 if (AudioConverterNew(&dstFormat, &srcFormat, &ilbc_codec->dec) != noErr)
517 return PJMEDIA_CODEC_EFAILED;
518 ilbc_codec->dec_samples_per_frame = CLOCK_RATE * dec_fmtp_mode / 1000;
519 #else
520 ilbc_codec->dec_samples_per_frame = initDecode(&ilbc_codec->dec,
521 dec_fmtp_mode,
522 attr->setting.penh);
523 #endif
524 ilbc_codec->dec_frame_size = (dec_fmtp_mode == 20? 38 : 50);
525 ilbc_codec->dec_ready = PJ_TRUE;
526
527 /* Save plc flags */
528 ilbc_codec->plc_enabled = (attr->setting.plc != 0);
529
530 /* Create silence detector. */
531 ilbc_codec->vad_enabled = (attr->setting.vad != 0);
532 status = pjmedia_silence_det_create(ilbc_codec->pool, CLOCK_RATE,
533 ilbc_codec->enc_samples_per_frame,
534 &ilbc_codec->vad);
535 if (status != PJ_SUCCESS)
536 return status;
537
538 /* Init last_tx (not necessary because of zalloc, but better
539 * be safe in case someone remove zalloc later.
540 */
541 pj_set_timestamp32(&ilbc_codec->last_tx, 0, 0);
542
543 PJ_LOG(4,(ilbc_codec->obj_name,
544 "iLBC codec opened, mode=%d", dec_fmtp_mode));
545
546 return PJ_SUCCESS;
547 }
548
549
550 /*
551 * Close codec.
552 */
ilbc_codec_close(pjmedia_codec * codec)553 static pj_status_t ilbc_codec_close( pjmedia_codec *codec )
554 {
555 struct ilbc_codec *ilbc_codec = (struct ilbc_codec*)codec;
556
557 PJ_UNUSED_ARG(codec);
558
559 PJ_LOG(5,(ilbc_codec->obj_name, "iLBC codec closed"));
560
561 return PJ_SUCCESS;
562 }
563
564 /*
565 * Modify codec settings.
566 */
ilbc_codec_modify(pjmedia_codec * codec,const pjmedia_codec_param * attr)567 static pj_status_t ilbc_codec_modify(pjmedia_codec *codec,
568 const pjmedia_codec_param *attr )
569 {
570 struct ilbc_codec *ilbc_codec = (struct ilbc_codec*)codec;
571
572 ilbc_codec->plc_enabled = (attr->setting.plc != 0);
573 ilbc_codec->vad_enabled = (attr->setting.vad != 0);
574
575 return PJ_SUCCESS;
576 }
577
578 /*
579 * Get frames in the packet.
580 */
ilbc_codec_parse(pjmedia_codec * codec,void * pkt,pj_size_t pkt_size,const pj_timestamp * ts,unsigned * frame_cnt,pjmedia_frame frames[])581 static pj_status_t ilbc_codec_parse( pjmedia_codec *codec,
582 void *pkt,
583 pj_size_t pkt_size,
584 const pj_timestamp *ts,
585 unsigned *frame_cnt,
586 pjmedia_frame frames[])
587 {
588 struct ilbc_codec *ilbc_codec = (struct ilbc_codec*)codec;
589 unsigned count;
590
591 PJ_ASSERT_RETURN(frame_cnt, PJ_EINVAL);
592
593 count = 0;
594 while (pkt_size >= ilbc_codec->dec_frame_size && count < *frame_cnt) {
595 frames[count].type = PJMEDIA_FRAME_TYPE_AUDIO;
596 frames[count].buf = pkt;
597 frames[count].size = ilbc_codec->dec_frame_size;
598 frames[count].timestamp.u64 = ts->u64 + (pj_uint64_t)count *
599 ilbc_codec->dec_samples_per_frame;
600
601 pkt = ((char*)pkt) + ilbc_codec->dec_frame_size;
602 pkt_size -= ilbc_codec->dec_frame_size;
603
604 ++count;
605 }
606
607 *frame_cnt = count;
608 return PJ_SUCCESS;
609 }
610
611 #if defined(PJMEDIA_ILBC_CODEC_USE_COREAUDIO)&& PJMEDIA_ILBC_CODEC_USE_COREAUDIO
encodeDataProc(AudioConverterRef inAudioConverter,UInt32 * ioNumberDataPackets,AudioBufferList * ioData,AudioStreamPacketDescription ** outDataPacketDescription,void * inUserData)612 static OSStatus encodeDataProc (
613 AudioConverterRef inAudioConverter,
614 UInt32 *ioNumberDataPackets,
615 AudioBufferList *ioData,
616 AudioStreamPacketDescription **outDataPacketDescription,
617 void *inUserData
618 )
619 {
620 struct ilbc_codec *ilbc_codec = (struct ilbc_codec*)inUserData;
621
622 /* Initialize in case of failure */
623 ioData->mBuffers[0].mData = NULL;
624 ioData->mBuffers[0].mDataByteSize = 0;
625
626 if (ilbc_codec->enc_total_packets < *ioNumberDataPackets) {
627 *ioNumberDataPackets = ilbc_codec->enc_total_packets;
628 }
629
630 if (*ioNumberDataPackets) {
631 ioData->mBuffers[0].mData = ilbc_codec->enc_buffer +
632 ilbc_codec->enc_buffer_offset;
633 ioData->mBuffers[0].mDataByteSize = *ioNumberDataPackets *
634 ilbc_codec->enc_samples_per_frame
635 << 1;
636 ilbc_codec->enc_buffer_offset += ioData->mBuffers[0].mDataByteSize;
637 }
638
639 ilbc_codec->enc_total_packets -= *ioNumberDataPackets;
640 return noErr;
641 }
642
decodeDataProc(AudioConverterRef inAudioConverter,UInt32 * ioNumberDataPackets,AudioBufferList * ioData,AudioStreamPacketDescription ** outDataPacketDescription,void * inUserData)643 static OSStatus decodeDataProc (
644 AudioConverterRef inAudioConverter,
645 UInt32 *ioNumberDataPackets,
646 AudioBufferList *ioData,
647 AudioStreamPacketDescription **outDataPacketDescription,
648 void *inUserData
649 )
650 {
651 struct ilbc_codec *ilbc_codec = (struct ilbc_codec*)inUserData;
652
653 /* Initialize in case of failure */
654 ioData->mBuffers[0].mData = NULL;
655 ioData->mBuffers[0].mDataByteSize = 0;
656
657 if (ilbc_codec->dec_total_packets < *ioNumberDataPackets) {
658 *ioNumberDataPackets = ilbc_codec->dec_total_packets;
659 }
660
661 if (*ioNumberDataPackets) {
662 ioData->mBuffers[0].mData = ilbc_codec->dec_buffer +
663 ilbc_codec->dec_buffer_offset;
664 ioData->mBuffers[0].mDataByteSize = *ioNumberDataPackets *
665 ilbc_codec->dec_frame_size;
666 ilbc_codec->dec_buffer_offset += ioData->mBuffers[0].mDataByteSize;
667 }
668
669 ilbc_codec->dec_total_packets -= *ioNumberDataPackets;
670 return noErr;
671 }
672 #endif
673
674 /*
675 * Encode frame.
676 */
ilbc_codec_encode(pjmedia_codec * codec,const struct pjmedia_frame * input,unsigned output_buf_len,struct pjmedia_frame * output)677 static pj_status_t ilbc_codec_encode(pjmedia_codec *codec,
678 const struct pjmedia_frame *input,
679 unsigned output_buf_len,
680 struct pjmedia_frame *output)
681 {
682 struct ilbc_codec *ilbc_codec = (struct ilbc_codec*)codec;
683 pj_int16_t *pcm_in;
684 pj_size_t nsamples;
685
686 pj_assert(ilbc_codec && input && output);
687
688 pcm_in = (pj_int16_t*)input->buf;
689 nsamples = input->size >> 1;
690
691 PJ_ASSERT_RETURN(nsamples % ilbc_codec->enc_samples_per_frame == 0,
692 PJMEDIA_CODEC_EPCMFRMINLEN);
693 PJ_ASSERT_RETURN(output_buf_len >= ilbc_codec->enc_frame_size * nsamples /
694 ilbc_codec->enc_samples_per_frame,
695 PJMEDIA_CODEC_EFRMTOOSHORT);
696
697 /* Detect silence */
698 if (ilbc_codec->vad_enabled) {
699 pj_bool_t is_silence;
700 pj_int32_t silence_period;
701
702 silence_period = pj_timestamp_diff32(&ilbc_codec->last_tx,
703 &input->timestamp);
704
705 is_silence = pjmedia_silence_det_detect(ilbc_codec->vad,
706 (const pj_int16_t*)input->buf,
707 (input->size >> 1),
708 NULL);
709 if (is_silence &&
710 (PJMEDIA_CODEC_MAX_SILENCE_PERIOD == -1 ||
711 silence_period < PJMEDIA_CODEC_MAX_SILENCE_PERIOD*8000/1000))
712 {
713 output->type = PJMEDIA_FRAME_TYPE_NONE;
714 output->buf = NULL;
715 output->size = 0;
716 output->timestamp = input->timestamp;
717 return PJ_SUCCESS;
718 } else {
719 ilbc_codec->last_tx = input->timestamp;
720 }
721 }
722
723 /* Encode */
724 output->size = 0;
725 while (nsamples >= ilbc_codec->enc_samples_per_frame) {
726 #if defined(PJMEDIA_ILBC_CODEC_USE_COREAUDIO)&& PJMEDIA_ILBC_CODEC_USE_COREAUDIO
727 OSStatus err;
728 AudioBufferList theABL;
729 UInt32 npackets = 1;
730
731 theABL.mNumberBuffers = 1;
732 theABL.mBuffers[0].mNumberChannels = 1;
733 theABL.mBuffers[0].mDataByteSize = output_buf_len;
734 theABL.mBuffers[0].mData = output->buf + output->size;
735
736 ilbc_codec->enc_total_packets = 1;
737 ilbc_codec->enc_buffer = (char *)input->buf;
738 ilbc_codec->enc_buffer_offset = input->size - (nsamples << 1);
739
740 err = AudioConverterFillComplexBuffer(ilbc_codec->enc, encodeDataProc,
741 ilbc_codec, &npackets,
742 &theABL, NULL);
743 if (err == noErr && npackets) {
744 output->size += npackets * ilbc_codec->enc_frame_size;
745 }
746 #else
747 unsigned i;
748
749 /* Convert to float */
750 for (i=0; i<ilbc_codec->enc_samples_per_frame; ++i) {
751 ilbc_codec->enc_block[i] = (float) (*pcm_in++);
752 }
753
754 iLBC_encode((unsigned char *)output->buf + output->size,
755 ilbc_codec->enc_block,
756 &ilbc_codec->enc);
757
758 output->size += ilbc_codec->enc.no_of_bytes;
759 #endif
760
761 nsamples -= ilbc_codec->enc_samples_per_frame;
762 }
763
764 output->type = PJMEDIA_FRAME_TYPE_AUDIO;
765 output->timestamp = input->timestamp;
766
767 return PJ_SUCCESS;
768 }
769
770 /*
771 * Decode frame.
772 */
ilbc_codec_decode(pjmedia_codec * codec,const struct pjmedia_frame * input,unsigned output_buf_len,struct pjmedia_frame * output)773 static pj_status_t ilbc_codec_decode(pjmedia_codec *codec,
774 const struct pjmedia_frame *input,
775 unsigned output_buf_len,
776 struct pjmedia_frame *output)
777 {
778 struct ilbc_codec *ilbc_codec = (struct ilbc_codec*)codec;
779 #if defined(PJMEDIA_ILBC_CODEC_USE_COREAUDIO)&& PJMEDIA_ILBC_CODEC_USE_COREAUDIO
780 UInt32 npackets;
781 OSStatus err;
782 AudioBufferList theABL;
783 #else
784 unsigned i;
785 #endif
786
787 pj_assert(ilbc_codec != NULL);
788 PJ_ASSERT_RETURN(input && output, PJ_EINVAL);
789
790 if (output_buf_len < (ilbc_codec->dec_samples_per_frame << 1))
791 return PJMEDIA_CODEC_EPCMTOOSHORT;
792
793 if (input->size != ilbc_codec->dec_frame_size)
794 return PJMEDIA_CODEC_EFRMINLEN;
795
796 /* Decode to temporary buffer */
797 #if defined(PJMEDIA_ILBC_CODEC_USE_COREAUDIO)&& PJMEDIA_ILBC_CODEC_USE_COREAUDIO
798 npackets = input->size / ilbc_codec->dec_frame_size *
799 ilbc_codec->dec_samples_per_frame;
800
801 theABL.mNumberBuffers = 1;
802 theABL.mBuffers[0].mNumberChannels = 1;
803 theABL.mBuffers[0].mDataByteSize = output_buf_len;
804 theABL.mBuffers[0].mData = output->buf;
805
806 ilbc_codec->dec_total_packets = npackets;
807 ilbc_codec->dec_buffer = (char *)input->buf;
808 ilbc_codec->dec_buffer_offset = 0;
809
810 err = AudioConverterFillComplexBuffer(ilbc_codec->dec, decodeDataProc,
811 ilbc_codec, &npackets,
812 &theABL, NULL);
813 if (err == noErr) {
814 output->size = npackets * (ilbc_codec->dec_samples_per_frame << 1);
815 }
816 #else
817 iLBC_decode(ilbc_codec->dec_block, (unsigned char*) input->buf,
818 &ilbc_codec->dec, 1);
819
820 /* Convert decodec samples from float to short */
821 for (i=0; i<ilbc_codec->dec_samples_per_frame; ++i) {
822 ((short*)output->buf)[i] = (short)ilbc_codec->dec_block[i];
823 }
824 output->size = (ilbc_codec->dec_samples_per_frame << 1);
825 #endif
826
827 output->type = PJMEDIA_FRAME_TYPE_AUDIO;
828 output->timestamp = input->timestamp;
829
830 return PJ_SUCCESS;
831 }
832
833
834 /*
835 * Recover lost frame.
836 */
ilbc_codec_recover(pjmedia_codec * codec,unsigned output_buf_len,struct pjmedia_frame * output)837 static pj_status_t ilbc_codec_recover(pjmedia_codec *codec,
838 unsigned output_buf_len,
839 struct pjmedia_frame *output)
840 {
841 struct ilbc_codec *ilbc_codec = (struct ilbc_codec*)codec;
842 #if defined(PJMEDIA_ILBC_CODEC_USE_COREAUDIO)&& PJMEDIA_ILBC_CODEC_USE_COREAUDIO
843 UInt32 npackets;
844 OSStatus err;
845 AudioBufferList theABL;
846 #else
847 unsigned i;
848 #endif
849
850 pj_assert(ilbc_codec != NULL);
851 PJ_ASSERT_RETURN(output, PJ_EINVAL);
852
853 if (output_buf_len < (ilbc_codec->dec_samples_per_frame << 1))
854 return PJMEDIA_CODEC_EPCMTOOSHORT;
855
856 /* Decode to temporary buffer */
857 #if defined(PJMEDIA_ILBC_CODEC_USE_COREAUDIO)&& PJMEDIA_ILBC_CODEC_USE_COREAUDIO
858 npackets = 1;
859
860 theABL.mNumberBuffers = 1;
861 theABL.mBuffers[0].mNumberChannels = 1;
862 theABL.mBuffers[0].mDataByteSize = output_buf_len;
863 theABL.mBuffers[0].mData = output->buf;
864
865 ilbc_codec->dec_total_packets = npackets;
866 ilbc_codec->dec_buffer_offset = 0;
867 if (ilbc_codec->dec_buffer) {
868 err = AudioConverterFillComplexBuffer(ilbc_codec->dec, decodeDataProc,
869 ilbc_codec, &npackets,
870 &theABL, NULL);
871 if (err == noErr) {
872 output->size = npackets *
873 (ilbc_codec->dec_samples_per_frame << 1);
874 }
875 } else {
876 output->size = npackets * (ilbc_codec->dec_samples_per_frame << 1);
877 pj_bzero(output->buf, output->size);
878 }
879 #else
880 iLBC_decode(ilbc_codec->dec_block, NULL, &ilbc_codec->dec, 0);
881
882 /* Convert decodec samples from float to short */
883 for (i=0; i<ilbc_codec->dec_samples_per_frame; ++i) {
884 ((short*)output->buf)[i] = (short)ilbc_codec->dec_block[i];
885 }
886 output->size = (ilbc_codec->dec_samples_per_frame << 1);
887 #endif
888 output->type = PJMEDIA_FRAME_TYPE_AUDIO;
889
890 return PJ_SUCCESS;
891 }
892
893
894 #endif /* PJMEDIA_HAS_ILBC_CODEC */
895