~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/passthrough.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: passthrough.c 4063 2012-04-20 03:19:42Z 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/passthrough.h>
21
 
#include <pjmedia/codec.h>
22
 
#include <pjmedia/errno.h>
23
 
#include <pjmedia/endpoint.h>
24
 
#include <pjmedia/port.h>
25
 
#include <pj/assert.h>
26
 
#include <pj/log.h>
27
 
#include <pj/math.h>
28
 
#include <pj/pool.h>
29
 
#include <pj/string.h>
30
 
#include <pj/os.h>
31
 
 
32
 
/*
33
 
 * Only build this file if PJMEDIA_HAS_PASSTHROUGH_CODECS != 0
34
 
 */
35
 
#if defined(PJMEDIA_HAS_PASSTHROUGH_CODECS) && PJMEDIA_HAS_PASSTHROUGH_CODECS!=0
36
 
 
37
 
#define THIS_FILE   "passthrough.c"
38
 
 
39
 
 
40
 
/* Prototypes for passthrough codecs factory */
41
 
static pj_status_t test_alloc( pjmedia_codec_factory *factory, 
42
 
                               const pjmedia_codec_info *id );
43
 
static pj_status_t default_attr( pjmedia_codec_factory *factory, 
44
 
                                 const pjmedia_codec_info *id, 
45
 
                                 pjmedia_codec_param *attr );
46
 
static pj_status_t enum_codecs( pjmedia_codec_factory *factory, 
47
 
                                unsigned *count, 
48
 
                                pjmedia_codec_info codecs[]);
49
 
static pj_status_t alloc_codec( pjmedia_codec_factory *factory, 
50
 
                                const pjmedia_codec_info *id, 
51
 
                                pjmedia_codec **p_codec);
52
 
static pj_status_t dealloc_codec( pjmedia_codec_factory *factory, 
53
 
                                  pjmedia_codec *codec );
54
 
 
55
 
/* Prototypes for passthrough codecs implementation. */
56
 
static pj_status_t codec_init( pjmedia_codec *codec, 
57
 
                               pj_pool_t *pool );
58
 
static pj_status_t codec_open( pjmedia_codec *codec, 
59
 
                               pjmedia_codec_param *attr );
60
 
static pj_status_t codec_close( pjmedia_codec *codec );
61
 
static pj_status_t codec_modify(pjmedia_codec *codec, 
62
 
                                const pjmedia_codec_param *attr );
63
 
static pj_status_t codec_parse( pjmedia_codec *codec,
64
 
                                void *pkt,
65
 
                                pj_size_t pkt_size,
66
 
                                const pj_timestamp *ts,
67
 
                                unsigned *frame_cnt,
68
 
                                pjmedia_frame frames[]);
69
 
static pj_status_t codec_encode( pjmedia_codec *codec, 
70
 
                                 const struct pjmedia_frame *input,
71
 
                                 unsigned output_buf_len,
72
 
                                 struct pjmedia_frame *output);
73
 
static pj_status_t codec_decode( pjmedia_codec *codec,
74
 
                                 const struct pjmedia_frame *input,
75
 
                                 unsigned output_buf_len, 
76
 
                                 struct pjmedia_frame *output);
77
 
static pj_status_t codec_recover( pjmedia_codec *codec, 
78
 
                                  unsigned output_buf_len, 
79
 
                                  struct pjmedia_frame *output);
80
 
 
81
 
/* Definition for passthrough codecs operations. */
82
 
static pjmedia_codec_op codec_op = 
83
 
{
84
 
    &codec_init,
85
 
    &codec_open,
86
 
    &codec_close,
87
 
    &codec_modify,
88
 
    &codec_parse,
89
 
    &codec_encode,
90
 
    &codec_decode,
91
 
    &codec_recover
92
 
};
93
 
 
94
 
/* Definition for passthrough codecs factory operations. */
95
 
static pjmedia_codec_factory_op codec_factory_op =
96
 
{
97
 
    &test_alloc,
98
 
    &default_attr,
99
 
    &enum_codecs,
100
 
    &alloc_codec,
101
 
    &dealloc_codec
102
 
};
103
 
 
104
 
/* Passthrough codecs factory */
105
 
static struct codec_factory {
106
 
    pjmedia_codec_factory    base;
107
 
    pjmedia_endpt           *endpt;
108
 
    pj_pool_t               *pool;
109
 
    pj_mutex_t              *mutex;
110
 
} codec_factory;
111
 
 
112
 
/* Passthrough codecs private data. */
113
 
typedef struct codec_private {
114
 
    pj_pool_t           *pool;              /**< Pool for each instance.    */
115
 
    int                  codec_idx;         /**< Codec index.               */
116
 
    void                *codec_setting;     /**< Specific codec setting.    */
117
 
    pj_uint16_t          avg_frame_size;    /**< Average of frame size.     */
118
 
    unsigned             samples_per_frame; /**< Samples per frame, for iLBC
119
 
                                                 this can be 240 or 160, can
120
 
                                                 only be known after codec is
121
 
                                                 opened.                    */
122
 
} codec_private_t;
123
 
 
124
 
 
125
 
 
126
 
/* CUSTOM CALLBACKS */
127
 
 
128
 
/* Parse frames from a packet. Default behaviour of frame parsing is 
129
 
 * just separating frames based on calculating frame length derived 
130
 
 * from bitrate. Implement this callback when the default behaviour is 
131
 
 * unapplicable.
132
 
 */
133
 
typedef pj_status_t (*parse_cb)(codec_private_t *codec_data, void *pkt, 
134
 
                                pj_size_t pkt_size, const pj_timestamp *ts,
135
 
                                unsigned *frame_cnt, pjmedia_frame frames[]);
136
 
 
137
 
/* Pack frames into a packet. Default behaviour of packing frames is 
138
 
 * just stacking the frames with octet aligned without adding any 
139
 
 * payload header. Implement this callback when the default behaviour is
140
 
 * unapplicable.
141
 
 */
142
 
typedef pj_status_t (*pack_cb)(codec_private_t *codec_data, 
143
 
                               const struct pjmedia_frame_ext *input,
144
 
                               unsigned output_buf_len, 
145
 
                               struct pjmedia_frame *output);
