1
/* $Id: l16.c 3664 2011-07-19 03:42:28Z nanang $ */
3
* Copyright (C) 2008-2011 Teluu Inc. (http://www.teluu.com)
4
* Copyright (C) 2003-2008 Benny Prijono <benny@prijono.org>
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
20
#include <pjmedia-codec/l16.h>
21
#include <pjmedia/codec.h>
22
#include <pjmedia/errno.h>
23
#include <pjmedia/endpoint.h>
24
#include <pjmedia/plc.h>
25
#include <pjmedia/silencedet.h>
26
#include <pj/assert.h>
29
#include <pj/string.h>
33
* Only build this file if PJMEDIA_HAS_L16_CODEC != 0
35
#if defined(PJMEDIA_HAS_L16_CODEC) && PJMEDIA_HAS_L16_CODEC != 0
37
#define PLC_DISABLED 0
40
static const pj_str_t STR_L16 = { "L16", 3 };
42
/* To keep frame size below 1400 MTU, set ptime to 10ms for
43
* sampling rate > 35 KHz
45
#define GET_PTIME(clock_rate) ((pj_uint16_t)(clock_rate > 35000 ? 10 : 20))
48
/* Prototypes for L16 factory */
49
static pj_status_t l16_test_alloc( pjmedia_codec_factory *factory,
50
const pjmedia_codec_info *id );
51
static pj_status_t l16_default_attr( pjmedia_codec_factory *factory,
52
const pjmedia_codec_info *id,
53
pjmedia_codec_param *attr );
54
static pj_status_t l16_enum_codecs (pjmedia_codec_factory *factory,
56
pjmedia_codec_info codecs[]);
57
static pj_status_t l16_alloc_codec( pjmedia_codec_factory *factory,
58
const pjmedia_codec_info *id,
59
pjmedia_codec **p_codec);
60
static pj_status_t l16_dealloc_codec( pjmedia_codec_factory *factory,
61
pjmedia_codec *codec );
63
/* Prototypes for L16 implementation. */
64
static pj_status_t l16_init( pjmedia_codec *codec,
66
static pj_status_t l16_open( pjmedia_codec *codec,
67
pjmedia_codec_param *attr );
68
static pj_status_t l16_close( pjmedia_codec *codec );
69
static pj_status_t l16_modify(pjmedia_codec *codec,
70
const pjmedia_codec_param *attr );
71
static pj_status_t l16_parse(pjmedia_codec *codec,
74
const pj_timestamp *ts,
76
pjmedia_frame frames[]);
77
static pj_status_t l16_encode( pjmedia_codec *codec,
78
const struct pjmedia_frame *input,
79
unsigned output_buf_len,
80
struct pjmedia_frame *output);
81
static pj_status_t l16_decode( pjmedia_codec *codec,
82
const struct pjmedia_frame *input,
83
unsigned output_buf_len,
84
struct pjmedia_frame *output);
86
static pj_status_t l16_recover(pjmedia_codec *codec,
87
unsigned output_buf_len,
88
struct pjmedia_frame *output);
91
/* Definition for L16 codec operations. */
92
static pjmedia_codec_op l16_op =
108
/* Definition for L16 codec factory operations. */
109
static pjmedia_codec_factory_op l16_factory_op =
116
&pjmedia_codec_l16_deinit
119
/* L16 factory private data */
120
static struct l16_factory
122
pjmedia_codec_factory base;
123
pjmedia_endpt *endpt;
129
/* L16 codec private data. */
133
unsigned frame_size; /* Frame size, in bytes */
134
unsigned clock_rate; /* Clock rate */
137
pj_bool_t plc_enabled;
140
pj_bool_t vad_enabled;
141
pjmedia_silence_det *vad;
142
pj_timestamp last_tx;
147
PJ_DEF(pj_status_t) pjmedia_codec_l16_init(pjmedia_endpt *endpt,
150
pjmedia_codec_mgr *codec_mgr;
154
PJ_UNUSED_ARG(options);
157
if (l16_factory.endpt != NULL) {
158
/* Already initialized. */
163
l16_factory.base.op = &l16_factory_op;
164
l16_factory.base.factory_data = NULL;
165
l16_factory.endpt = endpt;
168
l16_factory.pool = pjmedia_endpt_create_pool(endpt, "l16", 4000, 4000);
169
if (!l16_factory.pool)
173
status = pj_mutex_create_simple(l16_factory.pool, "l16",
175
if (status != PJ_SUCCESS)
178
/* Get the codec manager. */
179
codec_mgr = pjmedia_endpt_get_codec_mgr(endpt);
181
return PJ_EINVALIDOP;
184
/* Register codec factory to endpoint. */
185
status = pjmedia_codec_mgr_register_factory(codec_mgr,
187
if (status != PJ_SUCCESS)
194
if (l16_factory.mutex) {
195
pj_mutex_destroy(l16_factory.mutex);
196
l16_factory.mutex = NULL;
198
if (l16_factory.pool) {
199
pj_pool_release(l16_factory.pool);
200
l16_factory.pool = NULL;
205
PJ_DEF(pj_status_t) pjmedia_codec_l16_deinit(void)
207
pjmedia_codec_mgr *codec_mgr;
210
if (l16_factory.endpt == NULL) {
211
/* Not registered. */
216
pj_mutex_lock(l16_factory.mutex);
218
/* Get the codec manager. */
219
codec_mgr = pjmedia_endpt_get_codec_mgr(l16_factory.endpt);
221
l16_factory.endpt = NULL;
222
pj_mutex_unlock(l16_factory.mutex);
223
return PJ_EINVALIDOP;
226
/* Unregister L16 codec factory. */
227
status = pjmedia_codec_mgr_unregister_factory(codec_mgr,
229
l16_factory.endpt = NULL;
232
pj_mutex_destroy(l16_factory.mutex);
233
l16_factory.mutex = NULL;
237
pj_pool_release(l16_factory.pool);
238
l16_factory.pool = NULL;
244
static pj_status_t l16_test_alloc(pjmedia_codec_factory *factory,
245
const pjmedia_codec_info *id )
247
PJ_UNUSED_ARG(factory);
249
if (pj_stricmp(&id->encoding_name, &STR_L16)==0) {
257
static pj_status_t l16_default_attr( pjmedia_codec_factory *factory,
258
const pjmedia_codec_info *id,
259
pjmedia_codec_param *attr )
261
PJ_UNUSED_ARG(factory);
263
pj_bzero(attr, sizeof(pjmedia_codec_param));
264
attr->info.pt = (pj_uint8_t)id->pt;
265
attr->info.clock_rate = id->clock_rate;
266
attr->info.channel_cnt = id->channel_cnt;
267
attr->info.avg_bps = id->clock_rate * id->channel_cnt * 16;
268
attr->info.max_bps = attr->info.avg_bps;
269
attr->info.pcm_bits_per_sample = 16;
271
/* To keep frame size below 1400 MTU, set ptime to 10ms for
272
* sampling rate > 35 KHz
274
attr->info.frm_ptime = GET_PTIME(id->clock_rate);
276
attr->setting.frm_per_pkt = 1;
278
attr->setting.vad = 1;
280
attr->setting.plc = 1;
286
static pj_status_t l16_enum_codecs( pjmedia_codec_factory *factory,
288
pjmedia_codec_info codecs[])
292
PJ_UNUSED_ARG(factory);
294
if (count < *max_count) {
295
/* Register 44100Hz 1 channel L16 codec */
296
codecs[count].type = PJMEDIA_TYPE_AUDIO;
297
codecs[count].pt = PJMEDIA_RTP_PT_L16_1;
298
codecs[count].encoding_name = STR_L16;
299
codecs[count].clock_rate = 44100;
300
codecs[count].channel_cnt = 1;
304
if (count < *max_count) {
305
/* Register 44100Hz 2 channels L16 codec */
306
codecs[count].type = PJMEDIA_TYPE_AUDIO;
307
codecs[count].pt = PJMEDIA_RTP_PT_L16_2;
308
codecs[count].encoding_name = STR_L16;
309
codecs[count].clock_rate = 44100;
310
codecs[count].channel_cnt = 2;
314
if (count < *max_count) {
316
codecs[count].type = PJMEDIA_TYPE_AUDIO;
317
codecs[count].pt = PJMEDIA_RTP_PT_L16_8KHZ_MONO;
318
codecs[count].encoding_name = STR_L16;
319
codecs[count].clock_rate = 8000;
320
codecs[count].channel_cnt = 1;
324
if (count < *max_count) {
326
codecs[count].type = PJMEDIA_TYPE_AUDIO;
327
codecs[count].pt = PJMEDIA_RTP_PT_L16_8KHZ_STEREO;
328
codecs[count].encoding_name = STR_L16;
329
codecs[count].clock_rate = 8000;
330
codecs[count].channel_cnt = 2;
334
// disable some L16 modes
336
if (count < *max_count) {
338
codecs[count].type = PJMEDIA_TYPE_AUDIO;
339
codecs[count].pt = PJMEDIA_RTP_PT_L16_11KHZ_MONO;
340
codecs[count].encoding_name = STR_L16;
341
codecs[count].clock_rate = 11025;
342
codecs[count].channel_cnt = 1;
346
if (count < *max_count) {
347
/* 11025 Hz stereo */
348
codecs[count].type = PJMEDIA_TYPE_AUDIO;
349
codecs[count].pt = PJMEDIA_RTP_PT_L16_11KHZ_STEREO;
350
codecs[count].encoding_name = STR_L16;
351
codecs[count].clock_rate = 11025;
352
codecs[count].channel_cnt = 2;
357
if (count < *max_count) {
359
codecs[count].type = PJMEDIA_TYPE_AUDIO;
360
codecs[count].pt = PJMEDIA_RTP_PT_L16_16KHZ_MONO;
361
codecs[count].encoding_name = STR_L16;
362
codecs[count].clock_rate = 16000;
363
codecs[count].channel_cnt = 1;
368
if (count < *max_count) {
369
/* 16000 Hz stereo */
370
codecs[count].type = PJMEDIA_TYPE_AUDIO;
371
codecs[count].pt = PJMEDIA_RTP_PT_L16_16KHZ_STEREO;
372
codecs[count].encoding_name = STR_L16;
373
codecs[count].clock_rate = 16000;
374
codecs[count].channel_cnt = 2;
378
// disable some L16 modes
380
if (count < *max_count) {
382
codecs[count].type = PJMEDIA_TYPE_AUDIO;
383
codecs[count].pt = PJMEDIA_RTP_PT_L16_22KHZ_MONO;
384
codecs[count].encoding_name = STR_L16;
385
codecs[count].clock_rate = 22050;
386
codecs[count].channel_cnt = 1;
391
if (count < *max_count) {
392
/* 22050 Hz stereo */
393
codecs[count].type = PJMEDIA_TYPE_AUDIO;
394
codecs[count].pt = PJMEDIA_RTP_PT_L16_22KHZ_STEREO;
395
codecs[count].encoding_name = STR_L16;
396
codecs[count].clock_rate = 22050;
397
codecs[count].channel_cnt = 2;
401
if (count < *max_count) {
403
codecs[count].type = PJMEDIA_TYPE_AUDIO;
404
codecs[count].pt = PJMEDIA_RTP_PT_L16_32KHZ_MONO;
405
codecs[count].encoding_name = STR_L16;
406
codecs[count].clock_rate = 32000;
407
codecs[count].channel_cnt = 1;
411
if (count < *max_count) {
412
/* 32000 Hz stereo */
413
codecs[count].type = PJMEDIA_TYPE_AUDIO;
414
codecs[count].pt = PJMEDIA_RTP_PT_L16_32KHZ_STEREO;
415
codecs[count].encoding_name = STR_L16;
416
codecs[count].clock_rate = 32000;
417
codecs[count].channel_cnt = 2;
421
if (count < *max_count) {
423
codecs[count].type = PJMEDIA_TYPE_AUDIO;
424
codecs[count].pt = PJMEDIA_RTP_PT_L16_48KHZ_MONO;
425
codecs[count].encoding_name = STR_L16;
426
codecs[count].clock_rate = 48000;
427
codecs[count].channel_cnt = 1;
431
if (count < *max_count) {
433
codecs[count].type = PJMEDIA_TYPE_AUDIO;
434
codecs[count].pt = PJMEDIA_RTP_PT_L16_48KHZ_STEREO;
435
codecs[count].encoding_name = STR_L16;
436
codecs[count].clock_rate = 48000;
437
codecs[count].channel_cnt = 2;
448
static pj_status_t l16_alloc_codec( pjmedia_codec_factory *factory,
449
const pjmedia_codec_info *id,
450
pjmedia_codec **p_codec)
452
pjmedia_codec *codec = NULL;
453
struct l16_data *data;
459
PJ_ASSERT_RETURN(factory==&l16_factory.base, PJ_EINVAL);
462
pj_mutex_lock(l16_factory.mutex);
465
pool = pjmedia_endpt_create_pool(l16_factory.endpt, "l16", 4000, 4000);
466
codec = PJ_POOL_ZALLOC_T(pool, pjmedia_codec);
467
codec->codec_data = pj_pool_alloc(pool, sizeof(struct l16_data));
468
codec->factory = factory;
471
/* Init private data */
472
ptime = GET_PTIME(id->clock_rate);
473
data = (struct l16_data*) codec->codec_data;
474
data->frame_size = ptime * id->clock_rate * id->channel_cnt * 2 / 1000;
475
data->clock_rate = id->clock_rate;
480
status = pjmedia_plc_create(pool, id->clock_rate,
481
data->frame_size >> 1, 0,
483
if (status != PJ_SUCCESS) {
484
pj_mutex_unlock(l16_factory.mutex);
489
/* Create silence detector */
490
status = pjmedia_silence_det_create(pool, id->clock_rate,
491
data->frame_size >> 1,
493
if (status != PJ_SUCCESS) {
494
pj_mutex_unlock(l16_factory.mutex);
501
pj_mutex_unlock(l16_factory.mutex);
506
static pj_status_t l16_dealloc_codec(pjmedia_codec_factory *factory,
507
pjmedia_codec *codec )
509
struct l16_data *data;
511
PJ_ASSERT_RETURN(factory && codec, PJ_EINVAL);
512
PJ_ASSERT_RETURN(factory==&l16_factory.base, PJ_EINVAL);
515
pj_mutex_lock(l16_factory.mutex);
517
/* Just release codec data pool */
518
data = (struct l16_data*) codec->codec_data;
520
pj_pool_release(data->pool);
523
pj_mutex_unlock(l16_factory.mutex);
528
static pj_status_t l16_init( pjmedia_codec *codec, pj_pool_t *pool )
530
/* There's nothing to do here really */
531
PJ_UNUSED_ARG(codec);
537
static pj_status_t l16_open(pjmedia_codec *codec,
538
pjmedia_codec_param *attr )
540
struct l16_data *data = NULL;
542
PJ_ASSERT_RETURN(codec && codec->codec_data && attr, PJ_EINVAL);
544
data = (struct l16_data*) codec->codec_data;
546
data->vad_enabled = (attr->setting.vad != 0);
548
data->plc_enabled = (attr->setting.plc != 0);
554
static pj_status_t l16_close( pjmedia_codec *codec )
556
PJ_UNUSED_ARG(codec);
561
static pj_status_t l16_modify(pjmedia_codec *codec,
562
const pjmedia_codec_param *attr )
564
struct l16_data *data = (struct l16_data*) codec->codec_data;
566
pj_assert(data != NULL);
568
data->vad_enabled = (attr->setting.vad != 0);
570
data->plc_enabled = (attr->setting.plc != 0);
576
static pj_status_t l16_parse( pjmedia_codec *codec,
579
const pj_timestamp *ts,
581
pjmedia_frame frames[])
584
struct l16_data *data = (struct l16_data*) codec->codec_data;
586
PJ_UNUSED_ARG(codec);
587
PJ_ASSERT_RETURN(frame_cnt, PJ_EINVAL);
589
while (pkt_size >= data->frame_size && count < *frame_cnt) {
590
frames[count].type = PJMEDIA_FRAME_TYPE_AUDIO;
591
frames[count].buf = pkt;
592
frames[count].size = data->frame_size;
593
frames[count].timestamp.u64 = ts->u64 + (count * data->frame_size);
595
pkt = ((char*)pkt) + data->frame_size;
596
pkt_size -= data->frame_size;
605
static pj_status_t l16_encode(pjmedia_codec *codec,
606
const struct pjmedia_frame *input,
607
unsigned output_buf_len,
608
struct pjmedia_frame *output)
610
struct l16_data *data = (struct l16_data*) codec->codec_data;
611
const pj_int16_t *samp = (const pj_int16_t*) input->buf;
612
const pj_int16_t *samp_end = samp + input->size/sizeof(pj_int16_t);
613
pj_int16_t *samp_out = (pj_int16_t*) output->buf;
615
pj_assert(data && input && output);
617
/* Check output buffer length */
618
if (output_buf_len < input->size)
619
return PJMEDIA_CODEC_EFRMTOOSHORT;
622
if (data->vad_enabled) {
623
pj_bool_t is_silence;
624
pj_int32_t silence_duration;
626
silence_duration = pj_timestamp_diff32(&data->last_tx,
629
is_silence = pjmedia_silence_det_detect(data->vad,
630
(const pj_int16_t*) input->buf,
634
(PJMEDIA_CODEC_MAX_SILENCE_PERIOD == -1 ||
635
silence_duration < PJMEDIA_CODEC_MAX_SILENCE_PERIOD*
636
(int)data->clock_rate/1000))
638
output->type = PJMEDIA_FRAME_TYPE_NONE;
641
output->timestamp = input->timestamp;
644
data->last_tx = input->timestamp;
649
#if defined(PJ_IS_LITTLE_ENDIAN) && PJ_IS_LITTLE_ENDIAN!=0
650
while (samp!=samp_end)
651
*samp_out++ = pj_htons(*samp++);
653
pjmedia_copy_samples(samp_out, samp, input->size >> 1);
658
output->type = PJMEDIA_FRAME_TYPE_AUDIO;
659
output->size = input->size;
660
output->timestamp = input->timestamp;
665
static pj_status_t l16_decode(pjmedia_codec *codec,
666
const struct pjmedia_frame *input,
667
unsigned output_buf_len,
668
struct pjmedia_frame *output)
670
struct l16_data *l16_data = (struct l16_data*) codec->codec_data;
671
const pj_int16_t *samp = (const pj_int16_t*) input->buf;
672
const pj_int16_t *samp_end = samp + input->size/sizeof(pj_int16_t);
673
pj_int16_t *samp_out = (pj_int16_t*) output->buf;
675
pj_assert(l16_data != NULL);
676
PJ_ASSERT_RETURN(input && output, PJ_EINVAL);
679
/* Check output buffer length */
680
if (output_buf_len < input->size)
681
return PJMEDIA_CODEC_EPCMTOOSHORT;
685
#if defined(PJ_IS_LITTLE_ENDIAN) && PJ_IS_LITTLE_ENDIAN!=0
686
while (samp!=samp_end)
687
*samp_out++ = pj_htons(*samp++);
689
pjmedia_copy_samples(samp_out, samp, input->size >> 1);
693
output->type = PJMEDIA_FRAME_TYPE_AUDIO;
694
output->size = input->size;
695
output->timestamp = input->timestamp;
698
if (l16_data->plc_enabled)
699
pjmedia_plc_save( l16_data->plc, (pj_int16_t*)output->buf);
707
* Recover lost frame.
709
static pj_status_t l16_recover(pjmedia_codec *codec,
710
unsigned output_buf_len,
711
struct pjmedia_frame *output)
713
struct l16_data *data = (struct l16_data*) codec->codec_data;
715
PJ_ASSERT_RETURN(data->plc_enabled, PJ_EINVALIDOP);
717
PJ_ASSERT_RETURN(output_buf_len >= data->frame_size,
718
PJMEDIA_CODEC_EPCMTOOSHORT);
720
pjmedia_plc_generate(data->plc, (pj_int16_t*)output->buf);
721
output->size = data->frame_size;
727
#endif /* PJMEDIA_HAS_L16_CODEC */