Index: /pjproject/trunk/pjmedia/include/pjmedia/silencedet.h
===================================================================
--- /pjproject/trunk/pjmedia/include/pjmedia/silencedet.h	(revision 456)
+++ /pjproject/trunk/pjmedia/include/pjmedia/silencedet.h	(revision 457)
@@ -37,41 +37,81 @@
 
 /**
+ * Suggested or default threshold to be set for fixed silence detection
+ * or as starting threshold for adaptive silence detection. The threshold
+ * has the range from zero to 255.
+ */
+#define PJMEDIA_SILENCE_DET_THRESHOLD	4
+
+
+/**
  * Create voice activity detector with default settings. The default settings
- * are to perform adaptive silence detection, which adjusts the noise level
- * dynamically based on current input level.
+ * are set to adaptive silence detection with the default threshold.
  *
- * @param pool		Pool for allocating the structure.
- * @param p_sd		Pointer to receive the silence detector instance.
+ * @param pool		    Pool for allocating the structure.
+ * @param clock_rate	    Clock rate.
+ * @param samples_per_frame Number of samples per frame. The clock_rate and
+ *			    samples_per_frame is only used to calculate the
+ *			    frame time, from which some timing parameters
+ *			    are calculated from.
+ * @param p_sd		    Pointer to receive the silence detector instance.
  *
- * @return		PJ_SUCCESS on success.
+ * @return		    PJ_SUCCESS on success.
  */
 PJ_DECL(pj_status_t) pjmedia_silence_det_create( pj_pool_t *pool,
+						 unsigned clock_rate,
+						 unsigned samples_per_frame,
 						 pjmedia_silence_det **p_sd );
 
 
 /**
- * Set the sd to operate in adaptive mode.
- *
- * @param sd	        The silence detector
- * @param frame_size	Number of samples per frame.
- *
- * @return	        PJ_SUCCESS on success.
- */
-PJ_DECL(pj_status_t) pjmedia_silence_det_set_adaptive( pjmedia_silence_det *sd,
-						       unsigned frame_size);
-
-
-/**
- * Set the sd to operate in fixed threshold mode.
+ * Set the sd to operate in fixed threshold mode. With fixed threshold mode,
+ * the threshold will not be changed adaptively.
  *
  * @param sd		    The silence detector
- * @param frame_size Number of samplse per frame.
- * @param threshold	    The silence threshold.
+ * @param threshold	    The silence threshold, or -1 to use default
+ *			    threshold.
  *
  * @return		    PJ_SUCCESS on success.
  */
 PJ_DECL(pj_status_t) pjmedia_silence_det_set_fixed( pjmedia_silence_det *sd,
-						    unsigned frame_size,
-						    unsigned threshold );
+						    int threshold );
+
+/**
+ * Set the sd to operate in adaptive mode. This is the default mode
+ * when the silence detector is created.
+ *
+ * @param sd		    The silence detector
+ * @param threshold	    Initial threshold to be set, or -1 to use default
+ *			    threshold.
+ *
+ * @return		    PJ_SUCCESS on success.
+ */
+PJ_DECL(pj_status_t) pjmedia_silence_det_set_adaptive(pjmedia_silence_det *sd,
+						      int threshold);
+
+/**
+ * Set other silence detector parameters.
+ *
+ * @param sd		    The silence detector
+ * @param min_silence	    Minimum duration of silence (in msec) before 
+ *			    silence is reported. If -1 is specified, then
+ *			    the default value will be used. The default is
+ *			    400 msec.
+ * @param min_signal	    Minimum duration of signal (in msec) before
+ *			    signal is reported. If -1 is specified, then
+ *			    the default value will be used. The default is
+ *			    one frame.
+ * @param recalc_time	    The interval to recalculate signal and silence
+ *			    proportion and to readjust the silence threshold
+ *			    when adaptive silence detection is set. If -1
+ *			    is specified, then the default value will be used.
+ *			    The default value is 5000 (msec).
+ *
+ * @return		    PJ_SUCCESS on success.
+ */
+PJ_DECL(pj_status_t) pjmedia_silence_det_set_params( pjmedia_silence_det *sd,
+						     int min_silence,
+						     int min_signal,
+						     int recalc_time);
 
 /**
Index: /pjproject/trunk/pjmedia/src/pjmedia-codec/gsm.c
===================================================================
--- /pjproject/trunk/pjmedia/src/pjmedia-codec/gsm.c	(revision 456)
+++ /pjproject/trunk/pjmedia/src/pjmedia-codec/gsm.c	(revision 457)
@@ -21,5 +21,7 @@
 #include <pjmedia/errno.h>
 #include <pjmedia/endpoint.h>
+#include <pjmedia/plc.h>
 #include <pjmedia/port.h>
+#include <pjmedia/silencedet.h>
 #include <pj/assert.h>
 #include <pj/pool.h>
@@ -69,4 +71,7 @@
 				      unsigned output_buf_len, 
 				      struct pjmedia_frame *output);
+static pj_status_t  gsm_codec_recover(pjmedia_codec *codec,
+				      unsigned output_buf_len,
+				      struct pjmedia_frame *output);
 
 /* Definition for GSM codec operations. */
