~ubuntu-branches/ubuntu/trusty/sflphone/trusty

« back to all changes in this revision

Viewing changes to daemon/libs/pjproject-2.1.0/pjmedia/src/pjmedia/conference.c

  • Committer: Package Import Robot
  • Author(s): Mark Purcell
  • Date: 2014-01-28 18:23:36 UTC
  • mfrom: (4.3.4 sid)
  • Revision ID: package-import@ubuntu.com-20140128182336-jrsv0k9u6cawc068
Tags: 1.3.0-1
* New upstream release 
  - Fixes "New Upstream Release" (Closes: #735846)
  - Fixes "Ringtone does not stop" (Closes: #727164)
  - Fixes "[sflphone-kde] crash on startup" (Closes: #718178)
  - Fixes "sflphone GUI crashes when call is hung up" (Closes: #736583)
* Build-Depends: ensure GnuTLS 2.6
  - libucommon-dev (>= 6.0.7-1.1), libccrtp-dev (>= 2.0.6-3)
  - Fixes "FTBFS Build-Depends libgnutls{26,28}-dev" (Closes: #722040)
* Fix "boost 1.49 is going away" unversioned Build-Depends: (Closes: #736746)
* Add Build-Depends: libsndfile-dev, nepomuk-core-dev

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* $Id: conference.c 4198 2012-07-05 10:25:46Z nanang $ */
 
2
/* 
 
3
 * Copyright (C) 2008-2011 Teluu Inc. (http://www.teluu.com)
 
4
 * Copyright (C) 2003-2008 Benny Prijono <benny@prijono.org>
 
5
 *
 
6
 * This program is free software; you can redistribute it and/or modify
 
7
 * it under the terms of the GNU General Public License as published by
 
8
 * the Free Software Foundation; either version 2 of the License, or
 
9
 * (at your option) any later version.
 
10
 *
 
11
 * This program is distributed in the hope that it will be useful,
 
12
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 
13
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
14
 * GNU General Public License for more details.
 
15
 *
 
16
 * You should have received a copy of the GNU General Public License
 
17
 * along with this program; if not, write to the Free Software
 
18
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA 
 
19
 */
 
20
#include <pjmedia/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>
 
29
#include <pj/array.h>
 
30
#include <pj/assert.h>
 
31
#include <pj/log.h>
 
32
#include <pj/pool.h>
 
33
#include <pj/string.h>
 
34
 
 
35
#if !defined(PJMEDIA_CONF_USE_SWITCH_BOARD) || PJMEDIA_CONF_USE_SWITCH_BOARD==0
 
36
 
 
37
/* CONF_DEBUG enables detailed operation of the conference bridge.
 
38
 * Beware that it prints large amounts of logs (several lines per frame).
 
39
 */
 
40
//#define CONF_DEBUG
 
41
#ifdef CONF_DEBUG
 
42
#   include <stdio.h>
 
43
#   define TRACE_(x)   PJ_LOG(5,x)
 
44
#else
 
45
#   define TRACE_(x)
 
46
#endif
 
47
 
 
48
 
 
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*.
 
53
 */
 
54
//#define REC_FILE    "confrec.pcm"
 
55
#ifdef REC_FILE
 
56
static FILE *fhnd_rec;
 
57
#endif
 
58
 
 
59
 
 
60
#define THIS_FILE       "conference.c"
 
61
 
 
62
#define RX_BUF_COUNT        PJMEDIA_SOUND_BUFFER_COUNT
 
63
 
 
64
#define BYTES_PER_SAMPLE    2
 
65
 
 
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)
 
72
 
 
73
 
 
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).
 
77
 */
 
78
#define ATTACK_A    (conf->clock_rate / conf->samples_per_frame)
 
79
#define ATTACK_B    1
 
80
#define DECAY_A     0
 
81
#define DECAY_B     1
 
82
 
 
83
#define SIMPLE_AGC(last, target) \
 
84
    if (target >= last) \
 
85
        target = (ATTACK_A*(last+1)+ATTACK_B*target)/(ATTACK_A+ATTACK_B); \
 
86
    else \
 
87
        target = (DECAY_A*last+DECAY_B*target)/(DECAY_A+DECAY_B)
 
88
 
 
89
#define MAX_LEVEL   (32767)
 
90
#define MIN_LEVEL   (-32768)
 
91
 
 
92
#define IS_OVERFLOW(s) ((s > MAX_LEVEL) || (s < MIN_LEVEL))
 
93
 
 
94
 
 
95
/*
 
96
 * DON'T GET CONFUSED WITH TX/RX!!
 
97
 *
 
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
 
101
 * port.
 
102
 */
 
103
 
 
104
 
 
105
/**
 
106
 * This is a port connected to conference bridge.
 
107
 */
 
108
struct conf_port
 
109
{
 
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.        */
 
117
 
 
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.          */
 
122
 
 
123
    /* Calculated signal levels: */
 
124
    unsigned             tx_level;      /**< Last tx level to this port.    */
 
125
    unsigned             rx_level;      /**< Last rx level from this port.  */
 
126
 
 
127
    /* The normalized signal level adjustment.
 
128
     * A value of 128 (NORMAL_LEVEL) means there's no adjustment.
 
129
     */
 
130
    unsigned             tx_adj_level;  /**< Adjustment for TX.             */
 
131
    unsigned             rx_adj_level;  /**< Adjustment for RX.             */
 
132
 
 
133
    /* Resample, for converting clock rate, if they're different. */
 
134
    pjmedia_resample    *rx_resample;
 
135
    pjmedia_resample    *tx_resample;
 
136
 
 
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.
 
142
     *
 
143
     * When both sample rate AND ptime of the port match the conference 
 
144
     * settings, this buffer will not be created.
 
145
     * 
 
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.
 
149
     */
 
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.       */
 
153
 
 
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.
 
158
     *
 
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.
 
161
     */
 
162
 
 
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.           */
 
166
 
 
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.
 
172
     *
 
173
     * When both sample rate and ptime of the port match the bridge's 
 
174
     * settings, this buffer will not be created.
 
175
     * 
 
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.
 
179
     */
 
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.    */
 
183
 
 
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).
 
189
     *
 
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.
 
193
     *
 
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.
 
198
     */
 
199
    unsigned             tx_heart_beat;
 
200
 
 
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).
 
203
     *
 
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.
 
209
     *
 
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. 
 
213
     *
 
214
     * Burst and drift are handled by delay buffer.
 
215
     */
 
216
    pjmedia_delay_buf   *delay_buf;
 
217
};
 
218
 
 
219
 
 
220
/*
 
221
 * Conference bridge.
 
222
 */
 
223
struct pjmedia_conf
 
224
{
 
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.       */
 
238
};
 
239
 
 
240
 
 
241
/* Prototypes */
 
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);
 
250
 
 
251
 
 
252
/*
 
253
 * Create port.
 
254
 */
 
255
static pj_status_t create_conf_port( pj_pool_t *pool,
 
256
                                     pjmedia_conf *conf,
 
257
                                     pjmedia_port *port,
 
258
                                     const pj_str_t *name,
 
259
                                     struct conf_port **p_conf_port)
 
260
{
 
261
    struct conf_port *conf_port;
 
262
    pj_status_t status;
 
263
 
 
264
    /* Create port. */
 
265
    conf_port = PJ_POOL_ZALLOC_T(pool, struct conf_port);
 
266
    PJ_ASSERT_RETURN(conf_port, PJ_ENOMEM);
 
267
 
 
268
    /* Set name */
 
269
    pj_strdup_with_null(pool, &conf_port->name, name);
 
270
 
 
271
    /* Default has tx and rx enabled. */
 
272
    conf_port->rx_setting = PJMEDIA_PORT_ENABLE;
 
273
    conf_port->tx_setting = PJMEDIA_PORT_ENABLE;
 
274
 
 
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;
 
278
 
 
279
    /* Create transmit flag array */
 
280
    conf_port->listener_slots = (SLOT_TYPE*)
 
281
                                pj_pool_zalloc(pool, 
 
282
                                          conf->max_ports * sizeof(SLOT_TYPE));
 
283
    PJ_ASSERT_RETURN(conf_port->listener_slots, PJ_ENOMEM);
 
284
 
 
285
    /* Save some port's infos, for convenience. */
 
286
    if (port) {
 
287
        pjmedia_audio_format_detail *afd;
 
288
 
 
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;
 
294
    } else {
 
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;
 
299
    }
 
300
 
 
301
    /* If port's clock rate is different than conference's clock rate,
 
302
     * create a resample sessions.
 
303
     */
 
304
    if (conf_port->clock_rate != conf->clock_rate) {
 
305
 
 
306
        pj_bool_t high_quality;
 
307
        pj_bool_t large_filter;
 
308
 
 
309
        high_quality = ((conf->options & PJMEDIA_CONF_USE_LINEAR)==0);
 
310
        large_filter = ((conf->options & PJMEDIA_CONF_SMALL_FILTER)==0);
 
311
 
 
312
        /* Create resample for rx buffer. */
 
313
        status = pjmedia_resample_create( pool, 
 
314
                                          high_quality,
 
315
                                          large_filter,
 
316
                                          conf->channel_count,
 
317
                                          conf_port->clock_rate,/* Rate in */
 
318
                                          conf->clock_rate, /* Rate out */
 
319
                                          conf->samples_per_frame * 
 
320
                                            conf_port->clock_rate /
 
321
                                            conf->clock_rate,
 
322
                                          &conf_port->rx_resample);
 
323
        if (status != PJ_SUCCESS)
 
324
            return status;
 
325
 
 
326
 
 
327
        /* Create resample for tx buffer. */
 
328
        status = pjmedia_resample_create(pool,
 
329
                                         high_quality,
 
330
                                         large_filter,
 
331
                                         conf->channel_count,
 
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)
 
337
            return status;
 
338
    }
 
339
 
 
340
    /*
 
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
 
343
     * bridge settings.
 
344
     */
 
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)
 
348
    {
 
349
        unsigned port_ptime, conf_ptime, buff_ptime;
 
350
 
 
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;
 
355
 
 
356
        /* Calculate the size (in ptime) for the port buffer according to
 
357
         * this formula:
 
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)
 
362
         */
 
363
        if (port_ptime > conf_ptime) {
 
364
            buff_ptime = port_ptime;
 
365
            if (port_ptime % conf_ptime)
 
366
                buff_ptime += conf_ptime;
 
367
        } else {
 
368
            buff_ptime = conf_ptime;
 
369
            if (conf_ptime % port_ptime)
 
370
                buff_ptime += port_ptime;
 
371
        }
 
372
 
 
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;
 
381
        else
 
382
            conf_port->rx_buf_cap *= conf->channel_count;
 
383
 
 
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);
 
389
 
 
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);
 
