1
/* $Id: ilbc.c 3553 2011-05-05 06:14:19Z nanang $ */
3
* Copyright (C) 2008-2011 Teluu Inc. (http://www.teluu.com)
4
* Copyright (C) 2003-2008 Benny Prijono <benny@prijono.org>
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.
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.
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
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>
31
#include <pj/string.h>
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
40
#include "../../third_party/ilbc/iLBC_encode.h"
41
#include "../../third_party/ilbc/iLBC_decode.h"
45
* Only build this file if PJMEDIA_HAS_ILBC_CODEC != 0
47
#if defined(PJMEDIA_HAS_ILBC_CODEC) && PJMEDIA_HAS_ILBC_CODEC != 0
50
#define THIS_FILE "ilbc.c"
51
#define CLOCK_RATE 8000
52
#define DEFAULT_MODE 30
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,
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 );
70
/* Prototypes for iLBC implementation. */
71
static pj_status_t ilbc_codec_init(pjmedia_codec *codec,
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,
81
const pj_timestamp *ts,
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);
96
/* Definition for iLBC codec operations. */
97
static pjmedia_codec_op ilbc_op =
109
/* Definition for iLBC codec factory operations. */
110
static pjmedia_codec_factory_op ilbc_factory_op =
120
static struct ilbc_factory
122
pjmedia_codec_factory base;
123
pjmedia_endpt *endpt;
130
/* iLBC codec private data. */
135
char obj_name[PJ_MAX_OBJ_NAME];
136
pjmedia_silence_det *vad;
137
pj_bool_t vad_enabled;
138
pj_bool_t plc_enabled;
139
pj_timestamp last_tx;
144
unsigned enc_frame_size;
145
unsigned enc_samples_per_frame;
146
float enc_block[BLOCKL_MAX];
150
unsigned dec_frame_size;
151
unsigned dec_samples_per_frame;
152
float dec_block[BLOCKL_MAX];
154
#if defined(PJMEDIA_ILBC_CODEC_USE_COREAUDIO)&& PJMEDIA_ILBC_CODEC_USE_COREAUDIO
155
unsigned enc_total_packets;
157
unsigned enc_buffer_offset;
159
unsigned dec_total_packets;
161
unsigned dec_buffer_offset;
165
static pj_str_t STR_MODE = {"mode", 4};
168
* Initialize and register iLBC codec factory to pjmedia endpoint.
170
PJ_DEF(pj_status_t) pjmedia_codec_ilbc_init( pjmedia_endpt *endpt,
173
pjmedia_codec_mgr *codec_mgr;
176
PJ_ASSERT_RETURN(endpt != NULL, PJ_EINVAL);
177
PJ_ASSERT_RETURN(mode==0 || mode==20 || mode==30, PJ_EINVAL);
179
/* Create iLBC codec factory. */
180
ilbc_factory.base.op = &ilbc_factory_op;
181
ilbc_factory.base.factory_data = NULL;
182
ilbc_factory.endpt = endpt;
187
ilbc_factory.mode = mode;
190
ilbc_factory.bps = 15200;
192
ilbc_factory.bps = 13333;
195
/* Get the codec manager. */
196
codec_mgr = pjmedia_endpt_get_codec_mgr(endpt);
198
return PJ_EINVALIDOP;
200
/* Register codec factory to endpoint. */
201
status = pjmedia_codec_mgr_register_factory(codec_mgr,
203
if (status != PJ_SUCCESS)
214
* Unregister iLBC codec factory from pjmedia endpoint and deinitialize
215
* the iLBC codec library.
217
PJ_DEF(pj_status_t) pjmedia_codec_ilbc_deinit(void)
219
pjmedia_codec_mgr *codec_mgr;
223
/* Get the codec manager. */
224
codec_mgr = pjmedia_endpt_get_codec_mgr(ilbc_factory.endpt);
226
return PJ_EINVALIDOP;
228
/* Unregister iLBC codec factory. */
229
status = pjmedia_codec_mgr_unregister_factory(codec_mgr,
236
* Check if factory can allocate the specified codec.
238
static pj_status_t ilbc_test_alloc( pjmedia_codec_factory *factory,
239
const pjmedia_codec_info *info )
241
const pj_str_t ilbc_tag = { "iLBC", 4};
243
PJ_UNUSED_ARG(factory);
244
PJ_ASSERT_RETURN(factory==&ilbc_factory.base, PJ_EINVAL);
247
/* Type MUST be audio. */
248
if (info->type != PJMEDIA_TYPE_AUDIO)
249
return PJMEDIA_CODEC_EUNSUP;
251
/* Check encoding name. */
252
if (pj_stricmp(&info->encoding_name, &ilbc_tag) != 0)
253
return PJMEDIA_CODEC_EUNSUP;
255
/* Check clock-rate */
256
if (info->clock_rate != CLOCK_RATE)
257
return PJMEDIA_CODEC_EUNSUP;
259
/* Channel count must be one */
260
if (info->channel_cnt != 1)
261
return PJMEDIA_CODEC_EUNSUP;
263
/* Yes, this should be iLBC! */
269
* Generate default attribute.
271
static pj_status_t ilbc_default_attr (pjmedia_codec_factory *factory,
272
const pjmedia_codec_info *id,
273
pjmedia_codec_param *attr )
275
PJ_UNUSED_ARG(factory);
276
PJ_ASSERT_RETURN(factory==&ilbc_factory.base, PJ_EINVAL);
279
PJ_ASSERT_RETURN(pj_stricmp2(&id->encoding_name, "iLBC")==0, PJ_EINVAL);
281
pj_bzero(attr, sizeof(pjmedia_codec_param));
283
attr->info.clock_rate = CLOCK_RATE;
284
attr->info.channel_cnt = 1;
285
attr->info.avg_bps = ilbc_factory.bps;
286
attr->info.max_bps = 15200;
287
attr->info.pcm_bits_per_sample = 16;
288
attr->info.frm_ptime = (short)ilbc_factory.mode;
289
attr->info.pt = PJMEDIA_RTP_PT_ILBC;
291
attr->setting.frm_per_pkt = 1;
292
attr->setting.vad = 1;
293
attr->setting.plc = 1;
294
attr->setting.penh = 1;
295
attr->setting.dec_fmtp.cnt = 1;
296
attr->setting.dec_fmtp.param[0].name = STR_MODE;
297
if (ilbc_factory.mode == 30)
298
attr->setting.dec_fmtp.param[0].val = pj_str("30");
300
attr->setting.dec_fmtp.param[0].val = pj_str("20");
306
* Enum codecs supported by this factory (i.e. only iLBC!).
308
static pj_status_t ilbc_enum_codecs(pjmedia_codec_factory *factory,
310
pjmedia_codec_info codecs[])
312
PJ_UNUSED_ARG(factory);
313
PJ_ASSERT_RETURN(factory==&ilbc_factory.base, PJ_EINVAL);
315
PJ_ASSERT_RETURN(codecs && *count > 0, PJ_EINVAL);
317
pj_bzero(&codecs[0], sizeof(pjmedia_codec_info));
319
codecs[0].encoding_name = pj_str("iLBC");
320
codecs[0].pt = PJMEDIA_RTP_PT_ILBC;
321
codecs[0].type = PJMEDIA_TYPE_AUDIO;
322
codecs[0].clock_rate = 8000;
323
codecs[0].channel_cnt = 1;
331
* Allocate a new iLBC codec instance.
333
static pj_status_t ilbc_alloc_codec(pjmedia_codec_factory *factory,
334
const pjmedia_codec_info *id,
335
pjmedia_codec **p_codec)
338
struct ilbc_codec *codec;
340
PJ_ASSERT_RETURN(factory && id && p_codec, PJ_EINVAL);
341
PJ_ASSERT_RETURN(factory == &ilbc_factory.base, PJ_EINVAL);
343
pool = pjmedia_endpt_create_pool(ilbc_factory.endpt, "iLBC%p",
345
PJ_ASSERT_RETURN(pool != NULL, PJ_ENOMEM);
347
codec = PJ_POOL_ZALLOC_T(pool, struct ilbc_codec);
348
codec->base.op = &ilbc_op;
349
codec->base.factory = factory;
352
pj_ansi_snprintf(codec->obj_name, sizeof(codec->obj_name),
355
*p_codec = &codec->base;
363
static pj_status_t ilbc_dealloc_codec( pjmedia_codec_factory *factory,
364
pjmedia_codec *codec )
366
struct ilbc_codec *ilbc_codec;
368
PJ_ASSERT_RETURN(factory && codec, PJ_EINVAL);
369
PJ_UNUSED_ARG(factory);
370
PJ_ASSERT_RETURN(factory == &ilbc_factory.base, PJ_EINVAL);
372
ilbc_codec = (struct ilbc_codec*) codec;
374
#if defined(PJMEDIA_ILBC_CODEC_USE_COREAUDIO)&& PJMEDIA_ILBC_CODEC_USE_COREAUDIO
375
if (ilbc_codec->enc) {
376
AudioConverterDispose(ilbc_codec->enc);
377
ilbc_codec->enc = NULL;
379
if (ilbc_codec->dec) {
380
AudioConverterDispose(ilbc_codec->dec);
381
ilbc_codec->dec = NULL;
385
pj_pool_release(ilbc_codec->pool);
393
static pj_status_t ilbc_codec_init(pjmedia_codec *codec,
396
PJ_UNUSED_ARG(codec);
404
static pj_status_t ilbc_codec_open(pjmedia_codec *codec,
405
pjmedia_codec_param *attr )
407
struct ilbc_codec *ilbc_codec = (struct ilbc_codec*)codec;
410
pj_uint16_t dec_fmtp_mode = DEFAULT_MODE,
411
enc_fmtp_mode = DEFAULT_MODE;
413
#if defined(PJMEDIA_ILBC_CODEC_USE_COREAUDIO)&& PJMEDIA_ILBC_CODEC_USE_COREAUDIO
414
AudioStreamBasicDescription srcFormat, dstFormat;
417
srcFormat.mSampleRate = attr->info.clock_rate;
418
srcFormat.mFormatID = kAudioFormatLinearPCM;
419
srcFormat.mFormatFlags = kLinearPCMFormatFlagIsSignedInteger
420
| kLinearPCMFormatFlagIsPacked;
421
srcFormat.mBitsPerChannel = attr->info.pcm_bits_per_sample;
422
srcFormat.mChannelsPerFrame = attr->info.channel_cnt;
423
srcFormat.mBytesPerFrame = srcFormat.mChannelsPerFrame
424
* srcFormat.mBitsPerChannel >> 3;
425
srcFormat.mFramesPerPacket = 1;
426
srcFormat.mBytesPerPacket = srcFormat.mBytesPerFrame *
427
srcFormat.mFramesPerPacket;
429
memset(&dstFormat, 0, sizeof(dstFormat));
430
dstFormat.mSampleRate = attr->info.clock_rate;
431
dstFormat.mFormatID = kAudioFormatiLBC;
432
dstFormat.mChannelsPerFrame = attr->info.channel_cnt;
435
pj_assert(ilbc_codec != NULL);
436
pj_assert(ilbc_codec->enc_ready == PJ_FALSE &&
437
ilbc_codec->dec_ready == PJ_FALSE);
439
/* Get decoder mode */
440
for (i = 0; i < attr->setting.dec_fmtp.cnt; ++i) {
441
if (pj_stricmp(&attr->setting.dec_fmtp.param[i].name, &STR_MODE) == 0)
443
dec_fmtp_mode = (pj_uint16_t)
444
pj_strtoul(&attr->setting.dec_fmtp.param[i].val);
449
/* Decoder mode must be set */
450
PJ_ASSERT_RETURN(dec_fmtp_mode == 20 || dec_fmtp_mode == 30,
451
PJMEDIA_CODEC_EINMODE);
453
/* Get encoder mode */
454
for (i = 0; i < attr->setting.enc_fmtp.cnt; ++i) {
455
if (pj_stricmp(&attr->setting.enc_fmtp.param[i].name, &STR_MODE) == 0)
457
enc_fmtp_mode = (pj_uint16_t)
458
pj_strtoul(&attr->setting.enc_fmtp.param[i].val);
463
PJ_ASSERT_RETURN(enc_fmtp_mode==20 || enc_fmtp_mode==30,
464
PJMEDIA_CODEC_EINMODE);
466
/* Both sides of a bi-directional session MUST use the same "mode" value.
467
* In this point, possible values are only 20 or 30, so when encoder and
468
* decoder modes are not same, just use the default mode, it is 30.
470
if (enc_fmtp_mode != dec_fmtp_mode) {
471
enc_fmtp_mode = dec_fmtp_mode = DEFAULT_MODE;
472
PJ_LOG(4,(ilbc_codec->obj_name,
473
"Normalized iLBC encoder and decoder modes to %d",
477
/* Update some attributes based on negotiated mode. */
478
attr->info.avg_bps = (dec_fmtp_mode == 30? 13333 : 15200);
479
attr->info.frm_ptime = dec_fmtp_mode;
482
#if defined(PJMEDIA_ILBC_CODEC_USE_COREAUDIO)&& PJMEDIA_ILBC_CODEC_USE_COREAUDIO
483
dstFormat.mFramesPerPacket = CLOCK_RATE * enc_fmtp_mode / 1000;
484
dstFormat.mBytesPerPacket = (enc_fmtp_mode == 20? 38 : 50);
486
/* Use AudioFormat API to fill out the rest of the description */
487
size = sizeof(dstFormat);
488
AudioFormatGetProperty(kAudioFormatProperty_FormatInfo,
489
0, NULL, &size, &dstFormat);
491
if (AudioConverterNew(&srcFormat, &dstFormat, &ilbc_codec->enc) != noErr)
492
return PJMEDIA_CODEC_EFAILED;
493
ilbc_codec->enc_frame_size = (enc_fmtp_mode == 20? 38 : 50);
495
ilbc_codec->enc_frame_size = initEncode(&ilbc_codec->enc, enc_fmtp_mode);
497
ilbc_codec->enc_samples_per_frame = CLOCK_RATE * enc_fmtp_mode / 1000;
498
ilbc_codec->enc_ready = PJ_TRUE;
501
#if defined(PJMEDIA_ILBC_CODEC_USE_COREAUDIO)&& PJMEDIA_ILBC_CODEC_USE_COREAUDIO
502
if (AudioConverterNew(&dstFormat, &srcFormat, &ilbc_codec->dec) != noErr)
503
return PJMEDIA_CODEC_EFAILED;
504
ilbc_codec->dec_samples_per_frame = CLOCK_RATE * dec_fmtp_mode / 1000;
506
ilbc_codec->dec_samples_per_frame = initDecode(&ilbc_codec->dec,
510
ilbc_codec->dec_frame_size = (dec_fmtp_mode == 20? 38 : 50);
511
ilbc_codec->dec_ready = PJ_TRUE;
514
ilbc_codec->plc_enabled = (attr->setting.plc != 0);
516
/* Create silence detector. */
517
ilbc_codec->vad_enabled = (attr->setting.vad != 0);
518
status = pjmedia_silence_det_create(ilbc_codec->pool, CLOCK_RATE,
519
ilbc_codec->enc_samples_per_frame,
521
if (status != PJ_SUCCESS)
524
/* Init last_tx (not necessary because of zalloc, but better
525
* be safe in case someone remove zalloc later.
527
pj_set_timestamp32(&ilbc_codec->last_tx, 0, 0);
529
PJ_LOG(5,(ilbc_codec->obj_name,
530
"iLBC codec opened, mode=%d", dec_fmtp_mode));
539
static pj_status_t ilbc_codec_close( pjmedia_codec *codec )
541
struct ilbc_codec *ilbc_codec = (struct ilbc_codec*)codec;
543
PJ_UNUSED_ARG(codec);
545
PJ_LOG(5,(ilbc_codec->obj_name, "iLBC codec closed"));
551
* Modify codec settings.
553
static pj_status_t ilbc_codec_modify(pjmedia_codec *codec,
554
const pjmedia_codec_param *attr )
556
struct ilbc_codec *ilbc_codec = (struct ilbc_codec*)codec;
558
ilbc_codec->plc_enabled = (attr->setting.plc != 0);
559
ilbc_codec->vad_enabled = (attr->setting.vad != 0);
565
* Get frames in the packet.
567
static pj_status_t ilbc_codec_parse( pjmedia_codec *codec,
570
const pj_timestamp *ts,
572
pjmedia_frame frames[])
574
struct ilbc_codec *ilbc_codec = (struct ilbc_codec*)codec;
577
PJ_ASSERT_RETURN(frame_cnt, PJ_EINVAL);
580
while (pkt_size >= ilbc_codec->dec_frame_size && count < *frame_cnt) {
581
frames[count].type = PJMEDIA_FRAME_TYPE_AUDIO;
582
frames[count].buf = pkt;
583
frames[count].size = ilbc_codec->dec_frame_size;
584
frames[count].timestamp.u64 = ts->u64 + count *
585
ilbc_codec->dec_samples_per_frame;
587
pkt = ((char*)pkt) + ilbc_codec->dec_frame_size;
588
pkt_size -= ilbc_codec->dec_frame_size;
597
#if defined(PJMEDIA_ILBC_CODEC_USE_COREAUDIO)&& PJMEDIA_ILBC_CODEC_USE_COREAUDIO
598
static OSStatus encodeDataProc (
599
AudioConverterRef inAudioConverter,
600
UInt32 *ioNumberDataPackets,
601
AudioBufferList *ioData,
602
AudioStreamPacketDescription **outDataPacketDescription,
606
struct ilbc_codec *ilbc_codec = (struct ilbc_codec*)inUserData;
608
/* Initialize in case of failure */
609
ioData->mBuffers[0].mData = NULL;
610
ioData->mBuffers[0].mDataByteSize = 0;
612
if (ilbc_codec->enc_total_packets < *ioNumberDataPackets) {
613
*ioNumberDataPackets = ilbc_codec->enc_total_packets;
616
if (*ioNumberDataPackets) {
617
ioData->mBuffers[0].mData = ilbc_codec->enc_buffer +
618
ilbc_codec->enc_buffer_offset;
619
ioData->mBuffers[0].mDataByteSize = *ioNumberDataPackets *
620
ilbc_codec->enc_samples_per_frame
622
ilbc_codec->enc_buffer_offset += ioData->mBuffers[0].mDataByteSize;
625
ilbc_codec->enc_total_packets -= *ioNumberDataPackets;
629
static OSStatus decodeDataProc (
630
AudioConverterRef inAudioConverter,
631
UInt32 *ioNumberDataPackets,
632
AudioBufferList *ioData,
633
AudioStreamPacketDescription **outDataPacketDescription,
637
struct ilbc_codec *ilbc_codec = (struct ilbc_codec*)inUserData;
639
/* Initialize in case of failure */
640
ioData->mBuffers[0].mData = NULL;
641
ioData->mBuffers[0].mDataByteSize = 0;
643
if (ilbc_codec->dec_total_packets < *ioNumberDataPackets) {
644
*ioNumberDataPackets = ilbc_codec->dec_total_packets;
647
if (*ioNumberDataPackets) {
648
ioData->mBuffers[0].mData = ilbc_codec->dec_buffer +
649
ilbc_codec->dec_buffer_offset;
650
ioData->mBuffers[0].mDataByteSize = *ioNumberDataPackets *
651
ilbc_codec->dec_frame_size;
652
ilbc_codec->dec_buffer_offset += ioData->mBuffers[0].mDataByteSize;
655
ilbc_codec->dec_total_packets -= *ioNumberDataPackets;
663
static pj_status_t ilbc_codec_encode(pjmedia_codec *codec,
664
const struct pjmedia_frame *input,
665
unsigned output_buf_len,
666
struct pjmedia_frame *output)
668
struct ilbc_codec *ilbc_codec = (struct ilbc_codec*)codec;
671
#if defined(PJMEDIA_ILBC_CODEC_USE_COREAUDIO)&& PJMEDIA_ILBC_CODEC_USE_COREAUDIO
674
AudioBufferList theABL;
677
pj_assert(ilbc_codec && input && output);
679
pcm_in = (pj_int16_t*)input->buf;
680
nsamples = input->size >> 1;
682
PJ_ASSERT_RETURN(nsamples % ilbc_codec->enc_samples_per_frame == 0,
683
PJMEDIA_CODEC_EPCMFRMINLEN);
684
PJ_ASSERT_RETURN(output_buf_len >= ilbc_codec->enc_frame_size * nsamples /
685
ilbc_codec->enc_samples_per_frame,
686
PJMEDIA_CODEC_EFRMTOOSHORT);
689
if (ilbc_codec->vad_enabled) {
690
pj_bool_t is_silence;
691
pj_int32_t silence_period;
693
silence_period = pj_timestamp_diff32(&ilbc_codec->last_tx,
696
is_silence = pjmedia_silence_det_detect(ilbc_codec->vad,
697
(const pj_int16_t*)input->buf,
701
(PJMEDIA_CODEC_MAX_SILENCE_PERIOD == -1 ||
702
silence_period < PJMEDIA_CODEC_MAX_SILENCE_PERIOD*8000/1000))
704
output->type = PJMEDIA_FRAME_TYPE_NONE;
707
output->timestamp = input->timestamp;
710
ilbc_codec->last_tx = input->timestamp;
716
#if defined(PJMEDIA_ILBC_CODEC_USE_COREAUDIO)&& PJMEDIA_ILBC_CODEC_USE_COREAUDIO
717
npackets = nsamples / ilbc_codec->enc_samples_per_frame;
719
theABL.mNumberBuffers = 1;
720
theABL.mBuffers[0].mNumberChannels = 1;
721
theABL.mBuffers[0].mDataByteSize = output_buf_len;
722
theABL.mBuffers[0].mData = output->buf;
724
ilbc_codec->enc_total_packets = npackets;
725
ilbc_codec->enc_buffer = (char *)input->buf;
726
ilbc_codec->enc_buffer_offset = 0;
728
err = AudioConverterFillComplexBuffer(ilbc_codec->enc, encodeDataProc,
729
ilbc_codec, &npackets,
732
output->size = npackets * ilbc_codec->enc_frame_size;
735
while (nsamples >= ilbc_codec->enc_samples_per_frame) {
738
/* Convert to float */
739
for (i=0; i<ilbc_codec->enc_samples_per_frame; ++i) {
740
ilbc_codec->enc_block[i] = (float) (*pcm_in++);
743
iLBC_encode((unsigned char *)output->buf + output->size,
744
ilbc_codec->enc_block,
747
output->size += ilbc_codec->enc.no_of_bytes;
748
nsamples -= ilbc_codec->enc_samples_per_frame;
752
output->type = PJMEDIA_FRAME_TYPE_AUDIO;
753
output->timestamp = input->timestamp;
761
static pj_status_t ilbc_codec_decode(pjmedia_codec *codec,
762
const struct pjmedia_frame *input,
763
unsigned output_buf_len,
764
struct pjmedia_frame *output)
766
struct ilbc_codec *ilbc_codec = (struct ilbc_codec*)codec;
767
#if defined(PJMEDIA_ILBC_CODEC_USE_COREAUDIO)&& PJMEDIA_ILBC_CODEC_USE_COREAUDIO
770
AudioBufferList theABL;
775
pj_assert(ilbc_codec != NULL);
776
PJ_ASSERT_RETURN(input && output, PJ_EINVAL);
778
if (output_buf_len < (ilbc_codec->dec_samples_per_frame << 1))
779
return PJMEDIA_CODEC_EPCMTOOSHORT;
781
if (input->size != ilbc_codec->dec_frame_size)
782
return PJMEDIA_CODEC_EFRMINLEN;
784
/* Decode to temporary buffer */
785
#if defined(PJMEDIA_ILBC_CODEC_USE_COREAUDIO)&& PJMEDIA_ILBC_CODEC_USE_COREAUDIO
786
npackets = input->size / ilbc_codec->dec_frame_size *
787
ilbc_codec->dec_samples_per_frame;
789
theABL.mNumberBuffers = 1;
790
theABL.mBuffers[0].mNumberChannels = 1;
791
theABL.mBuffers[0].mDataByteSize = output_buf_len;
792
theABL.mBuffers[0].mData = output->buf;
794
ilbc_codec->dec_total_packets = npackets;
795
ilbc_codec->dec_buffer = (char *)input->buf;
796
ilbc_codec->dec_buffer_offset = 0;
798
err = AudioConverterFillComplexBuffer(ilbc_codec->dec, decodeDataProc,
799
ilbc_codec, &npackets,
802
output->size = npackets * (ilbc_codec->dec_samples_per_frame << 1);
805
iLBC_decode(ilbc_codec->dec_block, (unsigned char*) input->buf,
806
&ilbc_codec->dec, 1);
808
/* Convert decodec samples from float to short */
809
for (i=0; i<ilbc_codec->dec_samples_per_frame; ++i) {
810
((short*)output->buf)[i] = (short)ilbc_codec->dec_block[i];
812
output->size = (ilbc_codec->dec_samples_per_frame << 1);
815
output->type = PJMEDIA_FRAME_TYPE_AUDIO;
816
output->timestamp = input->timestamp;
823
* Recover lost frame.
825
static pj_status_t ilbc_codec_recover(pjmedia_codec *codec,
826
unsigned output_buf_len,
827
struct pjmedia_frame *output)
829
struct ilbc_codec *ilbc_codec = (struct ilbc_codec*)codec;
830
#if defined(PJMEDIA_ILBC_CODEC_USE_COREAUDIO)&& PJMEDIA_ILBC_CODEC_USE_COREAUDIO
833
AudioBufferList theABL;
838
pj_assert(ilbc_codec != NULL);
839
PJ_ASSERT_RETURN(output, PJ_EINVAL);
841
if (output_buf_len < (ilbc_codec->dec_samples_per_frame << 1))
842
return PJMEDIA_CODEC_EPCMTOOSHORT;
844
/* Decode to temporary buffer */
845
#if defined(PJMEDIA_ILBC_CODEC_USE_COREAUDIO)&& PJMEDIA_ILBC_CODEC_USE_COREAUDIO
848
theABL.mNumberBuffers = 1;
849
theABL.mBuffers[0].mNumberChannels = 1;
850
theABL.mBuffers[0].mDataByteSize = output_buf_len;
851
theABL.mBuffers[0].mData = output->buf;
853
ilbc_codec->dec_total_packets = npackets;
854
ilbc_codec->dec_buffer_offset = 0;
855
if (ilbc_codec->dec_buffer) {
856
err = AudioConverterFillComplexBuffer(ilbc_codec->dec, decodeDataProc,
857
ilbc_codec, &npackets,
860
output->size = npackets *
861
(ilbc_codec->dec_samples_per_frame << 1);
864
output->size = npackets * (ilbc_codec->dec_samples_per_frame << 1);
865
pj_bzero(output->buf, output->size);
868
iLBC_decode(ilbc_codec->dec_block, NULL, &ilbc_codec->dec, 0);
870
/* Convert decodec samples from float to short */
871
for (i=0; i<ilbc_codec->dec_samples_per_frame; ++i) {
872
((short*)output->buf)[i] = (short)ilbc_codec->dec_block[i];
874
output->size = (ilbc_codec->dec_samples_per_frame << 1);
876
output->type = PJMEDIA_FRAME_TYPE_AUDIO;
882
#endif /* PJMEDIA_HAS_ILBC_CODEC */