146
 
 
147
 
 
148
 
/* Custom callback implementations. */
149
 
static pj_status_t parse_amr( codec_private_t *codec_data, void *pkt, 
150
 
                              pj_size_t pkt_size, const pj_timestamp *ts,
151
 
                              unsigned *frame_cnt, pjmedia_frame frames[]);
152
 
static pj_status_t pack_amr ( codec_private_t *codec_data,
153
 
                              const struct pjmedia_frame_ext *input,
154
 
                              unsigned output_buf_len, 
155
 
                              struct pjmedia_frame *output);
156
 
 
157
 
 
158
 
/* Passthrough codec implementation descriptions. */
159
 
static struct codec_desc {
160
 
    int              enabled;           /* Is this codec enabled?           */
161
 
    const char      *name;              /* Codec name.                      */
162
 
    pj_uint8_t       pt;                /* Payload type.                    */
163
 
    pjmedia_format_id fmt_id;           /* Source format.                   */
164
 
    unsigned         clock_rate;        /* Codec's clock rate.              */
165
 
    unsigned         channel_count;     /* Codec's channel count.           */
166
 
    unsigned         samples_per_frame; /* Codec's samples count.           */
167
 
    unsigned         def_bitrate;       /* Default bitrate of this codec.   */
168
 
    unsigned         max_bitrate;       /* Maximum bitrate of this codec.   */
169
 
    pj_uint8_t       frm_per_pkt;       /* Default num of frames per packet.*/
170
 
    pj_uint8_t       vad;               /* VAD enabled/disabled.            */
171
 
    pj_uint8_t       plc;               /* PLC enabled/disabled.            */
172
 
    parse_cb         parse;             /* Callback to parse bitstream.     */
173
 
    pack_cb          pack;              /* Callback to pack bitstream.      */
174
 
    pjmedia_codec_fmtp dec_fmtp;        /* Decoder's fmtp params.           */
175
 
}
176
 
 
177
 
codec_desc[] = 
178
 
{
179
 
#   if PJMEDIA_HAS_PASSTHROUGH_CODEC_AMR
180
 
    {1, "AMR",      PJMEDIA_RTP_PT_AMR,       PJMEDIA_FORMAT_AMR,
181
 
                    8000, 1, 160, 
182
 
                    7400, 12200, 2, 1, 1,
183
 
                    &parse_amr, &pack_amr
184
 
                    /*, {1, {{{"octet-align", 11}, {"1", 1}}} } */
185
 
    },
186
 
#   endif
187
 
 
188
 
#   if PJMEDIA_HAS_PASSTHROUGH_CODEC_G729
189
 
    {1, "G729",     PJMEDIA_RTP_PT_G729,      PJMEDIA_FORMAT_G729,
190
 
                    8000, 1,  80,
191
 
                    8000, 8000, 2, 1, 1
192
 
    },
193
 
#   endif
194
 
 
195
 
#   if PJMEDIA_HAS_PASSTHROUGH_CODEC_ILBC
196
 
    {1, "iLBC",     PJMEDIA_RTP_PT_ILBC,      PJMEDIA_FORMAT_ILBC,
197
 
                    8000, 1,  240,
198
 
                    13333, 15200, 1, 1, 1,
199
 
                    NULL, NULL,
200
 
                    {1, {{{"mode", 4}, {"30", 2}}} }
201
 
    },
202
 
#   endif
203
 
 
204
 
#   if PJMEDIA_HAS_PASSTHROUGH_CODEC_PCMU
205
 
    {1, "PCMU",     PJMEDIA_RTP_PT_PCMU,      PJMEDIA_FORMAT_PCMU,
206
 
                    8000, 1,  80,
207
 
                    64000, 64000, 2, 1, 1
208
 
    },
209
 
#   endif
210
 
 
211
 
#   if PJMEDIA_HAS_PASSTHROUGH_CODEC_PCMA
212
 
    {1, "PCMA",     PJMEDIA_RTP_PT_PCMA,      PJMEDIA_FORMAT_PCMA,
213
 
                    8000, 1,  80,
214
 
                    64000, 64000, 2, 1, 1
215
 
    },
216
 
#   endif
217
 
};
218
 
 
219
 
 
220
 
#if PJMEDIA_HAS_PASSTHROUGH_CODEC_AMR
221
 
 
222
 
#include <pjmedia-codec/amr_helper.h>
223
 
 
224
 
typedef struct amr_settings_t {
225
 
    pjmedia_codec_amr_pack_setting enc_setting;
226
 
    pjmedia_codec_amr_pack_setting dec_setting;
227
 
    pj_int8_t enc_mode;
228
 
} amr_settings_t;
229
 
 
230
 
 
231
 
/* Pack AMR payload */
232
 
static pj_status_t pack_amr ( codec_private_t *codec_data,
233
 
                              const struct pjmedia_frame_ext *input,
234
 
                              unsigned output_buf_len, 
235
 
                              struct pjmedia_frame *output)
236
 