397
    }
 
398
 
 
399
 
 
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;
 
406
 
 
407
 
 
408
    /* Done */
 
409
    *p_conf_port = conf_port;
 
410
    return PJ_SUCCESS;
 
411
}
 
412
 
 
413
 
 
414
/*
 
415
 * Add passive port.
 
416
 */
 
417
static pj_status_t create_pasv_port( pjmedia_conf *conf,
 
418
                                     pj_pool_t *pool,
 
419
                                     const pj_str_t *name,
 
420
                                     pjmedia_port *port,
 
421
                                     struct conf_port **p_conf_port)
 
422
{
 
423
    struct conf_port *conf_port;
 
424
    pj_status_t status;
 
425
    unsigned ptime;
 
426
 
 
427
    /* Create port */
 
428
    status = create_conf_port(pool, conf, port, name, &conf_port);
 
429
    if (status != PJ_SUCCESS)
 
430
        return status;
 
431
 
 
432
    /* Passive port has delay buf. */
 
433
    ptime = conf->samples_per_frame * 1000 / conf->clock_rate / 
 
434
            conf->channel_count;
 
435
    status = pjmedia_delay_buf_create(pool, name->ptr, 
 
436
                                      conf->clock_rate,
 
437
                                      conf->samples_per_frame,
 
438
                                      conf->channel_count,
 
439
                                      RX_BUF_COUNT * ptime, /* max delay */
 
440
                                      0, /* options */
 
441
                                      &conf_port->delay_buf);
 
442
    if (status != PJ_SUCCESS)
 
443
        return status;
 
444
 
 
445
    *p_conf_port = conf_port;
 
446
 
 
447
    return PJ_SUCCESS;
 
448
}
 
449
 
 
450
 
 
451
/*
 
452
 * Create port zero for the sound device.
 
453
 */
 
454
static pj_status_t create_sound_port( pj_pool_t *pool,
 
455
                                      pjmedia_conf *conf )
 
456
{
 
457
    struct conf_port *conf_port;
 
458
    pj_str_t name = { "Master/sound", 12 };
 
459
    pj_status_t status;
 
460
 
 
461
 
 
462
    status = create_pasv_port(conf, pool, &name, NULL, &conf_port);
 
463
    if (status != PJ_SUCCESS)
 
464
        return status;
 
465
 
 
466
 
 
467
    /* Create sound device port: */
 
468
 
 
469
    if ((conf->options & PJMEDIA_CONF_NO_DEVICE) == 0) {
 
470
        pjmedia_aud_stream *strm;
 
471
        pjmedia_aud_param param;
 
472
 
 
473
        /*
 
474
         * If capture is disabled then create player only port.
 
475
         * Otherwise create bidirectional sound device port.
 
476
         */
 
477
        if (conf->options & PJMEDIA_CONF_NO_MIC)  {
 
478
            status = pjmedia_snd_port_create_player(pool, -1, conf->clock_rate,
 
479
                                                    conf->channel_count,
 
480
                                                    conf->samples_per_frame,
 
481
                                                    conf->bits_per_sample, 
 
482
                                                    0,  /* options */
 
483
                                                    &conf->snd_dev_port);
 
484
 
 
485
        } else {
 
486
            status = pjmedia_snd_port_create( pool, -1, -1, conf->clock_rate, 
 
487
                                              conf->channel_count, 
 
488
                                              conf->samples_per_frame,
 
489
                                              conf->bits_per_sample,
 
490
                                              0,    /* Options */
 
491
                                              &conf->snd_dev_port);
 
492
 
 
493
        }
 
494
 
 
495
        if (status != PJ_SUCCESS)
 
496
            return status;
 
497
 
 
498
        strm = pjmedia_snd_port_get_snd_stream(conf->snd_dev_port);
 
499
        status = pjmedia_aud_stream_get_param(strm, &param);
 
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);
 
504
            else
 
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);
 
507
        }
 
508
 
 
509
        PJ_LOG(5,(THIS_FILE, "Sound device successfully created for port 0"));
 
510
    }
 
511
 
 
512
 
 
513
     /* Add the port to the bridge */
 
514
    conf->ports[0] = conf_port;
 
515
    conf->port_cnt++;
 
516
 
 
517
    return PJ_SUCCESS;
 
518
}
 
519
 
 
520
/*
 
521
 * Create conference bridge.
 
522
 */
 
523
PJ_DEF(pj_status_t) pjmedia_conf_create( pj_pool_t *pool,
 
524
                                         unsigned max_ports,
 
525
                                         unsigned clock_rate,
 
526
                                         unsigned channel_count,
 
527
                                         unsigned samples_per_frame,
 
528
                                         unsigned bits_per_sample,
 
529
                                         unsigned options,
 
530
                                         pjmedia_conf **p_conf )
 
531
{
 
532
    pjmedia_conf *conf;
 
533
    const pj_str_t name = { "Conf", 4 };
 
534
    pj_status_t status;
 
535
 
 
536
    /* Can only accept 16bits per sample, for now.. */
 
537
    PJ_ASSERT_RETURN(bits_per_sample == 16, PJ_EINVAL);
 
538
 
 
539
    PJ_LOG(5,(THIS_FILE, "Creating conference bridge with %d ports",
 
540
              max_ports));
 
541
 
 
542
    /* Create and init conf structure. */
 
543
    conf = PJ_POOL_ZALLOC_T(pool, pjmedia_conf);
 
544
    PJ_ASSERT_RETURN(conf, PJ_ENOMEM);
 
545
 
 
546
    conf->ports = (struct conf_port**) 
 
547
                  pj_pool_zalloc(pool, max_ports*sizeof(void*));
 
548
    PJ_ASSERT_RETURN(conf->ports, PJ_ENOMEM);
 
549
 
 
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;
 
556
 
 
557
    
 
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);
 
561
    
 
562
    pjmedia_port_info_init(&conf->master_port->info, &name, SIGNATURE,
 
563
                           clock_rate, channel_count, bits_per_sample,
 
564
                           samples_per_frame);
 
565
 
 
566
    conf->master_port->port_data.pdata = conf;
 
567
    conf->master_port->port_data.ldata = 0;
 
568
 
 
569
    conf->master_port->get_frame = &get_frame;
 
570
    conf->master_port->put_frame = &put_frame;
 
571
    conf->master_port->on_destroy = &destroy_port;
 
572
 
 
573
 
 
574
    /* Create port zero for sound device. */
 
575
    status = create_sound_port(pool, conf);
 
576
    if (status != PJ_SUCCESS) {
 
577
        pjmedia_conf_destroy(conf);
 
578
        return status;
 
579
    }
 
