~noskcaj/ubuntu/saucy/sflphone/merge-1.2.3-2

« back to all changes in this revision

Viewing changes to daemon/libs/pjproject/pjmedia/src/pjmedia-codec/ilbc.c

  • Committer: Jackson Doak
  • Date: 2013-07-10 21:04:46 UTC
  • mfrom: (20.1.3 sid)
  • Revision ID: noskcaj@ubuntu.com-20130710210446-y8f587vza807icr9
Properly merged from upstream.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/* $Id: ilbc.c 3553 2011-05-05 06:14:19Z nanang $ */
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
 
};
118
 
 
119
 
/* iLBC factory */
120
 
static struct ilbc_factory
121
 
{
122
 
    pjmedia_codec_factory    base;
123
 
    pjmedia_endpt           *endpt;
124
 
 
125
 
    int                      mode;
126
 
    int                      bps;
127
 
} ilbc_factory;
128
 
 
129
 
 
130
 
/* iLBC codec private data. */
131
 
struct ilbc_codec
132
 
{
133
 
    pjmedia_codec        base;
134
 
    pj_pool_t           *pool;
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;
140
 
 
141
 
 
142
 
    pj_bool_t            enc_ready;
143
 
    iLBC_Enc_Inst_t      enc;
144
 
    unsigned             enc_frame_size;
145
 
    unsigned             enc_samples_per_frame;
146
 
    float                enc_block[BLOCKL_MAX];
147
 
 
148
 
    pj_bool_t            dec_ready;
149
 
    iLBC_Dec_Inst_t      dec;
150
 
    unsigned             dec_frame_size;
151
 
    unsigned             dec_samples_per_frame;
152
 
    float                dec_block[BLOCKL_MAX];
153
 
 
154
 
#if defined(PJMEDIA_ILBC_CODEC_USE_COREAUDIO)&& PJMEDIA_ILBC_CODEC_USE_COREAUDIO
155
 
    unsigned             enc_total_packets;
156
 
    char                 *enc_buffer;
157
 
    unsigned             enc_buffer_offset;
158
 
 
159
 
    unsigned             dec_total_packets;
160
 
    char                 *dec_buffer;
161
 
    unsigned             dec_buffer_offset;
162
 
#endif
163
 
};
164
 
 
165
 
static pj_str_t STR_MODE = {"mode", 4};
166
 
 
167
 
/*
168
 
 * Initialize and register iLBC codec factory to pjmedia endpoint.
169
 
 */
170
 
PJ_DEF(pj_status_t) pjmedia_codec_ilbc_init( pjmedia_endpt *endpt,
171
 
                                             int mode )
172
 
{
173
 
    pjmedia_codec_mgr *codec_mgr;
174
 
    pj_status_t status;
175
 
 
176
 
    PJ_ASSERT_RETURN(endpt != NULL, PJ_EINVAL);
177
 
    PJ_ASSERT_RETURN(mode==0 || mode==20 || mode==30, PJ_EINVAL);
178
 
 
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;
183
 
 
184
 
    if (mode == 0)
185
 
        mode = DEFAULT_MODE;
186
 
 
187
 
    ilbc_factory.mode = mode;
188
 
 
189
 
    if (mode == 20) {
190
 
        ilbc_factory.bps = 15200;       
191
 
    } else {
192
 
        ilbc_factory.bps = 13333;
193
 
    }
194
 
 
195
 
    /* Get the codec manager. */
196
 
    codec_mgr = pjmedia_endpt_get_codec_mgr(endpt);
197
 
    if (!codec_mgr)
198
 
        return PJ_EINVALIDOP;
199
 
 
200
 
    /* Register codec factory to endpoint. */
201
 
    status = pjmedia_codec_mgr_register_factory(codec_mgr, 
202
 
                                                &ilbc_factory.base);
203
 
    if (status != PJ_SUCCESS)
204
 
        return status;
205
 
 
206
 
 
207
 
    /* Done. */
208
 
    return PJ_SUCCESS;
209
 
}
210
 
 
211
 
 
212
 
 
213
 
