~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/stream.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: stream.c 4120 2012-05-12 07:18:09Z ming $ */
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/stream.h>
21
 
#include <pjmedia/errno.h>
22
 
#include <pjmedia/rtp.h>
23
 
#include <pjmedia/rtcp.h>
24
 
#include <pjmedia/jbuf.h>
25
 
#include <pjmedia/stream_common.h>
26
 
#include <pj/array.h>
27
 
#include <pj/assert.h>
28
 
#include <pj/ctype.h>
29
 
#include <pj/compat/socket.h>
30
 
#include <pj/errno.h>
31
 
#include <pj/ioqueue.h>
32
 
#include <pj/log.h>
33
 
#include <pj/os.h>
34
 
#include <pj/pool.h>
35
 
#include <pj/rand.h>
36
 
#include <pj/sock_select.h>
37
 
#include <pj/string.h>      /* memcpy() */
38
 
 
39
 
 
40
 
#define THIS_FILE                       "stream.c"
41
 
#define ERRLEVEL                        1
42
 
#define LOGERR_(expr)                   stream_perror expr
43
 
#define TRC_(expr)                      PJ_LOG(5,expr)
44
 
 
45
 
#define BYTES_PER_SAMPLE                2
46
 
 
47
 
/* Limit the number of synthetic audio samples that are generated by PLC.
48
 
 * Normally PLC should have it's own means to limit the number of
49
 
 * synthetic frames, so we need to set this to a reasonably large value
50
 
 * just as precaution
51
 
 */
52
 
#define MAX_PLC_MSEC                    PJMEDIA_MAX_PLC_DURATION_MSEC
53
 
 
54
 
 
55
 
/* Tracing jitter buffer operations in a stream session to a CSV file.
56
 
 * The trace will contain JB operation timestamp, frame info, RTP info, and
57
 
 * the JB state right after the operation.
58
 
 */
59
 
#define TRACE_JB                        0       /* Enable/disable trace.    */
60
 
#define TRACE_JB_PATH_PREFIX            ""      /* Optional path/prefix
61
 
                                                   for the CSV filename.    */
62
 
#if TRACE_JB
63
 
#   include <pj/file_io.h>
64
 
#   define TRACE_JB_INVALID_FD          ((pj_oshandle_t)-1)
65
 
#   define TRACE_JB_OPENED(s)           (s->trace_jb_fd != TRACE_JB_INVALID_FD)
66
 
#endif
67
 
 
68
 
#ifndef PJMEDIA_STREAM_SIZE
69
 
#   define PJMEDIA_STREAM_SIZE  1000
70
 
#endif
71
 
 
72
 
#ifndef PJMEDIA_STREAM_INC
73
 
#   define PJMEDIA_STREAM_INC   1000
74
 
#endif
75
 
 
76
 
 
77
 
/**
78
 
 * Media channel.
79
 
 */
80
 
struct pjmedia_channel
81
 
{
82
 
    pjmedia_stream         *stream;         /**< Parent stream.             */
83
 
    pjmedia_dir             dir;            /**< Channel direction.         */
84
 
    unsigned                pt;             /**< Payload type.              */
85
 
    pj_bool_t               paused;         /**< Paused?.                   */
86
 
    unsigned                out_pkt_size;   /**< Size of output buffer.     */
87
 
    void                   *out_pkt;        /**< Output buffer.             */
88
 
    unsigned                out_pkt_len;    /**< Length of data in buffer.  */
89
 
    pjmedia_rtp_session     rtp;            /**< RTP session.               */
90
 
};
91
 
 
92
 
 
93
 
struct dtmf
94
 
{
95
 
    int             event;
96
 
    pj_uint32_t     duration;
97
 
};
98
 
 
99
 
/**
100
 
 * This structure describes media stream.
101
 
 * A media stream is bidirectional media transmission between two endpoints.
102
 
 * It consists of two channels, i.e. encoding and decoding channels.
103
 
 * A media stream corresponds to a single "m=" line in a SDP session
104
 
 * description.
105
 
 */
106
 
struct pjmedia_stream
107
 
{
108
 
    pjmedia_endpt           *endpt;         /**< Media endpoint.            */
109
 
    pjmedia_codec_mgr       *codec_mgr;     /**< Codec manager instance.    */
110
 
    pjmedia_stream_info      si;            /**< Creation parameter.        */
111
 
    pjmedia_port             port;          /**< Port interface.            */
112
 
    pjmedia_channel         *enc;           /**< Encoding channel.          */
113
 
    pjmedia_channel         *dec;           /**< Decoding channel.          */
114
 
 
115
 
    pj_pool_t               *own_pool;      /**< Only created if not given  */
116
 
 
117
 
    pjmedia_dir              dir;           /**< Stream direction.          */
118
 
    void                    *user_data;     /**< User data.                 */
119
 
    pj_str_t                 cname;         /**< SDES CNAME                 */
120
 
 
121
 
    pjmedia_transport       *transport;     /**< Stream transport.          */
122
 
 
123
 
    pjmedia_codec           *codec;         /**< Codec instance being used. */
124
 
    pjmedia_codec_param      codec_param;   /**< Codec param.               */
125
 
    pj_int16_t              *enc_buf;       /**< Encoding buffer, when enc's
126
 
                                                 ptime is different than dec.
127
 
                                                 Otherwise it's NULL.       */
128
 
 
129
 
    unsigned                 enc_samples_per_pkt;
130
 
    unsigned                 enc_buf_size;  /**< Encoding buffer size, in
131
 
                                                 samples.                   */
132
 
    unsigned                 enc_buf_pos;   /**< First position in buf.     */
133
 
    unsigned                 enc_buf_count; /**< Number of samples in the
134
 
                                                 encoding buffer.           */
135
 
 
136
 
    unsigned                 plc_cnt;       /**< # of consecutive PLC frames*/
137
 
    unsigned                 max_plc_cnt;   /**< Max # of PLC frames        */
138
 
 
139
 
    unsigned                 vad_enabled;   /**< VAD enabled in param.      */
140
 
    unsigned                 frame_size;    /**< Size of encoded base frame.*/
141
 
    pj_bool_t                is_streaming;  /**< Currently streaming?. This
142
 
                                                 is used to put RTP marker
143
 
                                                 bit.                       */
144
 
    pj_uint32_t              ts_vad_disabled;/**< TS when VAD was disabled. */
145
 
    pj_uint32_t              tx_duration;   /**< TX duration in timestamp.  */
146
 
 
147
 
    pj_mutex_t              *jb_mutex;
148
 
    pjmedia_jbuf            *jb;            /**< Jitter buffer.             */
149
 
    char                     jb_last_frm;   /**< Last frame type from jb    */
150
 
    unsigned                 jb_last_frm_cnt;/**< Last JB frame type counter*/
151
 
 
152
 
    pjmedia_rtcp_session     rtcp;          /**< RTCP for incoming RTP.     */
153
 
 
154
 
    pj_uint32_t              rtcp_last_tx;  /**< RTCP tx time in timestamp  */
155
 
    pj_uint32_t              rtcp_interval; /**< Interval, in timestamp.    */
156
 
    pj_bool_t                initial_rr;    /**< Initial RTCP RR sent       */
157
 
    pj_bool_t                rtcp_sdes_bye_disabled;/**< Send RTCP SDES/BYE?*/
158
 
    void                    *out_rtcp_pkt;  /**< Outgoing RTCP packet.      */
159
 
    unsigned                 out_rtcp_pkt_size;
160
 
                                            /**< Outgoing RTCP packet size. */
161
 
 
162
 
    /* RFC 2833 DTMF transmission queue: */
163
 
    int                      tx_event_pt;   /**< Outgoing pt for dtmf.      */
164
 
    int                      tx_dtmf_count; /**< # of digits in tx dtmf buf.*/
165
 
    struct dtmf              tx_dtmf_buf[32];/**< Outgoing dtmf queue.      */
166
 
 
167
 
    /* Incoming DTMF: */
168
 
    int                      rx_event_pt;   /**< Incoming pt for dtmf.      */
169
 
    int                      last_dtmf;     /**< Current digit, or -1.      */
170
 
    pj_uint32_t              last_dtmf_dur; /**< Start ts for cur digit.    */
171
 
    unsigned                 rx_dtmf_count; /**< # of digits in dtmf rx buf.*/
172
 
    char                     rx_dtmf_buf[32];/**< Incoming DTMF buffer.     */
173
 
 
174
 
    /* DTMF callback */
175
 
    void                    (*dtmf_cb)(pjmedia_stream*, void*, int);
176
 
    void                     *dtmf_cb_user_data;
177
 
 
178
 
#if defined(PJMEDIA_HANDLE_G722_MPEG_BUG) && (PJMEDIA_HANDLE_G722_MPEG_BUG!=0)
179
 
    /* Enable support to handle codecs with inconsistent clock rate
180
 
     * between clock rate in SDP/RTP & the clock rate that is actually used.
181
 
     * This happens for example with G.722 and MPEG audio codecs.
182
 
     */
183
 
    pj_bool_t                has_g722_mpeg_bug;
184
 
                                            /**< Flag to specify whether
185
 
                                                 normalization process
186
 
                                                 is needed                  */
187
 
    unsigned                 rtp_tx_ts_len_per_pkt;
188
 
                                            /**< Normalized ts length per packet
189
 
                                                 transmitted according to
190
 
                                                 'erroneous' definition     */
191
 
    unsigned                 rtp_rx_ts_len_per_frame;
192
 
                                            /**< Normalized ts length per frame
193
 
                                                 received according to
194
 
                                                 'erroneous' definition     */
195
 
    unsigned                 rtp_rx_last_cnt;/**< Nb of frames in last pkt  */
196
 
    unsigned                 rtp_rx_check_cnt;
197
 
                                            /**< Counter of remote timestamp
198
 
                                                 checking */
199
 
#endif
200
 
 
201
 
#if defined(PJMEDIA_HAS_RTCP_XR) && (PJMEDIA_HAS_RTCP_XR != 0)
202
 
    pj_uint32_t              rtcp_xr_last_tx;  /**< RTCP XR tx time
203
 
                                                    in timestamp.           */
204
 
    pj_uint32_t              rtcp_xr_interval; /**< Interval, in timestamp. */
205
 
    pj_sockaddr              rtcp_xr_dest;     /**< Additional remote RTCP XR
206
 
                                                    dest. If sin_family is
207
 
                                                    zero, it will be ignored*/
208
 
    unsigned                 rtcp_xr_dest_len; /**< Length of RTCP XR dest
209
 
                                                    address                 */
210
 
#endif
211
 
 
212
 
#if defined(PJMEDIA_STREAM_ENABLE_KA) && PJMEDIA_STREAM_ENABLE_KA!=0
213
 
    pj_bool_t                use_ka;           /**< Stream keep-alive with non-
214
 
                                                    codec-VAD mechanism is
215
 
                                                    enabled?                */
216
 
    pj_timestamp             last_frm_ts_sent; /**< Timestamp of last sending
217
 
                                                    packet                  */
218
 
#endif
219
 
 
220
 
#if TRACE_JB
221
 
    pj_oshandle_t           trace_jb_fd;            /**< Jitter tracing file handle.*/
222
 
    char                   *trace_jb_buf;           /**< Jitter tracing buffer.     */
223
 
#endif
224
 
 
225
 
    pj_uint32_t              rtp_rx_last_ts;        /**< Last received RTP timestamp*/
226
 
};
227
 
 
228
 
 
229
 
/* RFC 2833 digit */
230
 
static const char digitmap[16] = { '0', '1', '2', '3',
231
 
                                   '4', '5', '6', '7',
232
 
                                   '8', '9', '*', '#',
233
 
                                   'A', 'B', 'C', 'D'};
234
 
 
235
 
/* Zero audio frame samples */
236
 
static pj_int16_t zero_frame[2 * 30 * 16000 / 1000];
237
 
 
238
 
/*
239
 
 * Print error.
240
 
 */
241
 
static void stream_perror(const char *sender, const char *title,
242
 
                          pj_status_t status)
243
 
{
244
 
    char errmsg[PJ_ERR_MSG_SIZE];
245
 
 
246
 
    pj_strerror(status, errmsg, sizeof(errmsg));
247
 
    PJ_LOG(4,(sender, "%s: %s [err:%d]", title, errmsg, status));
248
 
}
249
 
 
250
 
 
251
 
static pj_status_t send_rtcp(pjmedia_stream *stream,
252
 
                             pj_bool_t with_sdes,
253
 
                             pj_bool_t with_bye,
254
 
                             pj_bool_t with_xr);
255
 
 
256
 
 
257
 
#if TRACE_JB
258
 
 
259
 
PJ_INLINE(int) trace_jb_print_timestamp(char **buf, pj_ssize_t len)
260
 
{
261
 
    pj_time_val now;
262
 
    pj_parsed_time ptime;
263
 
    char *p = *buf;
264
 
 
265
 
    if (len < 14)
266
 
        return -1;
267
 
 
268
 
    pj_gettimeofday(&now);
269
 
    pj_time_decode(&now, &ptime);
270
 
    p += pj_utoa_pad(ptime.hour, p, 2, '0');
271
 
    *p++ = ':';
272
 
    p += pj_utoa_pad(ptime.min, p, 2, '0');
273
 
    *p++ = ':';
274
 
    p += pj_utoa_pad(ptime.sec, p, 2, '0');
275
 
    *p++ = '.';
276
 
    p += pj_utoa_pad(ptime.msec, p, 3, '0');
277
 
    *p++ = ',';
278
 
 
279
 
    *buf = p;
280
 
 
281
 
    return 0;
282
 
}
283
 
 
284
 
PJ_INLINE(int) trace_jb_print_state(pjmedia_stream *stream,
285
 
                                    char **buf, pj_ssize_t len)
286
 
{
287
 
    char *p = *buf;
288
 
    char *endp = *buf + len;
289
 
    pjmedia_jb_state state;
290
 
 
291
 
    pjmedia_jbuf_get_state(stream->jb, &state);
292
 
 
293
 
    len = pj_ansi_snprintf(p, endp-p, "%d, %d, %d",
294
 
                           state.size, state.burst, state.prefetch);
295
 
    if ((len < 0) || (len >= endp-p))
296
 
        return -1;
297
 
 
298
 
    p += len;
299
 
    *buf = p;
300
 
    return 0;
301
 
}
302
 
 
303
 
static void trace_jb_get(pjmedia_stream *stream, pjmedia_jb_frame_type ft,
304
 
                         pj_size_t fsize)
305
 
{
306
 
    char *p = stream->trace_jb_buf;
307
 
    char *endp = stream->trace_jb_buf + PJ_LOG_MAX_SIZE;
308
 
    pj_ssize_t len = 0;
309
 
    const char* ft_st;
310
 
 
311
 
    if (!TRACE_JB_OPENED(stream))
312
 
        return;
313
 
 
314
 
    /* Print timestamp. */
315
 
    if (trace_jb_print_timestamp(&p, endp-p))
316
 
        goto on_insuff_buffer;
317
 
 
318
 
    /* Print frame type and size */
319
 
    switch(ft) {
320
 
        case PJMEDIA_JB_MISSING_FRAME:
321
 
            ft_st = "missing";
322
 
            break;
323
 
        case PJMEDIA_JB_NORMAL_FRAME:
324
 
            ft_st = "normal";
325
 
            break;
326
 
        case PJMEDIA_JB_ZERO_PREFETCH_FRAME:
327
 
            ft_st = "prefetch";
328
 
            break;
329
 
        case PJMEDIA_JB_ZERO_EMPTY_FRAME:
330
 
            ft_st = "empty";
331
 
            break;
332
 
        default:
333
 
            ft_st = "unknown";
334
 
            break;
335
 
    }
336
 
 
337
 
    /* Print operation, size, frame count, frame type */
338
 
    len = pj_ansi_snprintf(p, endp-p, "GET,%d,1,%s,,,,", fsize, ft_st);
339
 
    if ((len < 0) || (len >= endp-p))
340
 
        goto on_insuff_buffer;
341
 
    p += len;
342
 
 
343
 
    /* Print JB state */
344
 
    if (trace_jb_print_state(stream, &p, endp-p))
345
 
        goto on_insuff_buffer;
346
 
 
347
 
    /* Print end of line */
348
 
    if (endp-p < 2)
349
 
        goto on_insuff_buffer;
350
 
    *p++ = '\n';
351
 
 
352
 
    /* Write and flush */
353
 
    len = p - stream->trace_jb_buf;
354
 
    pj_file_write(stream->trace_jb_fd, stream->trace_jb_buf, &len);
355
 
    pj_file_flush(stream->trace_jb_fd);
356
 
    return;
357
 
 
358
 
on_insuff_buffer:
359
 
    pj_assert(!"Trace buffer too small, check PJ_LOG_MAX_SIZE!");
360
 
}
361
 
 
362
 
