Index: pjproject/trunk/aconfigure
===================================================================
--- pjproject/trunk/aconfigure	(revision 5185)
+++ pjproject/trunk/aconfigure	(revision 5186)
@@ -639,4 +639,6 @@
 openssl_h_present
 ac_no_ssl
+ac_webrtc_ldflags
+ac_webrtc_cflags
 ac_libyuv_ldflags
 ac_libyuv_cflags
@@ -801,4 +803,6 @@
 with_libyuv
 enable_libyuv
+with_webrtc
+enable_webrtc
 enable_ipp
 with_ipp
@@ -1466,4 +1470,5 @@
   --disable-openh264      Disable OpenH264 (default: not disabled)
   --disable-libyuv        Exclude libyuv in the build
+  --disable-webrtc        Exclude webrtc in the build
   --enable-ipp            Enable Intel IPP support. Specify the Intel IPP
                           package and samples location using IPPROOT and
@@ -1506,4 +1511,5 @@
   --with-openh264=DIR     Specify alternate OpenH264 prefix
   --with-libyuv=DIR       Specify alternate libyuv prefix
+  --with-webrtc=DIR       Specify alternate WebRtc prefix
   --with-ipp=DIR          Specify the Intel IPP location
   --with-ipp-samples=DIR  Specify the Intel IPP samples location