{
237
 
    enum {MAX_FRAMES_PER_PACKET = PJMEDIA_MAX_FRAME_DURATION_MS / 20};
238
 
 
239
 
    pjmedia_frame frames[MAX_FRAMES_PER_PACKET];
240
 
    amr_settings_t* setting = (amr_settings_t*)codec_data->codec_setting;
241
 
    pjmedia_codec_amr_pack_setting *enc_setting = &setting->enc_setting;
242
 
    pj_uint8_t SID_FT;
243
 
    unsigned i;
244
 
 
245
 
    pj_assert(input->subframe_cnt <= MAX_FRAMES_PER_PACKET);
246
 
 
247
 
    SID_FT = (pj_uint8_t)(enc_setting->amr_nb? 8 : 9);
248
 
 
249
 
    /* Get frames */
250
 
    for (i = 0; i < input->subframe_cnt; ++i) {
251
 
        pjmedia_frame_ext_subframe *sf;
252
 
        pjmedia_codec_amr_bit_info *info;
253
 
        unsigned len;
254
 
        
255
 
        sf = pjmedia_frame_ext_get_subframe(input, i);
256
 
        len = (sf->bitlen + 7) >> 3;
257
 
        
258
 
        info = (pjmedia_codec_amr_bit_info*) &frames[i].bit_info;
259
 
        pj_bzero(info, sizeof(*info));
260
 
        
261
 
        if (len == 0) {
262
 
            /* DTX */
263
 
            info->frame_type = 15;
264
 
        } else {
265
 
            info->frame_type = pjmedia_codec_amr_get_mode2(enc_setting->amr_nb, 
266
 
                                                           len);
267
 
        }
268
 
        info->good_quality = 1;
269
 
        info->mode = setting->enc_mode;
270
 
        if (info->frame_type == SID_FT)
271
 
            info->STI = (sf->data[4] >> 4) & 1;
272
 
 
273
 
        frames[i].buf = sf->data;
274
 
        frames[i].size = len;
275
 
    }
276
 
 
277
 
    output->size = output_buf_len;
278
 
 
279
 
    return pjmedia_codec_amr_pack(frames, input->subframe_cnt, enc_setting, 
280
 
                                  output->buf, &output->size);
281
 
}
282
 
 
283
 
 
284
 
/* Parse AMR payload into frames. */
285
 
static pj_status_t parse_amr(codec_private_t *codec_data, void *pkt, 
286
 
                             pj_size_t pkt_size, const pj_timestamp *ts,
287
 
                             unsigned *frame_cnt, pjmedia_frame frames[])
288
 
{
289
 
    amr_settings_t* s = (amr_settings_t*)codec_data->codec_setting;
290
 
    pjmedia_codec_amr_pack_setting *setting;
291
 
    pj_status_t status;
292
 
    pj_uint8_t cmr;
293
 
 
294
 
    setting = &s->dec_setting;
295
 
 
296
 
    status = pjmedia_codec_amr_parse(pkt, pkt_size, ts, setting, frames, 
297
 
                                     frame_cnt, &cmr);
298
 
    if (status != PJ_SUCCESS)
299
 
        return status;
300
 
 
301
 
    // CMR is not supported for now. 
302
 
    /* Check Change Mode Request. */
303
 
    //if ((setting->amr_nb && cmr <= 7) || (!setting->amr_nb && cmr <= 8)) {
304
 
    //  s->enc_mode = cmr;
305
 
    //}
306
 
 
307
 
    return PJ_SUCCESS;
308
 
}
309
 
 
310
 
#endif /* PJMEDIA_HAS_PASSTROUGH_CODEC_AMR */
311
 
 
312
 
 
313
 
/*
314
 
 * Initialize and register passthrough codec factory to pjmedia endpoint.
315
 
 */
316
 
PJ_DEF(pj_status_t) pjmedia_codec_passthrough_init( pjmedia_endpt *endpt )
317
 
{
318
 
    pjmedia_codec_mgr *codec_mgr;
319
 
    pj_status_t status;
320
 
 
321
 
    if (codec_factory.pool != NULL) {
322
 
        /* Already initialized. */
323
 
        return PJ_EEXISTS;
324
 
    }
325
 
 
326
 
    /* Create passthrough codec factory. */
327
 
    codec_factory.base.op = &codec_factory_op;
328
 
    codec_factory.base.factory_data = NULL;
329
 
    codec_factory.endpt = endpt;
330
 
 
331
 
    codec_factory.pool = pjmedia_endpt_create_pool(endpt, "Passthrough codecs",
332
 
                                                   4000, 4000);
333
 
    if (!codec_factory.pool)
334
 
        return PJ_ENOMEM;
335
 
 
336
 
    /* Create mutex. */
337
 
    status = pj_mutex_create_simple(codec_factory.pool, "Passthrough codecs",
338
 
                                    &codec_factory.mutex);
339
 
    if (status != PJ_SUCCESS)
340
 
        goto on_error;
341
 
 
342
 
    /* Get the codec manager. */
343
 
    codec_mgr = pjmedia_endpt_get_codec_mgr(endpt);
344
 
    if (!codec_mgr) {
345
 
        status = PJ_EINVALIDOP;
346
 
        goto on_error;
347
 
    }
348
 
 
349
 
    /* Register codec factory to endpoint. */
350
 
    status = pjmedia_codec_mgr_register_factory(codec_mgr, 
351
 
                                                &codec_factory.base);
352
 
    if (status != PJ_SUCCESS)
353
 
        goto on_error;
354
 
 
355
 
    /* Done. */
356
 
    return PJ_SUCCESS;
357
 
 
358
 
on_error:
359
 
    pj_pool_release(codec_factory.pool);
360
 
    codec_factory.pool = NULL;
361
 
    return status;
362
 
}
363
 
 
364
 
/*
365
 
 * Initialize and register passthrough codec factory to pjmedia endpoint.
366
 
 */
367
 
PJ_DEF(pj_status_t) pjmedia_codec_passthrough_init2( 
368
 
                      pjmedia_endpt *endpt,
369
 
                      const pjmedia_codec_passthrough_setting *setting)
370
 
{
371
 
    if (codec_factory.pool != NULL) {
372
 
        /* Already initialized. */
373
 
        return PJ_EEXISTS;
374
 
    }
375
 
 
376
 
    if (setting != NULL) {
377
 
        unsigned i;
378
 
 
379
 
        /* Enable/disable codecs based on the specified encoding formats */
380
 
        for (i = 0; i < PJ_ARRAY_SIZE(codec_desc); ++i) {
381
 
            pj_bool_t enabled = PJ_FALSE;
382
 
            unsigned j;
383
 
 
384
 
            for (j = 0; j < setting->fmt_cnt && !enabled; ++j) {
385
 
                if (codec_desc[i].fmt_id == setting->fmts[j].id)
386
 
                    enabled = PJ_TRUE;
387
 
            }
388
 
 
389
 
            codec_desc[i].enabled = enabled;
390
 
        }
391
 
 
392
 
#if PJMEDIA_HAS_PASSTHROUGH_CODEC_ILBC
393
 
        /* Update iLBC codec description based on default mode setting. */
394
 
        for (i = 0; i < PJ_ARRAY_SIZE(codec_desc); ++i) {
395
 
            if (codec_desc[i].enabled && 
396
 
                codec_desc[i].fmt_id == PJMEDIA_FORMAT_ILBC)
397
 
            {
398
 
                codec_desc[i].samples_per_frame = 
399
 
                                (setting->ilbc_mode == 20? 160 : 240);
400
 
                codec_desc[i].def_bitrate = 
401
 
                                (setting->ilbc_mode == 20? 15200 : 13333);
402
 
                pj_strset2(&codec_desc[i].dec_fmtp.param[0].val, 
403
 
                                (setting->ilbc_mode == 20? "20" : "30"));
404
 
                break;
405
 
            }
406
 
        }
407
 
#endif
408
 
    }
409
 
 
410
 
    return pjmedia_codec_passthrough_init(endpt);
411
 
}
412
 
 
413
 