static void trace_jb_put(pjmedia_stream *stream, const pjmedia_rtp_hdr *hdr,
363
 
                         unsigned payloadlen, unsigned frame_cnt)
364
 
{
365
 
    char *p = stream->trace_jb_buf;
366
 
    char *endp = stream->trace_jb_buf + PJ_LOG_MAX_SIZE;
367
 
    pj_ssize_t len = 0;
368
 
 
369
 
    if (!TRACE_JB_OPENED(stream))
370
 
        return;
371
 
 
372
 
    /* Print timestamp. */
373
 
    if (trace_jb_print_timestamp(&p, endp-p))
374
 
        goto on_insuff_buffer;
375
 
 
376
 
    /* Print operation, size, frame count, RTP info */
377
 
    len = pj_ansi_snprintf(p, endp-p,
378
 
                           "PUT,%d,%d,,%d,%d,%d,",
379
 
                           payloadlen, frame_cnt,
380
 
                           pj_ntohs(hdr->seq), pj_ntohl(hdr->ts), hdr->m);
381
 
    if ((len < 0) || (len >= endp-p))
382
 
        goto on_insuff_buffer;
383
 
    p += len;
384
 
 
385
 
    /* Print JB state */
386
 
    if (trace_jb_print_state(stream, &p, endp-p))
387
 
        goto on_insuff_buffer;
388
 
 
389
 
    /* Print end of line */
390
 
    if (endp-p < 2)
391
 
        goto on_insuff_buffer;
392
 
    *p++ = '\n';
393
 
 
394
 
    /* Write and flush */
395
 
    len = p - stream->trace_jb_buf;
396
 
    pj_file_write(stream->trace_jb_fd, stream->trace_jb_buf, &len);
397
 
    pj_file_flush(stream->trace_jb_fd);
398
 
    return;
399
 
 
400
 
on_insuff_buffer:
401
 
    pj_assert(!"Trace buffer too small, check PJ_LOG_MAX_SIZE!");
402
 
}
403
 
 
404
 
#endif /* TRACE_JB */
405
 
 
406
 
 
407
 
#if defined(PJMEDIA_STREAM_ENABLE_KA) && PJMEDIA_STREAM_ENABLE_KA != 0
408
 
/*
409
 
 * Send keep-alive packet using non-codec frame.
410
 
 */
411
 
static void send_keep_alive_packet(pjmedia_stream *stream)
412
 
{
413
 
#if PJMEDIA_STREAM_ENABLE_KA == PJMEDIA_STREAM_KA_EMPTY_RTP
414
 
 
415
 
    /* Keep-alive packet is empty RTP */
416
 
    pj_status_t status;
417
 
    void *pkt;
418
 
    int pkt_len;
419
 
 
420
 
    TRC_((stream->port.info.name.ptr,
421
 
          "Sending keep-alive (RTCP and empty RTP)"));
422
 
 
423
 
    /* Send RTP */
424
 
    status = pjmedia_rtp_encode_rtp( &stream->enc->rtp,
425
 
                                     stream->enc->pt, 0,
426
 
                                     1,
427
 
                                     0,
428
 
                                     (const void**)&pkt,
429
 
                                     &pkt_len);
430
 
    pj_assert(status == PJ_SUCCESS);
431
 
 
432
 
    pj_memcpy(stream->enc->out_pkt, pkt, pkt_len);
433
 
    pjmedia_transport_send_rtp(stream->transport, stream->enc->out_pkt,
434
 
                               pkt_len);
435
 
 
436
 
    /* Send RTCP */
437
 
    send_rtcp(stream, PJ_TRUE, PJ_FALSE, PJ_FALSE);
438
 
 
439
 
#elif PJMEDIA_STREAM_ENABLE_KA == PJMEDIA_STREAM_KA_USER
440
 
 
441
 
    /* Keep-alive packet is defined in PJMEDIA_STREAM_KA_USER_PKT */
442
 
    int pkt_len;
443
 
    const pj_str_t str_ka = PJMEDIA_STREAM_KA_USER_PKT;
444
 
 
445
 
    TRC_((stream->port.info.name.ptr,
446
 
          "Sending keep-alive (custom RTP/RTCP packets)"));
447
 
 
448
 
    /* Send to RTP port */
449
 
    pj_memcpy(stream->enc->out_pkt, str_ka.ptr, str_ka.slen);
450
 
    pkt_len = str_ka.slen;
451
 
    pjmedia_transport_send_rtp(stream->transport, stream->enc->out_pkt,
452
 
                               pkt_len);
453
 
 
454
 
    /* Send to RTCP port */
455
 
    pjmedia_transport_send_rtcp(stream->transport, stream->enc->out_pkt,
456
 
                                pkt_len);
457
 
 
458
 
#else
459
 
 
460
 
    PJ_UNUSED_ARG(stream);
461
 
 
462
 
#endif
463
 
}
464
 
#endif  /* defined(PJMEDIA_STREAM_ENABLE_KA) */
465
 
 
466
 
/*
467
 
 * play_callback()
468
 
 *
469
 
 * This callback is called by sound device's player thread when it
470
 
 * needs to feed the player with some frames.
471
 
 */
472
 
static pj_status_t get_frame( pjmedia_port *port, pjmedia_frame *frame)
473
 
{
474
 
    pjmedia_stream *stream = (pjmedia_stream*) port->port_data.pdata;
475
 
    pjmedia_channel *channel = stream->dec;
476
 
    unsigned samples_count, samples_per_frame, samples_required;
477
 
    pj_int16_t *p_out_samp;
478
 
    pj_status_t status;
479
 
 
480
 
 
481
 
    /* Return no frame is channel is paused */
482
 
    if (channel->paused) {
483
 
        frame->type = PJMEDIA_FRAME_TYPE_NONE;
484
 
        return PJ_SUCCESS;
485
 
    }
486
 
 
487
 
    /* Repeat get frame from the jitter buffer and decode the frame
488
 
     * until we have enough frames according to codec's ptime.
489
 
     */
490
 
 
491
 
    /* Lock jitter buffer mutex first */
492
 
    pj_mutex_lock( stream->jb_mutex );
493
 
 
494
 
    samples_required = PJMEDIA_PIA_SPF(&stream->port.info);
495
 
    samples_per_frame = stream->codec_param.info.frm_ptime *
496
 
                        stream->codec_param.info.clock_rate *
497
 
                        stream->codec_param.info.channel_cnt /
498
 
                        1000;
499
 
    p_out_samp = (pj_int16_t*) frame->buf;
500
 
 
501
 
    for (samples_count=0; samples_count < samples_required;
502
 
         samples_count += samples_per_frame)
503
 
    {
504
 
        char frame_type;
505
 
        pj_size_t frame_size;
506
 
        pj_uint32_t bit_info;
507
 
 
508
 
        /* Get frame from jitter buffer. */
509
 
        pjmedia_jbuf_get_frame2(stream->jb, channel->out_pkt, &frame_size,
510
 
                                &frame_type, &bit_info);
511
 
 
512
 
#if TRACE_JB
513
 
        trace_jb_get(stream, frame_type, frame_size);
514
 
#endif
515
 
 
516
 
        if (frame_type == PJMEDIA_JB_MISSING_FRAME) {
517
 
 
518
 
            /* Activate PLC */
519
 
            if (stream->codec->op->recover &&
520
 
                stream->codec_param.setting.plc &&
521
 
                stream->plc_cnt < stream->max_plc_cnt)
522
 
            {
523
 
                pjmedia_frame frame_out;
524
 
 
525
 
                frame_out.buf = p_out_samp + samples_count;
526
 
                frame_out.size = frame->size - samples_count*2;
527
 
                status = pjmedia_codec_recover(stream->codec,
528
 
                                               frame_out.size,
529
 
                                               &frame_out);
530
 
 
531
 
                ++stream->plc_cnt;
532
 
 
533
 
            } else {
534
 
                status = -1;
535
 
            }
536
 
 
537
 
            if (status != PJ_SUCCESS) {
538
 
                /* Either PLC failed or PLC not supported/enabled */
539
 
                pjmedia_zero_samples(p_out_samp + samples_count,
540
 
                                     samples_required - samples_count);
541
 
            }
542
 
 
543
 
            if (frame_type != stream->jb_last_frm) {
544
 
                /* Report changing frame type event */
545
 
                PJ_LOG(5,(stream->port.info.name.ptr, "Frame lost%s!",
546
 
                          (status == PJ_SUCCESS? ", recovered":"")));
547
 
 
548
 
                stream->jb_last_frm = frame_type;
549
 
                stream->jb_last_frm_cnt = 1;
550
 
            } else {
551
 
                stream->jb_last_frm_cnt++;
552
 
            }
553
 
 
554
 
        } else if (frame_type == PJMEDIA_JB_ZERO_EMPTY_FRAME) {
555
 
 
556
 
            const char *with_plc = "";
557
 
 
558
 
            /* Jitter buffer is empty. If this is the first "empty" state,
559
 
             * activate PLC to smoothen the fade-out, otherwise zero
560
 
             * the frame.
561
 
             */
562
 
            //Using this "if" will only invoke PLC for the first packet
563
 
            //lost and not the subsequent ones.
564
 
            //if (frame_type != stream->jb_last_frm) {
565
 
            if (1) {
566
 
                /* Activate PLC to smoothen the missing frame */
567
 
                if (stream->codec->op->recover &&
568
 
                    stream->codec_param.setting.plc &&
569
 
                    stream->plc_cnt < stream->max_plc_cnt)
570
 
                {
571
 
                    pjmedia_frame frame_out;
572
 
 
573
 
                    do {
574
 
                        frame_out.buf = p_out_samp + samples_count;
575
 
                        frame_out.size = frame->size - samples_count*2;
576
 
                        status = pjmedia_codec_recover(stream->codec,
577
 
                                                       frame_out.size,
578
 
                                                       &frame_out);
579
 
                        if (status != PJ_SUCCESS)
580
 
                            break;
581
 
 
582
 
                        samples_count += samples_per_frame;
583
 
                        ++stream->plc_cnt;
584
 
 
585
 
                    } while (samples_count < samples_required &&
586
 
                             stream->plc_cnt < stream->max_plc_cnt);
587
 
 
588
 
                    with_plc = ", plc invoked";
589
 
                }
590
 
            }
591
 
 
592
 
            if (samples_count < samples_required) {
593
 
                pjmedia_zero_samples(p_out_samp + samples_count,
594
 
                                     samples_required - samples_count);
595
 
                samples_count = samples_required;
596
 
            }
597
 
 
598
 
            if (stream->jb_last_frm != frame_type) {
599
 
                pjmedia_jb_state jb_state;
600
 
 
601
 
                /* Report changing frame type event */
602
 
                pjmedia_jbuf_get_state(stream->jb, &jb_state);
603
 
                PJ_LOG(5,(stream->port.info.name.ptr,
604
 
                          "Jitter buffer empty (prefetch=%d)%s",
605
 
                          jb_state.prefetch, with_plc));
606
 
 
607
 
                stream->jb_last_frm = frame_type;
608
 
                stream->jb_last_frm_cnt = 1;
609
 
            } else {
610
 
                stream->jb_last_frm_cnt++;
611
 
            }
612
 
            break;
613
 
 
614
 
        } else if (frame_type != PJMEDIA_JB_NORMAL_FRAME) {
615
 
 
616
 
            const char *with_plc = "";
617
 
 
618
 
            /* It can only be PJMEDIA_JB_ZERO_PREFETCH frame */
619
 
            pj_assert(frame_type == PJMEDIA_JB_ZERO_PREFETCH_FRAME);
620
 
 
621
 
            /* Always activate PLC when it's available.. */
622
 
            if (stream->codec->op->recover &&
623
 
                stream->codec_param.setting.plc &&
624
 
                stream->plc_cnt < stream->max_plc_cnt)
625
 
            {
626
 
                pjmedia_frame frame_out;
627
 
 
628
 
                do {
629
 
                    frame_out.buf = p_out_samp + samples_count;
630
 
                    frame_out.size = frame->size - samples_count*2;
631
 
                    status = pjmedia_codec_recover(stream->codec,
632
 
                                                   frame_out.size,
633
 
                                                   &frame_out);
634
 
                    if (status != PJ_SUCCESS)
635
 
                        break;
636
 
                    samples_count += samples_per_frame;
637
 
 
638
 
                    ++stream->plc_cnt;
639
 
 
640
 
                } while (samples_count < samples_required &&
641
 
                         stream->plc_cnt < stream->max_plc_cnt);
642
 
 
643
 
                with_plc = ", plc invoked";
644
 
            }
645
 
 
646
 
            if (samples_count < samples_required) {
647
 
                pjmedia_zero_samples(p_out_samp + samples_count,
648
 
                                     samples_required - samples_count);
649
 
                samples_count = samples_required;
650
 
            }
651
 
 
652
 
            if (stream->jb_last_frm != frame_type) {
653
 
                pjmedia_jb_state jb_state;
654
 
 
655
 
                /* Report changing frame type event */
656
 
                pjmedia_jbuf_get_state(stream->jb, &jb_state);
657
 
                PJ_LOG(5,(stream->port.info.name.ptr,
658
 
                          "Jitter buffer is bufferring (prefetch=%d)%s",
659
 
                          jb_state.prefetch, with_plc));
660
 
 
661
 
                stream->jb_last_frm = frame_type;
662
 
                stream->jb_last_frm_cnt = 1;
663
 
            } else {
664
 
                stream->jb_last_frm_cnt++;
665
 
            }
666
 
            break;
667
 
 
668
 
        } else {
669
 
            /* Got "NORMAL" frame from jitter buffer */
670
 
            pjmedia_frame frame_in, frame_out;
671
 
 
672
 
            stream->plc_cnt = 0;
673
 
 
674
 
            /* Decode */
675
 
            frame_in.buf = channel->out_pkt;
676
 
            frame_in.size = frame_size;
677
 
            frame_in.bit_info = bit_info;
678
 
            frame_in.type = PJMEDIA_FRAME_TYPE_AUDIO;  /* ignored */
679
 
 
680
 
            frame_out.buf = p_out_samp + samples_count;
681
 
            frame_out.size = frame->size - samples_count*BYTES_PER_SAMPLE;
682
 
            status = pjmedia_codec_decode( stream->codec, &frame_in,
683
 
                                           frame_out.size, &frame_out);
684
 
            if (status != 0) {
685
 
                LOGERR_((port->info.name.ptr, "codec decode() error",
686
 
                         status));
687
 
 
688
 
                pjmedia_zero_samples(p_out_samp + samples_count,
689
 
                                     samples_per_frame);
690
 
            }
691
 
 
692
 
            if (stream->jb_last_frm != frame_type) {
693
 
                /* Report changing frame type event */
694
 
                PJ_LOG(5,(stream->port.info.name.ptr,
695
 
                          "Jitter buffer starts returning normal frames "
696
 
                          "(after %d empty/lost)",
697
 
                          stream->jb_last_frm_cnt, stream->jb_last_frm));
698
 
 
699
 
                stream->jb_last_frm = frame_type;
700
 
                stream->jb_last_frm_cnt = 1;
701
 
            } else {
702
 
                stream->jb_last_frm_cnt++;
703
 
            }
704
 
        }
705
 
    }
706
 
 
707
 
 
708
 
    /* Unlock jitter buffer mutex. */
709
 
    pj_mutex_unlock( stream->jb_mutex );
710
 
 
711
 
    /* Return PJMEDIA_FRAME_TYPE_NONE if we have no frames at all
712
 
     * (it can happen when jitter buffer returns PJMEDIA_JB_ZERO_EMPTY_FRAME).
713
 
     */
714
 
    if (samples_count == 0) {
715
 
        frame->type = PJMEDIA_FRAME_TYPE_NONE;
716
 
        frame->size = 0;
717
 
    } else {
718
 
        frame->type = PJMEDIA_FRAME_TYPE_AUDIO;
719
 
        frame->size = samples_count * BYTES_PER_SAMPLE;
720
 
        frame->timestamp.u64 = 0;
721
 
    }
722
 
 
723
 
    return PJ_SUCCESS;
724
 
}
725
 
 
726
 
 
727
 
/* The other version of get_frame callback used when stream port format
728
 
 * is non linear PCM.
729
 
 */
730
 
static pj_status_t get_frame_ext( pjmedia_port *port, pjmedia_frame *frame)
731
 