@@ -7323,4 +7329,121 @@
 
 
+
+# Check whether --with-webrtc was given.
+if test "${with_webrtc+set}" = set; then :
+  withval=$with_webrtc;
+else
+  with_webrtc=no
+
+fi
+
+
+if test "x$ac_cross_compile" != "x" -a "x$with_webrtc" = "xno"; then
+    enable_webrtc=no
+fi
+
+
+
+# Check whether --enable-webrtc was given.
+if test "${enable_webrtc+set}" = set; then :
+  enableval=$enable_webrtc; if test "$enable_webrtc" = "no"; then
+		{ $as_echo "$as_me:${as_lineno-$LINENO}: result: Checking if webrtc is disabled...yes" >&5
+$as_echo "Checking if webrtc is disabled...yes" >&6; }
+	       fi
+else
+
+		  if test "x$with_webrtc" != "xno" -a "x$with_webrtc" != "x"; then
+		        WEBRTC_PREFIX=$with_webrtc
+		  	WEBRTC_CFLAGS="-I$WEBRTC_PREFIX/src"
+
+			case $target in
+			    *-apple-darwin_ios*)
+				case $ARCH in
+				    *arm*)
+				    WEBRTC_CFLAGS="-DPJMEDIA_WEBRTC_AEC_USE_MOBILE=1 $WEBRTC_CFLAGS"
+				    WEBRTC_LDFLAGS="-L$WEBRTC_PREFIX/src/out_ios/Release-iphoneos"
+				    WEBRTC_LIBS="-laudio_processing_neon -lcommon_audio_neon"
+				    ;;
+				*)
+				    ;;
+				esac
+				;;
+			    *mingw* | *cygw* | *win32* | *w32* | *darwin* | *linux* | *android*)
+			        WEBRTC_LDFLAGS="-L$WEBRTC_PREFIX/src/out/Release"
+			        WEBRTC_LIBS="-laudio_processing_sse2"
+				;;
+			    *)
+				;;
+			esac
+
+			{ $as_echo "$as_me:${as_lineno-$LINENO}: result: Using webrtc prefix... $with_webrtc" >&5
+$as_echo "Using webrtc prefix... $with_webrtc" >&6; }
+		  else
+		  	WEBRTC_CFLAGS=""
+			WEBRTC_LDFLAGS=""
+		  fi
+
+		  WEBRTC_LIBS="$WEBRTC_LIBS -laudio_processing -lcommon_audio -lsystem_wrappers"
+
+		  SAVED_LIBS="$LIBS"
+		  SAVED_LDFLAGS="$LDFLAGS"
+		  SAVED_CFLAGS="$CFLAGS"
+
+		  LIBS="$WEBRTC_LIBS $LIBS"
+		  LDFLAGS="$WEBRTC_LDFLAGS $LDFLAGS"
+		  CFLAGS="$WEBRTC_CFLAGS $CFLAGS"
+
+		  { $as_echo "$as_me:${as_lineno-$LINENO}: checking for WebRtcAec_Process in -laudio_processing" >&5
+$as_echo_n "checking for WebRtcAec_Process in -laudio_processing... " >&6; }
+if ${ac_cv_lib_audio_processing_WebRtcAec_Process+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  ac_check_lib_save_LIBS=$LIBS
+LIBS="-laudio_processing
+			        $LIBS"
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+/* Override any GCC internal prototype to avoid an error.
+   Use char because int might match the return type of a GCC
+   builtin and then its argument prototype would still apply.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+char WebRtcAec_Process ();
+int
+main ()
+{
+return WebRtcAec_Process ();
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+  ac_cv_lib_audio_processing_WebRtcAec_Process=yes
+else
+  ac_cv_lib_audio_processing_WebRtcAec_Process=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_audio_processing_WebRtcAec_Process" >&5
+$as_echo "$ac_cv_lib_audio_processing_WebRtcAec_Process" >&6; }
+if test "x$ac_cv_lib_audio_processing_WebRtcAec_Process" = xyes; then :
+   ac_webrtc_cflags="-DPJMEDIA_HAS_WEBRTC_AEC=1 $WEBRTC_CFLAGS"
+		  		 ac_webrtc_ldflags="$WEBRTC_LDFLAGS $WEBRTC_LIBS"
+
+else
+   LIBS="$SAVED_LIBS"
+				 LDFLAGS="$SAVED_LDFLAGS"
+				 CFLAGS="$SAVED_CFLAGS"
+
+fi
+
+
+fi
+
+
 # Check whether --enable-ipp was given.
 if test "${enable_ipp+set}" = set; then :
Index: pjproject/trunk/aconfigure.ac
===================================================================
--- pjproject/trunk/aconfigure.ac	(revision 5185)
+++ pjproject/trunk/aconfigure.ac	(revision 5186)
@@ -1257,4 +1257,80 @@
 
 
+dnl # WebRtc alt prefix
+AC_ARG_WITH(webrtc,
+            AC_HELP_STRING([--with-webrtc=DIR],
+		           [Specify alternate WebRtc prefix]),
+            [],
+            [with_webrtc=no]
+            )
+
+dnl # Do not use default webrtc installation if we are cross-compiling
+if test "x$ac_cross_compile" != "x" -a "x$with_webrtc" = "xno"; then
+    enable_webrtc=no
+fi	      
+	      
+dnl # WebRtc
+AC_SUBST(ac_webrtc_cflags)
+AC_SUBST(ac_webrtc_ldflags)
+AC_ARG_ENABLE(webrtc,
+	      AC_HELP_STRING([--disable-webrtc],
+			     [Exclude webrtc in the build]),
+	      [if test "$enable_webrtc" = "no"; then
+		AC_MSG_RESULT([Checking if webrtc is disabled...yes])
+	       fi],
+	      [
+		  if test "x$with_webrtc" != "xno" -a "x$with_webrtc" != "x"; then
+		        WEBRTC_PREFIX=$with_webrtc
+		  	WEBRTC_CFLAGS="-I$WEBRTC_PREFIX/src"
+		  	
+			case $target in
+			    *-apple-darwin_ios*)
+				case $ARCH in
+				    *arm*)
+				    WEBRTC_CFLAGS="-DPJMEDIA_WEBRTC_AEC_USE_MOBILE=1 $WEBRTC_CFLAGS"
+				    WEBRTC_LDFLAGS="-L$WEBRTC_PREFIX/src/out_ios/Release-iphoneos"
+				    WEBRTC_LIBS="-laudio_processing_neon -lcommon_audio_neon"
+				    ;;
+				*)
+				    ;;
+				esac
+				;;			
+			    *mingw* | *cygw* | *win32* | *w32* | *darwin* | *linux* | *android*)
+			        WEBRTC_LDFLAGS="-L$WEBRTC_PREFIX/src/out/Release"
+			        WEBRTC_LIBS="-laudio_processing_sse2" 
+				;;
+			    *)
+				;;
+			esac		  	
+		  	
+			AC_MSG_RESULT([Using webrtc prefix... $with_webrtc])
+		  else
+		  	WEBRTC_CFLAGS=""
+			WEBRTC_LDFLAGS="" 
+		  fi
+		  		  
+		  WEBRTC_LIBS="$WEBRTC_LIBS -laudio_processing -lcommon_audio -lsystem_wrappers"
+		  
+		  SAVED_LIBS="$LIBS"
+		  SAVED_LDFLAGS="$LDFLAGS"
+		  SAVED_CFLAGS="$CFLAGS"
+		  
+		  LIBS="$WEBRTC_LIBS $LIBS"
+		  LDFLAGS="$WEBRTC_LDFLAGS $LDFLAGS"
+		  CFLAGS="$WEBRTC_CFLAGS $CFLAGS"
+		  
+		  AC_CHECK_LIB(audio_processing,
+			       WebRtcAec_Process,
+			       [ ac_webrtc_cflags="-DPJMEDIA_HAS_WEBRTC_AEC=1 $WEBRTC_CFLAGS"
+		  		 ac_webrtc_ldflags="$WEBRTC_LDFLAGS $WEBRTC_LIBS"
+			       ],
+			       [ LIBS="$SAVED_LIBS"
+				 LDFLAGS="$SAVED_LDFLAGS"
+				 CFLAGS="$SAVED_CFLAGS"
+			       ],
+			       []
+			       )
+	      ])
+
 dnl ########################################################
 dnl # Intel IPP support
Index: pjproject/trunk/pjmedia/build/Makefile
===================================================================
--- pjproject/trunk/pjmedia/build/Makefile	(revision 5185)
+++ pjproject/trunk/pjmedia/build/Makefile	(revision 5186)
@@ -63,5 +63,5 @@
 			conf_switch.o converter.o  converter_libswscale.o converter_libyuv.o \
 			delaybuf.o echo_common.o \
-			echo_port.o echo_suppress.o endpoint.o errno.o \
+			echo_port.o echo_suppress.o echo_webrtc.o endpoint.o errno.o \
 			event.o format.o ffmpeg_util.o \
 			g711.o jbuf.o master_port.o mem_capture.o mem_player.o \
Index: pjproject/trunk/pjmedia/build/os-auto.mak.in
===================================================================
--- pjproject/trunk/pjmedia/build/os-auto.mak.in	(revision 5185)
+++ pjproject/trunk/pjmedia/build/os-auto.mak.in	(revision 5186)
@@ -38,4 +38,8 @@
 OPENH264_LDFLAGS = @ac_openh264_ldflags@
 
+# WebRtc
+WEBRTC_CFLAGS = @ac_webrtc_cflags@
+WEBRTC_LDFLAGS = @ac_webrtc_ldflags@
+
 
 # PJMEDIA features exclusion
@@ -43,7 +47,7 @@
 		 $(SDL_CFLAGS) $(FFMPEG_CFLAGS) $(V4L2_CFLAGS) $(QT_CFLAGS) \
 		 $(IOS_CFLAGS) $(ANDROID_CFLAGS) $(LIBYUV_CFLAGS) \
-		 $(OPENH264_CFLAGS)
+		 $(OPENH264_CFLAGS) $(WEBRTC_CFLAGS)
 export LDFLAGS += $(SDL_LDFLAGS) $(FFMPEG_LDFLAGS) $(V4L2_LDFLAGS) \
-		  $(LIBYUV_LDFLAGS) $(OPENH264_LDFLAGS)
+		  $(LIBYUV_LDFLAGS) $(OPENH264_LDFLAGS) $(WEBRTC_LDFLAGS)
 
 # Define the desired sound device backend
Index: pjproject/trunk/pjmedia/include/pjmedia/config.h
===================================================================
--- pjproject/trunk/pjmedia/include/pjmedia/config.h	(revision 5185)
+++ pjproject/trunk/pjmedia/include/pjmedia/config.h	(revision 5186)
@@ -658,4 +658,22 @@
 
 /**
+ * WebRtc Accoustic Echo Cancellation (AEC).
+ * By default is disabled.
+ */
+#ifndef PJMEDIA_HAS_WEBRTC_AEC
+#   define PJMEDIA_HAS_WEBRTC_AEC		0
+#endif
+
+/**
+ * Specify whether WebRtc EC should use its mobile version AEC.
+ *
+ * Default: 0 (no)
+ */
+#ifndef PJMEDIA_WEBRTC_AEC_USE_MOBILE
+#   define PJMEDIA_WEBRTC_AEC_USE_MOBILE 	0
+#endif
+
+
+/**
  * Maximum number of parameters in SDP fmtp attribute.
  *
Index: pjproject/trunk/pjmedia/include/pjmedia/echo.h
===================================================================
--- pjproject/trunk/pjmedia/include/pjmedia/echo.h	(revision 5185)
+++ pjproject/trunk/pjmedia/include/pjmedia/echo.h	(revision 5186)
@@ -67,5 +67,6 @@
     /**
      * Force to use Speex AEC as the backend echo canceller algorithm.
-     * This setting is mutually exclusive with PJMEDIA_ECHO_SIMPLE.
+     * This setting is mutually exclusive with PJMEDIA_ECHO_SIMPLE and
+     * PJMEDIA_ECHO_WEBRTC.
      */
     PJMEDIA_ECHO_SPEEX	= 1,
@@ -75,7 +76,14 @@
      * creation, then a simple echo suppressor will be used instead of
      * an accoustic echo cancellation. This setting is mutually exclusive
-     * with PJMEDIA_ECHO_SPEEX.
+     * with PJMEDIA_ECHO_SPEEX and PJMEDIA_ECHO_WEBRTC.
      */
     PJMEDIA_ECHO_SIMPLE	= 2,
+
+    /**
+     * Force to use WebRTC AEC as the backend echo canceller algorithm.
+     * This setting is mutually exclusive with PJMEDIA_ECHO_SIMPLE and
+     * PJMEDIA_ECHO_SPEEX.
+     */
+    PJMEDIA_ECHO_WEBRTC = 3,
 
     /**
@@ -102,5 +110,44 @@
      * will be used instead of device EC.
      */
-    PJMEDIA_ECHO_USE_SW_ECHO = 64
+    PJMEDIA_ECHO_USE_SW_ECHO = 64,
+    
+    /**
+     * If PJMEDIA_ECHO_USE_NOISE_SUPPRESSOR flag is specified, the echo
+     * canceller will also apply noise suppressor method to reduce noise.
+     */
+    PJMEDIA_ECHO_USE_NOISE_SUPPRESSOR = 128,
+    
+    /**
+     * Use default aggressiveness setting for the echo canceller algorithm. 
+     * This setting is mutually exclusive with the other aggressiveness
+     * settings.
+     */
+    PJMEDIA_ECHO_AGGRESSIVENESS_DEFAULT = 0,
+    
+    /**
+     * Use conservative aggressiveness setting for the echo canceller
+     * algorithm. This setting is mutually exclusive with the other
+     * aggressiveness settings.
+     */
+    PJMEDIA_ECHO_AGGRESSIVENESS_CONSERVATIVE = 0x100,
+    
+    /**
+     * Use moderate aggressiveness setting for the echo canceller algorithm. 
+     * This setting is mutually exclusive with the other aggressiveness
+     * settings.
+     */
+    PJMEDIA_ECHO_AGGRESSIVENESS_MODERATE = 0x200,
+    
+    /**
+     * Use aggressive aggressiveness setting for the echo canceller
+     * algorithm. This setting is mutually exclusive with the other
+     * aggressiveness settings.
+     */
+    PJMEDIA_ECHO_AGGRESSIVENESS_AGGRESSIVE = 0x300,
+    
+    /**
+     * For internal use.
+     */
+    PJMEDIA_ECHO_AGGRESSIVENESS_MASK = 0xF00
 
 } pjmedia_echo_flag;