/*
214
 
 * Unregister iLBC codec factory from pjmedia endpoint and deinitialize
215
 
 * the iLBC codec library.
216
 
 */
217
 
PJ_DEF(pj_status_t) pjmedia_codec_ilbc_deinit(void)
218
 
{
219
 
    pjmedia_codec_mgr *codec_mgr;
220
 
    pj_status_t status;
221
 
 
222
 
 
223
 
    /* Get the codec manager. */
224
 
    codec_mgr = pjmedia_endpt_get_codec_mgr(ilbc_factory.endpt);
225
 
    if (!codec_mgr)
226
 
        return PJ_EINVALIDOP;
227
 
 
228
 
    /* Unregister iLBC codec factory. */
229
 
    status = pjmedia_codec_mgr_unregister_factory(codec_mgr,
230
 
                                                  &ilbc_factory.base);
231
 
    
232
 
    return status;
233
 
}
234
 
 
235
 
/* 
236
 
 * Check if factory can allocate the specified codec. 
237
 
 */
238
 
static pj_status_t ilbc_test_alloc( pjmedia_codec_factory *factory, 
239
 
                                   const pjmedia_codec_info *info )
240
 
{
241
 
    const pj_str_t ilbc_tag = { "iLBC", 4};
242
 
 
243
 
    PJ_UNUSED_ARG(factory);
244
 
    PJ_ASSERT_RETURN(factory==&ilbc_factory.base, PJ_EINVAL);
245
 
 
246
 
 
247
 
    /* Type MUST be audio. */
248
 
    if (info->type != PJMEDIA_TYPE_AUDIO)
249
 
        return PJMEDIA_CODEC_EUNSUP;
250
 
 
251
 
    /* Check encoding name. */
252
 
    if (pj_stricmp(&info->encoding_name, &ilbc_tag) != 0)
253
 
        return PJMEDIA_CODEC_EUNSUP;
254
 
 
255
 
    /* Check clock-rate */
256
 
    if (info->clock_rate != CLOCK_RATE)
257
 
        return PJMEDIA_CODEC_EUNSUP;
258
 
    
259
 
    /* Channel count must be one */
260
 
    if (info->channel_cnt != 1)
261
 
        return PJMEDIA_CODEC_EUNSUP;
262
 
 
263
 
    /* Yes, this should be iLBC! */
264
 
    return PJ_SUCCESS;
265
 
}
266
 
 
267
 
 
268
 
/*
269
 
 * Generate default attribute.
270
 
 */
271
 
static pj_status_t ilbc_default_attr (pjmedia_codec_factory *factory, 
272
 
                                      const pjmedia_codec_info *id, 
273
 
                                      pjmedia_codec_param *attr )
274
 
{
275
 
    PJ_UNUSED_ARG(factory);
276
 
    PJ_ASSERT_RETURN(factory==&ilbc_factory.base, PJ_EINVAL);
277
 
 
278
 
    PJ_UNUSED_ARG(id);
279
 
    PJ_ASSERT_RETURN(pj_stricmp2(&id->encoding_name, "iLBC")==0, PJ_EINVAL);
280
 
 
281
 
    pj_bzero(attr, sizeof(pjmedia_codec_param));
282
 
 
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;
290
 
 
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");
299
 
    else
300
 
        attr->setting.dec_fmtp.param[0].val = pj_str("20");
301
 
 
302
 
    return PJ_SUCCESS;
303
 
}
304
 
 
305
 
/*
306
 
 * Enum codecs supported by this factory (i.e. only iLBC!).
307
 
 */
308
 
static pj_status_t ilbc_enum_codecs(pjmedia_codec_factory *factory, 
309
 
                                    unsigned *count, 
310
 
                                    pjmedia_codec_info codecs[])
311
 