{
732
 
    pjmedia_stream *stream = (pjmedia_stream*) port->port_data.pdata;
733
 
    pjmedia_channel *channel = stream->dec;
734
 
    pjmedia_frame_ext *f = (pjmedia_frame_ext*)frame;
735
 
    unsigned samples_per_frame, samples_required;
736
 
    pj_status_t status;
737
 
 
738
 
    /* Return no frame if channel is paused */
739
 
    if (channel->paused) {
740
 
        frame->type = PJMEDIA_FRAME_TYPE_NONE;
741
 
        return PJ_SUCCESS;
742
 
    }
743
 
 
744
 
    /* Repeat get frame from the jitter buffer and decode the frame
745
 
     * until we have enough frames according to codec's ptime.
746
 
     */
747
 
 
748
 
    samples_required = PJMEDIA_PIA_SPF(&stream->port.info);
749
 
    samples_per_frame = stream->codec_param.info.frm_ptime *
750
 
                        stream->codec_param.info.clock_rate *
751
 
                        stream->codec_param.info.channel_cnt /
752
 
                        1000;
753
 
 
754
 
    pj_bzero(f, sizeof(pjmedia_frame_ext));
755
 
    f->base.type = PJMEDIA_FRAME_TYPE_EXTENDED;
756
 
 
757
 
    while (f->samples_cnt < samples_required) {
758
 
        char frame_type;
759
 
        pj_size_t frame_size;
760
 
        pj_uint32_t bit_info;
761
 
 
762
 
        /* Lock jitter buffer mutex first */
763
 
        pj_mutex_lock( stream->jb_mutex );
764
 
 
765
 
        /* Get frame from jitter buffer. */
766
 
        pjmedia_jbuf_get_frame2(stream->jb, channel->out_pkt, &frame_size,
767
 
                                &frame_type, &bit_info);
768
 
 
769
 
#if TRACE_JB
770
 
        trace_jb_get(stream, frame_type, frame_size);
771
 
#endif
772
 
 
773
 
        /* Unlock jitter buffer mutex. */
774
 
        pj_mutex_unlock( stream->jb_mutex );
775
 
 
776
 
        if (frame_type == PJMEDIA_JB_NORMAL_FRAME) {
777
 
            /* Got "NORMAL" frame from jitter buffer */
778
 
            pjmedia_frame frame_in;
779
 
 
780
 
            /* Decode */
781
 
            frame_in.buf = channel->out_pkt;
782
 
            frame_in.size = frame_size;
783
 
            frame_in.bit_info = bit_info;
784
 
            frame_in.type = PJMEDIA_FRAME_TYPE_AUDIO;
785
 
 
786
 
            status = pjmedia_codec_decode( stream->codec, &frame_in,
787
 
                                           0, frame);
788
 
            if (status != PJ_SUCCESS) {
789
 
                LOGERR_((port->info.name.ptr, "codec decode() error",
790
 
                         status));
791
 
                pjmedia_frame_ext_append_subframe(f, NULL, 0,
792
 
                                            (pj_uint16_t)samples_per_frame);
793
 
            }
794
 
 
795
 
            if (stream->jb_last_frm != frame_type) {
796
 
                /* Report changing frame type event */
797
 
                PJ_LOG(5,(stream->port.info.name.ptr,
798
 
                          "Jitter buffer starts returning normal frames "
799
 
                          "(after %d empty/lost)",
800
 
                          stream->jb_last_frm_cnt, stream->jb_last_frm));
801
 
 
802
 
                stream->jb_last_frm = frame_type;
803
 
                stream->jb_last_frm_cnt = 1;
804
 
            } else {
805
 
                stream->jb_last_frm_cnt++;
806
 
            }
807
 
 
808
 
        } else {
809
 
 
810
 
            /* Try to generate frame by invoking PLC (when any) */
811
 
            status = PJ_SUCCESS;
812
 
            if (stream->codec->op->recover) {
813
 
                status = pjmedia_codec_recover(stream->codec, 0, frame);
814
 
            }
815
 
 
816
 
            /* No PLC or PLC failed */
817
 
            if (!stream->codec->op->recover || status != PJ_SUCCESS) {
818
 
                pjmedia_frame_ext_append_subframe(f, NULL, 0,
819
 
                                            (pj_uint16_t)samples_per_frame);
820
 
            }
821
 
 
822
 
            if (frame_type == PJMEDIA_JB_MISSING_FRAME) {
823
 
                if (frame_type != stream->jb_last_frm) {
824
 
                    /* Report changing frame type event */
825
 
                    PJ_LOG(5,(stream->port.info.name.ptr, "Frame lost!"));
826
 
 
827
 
                    stream->jb_last_frm = frame_type;
828
 
                    stream->jb_last_frm_cnt = 1;
829
 
                } else {
830
 
                    stream->jb_last_frm_cnt++;
831
 
                }
832
 
            } else if (frame_type == PJMEDIA_JB_ZERO_EMPTY_FRAME) {
833
 
                if (frame_type != stream->jb_last_frm) {
834
 
                    pjmedia_jb_state jb_state;
835
 
 
836
 
                    /* Report changing frame type event */
837
 
                    pjmedia_jbuf_get_state(stream->jb, &jb_state);
838
 
                    PJ_LOG(5,(stream->port.info.name.ptr,
839
 
                              "Jitter buffer empty (prefetch=%d)",
840
 
                              jb_state.prefetch));
841
 
 
842
 
                    stream->jb_last_frm = frame_type;
843
 
                    stream->jb_last_frm_cnt = 1;
844
 
                } else {
845
 
                    stream->jb_last_frm_cnt++;
846
 
                }
847
 
            } else {
848
 
 
849
 
                /* It can only be PJMEDIA_JB_ZERO_PREFETCH frame */
850
 
                pj_assert(frame_type == PJMEDIA_JB_ZERO_PREFETCH_FRAME);
851
 
 
852
 
                if (stream->jb_last_frm != frame_type) {
853
 
                    pjmedia_jb_state jb_state;
854
 
 
855
 
                    /* Report changing frame type event */
856
 
                    pjmedia_jbuf_get_state(stream->jb, &jb_state);
857
 
                    PJ_LOG(5,(stream->port.info.name.ptr,
858
 
                              "Jitter buffer is bufferring (prefetch=%d)",
859
 
                              jb_state.prefetch));
860
 
 
861
 
                    stream->jb_last_frm = frame_type;
862
 
                    stream->jb_last_frm_cnt = 1;
863
 
                } else {
864
 
                    stream->jb_last_frm_cnt++;
865
 
                }
866
 
            }
867
 
        }
868
 
    }
869
 
 
870
 
    return PJ_SUCCESS;
871
 
}
872
 
 
873
 
 
874
 
/*
875
 
 * Transmit DTMF
876
 
 */
877
 
static void create_dtmf_payload(pjmedia_stream *stream,
878
 
                                struct pjmedia_frame *frame_out,
879
 
                                int *first, int *last)
880
 
{
881
 
    pjmedia_rtp_dtmf_event *event;
882
 
    struct dtmf *digit = &stream->tx_dtmf_buf[0];
883
 
    pj_uint32_t cur_ts;
884
 
 
885
 
    pj_assert(sizeof(pjmedia_rtp_dtmf_event) == 4);
886
 
 
887
 
    *first = *last = 0;
888
 
 
889
 
    event = (pjmedia_rtp_dtmf_event*) frame_out->buf;
890
 
    cur_ts = pj_ntohl(stream->enc->rtp.out_hdr.ts);
891
 
 
892
 
    if (digit->duration == 0) {
893
 
        PJ_LOG(5,(stream->port.info.name.ptr, "Sending DTMF digit id %c",
894
 
                  digitmap[digit->event]));
895
 
        *first = 1;
896
 
    }
897
 
 
898
 
    digit->duration += PJMEDIA_PIA_SPF(&stream->port.info);
899
 
 
900
 
    event->event = (pj_uint8_t)digit->event;
901
 
    event->e_vol = 10;
902
 
    event->duration = pj_htons((pj_uint16_t)digit->duration);
903
 
 
904
 
 
905
 
    if (digit->duration >= PJMEDIA_DTMF_DURATION) {
906
 
 
907
 
        event->e_vol |= 0x80;
908
 
        *last = 1;
909
 
 
910
 
        /* Prepare next digit. */
911
 
        pj_mutex_lock(stream->jb_mutex);
912
 
 
913
 
        pj_array_erase(stream->tx_dtmf_buf, sizeof(stream->tx_dtmf_buf[0]),
914
 
                       stream->tx_dtmf_count, 0);
915
 
        --stream->tx_dtmf_count;
916
 
 
917
 
        pj_mutex_unlock(stream->jb_mutex);
918
 
    }
919
 
 
920
 
    frame_out->size = 4;
921
 
}
922
 
 
923
 
 
924
 
static pj_status_t send_rtcp(pjmedia_stream *stream,
925
 
                             pj_bool_t with_sdes,
926
 
                             pj_bool_t with_bye,
927
 
                             pj_bool_t with_xr)
928
 
{
929
 
    void *sr_rr_pkt;
930
 
    pj_uint8_t *pkt;
931
 
    int len, max_len;
932
 
    pj_status_t status;
933
 
 
934
 
    /* Build RTCP RR/SR packet */
935
 
    pjmedia_rtcp_build_rtcp(&stream->rtcp, &sr_rr_pkt, &len);
936
 
 
937
 
#if !defined(PJMEDIA_HAS_RTCP_XR) || (PJMEDIA_HAS_RTCP_XR == 0)
938
 
    with_xr = PJ_FALSE;
939
 
#endif
940
 
 
941
 
    if (with_sdes || with_bye || with_xr) {
942
 
        pkt = (pj_uint8_t*) stream->out_rtcp_pkt;
943
 
        pj_memcpy(pkt, sr_rr_pkt, len);
944
 
        max_len = stream->out_rtcp_pkt_size;
945
 
    } else {
946
 
        pkt = (pj_uint8_t*)sr_rr_pkt;
947
 
        max_len = len;
948
 
    }
949
 
 
950
 
    /* Build RTCP SDES packet */
951
 
    if (with_sdes) {
952
 
        pjmedia_rtcp_sdes sdes;
953
 
        pj_size_t sdes_len;
954
 
 
955
 
        pj_bzero(&sdes, sizeof(sdes));
956
 
        sdes.cname = stream->cname;
957
 
        sdes_len = max_len - len;
958
 
        status = pjmedia_rtcp_build_rtcp_sdes(&stream->rtcp, pkt+len,
959
 
                                              &sdes_len, &sdes);
960
 
        if (status != PJ_SUCCESS) {
961
 
            PJ_PERROR(4,(stream->port.info.name.ptr, status,
962
 
                                     "Error generating RTCP SDES"));
963
 
        } else {
964
 
            len += (int)sdes_len;
965
 
        }
966
 
    }
967
 
 
968
 
    /* Build RTCP XR packet */
969
 
#if defined(PJMEDIA_HAS_RTCP_XR) && (PJMEDIA_HAS_RTCP_XR != 0)
970
 
    if (with_xr) {
971
 
        int i;
972
 
        pjmedia_jb_state jb_state;
973
 
        void *xr_pkt;
974
 
        int xr_len;
975
 
 
976
 
        /* Update RTCP XR with current JB states */
977
 
        pjmedia_jbuf_get_state(stream->jb, &jb_state);
978
 
 
979
 
        i = jb_state.avg_delay;
980
 
        status = pjmedia_rtcp_xr_update_info(&stream->rtcp.xr_session,
981
 
                                             PJMEDIA_RTCP_XR_INFO_JB_NOM, i);
982
 
        pj_assert(status == PJ_SUCCESS);
983
 
 
984
 
        i = jb_state.max_delay;
985
 
        status = pjmedia_rtcp_xr_update_info(&stream->rtcp.xr_session,
986
 
                                             PJMEDIA_RTCP_XR_INFO_JB_MAX, i);
987
 
        pj_assert(status == PJ_SUCCESS);
988
 
 
989
 
        pjmedia_rtcp_build_rtcp_xr(&stream->rtcp.xr_session, 0,
990
 
                                   &xr_pkt, &xr_len);
991
 
 
992
 
        if (xr_len + len <= max_len) {
993
 
            pj_memcpy(pkt+len, xr_pkt, xr_len);
994
 
            len += xr_len;
995
 
 
996
 
            /* Send the RTCP XR to third-party destination if specified */
997
 
            if (stream->rtcp_xr_dest_len) {
998
 
                pjmedia_transport_send_rtcp2(stream->transport,
999
 
                                             &stream->rtcp_xr_dest,
1000
 
                                             stream->rtcp_xr_dest_len,
1001
 
                                             xr_pkt, xr_len);
1002
 
            }
1003
 
 
1004
 
        } else {
1005
 
            PJ_PERROR(4,(stream->port.info.name.ptr, PJ_ETOOBIG,
1006
 
                         "Error generating RTCP-XR"));
1007
 
        }
1008
 
    }
1009
 
#endif
1010
 
 
1011
 
    /* Build RTCP BYE packet */
1012
 
    if (with_bye) {
1013
 
        pj_size_t bye_len;
1014
 
 
1015
 
        bye_len = max_len - len;
1016
 
        status = pjmedia_rtcp_build_rtcp_bye(&stream->rtcp, pkt+len,
1017
 
                                             &bye_len, NULL);
1018
 
        if (status != PJ_SUCCESS) {
1019
 
            PJ_PERROR(4,(stream->port.info.name.ptr, status,
1020
 
                                     "Error generating RTCP BYE"));
1021
 
        } else {
1022
 
            len += (int)bye_len;
1023
 
        }
1024
 
    }
1025
 
 
1026
 
    /* Send! */
1027
 
    status = pjmedia_transport_send_rtcp(stream->transport, pkt, len);
1028
 
 
1029
 
    return status;
1030
 
}
1031
 
 
1032
 
/**
1033
 
 * check_tx_rtcp()
1034
 
 *
1035
 
 * This function is can be called by either put_frame() or get_frame(),
1036
 
 * to transmit periodic RTCP SR/RR report.
1037
 
 */
1038
 
static void check_tx_rtcp(pjmedia_stream *stream, pj_uint32_t timestamp)
1039
 
{
1040
 
    /* Note that timestamp may represent local or remote timestamp,
1041
 
     * depending on whether this function is called from put_frame()
1042
 
     * or get_frame().
1043
 
     */
1044
 
 
1045
 
    if (stream->rtcp_last_tx == 0) {
1046
 
 
1047
 
        stream->rtcp_last_tx = timestamp;
1048
 
 
1049
 
    } else if (timestamp - stream->rtcp_last_tx >= stream->rtcp_interval) {
1050
 
        pj_bool_t with_xr = PJ_FALSE;
1051
 
        pj_status_t status;
1052
 
 
1053
 
#if defined(PJMEDIA_HAS_RTCP_XR) && (PJMEDIA_HAS_RTCP_XR != 0)
1054
 
        if (stream->rtcp.xr_enabled) {
1055
 
            if (stream->rtcp_xr_last_tx == 0) {
1056
 
                stream->rtcp_xr_last_tx = timestamp;
1057
 
            } else if (timestamp - stream->rtcp_xr_last_tx >=
1058
 
                       stream->rtcp_xr_interval)
1059
 
            {
1060
 
                with_xr = PJ_TRUE;
1061
 
 
1062
 
                /* Update last tx RTCP XR */
1063
 
                stream->rtcp_xr_last_tx = timestamp;
1064
 
            }
1065
 
        }
1066
 
#endif
1067
 
 
1068
 
        status = send_rtcp(stream, !stream->rtcp_sdes_bye_disabled, PJ_FALSE,
1069
 
                           with_xr);
1070
 
        if (status != PJ_SUCCESS) {
1071
 
            PJ_PERROR(4,(stream->port.info.name.ptr, status,
1072
 
                         "Error sending RTCP"));
1073
 
        }
1074
 
 
1075
 
        stream->rtcp_last_tx = timestamp;
1076
 
    }
1077
 
}
1078
 
 
1079
 
 
1080
 
/**
1081
 
 * Rebuffer the frame when encoder and decoder has different ptime
1082
 
 * (such as when different iLBC modes are used by local and remote)
1083
 
 */
1084
 
static void rebuffer(pjmedia_stream *stream,
1085
 
                     pjmedia_frame *frame)
1086
 
