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