Index: pjproject/trunk/pjmedia/src/pjmedia/echo_common.c
===================================================================
--- pjproject/trunk/pjmedia/src/pjmedia/echo_common.c	(revision 5185)
+++ pjproject/trunk/pjmedia/src/pjmedia/echo_common.c	(revision 5186)
@@ -126,4 +126,18 @@
 
 /*
+ * WebRTC AEC prototypes
+ */
+#if defined(PJMEDIA_HAS_WEBRTC_AEC) && PJMEDIA_HAS_WEBRTC_AEC!=0
+static struct ec_operations webrtc_aec_op =
+{
+    "WebRTC AEC",
+    &webrtc_aec_create,
+    &webrtc_aec_destroy,
+    &webrtc_aec_reset,
+    &webrtc_aec_cancel_echo
+};
+#endif
+
+/*
  * Create the echo canceller. 
  */
@@ -186,4 +200,11 @@
 #endif
 
+#if defined(PJMEDIA_HAS_WEBRTC_AEC) && PJMEDIA_HAS_WEBRTC_AEC!=0
+    } else if ((options & PJMEDIA_ECHO_ALGO_MASK) == PJMEDIA_ECHO_WEBRTC ||
+               (options & PJMEDIA_ECHO_ALGO_MASK) == PJMEDIA_ECHO_DEFAULT)
+    {
+        ec->op = &webrtc_aec_op;
+#endif
+        
     } else {
 	ec->op = &echo_supp_op;
Index: pjproject/trunk/pjmedia/src/pjmedia/echo_internal.h
===================================================================
--- pjproject/trunk/pjmedia/src/pjmedia/echo_internal.h	(revision 5185)
+++ pjproject/trunk/pjmedia/src/pjmedia/echo_internal.h	(revision 5186)
@@ -78,4 +78,19 @@
 					 void *reserved );
 