{
1087
 
    /* How many samples are needed */
1088
 
    unsigned count;
1089
 
 
1090
 
    /* Normalize frame */
1091
 
    if (frame->type != PJMEDIA_FRAME_TYPE_AUDIO)
1092
 
        frame->size = 0;
1093
 
 
1094
 
    /* Remove used frame from the buffer. */
1095
 
    if (stream->enc_buf_pos) {
1096
 
        if (stream->enc_buf_count) {
1097
 
            pj_memmove(stream->enc_buf,
1098
 
                       stream->enc_buf + stream->enc_buf_pos,
1099
 
                       (stream->enc_buf_count << 1));
1100
 
        }
1101
 
        stream->enc_buf_pos = 0;
1102
 
    }
1103
 
 
1104
 
    /* Make sure we have space to store the new frame */
1105
 
    pj_assert(stream->enc_buf_count + (frame->size >> 1) <
1106
 
                stream->enc_buf_size);
1107
 
 
1108
 
    /* Append new frame to the buffer */
1109
 
    if (frame->size) {
1110
 
        /* Handle case when there is no port transmitting to this port */
1111
 
        if (frame->buf) {
1112
 
            pj_memcpy(stream->enc_buf + stream->enc_buf_count,
1113
 
                      frame->buf, frame->size);
1114
 
        } else {
1115
 
            pj_bzero(stream->enc_buf + stream->enc_buf_count, frame->size);
1116
 
        }
1117
 
        stream->enc_buf_count += (frame->size >> 1);
1118
 
    }
1119
 
 
1120
 
    /* How many samples are needed */
1121
 
    count = stream->codec_param.info.enc_ptime *
1122
 
            PJMEDIA_PIA_SRATE(&stream->port.info) / 1000;
1123
 
 
1124
 
    /* See if we have enough samples */
1125
 
    if (stream->enc_buf_count >= count) {
1126
 
 
1127
 
        frame->type = PJMEDIA_FRAME_TYPE_AUDIO;
1128
 
        frame->buf = stream->enc_buf;
1129
 
        frame->size = (count << 1);
1130
 
 
1131
 
        stream->enc_buf_pos = count;
1132
 
        stream->enc_buf_count -= count;
1133
 
 
1134
 
    } else {
1135
 
        /* We don't have enough samples */
1136
 
        frame->type = PJMEDIA_FRAME_TYPE_NONE;
1137
 
    }
1138
 
}
1139
 
 
1140
 
 
1141
 
/**
1142
 
 * put_frame_imp()
1143
 
 */
1144
 
static pj_status_t put_frame_imp( pjmedia_port *port,
1145
 
                                  pjmedia_frame *frame )
1146
 
{
1147
 
    pjmedia_stream *stream = (pjmedia_stream*) port->port_data.pdata;
1148
 
    pjmedia_channel *channel = stream->enc;
1149
 
    pj_status_t status = 0;
1150
 
    pjmedia_frame frame_out;
1151
 
    unsigned ts_len, rtp_ts_len, samples_per_frame;
1152
 
    void *rtphdr;
1153
 
    int rtphdrlen;
1154
 
    int inc_timestamp = 0;
1155
 
 
1156
 
 
1157
 
#if defined(PJMEDIA_STREAM_ENABLE_KA) && PJMEDIA_STREAM_ENABLE_KA != 0
1158
 
    /* If the interval since last sending packet is greater than
1159
 
     * PJMEDIA_STREAM_KA_INTERVAL, send keep-alive packet.
1160
 
     */
1161
 
    if (stream->use_ka)
1162
 
    {
1163
 
        pj_uint32_t dtx_duration;
1164
 
 
1165
 
        dtx_duration = pj_timestamp_diff32(&stream->last_frm_ts_sent,
1166
 
                                           &frame->timestamp);
1167
 
        if (dtx_duration >
1168
 
            PJMEDIA_STREAM_KA_INTERVAL * PJMEDIA_PIA_SRATE(&stream->port.info))
1169
 
        {
1170
 
            send_keep_alive_packet(stream);
1171
 
            stream->last_frm_ts_sent = frame->timestamp;
1172
 
        }
1173
 
    }
1174
 
#endif
1175
 
 
1176
 
    /* Don't do anything if stream is paused */
1177
 
    if (channel->paused) {
1178
 
        stream->enc_buf_pos = stream->enc_buf_count = 0;
1179
 
        return PJ_SUCCESS;
1180
 
    }
1181
 
 
1182
 
    /* Number of samples in the frame */
1183
 
    if (frame->type == PJMEDIA_FRAME_TYPE_AUDIO)
1184
 
        ts_len = (frame->size >> 1) / stream->codec_param.info.channel_cnt;
1185
 
    else if (frame->type == PJMEDIA_FRAME_TYPE_EXTENDED)
1186
 
        ts_len = PJMEDIA_PIA_SPF(&stream->port.info) /
1187
 
                 PJMEDIA_PIA_CCNT(&stream->port.info);
1188
 
    else
1189
 
        ts_len = 0;
1190
 
 
1191
 
    /* Increment transmit duration */
1192
 
    stream->tx_duration += ts_len;
1193
 
 
1194
 
#if defined(PJMEDIA_HANDLE_G722_MPEG_BUG) && (PJMEDIA_HANDLE_G722_MPEG_BUG!=0)
1195
 
    /* Handle special case for audio codec with RTP timestamp inconsistence
1196
 
     * e.g: G722, MPEG audio.
1197
 
     */
1198
 
    if (stream->has_g722_mpeg_bug)
1199
 
        rtp_ts_len = stream->rtp_tx_ts_len_per_pkt;
1200
 
    else
1201
 
        rtp_ts_len = ts_len;
1202
 
#else
1203
 
    rtp_ts_len = ts_len;
1204
 
#endif
1205
 
 
1206
 
    /* Init frame_out buffer. */
1207
 
    frame_out.buf = ((char*)channel->out_pkt) + sizeof(pjmedia_rtp_hdr);
1208
 
    frame_out.size = 0;
1209
 
 
1210
 
    /* Calculate number of samples per frame */
1211
 
    samples_per_frame = stream->enc_samples_per_pkt;
1212
 
 
1213
 
 
1214
 
    /* If we have DTMF digits in the queue, transmit the digits.
1215
 
     * Otherwise encode the PCM buffer.
1216
 
     */
1217
 
    if (stream->tx_dtmf_count) {
1218
 
        int first=0, last=0;
1219
 
 
1220
 
        create_dtmf_payload(stream, &frame_out, &first, &last);
1221
 
 
1222
 
        /* Encapsulate into RTP packet. Note that:
1223
 
         *  - RTP marker should be set on the beginning of a new event
1224
 
         *  - RTP timestamp is constant for the same packet.
1225
 
         */
1226
 
        status = pjmedia_rtp_encode_rtp( &channel->rtp,
1227
 
                                         stream->tx_event_pt, first,
1228
 
                                         frame_out.size,
1229
 
                                         (first ? rtp_ts_len : 0),
1230
 
                                         (const void**)&rtphdr,
1231
 
                                         &rtphdrlen);
1232
 
 
1233
 
        if (last) {
1234
 
            /* This is the last packet for the event.
1235
 
             * Increment the RTP timestamp of the RTP session, for next
1236
 
             * RTP packets.
1237
 
             */
1238
 
            inc_timestamp = PJMEDIA_DTMF_DURATION - rtp_ts_len;
1239
 
        }
1240
 
 
1241
 
 
1242
 
    /*
1243
 
     * Special treatment for FRAME_TYPE_AUDIO but with frame->buf==NULL.
1244
 
     * This happens when stream input is disconnected from the bridge.
1245
 
     * In this case we periodically transmit RTP frame to keep NAT binding
1246
 
     * open, by giving zero PCM frame to the codec.
1247
 
     *
1248
 
     * This was originally done in http://trac.pjsip.org/repos/ticket/56,
1249
 
     * but then disabled in http://trac.pjsip.org/repos/ticket/439, but
1250
 
     * now it's enabled again.
1251
 
     */
1252
 
    } else if (frame->type == PJMEDIA_FRAME_TYPE_AUDIO &&
1253
 
               frame->buf == NULL &&
1254
 
               stream->port.info.fmt.id == PJMEDIA_FORMAT_L16 &&
1255
 
               (stream->dir & PJMEDIA_DIR_ENCODING) &&
1256
 
               stream->codec_param.info.frm_ptime *
1257
 
               stream->codec_param.info.channel_cnt *
1258
 
               stream->codec_param.info.clock_rate/1000 <
1259
 
                  PJ_ARRAY_SIZE(zero_frame))
1260
 
    {
1261
 
        pjmedia_frame silence_frame;
1262
 
 
1263
 
        pj_bzero(&silence_frame, sizeof(silence_frame));
1264
 
        silence_frame.buf = zero_frame;
1265
 
        silence_frame.size = stream->codec_param.info.frm_ptime * 2 *
1266
 
                             stream->codec_param.info.channel_cnt *
1267
 
                             stream->codec_param.info.clock_rate / 1000;
1268
 
        silence_frame.type = PJMEDIA_FRAME_TYPE_AUDIO;
1269
 
        silence_frame.timestamp.u32.lo = pj_ntohl(stream->enc->rtp.out_hdr.ts);
1270
 
 
1271
 
        /* Encode! */
1272
 
        status = pjmedia_codec_encode( stream->codec, &silence_frame,
1273
 
                                       channel->out_pkt_size -
1274
 
                                       sizeof(pjmedia_rtp_hdr),
1275
 
                                       &frame_out);
1276
 
        if (status != PJ_SUCCESS) {
1277
 
            LOGERR_((stream->port.info.name.ptr,
1278
 
                    "Codec encode() error", status));
1279
 
            return status;
1280
 
        }
1281
 
 
1282
 
        /* Encapsulate. */
1283
 
        status = pjmedia_rtp_encode_rtp( &channel->rtp,
1284
 
                                         channel->pt, 0,
1285
 
                                         frame_out.size, rtp_ts_len,
1286
 
                                         (const void**)&rtphdr,
1287
 
                                         &rtphdrlen);
1288
 
 
1289
 
 
1290
 
    /* Encode audio frame */
1291
 
    } else if ((frame->type == PJMEDIA_FRAME_TYPE_AUDIO &&
1292
 
                frame->buf != NULL) ||
1293
 
               (frame->type == PJMEDIA_FRAME_TYPE_EXTENDED))
1294
 
    {
1295
 
        /* Encode! */
1296
 
        status = pjmedia_codec_encode( stream->codec, frame,
1297
 
                                       channel->out_pkt_size -
1298
 
                                       sizeof(pjmedia_rtp_hdr),
1299
 
                                       &frame_out);
1300
 
        if (status != PJ_SUCCESS) {
1301
 
            LOGERR_((stream->port.info.name.ptr,
1302
 
                    "Codec encode() error", status));
1303
 
            return status;
1304
 
        }
1305
 
 
1306
 
        /* Encapsulate. */
1307
 
        status = pjmedia_rtp_encode_rtp( &channel->rtp,
1308
 
                                         channel->pt, 0,
1309
 
                                         frame_out.size, rtp_ts_len,
1310
 
                                         (const void**)&rtphdr,
1311
 
                                         &rtphdrlen);
1312
 
 
1313
 
    } else {
1314
 
 
1315
 
        /* Just update RTP session's timestamp. */
1316
 
        status = pjmedia_rtp_encode_rtp( &channel->rtp,
1317
 
                                         0, 0,
1318
 
                                         0, rtp_ts_len,
1319
 
                                         (const void**)&rtphdr,
1320
 
                                         &rtphdrlen);
1321
 
 
1322
 
    }
1323
 
 
1324
 
    if (status != PJ_SUCCESS) {
1325
 
        LOGERR_((stream->port.info.name.ptr,
1326
 
                "RTP encode_rtp() error", status));
1327
 
        return status;
1328
 
    }
1329
 
 
1330
 
    /* Check if now is the time to transmit RTCP SR/RR report.
1331
 
     * We only do this when stream direction is not "decoding only", because
1332
 
     * when it is, check_tx_rtcp() will be handled by get_frame().
1333
 
     */
1334
 
    if (stream->dir != PJMEDIA_DIR_DECODING) {
1335
 
        check_tx_rtcp(stream, pj_ntohl(channel->rtp.out_hdr.ts));
1336
 
    }
1337
 
 
1338
 
    /* Do nothing if we have nothing to transmit */
1339
 
    if (frame_out.size == 0) {
1340
 
        if (stream->is_streaming) {
1341
 
            PJ_LOG(5,(stream->port.info.name.ptr,"Starting silence"));
1342
 
            stream->is_streaming = PJ_FALSE;
1343
 
        }
1344
 
 
1345
 
        return PJ_SUCCESS;
1346
 
    }
1347
 
 
1348
 
 
1349
 
    /* Copy RTP header to the beginning of packet */
1350
 
    pj_memcpy(channel->out_pkt, rtphdr, sizeof(pjmedia_rtp_hdr));
1351
 
 
1352
 
    /* Special case for DTMF: timestamp remains constant for
1353
 
     * the same event, and is only updated after a complete event
1354
 
     * has been transmitted.
1355
 
     */
1356
 
    if (inc_timestamp) {
1357
 
        pjmedia_rtp_encode_rtp( &channel->rtp, stream->tx_event_pt, 0,
1358
 
                                0, inc_timestamp, NULL, NULL);
1359
 
    }
1360
 
 
1361
 
    /* Set RTP marker bit if currently not streaming */
1362
 
    if (stream->is_streaming == PJ_FALSE) {
1363
 
        pjmedia_rtp_hdr *rtp = (pjmedia_rtp_hdr*) channel->out_pkt;
1364
 
 
1365
 
        rtp->m = 1;
1366
 
        PJ_LOG(5,(stream->port.info.name.ptr,"Start talksprut.."));
1367
 
    }
1368
 
 
1369
 
    stream->is_streaming = PJ_TRUE;
1370
 
 
1371
 
    /* Send the RTP packet to the transport. */
1372
 
    status = pjmedia_transport_send_rtp(stream->transport, channel->out_pkt,
1373
 
                                        frame_out.size +
1374
 
                                            sizeof(pjmedia_rtp_hdr));
1375
 
    if (status != PJ_SUCCESS) {
1376
 
        PJ_PERROR(4,(stream->port.info.name.ptr, status,
1377
 
                     "Error sending RTP"));
1378
 
    }
1379
 
 
1380
 
    /* Update stat */
1381
 
    pjmedia_rtcp_tx_rtp(&stream->rtcp, frame_out.size);
1382
 
    stream->rtcp.stat.rtp_tx_last_ts = pj_ntohl(stream->enc->rtp.out_hdr.ts);
1383
 
    stream->rtcp.stat.rtp_tx_last_seq = pj_ntohs(stream->enc->rtp.out_hdr.seq);
1384
 
 
1385
 
#if defined(PJMEDIA_STREAM_ENABLE_KA) && PJMEDIA_STREAM_ENABLE_KA!=0
1386
 
    /* Update timestamp of last sending packet. */
1387
 
    stream->last_frm_ts_sent = frame->timestamp;
1388
 
#endif
1389
 
 
1390
 
    return PJ_SUCCESS;
1391
 
}
1392
 
 
1393
 
 
1394
 
/**
1395
 
 * put_frame()
1396
 
 *
1397
 
 * This callback is called by upstream component when it has PCM frame
1398
 
 * to transmit. This function encodes the PCM frame, pack it into
1399
 
 * RTP packet, and transmit to peer.
1400
 
 */
1401
 
static pj_status_t put_frame( pjmedia_port *port,
1402
 
                              pjmedia_frame *frame )
1403
 
