Index: /pjproject/trunk/pjmedia/include/pjmedia/sound.h
===================================================================
--- /pjproject/trunk/pjmedia/include/pjmedia/sound.h	(revision 743)
+++ /pjproject/trunk/pjmedia/include/pjmedia/sound.h	(revision 744)
@@ -74,4 +74,22 @@
     unsigned	default_samples_per_sec;/**< Default sampling rate.	    */
 } pjmedia_snd_dev_info;
+
+/** 
+ * Stream information, can be retrieved from a live stream by calling
+ * #pjmedia_snd_stream_get_info().
+ */
+typedef struct pjmedia_snd_stream_info
+{
+    pjmedia_dir	dir;		    /**< Stream direction.		    */
+    int		play_id;	    /**< Playback dev id, or -1 for rec only*/
+    int		rec_id;		    /**< Capture dev id, or -1 for play only*/
+    unsigned	clock_rate;	    /**< Actual clock rate.		    */
+    unsigned	channel_count;	    /**< Number of channels.		    */
+    unsigned	samples_per_frame;  /**< Samples per frame.		    */
+    unsigned	bits_per_sample;    /**< Bits per sample.		    */
+    unsigned	rec_latency;	    /**< Record latency, in samples.	    */
+    unsigned	play_latency;	    /**< Playback latency, in samples.	    */
+} pjmedia_snd_stream_info;
+
 
 /** 
@@ -233,4 +251,17 @@
 
 /**
+ * Get information about live stream.
+ *
+ * @param strm		The stream to be queried.
+ * @param i		Pointer to stream information to be filled up with
+ *			information about the stream.
+ *
+ * @return		PJ_SUCCESS on success or the appropriate error code.
+ */
+PJ_DECL(pj_status_t) pjmedia_snd_stream_get_info(pjmedia_snd_stream *strm,
+						 pjmedia_snd_stream_info *pi);
+
+
+/**
  * Start the stream.
  *
Index: /pjproject/trunk/pjmedia/src/pjmedia/dsound.c
===================================================================
--- /pjproject/trunk/pjmedia/src/pjmedia/dsound.c	(revision 743)
+++ /pjproject/trunk/pjmedia/src/pjmedia/dsound.c	(revision 744)
@@ -90,4 +90,6 @@
 {
     pjmedia_dir		    dir;		/**< Sound direction.	    */
+    int			    play_id;		/**< Playback dev id.	    */
+    int			    rec_id;		/**< Recording dev id.	    */
     pj_pool_t		   *pool;		/**< Memory pool.	    */
   
@@ -102,4 +104,6 @@
     unsigned		    clock_rate;		/**< Clock rate.	    */
     unsigned		    samples_per_frame;	/**< Samples per frame.	    */
+    unsigned		    bits_per_sample;	/**< Bits per sample.	    */
+    unsigned		    channel_count;	/**< Channel count.	    */
 
     pj_thread_t		   *thread;		/**< Thread handle.	    */
@@ -720,4 +724,6 @@
     strm = pj_pool_zalloc(pool, sizeof(pjmedia_snd_stream));
     strm->dir = dir;
+    strm->play_id = play_id;
+    strm->rec_id = rec_id;
     strm->pool = pool;
     strm->rec_cb = rec_cb;
@@ -726,4 +732,6 @@
     strm->clock_rate = clock_rate;
     strm->samples_per_frame = samples_per_frame;
+    strm->bits_per_sample = bits_per_sample;
+    strm->channel_count = channel_count;
     strm->buffer = pj_pool_alloc(pool, samples_per_frame * BYTES_PER_SAMPLE);
     if (!strm->buffer) {
@@ -828,4 +836,28 @@
 
 /*
+ * Get stream info.
+ */
+PJ_DEF(pj_status_t) pjmedia_snd_stream_get_info(pjmedia_snd_stream *strm,
+						pjmedia_snd_stream_info *pi)
+{
+
+    PJ_ASSERT_RETURN(strm && pi, PJ_EINVAL);
+
+    pj_bzero(pi, sizeof(*pi));
+    pi->dir = strm->dir;
+    pi->play_id = strm->play_id;
+    pi->rec_id = strm->rec_id;
+    pi->clock_rate = strm->clock_rate;
+    pi->channel_count = strm->channel_count;
+    pi->samples_per_frame = strm->samples_per_frame;
+    pi->bits_per_sample = strm->bits_per_sample;
+    pi->rec_latency = 0;
+    pi->play_latency = 0;
+
+    return PJ_SUCCESS;
+}
+
+
+/*
  * Start stream.
  */
Index: /pjproject/trunk/pjmedia/src/pjmedia/pasound.c
===================================================================
--- /pjproject/trunk/pjmedia/src/pjmedia/pasound.c	(revision 743)
+++ /pjproject/trunk/pjmedia/src/pjmedia/pasound.c	(revision 744)
@@ -19,4 +19,5 @@
 #include <pjmedia/sound.h>
 #include <pjmedia/errno.h>
+#include <pj/assert.h>
 #include <pj/log.h>
 #include <pj/os.h>
@@ -43,6 +44,9 @@
     pj_str_t		 name;
     pjmedia_dir		 dir;
+    int			 play_id;
+    int			 rec_id;
     int			 bytes_per_sample;
     pj_uint32_t		 samples_per_sec;
+    unsigned		 samples_per_frame;
     int			 channel_count;
 
@@ -242,5 +246,6 @@
     const PaDeviceInfo *paDevInfo = NULL;
     const PaHostApiInfo *paHostApiInfo = NULL;
-    unsigned paFrames;
+    unsigned paFrames, paRate, paLatency;
+    const PaStreamInfo *paSI;
     PaError err;
 
@@ -281,6 +286,9 @@
     pj_strdup2_with_null(pool, &stream->name, paDevInfo->name);
     stream->dir = PJMEDIA_DIR_CAPTURE;
+    stream->rec_id = index;
+    stream->play_id = -1;
     stream->user_data = user_data;
     stream->samples_per_sec = clock_rate;
+    stream->samples_per_frame = samples_per_frame;
     stream->bytes_per_sample = bits_per_sample / 8;
     stream->channel_count = channel_count;
@@ -307,11 +315,15 @@
     }
 
