Index: pjproject/trunk/pjmedia/include/pjmedia/codec.h
===================================================================
--- pjproject/trunk/pjmedia/include/pjmedia/codec.h	(revision 1982)
+++ pjproject/trunk/pjmedia/include/pjmedia/codec.h	(revision 1983)
@@ -376,5 +376,5 @@
     /** 
      * Instruct the codec to encode the specified input frame. The input
-     * PCM samples MUST have ptime that is exactly equal to base frame
+     * PCM samples MUST have ptime that is multiplication of base frame
      * ptime (i.e. the value of info.frm_ptime in #pjmedia_codec_param).
      *
Index: pjproject/trunk/pjmedia/include/pjmedia/jbuf.h
===================================================================
--- pjproject/trunk/pjmedia/include/pjmedia/jbuf.h	(revision 1982)
+++ pjproject/trunk/pjmedia/include/pjmedia/jbuf.h	(revision 1983)
@@ -220,4 +220,7 @@
  *			buffer.
  * @param size		The frame size.
+ * @param bit_info	Bit precise info of the frame, e.g: a frame may not 
+ *			exactly start and end at the octet boundary, so this
+ *			field may be used for specifying start & end bit offset.
  * @param frame_seq	The frame sequence number.
  * @param discarded	Flag whether the frame is discarded by jitter buffer.
@@ -226,4 +229,5 @@
 				       const void *frame, 
 				       pj_size_t size, 
+				       pj_uint32_t bit_info,
 				       int frame_seq,
 				       pj_bool_t *discarded);
@@ -268,9 +272,13 @@
  * @param p_frm_type	Pointer to receive frame type.
  *			@see pjmedia_jbuf_get_frame().    
+ * @param bit_info	Bit precise info of the frame, e.g: a frame may not 
+ *			exactly start and end at the octet boundary, so this
+ *			field may be used for specifying start & end bit offset.
  */
 PJ_DECL(void) pjmedia_jbuf_get_frame2(pjmedia_jbuf *jb, 
 				      void *frame, 
 				      pj_size_t *size, 
-				      char *p_frm_type);
+				      char *p_frm_type,
+				      pj_uint32_t *bit_info);
 
 
Index: pjproject/trunk/pjmedia/include/pjmedia/port.h
===================================================================
--- pjproject/trunk/pjmedia/include/pjmedia/port.h	(revision 1982)
+++ pjproject/trunk/pjmedia/include/pjmedia/port.h	(revision 1983)
@@ -299,8 +299,13 @@
 struct pjmedia_frame
 {
-    pjmedia_frame_type	 type;	    /**< Frame type.		    */
-    void		*buf;	    /**< Pointer to buffer.	    */
-    pj_size_t		 size;	    /**< Frame size in bytes.	    */
-    pj_timestamp	 timestamp; /**< Frame timestamp.	    */
+    pjmedia_frame_type	 type;	    /**< Frame type.			    */
+    void		*buf;	    /**< Pointer to buffer.		    */
+    pj_size_t		 size;	    /**< Frame size in bytes.		    */
+    pj_timestamp	 timestamp; /**< Frame timestamp.		    */
+    pj_uint32_t		 bit_info;  /**< Bit info of the frame, sample case:
+					 a frame may not exactly start and end
+					 at the octet boundary, so this field 
+					 may be used for specifying start & 
+					 end bit offset.		    */
 };
 
Index: pjproject/trunk/pjmedia/src/pjmedia-codec/g722.c
===================================================================
--- pjproject/trunk/pjmedia/src/pjmedia-codec/g722.c	(revision 1982)
+++ pjproject/trunk/pjmedia/src/pjmedia-codec/g722.c	(revision 1983)
@@ -533,12 +533,8 @@
     pj_status_t status;
 
-    pj_assert(g722_data != NULL);
-    PJ_ASSERT_RETURN(input && output, PJ_EINVAL);
-
-    if (output_buf_len < FRAME_LEN)
-	return PJMEDIA_CODEC_EFRMTOOSHORT;
-
-    PJ_ASSERT_RETURN(input->size/2 == SAMPLES_PER_FRAME, 
-                     PJMEDIA_CODEC_EPCMFRMINLEN);
+    pj_assert(g722_data && input && output);
+
+    PJ_ASSERT_RETURN((input->size >> 2) <= output_buf_len, 
+                     PJMEDIA_CODEC_EFRMTOOSHORT);
 
     /* Detect silence */