@@ -78,5 +83,6 @@
     &gsm_codec_parse,
     &gsm_codec_encode,
-    &gsm_codec_decode
+    &gsm_codec_decode,
+    &gsm_codec_recover
 };
 
@@ -101,9 +107,14 @@
 } gsm_codec_factory;
 
+
 /* GSM codec private data. */
 struct gsm_data
 {
-    void    *encoder;
-    void    *decoder;
+    void		*encoder;
+    void		*decoder;
+    pj_bool_t		 plc_enabled;
+    pjmedia_plc		*plc;
+    pj_bool_t		 vad_enabled;
+    pjmedia_silence_det	*vad;
 };
 
@@ -240,6 +251,8 @@
 
     attr->setting.frm_per_pkt = 1;
-
-    /* Default all flag bits disabled. */
+    attr->setting.vad = 1;
+    attr->setting.plc = 1;
+
+    /* Default all other flag bits disabled. */
 
     return PJ_SUCCESS;
@@ -277,4 +290,5 @@
     pjmedia_codec *codec;
     struct gsm_data *gsm_data;
+    pj_status_t status;
 
     PJ_ASSERT_RETURN(factory && id && p_codec, PJ_EINVAL);
@@ -298,4 +312,21 @@
 				  sizeof(struct gsm_data));
 	codec->codec_data = gsm_data;
+
+	/* Create PLC */
+	status = pjmedia_plc_create(gsm_codec_factory.pool, 8000, 
+				    160, 0, &gsm_data->plc);
+	if (status != PJ_SUCCESS) {
+	    pj_mutex_unlock(gsm_codec_factory.mutex);
+	    return status;
+	}
+
+	/* Create silence detector */
+	status = pjmedia_silence_det_create(gsm_codec_factory.pool,
+					    8000, 160,
+					    &gsm_data->vad);
+	if (status != PJ_SUCCESS) {
+	    pj_mutex_unlock(gsm_codec_factory.mutex);
+	    return status;
+	}
     }
 
@@ -361,4 +392,7 @@
     if (!gsm_data->decoder)
 	return PJMEDIA_CODEC_EFAILED;
+
+    gsm_data->vad_enabled = (attr->setting.vad != 0);
+    gsm_data->plc_enabled = (attr->setting.plc != 0);
 
     return PJ_SUCCESS;
@@ -438,4 +472,22 @@
 	return PJMEDIA_CODEC_EPCMTOOSHORT;
 
