From cb0e240d2210d391514286965cc20a05b6c65b6a Mon Sep 17 00:00:00 2001 From: Nanang Izzuddin Date: Sat, 26 Jun 2010 04:43:50 +0000 Subject: Fix #740: - Fixed zeroed/unset RTP timestamp in RTCP sender report. git-svn-id: http://svn.pjsip.org/repos/pjproject/trunk@3224 74dad513-b988-da41-8d7b-12977e46ad98 --- pjmedia/include/pjmedia/rtcp.h | 33 ++++++++++++++++++++++++++++ pjmedia/src/pjmedia/rtcp.c | 50 ++++++++++++++++++++++++++++++++++++++---- pjmedia/src/pjmedia/stream.c | 40 +++++++++++++++++++-------------- 3 files changed, 102 insertions(+), 21 deletions(-) diff --git a/pjmedia/include/pjmedia/rtcp.h b/pjmedia/include/pjmedia/rtcp.h index a443add4..df6e1848 100644 --- a/pjmedia/include/pjmedia/rtcp.h +++ b/pjmedia/include/pjmedia/rtcp.h @@ -246,6 +246,7 @@ struct pjmedia_rtcp_session pj_time_val tv_base; /**< Base time, in seconds. */ pj_timestamp ts_base; /**< Base system timestamp. */ pj_timestamp ts_freq; /**< System timestamp frequency. */ + pj_uint32_t rtp_ts_base;/**< Base RTP timestamp. */ pj_uint32_t rx_lsr; /**< NTP ts in last SR received */ pj_timestamp rx_lsr_time;/**< Time when last SR is received */ @@ -273,6 +274,28 @@ struct pjmedia_rtcp_session typedef struct pjmedia_rtcp_session pjmedia_rtcp_session; +/** + * RTCP session settings. + */ +typedef struct pjmedia_rtcp_session_setting +{ + char *name; /**< RTCP session name. */ + unsigned clock_rate; /**< Sequence. */ + unsigned samples_per_frame; /**< Timestamp. */ + pj_uint32_t ssrc; /**< Sender SSRC. */ + pj_uint32_t rtp_ts_base; /**< Base RTP timestamp. */ +} pjmedia_rtcp_session_setting; + + +/** + * Initialize RTCP session setting. + * + * @param settings The RTCP session setting to be initialized. + */ +PJ_DECL(void) pjmedia_rtcp_session_setting_default( + pjmedia_rtcp_session_setting *settings); + + /** * Initialize RTCP session. * @@ -290,6 +313,16 @@ PJ_DECL(void) pjmedia_rtcp_init( pjmedia_rtcp_session *session, pj_uint32_t ssrc ); +/** + * Initialize RTCP session. + * + * @param session The session + * @param settings The RTCP session settings. + */ +PJ_DECL(void) pjmedia_rtcp_init2(pjmedia_rtcp_session *session, + const pjmedia_rtcp_session_setting *settings); + + /** * Utility function to retrieve current NTP timestamp. * diff --git a/pjmedia/src/pjmedia/rtcp.c b/pjmedia/src/pjmedia/rtcp.c index 3dd7e9a1..3c2de9e3 100644 --- a/pjmedia/src/pjmedia/rtcp.c +++ b/pjmedia/src/pjmedia/rtcp.c @@ -125,11 +125,42 @@ PJ_DEF(pj_status_t) pjmedia_rtcp_get_ntp_time(const pjmedia_rtcp_session *sess, } +/* + * Initialize RTCP session setting. + */ +PJ_DEF(void) pjmedia_rtcp_session_setting_default( + pjmedia_rtcp_session_setting *settings) +{ + pj_bzero(&settings, sizeof(*settings)); +} + + +/* + * Initialize RTCP session. + */ PJ_DEF(void) pjmedia_rtcp_init(pjmedia_rtcp_session *sess, char *name, unsigned clock_rate, unsigned samples_per_frame, pj_uint32_t ssrc) +{ + pjmedia_rtcp_session_setting settings; + + pjmedia_rtcp_session_setting_default(&settings); + settings.name = name; + settings.clock_rate = clock_rate; + settings.samples_per_frame = samples_per_frame; + settings.ssrc = ssrc; + + pjmedia_rtcp_init2(sess, &settings); +} + + +/* + * Initialize RTCP session. + */ +PJ_DEF(void) pjmedia_rtcp_init2( pjmedia_rtcp_session *sess, + const pjmedia_rtcp_session_setting *settings) { pjmedia_rtcp_sr_pkt *sr_pkt = &sess->rtcp_sr_pkt; pj_time_val now; @@ -141,18 +172,18 @@ PJ_DEF(void) pjmedia_rtcp_init(pjmedia_rtcp_session *sess, sess->rtp_last_ts = (unsigned)-1; /* Name */ - sess->name = name ? name : (char*)THIS_FILE, + sess->name = settings->name ? settings->name : (char*)THIS_FILE; /* Set clock rate */ - sess->clock_rate = clock_rate; - sess->pkt_size = samples_per_frame; + sess->clock_rate = settings->clock_rate; + sess->pkt_size = settings->samples_per_frame; /* Init common RTCP SR header */ sr_pkt->common.version = 2; sr_pkt->common.count = 1; sr_pkt->common.pt = RTCP_SR; sr_pkt->common.length = pj_htons(12); - sr_pkt->common.ssrc = pj_htonl(ssrc); + sr_pkt->common.ssrc = pj_htonl(settings->ssrc); /* Copy to RTCP RR header */ pj_memcpy(&sess->rtcp_rr_pkt.common, &sr_pkt->common, @@ -166,6 +197,7 @@ PJ_DEF(void) pjmedia_rtcp_init(pjmedia_rtcp_session *sess, sess->stat.start = now; pj_get_timestamp(&sess->ts_base); pj_get_timestamp_freq(&sess->ts_freq); + sess->rtp_ts_base = settings->rtp_ts_base; /* Initialize statistics states */ pj_math_stat_init(&sess->stat.rtt); @@ -571,6 +603,8 @@ PJ_DEF(void) pjmedia_rtcp_build_rtcp(pjmedia_rtcp_session *sess, * sent RTCP SR. */ if (sess->stat.tx.pkt != pj_ntohl(sess->rtcp_sr_pkt.sr.sender_pcount)) { + pj_time_val ts_time; + pj_uint32_t rtp_ts; /* So we should send RTCP SR */ *ret_p_pkt = (void*) &sess->rtcp_sr_pkt; @@ -589,6 +623,14 @@ PJ_DEF(void) pjmedia_rtcp_build_rtcp(pjmedia_rtcp_session *sess, sr->ntp_sec = pj_htonl(ntp.hi); sr->ntp_frac = pj_htonl(ntp.lo); + /* Fill in RTP timestamp (corresponds to NTP timestamp) in SR. */ + ts_time.sec = ntp.hi - sess->tv_base.sec - JAN_1970; + ts_time.msec = (long)(ntp.lo * 1000.0 / 0xFFFFFFFF); + rtp_ts = sess->rtp_ts_base + + (pj_uint32_t)(sess->clock_rate*ts_time.sec) + + (pj_uint32_t)(sess->clock_rate*ts_time.msec/1000); + sr->rtp_ts = pj_htonl(rtp_ts); + TRACE_((sess->name, "TX RTCP SR: ntp_ts=%p", ((ntp.hi & 0xFFFF) << 16) + ((ntp.lo & 0xFFFF0000) >> 16))); diff --git a/pjmedia/src/pjmedia/stream.c b/pjmedia/src/pjmedia/stream.c index c7c0db73..ba5fad5c 100644 --- a/pjmedia/src/pjmedia/stream.c +++ b/pjmedia/src/pjmedia/stream.c @@ -2121,28 +2121,11 @@ PJ_DEF(pj_status_t) pjmedia_stream_create( pjmedia_endpt *endpt, stream->rtp_rx_ts_len_per_frame = stream->port.info.samples_per_frame / stream->codec_param.info.channel_cnt; - /* Init RTCP session: */ - - /* Special case for G.722 */ if (info->fmt.pt == PJMEDIA_RTP_PT_G722) { - pjmedia_rtcp_init(&stream->rtcp, stream->port.info.name.ptr, - 8000, - 160, - info->ssrc); stream->has_g722_mpeg_bug = PJ_TRUE; /* RTP clock rate = 1/2 real clock rate */ stream->rtp_tx_ts_len_per_pkt >>= 1; - } else { - pjmedia_rtcp_init(&stream->rtcp, stream->port.info.name.ptr, - info->fmt.clock_rate, - stream->port.info.samples_per_frame, - info->ssrc); } -#else - pjmedia_rtcp_init(&stream->rtcp, stream->port.info.name.ptr, - info->fmt.clock_rate, - stream->port.info.samples_per_frame, - info->ssrc); #endif /* Init jitter buffer parameters: */ @@ -2198,6 +2181,29 @@ PJ_DEF(pj_status_t) pjmedia_stream_create( pjmedia_endpt *endpt, goto err_cleanup; + /* Init RTCP session: */ + + { + pjmedia_rtcp_session_setting rtcp_setting; + + pjmedia_rtcp_session_setting_default(&rtcp_setting); + rtcp_setting.name = stream->port.info.name.ptr; + rtcp_setting.ssrc = info->ssrc; + rtcp_setting.rtp_ts_base = pj_ntohl(stream->enc->rtp.out_hdr.ts); + rtcp_setting.clock_rate = info->fmt.clock_rate; + rtcp_setting.samples_per_frame = stream->port.info.samples_per_frame; + +#if defined(PJMEDIA_HANDLE_G722_MPEG_BUG) && (PJMEDIA_HANDLE_G722_MPEG_BUG!=0) + /* Special case for G.722 */ + if (info->fmt.pt == PJMEDIA_RTP_PT_G722) { + rtcp_setting.clock_rate = 8000; + rtcp_setting.samples_per_frame = 160; + } +#endif + + pjmedia_rtcp_init2(&stream->rtcp, &rtcp_setting); + } + /* Only attach transport when stream is ready. */ status = pjmedia_transport_attach(tp, stream, &info->rem_addr, &info->rem_rtcp, -- cgit v1.2.3