blob: 83711802b95e58ee72e79b6606a65b9d7e970f65 [file] [log] [blame]
Nanang Izzuddin493a8db2008-08-15 13:17:39 +00001/* $Id$ */
2/*
3 * Copyright (C)2003-2008 Benny Prijono <benny@prijono.org>
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18 */
19#include <pjmedia-codec/ipp_codecs.h>
20#include <pjmedia/codec.h>
21#include <pjmedia/errno.h>
22#include <pjmedia/endpoint.h>
23#include <pjmedia/plc.h>
24#include <pjmedia/port.h>
25#include <pjmedia/silencedet.h>
26#include <pj/assert.h>
27#include <pj/log.h>
28#include <pj/pool.h>
29#include <pj/string.h>
30#include <pj/os.h>
31
Nanang Izzuddin23a00b72008-08-25 13:58:25 +000032
Nanang Izzuddin493a8db2008-08-15 13:17:39 +000033/*
Benny Prijonoa4e7cdd2008-08-19 15:01:48 +000034 * Only build this file if PJMEDIA_HAS_INTEL_IPP != 0
Nanang Izzuddin493a8db2008-08-15 13:17:39 +000035 */
Benny Prijonoa4e7cdd2008-08-19 15:01:48 +000036#if defined(PJMEDIA_HAS_INTEL_IPP) && PJMEDIA_HAS_INTEL_IPP != 0
Nanang Izzuddin493a8db2008-08-15 13:17:39 +000037
38#include <usc.h>
39
40#define THIS_FILE "ipp_codecs.c"
41
42/* Prototypes for IPP codecs factory */
43static pj_status_t ipp_test_alloc( pjmedia_codec_factory *factory,
44 const pjmedia_codec_info *id );
45static pj_status_t ipp_default_attr( pjmedia_codec_factory *factory,
46 const pjmedia_codec_info *id,
47 pjmedia_codec_param *attr );
48static pj_status_t ipp_enum_codecs( pjmedia_codec_factory *factory,
49 unsigned *count,
50 pjmedia_codec_info codecs[]);
51static pj_status_t ipp_alloc_codec( pjmedia_codec_factory *factory,
52 const pjmedia_codec_info *id,
53 pjmedia_codec **p_codec);
54static pj_status_t ipp_dealloc_codec( pjmedia_codec_factory *factory,
55 pjmedia_codec *codec );
56
57/* Prototypes for IPP codecs implementation. */
58static pj_status_t ipp_codec_init( pjmedia_codec *codec,
59 pj_pool_t *pool );
60static pj_status_t ipp_codec_open( pjmedia_codec *codec,
61 pjmedia_codec_param *attr );
62static pj_status_t ipp_codec_close( pjmedia_codec *codec );
63static pj_status_t ipp_codec_modify(pjmedia_codec *codec,
64 const pjmedia_codec_param *attr );
65static pj_status_t ipp_codec_parse( pjmedia_codec *codec,
66 void *pkt,
67 pj_size_t pkt_size,
68 const pj_timestamp *ts,
69 unsigned *frame_cnt,
70 pjmedia_frame frames[]);
71static pj_status_t ipp_codec_encode( pjmedia_codec *codec,
72 const struct pjmedia_frame *input,
73 unsigned output_buf_len,
74 struct pjmedia_frame *output);
75static pj_status_t ipp_codec_decode( pjmedia_codec *codec,
76 const struct pjmedia_frame *input,
77 unsigned output_buf_len,
78 struct pjmedia_frame *output);
79static pj_status_t ipp_codec_recover(pjmedia_codec *codec,
80 unsigned output_buf_len,
81 struct pjmedia_frame *output);
82
83/* Definition for IPP codecs operations. */
84static pjmedia_codec_op ipp_op =
85{
86 &ipp_codec_init,
87 &ipp_codec_open,
88 &ipp_codec_close,
89 &ipp_codec_modify,
90 &ipp_codec_parse,
91 &ipp_codec_encode,
92 &ipp_codec_decode,
93 &ipp_codec_recover
94};
95
96/* Definition for IPP codecs factory operations. */
97static pjmedia_codec_factory_op ipp_factory_op =
98{
99 &ipp_test_alloc,
100 &ipp_default_attr,
101 &ipp_enum_codecs,
102 &ipp_alloc_codec,
103 &ipp_dealloc_codec
104};
105
106/* IPP codecs factory */
107static struct ipp_factory {
108 pjmedia_codec_factory base;
109 pjmedia_endpt *endpt;
110 pj_pool_t *pool;
111 pj_mutex_t *mutex;
112} ipp_factory;
113
114/* IPP codecs private data. */
115typedef struct ipp_private {
116 int codec_idx; /**< Codec index. */
117 pj_pool_t *pool; /**< Pool for each instance. */
118
119 USC_Handle enc; /**< Encoder state. */
120 USC_Handle dec; /**< Decoder state. */
121 USC_CodecInfo *info; /**< Native codec info. */
122 pj_uint16_t frame_size; /**< Bitstream frame size. */
123
124 pj_bool_t plc_enabled;
125 pjmedia_plc *plc;
126
127 pj_bool_t vad_enabled;
128 pjmedia_silence_det *vad;
129 pj_timestamp last_tx;
130} ipp_private_t;
131
132
133/* USC codec implementations. */
134extern USC_Fxns USC_G729AFP_Fxns;
Nanang Izzuddin762a5bd2008-09-16 14:11:09 +0000135extern USC_Fxns USC_G729I_Fxns;
Nanang Izzuddin493a8db2008-08-15 13:17:39 +0000136extern USC_Fxns USC_G723_Fxns;
137extern USC_Fxns USC_G726_Fxns;
138extern USC_Fxns USC_G728_Fxns;
139extern USC_Fxns USC_G722_Fxns;
140extern USC_Fxns USC_GSMAMR_Fxns;
141extern USC_Fxns USC_AMRWB_Fxns;
142extern USC_Fxns USC_AMRWBE_Fxns;
143
Nanang Izzuddin762a5bd2008-09-16 14:11:09 +0000144
Nanang Izzuddin493a8db2008-08-15 13:17:39 +0000145/* CUSTOM CALLBACKS */
146
Nanang Izzuddindf361e02008-08-16 06:46:08 +0000147/* This callback is useful for translating RTP frame into USC frame, e.g:
148 * reassigning frame attributes, reorder bitstream. Default behaviour of
149 * the translation is just setting the USC frame buffer & its size as
150 * specified in RTP frame, setting USC frame frametype to 0, setting bitrate
151 * of USC frame to bitrate info of codec_data. Implement this callback when
152 * the default behaviour is unapplicable.
Nanang Izzuddin493a8db2008-08-15 13:17:39 +0000153 */
Nanang Izzuddindf361e02008-08-16 06:46:08 +0000154typedef void (*predecode_cb)(ipp_private_t *codec_data,
155 const pjmedia_frame *rtp_frame,
156 USC_Bitstream *usc_frame);
Nanang Izzuddin493a8db2008-08-15 13:17:39 +0000157
Nanang Izzuddindf361e02008-08-16 06:46:08 +0000158/* Parse frames from a packet. Default behaviour of frame parsing is
159 * just separating frames based on calculating frame length derived
160 * from bitrate. Implement this callback when the default behaviour is
161 * unapplicable.
Nanang Izzuddin493a8db2008-08-15 13:17:39 +0000162 */
163typedef pj_status_t (*parse_cb)(ipp_private_t *codec_data, void *pkt,
164 pj_size_t pkt_size, const pj_timestamp *ts,
165 unsigned *frame_cnt, pjmedia_frame frames[]);
166
Nanang Izzuddindf361e02008-08-16 06:46:08 +0000167/* Pack frames into a packet. Default behaviour of packing frames is
168 * just stacking the frames with octet aligned without adding any
169 * payload header. Implement this callback when the default behaviour is
170 * unapplicable.
Nanang Izzuddin493a8db2008-08-15 13:17:39 +0000171 */
172typedef pj_status_t (*pack_cb)(ipp_private_t *codec_data, void *pkt,
173 pj_size_t *pkt_size, pj_size_t max_pkt_size);
174
175
176
Nanang Izzuddindf361e02008-08-16 06:46:08 +0000177/* Custom callback implementations. */
178static void predecode_g723( ipp_private_t *codec_data,
179 const pjmedia_frame *rtp_frame,
180 USC_Bitstream *usc_frame);
181static pj_status_t parse_g723( ipp_private_t *codec_data, void *pkt,
182 pj_size_t pkt_size, const pj_timestamp *ts,
183 unsigned *frame_cnt, pjmedia_frame frames[]);
Nanang Izzuddin493a8db2008-08-15 13:17:39 +0000184
Nanang Izzuddindf361e02008-08-16 06:46:08 +0000185static void predecode_g729( ipp_private_t *codec_data,
186 const pjmedia_frame *rtp_frame,
187 USC_Bitstream *usc_frame);
188
189static void predecode_amr( ipp_private_t *codec_data,
190 const pjmedia_frame *rtp_frame,
191 USC_Bitstream *usc_frame);
192static pj_status_t parse_amr( ipp_private_t *codec_data, void *pkt,
Nanang Izzuddin493a8db2008-08-15 13:17:39 +0000193 pj_size_t pkt_size, const pj_timestamp *ts,
194 unsigned *frame_cnt, pjmedia_frame frames[]);
Nanang Izzuddindf361e02008-08-16 06:46:08 +0000195static pj_status_t pack_amr( ipp_private_t *codec_data, void *pkt,
196 pj_size_t *pkt_size, pj_size_t max_pkt_size);
Nanang Izzuddin493a8db2008-08-15 13:17:39 +0000197
198
199/* IPP codec implementation descriptions. */
200static struct ipp_codec {
201 int enabled; /* Is this codec enabled? */
202 const char *name; /* Codec name. */
203 pj_uint8_t pt; /* Payload type. */
204 USC_Fxns *fxns; /* USC callback functions. */
205 unsigned clock_rate; /* Codec's clock rate. */
206 unsigned channel_count; /* Codec's channel count. */
207 unsigned samples_per_frame; /* Codec's samples count. */
208
209 unsigned def_bitrate; /* Default bitrate of this codec. */
210 unsigned max_bitrate; /* Maximum bitrate of this codec. */
211 pj_uint8_t frm_per_pkt; /* Default num of frames per packet.*/
212 int has_native_vad; /* Codec has internal VAD? */
213 int has_native_plc; /* Codec has internal PLC? */
214
Nanang Izzuddindf361e02008-08-16 06:46:08 +0000215 predecode_cb predecode; /* Callback to translate RTP frame
Nanang Izzuddin23a00b72008-08-25 13:58:25 +0000216 into USC frame. */
217 parse_cb parse; /* Callback to parse bitstream. */
218 pack_cb pack; /* Callback to pack bitstream. */
219
220 pjmedia_codec_fmtp dec_fmtp; /* Decoder's fmtp params. */
221}
Nanang Izzuddin493a8db2008-08-15 13:17:39 +0000222
223ipp_codec[] =
224{
Benny Prijonoa4e7cdd2008-08-19 15:01:48 +0000225# if PJMEDIA_HAS_INTEL_IPP_CODEC_AMR
Nanang Izzuddin493a8db2008-08-15 13:17:39 +0000226 {1, "AMR", PJMEDIA_RTP_PT_AMR, &USC_GSMAMR_Fxns, 8000, 1, 160,
227 5900, 12200, 4, 1, 1,
Nanang Izzuddindf361e02008-08-16 06:46:08 +0000228 &predecode_amr, &parse_amr, &pack_amr
229 },
230# endif
231
Benny Prijonoa4e7cdd2008-08-19 15:01:48 +0000232# if PJMEDIA_HAS_INTEL_IPP_CODEC_AMRWB
233 {1, "AMR-WB", PJMEDIA_RTP_PT_AMRWB, &USC_AMRWB_Fxns, 16000, 1, 320,
234 15850, 23850, 1, 1, 1,
Nanang Izzuddindf361e02008-08-16 06:46:08 +0000235 &predecode_amr, &parse_amr, &pack_amr
Nanang Izzuddin493a8db2008-08-15 13:17:39 +0000236 },
237# endif
238
Benny Prijonoa4e7cdd2008-08-19 15:01:48 +0000239# if PJMEDIA_HAS_INTEL_IPP_CODEC_G729
Nanang Izzuddin762a5bd2008-09-16 14:11:09 +0000240# if defined(PJ_HAS_FLOATING_POINT) && (PJ_HAS_FLOATING_POINT != 0)
241 {1, "G729", PJMEDIA_RTP_PT_G729, &USC_G729AFP_Fxns, 8000, 1, 80,
Nanang Izzuddin23a00b72008-08-25 13:58:25 +0000242 8000, 11800, 2, 1, 1,
Nanang Izzuddindf361e02008-08-16 06:46:08 +0000243 &predecode_g729, NULL, NULL
Nanang Izzuddin493a8db2008-08-15 13:17:39 +0000244 },
Nanang Izzuddin762a5bd2008-09-16 14:11:09 +0000245# else
246 {1, "G729", PJMEDIA_RTP_PT_G729, &USC_G729I_Fxns, 8000, 1, 80,
247 8000, 11800, 2, 1, 1,
248 &predecode_g729, NULL, NULL
249 },
250# endif
Nanang Izzuddin493a8db2008-08-15 13:17:39 +0000251# endif
252
Benny Prijonoa4e7cdd2008-08-19 15:01:48 +0000253# if PJMEDIA_HAS_INTEL_IPP_CODEC_G723_1
Nanang Izzuddin493a8db2008-08-15 13:17:39 +0000254 /* This is actually G.723.1 */
255 {1, "G723", PJMEDIA_RTP_PT_G723, &USC_G723_Fxns, 8000, 1, 240,
Benny Prijonoa4e7cdd2008-08-19 15:01:48 +0000256 6300, 6300, 1, 1, 1,
Nanang Izzuddindf361e02008-08-16 06:46:08 +0000257 &predecode_g723, &parse_g723, NULL
Nanang Izzuddin493a8db2008-08-15 13:17:39 +0000258 },
259# endif
260
Benny Prijonoa4e7cdd2008-08-19 15:01:48 +0000261# if PJMEDIA_HAS_INTEL_IPP_CODEC_G726
Nanang Izzuddinf216f822008-08-15 18:35:50 +0000262 {0, "G726-16", PJMEDIA_RTP_PT_G726_16, &USC_G726_Fxns, 8000, 1, 80,
Nanang Izzuddin493a8db2008-08-15 13:17:39 +0000263 16000, 16000, 2, 0, 0,
264 NULL, NULL, NULL
265 },
Nanang Izzuddinf216f822008-08-15 18:35:50 +0000266 {0, "G726-24", PJMEDIA_RTP_PT_G726_24, &USC_G726_Fxns, 8000, 1, 80,
Nanang Izzuddin493a8db2008-08-15 13:17:39 +0000267 24000, 24000, 2, 0, 0,
268 NULL, NULL, NULL
269 },
270 {1, "G726-32", PJMEDIA_RTP_PT_G726_32, &USC_G726_Fxns, 8000, 1, 80,
271 32000, 32000, 2, 0, 0,
272 NULL, NULL, NULL
273 },
Nanang Izzuddinf216f822008-08-15 18:35:50 +0000274 {0, "G726-40", PJMEDIA_RTP_PT_G726_40, &USC_G726_Fxns, 8000, 1, 80,
Nanang Izzuddin493a8db2008-08-15 13:17:39 +0000275 40000, 40000, 2, 0, 0,
276 NULL, NULL, NULL
277 },
278# endif
279
Benny Prijonoa4e7cdd2008-08-19 15:01:48 +0000280# if PJMEDIA_HAS_INTEL_IPP_CODEC_G728
Nanang Izzuddin493a8db2008-08-15 13:17:39 +0000281 {1, "G728", PJMEDIA_RTP_PT_G728, &USC_G728_Fxns, 8000, 1, 80,
282 16000, 16000, 2, 0, 1,
283 NULL, NULL, NULL
284 },
285# endif
286
Benny Prijonoa4e7cdd2008-08-19 15:01:48 +0000287# if PJMEDIA_HAS_INTEL_IPP_CODEC_G722_1
Nanang Izzuddin23a00b72008-08-25 13:58:25 +0000288 {0, "G7221", PJMEDIA_RTP_PT_G722_1_16, &USC_G722_Fxns, 16000, 1, 320,
289 16000, 16000, 1, 0, 1,
290 NULL, NULL, NULL,
291 {1, {{{"bitrate", 7}, {"16000", 5}}} }
292 },
293 {1, "G7221", PJMEDIA_RTP_PT_G722_1_24, &USC_G722_Fxns, 16000, 1, 320,
294 24000, 24000, 1, 0, 1,
295 NULL, NULL, NULL,
296 {1, {{{"bitrate", 7}, {"24000", 5}}} }
297 },
298 {1, "G7221", PJMEDIA_RTP_PT_G722_1_32, &USC_G722_Fxns, 16000, 1, 320,
299 32000, 32000, 1, 0, 1,
300 NULL, NULL, NULL,
301 {1, {{{"bitrate", 7}, {"32000", 5}}} }
Nanang Izzuddin493a8db2008-08-15 13:17:39 +0000302 },
303# endif
304};
305
306
307static int amr_get_mode(unsigned bitrate);
Nanang Izzuddin493a8db2008-08-15 13:17:39 +0000308
309/*
310 * Initialize and register IPP codec factory to pjmedia endpoint.
311 */
312PJ_DEF(pj_status_t) pjmedia_codec_ipp_init( pjmedia_endpt *endpt )
313{
314 pjmedia_codec_mgr *codec_mgr;
315 pj_status_t status;
316
317 if (ipp_factory.pool != NULL) {
318 /* Already initialized. */
319 return PJ_SUCCESS;
320 }
321
322 /* Create IPP codec factory. */
323 ipp_factory.base.op = &ipp_factory_op;
324 ipp_factory.base.factory_data = NULL;
325 ipp_factory.endpt = endpt;
326
327 ipp_factory.pool = pjmedia_endpt_create_pool(endpt, "IPP codecs", 4000, 4000);
328 if (!ipp_factory.pool)
329 return PJ_ENOMEM;
330
331 /* Create mutex. */
332 status = pj_mutex_create_simple(ipp_factory.pool, "IPP codecs",
333 &ipp_factory.mutex);
334 if (status != PJ_SUCCESS)
335 goto on_error;
336
337 /* Get the codec manager. */
338 codec_mgr = pjmedia_endpt_get_codec_mgr(endpt);
339 if (!codec_mgr) {
340 status = PJ_EINVALIDOP;
341 goto on_error;
342 }
343
344 /* Register codec factory to endpoint. */
345 status = pjmedia_codec_mgr_register_factory(codec_mgr,
346 &ipp_factory.base);
347 if (status != PJ_SUCCESS)
348 goto on_error;
349
350 /* Done. */
351 return PJ_SUCCESS;
352
353on_error:
354 pj_pool_release(ipp_factory.pool);
355 ipp_factory.pool = NULL;
356 return status;
357}
358
359/*
360 * Unregister IPP codecs factory from pjmedia endpoint.
361 */
362PJ_DEF(pj_status_t) pjmedia_codec_ipp_deinit(void)
363{
364 pjmedia_codec_mgr *codec_mgr;
365 pj_status_t status;
366
367 if (ipp_factory.pool == NULL) {
368 /* Already deinitialized */
369 return PJ_SUCCESS;
370 }
371
372 pj_mutex_lock(ipp_factory.mutex);
373
374 /* Get the codec manager. */
375 codec_mgr = pjmedia_endpt_get_codec_mgr(ipp_factory.endpt);
376 if (!codec_mgr) {
377 pj_pool_release(ipp_factory.pool);
378 ipp_factory.pool = NULL;
379 return PJ_EINVALIDOP;
380 }
381
382 /* Unregister IPP codecs factory. */
383 status = pjmedia_codec_mgr_unregister_factory(codec_mgr,
384 &ipp_factory.base);
385
386 /* Destroy mutex. */
387 pj_mutex_destroy(ipp_factory.mutex);
388
389 /* Destroy pool. */
390 pj_pool_release(ipp_factory.pool);
391 ipp_factory.pool = NULL;
392
393 return status;
394}
395
396/*
397 * Check if factory can allocate the specified codec.
398 */
399static pj_status_t ipp_test_alloc( pjmedia_codec_factory *factory,
400 const pjmedia_codec_info *info )
401{
402 unsigned i;
403
404 PJ_UNUSED_ARG(factory);
405
406 /* Type MUST be audio. */
407 if (info->type != PJMEDIA_TYPE_AUDIO)
408 return PJMEDIA_CODEC_EUNSUP;
409
410 for (i = 0; i < PJ_ARRAY_SIZE(ipp_codec); ++i) {
411 pj_str_t name = pj_str((char*)ipp_codec[i].name);
412 if ((pj_stricmp(&info->encoding_name, &name) == 0) &&
413 (info->clock_rate == (unsigned)ipp_codec[i].clock_rate) &&
414 (info->channel_cnt == (unsigned)ipp_codec[i].channel_count) &&
415 (ipp_codec[i].enabled))
416 {
417 return PJ_SUCCESS;
418 }
419 }
420
421 /* Unsupported, or mode is disabled. */
422 return PJMEDIA_CODEC_EUNSUP;
423}
424
425/*
426 * Generate default attribute.
427 */
428static pj_status_t ipp_default_attr (pjmedia_codec_factory *factory,
429 const pjmedia_codec_info *id,
430 pjmedia_codec_param *attr )
431{
432 unsigned i;
433
434 PJ_ASSERT_RETURN(factory==&ipp_factory.base, PJ_EINVAL);
435
436 pj_bzero(attr, sizeof(pjmedia_codec_param));
437
438 for (i = 0; i < PJ_ARRAY_SIZE(ipp_codec); ++i) {
439 pj_str_t name = pj_str((char*)ipp_codec[i].name);
440 if ((pj_stricmp(&id->encoding_name, &name) == 0) &&
441 (id->clock_rate == (unsigned)ipp_codec[i].clock_rate) &&
Nanang Izzuddin23a00b72008-08-25 13:58:25 +0000442 (id->channel_cnt == (unsigned)ipp_codec[i].channel_count) &&
443 (id->pt == (unsigned)ipp_codec[i].pt))
Nanang Izzuddin493a8db2008-08-15 13:17:39 +0000444 {
445 attr->info.pt = (pj_uint8_t)id->pt;
446 attr->info.channel_cnt = ipp_codec[i].channel_count;
447 attr->info.clock_rate = ipp_codec[i].clock_rate;
448 attr->info.avg_bps = ipp_codec[i].def_bitrate;
449 attr->info.max_bps = ipp_codec[i].max_bitrate;
450 attr->info.pcm_bits_per_sample = 16;
451 attr->info.frm_ptime = (pj_uint16_t)
452 (ipp_codec[i].samples_per_frame * 1000 /
453 ipp_codec[i].channel_count /
454 ipp_codec[i].clock_rate);
455 attr->setting.frm_per_pkt = ipp_codec[i].frm_per_pkt;
456
457 /* Default flags. */
Nanang Izzuddin493a8db2008-08-15 13:17:39 +0000458 attr->setting.plc = 1;
459 attr->setting.penh= 0;
Nanang Izzuddin23a00b72008-08-25 13:58:25 +0000460 attr->setting.vad = 1;
461 attr->setting.cng = attr->setting.vad;
462 attr->setting.dec_fmtp = ipp_codec[i].dec_fmtp;
463
464 if (attr->setting.vad == 0) {
465#if PJMEDIA_HAS_INTEL_IPP_CODEC_G729
466 if (id->pt == PJMEDIA_RTP_PT_G729) {
467 /* Signal G729 Annex B is being disabled */
468 attr->setting.dec_fmtp.cnt = 1;
469 pj_strset2(&attr->setting.dec_fmtp.param[0].name, "annexb");
470 pj_strset2(&attr->setting.dec_fmtp.param[0].val, "no");
471 }
472#endif
473 }
Nanang Izzuddin493a8db2008-08-15 13:17:39 +0000474
475 return PJ_SUCCESS;
476 }
477 }
478
479 return PJMEDIA_CODEC_EUNSUP;
480}
481
482/*
483 * Enum codecs supported by this factory.
484 */
485static pj_status_t ipp_enum_codecs(pjmedia_codec_factory *factory,
486 unsigned *count,
487 pjmedia_codec_info codecs[])
488{
489 unsigned max;
490 unsigned i;
491
492 PJ_UNUSED_ARG(factory);
493 PJ_ASSERT_RETURN(codecs && *count > 0, PJ_EINVAL);
494
495 max = *count;
496
497 for (i = 0, *count = 0; i < PJ_ARRAY_SIZE(ipp_codec) && *count < max; ++i)
498 {
499 if (!ipp_codec[i].enabled)
500 continue;
501
502 pj_bzero(&codecs[*count], sizeof(pjmedia_codec_info));
503 codecs[*count].encoding_name = pj_str((char*)ipp_codec[i].name);
504 codecs[*count].pt = ipp_codec[i].pt;
505 codecs[*count].type = PJMEDIA_TYPE_AUDIO;
506 codecs[*count].clock_rate = ipp_codec[i].clock_rate;
507 codecs[*count].channel_cnt = ipp_codec[i].channel_count;
508
509 ++*count;
510 }
511
512 return PJ_SUCCESS;
513}
514
515/*
516 * Allocate a new codec instance.
517 */
518static pj_status_t ipp_alloc_codec( pjmedia_codec_factory *factory,
519 const pjmedia_codec_info *id,
520 pjmedia_codec **p_codec)
521{
522 ipp_private_t *codec_data;
523 pjmedia_codec *codec;
524 int idx;
525 pj_pool_t *pool;
526 unsigned i;
527
528 PJ_ASSERT_RETURN(factory && id && p_codec, PJ_EINVAL);
529 PJ_ASSERT_RETURN(factory == &ipp_factory.base, PJ_EINVAL);
530
531 pj_mutex_lock(ipp_factory.mutex);
532
533 /* Find codec's index */
534 idx = -1;
535 for (i = 0; i < PJ_ARRAY_SIZE(ipp_codec); ++i) {
536 pj_str_t name = pj_str((char*)ipp_codec[i].name);
537 if ((pj_stricmp(&id->encoding_name, &name) == 0) &&
538 (id->clock_rate == (unsigned)ipp_codec[i].clock_rate) &&
539 (id->channel_cnt == (unsigned)ipp_codec[i].channel_count) &&
540 (ipp_codec[i].enabled))
541 {
542 idx = i;
543 break;
544 }
545 }
546 if (idx == -1) {
547 *p_codec = NULL;
548 return PJMEDIA_CODEC_EFAILED;
549 }
550
551 /* Create pool for codec instance */
Benny Prijonoa4e7cdd2008-08-19 15:01:48 +0000552 pool = pjmedia_endpt_create_pool(ipp_factory.endpt, "IPPcodec", 512, 512);
Nanang Izzuddin493a8db2008-08-15 13:17:39 +0000553 codec = PJ_POOL_ZALLOC_T(pool, pjmedia_codec);
554 PJ_ASSERT_RETURN(codec != NULL, PJ_ENOMEM);
555 codec->op = &ipp_op;
556 codec->factory = factory;
557 codec->codec_data = PJ_POOL_ZALLOC_T(pool, ipp_private_t);
558 codec_data = (ipp_private_t*) codec->codec_data;
559
560 /* Create PLC if codec has no internal PLC */
561 if (!ipp_codec[idx].has_native_plc) {
562 pj_status_t status;
563 status = pjmedia_plc_create(pool, ipp_codec[idx].clock_rate,
564 ipp_codec[idx].samples_per_frame, 0,
565 &codec_data->plc);
566 if (status != PJ_SUCCESS) {
567 pj_pool_release(pool);
568 pj_mutex_unlock(ipp_factory.mutex);
569 return status;
570 }
571 }
572
573 /* Create silence detector if codec has no internal VAD */
574 if (!ipp_codec[idx].has_native_vad) {
575 pj_status_t status;
576 status = pjmedia_silence_det_create(pool,
577 ipp_codec[idx].clock_rate,
578 ipp_codec[idx].samples_per_frame,
579 &codec_data->vad);
580 if (status != PJ_SUCCESS) {
581 pj_pool_release(pool);
582 pj_mutex_unlock(ipp_factory.mutex);
583 return status;
584 }
585 }
586
587 codec_data->pool = pool;
588 codec_data->codec_idx = idx;
589
590 pj_mutex_unlock(ipp_factory.mutex);
591
592 *p_codec = codec;
593 return PJ_SUCCESS;
594}
595
596/*
597 * Free codec.
598 */
599static pj_status_t ipp_dealloc_codec( pjmedia_codec_factory *factory,
600 pjmedia_codec *codec )
601{
602 ipp_private_t *codec_data;
603
604 PJ_ASSERT_RETURN(factory && codec, PJ_EINVAL);
605 PJ_ASSERT_RETURN(factory == &ipp_factory.base, PJ_EINVAL);
606
607 /* Close codec, if it's not closed. */
608 codec_data = (ipp_private_t*) codec->codec_data;
609 if (codec_data->enc != NULL || codec_data->dec != NULL) {
610 ipp_codec_close(codec);
611 }
612
613 pj_pool_release(codec_data->pool);
614
615 return PJ_SUCCESS;
616}
617
618/*
619 * Init codec.
620 */
621static pj_status_t ipp_codec_init( pjmedia_codec *codec,
622 pj_pool_t *pool )
623{
624 PJ_UNUSED_ARG(codec);
625 PJ_UNUSED_ARG(pool);
626 return PJ_SUCCESS;
627}
628
629/*
630 * Open codec.
631 */
632static pj_status_t ipp_codec_open( pjmedia_codec *codec,
633 pjmedia_codec_param *attr )
634{
635 ipp_private_t *codec_data = (ipp_private_t*) codec->codec_data;
Benny Prijonoa4e7cdd2008-08-19 15:01:48 +0000636 struct ipp_codec *ippc = &ipp_codec[codec_data->codec_idx];
Nanang Izzuddin493a8db2008-08-15 13:17:39 +0000637 int info_size;
638 pj_pool_t *pool;
Benny Prijonoa4e7cdd2008-08-19 15:01:48 +0000639 int i, j;
Nanang Izzuddin493a8db2008-08-15 13:17:39 +0000640 USC_MemBank *membanks;
641 int nb_membanks;
642
643 pool = codec_data->pool;
Nanang Izzuddin493a8db2008-08-15 13:17:39 +0000644
645 /* Get the codec info size */
Benny Prijonoa4e7cdd2008-08-19 15:01:48 +0000646 if (USC_NoError != ippc->fxns->std.GetInfoSize(&info_size)) {
647 PJ_LOG(1,(THIS_FILE, "Error getting codec info size"));
Nanang Izzuddin493a8db2008-08-15 13:17:39 +0000648 goto on_error;
649 }
650 /* Get the codec info */
651 codec_data->info = pj_pool_zalloc(pool, info_size);
Benny Prijonoa4e7cdd2008-08-19 15:01:48 +0000652 if (USC_NoError != ippc->fxns->std.GetInfo((USC_Handle)NULL,
653 codec_data->info))
Nanang Izzuddin493a8db2008-08-15 13:17:39 +0000654 {
Benny Prijonoa4e7cdd2008-08-19 15:01:48 +0000655 PJ_LOG(1,(THIS_FILE, "Error getting codec info"));
Nanang Izzuddin493a8db2008-08-15 13:17:39 +0000656 goto on_error;
657 }
658
659 /* PREPARING THE ENCODER */
660
661 /* Setting the encoder params */
662 codec_data->info->params.direction = USC_ENCODE;
Nanang Izzuddinf216f822008-08-15 18:35:50 +0000663 codec_data->info->params.modes.vad = attr->setting.vad &&
Nanang Izzuddin23a00b72008-08-25 13:58:25 +0000664 ippc->has_native_vad;
Nanang Izzuddin493a8db2008-08-15 13:17:39 +0000665 codec_data->info->params.modes.bitrate = attr->info.avg_bps;
666 codec_data->info->params.law = 0; /* Linear PCM input */
667
Nanang Izzuddin23a00b72008-08-25 13:58:25 +0000668#if PJMEDIA_HAS_INTEL_IPP_CODEC_G729
669 if (ippc->pt == PJMEDIA_RTP_PT_G729) {
670 /* Check if G729 Annex B is signaled to be disabled */
671 for (i = 0; i < attr->setting.enc_fmtp.cnt; ++i) {
672 if (pj_stricmp2(&attr->setting.enc_fmtp.param[i].name, "annexb")==0)
673 {
674 if (pj_stricmp2(&attr->setting.enc_fmtp.param[i].val, "no")==0)
675 codec_data->info->params.modes.vad = 0;
676 break;
677 }
678 }
679 }
680#endif
681
Nanang Izzuddin493a8db2008-08-15 13:17:39 +0000682 /* Get number of memory blocks needed by the encoder */
Benny Prijonoa4e7cdd2008-08-19 15:01:48 +0000683 if (USC_NoError != ippc->fxns->std.NumAlloc(&codec_data->info->params,
684 &nb_membanks))
Nanang Izzuddin493a8db2008-08-15 13:17:39 +0000685 {
Benny Prijonoa4e7cdd2008-08-19 15:01:48 +0000686 PJ_LOG(1,(THIS_FILE, "Error getting no of memory blocks of encoder"));
Nanang Izzuddin493a8db2008-08-15 13:17:39 +0000687 goto on_error;
688 }
689
690 /* Allocate memory blocks table */
691 membanks = (USC_MemBank*) pj_pool_zalloc(pool,
692 sizeof(USC_MemBank) * nb_membanks);
693 /* Get size of each memory block */
Benny Prijonoa4e7cdd2008-08-19 15:01:48 +0000694 if (USC_NoError != ippc->fxns->std.MemAlloc(&codec_data->info->params,
695 membanks))
Nanang Izzuddin493a8db2008-08-15 13:17:39 +0000696 {
Benny Prijonoa4e7cdd2008-08-19 15:01:48 +0000697 PJ_LOG(1,(THIS_FILE, "Error getting memory blocks size of encoder"));
Nanang Izzuddin493a8db2008-08-15 13:17:39 +0000698 goto on_error;
699 }
700
701 /* Allocate memory for each block */
702 for (i = 0; i < nb_membanks; i++) {
703 membanks[i].pMem = (char*) pj_pool_zalloc(pool, membanks[i].nbytes);
704 }
705
706 /* Create encoder instance */
Benny Prijonoa4e7cdd2008-08-19 15:01:48 +0000707 if (USC_NoError != ippc->fxns->std.Init(&codec_data->info->params,
708 membanks,
709 &codec_data->enc))
Nanang Izzuddin493a8db2008-08-15 13:17:39 +0000710 {
Benny Prijonoa4e7cdd2008-08-19 15:01:48 +0000711 PJ_LOG(1,(THIS_FILE, "Error initializing encoder"));
Nanang Izzuddin493a8db2008-08-15 13:17:39 +0000712 goto on_error;
713 }
714
715 /* PREPARING THE DECODER */
716
717 /* Setting the decoder params */
718 codec_data->info->params.direction = USC_DECODE;
719
Nanang Izzuddin23a00b72008-08-25 13:58:25 +0000720 /* Not sure if VAD affects decoder, just try to be safe */
721 codec_data->info->params.modes.vad = ippc->has_native_vad;
722
Nanang Izzuddin493a8db2008-08-15 13:17:39 +0000723 /* Get number of memory blocks needed by the decoder */
Benny Prijonoa4e7cdd2008-08-19 15:01:48 +0000724 if (USC_NoError != ippc->fxns->std.NumAlloc(&codec_data->info->params,
725 &nb_membanks))
Nanang Izzuddin493a8db2008-08-15 13:17:39 +0000726 {
Benny Prijonoa4e7cdd2008-08-19 15:01:48 +0000727 PJ_LOG(1,(THIS_FILE, "Error getting no of memory blocks of decoder"));
Nanang Izzuddin493a8db2008-08-15 13:17:39 +0000728 goto on_error;
729 }
730
731 /* Allocate memory blocks table */
732 membanks = (USC_MemBank*) pj_pool_zalloc(pool,
733 sizeof(USC_MemBank) * nb_membanks);
734 /* Get size of each memory block */
Benny Prijonoa4e7cdd2008-08-19 15:01:48 +0000735 if (USC_NoError != ippc->fxns->std.MemAlloc(&codec_data->info->params,
736 membanks))
Nanang Izzuddin493a8db2008-08-15 13:17:39 +0000737 {
Benny Prijonoa4e7cdd2008-08-19 15:01:48 +0000738 PJ_LOG(1,(THIS_FILE, "Error getting memory blocks size of decoder"));
Nanang Izzuddin493a8db2008-08-15 13:17:39 +0000739 goto on_error;
740 }
741
742 /* Allocate memory for each block */
743 for (i = 0; i < nb_membanks; i++) {
744 membanks[i].pMem = (char*) pj_pool_zalloc(pool, membanks[i].nbytes);
745 }
746
747 /* Create decoder instance */
Benny Prijonoa4e7cdd2008-08-19 15:01:48 +0000748 if (USC_NoError != ippc->fxns->std.Init(&codec_data->info->params,
749 membanks, &codec_data->dec))
Nanang Izzuddin493a8db2008-08-15 13:17:39 +0000750 {
Benny Prijonoa4e7cdd2008-08-19 15:01:48 +0000751 PJ_LOG(1,(THIS_FILE, "Error initializing decoder"));
Nanang Izzuddin493a8db2008-08-15 13:17:39 +0000752 goto on_error;
753 }
754
755 /* Update codec info */
Benny Prijonoa4e7cdd2008-08-19 15:01:48 +0000756 ippc->fxns->std.GetInfo((USC_Handle)codec_data->enc, codec_data->info);
Nanang Izzuddin493a8db2008-08-15 13:17:39 +0000757
758 /* Get bitstream size */
Benny Prijonoa4e7cdd2008-08-19 15:01:48 +0000759 i = codec_data->info->params.modes.bitrate * ippc->samples_per_frame;
760 j = ippc->clock_rate << 3;
Nanang Izzuddin493a8db2008-08-15 13:17:39 +0000761 codec_data->frame_size = (pj_uint16_t)(i / j);
762 if (i % j) ++codec_data->frame_size;
763
764 codec_data->vad_enabled = (attr->setting.vad != 0);
765 codec_data->plc_enabled = (attr->setting.plc != 0);
766
767 return PJ_SUCCESS;
768
769on_error:
770 return PJMEDIA_CODEC_EFAILED;
771}
772
773/*
774 * Close codec.
775 */
776static pj_status_t ipp_codec_close( pjmedia_codec *codec )
777{
778 PJ_UNUSED_ARG(codec);
779
780 return PJ_SUCCESS;
781}
782
783
784/*
785 * Modify codec settings.
786 */
787static pj_status_t ipp_codec_modify(pjmedia_codec *codec,
788 const pjmedia_codec_param *attr )
789{
790 ipp_private_t *codec_data = (ipp_private_t*) codec->codec_data;
Benny Prijonoa4e7cdd2008-08-19 15:01:48 +0000791 struct ipp_codec *ippc = &ipp_codec[codec_data->codec_idx];
Nanang Izzuddin493a8db2008-08-15 13:17:39 +0000792
793 codec_data->vad_enabled = (attr->setting.vad != 0);
794 codec_data->plc_enabled = (attr->setting.plc != 0);
795
Benny Prijonoa4e7cdd2008-08-19 15:01:48 +0000796 if (ippc->has_native_vad) {
Nanang Izzuddin493a8db2008-08-15 13:17:39 +0000797 USC_Modes modes;
798
799 modes = codec_data->info->params.modes;
800 modes.vad = codec_data->vad_enabled;
Benny Prijonoa4e7cdd2008-08-19 15:01:48 +0000801 ippc->fxns->std.Control(&modes, codec_data->enc);
Nanang Izzuddin493a8db2008-08-15 13:17:39 +0000802 }
803
804 return PJ_SUCCESS;
805}
806
807/*
808 * Get frames in the packet.
809 */
810static pj_status_t ipp_codec_parse( pjmedia_codec *codec,
811 void *pkt,
812 pj_size_t pkt_size,
813 const pj_timestamp *ts,
814 unsigned *frame_cnt,
815 pjmedia_frame frames[])
816{
817 ipp_private_t *codec_data = (ipp_private_t*) codec->codec_data;
Benny Prijonoa4e7cdd2008-08-19 15:01:48 +0000818 struct ipp_codec *ippc = &ipp_codec[codec_data->codec_idx];
Nanang Izzuddin493a8db2008-08-15 13:17:39 +0000819 unsigned count = 0;
820
821 PJ_ASSERT_RETURN(frame_cnt, PJ_EINVAL);
822
Benny Prijonoa4e7cdd2008-08-19 15:01:48 +0000823 if (ippc->parse != NULL) {
824 return ippc->parse(codec_data, pkt, pkt_size, ts, frame_cnt, frames);
Nanang Izzuddin493a8db2008-08-15 13:17:39 +0000825 }
826
827 while (pkt_size >= codec_data->frame_size && count < *frame_cnt) {
828 frames[count].type = PJMEDIA_FRAME_TYPE_AUDIO;
829 frames[count].buf = pkt;
830 frames[count].size = codec_data->frame_size;
Benny Prijonoa4e7cdd2008-08-19 15:01:48 +0000831 frames[count].timestamp.u64 = ts->u64 + count*ippc->samples_per_frame;
Nanang Izzuddin493a8db2008-08-15 13:17:39 +0000832
833 pkt = ((char*)pkt) + codec_data->frame_size;
834 pkt_size -= codec_data->frame_size;
835
836 ++count;
837 }
838
839 if (pkt_size && count < *frame_cnt) {
840 frames[count].type = PJMEDIA_FRAME_TYPE_AUDIO;
841 frames[count].buf = pkt;
842 frames[count].size = pkt_size;
Benny Prijonoa4e7cdd2008-08-19 15:01:48 +0000843 frames[count].timestamp.u64 = ts->u64 + count*ippc->samples_per_frame;
Nanang Izzuddin493a8db2008-08-15 13:17:39 +0000844 ++count;
845 }
846
847 *frame_cnt = count;
848 return PJ_SUCCESS;
849}
850
851/*
852 * Encode frames.
853 */
854static pj_status_t ipp_codec_encode( pjmedia_codec *codec,
855 const struct pjmedia_frame *input,
856 unsigned output_buf_len,
857 struct pjmedia_frame *output)
858{
859 ipp_private_t *codec_data = (ipp_private_t*) codec->codec_data;
Benny Prijonoa4e7cdd2008-08-19 15:01:48 +0000860 struct ipp_codec *ippc = &ipp_codec[codec_data->codec_idx];
Nanang Izzuddin493a8db2008-08-15 13:17:39 +0000861 unsigned samples_per_frame;
862 unsigned nsamples;
863 pj_size_t tx = 0;
864 pj_int16_t *pcm_in = (pj_int16_t*)input->buf;
Benny Prijonob1339242008-08-21 20:58:55 +0000865 pj_uint8_t *bits_out = (pj_uint8_t*) output->buf;
Nanang Izzuddindf361e02008-08-16 06:46:08 +0000866 pj_uint8_t pt;
Nanang Izzuddin493a8db2008-08-15 13:17:39 +0000867
868 /* Invoke external VAD if codec has no internal VAD */
869 if (codec_data->vad && codec_data->vad_enabled) {
870 pj_bool_t is_silence;
871 pj_int32_t silence_duration;
872
873 silence_duration = pj_timestamp_diff32(&codec_data->last_tx,
874 &input->timestamp);
875
876 is_silence = pjmedia_silence_det_detect(codec_data->vad,
877 (const pj_int16_t*) input->buf,
878 (input->size >> 1),
879 NULL);
880 if (is_silence &&
881 PJMEDIA_CODEC_MAX_SILENCE_PERIOD != -1 &&
Benny Prijonoa4e7cdd2008-08-19 15:01:48 +0000882 silence_duration < (PJMEDIA_CODEC_MAX_SILENCE_PERIOD *
883 (int)ippc->clock_rate / 1000))
Nanang Izzuddin493a8db2008-08-15 13:17:39 +0000884 {
885 output->type = PJMEDIA_FRAME_TYPE_NONE;
886 output->buf = NULL;
887 output->size = 0;
888 output->timestamp = input->timestamp;
889 return PJ_SUCCESS;
890 } else {
891 codec_data->last_tx = input->timestamp;
892 }
893 }
894
895 nsamples = input->size >> 1;
Benny Prijonoa4e7cdd2008-08-19 15:01:48 +0000896 samples_per_frame = ippc->samples_per_frame;
897 pt = ippc->pt;
Nanang Izzuddin493a8db2008-08-15 13:17:39 +0000898
899 PJ_ASSERT_RETURN(nsamples % samples_per_frame == 0,
900 PJMEDIA_CODEC_EPCMFRMINLEN);
901
902 /* Encode the frames */
903 while (nsamples >= samples_per_frame) {
904 USC_PCMStream in;
905 USC_Bitstream out;
906
907 in.bitrate = codec_data->info->params.modes.bitrate;
908 in.nbytes = samples_per_frame << 1;
909 in.pBuffer = (char*)pcm_in;
910 in.pcmType.bitPerSample = codec_data->info->params.pcmType.bitPerSample;
911 in.pcmType.nChannels = codec_data->info->params.pcmType.nChannels;
912 in.pcmType.sample_frequency = codec_data->info->params.pcmType.sample_frequency;
913
Benny Prijonob1339242008-08-21 20:58:55 +0000914 out.pBuffer = (char*)bits_out;
Nanang Izzuddin493a8db2008-08-15 13:17:39 +0000915
Benny Prijonoa4e7cdd2008-08-19 15:01:48 +0000916#if PJMEDIA_HAS_INTEL_IPP_CODEC_AMR
Nanang Izzuddin493a8db2008-08-15 13:17:39 +0000917 /* For AMR: reserve the first byte for frame info */
Nanang Izzuddindf361e02008-08-16 06:46:08 +0000918 if (pt == PJMEDIA_RTP_PT_AMR || pt == PJMEDIA_RTP_PT_AMRWB) {
Nanang Izzuddin493a8db2008-08-15 13:17:39 +0000919 ++out.pBuffer;
920 }
921#endif
922
Benny Prijonoa4e7cdd2008-08-19 15:01:48 +0000923 if (USC_NoError != ippc->fxns->Encode(codec_data->enc, &in, &out)) {
Nanang Izzuddin493a8db2008-08-15 13:17:39 +0000924 break;
925 }
926
Benny Prijonoa4e7cdd2008-08-19 15:01:48 +0000927#if PJMEDIA_HAS_INTEL_IPP_CODEC_AMR
928 /* For AMR: put info (frametype, degraded, last frame) in the
929 * first byte
930 */
Nanang Izzuddindf361e02008-08-16 06:46:08 +0000931 if (pt == PJMEDIA_RTP_PT_AMR || pt == PJMEDIA_RTP_PT_AMRWB) {
Nanang Izzuddin493a8db2008-08-15 13:17:39 +0000932 pj_uint8_t *info = (pj_uint8_t*)bits_out;
933
934 ++out.nbytes;
935
936 /* One byte AMR frame type & quality flag:
937 * bit 0-3 : frame type
938 * bit 6 : last frame flag
939 * bit 7 : quality flag
940 */
Nanang Izzuddindf361e02008-08-16 06:46:08 +0000941 if (out.frametype == 0 || out.frametype == 4 ||
942 (pt == PJMEDIA_RTP_PT_AMR && out.frametype == 5) ||
943 (pt == PJMEDIA_RTP_PT_AMRWB && out.frametype == 6))
944 {
945 /* Speech */
946 *info = (char)amr_get_mode(out.bitrate);
Nanang Izzuddin493a8db2008-08-15 13:17:39 +0000947 /* Degraded */
Nanang Izzuddindf361e02008-08-16 06:46:08 +0000948 if (out.frametype == 5 || out.frametype == 6)
Nanang Izzuddin493a8db2008-08-15 13:17:39 +0000949 *info |= 0x80;
Nanang Izzuddindf361e02008-08-16 06:46:08 +0000950 } else if (out.frametype == 1 || out.frametype == 2 ||
951 (pt == PJMEDIA_RTP_PT_AMR && out.frametype == 6) ||
952 (pt == PJMEDIA_RTP_PT_AMRWB && out.frametype == 7))
953 {
954 /* SID */
Benny Prijonoa4e7cdd2008-08-19 15:01:48 +0000955 *info = (pj_uint8_t)(pt == PJMEDIA_RTP_PT_AMRWB? 9 : 8);
Nanang Izzuddindf361e02008-08-16 06:46:08 +0000956 /* Degraded */
957 if (out.frametype == 6 || out.frametype == 7)
958 *info |= 0x80;
959 } else {
Nanang Izzuddin493a8db2008-08-15 13:17:39 +0000960 /* Untransmited */
961 *info = 15;
962 out.nbytes = 1;
Nanang Izzuddin493a8db2008-08-15 13:17:39 +0000963 }
964
965 /* Last frame flag */
966 if (nsamples == samples_per_frame)
967 *info |= 0x40;
968 }
Nanang Izzuddin7dd32682008-08-19 11:23:33 +0000969#endif
Nanang Izzuddin493a8db2008-08-15 13:17:39 +0000970
971 pcm_in += samples_per_frame;
972 nsamples -= samples_per_frame;
973 tx += out.nbytes;
974 bits_out += out.nbytes;
Nanang Izzuddin23a00b72008-08-25 13:58:25 +0000975
976#if PJMEDIA_HAS_INTEL_IPP_CODEC_G729
Nanang Izzuddine3a6fca2008-08-27 13:15:25 +0000977 if (pt == PJMEDIA_RTP_PT_G729) {
978 if (out.frametype == 1) {
979 /* SID */
980 break;
981 } else if (out.frametype == 0) {
982 /* Untransmitted */
983 tx -= out.nbytes;
984 break;
985 }
Nanang Izzuddin23a00b72008-08-25 13:58:25 +0000986 }
987#endif
988
Nanang Izzuddin493a8db2008-08-15 13:17:39 +0000989 }
Nanang Izzuddin493a8db2008-08-15 13:17:39 +0000990
Benny Prijonoa4e7cdd2008-08-19 15:01:48 +0000991 if (ippc->pack != NULL) {
992 ippc->pack(codec_data, output->buf, &tx, output_buf_len);
Nanang Izzuddin493a8db2008-08-15 13:17:39 +0000993 }
994
995 /* Check if we don't need to transmit the frame (DTX) */
996 if (tx == 0) {
997 output->buf = NULL;
998 output->size = 0;
999 output->timestamp.u64 = input->timestamp.u64;
1000 output->type = PJMEDIA_FRAME_TYPE_NONE;
1001 return PJ_SUCCESS;
1002 }
1003
1004 output->size = tx;
1005 output->type = PJMEDIA_FRAME_TYPE_AUDIO;
1006 output->timestamp = input->timestamp;
1007
1008 return PJ_SUCCESS;
1009}
1010
1011/*
1012 * Decode frame.
1013 */
1014static pj_status_t ipp_codec_decode( pjmedia_codec *codec,
1015 const struct pjmedia_frame *input,
1016 unsigned output_buf_len,
1017 struct pjmedia_frame *output)
1018{
1019 ipp_private_t *codec_data = (ipp_private_t*) codec->codec_data;
Benny Prijonoa4e7cdd2008-08-19 15:01:48 +00001020 struct ipp_codec *ippc = &ipp_codec[codec_data->codec_idx];
Nanang Izzuddin493a8db2008-08-15 13:17:39 +00001021 unsigned samples_per_frame;
1022 USC_PCMStream out;
1023 USC_Bitstream in;
1024 pj_uint8_t pt;
1025
Benny Prijonoa4e7cdd2008-08-19 15:01:48 +00001026 pt = ippc->pt;
1027 samples_per_frame = ippc->samples_per_frame;
Nanang Izzuddin493a8db2008-08-15 13:17:39 +00001028
1029 PJ_ASSERT_RETURN(output_buf_len >= samples_per_frame << 1,
1030 PJMEDIA_CODEC_EPCMTOOSHORT);
1031
1032 if (input->type == PJMEDIA_FRAME_TYPE_AUDIO) {
Benny Prijonoa4e7cdd2008-08-19 15:01:48 +00001033 if (ippc->predecode) {
1034 ippc->predecode(codec_data, input, &in);
Nanang Izzuddin493a8db2008-08-15 13:17:39 +00001035 } else {
1036 /* Most IPP codecs have frametype==0 for speech frame */
Nanang Izzuddindf361e02008-08-16 06:46:08 +00001037 in.pBuffer = (char*)input->buf;
1038 in.nbytes = input->size;
Nanang Izzuddin493a8db2008-08-15 13:17:39 +00001039 in.frametype = 0;
1040 in.bitrate = codec_data->info->params.modes.bitrate;
1041 }
1042
1043 out.pBuffer = output->buf;
Nanang Izzuddin493a8db2008-08-15 13:17:39 +00001044 }
Nanang Izzuddin493a8db2008-08-15 13:17:39 +00001045
1046 if (input->type != PJMEDIA_FRAME_TYPE_AUDIO ||
Benny Prijonoa4e7cdd2008-08-19 15:01:48 +00001047 USC_NoError != ippc->fxns->Decode(codec_data->dec, &in, &out))
Nanang Izzuddin493a8db2008-08-15 13:17:39 +00001048 {
1049 pjmedia_zero_samples((pj_int16_t*)output->buf, samples_per_frame);
1050 output->size = samples_per_frame << 1;
1051 output->timestamp.u64 = input->timestamp.u64;
1052 output->type = PJMEDIA_FRAME_TYPE_AUDIO;
1053 return PJ_SUCCESS;
1054 }
1055
Benny Prijonoa4e7cdd2008-08-19 15:01:48 +00001056#if PJMEDIA_HAS_INTEL_IPP_CODEC_G726
Nanang Izzuddin493a8db2008-08-15 13:17:39 +00001057 /* For G.726: amplify decoding result (USC G.726 encoder deamplified it) */
Nanang Izzuddin493a8db2008-08-15 13:17:39 +00001058 if (pt == PJMEDIA_RTP_PT_G726_16 || pt == PJMEDIA_RTP_PT_G726_24 ||
1059 pt == PJMEDIA_RTP_PT_G726_32 || pt == PJMEDIA_RTP_PT_G726_40)
1060 {
1061 unsigned i;
1062 pj_int16_t *s = (pj_int16_t*)output->buf;
1063
1064 for (i = 0; i < samples_per_frame; ++i)
1065 s[i] <<= 2;
1066 }
1067#endif
1068
1069 output->type = PJMEDIA_FRAME_TYPE_AUDIO;
1070 output->size = samples_per_frame << 1;
1071 output->timestamp.u64 = input->timestamp.u64;
1072
1073 /* Invoke external PLC if codec has no internal PLC */
1074 if (codec_data->plc && codec_data->plc_enabled)
1075 pjmedia_plc_save(codec_data->plc, (pj_int16_t*)output->buf);
1076
1077 return PJ_SUCCESS;
1078}
1079
1080/*
1081 * Recover lost frame.
1082 */
1083static pj_status_t ipp_codec_recover(pjmedia_codec *codec,
1084 unsigned output_buf_len,
1085 struct pjmedia_frame *output)
1086{
1087 ipp_private_t *codec_data = (ipp_private_t*) codec->codec_data;
Benny Prijonoa4e7cdd2008-08-19 15:01:48 +00001088 struct ipp_codec *ippc = &ipp_codec[codec_data->codec_idx];
Nanang Izzuddin493a8db2008-08-15 13:17:39 +00001089 unsigned samples_per_frame;
1090
1091 PJ_UNUSED_ARG(output_buf_len);
1092
Benny Prijonoa4e7cdd2008-08-19 15:01:48 +00001093 samples_per_frame = ippc->samples_per_frame;
Nanang Izzuddin493a8db2008-08-15 13:17:39 +00001094
1095 output->type = PJMEDIA_FRAME_TYPE_AUDIO;
1096 output->size = samples_per_frame << 1;
1097
1098 if (codec_data->plc_enabled) {
1099 if (codec_data->plc) {
1100 pjmedia_plc_generate(codec_data->plc, (pj_int16_t*)output->buf);
1101 } else {
1102 USC_PCMStream out;
1103 out.pBuffer = output->buf;
Benny Prijonoa4e7cdd2008-08-19 15:01:48 +00001104 ippc->fxns->Decode(codec_data->dec, NULL, &out);
Nanang Izzuddin493a8db2008-08-15 13:17:39 +00001105 }
1106 } else {
1107 pjmedia_zero_samples((pj_int16_t*)output->buf, samples_per_frame);
1108 }
1109
1110 return PJ_SUCCESS;
1111}
1112
Benny Prijonoa4e7cdd2008-08-19 15:01:48 +00001113#if PJMEDIA_HAS_INTEL_IPP_CODEC_G729
Nanang Izzuddin493a8db2008-08-15 13:17:39 +00001114
Nanang Izzuddindf361e02008-08-16 06:46:08 +00001115static void predecode_g729( ipp_private_t *codec_data,
1116 const pjmedia_frame *rtp_frame,
1117 USC_Bitstream *usc_frame)
Nanang Izzuddin493a8db2008-08-15 13:17:39 +00001118{
Nanang Izzuddindf361e02008-08-16 06:46:08 +00001119 switch (rtp_frame->size) {
Nanang Izzuddin493a8db2008-08-15 13:17:39 +00001120 case 2:
1121 /* SID */
Nanang Izzuddindf361e02008-08-16 06:46:08 +00001122 usc_frame->frametype = 1;
1123 usc_frame->bitrate = codec_data->info->params.modes.bitrate;
Nanang Izzuddin493a8db2008-08-15 13:17:39 +00001124 break;
1125 case 8:
1126 /* G729D */
Nanang Izzuddindf361e02008-08-16 06:46:08 +00001127 usc_frame->frametype = 2;
1128 usc_frame->bitrate = 6400;
Nanang Izzuddin493a8db2008-08-15 13:17:39 +00001129 break;
1130 case 10:
1131 /* G729 */
Nanang Izzuddindf361e02008-08-16 06:46:08 +00001132 usc_frame->frametype = 3;
1133 usc_frame->bitrate = 8000;
Nanang Izzuddin493a8db2008-08-15 13:17:39 +00001134 break;
1135 case 15:
1136 /* G729E */
Nanang Izzuddindf361e02008-08-16 06:46:08 +00001137 usc_frame->frametype = 4;
1138 usc_frame->bitrate = 11800;
Nanang Izzuddin493a8db2008-08-15 13:17:39 +00001139 break;
1140 default:
Nanang Izzuddindf361e02008-08-16 06:46:08 +00001141 usc_frame->frametype = 0;
1142 usc_frame->bitrate = 0;
Nanang Izzuddin493a8db2008-08-15 13:17:39 +00001143 break;
1144 }
Nanang Izzuddindf361e02008-08-16 06:46:08 +00001145
1146 usc_frame->pBuffer = rtp_frame->buf;
1147 usc_frame->nbytes = rtp_frame->size;
Nanang Izzuddin493a8db2008-08-15 13:17:39 +00001148}
1149
1150#endif /* PJMEDIA_HAS_INTEL_IPP_CODEC_G729 */
1151
1152
Benny Prijonoa4e7cdd2008-08-19 15:01:48 +00001153#if PJMEDIA_HAS_INTEL_IPP_CODEC_G723_1
Nanang Izzuddin493a8db2008-08-15 13:17:39 +00001154
Nanang Izzuddindf361e02008-08-16 06:46:08 +00001155static void predecode_g723( ipp_private_t *codec_data,
1156 const pjmedia_frame *rtp_frame,
1157 USC_Bitstream *usc_frame)
Nanang Izzuddin493a8db2008-08-15 13:17:39 +00001158{
1159 int i, HDR = 0;
Nanang Izzuddindf361e02008-08-16 06:46:08 +00001160 pj_uint8_t *f = (pj_uint8_t*)rtp_frame->buf;
Nanang Izzuddin493a8db2008-08-15 13:17:39 +00001161
Nanang Izzuddindf361e02008-08-16 06:46:08 +00001162 PJ_UNUSED_ARG(codec_data);
Nanang Izzuddin493a8db2008-08-15 13:17:39 +00001163
1164 for (i = 0; i < 2; ++i){
1165 int tmp;
1166 tmp = (f[0] >> (i & 0x7)) & 1;
1167 HDR += tmp << i ;
1168 }
1169
Nanang Izzuddindf361e02008-08-16 06:46:08 +00001170 usc_frame->pBuffer = rtp_frame->buf;
1171 usc_frame->nbytes = rtp_frame->size;
1172 usc_frame->bitrate = HDR == 0? 6300 : 5300;
1173 usc_frame->frametype = 0;
Nanang Izzuddin493a8db2008-08-15 13:17:39 +00001174}
1175
1176static pj_status_t parse_g723(ipp_private_t *codec_data, void *pkt,
1177 pj_size_t pkt_size, const pj_timestamp *ts,
1178 unsigned *frame_cnt, pjmedia_frame frames[])
1179{
1180 unsigned count = 0;
1181 pj_uint8_t *f = (pj_uint8_t*)pkt;
1182
1183 while (pkt_size && count < *frame_cnt) {
1184 int framesize, i, j;
1185 int HDR = 0;
1186
1187 for (i = 0; i < 2; ++i){
1188 j = (f[0] >> (i & 0x7)) & 1;
1189 HDR += j << i ;
1190 }
1191
1192 if (HDR == 0)
1193 framesize = 24;
1194 else if (HDR == 1)
1195 framesize = 20;
1196 else if (HDR == 2)
1197 framesize = 4;
1198 else if (HDR == 3)
1199 framesize = 1;
1200 else {
Benny Prijonoa4e7cdd2008-08-19 15:01:48 +00001201 pj_assert(!"Unknown G723.1 frametype, packet may be corrupted!");
Nanang Izzuddin493a8db2008-08-15 13:17:39 +00001202 return PJMEDIA_CODEC_EINMODE;
1203 }
1204
1205 frames[count].type = PJMEDIA_FRAME_TYPE_AUDIO;
1206 frames[count].buf = f;
1207 frames[count].size = framesize;
1208 frames[count].timestamp.u64 = ts->u64 + count *
1209 ipp_codec[codec_data->codec_idx].samples_per_frame;
1210
1211 f += framesize;
1212 pkt_size -= framesize;
1213
1214 ++count;
1215 }
1216
1217 *frame_cnt = count;
1218 return PJ_SUCCESS;
1219}
1220
Benny Prijonoa4e7cdd2008-08-19 15:01:48 +00001221#endif /* PJMEDIA_HAS_INTEL_IPP_CODEC_G723_1 */
Nanang Izzuddin493a8db2008-08-15 13:17:39 +00001222
1223
Benny Prijonoa4e7cdd2008-08-19 15:01:48 +00001224#if PJMEDIA_HAS_INTEL_IPP_CODEC_AMR
Nanang Izzuddin493a8db2008-08-15 13:17:39 +00001225
1226/* AMR bitstream sensitivity order map */
1227static pj_int16_t AMRNB_ordermap122[244] =
1228{
Benny Prijonoa4e7cdd2008-08-19 15:01:48 +00001229 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,
1230 10, 11, 12, 13, 14, 23, 15, 16, 17, 18,
1231 19, 20, 21, 22, 24, 25, 26, 27, 28, 38,
1232 141, 39, 142, 40, 143, 41, 144, 42, 145, 43,
1233 146, 44, 147, 45, 148, 46, 149, 47, 97, 150,
1234 200, 48, 98, 151, 201, 49, 99, 152, 202, 86,
1235 136, 189, 239, 87, 137, 190, 240, 88, 138, 191,
1236 241, 91, 194, 92, 195, 93, 196, 94, 197, 95,
1237 198, 29, 30, 31, 32, 33, 34, 35, 50, 100,
1238 153, 203, 89, 139, 192, 242, 51, 101, 154, 204,
1239 55, 105, 158, 208, 90, 140, 193, 243, 59, 109,
1240 162, 212, 63, 113, 166, 216, 67, 117, 170, 220,
1241 36, 37, 54, 53, 52, 58, 57, 56, 62, 61,
1242 60, 66, 65, 64, 70, 69, 68, 104, 103, 102,
1243 108, 107, 106, 112, 111, 110, 116, 115, 114, 120,
1244 119, 118, 157, 156, 155, 161, 160, 159, 165, 164,
1245 163, 169, 168, 167, 173, 172, 171, 207, 206, 205,
1246 211, 210, 209, 215, 214, 213, 219, 218, 217, 223,
1247 222, 221, 73, 72, 71, 76, 75, 74, 79, 78,
1248 77, 82, 81, 80, 85, 84, 83, 123, 122, 121,
1249 126, 125, 124, 129, 128, 127, 132, 131, 130, 135,
1250 134, 133, 176, 175, 174, 179, 178, 177, 182, 181,
1251 180, 185, 184, 183, 188, 187, 186, 226, 225, 224,
1252 229, 228, 227, 232, 231, 230, 235, 234, 233, 238,
1253 237, 236, 96, 199
Nanang Izzuddin493a8db2008-08-15 13:17:39 +00001254};
1255
1256static pj_int16_t AMRNB_ordermap102[204] =
1257{
Benny Prijonoa4e7cdd2008-08-19 15:01:48 +00001258 7, 6, 5, 4, 3, 2, 1, 0, 16, 15,
1259 14, 13, 12, 11, 10, 9, 8, 26, 27, 28,
1260 29, 30, 31, 115, 116, 117, 118, 119, 120, 72,
1261 73, 161, 162, 65, 68, 69, 108, 111, 112, 154,
Nanang Izzuddin493a8db2008-08-15 13:17:39 +00001262 157, 158, 197, 200, 201, 32, 33, 121, 122, 74,
Benny Prijonoa4e7cdd2008-08-19 15:01:48 +00001263 75, 163, 164, 66, 109, 155, 198, 19, 23, 21,
1264 22, 18, 17, 20, 24, 25, 37, 36, 35, 34,
1265 80, 79, 78, 77, 126, 125, 124, 123, 169, 168,
Nanang Izzuddin493a8db2008-08-15 13:17:39 +00001266 167, 166, 70, 67, 71, 113, 110, 114, 159, 156,
1267 160, 202, 199, 203, 76, 165, 81, 82, 92, 91,
Benny Prijonoa4e7cdd2008-08-19 15:01:48 +00001268 93, 83, 95, 85, 84, 94, 101, 102, 96, 104,
1269 86, 103, 87, 97, 127, 128, 138, 137, 139, 129,
Nanang Izzuddin493a8db2008-08-15 13:17:39 +00001270 141, 131, 130, 140, 147, 148, 142, 150, 132, 149,
1271 133, 143, 170, 171, 181, 180, 182, 172, 184, 174,
1272 173, 183, 190, 191, 185, 193, 175, 192, 176, 186,
Benny Prijonoa4e7cdd2008-08-19 15:01:48 +00001273 38, 39, 49, 48, 50, 40, 52, 42, 41, 51,
1274 58, 59, 53, 61, 43, 60, 44, 54, 194, 179,
Nanang Izzuddin493a8db2008-08-15 13:17:39 +00001275 189, 196, 177, 195, 178, 187, 188, 151, 136, 146,
1276 153, 134, 152, 135, 144, 145, 105, 90, 100, 107,
Benny Prijonoa4e7cdd2008-08-19 15:01:48 +00001277 88, 106, 89, 98, 99, 62, 47, 57, 64, 45,
1278 63, 46, 55, 56
Nanang Izzuddin493a8db2008-08-15 13:17:39 +00001279};
1280
1281static pj_int16_t AMRNB_ordermap795[159] =
1282{
Benny Prijonoa4e7cdd2008-08-19 15:01:48 +00001283 8, 7, 6, 5, 4, 3, 2, 14, 16, 9,
1284 10, 12, 13, 15, 11, 17, 20, 22, 24, 23,
1285 19, 18, 21, 56, 88, 122, 154, 57, 89, 123,
1286 155, 58, 90, 124, 156, 52, 84, 118, 150, 53,
1287 85, 119, 151, 27, 93, 28, 94, 29, 95, 30,
1288 96, 31, 97, 61, 127, 62, 128, 63, 129, 59,
1289 91, 125, 157, 32, 98, 64, 130, 1, 0, 25,
1290 26, 33, 99, 34, 100, 65, 131, 66, 132, 54,
1291 86, 120, 152, 60, 92, 126, 158, 55, 87, 121,
1292 153, 117, 116, 115, 46, 78, 112, 144, 43, 75,
1293 109, 141, 40, 72, 106, 138, 36, 68, 102, 134,
1294 114, 149, 148, 147, 146, 83, 82, 81, 80, 51,
1295 50, 49, 48, 47, 45, 44, 42, 39, 35, 79,
1296 77, 76, 74, 71, 67, 113, 111, 110, 108, 105,
1297 101, 145, 143, 142, 140, 137, 133, 41, 73, 107,
1298 139, 37, 69, 103, 135, 38, 70, 104, 136
Nanang Izzuddin493a8db2008-08-15 13:17:39 +00001299
1300};
1301
1302static pj_int16_t AMRNB_ordermap74[148] =
1303{
Benny Prijonoa4e7cdd2008-08-19 15:01:48 +00001304 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,
1305 10, 11, 12, 13, 14, 15, 16, 26, 87, 27,
1306 88, 28, 89, 29, 90, 30, 91, 51, 80, 112,
Nanang Izzuddin493a8db2008-08-15 13:17:39 +00001307 141, 52, 81, 113, 142, 54, 83, 115, 144, 55,
Benny Prijonoa4e7cdd2008-08-19 15:01:48 +00001308 84, 116, 145, 58, 119, 59, 120, 21, 22, 23,
1309 17, 18, 19, 31, 60, 92, 121, 56, 85, 117,
Nanang Izzuddin493a8db2008-08-15 13:17:39 +00001310 146, 20, 24, 25, 50, 79, 111, 140, 57, 86,
1311 118, 147, 49, 78, 110, 139, 48, 77, 53, 82,
1312 114, 143, 109, 138, 47, 76, 108, 137, 32, 33,
Benny Prijonoa4e7cdd2008-08-19 15:01:48 +00001313 61, 62, 93, 94, 122, 123, 41, 42, 43, 44,
1314 45, 46, 70, 71, 72, 73, 74, 75, 102, 103,
Nanang Izzuddin493a8db2008-08-15 13:17:39 +00001315 104, 105, 106, 107, 131, 132, 133, 134, 135, 136,
Benny Prijonoa4e7cdd2008-08-19 15:01:48 +00001316 34, 63, 95, 124, 35, 64, 96, 125, 36, 65,
1317 97, 126, 37, 66, 98, 127, 38, 67, 99, 128,
1318 39, 68, 100, 129, 40, 69, 101, 130
Nanang Izzuddin493a8db2008-08-15 13:17:39 +00001319};
1320
1321static pj_int16_t AMRNB_ordermap67[134] =
1322{
Benny Prijonoa4e7cdd2008-08-19 15:01:48 +00001323 0, 1, 4, 3, 5, 6, 13, 7, 2, 8,
1324 9, 11, 15, 12, 14, 10, 28, 82, 29, 83,
1325 27, 81, 26, 80, 30, 84, 16, 55, 109, 56,
1326 110, 31, 85, 57, 111, 48, 73, 102, 127, 32,
1327 86, 51, 76, 105, 130, 52, 77, 106, 131, 58,
1328 112, 33, 87, 19, 23, 53, 78, 107, 132, 21,
1329 22, 18, 17, 20, 24, 25, 50, 75, 104, 129,
1330 47, 72, 101, 126, 54, 79, 108, 133, 46, 71,
1331 100, 125, 128, 103, 74, 49, 45, 70, 99, 124,
1332 42, 67, 96, 121, 39, 64, 93, 118, 38, 63,
1333 92, 117, 35, 60, 89, 114, 34, 59, 88, 113,
1334 44, 69, 98, 123, 43, 68, 97, 122, 41, 66,
1335 95, 120, 40, 65, 94, 119, 37, 62, 91, 116,
1336 36, 61, 90, 115
Nanang Izzuddin493a8db2008-08-15 13:17:39 +00001337};
1338
1339static pj_int16_t AMRNB_ordermap59[118] =
1340{
Benny Prijonoa4e7cdd2008-08-19 15:01:48 +00001341 0, 1, 4, 5, 3, 6, 7, 2, 13, 15,
1342 8, 9, 11, 12, 14, 10, 16, 28, 74, 29,
1343 75, 27, 73, 26, 72, 30, 76, 51, 97, 50,
1344 71, 96, 117, 31, 77, 52, 98, 49, 70, 95,
1345 116, 53, 99, 32, 78, 33, 79, 48, 69, 94,
1346 115, 47, 68, 93, 114, 46, 67, 92, 113, 19,
1347 21, 23, 22, 18, 17, 20, 24, 111, 43, 89,
1348 110, 64, 65, 44, 90, 25, 45, 66, 91, 112,
1349 54, 100, 40, 61, 86, 107, 39, 60, 85, 106,
1350 36, 57, 82, 103, 35, 56, 81, 102, 34, 55,
1351 80, 101, 42, 63, 88, 109, 41, 62, 87, 108,
1352 38, 59, 84, 105, 37, 58, 83, 104
Nanang Izzuddin493a8db2008-08-15 13:17:39 +00001353};
1354
1355static pj_int16_t AMRNB_ordermap515[103] =
1356{
Benny Prijonoa4e7cdd2008-08-19 15:01:48 +00001357 7, 6, 5, 4, 3, 2, 1, 0, 15, 14,
1358 13, 12, 11, 10, 9, 8, 23, 24, 25, 26,
1359 27, 46, 65, 84, 45, 44, 43, 64, 63, 62,
1360 83, 82, 81, 102, 101, 100, 42, 61, 80, 99,
1361 28, 47, 66, 85, 18, 41, 60, 79, 98, 29,
1362 48, 67, 17, 20, 22, 40, 59, 78, 97, 21,
1363 30, 49, 68, 86, 19, 16, 87, 39, 38, 58,
1364 57, 77, 35, 54, 73, 92, 76, 96, 95, 36,
1365 55, 74, 93, 32, 51, 33, 52, 70, 71, 89,
1366 90, 31, 50, 69, 88, 37, 56, 75, 94, 34,
1367 53, 72, 91
Nanang Izzuddin493a8db2008-08-15 13:17:39 +00001368};
1369
1370static pj_int16_t AMRNB_ordermap475[95] =
1371{
Benny Prijonoa4e7cdd2008-08-19 15:01:48 +00001372 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,
1373 10, 11, 12, 13, 14, 15, 23, 24, 25, 26,
1374 27, 28, 48, 49, 61, 62, 82, 83, 47, 46,
1375 45, 44, 81, 80, 79, 78, 17, 18, 20, 22,
1376 77, 76, 75, 74, 29, 30, 43, 42, 41, 40,
1377 38, 39, 16, 19, 21, 50, 51, 59, 60, 63,
1378 64, 72, 73, 84, 85, 93, 94, 32, 33, 35,
1379 36, 53, 54, 56, 57, 66, 67, 69, 70, 87,
1380 88, 90, 91, 34, 55, 68, 89, 37, 58, 71,
1381 92, 31, 52, 65, 86
Nanang Izzuddin493a8db2008-08-15 13:17:39 +00001382};
1383
1384static pj_int16_t *AMRNB_ordermaps[8] =
1385{
1386 AMRNB_ordermap475,
1387 AMRNB_ordermap515,
1388 AMRNB_ordermap59,
1389 AMRNB_ordermap67,
1390 AMRNB_ordermap74,
1391 AMRNB_ordermap795,
1392 AMRNB_ordermap102,
1393 AMRNB_ordermap122
1394};
1395
1396static pj_int16_t AMRWB_ordermap_660[] =
1397{
Benny Prijonoa4e7cdd2008-08-19 15:01:48 +00001398 0, 5, 6, 7, 61, 84, 107, 130, 62, 85,
1399 8, 4, 37, 38, 39, 40, 58, 81, 104, 127,
1400 60, 83, 106, 129, 108, 131, 128, 41, 42, 80,
1401 126, 1, 3, 57, 103, 82, 105, 59, 2, 63,
1402 109, 110, 86, 19, 22, 23, 64, 87, 18, 20,
1403 21, 17, 13, 88, 43, 89, 65, 111, 14, 24,
1404 25, 26, 27, 28, 15, 16, 44, 90, 66, 112,
1405 9, 11, 10, 12, 67, 113, 29, 30, 31, 32,
1406 34, 33, 35, 36, 45, 51, 68, 74, 91, 97,
1407 114, 120, 46, 69, 92, 115, 52, 75, 98, 121,
1408 47, 70, 93, 116, 53, 76, 99, 122, 48, 71,
1409 94, 117, 54, 77, 100, 123, 49, 72, 95, 118,
1410 55, 78, 101, 124, 50, 73, 96, 119, 56, 79,
Nanang Izzuddin493a8db2008-08-15 13:17:39 +00001411 102, 125
1412};
1413
1414static pj_int16_t AMRWB_ordermap_885[] =
1415{
Benny Prijonoa4e7cdd2008-08-19 15:01:48 +00001416 0, 4, 6, 7, 5, 3, 47, 48, 49, 112,
Nanang Izzuddin493a8db2008-08-15 13:17:39 +00001417 113, 114, 75, 106, 140, 171, 80, 111, 145, 176,
Benny Prijonoa4e7cdd2008-08-19 15:01:48 +00001418 77, 108, 142, 173, 78, 109, 143, 174, 79, 110,
Nanang Izzuddin493a8db2008-08-15 13:17:39 +00001419 144, 175, 76, 107, 141, 172, 50, 115, 51, 2,
Benny Prijonoa4e7cdd2008-08-19 15:01:48 +00001420 1, 81, 116, 146, 19, 21, 12, 17, 18, 20,
1421 16, 25, 13, 10, 14, 24, 23, 22, 26, 8,
1422 15, 52, 117, 31, 82, 147, 9, 33, 11, 83,
Nanang Izzuddin493a8db2008-08-15 13:17:39 +00001423 148, 53, 118, 28, 27, 84, 149, 34, 35, 29,
Benny Prijonoa4e7cdd2008-08-19 15:01:48 +00001424 46, 32, 30, 54, 119, 37, 36, 39, 38, 40,
1425 85, 150, 41, 42, 43, 44, 45, 55, 60, 65,
1426 70, 86, 91, 96, 101, 120, 125, 130, 135, 151,
Nanang Izzuddin493a8db2008-08-15 13:17:39 +00001427 156, 161, 166, 56, 87, 121, 152, 61, 92, 126,
1428 157, 66, 97, 131, 162, 71, 102, 136, 167, 57,
Benny Prijonoa4e7cdd2008-08-19 15:01:48 +00001429 88, 122, 153, 62, 93, 127, 158, 67, 98, 132,
Nanang Izzuddin493a8db2008-08-15 13:17:39 +00001430 163, 72, 103, 137, 168, 58, 89, 123, 154, 63,
Benny Prijonoa4e7cdd2008-08-19 15:01:48 +00001431 94, 128, 159, 68, 99, 133, 164, 73, 104, 138,
Nanang Izzuddin493a8db2008-08-15 13:17:39 +00001432 169, 59, 90, 124, 155, 64, 95, 129, 160, 69,
1433 100, 134, 165, 74, 105, 139, 170
1434};
1435
1436static pj_int16_t AMRWB_ordermap_1265[] =
1437{
Benny Prijonoa4e7cdd2008-08-19 15:01:48 +00001438 0, 4, 6, 93, 143, 196, 246, 7, 5, 3,
1439 47, 48, 49, 50, 51, 150, 151, 152, 153, 154,
1440 94, 144, 197, 247, 99, 149, 202, 252, 96, 146,
Nanang Izzuddin493a8db2008-08-15 13:17:39 +00001441 199, 249, 97, 147, 200, 250, 100, 203, 98, 148,
1442 201, 251, 95, 145, 198, 248, 52, 2, 1, 101,
1443 204, 155, 19, 21, 12, 17, 18, 20, 16, 25,
Benny Prijonoa4e7cdd2008-08-19 15:01:48 +00001444 13, 10, 14, 24, 23, 22, 26, 8, 15, 53,
Nanang Izzuddin493a8db2008-08-15 13:17:39 +00001445 156, 31, 102, 205, 9, 33, 11, 103, 206, 54,
1446 157, 28, 27, 104, 207, 34, 35, 29, 46, 32,
Benny Prijonoa4e7cdd2008-08-19 15:01:48 +00001447 30, 55, 158, 37, 36, 39, 38, 40, 105, 208,
1448 41, 42, 43, 44, 45, 56, 106, 159, 209, 57,
1449 66, 75, 84, 107, 116, 125, 134, 160, 169, 178,
Nanang Izzuddin493a8db2008-08-15 13:17:39 +00001450 187, 210, 219, 228, 237, 58, 108, 161, 211, 62,
1451 112, 165, 215, 67, 117, 170, 220, 71, 121, 174,
1452 224, 76, 126, 179, 229, 80, 130, 183, 233, 85,
1453 135, 188, 238, 89, 139, 192, 242, 59, 109, 162,
1454 212, 63, 113, 166, 216, 68, 118, 171, 221, 72,
1455 122, 175, 225, 77, 127, 180, 230, 81, 131, 184,
1456 234, 86, 136, 189, 239, 90, 140, 193, 243, 60,
1457 110, 163, 213, 64, 114, 167, 217, 69, 119, 172,
1458 222, 73, 123, 176, 226, 78, 128, 181, 231, 82,
1459 132, 185, 235, 87, 137, 190, 240, 91, 141, 194,
1460 244, 61, 111, 164, 214, 65, 115, 168, 218, 70,
1461 120, 173, 223, 74, 124, 177, 227, 79, 129, 182,
1462 232, 83, 133, 186, 236, 88, 138, 191, 241, 92,
1463 142, 195, 245
1464};
1465
1466static pj_int16_t AMRWB_ordermap_1425[] =
1467{
Benny Prijonoa4e7cdd2008-08-19 15:01:48 +00001468 0, 4, 6, 101, 159, 220, 278, 7, 5, 3,
1469 47, 48, 49, 50, 51, 166, 167, 168, 169, 170,
Nanang Izzuddin493a8db2008-08-15 13:17:39 +00001470 102, 160, 221, 279, 107, 165, 226, 284, 104, 162,
1471 223, 281, 105, 163, 224, 282, 108, 227, 106, 164,
1472 225, 283, 103, 161, 222, 280, 52, 2, 1, 109,
1473 228, 171, 19, 21, 12, 17, 18, 20, 16, 25,
Benny Prijonoa4e7cdd2008-08-19 15:01:48 +00001474 13, 10, 14, 24, 23, 22, 26, 8, 15, 53,
Nanang Izzuddin493a8db2008-08-15 13:17:39 +00001475 172, 31, 110, 229, 9, 33, 11, 111, 230, 54,
1476 173, 28, 27, 112, 231, 34, 35, 29, 46, 32,
Benny Prijonoa4e7cdd2008-08-19 15:01:48 +00001477 30, 55, 174, 37, 36, 39, 38, 40, 113, 232,
1478 41, 42, 43, 44, 45, 56, 114, 175, 233, 62,
Nanang Izzuddin493a8db2008-08-15 13:17:39 +00001479 120, 181, 239, 75, 133, 194, 252, 57, 115, 176,
1480 234, 63, 121, 182, 240, 70, 128, 189, 247, 76,
1481 134, 195, 253, 83, 141, 202, 260, 92, 150, 211,
1482 269, 84, 142, 203, 261, 93, 151, 212, 270, 85,
1483 143, 204, 262, 94, 152, 213, 271, 86, 144, 205,
1484 263, 95, 153, 214, 272, 64, 122, 183, 241, 77,
1485 135, 196, 254, 65, 123, 184, 242, 78, 136, 197,
1486 255, 87, 145, 206, 264, 96, 154, 215, 273, 58,
1487 116, 177, 235, 66, 124, 185, 243, 71, 129, 190,
1488 248, 79, 137, 198, 256, 88, 146, 207, 265, 97,
1489 155, 216, 274, 59, 117, 178, 236, 67, 125, 186,
1490 244, 72, 130, 191, 249, 80, 138, 199, 257, 89,
1491 147, 208, 266, 98, 156, 217, 275, 60, 118, 179,
1492 237, 68, 126, 187, 245, 73, 131, 192, 250, 81,
1493 139, 200, 258, 90, 148, 209, 267, 99, 157, 218,
1494 276, 61, 119, 180, 238, 69, 127, 188, 246, 74,
1495 132, 193, 251, 82, 140, 201, 259, 91, 149, 210,
1496 268, 100, 158, 219, 277
1497};
1498
1499static pj_int16_t AMRWB_ordermap_1585[] =
1500{
Benny Prijonoa4e7cdd2008-08-19 15:01:48 +00001501 0, 4, 6, 109, 175, 244, 310, 7, 5, 3,
1502 47, 48, 49, 50, 51, 182, 183, 184, 185, 186,
Nanang Izzuddin493a8db2008-08-15 13:17:39 +00001503 110, 176, 245, 311, 115, 181, 250, 316, 112, 178,
1504 247, 313, 113, 179, 248, 314, 116, 251, 114, 180,
1505 249, 315, 111, 177, 246, 312, 52, 2, 1, 117,
1506 252, 187, 19, 21, 12, 17, 18, 20, 16, 25,
Benny Prijonoa4e7cdd2008-08-19 15:01:48 +00001507 13, 10, 14, 24, 23, 22, 26, 8, 15, 53,
Nanang Izzuddin493a8db2008-08-15 13:17:39 +00001508 188, 31, 118, 253, 9, 33, 11, 119, 254, 54,
1509 189, 28, 27, 120, 255, 34, 35, 29, 46, 32,
Benny Prijonoa4e7cdd2008-08-19 15:01:48 +00001510 30, 55, 190, 37, 36, 39, 38, 40, 121, 256,
1511 41, 42, 43, 44, 45, 56, 122, 191, 257, 63,
Nanang Izzuddin493a8db2008-08-15 13:17:39 +00001512 129, 198, 264, 76, 142, 211, 277, 89, 155, 224,
1513 290, 102, 168, 237, 303, 57, 123, 192, 258, 70,
1514 136, 205, 271, 83, 149, 218, 284, 96, 162, 231,
1515 297, 62, 128, 197, 263, 75, 141, 210, 276, 88,
1516 154, 223, 289, 101, 167, 236, 302, 58, 124, 193,
1517 259, 71, 137, 206, 272, 84, 150, 219, 285, 97,
1518 163, 232, 298, 59, 125, 194, 260, 64, 130, 199,
1519 265, 67, 133, 202, 268, 72, 138, 207, 273, 77,
1520 143, 212, 278, 80, 146, 215, 281, 85, 151, 220,
1521 286, 90, 156, 225, 291, 93, 159, 228, 294, 98,
1522 164, 233, 299, 103, 169, 238, 304, 106, 172, 241,
1523 307, 60, 126, 195, 261, 65, 131, 200, 266, 68,
1524 134, 203, 269, 73, 139, 208, 274, 78, 144, 213,
1525 279, 81, 147, 216, 282, 86, 152, 221, 287, 91,
1526 157, 226, 292, 94, 160, 229, 295, 99, 165, 234,
1527 300, 104, 170, 239, 305, 107, 173, 242, 308, 61,
1528 127, 196, 262, 66, 132, 201, 267, 69, 135, 204,
1529 270, 74, 140, 209, 275, 79, 145, 214, 280, 82,
1530 148, 217, 283, 87, 153, 222, 288, 92, 158, 227,
1531 293, 95, 161, 230, 296, 100, 166, 235, 301, 105,
1532 171, 240, 306, 108, 174, 243, 309
1533};
1534
1535static pj_int16_t AMRWB_ordermap_1825[] =
1536{
Benny Prijonoa4e7cdd2008-08-19 15:01:48 +00001537 0, 4, 6, 121, 199, 280, 358, 7, 5, 3,
1538 47, 48, 49, 50, 51, 206, 207, 208, 209, 210,
Nanang Izzuddin493a8db2008-08-15 13:17:39 +00001539 122, 200, 281, 359, 127, 205, 286, 364, 124, 202,
1540 283, 361, 125, 203, 284, 362, 128, 287, 126, 204,
1541 285, 363, 123, 201, 282, 360, 52, 2, 1, 129,
1542 288, 211, 19, 21, 12, 17, 18, 20, 16, 25,
Benny Prijonoa4e7cdd2008-08-19 15:01:48 +00001543 13, 10, 14, 24, 23, 22, 26, 8, 15, 53,
Nanang Izzuddin493a8db2008-08-15 13:17:39 +00001544 212, 31, 130, 289, 9, 33, 11, 131, 290, 54,
1545 213, 28, 27, 132, 291, 34, 35, 29, 46, 32,
Benny Prijonoa4e7cdd2008-08-19 15:01:48 +00001546 30, 55, 214, 37, 36, 39, 38, 40, 133, 292,
1547 41, 42, 43, 44, 45, 56, 134, 215, 293, 198,
Nanang Izzuddin493a8db2008-08-15 13:17:39 +00001548 299, 136, 120, 138, 60, 279, 58, 62, 357, 139,
1549 140, 295, 156, 57, 219, 297, 63, 217, 137, 170,
1550 300, 222, 64, 106, 61, 78, 294, 92, 142, 141,
1551 135, 221, 296, 301, 343, 59, 298, 184, 329, 315,
1552 220, 216, 265, 251, 218, 237, 352, 223, 157, 86,
1553 171, 87, 164, 351, 111, 302, 65, 178, 115, 323,
Benny Prijonoa4e7cdd2008-08-19 15:01:48 +00001554 72, 192, 101, 179, 93, 73, 193, 151, 337, 309,
Nanang Izzuddin493a8db2008-08-15 13:17:39 +00001555 143, 274, 69, 324, 165, 150, 97, 338, 110, 310,
1556 330, 273, 68, 107, 175, 245, 114, 79, 113, 189,
1557 246, 259, 174, 71, 185, 96, 344, 100, 322, 83,
1558 334, 316, 333, 252, 161, 348, 147, 82, 269, 232,
1559 260, 308, 353, 347, 163, 231, 306, 320, 188, 270,
1560 146, 177, 266, 350, 256, 85, 149, 116, 191, 160,
1561 238, 258, 336, 305, 255, 88, 224, 99, 339, 230,
1562 228, 227, 272, 242, 241, 319, 233, 311, 102, 74,
1563 180, 275, 66, 194, 152, 325, 172, 247, 244, 261,
1564 117, 158, 166, 354, 75, 144, 108, 312, 94, 186,
1565 303, 80, 234, 89, 195, 112, 340, 181, 345, 317,
1566 326, 276, 239, 167, 118, 313, 70, 355, 327, 253,
1567 190, 176, 271, 104, 98, 153, 103, 90, 76, 267,
1568 277, 248, 225, 262, 182, 84, 154, 235, 335, 168,
1569 331, 196, 341, 249, 162, 307, 148, 349, 263, 321,
1570 257, 243, 229, 356, 159, 119, 67, 187, 173, 145,
1571 240, 77, 304, 332, 314, 342, 109, 254, 81, 278,
1572 105, 91, 346, 318, 183, 250, 197, 328, 95, 155,
1573 169, 268, 226, 236, 264
1574};
1575
1576static pj_int16_t AMRWB_ordermap_1985[] =
1577{
Benny Prijonoa4e7cdd2008-08-19 15:01:48 +00001578 0, 4, 6, 129, 215, 304, 390, 7, 5, 3,
1579 47, 48, 49, 50, 51, 222, 223, 224, 225, 226,
Nanang Izzuddin493a8db2008-08-15 13:17:39 +00001580 130, 216, 305, 391, 135, 221, 310, 396, 132, 218,
1581 307, 393, 133, 219, 308, 394, 136, 311, 134, 220,
1582 309, 395, 131, 217, 306, 392, 52, 2, 1, 137,
1583 312, 227, 19, 21, 12, 17, 18, 20, 16, 25,
Benny Prijonoa4e7cdd2008-08-19 15:01:48 +00001584 13, 10, 14, 24, 23, 22, 26, 8, 15, 53,
Nanang Izzuddin493a8db2008-08-15 13:17:39 +00001585 228, 31, 138, 313, 9, 33, 11, 139, 314, 54,
1586 229, 28, 27, 140, 315, 34, 35, 29, 46, 32,
Benny Prijonoa4e7cdd2008-08-19 15:01:48 +00001587 30, 55, 230, 37, 36, 39, 38, 40, 141, 316,
1588 41, 42, 43, 44, 45, 56, 142, 231, 317, 63,
1589 73, 92, 340, 82, 324, 149, 353, 159, 334, 165,
Nanang Izzuddin493a8db2008-08-15 13:17:39 +00001590 338, 178, 163, 254, 77, 168, 257, 153, 343, 57,
1591 248, 238, 79, 252, 166, 67, 80, 201, 101, 267,
1592 143, 164, 341, 255, 339, 187, 376, 318, 78, 328,
1593 362, 115, 232, 242, 253, 290, 276, 62, 58, 158,
Benny Prijonoa4e7cdd2008-08-19 15:01:48 +00001594 68, 93, 179, 319, 148, 169, 154, 72, 385, 329,
Nanang Izzuddin493a8db2008-08-15 13:17:39 +00001595 333, 344, 102, 83, 144, 233, 323, 124, 243, 192,
1596 354, 237, 64, 247, 202, 209, 150, 116, 335, 268,
1597 239, 299, 188, 196, 298, 94, 195, 258, 123, 363,
1598 384, 109, 325, 371, 170, 370, 84, 110, 295, 180,
Benny Prijonoa4e7cdd2008-08-19 15:01:48 +00001599 74, 210, 191, 106, 291, 205, 367, 381, 377, 206,
Nanang Izzuddin493a8db2008-08-15 13:17:39 +00001600 355, 122, 119, 120, 383, 160, 105, 108, 277, 380,
1601 294, 284, 285, 345, 208, 269, 249, 366, 386, 300,
1602 297, 259, 125, 369, 197, 97, 194, 286, 211, 281,
1603 280, 183, 372, 87, 155, 283, 59, 348, 327, 184,
Benny Prijonoa4e7cdd2008-08-19 15:01:48 +00001604 76, 111, 330, 203, 349, 69, 98, 152, 145, 189,
1605 66, 320, 337, 173, 358, 251, 198, 174, 263, 262,
Nanang Izzuddin493a8db2008-08-15 13:17:39 +00001606 126, 241, 193, 88, 388, 117, 95, 387, 112, 359,
1607 287, 244, 103, 272, 301, 171, 162, 234, 273, 127,
1608 373, 181, 292, 85, 378, 302, 121, 107, 364, 346,
1609 356, 212, 278, 213, 65, 382, 288, 207, 113, 175,
Benny Prijonoa4e7cdd2008-08-19 15:01:48 +00001610 99, 296, 374, 368, 199, 260, 185, 336, 331, 161,
Nanang Izzuddin493a8db2008-08-15 13:17:39 +00001611 270, 264, 250, 240, 75, 350, 151, 60, 89, 321,
1612 156, 274, 360, 326, 70, 282, 167, 146, 352, 81,
Benny Prijonoa4e7cdd2008-08-19 15:01:48 +00001613 91, 389, 266, 245, 177, 235, 190, 256, 204, 342,
Nanang Izzuddin493a8db2008-08-15 13:17:39 +00001614 128, 118, 303, 104, 379, 182, 114, 375, 200, 96,
1615 293, 172, 214, 365, 279, 86, 289, 351, 347, 357,
1616 261, 186, 176, 271, 90, 100, 147, 322, 275, 361,
Benny Prijonoa4e7cdd2008-08-19 15:01:48 +00001617 71, 332, 61, 265, 157, 246, 236
Nanang Izzuddin493a8db2008-08-15 13:17:39 +00001618};
1619
1620static pj_int16_t AMRWB_ordermap_2305[] =
1621{
Benny Prijonoa4e7cdd2008-08-19 15:01:48 +00001622 0, 4, 6, 145, 247, 352, 454, 7, 5, 3,
1623 47, 48, 49, 50, 51, 254, 255, 256, 257, 258,
Nanang Izzuddin493a8db2008-08-15 13:17:39 +00001624 146, 248, 353, 455, 151, 253, 358, 460, 148, 250,
1625 355, 457, 149, 251, 356, 458, 152, 359, 150, 252,
1626 357, 459, 147, 249, 354, 456, 52, 2, 1, 153,
1627 360, 259, 19, 21, 12, 17, 18, 20, 16, 25,
Benny Prijonoa4e7cdd2008-08-19 15:01:48 +00001628 13, 10, 14, 24, 23, 22, 26, 8, 15, 53,
Nanang Izzuddin493a8db2008-08-15 13:17:39 +00001629 260, 31, 154, 361, 9, 33, 11, 155, 362, 54,
1630 261, 28, 27, 156, 363, 34, 35, 29, 46, 32,
Benny Prijonoa4e7cdd2008-08-19 15:01:48 +00001631 30, 55, 262, 37, 36, 39, 38, 40, 157, 364,
1632 41, 42, 43, 44, 45, 56, 158, 263, 365, 181,
Nanang Izzuddin493a8db2008-08-15 13:17:39 +00001633 192, 170, 79, 57, 399, 90, 159, 297, 377, 366,
1634 275, 68, 183, 388, 286, 194, 299, 92, 70, 182,
1635 401, 172, 59, 91, 58, 400, 368, 161, 81, 160,
1636 264, 171, 80, 389, 390, 378, 379, 193, 298, 69,
1637 266, 265, 367, 277, 288, 276, 287, 184, 60, 195,
Benny Prijonoa4e7cdd2008-08-19 15:01:48 +00001638 82, 93, 71, 369, 402, 173, 162, 444, 300, 391,
1639 98, 76, 278, 61, 267, 374, 135, 411, 167, 102,
Nanang Izzuddin493a8db2008-08-15 13:17:39 +00001640 380, 200, 87, 178, 65, 94, 204, 124, 72, 342,
1641 189, 305, 381, 396, 433, 301, 226, 407, 289, 237,
1642 113, 215, 185, 128, 309, 403, 116, 320, 196, 331,
1643 370, 422, 174, 64, 392, 83, 425, 219, 134, 188,
1644 432, 112, 427, 139, 279, 163, 436, 208, 447, 218,
1645 236, 229, 97, 294, 385, 230, 166, 268, 177, 443,
1646 225, 426, 101, 272, 138, 127, 290, 117, 347, 199,
1647 414, 95, 140, 240, 410, 395, 209, 129, 283, 346,
1648 105, 241, 437, 86, 308, 448, 203, 345, 186, 107,
1649 220, 415, 334, 319, 106, 313, 118, 123, 73, 207,
1650 421, 214, 384, 373, 438, 62, 371, 341, 75, 449,
1651 168, 323, 164, 242, 416, 324, 304, 197, 335, 404,
1652 271, 63, 191, 325, 96, 169, 231, 280, 312, 187,
1653 406, 84, 201, 100, 67, 382, 175, 336, 202, 330,
1654 269, 393, 376, 383, 293, 307, 409, 179, 285, 314,
1655 302, 372, 398, 190, 180, 89, 99, 103, 232, 78,
Benny Prijonoa4e7cdd2008-08-19 15:01:48 +00001656 88, 77, 136, 387, 165, 198, 394, 125, 176, 428,
1657 74, 375, 238, 227, 66, 273, 282, 141, 306, 412,
Nanang Izzuddin493a8db2008-08-15 13:17:39 +00001658 114, 85, 130, 348, 119, 291, 296, 386, 233, 397,
1659 303, 405, 284, 445, 423, 221, 210, 205, 450, 108,
1660 274, 434, 216, 343, 337, 142, 243, 321, 408, 451,
1661 310, 292, 120, 109, 281, 439, 270, 429, 332, 295,
1662 418, 211, 315, 222, 326, 131, 430, 244, 327, 349,
1663 417, 316, 143, 338, 440, 234, 110, 212, 452, 245,
1664 121, 419, 350, 223, 132, 441, 328, 413, 317, 339,
1665 126, 104, 137, 446, 344, 239, 435, 115, 333, 206,
1666 322, 217, 228, 424, 453, 311, 351, 111, 442, 224,
1667 213, 122, 431, 340, 235, 246, 133, 144, 420, 329,
1668 318
1669};
1670
1671static pj_int16_t AMRWB_ordermap_2385[] =
1672{
Benny Prijonoa4e7cdd2008-08-19 15:01:48 +00001673 0, 4, 6, 145, 251, 360, 466, 7, 5, 3,
1674 47, 48, 49, 50, 51, 262, 263, 264, 265, 266,
Nanang Izzuddin493a8db2008-08-15 13:17:39 +00001675 146, 252, 361, 467, 151, 257, 366, 472, 148, 254,
1676 363, 469, 149, 255, 364, 470, 156, 371, 150, 256,
1677 365, 471, 147, 253, 362, 468, 52, 2, 1, 157,
1678 372, 267, 19, 21, 12, 17, 18, 20, 16, 25,
Benny Prijonoa4e7cdd2008-08-19 15:01:48 +00001679 13, 10, 14, 24, 23, 22, 26, 8, 15, 53,
Nanang Izzuddin493a8db2008-08-15 13:17:39 +00001680 268, 31, 152, 153, 154, 155, 258, 259, 260, 261,
1681 367, 368, 369, 370, 473, 474, 475, 476, 158, 373,
Benny Prijonoa4e7cdd2008-08-19 15:01:48 +00001682 9, 33, 11, 159, 374, 54, 269, 28, 27, 160,
Nanang Izzuddin493a8db2008-08-15 13:17:39 +00001683 375, 34, 35, 29, 46, 32, 30, 55, 270, 37,
Benny Prijonoa4e7cdd2008-08-19 15:01:48 +00001684 36, 39, 38, 40, 161, 376, 41, 42, 43, 44,
1685 45, 56, 162, 271, 377, 185, 196, 174, 79, 57,
Nanang Izzuddin493a8db2008-08-15 13:17:39 +00001686 411, 90, 163, 305, 389, 378, 283, 68, 187, 400,
1687 294, 198, 307, 92, 70, 186, 413, 176, 59, 91,
Benny Prijonoa4e7cdd2008-08-19 15:01:48 +00001688 58, 412, 380, 165, 81, 164, 272, 175, 80, 401,
Nanang Izzuddin493a8db2008-08-15 13:17:39 +00001689 402, 390, 391, 197, 306, 69, 274, 273, 379, 285,
1690 296, 284, 295, 188, 60, 199, 82, 93, 71, 381,
1691 414, 177, 166, 456, 308, 403, 98, 76, 286, 61,
1692 275, 386, 135, 423, 171, 102, 392, 204, 87, 182,
Benny Prijonoa4e7cdd2008-08-19 15:01:48 +00001693 65, 94, 208, 124, 72, 350, 193, 313, 393, 408,
Nanang Izzuddin493a8db2008-08-15 13:17:39 +00001694 445, 309, 230, 419, 297, 241, 113, 219, 189, 128,
1695 317, 415, 116, 328, 200, 339, 382, 434, 178, 64,
1696 404, 83, 437, 223, 134, 192, 444, 112, 439, 139,
1697 287, 167, 448, 212, 459, 222, 240, 233, 97, 302,
1698 397, 234, 170, 276, 181, 455, 229, 438, 101, 280,
1699 138, 127, 298, 117, 355, 203, 426, 95, 140, 244,
1700 422, 407, 213, 129, 291, 354, 105, 245, 449, 86,
1701 316, 460, 207, 353, 190, 107, 224, 427, 342, 327,
1702 106, 321, 118, 123, 73, 211, 433, 218, 396, 385,
1703 450, 62, 383, 349, 75, 461, 172, 331, 168, 246,
1704 428, 332, 312, 201, 343, 416, 279, 63, 195, 333,
Benny Prijonoa4e7cdd2008-08-19 15:01:48 +00001705 96, 173, 235, 288, 320, 191, 418, 84, 205, 100,
1706 67, 394, 179, 344, 206, 338, 277, 405, 388, 395,
Nanang Izzuddin493a8db2008-08-15 13:17:39 +00001707 301, 315, 421, 183, 293, 322, 310, 384, 410, 194,
1708 184, 89, 99, 103, 236, 78, 88, 77, 136, 399,
1709 169, 202, 406, 125, 180, 440, 74, 387, 242, 231,
Benny Prijonoa4e7cdd2008-08-19 15:01:48 +00001710 66, 281, 290, 141, 314, 424, 114, 85, 130, 356,
Nanang Izzuddin493a8db2008-08-15 13:17:39 +00001711 119, 299, 304, 398, 237, 409, 311, 417, 292, 457,
1712 435, 225, 214, 209, 462, 108, 282, 446, 220, 351,
1713 345, 142, 247, 329, 420, 463, 318, 300, 120, 109,
1714 289, 451, 278, 441, 340, 303, 430, 215, 323, 226,
1715 334, 131, 442, 248, 335, 357, 429, 324, 143, 346,
1716 452, 238, 110, 216, 464, 249, 121, 431, 358, 227,
1717 132, 453, 336, 425, 325, 347, 126, 104, 137, 458,
1718 352, 243, 447, 115, 341, 210, 330, 221, 232, 436,
1719 465, 319, 359, 111, 454, 228, 217, 122, 443, 348,
1720 239, 250, 133, 144, 432, 337, 326
1721};
1722
1723static pj_int16_t *AMRWB_ordermaps[9] =
1724{
1725 AMRWB_ordermap_660,
1726 AMRWB_ordermap_885,
1727 AMRWB_ordermap_1265,
1728 AMRWB_ordermap_1425,
1729 AMRWB_ordermap_1585,
1730 AMRWB_ordermap_1825,
1731 AMRWB_ordermap_1985,
1732 AMRWB_ordermap_2305,
1733 AMRWB_ordermap_2385
1734};
1735
Nanang Izzuddindf361e02008-08-16 06:46:08 +00001736static pj_uint8_t AMRNB_framelen[16] =
1737 {12, 13, 15, 17, 19, 20, 26, 31, 5, 0, 0, 0, 0, 0, 0, 5};
1738static pj_uint16_t AMRNB_framelenbits[9] =
Nanang Izzuddin493a8db2008-08-15 13:17:39 +00001739 {95, 103, 118, 134, 148, 159, 204, 244, 39};
Nanang Izzuddindf361e02008-08-16 06:46:08 +00001740static pj_uint16_t AMRNB_bitrates[8] =
Nanang Izzuddin493a8db2008-08-15 13:17:39 +00001741 {4750, 5150, 5900, 6700, 7400, 7950, 10200, 12200};
1742
Nanang Izzuddindf361e02008-08-16 06:46:08 +00001743static pj_uint8_t AMRWB_framelen[16] =
1744 {17, 23, 32, 37, 40, 46, 50, 58, 60, 5, 0, 0, 0, 0, 0, 5};
1745static pj_uint16_t AMRWB_framelenbits[10] =
1746 {132, 177, 253, 285, 317, 365, 397, 461, 477, 40};
1747static pj_uint16_t AMRWB_bitrates[9] =
1748 {6600, 8850, 12650, 14250, 15850, 18250, 19850, 23050, 23850};
1749
Nanang Izzuddin493a8db2008-08-15 13:17:39 +00001750
1751/* Get mode based on bitrate */
1752static int amr_get_mode(unsigned bitrate)
1753{
1754 int mode = -1;
1755
1756 if(bitrate==4750){
1757 mode = 0;
1758 } else if(bitrate==5150){
1759 mode = 1;
1760 } else if(bitrate==5900){
1761 mode = 2;
1762 } else if(bitrate==6700){
1763 mode = 3;
1764 } else if(bitrate==7400){
1765 mode = 4;
1766 } else if(bitrate==7950){
1767 mode = 5;
1768 } else if(bitrate==10200){
1769 mode = 6;
1770 } else if(bitrate==12200){
1771 mode = 7;
1772
1773 /* AMRWB */
1774 } else if(bitrate==6600){
1775 mode = 0;
1776 } else if(bitrate==8850){
1777 mode = 1;
1778 } else if(bitrate==12650){
1779 mode = 2;
1780 } else if(bitrate==14250){
1781 mode = 3;
1782 } else if(bitrate==15850){
1783 mode = 4;
1784 } else if(bitrate==18250){
1785 mode = 5;
1786 } else if(bitrate==19850){
1787 mode = 6;
1788 } else if(bitrate==23050){
1789 mode = 7;
1790 } else if(bitrate==23850){
1791 mode = 8;
1792 }
1793 return mode;
1794}
1795
Nanang Izzuddindf361e02008-08-16 06:46:08 +00001796/* Rearrange AMR bitstream of rtp_frame:
1797 * - make the start_bit to be 0
1798 * - if it is speech frame, reorder bitstream from sensitivity bits order
1799 * to encoder bits order.
1800 */
1801static void predecode_amr( ipp_private_t *codec_data,
1802 const pjmedia_frame *rtp_frame,
1803 USC_Bitstream *usc_frame)
1804{
1805 pj_uint8_t FT, Q;
1806 pj_int8_t amr_bits[477 + 7] = {0};
1807 pj_int8_t *p_amr_bits = &amr_bits[0];
1808 unsigned i;
1809 /* read cursor */
1810 pj_uint8_t *r = (pj_uint8_t*)rtp_frame->buf;
1811 pj_uint8_t start_bit;
1812 /* write cursor */
1813 pj_uint8_t *w = (pj_uint8_t*)rtp_frame->buf;
1814 /* env vars for AMR or AMRWB */
1815 pj_bool_t AMRWB;
1816 pj_uint8_t SID_FT = 8;
1817 pj_uint8_t *framelen_tbl = AMRNB_framelen;
1818 pj_uint16_t *framelenbit_tbl = AMRNB_framelenbits;
1819 pj_uint16_t *bitrate_tbl = AMRNB_bitrates;
1820 pj_int16_t **order_map = AMRNB_ordermaps;
1821
Benny Prijonoa4e7cdd2008-08-19 15:01:48 +00001822 AMRWB = (ipp_codec[codec_data->codec_idx].pt == PJMEDIA_RTP_PT_AMRWB);
Nanang Izzuddindf361e02008-08-16 06:46:08 +00001823 if (AMRWB) {
1824 SID_FT = 9;
1825 framelen_tbl = AMRWB_framelen;
1826 framelenbit_tbl = AMRWB_framelenbits;
1827 bitrate_tbl = AMRWB_bitrates;
1828 order_map = AMRWB_ordermaps;
1829 }
1830
1831 start_bit = (pj_uint8_t)((rtp_frame->bit_info & 0x0700) >> 8);
1832 FT = (pj_uint8_t)(rtp_frame->bit_info & 0x0F);
1833 Q = (pj_uint8_t)((rtp_frame->bit_info >> 16) & 0x01);
1834
1835 /* unpack AMR bitstream if there is any data */
1836 if (FT <= SID_FT) {
1837 i = 0;
1838 if (start_bit) {
1839 for (; i < (unsigned)(8-start_bit); ++i)
Benny Prijonoa4e7cdd2008-08-19 15:01:48 +00001840 *p_amr_bits++ = (pj_uint8_t)((*r >> (7-start_bit-i)) & 1);
Nanang Izzuddindf361e02008-08-16 06:46:08 +00001841 ++r;
1842 }
1843 for(; i < framelenbit_tbl[FT]; i += 8) {
Benny Prijonoa4e7cdd2008-08-19 15:01:48 +00001844 *p_amr_bits++ = (pj_uint8_t)((*r >> 7) & 1);
1845 *p_amr_bits++ = (pj_uint8_t)((*r >> 6) & 1);
1846 *p_amr_bits++ = (pj_uint8_t)((*r >> 5) & 1);
1847 *p_amr_bits++ = (pj_uint8_t)((*r >> 4) & 1);
1848 *p_amr_bits++ = (pj_uint8_t)((*r >> 3) & 1);
1849 *p_amr_bits++ = (pj_uint8_t)((*r >> 2) & 1);
1850 *p_amr_bits++ = (pj_uint8_t)((*r >> 1) & 1);
1851 *p_amr_bits++ = (pj_uint8_t)((*r ) & 1);
Nanang Izzuddindf361e02008-08-16 06:46:08 +00001852 ++r;
1853 }
1854 }
1855
1856 if (FT < SID_FT) {
1857 /* Speech */
1858 pj_int16_t *order_map_;
1859
1860 order_map_ = order_map[FT];
1861 pj_bzero(rtp_frame->buf, rtp_frame->size);
1862 for(i = 0; i < framelenbit_tbl[FT]; ++i) {
1863 if (amr_bits[i]) {
1864 pj_uint16_t bitpos;
1865 bitpos = order_map_[i];
1866 w[bitpos>>3] |= 1 << (7 - (bitpos % 8));
1867 }
1868 }
1869 usc_frame->nbytes = framelen_tbl[FT];
1870 if (Q)
1871 usc_frame->frametype = 0;
1872 else
1873 usc_frame->frametype = AMRWB ? 6 : 5;
1874 usc_frame->bitrate = bitrate_tbl[FT];
1875 } else if (FT == SID_FT) {
1876 /* SID */
1877 pj_uint8_t w_bitptr = 0;
1878 pj_uint8_t STI;
1879 pj_uint8_t FT_;
1880
1881 STI = amr_bits[35];
1882 if (AMRWB)
Benny Prijonoa4e7cdd2008-08-19 15:01:48 +00001883 FT_ = (pj_uint8_t)((amr_bits[36] << 3) | (amr_bits[37] << 2) |
1884 (amr_bits[38] << 1) | amr_bits[39]);
Nanang Izzuddindf361e02008-08-16 06:46:08 +00001885 else
Benny Prijonoa4e7cdd2008-08-19 15:01:48 +00001886 FT_ = (pj_uint8_t)((amr_bits[36] << 2) | (amr_bits[37] << 1) |
1887 amr_bits[38]);
Nanang Izzuddindf361e02008-08-16 06:46:08 +00001888
1889 pj_bzero(rtp_frame->buf, rtp_frame->size);
1890 for(i = 0; i < framelenbit_tbl[FT]; ++i) {
1891 if (amr_bits[i])
1892 *w |= (1 << (7-w_bitptr));
1893
1894 if (++w_bitptr == 8) {
1895 ++w;
1896 w_bitptr = 0;
1897 }
1898 }
1899
1900 usc_frame->nbytes = 5;
1901 if (Q)
1902 usc_frame->frametype = STI? 2 : 1;
1903 else
1904 usc_frame->frametype = AMRWB ? 7 : 6;
1905
1906 usc_frame->bitrate = bitrate_tbl[FT_];
1907 } else {
1908 /* NO DATA */
1909 usc_frame->nbytes = 0;
1910 usc_frame->frametype = 3;
1911 usc_frame->bitrate = 0;
1912 }
1913
1914 usc_frame->pBuffer = rtp_frame->buf;
1915}
Nanang Izzuddin493a8db2008-08-15 13:17:39 +00001916
1917static pj_status_t pack_amr(ipp_private_t *codec_data, void *pkt,
1918 pj_size_t *pkt_size, pj_size_t max_pkt_size)
1919{
1920 /* Settings */
1921 pj_uint8_t CMR = 15; /* We don't request any code mode */
1922 pj_uint8_t octet_aligned = 0; /* default==0 when SDP not specifying */
Nanang Izzuddin493a8db2008-08-15 13:17:39 +00001923 /* Write cursor */
1924 pj_uint8_t *w = (pj_uint8_t*)pkt;
1925 pj_uint8_t w_bitptr = 0;
Nanang Izzuddin493a8db2008-08-15 13:17:39 +00001926 /* Read cursor */
1927 pj_uint8_t *r;
Nanang Izzuddindf361e02008-08-16 06:46:08 +00001928 /* env vars for AMR or AMRWB */
1929 pj_bool_t AMRWB;
1930 pj_uint8_t SID_FT = 8;
1931 pj_uint8_t *framelen_tbl = AMRNB_framelen;
1932 pj_uint16_t *framelenbit_tbl = AMRNB_framelenbits;
1933 pj_uint16_t *bitrate_tbl = AMRNB_bitrates;
1934 pj_int16_t **order_map = AMRNB_ordermaps;
Nanang Izzuddin493a8db2008-08-15 13:17:39 +00001935
Nanang Izzuddindf361e02008-08-16 06:46:08 +00001936 AMRWB = ipp_codec[codec_data->codec_idx].pt == PJMEDIA_RTP_PT_AMRWB;
1937 if (AMRWB) {
1938 SID_FT = 9;
1939 framelen_tbl = AMRWB_framelen;
1940 framelenbit_tbl = AMRWB_framelenbits;
1941 bitrate_tbl = AMRWB_bitrates;
1942 order_map = AMRWB_ordermaps;
1943 }
Nanang Izzuddin493a8db2008-08-15 13:17:39 +00001944
1945 PJ_TODO(Make_sure_buffer_is_enough_for_packing_AMR_packet);
1946
1947 r = (pj_uint8_t*)pkt + max_pkt_size - *pkt_size;
1948
1949 /* Align pkt buf right */
1950 pj_memmove(r, w, *pkt_size);
1951
1952 /* Code Mode Request, 4 bits */
Benny Prijonoa4e7cdd2008-08-19 15:01:48 +00001953 *w = (pj_uint8_t)(CMR << 4);
Nanang Izzuddin493a8db2008-08-15 13:17:39 +00001954 w_bitptr = 4;
1955 if (octet_aligned) {
1956 ++w;
1957 w_bitptr = 0;
1958 }
1959
1960 /* Table Of Contents, 6 bits each */
1961 for (;;) {
1962 pj_uint8_t TOC;
1963 pj_uint8_t F, FT, Q;
1964
Benny Prijonoa4e7cdd2008-08-19 15:01:48 +00001965 F = (pj_uint8_t)((*r & 0x40) == 0);
1966 FT = (pj_uint8_t)(*r & 0x0F);
1967 Q = (pj_uint8_t)((*r & 0x80) == 0);
Nanang Izzuddin493a8db2008-08-15 13:17:39 +00001968
Nanang Izzuddindf361e02008-08-16 06:46:08 +00001969 pj_assert(FT <= SID_FT || FT == 14 || FT == 15);
Nanang Izzuddin493a8db2008-08-15 13:17:39 +00001970 TOC = (pj_uint8_t)((F<<5) | (FT<<1) | Q);
1971
1972 if (w_bitptr == 0) {
Benny Prijonoa4e7cdd2008-08-19 15:01:48 +00001973 *w = (pj_uint8_t)(TOC<<2);
Nanang Izzuddin493a8db2008-08-15 13:17:39 +00001974 w_bitptr = 6;
1975 } else if (w_bitptr == 2) {
1976 *w++ |= TOC;
1977 w_bitptr = 0;
1978 } else if (w_bitptr == 4) {
1979 *w++ |= TOC>>2;
Benny Prijonoa4e7cdd2008-08-19 15:01:48 +00001980 *w = (pj_uint8_t)(TOC<<6);
Nanang Izzuddin493a8db2008-08-15 13:17:39 +00001981 w_bitptr = 2;
1982 } else if (w_bitptr == 6) {
1983 *w++ |= TOC>>4;
Benny Prijonoa4e7cdd2008-08-19 15:01:48 +00001984 *w = (pj_uint8_t)(TOC<<4);
Nanang Izzuddin493a8db2008-08-15 13:17:39 +00001985 w_bitptr = 4;
1986 }
1987
1988 if (octet_aligned) {
1989 ++w;
1990 w_bitptr = 0;
1991 }
1992
Nanang Izzuddindf361e02008-08-16 06:46:08 +00001993 if (FT > SID_FT)
1994 /* NO DATA */
Nanang Izzuddin493a8db2008-08-15 13:17:39 +00001995 r += 1;
1996 else
Nanang Izzuddindf361e02008-08-16 06:46:08 +00001997 r += framelen_tbl[FT] + 1;
Nanang Izzuddin493a8db2008-08-15 13:17:39 +00001998
1999 /* Last frame */
2000 if (!F)
2001 break;
2002 }
2003
2004 /* Speech frames */
2005 r = (pj_uint8_t*)pkt + max_pkt_size - *pkt_size;
2006
2007 for (;;) {
2008 pj_uint8_t F, FT;
2009 pj_int8_t amr_bits[477 + 7] = {0};
2010 pj_int8_t *p_amr_bits = &amr_bits[0];
2011 unsigned i;
2012
Benny Prijonoa4e7cdd2008-08-19 15:01:48 +00002013 F = (pj_uint8_t)((*r & 0x40) == 0);
2014 FT = (pj_uint8_t)(*r & 0x0F);
Nanang Izzuddindf361e02008-08-16 06:46:08 +00002015 pj_assert(FT <= SID_FT || FT == 14 || FT == 15);
Nanang Izzuddin493a8db2008-08-15 13:17:39 +00002016
2017 ++r;
Nanang Izzuddindf361e02008-08-16 06:46:08 +00002018 if (FT > SID_FT) {
Nanang Izzuddin493a8db2008-08-15 13:17:39 +00002019 if (!F)
2020 break;
2021 continue;
2022 }
2023
2024 /* Unpack bits */
Nanang Izzuddindf361e02008-08-16 06:46:08 +00002025 for(i = 0; i < framelen_tbl[FT]; ++i) {
Benny Prijonoa4e7cdd2008-08-19 15:01:48 +00002026 *p_amr_bits++ = (pj_uint8_t)((*r >> 7) & 1);
2027 *p_amr_bits++ = (pj_uint8_t)((*r >> 6) & 1);
2028 *p_amr_bits++ = (pj_uint8_t)((*r >> 5) & 1);
2029 *p_amr_bits++ = (pj_uint8_t)((*r >> 4) & 1);
2030 *p_amr_bits++ = (pj_uint8_t)((*r >> 3) & 1);
2031 *p_amr_bits++ = (pj_uint8_t)((*r >> 2) & 1);
2032 *p_amr_bits++ = (pj_uint8_t)((*r >> 1) & 1);
2033 *p_amr_bits++ = (pj_uint8_t)((*r ) & 1);
Nanang Izzuddin493a8db2008-08-15 13:17:39 +00002034 ++r;
2035 }
2036
Nanang Izzuddindf361e02008-08-16 06:46:08 +00002037 if (FT < SID_FT) {
2038 /* Speech */
2039 pj_int16_t *order_map_;
Nanang Izzuddin493a8db2008-08-15 13:17:39 +00002040
Nanang Izzuddindf361e02008-08-16 06:46:08 +00002041 /* Put bits in the packet, sensitivity descending ordered */
2042 order_map_ = order_map[FT];
Nanang Izzuddin493a8db2008-08-15 13:17:39 +00002043 if (w_bitptr == 0) *w = 0;
Nanang Izzuddindf361e02008-08-16 06:46:08 +00002044 for(i = 0; i < framelenbit_tbl[FT]; ++i) {
2045 pj_uint8_t bit;
2046 bit = amr_bits[order_map_[i]];
2047
2048 if (bit)
Nanang Izzuddin493a8db2008-08-15 13:17:39 +00002049 *w |= (1 << (7-w_bitptr));
2050
2051 if (++w_bitptr == 8) {
2052 w_bitptr = 0;
2053 ++w;
2054 *w = 0;
2055 }
2056 }
2057
2058 if (octet_aligned) {
2059 ++w;
2060 w_bitptr = 0;
2061 }
Nanang Izzuddindf361e02008-08-16 06:46:08 +00002062 } else if (FT == SID_FT) {
2063 /* SID */
2064 pj_uint8_t STI = 0;
Nanang Izzuddin493a8db2008-08-15 13:17:39 +00002065
Benny Prijonoa4e7cdd2008-08-19 15:01:48 +00002066 amr_bits[35] = (pj_uint8_t)(STI & 1);
Nanang Izzuddindf361e02008-08-16 06:46:08 +00002067
2068 if (AMRWB) {
Benny Prijonoa4e7cdd2008-08-19 15:01:48 +00002069 amr_bits[36] = (pj_uint8_t)((FT >> 3) & 1);
2070 amr_bits[37] = (pj_uint8_t)((FT >> 2) & 1);
2071 amr_bits[38] = (pj_uint8_t)((FT >> 1) & 1);
2072 amr_bits[39] = (pj_uint8_t)((FT) & 1);
Nanang Izzuddindf361e02008-08-16 06:46:08 +00002073 } else {
Benny Prijonoa4e7cdd2008-08-19 15:01:48 +00002074 amr_bits[36] = (pj_uint8_t)((FT >> 2) & 1);
2075 amr_bits[37] = (pj_uint8_t)((FT >> 1) & 1);
2076 amr_bits[38] = (pj_uint8_t)((FT) & 1);
Nanang Izzuddindf361e02008-08-16 06:46:08 +00002077 }
2078
Nanang Izzuddin493a8db2008-08-15 13:17:39 +00002079 if (w_bitptr == 0) *w = 0;
Nanang Izzuddindf361e02008-08-16 06:46:08 +00002080 for(i = 0; i < framelenbit_tbl[FT]; ++i) {
2081 if (amr_bits[i])
Nanang Izzuddin493a8db2008-08-15 13:17:39 +00002082 *w |= (1 << (7-w_bitptr));
2083
2084 if (++w_bitptr == 8) {
2085 w_bitptr = 0;
2086 ++w;
2087 *w = 0;
2088 }
2089 }
2090
2091 if (octet_aligned) {
2092 ++w;
2093 w_bitptr = 0;
2094 }
2095 }
2096
2097 if (!F)
2098 break;
2099 }
2100
2101 *pkt_size = w - (pj_uint8_t*)pkt;
2102 if (w_bitptr)
2103 *pkt_size += 1;
2104
2105 pj_assert(*pkt_size <= max_pkt_size);
2106
2107 return PJ_SUCCESS;
2108}
2109
2110
2111/* Parse AMR payload into frames. Frame.bit_info will contain start_bit and
2112 * AMR frame type, it is mapped as below (bit 0:MSB - bit 31:LSB)
Nanang Izzuddindf361e02008-08-16 06:46:08 +00002113 * - bit 0-16: degraded quality flag (Q)
Nanang Izzuddin493a8db2008-08-15 13:17:39 +00002114 * - bit 17-24: start_bit
Nanang Izzuddindf361e02008-08-16 06:46:08 +00002115 * - bit 25-32: frame_type (FT)
Nanang Izzuddin493a8db2008-08-15 13:17:39 +00002116 */
2117static pj_status_t parse_amr(ipp_private_t *codec_data, void *pkt,
2118 pj_size_t pkt_size, const pj_timestamp *ts,
2119 unsigned *frame_cnt, pjmedia_frame frames[])
2120{
2121 unsigned cnt = 0;
2122 pj_timestamp ts_ = *ts;
Nanang Izzuddin493a8db2008-08-15 13:17:39 +00002123 /* Settings */
2124 pj_uint8_t CMR = 15; /* See if remote request code mode */
2125 pj_uint8_t octet_aligned = 0; /* default==0 when SDP not specifying */
Nanang Izzuddin493a8db2008-08-15 13:17:39 +00002126 /* Read cursor */
2127 pj_uint8_t r_bitptr = 0;
2128 pj_uint8_t *r = (pj_uint8_t*)pkt;
Nanang Izzuddindf361e02008-08-16 06:46:08 +00002129 /* env vars for AMR or AMRWB */
2130 pj_bool_t AMRWB;
2131 pj_uint8_t SID_FT = 8;
2132 pj_uint8_t *framelen_tbl = AMRNB_framelen;
2133 pj_uint16_t *framelenbit_tbl = AMRNB_framelenbits;
Nanang Izzuddin493a8db2008-08-15 13:17:39 +00002134
2135 PJ_UNUSED_ARG(pkt_size);
2136
Nanang Izzuddindf361e02008-08-16 06:46:08 +00002137 AMRWB = ipp_codec[codec_data->codec_idx].pt == PJMEDIA_RTP_PT_AMRWB;
2138 if (AMRWB) {
2139 SID_FT = 9;
2140 framelen_tbl = AMRWB_framelen;
2141 framelenbit_tbl = AMRWB_framelenbits;
2142 }
2143
Nanang Izzuddin493a8db2008-08-15 13:17:39 +00002144 *frame_cnt = 0;
2145
2146 /* Code Mode Request, 4 bits */
Benny Prijonoa4e7cdd2008-08-19 15:01:48 +00002147 CMR = (pj_uint8_t)((*r >> 4) & 0x0F);
Nanang Izzuddin493a8db2008-08-15 13:17:39 +00002148 r_bitptr = 4;
2149 if (octet_aligned) {
2150 ++r;
2151 r_bitptr = 0;
2152 }
2153
2154 /* Table Of Contents, 6 bits each */
2155 for (;;) {
2156 pj_uint8_t TOC = 0;
2157 pj_uint8_t F, FT, Q;
2158
2159 if (r_bitptr == 0) {
Benny Prijonoa4e7cdd2008-08-19 15:01:48 +00002160 TOC = (pj_uint8_t)(*r >> 2);
Nanang Izzuddin493a8db2008-08-15 13:17:39 +00002161 r_bitptr = 6;
2162 } else if (r_bitptr == 2) {
Benny Prijonoa4e7cdd2008-08-19 15:01:48 +00002163 TOC = (pj_uint8_t)(*r++ & 0x3F);
Nanang Izzuddin493a8db2008-08-15 13:17:39 +00002164 r_bitptr = 0;
2165 } else if (r_bitptr == 4) {
Benny Prijonoa4e7cdd2008-08-19 15:01:48 +00002166 TOC = (pj_uint8_t)((*r++ & 0x0f) << 2);
Nanang Izzuddin493a8db2008-08-15 13:17:39 +00002167 TOC |= *r >> 6;
2168 r_bitptr = 2;
2169 } else if (r_bitptr == 6) {
Benny Prijonoa4e7cdd2008-08-19 15:01:48 +00002170 TOC = (pj_uint8_t)((*r++ & 0x03) << 4);
Nanang Izzuddin493a8db2008-08-15 13:17:39 +00002171 TOC |= *r >> 4;
2172 r_bitptr = 4;
2173 }
2174
Benny Prijonoa4e7cdd2008-08-19 15:01:48 +00002175 F = (pj_uint8_t)(TOC >> 5);
2176 FT = (pj_uint8_t)((TOC >> 1) & 0x0F);
2177 Q = (pj_uint8_t)(TOC & 1);
Nanang Izzuddin493a8db2008-08-15 13:17:39 +00002178
Nanang Izzuddindf361e02008-08-16 06:46:08 +00002179 if (FT > SID_FT && FT < 14) {
2180 pj_assert(!"Invalid AMR frametype, stream may be corrupted!");
Nanang Izzuddin493a8db2008-08-15 13:17:39 +00002181 break;
Nanang Izzuddindf361e02008-08-16 06:46:08 +00002182 }
Nanang Izzuddin493a8db2008-08-15 13:17:39 +00002183
2184 if (octet_aligned) {
2185 ++r;
2186 r_bitptr = 0;
2187 }
2188
2189 /* Set frame attributes */
Nanang Izzuddindf361e02008-08-16 06:46:08 +00002190 frames[cnt].bit_info = FT | (Q << 16);
2191 frames[cnt].timestamp = ts_;
2192 frames[cnt].type = PJMEDIA_FRAME_TYPE_AUDIO;
Nanang Izzuddin493a8db2008-08-15 13:17:39 +00002193
Nanang Izzuddin493a8db2008-08-15 13:17:39 +00002194 ts_.u64 += ipp_codec[codec_data->codec_idx].samples_per_frame;
Nanang Izzuddindf361e02008-08-16 06:46:08 +00002195 ++cnt;
Nanang Izzuddin493a8db2008-08-15 13:17:39 +00002196
2197 if (!F || cnt == *frame_cnt)
2198 break;
2199 }
2200 *frame_cnt = cnt;
2201
2202 cnt = 0;
2203
2204 /* Speech frames */
2205 while (cnt < *frame_cnt) {
2206 unsigned FT;
2207
Nanang Izzuddindf361e02008-08-16 06:46:08 +00002208 FT = frames[cnt].bit_info & 0x0F;
Nanang Izzuddin493a8db2008-08-15 13:17:39 +00002209
2210 frames[cnt].bit_info |= (r_bitptr << 8);
2211 frames[cnt].buf = r;
2212
2213 if (octet_aligned) {
Nanang Izzuddindf361e02008-08-16 06:46:08 +00002214 r += framelen_tbl[FT];
2215 frames[cnt].size = framelen_tbl[FT];
Nanang Izzuddin493a8db2008-08-15 13:17:39 +00002216 } else {
Nanang Izzuddindf361e02008-08-16 06:46:08 +00002217 if (FT == 14 || FT == 15) {
2218 /* NO DATA */
2219 frames[cnt].size = 0;
2220 } else {
2221 unsigned adv_bit;
Nanang Izzuddin493a8db2008-08-15 13:17:39 +00002222
Nanang Izzuddindf361e02008-08-16 06:46:08 +00002223 adv_bit = framelenbit_tbl[FT] + r_bitptr;
2224 r += adv_bit >> 3;
2225 r_bitptr = (pj_uint8_t)(adv_bit % 8);
Nanang Izzuddin493a8db2008-08-15 13:17:39 +00002226
Nanang Izzuddindf361e02008-08-16 06:46:08 +00002227 frames[cnt].size = adv_bit >> 3;
2228 if (r_bitptr)
2229 ++frames[cnt].size;
2230 }
Nanang Izzuddin493a8db2008-08-15 13:17:39 +00002231 }
2232 ++cnt;
2233 }
2234
2235 return PJ_SUCCESS;
2236}
2237
Nanang Izzuddin493a8db2008-08-15 13:17:39 +00002238#endif /* PJMEDIA_HAS_INTEL_IPP_CODEC_AMR */
2239
2240
Benny Prijonoa4e7cdd2008-08-19 15:01:48 +00002241#if defined(_MSC_VER) && PJMEDIA_AUTO_LINK_IPP_LIBS
2242# pragma comment( lib, "ippcore.lib")
2243# pragma comment( lib, "ipps.lib")
2244# pragma comment( lib, "ippsc.lib")
2245# pragma comment( lib, "ippsr.lib")
2246# pragma comment( lib, "usc.lib")
Nanang Izzuddin493a8db2008-08-15 13:17:39 +00002247#endif
2248
2249
Benny Prijonoa4e7cdd2008-08-19 15:01:48 +00002250#endif /* PJMEDIA_HAS_INTEL_IPP */
Nanang Izzuddin493a8db2008-08-15 13:17:39 +00002251