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