1
/* $Id: conference.c 4198 2012-07-05 10:25:46Z 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/conference.h>
21
#include <pjmedia/alaw_ulaw.h>
22
#include <pjmedia/delaybuf.h>
23
#include <pjmedia/errno.h>
24
#include <pjmedia/port.h>
25
#include <pjmedia/resample.h>
26
#include <pjmedia/silencedet.h>
27
#include <pjmedia/sound_port.h>
28
#include <pjmedia/stereo.h>
30
#include <pj/assert.h>
33
#include <pj/string.h>
35
#if !defined(PJMEDIA_CONF_USE_SWITCH_BOARD) || PJMEDIA_CONF_USE_SWITCH_BOARD==0
37
/* CONF_DEBUG enables detailed operation of the conference bridge.
38
* Beware that it prints large amounts of logs (several lines per frame).
43
# define TRACE_(x) PJ_LOG(5,x)
49
/* REC_FILE macro enables recording of the samples written to the sound
50
* device. The file contains RAW PCM data with no header, and has the
51
* same settings (clock rate etc) as the conference bridge.
52
* This should only be enabled when debugging audio quality *only*.
54
//#define REC_FILE "confrec.pcm"
56
static FILE *fhnd_rec;
60
#define THIS_FILE "conference.c"
62
#define RX_BUF_COUNT PJMEDIA_SOUND_BUFFER_COUNT
64
#define BYTES_PER_SAMPLE 2
66
#define SIGNATURE PJMEDIA_CONF_BRIDGE_SIGNATURE
67
#define SIGNATURE_PORT PJMEDIA_SIG_PORT_CONF_PASV
68
/* Normal level is hardcodec to 128 in all over places */
69
#define NORMAL_LEVEL 128
70
#define SLOT_TYPE unsigned
71
#define INVALID_SLOT ((SLOT_TYPE)-1)
74
/* These are settings to control the adaptivity of changes in the
75
* signal level of the ports, so that sudden change in signal level
76
* in the port does not cause misaligned signal (which causes noise).
78
#define ATTACK_A (conf->clock_rate / conf->samples_per_frame)
83
#define SIMPLE_AGC(last, target) \
85
target = (ATTACK_A*(last+1)+ATTACK_B*target)/(ATTACK_A+ATTACK_B); \
87
target = (DECAY_A*last+DECAY_B*target)/(DECAY_A+DECAY_B)
89
#define MAX_LEVEL (32767)
90
#define MIN_LEVEL (-32768)
92
#define IS_OVERFLOW(s) ((s > MAX_LEVEL) || (s < MIN_LEVEL))
96
* DON'T GET CONFUSED WITH TX/RX!!
98
* TX and RX directions are always viewed from the conference bridge's point
99
* of view, and NOT from the port's point of view. So TX means the bridge
100
* is transmitting to the port, RX means the bridge is receiving from the
106
* This is a port connected to conference bridge.
110
pj_str_t name; /**< Port name. */
111
pjmedia_port *port; /**< get_frame() and put_frame() */
112
pjmedia_port_op rx_setting; /**< Can we receive from this port */
113
pjmedia_port_op tx_setting; /**< Can we transmit to this port */
114
unsigned listener_cnt; /**< Number of listeners. */
115
SLOT_TYPE *listener_slots;/**< Array of listeners. */
116
unsigned transmitter_cnt;/**<Number of transmitters. */
118
/* Shortcut for port info. */
119
unsigned clock_rate; /**< Port's clock rate. */
120
unsigned samples_per_frame; /**< Port's samples per frame. */
121
unsigned channel_count; /**< Port's channel count. */
123
/* Calculated signal levels: */
124
unsigned tx_level; /**< Last tx level to this port. */
125
unsigned rx_level; /**< Last rx level from this port. */
127
/* The normalized signal level adjustment.
128
* A value of 128 (NORMAL_LEVEL) means there's no adjustment.
130
unsigned tx_adj_level; /**< Adjustment for TX. */
131
unsigned rx_adj_level; /**< Adjustment for RX. */
133
/* Resample, for converting clock rate, if they're different. */
134
pjmedia_resample *rx_resample;
135
pjmedia_resample *tx_resample;
137
/* RX buffer is temporary buffer to be used when there is mismatch
138
* between port's sample rate or ptime with conference's sample rate
139
* or ptime. The buffer is used for sampling rate conversion AND/OR to
140
* buffer the samples until there are enough samples to fulfill a
141
* complete frame to be processed by the bridge.
143
* When both sample rate AND ptime of the port match the conference
144
* settings, this buffer will not be created.
146
* This buffer contains samples at port's clock rate.
147
* The size of this buffer is the sum between port's samples per frame
148
* and bridge's samples per frame.
150
pj_int16_t *rx_buf; /**< The RX buffer. */
151
unsigned rx_buf_cap; /**< Max size, in samples */
152
unsigned rx_buf_count; /**< # of samples in the buf. */
154
/* Mix buf is a temporary buffer used to mix all signal received
155
* by this port from all other ports. The mixed signal will be
156
* automatically adjusted to the appropriate level whenever
157
* there is possibility of clipping.
159
* This buffer contains samples at bridge's clock rate.
160
* The size of this buffer is equal to samples per frame of the bridge.
163
int mix_adj; /**< Adjustment level for mix_buf. */
164
int last_mix_adj; /**< Last adjustment level. */
165
pj_int32_t *mix_buf; /**< Total sum of signal. */
167
/* Tx buffer is a temporary buffer to be used when there's mismatch
168
* between port's clock rate or ptime with conference's sample rate
169
* or ptime. This buffer is used as the source of the sampling rate
170
* conversion AND/OR to buffer the samples until there are enough
171
* samples to fulfill a complete frame to be transmitted to the port.
173
* When both sample rate and ptime of the port match the bridge's
174
* settings, this buffer will not be created.
176
* This buffer contains samples at port's clock rate.
177
* The size of this buffer is the sum between port's samples per frame
178
* and bridge's samples per frame.
180
pj_int16_t *tx_buf; /**< Tx buffer. */
181
unsigned tx_buf_cap; /**< Max size, in samples. */
182
unsigned tx_buf_count; /**< # of samples in the buffer. */
184
/* When the port is not receiving signal from any other ports (e.g. when
185
* no other ports is transmitting to this port), the bridge periodically
186
* transmit NULL frame to the port to keep the port "alive" (for example,
187
* a stream port needs this heart-beat to periodically transmit silence
188
* frame to keep NAT binding alive).
190
* This NULL frame should be sent to the port at the port's ptime rate.
191
* So if the port's ptime is greater than the bridge's ptime, the bridge
192
* needs to delay the NULL frame until it's the right time to do so.
194
* This variable keeps track of how many pending NULL samples are being
195
* "held" for this port. Once this value reaches samples_per_frame
196
* value of the port, a NULL frame is sent. The samples value on this
197
* variable is clocked at the port's clock rate.
199
unsigned tx_heart_beat;
201
/* Delay buffer is a special buffer for sound device port (port 0, master
202
* port) and other passive ports (sound device port is also passive port).
204
* We need the delay buffer because we can not expect the mic and speaker
205
* thread to run equally after one another. In most systems, each thread
206
* will run multiple times before the other thread gains execution time.
207
* For example, in my system, mic thread is called three times, then
208
* speaker thread is called three times, and so on. This we call burst.
210
* There is also possibility of drift, unbalanced rate between put_frame
211
* and get_frame operation, in passive ports. If drift happens, snd_buf
212
* needs to be expanded or shrinked.
214
* Burst and drift are handled by delay buffer.
216
pjmedia_delay_buf *delay_buf;
225
unsigned options; /**< Bitmask options. */
226
unsigned max_ports; /**< Maximum ports. */
227
unsigned port_cnt; /**< Current number of ports. */
228
unsigned connect_cnt; /**< Total number of connections */
229
pjmedia_snd_port *snd_dev_port; /**< Sound device port. */
230
pjmedia_port *master_port; /**< Port zero's port. */
231
char master_name_buf[80]; /**< Port0 name buffer. */
232
pj_mutex_t *mutex; /**< Conference mutex. */
233
struct conf_port **ports; /**< Array of ports. */
234
unsigned clock_rate; /**< Sampling rate. */
235
unsigned channel_count;/**< Number of channels (1=mono). */
236
unsigned samples_per_frame; /**< Samples per frame. */
237
unsigned bits_per_sample; /**< Bits per sample. */
242
static pj_status_t put_frame(pjmedia_port *this_port,
243
pjmedia_frame *frame);
244
static pj_status_t get_frame(pjmedia_port *this_port,
245
pjmedia_frame *frame);
246
static pj_status_t get_frame_pasv(pjmedia_port *this_port,
247
pjmedia_frame *frame);
248
static pj_status_t destroy_port(pjmedia_port *this_port);
249
static pj_status_t destroy_port_pasv(pjmedia_port *this_port);
255
static pj_status_t create_conf_port( pj_pool_t *pool,
258
const pj_str_t *name,
259
struct conf_port **p_conf_port)
261
struct conf_port *conf_port;
265
conf_port = PJ_POOL_ZALLOC_T(pool, struct conf_port);
266
PJ_ASSERT_RETURN(conf_port, PJ_ENOMEM);
269
pj_strdup_with_null(pool, &conf_port->name, name);
271
/* Default has tx and rx enabled. */
272
conf_port->rx_setting = PJMEDIA_PORT_ENABLE;
273
conf_port->tx_setting = PJMEDIA_PORT_ENABLE;
275
/* Default level adjustment is 128 (which means no adjustment) */
276
conf_port->tx_adj_level = NORMAL_LEVEL;
277
conf_port->rx_adj_level = NORMAL_LEVEL;
279
/* Create transmit flag array */
280
conf_port->listener_slots = (SLOT_TYPE*)
282
conf->max_ports * sizeof(SLOT_TYPE));
283
PJ_ASSERT_RETURN(conf_port->listener_slots, PJ_ENOMEM);
285
/* Save some port's infos, for convenience. */
287
pjmedia_audio_format_detail *afd;
289
afd = pjmedia_format_get_audio_format_detail(&port->info.fmt, 1);
290
conf_port->port = port;
291
conf_port->clock_rate = afd->clock_rate;
292
conf_port->samples_per_frame = PJMEDIA_AFD_SPF(afd);
293
conf_port->channel_count = afd->channel_count;
295
conf_port->port = NULL;
296
conf_port->clock_rate = conf->clock_rate;
297
conf_port->samples_per_frame = conf->samples_per_frame;
298
conf_port->channel_count = conf->channel_count;
301
/* If port's clock rate is different than conference's clock rate,
302
* create a resample sessions.
304
if (conf_port->clock_rate != conf->clock_rate) {
306
pj_bool_t high_quality;
307
pj_bool_t large_filter;
309
high_quality = ((conf->options & PJMEDIA_CONF_USE_LINEAR)==0);
310
large_filter = ((conf->options & PJMEDIA_CONF_SMALL_FILTER)==0);
312
/* Create resample for rx buffer. */
313
status = pjmedia_resample_create( pool,
317
conf_port->clock_rate,/* Rate in */
318
conf->clock_rate, /* Rate out */
319
conf->samples_per_frame *
320
conf_port->clock_rate /
322
&conf_port->rx_resample);
323
if (status != PJ_SUCCESS)
327
/* Create resample for tx buffer. */
328
status = pjmedia_resample_create(pool,
332
conf->clock_rate, /* Rate in */
333
conf_port->clock_rate, /* Rate out */
334
conf->samples_per_frame,
335
&conf_port->tx_resample);
336
if (status != PJ_SUCCESS)
341
* Initialize rx and tx buffer, only when port's samples per frame or
342
* port's clock rate or channel number is different then the conference
345
if (conf_port->clock_rate != conf->clock_rate ||
346
conf_port->channel_count != conf->channel_count ||
347
conf_port->samples_per_frame != conf->samples_per_frame)
349
unsigned port_ptime, conf_ptime, buff_ptime;
351
port_ptime = conf_port->samples_per_frame / conf_port->channel_count *
352
1000 / conf_port->clock_rate;
353
conf_ptime = conf->samples_per_frame / conf->channel_count *
354
1000 / conf->clock_rate;
356
/* Calculate the size (in ptime) for the port buffer according to
358
* - if either ptime is an exact multiple of the other, then use
359
* the larger ptime (e.g. 20ms and 40ms, use 40ms).
360
* - if not, then the ptime is sum of both ptimes (e.g. 20ms
361
* and 30ms, use 50ms)
363
if (port_ptime > conf_ptime) {
364
buff_ptime = port_ptime;
365
if (port_ptime % conf_ptime)
366
buff_ptime += conf_ptime;
368
buff_ptime = conf_ptime;
369
if (conf_ptime % port_ptime)
370
buff_ptime += port_ptime;
373
/* Create RX buffer. */
374
//conf_port->rx_buf_cap = (unsigned)(conf_port->samples_per_frame +
375
// conf->samples_per_frame *
376
// conf_port->clock_rate * 1.0 /
377
// conf->clock_rate + 0.5);
378
conf_port->rx_buf_cap = conf_port->clock_rate * buff_ptime / 1000;
379
if (conf_port->channel_count > conf->channel_count)
380
conf_port->rx_buf_cap *= conf_port->channel_count;
382
conf_port->rx_buf_cap *= conf->channel_count;
384
conf_port->rx_buf_count = 0;
385
conf_port->rx_buf = (pj_int16_t*)
386
pj_pool_alloc(pool, conf_port->rx_buf_cap *
387
sizeof(conf_port->rx_buf[0]));
388
PJ_ASSERT_RETURN(conf_port->rx_buf, PJ_ENOMEM);
390
/* Create TX buffer. */
391
conf_port->tx_buf_cap = conf_port->rx_buf_cap;
392
conf_port->tx_buf_count = 0;
393
conf_port->tx_buf = (pj_int16_t*)
394
pj_pool_alloc(pool, conf_port->tx_buf_cap *
395
sizeof(conf_port->tx_buf[0]));
396
PJ_ASSERT_RETURN(conf_port->tx_buf, PJ_ENOMEM);
400
/* Create mix buffer. */
401
conf_port->mix_buf = (pj_int32_t*)
402
pj_pool_zalloc(pool, conf->samples_per_frame *
403
sizeof(conf_port->mix_buf[0]));
404
PJ_ASSERT_RETURN(conf_port->mix_buf, PJ_ENOMEM);
405
conf_port->last_mix_adj = NORMAL_LEVEL;
409
*p_conf_port = conf_port;
417
static pj_status_t create_pasv_port( pjmedia_conf *conf,
419
const pj_str_t *name,
421
struct conf_port **p_conf_port)
423
struct conf_port *conf_port;
428
status = create_conf_port(pool, conf, port, name, &conf_port);
429
if (status != PJ_SUCCESS)
432
/* Passive port has delay buf. */
433
ptime = conf->samples_per_frame * 1000 / conf->clock_rate /
435
status = pjmedia_delay_buf_create(pool, name->ptr,
437
conf->samples_per_frame,
439
RX_BUF_COUNT * ptime, /* max delay */
441
&conf_port->delay_buf);
442
if (status != PJ_SUCCESS)
445
*p_conf_port = conf_port;
452
* Create port zero for the sound device.
454
static pj_status_t create_sound_port( pj_pool_t *pool,
457
struct conf_port *conf_port;
458
pj_str_t name = { "Master/sound", 12 };
462
status = create_pasv_port(conf, pool, &name, NULL, &conf_port);
463
if (status != PJ_SUCCESS)
467
/* Create sound device port: */
469
if ((conf->options & PJMEDIA_CONF_NO_DEVICE) == 0) {
470
pjmedia_aud_stream *strm;
471
pjmedia_aud_param param;
474
* If capture is disabled then create player only port.
475
* Otherwise create bidirectional sound device port.
477
if (conf->options & PJMEDIA_CONF_NO_MIC) {
478
status = pjmedia_snd_port_create_player(pool, -1, conf->clock_rate,
480
conf->samples_per_frame,
481
conf->bits_per_sample,
483
&conf->snd_dev_port);
486
status = pjmedia_snd_port_create( pool, -1, -1, conf->clock_rate,
488
conf->samples_per_frame,
489
conf->bits_per_sample,
491
&conf->snd_dev_port);
495
if (status != PJ_SUCCESS)
498
strm = pjmedia_snd_port_get_snd_stream(conf->snd_dev_port);
499
status = pjmedia_aud_stream_get_param(strm, ¶m);
500
if (status == PJ_SUCCESS) {
501
pjmedia_aud_dev_info snd_dev_info;
502
if (conf->options & PJMEDIA_CONF_NO_MIC)
503
pjmedia_aud_dev_get_info(param.play_id, &snd_dev_info);
505
pjmedia_aud_dev_get_info(param.rec_id, &snd_dev_info);
506
pj_strdup2_with_null(pool, &conf_port->name, snd_dev_info.name);
509
PJ_LOG(5,(THIS_FILE, "Sound device successfully created for port 0"));
513
/* Add the port to the bridge */
514
conf->ports[0] = conf_port;
521
* Create conference bridge.
523
PJ_DEF(pj_status_t) pjmedia_conf_create( pj_pool_t *pool,
526
unsigned channel_count,
527
unsigned samples_per_frame,
528
unsigned bits_per_sample,
530
pjmedia_conf **p_conf )
533
const pj_str_t name = { "Conf", 4 };
536
/* Can only accept 16bits per sample, for now.. */
537
PJ_ASSERT_RETURN(bits_per_sample == 16, PJ_EINVAL);
539
PJ_LOG(5,(THIS_FILE, "Creating conference bridge with %d ports",
542
/* Create and init conf structure. */
543
conf = PJ_POOL_ZALLOC_T(pool, pjmedia_conf);
544
PJ_ASSERT_RETURN(conf, PJ_ENOMEM);
546
conf->ports = (struct conf_port**)
547
pj_pool_zalloc(pool, max_ports*sizeof(void*));
548
PJ_ASSERT_RETURN(conf->ports, PJ_ENOMEM);
550
conf->options = options;
551
conf->max_ports = max_ports;
552
conf->clock_rate = clock_rate;
553
conf->channel_count = channel_count;
554
conf->samples_per_frame = samples_per_frame;
555
conf->bits_per_sample = bits_per_sample;
558
/* Create and initialize the master port interface. */
559
conf->master_port = PJ_POOL_ZALLOC_T(pool, pjmedia_port);
560
PJ_ASSERT_RETURN(conf->master_port, PJ_ENOMEM);
562
pjmedia_port_info_init(&conf->master_port->info, &name, SIGNATURE,
563
clock_rate, channel_count, bits_per_sample,
566
conf->master_port->port_data.pdata = conf;
567
conf->master_port->port_data.ldata = 0;
569
conf->master_port->get_frame = &get_frame;
570
conf->master_port->put_frame = &put_frame;
571
conf->master_port->on_destroy = &destroy_port;
574
/* Create port zero for sound device. */
575
status = create_sound_port(pool, conf);
576
if (status != PJ_SUCCESS) {
577
pjmedia_conf_destroy(conf);
582
status = pj_mutex_create_recursive(pool, "conf", &conf->mutex);
583
if (status != PJ_SUCCESS) {
584
pjmedia_conf_destroy(conf);
588
/* If sound device was created, connect sound device to the
591
if (conf->snd_dev_port) {
592
status = pjmedia_snd_port_connect( conf->snd_dev_port,
594
if (status != PJ_SUCCESS) {
595
pjmedia_conf_destroy(conf);
610
* Pause sound device.
612
static pj_status_t pause_sound( pjmedia_conf *conf )
620
* Resume sound device.
622
static pj_status_t resume_sound( pjmedia_conf *conf )
631
* Destroy conference bridge.
633
PJ_DEF(pj_status_t) pjmedia_conf_destroy( pjmedia_conf *conf )
637
PJ_ASSERT_RETURN(conf != NULL, PJ_EINVAL);
639
/* Destroy sound device port. */
640
if (conf->snd_dev_port) {
641
pjmedia_snd_port_destroy(conf->snd_dev_port);
642
conf->snd_dev_port = NULL;
645
/* Destroy delay buf of all (passive) ports. */
646
for (i=0, ci=0; i<conf->max_ports && ci<conf->port_cnt; ++i) {
647
struct conf_port *cport;
649
cport = conf->ports[i];
654
if (cport->delay_buf) {
655
pjmedia_delay_buf_destroy(cport->delay_buf);
656
cport->delay_buf = NULL;
662
pj_mutex_destroy(conf->mutex);
669
* Destroy the master port (will destroy the conference)
671
static pj_status_t destroy_port(pjmedia_port *this_port)
673
pjmedia_conf *conf = (pjmedia_conf*) this_port->port_data.pdata;
674
return pjmedia_conf_destroy(conf);
677
static pj_status_t destroy_port_pasv(pjmedia_port *this_port) {
678
pjmedia_conf *conf = (pjmedia_conf*) this_port->port_data.pdata;
679
struct conf_port *port = conf->ports[this_port->port_data.ldata];
682
status = pjmedia_delay_buf_destroy(port->delay_buf);
683
if (status == PJ_SUCCESS)
684
port->delay_buf = NULL;
690
* Get port zero interface.
692
PJ_DEF(pjmedia_port*) pjmedia_conf_get_master_port(pjmedia_conf *conf)
695
PJ_ASSERT_RETURN(conf != NULL, NULL);
697
/* Can only return port interface when PJMEDIA_CONF_NO_DEVICE was
698
* present in the option.
700
PJ_ASSERT_RETURN((conf->options & PJMEDIA_CONF_NO_DEVICE) != 0, NULL);
702
return conf->master_port;
707
* Set master port name.
709
PJ_DEF(pj_status_t) pjmedia_conf_set_port0_name(pjmedia_conf *conf,
710
const pj_str_t *name)
715
PJ_ASSERT_RETURN(conf != NULL && name != NULL, PJ_EINVAL);
718
if (len > sizeof(conf->master_name_buf))
719
len = sizeof(conf->master_name_buf);
721
if (len > 0) pj_memcpy(conf->master_name_buf, name->ptr, len);
723
conf->ports[0]->name.ptr = conf->master_name_buf;
724
conf->ports[0]->name.slen = len;
726
if (conf->master_port)
727
conf->master_port->info.name = conf->ports[0]->name;
733
* Add stream port to the conference bridge.
735
PJ_DEF(pj_status_t) pjmedia_conf_add_port( pjmedia_conf *conf,
737
pjmedia_port *strm_port,
738
const pj_str_t *port_name,
741
struct conf_port *conf_port;
745
PJ_ASSERT_RETURN(conf && pool && strm_port, PJ_EINVAL);
747
/* If port_name is not specified, use the port's name */
749
port_name = &strm_port->info.name;
751
/* For this version of PJMEDIA, channel(s) number MUST be:
752
* - same between port & conference bridge.
753
* - monochannel on port or conference bridge.
755
if (PJMEDIA_PIA_CCNT(&strm_port->info) != conf->channel_count &&
756
(PJMEDIA_PIA_CCNT(&strm_port->info) != 1 &&
757
conf->channel_count != 1))
759
pj_assert(!"Number of channels mismatch");
760
return PJMEDIA_ENCCHANNEL;
763
pj_mutex_lock(conf->mutex);
765
if (conf->port_cnt >= conf->max_ports) {
766
pj_assert(!"Too many ports");
767
pj_mutex_unlock(conf->mutex);
771
/* Find empty port in the conference bridge. */
772
for (index=0; index < conf->max_ports; ++index) {
773
if (conf->ports[index] == NULL)
777
pj_assert(index != conf->max_ports);
779
/* Create conf port structure. */
780
status = create_conf_port(pool, conf, strm_port, port_name, &conf_port);
781
if (status != PJ_SUCCESS) {
782
pj_mutex_unlock(conf->mutex);
787
conf->ports[index] = conf_port;
795
pj_mutex_unlock(conf->mutex);
804
PJ_DEF(pj_status_t) pjmedia_conf_add_passive_port( pjmedia_conf *conf,
806
const pj_str_t *name,
808
unsigned channel_count,
809
unsigned samples_per_frame,
810
unsigned bits_per_sample,
813
pjmedia_port **p_port )
815
struct conf_port *conf_port;
821
PJ_LOG(1, (THIS_FILE, "This API has been deprecated since 1.3 and will "
822
"be removed in the future release!"));
824
PJ_ASSERT_RETURN(conf && pool, PJ_EINVAL);
826
/* For this version of PJMEDIA, channel(s) number MUST be:
827
* - same between port & conference bridge.
828
* - monochannel on port or conference bridge.
830
if (channel_count != conf->channel_count &&
831
(channel_count != 1 && conf->channel_count != 1))
833
pj_assert(!"Number of channels mismatch");
834
return PJMEDIA_ENCCHANNEL;
837
/* For this version, options must be zero */
838
PJ_ASSERT_RETURN(options == 0, PJ_EINVAL);
839
PJ_UNUSED_ARG(options);
841
pj_mutex_lock(conf->mutex);
843
if (conf->port_cnt >= conf->max_ports) {
844
pj_assert(!"Too many ports");
845
pj_mutex_unlock(conf->mutex);
849
/* Find empty port in the conference bridge. */
850
for (index=0; index < conf->max_ports; ++index) {
851
if (conf->ports[index] == NULL)
855
pj_assert(index != conf->max_ports);
860
tmp.ptr = (char*) pj_pool_alloc(pool, 32);
861
tmp.slen = pj_ansi_snprintf(tmp.ptr, 32, "ConfPort#%d", index);
864
/* Create and initialize the media port structure. */
865
port = PJ_POOL_ZALLOC_T(pool, pjmedia_port);
866
PJ_ASSERT_RETURN(port, PJ_ENOMEM);
868
pjmedia_port_info_init(&port->info, name, SIGNATURE_PORT,
869
clock_rate, channel_count, bits_per_sample,
872
port->port_data.pdata = conf;
873
port->port_data.ldata = index;
875
port->get_frame = &get_frame_pasv;
876
port->put_frame = &put_frame;
877
port->on_destroy = &destroy_port_pasv;
880
/* Create conf port structure. */
881
status = create_pasv_port(conf, pool, name, port, &conf_port);
882
if (status != PJ_SUCCESS) {
883
pj_mutex_unlock(conf->mutex);
889
conf->ports[index] = conf_port;
898
pj_mutex_unlock(conf->mutex);
906
* Change TX and RX settings for the port.
908
PJ_DEF(pj_status_t) pjmedia_conf_configure_port( pjmedia_conf *conf,
913
struct conf_port *conf_port;
915
/* Check arguments */
916
PJ_ASSERT_RETURN(conf && slot<conf->max_ports, PJ_EINVAL);
918
pj_mutex_lock(conf->mutex);
920
/* Port must be valid. */
921
conf_port = conf->ports[slot];
922
if (conf_port == NULL) {
923
pj_mutex_unlock(conf->mutex);
927
conf_port = conf->ports[slot];
929
if (tx != PJMEDIA_PORT_NO_CHANGE)
930
conf_port->tx_setting = tx;
932
if (rx != PJMEDIA_PORT_NO_CHANGE)
933
conf_port->rx_setting = rx;
935
pj_mutex_unlock(conf->mutex);
944
PJ_DEF(pj_status_t) pjmedia_conf_connect_port( pjmedia_conf *conf,
949
struct conf_port *src_port, *dst_port;
950
pj_bool_t start_sound = PJ_FALSE;
953
/* Check arguments */
954
PJ_ASSERT_RETURN(conf && src_slot<conf->max_ports &&
955
sink_slot<conf->max_ports, PJ_EINVAL);
957
/* For now, level MUST be zero. */
958
PJ_ASSERT_RETURN(level == 0, PJ_EINVAL);
960
pj_mutex_lock(conf->mutex);
962
/* Ports must be valid. */
963
src_port = conf->ports[src_slot];
964
dst_port = conf->ports[sink_slot];
965
if (!src_port || !dst_port) {
966
pj_mutex_unlock(conf->mutex);
970
/* Check if connection has been made */
971
for (i=0; i<src_port->listener_cnt; ++i) {
972
if (src_port->listener_slots[i] == sink_slot)
976
if (i == src_port->listener_cnt) {
977
src_port->listener_slots[src_port->listener_cnt] = sink_slot;
979
++src_port->listener_cnt;
980
++dst_port->transmitter_cnt;
982
if (conf->connect_cnt == 1)
985
PJ_LOG(4,(THIS_FILE,"Port %d (%.*s) transmitting to port %d (%.*s)",
987
(int)src_port->name.slen,
990
(int)dst_port->name.slen,
991
dst_port->name.ptr));
994
pj_mutex_unlock(conf->mutex);
996
/* Sound device must be started without mutex, otherwise the
997
* sound thread will deadlock (?)
1009
PJ_DEF(pj_status_t) pjmedia_conf_disconnect_port( pjmedia_conf *conf,
1011
unsigned sink_slot )
1013
struct conf_port *src_port, *dst_port;
1016
/* Check arguments */
1017
PJ_ASSERT_RETURN(conf && src_slot<conf->max_ports &&
1018
sink_slot<conf->max_ports, PJ_EINVAL);
1020
pj_mutex_lock(conf->mutex);
1022
/* Ports must be valid. */
1023
src_port = conf->ports[src_slot];
1024
dst_port = conf->ports[sink_slot];
1025
if (!src_port || !dst_port) {
1026
pj_mutex_unlock(conf->mutex);
1030
/* Check if connection has been made */
1031
for (i=0; i<src_port->listener_cnt; ++i) {
1032
if (src_port->listener_slots[i] == sink_slot)
1036
if (i != src_port->listener_cnt) {
1037
pj_assert(src_port->listener_cnt > 0 &&
1038
src_port->listener_cnt < conf->max_ports);
1039
pj_assert(dst_port->transmitter_cnt > 0 &&
1040
dst_port->transmitter_cnt < conf->max_ports);
1041
pj_array_erase(src_port->listener_slots, sizeof(SLOT_TYPE),
1042
src_port->listener_cnt, i);
1043
--conf->connect_cnt;
1044
--src_port->listener_cnt;
1045
--dst_port->transmitter_cnt;
1047
PJ_LOG(4,(THIS_FILE,
1048
"Port %d (%.*s) stop transmitting to port %d (%.*s)",
1050
(int)src_port->name.slen,
1053
(int)dst_port->name.slen,
1054
dst_port->name.ptr));
1056
/* if source port is passive port and has no listener, reset delaybuf */
1057
if (src_port->delay_buf && src_port->listener_cnt == 0)
1058
pjmedia_delay_buf_reset(src_port->delay_buf);
1061
pj_mutex_unlock(conf->mutex);
1063
if (conf->connect_cnt == 0) {
1071
* Get number of ports currently registered to the conference bridge.
1073
PJ_DEF(unsigned) pjmedia_conf_get_port_count(pjmedia_conf *conf)
1075
return conf->port_cnt;
1079
* Get total number of ports connections currently set up in the bridge.
1081
PJ_DEF(unsigned) pjmedia_conf_get_connect_count(pjmedia_conf *conf)
1083
return conf->connect_cnt;
1088
* Remove the specified port.
1090
PJ_DEF(pj_status_t) pjmedia_conf_remove_port( pjmedia_conf *conf,
1093
struct conf_port *conf_port;
1096
/* Check arguments */
1097
PJ_ASSERT_RETURN(conf && port < conf->max_ports, PJ_EINVAL);
1099
/* Suspend the sound devices.
1100
* Don't want to remove port while port is being accessed by sound
1104
pj_mutex_lock(conf->mutex);
1106
/* Port must be valid. */
1107
conf_port = conf->ports[port];
1108
if (conf_port == NULL) {
1109
pj_mutex_unlock(conf->mutex);
1113
conf_port->tx_setting = PJMEDIA_PORT_DISABLE;
1114
conf_port->rx_setting = PJMEDIA_PORT_DISABLE;
1116
/* Remove this port from transmit array of other ports. */
1117
for (i=0; i<conf->max_ports; ++i) {
1119
struct conf_port *src_port;
1121
src_port = conf->ports[i];
1126
if (src_port->listener_cnt == 0)
1129
for (j=0; j<src_port->listener_cnt; ++j) {
1130
if (src_port->listener_slots[j] == port) {
1131
pj_array_erase(src_port->listener_slots, sizeof(SLOT_TYPE),
1132
src_port->listener_cnt, j);
1133
pj_assert(conf->connect_cnt > 0);
1134
--conf->connect_cnt;
1135
--src_port->listener_cnt;
1141
/* Update transmitter_cnt of ports we're transmitting to */
1142
while (conf_port->listener_cnt) {
1144
struct conf_port *dst_port;
1146
dst_slot = conf_port->listener_slots[conf_port->listener_cnt-1];
1147
dst_port = conf->ports[dst_slot];
1148
--dst_port->transmitter_cnt;
1149
--conf_port->listener_cnt;
1150
pj_assert(conf->connect_cnt > 0);
1151
--conf->connect_cnt;
1154
/* Destroy pjmedia port if this conf port is passive port,
1155
* i.e: has delay buf.
1157
if (conf_port->delay_buf) {
1158
pjmedia_port_destroy(conf_port->port);
1159
conf_port->port = NULL;
1162
/* Remove the port. */
1163
conf->ports[port] = NULL;
1166
pj_mutex_unlock(conf->mutex);
1169
/* Stop sound if there's no connection. */
1170
if (conf->connect_cnt == 0) {
1181
PJ_DEF(pj_status_t) pjmedia_conf_enum_ports( pjmedia_conf *conf,
1185
unsigned i, count=0;
1187
PJ_ASSERT_RETURN(conf && p_count && ports, PJ_EINVAL);
1190
pj_mutex_lock(conf->mutex);
1192
for (i=0; i<conf->max_ports && count<*p_count; ++i) {
1193
if (!conf->ports[i])
1200
pj_mutex_unlock(conf->mutex);
1209
PJ_DEF(pj_status_t) pjmedia_conf_get_port_info( pjmedia_conf *conf,
1211
pjmedia_conf_port_info *info)
1213
struct conf_port *conf_port;
1215
/* Check arguments */
1216
PJ_ASSERT_RETURN(conf && slot<conf->max_ports, PJ_EINVAL);
1219
pj_mutex_lock(conf->mutex);
1221
/* Port must be valid. */
1222
conf_port = conf->ports[slot];
1223
if (conf_port == NULL) {
1224
pj_mutex_unlock(conf->mutex);
1229
info->name = conf_port->name;
1230
info->tx_setting = conf_port->tx_setting;
1231
info->rx_setting = conf_port->rx_setting;
1232
info->listener_cnt = conf_port->listener_cnt;
1233
info->listener_slots = conf_port->listener_slots;
1234
info->transmitter_cnt = conf_port->transmitter_cnt;
1235
info->clock_rate = conf_port->clock_rate;
1236
info->channel_count = conf_port->channel_count;
1237
info->samples_per_frame = conf_port->samples_per_frame;
1238
info->bits_per_sample = conf->bits_per_sample;
1239
info->tx_adj_level = conf_port->tx_adj_level - NORMAL_LEVEL;
1240
info->rx_adj_level = conf_port->rx_adj_level - NORMAL_LEVEL;
1243
pj_mutex_unlock(conf->mutex);
1249
PJ_DEF(pj_status_t) pjmedia_conf_get_ports_info(pjmedia_conf *conf,
1251
pjmedia_conf_port_info info[])
1253
unsigned i, count=0;
1255
PJ_ASSERT_RETURN(conf && size && info, PJ_EINVAL);
1258
pj_mutex_lock(conf->mutex);
1260
for (i=0; i<conf->max_ports && count<*size; ++i) {
1261
if (!conf->ports[i])
1264
pjmedia_conf_get_port_info(conf, i, &info[count]);
1269
pj_mutex_unlock(conf->mutex);
1279
PJ_DEF(pj_status_t) pjmedia_conf_get_signal_level( pjmedia_conf *conf,
1284
struct conf_port *conf_port;
1286
/* Check arguments */
1287
PJ_ASSERT_RETURN(conf && slot<conf->max_ports, PJ_EINVAL);
1290
pj_mutex_lock(conf->mutex);
1292
/* Port must be valid. */
1293
conf_port = conf->ports[slot];
1294
if (conf_port == NULL) {
1295
pj_mutex_unlock(conf->mutex);
1299
if (tx_level != NULL) {
1300
*tx_level = conf_port->tx_level;
1303
if (rx_level != NULL)
1304
*rx_level = conf_port->rx_level;
1307
pj_mutex_unlock(conf->mutex);
1314
* Adjust RX level of individual port.
1316
PJ_DEF(pj_status_t) pjmedia_conf_adjust_rx_level( pjmedia_conf *conf,
1320
struct conf_port *conf_port;
1322
/* Check arguments */
1323
PJ_ASSERT_RETURN(conf && slot<conf->max_ports, PJ_EINVAL);
1325
/* Value must be from -128 to +127 */
1326
/* Disabled, you can put more than +127, at your own risk:
1327
PJ_ASSERT_RETURN(adj_level >= -128 && adj_level <= 127, PJ_EINVAL);
1329
PJ_ASSERT_RETURN(adj_level >= -128, PJ_EINVAL);
1332
pj_mutex_lock(conf->mutex);
1334
/* Port must be valid. */
1335
conf_port = conf->ports[slot];
1336
if (conf_port == NULL) {
1337
pj_mutex_unlock(conf->mutex);
1341
/* Set normalized adjustment level. */
1342
conf_port->rx_adj_level = adj_level + NORMAL_LEVEL;
1345
pj_mutex_unlock(conf->mutex);
1352
* Adjust TX level of individual port.
1354
PJ_DEF(pj_status_t) pjmedia_conf_adjust_tx_level( pjmedia_conf *conf,
1358
struct conf_port *conf_port;
1360
/* Check arguments */
1361
PJ_ASSERT_RETURN(conf && slot<conf->max_ports, PJ_EINVAL);
1363
/* Value must be from -128 to +127 */
1364
/* Disabled, you can put more than +127,, at your own risk:
1365
PJ_ASSERT_RETURN(adj_level >= -128 && adj_level <= 127, PJ_EINVAL);
1367
PJ_ASSERT_RETURN(adj_level >= -128, PJ_EINVAL);
1370
pj_mutex_lock(conf->mutex);
1372
/* Port must be valid. */
1373
conf_port = conf->ports[slot];
1374
if (conf_port == NULL) {
1375
pj_mutex_unlock(conf->mutex);
1379
/* Set normalized adjustment level. */
1380
conf_port->tx_adj_level = adj_level + NORMAL_LEVEL;
1383
pj_mutex_unlock(conf->mutex);
1392
static pj_status_t read_port( pjmedia_conf *conf,
1393
struct conf_port *cport, pj_int16_t *frame,
1394
pj_size_t count, pjmedia_frame_type *type )
1397
pj_assert(count == conf->samples_per_frame);
1399
TRACE_((THIS_FILE, "read_port %.*s: count=%d",
1400
(int)cport->name.slen, cport->name.ptr,
1404
* If port's samples per frame and sampling rate and channel count
1405
* matche conference bridge's settings, get the frame directly from
1408
if (cport->rx_buf_cap == 0) {
1413
f.size = count * BYTES_PER_SAMPLE;
1415
TRACE_((THIS_FILE, " get_frame %.*s: count=%d",
1416
(int)cport->name.slen, cport->name.ptr,
1419
status = pjmedia_port_get_frame(cport->port, &f);
1426
unsigned samples_req;
1428
/* Initialize frame type */
1429
if (cport->rx_buf_count == 0) {
1430
*type = PJMEDIA_FRAME_TYPE_NONE;
1432
/* we got some samples in the buffer */
1433
*type = PJMEDIA_FRAME_TYPE_AUDIO;
1437
* If we don't have enough samples in rx_buf, read from the port
1438
* first. Remember that rx_buf may be in different clock rate and
1442
samples_req = (unsigned) (count * 1.0 *
1443
cport->clock_rate / conf->clock_rate + 0.5);
1445
while (cport->rx_buf_count < samples_req) {
1450
f.buf = cport->rx_buf + cport->rx_buf_count;
1451
f.size = cport->samples_per_frame * BYTES_PER_SAMPLE;
1453
TRACE_((THIS_FILE, " get_frame, count=%d",
1454
cport->samples_per_frame));
1456
status = pjmedia_port_get_frame(cport->port, &f);
1458
if (status != PJ_SUCCESS) {
1463
if (f.type != PJMEDIA_FRAME_TYPE_AUDIO) {
1464
TRACE_((THIS_FILE, " get_frame returned non-audio"));
1465
pjmedia_zero_samples( cport->rx_buf + cport->rx_buf_count,
1466
cport->samples_per_frame);
1468
/* We've got at least one frame */
1469
*type = PJMEDIA_FRAME_TYPE_AUDIO;
1472
/* Adjust channels */
1473
if (cport->channel_count != conf->channel_count) {
1474
if (cport->channel_count == 1) {
1475
pjmedia_convert_channel_1ton((pj_int16_t*)f.buf,
1476
(const pj_int16_t*)f.buf,
1477
conf->channel_count,
1478
cport->samples_per_frame,
1480
cport->rx_buf_count += (cport->samples_per_frame *
1481
conf->channel_count);
1482
} else { /* conf->channel_count == 1 */
1483
pjmedia_convert_channel_nto1((pj_int16_t*)f.buf,
1484
(const pj_int16_t*)f.buf,
1485
cport->channel_count,
1486
cport->samples_per_frame,
1487
PJMEDIA_STEREO_MIX, 0);
1488
cport->rx_buf_count += (cport->samples_per_frame /
1489
cport->channel_count);
1492
cport->rx_buf_count += cport->samples_per_frame;
1495
TRACE_((THIS_FILE, " rx buffer size is now %d",
1496
cport->rx_buf_count));
1498
pj_assert(cport->rx_buf_count <= cport->rx_buf_cap);
1502
* If port's clock_rate is different, resample.
1503
* Otherwise just copy.
1505
if (cport->clock_rate != conf->clock_rate) {
1509
TRACE_((THIS_FILE, " resample, input count=%d",
1510
pjmedia_resample_get_input_size(cport->rx_resample)));
1512
pjmedia_resample_run( cport->rx_resample,cport->rx_buf, frame);
1514
src_count = (unsigned)(count * 1.0 * cport->clock_rate /
1515
conf->clock_rate + 0.5);
1516
cport->rx_buf_count -= src_count;
1517
if (cport->rx_buf_count) {
1518
pjmedia_move_samples(cport->rx_buf, cport->rx_buf+src_count,
1519
cport->rx_buf_count);
1522
TRACE_((THIS_FILE, " rx buffer size is now %d",
1523
cport->rx_buf_count));
1527
pjmedia_copy_samples(frame, cport->rx_buf, count);
1528
cport->rx_buf_count -= count;
1529
if (cport->rx_buf_count) {
1530
pjmedia_move_samples(cport->rx_buf, cport->rx_buf+count,
1531
cport->rx_buf_count);
1541
* Write the mixed signal to the port.
1543
static pj_status_t write_port(pjmedia_conf *conf, struct conf_port *cport,
1544
const pj_timestamp *timestamp,
1545
pjmedia_frame_type *frm_type)
1550
pj_int32_t adj_level;
1551
pj_int32_t tx_level;
1554
*frm_type = PJMEDIA_FRAME_TYPE_AUDIO;
1556
/* If port is muted or nobody is transmitting to this port,
1557
* transmit NULL frame.
1559
if (cport->tx_setting == PJMEDIA_PORT_MUTE || cport->transmitter_cnt==0) {
1561
pjmedia_frame frame;
1563
/* Clear left-over samples in tx_buffer, if any, so that it won't
1564
* be transmitted next time we have audio signal.
1566
cport->tx_buf_count = 0;
1568
/* Add sample counts to heart-beat samples */
1569
cport->tx_heart_beat += conf->samples_per_frame * cport->clock_rate /
1571
cport->channel_count / conf->channel_count;
1573
/* Set frame timestamp */
1574
frame.timestamp.u64 = timestamp->u64 * cport->clock_rate /
1576
frame.type = PJMEDIA_FRAME_TYPE_NONE;
1580
/* Transmit heart-beat frames (may transmit more than one NULL frame
1581
* if port's ptime is less than bridge's ptime.
1583
if (cport->port && cport->port->put_frame) {
1584
while (cport->tx_heart_beat >= cport->samples_per_frame) {
1586
pjmedia_port_put_frame(cport->port, &frame);
1588
cport->tx_heart_beat -= cport->samples_per_frame;
1589
frame.timestamp.u64 += cport->samples_per_frame;
1593
cport->tx_level = 0;
1594
*frm_type = PJMEDIA_FRAME_TYPE_NONE;
1597
} else if (cport->tx_setting != PJMEDIA_PORT_ENABLE) {
1598
cport->tx_level = 0;
1599
*frm_type = PJMEDIA_FRAME_TYPE_NONE;
1603
/* Reset heart-beat sample count */
1604
cport->tx_heart_beat = 0;
1606
buf = (pj_int16_t*) cport->mix_buf;
1608
/* If there are sources in the mix buffer, convert the mixed samples
1609
* from 32bit to 16bit in the mixed samples itself. This is possible
1610
* because mixed sample is 32bit.
1612
* In addition to this process, if we need to change the level of
1613
* TX signal, we adjust is here too.
1616
/* Calculate signal level and adjust the signal when needed.
1617
* Two adjustments performed at once:
1618
* 1. user setting adjustment (tx_adj_level).
1619
* 2. automatic adjustment of overflowed mixed buffer (mix_adj).
1622
/* Apply simple AGC to the mix_adj, the automatic adjust, to avoid
1623
* dramatic change in the level thus causing noise because the signal
1624
* is now not aligned with the signal from the previous frame.
1626
SIMPLE_AGC(cport->last_mix_adj, cport->mix_adj);
1627
cport->last_mix_adj = cport->mix_adj;
1629
/* adj_level = cport->tx_adj_level * cport->mix_adj / NORMAL_LEVEL;*/
1630
adj_level = cport->tx_adj_level * cport->mix_adj;
1635
if (adj_level != NORMAL_LEVEL) {
1636
for (j=0; j<conf->samples_per_frame; ++j) {
1637
pj_int32_t itemp = cport->mix_buf[j];
1639
/* Adjust the level */
1640
/*itemp = itemp * adj_level / NORMAL_LEVEL;*/
1641
itemp = (itemp * adj_level) >> 7;
1643
/* Clip the signal if it's too loud */
1644
if (itemp > MAX_LEVEL) itemp = MAX_LEVEL;
1645
else if (itemp < MIN_LEVEL) itemp = MIN_LEVEL;
1647
/* Put back in the buffer. */
1648
buf[j] = (pj_int16_t) itemp;
1650
tx_level += (buf[j]>=0? buf[j] : -buf[j]);
1653
for (j=0; j<conf->samples_per_frame; ++j) {
1654
buf[j] = (pj_int16_t) cport->mix_buf[j];
1655
tx_level += (buf[j]>=0? buf[j] : -buf[j]);
1659
tx_level /= conf->samples_per_frame;
1661
/* Convert level to 8bit complement ulaw */
1662
tx_level = pjmedia_linear2ulaw(tx_level) ^ 0xff;
1664
cport->tx_level = tx_level;
1666
/* If port has the same clock_rate and samples_per_frame and
1667
* number of channels as the conference bridge, transmit the
1670
if (cport->clock_rate == conf->clock_rate &&
1671
cport->samples_per_frame == conf->samples_per_frame &&
1672
cport->channel_count == conf->channel_count)
1674
if (cport->port != NULL) {
1675
pjmedia_frame frame;
1677
frame.type = PJMEDIA_FRAME_TYPE_AUDIO;
1679
frame.size = conf->samples_per_frame * BYTES_PER_SAMPLE;
1680
/* No need to adjust timestamp, port has the same
1681
* clock rate as conference bridge
1683
frame.timestamp = *timestamp;
1685
TRACE_((THIS_FILE, "put_frame %.*s, count=%d",
1686
(int)cport->name.slen, cport->name.ptr,
1687
frame.size / BYTES_PER_SAMPLE));
1689
return pjmedia_port_put_frame(cport->port, &frame);
1694
/* If it has different clock_rate, must resample. */
1695
if (cport->clock_rate != conf->clock_rate) {
1696
pjmedia_resample_run( cport->tx_resample, buf,
1697
cport->tx_buf + cport->tx_buf_count );
1698
dst_count = (unsigned)(conf->samples_per_frame * 1.0 *
1699
cport->clock_rate / conf->clock_rate + 0.5);
1702
* Just copy the samples to tx_buffer.
1704
pjmedia_copy_samples( cport->tx_buf + cport->tx_buf_count,
1705
buf, conf->samples_per_frame );
1706
dst_count = conf->samples_per_frame;
1709
/* Adjust channels */
1710
if (cport->channel_count != conf->channel_count) {
1711
pj_int16_t *tx_buf = cport->tx_buf + cport->tx_buf_count;
1712
if (conf->channel_count == 1) {
1713
pjmedia_convert_channel_1ton(tx_buf, tx_buf,
1714
cport->channel_count,
1716
dst_count *= cport->channel_count;
1717
} else { /* cport->channel_count == 1 */
1718
pjmedia_convert_channel_nto1(tx_buf, tx_buf,
1719
conf->channel_count,
1720
dst_count, PJMEDIA_STEREO_MIX, 0);
1721
dst_count /= conf->channel_count;
1725
cport->tx_buf_count += dst_count;
1727
pj_assert(cport->tx_buf_count <= cport->tx_buf_cap);
1729
/* Transmit while we have enough frame in the tx_buf. */
1730
status = PJ_SUCCESS;
1732
while (cport->tx_buf_count >= cport->samples_per_frame &&
1733
status == PJ_SUCCESS)
1736
TRACE_((THIS_FILE, "write_port %.*s: count=%d",
1737
(int)cport->name.slen, cport->name.ptr,
1738
cport->samples_per_frame));
1741
pjmedia_frame frame;
1743
frame.type = PJMEDIA_FRAME_TYPE_AUDIO;
1744
frame.buf = cport->tx_buf;
1745
frame.size = cport->samples_per_frame * BYTES_PER_SAMPLE;
1746
/* Adjust timestamp as port may have different clock rate
1749
frame.timestamp.u64 = timestamp->u64 * cport->clock_rate /
1752
/* Add timestamp for individual frame */
1753
frame.timestamp.u64 += ts;
1754
ts += cport->samples_per_frame;
1756
TRACE_((THIS_FILE, "put_frame %.*s, count=%d",
1757
(int)cport->name.slen, cport->name.ptr,
1758
frame.size / BYTES_PER_SAMPLE));
1760
status = pjmedia_port_put_frame(cport->port, &frame);
1763
status = PJ_SUCCESS;
1765
cport->tx_buf_count -= cport->samples_per_frame;
1766
if (cport->tx_buf_count) {
1767
pjmedia_move_samples(cport->tx_buf,
1768
cport->tx_buf + cport->samples_per_frame,
1769
cport->tx_buf_count);
1772
TRACE_((THIS_FILE, " tx_buf count now is %d",
1773
cport->tx_buf_count));
1783
static pj_status_t get_frame(pjmedia_port *this_port,
1784
pjmedia_frame *frame)
1786
pjmedia_conf *conf = (pjmedia_conf*) this_port->port_data.pdata;
1787
pjmedia_frame_type speaker_frame_type = PJMEDIA_FRAME_TYPE_NONE;
1788
unsigned ci, cj, i, j;
1791
TRACE_((THIS_FILE, "- clock -"));
1793
/* Check that correct size is specified. */
1794
pj_assert(frame->size == conf->samples_per_frame *
1795
conf->bits_per_sample / 8);
1797
/* Must lock mutex */
1798
pj_mutex_lock(conf->mutex);
1800
/* Reset port source count. We will only reset port's mix
1801
* buffer when we have someone transmitting to it.
1803
for (i=0, ci=0; i<conf->max_ports && ci < conf->port_cnt; ++i) {
1804
struct conf_port *conf_port = conf->ports[i];
1806
/* Skip empty port. */
1810
/* Var "ci" is to count how many ports have been visited so far. */
1813
/* Reset buffer (only necessary if the port has transmitter) and
1814
* reset auto adjustment level for mixed signal.
1816
conf_port->mix_adj = NORMAL_LEVEL;
1817
if (conf_port->transmitter_cnt) {
1818
pj_bzero(conf_port->mix_buf,
1819
conf->samples_per_frame*sizeof(conf_port->mix_buf[0]));
1823
/* Get frames from all ports, and "mix" the signal
1824
* to mix_buf of all listeners of the port.
1826
for (i=0, ci=0; i < conf->max_ports && ci < conf->port_cnt; ++i) {
1827
struct conf_port *conf_port = conf->ports[i];
1828
pj_int32_t level = 0;
1830
/* Skip empty port. */
1834
/* Var "ci" is to count how many ports have been visited so far. */
1837
/* Skip if we're not allowed to receive from this port. */
1838
if (conf_port->rx_setting == PJMEDIA_PORT_DISABLE) {
1839
conf_port->rx_level = 0;
1843
/* Also skip if this port doesn't have listeners. */
1844
if (conf_port->listener_cnt == 0) {
1845
conf_port->rx_level = 0;
1849
/* Get frame from this port.
1850
* For passive ports, get the frame from the delay_buf.
1851
* For other ports, get the frame from the port.
1853
if (conf_port->delay_buf != NULL) {
1856
status = pjmedia_delay_buf_get(conf_port->delay_buf,
1857
(pj_int16_t*)frame->buf);
1858
if (status != PJ_SUCCESS)
1864
pjmedia_frame_type frame_type;
1866
status = read_port(conf, conf_port, (pj_int16_t*)frame->buf,
1867
conf->samples_per_frame, &frame_type);
1869
if (status != PJ_SUCCESS) {
1870
/* bennylp: why do we need this????
1871
* Also see comments on similar issue with write_port().
1872
PJ_LOG(4,(THIS_FILE, "Port %.*s get_frame() returned %d. "
1873
"Port is now disabled",
1874
(int)conf_port->name.slen,
1875
conf_port->name.ptr,
1877
conf_port->rx_setting = PJMEDIA_PORT_DISABLE;
1882
/* Check that the port is not removed when we call get_frame() */
1883
if (conf->ports[i] == NULL)
1886
/* Ignore if we didn't get any frame */
1887
if (frame_type != PJMEDIA_FRAME_TYPE_AUDIO)
1891
p_in = (pj_int16_t*) frame->buf;
1893
/* Adjust the RX level from this port
1894
* and calculate the average level at the same time.
1896
if (conf_port->rx_adj_level != NORMAL_LEVEL) {
1897
for (j=0; j<conf->samples_per_frame; ++j) {
1898
/* For the level adjustment, we need to store the sample to
1899
* a temporary 32bit integer value to avoid overflowing the
1900
* 16bit sample storage.
1905
/*itemp = itemp * adj / NORMAL_LEVEL;*/
1906
/* bad code (signed/unsigned badness):
1907
* itemp = (itemp * conf_port->rx_adj_level) >> 7;
1909
itemp *= conf_port->rx_adj_level;
1912
/* Clip the signal if it's too loud */
1913
if (itemp > MAX_LEVEL) itemp = MAX_LEVEL;
1914
else if (itemp < MIN_LEVEL) itemp = MIN_LEVEL;
1916
p_in[j] = (pj_int16_t) itemp;
1917
level += (p_in[j]>=0? p_in[j] : -p_in[j]);
1920
for (j=0; j<conf->samples_per_frame; ++j) {
1921
level += (p_in[j]>=0? p_in[j] : -p_in[j]);
1925
level /= conf->samples_per_frame;
1927
/* Convert level to 8bit complement ulaw */
1928
level = pjmedia_linear2ulaw(level) ^ 0xff;
1930
/* Put this level to port's last RX level. */
1931
conf_port->rx_level = level;
1933
// Ticket #671: Skipping very low audio signal may cause noise
1934
// to be generated in the remote end by some hardphones.
1935
/* Skip processing frame if level is zero */
1939
/* Add the signal to all listeners. */
1940
for (cj=0; cj < conf_port->listener_cnt; ++cj)
1942
struct conf_port *listener;
1943
pj_int32_t *mix_buf;
1946
listener = conf->ports[conf_port->listener_slots[cj]];
1948
/* Skip if this listener doesn't want to receive audio */
1949
if (listener->tx_setting != PJMEDIA_PORT_ENABLE)
1952
mix_buf = listener->mix_buf;
1954
if (listener->transmitter_cnt > 1) {
1956
* and calculate appropriate level adjustment if there is
1957
* any overflowed level in the mixed signal.
1959
for (k=0; k < conf->samples_per_frame; ++k) {
1960
mix_buf[k] += p_in[k];
1961
/* Check if normalization adjustment needed. */
1962
if (IS_OVERFLOW(mix_buf[k])) {
1963
/* NORMAL_LEVEL * MAX_LEVEL / mix_buf[k]; */
1964
int tmp_adj = (MAX_LEVEL<<7) / mix_buf[k];
1965
if (tmp_adj<0) tmp_adj = -tmp_adj;
1967
if (tmp_adj<listener->mix_adj)
1968
listener->mix_adj = tmp_adj;
1970
} /* if any overflow in the mixed signals */
1971
} /* loop mixing signals */
1973
/* Only 1 transmitter:
1974
* just copy the samples to the mix buffer
1975
* no mixing and level adjustment needed
1977
for (k=0; k<conf->samples_per_frame; ++k) {
1978
mix_buf[k] = p_in[k];
1981
} /* loop the listeners of conf port */
1982
} /* loop of all conf ports */
1984
/* Time for all ports to transmit whetever they have in their
1987
for (i=0, ci=0; i<conf->max_ports && ci<conf->port_cnt; ++i) {
1988
struct conf_port *conf_port = conf->ports[i];
1989
pjmedia_frame_type frm_type;
1995
/* Var "ci" is to count how many ports have been visited. */
1998
status = write_port( conf, conf_port, &frame->timestamp,
2000
if (status != PJ_SUCCESS) {
2001
/* bennylp: why do we need this????
2002
One thing for sure, put_frame()/write_port() may return
2003
non-successfull status on Win32 if there's temporary glitch
2004
on network interface, so disabling the port here does not
2005
sound like a good idea.
2007
PJ_LOG(4,(THIS_FILE, "Port %.*s put_frame() returned %d. "
2008
"Port is now disabled",
2009
(int)conf_port->name.slen,
2010
conf_port->name.ptr,
2012
conf_port->tx_setting = PJMEDIA_PORT_DISABLE;
2017
/* Set the type of frame to be returned to sound playback
2021
speaker_frame_type = frm_type;
2024
/* Return sound playback frame. */
2025
if (conf->ports[0]->tx_level) {
2026
TRACE_((THIS_FILE, "write to audio, count=%d",
2027
conf->samples_per_frame));
2028
pjmedia_copy_samples( (pj_int16_t*)frame->buf,
2029
(const pj_int16_t*)conf->ports[0]->mix_buf,
2030
conf->samples_per_frame);
2032
/* Force frame type NONE */
2033
speaker_frame_type = PJMEDIA_FRAME_TYPE_NONE;
2036
/* MUST set frame type */
2037
frame->type = speaker_frame_type;
2039
pj_mutex_unlock(conf->mutex);
2042
if (fhnd_rec == NULL)
2043
fhnd_rec = fopen(REC_FILE, "wb");
2045
fwrite(frame->buf, frame->size, 1, fhnd_rec);
2053
* get_frame() for passive port
2055
static pj_status_t get_frame_pasv(pjmedia_port *this_port,
2056
pjmedia_frame *frame)
2059
PJ_UNUSED_ARG(this_port);
2060
PJ_UNUSED_ARG(frame);
2066
* Recorder (or passive port) callback.
2068
static pj_status_t put_frame(pjmedia_port *this_port,
2069
pjmedia_frame *frame)
2071
pjmedia_conf *conf = (pjmedia_conf*) this_port->port_data.pdata;
2072
struct conf_port *port = conf->ports[this_port->port_data.ldata];
2075
/* Check for correct size. */
2076
PJ_ASSERT_RETURN( frame->size == conf->samples_per_frame *
2077
conf->bits_per_sample / 8,
2078
PJMEDIA_ENCSAMPLESPFRAME);
2080
/* Check existance of delay_buf instance */
2081
PJ_ASSERT_RETURN( port->delay_buf, PJ_EBUG );
2083
/* Skip if this port is muted/disabled. */
2084
if (port->rx_setting != PJMEDIA_PORT_ENABLE) {
2088
/* Skip if no port is listening to the microphone */
2089
if (port->listener_cnt == 0) {
2093
status = pjmedia_delay_buf_put(port->delay_buf, (pj_int16_t*)frame->buf);