+PJ_DECL(pj_status_t) webrtc_aec_create(pj_pool_t *pool,
+                                       unsigned clock_rate,
+                                       unsigned channel_count,
+                                       unsigned samples_per_frame,
+                                       unsigned tail_ms,
+                                       unsigned options,
+                                       void **p_echo );
+PJ_DECL(pj_status_t) webrtc_aec_destroy(void *state );
+PJ_DECL(void) webrtc_aec_reset(void *state );
+PJ_DECL(pj_status_t) webrtc_aec_cancel_echo(void *state,
+                                            pj_int16_t *rec_frm,
+                                            const pj_int16_t *play_frm,
+                                            unsigned options,
+                                            void *reserved );
+
 
 PJ_END_DECL
Index: pjproject/trunk/pjmedia/src/pjmedia/echo_webrtc.c
===================================================================
--- pjproject/trunk/pjmedia/src/pjmedia/echo_webrtc.c	(revision 5186)
+++ pjproject/trunk/pjmedia/src/pjmedia/echo_webrtc.c	(revision 5186)
@@ -0,0 +1,371 @@
+/* $Id$ */
+/* 
+ * Copyright (C) 2011-2015 Teluu Inc. (http://www.teluu.com)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA 
+ */
+
+#include <pjmedia/echo.h>
+#include <pjmedia/errno.h>
+#include <pj/assert.h>
+#include <pj/log.h>
+#include <pj/pool.h>
+
+#if defined(PJMEDIA_HAS_WEBRTC_AEC) && PJMEDIA_HAS_WEBRTC_AEC != 0
+
+#include <webrtc/modules/audio_processing/aec/include/echo_cancellation.h>
+#include <webrtc/modules/audio_processing/aecm/include/echo_control_mobile.h>
+#include <webrtc/modules/audio_processing/aec/aec_core.h>
+
+#include "echo_internal.h"
+
+#define THIS_FILE		"echo_webrtc.c"
+
+#if PJMEDIA_WEBRTC_AEC_USE_MOBILE == 1
+    #include <webrtc/modules/audio_processing/ns/include/noise_suppression_x.h>
+
+    #define NsHandle NsxHandle
+    #define WebRtcNs_Create WebRtcNsx_Create
+    #define WebRtcNs_Init WebRtcNsx_Init
+    #define WebRtcNs_Free WebRtcNsx_Free
+
+    #define WebRtcAec_Create WebRtcAecm_Create
+    #define WebRtcAec_Init(handle, clock, sclock) WebRtcAecm_Init(handle, clock)
+    #define WebRtcAec_Free WebRtcAecm_Free
+    #define WebRtcAec_get_error_code WebRtcAecm_get_error_code
+    #define WebRtcAec_enable_delay_agnostic(core, enable)
+    #define WebRtcAec_set_config WebRtcAecm_set_config
+    #define WebRtcAec_BufferFarend WebRtcAecm_BufferFarend
+    #define AecConfig AecmConfig
+    #define SHOW_DELAY_METRICS	0
+    typedef short sample;
+#else
+    #include <webrtc/modules/audio_processing/ns/include/noise_suppression.h>
+
+    typedef float sample;
+
+    /* If SHOW_DELAY_METRICS is set to non-zero, delay metrics stats will
+     * be printed every SHOW_DELAY_METRICS-th call to webrtc_aec_cancel_echo().
+     * For example, if ptime is 20ms, set this to 250 to print the metrics
+     * every 250*20/1000=5 seconds.
+     */
+    #define SHOW_DELAY_METRICS	0
+    
+#endif
+
+#define BUF_LEN			160
+
+typedef struct webrtc_ec
+{
+    void       *AEC_inst;
+    NsHandle   *NS_inst;
+    unsigned    options;
+    unsigned	samples_per_frame;
+    unsigned	tail;
+    unsigned    clock_rate;
+    unsigned	channel_count;
+    unsigned    subframe_len;
+    sample      tmp_buf[BUF_LEN];
+    sample      tmp_buf2[BUF_LEN];
+#if SHOW_DELAY_METRICS
+    unsigned	counter;
+#endif
+} webrtc_ec;
+
+
+static void print_webrtc_aec_error(const char *tag, void *AEC_inst)
+{
+    unsigned status = WebRtcAec_get_error_code(AEC_inst);
+    PJ_LOG(3, (THIS_FILE, "WebRTC AEC error (%s) %d ", tag, status));
+}
+
+static void set_config(void *AEC_inst, unsigned options)
+{
+    unsigned aggr_opt = options & PJMEDIA_ECHO_AGGRESSIVENESS_MASK;
+    int status;
+    AecConfig aec_config;
+
+#if PJMEDIA_WEBRTC_AEC_USE_MOBILE
+    aec_config.echoMode = 3;
+    if (aggr_opt == PJMEDIA_ECHO_AGGRESSIVENESS_CONSERVATIVE)
+        aec_config.echoMode = 0;
+    else if (aggr_opt == PJMEDIA_ECHO_AGGRESSIVENESS_AGGRESSIVE)
+   	aec_config.echoMode = 4;
+    aec_config.cngMode = AecmTrue;
+#else
+    
+    aec_config.nlpMode = kAecNlpModerate;
+    if (aggr_opt == PJMEDIA_ECHO_AGGRESSIVENESS_CONSERVATIVE)
+	aec_config.nlpMode = kAecNlpConservative;
+    else if (aggr_opt == PJMEDIA_ECHO_AGGRESSIVENESS_AGGRESSIVE)
+        aec_config.nlpMode = kAecNlpAggressive;
+    else
+        aec_config.nlpMode = kAecNlpModerate;
+    
+    aec_config.skewMode = kAecFalse;
+#if SHOW_DELAY_METRICS
+    aec_config.metricsMode = kAecTrue;
+    aec_config.delay_logging = kAecTrue;
+#else
+    aec_config.metricsMode = kAecFalse;
+    aec_config.delay_logging = kAecFalse;
+#endif
+
+#endif
+
+    status = WebRtcAec_set_config(AEC_inst, aec_config);
+    if (status != 0) {
+        print_webrtc_aec_error("Init config", AEC_inst);
+    }
+}
+
+/*
+ * Create the AEC.
+ */
+PJ_DEF(pj_status_t) webrtc_aec_create(pj_pool_t *pool,
+                                      unsigned clock_rate,
+                                      unsigned channel_count,
+                                      unsigned samples_per_frame,
+                                      unsigned tail_ms,
+                                      unsigned options,
+                                      void **p_echo )
+{
+    webrtc_ec *echo;
+    int status;
+    
+    *p_echo = NULL;
+    
+    echo = PJ_POOL_ZALLOC_T(pool, webrtc_ec);
+    PJ_ASSERT_RETURN(echo != NULL, PJ_ENOMEM);
+    
+    /* Currently we only support mono. */
+    if (channel_count != 1)
+    	return PJ_ENOTSUP;
+
+    echo->channel_count = channel_count;
+    echo->samples_per_frame = samples_per_frame;
+    echo->tail = tail_ms;
+    echo->clock_rate = clock_rate;
+    /* SWB is processed as 160 frame size */
+    if (clock_rate > 8000)
+        echo->subframe_len = 160;
+    else
+    	echo->subframe_len = 80;
+    echo->options = options;
+    
+    /* Create WebRTC AEC */
+    echo->AEC_inst = WebRtcAec_Create();
+    if (!echo->AEC_inst) {
+    	return PJ_ENOMEM;
+    }
+    
+    /* Init WebRTC AEC */
+    status = WebRtcAec_Init(echo->AEC_inst, clock_rate, clock_rate);
+    if (status != 0) {
+        print_webrtc_aec_error("Init", echo->AEC_inst);
+        WebRtcAec_Free(echo->AEC_inst);
+    	return PJ_ENOTSUP;
+    }
+
+    /* WebRtc is very dependent on delay calculation, which will be passed
+     * to WebRtcAec_Process() below. A poor estimate, even by as little as
+     * 40ms, may affect the echo cancellation results greatly.
+     * Hence, we need to enable delay-agnostic echo cancellation. This
+     * low-level feature relies on internally estimated delays between
+     * the process and reverse streams, thus not relying on reported
+     * system delays.
+     * Still, with the delay agnostic feature, it may take some time (5-10s
+     * or more) for the Aec module to learn the optimal delay, thus
+     * a good initial estimate is necessary for good EC quality in
+     * the beginning of a call.
+     */
+    WebRtcAec_enable_delay_agnostic(WebRtcAec_aec_core(echo->AEC_inst), 1);
+    
+    set_config(echo->AEC_inst, options);
+
+    if (options & PJMEDIA_ECHO_USE_NOISE_SUPPRESSOR) {
+        echo->NS_inst = WebRtcNs_Create();
+        if (echo->NS_inst) {
+            status = WebRtcNs_Init(echo->NS_inst, clock_rate);
+            if (status != 0) {
+                WebRtcNs_Free(echo->NS_inst);
+                echo->NS_inst = NULL;
+            }
+        }
+        if (!echo->NS_inst) {
+            PJ_LOG(3, (THIS_FILE, "Unable to create WebRTC noise suppressor"));
+        }
+    }
+
+    PJ_LOG(3, (THIS_FILE, "WebRTC AEC%s successfully created with options %d",
+#if PJMEDIA_WEBRTC_AEC_USE_MOBILE
+			  " mobile", options));
+#else
+			  "", options));
+#endif
+
+    /* Done */
+    *p_echo = echo;
+    return PJ_SUCCESS;
+    
+}
+
+
+/*
+ * Destroy AEC
+ */
+PJ_DEF(pj_status_t) webrtc_aec_destroy(void *state )
+{
+    webrtc_ec *echo = (webrtc_ec*) state;
+    PJ_ASSERT_RETURN(echo, PJ_EINVAL);
+    
+    if (echo->AEC_inst) {
+    	WebRtcAec_Free(echo->AEC_inst);
+    	echo->AEC_inst = NULL;
+    }
+    if (echo->NS_inst) {
+        WebRtcNs_Free(echo->NS_inst);
+        echo->NS_inst = NULL;
+    }
+    
+    return PJ_SUCCESS;
+}
+
+
+/*
+ * Reset AEC
+ */
+PJ_DEF(void) webrtc_aec_reset(void *state )
+{
+    webrtc_ec *echo = (webrtc_ec*) state;
+    int status;
+    
+    pj_assert(echo != NULL);
+    
+    /* Re-initialize the EC */
+    status = WebRtcAec_Init(echo->AEC_inst, echo->clock_rate, echo->clock_rate);
+    if (status != 0) {
+        print_webrtc_aec_error("reset", echo->AEC_inst);
+        return;
+    }
+    
+    set_config(echo->AEC_inst, echo->options);
+    
+    PJ_LOG(4, (THIS_FILE, "WebRTC AEC reset succeeded"));
+}
+
+
+/*
+ * Perform echo cancellation.
+ */
+PJ_DEF(pj_status_t) webrtc_aec_cancel_echo( void *state,
+					    pj_int16_t *rec_frm,
+					    const pj_int16_t *play_frm,
+					    unsigned options,
+					    void *reserved )
+{
+    webrtc_ec *echo = (webrtc_ec*) state;
+    int status;
+    unsigned i, j, frm_idx = 0;
+    const sample * buf_ptr;
+    sample * out_buf_ptr;
+
+    /* Sanity checks */
+    PJ_ASSERT_RETURN(echo && rec_frm && play_frm, PJ_EINVAL);
+    
+    for(i = echo->samples_per_frame / echo->subframe_len; i > 0; i--) {
+#if PJMEDIA_WEBRTC_AEC_USE_MOBILE
+	buf_ptr = &play_frm[frm_idx];
+#else
+        for (j = 0; j < echo->subframe_len; j++) {
+            echo->tmp_buf[j] = rec_frm[frm_idx+j];
+            echo->tmp_buf2[j] = play_frm[frm_idx+j];
+        }
+        buf_ptr = echo->tmp_buf2;
+#endif
+        
+        /* Feed farend buffer */
+        status = WebRtcAec_BufferFarend(echo->AEC_inst, buf_ptr,
+                                        echo->subframe_len);
+        if (status != 0) {
+            print_webrtc_aec_error("Buffer farend", echo->AEC_inst);
+            return PJ_EUNKNOWN;
+        }        
+        
+	buf_ptr = echo->tmp_buf;
+	out_buf_ptr = echo->tmp_buf2;
+        if (echo->NS_inst) {
+#if PJMEDIA_WEBRTC_AEC_USE_MOBILE
+	    buf_ptr = &rec_frm[frm_idx];
+            WebRtcNsx_Process(echo->NS_inst, &buf_ptr, echo->channel_count,
+            		      &out_buf_ptr);
+            buf_ptr = out_buf_ptr;
+            out_buf_ptr = echo->tmp_buf;
+#else
+            WebRtcNs_Analyze(echo->NS_inst, buf_ptr);
+#endif
+        }
+        
+        /* Process echo cancellation */
+#if PJMEDIA_WEBRTC_AEC_USE_MOBILE
+        status = WebRtcAecm_Process(echo->AEC_inst, &rec_frm[frm_idx],
+        			    (echo->NS_inst? buf_ptr: NULL),
+        			    out_buf_ptr, echo->subframe_len,
+        			    echo->tail);
+#else
+        status = WebRtcAec_Process(echo->AEC_inst, &buf_ptr,
+                                   echo->channel_count, &out_buf_ptr,
+                                   echo->subframe_len, echo->tail, 0);
+#endif
+        if (status != 0) {
+            print_webrtc_aec_error("Process echo", echo->AEC_inst);
+            return PJ_EUNKNOWN;
+        }
+
+#if !PJMEDIA_WEBRTC_AEC_USE_MOBILE
+    	if (echo->NS_inst) {
+            /* Noise suppression */
+	    buf_ptr = echo->tmp_buf2;
+	    out_buf_ptr = echo->tmp_buf;
+            WebRtcNs_Process(echo->NS_inst, &buf_ptr,
+                             echo->channel_count, &out_buf_ptr);
+    	}
+#endif
+    
+       	for (j = 0; j < echo->subframe_len; j++) {
+ 	    rec_frm[frm_idx++] = (pj_int16_t)out_buf_ptr[j];
+    	}
+    }
+
+#if SHOW_DELAY_METRICS
+    if (++echo->counter >= SHOW_DELAY_METRICS) {
+    	int median, std;
+    	float frac_delay;
+
+        if (WebRtcAec_GetDelayMetrics(echo->AEC_inst, &median, &std,
+        			      &frac_delay) == 0)
+        {
+            PJ_LOG(3, (THIS_FILE, "WebRTC delay metrics: median=%d, std=%d, "
+            			  "fraction of poor delays=%f",
+            			  median, std, frac_delay));
+        }
+        echo->counter = 0;
+    }
+#endif
+
+    return PJ_SUCCESS;
+}
+
+#endif
Index: pjproject/trunk/pjsip-apps/src/pjsua/pjsua_app_config.c
===================================================================
--- pjproject/trunk/pjsip-apps/src/pjsua/pjsua_app_config.c	(revision 5185)
+++ pjproject/trunk/pjsip-apps/src/pjsua/pjsua_app_config.c	(revision 5186)
@@ -23,4 +23,7 @@
 
 #define MAX_APP_OPTIONS 128