580
 
 
581
    /* Create mutex. */
 
582
    status = pj_mutex_create_recursive(pool, "conf", &conf->mutex);
 
583
    if (status != PJ_SUCCESS) {
 
584
        pjmedia_conf_destroy(conf);
 
585
        return status;
 
586
    }
 
587
 
 
588
    /* If sound device was created, connect sound device to the
 
589
     * master port.
 
590
     */
 
591
    if (conf->snd_dev_port) {
 
592
        status = pjmedia_snd_port_connect( conf->snd_dev_port, 
 
593
                                           conf->master_port );
 
594
        if (status != PJ_SUCCESS) {
 
595
            pjmedia_conf_destroy(conf);
 
596
            return status;
 
597
        }
 
598
    }
 
599
 
 
600
 
 
601
    /* Done */
 
602
 
 
603
    *p_conf = conf;
 
604
 
 
605
    return PJ_SUCCESS;
 
606
}
 
607
 
 
608
 
 
609
/*
 
610
 * Pause sound device.
 
611
 */
 
612
static pj_status_t pause_sound( pjmedia_conf *conf )
 
613
{
 
614
    /* Do nothing. */
 
615
    PJ_UNUSED_ARG(conf);
 
616
    return PJ_SUCCESS;
 
617
}
 
618
 
 
619
/*
 
620
 * Resume sound device.
 
621
 */
 
622
static pj_status_t resume_sound( pjmedia_conf *conf )
 
623
{
 
624
    /* Do nothing. */
 
625
    PJ_UNUSED_ARG(conf);
 
626
    return PJ_SUCCESS;
 
627
}
 
628
 
 
629
 
 
630
/**
 
631
 * Destroy conference bridge.
 
632
 */
 
633
PJ_DEF(pj_status_t) pjmedia_conf_destroy( pjmedia_conf *conf )
 
634
{
 
635
    unsigned i, ci;
 
636
 
 
637
    PJ_ASSERT_RETURN(conf != NULL, PJ_EINVAL);
 
638
 
 
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;
 
643
    }
 
644
 
 
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;
 
648
 
 
649
        cport = conf->ports[i];
 
650
        if (!cport)
 
651
            continue;
 
652
        
 
653
        ++ci;
 
654
        if (cport->delay_buf) {
 
655
            pjmedia_delay_buf_destroy(cport->delay_buf);
 
656
            cport->delay_buf = NULL;
 
657
        }
 
658
    }
 
659
 
 
660
    /* Destroy mutex */
 
661
    if (conf->mutex)
 
662
        pj_mutex_destroy(conf->mutex);
 
663
 
 
664
    return PJ_SUCCESS;
 
665
}
 
666
 
 
667
 
 
668
/*
 
669
 * Destroy the master port (will destroy the conference)
 
670
 */
 
671
static pj_status_t destroy_port(pjmedia_port *this_port)
 
672
{
 
673
    pjmedia_conf *conf = (pjmedia_conf*) this_port->port_data.pdata;
 
674
    return pjmedia_conf_destroy(conf);
 
675
}
 
676
 
 
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];
 
680
    pj_status_t status;
 
681
 
 
682
    status = pjmedia_delay_buf_destroy(port->delay_buf);
 
683
    if (status == PJ_SUCCESS)
 
684
        port->delay_buf = NULL;
 
685
 
 
686
    return status;
 
687
}
 
688
 
 
689
/*
 
690
 * Get port zero interface.
 
691
 */
 
692
PJ_DEF(pjmedia_port*) pjmedia_conf_get_master_port(pjmedia_conf *conf)
 
693
{
 
694
    /* Sanity check. */
 
695
    PJ_ASSERT_RETURN(conf != NULL, NULL);
 
696
 
 
697
    /* Can only return port interface when PJMEDIA_CONF_NO_DEVICE was
 
698
     * present in the option.
 
699
     */
 
700
    PJ_ASSERT_RETURN((conf->options & PJMEDIA_CONF_NO_DEVICE) != 0, NULL);
 
701
    
 
702
    return conf->master_port;
 
703
}
 
704
 
 
705
 
 
706
/*
 
707
 * Set master port name.
 
708
 */
 
709
PJ_DEF(pj_status_t) pjmedia_conf_set_port0_name(pjmedia_conf *conf,
 
710
                                                const pj_str_t *name)
 
711
{
 
712
    unsigned len;
 
713
 
 
714
    /* Sanity check. */
 
715
    PJ_ASSERT_RETURN(conf != NULL && name != NULL, PJ_EINVAL);
 
716
 
 
717
    len = name->slen;
 
718
    if (len > sizeof(conf->master_name_buf))
 
719
        len = sizeof(conf->master_name_buf);
 
720
    
 
721
    if (len > 0) pj_memcpy(conf->master_name_buf, name->ptr, len);
 
722
 
 
723
    conf->ports[0]->name.ptr = conf->master_name_buf;
 
724
    conf->ports[0]->name.slen = len;
 
725
 
 
726
    if (conf->master_port)
 
727
        conf->master_port->info.name = conf->ports[0]->name;
 
728
 
 
729
    return PJ_SUCCESS;
 
730
}
 
731
 
 
732
/*
 
733
 * Add stream port to the conference bridge.
 
734
 */
 
735
PJ_DEF(pj_status_t) pjmedia_conf_add_port( pjmedia_conf *conf,
 
736
                                           pj_pool_t *pool,
 
737
                                           pjmedia_port *strm_port,
 
738
                                           const pj_str_t *port_name,
 
739
                                           unsigned *p_port )
 
740
{
 
741
    struct conf_port *conf_port;
 
742
    unsigned index;
 
743
    pj_status_t status;
 
744
 
 
745
    PJ_ASSERT_RETURN(conf && pool && strm_port, PJ_EINVAL);
 
746
 
 
747
    /* If port_name is not specified, use the port's name */
 
748
    if (!port_name)
 
749
        port_name = &strm_port->info.name;
 
750
 
 
751
    /* For this version of PJMEDIA, channel(s) number MUST be:
 
752
     * - same between port & conference bridge.
 
753
     * - monochannel on port or conference bridge.
 
754
     */
 
755
    if (PJMEDIA_PIA_CCNT(&strm_port->info) != conf->channel_count &&
 
756
        (PJMEDIA_PIA_CCNT(&strm_port->info) != 1 &&
 
757
         conf->channel_count != 1))
 
758
    {
 
759
        pj_assert(!"Number of channels mismatch");
 
760
        return PJMEDIA_ENCCHANNEL;
 
761
    }
 
762
 
 
763
    pj_mutex_lock(conf->mutex);
 
764
 
 
765
    if (conf->port_cnt >= conf->max_ports) {
 
766
        pj_assert(!"Too many ports");
 
767
        pj_mutex_unlock(conf->mutex);
 
768
        return PJ_ETOOMANY;
 
769
    }
 
770
 
 
771
    /* Find empty port in the conference bridge. */
 
772
    for (index=0; index < conf->max_ports; ++index) {
 
773
        if (conf->ports[index] == NULL)
 
774
            break;
 
775
    }
 
776
 
 
777
    pj_assert(index != conf->max_ports);
 
778
 
 
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);
 
783
        return status;
 
784
    }
 
785
 
 
786
    /* Put the port. */
 
787
    conf->ports[index] = conf_port;
 
788
    conf->port_cnt++;
 
789
 
 
790
    /* Done. */
 
791
    if (p_port) {
 
792
        *p_port = index;
 
793
    }
 
794
 
 
795
    pj_mutex_unlock(conf->mutex);
 
796
 
 
797
    return PJ_SUCCESS;
 
798
}
 
799
 
 
800
 
 
801
/*
 
802
 * Add passive port.
 
803
 */
 
804
PJ_DEF(pj_status_t) pjmedia_conf_add_passive_port( pjmedia_conf *conf,
 
805
                                                   pj_pool_t *pool,
 
806
                                                   const pj_str_t *name,
 
807
                                                   unsigned clock_rate,
 
808
                                                   unsigned channel_count,
 
809
                                                   unsigned samples_per_frame,
 
810
                                                   unsigned bits_per_sample,
 
811
                                                   unsigned options,
 
812
                                                   unsigned *p_slot,
 
813
                                                   pjmedia_port **p_port )
 
