~ubuntu-branches/ubuntu/wily/sflphone/wily

« 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): Jonathan Riddell
  • Date: 2015-01-07 14:51:16 UTC
  • mfrom: (4.3.5 sid)
  • Revision ID: package-import@ubuntu.com-20150107145116-yxnafinf4lrdvrmx
Tags: 1.4.1-0.1ubuntu1
* Merge with Debian, remaining changes:
 - Drop soprano, nepomuk build-dep
* Drop ubuntu patches, now upstream

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