/*
414
 
 * Unregister passthrough codecs factory from pjmedia endpoint.
415
 
 */
416
 
PJ_DEF(pj_status_t) pjmedia_codec_passthrough_deinit(void)
417
 
{
418
 
    pjmedia_codec_mgr *codec_mgr;
419
 
    unsigned i;
420
 
    pj_status_t status;
421
 
 
422
 
    if (codec_factory.pool == NULL) {
423
 
        /* Already deinitialized */
424
 
        return PJ_SUCCESS;
425
 
    }
426
 
 
427
 
    pj_mutex_lock(codec_factory.mutex);
428
 
 
429
 
    /* Get the codec manager. */
430
 
    codec_mgr = pjmedia_endpt_get_codec_mgr(codec_factory.endpt);
431
 
    if (!codec_mgr) {
432
 
        pj_pool_release(codec_factory.pool);
433
 
        codec_factory.pool = NULL;
434
 
        return PJ_EINVALIDOP;
435
 
    }
436
 
 
437
 
    /* Unregister passthrough codecs factory. */
438
 
    status = pjmedia_codec_mgr_unregister_factory(codec_mgr,
439
 
                                                  &codec_factory.base);
440
 
    
441
 
    /* Destroy mutex. */
442
 
    pj_mutex_destroy(codec_factory.mutex);
443
 
 
444
 
    /* Destroy pool. */
445
 
    pj_pool_release(codec_factory.pool);
446
 
    codec_factory.pool = NULL;
447
 
 
448
 
    /* Re-enable all codecs in the codec_desc. */
449
 
    for (i = 0; i < PJ_ARRAY_SIZE(codec_desc); ++i) {
450
 
        codec_desc[i].enabled = PJ_TRUE;
451
 
    }
452
 
 
453
 
    return status;
454
 
}
455
 
 
456
 
/* 
457
 
 * Check if factory can allocate the specified codec. 
458
 
 */
459
 
static pj_status_t test_alloc( pjmedia_codec_factory *factory, 
460
 
                               const pjmedia_codec_info *info )
461
 
{
462
 
    unsigned i;
463
 
 
464
 
    PJ_UNUSED_ARG(factory);
465
 
 
466
 
    /* Type MUST be audio. */
467
 
    if (info->type != PJMEDIA_TYPE_AUDIO)
468
 
        return PJMEDIA_CODEC_EUNSUP;
469
 
 
470
 
    for (i = 0; i < PJ_ARRAY_SIZE(codec_desc); ++i) {
471
 
        pj_str_t name = pj_str((char*)codec_desc[i].name);
472
 
        if ((pj_stricmp(&info->encoding_name, &name) == 0) &&
473
 
            (info->clock_rate == (unsigned)codec_desc[i].clock_rate) &&
474
 
            (info->channel_cnt == (unsigned)codec_desc[i].channel_count) &&
475
 
            (codec_desc[i].enabled))
476
 
        {
477
 
            return PJ_SUCCESS;
478
 
        }
479
 
    }
480
 
    
481
 
    /* Unsupported, or mode is disabled. */
482
 
    return PJMEDIA_CODEC_EUNSUP;
483
 
}
484
 
 
485
 
/*
486
 
 * Generate default attribute.
487
 
 */
488
 
static pj_status_t default_attr ( pjmedia_codec_factory *factory, 
489
 
                                  const pjmedia_codec_info *id, 
490
 
                                  pjmedia_codec_param *attr )
491
 
{
492
 
    unsigned i;
493
 
 
494
 
    PJ_ASSERT_RETURN(factory==&codec_factory.base, PJ_EINVAL);
495
 
 
496
 
    pj_bzero(attr, sizeof(pjmedia_codec_param));
497
 
 
498
 
    for (i = 0; i < PJ_ARRAY_SIZE(codec_desc); ++i) {
499
 
        pj_str_t name = pj_str((char*)codec_desc[i].name);
500
 
        if ((pj_stricmp(&id->encoding_name, &name) == 0) &&
501
 
            (id->clock_rate == (unsigned)codec_desc[i].clock_rate) &&
502
 
            (id->channel_cnt == (unsigned)codec_desc[i].channel_count) &&
503
 
            (id->pt == (unsigned)codec_desc[i].pt))
504
 
        {
505
 
            attr->info.pt = (pj_uint8_t)id->pt;
506
 
            attr->info.channel_cnt = codec_desc[i].channel_count;
507
 
            attr->info.clock_rate = codec_desc[i].clock_rate;
508
 
            attr->info.avg_bps = codec_desc[i].def_bitrate;
509
 
            attr->info.max_bps = codec_desc[i].max_bitrate;
510
 
            attr->info.pcm_bits_per_sample = 16;
511
 
            attr->info.frm_ptime =  (pj_uint16_t)
512
 
                                    (codec_desc[i].samples_per_frame * 1000 / 
513
 
                                    codec_desc[i].channel_count / 
514
 
                                    codec_desc[i].clock_rate);
515
 
            attr->info.fmt_id = codec_desc[i].fmt_id;
516
 
 
517
 
            /* Default flags. */
518
 
            attr->setting.frm_per_pkt = codec_desc[i].frm_per_pkt;
519
 
            attr->setting.plc = codec_desc[i].plc;
520
 
            attr->setting.penh= 0;
521
 
            attr->setting.vad = codec_desc[i].vad;
522
 
            attr->setting.cng = attr->setting.vad;
523
 
            attr->setting.dec_fmtp = codec_desc[i].dec_fmtp;
524
 
 
525
 
            if (attr->setting.vad == 0) {
526
 
#if PJMEDIA_HAS_PASSTHROUGH_CODEC_G729
527
 
                if (id->pt == PJMEDIA_RTP_PT_G729) {
528
 
                    /* Signal G729 Annex B is being disabled */
529
 
                    attr->setting.dec_fmtp.cnt = 1;
530
 
                    pj_strset2(&attr->setting.dec_fmtp.param[0].name, "annexb");
531
 
                    pj_strset2(&attr->setting.dec_fmtp.param[0].val, "no");
532
 
                }
533
 
#endif
534
 
            }
535
 
 
536
 
            return PJ_SUCCESS;
537
 
        }
538
 
    }
539
 
 
540
 
    return PJMEDIA_CODEC_EUNSUP;
541
 
}
542
 
 
543
 