+    /* Detect silence */
+    if (gsm_data->vad_enabled) {
+	pj_bool_t is_silence;
+
+	is_silence = pjmedia_silence_det_detect(gsm_data->vad, 
+					        input->buf,
+						input->size / 2,
+						NULL);
+	if (is_silence) {
+	    output->type = PJMEDIA_FRAME_TYPE_NONE;
+	    output->buf = NULL;
+	    output->size = 0;
+	    output->timestamp.u64 = input->timestamp.u64;
+	    return PJ_SUCCESS;
+	}
+    }
+
+    /* Encode */
     gsm_encode(gsm_data->encoder, (short*)input->buf, 
 	       (unsigned char*)output->buf);
@@ -473,4 +525,27 @@
     output->type = PJMEDIA_FRAME_TYPE_AUDIO;
 
+    if (gsm_data->plc_enabled)
+	pjmedia_plc_save( gsm_data->plc, output->buf);
+
+    return PJ_SUCCESS;
+}
+
+
+/*
+ * Recover lost frame.
+ */
+static pj_status_t  gsm_codec_recover(pjmedia_codec *codec,
+				      unsigned output_buf_len,
+				      struct pjmedia_frame *output)
+{
+    struct gsm_data *gsm_data = codec->codec_data;
+
+    PJ_ASSERT_RETURN(gsm_data->plc_enabled, PJ_EINVALIDOP);
+
+    PJ_ASSERT_RETURN(output_buf_len >= 320, PJMEDIA_CODEC_EPCMTOOSHORT);
+
+    pjmedia_plc_generate(gsm_data->plc, output->buf);
+    output->size = 320;
+
     return PJ_SUCCESS;
 }
Index: /pjproject/trunk/pjmedia/src/pjmedia-codec/speex_codec.c
===================================================================
--- /pjproject/trunk/pjmedia/src/pjmedia-codec/speex_codec.c	(revision 456)
+++ /pjproject/trunk/pjmedia/src/pjmedia-codec/speex_codec.c	(revision 457)
@@ -38,6 +38,6 @@
 #define THIS_FILE   "speex_codec.c"
 
-#define DEFAULT_QUALITY	    4
-#define DEFAULT_COMPLEXITY  -1
+#define DEFAULT_QUALITY	    10
+#define DEFAULT_COMPLEXITY  10
 
 /* Prototypes for Speex factory */
@@ -256,6 +256,6 @@
 
     /* Somehow quality <=4 is broken in linux. */
