blob: bbc58b7390db5103cb68979feb7a0f089b3973fd [file] [log] [blame]
Nanang Izzuddin493a8db2008-08-15 13:17:39 +00001/* $Id$ */
2/*
Benny Prijono844653c2008-12-23 17:27:53 +00003 * Copyright (C) 2008-2009 Teluu Inc. (http://www.teluu.com)
4 * Copyright (C) 2003-2008 Benny Prijono <benny@prijono.org>
Nanang Izzuddin493a8db2008-08-15 13:17:39 +00005 *
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.h>
22#include <pjmedia/errno.h>
23#include <pjmedia/endpoint.h>
24#include <pjmedia/plc.h>
25#include <pjmedia/port.h>
26#include <pjmedia/silencedet.h>
27#include <pj/assert.h>
28#include <pj/log.h>
29#include <pj/pool.h>
30#include <pj/string.h>
31#include <pj/os.h>
32
Nanang Izzuddin23a00b72008-08-25 13:58:25 +000033
Nanang Izzuddin493a8db2008-08-15 13:17:39 +000034/*
Benny Prijonoa4e7cdd2008-08-19 15:01:48 +000035 * Only build this file if PJMEDIA_HAS_INTEL_IPP != 0
Nanang Izzuddin493a8db2008-08-15 13:17:39 +000036 */
Benny Prijonoa4e7cdd2008-08-19 15:01:48 +000037#if defined(PJMEDIA_HAS_INTEL_IPP) && PJMEDIA_HAS_INTEL_IPP != 0
Nanang Izzuddin493a8db2008-08-15 13:17:39 +000038
39#include <usc.h>
Benny Prijonoe1e6d512009-01-02 15:17:47 +000040#include <ippversion.h>
Nanang Izzuddin493a8db2008-08-15 13:17:39 +000041
42#define THIS_FILE "ipp_codecs.c"
43
44/* Prototypes for IPP codecs factory */
45static pj_status_t ipp_test_alloc( pjmedia_codec_factory *factory,
46 const pjmedia_codec_info *id );
47static pj_status_t ipp_default_attr( pjmedia_codec_factory *factory,
48 const pjmedia_codec_info *id,
49 pjmedia_codec_param *attr );
50static pj_status_t ipp_enum_codecs( pjmedia_codec_factory *factory,
51 unsigned *count,
52 pjmedia_codec_info codecs[]);
53static pj_status_t ipp_alloc_codec( pjmedia_codec_factory *factory,
54 const pjmedia_codec_info *id,
55 pjmedia_codec **p_codec);
56static pj_status_t ipp_dealloc_codec( pjmedia_codec_factory *factory,
57 pjmedia_codec *codec );
58
59/* Prototypes for IPP codecs implementation. */
60static pj_status_t ipp_codec_init( pjmedia_codec *codec,
61 pj_pool_t *pool );
62static pj_status_t ipp_codec_open( pjmedia_codec *codec,
63 pjmedia_codec_param *attr );
64static pj_status_t ipp_codec_close( pjmedia_codec *codec );
65static pj_status_t ipp_codec_modify(pjmedia_codec *codec,
66 const pjmedia_codec_param *attr );
67static pj_status_t ipp_codec_parse( pjmedia_codec *codec,
68 void *pkt,
69 pj_size_t pkt_size,
70 const pj_timestamp *ts,
71 unsigned *frame_cnt,
72 pjmedia_frame frames[]);
73static pj_status_t ipp_codec_encode( pjmedia_codec *codec,
74 const struct pjmedia_frame *input,
75 unsigned output_buf_len,
76 struct pjmedia_frame *output);
77static pj_status_t ipp_codec_decode( pjmedia_codec *codec,
78 const struct pjmedia_frame *input,
79 unsigned output_buf_len,
80 struct pjmedia_frame *output);
81static pj_status_t ipp_codec_recover(pjmedia_codec *codec,
82 unsigned output_buf_len,
83 struct pjmedia_frame *output);
84
85/* Definition for IPP codecs operations. */
86static pjmedia_codec_op ipp_op =
87{
88 &ipp_codec_init,
89 &ipp_codec_open,
90 &ipp_codec_close,
91 &ipp_codec_modify,
92 &ipp_codec_parse,
93 &ipp_codec_encode,
94 &ipp_codec_decode,
95 &ipp_codec_recover
96};
97
98/* Definition for IPP codecs factory operations. */
99static pjmedia_codec_factory_op ipp_factory_op =
100{
101 &ipp_test_alloc,
102 &ipp_default_attr,
103 &ipp_enum_codecs,
104 &ipp_alloc_codec,
105 &ipp_dealloc_codec
106};
107
108/* IPP codecs factory */
109static struct ipp_factory {
110 pjmedia_codec_factory base;
111 pjmedia_endpt *endpt;
112 pj_pool_t *pool;
113 pj_mutex_t *mutex;
114} ipp_factory;
115
116/* IPP codecs private data. */
117typedef struct ipp_private {
118 int codec_idx; /**< Codec index. */
Nanang Izzuddin35e01de2008-10-29 10:17:02 +0000119 void *codec_setting; /**< Specific codec setting. */
Nanang Izzuddin493a8db2008-08-15 13:17:39 +0000120 pj_pool_t *pool; /**< Pool for each instance. */
121
122 USC_Handle enc; /**< Encoder state. */
123 USC_Handle dec; /**< Decoder state. */
124 USC_CodecInfo *info; /**< Native codec info. */
125 pj_uint16_t frame_size; /**< Bitstream frame size. */
126
Nanang Izzuddin35e01de2008-10-29 10:17:02 +0000127 pj_bool_t plc_enabled; /**< PLC enabled flag. */
128 pjmedia_plc *plc; /**< PJMEDIA PLC engine, NULL if
129 codec has internal PLC. */
Nanang Izzuddin493a8db2008-08-15 13:17:39 +0000130
Nanang Izzuddin35e01de2008-10-29 10:17:02 +0000131 pj_bool_t vad_enabled; /**< VAD enabled flag. */
132 pjmedia_silence_det *vad; /**< PJMEDIA VAD engine, NULL if
133 codec has internal VAD. */
134 pj_timestamp last_tx; /**< Timestamp of last transmit.*/
Nanang Izzuddin493a8db2008-08-15 13:17:39 +0000135} ipp_private_t;
136
137
138/* USC codec implementations. */
139extern USC_Fxns USC_G729AFP_Fxns;
Nanang Izzuddin762a5bd2008-09-16 14:11:09 +0000140extern USC_Fxns USC_G729I_Fxns;
Nanang Izzuddin493a8db2008-08-15 13:17:39 +0000141extern USC_Fxns USC_G723_Fxns;
142extern USC_Fxns USC_G726_Fxns;
143extern USC_Fxns USC_G728_Fxns;
144extern USC_Fxns USC_G722_Fxns;
145extern USC_Fxns USC_GSMAMR_Fxns;
146extern USC_Fxns USC_AMRWB_Fxns;
147extern USC_Fxns USC_AMRWBE_Fxns;
148
Nanang Izzuddin762a5bd2008-09-16 14:11:09 +0000149
Nanang Izzuddin493a8db2008-08-15 13:17:39 +0000150/* CUSTOM CALLBACKS */
151
Nanang Izzuddindf361e02008-08-16 06:46:08 +0000152/* This callback is useful for translating RTP frame into USC frame, e.g:
153 * reassigning frame attributes, reorder bitstream. Default behaviour of
154 * the translation is just setting the USC frame buffer & its size as
155 * specified in RTP frame, setting USC frame frametype to 0, setting bitrate
156 * of USC frame to bitrate info of codec_data. Implement this callback when
157 * the default behaviour is unapplicable.
Nanang Izzuddin493a8db2008-08-15 13:17:39 +0000158 */
Nanang Izzuddindf361e02008-08-16 06:46:08 +0000159typedef void (*predecode_cb)(ipp_private_t *codec_data,
160 const pjmedia_frame *rtp_frame,
161 USC_Bitstream *usc_frame);
Nanang Izzuddin493a8db2008-08-15 13:17:39 +0000162
Nanang Izzuddindf361e02008-08-16 06:46:08 +0000163/* Parse frames from a packet. Default behaviour of frame parsing is
164 * just separating frames based on calculating frame length derived
165 * from bitrate. Implement this callback when the default behaviour is
166 * unapplicable.
Nanang Izzuddin493a8db2008-08-15 13:17:39 +0000167 */
168typedef pj_status_t (*parse_cb)(ipp_private_t *codec_data, void *pkt,
169 pj_size_t pkt_size, const pj_timestamp *ts,
170 unsigned *frame_cnt, pjmedia_frame frames[]);
171
Nanang Izzuddindf361e02008-08-16 06:46:08 +0000172/* Pack frames into a packet. Default behaviour of packing frames is
173 * just stacking the frames with octet aligned without adding any
174 * payload header. Implement this callback when the default behaviour is
175 * unapplicable.
Nanang Izzuddin493a8db2008-08-15 13:17:39 +0000176 */
177typedef pj_status_t (*pack_cb)(ipp_private_t *codec_data, void *pkt,
178 pj_size_t *pkt_size, pj_size_t max_pkt_size);
179
180
181
Nanang Izzuddindf361e02008-08-16 06:46:08 +0000182/* Custom callback implementations. */
183static void predecode_g723( ipp_private_t *codec_data,
184 const pjmedia_frame *rtp_frame,
185 USC_Bitstream *usc_frame);
186static pj_status_t parse_g723( ipp_private_t *codec_data, void *pkt,
187 pj_size_t pkt_size, const pj_timestamp *ts,
188 unsigned *frame_cnt, pjmedia_frame frames[]);
Nanang Izzuddin493a8db2008-08-15 13:17:39 +0000189
Nanang Izzuddindf361e02008-08-16 06:46:08 +0000190static void predecode_g729( ipp_private_t *codec_data,
191 const pjmedia_frame *rtp_frame,
192 USC_Bitstream *usc_frame);
193
194static void predecode_amr( ipp_private_t *codec_data,
195 const pjmedia_frame *rtp_frame,
196 USC_Bitstream *usc_frame);
197static pj_status_t parse_amr( ipp_private_t *codec_data, void *pkt,
Nanang Izzuddin493a8db2008-08-15 13:17:39 +0000198 pj_size_t pkt_size, const pj_timestamp *ts,
199 unsigned *frame_cnt, pjmedia_frame frames[]);
Nanang Izzuddindf361e02008-08-16 06:46:08 +0000200static pj_status_t pack_amr( ipp_private_t *codec_data, void *pkt,
201 pj_size_t *pkt_size, pj_size_t max_pkt_size);
Nanang Izzuddin493a8db2008-08-15 13:17:39 +0000202
203
204/* IPP codec implementation descriptions. */
205static struct ipp_codec {
206 int enabled; /* Is this codec enabled? */
207 const char *name; /* Codec name. */
208 pj_uint8_t pt; /* Payload type. */
209 USC_Fxns *fxns; /* USC callback functions. */
210 unsigned clock_rate; /* Codec's clock rate. */
211 unsigned channel_count; /* Codec's channel count. */
212 unsigned samples_per_frame; /* Codec's samples count. */
213
214 unsigned def_bitrate; /* Default bitrate of this codec. */
215 unsigned max_bitrate; /* Maximum bitrate of this codec. */
216 pj_uint8_t frm_per_pkt; /* Default num of frames per packet.*/
217 int has_native_vad; /* Codec has internal VAD? */
218 int has_native_plc; /* Codec has internal PLC? */
219
Nanang Izzuddindf361e02008-08-16 06:46:08 +0000220 predecode_cb predecode; /* Callback to translate RTP frame
Nanang Izzuddin23a00b72008-08-25 13:58:25 +0000221 into USC frame. */
222 parse_cb parse; /* Callback to parse bitstream. */
223 pack_cb pack; /* Callback to pack bitstream. */
224
225 pjmedia_codec_fmtp dec_fmtp; /* Decoder's fmtp params. */
226}
Nanang Izzuddin493a8db2008-08-15 13:17:39 +0000227
228ipp_codec[] =
229{
Benny Prijonoa4e7cdd2008-08-19 15:01:48 +0000230# if PJMEDIA_HAS_INTEL_IPP_CODEC_AMR
Nanang Izzuddin493a8db2008-08-15 13:17:39 +0000231 {1, "AMR", PJMEDIA_RTP_PT_AMR, &USC_GSMAMR_Fxns, 8000, 1, 160,
232 5900, 12200, 4, 1, 1,
Nanang Izzuddindf361e02008-08-16 06:46:08 +0000233 &predecode_amr, &parse_amr, &pack_amr
Nanang Izzuddin0b8f4ca2008-11-11 11:25:13 +0000234 /*, {1, {{{"octet-align", 11}, {"1", 1}}} } */
Nanang Izzuddindf361e02008-08-16 06:46:08 +0000235 },
236# endif
237
Benny Prijonoa4e7cdd2008-08-19 15:01:48 +0000238# if PJMEDIA_HAS_INTEL_IPP_CODEC_AMRWB
239 {1, "AMR-WB", PJMEDIA_RTP_PT_AMRWB, &USC_AMRWB_Fxns, 16000, 1, 320,
240 15850, 23850, 1, 1, 1,
Nanang Izzuddindf361e02008-08-16 06:46:08 +0000241 &predecode_amr, &parse_amr, &pack_amr
Nanang Izzuddin493a8db2008-08-15 13:17:39 +0000242 },
243# endif
244
Benny Prijonoa4e7cdd2008-08-19 15:01:48 +0000245# if PJMEDIA_HAS_INTEL_IPP_CODEC_G729
Nanang Izzuddin762a5bd2008-09-16 14:11:09 +0000246# if defined(PJ_HAS_FLOATING_POINT) && (PJ_HAS_FLOATING_POINT != 0)
247 {1, "G729", PJMEDIA_RTP_PT_G729, &USC_G729AFP_Fxns, 8000, 1, 80,
Nanang Izzuddin23a00b72008-08-25 13:58:25 +0000248 8000, 11800, 2, 1, 1,
Nanang Izzuddindf361e02008-08-16 06:46:08 +0000249 &predecode_g729, NULL, NULL
Nanang Izzuddin493a8db2008-08-15 13:17:39 +0000250 },
Nanang Izzuddin762a5bd2008-09-16 14:11:09 +0000251# else
252 {1, "G729", PJMEDIA_RTP_PT_G729, &USC_G729I_Fxns, 8000, 1, 80,
253 8000, 11800, 2, 1, 1,
254 &predecode_g729, NULL, NULL
255 },
256# endif
Nanang Izzuddin493a8db2008-08-15 13:17:39 +0000257# endif
258
Benny Prijonoa4e7cdd2008-08-19 15:01:48 +0000259# if PJMEDIA_HAS_INTEL_IPP_CODEC_G723_1
Nanang Izzuddin493a8db2008-08-15 13:17:39 +0000260 /* This is actually G.723.1 */
261 {1, "G723", PJMEDIA_RTP_PT_G723, &USC_G723_Fxns, 8000, 1, 240,
Benny Prijonoa4e7cdd2008-08-19 15:01:48 +0000262 6300, 6300, 1, 1, 1,
Nanang Izzuddindf361e02008-08-16 06:46:08 +0000263 &predecode_g723, &parse_g723, NULL
Nanang Izzuddin493a8db2008-08-15 13:17:39 +0000264 },
265# endif
266
Benny Prijonoa4e7cdd2008-08-19 15:01:48 +0000267# if PJMEDIA_HAS_INTEL_IPP_CODEC_G726
Nanang Izzuddinf216f822008-08-15 18:35:50 +0000268 {0, "G726-16", PJMEDIA_RTP_PT_G726_16, &USC_G726_Fxns, 8000, 1, 80,
Nanang Izzuddin493a8db2008-08-15 13:17:39 +0000269 16000, 16000, 2, 0, 0,
270 NULL, NULL, NULL
271 },
Nanang Izzuddinf216f822008-08-15 18:35:50 +0000272 {0, "G726-24", PJMEDIA_RTP_PT_G726_24, &USC_G726_Fxns, 8000, 1, 80,
Nanang Izzuddin493a8db2008-08-15 13:17:39 +0000273 24000, 24000, 2, 0, 0,
274 NULL, NULL, NULL
275 },
276 {1, "G726-32", PJMEDIA_RTP_PT_G726_32, &USC_G726_Fxns, 8000, 1, 80,
277 32000, 32000, 2, 0, 0,
278 NULL, NULL, NULL
279 },
Nanang Izzuddinf216f822008-08-15 18:35:50 +0000280 {0, "G726-40", PJMEDIA_RTP_PT_G726_40, &USC_G726_Fxns, 8000, 1, 80,
Nanang Izzuddin493a8db2008-08-15 13:17:39 +0000281 40000, 40000, 2, 0, 0,
282 NULL, NULL, NULL
283 },
284# endif
285
Benny Prijonoa4e7cdd2008-08-19 15:01:48 +0000286# if PJMEDIA_HAS_INTEL_IPP_CODEC_G728
Nanang Izzuddin493a8db2008-08-15 13:17:39 +0000287 {1, "G728", PJMEDIA_RTP_PT_G728, &USC_G728_Fxns, 8000, 1, 80,
288 16000, 16000, 2, 0, 1,
289 NULL, NULL, NULL
290 },
291# endif
292
Benny Prijonoa4e7cdd2008-08-19 15:01:48 +0000293# if PJMEDIA_HAS_INTEL_IPP_CODEC_G722_1
Nanang Izzuddin23a00b72008-08-25 13:58:25 +0000294 {0, "G7221", PJMEDIA_RTP_PT_G722_1_16, &USC_G722_Fxns, 16000, 1, 320,
295 16000, 16000, 1, 0, 1,
296 NULL, NULL, NULL,
297 {1, {{{"bitrate", 7}, {"16000", 5}}} }
298 },
299 {1, "G7221", PJMEDIA_RTP_PT_G722_1_24, &USC_G722_Fxns, 16000, 1, 320,
300 24000, 24000, 1, 0, 1,
301 NULL, NULL, NULL,
302 {1, {{{"bitrate", 7}, {"24000", 5}}} }
303 },
304 {1, "G7221", PJMEDIA_RTP_PT_G722_1_32, &USC_G722_Fxns, 16000, 1, 320,
305 32000, 32000, 1, 0, 1,
306 NULL, NULL, NULL,
307 {1, {{{"bitrate", 7}, {"32000", 5}}} }
Nanang Izzuddin493a8db2008-08-15 13:17:39 +0000308 },
309# endif
310};
311
312
Nanang Izzuddind55553a2008-10-28 02:24:46 +0000313#if PJMEDIA_HAS_INTEL_IPP_CODEC_G729
314
315static void predecode_g729( ipp_private_t *codec_data,
316 const pjmedia_frame *rtp_frame,
317 USC_Bitstream *usc_frame)
318{
319 switch (rtp_frame->size) {
320 case 2:
321 /* SID */
322 usc_frame->frametype = 1;
323 usc_frame->bitrate = codec_data->info->params.modes.bitrate;
324 break;
325 case 8:
326 /* G729D */
327 usc_frame->frametype = 2;
328 usc_frame->bitrate = 6400;
329 break;
330 case 10:
331 /* G729 */
332 usc_frame->frametype = 3;
333 usc_frame->bitrate = 8000;
334 break;
335 case 15:
336 /* G729E */
337 usc_frame->frametype = 4;
338 usc_frame->bitrate = 11800;
339 break;
340 default:
341 usc_frame->frametype = 0;
342 usc_frame->bitrate = 0;
343 break;
344 }
345
346 usc_frame->pBuffer = rtp_frame->buf;
347 usc_frame->nbytes = rtp_frame->size;
348}
349
350#endif /* PJMEDIA_HAS_INTEL_IPP_CODEC_G729 */
351
352
353#if PJMEDIA_HAS_INTEL_IPP_CODEC_G723_1
354
355static void predecode_g723( ipp_private_t *codec_data,
356 const pjmedia_frame *rtp_frame,
357 USC_Bitstream *usc_frame)
358{
359 int i, HDR = 0;
360 pj_uint8_t *f = (pj_uint8_t*)rtp_frame->buf;
361
362 PJ_UNUSED_ARG(codec_data);
363
364 for (i = 0; i < 2; ++i){
365 int tmp;
366 tmp = (f[0] >> (i & 0x7)) & 1;
367 HDR += tmp << i ;
368 }
369
370 usc_frame->pBuffer = rtp_frame->buf;
371 usc_frame->nbytes = rtp_frame->size;
372 usc_frame->bitrate = HDR == 0? 6300 : 5300;
373 usc_frame->frametype = 0;
374}
375
376static pj_status_t parse_g723(ipp_private_t *codec_data, void *pkt,
377 pj_size_t pkt_size, const pj_timestamp *ts,
378 unsigned *frame_cnt, pjmedia_frame frames[])
379{
380 unsigned count = 0;
381 pj_uint8_t *f = (pj_uint8_t*)pkt;
382
383 while (pkt_size && count < *frame_cnt) {
384 int framesize, i, j;
385 int HDR = 0;
386
387 for (i = 0; i < 2; ++i){
388 j = (f[0] >> (i & 0x7)) & 1;
389 HDR += j << i ;
390 }
391
392 if (HDR == 0)
393 framesize = 24;
394 else if (HDR == 1)
395 framesize = 20;
396 else if (HDR == 2)
397 framesize = 4;
398 else if (HDR == 3)
399 framesize = 1;
400 else {
401 pj_assert(!"Unknown G723.1 frametype, packet may be corrupted!");
402 return PJMEDIA_CODEC_EINMODE;
403 }
404
405 frames[count].type = PJMEDIA_FRAME_TYPE_AUDIO;
406 frames[count].buf = f;
407 frames[count].size = framesize;
408 frames[count].timestamp.u64 = ts->u64 + count *
409 ipp_codec[codec_data->codec_idx].samples_per_frame;
410
411 f += framesize;
412 pkt_size -= framesize;
413
414 ++count;
415 }
416
417 *frame_cnt = count;
418 return PJ_SUCCESS;
419}
420
421#endif /* PJMEDIA_HAS_INTEL_IPP_CODEC_G723_1 */
422
423
424#if PJMEDIA_HAS_INTEL_IPP_CODEC_AMR
425
426#include <pjmedia-codec/amr_helper.h>
427
Nanang Izzuddin35e01de2008-10-29 10:17:02 +0000428typedef struct amr_settings_t {
Nanang Izzuddin0b8f4ca2008-11-11 11:25:13 +0000429 pjmedia_codec_amr_pack_setting enc_setting;
430 pjmedia_codec_amr_pack_setting dec_setting;
Nanang Izzuddin35e01de2008-10-29 10:17:02 +0000431 pj_int8_t enc_mode;
432} amr_settings_t;
433
434
Nanang Izzuddind55553a2008-10-28 02:24:46 +0000435/* Rearrange AMR bitstream and convert RTP frame into USC frame:
436 * - make the start_bit to be 0
437 * - if it is speech frame, reorder bitstream from sensitivity bits order
438 * to encoder bits order.
439 * - set the appropriate value of usc_frame.
440 */
441static void predecode_amr( ipp_private_t *codec_data,
442 const pjmedia_frame *rtp_frame,
443 USC_Bitstream *usc_frame)
444{
445 pjmedia_frame frame;
446 pjmedia_codec_amr_bit_info *info;
Nanang Izzuddin0b8f4ca2008-11-11 11:25:13 +0000447 pjmedia_codec_amr_pack_setting *setting;
Nanang Izzuddind55553a2008-10-28 02:24:46 +0000448
Nanang Izzuddin35e01de2008-10-29 10:17:02 +0000449 setting = &((amr_settings_t*)codec_data->codec_setting)->dec_setting;
450
Nanang Izzuddind55553a2008-10-28 02:24:46 +0000451 frame = *rtp_frame;
Nanang Izzuddin35e01de2008-10-29 10:17:02 +0000452 pjmedia_codec_amr_predecode(rtp_frame, setting, &frame);
Nanang Izzuddind55553a2008-10-28 02:24:46 +0000453 info = (pjmedia_codec_amr_bit_info*) &frame.bit_info;
454
455 usc_frame->pBuffer = frame.buf;
456 usc_frame->nbytes = frame.size;
457 if (info->mode != -1) {
Nanang Izzuddin35e01de2008-10-29 10:17:02 +0000458 usc_frame->bitrate = setting->amr_nb?
Nanang Izzuddind55553a2008-10-28 02:24:46 +0000459 pjmedia_codec_amrnb_bitrates[info->mode]:
460 pjmedia_codec_amrwb_bitrates[info->mode];
461 } else {
462 usc_frame->bitrate = 0;
463 }
464
465 if (frame.size > 5) {
466 /* Speech */
467 if (info->good_quality)
468 usc_frame->frametype = 0;
469 else
Nanang Izzuddin35e01de2008-10-29 10:17:02 +0000470 usc_frame->frametype = setting->amr_nb ? 5 : 6;
Nanang Izzuddind55553a2008-10-28 02:24:46 +0000471 } else if (frame.size == 5) {
472 /* SID */
473 if (info->good_quality) {
474 pj_bool_t STI;
475 STI = (((pj_uint8_t*)frame.buf)[35 >> 3] & 0x10) != 0;
476 usc_frame->frametype = STI? 2 : 1;
477 } else {
Nanang Izzuddin35e01de2008-10-29 10:17:02 +0000478 usc_frame->frametype = setting->amr_nb ? 6 : 7;
Nanang Izzuddind55553a2008-10-28 02:24:46 +0000479 }
480 } else {
481 /* no data */
482 usc_frame->frametype = 3;
483 }
484}
485
486/* Pack AMR payload */
487static pj_status_t pack_amr(ipp_private_t *codec_data, void *pkt,
488 pj_size_t *pkt_size, pj_size_t max_pkt_size)
489{
490 enum {MAX_FRAMES_PER_PACKET = 16};
491
Nanang Izzuddind55553a2008-10-28 02:24:46 +0000492 pjmedia_frame frames[MAX_FRAMES_PER_PACKET];
493 unsigned nframes = 0;
494 pjmedia_codec_amr_bit_info *info;
495 pj_uint8_t *r; /* Read cursor */
496 pj_uint8_t SID_FT;
Nanang Izzuddin0b8f4ca2008-11-11 11:25:13 +0000497 pjmedia_codec_amr_pack_setting *setting;
Nanang Izzuddind55553a2008-10-28 02:24:46 +0000498
Nanang Izzuddin35e01de2008-10-29 10:17:02 +0000499 setting = &((amr_settings_t*)codec_data->codec_setting)->enc_setting;
Nanang Izzuddind55553a2008-10-28 02:24:46 +0000500
Nanang Izzuddin35e01de2008-10-29 10:17:02 +0000501 SID_FT = (pj_uint8_t)(setting->amr_nb? 8 : 9);
Nanang Izzuddind55553a2008-10-28 02:24:46 +0000502
503 /* Align pkt buf right */
504 r = (pj_uint8_t*)pkt + max_pkt_size - *pkt_size;
505 pj_memmove(r, pkt, *pkt_size);
506
507 /* Get frames */
508 for (;;) {
509 pj_bool_t eof;
510 pj_uint16_t info_;
511
512 info_ = *((pj_uint16_t*)r);
513 eof = ((info_ & 0x40) != 0);
514
515 info = (pjmedia_codec_amr_bit_info*) &frames[nframes].bit_info;
516 pj_bzero(info, sizeof(*info));
517 info->frame_type = (pj_uint8_t)(info_ & 0x0F);
518 info->good_quality = (pj_uint8_t)((info_ & 0x80) == 0);
519 info->mode = (pj_int8_t) ((info_ >> 8) & 0x0F);
520
521 frames[nframes].buf = r + 2;
522 frames[nframes].size = info->frame_type <= SID_FT ?
523 pjmedia_codec_amrnb_framelen[info->frame_type] :
524 0;
525
526 r += frames[nframes].size + 2;
527
528 /* Last frame */
529 if (++nframes >= MAX_FRAMES_PER_PACKET || eof)
530 break;
531 }
532
533 /* Pack */
534 *pkt_size = max_pkt_size;
Nanang Izzuddin35e01de2008-10-29 10:17:02 +0000535 return pjmedia_codec_amr_pack(frames, nframes, setting, pkt, pkt_size);
Nanang Izzuddind55553a2008-10-28 02:24:46 +0000536}
537
538
539/* Parse AMR payload into frames. */
540static pj_status_t parse_amr(ipp_private_t *codec_data, void *pkt,
541 pj_size_t pkt_size, const pj_timestamp *ts,
542 unsigned *frame_cnt, pjmedia_frame frames[])
543{
Nanang Izzuddin35e01de2008-10-29 10:17:02 +0000544 amr_settings_t* s = (amr_settings_t*)codec_data->codec_setting;
Nanang Izzuddin0b8f4ca2008-11-11 11:25:13 +0000545 pjmedia_codec_amr_pack_setting *setting;
Nanang Izzuddin35e01de2008-10-29 10:17:02 +0000546 pj_status_t status;
Nanang Izzuddin0b8f4ca2008-11-11 11:25:13 +0000547 pj_uint8_t cmr;
Nanang Izzuddind55553a2008-10-28 02:24:46 +0000548
Nanang Izzuddin35e01de2008-10-29 10:17:02 +0000549 setting = &s->dec_setting;
Nanang Izzuddind55553a2008-10-28 02:24:46 +0000550
Nanang Izzuddin35e01de2008-10-29 10:17:02 +0000551 status = pjmedia_codec_amr_parse(pkt, pkt_size, ts, setting, frames,
Nanang Izzuddin0b8f4ca2008-11-11 11:25:13 +0000552 frame_cnt, &cmr);
Nanang Izzuddin35e01de2008-10-29 10:17:02 +0000553 if (status != PJ_SUCCESS)
554 return status;
555
556 /* Check Change Mode Request. */
Nanang Izzuddin0b8f4ca2008-11-11 11:25:13 +0000557 if ((setting->amr_nb && cmr <= 7) || (!setting->amr_nb && cmr <= 8)) {
558 s->enc_mode = cmr;
Nanang Izzuddin35e01de2008-10-29 10:17:02 +0000559 }
560
561 return PJ_SUCCESS;
Nanang Izzuddind55553a2008-10-28 02:24:46 +0000562}
563
564#endif /* PJMEDIA_HAS_INTEL_IPP_CODEC_AMR */
565
Nanang Izzuddin493a8db2008-08-15 13:17:39 +0000566
567/*
568 * Initialize and register IPP codec factory to pjmedia endpoint.
569 */
570PJ_DEF(pj_status_t) pjmedia_codec_ipp_init( pjmedia_endpt *endpt )
571{
572 pjmedia_codec_mgr *codec_mgr;
573 pj_status_t status;
574
575 if (ipp_factory.pool != NULL) {
576 /* Already initialized. */
577 return PJ_SUCCESS;
578 }
579
580 /* Create IPP codec factory. */
581 ipp_factory.base.op = &ipp_factory_op;
582 ipp_factory.base.factory_data = NULL;
583 ipp_factory.endpt = endpt;
584
585 ipp_factory.pool = pjmedia_endpt_create_pool(endpt, "IPP codecs", 4000, 4000);
586 if (!ipp_factory.pool)
587 return PJ_ENOMEM;
588
589 /* Create mutex. */
590 status = pj_mutex_create_simple(ipp_factory.pool, "IPP codecs",
591 &ipp_factory.mutex);
592 if (status != PJ_SUCCESS)
593 goto on_error;
594
595 /* Get the codec manager. */
596 codec_mgr = pjmedia_endpt_get_codec_mgr(endpt);
597 if (!codec_mgr) {
598 status = PJ_EINVALIDOP;
599 goto on_error;
600 }
601
602 /* Register codec factory to endpoint. */
603 status = pjmedia_codec_mgr_register_factory(codec_mgr,
604 &ipp_factory.base);
605 if (status != PJ_SUCCESS)
606 goto on_error;
607
608 /* Done. */
609 return PJ_SUCCESS;
610
611on_error:
612 pj_pool_release(ipp_factory.pool);
613 ipp_factory.pool = NULL;
614 return status;
615}
616
617/*
618 * Unregister IPP codecs factory from pjmedia endpoint.
619 */
620PJ_DEF(pj_status_t) pjmedia_codec_ipp_deinit(void)
621{
622 pjmedia_codec_mgr *codec_mgr;
623 pj_status_t status;
624
625 if (ipp_factory.pool == NULL) {
626 /* Already deinitialized */
627 return PJ_SUCCESS;
628 }
629
630 pj_mutex_lock(ipp_factory.mutex);
631
632 /* Get the codec manager. */
633 codec_mgr = pjmedia_endpt_get_codec_mgr(ipp_factory.endpt);
634 if (!codec_mgr) {
635 pj_pool_release(ipp_factory.pool);
636 ipp_factory.pool = NULL;
637 return PJ_EINVALIDOP;
638 }
639
640 /* Unregister IPP codecs factory. */
641 status = pjmedia_codec_mgr_unregister_factory(codec_mgr,
642 &ipp_factory.base);
643
644 /* Destroy mutex. */
645 pj_mutex_destroy(ipp_factory.mutex);
646
647 /* Destroy pool. */
648 pj_pool_release(ipp_factory.pool);
649 ipp_factory.pool = NULL;
650
651 return status;
652}
653
654/*
655 * Check if factory can allocate the specified codec.
656 */
657static pj_status_t ipp_test_alloc( pjmedia_codec_factory *factory,
658 const pjmedia_codec_info *info )
659{
660 unsigned i;
661
662 PJ_UNUSED_ARG(factory);
663
664 /* Type MUST be audio. */
665 if (info->type != PJMEDIA_TYPE_AUDIO)
666 return PJMEDIA_CODEC_EUNSUP;
667
668 for (i = 0; i < PJ_ARRAY_SIZE(ipp_codec); ++i) {
669 pj_str_t name = pj_str((char*)ipp_codec[i].name);
670 if ((pj_stricmp(&info->encoding_name, &name) == 0) &&
671 (info->clock_rate == (unsigned)ipp_codec[i].clock_rate) &&
672 (info->channel_cnt == (unsigned)ipp_codec[i].channel_count) &&
673 (ipp_codec[i].enabled))
674 {
675 return PJ_SUCCESS;
676 }
677 }
678
679 /* Unsupported, or mode is disabled. */
680 return PJMEDIA_CODEC_EUNSUP;
681}
682
683/*
684 * Generate default attribute.
685 */
686static pj_status_t ipp_default_attr (pjmedia_codec_factory *factory,
687 const pjmedia_codec_info *id,
688 pjmedia_codec_param *attr )
689{
690 unsigned i;
691
692 PJ_ASSERT_RETURN(factory==&ipp_factory.base, PJ_EINVAL);
693
694 pj_bzero(attr, sizeof(pjmedia_codec_param));
695
696 for (i = 0; i < PJ_ARRAY_SIZE(ipp_codec); ++i) {
697 pj_str_t name = pj_str((char*)ipp_codec[i].name);
698 if ((pj_stricmp(&id->encoding_name, &name) == 0) &&
699 (id->clock_rate == (unsigned)ipp_codec[i].clock_rate) &&
Nanang Izzuddin23a00b72008-08-25 13:58:25 +0000700 (id->channel_cnt == (unsigned)ipp_codec[i].channel_count) &&
701 (id->pt == (unsigned)ipp_codec[i].pt))
Nanang Izzuddin493a8db2008-08-15 13:17:39 +0000702 {
703 attr->info.pt = (pj_uint8_t)id->pt;
704 attr->info.channel_cnt = ipp_codec[i].channel_count;
705 attr->info.clock_rate = ipp_codec[i].clock_rate;
706 attr->info.avg_bps = ipp_codec[i].def_bitrate;
707 attr->info.max_bps = ipp_codec[i].max_bitrate;
708 attr->info.pcm_bits_per_sample = 16;
709 attr->info.frm_ptime = (pj_uint16_t)
710 (ipp_codec[i].samples_per_frame * 1000 /
711 ipp_codec[i].channel_count /
712 ipp_codec[i].clock_rate);
713 attr->setting.frm_per_pkt = ipp_codec[i].frm_per_pkt;
714
715 /* Default flags. */
Nanang Izzuddin493a8db2008-08-15 13:17:39 +0000716 attr->setting.plc = 1;
717 attr->setting.penh= 0;
Nanang Izzuddin23a00b72008-08-25 13:58:25 +0000718 attr->setting.vad = 1;
719 attr->setting.cng = attr->setting.vad;
720 attr->setting.dec_fmtp = ipp_codec[i].dec_fmtp;
721
722 if (attr->setting.vad == 0) {
723#if PJMEDIA_HAS_INTEL_IPP_CODEC_G729
724 if (id->pt == PJMEDIA_RTP_PT_G729) {
725 /* Signal G729 Annex B is being disabled */
726 attr->setting.dec_fmtp.cnt = 1;
727 pj_strset2(&attr->setting.dec_fmtp.param[0].name, "annexb");
728 pj_strset2(&attr->setting.dec_fmtp.param[0].val, "no");
729 }
730#endif
731 }
Nanang Izzuddin493a8db2008-08-15 13:17:39 +0000732
733 return PJ_SUCCESS;
734 }
735 }
736
737 return PJMEDIA_CODEC_EUNSUP;
738}
739
740/*
741 * Enum codecs supported by this factory.
742 */
743static pj_status_t ipp_enum_codecs(pjmedia_codec_factory *factory,
744 unsigned *count,
745 pjmedia_codec_info codecs[])
746{
747 unsigned max;
748 unsigned i;
749
750 PJ_UNUSED_ARG(factory);
751 PJ_ASSERT_RETURN(codecs && *count > 0, PJ_EINVAL);
752
753 max = *count;
754
755 for (i = 0, *count = 0; i < PJ_ARRAY_SIZE(ipp_codec) && *count < max; ++i)
756 {
757 if (!ipp_codec[i].enabled)
758 continue;
759
760 pj_bzero(&codecs[*count], sizeof(pjmedia_codec_info));
761 codecs[*count].encoding_name = pj_str((char*)ipp_codec[i].name);
762 codecs[*count].pt = ipp_codec[i].pt;
763 codecs[*count].type = PJMEDIA_TYPE_AUDIO;
764 codecs[*count].clock_rate = ipp_codec[i].clock_rate;
765 codecs[*count].channel_cnt = ipp_codec[i].channel_count;
766
767 ++*count;
768 }
769
770 return PJ_SUCCESS;
771}
772
773/*
774 * Allocate a new codec instance.
775 */
776static pj_status_t ipp_alloc_codec( pjmedia_codec_factory *factory,
777 const pjmedia_codec_info *id,
778 pjmedia_codec **p_codec)
779{
780 ipp_private_t *codec_data;
781 pjmedia_codec *codec;
782 int idx;
783 pj_pool_t *pool;
784 unsigned i;
785
786 PJ_ASSERT_RETURN(factory && id && p_codec, PJ_EINVAL);
787 PJ_ASSERT_RETURN(factory == &ipp_factory.base, PJ_EINVAL);
788
789 pj_mutex_lock(ipp_factory.mutex);
790
791 /* Find codec's index */
792 idx = -1;
793 for (i = 0; i < PJ_ARRAY_SIZE(ipp_codec); ++i) {
794 pj_str_t name = pj_str((char*)ipp_codec[i].name);
795 if ((pj_stricmp(&id->encoding_name, &name) == 0) &&
796 (id->clock_rate == (unsigned)ipp_codec[i].clock_rate) &&
797 (id->channel_cnt == (unsigned)ipp_codec[i].channel_count) &&
798 (ipp_codec[i].enabled))
799 {
800 idx = i;
801 break;
802 }
803 }
804 if (idx == -1) {
805 *p_codec = NULL;
806 return PJMEDIA_CODEC_EFAILED;
807 }
808
809 /* Create pool for codec instance */
Benny Prijonoa4e7cdd2008-08-19 15:01:48 +0000810 pool = pjmedia_endpt_create_pool(ipp_factory.endpt, "IPPcodec", 512, 512);
Nanang Izzuddin493a8db2008-08-15 13:17:39 +0000811 codec = PJ_POOL_ZALLOC_T(pool, pjmedia_codec);
812 PJ_ASSERT_RETURN(codec != NULL, PJ_ENOMEM);
813 codec->op = &ipp_op;
814 codec->factory = factory;
815 codec->codec_data = PJ_POOL_ZALLOC_T(pool, ipp_private_t);
816 codec_data = (ipp_private_t*) codec->codec_data;
817
818 /* Create PLC if codec has no internal PLC */
819 if (!ipp_codec[idx].has_native_plc) {
820 pj_status_t status;
821 status = pjmedia_plc_create(pool, ipp_codec[idx].clock_rate,
822 ipp_codec[idx].samples_per_frame, 0,
823 &codec_data->plc);
824 if (status != PJ_SUCCESS) {
825 pj_pool_release(pool);
826 pj_mutex_unlock(ipp_factory.mutex);
827 return status;
828 }
829 }
830
831 /* Create silence detector if codec has no internal VAD */
832 if (!ipp_codec[idx].has_native_vad) {
833 pj_status_t status;
834 status = pjmedia_silence_det_create(pool,
835 ipp_codec[idx].clock_rate,
836 ipp_codec[idx].samples_per_frame,
837 &codec_data->vad);
838 if (status != PJ_SUCCESS) {
839 pj_pool_release(pool);
840 pj_mutex_unlock(ipp_factory.mutex);
841 return status;
842 }
843 }
844
845 codec_data->pool = pool;
846 codec_data->codec_idx = idx;
847
848 pj_mutex_unlock(ipp_factory.mutex);
849
850 *p_codec = codec;
851 return PJ_SUCCESS;
852}
853
854/*
855 * Free codec.
856 */
857static pj_status_t ipp_dealloc_codec( pjmedia_codec_factory *factory,
858 pjmedia_codec *codec )
859{
860 ipp_private_t *codec_data;
861
862 PJ_ASSERT_RETURN(factory && codec, PJ_EINVAL);
863 PJ_ASSERT_RETURN(factory == &ipp_factory.base, PJ_EINVAL);
864
865 /* Close codec, if it's not closed. */
866 codec_data = (ipp_private_t*) codec->codec_data;
867 if (codec_data->enc != NULL || codec_data->dec != NULL) {
868 ipp_codec_close(codec);
869 }
870
871 pj_pool_release(codec_data->pool);
872
873 return PJ_SUCCESS;
874}
875
876/*
877 * Init codec.
878 */
879static pj_status_t ipp_codec_init( pjmedia_codec *codec,
880 pj_pool_t *pool )
881{
882 PJ_UNUSED_ARG(codec);
883 PJ_UNUSED_ARG(pool);
884 return PJ_SUCCESS;
885}
886
887/*
888 * Open codec.
889 */
890static pj_status_t ipp_codec_open( pjmedia_codec *codec,
891 pjmedia_codec_param *attr )
892{
893 ipp_private_t *codec_data = (ipp_private_t*) codec->codec_data;
Benny Prijonoa4e7cdd2008-08-19 15:01:48 +0000894 struct ipp_codec *ippc = &ipp_codec[codec_data->codec_idx];
Nanang Izzuddin493a8db2008-08-15 13:17:39 +0000895 int info_size;
896 pj_pool_t *pool;
Benny Prijonoa4e7cdd2008-08-19 15:01:48 +0000897 int i, j;
Nanang Izzuddin493a8db2008-08-15 13:17:39 +0000898 USC_MemBank *membanks;
899 int nb_membanks;
900
901 pool = codec_data->pool;
Nanang Izzuddin493a8db2008-08-15 13:17:39 +0000902
903 /* Get the codec info size */
Benny Prijonoa4e7cdd2008-08-19 15:01:48 +0000904 if (USC_NoError != ippc->fxns->std.GetInfoSize(&info_size)) {
905 PJ_LOG(1,(THIS_FILE, "Error getting codec info size"));
Nanang Izzuddin493a8db2008-08-15 13:17:39 +0000906 goto on_error;
907 }
908 /* Get the codec info */
909 codec_data->info = pj_pool_zalloc(pool, info_size);
Benny Prijonoa4e7cdd2008-08-19 15:01:48 +0000910 if (USC_NoError != ippc->fxns->std.GetInfo((USC_Handle)NULL,
911 codec_data->info))
Nanang Izzuddin493a8db2008-08-15 13:17:39 +0000912 {
Benny Prijonoa4e7cdd2008-08-19 15:01:48 +0000913 PJ_LOG(1,(THIS_FILE, "Error getting codec info"));
Nanang Izzuddin493a8db2008-08-15 13:17:39 +0000914 goto on_error;
915 }
916
917 /* PREPARING THE ENCODER */
918
919 /* Setting the encoder params */
920 codec_data->info->params.direction = USC_ENCODE;
Nanang Izzuddinf216f822008-08-15 18:35:50 +0000921 codec_data->info->params.modes.vad = attr->setting.vad &&
Nanang Izzuddin23a00b72008-08-25 13:58:25 +0000922 ippc->has_native_vad;
Nanang Izzuddin493a8db2008-08-15 13:17:39 +0000923 codec_data->info->params.modes.bitrate = attr->info.avg_bps;
924 codec_data->info->params.law = 0; /* Linear PCM input */
925
Nanang Izzuddin23a00b72008-08-25 13:58:25 +0000926#if PJMEDIA_HAS_INTEL_IPP_CODEC_G729
927 if (ippc->pt == PJMEDIA_RTP_PT_G729) {
928 /* Check if G729 Annex B is signaled to be disabled */
929 for (i = 0; i < attr->setting.enc_fmtp.cnt; ++i) {
930 if (pj_stricmp2(&attr->setting.enc_fmtp.param[i].name, "annexb")==0)
931 {
932 if (pj_stricmp2(&attr->setting.enc_fmtp.param[i].val, "no")==0)
933 codec_data->info->params.modes.vad = 0;
934 break;
935 }
936 }
937 }
938#endif
939
Nanang Izzuddin493a8db2008-08-15 13:17:39 +0000940 /* Get number of memory blocks needed by the encoder */
Benny Prijonoa4e7cdd2008-08-19 15:01:48 +0000941 if (USC_NoError != ippc->fxns->std.NumAlloc(&codec_data->info->params,
942 &nb_membanks))
Nanang Izzuddin493a8db2008-08-15 13:17:39 +0000943 {
Benny Prijonoa4e7cdd2008-08-19 15:01:48 +0000944 PJ_LOG(1,(THIS_FILE, "Error getting no of memory blocks of encoder"));
Nanang Izzuddin493a8db2008-08-15 13:17:39 +0000945 goto on_error;
946 }
947
948 /* Allocate memory blocks table */
949 membanks = (USC_MemBank*) pj_pool_zalloc(pool,
950 sizeof(USC_MemBank) * nb_membanks);
951 /* Get size of each memory block */
Benny Prijonoa4e7cdd2008-08-19 15:01:48 +0000952 if (USC_NoError != ippc->fxns->std.MemAlloc(&codec_data->info->params,
953 membanks))
Nanang Izzuddin493a8db2008-08-15 13:17:39 +0000954 {
Benny Prijonoa4e7cdd2008-08-19 15:01:48 +0000955 PJ_LOG(1,(THIS_FILE, "Error getting memory blocks size of encoder"));
Nanang Izzuddin493a8db2008-08-15 13:17:39 +0000956 goto on_error;
957 }
958
959 /* Allocate memory for each block */
960 for (i = 0; i < nb_membanks; i++) {
961 membanks[i].pMem = (char*) pj_pool_zalloc(pool, membanks[i].nbytes);
962 }
963
964 /* Create encoder instance */
Benny Prijonoa4e7cdd2008-08-19 15:01:48 +0000965 if (USC_NoError != ippc->fxns->std.Init(&codec_data->info->params,
966 membanks,
967 &codec_data->enc))
Nanang Izzuddin493a8db2008-08-15 13:17:39 +0000968 {
Benny Prijonoa4e7cdd2008-08-19 15:01:48 +0000969 PJ_LOG(1,(THIS_FILE, "Error initializing encoder"));
Nanang Izzuddin493a8db2008-08-15 13:17:39 +0000970 goto on_error;
971 }
972
973 /* PREPARING THE DECODER */
974
975 /* Setting the decoder params */
976 codec_data->info->params.direction = USC_DECODE;
977
Nanang Izzuddin23a00b72008-08-25 13:58:25 +0000978 /* Not sure if VAD affects decoder, just try to be safe */
979 codec_data->info->params.modes.vad = ippc->has_native_vad;
980
Nanang Izzuddin493a8db2008-08-15 13:17:39 +0000981 /* Get number of memory blocks needed by the decoder */
Benny Prijonoa4e7cdd2008-08-19 15:01:48 +0000982 if (USC_NoError != ippc->fxns->std.NumAlloc(&codec_data->info->params,
983 &nb_membanks))
Nanang Izzuddin493a8db2008-08-15 13:17:39 +0000984 {
Benny Prijonoa4e7cdd2008-08-19 15:01:48 +0000985 PJ_LOG(1,(THIS_FILE, "Error getting no of memory blocks of decoder"));
Nanang Izzuddin493a8db2008-08-15 13:17:39 +0000986 goto on_error;
987 }
988
989 /* Allocate memory blocks table */
990 membanks = (USC_MemBank*) pj_pool_zalloc(pool,
991 sizeof(USC_MemBank) * nb_membanks);
992 /* Get size of each memory block */
Benny Prijonoa4e7cdd2008-08-19 15:01:48 +0000993 if (USC_NoError != ippc->fxns->std.MemAlloc(&codec_data->info->params,
994 membanks))
Nanang Izzuddin493a8db2008-08-15 13:17:39 +0000995 {
Benny Prijonoa4e7cdd2008-08-19 15:01:48 +0000996 PJ_LOG(1,(THIS_FILE, "Error getting memory blocks size of decoder"));
Nanang Izzuddin493a8db2008-08-15 13:17:39 +0000997 goto on_error;
998 }
999
1000 /* Allocate memory for each block */
1001 for (i = 0; i < nb_membanks; i++) {
1002 membanks[i].pMem = (char*) pj_pool_zalloc(pool, membanks[i].nbytes);
1003 }
1004
1005 /* Create decoder instance */
Benny Prijonoa4e7cdd2008-08-19 15:01:48 +00001006 if (USC_NoError != ippc->fxns->std.Init(&codec_data->info->params,
1007 membanks, &codec_data->dec))
Nanang Izzuddin493a8db2008-08-15 13:17:39 +00001008 {
Benny Prijonoa4e7cdd2008-08-19 15:01:48 +00001009 PJ_LOG(1,(THIS_FILE, "Error initializing decoder"));
Nanang Izzuddin493a8db2008-08-15 13:17:39 +00001010 goto on_error;
1011 }
1012
1013 /* Update codec info */
Benny Prijonoa4e7cdd2008-08-19 15:01:48 +00001014 ippc->fxns->std.GetInfo((USC_Handle)codec_data->enc, codec_data->info);
Nanang Izzuddin493a8db2008-08-15 13:17:39 +00001015
1016 /* Get bitstream size */
Benny Prijonoa4e7cdd2008-08-19 15:01:48 +00001017 i = codec_data->info->params.modes.bitrate * ippc->samples_per_frame;
1018 j = ippc->clock_rate << 3;
Nanang Izzuddin493a8db2008-08-15 13:17:39 +00001019 codec_data->frame_size = (pj_uint16_t)(i / j);
1020 if (i % j) ++codec_data->frame_size;
1021
1022 codec_data->vad_enabled = (attr->setting.vad != 0);
1023 codec_data->plc_enabled = (attr->setting.plc != 0);
1024
Nanang Izzuddin35e01de2008-10-29 10:17:02 +00001025#if PJMEDIA_HAS_INTEL_IPP_CODEC_AMR
1026 /* Init AMR settings */
1027 if (ippc->pt == PJMEDIA_RTP_PT_AMR || ippc->pt == PJMEDIA_RTP_PT_AMRWB) {
1028 amr_settings_t *s;
Nanang Izzuddin0b8f4ca2008-11-11 11:25:13 +00001029 pj_uint8_t octet_align = 0;
1030 const pj_str_t STR_FMTP_OCTET_ALIGN = {"octet-align", 11};
1031
1032 /* Check octet-align */
1033 for (i = 0; i < attr->setting.dec_fmtp.cnt; ++i) {
1034 if (pj_stricmp(&attr->setting.dec_fmtp.param[i].name,
1035 &STR_FMTP_OCTET_ALIGN) == 0)
1036 {
1037 octet_align=(pj_uint8_t)
1038 (pj_strtoul(&attr->setting.dec_fmtp.param[i].val));
1039 break;
1040 }
1041 }
Nanang Izzuddin35e01de2008-10-29 10:17:02 +00001042
1043 s = PJ_POOL_ZALLOC_T(pool, amr_settings_t);
1044 codec_data->codec_setting = s;
1045
1046 s->enc_mode = pjmedia_codec_amr_get_mode(ippc->def_bitrate);
1047 if (s->enc_mode < 0)
1048 goto on_error;
1049
Benny Prijono6b6fce12009-03-17 10:13:30 +00001050 s->enc_setting.amr_nb = (pj_uint8_t)(ippc->pt == PJMEDIA_RTP_PT_AMR);
Nanang Izzuddin0b8f4ca2008-11-11 11:25:13 +00001051 s->enc_setting.octet_aligned = octet_align;
Nanang Izzuddin35e01de2008-10-29 10:17:02 +00001052 s->enc_setting.reorder = PJ_TRUE;
Nanang Izzuddin0b8f4ca2008-11-11 11:25:13 +00001053 s->enc_setting.cmr = 15;
Nanang Izzuddin35e01de2008-10-29 10:17:02 +00001054
Benny Prijono6b6fce12009-03-17 10:13:30 +00001055 s->dec_setting.amr_nb = (pj_uint8_t)(ippc->pt == PJMEDIA_RTP_PT_AMR);
Nanang Izzuddin0b8f4ca2008-11-11 11:25:13 +00001056 s->dec_setting.octet_aligned = octet_align;
Nanang Izzuddin35e01de2008-10-29 10:17:02 +00001057 s->dec_setting.reorder = PJ_TRUE;
1058 }
1059#endif
1060
Nanang Izzuddin493a8db2008-08-15 13:17:39 +00001061 return PJ_SUCCESS;
1062
1063on_error:
1064 return PJMEDIA_CODEC_EFAILED;
1065}
1066
1067/*
1068 * Close codec.
1069 */
1070static pj_status_t ipp_codec_close( pjmedia_codec *codec )
1071{
1072 PJ_UNUSED_ARG(codec);
1073
1074 return PJ_SUCCESS;
1075}
1076
1077
1078/*
1079 * Modify codec settings.
1080 */
1081static pj_status_t ipp_codec_modify(pjmedia_codec *codec,
1082 const pjmedia_codec_param *attr )
1083{
1084 ipp_private_t *codec_data = (ipp_private_t*) codec->codec_data;
Benny Prijonoa4e7cdd2008-08-19 15:01:48 +00001085 struct ipp_codec *ippc = &ipp_codec[codec_data->codec_idx];
Nanang Izzuddin493a8db2008-08-15 13:17:39 +00001086
1087 codec_data->vad_enabled = (attr->setting.vad != 0);
1088 codec_data->plc_enabled = (attr->setting.plc != 0);
1089
Benny Prijonoa4e7cdd2008-08-19 15:01:48 +00001090 if (ippc->has_native_vad) {
Nanang Izzuddin493a8db2008-08-15 13:17:39 +00001091 USC_Modes modes;
1092
1093 modes = codec_data->info->params.modes;
1094 modes.vad = codec_data->vad_enabled;
Benny Prijonoa4e7cdd2008-08-19 15:01:48 +00001095 ippc->fxns->std.Control(&modes, codec_data->enc);
Nanang Izzuddin493a8db2008-08-15 13:17:39 +00001096 }
1097
1098 return PJ_SUCCESS;
1099}
1100
1101/*
1102 * Get frames in the packet.
1103 */
1104static pj_status_t ipp_codec_parse( pjmedia_codec *codec,
1105 void *pkt,
1106 pj_size_t pkt_size,
1107 const pj_timestamp *ts,
1108 unsigned *frame_cnt,
1109 pjmedia_frame frames[])
1110{
1111 ipp_private_t *codec_data = (ipp_private_t*) codec->codec_data;
Benny Prijonoa4e7cdd2008-08-19 15:01:48 +00001112 struct ipp_codec *ippc = &ipp_codec[codec_data->codec_idx];
Nanang Izzuddin493a8db2008-08-15 13:17:39 +00001113 unsigned count = 0;
1114
1115 PJ_ASSERT_RETURN(frame_cnt, PJ_EINVAL);
1116
Benny Prijonoa4e7cdd2008-08-19 15:01:48 +00001117 if (ippc->parse != NULL) {
1118 return ippc->parse(codec_data, pkt, pkt_size, ts, frame_cnt, frames);
Nanang Izzuddin493a8db2008-08-15 13:17:39 +00001119 }
1120
1121 while (pkt_size >= codec_data->frame_size && count < *frame_cnt) {
1122 frames[count].type = PJMEDIA_FRAME_TYPE_AUDIO;
1123 frames[count].buf = pkt;
1124 frames[count].size = codec_data->frame_size;
Benny Prijonoa4e7cdd2008-08-19 15:01:48 +00001125 frames[count].timestamp.u64 = ts->u64 + count*ippc->samples_per_frame;
Nanang Izzuddin493a8db2008-08-15 13:17:39 +00001126
1127 pkt = ((char*)pkt) + codec_data->frame_size;
1128 pkt_size -= codec_data->frame_size;
1129
1130 ++count;
1131 }
1132
1133 if (pkt_size && count < *frame_cnt) {
1134 frames[count].type = PJMEDIA_FRAME_TYPE_AUDIO;
1135 frames[count].buf = pkt;
1136 frames[count].size = pkt_size;
Benny Prijonoa4e7cdd2008-08-19 15:01:48 +00001137 frames[count].timestamp.u64 = ts->u64 + count*ippc->samples_per_frame;
Nanang Izzuddin493a8db2008-08-15 13:17:39 +00001138 ++count;
1139 }
1140
1141 *frame_cnt = count;
1142 return PJ_SUCCESS;
1143}
1144
1145/*
1146 * Encode frames.
1147 */
1148static pj_status_t ipp_codec_encode( pjmedia_codec *codec,
1149 const struct pjmedia_frame *input,
1150 unsigned output_buf_len,
1151 struct pjmedia_frame *output)
1152{
1153 ipp_private_t *codec_data = (ipp_private_t*) codec->codec_data;
Benny Prijonoa4e7cdd2008-08-19 15:01:48 +00001154 struct ipp_codec *ippc = &ipp_codec[codec_data->codec_idx];
Nanang Izzuddin493a8db2008-08-15 13:17:39 +00001155 unsigned samples_per_frame;
1156 unsigned nsamples;
1157 pj_size_t tx = 0;
1158 pj_int16_t *pcm_in = (pj_int16_t*)input->buf;
Benny Prijonob1339242008-08-21 20:58:55 +00001159 pj_uint8_t *bits_out = (pj_uint8_t*) output->buf;
Nanang Izzuddindf361e02008-08-16 06:46:08 +00001160 pj_uint8_t pt;
Nanang Izzuddin493a8db2008-08-15 13:17:39 +00001161
1162 /* Invoke external VAD if codec has no internal VAD */
1163 if (codec_data->vad && codec_data->vad_enabled) {
1164 pj_bool_t is_silence;
1165 pj_int32_t silence_duration;
1166
1167 silence_duration = pj_timestamp_diff32(&codec_data->last_tx,
1168 &input->timestamp);
1169
1170 is_silence = pjmedia_silence_det_detect(codec_data->vad,
1171 (const pj_int16_t*) input->buf,
1172 (input->size >> 1),
1173 NULL);
1174 if (is_silence &&
1175 PJMEDIA_CODEC_MAX_SILENCE_PERIOD != -1 &&
Benny Prijonoa4e7cdd2008-08-19 15:01:48 +00001176 silence_duration < (PJMEDIA_CODEC_MAX_SILENCE_PERIOD *
1177 (int)ippc->clock_rate / 1000))
Nanang Izzuddin493a8db2008-08-15 13:17:39 +00001178 {
1179 output->type = PJMEDIA_FRAME_TYPE_NONE;
1180 output->buf = NULL;
1181 output->size = 0;
1182 output->timestamp = input->timestamp;
1183 return PJ_SUCCESS;
1184 } else {
1185 codec_data->last_tx = input->timestamp;
1186 }
1187 }
1188
1189 nsamples = input->size >> 1;
Benny Prijonoa4e7cdd2008-08-19 15:01:48 +00001190 samples_per_frame = ippc->samples_per_frame;
1191 pt = ippc->pt;
Nanang Izzuddin493a8db2008-08-15 13:17:39 +00001192
1193 PJ_ASSERT_RETURN(nsamples % samples_per_frame == 0,
1194 PJMEDIA_CODEC_EPCMFRMINLEN);
1195
1196 /* Encode the frames */
1197 while (nsamples >= samples_per_frame) {
1198 USC_PCMStream in;
1199 USC_Bitstream out;
1200
1201 in.bitrate = codec_data->info->params.modes.bitrate;
1202 in.nbytes = samples_per_frame << 1;
1203 in.pBuffer = (char*)pcm_in;
1204 in.pcmType.bitPerSample = codec_data->info->params.pcmType.bitPerSample;
1205 in.pcmType.nChannels = codec_data->info->params.pcmType.nChannels;
1206 in.pcmType.sample_frequency = codec_data->info->params.pcmType.sample_frequency;
1207
Benny Prijonob1339242008-08-21 20:58:55 +00001208 out.pBuffer = (char*)bits_out;
Nanang Izzuddin493a8db2008-08-15 13:17:39 +00001209
Benny Prijonoa4e7cdd2008-08-19 15:01:48 +00001210#if PJMEDIA_HAS_INTEL_IPP_CODEC_AMR
Nanang Izzuddind55553a2008-10-28 02:24:46 +00001211 /* For AMR: reserve two octets for AMR frame info */
Nanang Izzuddindf361e02008-08-16 06:46:08 +00001212 if (pt == PJMEDIA_RTP_PT_AMR || pt == PJMEDIA_RTP_PT_AMRWB) {
Nanang Izzuddind55553a2008-10-28 02:24:46 +00001213 out.pBuffer += 2;
Nanang Izzuddin493a8db2008-08-15 13:17:39 +00001214 }
1215#endif
1216
Benny Prijonoa4e7cdd2008-08-19 15:01:48 +00001217 if (USC_NoError != ippc->fxns->Encode(codec_data->enc, &in, &out)) {
Nanang Izzuddin493a8db2008-08-15 13:17:39 +00001218 break;
1219 }
1220
Benny Prijonoa4e7cdd2008-08-19 15:01:48 +00001221#if PJMEDIA_HAS_INTEL_IPP_CODEC_AMR
Nanang Izzuddin35e01de2008-10-29 10:17:02 +00001222 /* For AMR: put info (frametype, degraded, last frame, mode) in the
1223 * first two octets for payload packing.
Benny Prijonoa4e7cdd2008-08-19 15:01:48 +00001224 */
Nanang Izzuddindf361e02008-08-16 06:46:08 +00001225 if (pt == PJMEDIA_RTP_PT_AMR || pt == PJMEDIA_RTP_PT_AMRWB) {
Nanang Izzuddind55553a2008-10-28 02:24:46 +00001226 pj_uint16_t *info = (pj_uint16_t*)bits_out;
Nanang Izzuddin493a8db2008-08-15 13:17:39 +00001227
Nanang Izzuddind55553a2008-10-28 02:24:46 +00001228 /* Two octets for AMR frame info, 0=LSB:
Nanang Izzuddin493a8db2008-08-15 13:17:39 +00001229 * bit 0-3 : frame type
1230 * bit 6 : last frame flag
1231 * bit 7 : quality flag
Nanang Izzuddind55553a2008-10-28 02:24:46 +00001232 * bit 8-11 : mode
Nanang Izzuddin493a8db2008-08-15 13:17:39 +00001233 */
Nanang Izzuddind55553a2008-10-28 02:24:46 +00001234 out.nbytes += 2;
Nanang Izzuddindf361e02008-08-16 06:46:08 +00001235 if (out.frametype == 0 || out.frametype == 4 ||
1236 (pt == PJMEDIA_RTP_PT_AMR && out.frametype == 5) ||
1237 (pt == PJMEDIA_RTP_PT_AMRWB && out.frametype == 6))
1238 {
Nanang Izzuddind55553a2008-10-28 02:24:46 +00001239 /* Speech frame type */
1240 *info = (char)pjmedia_codec_amr_get_mode(out.bitrate);
1241 /* Quality */
Nanang Izzuddindf361e02008-08-16 06:46:08 +00001242 if (out.frametype == 5 || out.frametype == 6)
Nanang Izzuddin493a8db2008-08-15 13:17:39 +00001243 *info |= 0x80;
Nanang Izzuddindf361e02008-08-16 06:46:08 +00001244 } else if (out.frametype == 1 || out.frametype == 2 ||
1245 (pt == PJMEDIA_RTP_PT_AMR && out.frametype == 6) ||
1246 (pt == PJMEDIA_RTP_PT_AMRWB && out.frametype == 7))
1247 {
Nanang Izzuddind55553a2008-10-28 02:24:46 +00001248 /* SID frame type */
Benny Prijonoa4e7cdd2008-08-19 15:01:48 +00001249 *info = (pj_uint8_t)(pt == PJMEDIA_RTP_PT_AMRWB? 9 : 8);
Nanang Izzuddind55553a2008-10-28 02:24:46 +00001250 /* Quality */
Nanang Izzuddindf361e02008-08-16 06:46:08 +00001251 if (out.frametype == 6 || out.frametype == 7)
1252 *info |= 0x80;
1253 } else {
Nanang Izzuddin493a8db2008-08-15 13:17:39 +00001254 /* Untransmited */
1255 *info = 15;
Nanang Izzuddind55553a2008-10-28 02:24:46 +00001256 out.nbytes = 2;
Nanang Izzuddin493a8db2008-08-15 13:17:39 +00001257 }
1258
Nanang Izzuddind55553a2008-10-28 02:24:46 +00001259 /* Mode */
1260 *info |= (char)pjmedia_codec_amr_get_mode(out.bitrate) << 8;
1261
Nanang Izzuddin493a8db2008-08-15 13:17:39 +00001262 /* Last frame flag */
1263 if (nsamples == samples_per_frame)
1264 *info |= 0x40;
1265 }
Nanang Izzuddin7dd32682008-08-19 11:23:33 +00001266#endif
Nanang Izzuddin493a8db2008-08-15 13:17:39 +00001267
1268 pcm_in += samples_per_frame;
1269 nsamples -= samples_per_frame;
1270 tx += out.nbytes;
1271 bits_out += out.nbytes;
Nanang Izzuddin23a00b72008-08-25 13:58:25 +00001272
1273#if PJMEDIA_HAS_INTEL_IPP_CODEC_G729
Nanang Izzuddine3a6fca2008-08-27 13:15:25 +00001274 if (pt == PJMEDIA_RTP_PT_G729) {
1275 if (out.frametype == 1) {
1276 /* SID */
1277 break;
1278 } else if (out.frametype == 0) {
1279 /* Untransmitted */
1280 tx -= out.nbytes;
1281 break;
1282 }
Nanang Izzuddin23a00b72008-08-25 13:58:25 +00001283 }
1284#endif
1285
Nanang Izzuddin493a8db2008-08-15 13:17:39 +00001286 }
Nanang Izzuddin493a8db2008-08-15 13:17:39 +00001287
Benny Prijonoa4e7cdd2008-08-19 15:01:48 +00001288 if (ippc->pack != NULL) {
1289 ippc->pack(codec_data, output->buf, &tx, output_buf_len);
Nanang Izzuddin493a8db2008-08-15 13:17:39 +00001290 }
1291
1292 /* Check if we don't need to transmit the frame (DTX) */
1293 if (tx == 0) {
1294 output->buf = NULL;
1295 output->size = 0;
1296 output->timestamp.u64 = input->timestamp.u64;
1297 output->type = PJMEDIA_FRAME_TYPE_NONE;
1298 return PJ_SUCCESS;
1299 }
1300
1301 output->size = tx;
1302 output->type = PJMEDIA_FRAME_TYPE_AUDIO;
1303 output->timestamp = input->timestamp;
1304
1305 return PJ_SUCCESS;
1306}
1307
1308/*
1309 * Decode frame.
1310 */
1311static pj_status_t ipp_codec_decode( pjmedia_codec *codec,
1312 const struct pjmedia_frame *input,
1313 unsigned output_buf_len,
1314 struct pjmedia_frame *output)
1315{
1316 ipp_private_t *codec_data = (ipp_private_t*) codec->codec_data;
Benny Prijonoa4e7cdd2008-08-19 15:01:48 +00001317 struct ipp_codec *ippc = &ipp_codec[codec_data->codec_idx];
Nanang Izzuddin493a8db2008-08-15 13:17:39 +00001318 unsigned samples_per_frame;
1319 USC_PCMStream out;
1320 USC_Bitstream in;
1321 pj_uint8_t pt;
1322
Benny Prijonoa4e7cdd2008-08-19 15:01:48 +00001323 pt = ippc->pt;
1324 samples_per_frame = ippc->samples_per_frame;
Nanang Izzuddin493a8db2008-08-15 13:17:39 +00001325
1326 PJ_ASSERT_RETURN(output_buf_len >= samples_per_frame << 1,
1327 PJMEDIA_CODEC_EPCMTOOSHORT);
1328
1329 if (input->type == PJMEDIA_FRAME_TYPE_AUDIO) {
Benny Prijonoa4e7cdd2008-08-19 15:01:48 +00001330 if (ippc->predecode) {
1331 ippc->predecode(codec_data, input, &in);
Nanang Izzuddin493a8db2008-08-15 13:17:39 +00001332 } else {
1333 /* Most IPP codecs have frametype==0 for speech frame */
Nanang Izzuddindf361e02008-08-16 06:46:08 +00001334 in.pBuffer = (char*)input->buf;
1335 in.nbytes = input->size;
Nanang Izzuddin493a8db2008-08-15 13:17:39 +00001336 in.frametype = 0;
1337 in.bitrate = codec_data->info->params.modes.bitrate;
1338 }
1339
1340 out.pBuffer = output->buf;
Nanang Izzuddin493a8db2008-08-15 13:17:39 +00001341 }
Nanang Izzuddin493a8db2008-08-15 13:17:39 +00001342
1343 if (input->type != PJMEDIA_FRAME_TYPE_AUDIO ||
Benny Prijonoa4e7cdd2008-08-19 15:01:48 +00001344 USC_NoError != ippc->fxns->Decode(codec_data->dec, &in, &out))
Nanang Izzuddin493a8db2008-08-15 13:17:39 +00001345 {
1346 pjmedia_zero_samples((pj_int16_t*)output->buf, samples_per_frame);
1347 output->size = samples_per_frame << 1;
1348 output->timestamp.u64 = input->timestamp.u64;
1349 output->type = PJMEDIA_FRAME_TYPE_AUDIO;
1350 return PJ_SUCCESS;
1351 }
1352
Benny Prijonoa4e7cdd2008-08-19 15:01:48 +00001353#if PJMEDIA_HAS_INTEL_IPP_CODEC_G726
Nanang Izzuddin493a8db2008-08-15 13:17:39 +00001354 /* For G.726: amplify decoding result (USC G.726 encoder deamplified it) */
Nanang Izzuddin493a8db2008-08-15 13:17:39 +00001355 if (pt == PJMEDIA_RTP_PT_G726_16 || pt == PJMEDIA_RTP_PT_G726_24 ||
1356 pt == PJMEDIA_RTP_PT_G726_32 || pt == PJMEDIA_RTP_PT_G726_40)
1357 {
1358 unsigned i;
1359 pj_int16_t *s = (pj_int16_t*)output->buf;
1360
1361 for (i = 0; i < samples_per_frame; ++i)
1362 s[i] <<= 2;
1363 }
1364#endif
1365
1366 output->type = PJMEDIA_FRAME_TYPE_AUDIO;
1367 output->size = samples_per_frame << 1;
1368 output->timestamp.u64 = input->timestamp.u64;
1369
1370 /* Invoke external PLC if codec has no internal PLC */
1371 if (codec_data->plc && codec_data->plc_enabled)
1372 pjmedia_plc_save(codec_data->plc, (pj_int16_t*)output->buf);
1373
1374 return PJ_SUCCESS;
1375}
1376
1377/*
1378 * Recover lost frame.
1379 */
1380static pj_status_t ipp_codec_recover(pjmedia_codec *codec,
1381 unsigned output_buf_len,
1382 struct pjmedia_frame *output)
1383{
1384 ipp_private_t *codec_data = (ipp_private_t*) codec->codec_data;
Benny Prijonoa4e7cdd2008-08-19 15:01:48 +00001385 struct ipp_codec *ippc = &ipp_codec[codec_data->codec_idx];
Nanang Izzuddin493a8db2008-08-15 13:17:39 +00001386 unsigned samples_per_frame;
1387
1388 PJ_UNUSED_ARG(output_buf_len);
1389
Benny Prijonoa4e7cdd2008-08-19 15:01:48 +00001390 samples_per_frame = ippc->samples_per_frame;
Nanang Izzuddin493a8db2008-08-15 13:17:39 +00001391
1392 output->type = PJMEDIA_FRAME_TYPE_AUDIO;
1393 output->size = samples_per_frame << 1;
1394
1395 if (codec_data->plc_enabled) {
1396 if (codec_data->plc) {
1397 pjmedia_plc_generate(codec_data->plc, (pj_int16_t*)output->buf);
1398 } else {
1399 USC_PCMStream out;
1400 out.pBuffer = output->buf;
Benny Prijonoa4e7cdd2008-08-19 15:01:48 +00001401 ippc->fxns->Decode(codec_data->dec, NULL, &out);
Nanang Izzuddin493a8db2008-08-15 13:17:39 +00001402 }
1403 } else {
1404 pjmedia_zero_samples((pj_int16_t*)output->buf, samples_per_frame);
1405 }
1406
1407 return PJ_SUCCESS;
1408}
1409
Nanang Izzuddin493a8db2008-08-15 13:17:39 +00001410
Benny Prijonoa4e7cdd2008-08-19 15:01:48 +00001411#if defined(_MSC_VER) && PJMEDIA_AUTO_LINK_IPP_LIBS
1412# pragma comment( lib, "ippcore.lib")
1413# pragma comment( lib, "ipps.lib")
1414# pragma comment( lib, "ippsc.lib")
1415# pragma comment( lib, "ippsr.lib")
Benny Prijonoc543e9e2009-01-03 12:19:53 +00001416//# pragma comment( lib, "ippcorel.lib")
1417//# pragma comment( lib, "ippsemerged.lib")
1418//# pragma comment( lib, "ippsmerged.lib")
1419//# pragma comment( lib, "ippscemerged.lib")
1420//# pragma comment( lib, "ippscmerged.lib")
1421//# pragma comment( lib, "ippsremerged.lib")
1422//# pragma comment( lib, "ippsrmerged.lib")
Benny Prijonoe1e6d512009-01-02 15:17:47 +00001423# if defined(IPP_VERSION_MAJOR) && IPP_VERSION_MAJOR>=6
1424# pragma comment( lib, "speech.lib")
1425# else
1426# pragma comment( lib, "usc.lib")
1427# endif
Nanang Izzuddin493a8db2008-08-15 13:17:39 +00001428#endif
1429
1430
Benny Prijonoa4e7cdd2008-08-19 15:01:48 +00001431#endif /* PJMEDIA_HAS_INTEL_IPP */
Nanang Izzuddin493a8db2008-08-15 13:17:39 +00001432