~ubuntu-branches/ubuntu/trusty/sflphone/trusty

« back to all changes in this revision

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

  • Committer: Package Import Robot
  • Author(s): Mark Purcell
  • Date: 2014-01-28 18:23:36 UTC
  • mfrom: (4.3.4 sid)
  • Revision ID: package-import@ubuntu.com-20140128182336-jrsv0k9u6cawc068
Tags: 1.3.0-1
* New upstream release 
  - Fixes "New Upstream Release" (Closes: #735846)
  - Fixes "Ringtone does not stop" (Closes: #727164)
  - Fixes "[sflphone-kde] crash on startup" (Closes: #718178)
  - Fixes "sflphone GUI crashes when call is hung up" (Closes: #736583)
* Build-Depends: ensure GnuTLS 2.6
  - libucommon-dev (>= 6.0.7-1.1), libccrtp-dev (>= 2.0.6-3)
  - Fixes "FTBFS Build-Depends libgnutls{26,28}-dev" (Closes: #722040)
* Fix "boost 1.49 is going away" unversioned Build-Depends: (Closes: #736746)
* Add Build-Depends: libsndfile-dev, nepomuk-core-dev

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* $Id: ipp_codecs.c 4002 2012-03-30 08:05:43Z bennylp $ */
 
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/ipp_codecs.h>
 
21
#include <pjmedia-codec/amr_sdp_match.h>
 
22
#include <pjmedia-codec/g7221_sdp_match.h>
 
23
#include <pjmedia/codec.h>
 
24
#include <pjmedia/errno.h>
 
25
#include <pjmedia/endpoint.h>
 
26
#include <pjmedia/plc.h>
 
27
#include <pjmedia/port.h>
 
28
#include <pjmedia/silencedet.h>
 
29
#include <pj/assert.h>
 
30
#include <pj/log.h>
 
31
#include <pj/math.h>
 
32
#include <pj/pool.h>
 
33
#include <pj/string.h>
 
34
#include <pj/os.h>
 
35
 
 
36
 
 
37
/*
 
38
 * Only build this file if PJMEDIA_HAS_INTEL_IPP != 0
 
39
 */
 
40
#if defined(PJMEDIA_HAS_INTEL_IPP) && PJMEDIA_HAS_INTEL_IPP != 0
 
41
 
 
42
#include <usc.h>
 
43
#include <ippversion.h>
 
44
 
 
45
#define THIS_FILE   "ipp_codecs.c"
 
46
 
 
47
 
 
48
/* Prototypes for IPP codecs factory */
 
49
static pj_status_t ipp_test_alloc( pjmedia_codec_factory *factory, 
 
50
                                   const pjmedia_codec_info *id );
 
51
static pj_status_t ipp_default_attr( pjmedia_codec_factory *factory, 
 
52
                                     const pjmedia_codec_info *id, 
 
53
                                     pjmedia_codec_param *attr );
 
54
static pj_status_t ipp_enum_codecs( pjmedia_codec_factory *factory, 
 
55
                                    unsigned *count, 
 
56
                                    pjmedia_codec_info codecs[]);
 
57
static pj_status_t ipp_alloc_codec( pjmedia_codec_factory *factory, 
 
58
                                    const pjmedia_codec_info *id, 
 
59
                                    pjmedia_codec **p_codec);
 
60
static pj_status_t ipp_dealloc_codec( pjmedia_codec_factory *factory, 
 
61
                                      pjmedia_codec *codec );
 
62
 
 
63
/* Prototypes for IPP codecs implementation. */
 
64
static pj_status_t  ipp_codec_init( pjmedia_codec *codec, 
 
65
                                    pj_pool_t *pool );
 
66
static pj_status_t  ipp_codec_open( pjmedia_codec *codec, 
 
67
                                    pjmedia_codec_param *attr );
 
68
static pj_status_t  ipp_codec_close( pjmedia_codec *codec );
 
69
static pj_status_t  ipp_codec_modify(pjmedia_codec *codec, 
 
70
                                     const pjmedia_codec_param *attr );
 
71
static pj_status_t  ipp_codec_parse( pjmedia_codec *codec,
 
72
                                     void *pkt,
 
73
                                     pj_size_t pkt_size,
 
74
                                     const pj_timestamp *ts,
 
75
                                     unsigned *frame_cnt,
 
76
                                     pjmedia_frame frames[]);
 
77
static pj_status_t  ipp_codec_encode( pjmedia_codec *codec, 
 
78
                                      const struct pjmedia_frame *input,
 
79
                                      unsigned output_buf_len, 
 
80
                                      struct pjmedia_frame *output);
 
81
static pj_status_t  ipp_codec_decode( pjmedia_codec *codec, 
 
82
                                      const struct pjmedia_frame *input,
 
83
                                      unsigned output_buf_len, 
 
84
                                      struct pjmedia_frame *output);
 
85
static pj_status_t  ipp_codec_recover(pjmedia_codec *codec, 
 
86
                                      unsigned output_buf_len, 
 
87
                                      struct pjmedia_frame *output);
 
88
 
 
89
/* Definition for IPP codecs operations. */
 
90
static pjmedia_codec_op ipp_op = 
 
91
{
 
92
    &ipp_codec_init,
 
93
    &ipp_codec_open,
 
94
    &ipp_codec_close,
 
95
    &ipp_codec_modify,
 
96
    &ipp_codec_parse,
 
97
    &ipp_codec_encode,
 
98
    &ipp_codec_decode,
 
99
    &ipp_codec_recover
 
100
};
 
101
 
 
102
/* Definition for IPP codecs factory operations. */
 
103
static pjmedia_codec_factory_op ipp_factory_op =
 
104
{
 
105
    &ipp_test_alloc,
 
106
    &ipp_default_attr,
 
107
    &ipp_enum_codecs,
 
108
    &ipp_alloc_codec,
 
109
    &ipp_dealloc_codec,
 
110
    &pjmedia_codec_ipp_deinit
 
111
};
 
112
 
 
113
/* IPP codecs factory */
 
114
static struct ipp_factory {
 
115
    pjmedia_codec_factory    base;
 
116
    pjmedia_endpt           *endpt;
 
117
    pj_pool_t               *pool;
 
118
    pj_mutex_t              *mutex;
 
119
    unsigned                 g7221_pcm_shift;
 
120
} ipp_factory;
 
121
 
 
122
/* IPP codecs private data. */
 
123
typedef struct ipp_private {
 
124
    int                  codec_idx;         /**< Codec index.               */
 
125
    void                *codec_setting;     /**< Specific codec setting.    */
 
126
    pj_pool_t           *pool;              /**< Pool for each instance.    */
 
127
 
 
128
    USC_Handle           enc;               /**< Encoder state.             */
 
129
    USC_Handle           dec;               /**< Decoder state.             */
 
130
    USC_CodecInfo       *info;              /**< Native codec info.         */
 
131
    pj_uint16_t          frame_size;        /**< Bitstream frame size.      */
 
132
 
 
133
    pj_bool_t            plc_enabled;       /**< PLC enabled flag.          */
 
134
    pjmedia_plc         *plc;               /**< PJMEDIA PLC engine, NULL if 
 
135
                                                 codec has internal PLC.    */
 
136
 
 
137
    pj_bool_t            vad_enabled;       /**< VAD enabled flag.          */
 
138
    pjmedia_silence_det *vad;               /**< PJMEDIA VAD engine, NULL if 
 
139
                                                 codec has internal VAD.    */
 
140
    pj_timestamp         last_tx;           /**< Timestamp of last transmit.*/
 
141
 
 
142
    unsigned             g7221_pcm_shift;   /**< G722.1 PCM level adjustment*/
 
143
} ipp_private_t;
 
144
 
 
145
 
 
146
/* USC codec implementations. */
 
147
extern USC_Fxns USC_G729AFP_Fxns;
 
148
extern USC_Fxns USC_G729I_Fxns;
 
149
extern USC_Fxns USC_G723_Fxns;
 
150
extern USC_Fxns USC_G726_Fxns;
 
151
extern USC_Fxns USC_G728_Fxns;
 
152
extern USC_Fxns USC_G722_Fxns;
 
153
extern USC_Fxns USC_GSMAMR_Fxns;
 
154
extern USC_Fxns USC_AMRWB_Fxns;
 
155
extern USC_Fxns USC_AMRWBE_Fxns;
 
156
 
 
157
 
 
158
/* CUSTOM CALLBACKS */
 
159
 
 
160
/* This callback is useful for translating RTP frame into USC frame, e.g:
 
161
 * reassigning frame attributes, reorder bitstream. Default behaviour of
 
162
 * the translation is just setting the USC frame buffer & its size as 
 
163
 * specified in RTP frame, setting USC frame frametype to 0, setting bitrate
 
164
 * of USC frame to bitrate info of codec_data. Implement this callback when 
 
165
 * the default behaviour is unapplicable.
 
166
 */
 
167
typedef void (*predecode_cb)(ipp_private_t *codec_data,
 
168
                             const pjmedia_frame *rtp_frame,
 
169
                             USC_Bitstream *usc_frame);
 
170
 
 
171
/* Parse frames from a packet. Default behaviour of frame parsing is 
 
172
 * just separating frames based on calculating frame length derived 
 
173
 * from bitrate. Implement this callback when the default behaviour is 
 
174
 * unapplicable.
 
175
 */
 
176
typedef pj_status_t (*parse_cb)(ipp_private_t *codec_data, void *pkt, 
 
177
                                pj_size_t pkt_size, const pj_timestamp *ts,
 
178
                                unsigned *frame_cnt, pjmedia_frame frames[]);
 
179
 
 
180
/* Pack frames into a packet. Default behaviour of packing frames is 
 
181
 * just stacking the frames with octet aligned without adding any 
 
182
 * payload header. Implement this callback when the default behaviour is
 
183
 * unapplicable.
 
184
 */
 
185
typedef pj_status_t (*pack_cb)(ipp_private_t *codec_data, void *pkt, 
 
186
                               pj_size_t *pkt_size, pj_size_t max_pkt_size);
 
187
 
 
188
 
 
189
 
 
190
/* Custom callback implementations. */
 
191
static    void predecode_g723( ipp_private_t *codec_data,
 
192
                               const pjmedia_frame *rtp_frame,
 
193
                               USC_Bitstream *usc_frame);
 
194
static pj_status_t parse_g723( ipp_private_t *codec_data, void *pkt, 
 
195
                               pj_size_t pkt_size, const pj_timestamp *ts,
 
196
                               unsigned *frame_cnt, pjmedia_frame frames[]);
 
197
 
 
198
static void predecode_g729( ipp_private_t *codec_data,
 
199
                            const pjmedia_frame *rtp_frame,
 
200
                            USC_Bitstream *usc_frame);
 
201
 
 
202
static    void predecode_amr( ipp_private_t *codec_data,
 
203
                              const pjmedia_frame *rtp_frame,
 
204
                              USC_Bitstream *usc_frame);
 
205
static pj_status_t parse_amr( ipp_private_t *codec_data, void *pkt, 
 
206
                              pj_size_t pkt_size, const pj_timestamp *ts,
 
207
                              unsigned *frame_cnt, pjmedia_frame frames[]);
 
208
static  pj_status_t pack_amr( ipp_private_t *codec_data, void *pkt, 
 
209
                              pj_size_t *pkt_size, pj_size_t max_pkt_size);
 
210
 
 
211
static    void predecode_g7221( ipp_private_t *codec_data,
 
212
                                const pjmedia_frame *rtp_frame,
 
213
                                USC_Bitstream *usc_frame);
 
214
static  pj_status_t pack_g7221( ipp_private_t *codec_data, void *pkt, 
 
215
                                pj_size_t *pkt_size, pj_size_t max_pkt_size);
 
216
 
 
217
/* IPP codec implementation descriptions. */
 
218
static struct ipp_codec {
 
219
    int              enabled;           /* Is this codec enabled?           */
 
220
    const char      *name;              /* Codec name.                      */
 
221
    pj_uint8_t       pt;                /* Payload type.                    */
 
222
    USC_Fxns        *fxns;              /* USC callback functions.          */
 
223
    unsigned         clock_rate;        /* Codec's clock rate.              */
 
224
    unsigned         channel_count;     /* Codec's channel count.           */
 
225
    unsigned         samples_per_frame; /* Codec's samples count.           */
 
226
 
 
227
    unsigned         def_bitrate;       /* Default bitrate of this codec.   */
 
228
    unsigned         max_bitrate;       /* Maximum bitrate of this codec.   */
 
229
    pj_uint8_t       frm_per_pkt;       /* Default num of frames per packet.*/
 
230
    int              has_native_vad;    /* Codec has internal VAD?          */
 
231
    int              has_native_plc;    /* Codec has internal PLC?          */
 
232
 
 
233
    predecode_cb     predecode;         /* Callback to translate RTP frame
 
234
                                           into USC frame.                  */
 
235
    parse_cb         parse;             /* Callback to parse bitstream.     */
 
236
    pack_cb          pack;              /* Callback to pack bitstream.      */
 
237
 
 
238
    pjmedia_codec_fmtp dec_fmtp;        /* Decoder's fmtp params.           */
 
239
}
 
240
 
 
241
ipp_codec[] = 
 
242
{
 
243
#   if PJMEDIA_HAS_INTEL_IPP_CODEC_AMR
 
244
    {1, "AMR",      PJMEDIA_RTP_PT_AMR,       &USC_GSMAMR_Fxns,  8000, 1, 160, 
 
245
                    7400, 12200, 2, 1, 1, 
 
246
                    &predecode_amr, &parse_amr, &pack_amr,
 
247
                    {1, {{{"octet-align", 11}, {"1", 1}}} }
 
248
    },
 
249
#   endif
 
250
 
 
251
#   if PJMEDIA_HAS_INTEL_IPP_CODEC_AMRWB
 
252
    {1, "AMR-WB",   PJMEDIA_RTP_PT_AMRWB,     &USC_AMRWB_Fxns,  16000, 1, 320,
 
253
                    15850, 23850, 2, 1, 1, 
 
254
                    &predecode_amr, &parse_amr, &pack_amr,
 
255
                    {1, {{{"octet-align", 11}, {"1", 1}}} }
 
256
    },
 
257
#   endif
 
258
 
 
259
#   if PJMEDIA_HAS_INTEL_IPP_CODEC_G729
 
260
#       if defined(PJ_HAS_FLOATING_POINT) && (PJ_HAS_FLOATING_POINT != 0)
 
261
    {1, "G729",     PJMEDIA_RTP_PT_G729,      &USC_G729AFP_Fxns, 8000, 1,  80,
 
262
                    8000, 11800, 2, 1, 1, 
 
263
                    &predecode_g729, NULL, NULL
 
264
    },
 
265
#       else
 
266
    {1, "G729",     PJMEDIA_RTP_PT_G729,      &USC_G729I_Fxns,   8000, 1,  80,
 
267
                    8000, 11800, 2, 1, 1, 
 
268
                    &predecode_g729, NULL, NULL
 
269
    },
 
270
#       endif
 
271
#   endif
 
272
 
 
273
#   if PJMEDIA_HAS_INTEL_IPP_CODEC_G723_1
 
274
    /* This is actually G.723.1 */
 
275
    {1, "G723",     PJMEDIA_RTP_PT_G723,      &USC_G723_Fxns,    8000, 1, 240,  
 
276
                    6300,  6300, 1, 1, 1, 
 
277
                    &predecode_g723, &parse_g723, NULL
 
278
    },
 
279
#   endif
 
280
 
 
281
#   if PJMEDIA_HAS_INTEL_IPP_CODEC_G726
 
282
    {0, "G726-16",  PJMEDIA_RTP_PT_G726_16,   &USC_G726_Fxns,    8000, 1,  80, 
 
283
                    16000, 16000, 2, 0, 0,
 
284
                    NULL, NULL, NULL
 
285
    },
 
286
    {0, "G726-24",  PJMEDIA_RTP_PT_G726_24,   &USC_G726_Fxns,    8000, 1,  80, 
 
287
                    24000, 24000, 2, 0, 0,
 
288
                    NULL, NULL, NULL
 
289
    },
 
290
    {1, "G726-32",  PJMEDIA_RTP_PT_G726_32,   &USC_G726_Fxns,    8000, 1,  80, 
 
291
                    32000, 32000, 2, 0, 0,
 
292
                    NULL, NULL, NULL
 
293
    },
 
294
    {0, "G726-40",  PJMEDIA_RTP_PT_G726_40,   &USC_G726_Fxns,    8000, 1,  80, 
 
295
                    40000, 40000, 2, 0, 0,
 
296
                    NULL, NULL, NULL
 
297
    },
 
298
    /* Old definition of G726-32 */
 
299
    {1, "G721",     PJMEDIA_RTP_PT_G721,      &USC_G726_Fxns,    8000, 1,  80, 
 
300
                    32000, 32000, 2, 0, 0,
 
301
                    NULL, NULL, NULL
 
302
    },
 
303
#   endif
 
304
 
 
305
#   if PJMEDIA_HAS_INTEL_IPP_CODEC_G728
 
306
    {1, "G728",     PJMEDIA_RTP_PT_G728,      &USC_G728_Fxns,    8000, 1,  80, 
 
307
                    16000, 16000, 2, 0, 1,
 
308
                    NULL, NULL, NULL
 
309
    },
 
310
#   endif
 
311
 
 
312
#   if PJMEDIA_HAS_INTEL_IPP_CODEC_G722_1
 
313
    {0, "G7221",    PJMEDIA_RTP_PT_G722_1_16, &USC_G722_Fxns,   16000, 1, 320, 
 
314
                    16000, 16000, 1, 0, 1,
 
315
                    predecode_g7221, NULL, pack_g7221,
 
316
                    {1, {{{"bitrate", 7}, {"16000", 5}}} }
 
317
    },
 
318
    {1, "G7221",    PJMEDIA_RTP_PT_G722_1_24, &USC_G722_Fxns,   16000, 1, 320, 
 
319
                    24000, 24000, 1, 0, 1,
 
320
                    predecode_g7221, NULL, pack_g7221,
 
321
                    {1, {{{"bitrate", 7}, {"24000", 5}}} }
 
322
    },
 
323
    {1, "G7221",    PJMEDIA_RTP_PT_G722_1_32, &USC_G722_Fxns,   16000, 1, 320, 
 
324
                    32000, 32000, 1, 0, 1,
 
325
                    predecode_g7221, NULL, pack_g7221,
 
326
                    {1, {{{"bitrate", 7}, {"32000", 5}}} }
 
327
    },
 
328
#   endif
 
329
};
 
330
 
 
331
 
 
332
#if PJMEDIA_HAS_INTEL_IPP_CODEC_G729
 
333
 
 
334
static void predecode_g729( ipp_private_t *codec_data,
 
335
                            const pjmedia_frame *rtp_frame,
 
336
                            USC_Bitstream *usc_frame)
 
337
{
 
338
    switch (rtp_frame->size) {
 
339
    case 2:
 
340
        /* SID */
 
341
        usc_frame->frametype = 1;
 
342
        usc_frame->bitrate = codec_data->info->params.modes.bitrate;
 
343
        break;
 
344
    case 8:  
 
345
        /* G729D */
 
346
        usc_frame->frametype = 2;
 
347
        usc_frame->bitrate = 6400;
 
348
        break;
 
349
    case 10: 
 
350
        /* G729 */
 
351
        usc_frame->frametype = 3;
 
352
        usc_frame->bitrate = 8000;
 
353
        break;
 
354
    case 15: 
 
355
        /* G729E */
 
356
        usc_frame->frametype = 4;
 
357
        usc_frame->bitrate = 11800;
 
358
        break;
 
359
    default: 
 
360
        usc_frame->frametype = 0;
 
361
        usc_frame->bitrate = 0;
 
362
        break;
 
363
    }
 
364
 
 
365
    usc_frame->pBuffer = rtp_frame->buf;
 
366
    usc_frame->nbytes = rtp_frame->size;
 
367
}
 
368
 
 
369
#endif /* PJMEDIA_HAS_INTEL_IPP_CODEC_G729 */
 
370
 
 
371
 
 
372
#if PJMEDIA_HAS_INTEL_IPP_CODEC_G723_1
 
373
 
 
374
static    void predecode_g723( ipp_private_t *codec_data,
 
375
                               const pjmedia_frame *rtp_frame,
 
376
                               USC_Bitstream *usc_frame)
 
377
{
 
378
    int i, HDR = 0;
 
379
    pj_uint8_t *f = (pj_uint8_t*)rtp_frame->buf;
 
380
 
 
381
    PJ_UNUSED_ARG(codec_data);
 
382
 
 
383
    for (i = 0; i < 2; ++i){
 
384
        int tmp;
 
385
        tmp = (f[0] >> (i & 0x7)) & 1;
 
386
        HDR +=  tmp << i ;
 
387
    }
 
388
 
 
389
    usc_frame->pBuffer = rtp_frame->buf;
 
390
    usc_frame->nbytes = rtp_frame->size;
 
391
    usc_frame->bitrate = HDR == 0? 6300 : 5300;
 
392
    usc_frame->frametype = 0;
 
393
}
 
394
 
 
395
static pj_status_t parse_g723(ipp_private_t *codec_data, void *pkt, 
 
396
                              pj_size_t pkt_size, const pj_timestamp *ts,
 
397
                              unsigned *frame_cnt, pjmedia_frame frames[])
 
398
{
 
399
    unsigned count = 0;
 
400
    pj_uint8_t *f = (pj_uint8_t*)pkt;
 
401
 
 
402
    while (pkt_size && count < *frame_cnt) {
 
403
        int framesize, i, j;
 
404
        int HDR = 0;
 
405
 
 
406
        for (i = 0; i < 2; ++i){
 
407
            j = (f[0] >> (i & 0x7)) & 1;
 
408
            HDR +=  j << i ;
 
409
        }
 
410
 
 
411
        if (HDR == 0)
 
412
            framesize = 24;
 
413
        else if (HDR == 1)
 
414
            framesize = 20;
 
415
        else if (HDR == 2)
 
416
            framesize = 4;
 
417
        else if (HDR == 3)
 
418
            framesize = 1;
 
419
        else {
 
420
            pj_assert(!"Unknown G723.1 frametype, packet may be corrupted!");
 
421
            return PJMEDIA_CODEC_EINMODE;
 
422
        }
 
423
 
 
424
        frames[count].type = PJMEDIA_FRAME_TYPE_AUDIO;
 
425
        frames[count].buf = f;
 
426
        frames[count].size = framesize;
 
427
        frames[count].timestamp.u64 = ts->u64 + count * 
 
428
                        ipp_codec[codec_data->codec_idx].samples_per_frame;
 
429
 
 
430
        f += framesize;
 
431
        pkt_size -= framesize;
 
432
 
 
433
        ++count;
 
434
    }
 
435
 
 
436
    *frame_cnt = count;
 
437
    return PJ_SUCCESS;
 
438
}
 
439
 
 
440
#endif /* PJMEDIA_HAS_INTEL_IPP_CODEC_G723_1 */
 
441
 
 
442
 
 
443
#if PJMEDIA_HAS_INTEL_IPP_CODEC_AMR || PJMEDIA_HAS_INTEL_IPP_CODEC_AMRWB
 
444
 
 
445
#include <pjmedia-codec/amr_helper.h>
 
446
 
 
447
typedef struct amr_settings_t {
 
448
    pjmedia_codec_amr_pack_setting enc_setting;
 
449
    pjmedia_codec_amr_pack_setting dec_setting;
 
450
    pj_int8_t enc_mode;
 
451
} amr_settings_t;
 
452
 
 
453
 
 
454
/* Rearrange AMR bitstream and convert RTP frame into USC frame:
 
455
 * - make the start_bit to be 0
 
456
 * - if it is speech frame, reorder bitstream from sensitivity bits order
 
457
 *   to encoder bits order.
 
458
 * - set the appropriate value of usc_frame.
 
459
 */
 
460
static void predecode_amr( ipp_private_t *codec_data,
 
461
                           const pjmedia_frame *rtp_frame,
 
462
                           USC_Bitstream *usc_frame)
 
463
{
 
464
    pjmedia_frame frame;
 
465
    pjmedia_codec_amr_bit_info *info;
 
466
    pjmedia_codec_amr_pack_setting *setting;
 
467
 
 
468
    setting = &((amr_settings_t*)codec_data->codec_setting)->dec_setting;
 
469
 
 
470
    frame = *rtp_frame;
 
471
    pjmedia_codec_amr_predecode(rtp_frame, setting, &frame);
 
472
    info = (pjmedia_codec_amr_bit_info*) &frame.bit_info;
 
473
 
 
474
    usc_frame->pBuffer = frame.buf;
 
475
    usc_frame->nbytes = frame.size;
 
476
    if (info->mode != -1) {
 
477
        usc_frame->bitrate = setting->amr_nb? 
 
478
                             pjmedia_codec_amrnb_bitrates[info->mode]:
 
479
                             pjmedia_codec_amrwb_bitrates[info->mode];
 
480
    } else {
 
481
        usc_frame->bitrate = 0;
 
482
    }
 
483
 
 
484
    if (frame.size > 5) {
 
485
        /* Speech */
 
486
        if (info->good_quality)
 
487
            usc_frame->frametype = 0;
 
488
        else
 
489
            usc_frame->frametype = setting->amr_nb ? 5 : 6;
 
490
    } else if (frame.size == 5) {
 
491
        /* SID */
 
492
        if (info->good_quality) {
 
493
            usc_frame->frametype = info->STI? 2 : 1;
 
494
        } else {
 
495
            usc_frame->frametype = setting->amr_nb ? 6 : 7;
 
496
        }
 
497
    } else {
 
498
        /* no data */
 
499
        usc_frame->frametype = 3;
 
500
    }
 
501
}
 
502
 
 
503
/* Pack AMR payload */
 
504
static pj_status_t pack_amr(ipp_private_t *codec_data, void *pkt, 
 
505
                            pj_size_t *pkt_size, pj_size_t max_pkt_size)
 
506
{
 
507
    enum {MAX_FRAMES_PER_PACKET = PJMEDIA_MAX_FRAME_DURATION_MS / 20};
 
508
 
 
509
    pjmedia_frame frames[MAX_FRAMES_PER_PACKET];
 
510
    unsigned nframes = 0;
 
511
    pjmedia_codec_amr_bit_info *info;
 
512
    pj_uint8_t *r; /* Read cursor */
 
513
    pj_uint8_t SID_FT;
 
514
    pjmedia_codec_amr_pack_setting *setting;
 
515
    const pj_uint8_t *framelen_tbl;
 
516
 
 
517
    setting = &((amr_settings_t*)codec_data->codec_setting)->enc_setting;
 
518
    framelen_tbl = setting->amr_nb? pjmedia_codec_amrnb_framelen:
 
519
                                    pjmedia_codec_amrwb_framelen;
 
520
 
 
521
    SID_FT = (pj_uint8_t)(setting->amr_nb? 8 : 9);
 
522
 
 
523
    /* Align pkt buf right */
 
524
    r = (pj_uint8_t*)pkt + max_pkt_size - *pkt_size;
 
525
    pj_memmove(r, pkt, *pkt_size);
 
526
 
 
527
    /* Get frames */
 
528
    for (;;) {
 
529
        pj_bool_t eof;
 
530
        pj_uint16_t info_;
 
531
 
 
532
        info_ = *((pj_uint16_t*)r);
 
533
        eof = ((info_ & 0x40) != 0);
 
534
 
 
535
        info = (pjmedia_codec_amr_bit_info*) &frames[nframes].bit_info;
 
536
        pj_bzero(info, sizeof(*info));
 
537
        info->frame_type = (pj_uint8_t)(info_ & 0x0F);
 
538
        info->good_quality = (pj_uint8_t)((info_ & 0x80) == 0);
 
539
        info->mode = (pj_int8_t) ((info_ >> 8) & 0x0F);
 
540
        info->STI = (pj_uint8_t)((info_ >> 5) & 1);
 
541
 
 
542
        frames[nframes].buf = r + 2;
 
543
        frames[nframes].size = info->frame_type <= SID_FT ?
 
544
                               framelen_tbl[info->frame_type] : 0;
 
545
 
 
546
        r += frames[nframes].size + 2;
 
547
 
 
548
        /* Last frame */
 
549
        if (++nframes >= MAX_FRAMES_PER_PACKET || eof)
 
550
            break;
 
551
    }
 
552
 
 
553
    /* Pack */
 
554
    *pkt_size = max_pkt_size;
 
555
    return pjmedia_codec_amr_pack(frames, nframes, setting, pkt, pkt_size);
 
556
}
 
557
 
 
558
 
 
559
/* Parse AMR payload into frames. */
 
560
static pj_status_t parse_amr(ipp_private_t *codec_data, void *pkt, 
 
561
                             pj_size_t pkt_size, const pj_timestamp *ts,
 
562
                             unsigned *frame_cnt, pjmedia_frame frames[])
 
563
{
 
564
    amr_settings_t* s = (amr_settings_t*)codec_data->codec_setting;
 
565
    pjmedia_codec_amr_pack_setting *setting;
 
566
    pj_status_t status;
 
567
    pj_uint8_t cmr;
 
568
 
 
569
    setting = &s->dec_setting;
 
570
 
 
571
    status = pjmedia_codec_amr_parse(pkt, pkt_size, ts, setting, frames, 
 
572
                                     frame_cnt, &cmr);
 
573
    if (status != PJ_SUCCESS)
 
574
        return status;
 
575
 
 
576
    /* Check Change Mode Request. */
 
577
    if (((setting->amr_nb && cmr <= 7) || (!setting->amr_nb && cmr <= 8)) &&
 
578
        s->enc_mode != cmr)
 
579
    {
 
580
        struct ipp_codec *ippc = &ipp_codec[codec_data->codec_idx];
 
581
 
 
582
        s->enc_mode = cmr;
 
583
        codec_data->info->params.modes.bitrate = s->enc_setting.amr_nb?
 
584
                                pjmedia_codec_amrnb_bitrates[s->enc_mode] :
 
585
                                pjmedia_codec_amrwb_bitrates[s->enc_mode];
 
586
        ippc->fxns->std.Control(&codec_data->info->params.modes, 
 
587
                                codec_data->enc);
 
588
 
 
589
        PJ_LOG(4,(THIS_FILE, "AMR%s switched encoding mode to: %d (%dbps)",
 
590
                  (s->enc_setting.amr_nb?"":"-WB"),
 
591
                  s->enc_mode,
 
592
                  codec_data->info->params.modes.bitrate));
 
593
    }
 
594
 
 
595
    return PJ_SUCCESS;
 
596
}
 
597
 
 
598
#endif /* PJMEDIA_HAS_INTEL_IPP_CODEC_AMR */
 
599
 
 
600
 
 
601
#if PJMEDIA_HAS_INTEL_IPP_CODEC_G722_1
 
602
 
 
603
static void predecode_g7221( ipp_private_t *codec_data,
 
604
                             const pjmedia_frame *rtp_frame,
 
605
                             USC_Bitstream *usc_frame)
 
606
{
 
607
    usc_frame->pBuffer = (char*)rtp_frame->buf;
 
608
    usc_frame->nbytes = rtp_frame->size;
 
609
    usc_frame->frametype = 0;
 
610
    usc_frame->bitrate = codec_data->info->params.modes.bitrate;
 
611
 
 
612
#if defined(PJ_IS_LITTLE_ENDIAN) && PJ_IS_LITTLE_ENDIAN!=0
 
613
    {
 
614
        pj_uint16_t *p, *p_end;
 
615
 
 
616
        p = (pj_uint16_t*)rtp_frame->buf;
 
617
        p_end = p + rtp_frame->size/2;
 
618
        while (p < p_end) {
 
619
            *p = pj_ntohs(*p);
 
620
            ++p;
 
621
        }
 
622
    }
 
623
#endif
 
624
}
 
625
 
 
626
static pj_status_t pack_g7221( ipp_private_t *codec_data, void *pkt, 
 
627
                               pj_size_t *pkt_size, pj_size_t max_pkt_size)
 
628
{
 
629
    PJ_UNUSED_ARG(codec_data);
 
630
    PJ_UNUSED_ARG(max_pkt_size);
 
631
 
 
632
#if defined(PJ_IS_LITTLE_ENDIAN) && PJ_IS_LITTLE_ENDIAN!=0
 
633
    {
 
634
        pj_uint16_t *p, *p_end;
 
635
 
 
636
        p = (pj_uint16_t*)pkt;
 
637
        p_end = p + *pkt_size/2;
 
638
        while (p < p_end) {
 
639
            *p = pj_htons(*p);
 
640
            ++p;
 
641
        }
 
642
    }
 
643
#else
 
644
    PJ_UNUSED_ARG(pkt);
 
645
    PJ_UNUSED_ARG(pkt_size);
 
646
#endif
 
647
 
 
648
    return PJ_SUCCESS;
 
649
}
 
650
 
 
651
 
 
652
#include <pjmedia-codec/g7221.h>
 
653
 
 
654
 
 
655
PJ_DEF(pj_status_t) pjmedia_codec_g7221_set_pcm_shift(int val)
 
656
{
 
657
    PJ_ASSERT_RETURN(val >= 0, PJ_EINVAL);
 
658
 
 
659
    ipp_factory.g7221_pcm_shift = val;
 
660
    return PJ_SUCCESS;
 
661
}
 
662
 
 
663
 
 
664
#endif /* PJMEDIA_HAS_INTEL_IPP_CODEC_G722_1 */
 
665
 
 
666
/*
 
667
 * Initialize and register IPP codec factory to pjmedia endpoint.
 
668
 */
 
669
PJ_DEF(pj_status_t) pjmedia_codec_ipp_init( pjmedia_endpt *endpt )
 
670
{
 
671
    pjmedia_codec_mgr *codec_mgr;
 
672
    pj_str_t codec_name;
 
673
    pj_status_t status;
 
674
 
 
675
    if (ipp_factory.pool != NULL) {
 
676
        /* Already initialized. */
 
677
        return PJ_SUCCESS;
 
678
    }
 
679
 
 
680
    /* Create IPP codec factory. */
 
681
    ipp_factory.base.op = &ipp_factory_op;
 
682
    ipp_factory.base.factory_data = NULL;
 
683
    ipp_factory.endpt = endpt;
 
684
    ipp_factory.g7221_pcm_shift = PJMEDIA_G7221_DEFAULT_PCM_SHIFT;
 
685
 
 
686
    ipp_factory.pool = pjmedia_endpt_create_pool(endpt, "IPP codecs", 4000, 4000);
 
687
    if (!ipp_factory.pool)
 
688
        return PJ_ENOMEM;
 
689
 
 
690
    /* Create mutex. */
 
691
    status = pj_mutex_create_simple(ipp_factory.pool, "IPP codecs", 
 
692
                                    &ipp_factory.mutex);
 
693
    if (status != PJ_SUCCESS)
 
694
        goto on_error;
 
695
 
 
696
    /* Get the codec manager. */
 
697
    codec_mgr = pjmedia_endpt_get_codec_mgr(endpt);
 
698
    if (!codec_mgr) {
 
699
        status = PJ_EINVALIDOP;
 
700
        goto on_error;
 
701
    }
 
702
 
 
703
    /* Register format match callback. */
 
704
#if PJMEDIA_HAS_INTEL_IPP_CODEC_G722_1
 
705
    pj_cstr(&codec_name, "G7221");
 
706
    status = pjmedia_sdp_neg_register_fmt_match_cb(
 
707
                                        &codec_name,
 
708
                                        &pjmedia_codec_g7221_match_sdp);
 
709
    if (status != PJ_SUCCESS)
 
710
        goto on_error;
 
711
#endif
 
712
 
 
713
#if PJMEDIA_HAS_INTEL_IPP_CODEC_AMR
 
714
    pj_cstr(&codec_name, "AMR");
 
715
    status = pjmedia_sdp_neg_register_fmt_match_cb(
 
716
                                        &codec_name,
 
717
                                        &pjmedia_codec_amr_match_sdp);
 
718
    if (status != PJ_SUCCESS)
 
719
        goto on_error;
 
720
#endif
 
721
 
 
722
#if PJMEDIA_HAS_INTEL_IPP_CODEC_AMRWB
 
723
    pj_cstr(&codec_name, "AMR-WB");
 
724
    status = pjmedia_sdp_neg_register_fmt_match_cb(
 
725
                                        &codec_name,
 
726
                                        &pjmedia_codec_amr_match_sdp);
 
727
    if (status != PJ_SUCCESS)
 
728
        goto on_error;
 
729
#endif
 
730
 
 
731
    /* Suppress compile warning */
 
732
    PJ_UNUSED_ARG(codec_name);
 
733
 
 
734
    /* Register codec factory to endpoint. */
 
735
    status = pjmedia_codec_mgr_register_factory(codec_mgr, 
 
736
                                                &ipp_factory.base);
 
737
    if (status != PJ_SUCCESS)
 
738
        goto on_error;
 
739
 
 
740
    /* Done. */
 
741
    return PJ_SUCCESS;
 
742
 
 
743
on_error:
 
744
    pj_pool_release(ipp_factory.pool);
 
745
    ipp_factory.pool = NULL;
 
746
    return status;
 
747
}
 
748
 
 
749
/*
 
750
 * Unregister IPP codecs factory from pjmedia endpoint.
 
751
 */
 
752
PJ_DEF(pj_status_t) pjmedia_codec_ipp_deinit(void)
 
753
{
 
754
    pjmedia_codec_mgr *codec_mgr;
 
755
    pj_status_t status;
 
756
 
 
757
    if (ipp_factory.pool == NULL) {
 
758
        /* Already deinitialized */
 
759
        return PJ_SUCCESS;
 
760
    }
 
761
 
 
762
    pj_mutex_lock(ipp_factory.mutex);
 
763
 
 
764
    /* Get the codec manager. */
 
765
    codec_mgr = pjmedia_endpt_get_codec_mgr(ipp_factory.endpt);
 
766
    if (!codec_mgr) {
 
767
        pj_pool_release(ipp_factory.pool);
 
768
        ipp_factory.pool = NULL;
 
769
        return PJ_EINVALIDOP;
 
770
    }
 
771
 
 
772
    /* Unregister IPP codecs factory. */
 
773
    status = pjmedia_codec_mgr_unregister_factory(codec_mgr,
 
774
                                                  &ipp_factory.base);
 
775
    
 
776
    /* Destroy mutex. */
 
777
    pj_mutex_destroy(ipp_factory.mutex);
 
778
 
 
779
    /* Destroy pool. */
 
780
    pj_pool_release(ipp_factory.pool);
 
781
    ipp_factory.pool = NULL;
 
782
 
 
783
    return status;
 
784
}
 
785
 
 
786
 
 
787
/* 
 
788
 * Check if factory can allocate the specified codec. 
 
789
 */
 
790
static pj_status_t ipp_test_alloc( pjmedia_codec_factory *factory, 
 
791
                                   const pjmedia_codec_info *info )
 
792
{
 
793
    unsigned i;
 
794
 
 
795
    PJ_UNUSED_ARG(factory);
 
796
 
 
797
    /* Type MUST be audio. */
 
798
    if (info->type != PJMEDIA_TYPE_AUDIO)
 
799
        return PJMEDIA_CODEC_EUNSUP;
 
800
 
 
801
    for (i = 0; i < PJ_ARRAY_SIZE(ipp_codec); ++i) {
 
802
        pj_str_t name = pj_str((char*)ipp_codec[i].name);
 
803
        if ((pj_stricmp(&info->encoding_name, &name) == 0) &&
 
804
            (info->clock_rate == (unsigned)ipp_codec[i].clock_rate) &&
 
805
            (info->channel_cnt == (unsigned)ipp_codec[i].channel_count) &&
 
806
            (ipp_codec[i].enabled))
 
807
        {
 
808
            return PJ_SUCCESS;
 
809
        }
 
810
    }
 
811
    
 
812
    /* Unsupported, or mode is disabled. */
 
813
    return PJMEDIA_CODEC_EUNSUP;
 
814
}
 
815
 
 
816
/*
 
817
 * Generate default attribute.
 
818
 */
 
819
static pj_status_t ipp_default_attr (pjmedia_codec_factory *factory, 
 
820
                                      const pjmedia_codec_info *id, 
 
821
                                      pjmedia_codec_param *attr )
 
822
{
 
823
    unsigned i;
 
824
 
 
825
    PJ_ASSERT_RETURN(factory==&ipp_factory.base, PJ_EINVAL);
 
826
 
 
827
    pj_bzero(attr, sizeof(pjmedia_codec_param));
 
828
 
 
829
    for (i = 0; i < PJ_ARRAY_SIZE(ipp_codec); ++i) {
 
830
        pj_str_t name = pj_str((char*)ipp_codec[i].name);
 
831
        if ((pj_stricmp(&id->encoding_name, &name) == 0) &&
 
832
            (id->clock_rate == (unsigned)ipp_codec[i].clock_rate) &&
 
833
            (id->channel_cnt == (unsigned)ipp_codec[i].channel_count) &&
 
834
            (id->pt == (unsigned)ipp_codec[i].pt))
 
835
        {
 
836
            attr->info.pt = (pj_uint8_t)id->pt;
 
837
            attr->info.channel_cnt = ipp_codec[i].channel_count;
 
838
            attr->info.clock_rate = ipp_codec[i].clock_rate;
 
839
            attr->info.avg_bps = ipp_codec[i].def_bitrate;
 
840
            attr->info.max_bps = ipp_codec[i].max_bitrate;
 
841
            attr->info.pcm_bits_per_sample = 16;
 
842
            attr->info.frm_ptime =  (pj_uint16_t)
 
843
                                    (ipp_codec[i].samples_per_frame * 1000 / 
 
844
                                    ipp_codec[i].channel_count / 
 
845
                                    ipp_codec[i].clock_rate);
 
846
            attr->setting.frm_per_pkt = ipp_codec[i].frm_per_pkt;
 
847
 
 
848
            /* Default flags. */
 
849
            attr->setting.plc = 1;
 
850
            attr->setting.penh= 0;
 
851
            attr->setting.vad = 1;
 
852
            attr->setting.cng = attr->setting.vad;
 
853
            attr->setting.dec_fmtp = ipp_codec[i].dec_fmtp;
 
854
 
 
855
            if (attr->setting.vad == 0) {
 
856
#if PJMEDIA_HAS_INTEL_IPP_CODEC_G729
 
857
                if (id->pt == PJMEDIA_RTP_PT_G729) {
 
858
                    /* Signal G729 Annex B is being disabled */
 
859
                    attr->setting.dec_fmtp.cnt = 1;
 
860
                    pj_strset2(&attr->setting.dec_fmtp.param[0].name, "annexb");
 
861
                    pj_strset2(&attr->setting.dec_fmtp.param[0].val, "no");
 
862
                }
 
863
#endif
 
864
            }
 
865
 
 
866
            return PJ_SUCCESS;
 
867
        }
 
868
    }
 
869
 
 
870
    return PJMEDIA_CODEC_EUNSUP;
 
871
}
 
872
 
 
873
/*
 
874
 * Enum codecs supported by this factory.
 
875
 */
 
876
static pj_status_t ipp_enum_codecs(pjmedia_codec_factory *factory, 
 
877
                                    unsigned *count, 
 
878
                                    pjmedia_codec_info codecs[])
 
879
{
 
880
    unsigned max;
 
881
    unsigned i;
 
882
 
 
883
    PJ_UNUSED_ARG(factory);
 
884
    PJ_ASSERT_RETURN(codecs && *count > 0, PJ_EINVAL);
 
885
 
 
886
    max = *count;
 
887
    
 
888
    for (i = 0, *count = 0; i < PJ_ARRAY_SIZE(ipp_codec) && *count < max; ++i) 
 
889
    {
 
890
        if (!ipp_codec[i].enabled)
 
891
            continue;
 
892
 
 
893
        pj_bzero(&codecs[*count], sizeof(pjmedia_codec_info));
 
894
        codecs[*count].encoding_name = pj_str((char*)ipp_codec[i].name);
 
895
        codecs[*count].pt = ipp_codec[i].pt;
 
896
        codecs[*count].type = PJMEDIA_TYPE_AUDIO;
 
897
        codecs[*count].clock_rate = ipp_codec[i].clock_rate;
 
898
        codecs[*count].channel_cnt = ipp_codec[i].channel_count;
 
899
 
 
900
        ++*count;
 
901
    }
 
902
 
 
903
    return PJ_SUCCESS;
 
904
}
 
905
 
 
906
/*
 
907
 * Allocate a new codec instance.
 
908
 */
 
909
static pj_status_t ipp_alloc_codec( pjmedia_codec_factory *factory, 
 
910
                                    const pjmedia_codec_info *id,
 
911
                                    pjmedia_codec **p_codec)
 
912
{
 
913
    ipp_private_t *codec_data;
 
914
    pjmedia_codec *codec;
 
915
    int idx;
 
916
    pj_pool_t *pool;
 
917
    unsigned i;
 
918
 
 
919
    PJ_ASSERT_RETURN(factory && id && p_codec, PJ_EINVAL);
 
920
    PJ_ASSERT_RETURN(factory == &ipp_factory.base, PJ_EINVAL);
 
921
 
 
922
    pj_mutex_lock(ipp_factory.mutex);
 
923
 
 
924
    /* Find codec's index */
 
925
    idx = -1;
 
926
    for (i = 0; i < PJ_ARRAY_SIZE(ipp_codec); ++i) {
 
927
        pj_str_t name = pj_str((char*)ipp_codec[i].name);
 
928
        if ((pj_stricmp(&id->encoding_name, &name) == 0) &&
 
929
            (id->clock_rate == (unsigned)ipp_codec[i].clock_rate) &&
 
930
            (id->channel_cnt == (unsigned)ipp_codec[i].channel_count) &&
 
931
            (ipp_codec[i].enabled))
 
932
        {
 
933
            idx = i;
 
934
            break;
 
935
        }
 
936
    }
 
937
    if (idx == -1) {
 
938
        *p_codec = NULL;
 
939
        return PJMEDIA_CODEC_EFAILED;
 
940
    }
 
941
 
 
942
    /* Create pool for codec instance */
 
943
    pool = pjmedia_endpt_create_pool(ipp_factory.endpt, "IPPcodec", 512, 512);
 
944
    codec = PJ_POOL_ZALLOC_T(pool, pjmedia_codec);
 
945
    PJ_ASSERT_RETURN(codec != NULL, PJ_ENOMEM);
 
946
    codec->op = &ipp_op;
 
947
    codec->factory = factory;
 
948
    codec->codec_data = PJ_POOL_ZALLOC_T(pool, ipp_private_t);
 
949
    codec_data = (ipp_private_t*) codec->codec_data;
 
950
 
 
951
    /* Create PLC if codec has no internal PLC */
 
952
    if (!ipp_codec[idx].has_native_plc) {
 
953
        pj_status_t status;
 
954
        status = pjmedia_plc_create(pool, ipp_codec[idx].clock_rate, 
 
955
                                    ipp_codec[idx].samples_per_frame, 0,
 
956
                                    &codec_data->plc);
 
957
        if (status != PJ_SUCCESS) {
 
958
            pj_pool_release(pool);
 
959
            pj_mutex_unlock(ipp_factory.mutex);
 
960
            return status;
 
961
        }
 
962
    }
 
963
 
 
964
    /* Create silence detector if codec has no internal VAD */
 
965
    if (!ipp_codec[idx].has_native_vad) {
 
966
        pj_status_t status;
 
967
        status = pjmedia_silence_det_create(pool,
 
968
                                            ipp_codec[idx].clock_rate,
 
969
                                            ipp_codec[idx].samples_per_frame,
 
970
                                            &codec_data->vad);
 
971
        if (status != PJ_SUCCESS) {
 
972
            pj_pool_release(pool);
 
973
            pj_mutex_unlock(ipp_factory.mutex);
 
974
            return status;
 
975
        }
 
976
    }
 
977
 
 
978
    codec_data->pool = pool;
 
979
    codec_data->codec_idx = idx;
 
980
 
 
981
    pj_mutex_unlock(ipp_factory.mutex);
 
982
 
 
983
    *p_codec = codec;
 
984
    return PJ_SUCCESS;
 
985
}
 
986
 
 
987
/*
 
988
 * Free codec.
 
989
 */
 
990
static pj_status_t ipp_dealloc_codec( pjmedia_codec_factory *factory, 
 
991
                                      pjmedia_codec *codec )
 
992
{
 
993
    ipp_private_t *codec_data;
 
994
 
 
995
    PJ_ASSERT_RETURN(factory && codec, PJ_EINVAL);
 
996
    PJ_ASSERT_RETURN(factory == &ipp_factory.base, PJ_EINVAL);
 
997
 
 
998
    /* Close codec, if it's not closed. */
 
999
    codec_data = (ipp_private_t*) codec->codec_data;
 
1000
    if (codec_data->enc != NULL || codec_data->dec != NULL) {
 
1001
        ipp_codec_close(codec);
 
1002
    }
 
1003
 
 
1004
    pj_pool_release(codec_data->pool);
 
1005
 
 
1006
    return PJ_SUCCESS;
 
1007
}
 
1008
 
 
1009
/*
 
1010
 * Init codec.
 
1011
 */
 
1012
static pj_status_t ipp_codec_init( pjmedia_codec *codec, 
 
1013
                                   pj_pool_t *pool )
 
1014
{
 
1015
    PJ_UNUSED_ARG(codec);
 
1016
    PJ_UNUSED_ARG(pool);
 
1017
    return PJ_SUCCESS;
 
1018
}
 
1019
 
 
1020
/*
 
1021
 * Open codec.
 
1022
 */
 
1023
static pj_status_t ipp_codec_open( pjmedia_codec *codec, 
 
1024
                                   pjmedia_codec_param *attr )
 
1025
{
 
1026
    ipp_private_t *codec_data = (ipp_private_t*) codec->codec_data;
 
1027
    struct ipp_codec *ippc = &ipp_codec[codec_data->codec_idx];
 
1028
    int info_size;
 
1029
    pj_pool_t *pool;
 
1030
    int i, j;
 
1031
    USC_MemBank *membanks;
 
1032
    int nb_membanks;
 
1033
 
 
1034
    pool = codec_data->pool;
 
1035
 
 
1036
    /* Get the codec info size */
 
1037
    if (USC_NoError != ippc->fxns->std.GetInfoSize(&info_size)) {
 
1038
        PJ_LOG(1,(THIS_FILE, "Error getting codec info size"));
 
1039
        goto on_error;
 
1040
    }
 
1041
    /* Get the codec info */
 
1042
    codec_data->info = pj_pool_zalloc(pool, info_size);
 
1043
    if (USC_NoError != ippc->fxns->std.GetInfo((USC_Handle)NULL, 
 
1044
                                               codec_data->info))
 
1045
    {
 
1046
        PJ_LOG(1,(THIS_FILE, "Error getting codec info"));
 
1047
        goto on_error;
 
1048
    }
 
1049
 
 
1050
    /* PREPARING THE ENCODER */
 
1051
 
 
1052
    /* Setting the encoder params */
 
1053
    codec_data->info->params.direction = USC_ENCODE;
 
1054
    codec_data->info->params.modes.vad = attr->setting.vad && 
 
1055
                                         ippc->has_native_vad;
 
1056
    codec_data->info->params.modes.bitrate = attr->info.avg_bps;
 
1057
    codec_data->info->params.law = 0; /* Linear PCM input */
 
1058
 
 
1059
#if PJMEDIA_HAS_INTEL_IPP_CODEC_G729
 
1060
    if (ippc->pt == PJMEDIA_RTP_PT_G729) {
 
1061
        /* Check if G729 Annex B is signaled to be disabled */
 
1062
        for (i = 0; i < attr->setting.enc_fmtp.cnt; ++i) {
 
1063
            if (pj_stricmp2(&attr->setting.enc_fmtp.param[i].name, "annexb")==0)
 
1064
            {
 
1065
                if (pj_stricmp2(&attr->setting.enc_fmtp.param[i].val, "no")==0)
 
1066
                {
 
1067
                    attr->setting.vad = 0;
 
1068
                    codec_data->info->params.modes.vad = 0;
 
1069
                }
 
1070
                break;
 
1071
            }
 
1072
        }
 
1073
    }
 
1074
#endif
 
1075
 
 
1076
    /* Get number of memory blocks needed by the encoder */
 
1077
    if (USC_NoError != ippc->fxns->std.NumAlloc(&codec_data->info->params,
 
1078
                                                &nb_membanks))
 
1079
    {
 
1080
        PJ_LOG(1,(THIS_FILE, "Error getting no of memory blocks of encoder"));
 
1081
        goto on_error;
 
1082
    }
 
1083
 
 
1084
    /* Allocate memory blocks table */
 
1085
    membanks = (USC_MemBank*) pj_pool_zalloc(pool, 
 
1086
                                             sizeof(USC_MemBank) * nb_membanks);
 
1087
    /* Get size of each memory block */
 
1088
    if (USC_NoError != ippc->fxns->std.MemAlloc(&codec_data->info->params, 
 
1089
                                                membanks))
 
1090
    {
 
1091
        PJ_LOG(1,(THIS_FILE, "Error getting memory blocks size of encoder"));
 
1092
        goto on_error;
 
1093
    }
 
1094
 
 
1095
    /* Allocate memory for each block */
 
1096
    for (i = 0; i < nb_membanks; i++) {
 
1097
        membanks[i].pMem = (char*) pj_pool_zalloc(pool, membanks[i].nbytes);
 
1098
    }
 
1099
 
 
1100
    /* Create encoder instance */
 
1101
    if (USC_NoError != ippc->fxns->std.Init(&codec_data->info->params,
 
1102
                                            membanks, 
 
1103
                                            &codec_data->enc))
 
1104
    {
 
1105
        PJ_LOG(1,(THIS_FILE, "Error initializing encoder"));
 
1106
        goto on_error;
 
1107
    }
 
1108
 
 
1109
    /* PREPARING THE DECODER */
 
1110
 
 
1111
    /* Setting the decoder params */
 
1112
    codec_data->info->params.direction = USC_DECODE;
 
1113
 
 
1114
    /* Not sure if VAD affects decoder, just try to be safe */
 
1115
    //codec_data->info->params.modes.vad = ippc->has_native_vad;
 
1116
 
 
1117
    /* Get number of memory blocks needed by the decoder */
 
1118
    if (USC_NoError != ippc->fxns->std.NumAlloc(&codec_data->info->params, 
 
1119
                                                 &nb_membanks))
 
1120
    {
 
1121
        PJ_LOG(1,(THIS_FILE, "Error getting no of memory blocks of decoder"));
 
1122
        goto on_error;
 
1123
    }
 
1124
 
 
1125
    /* Allocate memory blocks table */
 
1126
    membanks = (USC_MemBank*) pj_pool_zalloc(pool, 
 
1127
                                             sizeof(USC_MemBank) * nb_membanks);
 
1128
    /* Get size of each memory block */
 
1129
    if (USC_NoError != ippc->fxns->std.MemAlloc(&codec_data->info->params, 
 
1130
                                                membanks))
 
1131
    {
 
1132
        PJ_LOG(1,(THIS_FILE, "Error getting memory blocks size of decoder"));
 
1133
        goto on_error;
 
1134
    }
 
1135
 
 
1136
    /* Allocate memory for each block */
 
1137
    for (i = 0; i < nb_membanks; i++) {
 
1138
        membanks[i].pMem = (char*) pj_pool_zalloc(pool, membanks[i].nbytes);
 
1139
    }
 
1140
 
 
1141
    /* Create decoder instance */
 
1142
    if (USC_NoError != ippc->fxns->std.Init(&codec_data->info->params, 
 
1143
                                            membanks, &codec_data->dec))
 
1144
    {
 
1145
        PJ_LOG(1,(THIS_FILE, "Error initializing decoder"));
 
1146
        goto on_error;
 
1147
    }
 
1148
 
 
1149
    /* Update codec info */
 
1150
    ippc->fxns->std.GetInfo((USC_Handle)codec_data->enc, codec_data->info);
 
1151
 
 
1152
    /* Get bitstream size */
 
1153
    i = codec_data->info->params.modes.bitrate * ippc->samples_per_frame;
 
1154
    j = ippc->clock_rate << 3;
 
1155
    codec_data->frame_size = (pj_uint16_t)(i / j);
 
1156
    if (i % j) ++codec_data->frame_size;
 
1157
 
 
1158
    codec_data->vad_enabled = (attr->setting.vad != 0);
 
1159
    codec_data->plc_enabled = (attr->setting.plc != 0);
 
1160
 
 
1161
#if PJMEDIA_HAS_INTEL_IPP_CODEC_AMR
 
1162
    /* Init AMR settings */
 
1163
    if (ippc->pt == PJMEDIA_RTP_PT_AMR || ippc->pt == PJMEDIA_RTP_PT_AMRWB) {
 
1164
        amr_settings_t *s;
 
1165
        pj_uint8_t octet_align = 0;
 
1166
        pj_int8_t enc_mode;
 
1167
 
 
1168
        enc_mode = pjmedia_codec_amr_get_mode(
 
1169
                                codec_data->info->params.modes.bitrate);
 
1170
        pj_assert(enc_mode >= 0 && enc_mode <= 8);
 
1171
 
 
1172
        /* Check AMR specific attributes */
 
1173
 
 
1174
        for (i = 0; i < attr->setting.dec_fmtp.cnt; ++i) {
 
1175
            /* octet-align, one of the parameters that must have same value 
 
1176
             * in offer & answer (RFC 4867 Section 8.3.1). Just check fmtp
 
1177
             * in the decoder side, since it's value is guaranteed to fulfil 
 
1178
             * above requirement (by SDP negotiator).
 
1179
             */
 
1180
            const pj_str_t STR_FMTP_OCTET_ALIGN = {"octet-align", 11};
 
1181
            
 
1182
            if (pj_stricmp(&attr->setting.dec_fmtp.param[i].name, 
 
1183
                           &STR_FMTP_OCTET_ALIGN) == 0)
 
1184
            {
 
1185
                octet_align=(pj_uint8_t)
 
1186
                            pj_strtoul(&attr->setting.dec_fmtp.param[i].val);
 
1187
                break;
 
1188
            }
 
1189
        }
 
1190
 
 
1191
        for (i = 0; i < attr->setting.enc_fmtp.cnt; ++i) {
 
1192
            /* mode-set, encoding mode is chosen based on local default mode 
 
1193
             * setting:
 
1194
             * - if local default mode is included in the mode-set, use it
 
1195
             * - otherwise, find the closest mode to local default mode;
 
1196
             *   if there are two closest modes, prefer to use the higher
 
1197
             *   one, e.g: local default mode is 4, the mode-set param
 
1198
             *   contains '2,3,5,6', then 5 will be chosen.
 
1199
             */
 
1200
            const pj_str_t STR_FMTP_MODE_SET = {"mode-set", 8};
 
1201
            
 
1202
            if (pj_stricmp(&attr->setting.enc_fmtp.param[i].name, 
 
1203
                           &STR_FMTP_MODE_SET) == 0)
 
1204
            {
 
1205
                const char *p;
 
1206
                pj_size_t l;
 
1207
                pj_int8_t diff = 99;
 
1208
                
 
1209
                p = pj_strbuf(&attr->setting.enc_fmtp.param[i].val);
 
1210
                l = pj_strlen(&attr->setting.enc_fmtp.param[i].val);
 
1211
 
 
1212
                while (l--) {
 
1213
                    if ((ippc->pt==PJMEDIA_RTP_PT_AMR && *p>='0' && *p<='7') ||
 
1214
                        (ippc->pt==PJMEDIA_RTP_PT_AMRWB && *p>='0' && *p<='8'))
 
1215
                    {
 
1216
                        pj_int8_t tmp = (pj_int8_t)(*p - '0' - enc_mode);
 
1217
 
 
1218
                        if (PJ_ABS(diff) > PJ_ABS(tmp) || 
 
1219
                            (PJ_ABS(diff) == PJ_ABS(tmp) && tmp > diff))
 
1220
                        {
 
1221
                            diff = tmp;
 
1222
                            if (diff == 0) break;
 
1223
                        }
 
1224
                    }
 
1225
                    ++p;
 
1226
                }
 
1227
 
 
1228
                if (diff == 99)
 
1229
                    goto on_error;
 
1230
 
 
1231
                enc_mode = (pj_int8_t)(enc_mode + diff);
 
1232
 
 
1233
                break;
 
1234
            }
 
1235
        }
 
1236
 
 
1237
        /* Initialize AMR specific settings */
 
1238
        s = PJ_POOL_ZALLOC_T(pool, amr_settings_t);
 
1239
        codec_data->codec_setting = s;
 
1240
 
 
1241
        s->enc_setting.amr_nb = (pj_uint8_t)(ippc->pt == PJMEDIA_RTP_PT_AMR);
 
1242
        s->enc_setting.octet_aligned = octet_align;
 
1243
        s->enc_setting.reorder = PJ_TRUE;
 
1244
        s->enc_setting.cmr = 15;
 
1245
 
 
1246
        s->dec_setting.amr_nb = (pj_uint8_t)(ippc->pt == PJMEDIA_RTP_PT_AMR);
 
1247
        s->dec_setting.octet_aligned = octet_align;
 
1248
        s->dec_setting.reorder = PJ_TRUE;
 
1249
 
 
1250
        /* Apply encoder mode/bitrate */
 
1251
        s->enc_mode = enc_mode;
 
1252
        codec_data->info->params.modes.bitrate = s->enc_setting.amr_nb?
 
1253
                                pjmedia_codec_amrnb_bitrates[s->enc_mode]:
 
1254
                                pjmedia_codec_amrwb_bitrates[s->enc_mode];
 
1255
        ippc->fxns->std.Control(&codec_data->info->params.modes, 
 
1256
                                codec_data->enc);
 
1257
 
 
1258
        PJ_LOG(4,(THIS_FILE, "AMR%s encoding mode: %d (%dbps)", 
 
1259
                  (s->enc_setting.amr_nb?"":"-WB"),
 
1260
                  s->enc_mode,
 
1261
                  codec_data->info->params.modes.bitrate));
 
1262
 
 
1263
        /* Return back bitrate info to application */
 
1264
        attr->info.avg_bps = codec_data->info->params.modes.bitrate;
 
1265
    }
 
1266
#endif
 
1267
 
 
1268
#if PJMEDIA_HAS_INTEL_IPP_CODEC_G722_1
 
1269
    if (ippc->pt >= PJMEDIA_RTP_PT_G722_1_16 && 
 
1270
        ippc->pt <= PJMEDIA_RTP_PT_G7221_RSV2)
 
1271
    {
 
1272
        codec_data->g7221_pcm_shift = ipp_factory.g7221_pcm_shift;
 
1273
    }
 
1274
#endif
 
1275
 
 
1276
    return PJ_SUCCESS;
 
1277
 
 
1278
on_error:
 
1279
    return PJMEDIA_CODEC_EFAILED;
 
1280
}
 
1281
 
 
1282
/*
 
1283
 * Close codec.
 
1284
 */
 
1285
static pj_status_t ipp_codec_close( pjmedia_codec *codec )
 
1286
{
 
1287
    PJ_UNUSED_ARG(codec);
 
1288
 
 
1289
    return PJ_SUCCESS;
 
1290
}
 
1291
 
 
1292
 
 
1293
/*
 
1294
 * Modify codec settings.
 
1295
 */
 
1296
static pj_status_t  ipp_codec_modify(pjmedia_codec *codec, 
 
1297
                                     const pjmedia_codec_param *attr )
 
1298
{
 
1299
    ipp_private_t *codec_data = (ipp_private_t*) codec->codec_data;
 
1300
    struct ipp_codec *ippc = &ipp_codec[codec_data->codec_idx];
 
1301
 
 
1302
    codec_data->vad_enabled = (attr->setting.vad != 0);
 
1303
    codec_data->plc_enabled = (attr->setting.plc != 0);
 
1304
 
 
1305
    if (ippc->has_native_vad) {
 
1306
        USC_Modes modes;
 
1307
 
 
1308
        modes = codec_data->info->params.modes;
 
1309
        modes.vad = codec_data->vad_enabled;
 
1310
        ippc->fxns->std.Control(&modes, codec_data->enc);
 
1311
    }
 
1312
 
 
1313
    return PJ_SUCCESS;
 
1314
}
 
1315
 
 
1316
/*
 
1317
 * Get frames in the packet.
 
1318
 */
 
1319
static pj_status_t  ipp_codec_parse( pjmedia_codec *codec,
 
1320
                                     void *pkt,
 
1321
                                     pj_size_t pkt_size,
 
1322
                                     const pj_timestamp *ts,
 
1323
                                     unsigned *frame_cnt,
 
1324
                                     pjmedia_frame frames[])
 
1325
{
 
1326
    ipp_private_t *codec_data = (ipp_private_t*) codec->codec_data;
 
1327
    struct ipp_codec *ippc = &ipp_codec[codec_data->codec_idx];
 
1328
    unsigned count = 0;
 
1329
 
 
1330
    PJ_ASSERT_RETURN(frame_cnt, PJ_EINVAL);
 
1331
 
 
1332
    if (ippc->parse != NULL) {
 
1333
        return ippc->parse(codec_data, pkt,  pkt_size, ts, frame_cnt, frames);
 
1334
    }
 
1335
 
 
1336
    while (pkt_size >= codec_data->frame_size && count < *frame_cnt) {
 
1337
        frames[count].type = PJMEDIA_FRAME_TYPE_AUDIO;
 
1338
        frames[count].buf = pkt;
 
1339
        frames[count].size = codec_data->frame_size;
 
1340
        frames[count].timestamp.u64 = ts->u64 + count*ippc->samples_per_frame;
 
1341
 
 
1342
        pkt = ((char*)pkt) + codec_data->frame_size;
 
1343
        pkt_size -= codec_data->frame_size;
 
1344
 
 
1345
        ++count;
 
1346
    }
 
1347
 
 
1348
    if (pkt_size && count < *frame_cnt) {
 
1349
        frames[count].type = PJMEDIA_FRAME_TYPE_AUDIO;
 
1350
        frames[count].buf = pkt;
 
1351
        frames[count].size = pkt_size;
 
1352
        frames[count].timestamp.u64 = ts->u64 + count*ippc->samples_per_frame;
 
1353
        ++count;
 
1354
    }
 
1355
 
 
1356
    *frame_cnt = count;
 
1357
    return PJ_SUCCESS;
 
1358
}
 
1359
 
 
1360
/*
 
1361
 * Encode frames.
 
1362
 */
 
1363
static pj_status_t ipp_codec_encode( pjmedia_codec *codec, 
 
1364
                                     const struct pjmedia_frame *input,
 
1365
                                     unsigned output_buf_len, 
 
1366
                                     struct pjmedia_frame *output)
 
1367
{
 
1368
    ipp_private_t *codec_data = (ipp_private_t*) codec->codec_data;
 
1369
    struct ipp_codec *ippc = &ipp_codec[codec_data->codec_idx];
 
1370
    unsigned samples_per_frame;
 
1371
    unsigned nsamples;
 
1372
    pj_size_t tx = 0;
 
1373
    pj_int16_t *pcm_in   = (pj_int16_t*)input->buf;
 
1374
    pj_uint8_t  *bits_out = (pj_uint8_t*) output->buf;
 
1375
    pj_uint8_t pt;
 
1376
 
 
1377
    /* Invoke external VAD if codec has no internal VAD */
 
1378
    if (codec_data->vad && codec_data->vad_enabled) {
 
1379
        pj_bool_t is_silence;
 
1380
        pj_int32_t silence_duration;
 
1381
 
 
1382
        silence_duration = pj_timestamp_diff32(&codec_data->last_tx, 
 
1383
                                               &input->timestamp);
 
1384
 
 
1385
        is_silence = pjmedia_silence_det_detect(codec_data->vad, 
 
1386
                                                (const pj_int16_t*) input->buf,
 
1387
                                                (input->size >> 1),
 
1388
                                                NULL);
 
1389
        if (is_silence &&
 
1390
            (PJMEDIA_CODEC_MAX_SILENCE_PERIOD == -1 ||
 
1391
             silence_duration < (PJMEDIA_CODEC_MAX_SILENCE_PERIOD *
 
1392
                                 (int)ippc->clock_rate / 1000)))
 
1393
        {
 
1394
            output->type = PJMEDIA_FRAME_TYPE_NONE;
 
1395
            output->buf = NULL;
 
1396
            output->size = 0;
 
1397
            output->timestamp = input->timestamp;
 
1398
            return PJ_SUCCESS;
 
1399
        } else {
 
1400
            codec_data->last_tx = input->timestamp;
 
1401
        }
 
1402
    }
 
1403
 
 
1404
    nsamples = input->size >> 1;
 
1405
    samples_per_frame = ippc->samples_per_frame;
 
1406
    pt = ippc->pt;
 
1407
 
 
1408
    PJ_ASSERT_RETURN(nsamples % samples_per_frame == 0, 
 
1409
                     PJMEDIA_CODEC_EPCMFRMINLEN);
 
1410
 
 
1411
    /* Encode the frames */
 
1412
    while (nsamples >= samples_per_frame) {
 
1413
        USC_PCMStream in;
 
1414
        USC_Bitstream out;
 
1415
 
 
1416
        in.bitrate = codec_data->info->params.modes.bitrate;
 
1417
        in.nbytes = samples_per_frame << 1;
 
1418
        in.pBuffer = (char*)pcm_in;
 
1419
        in.pcmType.bitPerSample = codec_data->info->params.pcmType.bitPerSample;
 
1420
        in.pcmType.nChannels = codec_data->info->params.pcmType.nChannels;
 
1421
        in.pcmType.sample_frequency = codec_data->info->params.pcmType.sample_frequency;
 
1422
 
 
1423
        out.pBuffer = (char*)bits_out;
 
1424
 
 
1425
#if PJMEDIA_HAS_INTEL_IPP_CODEC_AMR
 
1426
        /* For AMR: reserve two octets for AMR frame info */
 
1427
        if (pt == PJMEDIA_RTP_PT_AMR || pt == PJMEDIA_RTP_PT_AMRWB) {
 
1428
            out.pBuffer += 2;
 
1429
        }
 
1430
#endif
 
1431
 
 
1432
#if PJMEDIA_HAS_INTEL_IPP_CODEC_G722_1
 
1433
        /* For G722.1: adjust the encoder input signal level */
 
1434
        if (pt >= PJMEDIA_RTP_PT_G722_1_16 && 
 
1435
            pt <= PJMEDIA_RTP_PT_G7221_RSV2 &&
 
1436
            codec_data->g7221_pcm_shift)
 
1437
        {
 
1438
            unsigned i;
 
1439
            for (i = 0; i < samples_per_frame; ++i)
 
1440
                pcm_in[i] >>= codec_data->g7221_pcm_shift;
 
1441
        }
 
1442
#endif
 
1443
 
 
1444
        if (USC_NoError != ippc->fxns->Encode(codec_data->enc, &in, &out)) {
 
1445
            break;
 
1446
        }
 
1447
 
 
1448
#if PJMEDIA_HAS_INTEL_IPP_CODEC_AMR
 
1449
        /* For AMR: put info (frametype, degraded, last frame, mode) in the 
 
1450
         * first two octets for payload packing.
 
1451
         */
 
1452
        if (pt == PJMEDIA_RTP_PT_AMR || pt == PJMEDIA_RTP_PT_AMRWB) {
 
1453
            pj_uint16_t *info = (pj_uint16_t*)bits_out;
 
1454
 
 
1455
            /* Two octets for AMR frame info, 0=LSB:
 
1456
             * bit 0-3  : frame type
 
1457
             * bit 5    : STI flag
 
1458
             * bit 6    : last frame flag
 
1459
             * bit 7    : quality flag
 
1460
             * bit 8-11 : mode
 
1461
             */
 
1462
            out.nbytes += 2;
 
1463
            if (out.frametype == 0 || out.frametype == 4 || 
 
1464
                (pt == PJMEDIA_RTP_PT_AMR && out.frametype == 5) ||
 
1465
                (pt == PJMEDIA_RTP_PT_AMRWB && out.frametype == 6))
 
1466
            {
 
1467
                /* Speech frame type */
 
1468
                *info = (char)pjmedia_codec_amr_get_mode(out.bitrate);
 
1469
                /* Quality */
 
1470
                if (out.frametype == 5 || out.frametype == 6)
 
1471
                    *info |= 0x80;
 
1472
            } else if (out.frametype == 1 || out.frametype == 2 || 
 
1473
                       (pt == PJMEDIA_RTP_PT_AMR && out.frametype == 6) ||
 
1474
                       (pt == PJMEDIA_RTP_PT_AMRWB && out.frametype == 7))
 
1475
            {
 
1476
                /* SID frame type */
 
1477
                *info = (pj_uint8_t)(pt == PJMEDIA_RTP_PT_AMRWB? 9 : 8);
 
1478
                /* Quality */
 
1479
                if (out.frametype == 6 || out.frametype == 7)
 
1480
                    *info |= 0x80;
 
1481
                /* STI */
 
1482
                if (out.frametype != 1)
 
1483
                    *info |= 0x20;
 
1484
            } else {
 
1485
                /* Untransmited */
 
1486
                *info = 15;
 
1487
                out.nbytes = 2;
 
1488
            }
 
1489
 
 
1490
            /* Mode */
 
1491
            *info |= (char)pjmedia_codec_amr_get_mode(out.bitrate) << 8;
 
1492
 
 
1493
            /* Last frame flag */
 
1494
            if (nsamples == samples_per_frame)
 
1495
                *info |= 0x40;
 
1496
        }
 
1497
#endif
 
1498
 
 
1499
        pcm_in += samples_per_frame;
 
1500
        nsamples -= samples_per_frame;
 
1501
        tx += out.nbytes;
 
1502
        bits_out += out.nbytes;
 
1503
 
 
1504
#if PJMEDIA_HAS_INTEL_IPP_CODEC_G729
 
1505
        if (pt == PJMEDIA_RTP_PT_G729) {
 
1506
            if (out.frametype == 1) {
 
1507
                /* SID */
 
1508
                break;
 
1509
            } else if (out.frametype == 0) {
 
1510
                /* Untransmitted */
 
1511
                tx -= out.nbytes;
 
1512
                break;
 
1513
            }
 
1514
        }
 
1515
#endif
 
1516
 
 
1517
    }
 
1518
 
 
1519
    if (ippc->pack != NULL) {
 
1520
        ippc->pack(codec_data, output->buf, &tx, output_buf_len);
 
1521
    }
 
1522
 
 
1523
    /* Check if we don't need to transmit the frame (DTX) */
 
1524
    if (tx == 0) {
 
1525
        output->buf = NULL;
 
1526
        output->size = 0;
 
1527
        output->timestamp.u64 = input->timestamp.u64;
 
1528
        output->type = PJMEDIA_FRAME_TYPE_NONE;
 
1529
        return PJ_SUCCESS;
 
1530
    }
 
1531
 
 
1532
    output->size = tx;
 
1533
    output->type = PJMEDIA_FRAME_TYPE_AUDIO;
 
1534
    output->timestamp = input->timestamp;
 
1535
 
 
1536
    return PJ_SUCCESS;
 
1537
}
 
1538
 
 
1539
/*
 
1540
 * Decode frame.
 
1541
 */
 
1542
static pj_status_t ipp_codec_decode( pjmedia_codec *codec, 
 
1543
                                     const struct pjmedia_frame *input,
 
1544
                                     unsigned output_buf_len, 
 
1545
                                     struct pjmedia_frame *output)
 
1546
{
 
1547
    ipp_private_t *codec_data = (ipp_private_t*) codec->codec_data;
 
1548
    struct ipp_codec *ippc = &ipp_codec[codec_data->codec_idx];
 
1549
    unsigned samples_per_frame;
 
1550
    USC_PCMStream out;
 
1551
    USC_Bitstream in;
 
1552
    pj_uint8_t pt;
 
1553
 
 
1554
    pt = ippc->pt; 
 
1555
    samples_per_frame = ippc->samples_per_frame;
 
1556
 
 
1557
    PJ_ASSERT_RETURN(output_buf_len >= samples_per_frame << 1,
 
1558
                     PJMEDIA_CODEC_EPCMTOOSHORT);
 
1559
 
 
1560
    if (input->type == PJMEDIA_FRAME_TYPE_AUDIO) {
 
1561
        if (ippc->predecode) {
 
1562
            ippc->predecode(codec_data, input, &in);
 
1563
        } else {
 
1564
            /* Most IPP codecs have frametype==0 for speech frame */
 
1565
            in.pBuffer = (char*)input->buf;
 
1566
            in.nbytes = input->size;
 
1567
            in.frametype = 0;
 
1568
            in.bitrate = codec_data->info->params.modes.bitrate;
 
1569
        }
 
1570
 
 
1571
        out.pBuffer = output->buf;
 
1572
    }
 
1573
 
 
1574
    if (input->type != PJMEDIA_FRAME_TYPE_AUDIO ||
 
1575
        USC_NoError != ippc->fxns->Decode(codec_data->dec, &in, &out)) 
 
1576
    {
 
1577
        pjmedia_zero_samples((pj_int16_t*)output->buf, samples_per_frame);
 
1578
        output->size = samples_per_frame << 1;
 
1579
        output->timestamp.u64 = input->timestamp.u64;
 
1580
        output->type = PJMEDIA_FRAME_TYPE_AUDIO;
 
1581
        return PJ_SUCCESS;
 
1582
    }
 
1583
 
 
1584
#if PJMEDIA_HAS_INTEL_IPP_CODEC_G726
 
1585
    /* For G.726: amplify decoding result (USC G.726 encoder deamplified it) */
 
1586
    if (pt == PJMEDIA_RTP_PT_G726_16 || pt == PJMEDIA_RTP_PT_G726_24 ||
 
1587
        pt == PJMEDIA_RTP_PT_G726_32 || pt == PJMEDIA_RTP_PT_G726_40 ||
 
1588
        pt == PJMEDIA_RTP_PT_G721)
 
1589
    {
 
1590
        unsigned i;
 
1591
        pj_int16_t *s = (pj_int16_t*)output->buf;
 
1592
 
 
1593
        for (i = 0; i < samples_per_frame; ++i)
 
1594
            s[i] <<= 2;
 
1595
    }
 
1596
#endif
 
1597
 
 
1598
#if PJMEDIA_HAS_INTEL_IPP_CODEC_G722_1
 
1599
    /* For G722.1: adjust the decoder output signal level */
 
1600
    if (pt >= PJMEDIA_RTP_PT_G722_1_16 && 
 
1601
        pt <= PJMEDIA_RTP_PT_G7221_RSV2 &&
 
1602
        codec_data->g7221_pcm_shift)
 
1603
    {
 
1604
        unsigned i;
 
1605
        pj_int16_t *s = (pj_int16_t*)output->buf;
 
1606
 
 
1607
        for (i = 0; i < samples_per_frame; ++i)
 
1608
            s[i] <<= codec_data->g7221_pcm_shift;
 
1609
    }
 
1610
#endif
 
1611
 
 
1612
    output->type = PJMEDIA_FRAME_TYPE_AUDIO;
 
1613
    output->size = samples_per_frame << 1;
 
1614
    output->timestamp.u64 = input->timestamp.u64;
 
1615
 
 
1616
    /* Invoke external PLC if codec has no internal PLC */
 
1617
    if (codec_data->plc && codec_data->plc_enabled)
 
1618
        pjmedia_plc_save(codec_data->plc, (pj_int16_t*)output->buf);
 
1619
 
 
1620
    return PJ_SUCCESS;
 
1621
}
 
1622
 
 
1623
/* 
 
1624
 * Recover lost frame.
 
1625
 */
 
1626
static pj_status_t  ipp_codec_recover(pjmedia_codec *codec, 
 
1627
                                      unsigned output_buf_len, 
 
1628
                                      struct pjmedia_frame *output)
 
1629
{
 
1630
    ipp_private_t *codec_data = (ipp_private_t*) codec->codec_data;
 
1631
    struct ipp_codec *ippc = &ipp_codec[codec_data->codec_idx];
 
1632
    unsigned samples_per_frame;
 
1633
 
 
1634
    PJ_UNUSED_ARG(output_buf_len);
 
1635
 
 
1636
    samples_per_frame = ippc->samples_per_frame;
 
1637
 
 
1638
    output->type = PJMEDIA_FRAME_TYPE_AUDIO;
 
1639
    output->size = samples_per_frame << 1;
 
1640
 
 
1641
    if (codec_data->plc_enabled) {
 
1642
        if (codec_data->plc) {
 
1643
            pjmedia_plc_generate(codec_data->plc, (pj_int16_t*)output->buf);
 
1644
        } else {
 
1645
            USC_PCMStream out;
 
1646
            out.pBuffer = output->buf;
 
1647
            ippc->fxns->Decode(codec_data->dec, NULL, &out);
 
1648
        }
 
1649
    } else {
 
1650
        pjmedia_zero_samples((pj_int16_t*)output->buf, samples_per_frame);
 
1651
    }
 
1652
 
 
1653
    return PJ_SUCCESS;
 
1654
}
 
1655
 
 
1656
 
 
1657
#if defined(_MSC_VER) && PJMEDIA_AUTO_LINK_IPP_LIBS
 
1658
#   pragma comment( lib, "ippcore.lib")
 
1659
#   pragma comment( lib, "ipps.lib")
 
1660
#   pragma comment( lib, "ippsc.lib")
 
1661
#   if defined(IPP_VERSION_MAJOR) && IPP_VERSION_MAJOR<=6
 
1662
#       pragma comment( lib, "ippsr.lib")
 
1663
#   endif
 
1664
//#   pragma comment( lib, "ippcorel.lib")
 
1665
//#   pragma comment( lib, "ippsemerged.lib")
 
1666
//#   pragma comment( lib, "ippsmerged.lib")
 
1667
//#   pragma comment( lib, "ippscemerged.lib")
 
1668
//#   pragma comment( lib, "ippscmerged.lib")
 
1669
//#   pragma comment( lib, "ippsremerged.lib")
 
1670
//#   pragma comment( lib, "ippsrmerged.lib")
 
1671
#   if defined(IPP_VERSION_MAJOR) && IPP_VERSION_MAJOR>=6
 
1672
#       pragma comment( lib, "speech.lib")
 
1673
#   else
 
1674
#       pragma comment( lib, "usc.lib")
 
1675
#   endif
 
1676
#endif
 
1677
 
 
1678
 
 
1679
#endif  /* PJMEDIA_HAS_INTEL_IPP */
 
1680