-    if (quality <= 4) {
-	PJ_LOG(4,(THIS_FILE, "Adjusting quality to 5 for uwb"));
+    if (quality <= 4 && quality >= 0) {
+	PJ_LOG(5,(THIS_FILE, "Adjusting quality to 5 for uwb"));
 	spx_factory.speex_param[PARAM_UWB].quality = 5;
     }
@@ -412,7 +412,5 @@
     attr->setting.lpf =1 ;
     attr->setting.penh =1 ;
-
-    /* Default, set VAD off as it caused voice chip off */
-    attr->setting.vad = 0;
+    attr->setting.vad = 1;
 
     return PJ_SUCCESS;
@@ -572,6 +570,7 @@
 
     /* VAD */
-    tmp = attr->setting.vad;
+    tmp = (attr->setting.vad != 0);
     speex_encoder_ctl(spx->enc, SPEEX_SET_VAD, &tmp);
+    speex_encoder_ctl(spx->enc, SPEEX_SET_DTX, &tmp);
 
     /* Complexity */
@@ -688,4 +687,5 @@
     pj_int16_t *samp_in;
     unsigned i, samp_count, sz;
+    int tx;
 
     spx = (struct spx_private*) codec->codec_data;
@@ -711,5 +711,14 @@
 
     /* Encode the frame */
-    speex_encode(spx->enc, tmp, &spx->enc_bits);
+    tx = speex_encode(spx->enc, tmp, &spx->enc_bits);
+
+    /* Check if we need not to transmit the frame (DTX) */
+    if (tx == 0) {
+	output->buf = NULL;
+	output->size = 0;
+	output->timestamp.u64 = input->timestamp.u64;
+	output->type = PJMEDIA_FRAME_TYPE_NONE;
+	return PJ_SUCCESS;
+    }
 
     /* Check size. */
Index: /pjproject/trunk/pjmedia/src/pjmedia/conference.c
===================================================================
--- /pjproject/trunk/pjmedia/src/pjmedia/conference.c	(revision 456)
+++ /pjproject/trunk/pjmedia/src/pjmedia/conference.c	(revision 457)
@@ -229,9 +229,12 @@
 
     /* Create and init vad. */
-    status = pjmedia_silence_det_create( pool, &conf_port->vad);
+    status = pjmedia_silence_det_create( pool, 
+					 port->info.clock_rate,
+					 port->info.samples_per_frame,
+					 &conf_port->vad);
     if (status != PJ_SUCCESS)
 	return status;
 
-    pjmedia_silence_det_set_adaptive(conf_port->vad, conf->samples_per_frame);
+    pjmedia_silence_det_set_fixed(conf_port->vad, 2);
 
     /* Save some port's infos, for convenience. */
Index: /pjproject/trunk/pjmedia/src/pjmedia/g711.c
===================================================================
--- /pjproject/trunk/pjmedia/src/pjmedia/g711.c	(revision 456)
+++ /pjproject/trunk/pjmedia/src/pjmedia/g711.c	(revision 457)
@@ -25,4 +25,5 @@
 #include <pjmedia/port.h>
 #include <pjmedia/plc.h>
+#include <pjmedia/silencedet.h>
 #include <pj/pool.h>
 #include <pj/string.h>
@@ -122,7 +123,9 @@
 struct g711_private
 {
-    unsigned	    pt;
-    pj_bool_t	    plc_enabled;
-    pjmedia_plc	   *plc;
+    unsigned		 pt;
+    pj_bool_t		 plc_enabled;
+    pjmedia_plc		*plc;
+    pj_bool_t		 vad_enabled;
+    pjmedia_silence_det *vad;
 };
 
@@ -251,5 +254,8 @@
     attr->setting.plc = 1;
 
-    /* Default all flag bits disabled. */
+    /* Enable VAD by default. */
+    attr->setting.vad = 1;
+
+    /* Default all other flag bits disabled. */
 
     return PJ_SUCCESS;
@@ -303,6 +309,6 @@
 
 	codec = pj_pool_alloc(g711_factory.pool, sizeof(pjmedia_codec));
-	codec_priv = pj_pool_alloc(g711_factory.pool, 
-				   sizeof(struct g711_private));
+	codec_priv = pj_pool_zalloc(g711_factory.pool, 
+				    sizeof(struct g711_private));
 	if (!codec || !codec_priv) {
 	    pj_mutex_unlock(g711_factory.mutex);
@@ -321,4 +327,13 @@
 	}
 
+	/* Create VAD */
+	status = pjmedia_silence_det_create(g711_factory.pool,
+					    8000, 80,
+					    &codec_priv->vad);
+	if (status != PJ_SUCCESS) {
+	    pj_mutex_unlock(g711_factory.mutex);
+	    return status;
+	}
+
 	codec->factory = factory;
 	codec->op = &g711_op;
@@ -379,4 +394,5 @@
     priv->pt = attr->info.pt;
     priv->plc_enabled = (attr->setting.plc != 0);
+    priv->vad_enabled = (attr->setting.vad != 0);
     return PJ_SUCCESS;
 }
@@ -429,4 +445,19 @@
     if (output_buf_len < input->size / 2)
 	return PJMEDIA_CODEC_EFRMTOOSHORT;
+
+    /* Detect silence if VAD is enabled */
+    if (priv->vad_enabled) {
+	pj_bool_t is_silence;
+
+	is_silence = pjmedia_silence_det_detect(priv->vad, input->buf, 
+						input->size / 2, NULL);
+	if (is_silence) {
+	    output->type = PJMEDIA_FRAME_TYPE_NONE;
+	    output->buf = NULL;
+	    output->size = 0;
+	    output->timestamp.u64 = input->timestamp.u64;
+	    return PJ_SUCCESS;
+	}
+    }
 
     /* Encode */