-    PJ_LOG(5,(THIS_FILE, "%s opening device %s (%s) for recording, sample "
+    paSI = Pa_GetStreamInfo(stream->stream);
+    paRate = (unsigned)paSI->sampleRate;
+    paLatency = (unsigned)(paSI->inputLatency * 1000);
+
+    PJ_LOG(5,(THIS_FILE, "Opened device %s (%s) for recording, sample "
 			 "rate=%d, ch=%d, "
-			 "bits=%d, %d samples per frame",
-			 (err==0 ? "Success" : "Error"),
+			 "bits=%d, %d samples per frame, latency=%d ms",
 			 paDevInfo->name, paHostApiInfo->name,
-			 clock_rate, channel_count,
-			 bits_per_sample, samples_per_frame));
+			 paSI->sampleRate, channel_count,
+			 bits_per_sample, samples_per_frame,
+			 paLatency));
 
     *p_snd_strm = stream;
@@ -335,5 +347,6 @@
     const PaDeviceInfo *paDevInfo = NULL;
     const PaHostApiInfo *paHostApiInfo = NULL;
-    unsigned paFrames;
+    const PaStreamInfo *paSI;
+    unsigned paFrames, paRate, paLatency;
     PaError err;
 
@@ -374,6 +387,9 @@
     pj_strdup2_with_null(pool, &stream->name, paDevInfo->name);
     stream->dir = stream->dir = PJMEDIA_DIR_PLAYBACK;
+    stream->play_id = index;
+    stream->rec_id = -1;
     stream->user_data = user_data;
     stream->samples_per_sec = clock_rate;
+    stream->samples_per_frame = samples_per_frame;
     stream->bytes_per_sample = bits_per_sample / 8;
     stream->channel_count = channel_count;
@@ -400,11 +416,14 @@
     }
 
-    PJ_LOG(5,(THIS_FILE, "%s opening device %d: %s(%s) for playing, sample rate=%d"
+    paSI = Pa_GetStreamInfo(stream->stream);
+    paRate = (unsigned)(paSI->sampleRate);
+    paLatency = (unsigned)(paSI->outputLatency * 1000);
+
+    PJ_LOG(5,(THIS_FILE, "Opened device %d: %s(%s) for playing, sample rate=%d"
 			 ", ch=%d, "
-			 "bits=%d, %d samples per frame",
-			 (err==0 ? "Success" : "Error"),
+			 "bits=%d, %d samples per frame, latency=%d ms",
 			 index, paDevInfo->name, paHostApiInfo->name, 
-			 clock_rate, channel_count,
-		 	 bits_per_sample, samples_per_frame));
+			 paRate, channel_count,
+		 	 bits_per_sample, samples_per_frame, paLatency));
 
     *p_snd_strm = stream;
@@ -437,5 +456,6 @@
     const PaHostApiInfo *paRecHostApiInfo = NULL;
     const PaHostApiInfo *paPlayHostApiInfo = NULL;
-    unsigned paFrames;
+    const PaStreamInfo *paSI;
+    unsigned paFrames, paRate, paInputLatency, paOutputLatency;
     PaError err;
 
@@ -495,6 +515,9 @@
     pj_strdup2_with_null(pool, &stream->name, paRecDevInfo->name);
     stream->dir = PJMEDIA_DIR_CAPTURE_PLAYBACK;
+    stream->play_id = play_id;
+    stream->rec_id = rec_id;
     stream->user_data = user_data;
     stream->samples_per_sec = clock_rate;
+    stream->samples_per_frame = samples_per_frame;
     stream->bytes_per_sample = bits_per_sample / 8;
     stream->channel_count = channel_count;
