From 8f801ac496cf978d41daf150c9d9b492b78cebac Mon Sep 17 00:00:00 2001 From: Nanang Izzuddin Date: Tue, 26 Aug 2008 16:51:28 +0000 Subject: Ticket #602: - Introduced new API pjmedia_rtp_session_init2() to enable intializing RTP session with non-default initial settings - Updated stream so it can be created with non-default initial RTP settings. - Updated pjsua-lib to make sure RTP timestamp and sequence contigue when stream session is restarted. git-svn-id: http://svn.pjsip.org/repos/pjproject/trunk@2241 74dad513-b988-da41-8d7b-12977e46ad98 --- pjmedia/include/pjmedia/rtcp.h | 3 +++ pjmedia/include/pjmedia/rtp.h | 34 ++++++++++++++++++++++++++++++++ pjmedia/include/pjmedia/stream.h | 7 +++++++ pjmedia/src/pjmedia/rtp.c | 27 +++++++++++++++++++++++++ pjmedia/src/pjmedia/stream.c | 15 +++++++++++++- pjsip/include/pjsua-lib/pjsua_internal.h | 7 +++++++ pjsip/src/pjsua-lib/pjsua_call.c | 3 +++ pjsip/src/pjsua-lib/pjsua_media.c | 26 ++++++++++++++++++++++++ 8 files changed, 121 insertions(+), 1 deletion(-) diff --git a/pjmedia/include/pjmedia/rtcp.h b/pjmedia/include/pjmedia/rtcp.h index e0f3cc5d..0afac656 100644 --- a/pjmedia/include/pjmedia/rtcp.h +++ b/pjmedia/include/pjmedia/rtcp.h @@ -210,6 +210,9 @@ struct pjmedia_rtcp_stat pjmedia_rtcp_stream_stat rx; /**< Decoder stream statistics. */ pj_math_stat rtt; /**< Round trip delay statistic(in usec)*/ + + pj_uint32_t rtp_tx_last_ts; /**< Last TX RTP timestamp. */ + pj_uint16_t rtp_tx_last_seq;/**< Last TX RTP sequence. */ }; diff --git a/pjmedia/include/pjmedia/rtp.h b/pjmedia/include/pjmedia/rtp.h index dd8e02ba..44163232 100644 --- a/pjmedia/include/pjmedia/rtp.h +++ b/pjmedia/include/pjmedia/rtp.h @@ -220,6 +220,26 @@ struct pjmedia_rtp_status value will be one. */ }; + +/** + * RTP session settings. + */ +typedef struct pjmedia_rtp_session_setting +{ + pj_uint8_t flags; /**< Bitmask flags to specify whether such + field is set. Bitmask contents are: + (bit #0 is LSB) + bit #0: default payload type + bit #1: sender SSRC + bit #2: sequence + bit #3: timestamp */ + int default_pt; /**< Default payload type. */ + pj_uint32_t sender_ssrc; /**< Sender SSRC. */ + pj_uint16_t seq; /**< Sequence. */ + pj_uint32_t ts; /**< Timestamp. */ +} pjmedia_rtp_session_setting; + + /** * @see pjmedia_rtp_status */ @@ -239,6 +259,20 @@ PJ_DECL(pj_status_t) pjmedia_rtp_session_init( pjmedia_rtp_session *ses, int default_pt, pj_uint32_t sender_ssrc ); +/** + * This function will initialize the RTP session according to given parameters + * defined in RTP session settings. + * + * @param ses The session. + * @param settings RTP session settings. + * + * @return PJ_SUCCESS if successfull. + */ +PJ_DECL(pj_status_t) pjmedia_rtp_session_init2( + pjmedia_rtp_session *ses, + pjmedia_rtp_session_setting settings); + + /** * Create the RTP header based on arguments and current state of the RTP * session. diff --git a/pjmedia/include/pjmedia/stream.h b/pjmedia/include/pjmedia/stream.h index b14ef377..bb82698f 100644 --- a/pjmedia/include/pjmedia/stream.h +++ b/pjmedia/include/pjmedia/stream.h @@ -112,6 +112,13 @@ struct pjmedia_stream_info int tx_event_pt;/**< Outgoing pt for telephone-events. */ int rx_event_pt;/**< Incoming pt for telephone-events. */ pj_uint32_t ssrc; /**< RTP SSRC. */ + pj_uint32_t rtp_ts; /**< Initial RTP timestamp. */ + pj_uint16_t rtp_seq; /**< Initial RTP sequence number. */ + pj_uint8_t rtp_seq_ts_set; + /**< Bitmask flags if initial RTP sequence + and/or timestamp for sender are set. + bit 0/LSB : sequence flag + bit 1 : timestamp flag */ int jb_init; /**< Jitter buffer init delay in msec. (-1 for default). */ int jb_min_pre; /**< Jitter buffer minimum prefetch diff --git a/pjmedia/src/pjmedia/rtp.c b/pjmedia/src/pjmedia/rtp.c index 1f4de9e9..abcee1c7 100644 --- a/pjmedia/src/pjmedia/rtp.c +++ b/pjmedia/src/pjmedia/rtp.c @@ -84,6 +84,33 @@ PJ_DEF(pj_status_t) pjmedia_rtp_session_init( pjmedia_rtp_session *ses, return PJ_SUCCESS; } +PJ_DEF(pj_status_t) pjmedia_rtp_session_init2( + pjmedia_rtp_session *ses, + pjmedia_rtp_session_setting settings) +{ + pj_status_t status; + int pt = 0; + pj_uint32_t sender_ssrc = 0; + + if (settings.flags & 1) + pt = settings.default_pt; + if (settings.flags & 2) + sender_ssrc = settings.sender_ssrc; + + status = pjmedia_rtp_session_init(ses, pt, sender_ssrc); + if (status != PJ_SUCCESS) + return status; + + if (settings.flags & 4) { + ses->out_extseq = settings.seq; + ses->out_hdr.seq = pj_htons((pj_uint16_t)ses->out_extseq); + } + if (settings.flags & 8) + ses->out_hdr.ts = pj_htonl(settings.ts); + + return PJ_SUCCESS; +} + PJ_DEF(pj_status_t) pjmedia_rtp_encode_rtp( pjmedia_rtp_session *ses, int pt, int m, diff --git a/pjmedia/src/pjmedia/stream.c b/pjmedia/src/pjmedia/stream.c index ce87d048..83132167 100644 --- a/pjmedia/src/pjmedia/stream.c +++ b/pjmedia/src/pjmedia/stream.c @@ -872,6 +872,8 @@ static pj_status_t put_frame_imp( pjmedia_port *port, /* Update stat */ pjmedia_rtcp_tx_rtp(&stream->rtcp, frame_out.size); + stream->rtcp.stat.rtp_tx_last_ts = pj_ntohl(stream->enc->rtp.out_hdr.ts); + stream->rtcp.stat.rtp_tx_last_seq = pj_ntohs(stream->enc->rtp.out_hdr.seq); return PJ_SUCCESS; } @@ -1412,7 +1414,18 @@ static pj_status_t create_channel( pj_pool_t *pool, /* Create RTP and RTCP sessions: */ - status = pjmedia_rtp_session_init(&channel->rtp, pt, param->ssrc); + if (param->rtp_seq_ts_set == 0) { + status = pjmedia_rtp_session_init(&channel->rtp, pt, param->ssrc); + } else { + pjmedia_rtp_session_setting settings; + + settings.flags = (param->rtp_seq_ts_set << 2) | 3; + settings.default_pt = pt; + settings.sender_ssrc = param->ssrc; + settings.seq = param->rtp_seq; + settings.ts = param->rtp_ts; + status = pjmedia_rtp_session_init2(&channel->rtp, settings); + } if (status != PJ_SUCCESS) return status; diff --git a/pjsip/include/pjsua-lib/pjsua_internal.h b/pjsip/include/pjsua-lib/pjsua_internal.h index 5d7ff8f4..3839fa8f 100644 --- a/pjsip/include/pjsua-lib/pjsua_internal.h +++ b/pjsip/include/pjsua-lib/pjsua_internal.h @@ -66,6 +66,13 @@ typedef struct pjsua_call pjmedia_session *session; /**< The media session. */ int audio_idx; /**< Index of m=audio in SDP. */ pj_uint32_t ssrc; /**< RTP SSRC */ + pj_uint32_t rtp_tx_ts; /**< Initial RTP timestamp for sender. */ + pj_uint16_t rtp_tx_seq;/**< Initial RTP sequence for sender. */ + pj_uint8_t rtp_tx_seq_ts_set; + /**< Bitmask flags if initial RTP sequence + and/or timestamp for sender are set. + bit 0/LSB : sequence flag + bit 1 : timestamp flag */ int conf_slot; /**< Slot # in conference bridge. */ pjsip_evsub *xfer_sub; /**< Xfer server subscription, if this call was triggered by xfer. */ diff --git a/pjsip/src/pjsua-lib/pjsua_call.c b/pjsip/src/pjsua-lib/pjsua_call.c index 114da50d..737cc017 100644 --- a/pjsip/src/pjsua-lib/pjsua_call.c +++ b/pjsip/src/pjsua-lib/pjsua_call.c @@ -105,6 +105,9 @@ static void reset_call(pjsua_call_id id) call->session = NULL; call->audio_idx = -1; call->ssrc = pj_rand(); + call->rtp_tx_seq = 0; + call->rtp_tx_ts = 0; + call->rtp_tx_seq_ts_set = 0; call->xfer_sub = NULL; call->last_code = (pjsip_status_code) 0; call->conf_slot = PJSUA_INVALID_ID; diff --git a/pjsip/src/pjsua-lib/pjsua_media.c b/pjsip/src/pjsua-lib/pjsua_media.c index 69314d30..6b0d2f63 100644 --- a/pjsip/src/pjsua-lib/pjsua_media.c +++ b/pjsip/src/pjsua-lib/pjsua_media.c @@ -1158,6 +1158,23 @@ static void stop_media_session(pjsua_call_id call_id) } if (call->session) { + pjmedia_rtcp_stat stat; + + if (pjmedia_session_get_stream_stat(call->session, + call->audio_idx, + &stat) == PJ_SUCCESS) + { + /* Save RTP timestamp & sequence, so when media session is + * restarted, those values will be restored as the initial + * RTP timestamp & sequence of the new media session. So in + * the same call session, RTP timestamp and sequence are + * guaranteed to be contigue. + */ + call->rtp_tx_seq_ts_set = 1 | (1 << 1); + call->rtp_tx_seq = stat.rtp_tx_last_seq; + call->rtp_tx_ts = stat.rtp_tx_last_ts; + } + if (pjsua_var.ua_cfg.cb.on_stream_destroyed) { pjsua_var.ua_cfg.cb.on_stream_destroyed(call_id, call->session, 0); } @@ -1322,6 +1339,15 @@ pj_status_t pjsua_media_channel_update(pjsua_call_id call_id, /* Set SSRC */ si->ssrc = call->ssrc; + /* Set RTP timestamp & sequence, normally these value are intialized + * automatically when stream session created, but for some cases (e.g: + * call reinvite, call update) timestamp and sequence need to be kept + * contigue. + */ + si->rtp_ts = call->rtp_tx_ts; + si->rtp_seq = call->rtp_tx_seq; + si->rtp_seq_ts_set = call->rtp_tx_seq_ts_set; + /* Create session based on session info. */ status = pjmedia_session_create( pjsua_var.med_endpt, &sess_info, &call->med_tp, -- cgit v1.2.3