Index: /pjproject/trunk/pjmedia/src/pjmedia/silencedet.c
===================================================================
--- /pjproject/trunk/pjmedia/src/pjmedia/silencedet.c	(revision 456)
+++ /pjproject/trunk/pjmedia/src/pjmedia/silencedet.c	(revision 457)
@@ -33,4 +33,5 @@
 
 
+
 /**
  * This structure holds the silence detector state.
@@ -39,6 +40,5 @@
 {
     int	      mode;		/**< VAD mode.				    */
-    unsigned  frame_size;	/**< Samples per frame.			    */
-
+    unsigned  ptime;		/**< Frame time, in msec.		    */
 
     unsigned  min_signal_cnt;	/**< # of signal frames.before talk burst   */
@@ -61,4 +61,6 @@
 
 PJ_DEF(pj_status_t) pjmedia_silence_det_create( pj_pool_t *pool,
+						unsigned clock_rate,
+						unsigned samples_per_frame,
 						pjmedia_silence_det **p_sd)
 {
@@ -69,12 +71,16 @@
     sd = pj_pool_zalloc(pool, sizeof(struct pjmedia_silence_det));
 
+    sd->ptime = samples_per_frame * 1000 / clock_rate;
+    sd->signal_cnt = 0;
+    sd->silence_cnt = 0;
     sd->weakest_signal = 0xFFFFFFFFUL;
     sd->loudest_silence = 0;
-    sd->signal_cnt = 0;
-    sd->silence_cnt = 0;
-    
-    /* Restart in adaptive, silent mode */
+     
+    /* Default settings */
+    pjmedia_silence_det_set_params(sd, -1, -1, -1);
+
+    /* Restart in fixed, silent mode */
     sd->in_talk = PJ_FALSE;
-    pjmedia_silence_det_set_adaptive( sd, 160 );
+    pjmedia_silence_det_set_adaptive( sd, -1 );
 
     *p_sd = sd;
@@ -82,15 +88,14 @@
 }
 
