summaryrefslogtreecommitdiff
path: root/pjsip
diff options
context:
space:
mode:
authorNanang Izzuddin <nanang@teluu.com>2013-01-23 02:57:30 +0000
committerNanang Izzuddin <nanang@teluu.com>2013-01-23 02:57:30 +0000
commit89e43bc5c1f286d4466d606fb96618cb87c4bf90 (patch)
tree7de5acf14dfd41ed719c4988005eba82448ea9da /pjsip
parent5a9d4fd7b11151e1b21d627d7197ceafccd38343 (diff)
Re #1568: backported to 1.x branch.
git-svn-id: http://svn.pjsip.org/repos/pjproject/branches/1.x@4329 74dad513-b988-da41-8d7b-12977e46ad98
Diffstat (limited to 'pjsip')
-rw-r--r--pjsip/include/pjsua-lib/pjsua.h11
-rw-r--r--pjsip/src/pjsua-lib/pjsua_media.c131
2 files changed, 132 insertions, 10 deletions
diff --git a/pjsip/include/pjsua-lib/pjsua.h b/pjsip/include/pjsua-lib/pjsua.h
index fc7c473d..417301e5 100644
--- a/pjsip/include/pjsua-lib/pjsua.h
+++ b/pjsip/include/pjsua-lib/pjsua.h
@@ -4433,6 +4433,17 @@ struct pjsua_media_config
* Default : 1
*/
int snd_auto_close_time;
+
+ /**
+ * Disable smart media update (ticket #1568). The smart media update
+ * will check for any changes in the media properties after a successful
+ * SDP negotiation and the media will only be reinitialized when any
+ * change is found. When it is disabled, media streams will always be
+ * reinitialized after a successful SDP negotiation.
+ *
+ * Default: PJ_FALSE
+ */
+ pj_bool_t no_smart_media_update;
};
diff --git a/pjsip/src/pjsua-lib/pjsua_media.c b/pjsip/src/pjsua-lib/pjsua_media.c
index dc996c97..a408f4c2 100644
--- a/pjsip/src/pjsua-lib/pjsua_media.c
+++ b/pjsip/src/pjsua-lib/pjsua_media.c
@@ -1566,6 +1566,99 @@ static void stop_media_session(pjsua_call_id call_id)
call->media_st = PJSUA_CALL_MEDIA_NONE;
}
+/* Match codec fmtp. This will compare the values and the order. */
+static pj_bool_t match_codec_fmtp(const pjmedia_codec_fmtp *fmtp1,
+ const pjmedia_codec_fmtp *fmtp2)
+{
+ unsigned i;
+
+ if (fmtp1->cnt != fmtp2->cnt)
+ return PJ_FALSE;
+
+ for (i = 0; i < fmtp1->cnt; ++i) {
+ if (pj_stricmp(&fmtp1->param[i].name, &fmtp2->param[i].name))
+ return PJ_FALSE;
+ if (pj_stricmp(&fmtp1->param[i].val, &fmtp2->param[i].val))
+ return PJ_FALSE;
+ }
+
+ return PJ_TRUE;
+}
+
+
+static pj_bool_t is_media_changed(const pjsua_call *call,
+ int new_audio_idx,
+ const pjmedia_session_info *new_sess)
+{
+ pjmedia_session_info old_sess;
+ const pjmedia_stream_info *old_si = NULL;
+ const pjmedia_stream_info *new_si;
+ const pjmedia_codec_info *old_ci = NULL;
+ const pjmedia_codec_info *new_ci;
+ const pjmedia_codec_param *old_cp = NULL;
+ const pjmedia_codec_param *new_cp;
+
+ /* Init new stream info (shortcut vars) */
+ new_si = &new_sess->stream_info[new_audio_idx];
+ new_ci = &new_si->fmt;
+ new_cp = new_si->param;
+
+ /* Get current stream info */
+ if (call->session) {
+ pjmedia_session_get_info(call->session, &old_sess);
+ /* PJSUA always uses one stream per session */
+ pj_assert(old_sess.stream_cnt == 1);
+ old_si = &old_sess.stream_info[0];
+ old_ci = &old_si->fmt;
+ old_cp = old_si->param;
+ }
+
+ /* Check for audio index change (is this really necessary?) */
+ if (new_audio_idx != call->audio_idx)
+ return PJ_TRUE;
+
+ /* Check if stream stays inactive */
+ if (!old_si && new_si->dir == PJMEDIA_DIR_NONE)
+ return PJ_FALSE;
+
+ /* Compare media direction */
+ if (!old_si || (old_si && old_si->dir != new_si->dir))
+ return PJ_TRUE;
+
+ /* Compare remote RTP address */
+ if (pj_sockaddr_cmp(&old_si->rem_addr, &new_si->rem_addr))
+ return PJ_TRUE;
+
+ /* Compare codec info */
+ if (pj_stricmp(&old_ci->encoding_name, &new_ci->encoding_name) ||
+ old_ci->clock_rate != new_ci->clock_rate ||
+ old_ci->channel_cnt != new_ci->channel_cnt ||
+ //old_si->rx_pt != new_si->rx_pt ||
+ old_si->tx_pt != new_si->tx_pt ||
+ old_si->rx_event_pt != new_si->tx_event_pt ||
+ old_si->tx_event_pt != new_si->tx_event_pt)
+ {
+ return PJ_TRUE;
+ }
+
+ /* Compare codec param */
+ if (old_cp->setting.frm_per_pkt != new_cp->setting.frm_per_pkt ||
+ old_cp->setting.vad != new_cp->setting.vad ||
+ old_cp->setting.cng != new_cp->setting.cng ||
+ old_cp->setting.plc != new_cp->setting.plc ||
+ old_cp->setting.penh != new_cp->setting.penh ||
+ !match_codec_fmtp(&old_cp->setting.dec_fmtp,
+ &new_cp->setting.dec_fmtp) ||
+ !match_codec_fmtp(&old_cp->setting.enc_fmtp,
+ &new_cp->setting.enc_fmtp))
+ {
+ return PJ_TRUE;
+ }
+
+ return PJ_FALSE;
+}
+
+
pj_status_t pjsua_media_channel_deinit(pjsua_call_id call_id)
{
pjsua_call *call = &pjsua_var.calls[call_id];
@@ -1613,6 +1706,12 @@ static void dtmf_callback(pjmedia_stream *strm, void *user_data,
}
+/* Internal function: update media channel after SDP negotiation.
+ * Warning: do not use temporary/flip-flop pool, e.g: inv->pool_prov,
+ * for creating stream, etc, as after SDP negotiation and when
+ * the SDP media is not changed, the stream should remain running
+ * while the temporary/flip-flop pool may be released.
+ */
pj_status_t pjsua_media_channel_update(pjsua_call_id call_id,
const pjmedia_sdp_session *local_sdp,
const pjmedia_sdp_session *remote_sdp)
@@ -1624,31 +1723,43 @@ pj_status_t pjsua_media_channel_update(pjsua_call_id call_id,
pjmedia_stream_info *si = NULL;
pjmedia_port *media_port;
pj_status_t status;
+ int audio_idx;
if (!pjsua_var.med_endpt) {
/* We're being shutdown */
return PJ_EBUSY;
}
- /* Destroy existing media session, if any. */
- prev_media_st = call->media_st;
- stop_media_session(call->index);
-
- /* Create media session info based on SDP parameters.
- */
- status = pjmedia_session_info_from_sdp( call->inv->pool_prov,
- pjsua_var.med_endpt,
+ /* Create media session info based on SDP parameters. */
+ status = pjmedia_session_info_from_sdp( call->inv->pool_prov,
+ pjsua_var.med_endpt,
PJMEDIA_MAX_SDP_MEDIA, &sess_info,
local_sdp, remote_sdp);
if (status != PJ_SUCCESS)
return status;
+ /* Get audio index from the negotiated SDP */
+ audio_idx = find_audio_index(local_sdp, PJ_TRUE);
+
+ /* Check if media has just been changed. */
+ if (!pjsua_var.media_cfg.no_smart_media_update &&
+ !is_media_changed(call, audio_idx, &sess_info))
+ {
+ PJ_LOG(4,(THIS_FILE, "Media session for call %d is unchanged",
+ call_id));
+ return PJ_SUCCESS;
+ }
+
+ /* Destroy existing media session, if any. */
+ prev_media_st = call->media_st;
+ stop_media_session(call->index);
+
for (i = 0; i < sess_info.stream_cnt; ++i) {
sess_info.stream_info[i].rtcp_sdes_bye_disabled = PJ_TRUE;
}
/* Update audio index from the negotiated SDP */
- call->audio_idx = find_audio_index(local_sdp, PJ_TRUE);
+ call->audio_idx = audio_idx;
/* Find which session is audio */
PJ_ASSERT_RETURN(call->audio_idx != -1, PJ_EBUG);
@@ -1807,7 +1918,7 @@ pj_status_t pjsua_media_channel_update(pjsua_call_id call_id,
port_name = pj_str("call");
}
status = pjmedia_conf_add_port( pjsua_var.mconf,
- call->inv->pool_prov,
+ call->inv->pool,
media_port,
&port_name,
(unsigned*)&call->conf_slot);