@@ -531,12 +554,18 @@
     }
 
-    PJ_LOG(5,(THIS_FILE, "%s opening device %s(%s)/%s(%s) for recording and "
+    paSI = Pa_GetStreamInfo(stream->stream);
+    paRate = (unsigned)(paSI->sampleRate);
+    paInputLatency = (unsigned)(paSI->inputLatency * 1000);
+    paOutputLatency = (unsigned)(paSI->outputLatency * 1000);
+
+    PJ_LOG(5,(THIS_FILE, "Opened device %s(%s)/%s(%s) for recording and "
 			 "playback, sample rate=%d, ch=%d, "
-			 "bits=%d, %d samples per frame",
-			 (err==0 ? "Success" : "Error"),
+			 "bits=%d, %d samples per frame, input latency=%d ms, "
+			 "output latency=%d ms",
 			 paRecDevInfo->name, paRecHostApiInfo->name,
 			 paPlayDevInfo->name, paPlayHostApiInfo->name,
-			 clock_rate, channel_count,
-			 bits_per_sample, samples_per_frame));
+			 paRate, channel_count,
+			 bits_per_sample, samples_per_frame,
+			 paInputLatency, paOutputLatency));
 
     *p_snd_strm = stream;
@@ -545,4 +574,33 @@
     return PJ_SUCCESS;
 }
+
+
+/*
+ * Get stream info.
+ */
+PJ_DEF(pj_status_t) pjmedia_snd_stream_get_info(pjmedia_snd_stream *strm,
+						pjmedia_snd_stream_info *pi)
+{
+    const PaStreamInfo *paSI;
+
+    PJ_ASSERT_RETURN(strm && pi, PJ_EINVAL);
+    PJ_ASSERT_RETURN(strm->stream, PJ_EINVALIDOP);
+
+    paSI = Pa_GetStreamInfo(strm->stream);
+
+    pj_bzero(pi, sizeof(*pi));
+    pi->dir = strm->dir;
+    pi->play_id = strm->play_id;
+    pi->rec_id = strm->rec_id;
+    pi->clock_rate = (unsigned)(paSI->sampleRate);
+    pi->channel_count = strm->channel_count;
+    pi->samples_per_frame = strm->samples_per_frame;
+    pi->bits_per_sample = strm->bytes_per_sample * 8;
+    pi->rec_latency = (unsigned)(paSI->inputLatency * paSI->sampleRate);
+    pi->play_latency = (unsigned)(paSI->outputLatency * paSI->sampleRate);
+
+    return PJ_SUCCESS;
+}
+
 
 /*
Index: /pjproject/trunk/pjmedia/src/pjmedia/sound_port.c
===================================================================
--- /pjproject/trunk/pjmedia/src/pjmedia/sound_port.c	(revision 743)
+++ /pjproject/trunk/pjmedia/src/pjmedia/sound_port.c	(revision 744)
@@ -125,4 +125,5 @@
 	if (snd_port->ec_suspended) {
 	    snd_port->ec_suspended = PJ_FALSE;
+	    //pjmedia_echo_state_reset(snd_port->ec_state);
 	    PJ_LOG(4,(THIS_FILE, "EC activated"));
 	}
@@ -141,4 +142,8 @@
 	    snd_port->ec_suspended = PJ_TRUE;
 	    PJ_LOG(4,(THIS_FILE, "EC suspended because of inactivity"));
+	}
+	if (snd_port->ec_state) {
+	    /* To maintain correct delay in EC */
+	    pjmedia_echo_playback(snd_port->ec_state, output);
 	}
     }
@@ -354,5 +359,5 @@
 
 /*
- * Create sound recorder port.
+ * Create sound recorder AEC.
  */
 PJ_DEF(pj_status_t) pjmedia_snd_port_create_rec( pj_pool_t *pool,
@@ -457,4 +462,5 @@
 					     unsigned options)
 {
+    pjmedia_snd_stream_info si;
     pj_status_t status;
 
@@ -464,4 +470,8 @@
 		     PJ_EINVALIDOP);
 
+    /* Sound port must have 16bits per sample */
+    PJ_ASSERT_RETURN(snd_port->bits_per_sample == 16,
+		     PJ_EINVALIDOP);
+
     /* Destroy AEC */
     if (snd_port->ec_state) {
@@ -473,4 +483,12 @@
 
     if (tail_ms != 0) {
+	unsigned delay_ms;
+
+	status = pjmedia_snd_stream_get_info(snd_port->snd_stream, &si);
+	if (status != PJ_SUCCESS)
+	    si.rec_latency = si.play_latency = 0;
+
+	delay_ms = (si.rec_latency + si.play_latency) * 1000 /
+		   snd_port->clock_rate;
 	status = pjmedia_echo_create(pool, snd_port->clock_rate, 
 				    snd_port->samples_per_frame, 
