diff --git a/coreapi/callbacks.c b/coreapi/callbacks.c
index 6cee4473d51a3267f5ca9a50670ed1fefac6a6b8..f4f0a0425e463355a8c58fdef691d90828ce2b8e 100644
--- a/coreapi/callbacks.c
+++ b/coreapi/callbacks.c
@@ -532,6 +532,20 @@ static void call_failure(SalOp *op, SalError error, SalReason sr, const char *de
 					lc->vtable.display_status(lc,msg600);
 			break;
 			case SalReasonMedia:
+			//media_encryption_mandatory
+				if (call->params.media_encryption == LinphoneMediaEncryptionSRTP && 
+					!linphone_core_is_media_encryption_mandatory(lc)) {
+					int i;
+					ms_message("Outgoing call failed with SRTP (SAVP) enabled - retrying with AVP");
+					/* clear SRTP local params */
+					call->params.media_encryption = LinphoneMediaEncryptionNone;
+					for(i=0; i<call->localdesc->nstreams; i++) {
+						call->localdesc->streams[i].proto = SalProtoRtpAvp;
+						memset(call->localdesc->streams[i].crypto, 0, sizeof(call->localdesc->streams[i].crypto));
+					}
+					linphone_core_start_invite(lc, call, NULL);
+					return;
+				}
 				msg=_("No common codecs");
 				if (lc->vtable.display_status)
 					lc->vtable.display_status(lc,msg);
diff --git a/coreapi/conference.c b/coreapi/conference.c
index 065a6d99d0fb28607dd9ec8b8025d2db793c4c86..5992024ae23da5eb4f190a9b37518ab0036ddc1f 100644
--- a/coreapi/conference.c
+++ b/coreapi/conference.c
@@ -140,6 +140,7 @@ int linphone_core_add_to_conference(LinphoneCore *lc, LinphoneCall *call){
 	conference_check_init(&lc->conf_ctx);
 	call->params.in_conference=TRUE;
 	call->params.has_video=FALSE;
+	call->params.media_encryption=LinphoneMediaEncryptionNone;
 	params=call->params;
 	if (call->state==LinphoneCallPaused)
 		linphone_core_resume_call(lc,call);
diff --git a/coreapi/linphonecall.c b/coreapi/linphonecall.c
index dee7a21cc79a7393221dafb1fc99880f5a31bf51..918fb18951a5ee4044decdda4d63521b5721178d 100644
--- a/coreapi/linphonecall.c
+++ b/coreapi/linphonecall.c
@@ -26,6 +26,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 #include "lpconfig.h"
 #include "private.h"
 #include <ortp/event.h>
+#include <ortp/b64.h>
 
 
 #include "mediastreamer2/mediastream.h"
@@ -41,6 +42,27 @@ static MSWebCam *get_nowebcam_device(){
 }
 #endif
 
+static bool_t generate_b64_crypto_key(int key_length, char* key_out) {
+	int b64_size;
+	uint8_t* tmp = (uint8_t*) malloc(key_length);			
+	if (ortp_crypto_get_random(tmp, key_length)!=0) {
+		ms_error("Failed to generate random key");
+		free(tmp);
+		return FALSE;
+	}
+	
+	b64_size = b64_encode((const char*)tmp, key_length, NULL, 0);
+	if (b64_size == 0) {
+		ms_error("Failed to b64 encode key");
+		free(tmp);
+		return FALSE;
+	}
+	key_out[b64_size] = '\0';
+	b64_encode((const char*)tmp, key_length, key_out, 40);
+	free(tmp);
+	return TRUE;
+}
+
 LinphoneCore *linphone_call_get_core(const LinphoneCall *call){
 	return call->core;
 }
@@ -165,6 +187,7 @@ static MSList *make_codec_list(LinphoneCore *lc, const MSList *codecs, int bandw
 static SalMediaDescription *_create_local_media_description(LinphoneCore *lc, LinphoneCall *call, unsigned int session_id, unsigned int session_ver){
 	MSList *l;
 	PayloadType *pt;
+	int i;
 	const char *me=linphone_core_get_identity(lc);
 	LinphoneAddress *addr=linphone_address_new(me);
 	const char *username=linphone_address_get_username (addr);
@@ -180,7 +203,8 @@ static SalMediaDescription *_create_local_media_description(LinphoneCore *lc, Li
 	/*set audio capabilities */
 	strncpy(md->streams[0].addr,call->localip,sizeof(md->streams[0].addr));
 	md->streams[0].port=call->audio_port;
-	md->streams[0].proto=SalProtoRtpAvp;
+	md->streams[0].proto=(call->params.media_encryption == LinphoneMediaEncryptionSRTP) ? 
+		SalProtoRtpSavp : SalProtoRtpAvp;
 	md->streams[0].type=SalAudio;
 	md->streams[0].ptime=lc->net_conf.down_ptime;
 	l=make_codec_list(lc,lc->codecs_conf.audio_codecs,call->params.audio_bw);
@@ -192,11 +216,26 @@ static SalMediaDescription *_create_local_media_description(LinphoneCore *lc, Li
 	if (call->params.has_video){
 		md->nstreams++;
 		md->streams[1].port=call->video_port;
-		md->streams[1].proto=SalProtoRtpAvp;
+		md->streams[1].proto=md->streams[0].proto;
 		md->streams[1].type=SalVideo;
 		l=make_codec_list(lc,lc->codecs_conf.video_codecs,0);
 		md->streams[1].payloads=l;
 	}
+	
+	for(i=0; i<md->nstreams; i++) {
+		if (md->streams[i].proto == SalProtoRtpSavp) {
+			md->streams[i].crypto[0].tag = 1;
+			md->streams[i].crypto[0].algo = AES_128_SHA1_80;
+			if (!generate_b64_crypto_key(30, md->streams[i].crypto[0].master_key))
+				md->streams[i].crypto[0].algo = 0;
+			md->streams[i].crypto[1].tag = 2;
+			md->streams[i].crypto[1].algo = AES_128_SHA1_32;
+			if (!generate_b64_crypto_key(30, md->streams[i].crypto[1].master_key))
+				md->streams[i].crypto[1].algo = 0;
+			md->streams[i].crypto[2].algo = 0;
+		}
+	}
+	
 	linphone_address_destroy(addr);
 	return md;
 }
@@ -314,7 +353,7 @@ LinphoneCall * linphone_call_new_incoming(LinphoneCore *lc, LinphoneAddress *fro
 	linphone_address_clean(from);
 	linphone_core_get_local_ip(lc,linphone_address_get_domain(from),call->localip);
 	linphone_call_init_common(call, from, to);
-	call->params.has_video=linphone_core_video_enabled(lc);
+	linphone_core_init_default_params(lc, &call->params);
 	call->localdesc=create_local_media_description (lc,call);
 	call->camera_active=call->params.has_video;
 	if (linphone_core_get_firewall_policy(call->core)==LinphonePolicyUseStun)
@@ -408,7 +447,7 @@ void linphone_call_set_state(LinphoneCall *call, LinphoneCallState cstate, const
 		if (call->state==LinphoneCallEnd || call->state==LinphoneCallError){
 			if (cstate!=LinphoneCallReleased){
 				ms_warning("Spurious call state change from %s to %s, ignored.",linphone_call_state_to_string(call->state),
-		           linphone_call_state_to_string(cstate));
+				   linphone_call_state_to_string(cstate));
 				return;
 			}
 		}
@@ -421,13 +460,13 @@ void linphone_call_set_state(LinphoneCall *call, LinphoneCallState cstate, const
 		}
 		if (cstate==LinphoneCallEnd || cstate==LinphoneCallError){
              if (call->reason==LinphoneReasonDeclined){
-                 call->log->status=LinphoneCallDeclined;
-             }
-            linphone_call_set_terminated (call);
+				call->log->status=LinphoneCallDeclined;
+			}
+			linphone_call_set_terminated (call);
+		}
+		if (cstate == LinphoneCallConnected) {
+			call->log->status=LinphoneCallSuccess;
 		}
-        if (cstate == LinphoneCallConnected) {
-            call->log->status=LinphoneCallSuccess;
-        }
 
 		if (lc->vtable.call_state_changed)
 			lc->vtable.call_state_changed(lc,call,cstate,message);
@@ -679,6 +718,15 @@ bool_t linphone_call_params_video_enabled(const LinphoneCallParams *cp){
 	return cp->has_video;
 }
 
+enum LinphoneMediaEncryption linphone_call_params_get_media_encryption(LinphoneCallParams *cp) {
+	return cp->media_encryption;
+}
+
+void linphone_call_params_set_media_encryption(LinphoneCallParams *cp, enum LinphoneMediaEncryption e) {
+	cp->media_encryption = e;
+}
+
+
 /**
  * Enable sending of real early media (during outgoing calls).
 **/
@@ -989,7 +1037,12 @@ static void linphone_call_start_audio_stream(LinphoneCall *call, const char *cna
 	LinphoneCore *lc=call->core;
 	int jitt_comp=lc->rtp_conf.audio_jitt_comp;
 	int used_pt=-1;
+	/* look for savp stream first */
 	const SalStreamDescription *stream=sal_media_description_find_stream(call->resultdesc,
+	    					SalProtoRtpSavp,SalAudio);
+	/* no savp audio stream, use avp */
+	if (!stream)
+		stream=sal_media_description_find_stream(call->resultdesc,
 	    					SalProtoRtpAvp,SalAudio);
 
 	if (stream && stream->dir!=SalStreamInactive && stream->port!=0){
@@ -1070,6 +1123,17 @@ static void linphone_call_start_audio_stream(LinphoneCall *call, const char *cna
 				/*transform the graph to connect it to the conference filter */
 				linphone_call_add_to_conf(call);
 			}
+			
+			if (stream->proto == SalProtoRtpSavp) {
+				const SalStreamDescription *local_st_desc=sal_media_description_find_stream(call->localdesc,
+	    					SalProtoRtpSavp,SalAudio);
+	    					
+				audio_stream_enable_strp(
+					call->audiostream, 
+					stream->crypto[0].algo,
+					local_st_desc->crypto[0].master_key,
+					stream->crypto[0].master_key);				
+			}
 		}else ms_warning("No audio stream accepted ?");
 	}
 }
@@ -1078,8 +1142,14 @@ static void linphone_call_start_video_stream(LinphoneCall *call, const char *cna
 #ifdef VIDEO_ENABLED
 	LinphoneCore *lc=call->core;
 	int used_pt=-1;
+	/* look for savp stream first */
 	const SalStreamDescription *vstream=sal_media_description_find_stream(call->resultdesc,
-		    					SalProtoRtpAvp,SalVideo);
+	    					SalProtoRtpSavp,SalVideo);
+	/* no savp audio stream, use avp */
+	if (!vstream)
+		vstream=sal_media_description_find_stream(call->resultdesc,
+	    					SalProtoRtpAvp,SalVideo);
+	    					
 	/* shutdown preview */
 	if (lc->previewstream!=NULL) {
 		video_preview_stop(lc->previewstream);
@@ -1136,6 +1206,18 @@ static void linphone_call_start_video_stream(LinphoneCall *call, const char *cna
 					used_pt, lc->rtp_conf.audio_jitt_comp, cam);
 				video_stream_set_rtcp_information(call->videostream, cname,LINPHONE_RTCP_SDES_TOOL);
 			}
+			
+			if (vstream->proto == SalProtoRtpSavp) {
+				const SalStreamDescription *local_st_desc=sal_media_description_find_stream(call->localdesc,
+	    					SalProtoRtpSavp,SalVideo);
+	    					
+				video_stream_enable_strp(
+					call->videostream, 
+					vstream->crypto[0].algo,
+					local_st_desc->crypto[0].master_key, 
+					vstream->crypto[0].master_key
+					);				
+			}
 		}else ms_warning("No video stream accepted.");
 	}else{
 		ms_warning("No valid video stream defined.");
diff --git a/coreapi/linphonecore.c b/coreapi/linphonecore.c
index 66334ea0f4e3022a7ac8062f6d6bb324dbcf2151..c4b5dbb6e91ea720f2a5234a7d3716b7495ff6be 100644
--- a/coreapi/linphonecore.c
+++ b/coreapi/linphonecore.c
@@ -23,6 +23,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 #include "private.h"
 
 #include <ortp/telephonyevents.h>
+#include <ortp/zrtp.h>
 #include "mediastreamer2/mediastream.h"
 #include "mediastreamer2/mseventqueue.h"
 #include "mediastreamer2/msvolume.h"
@@ -35,6 +36,10 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 #endif
 #endif
 
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
 /*#define UNSTANDART_GSM_11K 1*/
 
 #define ROOT_CA_FILE PACKAGE_DATA_DIR "/linphone/rootca.pem"
@@ -523,7 +528,7 @@ static void sip_config_read(LinphoneCore *lc)
 #else
 	sal_root_ca(lc->sal, lp_config_get_string(lc->config,"sip","root_ca", ROOT_CA_FILE));
 #endif
-
+	
 	tmp=lp_config_get_int(lc->config,"sip","guess_hostname",1);
 	linphone_core_set_guess_hostname(lc,tmp);
 
@@ -4260,7 +4265,7 @@ LinphoneGlobalState linphone_core_get_global_state(const LinphoneCore *lc){
 
 LinphoneCallParams *linphone_core_create_default_call_parameters(LinphoneCore *lc){
 	LinphoneCallParams *p=ms_new0(LinphoneCallParams,1);
-	p->has_video=linphone_core_video_enabled(lc);
+	linphone_core_init_default_params(lc, p);
 	return p;
 }
 
@@ -4363,7 +4368,6 @@ void linphone_core_set_zrtp_secrets_file(LinphoneCore *lc, const char* file){
 	lc->zrtp_secrets_cache=file ? ms_strdup(file) : NULL;
 }
 
-//				if (stringUri.equals(call.getRemoteAddress().asStringUriOnly())) {
 const LinphoneCall* linphone_core_find_call_from_uri(LinphoneCore *lc, const char *uri) {
 	if (uri == NULL) return NULL;
 	MSList *calls=lc->calls;
@@ -4410,3 +4414,59 @@ bool_t linphone_core_sound_resources_locked(LinphoneCore *lc){
 	}
 	return FALSE;
 }
+
+void linphone_core_set_srtp_enabled(LinphoneCore *lc, bool_t enabled) {
+	lp_config_set_int(lc->config,"sip","srtp",(int)enabled);
+}
+
+/**
+ * Returns whether a media encryption scheme is supported by the LinphoneCore engine
+**/
+bool_t linphone_core_media_encryption_supported(const LinphoneCore *lc, LinphoneMediaEncryption menc){
+	switch(menc){
+		case LinphoneMediaEncryptionSRTP:
+			return ortp_srtp_supported();
+		case LinphoneMediaEncryptionZRTP:
+			return ortp_zrtp_available();
+		case LinphoneMediaEncryptionNone:
+			return TRUE;
+	}
+	return FALSE;
+}
+
+void linphone_core_set_media_encryption(LinphoneCore *lc, enum LinphoneMediaEncryption menc) {
+	if (menc == LinphoneMediaEncryptionSRTP)
+		lp_config_set_string(lc->config,"sip","media_encryption","srtp");
+	else if (menc == LinphoneMediaEncryptionZRTP)
+		lp_config_set_string(lc->config,"sip","media_encryption","zrtp");
+	else
+		lp_config_set_string(lc->config,"sip","media_encryption","none");
+}
+
+LinphoneMediaEncryption linphone_core_get_media_encryption(LinphoneCore *lc) {
+	const char* menc = lp_config_get_string(lc->config, "sip", "media_encryption", NULL);
+	
+	if (menc == NULL)
+		return LinphoneMediaEncryptionNone;
+	else if (strcmp(menc, "srtp")==0)
+		return LinphoneMediaEncryptionSRTP;
+	else if (strcmp(menc, "zrtp")==0)
+		return LinphoneMediaEncryptionZRTP;
+	else
+		return LinphoneMediaEncryptionNone;
+}
+
+bool_t linphone_core_is_media_encryption_mandatory(LinphoneCore *lc) {
+	return (bool_t)lp_config_get_int(lc->config, "sip", "media_encryption_mandatory", 0);
+}
+
+void linphone_core_set_media_encryption_mandatory(LinphoneCore *lc, bool_t m) {
+	lp_config_set_int(lc->config, "sip", "media_encryption_mandatory", (int)m);
+}
+
+void linphone_core_init_default_params(LinphoneCore*lc, LinphoneCallParams *params) {
+	params->has_video=linphone_core_video_enabled(lc);
+	params->media_encryption=linphone_core_get_media_encryption(lc);	
+	params->in_conference=FALSE;
+}
+
diff --git a/coreapi/linphonecore.h b/coreapi/linphonecore.h
index 0f49a4593e561decd055992ab718fc1d9a404971..f4bb368c61240e1c40ed9ee7b10e1e69fa41ffe8 100644
--- a/coreapi/linphonecore.h
+++ b/coreapi/linphonecore.h
@@ -156,7 +156,13 @@ typedef struct _LinphoneCallLog{
 	struct _LinphoneCore *lc;
 } LinphoneCallLog;
 
+enum LinphoneMediaEncryption {
+	LinphoneMediaEncryptionNone,
+	LinphoneMediaEncryptionSRTP,
+	LinphoneMediaEncryptionZRTP
+};
 
+typedef enum LinphoneMediaEncryption LinphoneMediaEncryption;
 
 /*public: */
 void linphone_call_log_set_user_pointer(LinphoneCallLog *cl, void *up);
@@ -179,6 +185,8 @@ typedef struct _LinphoneCallParams LinphoneCallParams;
 LinphoneCallParams * linphone_call_params_copy(const LinphoneCallParams *cp);
 void linphone_call_params_enable_video(LinphoneCallParams *cp, bool_t enabled);
 bool_t linphone_call_params_video_enabled(const LinphoneCallParams *cp);
+enum LinphoneMediaEncryption linphone_call_params_get_media_encryption(LinphoneCallParams *cp);
+void linphone_call_params_set_media_encryption(LinphoneCallParams *cp, enum LinphoneMediaEncryption e);
 void linphone_call_params_enable_early_media_sending(LinphoneCallParams *cp, bool_t enabled);
 bool_t linphone_call_params_early_media_sending_enabled(const LinphoneCallParams *cp);
 bool_t linphone_call_params_local_conference_mode(const LinphoneCallParams *cp);
@@ -259,6 +267,10 @@ float linphone_call_get_play_volume(LinphoneCall *call);
 float linphone_call_get_record_volume(LinphoneCall *call);
 float linphone_call_get_current_quality(LinphoneCall *call);
 float linphone_call_get_average_quality(LinphoneCall *call);
+bool_t linphone_call_are_all_streams_encrypted(LinphoneCall *call);
+const char* linphone_call_get_authentication_token(LinphoneCall *call);
+bool_t linphone_call_get_authentication_token_verified(LinphoneCall *call);
+void linphone_call_send_vfu_request(LinphoneCall *call);
 void *linphone_call_get_user_pointer(LinphoneCall *call);
 void linphone_call_set_user_pointer(LinphoneCall *call, void *user_pointer);
 /**
@@ -1007,15 +1019,9 @@ LinphoneGlobalState linphone_core_get_global_state(const LinphoneCore *lc);
  */
 void linphone_core_refresh_registers(LinphoneCore* lc);
 
-
-void linphone_call_send_vfu_request(LinphoneCall *call);
-
 /* Path to the file storing secrets cache */
 void linphone_core_set_zrtp_secrets_file(LinphoneCore *lc, const char* file);
 
-bool_t linphone_call_are_all_streams_encrypted(LinphoneCall *call);
-const char* linphone_call_get_authentication_token(LinphoneCall *call);
-bool_t linphone_call_get_authentication_token_verified(LinphoneCall *call);
 
 const LinphoneCall* linphone_core_find_call_from_uri(LinphoneCore *lc, const char *uri);
 
@@ -1033,6 +1039,26 @@ int linphone_core_get_conference_size(LinphoneCore *lc);
 int linphone_core_get_max_calls(LinphoneCore *lc);
 bool_t linphone_core_sound_resources_locked(LinphoneCore *lc);
 
+bool_t linphone_core_media_encryption_supported(const LinphoneCore *lc, LinphoneMediaEncryption menc);
+
+/**
+ * Choose media encryption policy to be used for RTP packets
+ */
+void linphone_core_set_media_encryption(LinphoneCore *lc, enum LinphoneMediaEncryption menc);
+enum LinphoneMediaEncryption linphone_core_get_media_encryption(LinphoneCore *lc);
+
+bool_t linphone_core_is_media_encryption_mandatory(LinphoneCore *lc);
+/**
+ * Defines Linphone behaviour when encryption parameters negociation fails on outoing call.
+ * If set to TRUE call will fail; if set to FALSE will resend an INVITE with encryption disabled
+ */
+void linphone_core_set_media_encryption_mandatory(LinphoneCore *lc, bool_t m);
+
+/**
+ * Init call params using LinphoneCore's current configuration
+ */
+void linphone_core_init_default_params(LinphoneCore*lc, LinphoneCallParams *params);
+
 #ifdef __cplusplus
 }
 #endif
diff --git a/coreapi/linphonecore_jni.cc b/coreapi/linphonecore_jni.cc
index 6da09ef6b9ae9f549d0deba7c2174b2a1c52d599..4dab0d0a84ca2cf505cafc0b252b62306136ce23 100644
--- a/coreapi/linphonecore_jni.cc
+++ b/coreapi/linphonecore_jni.cc
@@ -775,7 +775,82 @@ extern "C" jint Java_org_linphone_core_LinphoneCoreImpl_startEchoCalibration(JNI
 
 }
 
+static enum LinphoneMediaEncryption media_encryption_string_to_enum(const char* menc) {
+	if (menc==NULL)
+		return LinphoneMediaEncryptionNone;
+	else if (strcasecmp(menc, "none")==0)
+		return LinphoneMediaEncryptionNone;
+	else if (strcasecmp(menc, "srtp")==0)
+		return LinphoneMediaEncryptionSRTP;
+	else if (strcasecmp(menc, "zrtp")==0)
+		return LinphoneMediaEncryptionZRTP;
+	else
+		return LinphoneMediaEncryptionNone;
+}
+
+static jstring media_encryption_enum_to_jstring(JNIEnv*  env, enum LinphoneMediaEncryption enc) {
+	switch (enc) {
+		case LinphoneMediaEncryptionSRTP:
+			return env->NewStringUTF("srtp");
+		case LinphoneMediaEncryptionZRTP:
+			return env->NewStringUTF("zrtp");
+		case LinphoneMediaEncryptionNone:
+			return env->NewStringUTF("none");
+		default:
+			return NULL;
+	}
+}
 
+extern "C" jstring Java_org_linphone_core_LinphoneCoreImpl_getMediaEncryption(JNIEnv*  env
+																			,jobject  thiz
+																			,jlong lc
+																			) {
+	return media_encryption_enum_to_jstring(env,
+		linphone_core_get_media_encryption((LinphoneCore*)lc));
+}
+extern "C" void Java_org_linphone_core_LinphoneCoreImpl_setMediaEncryption(JNIEnv*  env
+																			,jobject  thiz
+																			,jlong lc
+																			,jstring jmenc) {
+	const char* menc = jmenc?env->GetStringUTFChars(jmenc, NULL):NULL;
+	
+	linphone_core_set_media_encryption((LinphoneCore*)lc,
+		media_encryption_string_to_enum(menc));
+
+	if (menc) env->ReleaseStringUTFChars(jmenc, menc);
+}
+
+extern "C" jstring Java_org_linphone_core_LinphoneCallParamsImpl_getMediaEncryption(JNIEnv*  env
+																			,jobject  thiz
+																			,jlong lc
+																			) {
+	return media_encryption_enum_to_jstring(env,
+		linphone_call_params_get_media_encryption((LinphoneCallParams*)lc));
+}
+extern "C" void Java_org_linphone_core_LinphoneCallParamsImpl_setMediaEncryption(JNIEnv*  env
+																			,jobject  thiz
+																			,jlong lc
+																			,jstring jmenc) {
+	const char* menc = jmenc?env->GetStringUTFChars(jmenc, NULL):NULL;
+	linphone_call_params_set_media_encryption((LinphoneCallParams*)lc,
+		media_encryption_string_to_enum(menc));
+	if (menc) env->ReleaseStringUTFChars(jmenc, menc);
+}
+
+extern "C" jboolean Java_org_linphone_core_LinphoneCoreImpl_getMediaEncryptionMandatory(JNIEnv*  env
+																			,jobject  thiz
+																			,jlong lc
+																			) {
+	return linphone_core_is_media_encryption_mandatory((LinphoneCore*)lc);
+}
+
+extern "C" void Java_org_linphone_core_LinphoneCoreImpl_setMediaEncryptionMandatory(JNIEnv*  env
+																			,jobject  thiz
+																			,jlong lc
+																			, jboolean yesno
+																			) {
+	linphone_core_set_media_encryption_mandatory((LinphoneCore*)lc, yesno);
+}
 
 //ProxyConfig
 
diff --git a/coreapi/offeranswer.c b/coreapi/offeranswer.c
index 3e054508b1aa5a863287569b5ed9730957f49619..ab213a2391b591c3013603e26657145a6538d256 100644
--- a/coreapi/offeranswer.c
+++ b/coreapi/offeranswer.c
@@ -128,6 +128,31 @@ static MSList *match_payloads(const MSList *local, const MSList *remote, bool_t
 	return res;
 }
 
+static bool_t match_crypto_algo(const SalSrtpCryptoAlgo* local, const SalSrtpCryptoAlgo* remote, 
+	SalSrtpCryptoAlgo* result, bool_t use_local_key) {
+	int i,j;
+	for(i=0; i<SAL_CRYPTO_ALGO_MAX; i++) {
+		if (remote[i].algo == 0)
+			break;
+			
+		for(j=0; j<SAL_CRYPTO_ALGO_MAX; j++) {
+			if (remote[i].algo == local[j].algo) {
+				result->algo = remote[i].algo;
+				if (use_local_key) {
+					strncpy(result->master_key, local[j].master_key, 41);
+					result->tag = local[j].tag;
+				} else {
+					strncpy(result->master_key, remote[j].master_key, 41);
+					result->tag = remote[j].tag;
+				}
+				result->master_key[40] = '\0';
+				return TRUE;
+			}
+		}
+	}
+	return FALSE;
+}
+
 
 
 static SalStreamDir compute_dir_outgoing(SalStreamDir local, SalStreamDir answered){
@@ -174,7 +199,7 @@ static void initiate_outgoing(const SalStreamDescription *local_offer,
     					SalStreamDescription *result){
 	if (remote_answer->port!=0)
 		result->payloads=match_payloads(local_offer->payloads,remote_answer->payloads,TRUE,FALSE);
-	result->proto=local_offer->proto;
+	result->proto=remote_answer->proto;
 	result->type=local_offer->type;
 	result->dir=compute_dir_outgoing(local_offer->dir,remote_answer->dir);
 
@@ -186,6 +211,12 @@ static void initiate_outgoing(const SalStreamDescription *local_offer,
 	}else{
 		result->port=0;
 	}
+	if (result->proto == SalProtoRtpSavp) {
+		/* verify crypto algo */
+		memset(result->crypto, 0, sizeof(result->crypto));
+		if (!match_crypto_algo(local_offer->crypto, remote_answer->crypto, &result->crypto[0], FALSE))
+			result->port = 0;
+	}
 }
 
 
@@ -193,7 +224,7 @@ static void initiate_incoming(const SalStreamDescription *local_cap,
     					const SalStreamDescription *remote_offer,
     					SalStreamDescription *result, bool_t one_matching_codec){
 	result->payloads=match_payloads(local_cap->payloads,remote_offer->payloads, FALSE, one_matching_codec);
-	result->proto=local_cap->proto;
+	result->proto=remote_offer->proto;
 	result->type=local_cap->type;
 	result->dir=compute_dir_incoming(local_cap->dir,remote_offer->dir);
 	if (result->payloads && !only_telephone_event(result->payloads)){
@@ -205,6 +236,13 @@ static void initiate_incoming(const SalStreamDescription *local_cap,
 	}else{
 		result->port=0;
 	}
+	if (result->proto == SalProtoRtpSavp) {
+		/* select crypto algo */
+		memset(result->crypto, 0, sizeof(result->crypto));
+		if (!match_crypto_algo(local_cap->crypto, remote_offer->crypto, &result->crypto[0], TRUE))
+			result->port = 0; 
+		
+	}
 }
 
 /**
@@ -215,6 +253,7 @@ int offer_answer_initiate_outgoing(const SalMediaDescription *local_offer,
 									const SalMediaDescription *remote_answer,
     							SalMediaDescription *result){
     int i,j;
+    
 	const SalStreamDescription *ls,*rs;
     for(i=0,j=0;i<local_offer->nstreams;++i){
 		ms_message("Processing for stream %i",i);
@@ -246,10 +285,18 @@ int offer_answer_initiate_incoming(const SalMediaDescription *local_capabilities
     for(i=0;i<remote_offer->nstreams;++i){
 		rs=&remote_offer->streams[i];
 		ms_message("Processing for stream %i",i);
+		
 		ls=sal_media_description_find_stream((SalMediaDescription*)local_capabilities,rs->proto,rs->type);
+		ms_message("remote proto: %s => %p", (rs->proto == SalProtoRtpAvp)?"AVP":"SAVP", ls);
+		/* if matching failed, and remote proposes Avp only, ask for local Savp streams */ 
+		if (!ls && rs->proto == SalProtoRtpAvp) {
+			ls=sal_media_description_find_stream((SalMediaDescription*)local_capabilities,SalProtoRtpSavp,rs->type);
+			ms_message("retry with AVP => %p", ls);
+		}
 		if (ls){
     		initiate_incoming(ls,rs,&result->streams[i],one_matching_codec);
-		} else {
+		}
+		else {
 			/* create an inactive stream for the answer, as there where no matching stream a local capability */
 			result->streams[i].dir=SalStreamInactive;
 			result->streams[i].port=0;
diff --git a/coreapi/private.h b/coreapi/private.h
index 49c7c4016703525e135b778cb41df1e99fe58464..216d26f15d1147ed70e9f35fa375f362474c6d76 100644
--- a/coreapi/private.h
+++ b/coreapi/private.h
@@ -57,7 +57,6 @@
 #endif
 #endif
 
-
 struct _LinphoneCallParams{
 	LinphoneCall *referer; /*in case this call creation is consecutive to an incoming transfer, this points to the original call */
 	int audio_bw; /* bandwidth limit for audio stream */
@@ -65,6 +64,7 @@ struct _LinphoneCallParams{
 	bool_t real_early_media; /*send real media even during early media (for outgoing calls)*/
 	bool_t in_conference; /*in conference mode */
 	bool_t pad;
+	enum LinphoneMediaEncryption media_encryption;
 };
 
 struct _LinphoneCall
diff --git a/coreapi/sal.h b/coreapi/sal.h
index b2a0ecd595f126b1225c0d4eddd3cd1e4376546f..86a0fb86b6042688a8b6ea4788f0484527335346 100644
--- a/coreapi/sal.h
+++ b/coreapi/sal.h
@@ -112,6 +112,15 @@ typedef struct SalEndpointCandidate{
 
 #define SAL_ENDPOINT_CANDIDATE_MAX 2
 
+typedef struct SalSrtpCryptoAlgo {
+	unsigned int tag;
+	enum ortp_srtp_crypto_suite_t algo;
+	/* 41= 40 max(key_length for all algo) + '\0' */
+	char master_key[41];
+} SalSrtpCryptoAlgo;
+
+#define SAL_CRYPTO_ALGO_MAX 4
+
 typedef struct SalStreamDescription{
 	SalMediaProto proto;
 	SalStreamType type;
@@ -123,6 +132,7 @@ typedef struct SalStreamDescription{
 	int ptime;
 	SalEndpointCandidate candidates[SAL_ENDPOINT_CANDIDATE_MAX];
 	SalStreamDir dir;
+	SalSrtpCryptoAlgo crypto[SAL_CRYPTO_ALGO_MAX];
 } SalStreamDescription;
 
 #define SAL_MEDIA_DESCRIPTION_MAX_STREAMS 4
diff --git a/coreapi/sal_eXosip2.c b/coreapi/sal_eXosip2.c
index 772997b6b67b876bcb938ac3fe07b2494454b28d..5314bb28160b83b06ce7e4bbda891b710034fe30 100644
--- a/coreapi/sal_eXosip2.c
+++ b/coreapi/sal_eXosip2.c
@@ -514,12 +514,18 @@ static void sdp_process(SalOp *h){
 		 It should contains media parameters constraint from the remote offer, not our response*/
 		strcpy(h->result->addr,h->base.remote_media->addr);
 		h->result->bandwidth=h->base.remote_media->bandwidth;
+		
+		//remplacer la cle
 		for(i=0;i<h->result->nstreams;++i){
 			if (h->result->streams[i].port>0){
 				strcpy(h->result->streams[i].addr,h->base.remote_media->streams[i].addr);
 				h->result->streams[i].ptime=h->base.remote_media->streams[i].ptime;
 				h->result->streams[i].bandwidth=h->base.remote_media->streams[i].bandwidth;
 				h->result->streams[i].port=h->base.remote_media->streams[i].port;
+				
+				if (h->result->streams[i].proto == SalProtoRtpSavp) {
+					h->result->streams[i].crypto[0] = h->base.remote_media->streams[i].crypto[0]; 
+				}
 			}
 		}
 	}
@@ -546,6 +552,9 @@ int sal_call(SalOp *h, const char *from, const char *to){
 	sal_op_set_from(h,from);
 	sal_op_set_to(h,to);
 	sal_exosip_fix_route(h);
+	
+	h->terminated = FALSE;
+
 	route = sal_op_get_route(h);
 	err=eXosip_call_build_initial_invite(&invite,to,from,route,"Phone call");
 	if (err!=0){
diff --git a/coreapi/sal_eXosip2_sdp.c b/coreapi/sal_eXosip2_sdp.c
index 5160777a782ee4f88f07a32eb0046082578f502a..f67fb9cfd714e1f520534b39ac41fd6a2ea49e4d 100644
--- a/coreapi/sal_eXosip2_sdp.c
+++ b/coreapi/sal_eXosip2_sdp.c
@@ -234,9 +234,47 @@ static void add_line(sdp_message_t *msg, int lineno, const SalStreamDescription
 			      osip_strdup ("IN"), inet6 ? osip_strdup ("IP6") : osip_strdup ("IP4"),
 			      osip_strdup (addr), NULL, NULL);
 	}
-	sdp_message_m_media_add (msg, osip_strdup (mt),
-				 int_2char (port), NULL,
-				 osip_strdup ("RTP/AVP"));
+	
+	if (desc->proto == SalProtoRtpSavp) {
+		int i;
+		
+		sdp_message_m_media_add (msg, osip_strdup (mt),
+					 int_2char (port), NULL,
+					 osip_strdup ("RTP/SAVP"));
+       
+		/* add crypto lines */
+		for(i=0; i<SAL_CRYPTO_ALGO_MAX; i++) {
+			char buffer[1024];
+			switch (desc->crypto[i].algo) {
+				case AES_128_SHA1_80:
+					snprintf(buffer, 1024, "%d %s inline:%s",
+						desc->crypto[i].tag, "AES_CM_128_HMAC_SHA1_80", desc->crypto[i].master_key);
+					sdp_message_a_attribute_add(msg, lineno, osip_strdup("crypto"),
+						osip_strdup(buffer));
+					break;
+				case AES_128_SHA1_32:
+					snprintf(buffer, 1024, "%d %s inline:%s",
+						desc->crypto[i].tag, "AES_CM_128_HMAC_SHA1_32", desc->crypto[i].master_key);
+					sdp_message_a_attribute_add(msg, lineno, osip_strdup("crypto"),
+						osip_strdup(buffer));
+					break;
+				case AES_128_NO_AUTH:
+					ms_warning("Unsupported crypto suite: AES_128_NO_AUTH");
+					break;
+				case NO_CIPHER_SHA1_80:
+					ms_warning("Unsupported crypto suite: NO_CIPHER_SHA1_80");
+					break; 
+				default:
+					i = SAL_CRYPTO_ALGO_MAX;
+			}
+		}
+		
+	} else {
+		sdp_message_m_media_add (msg, osip_strdup (mt),
+					 int_2char (port), NULL,
+					 osip_strdup ("RTP/AVP"));
+		
+	}
 	if (desc->bandwidth>0) sdp_message_b_bandwidth_add (msg, lineno, osip_strdup ("AS"),
 				     int_2char(desc->bandwidth));
 	if (desc->ptime>0) sdp_message_a_attribute_add(msg,lineno,osip_strdup("ptime"),
@@ -356,7 +394,7 @@ int sdp_to_media_description(sdp_message_t *msg, SalMediaDescription *desc){
 		for(j=0;(sbw=sdp_message_bandwidth_get(msg,i,j))!=NULL;++j){
 			if (strcasecmp(sbw->b_bwtype,"AS")==0) stream->bandwidth=atoi(sbw->b_bandwidth);
 		}
-		stream->dir=_sdp_message_get_mline_dir(msg,i);
+		stream->dir=_sdp_message_get_mline_dir(msg,i);		
 		/* for each payload type */
 		for (j=0;((number=sdp_message_m_payload_get (msg, i,j)) != NULL); j++){
 			const char *rtpmap,*fmtp;
@@ -374,6 +412,49 @@ int sdp_to_media_description(sdp_message_t *msg, SalMediaDescription *desc){
 					pt->send_fmtp ? pt->send_fmtp : "");
 			}
 		}
+		
+		/* read crypto lines if any */
+		if (stream->proto == SalProtoRtpSavp) {
+			int k, valid_count = 0;
+			sdp_attribute_t *attr;
+				
+			memset(&stream->crypto, 0, sizeof(stream->crypto));
+			for (k=0;valid_count < SAL_CRYPTO_ALGO_MAX && (attr=sdp_message_attribute_get(msg,i,k))!=NULL;k++){
+				char tmp[256], tmp2[256];
+				if (keywordcmp("crypto",attr->a_att_field)==0 && attr->a_att_value!=NULL){
+					int nb = sscanf(attr->a_att_value, "%d %256s inline:%256s",
+						&stream->crypto[valid_count].tag,
+						tmp,
+						tmp2);
+						ms_message("Found valid crypto line (tag:%d algo:'%s' key:'%s'", 
+								stream->crypto[valid_count].tag, 
+								tmp, 
+								tmp2);
+					if (nb == 3) {
+						if (strcmp(tmp, "AES_CM_128_HMAC_SHA1_80") == 0)
+							stream->crypto[valid_count].algo = AES_128_SHA1_80;
+						else if (strcmp(tmp, "AES_CM_128_HMAC_SHA1_32") == 0)
+							stream->crypto[valid_count].algo = AES_128_SHA1_32;
+						else {
+							ms_warning("Failed to parse crypto-algo: '%s'", tmp);
+							stream->crypto[valid_count].algo = 0;
+						}
+						if (stream->crypto[valid_count].algo) {
+							strncpy(stream->crypto[valid_count].master_key, tmp2, 41);
+							stream->crypto[valid_count].master_key[40] = '\0';
+							ms_message("Found valid crypto line (tag:%d algo:'%s' key:'%s'", 
+								stream->crypto[valid_count].tag, 
+								tmp, 
+								stream->crypto[valid_count].master_key);
+							valid_count++;
+						}
+					} else {
+						ms_warning("sdp has a strange a= line (%s) nb=%i",attr->a_att_value,nb);
+					}
+				}
+			}
+			ms_message("Found: %d valid crypto lines", valid_count);
+		}
 	}
 	desc->nstreams=i;
 	return 0;
diff --git a/gtk/parameters.ui b/gtk/parameters.ui
index 3bec2e63ed2fb1be6e368bac06afe80c868f0282..d853a4bb019c8de96f5b4da71747b6ab4ae41305 100644
--- a/gtk/parameters.ui
+++ b/gtk/parameters.ui
@@ -296,116 +296,129 @@
                         <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
                         <property name="left_padding">12</property>
                         <child>
-                          <object class="GtkVBox" id="vbox6">
+                          <object class="GtkTable" id="table1">
                             <property name="visible">True</property>
                             <property name="can_focus">False</property>
+                            <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
+                            <property name="n_rows">4</property>
+                            <property name="n_columns">2</property>
                             <child>
-                              <placeholder/>
+                              <object class="GtkComboBox" id="proto_combo">
+                                <property name="visible">True</property>
+                                <property name="can_focus">False</property>
+                                <property name="model">model8</property>
+                                <child>
+                                  <object class="GtkCellRendererText" id="renderer1"/>
+                                  <attributes>
+                                    <attribute name="text">0</attribute>
+                                  </attributes>
+                                </child>
+                              </object>
+                            </child>
+                            <child>
+                              <object class="GtkSpinButton" id="proto_port">
+                                <property name="visible">True</property>
+                                <property name="can_focus">True</property>
+                                <property name="invisible_char">•</property>
+                                <property name="invisible_char_set">True</property>
+                                <property name="primary_icon_activatable">False</property>
+                                <property name="secondary_icon_activatable">False</property>
+                                <property name="adjustment">adjustment7</property>
+                              </object>
+                              <packing>
+                                <property name="left_attach">1</property>
+                                <property name="right_attach">2</property>
+                              </packing>
+                            </child>
+                            <child>
+                              <object class="GtkSpinButton" id="video_rtp_port">
+                                <property name="visible">True</property>
+                                <property name="can_focus">True</property>
+                                <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
+                                <property name="invisible_char">•</property>
+                                <property name="invisible_char_set">True</property>
+                                <property name="primary_icon_activatable">False</property>
+                                <property name="secondary_icon_activatable">False</property>
+                                <property name="adjustment">adjustment2</property>
+                                <signal name="value-changed" handler="linphone_gtk_video_port_changed" swapped="no"/>
+                              </object>
+                              <packing>
+                                <property name="left_attach">1</property>
+                                <property name="right_attach">2</property>
+                                <property name="top_attach">1</property>
+                                <property name="bottom_attach">2</property>
+                              </packing>
                             </child>
                             <child>
-                              <object class="GtkTable" id="table1">
+                              <object class="GtkSpinButton" id="audio_rtp_port">
+                                <property name="visible">True</property>
+                                <property name="can_focus">True</property>
+                                <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
+                                <property name="invisible_char">•</property>
+                                <property name="invisible_char_set">True</property>
+                                <property name="primary_icon_activatable">False</property>
+                                <property name="secondary_icon_activatable">False</property>
+                                <property name="adjustment">adjustment3</property>
+                                <signal name="value-changed" handler="linphone_gtk_audio_port_changed" swapped="no"/>
+                              </object>
+                              <packing>
+                                <property name="left_attach">1</property>
+                                <property name="right_attach">2</property>
+                                <property name="top_attach">2</property>
+                                <property name="bottom_attach">3</property>
+                              </packing>
+                            </child>
+                            <child>
+                              <object class="GtkLabel" id="label7">
                                 <property name="visible">True</property>
                                 <property name="can_focus">False</property>
                                 <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
-                                <property name="n_rows">3</property>
-                                <property name="n_columns">2</property>
-                                <child>
-                                  <object class="GtkComboBox" id="proto_combo">
-                                    <property name="visible">True</property>
-                                    <property name="can_focus">False</property>
-                                    <property name="model">model8</property>
-                                    <child>
-                                      <object class="GtkCellRendererText" id="renderer1"/>
-                                      <attributes>
-                                        <attribute name="text">0</attribute>
-                                      </attributes>
-                                    </child>
-                                  </object>
-                                </child>
-                                <child>
-                                  <object class="GtkSpinButton" id="proto_port">
-                                    <property name="visible">True</property>
-                                    <property name="can_focus">True</property>
-                                    <property name="invisible_char">•</property>
-                                    <property name="invisible_char_set">True</property>
-                                    <property name="primary_icon_activatable">False</property>
-                                    <property name="secondary_icon_activatable">False</property>
-                                    <property name="adjustment">adjustment7</property>
-                                  </object>
-                                  <packing>
-                                    <property name="left_attach">1</property>
-                                    <property name="right_attach">2</property>
-                                  </packing>
-                                </child>
-                                <child>
-                                  <object class="GtkSpinButton" id="video_rtp_port">
-                                    <property name="visible">True</property>
-                                    <property name="can_focus">True</property>
-                                    <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
-                                    <property name="invisible_char">•</property>
-                                    <property name="invisible_char_set">True</property>
-                                    <property name="primary_icon_activatable">False</property>
-                                    <property name="secondary_icon_activatable">False</property>
-                                    <property name="adjustment">adjustment2</property>
-                                    <signal name="value-changed" handler="linphone_gtk_video_port_changed" swapped="no"/>
-                                  </object>
-                                  <packing>
-                                    <property name="left_attach">1</property>
-                                    <property name="right_attach">2</property>
-                                    <property name="top_attach">1</property>
-                                    <property name="bottom_attach">2</property>
-                                  </packing>
-                                </child>
-                                <child>
-                                  <object class="GtkSpinButton" id="audio_rtp_port">
-                                    <property name="visible">True</property>
-                                    <property name="can_focus">True</property>
-                                    <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
-                                    <property name="invisible_char">•</property>
-                                    <property name="invisible_char_set">True</property>
-                                    <property name="primary_icon_activatable">False</property>
-                                    <property name="secondary_icon_activatable">False</property>
-                                    <property name="adjustment">adjustment3</property>
-                                    <signal name="value-changed" handler="linphone_gtk_audio_port_changed" swapped="no"/>
-                                  </object>
-                                  <packing>
-                                    <property name="left_attach">1</property>
-                                    <property name="right_attach">2</property>
-                                    <property name="top_attach">2</property>
-                                    <property name="bottom_attach">3</property>
-                                  </packing>
-                                </child>
-                                <child>
-                                  <object class="GtkLabel" id="label7">
-                                    <property name="visible">True</property>
-                                    <property name="can_focus">False</property>
-                                    <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
-                                    <property name="label" translatable="yes">Video RTP/UDP:</property>
-                                    <property name="justify">right</property>
-                                  </object>
-                                  <packing>
-                                    <property name="top_attach">1</property>
-                                    <property name="bottom_attach">2</property>
-                                  </packing>
-                                </child>
-                                <child>
-                                  <object class="GtkLabel" id="label6">
-                                    <property name="visible">True</property>
-                                    <property name="can_focus">False</property>
-                                    <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
-                                    <property name="label" translatable="yes">Audio RTP/UDP:</property>
-                                    <property name="justify">right</property>
-                                  </object>
-                                  <packing>
-                                    <property name="top_attach">2</property>
-                                    <property name="bottom_attach">3</property>
-                                  </packing>
-                                </child>
+                                <property name="label" translatable="yes">Video RTP/UDP:</property>
+                                <property name="justify">right</property>
                               </object>
                               <packing>
-                                <property name="expand">True</property>
-                                <property name="fill">True</property>
-                                <property name="position">1</property>
+                                <property name="top_attach">1</property>
+                                <property name="bottom_attach">2</property>
+                              </packing>
+                            </child>
+                            <child>
+                              <object class="GtkLabel" id="label6">
+                                <property name="visible">True</property>
+                                <property name="can_focus">False</property>
+                                <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
+                                <property name="label" translatable="yes">Audio RTP/UDP:</property>
+                                <property name="justify">right</property>
+                              </object>
+                              <packing>
+                                <property name="top_attach">2</property>
+                                <property name="bottom_attach">3</property>
+                              </packing>
+                            </child>
+                            <child>
+                              <object class="GtkLabel" id="media_encryption_label">
+                                <property name="visible">True</property>
+                                <property name="can_focus">False</property>
+                                <property name="label" translatable="yes">Media encryption type</property>
+                              </object>
+                              <packing>
+                                <property name="top_attach">3</property>
+                                <property name="bottom_attach">4</property>
+                              </packing>
+                            </child>
+                            <child>
+                              <object class="GtkComboBoxText" id="media_encryption_combo">
+                                <property name="visible">True</property>
+                                <property name="can_focus">False</property>
+                                <property name="active">0</property>
+                                <items>
+                                  <item translatable="yes">None</item>
+                                </items>
+                              </object>
+                              <packing>
+                                <property name="left_attach">1</property>
+                                <property name="right_attach">2</property>
+                                <property name="top_attach">3</property>
+                                <property name="bottom_attach">4</property>
                               </packing>
                             </child>
                           </object>
@@ -1202,6 +1215,9 @@
                                     <property name="visible">True</property>
                                     <property name="can_focus">True</property>
                                     <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
+                                    <child internal-child="selection">
+                                      <object class="GtkTreeSelection" id="treeview-selection1"/>
+                                    </child>
                                   </object>
                                 </child>
                               </object>
@@ -1620,6 +1636,9 @@ virtual network !</property>
                                         <property name="can_focus">True</property>
                                         <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
                                         <property name="has_tooltip">True</property>
+                                        <child internal-child="selection">
+                                          <object class="GtkTreeSelection" id="treeview-selection2"/>
+                                        </child>
                                       </object>
                                     </child>
                                   </object>
diff --git a/gtk/propertybox.c b/gtk/propertybox.c
index c7c3d7cd7abd771d136e229897791c66e5ae8292..aece58048600ea0cc3e0cd5cc3ef525df797dae5 100644
--- a/gtk/propertybox.c
+++ b/gtk/propertybox.c
@@ -803,6 +803,56 @@ void linphone_gtk_ui_level_toggled(GtkWidget *w) {
 	linphone_gtk_ui_level_adapt(top);
 }
 
+static void linphone_gtk_media_encryption_changed(GtkWidget *combo){
+	const char *selected=gtk_combo_box_get_active_text(GTK_COMBO_BOX(combo));
+	LinphoneCore *lc=linphone_gtk_get_core();
+	if (selected!=NULL){
+		if (strcasecmp(selected,"SRTP")==0)
+			linphone_core_set_media_encryption(lc,LinphoneMediaEncryptionSRTP);
+		else if (strcasecmp(selected,"ZRTP")==0)
+			linphone_core_set_media_encryption(lc,LinphoneMediaEncryptionZRTP);
+		else linphone_core_set_media_encryption(lc,LinphoneMediaEncryptionNone);
+	}else g_warning("gtk_combo_box_get_active_text() returned NULL");
+}
+
+static void linphone_gtk_show_media_encryption(GtkWidget *pb){
+	LinphoneCore *lc=linphone_gtk_get_core();
+	GtkWidget *combo=linphone_gtk_get_widget(pb,"media_encryption_combo");
+	bool_t no_enc=TRUE;
+	int srtp_id=-1,zrtp_id=-1;
+
+	if (linphone_core_media_encryption_supported(lc,LinphoneMediaEncryptionSRTP)){
+		gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo),_("SRTP"));
+		srtp_id=1;
+		no_enc=FALSE;
+	}
+	if (linphone_core_media_encryption_supported(lc,LinphoneMediaEncryptionZRTP)){
+		gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo),_("ZRTP"));
+		no_enc=FALSE;
+		if (srtp_id!=-1) zrtp_id=2;
+		else zrtp_id=1;
+	}
+	if (no_enc){
+		/*hide this setting*/
+		gtk_widget_hide(combo);
+		gtk_widget_hide(linphone_gtk_get_widget(pb,"media_encryption_label"));
+	}else{
+		LinphoneMediaEncryption menc=linphone_core_get_media_encryption(lc);
+		switch(menc){
+			case LinphoneMediaEncryptionNone:
+				gtk_combo_box_set_active(GTK_COMBO_BOX(combo),0);
+			break;
+			case LinphoneMediaEncryptionSRTP:
+				if (srtp_id!=-1) gtk_combo_box_set_active(GTK_COMBO_BOX(combo),srtp_id);
+			break;
+			case LinphoneMediaEncryptionZRTP:
+				if (zrtp_id!=-1) gtk_combo_box_set_active(GTK_COMBO_BOX(combo),zrtp_id);
+			break;
+		}
+		g_signal_connect(G_OBJECT(combo),"changed",(GCallback)linphone_gtk_media_encryption_changed,NULL);
+	}
+}
+
 void linphone_gtk_show_parameters(void){
 	GtkWidget *pb=linphone_gtk_create_window("parameters");
 	LinphoneCore *lc=linphone_gtk_get_core();
@@ -841,6 +891,8 @@ void linphone_gtk_show_parameters(void){
 	gtk_spin_button_set_value(GTK_SPIN_BUTTON(linphone_gtk_get_widget(pb,"video_rtp_port")),
 				linphone_core_get_video_port(lc));
 
+	linphone_gtk_show_media_encryption(pb);
+	
 	tmp=linphone_core_get_nat_address(lc);
 	if (tmp) gtk_entry_set_text(GTK_ENTRY(linphone_gtk_get_widget(pb,"nat_address")),tmp);
 	tmp=linphone_core_get_stun_server(lc);
diff --git a/java/common/org/linphone/core/LinphoneCallParams.java b/java/common/org/linphone/core/LinphoneCallParams.java
index 78a63d3fa9fd495fad08b3862af2507d3b275edf..c3bdc43ec8439e18da622cb2ba5068b154a7e038 100644
--- a/java/common/org/linphone/core/LinphoneCallParams.java
+++ b/java/common/org/linphone/core/LinphoneCallParams.java
@@ -35,4 +35,15 @@ public interface LinphoneCallParams {
 	 */
 	void setAudioBandwidth(int value);
 	
+	/**
+	 * return selected media encryption
+	 * @return 'none', 'srtp' or 'zrtp'
+	 */
+	String getMediaEncryption();
+	/**
+	 * set media encryption (rtp) to use
+	 * @params menc: 'none', 'srtp' or 'zrtp'
+	 */
+	void setMediaEnctyption(String menc);
+	
 }
diff --git a/java/common/org/linphone/core/LinphoneCore.java b/java/common/org/linphone/core/LinphoneCore.java
index fcd041dc8a6c5745fef27c0abd5d7ce0aee72f0b..0bea6f60c4d1ffefcf2d611b90b29a466c31600c 100644
--- a/java/common/org/linphone/core/LinphoneCore.java
+++ b/java/common/org/linphone/core/LinphoneCore.java
@@ -634,4 +634,22 @@ public interface LinphoneCore {
 	 * @return
 	 */
 	boolean soundResourcesLocked();
+	/**
+	 * set media encryption (rtp) to use
+	 * @params menc: 'none', 'srtp' or 'zrtp'
+	 */
+	void setMediaEncryption(String menc);
+	/**
+	 * return selected media encryption
+	 * @return 'none', 'srtp' or 'zrtp'
+	 */
+	String getMediaEncryption();
+/**
+	 * Set media encryption required for outgoing calls
+	 */
+	void setMediaEncryptionMandatory(boolean yesno);
+	/**
+	 * @return if media encryption is required for ougtoing calls
+	 */
+	boolean isMediaEncryptionMandatory();
 }
diff --git a/oRTP b/oRTP
index 7606207905bd3dc661e68576097adce471916697..fd6d3f04884a51d20fdd02e0d73b41bb9bd28495 160000
--- a/oRTP
+++ b/oRTP
@@ -1 +1 @@
-Subproject commit 7606207905bd3dc661e68576097adce471916697
+Subproject commit fd6d3f04884a51d20fdd02e0d73b41bb9bd28495