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

« back to all changes in this revision

Viewing changes to daemon/libs/pjproject-2.0.1/pjmedia/src/pjmedia/master_port.c

  • Committer: Package Import Robot
  • Author(s): Mark Purcell
  • Date: 2014-01-28 18:23:36 UTC
  • mfrom: (1.1.11)
  • mto: This revision was merged to the branch mainline in revision 24.
  • Revision ID: package-import@ubuntu.com-20140128182336-3xenud1kbnwmf3mz
* 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: master_port.c 3664 2011-07-19 03:42:28Z 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/master_port.h>
21
 
#include <pjmedia/clock.h>
22
 
#include <pjmedia/errno.h>
23
 
#include <pj/assert.h>
24
 
#include <pj/lock.h>
25
 
#include <pj/pool.h>
26
 
#include <pj/string.h>
27
 
 
28
 
 
29
 
struct pjmedia_master_port
30
 
{
31
 
    unsigned         options;
32
 
    pjmedia_clock   *clock;
33
 
    pjmedia_port    *u_port;
34
 
    pjmedia_port    *d_port;
35
 
    unsigned         buff_size;
36
 
    void            *buff;
37
 
    pj_lock_t       *lock;
38
 
};
39
 
 
40
 
 
41
 
static void clock_callback(const pj_timestamp *ts, void *user_data);
42
 
 
43
 
 
44
 
/*
45
 
 * Create a master port.
46
 
 *
47
 
 */
48
 
PJ_DEF(pj_status_t) pjmedia_master_port_create( pj_pool_t *pool,
49
 
                                                pjmedia_port *u_port,
50
 
                                                pjmedia_port *d_port,
51
 
                                                unsigned options,
52
 
                                                pjmedia_master_port **p_m)
53
 
{
54
 
    pjmedia_master_port *m;
55
 
    unsigned clock_rate;
56
 
    unsigned channel_count;
57
 
    unsigned samples_per_frame;
58
 
    unsigned bytes_per_frame;
59
 
    pjmedia_audio_format_detail *u_afd, *d_afd;
60
 
    pj_status_t status;
61
 
 
62
 
    /* Sanity check */
63
 
    PJ_ASSERT_RETURN(pool && u_port && d_port && p_m, PJ_EINVAL);
64
 
 
65
 
    u_afd = pjmedia_format_get_audio_format_detail(&u_port->info.fmt, PJ_TRUE);
66
 
    d_afd = pjmedia_format_get_audio_format_detail(&d_port->info.fmt, PJ_TRUE);
67
 
 
68
 
    /* Both ports MUST have equal clock rate */
69
 
    PJ_ASSERT_RETURN(u_afd->clock_rate == d_afd->clock_rate,
70
 
                     PJMEDIA_ENCCLOCKRATE);
71
 
 
72
 
    /* Both ports MUST have equal samples per frame */
73
 
    PJ_ASSERT_RETURN(PJMEDIA_PIA_SPF(&u_port->info)==
74
 
                        PJMEDIA_PIA_SPF(&d_port->info),
75
 
                     PJMEDIA_ENCSAMPLESPFRAME);
76
 
 
77
 
    /* Both ports MUST have equal channel count */
78
 
    PJ_ASSERT_RETURN(u_afd->channel_count == d_afd->channel_count,
79
 
                     PJMEDIA_ENCCHANNEL);
80
 
 
81
 
 
82
 
    /* Get clock_rate and samples_per_frame from one of the port. */
83
 
    clock_rate = u_afd->clock_rate;
84
 
    samples_per_frame = PJMEDIA_PIA_SPF(&u_port->info);
85
 
    channel_count = u_afd->channel_count;
86
 
 
87
 
 
88
 
    /* Get the bytes_per_frame value, to determine the size of the
89
 
     * buffer. We take the larger size of the two ports.
90
 
     */
91
 
    bytes_per_frame = PJMEDIA_AFD_AVG_FSZ(u_afd);
92
 
    if (PJMEDIA_AFD_AVG_FSZ(d_afd) > bytes_per_frame)
93
 
        bytes_per_frame = PJMEDIA_AFD_AVG_FSZ(d_afd);
94
 
 
95
 
 
96
 
    /* Create the master port instance */
97
 
    m = PJ_POOL_ZALLOC_T(pool, pjmedia_master_port);
98
 
    m->options = options;
99
 
    m->u_port = u_port;
100
 
    m->d_port = d_port;
101
 
 
102
 
 
103
 
    /* Create buffer */
104
 
    m->buff_size = bytes_per_frame;
105
 
    m->buff = pj_pool_alloc(pool, m->buff_size);
106
 
    if (!m->buff)
107
 
        return PJ_ENOMEM;
108
 
 
109
 
    /* Create lock object */
110
 
    status = pj_lock_create_simple_mutex(pool, "mport", &m->lock);
111
 
    if (status != PJ_SUCCESS)
112
 
        return status;
113
 
 
114
 
    /* Create media clock */
115
 
    status = pjmedia_clock_create(pool, clock_rate, channel_count,
116
 
                                  samples_per_frame, options, &clock_callback,
117
 
                                  m, &m->clock);
118
 
    if (status != PJ_SUCCESS) {
119
 
        pj_lock_destroy(m->lock);
120
 
        return status;
121
 
    }
122
 
 
123
 
    /* Done */
124
 
    *p_m = m;
125
 
 
126
 
    return PJ_SUCCESS;
127
 
}
128
 
 
129
 
 
130
 