-PJ_DEF(pj_status_t) pjmedia_silence_det_set_adaptive( pjmedia_silence_det *sd,
-						      unsigned frame_size)
-{
-    PJ_ASSERT_RETURN(sd && frame_size, PJ_EINVAL);
-
-    sd->frame_size = frame_size;
+PJ_DEF(pj_status_t) pjmedia_silence_det_set_adaptive(pjmedia_silence_det *sd,
+						     int threshold)
+{
+    PJ_ASSERT_RETURN(sd, PJ_EINVAL);
+
+    if (threshold < 0)
+	threshold = PJMEDIA_SILENCE_DET_THRESHOLD;
+
     sd->mode = VAD_MODE_ADAPTIVE;
-    sd->min_signal_cnt = 10;
-    sd->min_silence_cnt = 64;
-    sd->recalc_cnt = 250;
-    sd->cur_threshold = 20;
+    sd->cur_threshold = threshold;
 
     return PJ_SUCCESS;
@@ -98,15 +103,38 @@
 
 PJ_DEF(pj_status_t) pjmedia_silence_det_set_fixed( pjmedia_silence_det *sd,
-						   unsigned frame_size,
-						   unsigned threshold )
-{
-    PJ_ASSERT_RETURN(sd && frame_size, PJ_EINVAL);
+						   int threshold )
+{
+    PJ_ASSERT_RETURN(sd, PJ_EINVAL);
+
+    if (threshold < 0)
+	threshold = PJMEDIA_SILENCE_DET_THRESHOLD;
 
     sd->mode = VAD_MODE_FIXED;
-    sd->frame_size = frame_size;
     sd->cur_threshold = threshold;
 
     return PJ_SUCCESS;
 }
+
+PJ_DEF(pj_status_t) pjmedia_silence_det_set_params( pjmedia_silence_det *sd,
+						    int min_silence,
+						    int min_signal,
+						    int recalc_time)
+{
+    PJ_ASSERT_RETURN(sd, PJ_EINVAL);
+
+    if (min_silence == -1)
+	min_silence = 500;
+    if (min_signal < 0)
+	min_signal = sd->ptime;
+    if (recalc_time < 0)
+	recalc_time = 5000;
+
+    sd->min_signal_cnt = min_signal / sd->ptime;
+    sd->min_silence_cnt = min_silence / sd->ptime;
+    sd->recalc_cnt = recalc_time / sd->ptime;
+
+    return PJ_SUCCESS;
+}
+
 
 PJ_DEF(pj_status_t) pjmedia_silence_det_disable( pjmedia_silence_det *sd )
@@ -185,9 +213,4 @@
     }
     
-    /* For fixed threshold sd, everything is done. */
-    if (sd->mode == VAD_MODE_FIXED) {
-	return !sd->in_talk;
-    }
-    
 
     /* Count the number of silent and signal frames and calculate min/max */
@@ -208,37 +231,27 @@
     if ((sd->signal_cnt + sd->silence_cnt) > sd->recalc_cnt) {
 	
-	/* Adjust silence threshold by looking at the proportions of
-	 * signal and silence frames.
-	 */
-	if (sd->signal_cnt >= sd->recalc_cnt) {
-	    /* All frames where signal frames.
-	     * Increase silence threshold.
-	     */
-	    sd->cur_threshold += (sd->weakest_signal - sd->cur_threshold)/4;
-	    PJ_LOG(6,(THIS_FILE, "Vad cur_threshold increased to %d",
-		      sd->cur_threshold));
-	}
-	else if (sd->silence_cnt >= sd->recalc_cnt) {
-	    /* All frames where silence frames.
-	     * Decrease silence threshold.
-	     */
-	    sd->cur_threshold = (sd->cur_threshold+sd->loudest_silence)/2+1;
-	    PJ_LOG(6,(THIS_FILE, "Vad cur_threshold decreased to %d",
-		      sd->cur_threshold));
-	}
-	else { 
+	if (sd->mode == VAD_MODE_ADAPTIVE) {
 	    pj_bool_t updated = PJ_TRUE;
+	    unsigned pct_signal;
+
+	    /* Get percentage of signal */
+	    pct_signal = sd->signal_cnt * 100 / 
+		        (sd->signal_cnt + sd->silence_cnt);
 
 	    /* Adjust according to signal/silence proportions. */
-	    if (sd->signal_cnt > sd->silence_cnt * 2)
+	    if (pct_signal > 95) {
+		sd->cur_threshold += (sd->weakest_signal - sd->cur_threshold)/4;
+	    } else if (pct_signal < 5) {
+		sd->cur_threshold = (sd->cur_threshold+sd->loudest_silence)/2+1;
+	    } else if (pct_signal > 90) {
 		sd->cur_threshold++;
-	    else if (sd->silence_cnt >  sd->signal_cnt* 2)
+	    } else if (pct_signal < 10) {
 		sd->cur_threshold--;
-	    else
+	    } else {
 		updated = PJ_FALSE;
+	    }
 
 	    if (updated) {
-		PJ_LOG(6,(THIS_FILE,
-			  "Vad cur_threshold updated to %d",
+		PJ_LOG(5,(THIS_FILE, "Vad cur_threshold updated to %d",
 			  sd->cur_threshold));
 	    }
Index: /pjproject/trunk/pjmedia/src/pjmedia/stream.c
===================================================================
--- /pjproject/trunk/pjmedia/src/pjmedia/stream.c	(revision 456)
+++ /pjproject/trunk/pjmedia/src/pjmedia/stream.c	(revision 457)
@@ -57,5 +57,4 @@
     void		   *out_pkt;	    /**< Output buffer.		    */
     pjmedia_rtp_session	    rtp;	    /**< RTP session.		    */
-    char		    last_frm_type;  /**< Last frame type from jb    */
 };
 
@@ -91,6 +90,11 @@
     pjmedia_codec_param	     codec_param;   /**< Codec param.		    */
     unsigned		     frame_size;    /**< Size of encoded base frame.*/
+    pj_bool_t		     is_streaming;  /**< Currently streaming?. This
+						 is used to put RTP marker
+						 bit.			    */
+
     pj_mutex_t		    *jb_mutex;
     pjmedia_jbuf	    *jb;	    /**< Jitter buffer.		    */
+    char		     jb_last_frm;   /**< Last frame type from jb    */
 
     pjmedia_rtcp_session     rtcp;	    /**< RTCP for incoming RTP.	    */
@@ -210,5 +214,5 @@
 	     * the frame. 
 	     */
-	    if (frame_type != channel->last_frm_type) {
+	    if (frame_type != stream->jb_last_frm) {
 		pjmedia_jb_state jb_state;
 
@@ -244,7 +248,8 @@
 		pjmedia_zero_samples(p_out_samp + samples_count,
 				     samples_required - samples_count);
+		samples_count = samples_required;
 	    }
 
-	    channel->last_frm_type = frame_type;
+	    stream->jb_last_frm = frame_type;
 	    break;
 
@@ -277,5 +282,5 @@
 		} while (samples_count < samples_required);
 
-		if (channel->last_frm_type != frame_type) {
+		if (stream->jb_last_frm != frame_type) {
 		    PJ_LOG(5,(stream->port.info.name.ptr, 
 			      "Jitter buffer is bufferring with plc (prefetch=%d)",
@@ -288,4 +293,5 @@
 		pjmedia_zero_samples(p_out_samp + samples_count,
 				     samples_required - samples_count);
+		samples_count = samples_required;
 		PJ_LOG(5,(stream->port.info.name.ptr, 
 			  "Jitter buffer is bufferring (prefetch=%d)..", 
@@ -293,5 +299,5 @@
 	    }
 
-	    channel->last_frm_type = frame_type;
+	    stream->jb_last_frm = frame_type;
 	    break;
 
@@ -318,5 +324,5 @@
 	}
 
-	channel->last_frm_type = frame_type;
+	stream->jb_last_frm = frame_type;
     }
 
@@ -438,8 +444,6 @@
     struct pjmedia_frame frame_out;
     unsigned ts_len;
-    pj_bool_t has_tx;
     void *rtphdr;
     int rtphdrlen;
-    pj_ssize_t sent;
 
 
@@ -454,7 +458,6 @@
     /* Init frame_out buffer. */
     frame_out.buf = ((char*)channel->out_pkt) + sizeof(pjmedia_rtp_hdr);
-
-    /* Make compiler happy */
     frame_out.size = 0;
+
 
     /* If we have DTMF digits in the queue, transmit the digits. 
@@ -463,5 +466,4 @@
     if (stream->tx_dtmf_count) {
 
-	has_tx = PJ_TRUE;
 	create_dtmf_payload(stream, &frame_out);
 
@@ -475,6 +477,4 @@
     } else if (frame->type != PJMEDIA_FRAME_TYPE_NONE) {
 	unsigned ts, samples_per_frame;
-
-	has_tx = PJ_TRUE;
 
 	/* Repeatedly call encode if there are multiple frames to be
@@ -490,10 +490,13 @@
 	    unsigned bytes_per_sample, max_size;
 
+	    /* Nb of bytes in PCM sample */
 	    bytes_per_sample = stream->codec_param.info.pcm_bits_per_sample/8;
 
+	    /* Split original PCM input frame into base frame size */
 	    tmp_in_frame.buf = ((char*)frame->buf) + ts * bytes_per_sample;
 	    tmp_in_frame.size = samples_per_frame * bytes_per_sample;
 	    tmp_in_frame.type = PJMEDIA_FRAME_TYPE_AUDIO;
 
+	    /* Set output frame position */
 	    tmp_out_frame.buf = ((char*)frame_out.buf) + frame_out.size;
 
@@ -501,4 +504,5 @@
 		       frame_out.size;
 
+	    /* Encode! */
 	    status = stream->codec->op->encode( stream->codec, &tmp_in_frame, 
 						max_size, &tmp_out_frame);
@@ -509,8 +513,17 @@
 	    }
 
+	    /* tmp_out_frame.size may be zero for silence frame. */
 	    frame_out.size += tmp_out_frame.size;
+
+	    /* Stop processing next PCM frame when encode() returns either 
+	     * CNG frame or NULL frame.
+	     */
+	    if (tmp_out_frame.type!=PJMEDIA_FRAME_TYPE_AUDIO || 
+		tmp_out_frame.size==0) 
+	    {
+		break;
+	    }
+
 	}
-
-	//printf("p"); fflush(stdout);
 
 	/* Encapsulate. */
@@ -523,5 +536,4 @@
 
 	/* Just update RTP session's timestamp. */
-	has_tx = PJ_FALSE;
 	status = pjmedia_rtp_encode_rtp( &channel->rtp, 
 					 0, 0, 
@@ -547,21 +559,32 @@
 
     /* Do nothing if we have nothing to transmit */
-    if (!has_tx)
+    if (frame_out.size == 0) {
+	if (stream->is_streaming) {
+	    PJ_LOG(5,(stream->port.info.name.ptr,"Starting silence"));
+	    stream->is_streaming = PJ_FALSE;
+	}
 	return PJ_SUCCESS;
-
-    if (rtphdrlen != sizeof(pjmedia_rtp_hdr)) {
-	/* We don't support RTP with extended header yet. */
-	PJ_TODO(SUPPORT_SENDING_RTP_WITH_EXTENDED_HEADER);
-	return PJ_SUCCESS;
-    }
-
+    }
+
+
+    /* Copy RTP header to the beginning of packet */
     pj_memcpy(channel->out_pkt, rtphdr, sizeof(pjmedia_rtp_hdr));
 
 
-    /* Send. */
-    sent = frame_out.size+sizeof(pjmedia_rtp_hdr);
-
+    /* Set RTP marker bit if currently not streaming */
+    if (stream->is_streaming == PJ_FALSE) {
+	pjmedia_rtp_hdr *rtp = channel->out_pkt;
+
+	rtp->m = 1;
+	PJ_LOG(5,(stream->port.info.name.ptr,"Start talksprut.."));
+    }
+
+    stream->is_streaming = PJ_TRUE;
+
+    /* Send the RTP packet to the transport. */
     (*stream->transport->op->send_rtp)(stream->transport,
-				       channel->out_pkt, sent);
+				       channel->out_pkt, 
+				       frame_out.size + 
+					    sizeof(pjmedia_rtp_hdr));
 
 
Index: /pjproject/trunk/pjmedia/src/pjmedia/transport_udp.c
===================================================================
--- /pjproject/trunk/pjmedia/src/pjmedia/transport_udp.c	(revision 456)
+++ /pjproject/trunk/pjmedia/src/pjmedia/transport_udp.c	(revision 457)
@@ -398,9 +398,4 @@
     PJ_ASSERT_RETURN(tp && strm && rem_addr && addr_len, PJ_EINVAL);
 
-    /* Remote address must be Internet address */
-    PJ_ASSERT_RETURN(addr_len == sizeof(pj_sockaddr_in) &&
-		     ((pj_sockaddr_in*)rem_addr)->sin_family == PJ_AF_INET,
-		     PJ_EINVAL);
-
     /* Must not be "attached" to existing stream */
     PJ_ASSERT_RETURN(udp->stream == NULL, PJ_EINVALIDOP);