814
{
 
815
    struct conf_port *conf_port;
 
816
    pjmedia_port *port;
 
817
    unsigned index;
 
818
    pj_str_t tmp;
 
819
    pj_status_t status;
 
820
 
 
821
    PJ_LOG(1, (THIS_FILE, "This API has been deprecated since 1.3 and will "
 
822
                          "be removed in the future release!"));
 
823
 
 
824
    PJ_ASSERT_RETURN(conf && pool, PJ_EINVAL);
 
825
 
 
826
    /* For this version of PJMEDIA, channel(s) number MUST be:
 
827
     * - same between port & conference bridge.
 
828
     * - monochannel on port or conference bridge.
 
829
     */
 
830
    if (channel_count != conf->channel_count && 
 
831
        (channel_count != 1 && conf->channel_count != 1)) 
 
832
    {
 
833
        pj_assert(!"Number of channels mismatch");
 
834
        return PJMEDIA_ENCCHANNEL;
 
835
    }
 
836
 
 
837
    /* For this version, options must be zero */
 
838
    PJ_ASSERT_RETURN(options == 0, PJ_EINVAL);
 
839
    PJ_UNUSED_ARG(options);
 
840
 
 
841
    pj_mutex_lock(conf->mutex);
 
842
 
 
843
    if (conf->port_cnt >= conf->max_ports) {
 
844
        pj_assert(!"Too many ports");
 
845
        pj_mutex_unlock(conf->mutex);
 
846
        return PJ_ETOOMANY;
 
847
    }
 
848
 
 
849
    /* Find empty port in the conference bridge. */
 
850
    for (index=0; index < conf->max_ports; ++index) {
 
851
        if (conf->ports[index] == NULL)
 
852
            break;
 
853
    }
 
854
 
 
855
    pj_assert(index != conf->max_ports);
 
856
 
 
857
    if (name == NULL) {
 
858
        name = &tmp;
 
859
 
 
860
        tmp.ptr = (char*) pj_pool_alloc(pool, 32);
 
861
        tmp.slen = pj_ansi_snprintf(tmp.ptr, 32, "ConfPort#%d", index);
 
862
    }
 
863
 
 
864
    /* Create and initialize the media port structure. */
 
865
    port = PJ_POOL_ZALLOC_T(pool, pjmedia_port);
 
866
    PJ_ASSERT_RETURN(port, PJ_ENOMEM);
 
867
    
 
868
    pjmedia_port_info_init(&port->info, name, SIGNATURE_PORT,
 
869
                           clock_rate, channel_count, bits_per_sample,
 
870
                           samples_per_frame);
 
871
 
 
872
    port->port_data.pdata = conf;
 
873
    port->port_data.ldata = index;
 
874
 
 
875
    port->get_frame = &get_frame_pasv;
 
876
    port->put_frame = &put_frame;
 
877
    port->on_destroy = &destroy_port_pasv;
 
878
 
 
879
    
 
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);
 
884
        return status;
 
885
    }
 
886
 
 
887
 
 
888
    /* Put the port. */
 
889
    conf->ports[index] = conf_port;
 
890
    conf->port_cnt++;
 
891
 
 
892
    /* Done. */
 
893
    if (p_slot)
 
894
        *p_slot = index;
 
895
    if (p_port)
 
896
        *p_port = port;
 
897
 
 
898
    pj_mutex_unlock(conf->mutex);
 
899
 
 
900
    return PJ_SUCCESS;
 
901
}
 
902
 
 
903
 
 
904
 
 
905
/*
 
906
 * Change TX and RX settings for the port.
 
907
 */
 
908
PJ_DEF(pj_status_t) pjmedia_conf_configure_port( pjmedia_conf *conf,
 
909
                                                  unsigned slot,
 
910
                                                  pjmedia_port_op tx,
 
911
                                                  pjmedia_port_op rx)
 
912
{
 
913
    struct conf_port *conf_port;
 
914
 
 
915
    /* Check arguments */
 
916
    PJ_ASSERT_RETURN(conf && slot<conf->max_ports, PJ_EINVAL);
 
917
 
 
918
    pj_mutex_lock(conf->mutex);
 
919
 
 
920
    /* Port must be valid. */
 
921
    conf_port = conf->ports[slot];
 
922
    if (conf_port == NULL) {
 
923
        pj_mutex_unlock(conf->mutex);
 
924
        return PJ_EINVAL;
 
925
    }
 
926
 
 
927
    conf_port = conf->ports[slot];
 
928
 
 
929
    if (tx != PJMEDIA_PORT_NO_CHANGE)
 
930
        conf_port->tx_setting = tx;
 
931
 
 
932
    if (rx != PJMEDIA_PORT_NO_CHANGE)
 
933
        conf_port->rx_setting = rx;
 
934
 
 
935
    pj_mutex_unlock(conf->mutex);
 
936
 
 
937
    return PJ_SUCCESS;
 
938
}
 
939
 
 
940
 
 
941
/*
 
942
 * Connect port.
 
943
 */
 
944
PJ_DEF(pj_status_t) pjmedia_conf_connect_port( pjmedia_conf *conf,
 
945
                                               unsigned src_slot,
 
946
                                               unsigned sink_slot,
 
947
                                               int level )
 
948
{
 
949
    struct conf_port *src_port, *dst_port;
 
950
    pj_bool_t start_sound = PJ_FALSE;
 
951
    unsigned i;
 
952
 
 
953
    /* Check arguments */
 
954
    PJ_ASSERT_RETURN(conf && src_slot<conf->max_ports && 
 
955
                     sink_slot<conf->max_ports, PJ_EINVAL);
 
956
 
 
957
    /* For now, level MUST be zero. */
 
958
    PJ_ASSERT_RETURN(level == 0, PJ_EINVAL);
 
959
 
 
960
    pj_mutex_lock(conf->mutex);
 
961
 
 
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);
 
967
        return PJ_EINVAL;
 
968
    }
 
969
 
 
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)
 
973
            break;
 
974
    }
 
975
 
 
976
    if (i == src_port->listener_cnt) {
 
977
        src_port->listener_slots[src_port->listener_cnt] = sink_slot;
 
978
        ++conf->connect_cnt;
 
979
        ++src_port->listener_cnt;
 
980
        ++dst_port->transmitter_cnt;
 
981
 
 
982
        if (conf->connect_cnt == 1)
 
983
            start_sound = 1;
 
984
 
 
985
        PJ_LOG(4,(THIS_FILE,"Port %d (%.*s) transmitting to port %d (%.*s)",
 
986
                  src_slot,
 
987
                  (int)src_port->name.slen,
 
988
                  src_port->name.ptr,
 
989
                  sink_slot,
 
990
                  (int)dst_port->name.slen,
 
991
                  dst_port->name.ptr));
 
992
    }
 
993
 
 
994
    pj_mutex_unlock(conf->mutex);
 
995
 
 
996
    /* Sound device must be started without mutex, otherwise the
 
997
     * sound thread will deadlock (?)
 
998
     */
 
999
    if (start_sound)
 
1000
        resume_sound(conf);
 
1001
 
 
1002
    return PJ_SUCCESS;
 
1003
}
 
1004
 
 
1005
 
 
1006
/*
 
1007
 * Disconnect port
 
1008
 */
 
1009
PJ_DEF(pj_status_t) pjmedia_conf_disconnect_port( pjmedia_conf *conf,
 
1010
                                                  unsigned src_slot,
 
1011
                                                  unsigned sink_slot )
 
1012
{
 
1013
    struct conf_port *src_port, *dst_port;
 
1014
    unsigned i;
 
1015
 
 
1016
    /* Check arguments */
 
1017
    PJ_ASSERT_RETURN(conf && src_slot<conf->max_ports && 
 
1018
                     sink_slot<conf->max_ports, PJ_EINVAL);
 
1019
 
 
1020
    pj_mutex_lock(conf->mutex);
 
1021
 
 
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);
 
1027
        return PJ_EINVAL;
 
1028
    }
 
1029
 
 
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)
 
1033
            break;
 
1034
    }
 
1035
 
 
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;
 
1046
 
 
1047
        PJ_LOG(4,(THIS_FILE,
 
1048
                  "Port %d (%.*s) stop transmitting to port %d (%.*s)",
 
1049
                  src_slot,
 
1050
                  (int)src_port->name.slen,
 
1051
                  src_port->name.ptr,
 
1052
                  sink_slot,
 
1053
                  (int)dst_port->name.slen,
 
1054
                  dst_port->name.ptr));
 
1055
 
 
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);
 
1059
    }
 
1060
 
 
1061
    pj_mutex_unlock(conf->mutex);
 
1062
 
 
1063
    if (conf->connect_cnt == 0) {
 
1064
        pause_sound(conf);
 
1065
    }
 
1066
 
 
1067
    return PJ_SUCCESS;
 
1068
}
 
1069
 
 
1070
/*
 
1071
 * Get number of ports currently registered to the conference bridge.
 
1072
 */
 
1073
PJ_DEF(unsigned) pjmedia_conf_get_port_count(pjmedia_conf *conf)
 
1074
{
 
1075
    return conf->port_cnt;
 
1076
}
 
