1
/* $Id: vid_stream.c 4613 2013-10-08 09:08:13Z bennylp $ */
3
* Copyright (C) 2011 Teluu Inc. (http://www.teluu.com)
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.
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.
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
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>
27
#include <pj/assert.h>
28
#include <pj/compat/socket.h>
30
#include <pj/ioqueue.h>
35
#include <pj/sock_select.h>
36
#include <pj/string.h> /* memcpy() */
39
#if defined(PJMEDIA_HAS_VIDEO) && (PJMEDIA_HAS_VIDEO != 0)
42
#define THIS_FILE "vid_stream.c"
44
#define LOGERR_(expr) stream_perror expr
45
#define TRC_(expr) PJ_LOG(5,expr)
46
#define SIGNATURE PJMEDIA_SIG_PORT_VID_STREAM
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.
54
#define TRACE_JB 0 /* Enable/disable trace. */
55
#define TRACE_JB_PATH_PREFIX "" /* Optional path/prefix
56
for the CSV filename. */
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)
63
#ifndef PJMEDIA_VSTREAM_SIZE
64
# define PJMEDIA_VSTREAM_SIZE 1000
67
#ifndef PJMEDIA_VSTREAM_INC
68
# define PJMEDIA_VSTREAM_INC 1000
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.
76
#define MIN_CHUNKS_PER_FRM 30
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
88
typedef struct pjmedia_vid_channel
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;
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
108
struct pjmedia_vid_stream
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. */
115
pjmedia_vid_channel *enc; /**< Encoding channel. */
116
pjmedia_vid_channel *dec; /**< Decoding channel. */
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 */
123
pjmedia_transport *transport; /**< Stream transport. */
124
unsigned send_err_cnt; /**< Send error count. */
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*/
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. */
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
145
pjmedia_event miss_keyframe_event;
146
/**< Buffered missing keyframe
147
event for delayed republish*/
149
unsigned frame_size; /**< Size of encoded base frame.*/
150
unsigned frame_ts_len; /**< Frame length in timestamp. */
152
unsigned rx_frame_cnt; /**< # of array in rx_frames */
153
pjmedia_frame *rx_frames; /**< Temp. buffer for incoming
156
pj_bool_t force_keyframe;/**< Forced to encode keyframe? */
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
162
pj_timestamp last_frm_ts_sent; /**< Timestamp of last sending
167
pj_oshandle_t trace_jb_fd; /**< Jitter tracing file handle.*/
168
char *trace_jb_buf; /**< Jitter tracing buffer. */
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. */
176
pj_timestamp ts_freq; /**< Timestamp frequency. */
179
unsigned rc_total_sleep;
180
unsigned rc_total_pkt;
181
unsigned rc_total_img;
182
pj_timestamp tx_start;
188
static pj_status_t decode_frame(pjmedia_vid_stream *stream,
189
pjmedia_frame *frame);
194
static void stream_perror(const char *sender, const char *title,
197
char errmsg[PJ_ERR_MSG_SIZE];
199
pj_strerror(status, errmsg, sizeof(errmsg));
200
PJ_LOG(4,(sender, "%s: %s [err:%d]", title, errmsg, status));
204
static pj_status_t send_rtcp(pjmedia_vid_stream *stream,
211
PJ_INLINE(int) trace_jb_print_timestamp(char **buf, pj_ssize_t len)
214
pj_parsed_time ptime;
220
pj_gettimeofday(&now);
221
pj_time_decode(&now, &ptime);
222
p += pj_utoa_pad(ptime.hour, p, 2, '0');
224
p += pj_utoa_pad(ptime.min, p, 2, '0');
226
p += pj_utoa_pad(ptime.sec, p, 2, '0');
228
p += pj_utoa_pad(ptime.msec, p, 3, '0');
236
PJ_INLINE(int) trace_jb_print_state(pjmedia_vid_stream *stream,
237
char **buf, pj_ssize_t len)
240
char *endp = *buf + len;
241
pjmedia_jb_state state;
243
pjmedia_jbuf_get_state(stream->jb, &state);
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))
255
static void trace_jb_get(pjmedia_vid_stream *stream, pjmedia_jb_frame_type ft,
258
char *p = stream->trace_jb_buf;
259
char *endp = stream->trace_jb_buf + PJ_LOG_MAX_SIZE;
263
if (!TRACE_JB_OPENED(stream))
266
/* Print timestamp. */
267
if (trace_jb_print_timestamp(&p, endp-p))
268
goto on_insuff_buffer;
270
/* Print frame type and size */
272
case PJMEDIA_JB_MISSING_FRAME:
275
case PJMEDIA_JB_NORMAL_FRAME:
278
case PJMEDIA_JB_ZERO_PREFETCH_FRAME:
281
case PJMEDIA_JB_ZERO_EMPTY_FRAME:
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;
296
if (trace_jb_print_state(stream, &p, endp-p))
297
goto on_insuff_buffer;
299
/* Print end of line */
301
goto on_insuff_buffer;
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);
311
pj_assert(!"Trace buffer too small, check PJ_LOG_MAX_SIZE!");
314
static void trace_jb_put(pjmedia_vid_stream *stream,
315
const pjmedia_rtp_hdr *hdr,
316
unsigned payloadlen, unsigned frame_cnt)
318
char *p = stream->trace_jb_buf;
319
char *endp = stream->trace_jb_buf + PJ_LOG_MAX_SIZE;
322
if (!TRACE_JB_OPENED(stream))
325
/* Print timestamp. */
326
if (trace_jb_print_timestamp(&p, endp-p))
327
goto on_insuff_buffer;
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;
339
if (trace_jb_print_state(stream, &p, endp-p))
340
goto on_insuff_buffer;
342
/* Print end of line */
344
goto on_insuff_buffer;
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);
354
pj_assert(!"Trace buffer too small, check PJ_LOG_MAX_SIZE!");
357
#endif /* TRACE_JB */
359
static void dump_port_info(const pjmedia_vid_channel *chan,
360
const char *event_name)
362
const pjmedia_port_info *pi = &chan->port.info;
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"),
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));
377
* Handle events from stream components.
379
static pj_status_t stream_event_cb(pjmedia_event *event,
382
pjmedia_vid_stream *stream = (pjmedia_vid_stream*)user_data;
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.
392
pj_memcpy(&stream->fmt_event, event, sizeof(*event));
395
case PJMEDIA_EVENT_KEYFRAME_MISSING:
396
/* Republish this event later from get_frame(). */
397
pj_memcpy(&stream->miss_keyframe_event, event, sizeof(*event));
405
return pjmedia_event_publish(NULL, stream, event, 0);
408
#if defined(PJMEDIA_STREAM_ENABLE_KA) && PJMEDIA_STREAM_ENABLE_KA != 0
410
* Send keep-alive packet using non-codec frame.
412
static void send_keep_alive_packet(pjmedia_vid_stream *stream)
414
#if PJMEDIA_STREAM_ENABLE_KA == PJMEDIA_STREAM_KA_EMPTY_RTP
416
/* Keep-alive packet is empty RTP */
417
pjmedia_vid_channel *channel = stream->enc;
422
TRC_((channel->port.info.name.ptr,
423
"Sending keep-alive (RTCP and empty RTP)"));
426
status = pjmedia_rtp_encode_rtp( &stream->enc->rtp,
432
pj_assert(status == PJ_SUCCESS);
434
pj_memcpy(stream->enc->buf, pkt, pkt_len);
435
pjmedia_transport_send_rtp(stream->transport, stream->enc->buf,
439
send_rtcp(stream, PJ_TRUE, PJ_FALSE);
441
#elif PJMEDIA_STREAM_ENABLE_KA == PJMEDIA_STREAM_KA_USER
443
/* Keep-alive packet is defined in PJMEDIA_STREAM_KA_USER_PKT */
444
pjmedia_vid_channel *channel = stream->enc;
446
const pj_str_t str_ka = PJMEDIA_STREAM_KA_USER_PKT;
448
TRC_((channel->port.info.name.ptr,
449
"Sending keep-alive (custom RTP/RTCP packets)"));
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,
457
/* Send to RTCP port */
458
pjmedia_transport_send_rtcp(stream->transport, stream->enc->buf,
463
PJ_UNUSED_ARG(stream);
467
#endif /* defined(PJMEDIA_STREAM_ENABLE_KA) */
470
static pj_status_t send_rtcp(pjmedia_vid_stream *stream,
479
/* Build RTCP RR/SR packet */
480
pjmedia_rtcp_build_rtcp(&stream->rtcp, &sr_rr_pkt, &len);
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;
487
pkt = (pj_uint8_t*)sr_rr_pkt;
491
/* Build RTCP SDES packet */
493
pjmedia_rtcp_sdes sdes;
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,
501
if (status != PJ_SUCCESS) {
502
PJ_PERROR(4,(stream->name.ptr, status,
503
"Error generating RTCP SDES"));
505
len += (int)sdes_len;
509
/* Build RTCP BYE packet */
513
bye_len = max_len - len;
514
status = pjmedia_rtcp_build_rtcp_bye(&stream->rtcp, pkt+len,
516
if (status != PJ_SUCCESS) {
517
PJ_PERROR(4,(stream->name.ptr, status,
518
"Error generating RTCP BYE"));
525
status = pjmedia_transport_send_rtcp(stream->transport, pkt, len);
534
* This function is can be called by either put_frame() or get_frame(),
535
* to transmit periodic RTCP SR/RR report.
537
static void check_tx_rtcp(pjmedia_vid_stream *stream, pj_uint32_t timestamp)
539
/* Note that timestamp may represent local or remote timestamp,
540
* depending on whether this function is called from put_frame()
545
if (stream->rtcp_last_tx == 0) {
547
stream->rtcp_last_tx = timestamp;
549
} else if (timestamp - stream->rtcp_last_tx >= stream->rtcp_interval) {
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"));
558
stream->rtcp_last_tx = timestamp;
564
static void dump_bin(const char *buf, unsigned len)
568
PJ_LOG(3,(THIS_FILE, "begin dump"));
569
for (i=0; i<len; ++i) {
572
unsigned val = buf[i] & 0xFF;
575
for (j=0; j<8; ++j) {
576
if (val & (1 << (7-j)))
582
PJ_LOG(3,(THIS_FILE, "%2d %s [%d]", i, bits, val));
584
PJ_LOG(3,(THIS_FILE, "end dump"));
590
* This callback is called by stream transport on receipt of packets
593
static void on_rx_rtp( void *data,
595
pj_ssize_t bytes_read)
598
pjmedia_vid_stream *stream = (pjmedia_vid_stream*) data;
599
pjmedia_vid_channel *channel = stream->dec;
600
const pjmedia_rtp_hdr *hdr;
603
pjmedia_rtp_status seq_st;
605
pj_bool_t pkt_discarded = PJ_FALSE;
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));
614
/* Ignore keep-alive packets */
615
if (bytes_read < (pj_ssize_t) sizeof(pjmedia_rtp_hdr))
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++;
627
/* Ignore the packet if decoder is paused */
631
/* Update RTP session (also checks if RTP session can accept
632
* the incoming packet.
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));
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));
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;
662
/* Skip bad RTP packet */
663
if (seq_st.status.flag.bad) {
664
pkt_discarded = PJ_TRUE;
668
/* Ignore if payloadlen is zero */
669
if (payloadlen == 0) {
670
pkt_discarded = PJ_TRUE;
674
pj_mutex_lock( stream->jb_mutex );
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().
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
684
pj_size_t old_size = stream->dec_frame.size;
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;
691
/* Only decode if we don't already have decoded one,
692
* unless the jb is full.
694
pj_bool_t can_decode = PJ_FALSE;
696
if (pjmedia_jbuf_is_full(stream->jb)) {
697
can_decode = PJ_TRUE;
699
else if (stream->dec_frame.size == 0) {
700
can_decode = PJ_TRUE;
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;
712
/* Put "good" packet to jitter buffer, or reset the jitter buffer
713
* when RTP session is restarted.
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"));
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);
724
trace_jb_put(stream, hdr, payloadlen, count);
728
pj_mutex_unlock( stream->jb_mutex );
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()
735
if (stream->dir == PJMEDIA_DIR_DECODING) {
736
check_tx_rtcp(stream, pj_ntohl(hdr->ts));
740
LOGERR_((channel->port.info.name.ptr, "Jitter buffer put() error",
742
pkt_discarded = PJ_TRUE;
747
/* Update RTCP session */
748
if (stream->rtcp.peer_ssrc == 0)
749
stream->rtcp.peer_ssrc = channel->rtp.peer_ssrc;
751
pjmedia_rtcp_rx_rtp2(&stream->rtcp, pj_ntohs(hdr->seq),
752
pj_ntohl(hdr->ts), payloadlen, pkt_discarded);
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,
758
if (status != PJ_SUCCESS) {
759
PJ_PERROR(4,(stream->name.ptr, status,
760
"Error sending initial RTCP RR"));
762
stream->initial_rr = PJ_TRUE;
769
* This callback is called by stream transport on receipt of packets
770
* in the RTCP socket.
772
static void on_rx_rtcp( void *data,
774
pj_ssize_t bytes_read)
776
pjmedia_vid_stream *stream = (pjmedia_vid_stream*) data;
778
/* Check for errors */
779
if (bytes_read < 0) {
780
LOGERR_((stream->cname.ptr, "RTCP recv() error",
781
(pj_status_t)-bytes_read));
785
pjmedia_rtcp_rx_rtcp(&stream->rtcp, pkt, bytes_read);
788
static pj_status_t put_frame(pjmedia_port *port,
789
pjmedia_frame *frame)
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;
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;
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.
810
pj_uint32_t dtx_duration;
812
dtx_duration = pj_timestamp_diff32(&stream->last_frm_ts_sent,
814
/* Video stream keep-alive feature is currently disabled. */
817
PJMEDIA_STREAM_KA_INTERVAL *
818
PJMEDIA_PIA_SRATE(&channel->port.info))
820
send_keep_alive_packet(stream);
821
stream->last_frm_ts_sent = frame->timestamp;
827
/* Don't do anything if stream is paused */
828
if (channel->paused) {
832
/* Get frame length in timestamp unit */
833
rtp_ts_len = stream->frame_ts_len;
835
/* Init frame_out buffer. */
836
frame_out.buf = ((char*)channel->buf) + sizeof(pjmedia_rtp_hdr);
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"));
850
status = pjmedia_vid_codec_encode_begin(stream->codec, &enc_opt, frame,
852
sizeof(pjmedia_rtp_hdr),
855
if (status != PJ_SUCCESS) {
856
LOGERR_((channel->port.info.name.ptr,
857
"Codec encode_begin() error", status));
859
/* Update RTP timestamp */
860
pjmedia_rtp_encode_rtp(&channel->rtp, channel->pt, 1, 0,
861
rtp_ts_len, (const void**)&rtphdr,
866
pj_get_timestamp(&initial_time);
868
/* Loop while we have frame to send */
870
status = pjmedia_rtp_encode_rtp(&channel->rtp,
872
(has_more_data == PJ_FALSE ? 1 : 0),
875
(const void**)&rtphdr,
877
if (status != PJ_SUCCESS) {
878
LOGERR_((channel->port.info.name.ptr,
879
"RTP encode_rtp() error", status));
883
// Copy RTP header to the beginning of packet
884
pj_memcpy(channel->buf, rtphdr, sizeof(pjmedia_rtp_hdr));
886
// Send the RTP packet to the transport.
887
status = pjmedia_transport_send_rtp(stream->transport,
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",
898
if (stream->send_err_cnt > COUNT_TO_REPORT)
899
stream->send_err_cnt = 0;
900
/* Ignore this error */
903
pjmedia_rtcp_tx_rtp(&stream->rtcp, (unsigned)frame_out.size);
904
total_sent += frame_out.size;
910
/* Next packets use same timestamp */
916
status = pjmedia_vid_codec_encode_more(stream->codec,
918
sizeof(pjmedia_rtp_hdr),
921
if (status != PJ_SUCCESS) {
922
LOGERR_((channel->port.info.name.ptr,
923
"Codec encode_more() error", status));
924
/* Ignore this error (?) */
928
/* Send rate control */
929
if (stream->info.rc_cfg.method==PJMEDIA_VID_STREAM_RC_SIMPLE_BLOCKING)
931
pj_timestamp now, next_send_ts, total_send_ts;
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);
938
pj_get_timestamp(&now);
939
if (pj_cmp_timestamp(&now, &next_send_ts) < 0) {
941
ms_sleep = pj_elapsed_msec(&now, &next_send_ts);
946
pj_thread_sleep(ms_sleep);
952
/* Trace log for rate control */
954
pj_timestamp end_time;
955
unsigned total_sleep;
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));
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++;
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().
975
if (stream->dir != PJMEDIA_DIR_DECODING) {
976
check_tx_rtcp(stream, pj_ntohl(channel->rtp.out_hdr.ts));
979
/* Do nothing if we have nothing to transmit */
980
if (total_sent == 0) {
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);
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;
996
/* Decode one image from jitter buffer */
997
static pj_status_t decode_frame(pjmedia_vid_stream *stream,
998
pjmedia_frame *frame)
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;
1007
/* Repeat get payload from the jitter buffer until all payloads with same
1008
* timestamp are collected.
1011
/* Check if we got a decodable frame */
1012
for (cnt=0; ; ++cnt) {
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) {
1023
frm_first_seq = seq;
1025
if (ts != last_ts) {
1026
got_frame = PJ_TRUE;
1030
} else if (ptype == PJMEDIA_JB_ZERO_EMPTY_FRAME) {
1031
/* No more packet in the jitter buffer */
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;
1048
for (i = 0; i < cnt; ++i) {
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;
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.
1058
pjmedia_jbuf_peek_frame(stream->jb, i,
1059
(const void**)&stream->rx_frames[i].buf,
1060
&stream->rx_frames[i].size, &ptype,
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;
1073
status = pjmedia_vid_codec_decode(stream->codec, cnt,
1075
(unsigned)frame->size, frame);
1076
if (status != PJ_SUCCESS) {
1077
LOGERR_((channel->port.info.name.ptr, "codec decode() error",
1079
frame->type = PJMEDIA_FRAME_TYPE_NONE;
1083
pjmedia_jbuf_remove_frame(stream->jb, cnt);
1086
/* Learn remote frame rate after successful decoding */
1087
if (frame->type == PJMEDIA_FRAME_TYPE_VIDEO && frame->size)
1089
/* Only check remote frame rate when timestamp is not wrapping and
1090
* sequence is increased by 1.
1092
if (last_ts > stream->last_dec_ts &&
1093
frm_first_seq - stream->last_dec_seq == 1)
1095
pj_uint32_t ts_diff;
1096
pjmedia_video_format_detail *vfd;
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)
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;
1109
vfd->fps.num = stream->info.codec_info.clock_rate;
1110
vfd->fps.denum = ts_diff;
1113
/* Update stream info */
1114
stream->info.codec_param->dec_fmt.det.vid.fps = vfd->fps;
1116
/* Publish PJMEDIA_EVENT_FMT_CHANGED event if frame rate
1117
* increased and not exceeding 100fps.
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)
1123
pjmedia_event *event = &stream->fmt_event;
1125
/* Update max fps of decoding dir */
1126
stream->dec_max_fps = vfd->fps;
1128
/* Use the buffered format changed event:
1129
* - just update the framerate if there is pending event,
1130
* - otherwise, init the whole event.
1132
if (stream->fmt_event.type != PJMEDIA_EVENT_NONE) {
1133
event->data.fmt_changed.new_fmt.det.vid.fps = vfd->fps;
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));
1146
/* Update last frame seq and timestamp */
1147
stream->last_dec_seq = frm_last_seq;
1148
stream->last_dec_ts = last_ts;
1151
return got_frame ? PJ_SUCCESS : PJ_ENOTFOUND;
1155
static pj_status_t get_frame(pjmedia_port *port,
1156
pjmedia_frame *frame)
1158
pjmedia_vid_stream *stream = (pjmedia_vid_stream*) port->port_data.pdata;
1159
pjmedia_vid_channel *channel = stream->dec;
1161
/* Return no frame is channel is paused */
1162
if (channel->paused) {
1163
frame->type = PJMEDIA_FRAME_TYPE_NONE;
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.
1173
if (stream->fmt_event.type != PJMEDIA_EVENT_NONE) {
1174
pjmedia_event_fmt_changed_data *fmt_chg_data;
1176
fmt_chg_data = &stream->fmt_event.data.fmt_changed;
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);
1185
/* Override the framerate to be 1.5x higher in the event
1188
fmt_chg_data->new_fmt.det.vid.fps.num *= 3;
1189
fmt_chg_data->new_fmt.det.vid.fps.num /= 2;
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);
1197
dump_port_info(fmt_chg_data->dir==PJMEDIA_DIR_DECODING ?
1198
stream->dec : stream->enc,
1201
pjmedia_event_publish(NULL, port, &stream->fmt_event, 0);
1203
stream->fmt_event.type = PJMEDIA_EVENT_NONE;
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;
1212
pj_mutex_lock( stream->jb_mutex );
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;
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;
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);
1235
stream->dec_frame.size = 0;
1238
pj_mutex_unlock( stream->jb_mutex );
1244
* Create media channel.
1246
static pj_status_t create_channel( pj_pool_t *pool,
1247
pjmedia_vid_stream *stream,
1250
const pjmedia_vid_stream_info *info,
1251
pjmedia_vid_channel **p_channel)
1254
pjmedia_vid_channel *channel;
1256
unsigned min_out_pkt_size;
1258
const char *type_name;
1259
pjmedia_format *fmt;
1260
char fourcc_name[5];
1261
pjmedia_port_info *pi;
1263
pj_assert(info->type == PJMEDIA_TYPE_VIDEO);
1264
pj_assert(dir == PJMEDIA_DIR_DECODING || dir == PJMEDIA_DIR_ENCODING);
1266
/* Allocate memory for channel descriptor */
1267
channel = PJ_POOL_ZALLOC_T(pool, pjmedia_vid_channel);
1268
PJ_ASSERT_RETURN(channel != NULL, PJ_ENOMEM);
1271
if (dir==PJMEDIA_DIR_DECODING) {
1272
type_name = "vstdec";
1273
fmt = &info->codec_param->dec_fmt;
1275
type_name = "vstenc";
1276
fmt = &info->codec_param->enc_fmt;
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;
1282
/* Init channel info. */
1283
channel->stream = stream;
1285
channel->paused = 1;
1288
/* Allocate buffer for outgoing packet. */
1289
if (dir == PJMEDIA_DIR_ENCODING) {
1290
channel->buf_size = sizeof(pjmedia_rtp_hdr) + stream->frame_size;
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) +
1298
if (channel->buf_size < min_out_pkt_size)
1299
channel->buf_size = min_out_pkt_size;
1301
channel->buf = pj_pool_alloc(pool, channel->buf_size);
1302
PJ_ASSERT_RETURN(channel->buf != NULL, PJ_ENOMEM);
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);
1309
pjmedia_rtp_session_setting settings;
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);
1318
if (status != PJ_SUCCESS)
1322
pjmedia_port_info_init2(pi, &name, SIGNATURE, dir, fmt);
1323
if (dir == PJMEDIA_DIR_DECODING) {
1324
channel->port.get_frame = &get_frame;
1326
pi->fmt.id = info->codec_param->dec_fmt.id;
1327
channel->port.put_frame = &put_frame;
1331
channel->port.port_data.pdata = stream;
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));
1345
*p_channel = channel;
1353
PJ_DEF(pj_status_t) pjmedia_vid_stream_create(
1354
pjmedia_endpt *endpt,
1356
pjmedia_vid_stream_info *info,
1357
pjmedia_transport *tp,
1359
pjmedia_vid_stream **p_stream)
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;
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);
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;
1383
/* Get codec manager */
1384
stream->codec_mgr = pjmedia_vid_codec_mgr_instance();
1385
PJ_ASSERT_RETURN(stream->codec_mgr, PJMEDIA_CODEC_EFAILED);
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,
1392
/* Create and initialize codec: */
1393
status = pjmedia_vid_codec_mgr_alloc_codec(stream->codec_mgr,
1396
if (status != PJ_SUCCESS)
1399
/* Get codec param: */
1400
if (!info->codec_param) {
1401
pjmedia_vid_codec_param def_param;
1403
status = pjmedia_vid_codec_mgr_get_default_param(stream->codec_mgr,
1406
if (status != PJ_SUCCESS)
1409
info->codec_param = pjmedia_vid_codec_param_clone(pool, &def_param);
1410
pj_assert(info->codec_param);
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;
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);
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;
1434
stream->jb_last_frm = PJMEDIA_JB_NORMAL_FRAME;
1436
#if defined(PJMEDIA_STREAM_ENABLE_KA) && PJMEDIA_STREAM_ENABLE_KA!=0
1437
stream->use_ka = info->use_ka;
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);
1444
*p++ = '@'; *p++ = 'p'; *p++ = 'j';
1445
pj_create_random_string(p, 6);
1447
*p++ = '.'; *p++ = 'o'; *p++ = 'r'; *p++ = 'g';
1448
stream->cname.slen = p - stream->cname.ptr;
1451
/* Create mutex to protect jitter buffer: */
1453
status = pj_mutex_create_simple(pool, NULL, &stream->jb_mutex);
1454
if (status != PJ_SUCCESS)
1457
/* Init and open the codec. */
1458
status = pjmedia_vid_codec_init(stream->codec, pool);
1459
if (status != PJ_SUCCESS)
1461
status = pjmedia_vid_codec_open(stream->codec, info->codec_param);
1462
if (status != PJ_SUCCESS)
1465
/* Subscribe to codec events */
1466
pjmedia_event_subscribe(NULL, &stream_event_cb, stream,
1469
/* Estimate the maximum frame size */
1470
stream->frame_size = vfd_enc->size.w * vfd_enc->size.h * 4;
1473
stream->frame_size = vfd_enc->max_bps/8 * vfd_enc->fps.denum /
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.
1480
stream->frame_size <<= 4;
1483
/* Validate the frame size */
1484
if (stream->frame_size == 0 ||
1485
stream->frame_size > PJMEDIA_MAX_VIDEO_ENC_FRAME_SIZE)
1487
stream->frame_size = PJMEDIA_MAX_VIDEO_ENC_FRAME_SIZE;
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;
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;
1499
/* For simple blocking, need to have bandwidth large enough, otherwise
1500
* we can slow down the transmission too much
1502
if (info->rc_cfg.method==PJMEDIA_VID_STREAM_RC_SIMPLE_BLOCKING &&
1503
info->rc_cfg.bandwidth < vfd_enc->avg_bps * 3)
1505
info->rc_cfg.bandwidth = vfd_enc->avg_bps * 3;
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.
1515
vfd_dec->fps.num = vfd_dec->fps.num * 3 / 2;
1516
stream->dec_max_fps = vfd_dec->fps;
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)
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)
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);
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;
1540
/* JB max count, default 500ms */
1541
if (info->jb_max >= frm_ptime)
1542
jb_max = info->jb_max * chunks_per_frm / frm_ptime;
1544
jb_max = 500 * chunks_per_frm / frm_ptime;
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;
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;
1556
jb_max_pre = jb_max * 4 / 5;
1558
/* JB init prefetch, default 0 */
1559
if (info->jb_init >= frm_ptime)
1560
jb_init = info->jb_init * chunks_per_frm / frm_ptime;
1564
/* Allocate array for temporary storage for assembly of incoming
1565
* frames. Add more just in case.
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]));
1571
/* Create jitter buffer */
1572
status = pjmedia_jbuf_create(pool, &stream->dec->port.info.name,
1574
1000 * vfd_enc->fps.denum / vfd_enc->fps.num,
1575
jb_max, &stream->jb);
1576
if (status != PJ_SUCCESS)
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);
1584
/* Init RTCP session: */
1586
pjmedia_rtcp_session_setting rtcp_setting;
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;
1595
pjmedia_rtcp_init2(&stream->rtcp, &rtcp_setting);
1598
/* Allocate outgoing RTCP buffer, should be enough to hold SR/RR, SDES,
1601
stream->out_rtcp_pkt_size = sizeof(pjmedia_rtcp_sr_pkt) +
1602
sizeof(pjmedia_rtcp_common) +
1603
(4 + (unsigned)stream->cname.slen) +
1605
if (stream->out_rtcp_pkt_size > PJMEDIA_MAX_MTU)
1606
stream->out_rtcp_pkt_size = PJMEDIA_MAX_MTU;
1608
stream->out_rtcp_pkt = pj_pool_alloc(pool, stream->out_rtcp_pkt_size);
1610
/* Only attach transport when stream is ready. */
1611
status = pjmedia_transport_attach(tp, stream, &info->rem_addr,
1613
pj_sockaddr_get_len(&info->rem_addr),
1614
&on_rx_rtp, &on_rx_rtcp);
1615
if (status != PJ_SUCCESS)
1618
stream->transport = tp;
1620
/* Send RTCP SDES */
1621
if (!stream->rtcp_sdes_bye_disabled) {
1622
pjmedia_vid_stream_send_rtcp_sdes(stream);
1625
#if defined(PJMEDIA_STREAM_ENABLE_KA) && PJMEDIA_STREAM_ENABLE_KA!=0
1626
/* NAT hole punching by sending KA packet via RTP transport. */
1628
send_keep_alive_packet(stream);
1633
char trace_name[PJ_MAXPATH];
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'",
1646
stream->trace_jb_buf = (char*)pj_pool_alloc(pool, PJ_LOG_MAX_SIZE);
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
if (len < 1 || len >= PJ_LOG_MAX_SIZE)
1654
len = PJ_LOG_MAX_SIZE - 1;
1655
pj_file_write(stream->trace_jb_fd, stream->trace_jb_buf, &len);
1656
pj_file_flush(stream->trace_jb_fd);
1661
/* Save the stream info */
1662
pj_memcpy(&stream->info, info, sizeof(*info));
1663
stream->info.codec_param = pjmedia_vid_codec_param_clone(
1664
pool, info->codec_param);
1669
PJ_LOG(5,(THIS_FILE, "Video stream %s created", stream->name.ptr));
1678
PJ_DEF(pj_status_t) pjmedia_vid_stream_destroy( pjmedia_vid_stream *stream )
1680
PJ_ASSERT_RETURN(stream != NULL, PJ_EINVAL);
1684
unsigned total_time;
1686
total_time = pj_elapsed_msec(&stream->tx_start, &stream->tx_end);
1687
PJ_LOG(5, (stream->name.ptr,
1688
"RC stat: pkt_cnt=%.2f/image, sleep=%.2fms/s, fps=%.2f",
1689
stream->rc_total_pkt*1.0/stream->rc_total_img,
1690
stream->rc_total_sleep*1000.0/total_time,
1691
stream->rc_total_img*1000.0/total_time));
1695
/* Send RTCP BYE (also SDES) */
1696
if (!stream->rtcp_sdes_bye_disabled) {
1697
send_rtcp(stream, PJ_TRUE, PJ_TRUE);
1700
/* Detach from transport
1701
* MUST NOT hold stream mutex while detaching from transport, as
1702
* it may cause deadlock. See ticket #460 for the details.
1704
if (stream->transport) {
1705
pjmedia_transport_detach(stream->transport, stream);
1706
stream->transport = NULL;
1709
/* This function may be called when stream is partly initialized. */
1710
if (stream->jb_mutex)
1711
pj_mutex_lock(stream->jb_mutex);
1715
if (stream->codec) {
1716
pjmedia_event_unsubscribe(NULL, &stream_event_cb, stream,
1718
pjmedia_vid_codec_close(stream->codec);
1719
pjmedia_vid_codec_mgr_dealloc_codec(stream->codec_mgr, stream->codec);
1720
stream->codec = NULL;
1725
if (stream->jb_mutex) {
1726
pj_mutex_destroy(stream->jb_mutex);
1727
stream->jb_mutex = NULL;
1730
/* Destroy jitter buffer */
1732
pjmedia_jbuf_destroy(stream->jb);
1737
if (TRACE_JB_OPENED(stream)) {
1738
pj_file_close(stream->trace_jb_fd);
1739
stream->trace_jb_fd = TRACE_JB_INVALID_FD;
1743
if (stream->own_pool) {
1744
pj_pool_t *pool = stream->own_pool;
1745
stream->own_pool = NULL;
1746
pj_pool_release(pool);
1754
* Get the port interface.
1756
PJ_DEF(pj_status_t) pjmedia_vid_stream_get_port(pjmedia_vid_stream *stream,
1758
pjmedia_port **p_port )
1760
PJ_ASSERT_RETURN(dir==PJMEDIA_DIR_ENCODING || dir==PJMEDIA_DIR_DECODING,
1763
if (dir == PJMEDIA_DIR_ENCODING)
1764
*p_port = &stream->enc->port;
1766
*p_port = &stream->dec->port;
1773
* Get the transport object
1775
PJ_DEF(pjmedia_transport*) pjmedia_vid_stream_get_transport(
1776
pjmedia_vid_stream *st)
1778
return st->transport;
1783
* Get stream statistics.
1785
PJ_DEF(pj_status_t) pjmedia_vid_stream_get_stat(
1786
const pjmedia_vid_stream *stream,
1787
pjmedia_rtcp_stat *stat)
1789
PJ_ASSERT_RETURN(stream && stat, PJ_EINVAL);
1791
pj_memcpy(stat, &stream->rtcp.stat, sizeof(pjmedia_rtcp_stat));
1797
* Reset the stream statistics in the middle of a stream session.
1799
PJ_DEF(pj_status_t) pjmedia_vid_stream_reset_stat(pjmedia_vid_stream *stream)
1801
PJ_ASSERT_RETURN(stream, PJ_EINVAL);
1803
pjmedia_rtcp_init_stat(&stream->rtcp.stat);
1810
* Get jitter buffer state.
1812
PJ_DEF(pj_status_t) pjmedia_vid_stream_get_stat_jbuf(
1813
const pjmedia_vid_stream *stream,
1814
pjmedia_jb_state *state)
1816
PJ_ASSERT_RETURN(stream && state, PJ_EINVAL);
1817
return pjmedia_jbuf_get_state(stream->jb, state);
1822
* Get the stream info.
1824
PJ_DEF(pj_status_t) pjmedia_vid_stream_get_info(
1825
const pjmedia_vid_stream *stream,
1826
pjmedia_vid_stream_info *info)
1828
PJ_ASSERT_RETURN(stream && info, PJ_EINVAL);
1829
pj_memcpy(info, &stream->info, sizeof(*info));
1837
PJ_DEF(pj_status_t) pjmedia_vid_stream_start(pjmedia_vid_stream *stream)
1840
PJ_ASSERT_RETURN(stream && stream->enc && stream->dec, PJ_EINVALIDOP);
1842
if (stream->enc && (stream->dir & PJMEDIA_DIR_ENCODING)) {
1843
stream->enc->paused = 0;
1844
//pjmedia_snd_stream_start(stream->enc->snd_stream);
1845
PJ_LOG(4,(stream->enc->port.info.name.ptr, "Encoder stream started"));
1847
PJ_LOG(4,(stream->enc->port.info.name.ptr, "Encoder stream paused"));
1850
if (stream->dec && (stream->dir & PJMEDIA_DIR_DECODING)) {
1851
stream->dec->paused = 0;
1852
//pjmedia_snd_stream_start(stream->dec->snd_stream);
1853
PJ_LOG(4,(stream->dec->port.info.name.ptr, "Decoder stream started"));
1855
PJ_LOG(4,(stream->dec->port.info.name.ptr, "Decoder stream paused"));
1865
PJ_DEF(pj_bool_t) pjmedia_vid_stream_is_running(pjmedia_vid_stream *stream,
1868
pj_bool_t is_running = PJ_TRUE;
1870
PJ_ASSERT_RETURN(stream, PJ_FALSE);
1872
if (dir & PJMEDIA_DIR_ENCODING) {
1873
is_running &= (stream->enc && !stream->enc->paused);
1876
if (dir & PJMEDIA_DIR_DECODING) {
1877
is_running &= (stream->dec && !stream->dec->paused);
1886
PJ_DEF(pj_status_t) pjmedia_vid_stream_pause(pjmedia_vid_stream *stream,
1889
PJ_ASSERT_RETURN(stream, PJ_EINVAL);
1891
if ((dir & PJMEDIA_DIR_ENCODING) && stream->enc) {
1892
stream->enc->paused = 1;
1893
PJ_LOG(4,(stream->enc->port.info.name.ptr, "Encoder stream paused"));
1896
if ((dir & PJMEDIA_DIR_DECODING) && stream->dec) {
1897
stream->dec->paused = 1;
1899
/* Also reset jitter buffer */
1900
pj_mutex_lock( stream->jb_mutex );
1901
pjmedia_jbuf_reset(stream->jb);
1902
pj_mutex_unlock( stream->jb_mutex );
1904
PJ_LOG(4,(stream->dec->port.info.name.ptr, "Decoder stream paused"));
1914
PJ_DEF(pj_status_t) pjmedia_vid_stream_resume(pjmedia_vid_stream *stream,
1917
PJ_ASSERT_RETURN(stream, PJ_EINVAL);
1919
if ((dir & PJMEDIA_DIR_ENCODING) && stream->enc) {
1920
stream->enc->paused = 0;
1921
PJ_LOG(4,(stream->enc->port.info.name.ptr, "Encoder stream resumed"));
1924
if ((dir & PJMEDIA_DIR_DECODING) && stream->dec) {
1925
stream->dec->paused = 0;
1926
PJ_LOG(4,(stream->dec->port.info.name.ptr, "Decoder stream resumed"));
1934
* Force stream to send video keyframe.
1936
PJ_DEF(pj_status_t) pjmedia_vid_stream_send_keyframe(
1937
pjmedia_vid_stream *stream)
1939
PJ_ASSERT_RETURN(stream, PJ_EINVAL);
1941
if (!pjmedia_vid_stream_is_running(stream, PJMEDIA_DIR_ENCODING))
1942
return PJ_EINVALIDOP;
1944
stream->force_keyframe = PJ_TRUE;
1953
PJ_DEF(pj_status_t) pjmedia_vid_stream_send_rtcp_sdes(
1954
pjmedia_vid_stream *stream)
1956
PJ_ASSERT_RETURN(stream, PJ_EINVAL);
1958
return send_rtcp(stream, PJ_TRUE, PJ_FALSE);
1965
PJ_DEF(pj_status_t) pjmedia_vid_stream_send_rtcp_bye(
1966
pjmedia_vid_stream *stream)
1968
PJ_ASSERT_RETURN(stream, PJ_EINVAL);
1970
if (stream->enc && stream->transport) {
1971
return send_rtcp(stream, PJ_TRUE, PJ_TRUE);
1979
* Initialize the video stream rate control with default settings.
1982
pjmedia_vid_stream_rc_config_default(pjmedia_vid_stream_rc_config *cfg)
1984
pj_bzero(cfg, sizeof(*cfg));
1985
cfg->method = PJMEDIA_VID_STREAM_RC_SIMPLE_BLOCKING;
1989
#endif /* PJMEDIA_HAS_VIDEO */