{
312
 
    PJ_UNUSED_ARG(factory);
313
 
    PJ_ASSERT_RETURN(factory==&ilbc_factory.base, PJ_EINVAL);
314
 
 
315
 
    PJ_ASSERT_RETURN(codecs && *count > 0, PJ_EINVAL);
316
 
 
317
 
    pj_bzero(&codecs[0], sizeof(pjmedia_codec_info));
318
 
 
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;
324
 
 
325
 
    *count = 1;
326
 
 
327
 
    return PJ_SUCCESS;
328
 
}
329
 
 
330
 
/*
331
 
 * Allocate a new iLBC codec instance.
332
 
 */
333
 
static pj_status_t ilbc_alloc_codec(pjmedia_codec_factory *factory, 
334
 
                                    const pjmedia_codec_info *id,
335
 
                                    pjmedia_codec **p_codec)
336
 
{
337
 
    pj_pool_t *pool;
338
 
    struct ilbc_codec *codec;
339
 
 
340
 
    PJ_ASSERT_RETURN(factory && id && p_codec, PJ_EINVAL);
341
 
    PJ_ASSERT_RETURN(factory == &ilbc_factory.base, PJ_EINVAL);
342
 
 
343
 
    pool = pjmedia_endpt_create_pool(ilbc_factory.endpt, "iLBC%p",
344
 
                                     2000, 2000);
345
 
    PJ_ASSERT_RETURN(pool != NULL, PJ_ENOMEM);
346
 
 
347
 
    codec = PJ_POOL_ZALLOC_T(pool, struct ilbc_codec);
348
 
    codec->base.op = &ilbc_op;
349
 
    codec->base.factory = factory;
350
 
    codec->pool = pool;
351
 
 
352
 
    pj_ansi_snprintf(codec->obj_name,  sizeof(codec->obj_name),
353
 
                     "ilbc%p", codec);
354
 
 
355
 
    *p_codec = &codec->base;
356
 
    return PJ_SUCCESS;
357
 
}
358
 
 
359
 
 
360
 
/*
361
 
 * Free codec.
362
 
 */
363
 
static pj_status_t ilbc_dealloc_codec( pjmedia_codec_factory *factory, 
364
 
                                      pjmedia_codec *codec )
365
 
{
366
 
    struct ilbc_codec *ilbc_codec;
367
 
 
368
 
    PJ_ASSERT_RETURN(factory && codec, PJ_EINVAL);
369
 
    PJ_UNUSED_ARG(factory);
370
 
    PJ_ASSERT_RETURN(factory == &ilbc_factory.base, PJ_EINVAL);
371
 
 
372
 
    ilbc_codec = (struct ilbc_codec*) codec;
373
 
 
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;
378
 
    }
379
 
    if (ilbc_codec->dec) {
380
 
        AudioConverterDispose(ilbc_codec->dec);
381
 
        ilbc_codec->dec = NULL;
382
 
    }
383
 
#endif
384
 
 
385
 
    pj_pool_release(ilbc_codec->pool);
386
 
 
387
 
    return PJ_SUCCESS;
388
 
}
389
 
 
390
 
/*
391
 
 * Init codec.
392
 
 */
393
 
static pj_status_t ilbc_codec_init(pjmedia_codec *codec, 
394
 
                                   pj_pool_t *pool )
395
 
{
396
 
    PJ_UNUSED_ARG(codec);
397
 
    PJ_UNUSED_ARG(pool);
398
 
    return PJ_SUCCESS;
399
 
}
400
 
 
401
 
/*
402
 
 * Open codec.
403
 
 */
404
 
static pj_status_t ilbc_codec_open(pjmedia_codec *codec, 
405
 
                                   pjmedia_codec_param *attr )
406
 