1077
 
 
1078
/*
 
1079
 * Get total number of ports connections currently set up in the bridge.
 
1080
 */
 
1081
PJ_DEF(unsigned) pjmedia_conf_get_connect_count(pjmedia_conf *conf)
 
1082
{
 
1083
    return conf->connect_cnt;
 
1084
}
 
1085
 
 
1086
 
 
1087
/*
 
1088
 * Remove the specified port.
 
1089
 */
 
1090
PJ_DEF(pj_status_t) pjmedia_conf_remove_port( pjmedia_conf *conf,
 
1091
                                              unsigned port )
 
1092
{
 
1093
    struct conf_port *conf_port;
 
1094
    unsigned i;
 
1095
 
 
1096
    /* Check arguments */
 
1097
    PJ_ASSERT_RETURN(conf && port < conf->max_ports, PJ_EINVAL);
 
1098
 
 
1099
    /* Suspend the sound devices.
 
1100
     * Don't want to remove port while port is being accessed by sound
 
1101
     * device's threads!
 
1102
     */
 
1103
 
 
1104
    pj_mutex_lock(conf->mutex);
 
1105
 
 
1106
    /* Port must be valid. */
 
1107
    conf_port = conf->ports[port];
 
1108
    if (conf_port == NULL) {
 
1109
        pj_mutex_unlock(conf->mutex);
 
1110
        return PJ_EINVAL;
 
1111
    }
 
1112
 
 
1113
    conf_port->tx_setting = PJMEDIA_PORT_DISABLE;
 
1114
    conf_port->rx_setting = PJMEDIA_PORT_DISABLE;
 
1115
 
 
1116
    /* Remove this port from transmit array of other ports. */
 
1117
    for (i=0; i<conf->max_ports; ++i) {
 
1118
        unsigned j;
 
1119
        struct conf_port *src_port;
 
1120
 
 
1121
        src_port = conf->ports[i];
 
1122
 
 
1123
        if (!src_port)
 
1124
            continue;
 
1125
 
 
1126
        if (src_port->listener_cnt == 0)
 
1127
            continue;
 
1128
 
 
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;
 
1136
                break;
 
1137
            }
 
1138
        }
 
1139
    }
 
1140
 
 
1141
    /* Update transmitter_cnt of ports we're transmitting to */
 
1142
    while (conf_port->listener_cnt) {
 
1143
        unsigned dst_slot;
 
1144
        struct conf_port *dst_port;
 
1145
 
 
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;
 
1152
    }
 
1153
 
 
1154
    /* Destroy pjmedia port if this conf port is passive port,
 
1155
     * i.e: has delay buf.
 
1156
     */
 
1157
    if (conf_port->delay_buf) {
 
1158
        pjmedia_port_destroy(conf_port->port);
 
1159
        conf_port->port = NULL;
 
1160
    }
 
1161
 
 
1162
    /* Remove the port. */
 
1163
    conf->ports[port] = NULL;
 
1164
    --conf->port_cnt;
 
1165
 
 
1166
    pj_mutex_unlock(conf->mutex);
 
1167
 
 
1168
 
 
1169
    /* Stop sound if there's no connection. */
 
1170
    if (conf->connect_cnt == 0) {
 
1171
        pause_sound(conf);
 
1172
    }
 
1173
 
 
1174
    return PJ_SUCCESS;
 
1175
}
 
1176
 
 
1177
 
 
1178
/*
 
1179
 * Enum ports.
 
1180
 */
 
1181
PJ_DEF(pj_status_t) pjmedia_conf_enum_ports( pjmedia_conf *conf,
 
1182
                                             unsigned ports[],
 
1183
                                             unsigned *p_count )
 
1184
{
 
1185
    unsigned i, count=0;
 
1186
 
 
1187
    PJ_ASSERT_RETURN(conf && p_count && ports, PJ_EINVAL);
 
1188
 
 
1189
    /* Lock mutex */
 
1190
    pj_mutex_lock(conf->mutex);
 
1191
 
 
1192
    for (i=0; i<conf->max_ports && count<*p_count; ++i) {
 
1193
        if (!conf->ports[i])
 
1194
            continue;
 
1195
 
 
1196
        ports[count++] = i;
 
1197
    }
 
1198
 
 
1199
    /* Unlock mutex */
 
1200
    pj_mutex_unlock(conf->mutex);
 
1201
 
 
1202
    *p_count = count;
 
1203
    return PJ_SUCCESS;
 
1204
}
 
1205
 
 
1206
/*
 
1207
 * Get port info
 
1208
 */
 
1209
PJ_DEF(pj_status_t) pjmedia_conf_get_port_info( pjmedia_conf *conf,
 
1210
                                                unsigned slot,
 
1211
                                                pjmedia_conf_port_info *info)
 
1212
{
 
1213
    struct conf_port *conf_port;
 
1214
 
 
1215
    /* Check arguments */
 
1216
    PJ_ASSERT_RETURN(conf && slot<conf->max_ports, PJ_EINVAL);
 
1217
 
 
1218
    /* Lock mutex */
 
1219
    pj_mutex_lock(conf->mutex);
 
1220
 
 
1221
    /* Port must be valid. */
 
1222
    conf_port = conf->ports[slot];
 
1223
    if (conf_port == NULL) {
 
1224
        pj_mutex_unlock(conf->mutex);
 
1225
        return PJ_EINVAL;
 
1226
    }
 
1227
 
 
1228
    info->slot = slot;
 
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;
 
1241
 
 
1242
    /* Unlock mutex */
 
1243
    pj_mutex_unlock(conf->mutex);
 
1244
 
 
1245
    return PJ_SUCCESS;
 
1246
}
 
1247
 
 
1248
 
 
1249
PJ_DEF(pj_status_t) pjmedia_conf_get_ports_info(pjmedia_conf *conf,
 
1250
                                                unsigned *size,
 
1251
                                                pjmedia_conf_port_info info[])
 
1252
{
 
1253
    unsigned i, count=0;
 
1254
 
 
1255
    PJ_ASSERT_RETURN(conf && size && info, PJ_EINVAL);
 
1256
 
 
1257
    /* Lock mutex */
 
1258
    pj_mutex_lock(conf->mutex);
 
1259
 
 
1260
    for (i=0; i<conf->max_ports && count<*size; ++i) {
 
1261
        if (!conf->ports[i])
 
1262
            continue;
 
1263
 
 
1264
        pjmedia_conf_get_port_info(conf, i, &info[count]);
 
1265
        ++count;
 
1266
    }
 
1267
 
 
1268
    /* Unlock mutex */
 
1269
    pj_mutex_unlock(conf->mutex);
 
1270
 
 
1271
    *size = count;
 
1272
    return PJ_SUCCESS;
 
1273
}
 
1274
 
 
1275
 
 
1276
/*
 
1277
 * Get signal level.
 
1278
 */
 
1279
PJ_DEF(pj_status_t) pjmedia_conf_get_signal_level( pjmedia_conf *conf,
 
1280
                                                   unsigned slot,
 
1281
                                                   unsigned *tx_level,
 
1282
                                                   unsigned *rx_level)
 
1283
{
 
1284
    struct conf_port *conf_port;
 
1285
 
 
1286
    /* Check arguments */
 
1287
    PJ_ASSERT_RETURN(conf && slot<conf->max_ports, PJ_EINVAL);
 
1288
 
 
1289
    /* Lock mutex */
 
1290
    pj_mutex_lock(conf->mutex);
 
1291
 
 
1292
    /* Port must be valid. */
 
1293
    conf_port = conf->ports[slot];
 
1294
    if (conf_port == NULL) {
 
1295
        pj_mutex_unlock(conf->mutex);
 
1296
        return PJ_EINVAL;
 
1297
    }
 
1298
 
 
1299
    if (tx_level != NULL) {
 
1300
        *tx_level = conf_port->tx_level;
 
1301
    }
 
1302
 
 
1303
    if (rx_level != NULL) 
 
1304
        *rx_level = conf_port->rx_level;
 
1305
 
 
1306
    /* Unlock mutex */
 
1307
    pj_mutex_unlock(conf->mutex);
 
1308
 
 
1309
    return PJ_SUCCESS;
 
1310
}
 
1311
 
 
1312
 
 
1313
/*
 
1314
 * Adjust RX level of individual port.
 
1315
 */
 
1316
PJ_DEF(pj_status_t) pjmedia_conf_adjust_rx_level( pjmedia_conf *conf,
 
1317
                                                  unsigned slot,
 
1318
                                                  int adj_level )
 
1319
{
 
1320
    struct conf_port *conf_port;
 
1321
 
 
1322
    /* Check arguments */
 
1323
    PJ_ASSERT_RETURN(conf && slot<conf->max_ports, PJ_EINVAL);
 
1324
 
 
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);
 