/*
544
 
 * Enum codecs supported by this factory.
545
 
 */
546
 
static pj_status_t enum_codecs( pjmedia_codec_factory *factory, 
547
 
                                unsigned *count, 
548
 
                                pjmedia_codec_info codecs[])
549
 
{
550
 
    unsigned max;
551
 
    unsigned i;
552
 
 
553
 
    PJ_UNUSED_ARG(factory);
554
 
    PJ_ASSERT_RETURN(codecs && *count > 0, PJ_EINVAL);
555
 
 
556
 
    max = *count;
557
 
    
558
 
    for (i = 0, *count = 0; i < PJ_ARRAY_SIZE(codec_desc) && *count < max; ++i) 
559
 
    {
560
 
        if (!codec_desc[i].enabled)
561
 
            continue;
562
 
 
563
 
        pj_bzero(&codecs[*count], sizeof(pjmedia_codec_info));
564
 
        codecs[*count].encoding_name = pj_str((char*)codec_desc[i].name);
565
 
        codecs[*count].pt = codec_desc[i].pt;
566
 
        codecs[*count].type = PJMEDIA_TYPE_AUDIO;
567
 
        codecs[*count].clock_rate = codec_desc[i].clock_rate;
568
 
        codecs[*count].channel_cnt = codec_desc[i].channel_count;
569
 
 
570
 
        ++*count;
571
 
    }
572
 
 
573
 
    return PJ_SUCCESS;
574
 
}
575
 
 
576
 
/*
577
 
 * Allocate a new codec instance.
578
 
 */
579
 
static pj_status_t alloc_codec( pjmedia_codec_factory *factory, 
580
 
                                const pjmedia_codec_info *id,
581
 
                                pjmedia_codec **p_codec)
582
 
{
583
 
    codec_private_t *codec_data;
584
 
    pjmedia_codec *codec;
585
 
    int idx;
586
 
    pj_pool_t *pool;
587
 
    unsigned i;
588
 
 
589
 
    PJ_ASSERT_RETURN(factory && id && p_codec, PJ_EINVAL);
590
 
    PJ_ASSERT_RETURN(factory == &codec_factory.base, PJ_EINVAL);
591
 
 
592
 
    pj_mutex_lock(codec_factory.mutex);
593
 
 
594
 
    /* Find codec's index */
595
 
    idx = -1;
596
 
    for (i = 0; i < PJ_ARRAY_SIZE(codec_desc); ++i) {
597
 
        pj_str_t name = pj_str((char*)codec_desc[i].name);
598
 
        if ((pj_stricmp(&id->encoding_name, &name) == 0) &&
599
 
            (id->clock_rate == (unsigned)codec_desc[i].clock_rate) &&
600
 
            (id->channel_cnt == (unsigned)codec_desc[i].channel_count) &&
601
 
            (codec_desc[i].enabled))
602
 
        {
603
 
            idx = i;
604
 
            break;
605
 
        }
606
 
    }
607
 
    if (idx == -1) {
608
 
        *p_codec = NULL;
609
 
        return PJMEDIA_CODEC_EUNSUP;
610
 
    }
611
 
 
612
 
    /* Create pool for codec instance */
613
 
    pool = pjmedia_endpt_create_pool(codec_factory.endpt, "passthroughcodec",
614
 
                                     512, 512);
615
 
    codec = PJ_POOL_ZALLOC_T(pool, pjmedia_codec);
616
 
    codec->op = &codec_op;
617
 
    codec->factory = factory;
618
 
    codec->codec_data = PJ_POOL_ZALLOC_T(pool, codec_private_t);
619
 
    codec_data = (codec_private_t*) codec->codec_data;
620
 
    codec_data->pool = pool;
621
 
    codec_data->codec_idx = idx;
622
 
 
623
 
    pj_mutex_unlock(codec_factory.mutex);
624
 
 
625
 
    *p_codec = codec;
626
 
    return PJ_SUCCESS;
627
 
}
628
 
 
629
 
/*
630
 
 * Free codec.
631
 
 */
632
 
static pj_status_t dealloc_codec( pjmedia_codec_factory *factory, 
633
 
                                  pjmedia_codec *codec )
634
 
{
635
 
    codec_private_t *codec_data;
636
 
 
637
 
    PJ_ASSERT_RETURN(factory && codec, PJ_EINVAL);
638
 
    PJ_ASSERT_RETURN(factory == &codec_factory.base, PJ_EINVAL);
639
 
 
640
 
    /* Close codec, if it's not closed. */
641
 
    codec_data = (codec_private_t*) codec->codec_data;
642
 
    codec_close(codec);
643
 
 
644
 
    pj_pool_release(codec_data->pool);
645
 
 
646
 
    return PJ_SUCCESS;
647
 
}
648
 
 
649
 
/*
650
 
 * Init codec.
651
 
 */
652
 
static pj_status_t codec_init( pjmedia_codec *codec, 
653
 
                               pj_pool_t *pool )
654
 
{
655
 
    PJ_UNUSED_ARG(codec);
656
 
    PJ_UNUSED_ARG(pool);
657
 
    return PJ_SUCCESS;
658
 
}
659
 
 
660
 