{
407
 
    struct ilbc_codec *ilbc_codec = (struct ilbc_codec*)codec;
408
 
    pj_status_t status;
409
 
    unsigned i;
410
 
    pj_uint16_t dec_fmtp_mode = DEFAULT_MODE, 
411
 
                enc_fmtp_mode = DEFAULT_MODE;
412
 
 
413
 
#if defined(PJMEDIA_ILBC_CODEC_USE_COREAUDIO)&& PJMEDIA_ILBC_CODEC_USE_COREAUDIO
414
 
    AudioStreamBasicDescription srcFormat, dstFormat;
415
 
    UInt32 size;
416
 
 
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;
428
 
 
429
 
    memset(&dstFormat, 0, sizeof(dstFormat));
430
 
    dstFormat.mSampleRate       = attr->info.clock_rate;
431
 
    dstFormat.mFormatID         = kAudioFormatiLBC;
432
 
    dstFormat.mChannelsPerFrame = attr->info.channel_cnt;
433
 
#endif
434
 
 
435
 
    pj_assert(ilbc_codec != NULL);
436
 
    pj_assert(ilbc_codec->enc_ready == PJ_FALSE && 
437
 
              ilbc_codec->dec_ready == PJ_FALSE);
438
 
 
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)
442
 
        {
443
 
            dec_fmtp_mode = (pj_uint16_t)
444
 
                            pj_strtoul(&attr->setting.dec_fmtp.param[i].val);
445
 
            break;
446
 
        }
447
 
    }
448
 
 
449
 
    /* Decoder mode must be set */
450
 
    PJ_ASSERT_RETURN(dec_fmtp_mode == 20 || dec_fmtp_mode == 30, 
451
 
                     PJMEDIA_CODEC_EINMODE);
452
 
 
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)
456
 
        {
457
 
            enc_fmtp_mode = (pj_uint16_t)
458
 
                            pj_strtoul(&attr->setting.enc_fmtp.param[i].val);
459
 
            break;
460
 
        }
461
 
    }
462
 
 
463
 
    PJ_ASSERT_RETURN(enc_fmtp_mode==20 || enc_fmtp_mode==30, 
464
 
                     PJMEDIA_CODEC_EINMODE);
465
 
 
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.
469
 
     */
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", 
474
 
                  DEFAULT_MODE));
475
 
    }
476
 
 
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;
480
 
 
481
 
    /* Create encoder */
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);
485
 
 
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);
490
 
 
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);
494
 
#else
495
 
    ilbc_codec->enc_frame_size = initEncode(&ilbc_codec->enc, enc_fmtp_mode);
496
 
#endif
497
 
    ilbc_codec->enc_samples_per_frame = CLOCK_RATE * enc_fmtp_mode / 1000;
498
 
    ilbc_codec->enc_ready = PJ_TRUE;
499
 
 
500
 
    /* Create decoder */
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;
505
 
#else
506
 
    ilbc_codec->dec_samples_per_frame = initDecode(&ilbc_codec->dec,
507
 
                                                   dec_fmtp_mode,
508
 
                                                   attr->setting.penh);
509
 
#endif
510
 
    ilbc_codec->dec_frame_size = (dec_fmtp_mode == 20? 38 : 50);
511
 
    ilbc_codec->dec_ready = PJ_TRUE;
512
 
 
513
 
    /* Save plc flags */
514
 
    ilbc_codec->plc_enabled = (attr->setting.plc != 0);
515
 
 
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,
520
 
                                        &ilbc_codec->vad);
521
 
    if (status != PJ_SUCCESS)
522
 
        return status;
523
 
 
524
 
    /* Init last_tx (not necessary because of zalloc, but better
525
 
     * be safe in case someone remove zalloc later.
526
 
     */
527
 
    pj_set_timestamp32(&ilbc_codec->last_tx, 0, 0);
528
 
 
529
 
    PJ_LOG(5,(ilbc_codec->obj_name, 
530
 
              "iLBC codec opened, mode=%d", dec_fmtp_mode));
531
 
 
532
 
    return PJ_SUCCESS;
533
 
}
534
 
 
535
 
 
536
 
/*
537
 
 * Close codec.
538
 
 */
539
 
static pj_status_t ilbc_codec_close( pjmedia_codec *codec )
540
 
{
541
 
    struct ilbc_codec *ilbc_codec = (struct ilbc_codec*)codec;
542
 
 
543
 
    PJ_UNUSED_ARG(codec);
544
 
 
545
 
    PJ_LOG(5,(ilbc_codec->obj_name, "iLBC codec closed"));
546
 
 
547
 
    return PJ_SUCCESS;
548
 
}
549
 
 
550
 
