blob: 4b84b8bca914acb9a9ab695b2da82b76fac6ffda [file] [log] [blame]
Tristan Matthews0a329cc2013-07-17 13:20:14 -04001/* $Id$ */
2/*
3 * Copyright (C) 2011 Teluu Inc. (http://www.teluu.com)
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18 */
19#include <pjmedia/vid_stream.h>
20#include <pjmedia/errno.h>
21#include <pjmedia/event.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/compat/socket.h>
29#include <pj/errno.h>
30#include <pj/ioqueue.h>
31#include <pj/log.h>
32#include <pj/os.h>
33#include <pj/pool.h>
34#include <pj/rand.h>
35#include <pj/sock_select.h>
36#include <pj/string.h> /* memcpy() */
37
38
39#if defined(PJMEDIA_HAS_VIDEO) && (PJMEDIA_HAS_VIDEO != 0)
40
41
42#define THIS_FILE "vid_stream.c"
43#define ERRLEVEL 1
44#define LOGERR_(expr) stream_perror expr
45#define TRC_(expr) PJ_LOG(5,expr)
46#define SIGNATURE PJMEDIA_SIG_PORT_VID_STREAM
47
48#define TRACE_RC 0
49
50/* Tracing jitter buffer operations in a stream session to a CSV file.
51 * The trace will contain JB operation timestamp, frame info, RTP info, and
52 * the JB state right after the operation.
53 */
54#define TRACE_JB 0 /* Enable/disable trace. */
55#define TRACE_JB_PATH_PREFIX "" /* Optional path/prefix
56 for the CSV filename. */
57#if TRACE_JB
58# include <pj/file_io.h>
59# define TRACE_JB_INVALID_FD ((pj_oshandle_t)-1)
60# define TRACE_JB_OPENED(s) (s->trace_jb_fd != TRACE_JB_INVALID_FD)
61#endif
62
63#ifndef PJMEDIA_VSTREAM_SIZE
64# define PJMEDIA_VSTREAM_SIZE 1000
65#endif
66
67#ifndef PJMEDIA_VSTREAM_INC
68# define PJMEDIA_VSTREAM_INC 1000
69#endif
70
71/* Due to network MTU limitation, a picture bitstream may be splitted into
72 * several chunks for RTP delivery. The chunk number may vary depend on the
73 * picture resolution and MTU. This constant specifies the minimum chunk
74 * number to be allocated to store a picture bitstream in decoding direction.
75 */
76#define MIN_CHUNKS_PER_FRM 30
77
78/* Video stream keep-alive feature is currently disabled. */
79#if defined(PJMEDIA_STREAM_ENABLE_KA) && PJMEDIA_STREAM_ENABLE_KA != 0
80# undef PJMEDIA_STREAM_ENABLE_KA
81# define PJMEDIA_STREAM_ENABLE_KA 0
82#endif
83
84
85/**
86 * Media channel.
87 */
88typedef struct pjmedia_vid_channel
89{
90 pjmedia_vid_stream *stream; /**< Parent stream. */
91 pjmedia_dir dir; /**< Channel direction. */
92 pjmedia_port port; /**< Port interface. */
93 unsigned pt; /**< Payload type. */
94 pj_bool_t paused; /**< Paused?. */
95 void *buf; /**< Output buffer. */
96 unsigned buf_size; /**< Size of output buffer. */
97 pjmedia_rtp_session rtp; /**< RTP session. */
98} pjmedia_vid_channel;
99
100
101/**
102 * This structure describes media stream.
103 * A media stream is bidirectional media transmission between two endpoints.
104 * It consists of two channels, i.e. encoding and decoding channels.
105 * A media stream corresponds to a single "m=" line in a SDP session
106 * description.
107 */
108struct pjmedia_vid_stream
109{
110 pj_pool_t *own_pool; /**< Internal pool. */
111 pjmedia_endpt *endpt; /**< Media endpoint. */
112 pjmedia_vid_codec_mgr *codec_mgr; /**< Codec manager. */
113 pjmedia_vid_stream_info info; /**< Stream info. */
114
115 pjmedia_vid_channel *enc; /**< Encoding channel. */
116 pjmedia_vid_channel *dec; /**< Decoding channel. */
117
118 pjmedia_dir dir; /**< Stream direction. */
119 void *user_data; /**< User data. */
120 pj_str_t name; /**< Stream name */
121 pj_str_t cname; /**< SDES CNAME */
122
123 pjmedia_transport *transport; /**< Stream transport. */
124 unsigned send_err_cnt; /**< Send error count. */
125
126 pj_mutex_t *jb_mutex;
127 pjmedia_jbuf *jb; /**< Jitter buffer. */
128 char jb_last_frm; /**< Last frame type from jb */
129 unsigned jb_last_frm_cnt;/**< Last JB frame type counter*/
130
131 pjmedia_rtcp_session rtcp; /**< RTCP for incoming RTP. */
132 pj_uint32_t rtcp_last_tx; /**< RTCP tx time in timestamp */
133 pj_uint32_t rtcp_interval; /**< Interval, in timestamp. */
134 pj_bool_t initial_rr; /**< Initial RTCP RR sent */
135 pj_bool_t rtcp_sdes_bye_disabled;/**< Send RTCP SDES/BYE?*/
136 void *out_rtcp_pkt; /**< Outgoing RTCP packet. */
137 unsigned out_rtcp_pkt_size;
138 /**< Outgoing RTCP packet size. */
139
140 unsigned dec_max_size; /**< Size of decoded/raw picture*/
141 pjmedia_ratio dec_max_fps; /**< Max fps of decoding dir. */
142 pjmedia_frame dec_frame; /**< Current decoded frame. */
143 pjmedia_event fmt_event; /**< Buffered fmt_changed event
144 to avoid deadlock */
145 pjmedia_event miss_keyframe_event;
146 /**< Buffered missing keyframe
147 event for delayed republish*/
148
149 unsigned frame_size; /**< Size of encoded base frame.*/
150 unsigned frame_ts_len; /**< Frame length in timestamp. */
151
152 unsigned rx_frame_cnt; /**< # of array in rx_frames */
153 pjmedia_frame *rx_frames; /**< Temp. buffer for incoming
154 frame assembly. */
155
156 pj_bool_t force_keyframe;/**< Forced to encode keyframe? */
157
158#if defined(PJMEDIA_STREAM_ENABLE_KA) && PJMEDIA_STREAM_ENABLE_KA!=0
159 pj_bool_t use_ka; /**< Stream keep-alive with non-
160 codec-VAD mechanism is
161 enabled? */
162 pj_timestamp last_frm_ts_sent; /**< Timestamp of last sending
163 packet */
164#endif
165
166#if TRACE_JB
167 pj_oshandle_t trace_jb_fd; /**< Jitter tracing file handle.*/
168 char *trace_jb_buf; /**< Jitter tracing buffer. */
169#endif
170
171 pjmedia_vid_codec *codec; /**< Codec instance being used. */
172 pj_uint32_t last_dec_ts; /**< Last decoded timestamp. */
173 int last_dec_seq; /**< Last decoded sequence. */
174
175
176 pj_timestamp ts_freq; /**< Timestamp frequency. */
177
178#if TRACE_RC
179 unsigned rc_total_sleep;
180 unsigned rc_total_pkt;
181 unsigned rc_total_img;
182 pj_timestamp tx_start;
183 pj_timestamp tx_end;
184#endif
185};
186
187/* Prototypes */
188static pj_status_t decode_frame(pjmedia_vid_stream *stream,
189 pjmedia_frame *frame);
190
191/*
192 * Print error.
193 */
194static void stream_perror(const char *sender, const char *title,
195 pj_status_t status)
196{
197 char errmsg[PJ_ERR_MSG_SIZE];
198
199 pj_strerror(status, errmsg, sizeof(errmsg));
200 PJ_LOG(4,(sender, "%s: %s [err:%d]", title, errmsg, status));
201}
202
203
204static pj_status_t send_rtcp(pjmedia_vid_stream *stream,
205 pj_bool_t with_sdes,
206 pj_bool_t with_bye);
207
208
209#if TRACE_JB
210
211PJ_INLINE(int) trace_jb_print_timestamp(char **buf, pj_ssize_t len)
212{
213 pj_time_val now;
214 pj_parsed_time ptime;
215 char *p = *buf;
216
217 if (len < 14)
218 return -1;
219
220 pj_gettimeofday(&now);
221 pj_time_decode(&now, &ptime);
222 p += pj_utoa_pad(ptime.hour, p, 2, '0');
223 *p++ = ':';
224 p += pj_utoa_pad(ptime.min, p, 2, '0');
225 *p++ = ':';
226 p += pj_utoa_pad(ptime.sec, p, 2, '0');
227 *p++ = '.';
228 p += pj_utoa_pad(ptime.msec, p, 3, '0');
229 *p++ = ',';
230
231 *buf = p;
232
233 return 0;
234}
235
236PJ_INLINE(int) trace_jb_print_state(pjmedia_vid_stream *stream,
237 char **buf, pj_ssize_t len)
238{
239 char *p = *buf;
240 char *endp = *buf + len;
241 pjmedia_jb_state state;
242
243 pjmedia_jbuf_get_state(stream->jb, &state);
244
245 len = pj_ansi_snprintf(p, endp-p, "%d, %d, %d",
246 state.size, state.burst, state.prefetch);
247 if ((len < 0) || (len >= endp-p))
248 return -1;
249
250 p += len;
251 *buf = p;
252 return 0;
253}
254
255static void trace_jb_get(pjmedia_vid_stream *stream, pjmedia_jb_frame_type ft,
256 pj_size_t fsize)
257{
258 char *p = stream->trace_jb_buf;
259 char *endp = stream->trace_jb_buf + PJ_LOG_MAX_SIZE;
260 pj_ssize_t len = 0;
261 const char* ft_st;
262
263 if (!TRACE_JB_OPENED(stream))
264 return;
265
266 /* Print timestamp. */
267 if (trace_jb_print_timestamp(&p, endp-p))
268 goto on_insuff_buffer;
269
270 /* Print frame type and size */
271 switch(ft) {
272 case PJMEDIA_JB_MISSING_FRAME:
273 ft_st = "missing";
274 break;
275 case PJMEDIA_JB_NORMAL_FRAME:
276 ft_st = "normal";
277 break;
278 case PJMEDIA_JB_ZERO_PREFETCH_FRAME:
279 ft_st = "prefetch";
280 break;
281 case PJMEDIA_JB_ZERO_EMPTY_FRAME:
282 ft_st = "empty";
283 break;
284 default:
285 ft_st = "unknown";
286 break;
287 }
288
289 /* Print operation, size, frame count, frame type */
290 len = pj_ansi_snprintf(p, endp-p, "GET,%d,1,%s,,,,", fsize, ft_st);
291 if ((len < 0) || (len >= endp-p))
292 goto on_insuff_buffer;
293 p += len;
294
295 /* Print JB state */
296 if (trace_jb_print_state(stream, &p, endp-p))
297 goto on_insuff_buffer;
298
299 /* Print end of line */
300 if (endp-p < 2)
301 goto on_insuff_buffer;
302 *p++ = '\n';
303
304 /* Write and flush */
305 len = p - stream->trace_jb_buf;
306 pj_file_write(stream->trace_jb_fd, stream->trace_jb_buf, &len);
307 pj_file_flush(stream->trace_jb_fd);
308 return;
309
310on_insuff_buffer:
311 pj_assert(!"Trace buffer too small, check PJ_LOG_MAX_SIZE!");
312}
313
314static void trace_jb_put(pjmedia_vid_stream *stream,
315 const pjmedia_rtp_hdr *hdr,
316 unsigned payloadlen, unsigned frame_cnt)
317{
318 char *p = stream->trace_jb_buf;
319 char *endp = stream->trace_jb_buf + PJ_LOG_MAX_SIZE;
320 pj_ssize_t len = 0;
321
322 if (!TRACE_JB_OPENED(stream))
323 return;
324
325 /* Print timestamp. */
326 if (trace_jb_print_timestamp(&p, endp-p))
327 goto on_insuff_buffer;
328
329 /* Print operation, size, frame count, RTP info */
330 len = pj_ansi_snprintf(p, endp-p,
331 "PUT,%d,%d,,%d,%d,%d,",
332 payloadlen, frame_cnt,
333 pj_ntohs(hdr->seq), pj_ntohl(hdr->ts), hdr->m);
334 if ((len < 0) || (len >= endp-p))
335 goto on_insuff_buffer;
336 p += len;
337
338 /* Print JB state */
339 if (trace_jb_print_state(stream, &p, endp-p))
340 goto on_insuff_buffer;
341
342 /* Print end of line */
343 if (endp-p < 2)
344 goto on_insuff_buffer;
345 *p++ = '\n';
346
347 /* Write and flush */
348 len = p - stream->trace_jb_buf;
349 pj_file_write(stream->trace_jb_fd, stream->trace_jb_buf, &len);
350 pj_file_flush(stream->trace_jb_fd);
351 return;
352
353on_insuff_buffer:
354 pj_assert(!"Trace buffer too small, check PJ_LOG_MAX_SIZE!");
355}
356
357#endif /* TRACE_JB */
358
359static void dump_port_info(const pjmedia_vid_channel *chan,
360 const char *event_name)
361{
362 const pjmedia_port_info *pi = &chan->port.info;
363 char fourcc_name[5];
364
365 PJ_LOG(5, (pi->name.ptr,
366 " %s format %s: %dx%d %s%s %d/%d(~%d)fps",
367 (chan->dir==PJMEDIA_DIR_DECODING? "Decoding":"Encoding"),
368 event_name,
369 pi->fmt.det.vid.size.w, pi->fmt.det.vid.size.h,
370 pjmedia_fourcc_name(pi->fmt.id, fourcc_name),
371 (chan->dir==PJMEDIA_DIR_ENCODING?"->":"<-"),
372 pi->fmt.det.vid.fps.num, pi->fmt.det.vid.fps.denum,
373 pi->fmt.det.vid.fps.num/pi->fmt.det.vid.fps.denum));
374}
375
376/*
377 * Handle events from stream components.
378 */
379static pj_status_t stream_event_cb(pjmedia_event *event,
380 void *user_data)
381{
382 pjmedia_vid_stream *stream = (pjmedia_vid_stream*)user_data;
383
384 if (event->epub == stream->codec) {
385 /* This is codec event */
386 switch (event->type) {
387 case PJMEDIA_EVENT_FMT_CHANGED:
388 /* Copy the event to avoid deadlock if we publish the event
389 * now. This happens because fmt_event may trigger restart
390 * while we're still holding the jb_mutex.
391 */
392 pj_memcpy(&stream->fmt_event, event, sizeof(*event));
393 return PJ_SUCCESS;
394
395 case PJMEDIA_EVENT_KEYFRAME_MISSING:
396 /* Republish this event later from get_frame(). */
397 pj_memcpy(&stream->miss_keyframe_event, event, sizeof(*event));
398 return PJ_SUCCESS;
399
400 default:
401 break;
402 }
403 }
404
405 return pjmedia_event_publish(NULL, stream, event, 0);
406}
407
408#if defined(PJMEDIA_STREAM_ENABLE_KA) && PJMEDIA_STREAM_ENABLE_KA != 0
409/*
410 * Send keep-alive packet using non-codec frame.
411 */
412static void send_keep_alive_packet(pjmedia_vid_stream *stream)
413{
414#if PJMEDIA_STREAM_ENABLE_KA == PJMEDIA_STREAM_KA_EMPTY_RTP
415
416 /* Keep-alive packet is empty RTP */
417 pjmedia_vid_channel *channel = stream->enc;
418 pj_status_t status;
419 void *pkt;
420 int pkt_len;
421
422 TRC_((channel->port.info.name.ptr,
423 "Sending keep-alive (RTCP and empty RTP)"));
424
425 /* Send RTP */
426 status = pjmedia_rtp_encode_rtp( &stream->enc->rtp,
427 stream->enc->pt, 0,
428 1,
429 0,
430 (const void**)&pkt,
431 &pkt_len);
432 pj_assert(status == PJ_SUCCESS);
433
434 pj_memcpy(stream->enc->buf, pkt, pkt_len);
435 pjmedia_transport_send_rtp(stream->transport, stream->enc->buf,
436 pkt_len);
437
438 /* Send RTCP */
439 send_rtcp(stream, PJ_TRUE, PJ_FALSE);
440
441#elif PJMEDIA_STREAM_ENABLE_KA == PJMEDIA_STREAM_KA_USER
442
443 /* Keep-alive packet is defined in PJMEDIA_STREAM_KA_USER_PKT */
444 pjmedia_vid_channel *channel = stream->enc;
445 int pkt_len;
446 const pj_str_t str_ka = PJMEDIA_STREAM_KA_USER_PKT;
447
448 TRC_((channel->port.info.name.ptr,
449 "Sending keep-alive (custom RTP/RTCP packets)"));
450
451 /* Send to RTP port */
452 pj_memcpy(stream->enc->buf, str_ka.ptr, str_ka.slen);
453 pkt_len = str_ka.slen;
454 pjmedia_transport_send_rtp(stream->transport, stream->enc->buf,
455 pkt_len);
456
457 /* Send to RTCP port */
458 pjmedia_transport_send_rtcp(stream->transport, stream->enc->buf,
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
470static pj_status_t send_rtcp(pjmedia_vid_stream *stream,
471 pj_bool_t with_sdes,
472 pj_bool_t with_bye)
473{
474 void *sr_rr_pkt;
475 pj_uint8_t *pkt;
476 int len, max_len;
477 pj_status_t status;
478
479 /* Build RTCP RR/SR packet */
480 pjmedia_rtcp_build_rtcp(&stream->rtcp, &sr_rr_pkt, &len);
481
482 if (with_sdes || with_bye) {
483 pkt = (pj_uint8_t*) stream->out_rtcp_pkt;
484 pj_memcpy(pkt, sr_rr_pkt, len);
485 max_len = stream->out_rtcp_pkt_size;
486 } else {
487 pkt = (pj_uint8_t*)sr_rr_pkt;
488 max_len = len;
489 }
490
491 /* Build RTCP SDES packet */
492 if (with_sdes) {
493 pjmedia_rtcp_sdes sdes;
494 pj_size_t sdes_len;
495
496 pj_bzero(&sdes, sizeof(sdes));
497 sdes.cname = stream->cname;
498 sdes_len = max_len - len;
499 status = pjmedia_rtcp_build_rtcp_sdes(&stream->rtcp, pkt+len,
500 &sdes_len, &sdes);
501 if (status != PJ_SUCCESS) {
502 PJ_PERROR(4,(stream->name.ptr, status,
503 "Error generating RTCP SDES"));
504 } else {
505 len += (int)sdes_len;
506 }
507 }
508
509 /* Build RTCP BYE packet */
510 if (with_bye) {
511 pj_size_t bye_len;
512
513 bye_len = max_len - len;
514 status = pjmedia_rtcp_build_rtcp_bye(&stream->rtcp, pkt+len,
515 &bye_len, NULL);
516 if (status != PJ_SUCCESS) {
517 PJ_PERROR(4,(stream->name.ptr, status,
518 "Error generating RTCP BYE"));
519 } else {
520 len += (int)bye_len;
521 }
522 }
523
524 /* Send! */
525 status = pjmedia_transport_send_rtcp(stream->transport, pkt, len);
526
527 return status;
528}
529
530
531/**
532 * check_tx_rtcp()
533 *
534 * This function is can be called by either put_frame() or get_frame(),
535 * to transmit periodic RTCP SR/RR report.
536 */
537static void check_tx_rtcp(pjmedia_vid_stream *stream, pj_uint32_t timestamp)
538{
539 /* Note that timestamp may represent local or remote timestamp,
540 * depending on whether this function is called from put_frame()
541 * or get_frame().
542 */
543
544
545 if (stream->rtcp_last_tx == 0) {
546
547 stream->rtcp_last_tx = timestamp;
548
549 } else if (timestamp - stream->rtcp_last_tx >= stream->rtcp_interval) {
550 pj_status_t status;
551
552 status = send_rtcp(stream, !stream->rtcp_sdes_bye_disabled, PJ_FALSE);
553 if (status != PJ_SUCCESS) {
554 PJ_PERROR(4,(stream->name.ptr, status,
555 "Error sending RTCP"));
556 }
557
558 stream->rtcp_last_tx = timestamp;
559 }
560}
561
562
563#if 0
564static void dump_bin(const char *buf, unsigned len)
565{
566 unsigned i;
567
568 PJ_LOG(3,(THIS_FILE, "begin dump"));
569 for (i=0; i<len; ++i) {
570 int j;
571 char bits[9];
572 unsigned val = buf[i] & 0xFF;
573
574 bits[8] = '\0';
575 for (j=0; j<8; ++j) {
576 if (val & (1 << (7-j)))
577 bits[j] = '1';
578 else
579 bits[j] = '0';
580 }
581
582 PJ_LOG(3,(THIS_FILE, "%2d %s [%d]", i, bits, val));
583 }
584 PJ_LOG(3,(THIS_FILE, "end dump"));
585}
586#endif
587
588
589/*
590 * This callback is called by stream transport on receipt of packets
591 * in the RTP socket.
592 */
593static void on_rx_rtp( void *data,
594 void *pkt,
595 pj_ssize_t bytes_read)
596
597{
598 pjmedia_vid_stream *stream = (pjmedia_vid_stream*) data;
599 pjmedia_vid_channel *channel = stream->dec;
600 const pjmedia_rtp_hdr *hdr;
601 const void *payload;
602 unsigned payloadlen;
603 pjmedia_rtp_status seq_st;
604 pj_status_t status;
605 pj_bool_t pkt_discarded = PJ_FALSE;
606
607 /* Check for errors */
608 if (bytes_read < 0) {
609 LOGERR_((channel->port.info.name.ptr, "RTP recv() error",
610 (pj_status_t)-bytes_read));
611 return;
612 }
613
614 /* Ignore keep-alive packets */
615 if (bytes_read < (pj_ssize_t) sizeof(pjmedia_rtp_hdr))
616 return;
617
618 /* Update RTP and RTCP session. */
619 status = pjmedia_rtp_decode_rtp(&channel->rtp, pkt, (int)bytes_read,
620 &hdr, &payload, &payloadlen);
621 if (status != PJ_SUCCESS) {
622 LOGERR_((channel->port.info.name.ptr, "RTP decode error", status));
623 stream->rtcp.stat.rx.discard++;
624 return;
625 }
626
627 /* Ignore the packet if decoder is paused */
628 if (channel->paused)
629 goto on_return;
630
631 /* Update RTP session (also checks if RTP session can accept
632 * the incoming packet.
633 */
634 pjmedia_rtp_session_update2(&channel->rtp, hdr, &seq_st, PJ_TRUE);
635 if (seq_st.status.value) {
636 TRC_ ((channel->port.info.name.ptr,
637 "RTP status: badpt=%d, badssrc=%d, dup=%d, "
638 "outorder=%d, probation=%d, restart=%d",
639 seq_st.status.flag.badpt,
640 seq_st.status.flag.badssrc,
641 seq_st.status.flag.dup,
642 seq_st.status.flag.outorder,
643 seq_st.status.flag.probation,
644 seq_st.status.flag.restart));
645
646 if (seq_st.status.flag.badpt) {
647 PJ_LOG(4,(channel->port.info.name.ptr,
648 "Bad RTP pt %d (expecting %d)",
649 hdr->pt, channel->rtp.out_pt));
650 }
651
652 if (seq_st.status.flag.badssrc) {
653 PJ_LOG(4,(channel->port.info.name.ptr,
654 "Changed RTP peer SSRC %d (previously %d)",
655 channel->rtp.peer_ssrc, stream->rtcp.peer_ssrc));
656 stream->rtcp.peer_ssrc = channel->rtp.peer_ssrc;
657 }
658
659
660 }
661
662 /* Skip bad RTP packet */
663 if (seq_st.status.flag.bad) {
664 pkt_discarded = PJ_TRUE;
665 goto on_return;
666 }
667
668 /* Ignore if payloadlen is zero */
669 if (payloadlen == 0) {
670 pkt_discarded = PJ_TRUE;
671 goto on_return;
672 }
673
674 pj_mutex_lock( stream->jb_mutex );
675
676 /* Quickly see if there may be a full picture in the jitter buffer, and
677 * decode them if so. More thorough check will be done in decode_frame().
678 */
679 if ((pj_ntohl(hdr->ts) != stream->dec_frame.timestamp.u32.lo) || hdr->m) {
680 if (PJMEDIA_VID_STREAM_SKIP_PACKETS_TO_REDUCE_LATENCY) {
681 /* Always decode whenever we have picture in jb and
682 * overwrite already decoded picture if necessary
683 */
684 pj_size_t old_size = stream->dec_frame.size;
685
686 stream->dec_frame.size = stream->dec_max_size;
687 if (decode_frame(stream, &stream->dec_frame) != PJ_SUCCESS) {
688 stream->dec_frame.size = old_size;
689 }
690 } else {
691 /* Only decode if we don't already have decoded one,
692 * unless the jb is full.
693 */
694 pj_bool_t can_decode = PJ_FALSE;
695
696 if (pjmedia_jbuf_is_full(stream->jb)) {
697 can_decode = PJ_TRUE;
698 }
699 else if (stream->dec_frame.size == 0) {
700 can_decode = PJ_TRUE;
701 }
702
703 if (can_decode) {
704 stream->dec_frame.size = stream->dec_max_size;
705 if (decode_frame(stream, &stream->dec_frame) != PJ_SUCCESS) {
706 stream->dec_frame.size = 0;
707 }
708 }
709 }
710 }
711
712 /* Put "good" packet to jitter buffer, or reset the jitter buffer
713 * when RTP session is restarted.
714 */
715 if (seq_st.status.flag.restart) {
716 status = pjmedia_jbuf_reset(stream->jb);
717 PJ_LOG(4,(channel->port.info.name.ptr, "Jitter buffer reset"));
718 } else {
719 /* Just put the payload into jitter buffer */
720 pjmedia_jbuf_put_frame3(stream->jb, payload, payloadlen, 0,
721 pj_ntohs(hdr->seq), pj_ntohl(hdr->ts), NULL);
722
723#if TRACE_JB
724 trace_jb_put(stream, hdr, payloadlen, count);
725#endif
726
727 }
728 pj_mutex_unlock( stream->jb_mutex );
729
730
731 /* Check if now is the time to transmit RTCP SR/RR report.
732 * We only do this when stream direction is "decoding only",
733 * because otherwise check_tx_rtcp() will be handled by put_frame()
734 */
735 if (stream->dir == PJMEDIA_DIR_DECODING) {
736 check_tx_rtcp(stream, pj_ntohl(hdr->ts));
737 }
738
739 if (status != 0) {
740 LOGERR_((channel->port.info.name.ptr, "Jitter buffer put() error",
741 status));
742 pkt_discarded = PJ_TRUE;
743 goto on_return;
744 }
745
746on_return:
747 /* Update RTCP session */
748 if (stream->rtcp.peer_ssrc == 0)
749 stream->rtcp.peer_ssrc = channel->rtp.peer_ssrc;
750
751 pjmedia_rtcp_rx_rtp2(&stream->rtcp, pj_ntohs(hdr->seq),
752 pj_ntohl(hdr->ts), payloadlen, pkt_discarded);
753
754 /* Send RTCP RR and SDES after we receive some RTP packets */
755 if (stream->rtcp.received >= 10 && !stream->initial_rr) {
756 status = send_rtcp(stream, !stream->rtcp_sdes_bye_disabled,
757 PJ_FALSE);
758 if (status != PJ_SUCCESS) {
759 PJ_PERROR(4,(stream->name.ptr, status,
760 "Error sending initial RTCP RR"));
761 } else {
762 stream->initial_rr = PJ_TRUE;
763 }
764 }
765}
766
767
768/*
769 * This callback is called by stream transport on receipt of packets
770 * in the RTCP socket.
771 */
772static void on_rx_rtcp( void *data,
773 void *pkt,
774 pj_ssize_t bytes_read)
775{
776 pjmedia_vid_stream *stream = (pjmedia_vid_stream*) data;
777
778 /* Check for errors */
779 if (bytes_read < 0) {
780 LOGERR_((stream->cname.ptr, "RTCP recv() error",
781 (pj_status_t)-bytes_read));
782 return;
783 }
784
785 pjmedia_rtcp_rx_rtcp(&stream->rtcp, pkt, bytes_read);
786}
787
788static pj_status_t put_frame(pjmedia_port *port,
789 pjmedia_frame *frame)
790{
791 pjmedia_vid_stream *stream = (pjmedia_vid_stream*) port->port_data.pdata;
792 pjmedia_vid_channel *channel = stream->enc;
793 pj_status_t status = 0;
794 pjmedia_frame frame_out;
795 unsigned rtp_ts_len;
796 void *rtphdr;
797 int rtphdrlen;
798 pj_bool_t has_more_data = PJ_FALSE;
799 pj_size_t total_sent = 0;
800 pjmedia_vid_encode_opt enc_opt;
801 unsigned pkt_cnt = 0;
802 pj_timestamp initial_time;
803
804#if defined(PJMEDIA_STREAM_ENABLE_KA) && PJMEDIA_STREAM_ENABLE_KA != 0
805 /* If the interval since last sending packet is greater than
806 * PJMEDIA_STREAM_KA_INTERVAL, send keep-alive packet.
807 */
808 if (stream->use_ka)
809 {
810 pj_uint32_t dtx_duration;
811
812 dtx_duration = pj_timestamp_diff32(&stream->last_frm_ts_sent,
813 &frame->timestamp);
814 /* Video stream keep-alive feature is currently disabled. */
815 /*
816 if (dtx_duration >
817 PJMEDIA_STREAM_KA_INTERVAL *
818 PJMEDIA_PIA_SRATE(&channel->port.info))
819 {
820 send_keep_alive_packet(stream);
821 stream->last_frm_ts_sent = frame->timestamp;
822 }
823 */
824 }
825#endif
826
827 /* Don't do anything if stream is paused */
828 if (channel->paused) {
829 return PJ_SUCCESS;
830 }
831
832 /* Get frame length in timestamp unit */
833 rtp_ts_len = stream->frame_ts_len;
834
835 /* Init frame_out buffer. */
836 frame_out.buf = ((char*)channel->buf) + sizeof(pjmedia_rtp_hdr);
837 frame_out.size = 0;
838
839 /* Init encoding option */
840 pj_bzero(&enc_opt, sizeof(enc_opt));
841 if (stream->force_keyframe) {
842 /* Force encoder to generate keyframe */
843 enc_opt.force_keyframe = PJ_TRUE;
844 stream->force_keyframe = PJ_FALSE;
845 TRC_((channel->port.info.name.ptr,
846 "Forcing encoder to generate keyframe"));
847 }
848
849 /* Encode! */
850 status = pjmedia_vid_codec_encode_begin(stream->codec, &enc_opt, frame,
851 channel->buf_size -
852 sizeof(pjmedia_rtp_hdr),
853 &frame_out,
854 &has_more_data);
855 if (status != PJ_SUCCESS) {
856 LOGERR_((channel->port.info.name.ptr,
857 "Codec encode_begin() error", status));
858
859 /* Update RTP timestamp */
860 pjmedia_rtp_encode_rtp(&channel->rtp, channel->pt, 1, 0,
861 rtp_ts_len, (const void**)&rtphdr,
862 &rtphdrlen);
863 return status;
864 }
865
866 pj_get_timestamp(&initial_time);
867
868 /* Loop while we have frame to send */
869 for (;;) {
870 status = pjmedia_rtp_encode_rtp(&channel->rtp,
871 channel->pt,
872 (has_more_data == PJ_FALSE ? 1 : 0),
873 (int)frame_out.size,
874 rtp_ts_len,
875 (const void**)&rtphdr,
876 &rtphdrlen);
877 if (status != PJ_SUCCESS) {
878 LOGERR_((channel->port.info.name.ptr,
879 "RTP encode_rtp() error", status));
880 return status;
881 }
882
883 // Copy RTP header to the beginning of packet
884 pj_memcpy(channel->buf, rtphdr, sizeof(pjmedia_rtp_hdr));
885
886 // Send the RTP packet to the transport.
887 status = pjmedia_transport_send_rtp(stream->transport,
888 (char*)channel->buf,
889 frame_out.size +
890 sizeof(pjmedia_rtp_hdr));
891 if (status != PJ_SUCCESS) {
892 enum { COUNT_TO_REPORT = 20 };
893 if (stream->send_err_cnt++ == 0) {
894 LOGERR_((channel->port.info.name.ptr,
895 "Transport send_rtp() error",
896 status));
897 }
898 if (stream->send_err_cnt > COUNT_TO_REPORT)
899 stream->send_err_cnt = 0;
900 /* Ignore this error */
901 }
902
903 pjmedia_rtcp_tx_rtp(&stream->rtcp, (unsigned)frame_out.size);
904 total_sent += frame_out.size;
905 pkt_cnt++;
906
907 if (!has_more_data)
908 break;
909
910 /* Next packets use same timestamp */
911 rtp_ts_len = 0;
912
913 frame_out.size = 0;
914
915 /* Encode more! */
916 status = pjmedia_vid_codec_encode_more(stream->codec,
917 channel->buf_size -
918 sizeof(pjmedia_rtp_hdr),
919 &frame_out,
920 &has_more_data);
921 if (status != PJ_SUCCESS) {
922 LOGERR_((channel->port.info.name.ptr,
923 "Codec encode_more() error", status));
924 /* Ignore this error (?) */
925 break;
926 }
927
928 /* Send rate control */
929 if (stream->info.rc_cfg.method==PJMEDIA_VID_STREAM_RC_SIMPLE_BLOCKING)
930 {
931 pj_timestamp now, next_send_ts, total_send_ts;
932
933 total_send_ts.u64 = total_sent * stream->ts_freq.u64 * 8 /
934 stream->info.rc_cfg.bandwidth;
935 next_send_ts = initial_time;
936 pj_add_timestamp(&next_send_ts, &total_send_ts);
937
938 pj_get_timestamp(&now);
939 if (pj_cmp_timestamp(&now, &next_send_ts) < 0) {
940 unsigned ms_sleep;
941 ms_sleep = pj_elapsed_msec(&now, &next_send_ts);
942
943 if (ms_sleep > 10)
944 ms_sleep = 10;
945
946 pj_thread_sleep(ms_sleep);
947 }
948 }
949 }
950
951#if TRACE_RC
952 /* Trace log for rate control */
953 {
954 pj_timestamp end_time;
955 unsigned total_sleep;
956
957 pj_get_timestamp(&end_time);
958 total_sleep = pj_elapsed_msec(&initial_time, &end_time);
959 PJ_LOG(5, (stream->name.ptr, "total pkt=%d size=%d sleep=%d",
960 pkt_cnt, total_sent, total_sleep));
961
962 if (stream->tx_start.u64 == 0)
963 stream->tx_start = initial_time;
964 stream->tx_end = end_time;
965 stream->rc_total_pkt += pkt_cnt;
966 stream->rc_total_sleep += total_sleep;
967 stream->rc_total_img++;
968 }
969#endif
970
971 /* Check if now is the time to transmit RTCP SR/RR report.
972 * We only do this when stream direction is not "decoding only", because
973 * when it is, check_tx_rtcp() will be handled by get_frame().
974 */
975 if (stream->dir != PJMEDIA_DIR_DECODING) {
976 check_tx_rtcp(stream, pj_ntohl(channel->rtp.out_hdr.ts));
977 }
978
979 /* Do nothing if we have nothing to transmit */
980 if (total_sent == 0) {
981 return PJ_SUCCESS;
982 }
983
984 /* Update stat */
985 stream->rtcp.stat.rtp_tx_last_ts = pj_ntohl(stream->enc->rtp.out_hdr.ts);
986 stream->rtcp.stat.rtp_tx_last_seq = pj_ntohs(stream->enc->rtp.out_hdr.seq);
987
988#if defined(PJMEDIA_STREAM_ENABLE_KA) && PJMEDIA_STREAM_ENABLE_KA!=0
989 /* Update timestamp of last sending packet. */
990 stream->last_frm_ts_sent = frame->timestamp;
991#endif
992
993 return PJ_SUCCESS;
994}
995
996/* Decode one image from jitter buffer */
997static pj_status_t decode_frame(pjmedia_vid_stream *stream,
998 pjmedia_frame *frame)
999{
1000 pjmedia_vid_channel *channel = stream->dec;
1001 pj_uint32_t last_ts = 0;
1002 int frm_first_seq = 0, frm_last_seq = 0;
1003 pj_bool_t got_frame = PJ_FALSE;
1004 unsigned cnt;
1005 pj_status_t status;
1006
1007 /* Repeat get payload from the jitter buffer until all payloads with same
1008 * timestamp are collected.
1009 */
1010
1011 /* Check if we got a decodable frame */
1012 for (cnt=0; ; ++cnt) {
1013 char ptype;
1014 pj_uint32_t ts;
1015 int seq;
1016
1017 /* Peek frame from jitter buffer. */
1018 pjmedia_jbuf_peek_frame(stream->jb, cnt, NULL, NULL,
1019 &ptype, NULL, &ts, &seq);
1020 if (ptype == PJMEDIA_JB_NORMAL_FRAME) {
1021 if (last_ts == 0) {
1022 last_ts = ts;
1023 frm_first_seq = seq;
1024 }
1025 if (ts != last_ts) {
1026 got_frame = PJ_TRUE;
1027 break;
1028 }
1029 frm_last_seq = seq;
1030 } else if (ptype == PJMEDIA_JB_ZERO_EMPTY_FRAME) {
1031 /* No more packet in the jitter buffer */
1032 break;
1033 }
1034 }
1035
1036 if (got_frame) {
1037 unsigned i;
1038
1039 /* Generate frame bitstream from the payload */
1040 if (cnt > stream->rx_frame_cnt) {
1041 PJ_LOG(1,(channel->port.info.name.ptr,
1042 "Discarding %u frames because array is full!",
1043 cnt - stream->rx_frame_cnt));
1044 pjmedia_jbuf_remove_frame(stream->jb, cnt - stream->rx_frame_cnt);
1045 cnt = stream->rx_frame_cnt;
1046 }
1047
1048 for (i = 0; i < cnt; ++i) {
1049 char ptype;
1050
1051 stream->rx_frames[i].type = PJMEDIA_FRAME_TYPE_VIDEO;
1052 stream->rx_frames[i].timestamp.u64 = last_ts;
1053 stream->rx_frames[i].bit_info = 0;
1054
1055 /* We use jbuf_peek_frame() as it will returns the pointer of
1056 * the payload (no buffer and memcpy needed), just as we need.
1057 */
1058 pjmedia_jbuf_peek_frame(stream->jb, i,
1059 (const void**)&stream->rx_frames[i].buf,
1060 &stream->rx_frames[i].size, &ptype,
1061 NULL, NULL, NULL);
1062
1063 if (ptype != PJMEDIA_JB_NORMAL_FRAME) {
1064 /* Packet lost, must set payload to NULL and keep going */
1065 stream->rx_frames[i].buf = NULL;
1066 stream->rx_frames[i].size = 0;
1067 stream->rx_frames[i].type = PJMEDIA_FRAME_TYPE_NONE;
1068 continue;
1069 }
1070 }
1071
1072 /* Decode */
1073 status = pjmedia_vid_codec_decode(stream->codec, cnt,
1074 stream->rx_frames,
1075 (unsigned)frame->size, frame);
1076 if (status != PJ_SUCCESS) {
1077 LOGERR_((channel->port.info.name.ptr, "codec decode() error",
1078 status));
1079 frame->type = PJMEDIA_FRAME_TYPE_NONE;
1080 frame->size = 0;
1081 }
1082
1083 pjmedia_jbuf_remove_frame(stream->jb, cnt);
1084 }
1085
1086 /* Learn remote frame rate after successful decoding */
1087 if (frame->type == PJMEDIA_FRAME_TYPE_VIDEO && frame->size)
1088 {
1089 /* Only check remote frame rate when timestamp is not wrapping and
1090 * sequence is increased by 1.
1091 */
1092 if (last_ts > stream->last_dec_ts &&
1093 frm_first_seq - stream->last_dec_seq == 1)
1094 {
1095 pj_uint32_t ts_diff;
1096 pjmedia_video_format_detail *vfd;
1097
1098 ts_diff = last_ts - stream->last_dec_ts;
1099 vfd = pjmedia_format_get_video_format_detail(
1100 &channel->port.info.fmt, PJ_TRUE);
1101 if (stream->info.codec_info.clock_rate * vfd->fps.denum !=
1102 vfd->fps.num * ts_diff)
1103 {
1104 /* Frame rate changed, update decoding port info */
1105 if (stream->info.codec_info.clock_rate % ts_diff == 0) {
1106 vfd->fps.num = stream->info.codec_info.clock_rate/ts_diff;
1107 vfd->fps.denum = 1;
1108 } else {
1109 vfd->fps.num = stream->info.codec_info.clock_rate;
1110 vfd->fps.denum = ts_diff;
1111 }
1112
1113 /* Update stream info */
1114 stream->info.codec_param->dec_fmt.det.vid.fps = vfd->fps;
1115
1116 /* Publish PJMEDIA_EVENT_FMT_CHANGED event if frame rate
1117 * increased and not exceeding 100fps.
1118 */
1119 if (vfd->fps.num/vfd->fps.denum <= 100 &&
1120 vfd->fps.num * stream->dec_max_fps.denum >
1121 stream->dec_max_fps.num * vfd->fps.denum)
1122 {
1123 pjmedia_event *event = &stream->fmt_event;
1124
1125 /* Update max fps of decoding dir */
1126 stream->dec_max_fps = vfd->fps;
1127
1128 /* Use the buffered format changed event:
1129 * - just update the framerate if there is pending event,
1130 * - otherwise, init the whole event.
1131 */
1132 if (stream->fmt_event.type != PJMEDIA_EVENT_NONE) {
1133 event->data.fmt_changed.new_fmt.det.vid.fps = vfd->fps;
1134 } else {
1135 pjmedia_event_init(event, PJMEDIA_EVENT_FMT_CHANGED,
1136 &frame->timestamp, stream);
1137 event->data.fmt_changed.dir = PJMEDIA_DIR_DECODING;
1138 pj_memcpy(&event->data.fmt_changed.new_fmt,
1139 &stream->info.codec_param->dec_fmt,
1140 sizeof(pjmedia_format));
1141 }
1142 }
1143 }
1144 }
1145
1146 /* Update last frame seq and timestamp */
1147 stream->last_dec_seq = frm_last_seq;
1148 stream->last_dec_ts = last_ts;
1149 }
1150
1151 return got_frame ? PJ_SUCCESS : PJ_ENOTFOUND;
1152}
1153
1154
1155static pj_status_t get_frame(pjmedia_port *port,
1156 pjmedia_frame *frame)
1157{
1158 pjmedia_vid_stream *stream = (pjmedia_vid_stream*) port->port_data.pdata;
1159 pjmedia_vid_channel *channel = stream->dec;
1160
1161 /* Return no frame is channel is paused */
1162 if (channel->paused) {
1163 frame->type = PJMEDIA_FRAME_TYPE_NONE;
1164 frame->size = 0;
1165 return PJ_SUCCESS;
1166 }
1167
1168 /* Report pending events. Do not publish the event while holding the
1169 * jb_mutex as that would lead to deadlock. It should be safe to
1170 * operate on fmt_event without the mutex because format change normally
1171 * would only occur once during the start of the media.
1172 */
1173 if (stream->fmt_event.type != PJMEDIA_EVENT_NONE) {
1174 pjmedia_event_fmt_changed_data *fmt_chg_data;
1175
1176 fmt_chg_data = &stream->fmt_event.data.fmt_changed;
1177
1178 /* Update stream info and decoding channel port info */
1179 if (fmt_chg_data->dir == PJMEDIA_DIR_DECODING) {
1180 pjmedia_format_copy(&stream->info.codec_param->dec_fmt,
1181 &fmt_chg_data->new_fmt);
1182 pjmedia_format_copy(&stream->dec->port.info.fmt,
1183 &fmt_chg_data->new_fmt);
1184
1185 /* Override the framerate to be 1.5x higher in the event
1186 * for the renderer.
1187 */
1188 fmt_chg_data->new_fmt.det.vid.fps.num *= 3;
1189 fmt_chg_data->new_fmt.det.vid.fps.num /= 2;
1190 } else {
1191 pjmedia_format_copy(&stream->info.codec_param->enc_fmt,
1192 &fmt_chg_data->new_fmt);
1193 pjmedia_format_copy(&stream->enc->port.info.fmt,
1194 &fmt_chg_data->new_fmt);
1195 }
1196
1197 dump_port_info(fmt_chg_data->dir==PJMEDIA_DIR_DECODING ?
1198 stream->dec : stream->enc,
1199 "changed");
1200
1201 pjmedia_event_publish(NULL, port, &stream->fmt_event, 0);
1202
1203 stream->fmt_event.type = PJMEDIA_EVENT_NONE;
1204 }
1205
1206 if (stream->miss_keyframe_event.type != PJMEDIA_EVENT_NONE) {
1207 pjmedia_event_publish(NULL, port, &stream->miss_keyframe_event,
1208 PJMEDIA_EVENT_PUBLISH_POST_EVENT);
1209 stream->miss_keyframe_event.type = PJMEDIA_EVENT_NONE;
1210 }
1211
1212 pj_mutex_lock( stream->jb_mutex );
1213
1214 if (stream->dec_frame.size == 0) {
1215 /* Don't have frame in buffer, try to decode one */
1216 if (decode_frame(stream, frame) != PJ_SUCCESS) {
1217 frame->type = PJMEDIA_FRAME_TYPE_NONE;
1218 frame->size = 0;
1219 }
1220 } else {
1221 if (frame->size < stream->dec_frame.size) {
1222 PJ_LOG(4,(stream->dec->port.info.name.ptr,
1223 "Error: not enough buffer for decoded frame "
1224 "(supplied=%d, required=%d)",
1225 (int)frame->size, (int)stream->dec_frame.size));
1226 frame->type = PJMEDIA_FRAME_TYPE_NONE;
1227 frame->size = 0;
1228 } else {
1229 frame->type = stream->dec_frame.type;
1230 frame->timestamp = stream->dec_frame.timestamp;
1231 frame->size = stream->dec_frame.size;
1232 pj_memcpy(frame->buf, stream->dec_frame.buf, frame->size);
1233 }
1234
1235 stream->dec_frame.size = 0;
1236 }
1237
1238 pj_mutex_unlock( stream->jb_mutex );
1239
1240 return PJ_SUCCESS;
1241}
1242
1243/*
1244 * Create media channel.
1245 */
1246static pj_status_t create_channel( pj_pool_t *pool,
1247 pjmedia_vid_stream *stream,
1248 pjmedia_dir dir,
1249 unsigned pt,
1250 const pjmedia_vid_stream_info *info,
1251 pjmedia_vid_channel **p_channel)
1252{
1253 enum { M = 32 };
1254 pjmedia_vid_channel *channel;
1255 pj_status_t status;
1256 unsigned min_out_pkt_size;
1257 pj_str_t name;
1258 const char *type_name;
1259 pjmedia_format *fmt;
1260 char fourcc_name[5];
1261 pjmedia_port_info *pi;
1262
1263 pj_assert(info->type == PJMEDIA_TYPE_VIDEO);
1264 pj_assert(dir == PJMEDIA_DIR_DECODING || dir == PJMEDIA_DIR_ENCODING);
1265
1266 /* Allocate memory for channel descriptor */
1267 channel = PJ_POOL_ZALLOC_T(pool, pjmedia_vid_channel);
1268 PJ_ASSERT_RETURN(channel != NULL, PJ_ENOMEM);
1269
1270 /* Init vars */
1271 if (dir==PJMEDIA_DIR_DECODING) {
1272 type_name = "vstdec";
1273 fmt = &info->codec_param->dec_fmt;
1274 } else {
1275 type_name = "vstenc";
1276 fmt = &info->codec_param->enc_fmt;
1277 }
1278 name.ptr = (char*) pj_pool_alloc(pool, M);
1279 name.slen = pj_ansi_snprintf(name.ptr, M, "%s%p", type_name, stream);
1280 pi = &channel->port.info;
1281
1282 /* Init channel info. */
1283 channel->stream = stream;
1284 channel->dir = dir;
1285 channel->paused = 1;
1286 channel->pt = pt;
1287
1288 /* Allocate buffer for outgoing packet. */
1289 if (dir == PJMEDIA_DIR_ENCODING) {
1290 channel->buf_size = sizeof(pjmedia_rtp_hdr) + stream->frame_size;
1291
1292 /* It should big enough to hold (minimally) RTCP SR with an SDES. */
1293 min_out_pkt_size = sizeof(pjmedia_rtcp_sr_pkt) +
1294 sizeof(pjmedia_rtcp_common) +
1295 (4 + (unsigned)stream->cname.slen) +
1296 32;
1297
1298 if (channel->buf_size < min_out_pkt_size)
1299 channel->buf_size = min_out_pkt_size;
1300
1301 channel->buf = pj_pool_alloc(pool, channel->buf_size);
1302 PJ_ASSERT_RETURN(channel->buf != NULL, PJ_ENOMEM);
1303 }
1304
1305 /* Create RTP and RTCP sessions: */
1306 if (info->rtp_seq_ts_set == 0) {
1307 status = pjmedia_rtp_session_init(&channel->rtp, pt, info->ssrc);
1308 } else {
1309 pjmedia_rtp_session_setting settings;
1310
1311 settings.flags = (pj_uint8_t)((info->rtp_seq_ts_set << 2) | 3);
1312 settings.default_pt = pt;
1313 settings.sender_ssrc = info->ssrc;
1314 settings.seq = info->rtp_seq;
1315 settings.ts = info->rtp_ts;
1316 status = pjmedia_rtp_session_init2(&channel->rtp, settings);
1317 }
1318 if (status != PJ_SUCCESS)
1319 return status;
1320
1321 /* Init port. */
1322 pjmedia_port_info_init2(pi, &name, SIGNATURE, dir, fmt);
1323 if (dir == PJMEDIA_DIR_DECODING) {
1324 channel->port.get_frame = &get_frame;
1325 } else {
1326 pi->fmt.id = info->codec_param->dec_fmt.id;
1327 channel->port.put_frame = &put_frame;
1328 }
1329
1330 /* Init port. */
1331 channel->port.port_data.pdata = stream;
1332
1333 PJ_LOG(5, (name.ptr,
1334 "%s channel created %dx%d %s%s%.*s %d/%d(~%d)fps",
1335 (dir==PJMEDIA_DIR_ENCODING?"Encoding":"Decoding"),
1336 pi->fmt.det.vid.size.w, pi->fmt.det.vid.size.h,
1337 pjmedia_fourcc_name(pi->fmt.id, fourcc_name),
1338 (dir==PJMEDIA_DIR_ENCODING?"->":"<-"),
1339 info->codec_info.encoding_name.slen,
1340 info->codec_info.encoding_name.ptr,
1341 pi->fmt.det.vid.fps.num, pi->fmt.det.vid.fps.denum,
1342 pi->fmt.det.vid.fps.num/pi->fmt.det.vid.fps.denum));
1343
1344 /* Done. */
1345 *p_channel = channel;
1346 return PJ_SUCCESS;
1347}
1348
1349
1350/*
1351 * Create stream.
1352 */
1353PJ_DEF(pj_status_t) pjmedia_vid_stream_create(
1354 pjmedia_endpt *endpt,
1355 pj_pool_t *pool,
1356 pjmedia_vid_stream_info *info,
1357 pjmedia_transport *tp,
1358 void *user_data,
1359 pjmedia_vid_stream **p_stream)
1360{
1361 enum { M = 32 };
1362 pj_pool_t *own_pool = NULL;
1363 pjmedia_vid_stream *stream;
1364 unsigned jb_init, jb_max, jb_min_pre, jb_max_pre;
1365 int frm_ptime, chunks_per_frm;
1366 pjmedia_video_format_detail *vfd_enc, *vfd_dec;
1367 char *p;
1368 pj_status_t status;
1369
1370 if (!pool) {
1371 own_pool = pjmedia_endpt_create_pool( endpt, "vstrm%p",
1372 PJMEDIA_VSTREAM_SIZE,
1373 PJMEDIA_VSTREAM_INC);
1374 PJ_ASSERT_RETURN(own_pool != NULL, PJ_ENOMEM);
1375 pool = own_pool;
1376 }
1377
1378 /* Allocate stream */
1379 stream = PJ_POOL_ZALLOC_T(pool, pjmedia_vid_stream);
1380 PJ_ASSERT_RETURN(stream != NULL, PJ_ENOMEM);
1381 stream->own_pool = own_pool;
1382
1383 /* Get codec manager */
1384 stream->codec_mgr = pjmedia_vid_codec_mgr_instance();
1385 PJ_ASSERT_RETURN(stream->codec_mgr, PJMEDIA_CODEC_EFAILED);
1386
1387 /* Init stream/port name */
1388 stream->name.ptr = (char*) pj_pool_alloc(pool, M);
1389 stream->name.slen = pj_ansi_snprintf(stream->name.ptr, M,
1390 "vstrm%p", stream);
1391
1392 /* Create and initialize codec: */
1393 status = pjmedia_vid_codec_mgr_alloc_codec(stream->codec_mgr,
1394 &info->codec_info,
1395 &stream->codec);
1396 if (status != PJ_SUCCESS)
1397 return status;
1398
1399 /* Get codec param: */
1400 if (!info->codec_param) {
1401 pjmedia_vid_codec_param def_param;
1402
1403 status = pjmedia_vid_codec_mgr_get_default_param(stream->codec_mgr,
1404 &info->codec_info,
1405 &def_param);
1406 if (status != PJ_SUCCESS)
1407 return status;
1408
1409 info->codec_param = pjmedia_vid_codec_param_clone(pool, &def_param);
1410 pj_assert(info->codec_param);
1411 }
1412
1413 /* Init codec param and adjust MTU */
1414 info->codec_param->dir = info->dir;
1415 info->codec_param->enc_mtu -= (sizeof(pjmedia_rtp_hdr) +
1416 PJMEDIA_STREAM_RESV_PAYLOAD_LEN);
1417 if (info->codec_param->enc_mtu > PJMEDIA_MAX_MTU)
1418 info->codec_param->enc_mtu = PJMEDIA_MAX_MTU;
1419
1420 /* Packet size estimation for decoding direction */
1421 vfd_enc = pjmedia_format_get_video_format_detail(
1422 &info->codec_param->enc_fmt, PJ_TRUE);
1423 vfd_dec = pjmedia_format_get_video_format_detail(
1424 &info->codec_param->dec_fmt, PJ_TRUE);
1425
1426 /* Init stream: */
1427 stream->endpt = endpt;
1428 stream->dir = info->dir;
1429 stream->user_data = user_data;
1430 stream->rtcp_interval = (PJMEDIA_RTCP_INTERVAL-500 + (pj_rand()%1000)) *
1431 info->codec_info.clock_rate / 1000;
1432 stream->rtcp_sdes_bye_disabled = info->rtcp_sdes_bye_disabled;
1433
1434 stream->jb_last_frm = PJMEDIA_JB_NORMAL_FRAME;
1435
1436#if defined(PJMEDIA_STREAM_ENABLE_KA) && PJMEDIA_STREAM_ENABLE_KA!=0
1437 stream->use_ka = info->use_ka;
1438#endif
1439
1440 /* Build random RTCP CNAME. CNAME has user@host format */
1441 stream->cname.ptr = p = (char*) pj_pool_alloc(pool, 20);
1442 pj_create_random_string(p, 5);
1443 p += 5;
1444 *p++ = '@'; *p++ = 'p'; *p++ = 'j';
1445 pj_create_random_string(p, 6);
1446 p += 6;
1447 *p++ = '.'; *p++ = 'o'; *p++ = 'r'; *p++ = 'g';
1448 stream->cname.slen = p - stream->cname.ptr;
1449
1450
1451 /* Create mutex to protect jitter buffer: */
1452
1453 status = pj_mutex_create_simple(pool, NULL, &stream->jb_mutex);
1454 if (status != PJ_SUCCESS)
1455 return status;
1456
1457 /* Init and open the codec. */
1458 status = pjmedia_vid_codec_init(stream->codec, pool);
1459 if (status != PJ_SUCCESS)
1460 return status;
1461 status = pjmedia_vid_codec_open(stream->codec, info->codec_param);
1462 if (status != PJ_SUCCESS)
1463 return status;
1464
1465 /* Subscribe to codec events */
1466 pjmedia_event_subscribe(NULL, &stream_event_cb, stream,
1467 stream->codec);
1468
1469 /* Estimate the maximum frame size */
1470 stream->frame_size = vfd_enc->size.w * vfd_enc->size.h * 4;
1471
1472#if 0
1473 stream->frame_size = vfd_enc->max_bps/8 * vfd_enc->fps.denum /
1474 vfd_enc->fps.num;
1475
1476 /* As the maximum frame_size is not represented directly by maximum bps
1477 * (which includes intra and predicted frames), let's increase the
1478 * frame size value for safety.
1479 */
1480 stream->frame_size <<= 4;
1481#endif
1482
1483 /* Validate the frame size */
1484 if (stream->frame_size == 0 ||
1485 stream->frame_size > PJMEDIA_MAX_VIDEO_ENC_FRAME_SIZE)
1486 {
1487 stream->frame_size = PJMEDIA_MAX_VIDEO_ENC_FRAME_SIZE;
1488 }
1489
1490 /* Get frame length in timestamp unit */
1491 stream->frame_ts_len = info->codec_info.clock_rate *
1492 vfd_enc->fps.denum / vfd_enc->fps.num;
1493
1494 /* Initialize send rate states */
1495 pj_get_timestamp_freq(&stream->ts_freq);
1496 if (info->rc_cfg.bandwidth == 0)
1497 info->rc_cfg.bandwidth = vfd_enc->max_bps;
1498
1499 /* For simple blocking, need to have bandwidth large enough, otherwise
1500 * we can slow down the transmission too much
1501 */
1502 if (info->rc_cfg.method==PJMEDIA_VID_STREAM_RC_SIMPLE_BLOCKING &&
1503 info->rc_cfg.bandwidth < vfd_enc->avg_bps * 3)
1504 {
1505 info->rc_cfg.bandwidth = vfd_enc->avg_bps * 3;
1506 }
1507
1508 /* Override the initial framerate in the decoding direction. This initial
1509 * value will be used by the renderer to configure its clock, and setting
1510 * it to a bit higher value can avoid the possibility of high latency
1511 * caused by clock drift (remote encoder clock runs slightly faster than
1512 * local renderer clock) or video setup lag. Note that the actual framerate
1513 * will be continuously calculated based on the incoming RTP timestamps.
1514 */
1515 vfd_dec->fps.num = vfd_dec->fps.num * 3 / 2;
1516 stream->dec_max_fps = vfd_dec->fps;
1517
1518 /* Create decoder channel */
1519 status = create_channel( pool, stream, PJMEDIA_DIR_DECODING,
1520 info->rx_pt, info, &stream->dec);
1521 if (status != PJ_SUCCESS)
1522 return status;
1523
1524 /* Create encoder channel */
1525 status = create_channel( pool, stream, PJMEDIA_DIR_ENCODING,
1526 info->tx_pt, info, &stream->enc);
1527 if (status != PJ_SUCCESS)
1528 return status;
1529
1530 /* Create temporary buffer for immediate decoding */
1531 stream->dec_max_size = vfd_dec->size.w * vfd_dec->size.h * 4;
1532 stream->dec_frame.buf = pj_pool_alloc(pool, stream->dec_max_size);
1533
1534 /* Init jitter buffer parameters: */
1535 frm_ptime = 1000 * vfd_enc->fps.denum / vfd_enc->fps.num;
1536 chunks_per_frm = stream->frame_size / PJMEDIA_MAX_MRU;
1537 if (chunks_per_frm < MIN_CHUNKS_PER_FRM)
1538 chunks_per_frm = MIN_CHUNKS_PER_FRM;
1539
1540 /* JB max count, default 500ms */
1541 if (info->jb_max >= frm_ptime)
1542 jb_max = info->jb_max * chunks_per_frm / frm_ptime;
1543 else
1544 jb_max = 500 * chunks_per_frm / frm_ptime;
1545
1546 /* JB min prefetch, default 1 frame */
1547 if (info->jb_min_pre >= frm_ptime)
1548 jb_min_pre = info->jb_min_pre * chunks_per_frm / frm_ptime;
1549 else
1550 jb_min_pre = 1;
1551
1552 /* JB max prefetch, default 4/5 JB max count */
1553 if (info->jb_max_pre >= frm_ptime)
1554 jb_max_pre = info->jb_max_pre * chunks_per_frm / frm_ptime;
1555 else
1556 jb_max_pre = jb_max * 4 / 5;
1557
1558 /* JB init prefetch, default 0 */
1559 if (info->jb_init >= frm_ptime)
1560 jb_init = info->jb_init * chunks_per_frm / frm_ptime;
1561 else
1562 jb_init = 0;
1563
1564 /* Allocate array for temporary storage for assembly of incoming
1565 * frames. Add more just in case.
1566 */
1567 stream->rx_frame_cnt = chunks_per_frm * 2;
1568 stream->rx_frames = pj_pool_calloc(pool, stream->rx_frame_cnt,
1569 sizeof(stream->rx_frames[0]));
1570
1571 /* Create jitter buffer */
1572 status = pjmedia_jbuf_create(pool, &stream->dec->port.info.name,
1573 PJMEDIA_MAX_MRU,
1574 1000 * vfd_enc->fps.denum / vfd_enc->fps.num,
1575 jb_max, &stream->jb);
1576 if (status != PJ_SUCCESS)
1577 return status;
1578
1579
1580 /* Set up jitter buffer */
1581 pjmedia_jbuf_set_adaptive(stream->jb, jb_init, jb_min_pre, jb_max_pre);
1582 pjmedia_jbuf_set_discard(stream->jb, PJMEDIA_JB_DISCARD_NONE);
1583
1584 /* Init RTCP session: */
1585 {
1586 pjmedia_rtcp_session_setting rtcp_setting;
1587
1588 pjmedia_rtcp_session_setting_default(&rtcp_setting);
1589 rtcp_setting.name = stream->name.ptr;
1590 rtcp_setting.ssrc = info->ssrc;
1591 rtcp_setting.rtp_ts_base = pj_ntohl(stream->enc->rtp.out_hdr.ts);
1592 rtcp_setting.clock_rate = info->codec_info.clock_rate;
1593 rtcp_setting.samples_per_frame = 1;
1594
1595 pjmedia_rtcp_init2(&stream->rtcp, &rtcp_setting);
1596 }
1597
1598 /* Allocate outgoing RTCP buffer, should be enough to hold SR/RR, SDES,
1599 * BYE, and XR.
1600 */
1601 stream->out_rtcp_pkt_size = sizeof(pjmedia_rtcp_sr_pkt) +
1602 sizeof(pjmedia_rtcp_common) +
1603 (4 + (unsigned)stream->cname.slen) +
1604 32;
1605 if (stream->out_rtcp_pkt_size > PJMEDIA_MAX_MTU)
1606 stream->out_rtcp_pkt_size = PJMEDIA_MAX_MTU;
1607
1608 stream->out_rtcp_pkt = pj_pool_alloc(pool, stream->out_rtcp_pkt_size);
1609
1610 /* Only attach transport when stream is ready. */
1611 status = pjmedia_transport_attach(tp, stream, &info->rem_addr,
1612 &info->rem_rtcp,
1613 pj_sockaddr_get_len(&info->rem_addr),
1614 &on_rx_rtp, &on_rx_rtcp);
1615 if (status != PJ_SUCCESS)
1616 return status;
1617
1618 stream->transport = tp;
1619
1620 /* Send RTCP SDES */
1621 if (!stream->rtcp_sdes_bye_disabled) {
1622 pjmedia_vid_stream_send_rtcp_sdes(stream);
1623 }
1624
1625#if defined(PJMEDIA_STREAM_ENABLE_KA) && PJMEDIA_STREAM_ENABLE_KA!=0
1626 /* NAT hole punching by sending KA packet via RTP transport. */
1627 if (stream->use_ka)
1628 send_keep_alive_packet(stream);
1629#endif
1630
1631#if TRACE_JB
1632 {
1633 char trace_name[PJ_MAXPATH];
1634 pj_ssize_t len;
1635
1636 pj_ansi_snprintf(trace_name, sizeof(trace_name),
1637 TRACE_JB_PATH_PREFIX "%s.csv",
1638 channel->port.info.name.ptr);
1639 status = pj_file_open(pool, trace_name, PJ_O_RDWR,
1640 &stream->trace_jb_fd);
1641 if (status != PJ_SUCCESS) {
1642 stream->trace_jb_fd = TRACE_JB_INVALID_FD;
1643 PJ_LOG(3,(THIS_FILE, "Failed creating RTP trace file '%s'",
1644 trace_name));
1645 } else {
1646 stream->trace_jb_buf = (char*)pj_pool_alloc(pool, PJ_LOG_MAX_SIZE);
1647
1648 /* Print column header */
1649 len = pj_ansi_snprintf(stream->trace_jb_buf, PJ_LOG_MAX_SIZE,
1650 "Time, Operation, Size, Frame Count, "
1651 "Frame type, RTP Seq, RTP TS, RTP M, "
1652 "JB size, JB burst level, JB prefetch\n");
1653 pj_file_write(stream->trace_jb_fd, stream->trace_jb_buf, &len);
1654 pj_file_flush(stream->trace_jb_fd);
1655 }
1656 }
1657#endif
1658
1659 /* Save the stream info */
1660 pj_memcpy(&stream->info, info, sizeof(*info));
1661 stream->info.codec_param = pjmedia_vid_codec_param_clone(
1662 pool, info->codec_param);
1663
1664 /* Success! */
1665 *p_stream = stream;
1666
1667 PJ_LOG(5,(THIS_FILE, "Video stream %s created", stream->name.ptr));
1668
1669 return PJ_SUCCESS;
1670}
1671
1672
1673/*
1674 * Destroy stream.
1675 */
1676PJ_DEF(pj_status_t) pjmedia_vid_stream_destroy( pjmedia_vid_stream *stream )
1677{
1678 PJ_ASSERT_RETURN(stream != NULL, PJ_EINVAL);
1679
1680#if TRACE_RC
1681 {
1682 unsigned total_time;
1683
1684 total_time = pj_elapsed_msec(&stream->tx_start, &stream->tx_end);
1685 PJ_LOG(5, (stream->name.ptr,
1686 "RC stat: pkt_cnt=%.2f/image, sleep=%.2fms/s, fps=%.2f",
1687 stream->rc_total_pkt*1.0/stream->rc_total_img,
1688 stream->rc_total_sleep*1000.0/total_time,
1689 stream->rc_total_img*1000.0/total_time));
1690 }
1691#endif
1692
1693 /* Send RTCP BYE (also SDES) */
1694 if (!stream->rtcp_sdes_bye_disabled) {
1695 send_rtcp(stream, PJ_TRUE, PJ_TRUE);
1696 }
1697
1698 /* Detach from transport
1699 * MUST NOT hold stream mutex while detaching from transport, as
1700 * it may cause deadlock. See ticket #460 for the details.
1701 */
1702 if (stream->transport) {
1703 pjmedia_transport_detach(stream->transport, stream);
1704 stream->transport = NULL;
1705 }
1706
1707 /* This function may be called when stream is partly initialized. */
1708 if (stream->jb_mutex)
1709 pj_mutex_lock(stream->jb_mutex);
1710
1711
1712 /* Free codec. */
1713 if (stream->codec) {
1714 pjmedia_event_unsubscribe(NULL, &stream_event_cb, stream,
1715 stream->codec);
1716 pjmedia_vid_codec_close(stream->codec);
1717 pjmedia_vid_codec_mgr_dealloc_codec(stream->codec_mgr, stream->codec);
1718 stream->codec = NULL;
1719 }
1720
1721 /* Free mutex */
1722
1723 if (stream->jb_mutex) {
1724 pj_mutex_destroy(stream->jb_mutex);
1725 stream->jb_mutex = NULL;
1726 }
1727
1728 /* Destroy jitter buffer */
1729 if (stream->jb) {
1730 pjmedia_jbuf_destroy(stream->jb);
1731 stream->jb = NULL;
1732 }
1733
1734#if TRACE_JB
1735 if (TRACE_JB_OPENED(stream)) {
1736 pj_file_close(stream->trace_jb_fd);
1737 stream->trace_jb_fd = TRACE_JB_INVALID_FD;
1738 }
1739#endif
1740
1741 if (stream->own_pool) {
1742 pj_pool_t *pool = stream->own_pool;
1743 stream->own_pool = NULL;
1744 pj_pool_release(pool);
1745 }
1746
1747 return PJ_SUCCESS;
1748}
1749
1750
1751/*
1752 * Get the port interface.
1753 */
1754PJ_DEF(pj_status_t) pjmedia_vid_stream_get_port(pjmedia_vid_stream *stream,
1755 pjmedia_dir dir,
1756 pjmedia_port **p_port )
1757{
1758 PJ_ASSERT_RETURN(dir==PJMEDIA_DIR_ENCODING || dir==PJMEDIA_DIR_DECODING,
1759 PJ_EINVAL);
1760
1761 if (dir == PJMEDIA_DIR_ENCODING)
1762 *p_port = &stream->enc->port;
1763 else
1764 *p_port = &stream->dec->port;
1765
1766 return PJ_SUCCESS;
1767}
1768
1769
1770/*
1771 * Get the transport object
1772 */
1773PJ_DEF(pjmedia_transport*) pjmedia_vid_stream_get_transport(
1774 pjmedia_vid_stream *st)
1775{
1776 return st->transport;
1777}
1778
1779
1780/*
1781 * Get stream statistics.
1782 */
1783PJ_DEF(pj_status_t) pjmedia_vid_stream_get_stat(
1784 const pjmedia_vid_stream *stream,
1785 pjmedia_rtcp_stat *stat)
1786{
1787 PJ_ASSERT_RETURN(stream && stat, PJ_EINVAL);
1788
1789 pj_memcpy(stat, &stream->rtcp.stat, sizeof(pjmedia_rtcp_stat));
1790 return PJ_SUCCESS;
1791}
1792
1793
1794/*
1795 * Reset the stream statistics in the middle of a stream session.
1796 */
1797PJ_DEF(pj_status_t) pjmedia_vid_stream_reset_stat(pjmedia_vid_stream *stream)
1798{
1799 PJ_ASSERT_RETURN(stream, PJ_EINVAL);
1800
1801 pjmedia_rtcp_init_stat(&stream->rtcp.stat);
1802
1803 return PJ_SUCCESS;
1804}
1805
1806
1807/*
1808 * Get jitter buffer state.
1809 */
1810PJ_DEF(pj_status_t) pjmedia_vid_stream_get_stat_jbuf(
1811 const pjmedia_vid_stream *stream,
1812 pjmedia_jb_state *state)
1813{
1814 PJ_ASSERT_RETURN(stream && state, PJ_EINVAL);
1815 return pjmedia_jbuf_get_state(stream->jb, state);
1816}
1817
1818
1819/*
1820 * Get the stream info.
1821 */
1822PJ_DEF(pj_status_t) pjmedia_vid_stream_get_info(
1823 const pjmedia_vid_stream *stream,
1824 pjmedia_vid_stream_info *info)
1825{
1826 PJ_ASSERT_RETURN(stream && info, PJ_EINVAL);
1827 pj_memcpy(info, &stream->info, sizeof(*info));
1828 return PJ_SUCCESS;
1829}
1830
1831
1832/*
1833 * Start stream.
1834 */
1835PJ_DEF(pj_status_t) pjmedia_vid_stream_start(pjmedia_vid_stream *stream)
1836{
1837
1838 PJ_ASSERT_RETURN(stream && stream->enc && stream->dec, PJ_EINVALIDOP);
1839
1840 if (stream->enc && (stream->dir & PJMEDIA_DIR_ENCODING)) {
1841 stream->enc->paused = 0;
1842 //pjmedia_snd_stream_start(stream->enc->snd_stream);
1843 PJ_LOG(4,(stream->enc->port.info.name.ptr, "Encoder stream started"));
1844 } else {
1845 PJ_LOG(4,(stream->enc->port.info.name.ptr, "Encoder stream paused"));
1846 }
1847
1848 if (stream->dec && (stream->dir & PJMEDIA_DIR_DECODING)) {
1849 stream->dec->paused = 0;
1850 //pjmedia_snd_stream_start(stream->dec->snd_stream);
1851 PJ_LOG(4,(stream->dec->port.info.name.ptr, "Decoder stream started"));
1852 } else {
1853 PJ_LOG(4,(stream->dec->port.info.name.ptr, "Decoder stream paused"));
1854 }
1855
1856 return PJ_SUCCESS;
1857}
1858
1859
1860/*
1861 * Check status.
1862 */
1863PJ_DEF(pj_bool_t) pjmedia_vid_stream_is_running(pjmedia_vid_stream *stream,
1864 pjmedia_dir dir)
1865{
1866 pj_bool_t is_running = PJ_TRUE;
1867
1868 PJ_ASSERT_RETURN(stream, PJ_FALSE);
1869
1870 if (dir & PJMEDIA_DIR_ENCODING) {
1871 is_running &= (stream->enc && !stream->enc->paused);
1872 }
1873
1874 if (dir & PJMEDIA_DIR_DECODING) {
1875 is_running &= (stream->dec && !stream->dec->paused);
1876 }
1877
1878 return is_running;
1879}
1880
1881/*
1882 * Pause stream.
1883 */
1884PJ_DEF(pj_status_t) pjmedia_vid_stream_pause(pjmedia_vid_stream *stream,
1885 pjmedia_dir dir)
1886{
1887 PJ_ASSERT_RETURN(stream, PJ_EINVAL);
1888
1889 if ((dir & PJMEDIA_DIR_ENCODING) && stream->enc) {
1890 stream->enc->paused = 1;
1891 PJ_LOG(4,(stream->enc->port.info.name.ptr, "Encoder stream paused"));
1892 }
1893
1894 if ((dir & PJMEDIA_DIR_DECODING) && stream->dec) {
1895 stream->dec->paused = 1;
1896
1897 /* Also reset jitter buffer */
1898 pj_mutex_lock( stream->jb_mutex );
1899 pjmedia_jbuf_reset(stream->jb);
1900 pj_mutex_unlock( stream->jb_mutex );
1901
1902 PJ_LOG(4,(stream->dec->port.info.name.ptr, "Decoder stream paused"));
1903 }
1904
1905 return PJ_SUCCESS;
1906}
1907
1908
1909/*
1910 * Resume stream
1911 */
1912PJ_DEF(pj_status_t) pjmedia_vid_stream_resume(pjmedia_vid_stream *stream,
1913 pjmedia_dir dir)
1914{
1915 PJ_ASSERT_RETURN(stream, PJ_EINVAL);
1916
1917 if ((dir & PJMEDIA_DIR_ENCODING) && stream->enc) {
1918 stream->enc->paused = 0;
1919 PJ_LOG(4,(stream->enc->port.info.name.ptr, "Encoder stream resumed"));
1920 }
1921
1922 if ((dir & PJMEDIA_DIR_DECODING) && stream->dec) {
1923 stream->dec->paused = 0;
1924 PJ_LOG(4,(stream->dec->port.info.name.ptr, "Decoder stream resumed"));
1925 }
1926
1927 return PJ_SUCCESS;
1928}
1929
1930
1931/*
1932 * Force stream to send video keyframe.
1933 */
1934PJ_DEF(pj_status_t) pjmedia_vid_stream_send_keyframe(
1935 pjmedia_vid_stream *stream)
1936{
1937 PJ_ASSERT_RETURN(stream, PJ_EINVAL);
1938
1939 if (!pjmedia_vid_stream_is_running(stream, PJMEDIA_DIR_ENCODING))
1940 return PJ_EINVALIDOP;
1941
1942 stream->force_keyframe = PJ_TRUE;
1943
1944 return PJ_SUCCESS;
1945}
1946
1947
1948/*
1949 * Send RTCP SDES.
1950 */
1951PJ_DEF(pj_status_t) pjmedia_vid_stream_send_rtcp_sdes(
1952 pjmedia_vid_stream *stream)
1953{
1954 PJ_ASSERT_RETURN(stream, PJ_EINVAL);
1955
1956 return send_rtcp(stream, PJ_TRUE, PJ_FALSE);
1957}
1958
1959
1960/*
1961 * Send RTCP BYE.
1962 */
1963PJ_DEF(pj_status_t) pjmedia_vid_stream_send_rtcp_bye(
1964 pjmedia_vid_stream *stream)
1965{
1966 PJ_ASSERT_RETURN(stream, PJ_EINVAL);
1967
1968 if (stream->enc && stream->transport) {
1969 return send_rtcp(stream, PJ_TRUE, PJ_TRUE);
1970 }
1971
1972 return PJ_SUCCESS;
1973}
1974
1975
1976/*
1977 * Initialize the video stream rate control with default settings.
1978 */
1979PJ_DEF(void)
1980pjmedia_vid_stream_rc_config_default(pjmedia_vid_stream_rc_config *cfg)
1981{
1982 pj_bzero(cfg, sizeof(*cfg));
1983 cfg->method = PJMEDIA_VID_STREAM_RC_SIMPLE_BLOCKING;
1984}
1985
1986
1987#endif /* PJMEDIA_HAS_VIDEO */