/*
661
 
 * Open codec.
662
 
 */
663
 
static pj_status_t codec_open( pjmedia_codec *codec, 
664
 
                               pjmedia_codec_param *attr )
665
 
{
666
 
    codec_private_t *codec_data = (codec_private_t*) codec->codec_data;
667
 
    struct codec_desc *desc = &codec_desc[codec_data->codec_idx];
668
 
    pj_pool_t *pool;
669
 
    int i, j;
670
 
 
671
 
    pool = codec_data->pool;
672
 
 
673
 
    /* Cache samples per frame value */
674
 
    codec_data->samples_per_frame = desc->samples_per_frame;
675
 
 
676
 
    /* Calculate bitstream size */
677
 
    i = attr->info.avg_bps * codec_data->samples_per_frame;
678
 
    j = desc->clock_rate << 3;
679
 
    codec_data->avg_frame_size = (pj_uint16_t)(i / j);
680
 
    if (i % j) ++codec_data->avg_frame_size;
681
 
 
682
 
#if PJMEDIA_HAS_PASSTHROUGH_CODEC_AMR
683
 
    /* Init AMR settings */
684
 
    if (desc->pt == PJMEDIA_RTP_PT_AMR || desc->pt == PJMEDIA_RTP_PT_AMRWB) {
685
 
        amr_settings_t *s;
686
 
        pj_uint8_t octet_align = 0;
687
 
        pj_int8_t enc_mode;
688
 
        
689
 
        enc_mode = pjmedia_codec_amr_get_mode(attr->info.avg_bps);
690
 
        pj_assert(enc_mode >= 0 && enc_mode <= 8);
691
 
 
692
 
        for (i = 0; i < attr->setting.dec_fmtp.cnt; ++i) {
693
 
            const pj_str_t STR_FMTP_OCTET_ALIGN = {"octet-align", 11};
694
 
            
695
 
            /* Fetch octet-align setting. It should be fine to fetch only 
696
 
             * the decoder, since encoder & decoder must use the same setting 
697
 
             * (RFC 4867 section 8.3.1).
698
 
             */
699
 
            if (pj_stricmp(&attr->setting.dec_fmtp.param[i].name, 
700
 
                           &STR_FMTP_OCTET_ALIGN) == 0)
701
 
            {
702
 
                octet_align=(pj_uint8_t)
703
 
                            (pj_strtoul(&attr->setting.dec_fmtp.param[i].val));
704
 
                break;
705
 
            }
706
 
        }
707
 
 
708
 
        for (i = 0; i < attr->setting.enc_fmtp.cnt; ++i) {
709
 
            const pj_str_t STR_FMTP_MODE_SET = {"mode-set", 8};
710
 
 
711
 
            /* mode-set, encoding mode is chosen based on local default mode 
712
 
             * setting:
713
 
             * - if local default mode is included in the mode-set, use it
714
 
             * - otherwise, find the closest mode to local default mode;
715
 
             *   if there are two closest modes, prefer to use the higher
716
 
             *   one, e.g: local default mode is 4, the mode-set param
717
 
             *   contains '2,3,5,6', then 5 will be chosen.
718
 
             */
719
 
            if (pj_stricmp(&attr->setting.enc_fmtp.param[i].name, 
720
 
                           &STR_FMTP_MODE_SET) == 0)
721
 
            {
722
 
                const char *p;
723
 
                pj_size_t l;
724
 
                pj_int8_t diff = 99;
725
 
                
726
 
                p = pj_strbuf(&attr->setting.enc_fmtp.param[i].val);
727
 
                l = pj_strlen(&attr->setting.enc_fmtp.param[i].val);
728
 
 
729
 
                while (l--) {
730
 
                    if ((desc->pt==PJMEDIA_RTP_PT_AMR && *p>='0' && *p<='7') ||
731
 
                        (desc->pt==PJMEDIA_RTP_PT_AMRWB && *p>='0' && *p<='8'))
732
 
                    {
733
 
                        pj_int8_t tmp = (pj_int8_t)(*p - '0' - enc_mode);
734
 
 
735
 
                        if (PJ_ABS(diff) > PJ_ABS(tmp) || 
736
 
                            (PJ_ABS(diff) == PJ_ABS(tmp) && tmp > diff))
737
 
                        {
738
 
                            diff = tmp;
739
 
                            if (diff == 0) break;
740
 
                        }
741
 
                    }
742
 
                    ++p;
743
 
                }
744
 
 
745
 
                if (diff == 99)
746
 
                    return PJMEDIA_CODEC_EFAILED;
747
 
 
748
 
                enc_mode = (pj_int8_t)(enc_mode + diff);
749
 
 
750
 
                break;
751
 
            }
752
 
        }
753
 
 
754
 
        s = PJ_POOL_ZALLOC_T(pool, amr_settings_t);
755
 
        codec_data->codec_setting = s;
756
 
 
757
 
        s->enc_mode = enc_mode;
758
 
        if (s->enc_mode < 0)
759
 
            return PJMEDIA_CODEC_EINMODE;
760
 
 
761
 
        s->enc_setting.amr_nb = (pj_uint8_t)(desc->pt == PJMEDIA_RTP_PT_AMR);
762
 
        s->enc_setting.octet_aligned = octet_align;
763
 
        s->enc_setting.reorder = PJ_FALSE; /* Note this! passthrough codec
764
 
                                              doesn't do sensitivity bits 
765
 
                                              reordering */
766
 
        s->enc_setting.cmr = 15;
767
 
        
768
 
        s->dec_setting.amr_nb = (pj_uint8_t)(desc->pt == PJMEDIA_RTP_PT_AMR);
769
 
        s->dec_setting.octet_aligned = octet_align;
770
 
        s->dec_setting.reorder = PJ_FALSE; /* Note this! passthrough codec
771
 
                                              doesn't do sensitivity bits 
772
 
                                              reordering */
773
 
        
774
 
        /* Return back bitrate info to application */
775
 
        attr->info.avg_bps = s->enc_setting.amr_nb?
776
 
                             pjmedia_codec_amrnb_bitrates[s->enc_mode]:
777
 
                             pjmedia_codec_amrwb_bitrates[s->enc_mode];
778
 
    }
779
 
#endif
780
 
 
781
 
#if PJMEDIA_HAS_PASSTHROUGH_CODEC_ILBC
782
 
    /* Init iLBC settings */
783
 
    if (desc->pt == PJMEDIA_RTP_PT_ILBC)
784
 
    {
785
 
        enum { DEFAULT_MODE = 30 };
786
 
        static pj_str_t STR_MODE = {"mode", 4};
787
 
        pj_uint16_t dec_fmtp_mode = DEFAULT_MODE, 
788
 
                    enc_fmtp_mode = DEFAULT_MODE;
789
 
 
790
 
        /* Get decoder mode */
791
 
        for (i = 0; i < attr->setting.dec_fmtp.cnt; ++i) {
792
 
            if (pj_stricmp(&attr->setting.dec_fmtp.param[i].name, &STR_MODE) == 0)
793
 
            {
794
 
                dec_fmtp_mode = (pj_uint16_t)
795
 
                                pj_strtoul(&attr->setting.dec_fmtp.param[i].val);
796
 
                break;
797
 
            }
798
 
        }
799
 
 
800
 
        /* Decoder mode must be set */
801
 
        PJ_ASSERT_RETURN(dec_fmtp_mode == 20 || dec_fmtp_mode == 30, 
802
 
                         PJMEDIA_CODEC_EINMODE);
803
 
 
804
 
        /* Get encoder mode */
805
 
        for (i = 0; i < attr->setting.enc_fmtp.cnt; ++i) {
806
 
            if (pj_stricmp(&attr->setting.enc_fmtp.param[i].name, &STR_MODE) == 0)
807
 
            {
808
 
                enc_fmtp_mode = (pj_uint16_t)
809
 
                                pj_strtoul(&attr->setting.enc_fmtp.param[i].val);
810
 
                break;
811
 
            }
812
 
        }
813
 
 
814
 
        PJ_ASSERT_RETURN(enc_fmtp_mode==20 || enc_fmtp_mode==30, 
815
 
                         PJMEDIA_CODEC_EINMODE);
816
 
 
817
 
        /* Both sides of a bi-directional session MUST use the same "mode" value.
818
 
         * In this point, possible values are only 20 or 30, so when encoder and
819
 
         * decoder modes are not same, just use the default mode, it is 30.
820
 
         */
821
 
        if (enc_fmtp_mode != dec_fmtp_mode) {
822
 
            enc_fmtp_mode = dec_fmtp_mode = DEFAULT_MODE;
823
 
            PJ_LOG(4,(pool->obj_name, 
824
 
                      "Normalized iLBC encoder and decoder modes to %d", 
825
 
                      DEFAULT_MODE));
826
 
        }
827
 
 
828
 
        /* Update some attributes based on negotiated mode. */
829
 
        attr->info.avg_bps = (dec_fmtp_mode == 30? 13333 : 15200);
830
 
        attr->info.frm_ptime = dec_fmtp_mode;
831
 
 
832
 
        /* Override average frame size */
833
 
        codec_data->avg_frame_size = (dec_fmtp_mode == 30? 50 : 38);
834
 
 
835
 
        /* Override samples per frame */
836
 
        codec_data->samples_per_frame = (dec_fmtp_mode == 30? 240 : 160);
837
 
    }
838
 
#endif
839
 
 
840
 
    return PJ_SUCCESS;
841
 
}
842
 
 
843
 
