Index: /pjproject/trunk/pjsip/src/pjsua-lib/pjsua_call.c
===================================================================
--- /pjproject/trunk/pjsip/src/pjsua-lib/pjsua_call.c	(revision 3333)
+++ /pjproject/trunk/pjsip/src/pjsua-lib/pjsua_call.c	(revision 3334)
@@ -3581,4 +3581,6 @@
 					   pjmedia_sdp_session *sdp)
 {
+    pjmedia_sdp_media *m;
+
     /* Call-hold is done by set the media direction to 'sendonly' 
      * (PJMEDIA_DIR_ENCODING), except when current media direction is 
@@ -3592,4 +3594,7 @@
      *  configuration to use c=0.0.0.0 for call hold.
      */
+
+    m = sdp->media[call->audio_idx];
+
     if (call->call_hold_type == PJSUA_CALL_HOLD_TYPE_RFC2543) {
 	pjmedia_sdp_conn *conn;
@@ -3597,5 +3602,5 @@
 
 	/* Get SDP media connection line */
-	conn = sdp->media[0]->conn;
+	conn = m->conn;
 	if (!conn)
 	    conn = sdp->conn;
@@ -3605,12 +3610,12 @@
 
 	/* Remove existing directions attributes */
-	pjmedia_sdp_media_remove_all_attr(sdp->media[0], "sendrecv");
-	pjmedia_sdp_media_remove_all_attr(sdp->media[0], "sendonly");
-	pjmedia_sdp_media_remove_all_attr(sdp->media[0], "recvonly");
-	pjmedia_sdp_media_remove_all_attr(sdp->media[0], "inactive");
+	pjmedia_sdp_media_remove_all_attr(m, "sendrecv");
+	pjmedia_sdp_media_remove_all_attr(m, "sendonly");
+	pjmedia_sdp_media_remove_all_attr(m, "recvonly");
+	pjmedia_sdp_media_remove_all_attr(m, "inactive");
 
 	/* Add inactive attribute */
 	attr = pjmedia_sdp_attr_create(pool, "inactive", NULL);
-	pjmedia_sdp_media_add_attr(sdp->media[0], attr);
+	pjmedia_sdp_media_add_attr(m, attr);
 
 
@@ -3619,17 +3624,17 @@
 
 	/* Remove existing directions attributes */
-	pjmedia_sdp_media_remove_all_attr(sdp->media[0], "sendrecv");
-	pjmedia_sdp_media_remove_all_attr(sdp->media[0], "sendonly");
-	pjmedia_sdp_media_remove_all_attr(sdp->media[0], "recvonly");
-	pjmedia_sdp_media_remove_all_attr(sdp->media[0], "inactive");
+	pjmedia_sdp_media_remove_all_attr(m, "sendrecv");
+	pjmedia_sdp_media_remove_all_attr(m, "sendonly");
+	pjmedia_sdp_media_remove_all_attr(m, "recvonly");
+	pjmedia_sdp_media_remove_all_attr(m, "inactive");
 
 	if (call->media_dir & PJMEDIA_DIR_ENCODING) {
 	    /* Add sendonly attribute */
 	    attr = pjmedia_sdp_attr_create(pool, "sendonly", NULL);
-	    pjmedia_sdp_media_add_attr(sdp->media[0], attr);
+	    pjmedia_sdp_media_add_attr(m, attr);
 	} else {
 	    /* Add inactive attribute */
 	    attr = pjmedia_sdp_attr_create(pool, "inactive", NULL);
-	    pjmedia_sdp_media_add_attr(sdp->media[0], attr);
+	    pjmedia_sdp_media_add_attr(m, attr);
 	}
     }
@@ -3673,5 +3678,5 @@
 {
     pjsua_call *call;
-    pjmedia_sdp_conn *conn;
+    pjmedia_sdp_conn *conn = NULL;
     pjmedia_sdp_session *answer;
     pj_status_t status;
@@ -3681,5 +3686,7 @@
     call = (pjsua_call*) inv->dlg->mod_data[pjsua_var.mod.id];
 
-    conn = offer->media[0]->conn;
+    if (call->audio_idx < (int)offer->media_count)
+	conn = offer->media[call->audio_idx]->conn;
+
     if (!conn)
 	conn = offer->conn;
Index: /pjproject/trunk/pjsip/src/pjsua-lib/pjsua_media.c
===================================================================
--- /pjproject/trunk/pjsip/src/pjsua-lib/pjsua_media.c	(revision 3333)
+++ /pjproject/trunk/pjsip/src/pjsua-lib/pjsua_media.c	(revision 3334)
@@ -1115,4 +1115,55 @@
 
 
+static int find_audio_index(const pjmedia_sdp_session *sdp, 
+			    pj_bool_t prefer_srtp)
+{
+    unsigned i;
+    int audio_idx = -1;
+
+    for (i=0; i<sdp->media_count; ++i) {
+	const pjmedia_sdp_media *m = sdp->media[i];
+
+	/* Skip if media is not audio */
+	if (pj_stricmp2(&m->desc.media, "audio") != 0)
+	    continue;
+
+	/* Skip if media is disabled */
+	if (m->desc.port == 0)
+	    continue;
+
+	/* Skip if transport is not supported */
+	if (pj_stricmp2(&m->desc.transport, "RTP/AVP") != 0 &&
+	    pj_stricmp2(&m->desc.transport, "RTP/SAVP") != 0)
+	{
+	    continue;
+	}
+
+	if (audio_idx == -1) {
+	    audio_idx = i;
+	} else {
+	    /* We've found multiple candidates. This could happen
+	     * e.g. when remote is offering both RTP/SAVP and RTP/AVP,
+	     * or when remote for some reason offers two audio.
+	     */
+
+	    if (prefer_srtp &&
+		pj_stricmp2(&m->desc.transport, "RTP/SAVP")==0)
+	    {
+		/* Prefer RTP/SAVP when our media transport is SRTP */
+		audio_idx = i;
+		break;
+	    } else if (!prefer_srtp &&
+		       pj_stricmp2(&m->desc.transport, "RTP/AVP")==0)
+	    {
+		/* Prefer RTP/AVP when our media transport is NOT SRTP */
+		audio_idx = i;
+	    }
+	}
+    }
+
+    return audio_idx;
+}
+
+
 pj_status_t pjsua_media_channel_init(pjsua_call_id call_id,
 				     pjsip_role_e role,
@@ -1187,12 +1238,11 @@
 
     /* Find out which media line in SDP that we support. If we are offerer,
-     * audio will be at index 0 in SDP. 
+     * audio will be initialized at index 0 in SDP. 
      */
-    if (rem_sdp == 0) {
+    if (rem_sdp == NULL) {
 	call->audio_idx = 0;
     } 
     /* Otherwise find out the candidate audio media line in SDP */
     else {
-	unsigned i;
 	pj_bool_t srtp_active;
 
@@ -1206,43 +1256,5 @@
 	pj_assert(rem_sdp->media_count != 0);
 
-	for (i=0; i<rem_sdp->media_count; ++i) {
-	    const pjmedia_sdp_media *m = rem_sdp->media[i];
-
-	    /* Skip if media is not audio */
-	    if (pj_stricmp2(&m->desc.media, "audio") != 0)
-		continue;
-
-	    /* Skip if media is disabled */
-	    if (m->desc.port == 0)
-		continue;
-
-	    /* Skip if transport is not supported */
-	    if (pj_stricmp2(&m->desc.transport, "RTP/AVP") != 0 &&
-		pj_stricmp2(&m->desc.transport, "RTP/SAVP") != 0)
-	    {
-		continue;
-	    }
-
-	    if (call->audio_idx == -1) {
-		call->audio_idx = i;
-	    } else {
-		/* We've found multiple candidates. This could happen
-		 * e.g. when remote is offering both RTP/AVP and RTP/AVP,
-		 * or when remote for some reason offers two audio.
-		 */
-
-		if (srtp_active &&
-		    pj_stricmp2(&m->desc.transport, "RTP/SAVP")==0)
-		{
-		    /* Prefer RTP/SAVP when our media transport is SRTP */
-		    call->audio_idx = i;
-		} else if (!srtp_active &&
-		           pj_stricmp2(&m->desc.transport, "RTP/AVP")==0)
-		{
-		    /* Prefer RTP/AVP when our media transport is NOT SRTP */
-		    call->audio_idx = i;
-		}
-	    }
-	}
+	call->audio_idx = find_audio_index(rem_sdp, srtp_active);
     }
 
@@ -1280,4 +1292,5 @@
     pjmedia_transport_info tpinfo;
     pjsua_call *call = &pjsua_var.calls[call_id];
+    pjmedia_sdp_neg_state sdp_neg_state = PJMEDIA_SDP_NEG_STATE_NULL;
     pj_status_t status;
 
@@ -1304,4 +1317,8 @@
     }
 
+    /* Get SDP negotiator state */
+    if (call->inv && call->inv->neg)
+	sdp_neg_state = pjmedia_sdp_neg_get_state(call->inv->neg);
+
     /* Get media socket info */
     pjmedia_transport_info_init(&tpinfo);
@@ -1316,14 +1333,25 @@
     }
 
-    /* If we're answering and the selected media is not the first media
+    /* If we're answering or updating the session with a new offer,
+     * and the selected media is not the first media
      * in SDP, then fill in the unselected media with with zero port. 
      * Otherwise we'll crash in transport_encode_sdp() because the media
      * lines are not aligned between offer and answer.
      */
-    if (rem_sdp && call->audio_idx != 0) {
+    if (call->audio_idx != 0 && 
+	(rem_sdp || sdp_neg_state==PJMEDIA_SDP_NEG_STATE_DONE))
+    {
 	unsigned i;
-
-	for (i=0; i<rem_sdp->media_count; ++i) {
-	    const pjmedia_sdp_media *rem_m = rem_sdp->media[i];
+	const pjmedia_sdp_session *ref_sdp = rem_sdp;
+
+	if (!ref_sdp) {
+	    /* We are updating session with a new offer */
+	    status = pjmedia_sdp_neg_get_active_local(call->inv->neg,
+						      &ref_sdp);
+	    pj_assert(status == PJ_SUCCESS);
+	}
+
+	for (i=0; i<ref_sdp->media_count; ++i) {
+	    const pjmedia_sdp_media *ref_m = ref_sdp->media[i];
 	    pjmedia_sdp_media *m;
 
@@ -1331,5 +1359,5 @@
 		continue;
 
-	    m = pjmedia_sdp_media_clone_deactivate(pool, rem_m);
+	    m = pjmedia_sdp_media_clone_deactivate(pool, ref_m);
 	    if (i==sdp->media_count)
 		sdp->media[sdp->media_count++] = m;
@@ -1393,19 +1421,32 @@
 		pjmedia_sdp_media_find_attr2(m, "crypto", NULL) != NULL)
 	    {
-		pjmedia_sdp_media *new_m;
-
-		/* Duplicate this media and apply secured transport */
-		new_m = pjmedia_sdp_media_clone(pool, m);
-		pj_strdup2(pool, &new_m->desc.transport, "RTP/SAVP");
-
-		/* Remove the "crypto" attribute in the unsecured media */
-		pjmedia_sdp_media_remove_all_attr(m, "crypto");
-
-		/* Insert the new media before the unsecured media */
-		if (sdp->media_count < PJMEDIA_MAX_SDP_MEDIA) {
-		    pj_array_insert(sdp->media, sizeof(new_m), 
-				    sdp->media_count, i, &new_m);
-		    ++sdp->media_count;
-		    ++i;
+		if (i == (unsigned)call->audio_idx && 
+		    sdp_neg_state == PJMEDIA_SDP_NEG_STATE_DONE)
+		{
+		    /* This is a session update, and peer has chosen the
+		     * unsecured version, so let's make this unsecured too.
+		     */
+		    pjmedia_sdp_media_remove_all_attr(m, "crypto");
+		} else {
+		    /* This is new offer, duplicate media so we'll have
+		     * secured (with "RTP/SAVP" transport) and and unsecured
+		     * versions.
+		     */
+		    pjmedia_sdp_media *new_m;
+
+		    /* Duplicate this media and apply secured transport */
+		    new_m = pjmedia_sdp_media_clone(pool, m);
+		    pj_strdup2(pool, &new_m->desc.transport, "RTP/SAVP");
+
+		    /* Remove the "crypto" attribute in the unsecured media */
+		    pjmedia_sdp_media_remove_all_attr(m, "crypto");
+
+		    /* Insert the new media before the unsecured media */
+		    if (sdp->media_count < PJMEDIA_MAX_SDP_MEDIA) {
+			pj_array_insert(sdp->media, sizeof(new_m), 
+					sdp->media_count, i, &new_m);
+			++sdp->media_count;
+			++i;
+		    }
 		}
 	    }
@@ -1539,4 +1580,7 @@
 	return status;
 
+    /* Update audio index from the negotiated SDP */
+    call->audio_idx = find_audio_index(local_sdp, PJ_TRUE);
+
     /* Find which session is audio */
     PJ_ASSERT_RETURN(call->audio_idx != -1, PJ_EBUG);
@@ -1584,5 +1628,6 @@
 	status = pjmedia_transport_media_start(call->med_tp, 
 					       call->inv->pool_prov,
-					       local_sdp, remote_sdp, 0);
+					       local_sdp, remote_sdp,
+					       call->audio_idx);
 	if (status != PJ_SUCCESS)
 	    return status;
Index: /pjproject/trunk/tests/pjsua/scripts-call/150_srtp_0_3.py
===================================================================
--- /pjproject/trunk/tests/pjsua/scripts-call/150_srtp_0_3.py	(revision 3334)
+++ /pjproject/trunk/tests/pjsua/scripts-call/150_srtp_0_3.py	(revision 3334)
@@ -0,0 +1,11 @@
+# $Id$
+#
+from inc_cfg import *
+
+test_param = TestParam(
+		"Callee=no SRTP, caller=optional (with duplicated offer) SRTP",
+		[
+			InstanceParam("callee", "--null-audio --use-srtp=0 --srtp-secure=0 --max-calls=1"),
+			InstanceParam("caller", "--null-audio --use-srtp=3 --srtp-secure=0 --max-calls=1")
+		]
+		)
Index: /pjproject/trunk/tests/pjsua/scripts-call/150_srtp_1_3.py
===================================================================
--- /pjproject/trunk/tests/pjsua/scripts-call/150_srtp_1_3.py	(revision 3334)
+++ /pjproject/trunk/tests/pjsua/scripts-call/150_srtp_1_3.py	(revision 3334)
@@ -0,0 +1,11 @@
+# $Id$
+#
+from inc_cfg import *
+
+test_param = TestParam(
+		"Callee=optional SRTP, caller=optional (with duplicated offer) SRTP",
+		[
+			InstanceParam("callee", "--null-audio --use-srtp=1 --srtp-secure=0 --max-calls=1"),
+			InstanceParam("caller", "--null-audio --use-srtp=3 --srtp-secure=0 --max-calls=1")
+		]
+		)
Index: /pjproject/trunk/tests/pjsua/scripts-call/150_srtp_2_3.py
===================================================================
--- /pjproject/trunk/tests/pjsua/scripts-call/150_srtp_2_3.py	(revision 3334)
+++ /pjproject/trunk/tests/pjsua/scripts-call/150_srtp_2_3.py	(revision 3334)
@@ -0,0 +1,11 @@
+# $Id$
+#
+from inc_cfg import *
+
+test_param = TestParam(
+		"Callee=mandatory SRTP, caller=optional (with duplicated offer) SRTP",
+		[
+			InstanceParam("callee", "--null-audio --use-srtp=2 --srtp-secure=0 --max-calls=1"),
+			InstanceParam("caller", "--null-audio --use-srtp=3 --srtp-secure=0 --max-calls=1")
+		]
+		)
Index: /pjproject/trunk/tests/pjsua/scripts-call/150_srtp_3_0.py
===================================================================
--- /pjproject/trunk/tests/pjsua/scripts-call/150_srtp_3_0.py	(revision 3334)
+++ /pjproject/trunk/tests/pjsua/scripts-call/150_srtp_3_0.py	(revision 3334)
@@ -0,0 +1,11 @@
+# $Id$
+#
+from inc_cfg import *
+
+test_param = TestParam(
+		"Callee=optional (with duplicated offer) SRTP, caller=no SRTP",
+		[
+			InstanceParam("callee", "--null-audio --use-srtp=3 --srtp-secure=0 --max-calls=1"),
+			InstanceParam("caller", "--null-audio --use-srtp=0 --srtp-secure=0 --max-calls=1")
+		]
+		)
Index: /pjproject/trunk/tests/pjsua/scripts-call/150_srtp_3_1.py
===================================================================
--- /pjproject/trunk/tests/pjsua/scripts-call/150_srtp_3_1.py	(revision 3334)
+++ /pjproject/trunk/tests/pjsua/scripts-call/150_srtp_3_1.py	(revision 3334)
@@ -0,0 +1,11 @@
+# $Id$
+#
+from inc_cfg import *
+
+test_param = TestParam(
+		"Callee=optional (with duplicated offer) SRTP, caller=optional SRTP",
+		[
+			InstanceParam("callee", "--null-audio --use-srtp=3 --srtp-secure=0 --max-calls=1"),
+			InstanceParam("caller", "--null-audio --use-srtp=1 --srtp-secure=0 --max-calls=1")
+		]
+		)
Index: /pjproject/trunk/tests/pjsua/scripts-call/150_srtp_3_2.py
===================================================================
--- /pjproject/trunk/tests/pjsua/scripts-call/150_srtp_3_2.py	(revision 3334)
+++ /pjproject/trunk/tests/pjsua/scripts-call/150_srtp_3_2.py	(revision 3334)
@@ -0,0 +1,11 @@
+# $Id$
+#
+from inc_cfg import *
+
+test_param = TestParam(
+		"Callee=optional (with duplicated offer) SRTP, caller=mandatory SRTP",
+		[
+			InstanceParam("callee", "--null-audio --use-srtp=3 --srtp-secure=0 --max-calls=1"),
+			InstanceParam("caller", "--null-audio --use-srtp=2 --srtp-secure=0 --max-calls=1")
+		]
+		)
Index: /pjproject/trunk/tests/pjsua/scripts-call/150_srtp_3_3.py
===================================================================
--- /pjproject/trunk/tests/pjsua/scripts-call/150_srtp_3_3.py	(revision 3334)
+++ /pjproject/trunk/tests/pjsua/scripts-call/150_srtp_3_3.py	(revision 3334)
@@ -0,0 +1,11 @@
+# $Id$
+#
+from inc_cfg import *
+
+test_param = TestParam(
+		"Callee=optional (with duplicated offer) SRTP, caller=optional (with duplicated offer) SRTP",
+		[
+			InstanceParam("callee", "--null-audio --use-srtp=3 --srtp-secure=0 --max-calls=1"),
+			InstanceParam("caller", "--null-audio --use-srtp=3 --srtp-secure=0 --max-calls=1")
+		]
+		)