/*
131
 
 * Start the media flow.
132
 
 */
133
 
PJ_DEF(pj_status_t) pjmedia_master_port_start(pjmedia_master_port *m)
134
 
{
135
 
    PJ_ASSERT_RETURN(m && m->clock, PJ_EINVAL);
136
 
    PJ_ASSERT_RETURN(m->u_port && m->d_port, PJ_EINVALIDOP);
137
 
 
138
 
    return pjmedia_clock_start(m->clock);
139
 
}
140
 
 
141
 
 
142
 
/*
143
 
 * Stop the media flow.
144
 
 */
145
 
PJ_DEF(pj_status_t) pjmedia_master_port_stop(pjmedia_master_port *m)
146
 
{
147
 
    PJ_ASSERT_RETURN(m && m->clock, PJ_EINVAL);
148
 
 
149
 
    return pjmedia_clock_stop(m->clock);
150
 
}
151
 
 
152
 
 
153
 
/* Poll the master port clock */
154
 
PJ_DEF(pj_bool_t) pjmedia_master_port_wait( pjmedia_master_port *m,
155
 
                                            pj_bool_t wait,
156
 
                                            pj_timestamp *ts)
157
 
{
158
 
    PJ_ASSERT_RETURN(m && m->clock, PJ_FALSE);
159
 
 
160
 
    return pjmedia_clock_wait(m->clock, wait, ts);
161
 
}
162
 
 
163
 
/*
164
 
 * Callback to be called for each clock ticks.
165
 
 */
166
 
static void clock_callback(const pj_timestamp *ts, void *user_data)
167
 
{
168
 
    pjmedia_master_port *m = (pjmedia_master_port*) user_data;
169
 
    pjmedia_frame frame;
170
 
    pj_status_t status;
171
 
 
172
 
 
173
 
    /* Lock access to ports. */
174
 
    pj_lock_acquire(m->lock);
175
 
 
176
 
    /* Get frame from upstream port and pass it to downstream port */
177
 
    pj_bzero(&frame, sizeof(frame));
178
 
    frame.buf = m->buff;
179
 
    frame.size = m->buff_size;
180
 
    frame.timestamp.u64 = ts->u64;
181
 
 
182
 
    status = pjmedia_port_get_frame(m->u_port, &frame);
183
 
    if (status != PJ_SUCCESS)
184
 
        frame.type = PJMEDIA_FRAME_TYPE_NONE;
185
 
 
186
 
    status = pjmedia_port_put_frame(m->d_port, &frame);
187
 
 
188
 
    /* Get frame from downstream port and pass it to upstream port */
189
 
    pj_bzero(&frame, sizeof(frame));
190
 
    frame.buf = m->buff;
191
 
    frame.size = m->buff_size;
192
 
    frame.timestamp.u64 = ts->u64;
193
 
 
194
 
    status = pjmedia_port_get_frame(m->d_port, &frame);
195
 
    if (status != PJ_SUCCESS)
196
 
        frame.type = PJMEDIA_FRAME_TYPE_NONE;
197
 
 
198
 
    status = pjmedia_port_put_frame(m->u_port, &frame);
199
 
 
200
 
    /* Release lock */
201
 
    pj_lock_release(m->lock);
202
 
}
203
 
 
204
 
 
205
 
/*
206
 
 * Change the upstream port.
207
 
 */
208
 