{
1404
 
    pjmedia_stream *stream = (pjmedia_stream*) port->port_data.pdata;
1405
 
    pjmedia_frame tmp_zero_frame;
1406
 
    unsigned samples_per_frame;
1407
 
 
1408
 
    samples_per_frame = stream->enc_samples_per_pkt;
1409
 
 
1410
 
    /* http://www.pjsip.org/trac/ticket/56:
1411
 
     *  when input is PJMEDIA_FRAME_TYPE_NONE, feed zero PCM frame
1412
 
     *  instead so that encoder can decide whether or not to transmit
1413
 
     *  silence frame.
1414
 
     */
1415
 
    if (frame->type == PJMEDIA_FRAME_TYPE_NONE) {
1416
 
        pj_memcpy(&tmp_zero_frame, frame, sizeof(pjmedia_frame));
1417
 
        frame = &tmp_zero_frame;
1418
 
 
1419
 
        tmp_zero_frame.buf = NULL;
1420
 
        tmp_zero_frame.size = samples_per_frame * 2;
1421
 
        tmp_zero_frame.type = PJMEDIA_FRAME_TYPE_AUDIO;
1422
 
    }
1423
 
 
1424
 
#if 0
1425
 
    // This is no longer needed because each TYPE_NONE frame will
1426
 
    // be converted into zero frame above
1427
 
 
1428
 
    /* If VAD is temporarily disabled during creation, feed zero PCM frame
1429
 
     * to the codec.
1430
 
     */
1431
 
    if (stream->vad_enabled != stream->codec_param.setting.vad &&
1432
 
        stream->vad_enabled != 0 &&
1433
 
        frame->type == PJMEDIA_FRAME_TYPE_NONE &&
1434
 
        samples_per_frame <= ZERO_PCM_MAX_SIZE)
1435
 
    {
1436
 
        pj_memcpy(&tmp_in_frame, frame, sizeof(pjmedia_frame));
1437
 
        frame = &tmp_in_frame;
1438
 
 
1439
 
        tmp_in_frame.buf = NULL;
1440
 
        tmp_in_frame.size = samples_per_frame * 2;
1441
 
        tmp_in_frame.type = PJMEDIA_FRAME_TYPE_AUDIO;
1442
 
    }
1443
 
#endif
1444
 
 
1445
 
    /* If VAD is temporarily disabled during creation, enable it
1446
 
     * after transmitting for VAD_SUSPEND_SEC seconds.
1447
 
     */
1448
 
    if (stream->vad_enabled != stream->codec_param.setting.vad &&
1449
 
        (stream->tx_duration - stream->ts_vad_disabled) >
1450
 
           PJMEDIA_PIA_SRATE(&stream->port.info) *
1451
 
          PJMEDIA_STREAM_VAD_SUSPEND_MSEC / 1000)
1452
 
    {
1453
 
        stream->codec_param.setting.vad = stream->vad_enabled;
1454
 
        pjmedia_codec_modify(stream->codec, &stream->codec_param);
1455
 
        PJ_LOG(4,(stream->port.info.name.ptr,"VAD re-enabled"));
1456
 
    }
1457
 
 
1458
 
 
1459
 
    /* If encoder has different ptime than decoder, then the frame must
1460
 
     * be passed through the encoding buffer via rebuffer() function.
1461
 
     */
1462
 
    if (stream->enc_buf != NULL) {
1463
 
        pjmedia_frame tmp_rebuffer_frame;
1464
 
        pj_status_t status = PJ_SUCCESS;
1465
 
 
1466
 
        /* Copy original frame to temporary frame since we need
1467
 
         * to modify it.
1468
 
         */
1469
 
        pj_memcpy(&tmp_rebuffer_frame, frame, sizeof(pjmedia_frame));
1470
 
 
1471
 
        /* Loop while we have full frame in enc_buffer */
1472
 
        for (;;) {
1473
 
            pj_status_t st;
1474
 
 
1475
 
            /* Run rebuffer() */
1476
 
            rebuffer(stream, &tmp_rebuffer_frame);
1477
 
 
1478
 
            /* Process this frame */
1479
 
            st = put_frame_imp(port, &tmp_rebuffer_frame);
1480
 
            if (st != PJ_SUCCESS)
1481
 
                status = st;
1482
 
 
1483
 
            /* If we still have full frame in the buffer, re-run
1484
 
             * rebuffer() with NULL frame.
1485
 
             */
1486
 
            if (stream->enc_buf_count >= stream->enc_samples_per_pkt) {
1487
 
 
1488
 
                tmp_rebuffer_frame.type = PJMEDIA_FRAME_TYPE_NONE;
1489
 
 
1490
 
            } else {
1491
 
 
1492
 
                /* Otherwise break */
1493
 
                break;
1494
 
            }
1495
 
        }
1496
 
 
1497
 
        return status;
1498
 
 
1499
 
    } else {
1500
 
        return put_frame_imp(port, frame);
1501
 
    }
1502
 
}
1503
 
 
1504
 
 
1505
 
#if 0
1506
 
static void dump_bin(const char *buf, unsigned len)
1507
 
{
1508
 
    unsigned i;
1509
 
 
1510
 
    PJ_LOG(3,(THIS_FILE, "begin dump"));
1511
 
    for (i=0; i<len; ++i) {
1512
 
        int j;
1513
 
        char bits[9];
1514
 
        unsigned val = buf[i] & 0xFF;
1515
 
 
1516
 
        bits[8] = '\0';
1517
 
        for (j=0; j<8; ++j) {
1518
 
            if (val & (1 << (7-j)))
1519
 
                bits[j] = '1';
1520
 
            else
1521
 
                bits[j] = '0';
1522
 
        }
1523
 
 
1524
 
        PJ_LOG(3,(THIS_FILE, "%2d %s [%d]", i, bits, val));
1525
 
    }
1526
 
    PJ_LOG(3,(THIS_FILE, "end dump"));
1527
 
}
1528
 
#endif
1529
 
 
1530
 
/*
1531
 
 * Handle incoming DTMF digits.
1532
 
 */
1533
 
static void handle_incoming_dtmf( pjmedia_stream *stream,
1534
 
                                  const void *payload, unsigned payloadlen)
1535
 
{
1536
 
    pjmedia_rtp_dtmf_event *event = (pjmedia_rtp_dtmf_event*) payload;
1537
 
 
1538
 
    /* Check compiler packing. */
1539
 
    pj_assert(sizeof(pjmedia_rtp_dtmf_event)==4);
1540
 
 
1541
 
    /* Must have sufficient length before we proceed. */
1542
 
    if (payloadlen < sizeof(pjmedia_rtp_dtmf_event))
1543
 
        return;
1544
 
 
1545
 
    //dump_bin(payload, payloadlen);
1546
 
 
1547
 
    /* Check if this is the same/current digit of the last packet. */
1548
 
    if (stream->last_dtmf != -1 &&
1549
 
        event->event == stream->last_dtmf &&
1550
 
        pj_ntohs(event->duration) >= stream->last_dtmf_dur)
1551
 
    {
1552
 
        /* Yes, this is the same event. */
1553
 
        stream->last_dtmf_dur = pj_ntohs(event->duration);
1554
 
        return;
1555
 
    }
1556
 
 
1557
 
    /* Ignore unknown event. */
1558
 
    if (event->event > 15) {
1559
 
        PJ_LOG(5,(stream->port.info.name.ptr,
1560
 
                  "Ignored RTP pkt with bad DTMF event %d",
1561
 
                  event->event));
1562
 
        return;
1563
 
    }
1564
 
 
1565
 
    /* New event! */
1566
 
    PJ_LOG(5,(stream->port.info.name.ptr, "Received DTMF digit %c, vol=%d",
1567
 
              digitmap[event->event],
1568
 
              (event->e_vol & 0x3F)));
1569
 
 
1570
 
    stream->last_dtmf = event->event;
1571
 
    stream->last_dtmf_dur = pj_ntohs(event->duration);
1572
 
 
1573
 
    /* If DTMF callback is installed, call the callback, otherwise keep
1574
 
     * the DTMF digits in the buffer.
1575
 
     */
1576
 
    if (stream->dtmf_cb) {
1577
 
 
1578
 
        stream->dtmf_cb(stream, stream->dtmf_cb_user_data,
1579
 
                        digitmap[event->event]);
1580
 
 
1581
 
    } else {
1582
 
        /* By convention, we use jitter buffer's mutex to access shared
1583
 
         * DTMF variables.
1584
 
         */
1585
 
        pj_mutex_lock(stream->jb_mutex);
1586
 
        if (stream->rx_dtmf_count >= PJ_ARRAY_SIZE(stream->rx_dtmf_buf)) {
1587
 
            /* DTMF digits overflow.  Discard the oldest digit. */
1588
 
            pj_array_erase(stream->rx_dtmf_buf,
1589
 
                           sizeof(stream->rx_dtmf_buf[0]),
1590
 
                           stream->rx_dtmf_count, 0);
1591
 
            --stream->rx_dtmf_count;
1592
 
        }
1593
 
        stream->rx_dtmf_buf[stream->rx_dtmf_count++] = digitmap[event->event];
1594
 
        pj_mutex_unlock(stream->jb_mutex);
1595
 
    }
1596
 
}
1597
 
 
1598
 
 
1599
 
/*
1600
 
 * This callback is called by stream transport on receipt of packets
1601
 
 * in the RTP socket.
1602
 
 */
1603
 
static void on_rx_rtp( void *data,
1604
 
                       void *pkt,
1605
 
                       pj_ssize_t bytes_read)
1606
 
 
1607
 
{
1608
 
    pjmedia_stream *stream = (pjmedia_stream*) data;
1609
 
    pjmedia_channel *channel = stream->dec;
1610
 
    const pjmedia_rtp_hdr *hdr;
1611
 
    const void *payload;
1612
 
    unsigned payloadlen;
1613
 
    pjmedia_rtp_status seq_st;
1614
 
    pj_status_t status;
1615
 
    pj_bool_t pkt_discarded = PJ_FALSE;
1616
 
 
1617
 
    /* Check for errors */
1618
 
    if (bytes_read < 0) {
1619
 
        LOGERR_((stream->port.info.name.ptr, "RTP recv() error", -bytes_read));
1620
 
        return;
1621
 
    }
1622
 
 
1623
 
    /* Ignore keep-alive packets */
1624
 
    if (bytes_read < (pj_ssize_t) sizeof(pjmedia_rtp_hdr))
1625
 
        return;
1626
 
 
1627
 
    /* Update RTP and RTCP session. */
1628
 
    status = pjmedia_rtp_decode_rtp(&channel->rtp, pkt, bytes_read,
1629
 
                                    &hdr, &payload, &payloadlen);
1630
 
    if (status != PJ_SUCCESS) {
1631
 
        LOGERR_((stream->port.info.name.ptr, "RTP decode error", status));
1632
 
        stream->rtcp.stat.rx.discard++;
1633
 
        return;
1634
 
    }
1635
 
 
1636
 
    /* Ignore the packet if decoder is paused */
1637
 
    if (channel->paused)
1638
 
        goto on_return;
1639
 
 
1640
 
    /* Update RTP session (also checks if RTP session can accept
1641
 
     * the incoming packet.
1642
 
     */
1643
 
    pjmedia_rtp_session_update2(&channel->rtp, hdr, &seq_st,
1644
 
                                hdr->pt != stream->rx_event_pt);
1645
 
    if (seq_st.status.value) {
1646
 
        TRC_  ((stream->port.info.name.ptr,
1647
 
                "RTP status: badpt=%d, badssrc=%d, dup=%d, "
1648
 
                "outorder=%d, probation=%d, restart=%d",
1649
 
                seq_st.status.flag.badpt,
1650
 
                seq_st.status.flag.badssrc,
1651
 
                seq_st.status.flag.dup,
1652
 
                seq_st.status.flag.outorder,
1653
 
                seq_st.status.flag.probation,
1654
 
                seq_st.status.flag.restart));
1655
 
 
1656
 
        if (seq_st.status.flag.badpt) {
1657
 
            PJ_LOG(4,(stream->port.info.name.ptr,
1658
 
                      "Bad RTP pt %d (expecting %d)",
1659
 
                      hdr->pt, channel->rtp.out_pt));
1660
 
        }
1661
 
 
1662
 
        if (seq_st.status.flag.badssrc) {
1663
 
            PJ_LOG(4,(stream->port.info.name.ptr,
1664
 
                      "Changed RTP peer SSRC %d (previously %d)",
1665
 
                      channel->rtp.peer_ssrc, stream->rtcp.peer_ssrc));
1666
 
            stream->rtcp.peer_ssrc = channel->rtp.peer_ssrc;
1667
 
        }
1668
 
 
1669
 
 
1670
 
    }
1671
 
 
1672
 
    /* Skip bad RTP packet */
1673
 
    if (seq_st.status.flag.bad) {
1674
 
        pkt_discarded = PJ_TRUE;
1675
 
        goto on_return;
1676
 
    }
1677
 
 
1678
 
    /* Ignore if payloadlen is zero */
1679
 
    if (payloadlen == 0) {
1680
 
        pkt_discarded = PJ_TRUE;
1681
 
        goto on_return;
1682
 
    }
1683
 
 
1684
 
    /* Handle incoming DTMF. */
1685
 
    if (hdr->pt == stream->rx_event_pt) {
1686
 
        /* Ignore out-of-order packet as it will be detected as new
1687
 
         * digit. Also ignore duplicate packet as it serves no use.
1688
 
         */
1689
 
        if (seq_st.status.flag.outorder || seq_st.status.flag.dup) {
1690
 
            goto on_return;
1691
 
        }
1692
 
 
1693
 
        handle_incoming_dtmf(stream, payload, payloadlen);
1694
 
        goto on_return;
1695
 
    }
1696
 
 
1697
 
    /* Put "good" packet to jitter buffer, or reset the jitter buffer
1698
 
     * when RTP session is restarted.
1699
 
     */
1700
 
    pj_mutex_lock( stream->jb_mutex );
1701
 
    if (seq_st.status.flag.restart) {
1702
 
        status = pjmedia_jbuf_reset(stream->jb);
1703
 
        PJ_LOG(4,(stream->port.info.name.ptr, "Jitter buffer reset"));
1704
 
    } else {
1705
 
        /*
1706
 
         * Packets may contain more than one frames, while the jitter
1707
 
         * buffer can only take one frame per "put" operation. So we need
1708
 
         * to ask the codec to "parse" the payload into multiple frames.
1709
 
         */
1710
 
        enum { MAX = 16 };
1711
 
        pj_timestamp ts;
1712
 
        unsigned i, count = MAX;
1713
 
        unsigned ts_span;
1714
 
        pjmedia_frame frames[MAX];
1715
 
 
1716
 
        /* Get the timestamp of the first sample */
1717
 
        ts.u64 = pj_ntohl(hdr->ts);
1718
 
 
1719
 
        /* Parse the payload. */
1720
 
        status = pjmedia_codec_parse(stream->codec, (void*)payload,
1721
 
                                     payloadlen, &ts, &count, frames);
1722
 
        if (status != PJ_SUCCESS) {
1723
 
            LOGERR_((stream->port.info.name.ptr,
1724
 
                     "Codec parse() error",
1725
 
                     status));
1726
 
            count = 0;
1727
 
        }
1728
 
 
1729
 
#if defined(PJMEDIA_HANDLE_G722_MPEG_BUG) && (PJMEDIA_HANDLE_G722_MPEG_BUG!=0)
1730
 
        /* This code is used to learn the samples per frame value that is put
1731
 
         * by remote endpoint, for codecs with inconsistent clock rate such
1732
 
         * as G.722 or MPEG audio. We need to learn the samples per frame
1733
 
         * value as it is used as divider when inserting frames into the
1734
 
         * jitter buffer.
1735
 
         */
1736
 
        if (stream->has_g722_mpeg_bug) {
1737
 
            if (stream->rtp_rx_check_cnt) {
1738
 
                /* Make sure the detection performed only on two consecutive
1739
 
                 * packets with valid RTP sequence and no wrapped timestamp.
1740
 
                 */
1741
 
                if (seq_st.diff == 1 && stream->rtp_rx_last_ts &&
1742
 
                    ts.u64 > stream->rtp_rx_last_ts &&
1743
 
                    stream->rtp_rx_last_cnt > 0)
1744
 
                {
1745
 
                    unsigned peer_frm_ts_diff;
1746
 
                    unsigned frm_ts_span;
1747
 
 
1748
 
                    /* Calculate actual frame timestamp span */
1749
 
                    frm_ts_span = PJMEDIA_PIA_SPF(&stream->port.info) /
1750
 
                                  stream->codec_param.setting.frm_per_pkt/
1751
 
                                  PJMEDIA_PIA_CCNT(&stream->port.info);
1752
 
 
1753
 
                    /* Get remote frame timestamp span */
1754
 
                    peer_frm_ts_diff =
1755
 
                        ((pj_uint32_t)ts.u64-stream->rtp_rx_last_ts) /
1756
 
                        stream->rtp_rx_last_cnt;
1757
 
 
1758
 
                    /* Possibilities remote's samples per frame for G.722
1759
 
                     * are only (frm_ts_span) and (frm_ts_span/2), this
1760
 
                     * validation is needed to avoid wrong decision because
1761
 
                     * of silence frames.
1762
 
                     */
1763
 
                    if (stream->codec_param.info.pt == PJMEDIA_RTP_PT_G722 &&
1764
 
                        (peer_frm_ts_diff == frm_ts_span ||
1765
 
                         peer_frm_ts_diff == (frm_ts_span>>1)))
1766
 
                    {
1767
 
                        if (peer_frm_ts_diff < stream->rtp_rx_ts_len_per_frame)
1768
 
                            stream->rtp_rx_ts_len_per_frame = peer_frm_ts_diff;
1769
 
 
1770
 
                        if (--stream->rtp_rx_check_cnt == 0) {
1771
 
                            PJ_LOG(4, (THIS_FILE, "G722 codec used, remote"
1772
 
                                       " samples per frame detected = %d",
1773
 
                                       stream->rtp_rx_ts_len_per_frame));
1774
 
 
1775
 
                            /* Reset jitter buffer once detection done */
1776
 
                            pjmedia_jbuf_reset(stream->jb);
1777
 
                        }
1778
 
                    }
1779
 
                }
1780
 
 
1781
 
                stream->rtp_rx_last_ts = (pj_uint32_t)ts.u64;
1782
 
                stream->rtp_rx_last_cnt = count;
1783
 
            }
1784
 
 
1785
 
            ts_span = stream->rtp_rx_ts_len_per_frame;
1786
 
 
1787
 
            /* Adjust the timestamp of the parsed frames */
1788
 
            for (i=0; i<count; ++i) {
1789
 
                frames[i].timestamp.u64 = ts.u64 + ts_span * i;
1790
 
            }
1791
 
 
1792
 
        } else {
1793
 
            ts_span = stream->codec_param.info.frm_ptime *
1794
 
                      stream->codec_param.info.clock_rate /
1795
 
                      1000;
1796
 
        }
1797
 
#else
1798
 
        ts_span = stream->codec_param.info.frm_ptime *
1799
 
                  stream->codec_param.info.clock_rate /
1800
 
                  1000;
1801
 
#endif
1802
 
 
1803
 
        /* Put each frame to jitter buffer. */
1804
 
        for (i=0; i<count; ++i) {
1805
 
            unsigned ext_seq;
1806
 
            pj_bool_t discarded;
1807
 
 
1808
 
            ext_seq = (unsigned)(frames[i].timestamp.u64 / ts_span);
1809
 
            pjmedia_jbuf_put_frame2(stream->jb, frames[i].buf, frames[i].size,
1810
 
                                    frames[i].bit_info, ext_seq, &discarded);
1811
 
            if (discarded)
1812
 
                pkt_discarded = PJ_TRUE;
1813
 
        }
1814
 
 
1815
 
#if TRACE_JB
1816
 
        trace_jb_put(stream, hdr, payloadlen, count);
1817
 
#endif
1818
 
 
1819
 
    }
1820
 
    pj_mutex_unlock( stream->jb_mutex );
1821
 
 
1822
 
 
1823
 
    /* Check if now is the time to transmit RTCP SR/RR report.
1824
 
     * We only do this when stream direction is "decoding only",
1825
 
     * because otherwise check_tx_rtcp() will be handled by put_frame()
1826
 
     */
1827
 
    if (stream->dir == PJMEDIA_DIR_DECODING) {
1828
 
        check_tx_rtcp(stream, pj_ntohl(hdr->ts));
1829
 
    }
1830
 
 
1831
 
    if (status != 0) {
1832
 
        LOGERR_((stream->port.info.name.ptr, "Jitter buffer put() error",
1833
 
                status));
1834
 
        pkt_discarded = PJ_TRUE;
1835
 
        goto on_return;
1836
 
    }
1837
 
 
1838
 
on_return:
1839
 
    /* Update RTCP session */
1840
 
    if (stream->rtcp.peer_ssrc == 0)
1841
 
        stream->rtcp.peer_ssrc = channel->rtp.peer_ssrc;
1842
 
 
1843
 
    pjmedia_rtcp_rx_rtp2(&stream->rtcp, pj_ntohs(hdr->seq),
1844
 
                         pj_ntohl(hdr->ts), payloadlen, pkt_discarded);
1845
 
 
1846
 
    /* Send RTCP RR and SDES after we receive some RTP packets */
1847
 
    if (stream->rtcp.received >= 10 && !stream->initial_rr) {
1848
 
        status = send_rtcp(stream, !stream->rtcp_sdes_bye_disabled,
1849
 
                           PJ_FALSE, PJ_FALSE);
1850
 
        if (status != PJ_SUCCESS) {
1851
 
            PJ_PERROR(4,(stream->port.info.name.ptr, status,
1852
 
                     "Error sending initial RTCP RR"));
1853
 
        } else {
1854
 
            stream->initial_rr = PJ_TRUE;
1855
 
        }
1856
 
    }
1857
 
}
1858
 
 
1859
 
 
1860
 
