1
/* $Id: opencore_amr.c 4348 2013-02-14 02:00:13Z ming $ */
3
* Copyright (C) 2011-2013 Teluu Inc. (http://www.teluu.com)
4
* Copyright (C) 2011 Dan Arrhenius <dan@keystream.se>
6
* This program is free software; you can redistribute it and/or modify
7
* it under the terms of the GNU General Public License as published by
8
* the Free Software Foundation; either version 2 of the License, or
9
* (at your option) any later version.
11
* This program is distributed in the hope that it will be useful,
12
* but WITHOUT ANY WARRANTY; without even the implied warranty of
13
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14
* GNU General Public License for more details.
16
* You should have received a copy of the GNU General Public License
17
* along with this program; if not, write to the Free Software
18
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22
* AMR codec implementation with OpenCORE AMR library
24
#include <pjmedia-codec/g722.h>
25
#include <pjmedia-codec/amr_sdp_match.h>
26
#include <pjmedia/codec.h>
27
#include <pjmedia/errno.h>
28
#include <pjmedia/endpoint.h>
29
#include <pjmedia/plc.h>
30
#include <pjmedia/port.h>
31
#include <pjmedia/silencedet.h>
32
#include <pj/assert.h>
35
#include <pj/string.h>
39
#if defined(PJMEDIA_HAS_OPENCORE_AMRNB_CODEC) && \
40
(PJMEDIA_HAS_OPENCORE_AMRNB_CODEC != 0)
44
#if defined(PJMEDIA_HAS_OPENCORE_AMRWB_CODEC) && \
45
(PJMEDIA_HAS_OPENCORE_AMRWB_CODEC != 0)
49
#if defined(USE_AMRNB) || defined(USE_AMRWB)
52
#include <opencore-amrnb/interf_enc.h>
53
#include <opencore-amrnb/interf_dec.h>
57
#include <vo-amrwbenc/enc_if.h>
58
#include <opencore-amrwb/dec_if.h>
61
#include <pjmedia-codec/amr_helper.h>
62
#include <pjmedia-codec/opencore_amr.h>
64
#define THIS_FILE "opencore_amr.c"
70
# define TRACE_(expr) PJ_LOG(4,expr)
76
#define USE_PJMEDIA_PLC 1
78
#define FRAME_LENGTH_MS 20
81
/* Prototypes for AMR factory */
82
static pj_status_t amr_test_alloc(pjmedia_codec_factory *factory,
83
const pjmedia_codec_info *id );
84
static pj_status_t amr_default_attr(pjmedia_codec_factory *factory,
85
const pjmedia_codec_info *id,
86
pjmedia_codec_param *attr );
87
static pj_status_t amr_enum_codecs(pjmedia_codec_factory *factory,
89
pjmedia_codec_info codecs[]);
90
static pj_status_t amr_alloc_codec(pjmedia_codec_factory *factory,
91
const pjmedia_codec_info *id,
92
pjmedia_codec **p_codec);
93
static pj_status_t amr_dealloc_codec(pjmedia_codec_factory *factory,
94
pjmedia_codec *codec );
96
/* Prototypes for AMR implementation. */
97
static pj_status_t amr_codec_init(pjmedia_codec *codec,
99
static pj_status_t amr_codec_open(pjmedia_codec *codec,
100
pjmedia_codec_param *attr );
101
static pj_status_t amr_codec_close(pjmedia_codec *codec );
102
static pj_status_t amr_codec_modify(pjmedia_codec *codec,
103
const pjmedia_codec_param *attr );
104
static pj_status_t amr_codec_parse(pjmedia_codec *codec,
107
const pj_timestamp *ts,
109
pjmedia_frame frames[]);
110
static pj_status_t amr_codec_encode(pjmedia_codec *codec,
111
const struct pjmedia_frame *input,
112
unsigned output_buf_len,
113
struct pjmedia_frame *output);
114
static pj_status_t amr_codec_decode(pjmedia_codec *codec,
115
const struct pjmedia_frame *input,
116
unsigned output_buf_len,
117
struct pjmedia_frame *output);
118
static pj_status_t amr_codec_recover(pjmedia_codec *codec,
119
unsigned output_buf_len,
120
struct pjmedia_frame *output);
124
/* Definition for AMR codec operations. */
125
static pjmedia_codec_op amr_op =
137
/* Definition for AMR codec factory operations. */
138
static pjmedia_codec_factory_op amr_factory_op =
145
&pjmedia_codec_opencore_amr_deinit
150
static struct amr_codec_factory
152
pjmedia_codec_factory base;
153
pjmedia_endpt *endpt;
159
/* AMR codec private data. */
166
pj_bool_t plc_enabled;
167
pj_bool_t vad_enabled;
169
pjmedia_codec_amr_pack_setting enc_setting;
170
pjmedia_codec_amr_pack_setting dec_setting;
174
pj_timestamp last_tx;
177
/* Index for AMR tables. */
180
IDX_AMR_NB, /* Index for narrowband. */
181
IDX_AMR_WB /* Index for wideband. */
184
static pjmedia_codec_amr_config def_config[2] =
186
PJ_FALSE, /* octet align */
190
PJ_FALSE, /* octet align */
194
static const pj_uint16_t* amr_bitrates[2] =
195
{pjmedia_codec_amrnb_bitrates, pjmedia_codec_amrwb_bitrates};
197
static const unsigned amr_bitrates_size[2] =
199
PJ_ARRAY_SIZE(pjmedia_codec_amrnb_bitrates),
200
PJ_ARRAY_SIZE(pjmedia_codec_amrwb_bitrates)
205
* Initialize and register AMR codec factory to pjmedia endpoint.
207
PJ_DEF(pj_status_t) pjmedia_codec_opencore_amr_init( pjmedia_endpt *endpt,
210
pjmedia_codec_mgr *codec_mgr;
214
if (amr_codec_factory.pool != NULL)
217
/* Create AMR codec factory. */
218
amr_codec_factory.base.op = &amr_factory_op;
219
amr_codec_factory.base.factory_data = NULL;
220
amr_codec_factory.endpt = endpt;
222
amr_codec_factory.init[IDX_AMR_NB] = ((options & PJMEDIA_AMR_NO_NB) == 0);
224
amr_codec_factory.init[IDX_AMR_NB] = PJ_FALSE;
227
amr_codec_factory.init[IDX_AMR_WB] = ((options & PJMEDIA_AMR_NO_WB) == 0);
229
amr_codec_factory.init[IDX_AMR_WB] = PJ_FALSE;
232
amr_codec_factory.pool = pjmedia_endpt_create_pool(endpt, "amr", 1000,
234
if (!amr_codec_factory.pool)
237
/* Get the codec manager. */
238
codec_mgr = pjmedia_endpt_get_codec_mgr(endpt);
240
status = PJ_EINVALIDOP;
244
/* Register format match callback. */
245
pj_cstr(&codec_name, "AMR");
246
status = pjmedia_sdp_neg_register_fmt_match_cb(
248
&pjmedia_codec_amr_match_sdp);
249
if (status != PJ_SUCCESS)
252
/* Register codec factory to endpoint. */
253
status = pjmedia_codec_mgr_register_factory(codec_mgr,
254
&amr_codec_factory.base);
255
if (status != PJ_SUCCESS)
262
pj_pool_release(amr_codec_factory.pool);
263
amr_codec_factory.pool = NULL;
268
pjmedia_codec_opencore_amr_init_default( pjmedia_endpt *endpt )
270
return pjmedia_codec_opencore_amr_init(endpt, 0);
273
PJ_DEF(pj_status_t) pjmedia_codec_opencore_amrnb_init( pjmedia_endpt *endpt )
275
return pjmedia_codec_opencore_amr_init(endpt, PJMEDIA_AMR_NO_WB);
280
* Unregister AMR codec factory from pjmedia endpoint and deinitialize
281
* the AMR codec library.
283
PJ_DEF(pj_status_t) pjmedia_codec_opencore_amr_deinit(void)
285
pjmedia_codec_mgr *codec_mgr;
288
amr_codec_factory.init[IDX_AMR_NB] = PJ_FALSE;
289
amr_codec_factory.init[IDX_AMR_WB] = PJ_FALSE;
291
if (amr_codec_factory.pool == NULL)
294
/* Get the codec manager. */
295
codec_mgr = pjmedia_endpt_get_codec_mgr(amr_codec_factory.endpt);
297
pj_pool_release(amr_codec_factory.pool);
298
amr_codec_factory.pool = NULL;
299
return PJ_EINVALIDOP;
302
/* Unregister AMR codec factory. */
303
status = pjmedia_codec_mgr_unregister_factory(codec_mgr,
304
&amr_codec_factory.base);
307
pj_pool_release(amr_codec_factory.pool);
308
amr_codec_factory.pool = NULL;
313
PJ_DEF(pj_status_t) pjmedia_codec_opencore_amrnb_deinit(void)
315
if (amr_codec_factory.init[IDX_AMR_NB] &&
316
amr_codec_factory.init[IDX_AMR_WB])
318
PJ_LOG(4, (THIS_FILE, "Should call "
319
"pjmedia_codec_opencore_amr_deinit() instead"));
321
return PJ_EINVALIDOP;
324
return pjmedia_codec_opencore_amr_deinit();
328
amr_set_config(unsigned idx, const pjmedia_codec_amr_config *config)
332
def_config[idx] = *config;
334
/* Normalize bitrate. */
335
nbitrates = amr_bitrates_size[idx];
336
if (def_config[idx].bitrate < amr_bitrates[idx][0]) {
337
def_config[idx].bitrate = amr_bitrates[idx][0];
338
} else if (def_config[idx].bitrate > amr_bitrates[idx][nbitrates-1]) {
339
def_config[idx].bitrate = amr_bitrates[idx][nbitrates-1];
344
for (i = 0; i < nbitrates; ++i) {
345
if (def_config[idx].bitrate <= amr_bitrates[idx][i])
348
def_config[idx].bitrate = amr_bitrates[idx][i];
354
PJ_DEF(pj_status_t) pjmedia_codec_opencore_amrnb_set_config(
355
const pjmedia_codec_amrnb_config *config)
357
return amr_set_config(IDX_AMR_NB, (const pjmedia_codec_amr_config *)config);
360
PJ_DEF(pj_status_t) pjmedia_codec_opencore_amrwb_set_config(
361
const pjmedia_codec_amrwb_config *config)
363
return amr_set_config(IDX_AMR_WB, (const pjmedia_codec_amr_config *)config);
367
* Check if factory can allocate the specified codec.
369
static pj_status_t amr_test_alloc( pjmedia_codec_factory *factory,
370
const pjmedia_codec_info *info )
372
const pj_str_t amr_tag = { "AMR", 3};
373
const pj_str_t amrwb_tag = { "AMR-WB", 6};
374
PJ_UNUSED_ARG(factory);
376
/* Type MUST be audio. */
377
if (info->type != PJMEDIA_TYPE_AUDIO)
378
return PJMEDIA_CODEC_EUNSUP;
380
/* Check payload type. */
381
if (info->pt != PJMEDIA_RTP_PT_AMR && info->pt != PJMEDIA_RTP_PT_AMRWB)
382
return PJMEDIA_CODEC_EUNSUP;
384
/* Check encoding name. */
385
if (pj_stricmp(&info->encoding_name, &amr_tag) != 0 &&
386
pj_stricmp(&info->encoding_name, &amrwb_tag) != 0)
388
return PJMEDIA_CODEC_EUNSUP;
391
/* Check clock-rate */
392
if ((info->clock_rate == 8000 && amr_codec_factory.init[IDX_AMR_NB]) ||
393
(info->clock_rate == 16000 && amr_codec_factory.init[IDX_AMR_WB]))
398
/* Unsupported or disabled. */
399
return PJMEDIA_CODEC_EUNSUP;
403
* Generate default attribute.
405
static pj_status_t amr_default_attr( pjmedia_codec_factory *factory,
406
const pjmedia_codec_info *id,
407
pjmedia_codec_param *attr )
411
PJ_UNUSED_ARG(factory);
413
idx = (id->clock_rate <= 8000? IDX_AMR_NB: IDX_AMR_WB);
414
pj_bzero(attr, sizeof(pjmedia_codec_param));
415
attr->info.clock_rate = (id->clock_rate <= 8000? 8000: 16000);
416
attr->info.channel_cnt = 1;
417
attr->info.avg_bps = def_config[idx].bitrate;
418
attr->info.max_bps = amr_bitrates[idx][amr_bitrates_size[idx]-1];
419
attr->info.pcm_bits_per_sample = 16;
420
attr->info.frm_ptime = 20;
421
attr->info.pt = (pj_uint8_t)id->pt;
423
attr->setting.frm_per_pkt = 2;
424
attr->setting.vad = 1;
425
attr->setting.plc = 1;
427
if (def_config[idx].octet_align) {
428
attr->setting.dec_fmtp.cnt = 1;
429
attr->setting.dec_fmtp.param[0].name = pj_str("octet-align");
430
attr->setting.dec_fmtp.param[0].val = pj_str("1");
433
/* Default all other flag bits disabled. */
440
* Enum codecs supported by this factory (i.e. AMR-NB and AMR-WB).
442
static pj_status_t amr_enum_codecs( pjmedia_codec_factory *factory,
444
pjmedia_codec_info codecs[])
446
PJ_UNUSED_ARG(factory);
447
PJ_ASSERT_RETURN(codecs && *count > 0, PJ_EINVAL);
451
if (amr_codec_factory.init[IDX_AMR_NB]) {
452
pj_bzero(&codecs[*count], sizeof(pjmedia_codec_info));
453
codecs[*count].encoding_name = pj_str("AMR");
454
codecs[*count].pt = PJMEDIA_RTP_PT_AMR;
455
codecs[*count].type = PJMEDIA_TYPE_AUDIO;
456
codecs[*count].clock_rate = 8000;
457
codecs[*count].channel_cnt = 1;
461
if (amr_codec_factory.init[IDX_AMR_WB]) {
462
pj_bzero(&codecs[*count], sizeof(pjmedia_codec_info));
463
codecs[*count].encoding_name = pj_str("AMR-WB");
464
codecs[*count].pt = PJMEDIA_RTP_PT_AMRWB;
465
codecs[*count].type = PJMEDIA_TYPE_AUDIO;
466
codecs[*count].clock_rate = 16000;
467
codecs[*count].channel_cnt = 1;
476
* Allocate a new AMR codec instance.
478
static pj_status_t amr_alloc_codec( pjmedia_codec_factory *factory,
479
const pjmedia_codec_info *id,
480
pjmedia_codec **p_codec)
483
pjmedia_codec *codec;
484
struct amr_data *amr_data;
487
PJ_ASSERT_RETURN(factory && id && p_codec, PJ_EINVAL);
488
PJ_ASSERT_RETURN(factory == &amr_codec_factory.base, PJ_EINVAL);
490
pool = pjmedia_endpt_create_pool(amr_codec_factory.endpt, "amr-inst",
493
codec = PJ_POOL_ZALLOC_T(pool, pjmedia_codec);
494
PJ_ASSERT_RETURN(codec != NULL, PJ_ENOMEM);
496
codec->factory = factory;
498
amr_data = PJ_POOL_ZALLOC_T(pool, struct amr_data);
499
codec->codec_data = amr_data;
500
amr_data->pool = pool;
504
status = pjmedia_plc_create(pool, id->clock_rate,
505
id->clock_rate * FRAME_LENGTH_MS / 1000, 0,
507
if (status != PJ_SUCCESS) {
511
PJ_UNUSED_ARG(status);
521
static pj_status_t amr_dealloc_codec( pjmedia_codec_factory *factory,
522
pjmedia_codec *codec )
524
struct amr_data *amr_data;
526
PJ_ASSERT_RETURN(factory && codec, PJ_EINVAL);
527
PJ_ASSERT_RETURN(factory == &amr_codec_factory.base, PJ_EINVAL);
529
amr_data = (struct amr_data*) codec->codec_data;
531
/* Close codec, if it's not closed. */
532
amr_codec_close(codec);
534
pj_pool_release(amr_data->pool);
543
static pj_status_t amr_codec_init( pjmedia_codec *codec,
546
PJ_UNUSED_ARG(codec);
555
static pj_status_t amr_codec_open( pjmedia_codec *codec,
556
pjmedia_codec_param *attr )
558
struct amr_data *amr_data = (struct amr_data*) codec->codec_data;
559
pjmedia_codec_amr_pack_setting *setting;
561
pj_uint8_t octet_align = 0;
563
const pj_str_t STR_FMTP_OCTET_ALIGN = {"octet-align", 11};
566
PJ_ASSERT_RETURN(codec && attr, PJ_EINVAL);
567
PJ_ASSERT_RETURN(amr_data != NULL, PJ_EINVALIDOP);
569
idx = (attr->info.clock_rate <= 8000? IDX_AMR_NB: IDX_AMR_WB);
570
enc_mode = pjmedia_codec_amr_get_mode(attr->info.avg_bps);
571
pj_assert(enc_mode >= 0 && enc_mode < amr_bitrates_size[idx]);
573
/* Check octet-align */
574
for (i = 0; i < attr->setting.dec_fmtp.cnt; ++i) {
575
if (pj_stricmp(&attr->setting.dec_fmtp.param[i].name,
576
&STR_FMTP_OCTET_ALIGN) == 0)
578
octet_align = (pj_uint8_t)
579
(pj_strtoul(&attr->setting.dec_fmtp.param[i].val));
585
for (i = 0; i < attr->setting.enc_fmtp.cnt; ++i) {
586
const pj_str_t STR_FMTP_MODE_SET = {"mode-set", 8};
588
if (pj_stricmp(&attr->setting.enc_fmtp.param[i].name,
589
&STR_FMTP_MODE_SET) == 0)
595
/* Encoding mode is chosen based on local default mode setting:
596
* - if local default mode is included in the mode-set, use it
597
* - otherwise, find the closest mode to local default mode;
598
* if there are two closest modes, prefer to use the higher
599
* one, e.g: local default mode is 4, the mode-set param
600
* contains '2,3,5,6', then 5 will be chosen.
602
p = pj_strbuf(&attr->setting.enc_fmtp.param[i].val);
603
l = pj_strlen(&attr->setting.enc_fmtp.param[i].val);
605
if (*p>='0' && *p<=('0'+amr_bitrates_size[idx]-1)) {
606
pj_int8_t tmp = *p - '0' - enc_mode;
608
if (PJ_ABS(diff) > PJ_ABS(tmp) ||
609
(PJ_ABS(diff) == PJ_ABS(tmp) && tmp > diff))
612
if (diff == 0) break;
617
PJ_ASSERT_RETURN(diff != 99, PJMEDIA_CODEC_EFAILED);
619
enc_mode = enc_mode + diff;
625
amr_data->clock_rate = attr->info.clock_rate;
626
amr_data->vad_enabled = (attr->setting.vad != 0);
627
amr_data->plc_enabled = (attr->setting.plc != 0);
628
amr_data->enc_mode = enc_mode;
630
if (idx == IDX_AMR_NB) {
632
amr_data->encoder = Encoder_Interface_init(amr_data->vad_enabled);
636
amr_data->encoder = E_IF_init();
639
if (amr_data->encoder == NULL) {
640
TRACE_((THIS_FILE, "Encoder initialization failed"));
641
amr_codec_close(codec);
642
return PJMEDIA_CODEC_EFAILED;
644
setting = &amr_data->enc_setting;
645
pj_bzero(setting, sizeof(pjmedia_codec_amr_pack_setting));
646
setting->amr_nb = (idx == IDX_AMR_NB? 1: 0);
647
setting->reorder = 0;
648
setting->octet_aligned = octet_align;
651
if (idx == IDX_AMR_NB) {
653
amr_data->decoder = Decoder_Interface_init();
657
amr_data->decoder = D_IF_init();
660
if (amr_data->decoder == NULL) {
661
TRACE_((THIS_FILE, "Decoder initialization failed"));
662
amr_codec_close(codec);
663
return PJMEDIA_CODEC_EFAILED;
665
setting = &amr_data->dec_setting;
666
pj_bzero(setting, sizeof(pjmedia_codec_amr_pack_setting));
667
setting->amr_nb = (idx == IDX_AMR_NB? 1: 0);
668
setting->reorder = 0;
669
setting->octet_aligned = octet_align;
671
TRACE_((THIS_FILE, "AMR codec allocated: clockrate=%d vad=%d, plc=%d,"
672
" bitrate=%d", amr_data->clock_rate,
673
amr_data->vad_enabled, amr_data->plc_enabled,
674
amr_bitrates[idx][amr_data->enc_mode]));
682
static pj_status_t amr_codec_close( pjmedia_codec *codec )
684
struct amr_data *amr_data;
686
PJ_ASSERT_RETURN(codec, PJ_EINVAL);
688
amr_data = (struct amr_data*) codec->codec_data;
689
PJ_ASSERT_RETURN(amr_data != NULL, PJ_EINVALIDOP);
691
if (amr_data->encoder) {
692
if (amr_data->enc_setting.amr_nb) {
694
Encoder_Interface_exit(amr_data->encoder);
698
E_IF_exit(amr_data->encoder);
701
amr_data->encoder = NULL;
704
if (amr_data->decoder) {
705
if (amr_data->dec_setting.amr_nb) {
707
Decoder_Interface_exit(amr_data->decoder);
711
D_IF_exit(amr_data->decoder);
714
amr_data->decoder = NULL;
717
TRACE_((THIS_FILE, "AMR codec closed"));
723
* Modify codec settings.
725
static pj_status_t amr_codec_modify( pjmedia_codec *codec,
726
const pjmedia_codec_param *attr )
728
struct amr_data *amr_data = (struct amr_data*) codec->codec_data;
729
pj_bool_t prev_vad_state;
731
pj_assert(amr_data != NULL);
732
pj_assert(amr_data->encoder != NULL && amr_data->decoder != NULL);
734
prev_vad_state = amr_data->vad_enabled;
735
amr_data->vad_enabled = (attr->setting.vad != 0);
736
amr_data->plc_enabled = (attr->setting.plc != 0);
738
if (amr_data->enc_setting.amr_nb &&
739
prev_vad_state != amr_data->vad_enabled)
741
/* Reinit AMR encoder to update VAD setting */
742
TRACE_((THIS_FILE, "Reiniting AMR encoder to update VAD setting."));
744
Encoder_Interface_exit(amr_data->encoder);
745
amr_data->encoder = Encoder_Interface_init(amr_data->vad_enabled);
747
if (amr_data->encoder == NULL) {
748
TRACE_((THIS_FILE, "Encoder_Interface_init() failed"));
749
amr_codec_close(codec);
750
return PJMEDIA_CODEC_EFAILED;
754
TRACE_((THIS_FILE, "AMR codec modified: vad=%d, plc=%d",
755
amr_data->vad_enabled, amr_data->plc_enabled));
761
* Get frames in the packet.
763
static pj_status_t amr_codec_parse( pjmedia_codec *codec,
766
const pj_timestamp *ts,
768
pjmedia_frame frames[])
770
struct amr_data *amr_data = (struct amr_data*) codec->codec_data;
773
unsigned idx = (amr_data->enc_setting.amr_nb? 0: 1);
775
status = pjmedia_codec_amr_parse(pkt, pkt_size, ts, &amr_data->dec_setting,
776
frames, frame_cnt, &cmr);
777
if (status != PJ_SUCCESS)
780
/* Check for Change Mode Request. */
781
if (cmr < amr_bitrates_size[idx] && amr_data->enc_mode != cmr) {
782
amr_data->enc_mode = cmr;
783
TRACE_((THIS_FILE, "AMR encoder switched mode to %d (%dbps)",
785
amr_bitrates[idx][amr_data->enc_mode]));
795
static pj_status_t amr_codec_encode( pjmedia_codec *codec,
796
const struct pjmedia_frame *input,
797
unsigned output_buf_len,
798
struct pjmedia_frame *output)
800
struct amr_data *amr_data = (struct amr_data*) codec->codec_data;
801
unsigned char *bitstream;
803
unsigned nsamples, samples_per_frame;
804
enum {MAX_FRAMES_PER_PACKET = 16};
805
pjmedia_frame frames[MAX_FRAMES_PER_PACKET];
807
unsigned i, out_size = 0, nframes = 0;
808
pj_size_t payload_len;
809
unsigned dtx_cnt, sid_cnt;
813
pj_assert(amr_data != NULL);
814
PJ_ASSERT_RETURN(input && output, PJ_EINVAL);
816
nsamples = input->size >> 1;
817
samples_per_frame = amr_data->clock_rate * FRAME_LENGTH_MS / 1000;
818
PJ_ASSERT_RETURN(nsamples % samples_per_frame == 0,
819
PJMEDIA_CODEC_EPCMFRMINLEN);
821
nframes = nsamples / samples_per_frame;
822
PJ_ASSERT_RETURN(nframes <= MAX_FRAMES_PER_PACKET,
823
PJMEDIA_CODEC_EFRMTOOSHORT);
825
/* Encode the frames */
826
speech = (pj_int16_t*)input->buf;
827
bitstream = (unsigned char*)output->buf;
828
while (nsamples >= samples_per_frame) {
829
if (amr_data->enc_setting.amr_nb) {
831
size = Encoder_Interface_Encode (amr_data->encoder,
833
speech, bitstream, 0);
837
size = E_IF_encode (amr_data->encoder, amr_data->enc_mode,
838
speech, bitstream, 0);
844
output->type = PJMEDIA_FRAME_TYPE_NONE;
845
TRACE_((THIS_FILE, "AMR encode() failed"));
846
return PJMEDIA_CODEC_EFAILED;
848
nsamples -= samples_per_frame;
849
speech += samples_per_frame;
852
TRACE_((THIS_FILE, "AMR encode(): mode=%d, size=%d",
853
amr_data->enc_mode, out_size));
857
p = (pj_uint8_t*)output->buf + output_buf_len - out_size;
858
pj_memmove(p, output->buf, out_size);
859
dtx_cnt = sid_cnt = 0;
860
for (i = 0; i < nframes; ++i) {
861
pjmedia_codec_amr_bit_info *info = (pjmedia_codec_amr_bit_info*)
863
info->frame_type = (pj_uint8_t)((*p >> 3) & 0x0F);
864
info->good_quality = (pj_uint8_t)((*p >> 2) & 0x01);
865
info->mode = (pj_int8_t)amr_data->enc_mode;
867
frames[i].buf = p + 1;
868
if (amr_data->enc_setting.amr_nb) {
869
frames[i].size = (info->frame_type <= 8)?
870
pjmedia_codec_amrnb_framelen[info->frame_type] : 0;
872
frames[i].size = (info->frame_type <= 9)?
873
pjmedia_codec_amrwb_framelen[info->frame_type] : 0;
875
p += frames[i].size + 1;
877
/* Count the number of SID and DTX frames */
878
if (info->frame_type == 15) /* DTX*/
880
else if (info->frame_type == 8) /* SID */
884
/* VA generates DTX frames as DTX+SID frames switching quickly and it
885
* seems that the SID frames occur too often (assuming the purpose is
886
* only for keeping NAT alive?). So let's modify the behavior a bit.
887
* Only an SID frame will be sent every PJMEDIA_CODEC_MAX_SILENCE_PERIOD
890
if (sid_cnt + dtx_cnt == nframes) {
891
pj_int32_t dtx_duration;
893
dtx_duration = pj_timestamp_diff32(&amr_data->last_tx,
895
if (PJMEDIA_CODEC_MAX_SILENCE_PERIOD == -1 ||
896
dtx_duration < PJMEDIA_CODEC_MAX_SILENCE_PERIOD*
897
amr_data->clock_rate/1000)
900
output->type = PJMEDIA_FRAME_TYPE_NONE;
901
output->timestamp = input->timestamp;
906
payload_len = output_buf_len;
908
status = pjmedia_codec_amr_pack(frames, nframes, &amr_data->enc_setting,
909
output->buf, &payload_len);
910
if (status != PJ_SUCCESS) {
913
output->type = PJMEDIA_FRAME_TYPE_NONE;
914
TRACE_((THIS_FILE, "Failed to pack AMR payload, status=%d", status));
918
output->size = payload_len;
919
output->type = PJMEDIA_FRAME_TYPE_AUDIO;
920
output->timestamp = input->timestamp;
922
amr_data->last_tx = input->timestamp;
931
static pj_status_t amr_codec_decode( pjmedia_codec *codec,
932
const struct pjmedia_frame *input,
933
unsigned output_buf_len,
934
struct pjmedia_frame *output)
936
struct amr_data *amr_data = (struct amr_data*) codec->codec_data;
937
pjmedia_frame input_;
938
pjmedia_codec_amr_bit_info *info;
940
/* AMR decoding buffer: AMR max frame size + 1 byte header. */
941
unsigned char bitstream[61];
943
pj_assert(amr_data != NULL);
944
PJ_ASSERT_RETURN(input && output, PJ_EINVAL);
946
out_size = amr_data->clock_rate * FRAME_LENGTH_MS / 1000 * 2;
947
if (output_buf_len < out_size)
948
return PJMEDIA_CODEC_EPCMTOOSHORT;
950
input_.buf = &bitstream[1];
951
/* AMR max frame size */
952
input_.size = (amr_data->dec_setting.amr_nb? 31: 60);
953
pjmedia_codec_amr_predecode(input, &amr_data->dec_setting, &input_);
954
info = (pjmedia_codec_amr_bit_info*)&input_.bit_info;
956
/* VA AMR decoder requires frame info in the first byte. */
957
bitstream[0] = (info->frame_type << 3) | (info->good_quality << 2);
959
TRACE_((THIS_FILE, "AMR decode(): mode=%d, ft=%d, size=%d",
960
info->mode, info->frame_type, input_.size));
963
if (amr_data->dec_setting.amr_nb) {
965
Decoder_Interface_Decode(amr_data->decoder, bitstream,
966
(pj_int16_t*)output->buf, 0);
970
D_IF_decode(amr_data->decoder, bitstream,
971
(pj_int16_t*)output->buf, 0);
975
output->size = out_size;
976
output->type = PJMEDIA_FRAME_TYPE_AUDIO;
977
output->timestamp = input->timestamp;
980
if (amr_data->plc_enabled)
981
pjmedia_plc_save(amr_data->plc, (pj_int16_t*)output->buf);
989
* Recover lost frame.
993
* Recover lost frame.
995
static pj_status_t amr_codec_recover( pjmedia_codec *codec,
996
unsigned output_buf_len,
997
struct pjmedia_frame *output)
999
struct amr_data *amr_data = codec->codec_data;
1000
unsigned out_size = amr_data->clock_rate * FRAME_LENGTH_MS / 1000 * 2;
1002
TRACE_((THIS_FILE, "amr_codec_recover"));
1004
PJ_ASSERT_RETURN(amr_data->plc_enabled, PJ_EINVALIDOP);
1006
PJ_ASSERT_RETURN(output_buf_len >= out_size, PJMEDIA_CODEC_EPCMTOOSHORT);
1008
pjmedia_plc_generate(amr_data->plc, (pj_int16_t*)output->buf);
1010
output->size = out_size;
1011
output->type = PJMEDIA_FRAME_TYPE_AUDIO;
1017
#if defined(_MSC_VER) && PJMEDIA_AUTO_LINK_OPENCORE_AMR_LIBS
1018
# if PJMEDIA_OPENCORE_AMR_BUILT_WITH_GCC
1020
# pragma comment( lib, "libopencore-amrnb.a")
1023
# pragma comment( lib, "libopencore-amrwb.a")
1024
# pragma comment( lib, "libvo-amrwbenc.a")
1027
# error Unsupported OpenCORE AMR library, fix here