~ubuntu-branches/ubuntu/wily/sflphone/wily

« back to all changes in this revision

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

  • Committer: Package Import Robot
  • Author(s): Mark Purcell
  • Date: 2014-01-28 18:23:36 UTC
  • mfrom: (1.1.11)
  • mto: This revision was merged to the branch mainline in revision 24.
  • Revision ID: package-import@ubuntu.com-20140128182336-3xenud1kbnwmf3mz
* 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 */