/*
844
 
 * Close codec.
845
 
 */
846
 
static pj_status_t codec_close( pjmedia_codec *codec )
847
 
{
848
 
    PJ_UNUSED_ARG(codec);
849
 
 
850
 
    return PJ_SUCCESS;
851
 
}
852
 
 
853
 
 
854
 
/*
855
 
 * Modify codec settings.
856
 
 */
857
 
static pj_status_t codec_modify( pjmedia_codec *codec, 
858
 
                                 const pjmedia_codec_param *attr )
859
 
{
860
 
    /* Not supported yet. */
861
 
    PJ_UNUSED_ARG(codec);
862
 
    PJ_UNUSED_ARG(attr);
863
 
 
864
 
    return PJ_ENOTSUP;
865
 
}
866
 
 
867
 
/*
868
 
 * Get frames in the packet.
869
 
 */
870
 
static pj_status_t codec_parse( pjmedia_codec *codec,
871
 
                                void *pkt,
872
 
                                pj_size_t pkt_size,
873
 
                                const pj_timestamp *ts,
874
 
                                unsigned *frame_cnt,
875
 
                                pjmedia_frame frames[])
876
 
{
877
 
    codec_private_t *codec_data = (codec_private_t*) codec->codec_data;
878
 
    struct codec_desc *desc = &codec_desc[codec_data->codec_idx];
879
 
    unsigned count = 0;
880
 
 
881
 
    PJ_ASSERT_RETURN(frame_cnt, PJ_EINVAL);
882
 
 
883
 
    if (desc->parse != NULL) {
884
 
        return desc->parse(codec_data, pkt,  pkt_size, ts, frame_cnt, frames);
885
 
    }
886
 
 
887
 
    while (pkt_size >= codec_data->avg_frame_size && count < *frame_cnt) {
888
 
        frames[count].type = PJMEDIA_FRAME_TYPE_AUDIO;
889
 
        frames[count].buf = pkt;
890
 
        frames[count].size = codec_data->avg_frame_size;
891
 
        frames[count].timestamp.u64 = ts->u64 + 
892
 
                                      count * codec_data->samples_per_frame;
893
 
 
894
 
        pkt = (pj_uint8_t*)pkt + codec_data->avg_frame_size;
895
 
        pkt_size -= codec_data->avg_frame_size;
896
 
 
897
 
        ++count;
898
 
    }
899
 
 
900
 
    if (pkt_size && count < *frame_cnt) {
901
 
        frames[count].type = PJMEDIA_FRAME_TYPE_AUDIO;
902
 
        frames[count].buf = pkt;
903
 
        frames[count].size = pkt_size;
904
 
        frames[count].timestamp.u64 = ts->u64 + 
905
 
                                       count * codec_data->samples_per_frame;
906
 
        ++count;
907
 
    }
908
 
 
909
 
    *frame_cnt = count;
910
 
    return PJ_SUCCESS;
911
 
}
912
 
 
913
 