+
+#define str(s) #s
+#define xstr(s) str(s)
 
 char   *stdout_refresh_text = "STDOUT_REFRESH";
@@ -142,15 +145,20 @@
     puts  ("  --rec-file=file     Open file recorder (extension can be .wav or .mp3");
     puts  ("  --auto-rec          Automatically record conversation");
-    puts  ("  --quality=N         Specify media quality (0-10, default=6)");
+    puts  ("  --quality=N         Specify media quality (0-10, default="
+    				  xstr(PJSUA_DEFAULT_CODEC_QUALITY) ")");
     puts  ("  --ptime=MSEC        Override codec ptime to MSEC (default=specific)");
     puts  ("  --no-vad            Disable VAD/silence detector (default=vad enabled)");
-    puts  ("  --ec-tail=MSEC      Set echo canceller tail length (default=256)");
+    puts  ("  --ec-tail=MSEC      Set echo canceller tail length (default="
+	   			  xstr(PJSUA_DEFAULT_EC_TAIL_LEN) ")");
     puts  ("  --ec-opt=OPT        Select echo canceller algorithm (0=default, ");
-    puts  ("                        1=speex, 2=suppressor)");
-    puts  ("  --ilbc-mode=MODE    Set iLBC codec mode (20 or 30, default is 30)");
+    puts  ("                        1=speex, 2=suppressor, 3=WebRtc)");
+    puts  ("  --ilbc-mode=MODE    Set iLBC codec mode (20 or 30, default is "
+    				  xstr(PJSUA_DEFAULT_ILBC_MODE) ")");
     puts  ("  --capture-dev=id    Audio capture device ID (default=-1)");
     puts  ("  --playback-dev=id   Audio playback device ID (default=-1)");
-    puts  ("  --capture-lat=N     Audio capture latency, in ms (default=100)");
-    puts  ("  --playback-lat=N    Audio playback latency, in ms (default=100)");
+    puts  ("  --capture-lat=N     Audio capture latency, in ms (default="
+    				  xstr(PJMEDIA_SND_DEFAULT_REC_LATENCY) ")");
+    puts  ("  --playback-lat=N    Audio playback latency, in ms (default="
+    				  xstr(PJMEDIA_SND_DEFAULT_PLAY_LATENCY) ")");
     puts  ("  --snd-auto-close=N  Auto close audio device when idle for N secs (default=1)");
     puts  ("                      Specify N=-1 to disable this feature.");