/*
1861
 
 * This callback is called by stream transport on receipt of packets
1862
 
 * in the RTCP socket.
1863
 
 */
1864
 
static void on_rx_rtcp( void *data,
1865
 
                        void *pkt,
1866
 
                        pj_ssize_t bytes_read)
1867
 
{
1868
 
    pjmedia_stream *stream = (pjmedia_stream*) data;
1869
 
 
1870
 
    /* Check for errors */
1871
 
    if (bytes_read < 0) {
1872
 
        LOGERR_((stream->port.info.name.ptr, "RTCP recv() error",
1873
 
                 -bytes_read));
1874
 
        return;
1875
 
    }
1876
 
 
1877
 
    pjmedia_rtcp_rx_rtcp(&stream->rtcp, pkt, bytes_read);
1878
 
}
1879
 
 
1880
 
 
1881
 
/*
1882
 
 * Create media channel.
1883
 
 */
1884
 
static pj_status_t create_channel( pj_pool_t *pool,
1885
 
                                   pjmedia_stream *stream,
1886
 
                                   pjmedia_dir dir,
1887
 
                                   unsigned pt,
1888
 
                                   const pjmedia_stream_info *param,
1889
 
                                   pjmedia_channel **p_channel)
1890
 
{
1891
 
    pjmedia_channel *channel;
1892
 
    pj_status_t status;
1893
 
 
1894
 
    /* Allocate memory for channel descriptor */
1895
 
 
1896
 
    channel = PJ_POOL_ZALLOC_T(pool, pjmedia_channel);
1897
 
    PJ_ASSERT_RETURN(channel != NULL, PJ_ENOMEM);
1898
 
 
1899
 
    /* Init channel info. */
1900
 
 
1901
 
    channel->stream = stream;
1902
 
    channel->dir = dir;
1903
 
    channel->paused = 1;
1904
 
    channel->pt = pt;
1905
 
 
1906
 
 
1907
 
    /* Allocate buffer for outgoing packet. */
1908
 
 
1909
 
    if (param->type == PJMEDIA_TYPE_AUDIO) {
1910
 
        channel->out_pkt_size = sizeof(pjmedia_rtp_hdr) +
1911
 
                                stream->codec_param.info.max_bps *
1912
 
                                PJMEDIA_MAX_FRAME_DURATION_MS /
1913
 
                                8 / 1000;
1914
 
        if (channel->out_pkt_size > PJMEDIA_MAX_MTU -
1915
 
                                    PJMEDIA_STREAM_RESV_PAYLOAD_LEN)
1916
 
        {
1917
 
            channel->out_pkt_size = PJMEDIA_MAX_MTU -
1918
 
                                    PJMEDIA_STREAM_RESV_PAYLOAD_LEN;
1919
 
        }
1920
 
    } else {
1921
 
        return PJ_ENOTSUP;
1922
 
    }
1923
 
 
1924
 
    channel->out_pkt = pj_pool_alloc(pool, channel->out_pkt_size);
1925
 
    PJ_ASSERT_RETURN(channel->out_pkt != NULL, PJ_ENOMEM);
1926
 
 
1927
 
 
1928
 
 
1929
 
    /* Create RTP and RTCP sessions: */
1930
 
 
1931
 
    if (param->rtp_seq_ts_set == 0) {
1932
 
        status = pjmedia_rtp_session_init(&channel->rtp, pt, param->ssrc);
1933
 
    } else {
1934
 
        pjmedia_rtp_session_setting settings;
1935
 
 
1936
 
        settings.flags = (pj_uint8_t)((param->rtp_seq_ts_set << 2) | 3);
1937
 
        settings.default_pt = pt;
1938
 
        settings.sender_ssrc = param->ssrc;
1939
 
        settings.seq = param->rtp_seq;
1940
 
        settings.ts = param->rtp_ts;
1941
 
        status = pjmedia_rtp_session_init2(&channel->rtp, settings);
1942
 
    }
1943
 
    if (status != PJ_SUCCESS)
1944
 
        return status;
1945
 
 
1946
 
    /* Done. */
1947
 
    *p_channel = channel;
1948
 
    return PJ_SUCCESS;
1949
 
}
1950
 
 
1951
 
 
1952
 
/*
1953
 
 * Create media stream.
1954
 
 */
1955
 
PJ_DEF(pj_status_t) pjmedia_stream_create( pjmedia_endpt *endpt,
1956
 
                                           pj_pool_t *pool,
1957
 
                                           const pjmedia_stream_info *info,
1958
 
                                           pjmedia_transport *tp,
1959
 
                                           void *user_data,
1960
 
                                           pjmedia_stream **p_stream)
1961
 
 
1962
 