/*
914
 
 * Encode frames.
915
 
 */
916
 
static pj_status_t codec_encode( pjmedia_codec *codec, 
917
 
                                 const struct pjmedia_frame *input,
918
 
                                 unsigned output_buf_len, 
919
 
                                 struct pjmedia_frame *output)
920
 
{
921
 
    codec_private_t *codec_data = (codec_private_t*) codec->codec_data;
922
 
    struct codec_desc *desc = &codec_desc[codec_data->codec_idx];
923
 
    const pjmedia_frame_ext *input_ = (const pjmedia_frame_ext*) input;
924
 
 
925
 
    pj_assert(input && input->type == PJMEDIA_FRAME_TYPE_EXTENDED);
926
 
 
927
 
    if (desc->pack != NULL) {
928
 
        desc->pack(codec_data, input_, output_buf_len, output);
929
 
    } else {
930
 
        if (input_->subframe_cnt == 0) {
931
 
            /* DTX */
932
 
            output->buf = NULL;
933
 
            output->size = 0;
934
 
            output->type = PJMEDIA_FRAME_TYPE_NONE;
935
 
        } else {
936
 
            unsigned i;
937
 
            pj_uint8_t *p = output->buf;
938
 
 
939
 
            output->type = PJMEDIA_FRAME_TYPE_AUDIO;
940
 
            output->size = 0;
941
 
            
942
 
            for (i = 0; i < input_->subframe_cnt; ++i) {
943
 
                pjmedia_frame_ext_subframe *sf;
944
 
                unsigned sf_len;
945
 
 
946
 
                sf = pjmedia_frame_ext_get_subframe(input_, i);
947
 
                pj_assert(sf);
948
 
 
949
 
                sf_len = (sf->bitlen + 7) >> 3;
950
 
 
951
 
                pj_memcpy(p, sf->data, sf_len);
952
 
                p += sf_len;
953
 
                output->size += sf_len;
954
 
 
955
 
                /* If there is SID or DTX frame, break the loop. */
956
 
                if (desc->pt == PJMEDIA_RTP_PT_G729 && 
957
 
                    sf_len < codec_data->avg_frame_size)
958
 
                {
959
 
                    break;
960
 
                }
961
 
                
962
 
            }
963
 
        }
964
 
    }
965
 
 
966
 
    output->timestamp = input->timestamp;
967
 
 
968
 
    return PJ_SUCCESS;
969
 
}
970
 
 
971
 
/*
972
 
 * Decode frame.
973
 
 */
974
 
static pj_status_t codec_decode( pjmedia_codec *codec, 
975
 
                                 const struct pjmedia_frame *input,
976
 
                                 unsigned output_buf_len, 
977
 
                                 struct pjmedia_frame *output)
978
 
{
979
 
    codec_private_t *codec_data = (codec_private_t*) codec->codec_data;
980
 
#if PJMEDIA_HAS_PASSTHROUGH_CODEC_AMR
981
 
    struct codec_desc *desc = &codec_desc[codec_data->codec_idx];
982
 
#endif
983
 
    pjmedia_frame_ext *output_ = (pjmedia_frame_ext*) output;
984
 
 
985
 
    pj_assert(input);
986
 
    PJ_UNUSED_ARG(output_buf_len);
987
 
 
988
 
#if PJMEDIA_HAS_PASSTHROUGH_CODEC_AMR
989
 
    /* Need to rearrange the AMR bitstream, since the bitstream may not be 
990
 
     * started from bit 0 or may need to be reordered from sensitivity order 
991
 
     * into encoder bits order.
992
 
     */
993
 
    if (desc->pt == PJMEDIA_RTP_PT_AMR || desc->pt == PJMEDIA_RTP_PT_AMRWB) {
994
 
        pjmedia_frame input_;
995
 
        pjmedia_codec_amr_pack_setting *setting;
996
 
 
997
 
        setting = &((amr_settings_t*)codec_data->codec_setting)->dec_setting;
998
 
 
999
 
        input_ = *input;
1000
 
        pjmedia_codec_amr_predecode(input, setting, &input_);
1001
 
        
1002
 
        pjmedia_frame_ext_append_subframe(output_, input_.buf, 
1003
 
                                          (pj_uint16_t)(input_.size << 3),
1004
 
                                          (pj_uint16_t)codec_data->samples_per_frame);
1005
 
        output->timestamp = input->timestamp;
1006
 
        
1007
 
        return PJ_SUCCESS;
1008
 
    }
1009
 
#endif
1010
 
    
1011
 
    pjmedia_frame_ext_append_subframe(output_, input->buf, 
1012
 
                                      (pj_uint16_t)(input->size << 3),
1013
 
                                      (pj_uint16_t)codec_data->samples_per_frame);
1014
 
    output->timestamp = input->timestamp;
1015
 
 
1016
 
    return PJ_SUCCESS;
1017
 
}
1018
 
 
1019
 
/* 
1020
 
 * Recover lost frame.
1021
 
 */
1022
 
static pj_status_t codec_recover( pjmedia_codec *codec, 
1023
 
                                  unsigned output_buf_len, 
1024
 
                                  struct pjmedia_frame *output)
1025
 
{
1026
 
    codec_private_t *codec_data = (codec_private_t*) codec->codec_data;
1027
 
    pjmedia_frame_ext *output_ = (pjmedia_frame_ext*) output;
1028
 
 
1029
 
    PJ_UNUSED_ARG(output_buf_len);
1030
 
 
1031
 
    pjmedia_frame_ext_append_subframe(output_, NULL, 0,
1032
 
                                      (pj_uint16_t)codec_data->samples_per_frame);
1033
 
 
1034
 
    return PJ_SUCCESS;
1035
 
}
1036
 
 
1037
 
#endif  /* PJMEDIA_HAS_PASSTHROUGH_CODECS */
1038