/*
551
 
 * Modify codec settings.
552
 
 */
553
 
static pj_status_t  ilbc_codec_modify(pjmedia_codec *codec, 
554
 
                                      const pjmedia_codec_param *attr )
555
 
{
556
 
    struct ilbc_codec *ilbc_codec = (struct ilbc_codec*)codec;
557
 
 
558
 
    ilbc_codec->plc_enabled = (attr->setting.plc != 0);
559
 
    ilbc_codec->vad_enabled = (attr->setting.vad != 0);
560
 
 
561
 
    return PJ_SUCCESS;
562
 
}
563
 
 
564
 
/*
565
 
 * Get frames in the packet.
566
 
 */
567
 
static pj_status_t  ilbc_codec_parse( pjmedia_codec *codec,
568
 
                                     void *pkt,
569
 
                                     pj_size_t pkt_size,
570
 
                                     const pj_timestamp *ts,
571
 
                                     unsigned *frame_cnt,
572
 
                                     pjmedia_frame frames[])
573
 
{
574
 
    struct ilbc_codec *ilbc_codec = (struct ilbc_codec*)codec;
575
 
    unsigned count;
576
 
 
577
 
    PJ_ASSERT_RETURN(frame_cnt, PJ_EINVAL);
578
 
 
579
 
    count = 0;
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;
586
 
 
587
 
        pkt = ((char*)pkt) + ilbc_codec->dec_frame_size;
588
 
        pkt_size -= ilbc_codec->dec_frame_size;
589
 
 
590
 
        ++count;
591
 
    }
592
 
 
593
 
    *frame_cnt = count;
594
 
    return PJ_SUCCESS;
595
 
}
596
 
 
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,
603
 
    void                          *inUserData
604
 
)
605
 
{
606
 
    struct ilbc_codec *ilbc_codec = (struct ilbc_codec*)inUserData;
607
 
 
608
 
    /* Initialize in case of failure */
609
 
    ioData->mBuffers[0].mData = NULL;
610
 
    ioData->mBuffers[0].mDataByteSize = 0;
611
 
 
612
 
    if (ilbc_codec->enc_total_packets < *ioNumberDataPackets) {
613
 
        *ioNumberDataPackets = ilbc_codec->enc_total_packets;
614
 
    }
615
 
 
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
621
 
                                            << 1;
622
 
        ilbc_codec->enc_buffer_offset += ioData->mBuffers[0].mDataByteSize;
623
 
    }
624
 
 
625
 
    ilbc_codec->enc_total_packets -= *ioNumberDataPackets;
626
 
    return noErr;
627
 
}
628
 
 
629
 
static OSStatus decodeDataProc (
630
 
    AudioConverterRef             inAudioConverter,
631
 
    UInt32                        *ioNumberDataPackets,
632
 
    AudioBufferList               *ioData,
633
 
    AudioStreamPacketDescription  **outDataPacketDescription,
634
 
    void                          *inUserData
635
 
)
636
 
{
637
 
    struct ilbc_codec *ilbc_codec = (struct ilbc_codec*)inUserData;
638
 
 
639
 
    /* Initialize in case of failure */
640
 
    ioData->mBuffers[0].mData = NULL;
641
 
    ioData->mBuffers[0].mDataByteSize = 0;
642
 
 
643
 
    if (ilbc_codec->dec_total_packets < *ioNumberDataPackets) {
644
 
        *ioNumberDataPackets = ilbc_codec->dec_total_packets;
645
 
    }
646
 
 
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;
653
 
    }
654
 
 
655
 
    ilbc_codec->dec_total_packets -= *ioNumberDataPackets;
656
 
    return noErr;
657
 
}
658
 
#endif
659
 
 
660
 
/*
661
 
 * Encode frame.
662
 
 */
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)
667
 