{
1963
 
    enum { M = 32 };
1964
 
    pjmedia_stream *stream;
1965
 
    pj_str_t name;
1966
 
    unsigned jb_init, jb_max, jb_min_pre, jb_max_pre;
1967
 
    pjmedia_audio_format_detail *afd;
1968
 
    pj_pool_t *own_pool = NULL;
1969
 
    char *p;
1970
 
    pj_status_t status;
1971
 
 
1972
 
    PJ_ASSERT_RETURN(endpt && info && p_stream, PJ_EINVAL);
1973
 
 
1974
 
    if (pool == NULL) {
1975
 
        own_pool = pjmedia_endpt_create_pool( endpt, "strm%p",
1976
 
                                              PJMEDIA_STREAM_SIZE,
1977
 
                                              PJMEDIA_STREAM_INC);
1978
 
        PJ_ASSERT_RETURN(own_pool != NULL, PJ_ENOMEM);
1979
 
        pool = own_pool;
1980
 
    }
1981
 
 
1982
 
    /* Allocate the media stream: */
1983
 
 
1984
 
    stream = PJ_POOL_ZALLOC_T(pool, pjmedia_stream);
1985
 
    PJ_ASSERT_RETURN(stream != NULL, PJ_ENOMEM);
1986
 
    stream->own_pool = own_pool;
1987
 
    pj_memcpy(&stream->si, info, sizeof(*info));
1988
 
 
1989
 
    /* Init stream/port name */
1990
 
    name.ptr = (char*) pj_pool_alloc(pool, M);
1991
 
    name.slen = pj_ansi_snprintf(name.ptr, M, "strm%p", stream);
1992
 
 
1993
 
    /* Init some port-info. Some parts of the info will be set later
1994
 
     * once we have more info about the codec.
1995
 
     */
1996
 
    pjmedia_port_info_init(&stream->port.info, &name,
1997
 
                           PJMEDIA_SIG_PORT_STREAM,
1998
 
                           info->fmt.clock_rate, info->fmt.channel_cnt,
1999
 
                           16, 80);
2000
 
    afd = pjmedia_format_get_audio_format_detail(&stream->port.info.fmt, 1);
2001
 
 
2002
 
    /* Init port. */
2003
 
 
2004
 
    //No longer there in 2.0
2005
 
    //pj_strdup(pool, &stream->port.info.encoding_name, &info->fmt.encoding_name);
2006
 
    afd->clock_rate = info->fmt.clock_rate;
2007
 
    afd->channel_count = info->fmt.channel_cnt;
2008
 
    stream->port.port_data.pdata = stream;
2009
 
 
2010
 
    /* Init stream: */
2011
 
    stream->endpt = endpt;
2012
 
    stream->codec_mgr = pjmedia_endpt_get_codec_mgr(endpt);
2013
 
    stream->dir = info->dir;
2014
 
    stream->user_data = user_data;
2015
 
    stream->rtcp_interval = (PJMEDIA_RTCP_INTERVAL-500 + (pj_rand()%1000)) *
2016
 
                            info->fmt.clock_rate / 1000;
2017
 
    stream->rtcp_sdes_bye_disabled = info->rtcp_sdes_bye_disabled;
2018
 
 
2019
 
    stream->tx_event_pt = info->tx_event_pt ? info->tx_event_pt : -1;
2020
 
    stream->rx_event_pt = info->rx_event_pt ? info->rx_event_pt : -1;
2021
 
    stream->last_dtmf = -1;
2022
 
    stream->jb_last_frm = PJMEDIA_JB_NORMAL_FRAME;
2023
 
 
2024
 
#if defined(PJMEDIA_STREAM_ENABLE_KA) && PJMEDIA_STREAM_ENABLE_KA!=0
2025
 
    stream->use_ka = info->use_ka;
2026
 
#endif
2027
 
 
2028
 
    /* Build random RTCP CNAME. CNAME has user@host format */
2029
 
    stream->cname.ptr = p = (char*) pj_pool_alloc(pool, 20);
2030
 
    pj_create_random_string(p, 5);
2031
 
    p += 5;
2032
 
    *p++ = '@'; *p++ = 'p'; *p++ = 'j';
2033
 
    pj_create_random_string(p, 6);
2034
 
    p += 6;
2035
 
    *p++ = '.'; *p++ = 'o'; *p++ = 'r'; *p++ = 'g';
2036
 
    stream->cname.slen = p - stream->cname.ptr;
2037
 
 
2038
 
 
2039
 
    /* Create mutex to protect jitter buffer: */
2040
 
 
2041
 
    status = pj_mutex_create_simple(pool, NULL, &stream->jb_mutex);
2042
 
    if (status != PJ_SUCCESS)
2043
 
        goto err_cleanup;
2044
 
 
2045
 
 
2046
 
    /* Create and initialize codec: */
2047
 
 
2048
 
    status = pjmedia_codec_mgr_alloc_codec( stream->codec_mgr,
2049
 
                                            &info->fmt, &stream->codec);
2050
 
    if (status != PJ_SUCCESS)
2051
 
        goto err_cleanup;
2052
 
 
2053
 
 
2054
 
    /* Get codec param: */
2055
 
    if (info->param)
2056
 
        stream->codec_param = *info->param;
2057
 
    else {
2058
 
        status = pjmedia_codec_mgr_get_default_param(stream->codec_mgr,
2059
 
                                                     &info->fmt,
2060
 
                                                     &stream->codec_param);
2061
 
        if (status != PJ_SUCCESS)
2062
 
            goto err_cleanup;
2063
 
    }
2064
 
 
2065
 
    /* Check for invalid max_bps. */
2066
 
    if (stream->codec_param.info.max_bps < stream->codec_param.info.avg_bps)
2067
 
        stream->codec_param.info.max_bps = stream->codec_param.info.avg_bps;
2068
 
 
2069
 
    /* Check for invalid frame per packet. */
2070
 
    if (stream->codec_param.setting.frm_per_pkt < 1)
2071
 
        stream->codec_param.setting.frm_per_pkt = 1;
2072
 
 
2073
 
    /* Init the codec. */
2074
 
    status = pjmedia_codec_init(stream->codec, pool);
2075
 
    if (status != PJ_SUCCESS)
2076
 
        goto err_cleanup;
2077
 
 
2078
 
    /* Open the codec. */
2079
 
    status = pjmedia_codec_open(stream->codec, &stream->codec_param);
2080
 
    if (status != PJ_SUCCESS)
2081
 
        goto err_cleanup;
2082
 
 
2083
 
    /* Set additional info and callbacks. */
2084
 
    afd->bits_per_sample = 16;
2085
 
    afd->frame_time_usec = stream->codec_param.info.frm_ptime *
2086
 
                           stream->codec_param.setting.frm_per_pkt * 1000;
2087
 
    stream->port.info.fmt.id = stream->codec_param.info.fmt_id;
2088
 
    if (stream->codec_param.info.fmt_id == PJMEDIA_FORMAT_L16) {
2089
 
        /* Raw format */
2090
 
        afd->avg_bps = afd->max_bps = afd->clock_rate * afd->channel_count *
2091
 
                                      afd->bits_per_sample;
2092
 
 
2093
 
        stream->port.put_frame = &put_frame;
2094
 
        stream->port.get_frame = &get_frame;
2095
 
    } else {
2096
 
        /* Encoded format */
2097
 
        afd->avg_bps = stream->codec_param.info.avg_bps;
2098
 
        afd->max_bps = stream->codec_param.info.max_bps;
2099
 
 
2100
 
        /* Not applicable for 2.0
2101
 
        if ((stream->codec_param.info.max_bps *
2102
 
             stream->codec_param.info.frm_ptime *
2103
 
             stream->codec_param.setting.frm_per_pkt) % 8000 != 0)
2104
 
        {
2105
 
            ++stream->port.info.bytes_per_frame;
2106
 
        }
2107
 
        stream->port.info.format.bitrate = stream->codec_param.info.avg_bps;
2108
 
        stream->port.info.format.vad = (stream->codec_param.setting.vad != 0);
2109
 
        */
2110
 
 
2111
 
        stream->port.put_frame = &put_frame;
2112
 
        stream->port.get_frame = &get_frame_ext;
2113
 
    }
2114
 
 
2115
 
    /* If encoder and decoder's ptime are asymmetric, then we need to
2116
 
     * create buffer on the encoder side. This could happen for example
2117
 
     * with iLBC
2118
 
     */
2119
 
    if (stream->codec_param.info.enc_ptime!=0 &&
2120
 
        stream->codec_param.info.enc_ptime!=stream->codec_param.info.frm_ptime)
2121
 
    {
2122
 
        unsigned ptime;
2123
 
 
2124
 
        stream->enc_samples_per_pkt = stream->codec_param.info.enc_ptime *
2125
 
                                      stream->codec_param.info.channel_cnt *
2126
 
                                      afd->clock_rate / 1000;
2127
 
 
2128
 
        /* Set buffer size as twice the largest ptime value between
2129
 
         * stream's ptime, encoder ptime, or decoder ptime.
2130
 
         */
2131
 
 
2132
 
        ptime = afd->frame_time_usec / 1000;
2133
 
 
2134
 
        if (stream->codec_param.info.enc_ptime > ptime)
2135
 
            ptime = stream->codec_param.info.enc_ptime;
2136
 
 
2137
 
        if (stream->codec_param.info.frm_ptime > ptime)
2138
 
            ptime = stream->codec_param.info.frm_ptime;
2139
 
 
2140
 
        ptime <<= 1;
2141
 
 
2142
 
        /* Allocate buffer */
2143
 
        stream->enc_buf_size = afd->clock_rate * ptime / 1000;
2144
 
        stream->enc_buf = (pj_int16_t*)
2145
 
                          pj_pool_alloc(pool, stream->enc_buf_size * 2);
2146
 
 
2147
 
    } else {
2148
 
        stream->enc_samples_per_pkt = PJMEDIA_AFD_SPF(afd);
2149
 
    }
2150
 
 
2151
 
 
2152
 
    /* Initially disable the VAD in the stream, to help traverse NAT better */
2153
 
    stream->vad_enabled = stream->codec_param.setting.vad;
2154
 
    if (PJMEDIA_STREAM_VAD_SUSPEND_MSEC > 0 && stream->vad_enabled) {
2155
 
        stream->codec_param.setting.vad = 0;
2156
 
        stream->ts_vad_disabled = 0;
2157
 
        pjmedia_codec_modify(stream->codec, &stream->codec_param);
2158
 
        PJ_LOG(4,(stream->port.info.name.ptr,"VAD temporarily disabled"));
2159
 
    }
2160
 
 
2161
 
    /* Get the frame size */
2162
 
    stream->frame_size = stream->codec_param.info.max_bps *
2163
 
                         stream->codec_param.info.frm_ptime / 8 / 1000;
2164
 
    if ((stream->codec_param.info.max_bps * stream->codec_param.info.frm_ptime)
2165
 
        % 8000 != 0)
2166
 
    {
2167
 
        ++stream->frame_size;
2168
 
    }
2169
 
 
2170
 
    /* How many consecutive PLC frames can be generated */
2171
 
    stream->max_plc_cnt = (MAX_PLC_MSEC+stream->codec_param.info.frm_ptime-1)/
2172
 
                            stream->codec_param.info.frm_ptime;
2173
 
 
2174
 
#if defined(PJMEDIA_HANDLE_G722_MPEG_BUG) && (PJMEDIA_HANDLE_G722_MPEG_BUG!=0)
2175
 
    stream->rtp_rx_check_cnt = 5;
2176
 
    stream->has_g722_mpeg_bug = PJ_FALSE;
2177
 
    stream->rtp_rx_last_ts = 0;
2178
 
    stream->rtp_rx_last_cnt = 0;
2179
 
    stream->rtp_tx_ts_len_per_pkt = stream->enc_samples_per_pkt /
2180
 
                                     stream->codec_param.info.channel_cnt;
2181
 
    stream->rtp_rx_ts_len_per_frame = PJMEDIA_AFD_SPF(afd) /
2182
 
                                      stream->codec_param.setting.frm_per_pkt /
2183
 
                                      stream->codec_param.info.channel_cnt;
2184
 
 
2185
 
    if (info->fmt.pt == PJMEDIA_RTP_PT_G722) {
2186
 
        stream->has_g722_mpeg_bug = PJ_TRUE;
2187
 
        /* RTP clock rate = 1/2 real clock rate */
2188
 
        stream->rtp_tx_ts_len_per_pkt >>= 1;
2189
 
    }
2190
 
#endif
2191
 
 
2192
 
    /* Init jitter buffer parameters: */
2193
 
    if (info->jb_max >= stream->codec_param.info.frm_ptime)
2194
 
        jb_max = (info->jb_max + stream->codec_param.info.frm_ptime - 1) /
2195
 
                 stream->codec_param.info.frm_ptime;
2196
 
    else
2197
 
        jb_max = 500 / stream->codec_param.info.frm_ptime;
2198
 
 
2199
 
    if (info->jb_min_pre >= stream->codec_param.info.frm_ptime)
2200
 
        jb_min_pre = info->jb_min_pre / stream->codec_param.info.frm_ptime;
2201
 
    else
2202
 
        //jb_min_pre = 60 / stream->codec_param.info.frm_ptime;
2203
 
        jb_min_pre = 1;
2204
 
 
2205
 
    if (info->jb_max_pre >= stream->codec_param.info.frm_ptime)
2206
 
        jb_max_pre = info->jb_max_pre / stream->codec_param.info.frm_ptime;
2207
 
    else
2208
 
        //jb_max_pre = 240 / stream->codec_param.info.frm_ptime;
2209
 
        jb_max_pre = jb_max * 4 / 5;
2210
 
 
2211
 
    if (info->jb_init >= stream->codec_param.info.frm_ptime)
2212
 
        jb_init = info->jb_init / stream->codec_param.info.frm_ptime;
2213
 
    else
2214
 
        //jb_init = (jb_min_pre + jb_max_pre) / 2;
2215
 
        jb_init = 0;
2216
 
 
2217
 
    /* Create jitter buffer */
2218
 
    status = pjmedia_jbuf_create(pool, &stream->port.info.name,
2219
 
                                 stream->frame_size,
2220
 
                                 stream->codec_param.info.frm_ptime,
2221
 
                                 jb_max, &stream->jb);
2222
 
    if (status != PJ_SUCCESS)
2223
 
        goto err_cleanup;
2224
 
 
2225
 
 
2226
 
    /* Set up jitter buffer */
2227
 
    pjmedia_jbuf_set_adaptive( stream->jb, jb_init, jb_min_pre, jb_max_pre);
2228
 
 
2229
 
    /* Create decoder channel: */
2230
 
 
2231
 
    status = create_channel( pool, stream, PJMEDIA_DIR_DECODING,
2232
 
                             info->rx_pt, info, &stream->dec);
2233
 
    if (status != PJ_SUCCESS)
2234
 
        goto err_cleanup;
2235
 
 
2236
 
 
2237
 
    /* Create encoder channel: */
2238
 
 
2239
 
    status = create_channel( pool, stream, PJMEDIA_DIR_ENCODING,
2240
 
                             info->tx_pt, info, &stream->enc);
2241
 
    if (status != PJ_SUCCESS)
2242
 
        goto err_cleanup;
2243
 
 
2244
 
 
2245
 
    /* Init RTCP session: */
2246
 
 
2247
 
    {
2248
 
        pjmedia_rtcp_session_setting rtcp_setting;
2249
 
 
2250
 
        pjmedia_rtcp_session_setting_default(&rtcp_setting);
2251
 
        rtcp_setting.name = stream->port.info.name.ptr;
2252
 
        rtcp_setting.ssrc = info->ssrc;
2253
 
        rtcp_setting.rtp_ts_base = pj_ntohl(stream->enc->rtp.out_hdr.ts);
2254
 
        rtcp_setting.clock_rate = info->fmt.clock_rate;
2255
 
        rtcp_setting.samples_per_frame = PJMEDIA_AFD_SPF(afd);
2256
 
 
2257
 
#if defined(PJMEDIA_HANDLE_G722_MPEG_BUG) && (PJMEDIA_HANDLE_G722_MPEG_BUG!=0)
2258
 
        /* Special case for G.722 */
2259
 
        if (info->fmt.pt == PJMEDIA_RTP_PT_G722) {
2260
 
            rtcp_setting.clock_rate = 8000;
2261
 
            rtcp_setting.samples_per_frame = 160;
2262
 
        }
2263
 
#endif
2264
 
 
2265
 
        pjmedia_rtcp_init2(&stream->rtcp, &rtcp_setting);
2266
 
 
2267
 
        if (info->rtp_seq_ts_set) {
2268
 
            stream->rtcp.stat.rtp_tx_last_seq = info->rtp_seq;
2269
 
            stream->rtcp.stat.rtp_tx_last_ts = info->rtp_ts;
2270
 
        }
2271
 
    }
2272
 
 
2273
 
    /* Allocate outgoing RTCP buffer, should be enough to hold SR/RR, SDES,
2274
 
     * BYE, and XR.
2275
 
     */
2276
 
    stream->out_rtcp_pkt_size =  sizeof(pjmedia_rtcp_sr_pkt) +
2277
 
                                 sizeof(pjmedia_rtcp_common) +
2278
 
                                 (4 + stream->cname.slen) +
2279
 
                                 32;
2280
 
#if defined(PJMEDIA_HAS_RTCP_XR) && (PJMEDIA_HAS_RTCP_XR != 0)
2281
 
    if (info->rtcp_xr_enabled) {
2282
 
        stream->out_rtcp_pkt_size += sizeof(pjmedia_rtcp_xr_pkt);
2283
 
    }
2284
 
#endif
2285
 
 
2286
 
    if (stream->out_rtcp_pkt_size > PJMEDIA_MAX_MTU)
2287
 
        stream->out_rtcp_pkt_size = PJMEDIA_MAX_MTU;
2288
 
 
2289
 
    stream->out_rtcp_pkt = pj_pool_alloc(pool, stream->out_rtcp_pkt_size);
2290
 
 
2291
 
    /* Only attach transport when stream is ready. */
2292
 
    status = pjmedia_transport_attach(tp, stream, &info->rem_addr,
2293
 
                                      &info->rem_rtcp,
2294
 
                                      pj_sockaddr_get_len(&info->rem_addr),
2295
 
                                      &on_rx_rtp, &on_rx_rtcp);
2296
 
    if (status != PJ_SUCCESS)
2297
 
        goto err_cleanup;
2298
 
 
2299
 
    stream->transport = tp;
2300
 
 
2301
 
#if defined(PJMEDIA_HAS_RTCP_XR) && (PJMEDIA_HAS_RTCP_XR != 0)
2302
 
    /* Enable RTCP XR and update stream info/config to RTCP XR */
2303
 
    if (info->rtcp_xr_enabled) {
2304
 
        int i;
2305
 
 
2306
 
        pjmedia_rtcp_enable_xr(&stream->rtcp, PJ_TRUE);
2307
 
 
2308
 
        /* Set RTCP XR TX interval */
2309
 
        if (info->rtcp_xr_interval != 0)
2310
 
            stream->rtcp_xr_interval = info->rtcp_xr_interval;
2311
 
        else
2312
 
            stream->rtcp_xr_interval = (PJMEDIA_RTCP_INTERVAL +
2313
 
                                       (pj_rand() % 8000)) *
2314
 
                                       info->fmt.clock_rate / 1000;
2315
 
 
2316
 
        /* Additional third-party RTCP XR destination */
2317
 
        if (info->rtcp_xr_dest.addr.sa_family != 0) {
2318
 
            stream->rtcp_xr_dest_len = pj_sockaddr_get_len(&info->rtcp_xr_dest);
2319
 
            pj_memcpy(&stream->rtcp_xr_dest, &info->rtcp_xr_dest,
2320
 
                      stream->rtcp_xr_dest_len);
2321
 
        }
2322
 
 
2323
 
        /* jitter buffer adaptive info */
2324
 
        i = PJMEDIA_RTCP_XR_JB_ADAPTIVE;
2325
 
        pjmedia_rtcp_xr_update_info(&stream->rtcp.xr_session,
2326
 
                                    PJMEDIA_RTCP_XR_INFO_CONF_JBA,
2327
 
                                    i);
2328
 
 
2329
 
        /* Jitter buffer aggressiveness info (estimated) */
2330
 
        i = 7;
2331
 
        pjmedia_rtcp_xr_update_info(&stream->rtcp.xr_session,
2332
 
                                    PJMEDIA_RTCP_XR_INFO_CONF_JBR,
2333
 
                                    i);
2334
 
 
2335
 
        /* Jitter buffer absolute maximum delay */
2336
 
        i = jb_max * stream->codec_param.info.frm_ptime;
2337
 
        pjmedia_rtcp_xr_update_info(&stream->rtcp.xr_session,
2338
 
                                    PJMEDIA_RTCP_XR_INFO_JB_ABS_MAX,
2339
 
                                    i);
2340
 
 
2341
 
        /* PLC info */
2342
 
        if (stream->codec_param.setting.plc == 0)
2343
 
            i = PJMEDIA_RTCP_XR_PLC_DIS;
2344
 
        else
2345
 
#if PJMEDIA_WSOLA_IMP==PJMEDIA_WSOLA_IMP_WSOLA
2346
 
            i = PJMEDIA_RTCP_XR_PLC_ENH;
2347
 
#else
2348
 
            i = PJMEDIA_RTCP_XR_PLC_DIS;
2349
 
#endif
2350
 
        pjmedia_rtcp_xr_update_info(&stream->rtcp.xr_session,
2351
 
                                    PJMEDIA_RTCP_XR_INFO_CONF_PLC,
2352
 
                                    i);
2353
 
    }
2354
 
#endif
2355
 
 
2356
 
    /* Send RTCP SDES */
2357
 
    if (!stream->rtcp_sdes_bye_disabled) {
2358
 
        pjmedia_stream_send_rtcp_sdes(stream);
2359
 
    }
2360
 
 
2361
 
#if defined(PJMEDIA_STREAM_ENABLE_KA) && PJMEDIA_STREAM_ENABLE_KA!=0
2362
 
    /* NAT hole punching by sending KA packet via RTP transport. */
2363
 
    if (stream->use_ka)
2364
 
        send_keep_alive_packet(stream);
2365
 
#endif
2366
 
 
2367
 
#if TRACE_JB
2368
 
    {
2369
 
        char trace_name[PJ_MAXPATH];
2370
 
        pj_ssize_t len;
2371
 
 
2372
 
        pj_ansi_snprintf(trace_name, sizeof(trace_name),
2373
 
                         TRACE_JB_PATH_PREFIX "%s.csv",
2374
 
                         stream->port.info.name.ptr);
2375
 
        status = pj_file_open(pool, trace_name, PJ_O_WRONLY, &stream->trace_jb_fd);
2376
 
        if (status != PJ_SUCCESS) {
2377
 
            stream->trace_jb_fd = TRACE_JB_INVALID_FD;
2378
 
            PJ_LOG(3,(THIS_FILE, "Failed creating RTP trace file '%s'",
2379
 
                      trace_name));
2380
 
        } else {
2381
 
            stream->trace_jb_buf = (char*)pj_pool_alloc(pool, PJ_LOG_MAX_SIZE);
2382
 
 
2383
 
            /* Print column header */
2384
 
            len = pj_ansi_snprintf(stream->trace_jb_buf, PJ_LOG_MAX_SIZE,
2385
 
                                   "Time, Operation, Size, Frame Count, "
2386
 
                                   "Frame type, RTP Seq, RTP TS, RTP M, "
2387
 
                                   "JB size, JB burst level, JB prefetch\n");
2388
 
            pj_file_write(stream->trace_jb_fd, stream->trace_jb_buf, &len);
2389
 
            pj_file_flush(stream->trace_jb_fd);
2390
 
        }
2391
 
    }
2392
 
#endif
2393
 
 
2394
 
    /* Success! */
2395
 
    *p_stream = stream;
2396
 
 
2397
 
    PJ_LOG(5,(THIS_FILE, "Stream %s created", stream->port.info.name.ptr));
2398
 
 
2399
 
    return PJ_SUCCESS;
2400
 
 
2401
 
 
2402
 
err_cleanup:
2403
 
    pjmedia_stream_destroy(stream);
2404
 
    return status;
2405
 
}
2406
 
 
2407
 
 
2408
 
/*
2409
 
 * Destroy stream.
2410
 
 */
2411
 
PJ_DEF(pj_status_t) pjmedia_stream_destroy( pjmedia_stream *stream )
2412
 
