Index: pjproject/trunk/pjmedia/include/pjmedia/jbuf.h
===================================================================
--- pjproject/trunk/pjmedia/include/pjmedia/jbuf.h	(revision 441)
+++ pjproject/trunk/pjmedia/include/pjmedia/jbuf.h	(revision 442)
@@ -112,4 +112,6 @@
  *			delay that may be introduced by this jitter 
  *			buffer.
+ * @param ptime		Indication of frame duration, used to calculate 
+ *			the interval between jitter recalculation.
  * @param p_jb		Pointer to receive jitter buffer instance.
  *
@@ -119,4 +121,5 @@
 					 const pj_str_t *name,
 					 unsigned frame_size,
+					 unsigned ptime,
 					 unsigned max_count,
 					 pjmedia_jbuf **p_jb);
Index: pjproject/trunk/pjmedia/src/pjmedia/conference.c
===================================================================
--- pjproject/trunk/pjmedia/src/pjmedia/conference.c	(revision 441)
+++ pjproject/trunk/pjmedia/src/pjmedia/conference.c	(revision 442)
@@ -1096,4 +1096,8 @@
      * transmit NULL frame. 
      */
+    /* note:
+     *  the "cport->sources==0" checking will cause discontinuous
+     *  transmission for RTP stream.
+     */
     if (cport->tx_setting == PJMEDIA_PORT_MUTE || cport->sources==0) {
 
@@ -1125,5 +1129,5 @@
     buf = (pj_int16_t*)cport->mix_buf;
 
-    if (cport->tx_adj_level != NORMAL_LEVEL) {
+    if (cport->tx_adj_level != NORMAL_LEVEL && cport->sources) {
 
 	unsigned adj_level = cport->tx_adj_level;
@@ -1169,5 +1173,5 @@
      * indication of the signal level of the port.
      */
-    if (cport->need_tx_level) {
+    if (cport->need_tx_level && cport->sources) {
 	pj_uint32_t level;
 
Index: pjproject/trunk/pjmedia/src/pjmedia/jbuf.c
===================================================================
--- pjproject/trunk/pjmedia/src/pjmedia/jbuf.c	(revision 441)
+++ pjproject/trunk/pjmedia/src/pjmedia/jbuf.c	(revision 442)
@@ -51,4 +51,5 @@
     jb_framelist    jb_framelist;
     pj_size_t	    jb_frame_size;	  // frame size	
+    unsigned	    jb_frame_ptime;	  // frame duration.
     pj_size_t	    jb_max_count;	  // max frames in the jitter framelist->flist_buffer
 
@@ -81,4 +82,13 @@
 
 
+/* Enabling this would log the jitter buffer state about once per 
+ * second.
+ */
+#if 0
+#  define TRACE__(args)	    PJ_LOG(4,args)
+#else
+#  define TRACE__(args)
+#endif
+
 
 static pj_status_t jb_framelist_init( pj_pool_t *pool,
@@ -268,4 +278,5 @@
 					const pj_str_t *name,
 					unsigned frame_size, 
+					unsigned ptime,
 					unsigned max_count,
 					pjmedia_jbuf **p_jb)
@@ -282,4 +293,5 @@
     pj_strdup_with_null(pool, &jb->name, name);
     jb->jb_frame_size	 = frame_size;
+    jb->jb_frame_ptime   = ptime;
     jb->jb_last_seq_no	 = -1;
     jb->jb_level	 = 0;
@@ -368,5 +380,7 @@
 static void jbuf_calculate_jitter(pjmedia_jbuf *jb)
 {
-    enum { STABLE_HISTORY_LIMIT = (100*2) };
+    unsigned stable_history_limit;
+
+    stable_history_limit = 1000 / jb->jb_frame_ptime;
 
     jb->jb_last_jitter = PJ_ABS(jb->jb_level-jb->jb_last_level);
@@ -377,5 +391,5 @@
     if (jb->jb_last_jitter < jb->jb_prefetch) {
 	jb->jb_stable_hist += jb->jb_last_jitter;
-	if (jb->jb_stable_hist > STABLE_HISTORY_LIMIT) {
+	if (jb->jb_stable_hist > (int)stable_history_limit) {
 	    int seq_diff = (jb->jb_prefetch - jb->jb_max_hist_jitter)/3;
 	    if (seq_diff<1) seq_diff = 1;
@@ -388,5 +402,10 @@
 	    jb->jb_max_hist_jitter = 0;
 
-	    if (jb->jb_op_count >= STABLE_HISTORY_LIMIT*2 &&
+	    TRACE__((THIS_FILE,"jb updated(1), prefetch=%d, size=%d", 
+		     jb->jb_prefetch, jb_framelist_size(&jb->jb_framelist)));
+
+	    /* These code is used to shorten the delay in the jitter buffer.
+
+	    if (jb->jb_op_count >= stable_history_limit*2 &&
 		(int)jb_framelist_size(&jb->jb_framelist) > jb->jb_prefetch+2)
 	    {
@@ -399,4 +418,5 @@
 		jb->jb_op_count = 0;
 	    }
+	    */
 
 	}
@@ -409,5 +429,13 @@
 	jb->jb_max_hist_jitter = 0;
 
-	if (jb->jb_op_count >= STABLE_HISTORY_LIMIT * 2) {
+	TRACE__((THIS_FILE,"jb updated(2), prefetch=%d, size=%d", 
+	         jb->jb_prefetch, jb_framelist_size(&jb->jb_framelist)));
+
+	/* These code is used to shorten the delay in the jitter buffer
+	   when the current size is larger than the prefetch. But it does
+	   not really work when the stream supports multiple frames, since
+	   the size may grow only temporarily.
+
+	if (jb->jb_op_count >= stable_history_limit * 2) {
 	    if ((int)jb_framelist_size(&jb->jb_framelist) > jb->jb_prefetch+2) 
 	    {
@@ -422,4 +450,5 @@
 	    jb->jb_op_count = 0;
 	}
+	*/
     }
 }
Index: pjproject/trunk/pjmedia/src/pjmedia/stream.c
===================================================================
--- pjproject/trunk/pjmedia/src/pjmedia/stream.c	(revision 441)
+++ pjproject/trunk/pjmedia/src/pjmedia/stream.c	(revision 442)
@@ -41,4 +41,6 @@
 #define TRC_(expr)			PJ_LOG(5,expr)
 
+#define BYTES_PER_SAMPLE		2
+
 /**
  * Media channel.
@@ -55,4 +57,5 @@
     void		   *out_pkt;	    /**< Output buffer.		    */
     pjmedia_rtp_session	    rtp;	    /**< RTP session.		    */
+    char		    last_frm_type;  /**< Last frame type from jb    */
 };
 
@@ -153,8 +156,8 @@
     pjmedia_stream *stream = port->user_data;
     pjmedia_channel *channel = stream->dec;
-    
-    pj_status_t status;
     unsigned samples_count, samples_per_frame, samples_required;
     pj_int16_t *p_out_samp;
+    pj_status_t status;
+
 
     /* Return no frame is channel is paused */
@@ -181,5 +184,5 @@
 	 samples_count += samples_per_frame) 
     {
-	 char frame_type;
+	char frame_type;
 
 	/* Get frame from jitter buffer. */
@@ -199,4 +202,5 @@
 						       frame_out.size,
 						       &frame_out);
+
 	    } else {
 		status = -1;
@@ -207,23 +211,100 @@
 		pjmedia_zero_samples(p_out_samp + samples_count,
 				     samples_required - samples_count);
+		PJ_LOG(5,(stream->port.info.name.ptr,  "Frame lost!"));
+
+	    } else {
+		PJ_LOG(5,(stream->port.info.name.ptr, 
+			  "Lost frame recovered"));
 	    }
 	    
 	} else if (frame_type == PJMEDIA_JB_ZERO_EMPTY_FRAME) {
 
-	    /* Jitter buffer is empty, zero the remaining samples and break
-	     * the loop.
+	    /* Jitter buffer is empty. If this is the first "empty" state,
+	     * activate PLC to smoothen the fade-out, otherwise zero
+	     * the frame. 
 	     */
-	    pjmedia_zero_samples(p_out_samp + samples_count,
-				 samples_required - samples_count);
+	    if (frame_type != channel->last_frm_type) {
+		pjmedia_jb_state jb_state;
+
+		/* Activate PLC to smoothen the missing frame */
+		if (stream->codec->op->recover && 
+		    stream->codec_param.setting.plc) 
+		{
+		    pjmedia_frame frame_out;
+
+		    do {
+			frame_out.buf = p_out_samp + samples_count;
+			frame_out.size = frame->size - samples_count*2;
+			status = (*stream->codec->op->recover)(stream->codec,
+							       frame_out.size,
+							       &frame_out);
+			if (status != PJ_SUCCESS)
+			    break;
+			samples_count += samples_per_frame;
+
+		    } while (samples_count < samples_required);
+
+		} 
+
+		/* Report the state of jitter buffer */
+		pjmedia_jbuf_get_state(stream->jb, &jb_state);
+		PJ_LOG(5,(stream->port.info.name.ptr, 
+			  "Jitter buffer empty (prefetch=%d)", 
+			  jb_state.prefetch));
+
+	    }
+
+	    if (samples_count < samples_required) {
+		pjmedia_zero_samples(p_out_samp + samples_count,
+				     samples_required - samples_count);
+	    }
+
+	    channel->last_frm_type = frame_type;
 	    break;
 
 	} else if (frame_type != PJMEDIA_JB_NORMAL_FRAME) {
+
+	    pjmedia_jb_state jb_state;
 
 	    /* It can only be PJMEDIA_JB_ZERO_PREFETCH frame */
 	    pj_assert(frame_type == PJMEDIA_JB_ZERO_PREFETCH_FRAME);
 
-	    /* Zero frame returned. We should zero the PCM buffer then.. */
-	    pjmedia_zero_samples(p_out_samp + samples_count, 
-				 samples_per_frame);
+	    /* Get the state of jitter buffer */
+	    pjmedia_jbuf_get_state(stream->jb, &jb_state);
+
+	    /* Always activate PLC when it's available.. */
+	    if (stream->codec->op->recover && 
+		stream->codec_param.setting.plc) 
+	    {
+		pjmedia_frame frame_out;
+
+		do {
+		    frame_out.buf = p_out_samp + samples_count;
+		    frame_out.size = frame->size - samples_count*2;
+		    status = (*stream->codec->op->recover)(stream->codec,
+							   frame_out.size,
+							   &frame_out);
+		    if (status != PJ_SUCCESS)
+			break;
+		    samples_count += samples_per_frame;
+
+		} while (samples_count < samples_required);
+
+		PJ_LOG(5,(stream->port.info.name.ptr, 
+			  "Jitter buffer is bufferring with plc (prefetch=%d)",
+			  jb_state.prefetch));
+
+	    } 
+
+	    if (samples_count < samples_required) {
+		pjmedia_zero_samples(p_out_samp + samples_count,
+				     samples_required - samples_count);
+		PJ_LOG(5,(stream->port.info.name.ptr, 
+			  "Jitter buffer is bufferring (prefetch=%d)..", 
+			  jb_state.prefetch));
+	    }
+
+	    channel->last_frm_type = frame_type;
+	    break;
 
 	} else {
@@ -237,5 +318,5 @@
 
 	    frame_out.buf = p_out_samp + samples_count;
-	    frame_out.size = frame->size - samples_count*2;
+	    frame_out.size = frame->size - samples_count*BYTES_PER_SAMPLE;
 	    status = stream->codec->op->decode( stream->codec, &frame_in,
 						frame_out.size, &frame_out);
@@ -248,4 +329,6 @@
 	    }
 	}
+
+	channel->last_frm_type = frame_type;
     }
 
@@ -262,5 +345,5 @@
     } else {
 	frame->type = PJMEDIA_FRAME_TYPE_AUDIO;
-	frame->size = samples_count * 2;
+	frame->size = samples_count * BYTES_PER_SAMPLE;
 	frame->timestamp.u64 = 0;
     }
@@ -498,4 +581,5 @@
 
     pj_memcpy(channel->out_pkt, rtphdr, sizeof(pjmedia_rtp_hdr));
+
 
     /* Send. */
@@ -1030,21 +1114,20 @@
 	jb_max = info->jb_max;
     else
-	jb_max = 240 / (stream->port.info.samples_per_frame * 1000 / 
-			   info->fmt.clock_rate);
+	jb_max = 360 / stream->codec_param.info.frm_ptime;
 
     if (info->jb_min_pre >= 0)
 	jb_min_pre = info->jb_min_pre;
     else
-	jb_min_pre = 0;
+	jb_min_pre = 60 / stream->codec_param.info.frm_ptime;
 
     if (info->jb_max_pre > 0)
 	jb_max_pre = info->jb_max_pre;
     else
-	jb_max_pre = jb_max * 4 / 5;
+	jb_max_pre = 240 / stream->codec_param.info.frm_ptime;
 
     if (info->jb_init >= 0)
 	jb_init = info->jb_init;
     else
-	jb_init = jb_min_pre;
+	jb_init = (jb_min_pre + jb_max_pre) / 2;
 
 
@@ -1052,4 +1135,5 @@
     status = pjmedia_jbuf_create(pool, &stream->port.info.name,
 				 stream->frame_size, 
+				 stream->codec_param.info.frm_ptime,
 				 jb_max, &stream->jb);
     if (status != PJ_SUCCESS)
Index: pjproject/trunk/pjsip-apps/src/samples/siprtp_report.c
===================================================================
--- pjproject/trunk/pjsip-apps/src/samples/siprtp_report.c	(revision 441)
+++ pjproject/trunk/pjsip-apps/src/samples/siprtp_report.c	(revision 442)
@@ -60,5 +60,5 @@
 
     /* Print duration */
-    if (inv->state >= PJSIP_INV_STATE_CONFIRMED) {
+    if (inv->state >= PJSIP_INV_STATE_CONFIRMED && call->connect_time) {
 
 	PJ_TIME_VAL_SUB(now, call->connect_time);
