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