{
2413
 
    PJ_ASSERT_RETURN(stream != NULL, PJ_EINVAL);
2414
 
 
2415
 
    /* Send RTCP BYE (also SDES & XR) */
2416
 
    if (!stream->rtcp_sdes_bye_disabled) {
2417
 
        send_rtcp(stream, PJ_TRUE, PJ_TRUE, PJ_TRUE);
2418
 
    }
2419
 
 
2420
 
    /* Detach from transport
2421
 
     * MUST NOT hold stream mutex while detaching from transport, as
2422
 
     * it may cause deadlock. See ticket #460 for the details.
2423
 
     */
2424
 
    if (stream->transport) {
2425
 
        pjmedia_transport_detach(stream->transport, stream);
2426
 
        stream->transport = NULL;
2427
 
    }
2428
 
 
2429
 
    /* This function may be called when stream is partly initialized. */
2430
 
    if (stream->jb_mutex)
2431
 
        pj_mutex_lock(stream->jb_mutex);
2432
 
 
2433
 
 
2434
 
    /* Free codec. */
2435
 
 
2436
 
    if (stream->codec) {
2437
 
        pjmedia_codec_close(stream->codec);
2438
 
        pjmedia_codec_mgr_dealloc_codec(stream->codec_mgr, stream->codec);
2439
 
        stream->codec = NULL;
2440
 
    }
2441
 
 
2442
 
    /* Free mutex */
2443
 
 
2444
 
    if (stream->jb_mutex) {
2445
 
        pj_mutex_destroy(stream->jb_mutex);
2446
 
        stream->jb_mutex = NULL;
2447
 
    }
2448
 
 
2449
 
    /* Destroy jitter buffer */
2450
 
    if (stream->jb)
2451
 
        pjmedia_jbuf_destroy(stream->jb);
2452
 
 
2453
 
#if TRACE_JB
2454
 
    if (TRACE_JB_OPENED(stream)) {
2455
 
        pj_file_close(stream->trace_jb_fd);
2456
 
        stream->trace_jb_fd = TRACE_JB_INVALID_FD;
2457
 
    }
2458
 
#endif
2459
 
 
2460
 
    if (stream->own_pool) {
2461
 
        pj_pool_t *pool = stream->own_pool;
2462
 
        stream->own_pool = NULL;
2463
 
        pj_pool_release(pool);
2464
 
    }
2465
 
    return PJ_SUCCESS;
2466
 
}
2467
 
 
2468
 
 
2469
 
/*
2470
 
 * Get the last frame frame type retreived from the jitter buffer.
2471
 
 */
2472
 
PJ_DEF(char) pjmedia_stream_get_last_jb_frame_type(pjmedia_stream *stream)
2473
 
{
2474
 
    return stream->jb_last_frm;
2475
 
}
2476
 
 
2477
 
 
2478
 
/*
2479
 
 * Get the port interface.
2480
 
 */
2481
 
PJ_DEF(pj_status_t) pjmedia_stream_get_port( pjmedia_stream *stream,
2482
 
                                             pjmedia_port **p_port )
2483
 
{
2484
 
    *p_port = &stream->port;
2485
 
    return PJ_SUCCESS;
2486
 
}
2487
 
 
2488
 
 
2489
 
/*
2490
 
 * Get the transport object
2491
 
 */
2492
 
PJ_DEF(pjmedia_transport*) pjmedia_stream_get_transport(pjmedia_stream *st)
2493
 
{
2494
 
    return st->transport;
2495
 
}
2496
 
 
2497
 
 
2498
 
/*
2499
 
 * Start stream.
2500
 
 */
2501
 
PJ_DEF(pj_status_t) pjmedia_stream_start(pjmedia_stream *stream)
2502
 
{
2503
 
 
2504
 
    PJ_ASSERT_RETURN(stream && stream->enc && stream->dec, PJ_EINVALIDOP);
2505
 
 
2506
 
    if (stream->enc && (stream->dir & PJMEDIA_DIR_ENCODING)) {
2507
 
        stream->enc->paused = 0;
2508
 
        //pjmedia_snd_stream_start(stream->enc->snd_stream);
2509
 
        PJ_LOG(4,(stream->port.info.name.ptr, "Encoder stream started"));
2510
 
    } else {
2511
 
        PJ_LOG(4,(stream->port.info.name.ptr, "Encoder stream paused"));
2512
 
    }
2513
 
 
2514
 
    if (stream->dec && (stream->dir & PJMEDIA_DIR_DECODING)) {
2515
 
        stream->dec->paused = 0;
2516
 
        //pjmedia_snd_stream_start(stream->dec->snd_stream);
2517
 
        PJ_LOG(4,(stream->port.info.name.ptr, "Decoder stream started"));
2518
 
    } else {
2519
 
        PJ_LOG(4,(stream->port.info.name.ptr, "Decoder stream paused"));
2520
 
    }
2521
 
 
2522
 
    return PJ_SUCCESS;
2523
 
}
2524
 
 
2525
 
 
2526
 
PJ_DEF(pj_status_t) pjmedia_stream_get_info( const pjmedia_stream *stream,
2527
 
                                             pjmedia_stream_info *info)
2528
 
{
2529
 
    PJ_ASSERT_RETURN(stream && info, PJ_EINVAL);
2530
 
 
2531
 
    pj_memcpy(info, &stream->si, sizeof(pjmedia_stream_info));
2532
 
    return PJ_SUCCESS;
2533
 
}
2534
 
 
2535
 
/*
2536
 
 * Get stream statistics.
2537
 
 */
2538
 
PJ_DEF(pj_status_t) pjmedia_stream_get_stat( const pjmedia_stream *stream,
2539
 
                                             pjmedia_rtcp_stat *stat)
2540
 
{
2541
 
    PJ_ASSERT_RETURN(stream && stat, PJ_EINVAL);
2542
 
 
2543
 
    pj_memcpy(stat, &stream->rtcp.stat, sizeof(pjmedia_rtcp_stat));
2544
 
    return PJ_SUCCESS;
2545
 
}
2546
 
 
2547
 
 
2548
 
/*
2549
 
 * Reset the stream statistics in the middle of a stream session.
2550
 
 */
2551
 
PJ_DEF(pj_status_t) pjmedia_stream_reset_stat(pjmedia_stream *stream)
2552
 
{
2553
 
    PJ_ASSERT_RETURN(stream, PJ_EINVAL);
2554
 
 
2555
 
    pjmedia_rtcp_init_stat(&stream->rtcp.stat);
2556
 
 
2557
 
    return PJ_SUCCESS;
2558
 
}
2559
 
 
2560
 
 
2561
 
#if defined(PJMEDIA_HAS_RTCP_XR) && (PJMEDIA_HAS_RTCP_XR != 0)
2562
 
/*
2563
 
 * Get stream extended statistics.
2564
 
 */
2565
 
PJ_DEF(pj_status_t) pjmedia_stream_get_stat_xr( const pjmedia_stream *stream,
2566
 
                                                pjmedia_rtcp_xr_stat *stat)
2567
 
{
2568
 
    PJ_ASSERT_RETURN(stream && stat, PJ_EINVAL);
2569
 
 
2570
 
    if (stream->rtcp.xr_enabled) {
2571
 
        pj_memcpy(stat, &stream->rtcp.xr_session.stat, sizeof(pjmedia_rtcp_xr_stat));
2572
 
        return PJ_SUCCESS;
2573
 
    }
2574
 
    return PJ_ENOTFOUND;
2575
 
}
2576
 
#endif
2577
 
 
2578
 
/*
2579
 
 * Get jitter buffer state.
2580
 
 */
2581
 
PJ_DEF(pj_status_t) pjmedia_stream_get_stat_jbuf(const pjmedia_stream *stream,
2582
 
                                                 pjmedia_jb_state *state)
2583
 
{
2584
 
    PJ_ASSERT_RETURN(stream && state, PJ_EINVAL);
2585
 
    return pjmedia_jbuf_get_state(stream->jb, state);
2586
 
}
2587
 
 
2588
 
/*
2589
 
 * Pause stream.
2590
 
 */
2591
 
PJ_DEF(pj_status_t) pjmedia_stream_pause( pjmedia_stream *stream,
2592
 
                                          pjmedia_dir dir)
2593
 
{
2594
 
    PJ_ASSERT_RETURN(stream, PJ_EINVAL);
2595
 
 
2596
 
    if ((dir & PJMEDIA_DIR_ENCODING) && stream->enc) {
2597
 
        stream->enc->paused = 1;
2598
 
        PJ_LOG(4,(stream->port.info.name.ptr, "Encoder stream paused"));
2599
 
    }
2600
 
 
2601
 
    if ((dir & PJMEDIA_DIR_DECODING) && stream->dec) {
2602
 
        stream->dec->paused = 1;
2603
 
 
2604
 
        /* Also reset jitter buffer */
2605
 
        pj_mutex_lock( stream->jb_mutex );
2606
 
        pjmedia_jbuf_reset(stream->jb);
2607
 
        pj_mutex_unlock( stream->jb_mutex );
2608
 
 
2609
 
        PJ_LOG(4,(stream->port.info.name.ptr, "Decoder stream paused"));
2610
 
    }
2611
 
 
2612
 
    return PJ_SUCCESS;
2613
 
}
2614
 
 
2615
 
 
2616
 
/*
2617
 
 * Resume stream
2618
 
 */
2619
 
PJ_DEF(pj_status_t) pjmedia_stream_resume( pjmedia_stream *stream,
2620
 
                                           pjmedia_dir dir)
2621
 
{
2622
 
    PJ_ASSERT_RETURN(stream, PJ_EINVAL);
2623
 
 
2624
 
    if ((dir & PJMEDIA_DIR_ENCODING) && stream->enc) {
2625
 
        stream->enc->paused = 0;
2626
 
        PJ_LOG(4,(stream->port.info.name.ptr, "Encoder stream resumed"));
2627
 
    }
2628
 
 
2629
 
    if ((dir & PJMEDIA_DIR_DECODING) && stream->dec) {
2630
 
        stream->dec->paused = 0;
2631
 
        PJ_LOG(4,(stream->port.info.name.ptr, "Decoder stream resumed"));
2632
 
    }
2633
 
 
2634
 
    return PJ_SUCCESS;
2635
 
}
2636
 
 
2637
 
/*
2638
 
 * Dial DTMF
2639
 
 */
2640
 
PJ_DEF(pj_status_t) pjmedia_stream_dial_dtmf( pjmedia_stream *stream,
2641
 
                                              const pj_str_t *digit_char)
2642
 
{
2643
 
    pj_status_t status = PJ_SUCCESS;
2644
 
 
2645
 
    /* By convention we use jitter buffer mutex to access DTMF
2646
 
     * queue.
2647
 
     */
2648
 
    PJ_ASSERT_RETURN(stream && digit_char, PJ_EINVAL);
2649
 
 
2650
 
    /* Check that remote can receive DTMF events. */
2651
 
    if (stream->tx_event_pt < 0) {
2652
 
        return PJMEDIA_RTP_EREMNORFC2833;
2653
 
    }
2654
 
 
2655
 
    pj_mutex_lock(stream->jb_mutex);
2656
 
 
2657
 
    if (stream->tx_dtmf_count+digit_char->slen >=
2658
 
        (long)PJ_ARRAY_SIZE(stream->tx_dtmf_buf))
2659
 
    {
2660
 
        status = PJ_ETOOMANY;
2661
 
    } else {
2662
 
        int i;
2663
 
 
2664
 
        /* convert ASCII digits into payload type first, to make sure
2665
 
         * that all digits are valid.
2666
 
         */
2667
 
        for (i=0; i<digit_char->slen; ++i) {
2668
 
            unsigned pt;
2669
 
            int dig = pj_tolower(digit_char->ptr[i]);
2670
 
 
2671
 
            if (dig >= '0' && dig <= '9')
2672
 
            {
2673
 
                pt = dig - '0';
2674
 
            }
2675
 
            else if (dig >= 'a' && dig <= 'd')
2676
 
            {
2677
 
                pt = dig - 'a' + 12;
2678
 
            }
2679
 
            else if (dig == '*')
2680
 
            {
2681
 
                pt = 10;
2682
 
            }
2683
 
            else if (dig == '#')
2684
 
            {
2685
 
                pt = 11;
2686
 
            }
2687
 
            else
2688
 
            {
2689
 
                status = PJMEDIA_RTP_EINDTMF;
2690
 
                break;
2691
 
            }
2692
 
 
2693
 
            stream->tx_dtmf_buf[stream->tx_dtmf_count+i].event = pt;
2694
 
            stream->tx_dtmf_buf[stream->tx_dtmf_count+i].duration = 0;
2695
 
        }
2696
 
 
2697
 
        if (status != PJ_SUCCESS)
2698
 
            goto on_return;
2699
 
 
2700
 
        /* Increment digit count only if all digits are valid. */
2701
 
        stream->tx_dtmf_count += digit_char->slen;
2702
 
    }
2703
 
 
2704
 
on_return:
2705
 
    pj_mutex_unlock(stream->jb_mutex);
2706
 
 
2707
 
    return status;
2708
 
}
2709
 
 
2710
 
 
2711
 
/*
2712
 
 * See if we have DTMF digits in the rx buffer.
2713
 
 */
2714
 
PJ_DEF(pj_bool_t) pjmedia_stream_check_dtmf(pjmedia_stream *stream)
2715
 
{
2716
 
    return stream->rx_dtmf_count != 0;
2717
 
}
2718
 
 
2719
 
 
2720
 
/*
2721
 
 * Retrieve incoming DTMF digits from the stream's DTMF buffer.
2722
 
 */
2723
 
PJ_DEF(pj_status_t) pjmedia_stream_get_dtmf( pjmedia_stream *stream,
2724
 
                                             char *digits,
2725
 
                                             unsigned *size)
2726
 
{
2727
 
    PJ_ASSERT_RETURN(stream && digits && size, PJ_EINVAL);
2728
 
 
2729
 
    pj_assert(sizeof(stream->rx_dtmf_buf[0]) == 0);
2730
 
 
2731
 
    /* By convention, we use jitter buffer's mutex to access DTMF
2732
 
     * digits resources.
2733
 
     */
2734
 
    pj_mutex_lock(stream->jb_mutex);
2735
 
 
2736
 
    if (stream->rx_dtmf_count < *size)
2737
 
        *size = stream->rx_dtmf_count;
2738
 
 
2739
 
    if (*size) {
2740
 
        pj_memcpy(digits, stream->rx_dtmf_buf, *size);
2741
 
        stream->rx_dtmf_count -= *size;
2742
 
        if (stream->rx_dtmf_count) {
2743
 
            pj_memmove(stream->rx_dtmf_buf,
2744
 
                       &stream->rx_dtmf_buf[*size],
2745
 
                       stream->rx_dtmf_count);
2746
 
        }
2747
 
    }
2748
 
 
2749
 
    pj_mutex_unlock(stream->jb_mutex);
2750
 
 
2751
 
    return PJ_SUCCESS;
2752
 
}
2753
 
 
2754
 
 
2755
 
/*
2756
 
 * Set callback to be called upon receiving DTMF digits.
2757
 
 */
2758
 
PJ_DEF(pj_status_t) pjmedia_stream_set_dtmf_callback(pjmedia_stream *stream,
2759
 
                                 void (*cb)(pjmedia_stream*,
2760
 
                                            void *user_data,
2761
 
                                            int digit),
2762
 
                                 void *user_data)
2763
 
{
2764
 
    PJ_ASSERT_RETURN(stream, PJ_EINVAL);
2765
 
 
2766
 
    /* By convention, we use jitter buffer's mutex to access DTMF
2767
 
     * digits resources.
2768
 
     */
2769
 
    pj_mutex_lock(stream->jb_mutex);
2770
 
 
2771
 
    stream->dtmf_cb = cb;
2772
 
    stream->dtmf_cb_user_data = user_data;
2773
 
 
2774
 
    pj_mutex_unlock(stream->jb_mutex);
2775
 
 
2776
 
    return PJ_SUCCESS;
2777
 
}
2778
 
 
2779
 
/*
2780
 
 * Send RTCP SDES.
2781
 
 */
2782
 
PJ_DEF(pj_status_t)
2783
 
pjmedia_stream_send_rtcp_sdes( pjmedia_stream *stream )
2784
 
{
2785
 
    PJ_ASSERT_RETURN(stream, PJ_EINVAL);
2786
 
 
2787
 
    return send_rtcp(stream, PJ_TRUE, PJ_FALSE, PJ_FALSE);
2788
 
}
2789
 
 
2790
 
/*
2791
 
 * Send RTCP BYE.
2792
 
 */
2793
 
PJ_DEF(pj_status_t)
2794
 
pjmedia_stream_send_rtcp_bye( pjmedia_stream *stream )
2795
 
{
2796
 
    PJ_ASSERT_RETURN(stream, PJ_EINVAL);
2797
 
 
2798
 
    if (stream->enc && stream->transport) {
2799
 
        return send_rtcp(stream, PJ_TRUE, PJ_TRUE, PJ_FALSE);
2800
 
    }
2801
 
 
2802
 
    return PJ_SUCCESS;
2803
 
}