{
668
 
    struct ilbc_codec *ilbc_codec = (struct ilbc_codec*)codec;
669
 
    pj_int16_t *pcm_in;
670
 
    unsigned nsamples;
671
 
#if defined(PJMEDIA_ILBC_CODEC_USE_COREAUDIO)&& PJMEDIA_ILBC_CODEC_USE_COREAUDIO
672
 
    UInt32 npackets;
673
 
    OSStatus err;
674
 
    AudioBufferList theABL;
675
 
#endif
676
 
 
677
 
    pj_assert(ilbc_codec && input && output);
678
 
 
679
 
    pcm_in = (pj_int16_t*)input->buf;
680
 
    nsamples = input->size >> 1;
681
 
 
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);
687
 
 
688
 
    /* Detect silence */
689
 
    if (ilbc_codec->vad_enabled) {
690
 
        pj_bool_t is_silence;
691
 
        pj_int32_t silence_period;
692
 
 
693
 
        silence_period = pj_timestamp_diff32(&ilbc_codec->last_tx,
694
 
                                              &input->timestamp);
695
 
 
696
 
        is_silence = pjmedia_silence_det_detect(ilbc_codec->vad, 
697
 
                                                (const pj_int16_t*)input->buf,
698
 
                                                (input->size >> 1),
699
 
                                                NULL);
700
 
        if (is_silence &&
701
 
            (PJMEDIA_CODEC_MAX_SILENCE_PERIOD == -1 ||
702
 
             silence_period < PJMEDIA_CODEC_MAX_SILENCE_PERIOD*8000/1000))
703
 
        {
704
 
            output->type = PJMEDIA_FRAME_TYPE_NONE;
705
 
            output->buf = NULL;
706
 
            output->size = 0;
707
 
            output->timestamp = input->timestamp;
708
 
            return PJ_SUCCESS;
709
 
        } else {
710
 
            ilbc_codec->last_tx = input->timestamp;
711
 
        }
712
 
    }
713
 
 
714
 
    /* Encode */
715
 
    output->size = 0;
716
 
#if defined(PJMEDIA_ILBC_CODEC_USE_COREAUDIO)&& PJMEDIA_ILBC_CODEC_USE_COREAUDIO
717
 
    npackets = nsamples / ilbc_codec->enc_samples_per_frame;
718
 
 
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;
723
 
 
724
 
    ilbc_codec->enc_total_packets = npackets;
725
 
    ilbc_codec->enc_buffer = (char *)input->buf;
726
 
    ilbc_codec->enc_buffer_offset = 0;
727
 
 
728
 
    err = AudioConverterFillComplexBuffer(ilbc_codec->enc, encodeDataProc,
729
 
                                          ilbc_codec, &npackets,
730
 
                                          &theABL, NULL);
731
 
    if (err == noErr) {
732
 
        output->size = npackets * ilbc_codec->enc_frame_size;
733
 
    }
734
 
#else
735
 
    while (nsamples >= ilbc_codec->enc_samples_per_frame) {
736
 
        unsigned i;
737
 
        
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++);
741
 
        }
742
 
 
743
 
        iLBC_encode((unsigned char *)output->buf + output->size, 
744
 
                    ilbc_codec->enc_block, 
745
 
                    &ilbc_codec->enc);
746
 
 
747
 
        output->size += ilbc_codec->enc.no_of_bytes;
748
 
        nsamples -= ilbc_codec->enc_samples_per_frame;
749
 
    }
750
 
#endif
751
 
 
752
 
    output->type = PJMEDIA_FRAME_TYPE_AUDIO;
753
 
    output->timestamp = input->timestamp;
754
 
 
755
 
    return PJ_SUCCESS;
756
 
}
757
 
 
758
 
/*
759
 
 * Decode frame.
760
 
 */
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)
765
 