PJ_DEF(pj_status_t) pjmedia_master_port_set_uport(pjmedia_master_port *m,
209
 
                                                     pjmedia_port *port)
210
 
{
211
 
    PJ_ASSERT_RETURN(m && port, PJ_EINVAL);
212
 
 
213
 
    /* Only supports audio for now */
214
 
    PJ_ASSERT_RETURN(port->info.fmt.type==PJMEDIA_TYPE_AUDIO, PJ_ENOTSUP);
215
 
 
216
 
    /* If we have downstream port, make sure they have matching samples per
217
 
     * frame.
218
 
     */
219
 
    if (m->d_port) {
220
 
        PJ_ASSERT_RETURN(
221
 
            PJMEDIA_PIA_PTIME(&port->info) ==
222
 
                PJMEDIA_PIA_PTIME(&m->d_port->info),
223
 
            PJMEDIA_ENCSAMPLESPFRAME
224
 
        );
225
 
    }
226
 
 
227
 
    pj_lock_acquire(m->lock);
228
 
 
229
 
    m->u_port = port;
230
 
 
231
 
    pj_lock_release(m->lock);
232
 
 
233
 
    return PJ_SUCCESS;
234
 
}
235
 
 
236
 
 
237
 
/*
238
 
 * Get the upstream port.
239
 
 */
240
 
PJ_DEF(pjmedia_port*) pjmedia_master_port_get_uport(pjmedia_master_port*m)
241
 
{
242
 
    PJ_ASSERT_RETURN(m, NULL);
243
 
    return m->u_port;
244
 
}
245
 
 
246
 
 
247
 
/*
248
 
 * Change the downstream port.
249
 
 */
250
 
PJ_DEF(pj_status_t) pjmedia_master_port_set_dport(pjmedia_master_port *m,
251
 
                                                  pjmedia_port *port)
252
 
{
253
 
    PJ_ASSERT_RETURN(m && port, PJ_EINVAL);
254
 
 
255
 
    /* Only supports audio for now */
256
 
    PJ_ASSERT_RETURN(port->info.fmt.type==PJMEDIA_TYPE_AUDIO, PJ_ENOTSUP);
257
 
 
258
 
    /* If we have upstream port, make sure they have matching samples per
259
 
     * frame.
260
 
     */
261
 
    if (m->u_port) {
262
 
        PJ_ASSERT_RETURN(
263
 
            PJMEDIA_PIA_PTIME(&port->info) ==
264
 
                    PJMEDIA_PIA_PTIME(&m->u_port->info),
265
 
            PJMEDIA_ENCSAMPLESPFRAME
266
 
        );
267
 
    }
268
 
 
269
 
    pj_lock_acquire(m->lock);
270
 
 
271
 
    m->d_port = port;
272
 
 
273
 
    pj_lock_release(m->lock);
274
 
 
275
 
    return PJ_SUCCESS;
276
 
}
277
 
 
278
 
 
279
 
/*
280
 
 * Get the downstream port.
281
 
 */
282
 
PJ_DEF(pjmedia_port*) pjmedia_master_port_get_dport(pjmedia_master_port*m)
283
 
{
284
 
    PJ_ASSERT_RETURN(m, NULL);
285
 
    return m->d_port;
286
 
}
287
 
 
288
 
 
289
 
/*
290
 
 * Destroy the master port, and optionally destroy the u_port and
291
 
 * d_port ports.
292
 
 */
293
 
PJ_DEF(pj_status_t) pjmedia_master_port_destroy(pjmedia_master_port *m,
294
 
                                                pj_bool_t destroy_ports)
295
 
{
296
 
    PJ_ASSERT_RETURN(m, PJ_EINVAL);
297
 
 
298
 
    if (m->clock) {
299
 
        pjmedia_clock_destroy(m->clock);
300
 
        m->clock = NULL;
301
 
    }
302
 
 
303
 
    if (m->u_port && destroy_ports) {
304
 
        pjmedia_port_destroy(m->u_port);
305
 
        m->u_port = NULL;
306
 
    }
307
 
 
308
 
    if (m->d_port && destroy_ports) {
309
 
        pjmedia_port_destroy(m->d_port);
310
 
        m->d_port = NULL;
311
 
    }
312
 
 
313
 
    if (m->lock) {
314
 
        pj_lock_destroy(m->lock);
315
 
        m->lock = NULL;
316
 
    }
317
 
 
318
 
    return PJ_SUCCESS;
319
 
}