@@ -571,5 +567,5 @@
     output->size = output_buf_len;
     status = g722_enc_encode(&g722_data->encoder, (pj_int16_t*)input->buf, 
-			     SAMPLES_PER_FRAME, output->buf, &output->size);
+			     (input->size >> 1), output->buf, &output->size);
     if (status != PJ_SUCCESS) {
 	output->size = 0;
Index: pjproject/trunk/pjmedia/src/pjmedia-codec/gsm.c
===================================================================
--- pjproject/trunk/pjmedia/src/pjmedia-codec/gsm.c	(revision 1982)
+++ pjproject/trunk/pjmedia/src/pjmedia-codec/gsm.c	(revision 1983)
@@ -516,12 +516,15 @@
 {
     struct gsm_data *gsm_data = (struct gsm_data*) codec->codec_data;
-
-    pj_assert(gsm_data != NULL);
-    PJ_ASSERT_RETURN(input && output, PJ_EINVAL);
-
-    if (output_buf_len < 33)
-	return PJMEDIA_CODEC_EFRMTOOSHORT;
-
-    PJ_ASSERT_RETURN(input->size==320, PJMEDIA_CODEC_EPCMFRMINLEN);
+    pj_int16_t *pcm_in;
+    unsigned in_size;
+
+    pj_assert(gsm_data && input && output);
+    
+    pcm_in = (pj_int16_t*)input->buf;
+    in_size = input->size;
+
+    PJ_ASSERT_RETURN(in_size % 320 == 0, PJMEDIA_CODEC_EPCMFRMINLEN);
+    PJ_ASSERT_RETURN(output_buf_len >= 33 * in_size/320, 
+		     PJMEDIA_CODEC_EFRMTOOSHORT);
 
     /* Detect silence */
@@ -552,8 +555,13 @@
 
     /* Encode */
-    gsm_encode(gsm_data->encoder, (short*)input->buf, 
-	       (unsigned char*)output->buf);
-
-    output->size = 33;
+    output->size = 0;
+    while (in_size >= 320) {
+	gsm_encode(gsm_data->encoder, pcm_in, 
+		   (unsigned char*)output->buf + output->size);
+	pcm_in += 160;
+	output->size += 33;
+	in_size -= 320;
+    }
+
     output->type = PJMEDIA_FRAME_TYPE_AUDIO;
 
Index: pjproject/trunk/pjmedia/src/pjmedia-codec/ilbc.c
===================================================================
--- pjproject/trunk/pjmedia/src/pjmedia-codec/ilbc.c	(revision 1982)
+++ pjproject/trunk/pjmedia/src/pjmedia-codec/ilbc.c	(revision 1983)
@@ -511,14 +511,17 @@
 {
     struct ilbc_codec *ilbc_codec = (struct ilbc_codec*)codec;
-    unsigned i;
-
-    pj_assert(ilbc_codec != NULL);
-    PJ_ASSERT_RETURN(input && output, PJ_EINVAL);
-
-    if (output_buf_len < ilbc_codec->enc_frame_size)
-	return PJMEDIA_CODEC_EFRMTOOSHORT;
-
-    if (input->size != (ilbc_codec->enc_samples_per_frame << 1))
-	return PJMEDIA_CODEC_EPCMFRMINLEN;
+    pj_int16_t *pcm_in;
+    unsigned nsamples;
+
+    pj_assert(ilbc_codec && input && output);
+
+    pcm_in = (pj_int16_t*)input->buf;
+    nsamples = input->size >> 1;
+
+    PJ_ASSERT_RETURN(nsamples % ilbc_codec->enc_samples_per_frame == 0, 
+		     PJMEDIA_CODEC_EPCMFRMINLEN);
+    PJ_ASSERT_RETURN(output_buf_len >= ilbc_codec->enc_frame_size * nsamples /
+		     ilbc_codec->enc_samples_per_frame,
+		     PJMEDIA_CODEC_EFRMTOOSHORT);
 
     /* Detect silence */
@@ -548,16 +551,23 @@
     }
 
-    /* Convert to float */
-    for (i=0; i<ilbc_codec->enc_samples_per_frame; ++i) {
-	ilbc_codec->enc_block[i] = (float) (((pj_int16_t*)input->buf)[i]);
-    }
-
     /* Encode */
-    iLBC_encode((unsigned char *)output->buf, 
-		ilbc_codec->enc_block, 
-		&ilbc_codec->enc);
+    output->size = 0;
+    while (nsamples >= ilbc_codec->enc_samples_per_frame) {
+	unsigned i;
+	
+	/* Convert to float */
+	for (i=0; i<ilbc_codec->enc_samples_per_frame; ++i) {
+	    ilbc_codec->enc_block[i] = (float) (*pcm_in++);
+	}
+
+	iLBC_encode((unsigned char *)output->buf + output->size, 
+		    ilbc_codec->enc_block, 
+		    &ilbc_codec->enc);
+
+	output->size += ilbc_codec->enc.no_of_bytes;
+	nsamples -= ilbc_codec->enc_samples_per_frame;
+    }
 
     output->type = PJMEDIA_FRAME_TYPE_AUDIO;
-    output->size = ilbc_codec->enc.no_of_bytes;
     output->timestamp = input->timestamp;
 
Index: pjproject/trunk/pjmedia/src/pjmedia-codec/l16.c
===================================================================
--- pjproject/trunk/pjmedia/src/pjmedia-codec/l16.c	(revision 1982)
+++ pjproject/trunk/pjmedia/src/pjmedia-codec/l16.c	(revision 1983)
@@ -565,4 +565,6 @@
     while (samp!=samp_end)
 	*samp_out++ = pj_htons(*samp++);
+#else
+    pjmedia_copy_samples(samp_out, samp, input->size >> 1);
 #endif
 
@@ -597,4 +599,6 @@
     while (samp!=samp_end)
 	*samp_out++ = pj_htons(*samp++);
+#else
+    pjmedia_copy_samples(samp_out, samp, input->size >> 1);
 #endif
 
Index: pjproject/trunk/pjmedia/src/pjmedia-codec/speex_codec.c
===================================================================
--- pjproject/trunk/pjmedia/src/pjmedia-codec/speex_codec.c	(revision 1982)
+++ pjproject/trunk/pjmedia/src/pjmedia-codec/speex_codec.c	(revision 1983)
@@ -161,7 +161,7 @@
 	return PJMEDIA_CODEC_EFAILED;
 
-    /* Set the quality */
-    if (p->quality != -1)
-	speex_encoder_ctl(state, SPEEX_SET_QUALITY, &p->quality);
+    /* We have to get maximum bitrate, so let's set maximum quality */
+    tmp = 10;
+    speex_encoder_ctl(state, SPEEX_SET_QUALITY, &tmp);
 
     /* Sampling rate. */
@@ -596,7 +596,4 @@
     id = spx->param_id;
 
-    /* Only supports one frame per packet */
-    PJ_ASSERT_RETURN(attr->setting.frm_per_pkt==1, PJ_EINVAL);
-
     /* 
      * Create and initialize encoder. 
@@ -688,7 +685,4 @@
     spx = (struct spx_private*) codec->codec_data;
 
-    /* Only supports one frame per packet */
-    PJ_ASSERT_RETURN(attr->setting.frm_per_pkt==1, PJ_EINVAL);
-
     /* VAD */
     tmp = (attr->setting.vad != 0);
@@ -701,4 +695,117 @@
 
     return PJ_SUCCESS;
+}
+
+#if 0
+#  define TRACE__(args)	    PJ_LOG(5,args)
+#else
+#  define TRACE__(args)
+#endif
+
+#undef THIS_FUNC
+#define THIS_FUNC "speex_get_next_frame"
+
+#define NB_SUBMODES 16
+#define NB_SUBMODE_BITS 4
+
+#define SB_SUBMODES 8
+#define SB_SUBMODE_BITS 3
+
+/* This function will iterate frames & submodes in the Speex bits.
+ * Returns 0 if a frame found, otherwise returns -1.
+ */
+int speex_get_next_frame(SpeexBits *bits)
+{
+    static const int inband_skip_table[NB_SUBMODES] =
+       {1, 1, 4, 4, 4, 4, 4, 4, 8, 8, 16, 16, 32, 32, 64, 64 };
+    static const int wb_skip_table[SB_SUBMODES] =
+       {SB_SUBMODE_BITS+1, 36, 112, 192, 352, -1, -1, -1};
+
+    unsigned submode;
+    unsigned nb_count = 0;
+
+    while (speex_bits_remaining(bits) >= 5) {
+	unsigned wb_count = 0;
+	unsigned bit_ptr = bits->bitPtr;
+	unsigned char_ptr = bits->charPtr;
+
+	/* WB frame */
+	while ((speex_bits_remaining(bits) >= 4)
+	    && speex_bits_unpack_unsigned(bits, 1))
+	{
+	    int advance;
+
+	    submode = speex_bits_unpack_unsigned(bits, 3);
+	    advance = wb_skip_table[submode];
+	    if (advance < 0) {
+		TRACE__((THIS_FUNC, "Invalid mode encountered. "
+			 "The stream is corrupted."));
+		return -1;
+	    } 
+	    TRACE__((THIS_FUNC, "WB layer skipped: %d bits", advance));
+	    advance -= (SB_SUBMODE_BITS+1);
+	    speex_bits_advance(bits, advance);
+
+	    bit_ptr = bits->bitPtr;
+	    char_ptr = bits->charPtr;
+
+	    /* Consecutive subband frames may not exceed 2 frames */
+	    if (++wb_count > 2)
+		return -1;
+	}
+
+	/* End of bits, return the frame */
+	if (speex_bits_remaining(bits) < 4) {
+	    TRACE__((THIS_FUNC, "End of stream"));
+	    return 0;
+	}
+
+	/* Stop iteration, return the frame */
+	if (nb_count > 0) {
+	    bits->bitPtr = bit_ptr;
+	    bits->charPtr = char_ptr;
+	    return 0;
+	}
+
+	/* Get control bits */
+	submode = speex_bits_unpack_unsigned(bits, 4);
+	TRACE__((THIS_FUNC, "Control bits: %d at %d", 
+		 submode, bits->charPtr*8+bits->bitPtr));
+
+	if (submode == 15) {
+	    TRACE__((THIS_FUNC, "Found submode: terminator"));
+	    return 0;
+	} else if (submode == 14) {
+	    /* in-band signal; next 4 bits contain signal id */
+	    submode = speex_bits_unpack_unsigned(bits, 4);
+	    TRACE__((THIS_FUNC, "Found submode: in-band %d bits", 
+		     inband_skip_table[submode]));
+	    speex_bits_advance(bits, inband_skip_table[submode]);
+	} else if (submode == 13) {
+	    /* user in-band; next 5 bits contain msg len */
+	    submode = speex_bits_unpack_unsigned(bits, 5);
+	    TRACE__((THIS_FUNC, "Found submode: user-band %d bytes", submode));
+	    speex_bits_advance(bits, submode * 8);
+	} else if (submode > 8) {
+	    TRACE__((THIS_FUNC, "Unknown sub-mode %d", submode));
+	    return 0;
+	} else {
+	    /* NB frame */
+	    unsigned int advance = submode;
+	    speex_mode_query(&speex_nb_mode, SPEEX_SUBMODE_BITS_PER_FRAME, &advance);
+	    if (advance < 0) {
+		TRACE__((THIS_FUNC, "Invalid mode encountered. "
+			 "The stream is corrupted."));
+		return -1;
+	    }
+	    TRACE__((THIS_FUNC, "Submode %d: %d bits", submode, advance));
+	    advance -= (NB_SUBMODE_BITS+1);
+	    speex_bits_advance(bits, advance);
+
+	    ++nb_count;
+	}
+    }
+
+    return 0;
 }
 
@@ -714,43 +821,40 @@
 				     pjmedia_frame frames[])
 {
-    struct spx_private *spx;
-    unsigned frame_size, samples_per_frame;
-    unsigned count;
-
-    spx = (struct spx_private*) codec->codec_data;
-
-    frame_size = spx_factory.speex_param[spx->param_id].framesize;
-    samples_per_frame = spx_factory.speex_param[spx->param_id].samples_per_frame;
-
-    /* Don't really know how to do this... */
-    count = 0;
-    while (pkt_size >= frame_size && count < *frame_cnt) {
-	frames[count].buf = pkt;
-	frames[count].size = frame_size;
+    struct spx_private *spx = (struct spx_private*) codec->codec_data;
+    unsigned samples_per_frame;
+    unsigned count = 0;
+    int char_ptr = 0;
+    int bit_ptr = 0;
+
+    samples_per_frame=spx_factory.speex_param[spx->param_id].samples_per_frame;
+
+    /* Copy the data into the speex bit-stream */
+    speex_bits_read_from(&spx->dec_bits, (char*)pkt, pkt_size);
+
+    while (speex_get_next_frame(&spx->dec_bits) == 0 && 
+	   spx->dec_bits.charPtr != char_ptr)
+    {
+	frames[count].buf = (char*)pkt + char_ptr;
+	/* Bit info contains start bit offset of the frame */
+	frames[count].bit_info = bit_ptr;
 	frames[count].type = PJMEDIA_FRAME_TYPE_AUDIO;
 	frames[count].timestamp.u64 = ts->u64 + count * samples_per_frame;
-
-	pkt_size -= frame_size;
+	frames[count].size = spx->dec_bits.charPtr - char_ptr;
+	if (spx->dec_bits.bitPtr)
+	    ++frames[count].size;
+
+	bit_ptr = spx->dec_bits.bitPtr;
+	char_ptr = spx->dec_bits.charPtr;
+
 	++count;
-	pkt = ((char*)pkt) + frame_size;
-    }
-
-    /* Just in case speex has silence frame which size is less than normal
-     * frame size...
-     */
-    if (pkt_size && count < *frame_cnt) {
-	frames[count].buf = pkt;
-	frames[count].size = pkt_size;
-	frames[count].type = PJMEDIA_FRAME_TYPE_AUDIO;
-	frames[count].timestamp.u64 = ts->u64 + count * samples_per_frame;
-	++count;
     }
 
     *frame_cnt = count;
-    return PJ_SUCCESS;
-}
-
-/*
- * Encode frame.
+
+    return PJ_SUCCESS;
+}
+
+/*
+ * Encode frames.
  */
 static pj_status_t spx_codec_encode( pjmedia_codec *codec, 
@@ -760,6 +864,8 @@
 {
     struct spx_private *spx;
-    unsigned sz;
-    int tx;
+    unsigned samples_per_frame;
+    int tx = 0;
+    spx_int16_t *pcm_in = (spx_int16_t*)input->buf;
+    unsigned nsamples;
 
     spx = (struct spx_private*) codec->codec_data;
@@ -773,10 +879,19 @@
     }
 
+    nsamples = input->size >> 1;
+    samples_per_frame=spx_factory.speex_param[spx->param_id].samples_per_frame;
+
+    PJ_ASSERT_RETURN(nsamples % samples_per_frame == 0, 
+		     PJMEDIA_CODEC_EPCMFRMINLEN);
+
     /* Flush all the bits in the struct so we can encode a new frame */
     speex_bits_reset(&spx->enc_bits);
 
-    /* Encode the frame */
-    tx = speex_encode_int(spx->enc, (spx_int16_t*)input->buf, 
-			  &spx->enc_bits);
+    /* Encode the frames */
+    while (nsamples >= samples_per_frame) {
+	tx += speex_encode_int(spx->enc, pcm_in, &spx->enc_bits);
+	pcm_in += samples_per_frame;
+	nsamples -= samples_per_frame;
+    }
 
     /* Check if we need not to transmit the frame (DTX) */
@@ -790,6 +905,5 @@
 
     /* Check size. */
-    sz = speex_bits_nbytes(&spx->enc_bits);
-    pj_assert(sz <= output_buf_len);
+    pj_assert(speex_bits_nbytes(&spx->enc_bits) <= (int)output_buf_len);
 
     /* Copy the bits to an array of char that can be written */
@@ -811,12 +925,15 @@
 {
     struct spx_private *spx;
+    unsigned samples_per_frame;
 
     spx = (struct spx_private*) codec->codec_data;
-
-    PJ_ASSERT_RETURN(output_buf_len >= 320, PJMEDIA_CODEC_EPCMTOOSHORT);
+    samples_per_frame=spx_factory.speex_param[spx->param_id].samples_per_frame;
+
+    PJ_ASSERT_RETURN(output_buf_len >= samples_per_frame << 1,
+		     PJMEDIA_CODEC_EPCMTOOSHORT);
 
     if (input->type != PJMEDIA_FRAME_TYPE_AUDIO) {
-	pjmedia_zero_samples((pj_int16_t*)output->buf, 160);
-	output->size = 320;
+	pjmedia_zero_samples((pj_int16_t*)output->buf, samples_per_frame);
+	output->size = samples_per_frame << 1;
 	output->timestamp.u64 = input->timestamp.u64;
 	output->type = PJMEDIA_FRAME_TYPE_AUDIO;
@@ -826,4 +943,7 @@
     /* Copy the data into the bit-stream struct */
     speex_bits_read_from(&spx->dec_bits, (char*)input->buf, input->size);
+    
+    /* Set Speex dec_bits pointer to the start bit of the frame */
+    speex_bits_advance(&spx->dec_bits, input->bit_info);
 
     /* Decode the data */
@@ -831,7 +951,6 @@
 
     output->type = PJMEDIA_FRAME_TYPE_AUDIO;
-    output->size = 320;
+    output->size = samples_per_frame << 1;
     output->timestamp.u64 = input->timestamp.u64;
-
 
     return PJ_SUCCESS;
Index: pjproject/trunk/pjmedia/src/pjmedia/jbuf.c
===================================================================
--- pjproject/trunk/pjmedia/src/pjmedia/jbuf.c	(revision 1982)
+++ pjproject/trunk/pjmedia/src/pjmedia/jbuf.c	(revision 1983)
@@ -39,4 +39,5 @@
     int		*flist_frame_type;
     pj_size_t	*flist_content_len;
+    pj_uint32_t	*flist_bit_info;
     unsigned	 flist_frame_size;
     unsigned	 flist_max_count;
@@ -109,4 +110,8 @@
 				framelist->flist_max_count);
 
+    framelist->flist_bit_info = (pj_uint32_t*)
+	pj_pool_zalloc(pool, sizeof(framelist->flist_bit_info[0]) * 
+				framelist->flist_max_count);
+
     framelist->flist_empty = 1;
 
@@ -135,5 +140,6 @@
 static pj_bool_t jb_framelist_get(jb_framelist_t *framelist,
 				  void *frame, pj_size_t *size,
-				  pjmedia_jb_frame_type *p_type) 
+				  pjmedia_jb_frame_type *p_type,
+				  pj_uint32_t *bit_info) 
 {
     if (!framelist->flist_empty) {
@@ -144,5 +150,8 @@
 	*p_type = (pjmedia_jb_frame_type) 
 		  framelist->flist_frame_type[framelist->flist_head];
-	*size   = framelist->flist_content_len[framelist->flist_head];
+	if (size)
+	    *size   = framelist->flist_content_len[framelist->flist_head];
+	if (bit_info)
+	    *bit_info = framelist->flist_bit_info[framelist->flist_head];
 
 	pj_bzero(framelist->flist_buffer + 
@@ -222,5 +231,6 @@
 				     unsigned index,
 				     const void *frame,
-				     unsigned frame_size) 
+				     unsigned frame_size,
+				     pj_uint32_t bit_info)
 {
     unsigned where;
@@ -264,4 +274,5 @@
     framelist->flist_frame_type[where] = PJMEDIA_JB_NORMAL_FRAME;
     framelist->flist_content_len[where] = frame_size;
+    framelist->flist_bit_info[where] = bit_info;
 
     return PJ_TRUE;
@@ -479,5 +490,5 @@
 				     int frame_seq)
 {
-    pjmedia_jbuf_put_frame2(jb, frame, frame_size, frame_seq, NULL);
+    pjmedia_jbuf_put_frame2(jb, frame, frame_size, 0, frame_seq, NULL);
 }
 
@@ -485,4 +496,5 @@
 				     const void *frame, 
 				     pj_size_t frame_size, 
+				     pj_uint32_t bit_info,
 				     int frame_seq,
 				     pj_bool_t *discarded)
@@ -509,6 +521,6 @@
     if (seq_diff > 0) {
 
-	while (jb_framelist_put_at(&jb->jb_framelist,
-				   frame_seq,frame,min_frame_size) == PJ_FALSE)
+	while (jb_framelist_put_at(&jb->jb_framelist, frame_seq, frame,
+				   min_frame_size, bit_info) == PJ_FALSE)
 	{
 	    jb_framelist_remove_head(&jb->jb_framelist,
@@ -526,5 +538,5 @@
 	pj_bool_t res;
 	res = jb_framelist_put_at(&jb->jb_framelist,frame_seq,frame,
-				  min_frame_size);
+				  min_frame_size, bit_info);
 	if (discarded)
 	    *discarded = !res;
@@ -539,7 +551,5 @@
 				     char *p_frame_type)
 {
-    pj_size_t size;
-
-    pjmedia_jbuf_get_frame2(jb, frame, &size, p_frame_type);
+    pjmedia_jbuf_get_frame2(jb, frame, NULL, p_frame_type, NULL);
 }
 
@@ -550,5 +560,6 @@
 				     void *frame, 
 				     pj_size_t *size,
-				     char *p_frame_type)
+				     char *p_frame_type,
+				     pj_uint32_t *bit_info)
 {
     pjmedia_jb_frame_type ftype;
@@ -582,5 +593,7 @@
 
     /* Retrieve a frame from frame list */
-    if (jb_framelist_get(&jb->jb_framelist,frame,size,&ftype) == PJ_FALSE) {
+    if (jb_framelist_get(&jb->jb_framelist,frame,size,&ftype,bit_info) ==
+	PJ_FALSE) 
+    {
 	/* Can't return frame because jitter buffer is empty! */
 	pj_bzero(frame, jb->jb_frame_size);
Index: pjproject/trunk/pjmedia/src/pjmedia/stream.c
===================================================================
--- pjproject/trunk/pjmedia/src/pjmedia/stream.c	(revision 1982)
+++ pjproject/trunk/pjmedia/src/pjmedia/stream.c	(revision 1983)
@@ -230,8 +230,9 @@
 	char frame_type;
 	pj_size_t frame_size;
+	pj_uint32_t bit_info;
 
 	/* Get frame from jitter buffer. */
 	pjmedia_jbuf_get_frame2(stream->jb, channel->out_pkt, &frame_size,
-			        &frame_type);
+			        &frame_type, &bit_info);
 	
 	if (frame_type == PJMEDIA_JB_MISSING_FRAME) {
@@ -365,4 +366,5 @@
 	    frame_in.buf = channel->out_pkt;
 	    frame_in.size = frame_size;
+	    frame_in.bit_info = bit_info;
 	    frame_in.type = PJMEDIA_FRAME_TYPE_AUDIO;  /* ignored */
 
@@ -678,58 +680,13 @@
 	       frame->buf != NULL) 
     {
-	unsigned ts, codec_samples_per_frame;
-
-	/* Repeatedly call encode if there are multiple frames to be
-	 * sent.
-	 */
-	codec_samples_per_frame = stream->codec_param.info.enc_ptime *
-				  stream->codec_param.info.clock_rate /
-				  1000;
-	if (codec_samples_per_frame == 0) {
-	    codec_samples_per_frame = stream->codec_param.info.frm_ptime *
-				      stream->codec_param.info.clock_rate /
-				      1000;
-	}
-
-	for (ts=0; ts<ts_len; ts += codec_samples_per_frame) {
-	    pjmedia_frame tmp_out_frame, tmp_in_frame;
-	    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.timestamp.u64 = frame->timestamp.u64 + ts;
-	    tmp_in_frame.buf = ((char*)frame->buf) + ts * bytes_per_sample;
-	    tmp_in_frame.size = codec_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;
-
-	    max_size = channel->out_pkt_size - sizeof(pjmedia_rtp_hdr) -
-		       frame_out.size;
-
-	    /* Encode! */
-	    status = stream->codec->op->encode( stream->codec, &tmp_in_frame, 
-						max_size, &tmp_out_frame);
-	    if (status != PJ_SUCCESS) {
-		LOGERR_((stream->port.info.name.ptr, 
-			"Codec encode() error", status));
-		return status;
-	    }
-
-	    /* 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;
-	    }
-
+	/* Encode! */
+	status = stream->codec->op->encode( stream->codec, frame, 
+					    channel->out_pkt_size - 
+					    sizeof(pjmedia_rtp_hdr),
+					    &frame_out);
+	if (status != PJ_SUCCESS) {
+	    LOGERR_((stream->port.info.name.ptr, 
+		    "Codec encode() error", status));
+	    return status;
 	}
 
@@ -1218,5 +1175,5 @@
 	    ext_seq = (unsigned)(frames[i].timestamp.u64 / ts_span);
 	    pjmedia_jbuf_put_frame2(stream->jb, frames[i].buf, frames[i].size,
-				    ext_seq, &discarded);
+				    frames[i].bit_info, ext_seq, &discarded);
 	    if (discarded)
 		pkt_discarded = PJ_TRUE;