1328
     */
 
1329
    PJ_ASSERT_RETURN(adj_level >= -128, PJ_EINVAL);
 
1330
 
 
1331
    /* Lock mutex */
 
1332
    pj_mutex_lock(conf->mutex);
 
1333
 
 
1334
    /* Port must be valid. */
 
1335
    conf_port = conf->ports[slot];
 
1336
    if (conf_port == NULL) {
 
1337
        pj_mutex_unlock(conf->mutex);
 
1338
        return PJ_EINVAL;
 
1339
    }
 
1340
 
 
1341
    /* Set normalized adjustment level. */
 
1342
    conf_port->rx_adj_level = adj_level + NORMAL_LEVEL;
 
1343
 
 
1344
    /* Unlock mutex */
 
1345
    pj_mutex_unlock(conf->mutex);
 
1346
 
 
1347
    return PJ_SUCCESS;
 
1348
}
 
1349
 
 
1350
 
 
1351
/*
 
1352
 * Adjust TX level of individual port.
 
1353
 */
 
1354
PJ_DEF(pj_status_t) pjmedia_conf_adjust_tx_level( pjmedia_conf *conf,
 
1355
                                                  unsigned slot,
 
1356
                                                  int adj_level )
 
1357
{
 
1358
    struct conf_port *conf_port;
 
1359
 
 
1360
    /* Check arguments */
 
1361
    PJ_ASSERT_RETURN(conf && slot<conf->max_ports, PJ_EINVAL);
 
1362
 
 
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);
 
1366
     */
 
1367
    PJ_ASSERT_RETURN(adj_level >= -128, PJ_EINVAL);
 
1368
 
 
1369
    /* Lock mutex */
 
1370
    pj_mutex_lock(conf->mutex);
 
1371
 
 
1372
    /* Port must be valid. */
 
1373
    conf_port = conf->ports[slot];
 
1374
    if (conf_port == NULL) {
 
1375
        pj_mutex_unlock(conf->mutex);
 
1376
        return PJ_EINVAL;
 
1377
    }
 
1378
 
 
1379
    /* Set normalized adjustment level. */
 
1380
    conf_port->tx_adj_level = adj_level + NORMAL_LEVEL;
 
1381
 
 
1382
    /* Unlock mutex */
 
1383
    pj_mutex_unlock(conf->mutex);
 
1384
 
 
1385
    return PJ_SUCCESS;
 
1386
}
 
1387
 
 
1388
 
 
1389
/*
 
1390
 * Read from port.
 
1391
 */
 
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 )
 
1395
{
 
1396
 
 
1397
    pj_assert(count == conf->samples_per_frame);
 
1398
 
 
1399
    TRACE_((THIS_FILE, "read_port %.*s: count=%d", 
 
1400
                       (int)cport->name.slen, cport->name.ptr,
 
1401
                       count));
 
1402
 
 
1403
    /* 
 
1404
     * If port's samples per frame and sampling rate and channel count
 
1405
     * matche conference bridge's settings, get the frame directly from
 
1406
     * the port.
 
1407
     */
 
1408
    if (cport->rx_buf_cap == 0) {
 
1409
        pjmedia_frame f;
 
1410
        pj_status_t status;
 
1411
 
 
1412
        f.buf = frame;
 
1413
        f.size = count * BYTES_PER_SAMPLE;
 
1414
 
 
1415
        TRACE_((THIS_FILE, "  get_frame %.*s: count=%d", 
 
1416
                   (int)cport->name.slen, cport->name.ptr,
 
1417
                   count));
 
1418
 
 
1419
        status = pjmedia_port_get_frame(cport->port, &f);
 
1420
 
 
1421
        *type = f.type;
 
1422
 
 
1423
        return status;
 
1424
 
 
1425
    } else {
 
1426
        unsigned samples_req;
 
1427
 
 
1428
        /* Initialize frame type */
 
1429
        if (cport->rx_buf_count == 0) {
 
1430
            *type = PJMEDIA_FRAME_TYPE_NONE;
 
1431
        } else {
 
1432
            /* we got some samples in the buffer */
 
1433
            *type = PJMEDIA_FRAME_TYPE_AUDIO;
 
1434
        }
 
1435
 
 
1436
        /*
 
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
 
1439
         * channel count!
 
1440
         */
 
1441
 
 
1442
        samples_req = (unsigned) (count * 1.0 * 
 
1443
                      cport->clock_rate / conf->clock_rate + 0.5);
 
1444
 
 
1445
        while (cport->rx_buf_count < samples_req) {
 
1446
 
 
1447
            pjmedia_frame f;
 
1448
            pj_status_t status;
 
1449
 
 
1450
            f.buf = cport->rx_buf + cport->rx_buf_count;
 
1451
            f.size = cport->samples_per_frame * BYTES_PER_SAMPLE;
 
1452
 
 
1453
            TRACE_((THIS_FILE, "  get_frame, count=%d", 
 
1454
                       cport->samples_per_frame));
 
1455
 
 
1456
            status = pjmedia_port_get_frame(cport->port, &f);
 
1457
 
 
1458
            if (status != PJ_SUCCESS) {
 
1459
                /* Fatal error! */
 
1460
                return status;
 
1461
            }
 
1462
 
 
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);
 
1467
            } else {
 
1468
                /* We've got at least one frame */
 
1469
                *type = PJMEDIA_FRAME_TYPE_AUDIO;
 
1470
            }
 
1471
 
 
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,
 
1479
                                                 0);
 
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);
 
1490
                }
 
1491
            } else {
 
1492
                cport->rx_buf_count += cport->samples_per_frame;
 
1493
            }
 
1494
 
 
1495
            TRACE_((THIS_FILE, "  rx buffer size is now %d",
 
1496
                    cport->rx_buf_count));
 
1497
 
 
1498
            pj_assert(cport->rx_buf_count <= cport->rx_buf_cap);
 
1499
        }
 
1500
 
 
1501
        /*
 
1502
         * If port's clock_rate is different, resample.
 
1503
         * Otherwise just copy.
 
1504
         */
 
1505
        if (cport->clock_rate != conf->clock_rate) {
 
1506
            
 
1507
            unsigned src_count;
 
1508
 
 
1509
            TRACE_((THIS_FILE, "  resample, input count=%d", 
 
1510
                    pjmedia_resample_get_input_size(cport->rx_resample)));
 
1511
 
 
1512
            pjmedia_resample_run( cport->rx_resample,cport->rx_buf, frame);
 
1513
 
 
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);
 
1520
            }
 
1521
 
 
1522
            TRACE_((THIS_FILE, "  rx buffer size is now %d",
 
1523
                    cport->rx_buf_count));
 
1524
 
 
1525
        } else {
 
1526
 
 
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);
 
1532
            }
 
1533
        }
 
1534
    }
 
1535
 
 
1536
    return PJ_SUCCESS;
 
1537
}
 
1538
 
 
1539
 
 
1540
/*
 
1541
 * Write the mixed signal to the port.
 
1542
 */
 
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)
 
1546
{
 
1547
    pj_int16_t *buf;
 
1548
    unsigned j, ts;
 
1549
    pj_status_t status;
 
1550
    pj_int32_t adj_level;
 
1551
    pj_int32_t tx_level;
 
1552
    unsigned dst_count;
 
1553
 
 
1554
    *frm_type = PJMEDIA_FRAME_TYPE_AUDIO;
 
1555
 
 
1556
    /* If port is muted or nobody is transmitting to this port, 
 
1557
     * transmit NULL frame. 
 
1558
     */
 
1559
    if (cport->tx_setting == PJMEDIA_PORT_MUTE || cport->transmitter_cnt==0) {
 
1560
 
 
1561
        pjmedia_frame frame;
 
1562
 
 
1563
        /* Clear left-over samples in tx_buffer, if any, so that it won't
 
1564
         * be transmitted next time we have audio signal.
 
1565
         */
 
1566
        cport->tx_buf_count = 0;
 
1567
 
 
1568
        /* Add sample counts to heart-beat samples */
 
1569
        cport->tx_heart_beat += conf->samples_per_frame * cport->clock_rate /
 
1570
                                conf->clock_rate * 
 
1571
                                cport->channel_count / conf->channel_count;
 
1572
 
 
1573
        /* Set frame timestamp */
 
1574
        frame.timestamp.u64 = timestamp->u64 * cport->clock_rate /
 
1575
                                conf->clock_rate;
 
1576
        frame.type = PJMEDIA_FRAME_TYPE_NONE;
 
1577
        frame.buf = NULL;
 
1578
        frame.size = 0;
 
1579
 
 
1580
        /* Transmit heart-beat frames (may transmit more than one NULL frame
 
1581
         * if port's ptime is less than bridge's ptime.
 
1582
         */
 
1583
        if (cport->port && cport->port->put_frame) {
 
1584
            while (cport->tx_heart_beat >= cport->samples_per_frame) {
 
1585
 
 
1586
                pjmedia_port_put_frame(cport->port, &frame);
 
1587
 
 
1588
                cport->tx_heart_beat -= cport->samples_per_frame;
 
1589
                frame.timestamp.u64 += cport->samples_per_frame;
 
1590
            }
 
1591
        }
 
1592
 
 
1593
        cport->tx_level = 0;
 
1594
        *frm_type = PJMEDIA_FRAME_TYPE_NONE;
 
1595
        return PJ_SUCCESS;
 
1596
 
 
1597
    } else if (cport->tx_setting != PJMEDIA_PORT_ENABLE) {
 
1598
        cport->tx_level = 0;
 
1599
        *frm_type = PJMEDIA_FRAME_TYPE_NONE;
 
1600
        return PJ_SUCCESS;
 
1601
    }
 
1602
 
 
1603
    /* Reset heart-beat sample count */
 
1604
    cport->tx_heart_beat = 0;
 
1605
 
 
1606
    buf = (pj_int16_t*) cport->mix_buf;
 
1607
 
 
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.
 
1611
     *
 
1612
     * In addition to this process, if we need to change the level of
 
1613
     * TX signal, we adjust is here too.
 
1614
     */
 
1615
 
 
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).
 