{
766
 
    struct ilbc_codec *ilbc_codec = (struct ilbc_codec*)codec;
767
 
#if defined(PJMEDIA_ILBC_CODEC_USE_COREAUDIO)&& PJMEDIA_ILBC_CODEC_USE_COREAUDIO
768
 
    UInt32 npackets;
769
 
    OSStatus err;
770
 
    AudioBufferList theABL;
771
 
#else
772
 
    unsigned i;
773
 
#endif
774
 
 
775
 
    pj_assert(ilbc_codec != NULL);
776
 
    PJ_ASSERT_RETURN(input && output, PJ_EINVAL);
777
 
 
778
 
    if (output_buf_len < (ilbc_codec->dec_samples_per_frame << 1))
779
 
        return PJMEDIA_CODEC_EPCMTOOSHORT;
780
 
 
781
 
    if (input->size != ilbc_codec->dec_frame_size)
782
 
        return PJMEDIA_CODEC_EFRMINLEN;
783
 
 
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;
788
 
 
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;
793
 
 
794
 
    ilbc_codec->dec_total_packets = npackets;
795
 
    ilbc_codec->dec_buffer = (char *)input->buf;
796
 
    ilbc_codec->dec_buffer_offset = 0;
797
 
 
798
 
    err = AudioConverterFillComplexBuffer(ilbc_codec->dec, decodeDataProc,
799
 
                                          ilbc_codec, &npackets,
800
 
                                          &theABL, NULL);
801
 
    if (err == noErr) {
802
 
        output->size = npackets * (ilbc_codec->dec_samples_per_frame << 1);
803
 
    }
804
 
#else
805
 
    iLBC_decode(ilbc_codec->dec_block, (unsigned char*) input->buf,
806
 
                &ilbc_codec->dec, 1);
807
 
 
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];
811
 
    }
812
 
    output->size = (ilbc_codec->dec_samples_per_frame << 1);
813
 
#endif
814
 
 
815
 
    output->type = PJMEDIA_FRAME_TYPE_AUDIO;
816
 
    output->timestamp = input->timestamp;
817
 
 
818
 
    return PJ_SUCCESS;
819
 
}
820
 
 
821
 
 
822
 
/*
823
 
 * Recover lost frame.
824
 
 */
825
 
static pj_status_t  ilbc_codec_recover(pjmedia_codec *codec,
826
 
                                      unsigned output_buf_len,
827
 
                                      struct pjmedia_frame *output)
828
 
{
829
 
    struct ilbc_codec *ilbc_codec = (struct ilbc_codec*)codec;
830
 
#if defined(PJMEDIA_ILBC_CODEC_USE_COREAUDIO)&& PJMEDIA_ILBC_CODEC_USE_COREAUDIO
831
 
    UInt32 npackets;
832
 
    OSStatus err;
833
 
    AudioBufferList theABL;
834
 
#else
835
 
    unsigned i;
836
 
#endif
837
 
 
838
 
    pj_assert(ilbc_codec != NULL);
839
 
    PJ_ASSERT_RETURN(output, PJ_EINVAL);
840
 
 
841
 
    if (output_buf_len < (ilbc_codec->dec_samples_per_frame << 1))
842
 
        return PJMEDIA_CODEC_EPCMTOOSHORT;
843
 
 
844
 
    /* Decode to temporary buffer */
845
 
#if defined(PJMEDIA_ILBC_CODEC_USE_COREAUDIO)&& PJMEDIA_ILBC_CODEC_USE_COREAUDIO
846
 
    npackets = 1;
847
 
 
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;
852
 
 
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,
858
 
                                              &theABL, NULL);
859
 
        if (err == noErr) {
860
 
            output->size = npackets *
861
 
                           (ilbc_codec->dec_samples_per_frame << 1);
862
 
        }
863
 
    } else {
864
 
        output->size = npackets * (ilbc_codec->dec_samples_per_frame << 1);
865
 
        pj_bzero(output->buf, output->size);
866
 
    }
867
 
#else
868
 
    iLBC_decode(ilbc_codec->dec_block, NULL, &ilbc_codec->dec, 0);
869
 
 
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];
873
 
    }
874
 
    output->size = (ilbc_codec->dec_samples_per_frame << 1);
875
 
#endif
876
 
    output->type = PJMEDIA_FRAME_TYPE_AUDIO;
877
 
 
878
 
    return PJ_SUCCESS;
879
 
}
880
 
 
881
 
 
882
 
#endif  /* PJMEDIA_HAS_ILBC_CODEC */