diff options
author | Nanang Izzuddin <nanang@teluu.com> | 2012-04-03 10:10:11 +0000 |
---|---|---|
committer | Nanang Izzuddin <nanang@teluu.com> | 2012-04-03 10:10:11 +0000 |
commit | 8f3750ee024a29a101156836adb14a646bb28842 (patch) | |
tree | 72c1a8f67c43a62702c06d801dcae7dcfbc7d943 /pjmedia/src | |
parent | f414122b18c19e10aa49d86478d2abf422ebc2f8 (diff) |
Close #1479: Applied RTCP related enhancements (#1268 & #1440) into video stream.
git-svn-id: http://svn.pjsip.org/repos/pjproject/trunk@4012 74dad513-b988-da41-8d7b-12977e46ad98
Diffstat (limited to 'pjmedia/src')
-rw-r--r-- | pjmedia/src/pjmedia/vid_stream.c | 237 |
1 files changed, 132 insertions, 105 deletions
diff --git a/pjmedia/src/pjmedia/vid_stream.c b/pjmedia/src/pjmedia/vid_stream.c index 2d52b760..ecd54400 100644 --- a/pjmedia/src/pjmedia/vid_stream.c +++ b/pjmedia/src/pjmedia/vid_stream.c @@ -117,6 +117,10 @@ struct pjmedia_vid_stream pj_uint32_t rtcp_last_tx; /**< RTCP tx time in timestamp */ pj_uint32_t rtcp_interval; /**< Interval, in timestamp. */ pj_bool_t initial_rr; /**< Initial RTCP RR sent */ + pj_bool_t rtcp_sdes_bye_disabled;/**< Send RTCP SDES/BYE?*/ + void *out_rtcp_pkt; /**< Outgoing RTCP packet. */ + unsigned out_rtcp_pkt_size; + /**< Outgoing RTCP packet size. */ unsigned dec_max_size; /**< Size of decoded/raw picture*/ pjmedia_frame dec_frame; /**< Current decoded frame. */ @@ -170,6 +174,11 @@ static void stream_perror(const char *sender, const char *title, } +static pj_status_t send_rtcp(pjmedia_vid_stream *stream, + pj_bool_t with_sdes, + pj_bool_t with_bye); + + #if TRACE_JB PJ_INLINE(int) trace_jb_print_timestamp(char **buf, pj_ssize_t len) @@ -399,8 +408,7 @@ static void send_keep_alive_packet(pjmedia_vid_stream *stream) pkt_len); /* Send RTCP */ - pjmedia_rtcp_build_rtcp(&stream->rtcp, &pkt, &pkt_len); - pjmedia_transport_send_rtcp(stream->transport, pkt, pkt_len); + send_rtcp(stream, PJ_TRUE, PJ_FALSE, PJ_FALSE); #elif PJMEDIA_STREAM_ENABLE_KA == PJMEDIA_STREAM_KA_USER @@ -430,6 +438,67 @@ static void send_keep_alive_packet(pjmedia_vid_stream *stream) #endif /* defined(PJMEDIA_STREAM_ENABLE_KA) */ +static pj_status_t send_rtcp(pjmedia_vid_stream *stream, + pj_bool_t with_sdes, + pj_bool_t with_bye) +{ + void *sr_rr_pkt; + pj_uint8_t *pkt; + int len, max_len; + pj_status_t status; + + /* Build RTCP RR/SR packet */ + pjmedia_rtcp_build_rtcp(&stream->rtcp, &sr_rr_pkt, &len); + + if (with_sdes || with_bye) { + pkt = (pj_uint8_t*) stream->out_rtcp_pkt; + pj_memcpy(pkt, sr_rr_pkt, len); + max_len = stream->out_rtcp_pkt_size; + } else { + pkt = sr_rr_pkt; + max_len = len; + } + + /* Build RTCP SDES packet */ + if (with_sdes) { + pjmedia_rtcp_sdes sdes; + pj_size_t sdes_len; + + pj_bzero(&sdes, sizeof(sdes)); + sdes.cname = stream->cname; + sdes_len = max_len - len; + status = pjmedia_rtcp_build_rtcp_sdes(&stream->rtcp, pkt+len, + &sdes_len, &sdes); + if (status != PJ_SUCCESS) { + PJ_PERROR(4,(stream->name.ptr, status, + "Error generating RTCP SDES")); + } else { + len += sdes_len; + } + } + + /* Build RTCP BYE packet */ + if (with_bye) { + pj_size_t bye_len; + + bye_len = max_len - len; + status = pjmedia_rtcp_build_rtcp_bye(&stream->rtcp, pkt+len, + &bye_len, NULL); + if (status != PJ_SUCCESS) { + PJ_PERROR(4,(stream->name.ptr, status, + "Error generating RTCP BYE")); + } else { + len += bye_len; + } + } + + /* Send! */ + status = pjmedia_transport_send_rtcp(stream->transport, pkt, len); + + return status; +} + + /** * check_tx_rtcp() * @@ -449,80 +518,18 @@ static void check_tx_rtcp(pjmedia_vid_stream *stream, pj_uint32_t timestamp) stream->rtcp_last_tx = timestamp; } else if (timestamp - stream->rtcp_last_tx >= stream->rtcp_interval) { + pj_status_t status; - void *rtcp_pkt; - int len; - - pjmedia_rtcp_build_rtcp(&stream->rtcp, &rtcp_pkt, &len); - - pjmedia_transport_send_rtcp(stream->transport, rtcp_pkt, len); + status = send_rtcp(stream, !stream->rtcp_sdes_bye_disabled, PJ_FALSE); + if (status != PJ_SUCCESS) { + PJ_PERROR(4,(stream->name.ptr, status, + "Error sending RTCP")); + } stream->rtcp_last_tx = timestamp; } } -/* Build RTCP SDES packet */ -static unsigned create_rtcp_sdes(pjmedia_vid_stream *stream, pj_uint8_t *pkt, - unsigned max_len) -{ - pjmedia_rtcp_common hdr; - pj_uint8_t *p = pkt; - - /* SDES header */ - hdr.version = 2; - hdr.p = 0; - hdr.count = 1; - hdr.pt = 202; - hdr.length = 2 + (4+stream->cname.slen+3)/4 - 1; - if (max_len < (hdr.length << 2)) { - pj_assert(!"Not enough buffer for SDES packet"); - return 0; - } - hdr.length = pj_htons((pj_uint16_t)hdr.length); - hdr.ssrc = stream->enc->rtp.out_hdr.ssrc; - pj_memcpy(p, &hdr, sizeof(hdr)); - p += sizeof(hdr); - - /* CNAME item */ - *p++ = 1; - *p++ = (pj_uint8_t)stream->cname.slen; - pj_memcpy(p, stream->cname.ptr, stream->cname.slen); - p += stream->cname.slen; - - /* END */ - *p++ = '\0'; - *p++ = '\0'; - - /* Pad to 32bit */ - while ((p-pkt) % 4) - *p++ = '\0'; - - return (p - pkt); -} - -/* Build RTCP BYE packet */ -static unsigned create_rtcp_bye(pjmedia_vid_stream *stream, pj_uint8_t *pkt, - unsigned max_len) -{ - pjmedia_rtcp_common hdr; - - /* BYE header */ - hdr.version = 2; - hdr.p = 0; - hdr.count = 1; - hdr.pt = 203; - hdr.length = 1; - if (max_len < (hdr.length << 2)) { - pj_assert(!"Not enough buffer for SDES packet"); - return 0; - } - hdr.length = pj_htons((pj_uint16_t)hdr.length); - hdr.ssrc = stream->enc->rtp.out_hdr.ssrc; - pj_memcpy(pkt, &hdr, sizeof(hdr)); - - return sizeof(hdr); -} - #if 0 static void dump_bin(const char *buf, unsigned len) @@ -716,27 +723,14 @@ on_return: /* Send RTCP RR and SDES after we receive some RTP packets */ if (stream->rtcp.received >= 10 && !stream->initial_rr) { - void *sr_rr_pkt; - pj_uint8_t *pkt; - int len; - - /* Build RR or SR */ - pjmedia_rtcp_build_rtcp(&stream->rtcp, &sr_rr_pkt, &len); - pkt = (pj_uint8_t*) stream->enc->buf; - pj_memcpy(pkt, sr_rr_pkt, len); - pkt += len; - - /* Append SDES */ - len = create_rtcp_sdes(stream, (pj_uint8_t*)pkt, - stream->enc->buf_size - len); - if (len > 0) { - pkt += len; - len = ((pj_uint8_t*)pkt) - ((pj_uint8_t*)stream->enc->buf); - pjmedia_transport_send_rtcp(stream->transport, - stream->enc->buf, len); + status = send_rtcp(stream, !stream->rtcp_sdes_bye_disabled, + PJ_FALSE); + if (status != PJ_SUCCESS) { + PJ_PERROR(4,(stream->name.ptr, status, + "Error sending initial RTCP RR")); + } else { + stream->initial_rr = PJ_TRUE; } - - stream->initial_rr = PJ_TRUE; } } @@ -1286,7 +1280,7 @@ PJ_DEF(pj_status_t) pjmedia_vid_stream_create( enum { M = 32 }; pj_pool_t *own_pool = NULL; pjmedia_vid_stream *stream; - unsigned jb_init, jb_max, jb_min_pre, jb_max_pre, len; + unsigned jb_init, jb_max, jb_min_pre, jb_max_pre; int frm_ptime, chunks_per_frm; pjmedia_video_format_detail *vfd_enc, *vfd_dec; char *p; @@ -1357,6 +1351,7 @@ PJ_DEF(pj_status_t) pjmedia_vid_stream_create( stream->user_data = user_data; stream->rtcp_interval = (PJMEDIA_RTCP_INTERVAL-500 + (pj_rand()%1000)) * info->codec_info.clock_rate / 1000; + stream->rtcp_sdes_bye_disabled = info->rtcp_sdes_bye_disabled; stream->jb_last_frm = PJMEDIA_JB_NORMAL_FRAME; @@ -1507,6 +1502,18 @@ PJ_DEF(pj_status_t) pjmedia_vid_stream_create( pjmedia_rtcp_init2(&stream->rtcp, &rtcp_setting); } + /* Allocate outgoing RTCP buffer, should be enough to hold SR/RR, SDES, + * BYE, and XR. + */ + stream->out_rtcp_pkt_size = sizeof(pjmedia_rtcp_sr_pkt) + + sizeof(pjmedia_rtcp_common) + + (4 + stream->cname.slen) + + 32; + if (stream->out_rtcp_pkt_size > PJMEDIA_MAX_MTU) + stream->out_rtcp_pkt_size = PJMEDIA_MAX_MTU; + + stream->out_rtcp_pkt = pj_pool_alloc(pool, stream->out_rtcp_pkt_size); + /* Only attach transport when stream is ready. */ status = pjmedia_transport_attach(tp, stream, &info->rem_addr, &info->rem_rtcp, @@ -1518,11 +1525,8 @@ PJ_DEF(pj_status_t) pjmedia_vid_stream_create( stream->transport = tp; /* Send RTCP SDES */ - len = create_rtcp_sdes(stream, (pj_uint8_t*)stream->enc->buf, - stream->enc->buf_size); - if (len != 0) { - pjmedia_transport_send_rtcp(stream->transport, - stream->enc->buf, len); + if (!stream->rtcp_sdes_bye_disabled) { + pjmedia_vid_stream_send_rtcp_sdes(stream); } #if defined(PJMEDIA_STREAM_ENABLE_KA) && PJMEDIA_STREAM_ENABLE_KA!=0 @@ -1578,17 +1582,11 @@ PJ_DEF(pj_status_t) pjmedia_vid_stream_create( */ PJ_DEF(pj_status_t) pjmedia_vid_stream_destroy( pjmedia_vid_stream *stream ) { - unsigned len; PJ_ASSERT_RETURN(stream != NULL, PJ_EINVAL); - /* Send RTCP BYE */ - if (stream->enc && stream->transport) { - len = create_rtcp_bye(stream, (pj_uint8_t*)stream->enc->buf, - stream->enc->buf_size); - if (len != 0) { - pjmedia_transport_send_rtcp(stream->transport, - stream->enc->buf, len); - } + /* Send RTCP BYE (also SDES) */ + if (!stream->rtcp_sdes_bye_disabled) { + send_rtcp(stream, PJ_TRUE, PJ_TRUE); } /* Detach from transport @@ -1823,6 +1821,7 @@ PJ_DEF(pj_status_t) pjmedia_vid_stream_resume(pjmedia_vid_stream *stream, return PJ_SUCCESS; } + /* * Force stream to send video keyframe. */ @@ -1840,4 +1839,32 @@ PJ_DEF(pj_status_t) pjmedia_vid_stream_send_keyframe( } +/* + * Send RTCP SDES. + */ +PJ_DEF(pj_status_t) pjmedia_vid_stream_send_rtcp_sdes( + pjmedia_vid_stream *stream) +{ + PJ_ASSERT_RETURN(stream, PJ_EINVAL); + + return send_rtcp(stream, PJ_TRUE, PJ_FALSE); +} + + +/* + * Send RTCP BYE. + */ +PJ_DEF(pj_status_t) pjmedia_vid_stream_send_rtcp_bye( + pjmedia_vid_stream *stream) +{ + PJ_ASSERT_RETURN(stream, PJ_EINVAL); + + if (stream->enc && stream->transport) { + return send_rtcp(stream, PJ_TRUE, PJ_TRUE); + } + + return PJ_SUCCESS; +} + + #endif /* PJMEDIA_HAS_VIDEO */ |