1620
     */
 
1621
 
 
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.
 
1625
     */
 
1626
    SIMPLE_AGC(cport->last_mix_adj, cport->mix_adj);
 
1627
    cport->last_mix_adj = cport->mix_adj;
 
1628
 
 
1629
    /* adj_level = cport->tx_adj_level * cport->mix_adj / NORMAL_LEVEL;*/
 
1630
    adj_level = cport->tx_adj_level * cport->mix_adj;
 
1631
    adj_level >>= 7;
 
1632
 
 
1633
    tx_level = 0;
 
1634
 
 
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];
 
1638
 
 
1639
            /* Adjust the level */
 
1640
            /*itemp = itemp * adj_level / NORMAL_LEVEL;*/
 
1641
            itemp = (itemp * adj_level) >> 7;
 
1642
 
 
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;
 
1646
 
 
1647
            /* Put back in the buffer. */
 
1648
            buf[j] = (pj_int16_t) itemp;
 
1649
 
 
1650
            tx_level += (buf[j]>=0? buf[j] : -buf[j]);
 
1651
        }
 
1652
    } else {
 
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]);
 
1656
        }
 
1657
    }
 
1658
 
 
1659
    tx_level /= conf->samples_per_frame;
 
1660
 
 
1661
    /* Convert level to 8bit complement ulaw */
 
1662
    tx_level = pjmedia_linear2ulaw(tx_level) ^ 0xff;
 
1663
 
 
1664
    cport->tx_level = tx_level;
 
1665
 
 
1666
    /* If port has the same clock_rate and samples_per_frame and 
 
1667
     * number of channels as the conference bridge, transmit the 
 
1668
     * frame as is.
 
1669
     */
 
1670
    if (cport->clock_rate == conf->clock_rate &&
 
1671
        cport->samples_per_frame == conf->samples_per_frame &&
 
1672
        cport->channel_count == conf->channel_count)
 
1673
    {
 
1674
        if (cport->port != NULL) {
 
1675
            pjmedia_frame frame;
 
1676
 
 
1677
            frame.type = PJMEDIA_FRAME_TYPE_AUDIO;
 
1678
            frame.buf = buf;
 
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 
 
1682
             */
 
1683
            frame.timestamp = *timestamp;
 
1684
 
 
1685
            TRACE_((THIS_FILE, "put_frame %.*s, count=%d", 
 
1686
                               (int)cport->name.slen, cport->name.ptr,
 
1687
                               frame.size / BYTES_PER_SAMPLE));
 
1688
 
 
1689
            return pjmedia_port_put_frame(cport->port, &frame);
 
1690
        } else
 
1691
            return PJ_SUCCESS;
 
1692
    }
 
1693
 
 
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);
 
1700
    } else {
 
1701
        /* Same clock rate.
 
1702
         * Just copy the samples to tx_buffer.
 
1703
         */
 
1704
        pjmedia_copy_samples( cport->tx_buf + cport->tx_buf_count,
 
1705
                              buf, conf->samples_per_frame );
 
1706
        dst_count = conf->samples_per_frame;
 
1707
    }
 
1708
 
 
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, 
 
1715
                                         dst_count, 0);
 
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;
 
1722
        }
 
1723
    }
 
1724
 
 
1725
    cport->tx_buf_count += dst_count;
 
1726
 
 
1727
    pj_assert(cport->tx_buf_count <= cport->tx_buf_cap);
 
1728
 
 
1729
    /* Transmit while we have enough frame in the tx_buf. */
 
1730
    status = PJ_SUCCESS;
 
1731
    ts = 0;
 
1732
    while (cport->tx_buf_count >= cport->samples_per_frame &&
 
1733
           status == PJ_SUCCESS) 
 
1734
    {
 
1735
        
 
1736
        TRACE_((THIS_FILE, "write_port %.*s: count=%d", 
 
1737
                           (int)cport->name.slen, cport->name.ptr,
 
1738
                           cport->samples_per_frame));
 
1739
 
 
1740
        if (cport->port) {
 
1741
            pjmedia_frame frame;
 
1742
 
 
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
 
1747
             * than the bridge.
 
1748
             */
 
1749
            frame.timestamp.u64 = timestamp->u64 * cport->clock_rate /
 
1750
                                  conf->clock_rate;
 
1751
 
 
1752
            /* Add timestamp for individual frame */
 
1753
            frame.timestamp.u64 += ts;
 
1754
            ts += cport->samples_per_frame;
 
1755
 
 
1756
            TRACE_((THIS_FILE, "put_frame %.*s, count=%d", 
 
1757
                               (int)cport->name.slen, cport->name.ptr,
 
1758
                               frame.size / BYTES_PER_SAMPLE));
 
1759
 
 
1760
            status = pjmedia_port_put_frame(cport->port, &frame);
 
1761
 
 
1762
        } else
 
1763
            status = PJ_SUCCESS;
 
1764
 
 
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);
 
1770
        }
 
1771
 
 
1772
        TRACE_((THIS_FILE, " tx_buf count now is %d", 
 
1773
                           cport->tx_buf_count));
 
1774
    }
 
1775
 
 
1776
    return status;
 
1777
}
 
1778
 
 
1779
 
 
1780
/*
 
1781
 * Player callback.
 
1782
 */
 
1783
static pj_status_t get_frame(pjmedia_port *this_port, 
 
1784
                             pjmedia_frame *frame)
 
1785
{
 
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;
 
1789
    pj_int16_t *p_in;
 
1790
    
 
1791
    TRACE_((THIS_FILE, "- clock -"));
 
1792
 
 
1793
    /* Check that correct size is specified. */
 
1794
    pj_assert(frame->size == conf->samples_per_frame *
 
1795
                             conf->bits_per_sample / 8);
 
1796
 
 
1797
    /* Must lock mutex */
 
1798
    pj_mutex_lock(conf->mutex);
 
1799
 
 
1800
    /* Reset port source count. We will only reset port's mix
 
1801
     * buffer when we have someone transmitting to it.
 
1802
     */
 
1803
    for (i=0, ci=0; i<conf->max_ports && ci < conf->port_cnt; ++i) {
 
1804
        struct conf_port *conf_port = conf->ports[i];
 
1805
 
 
1806
        /* Skip empty port. */
 
1807
        if (!conf_port)
 
1808
            continue;
 
1809
 
 
1810
        /* Var "ci" is to count how many ports have been visited so far. */
 
1811
        ++ci;
 
1812
 
 
1813
        /* Reset buffer (only necessary if the port has transmitter) and
 
1814
         * reset auto adjustment level for mixed signal.
 
1815
         */
 
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]));
 
1820
        }
 
1821
    }
 
1822
 
 
1823
    /* Get frames from all ports, and "mix" the signal 
 
1824
     * to mix_buf of all listeners of the port.
 
1825
     */
 
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;
 
1829
 
 
1830
        /* Skip empty port. */
 
1831
        if (!conf_port)
 
1832
            continue;
 
1833
 
 
1834
        /* Var "ci" is to count how many ports have been visited so far. */
 
1835
        ++ci;
 
1836
 
 
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;
 
1840
            continue;
 
1841
        }
 
1842
 
 
1843
        /* Also skip if this port doesn't have listeners. */
 
1844
        if (conf_port->listener_cnt == 0) {
 
1845
            conf_port->rx_level = 0;
 
1846
            continue;
 
1847
        }
 
1848
 
 
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. 
 
1852
         */
 
1853
        if (conf_port->delay_buf != NULL) {
 
1854
            pj_status_t status;
 
1855
        
 
1856
            status = pjmedia_delay_buf_get(conf_port->delay_buf,
 
1857
                                  (pj_int16_t*)frame->buf);
 
1858
            if (status != PJ_SUCCESS)
 
1859
                continue;
 
1860
 
 
1861
        } else {
 
1862
 
 
1863
            pj_status_t status;
 
1864
            pjmedia_frame_type frame_type;
 
1865
 
 
1866
            status = read_port(conf, conf_port, (pj_int16_t*)frame->buf, 
 
1867
                               conf->samples_per_frame, &frame_type);
 
1868
            
 
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,
 
1876
                                     status));
 
1877
                conf_port->rx_setting = PJMEDIA_PORT_DISABLE;
 
1878
                 */
 
1879
                continue;
 
1880
            }
 
1881
 
 
1882
            /* Check that the port is not removed when we call get_frame() */
 
1883
            if (conf->ports[i] == NULL)
 
1884
                continue;
 
1885
 
 
1886
            /* Ignore if we didn't get any frame */
 
1887
            if (frame_type != PJMEDIA_FRAME_TYPE_AUDIO)
 
1888
                continue;
 
1889
        }
 
1890
 
 
1891
        p_in = (pj_int16_t*) frame->buf;
 
1892
 
 
1893
        /* Adjust the RX level from this port
 
1894
         * and calculate the average level at the same time.
 
1895
         */
 
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.
 
1901
                 */
 
1902
                pj_int32_t itemp;
 
1903
 
 
1904
                itemp = p_in[j];
 
1905
                /*itemp = itemp * adj / NORMAL_LEVEL;*/
 
1906
                /* bad code (signed/unsigned badness):
 
1907
                 *  itemp = (itemp * conf_port->rx_adj_level) >> 7;
 
1908
                 */
 
1909
                itemp *= conf_port->rx_adj_level;
 
1910
                itemp >>= 7;
 
1911
 
 
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;
 
1915
 
 
1916
                p_in[j] = (pj_int16_t) itemp;
 
1917
                level += (p_in[j]>=0? p_in[j] : -p_in[j]);
 
1918
            }
 
1919
        } else {
 
1920
            for (j=0; j<conf->samples_per_frame; ++j) {
 
1921
                level += (p_in[j]>=0? p_in[j] : -p_in[j]);
 
1922
            }
 
1923
        }
 
1924
 
 
1925
        level /= conf->samples_per_frame;
 
1926
 
 
1927
        /* Convert level to 8bit complement ulaw */
 
1928
        level = pjmedia_linear2ulaw(level) ^ 0xff;
 
1929
 
 
1930
        /* Put this level to port's last RX level. */
 
1931
        conf_port->rx_level = level;
 
1932
 
 
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 */
 
1936
        //if (level == 0)
 
1937
        //    continue;
 
1938
 
 
1939
        /* Add the signal to all listeners. */
 
1940
        for (cj=0; cj < conf_port->listener_cnt; ++cj) 
 
1941
        {
 
1942
            struct conf_port *listener;
 
1943
            pj_int32_t *mix_buf;
 
1944
            unsigned k;
 
1945
 
 
1946
            listener = conf->ports[conf_port->listener_slots[cj]];
 
1947
 
 
1948
            /* Skip if this listener doesn't want to receive audio */
 
1949
            if (listener->tx_setting != PJMEDIA_PORT_ENABLE)
 
1950
                continue;
 
1951
 
 
1952
            mix_buf = listener->mix_buf;
 
1953
 
 
1954
            if (listener->transmitter_cnt > 1) {
 
1955
                /* Mixing signals,
 
1956
                 * and calculate appropriate level adjustment if there is
 
1957
                 * any overflowed level in the mixed signal.
 
1958
                 */
 
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;
 
1966
 
 
1967
                        if (tmp_adj<listener->mix_adj)
 
1968
                            listener->mix_adj = tmp_adj;
 
1969
 
 
1970
                    } /* if any overflow in the mixed signals */
 
1971
                } /* loop mixing signals */
 
1972
            } else {
 
1973
                /* Only 1 transmitter:
 
1974
                 * just copy the samples to the mix buffer
 
1975
                 * no mixing and level adjustment needed
 
1976
                 */
 
1977
                for (k=0; k<conf->samples_per_frame; ++k) {
 
1978
                    mix_buf[k] = p_in[k];
 
1979
                }
 
1980
            }
 
1981
        } /* loop the listeners of conf port */
 
1982
    } /* loop of all conf ports */
 
1983
 
 
1984
    /* Time for all ports to transmit whetever they have in their
 
1985
     * buffer. 
 
1986
     */
 
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;
 
1990
        pj_status_t status;
 
1991
 
 
1992
        if (!conf_port)
 
1993
            continue;
 
1994
 
 
1995
        /* Var "ci" is to count how many ports have been visited. */
 
1996
        ++ci;
 
1997
 
 
1998
        status = write_port( conf, conf_port, &frame->timestamp,
 
1999
                             &frm_type);
 
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.
 
2006
 
 
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,
 
2011
                                 status));
 
2012
            conf_port->tx_setting = PJMEDIA_PORT_DISABLE;
 
2013
            */
 
2014
            continue;
 
2015
        }
 
2016
 
 
2017
        /* Set the type of frame to be returned to sound playback
 
2018
         * device.
 
2019
         */
 
2020
        if (i == 0)
 
2021
            speaker_frame_type = frm_type;
 
2022
    }
 
2023
 
 
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);
 
2031
    } else {
 
2032
        /* Force frame type NONE */
 
2033
        speaker_frame_type = PJMEDIA_FRAME_TYPE_NONE;
 
2034
    }
 
2035
 
 
2036
    /* MUST set frame type */
 
2037
    frame->type = speaker_frame_type;
 
2038
 
 
2039
    pj_mutex_unlock(conf->mutex);
 
2040
 
 
2041
#ifdef REC_FILE
 
2042
    if (fhnd_rec == NULL)
 
2043
        fhnd_rec = fopen(REC_FILE, "wb");
 
2044
    if (fhnd_rec)
 
2045
        fwrite(frame->buf, frame->size, 1, fhnd_rec);
 
2046
#endif
 
2047
 
 
2048
    return PJ_SUCCESS;
 
2049
}
 
2050
 
 
2051
 
 
2052
/*
 
2053
 * get_frame() for passive port
 
2054
 */
 
2055
static pj_status_t get_frame_pasv(pjmedia_port *this_port, 
 
2056
                                  pjmedia_frame *frame)
 
2057
{
 
2058
    pj_assert(0);
 
2059
    PJ_UNUSED_ARG(this_port);
 
2060
    PJ_UNUSED_ARG(frame);
 
2061
    return -1;
 
2062
}
 
2063
 
 
2064
 
 
2065
/*
 
2066
 * Recorder (or passive port) callback.
 
2067
 */
 
2068
static pj_status_t put_frame(pjmedia_port *this_port, 
 
2069
                             pjmedia_frame *frame)
 
2070
{
 
2071
    pjmedia_conf *conf = (pjmedia_conf*) this_port->port_data.pdata;
 
2072
    struct conf_port *port = conf->ports[this_port->port_data.ldata];
 
2073
    pj_status_t status;
 
2074
 
 
2075
    /* Check for correct size. */
 
2076
    PJ_ASSERT_RETURN( frame->size == conf->samples_per_frame *
 
2077
                                     conf->bits_per_sample / 8,
 
2078
                      PJMEDIA_ENCSAMPLESPFRAME);
 
2079
 
 
2080
    /* Check existance of delay_buf instance */
 
2081
    PJ_ASSERT_RETURN( port->delay_buf, PJ_EBUG );
 
2082
 
 
2083
    /* Skip if this port is muted/disabled. */
 
2084
    if (port->rx_setting != PJMEDIA_PORT_ENABLE) {
 
2085
        return PJ_SUCCESS;
 
2086
    }
 
2087
 
 
2088
    /* Skip if no port is listening to the microphone */
 
2089
    if (port->listener_cnt == 0) {
 
2090
        return PJ_SUCCESS;
 
2091
    }
 
2092
 
 
2093
    status = pjmedia_delay_buf_put(port->delay_buf, (pj_int16_t*)frame->buf);
 
2094
 
 
2095
    return status;
 
2096
}
 
2097
 
 
2098
#endif