Index: pjproject/trunk/pjmedia/include/pjmedia-codec/amr_helper.h
===================================================================
--- pjproject/trunk/pjmedia/include/pjmedia-codec/amr_helper.h	(revision 2358)
+++ pjproject/trunk/pjmedia/include/pjmedia-codec/amr_helper.h	(revision 2359)
@@ -605,5 +605,5 @@
     pj_int8_t  mode;		/**< AMR mode.				*/
     pj_uint8_t start_bit;	/**< Frame start bit.			*/
-    pj_uint8_t good_quality:1;	/**< Flag if frame contains good data.	*/
+    pj_uint8_t good_quality:1;	/**< Flag if frame is good/degraded.	*/
 } pjmedia_codec_amr_bit_info;
 #pragma pack()
@@ -614,10 +614,12 @@
  */
 typedef struct pjmedia_codec_amr_settings {
-    pj_bool_t  amr_nb;		/**< TRUE for AMR-NB, FALSE for AMR-WB	*/
-    pj_uint8_t CMR;		/**< Change Mode Request, 
-				     in band message from encoder.	*/
+    pj_bool_t  amr_nb;		/**< TRUE for AMR-NB, FALSE for AMR-WB.	*/
+    pj_bool_t  reorder;		/**< Reorder bitstream into descending 
+				     sensitivity order or vice versa.	*/
     pj_uint8_t octet_aligned;	/**< TRUE if payload is in octet-aligned mode,
 				     FALSE if payload is in bandwidth 
 				     efficient mode.			*/
+    pj_uint8_t CMR;		/**< Change Mode Request for remote
+				     encoder.				*/
 } pjmedia_codec_amr_settings;
 
@@ -631,7 +633,7 @@
  */
 
-PJ_INLINE(int) pjmedia_codec_amr_get_mode(unsigned bitrate)
-{
-    int mode = -1;
+PJ_INLINE(pj_int8_t) pjmedia_codec_amr_get_mode(unsigned bitrate)
+{
+    pj_int8_t mode = -1;
 
     if(bitrate==4750){
@@ -676,18 +678,21 @@
 
 /**
- * Rearrange AMR bitstream from sensitivity bits order into encoder bits order.
- * This will also make the start_bit to be 0. Basically this function should be
- * called before invoking decoder.
+ * Prepare a frame before pass it to decoder. This function will do:
+ * - reorder AMR bitstream from descending sensitivity order into 
+ *   encoder bits order. This can be enabled/disabled via param 
+ *   'setting' by setting/resetting field 'reorder'.
+ * - align left the start bit (make the start_bit to be 0).
  *
  * @param amr_nb    Set PJ_TRUE for AMR-NB and PJ_FALSE for AMR-WB.
  * @param in	    Input frame.
+ * @param setting   Settings, see @pjmedia_codec_amr_settings.
  * @param out	    Output frame.
  *
  * @return	    PJ_SUCCESS on success.
  */
-PJ_INLINE(pj_status_t) pjmedia_codec_amr_reorder_sens_to_enc(
-						pj_bool_t amr_nb,
-						const pjmedia_frame *in,
-						pjmedia_frame *out)
+PJ_INLINE(pj_status_t) pjmedia_codec_amr_predecode(
+				    const pjmedia_frame *in,
+				    const pjmedia_codec_amr_settings *setting,
+				    pjmedia_frame *out)
 {
     pj_int8_t    amr_bits[477 + 7] = {0};
@@ -713,5 +718,5 @@
     *out_info = *in_info;
 
-    if (amr_nb) {
+    if (setting->amr_nb) {
 	SID_FT		= 8;
 	framelen_tbl	= pjmedia_codec_amrnb_framelen;
@@ -751,17 +756,25 @@
 
 	/* Speech */
-	const pj_int16_t *order_map;
-
 	out_info->mode = in_info->frame_type;
 	out->size = framelen_tbl[out_info->mode];
 	PJ_ASSERT_RETURN(out->size <= in->size, PJMEDIA_CODEC_EFRMINLEN);
 
-	order_map = order_maps[out_info->mode];
 	pj_bzero(out->buf, out->size);
-	for(i = 0; i < framelenbit_tbl[out_info->mode]; ++i) {
-	    if (amr_bits[i]) {
-		pj_uint16_t bitpos;
-		bitpos = order_map[i];
-		w[bitpos>>3] |= 1 << (7 - (bitpos % 8));
+
+	if (setting->reorder) {
+	    const pj_int16_t *order_map;
+
+	    order_map = order_maps[out_info->mode];
+	    for(i = 0; i < framelenbit_tbl[out_info->mode]; ++i) {
+		if (amr_bits[i]) {
+		    pj_uint16_t bitpos;
+		    bitpos = order_map[i];
+		    w[bitpos>>3] |= 1 << (7 - (bitpos % 8));
+		}
+	    }
+	} else {
+	    for(i = 0; i < framelenbit_tbl[out_info->mode]; ++i) {
+		if (amr_bits[i])
+		    w[i >> 3] |= 1 << (7 - (i % 8));
 	    }
 	}
@@ -773,5 +786,5 @@
 	pj_uint8_t FT_;
 
-	if (amr_nb)
+	if (setting->amr_nb)
 	    FT_ = (pj_uint8_t)((amr_bits[36] << 2) | (amr_bits[37] << 1) | 
 	                       amr_bits[38]);
@@ -949,17 +962,31 @@
 
 	    /* Speech */
-	    const pj_int16_t *order_map;
-
-	    /* Put bits in the packet, sensitivity descending ordered */
-	    order_map = order_maps[info->frame_type];
 	    if (w_bitptr == 0) *w = 0;
-	    for(j = 0; j < framelenbit_tbl[info->frame_type]; ++j) {
-		if (amr_bits[order_map[j]])
-		    *w |= (1 << (7-w_bitptr));
-
-		if (++w_bitptr == 8) {
-		    w_bitptr = 0;
-		    ++w;
-		    *w = 0;
+
+	    if (setting->reorder) {
+		const pj_int16_t *order_map;
+
+		/* Put bits in the packet, sensitivity descending ordered */
+		order_map = order_maps[info->frame_type];
+		for(j = 0; j < framelenbit_tbl[info->frame_type]; ++j) {
+		    if (amr_bits[order_map[j]])
+			*w |= (1 << (7-w_bitptr));
+
+		    if (++w_bitptr == 8) {
+			w_bitptr = 0;
+			++w;
+			*w = 0;
+		    }
+		}
+	    } else {
+		for(j = 0; j < framelenbit_tbl[info->frame_type]; ++j) {
+		    if (amr_bits[j])
+			*w |= (1 << (7-w_bitptr));
+
+		    if (++w_bitptr == 8) {
+			w_bitptr = 0;
+			++w;
+			*w = 0;
+		    }
 		}
 	    }
@@ -1019,5 +1046,5 @@
  * @param frames    Frames parsed.
  * @param nframes   Number of frames parsed.
- * @param CMR	    Change Mode Request message from the encoder.
+ * @param CMR	    Change Mode Request message for local encoder.
  *
  * @return	    PJ_SUCCESS on success.
Index: pjproject/trunk/pjmedia/src/pjmedia-codec/ipp_codecs.c
===================================================================
--- pjproject/trunk/pjmedia/src/pjmedia-codec/ipp_codecs.c	(revision 2358)
+++ pjproject/trunk/pjmedia/src/pjmedia-codec/ipp_codecs.c	(revision 2359)
@@ -115,4 +115,5 @@
 typedef struct ipp_private {
     int			 codec_idx;	    /**< Codec index.		    */
+    void		*codec_setting;	    /**< Specific codec setting.    */
     pj_pool_t		*pool;		    /**< Pool for each instance.    */
 
@@ -122,10 +123,12 @@
     pj_uint16_t		 frame_size;	    /**< Bitstream frame size.	    */
 
-    pj_bool_t		 plc_enabled;
-    pjmedia_plc		*plc;
-
-    pj_bool_t		 vad_enabled;
-    pjmedia_silence_det	*vad;
-    pj_timestamp	 last_tx;
+    pj_bool_t		 plc_enabled;	    /**< PLC enabled flag.	    */
+    pjmedia_plc		*plc;		    /**< PJMEDIA PLC engine, NULL if 
+						 codec has internal PLC.    */
+
+    pj_bool_t		 vad_enabled;	    /**< VAD enabled flag.	    */
+    pjmedia_silence_det	*vad;		    /**< PJMEDIA VAD engine, NULL if 
+						 codec has internal VAD.    */
+    pj_timestamp	 last_tx;	    /**< Timestamp of last transmit.*/
 } ipp_private_t;
 
@@ -420,4 +423,11 @@
 #include <pjmedia-codec/amr_helper.h>
 
+typedef struct amr_settings_t {
+    pjmedia_codec_amr_settings enc_setting;
+    pjmedia_codec_amr_settings dec_setting;
+    pj_int8_t enc_mode;
+} amr_settings_t;
+
+
 /* Rearrange AMR bitstream and convert RTP frame into USC frame:
  * - make the start_bit to be 0
@@ -432,9 +442,10 @@
     pjmedia_frame frame;
     pjmedia_codec_amr_bit_info *info;
-    pj_bool_t amr_nb;
-
-    amr_nb = (ipp_codec[codec_data->codec_idx].pt == PJMEDIA_RTP_PT_AMR);
+    pjmedia_codec_amr_settings *setting;
+
+    setting = &((amr_settings_t*)codec_data->codec_setting)->dec_setting;
+
     frame = *rtp_frame;
-    pjmedia_codec_amr_reorder_sens_to_enc(amr_nb, rtp_frame, &frame);
+    pjmedia_codec_amr_predecode(rtp_frame, setting, &frame);
     info = (pjmedia_codec_amr_bit_info*) &frame.bit_info;
 
@@ -442,5 +453,5 @@
     usc_frame->nbytes = frame.size;
     if (info->mode != -1) {
-	usc_frame->bitrate = amr_nb? 
+	usc_frame->bitrate = setting->amr_nb? 
 			     pjmedia_codec_amrnb_bitrates[info->mode]:
 			     pjmedia_codec_amrwb_bitrates[info->mode];
@@ -454,5 +465,5 @@
 	    usc_frame->frametype = 0;
 	else
-	    usc_frame->frametype = amr_nb ? 5 : 6;
+	    usc_frame->frametype = setting->amr_nb ? 5 : 6;
     } else if (frame.size == 5) {
 	/* SID */
@@ -462,5 +473,5 @@
 	    usc_frame->frametype = STI? 2 : 1;
 	} else {
-	    usc_frame->frametype = amr_nb ? 6 : 7;
+	    usc_frame->frametype = setting->amr_nb ? 6 : 7;
 	}
     } else {
@@ -476,5 +487,4 @@
     enum {MAX_FRAMES_PER_PACKET = 16};
 
-    pjmedia_codec_amr_settings setting;
     pjmedia_frame frames[MAX_FRAMES_PER_PACKET];
     unsigned nframes = 0;
@@ -482,10 +492,9 @@
     pj_uint8_t *r; /* Read cursor */
     pj_uint8_t SID_FT;
-
-    setting.amr_nb = ipp_codec[codec_data->codec_idx].pt == PJMEDIA_RTP_PT_AMR;
-    setting.CMR = 15; /* not requesting any mode */
-    setting.octet_aligned = 0;
-
-    SID_FT = (pj_uint8_t)(setting.amr_nb? 8 : 9);
+    pjmedia_codec_amr_settings *setting;
+
+    setting = &((amr_settings_t*)codec_data->codec_setting)->enc_setting;
+
+    SID_FT = (pj_uint8_t)(setting->amr_nb? 8 : 9);
 
     /* Align pkt buf right */
@@ -521,5 +530,5 @@
     /* Pack */
     *pkt_size = max_pkt_size;
-    return pjmedia_codec_amr_pack(frames, nframes, &setting, pkt, pkt_size);
+    return pjmedia_codec_amr_pack(frames, nframes, setting, pkt, pkt_size);
 }
 
@@ -530,12 +539,22 @@
 			     unsigned *frame_cnt, pjmedia_frame frames[])
 {
-    pjmedia_codec_amr_settings setting;
+    amr_settings_t* s = (amr_settings_t*)codec_data->codec_setting;
+    pjmedia_codec_amr_settings *setting;
+    pj_status_t status;
     pj_uint8_t CMR;
 
-    setting.amr_nb = ipp_codec[codec_data->codec_idx].pt == PJMEDIA_RTP_PT_AMR;
-    setting.octet_aligned = 0;
-
-    return pjmedia_codec_amr_parse(pkt, pkt_size, ts, &setting, frames, 
-				   frame_cnt, &CMR);
+    setting = &s->dec_setting;
+
+    status = pjmedia_codec_amr_parse(pkt, pkt_size, ts, setting, frames, 
+				     frame_cnt, &CMR);
+    if (status != PJ_SUCCESS)
+	return status;
+
+    /* Check Change Mode Request. */
+    if ((setting->amr_nb && CMR <= 7) || (!setting->amr_nb && CMR <= 8)) {
+	s->enc_mode = CMR;
+    }
+
+    return PJ_SUCCESS;
 }
 
@@ -1001,4 +1020,27 @@
     codec_data->plc_enabled = (attr->setting.plc != 0);
 
+#if PJMEDIA_HAS_INTEL_IPP_CODEC_AMR
+    /* Init AMR settings */
+    if (ippc->pt == PJMEDIA_RTP_PT_AMR || ippc->pt == PJMEDIA_RTP_PT_AMRWB) {
+	amr_settings_t *s;
+
+	s = PJ_POOL_ZALLOC_T(pool, amr_settings_t);
+	codec_data->codec_setting = s;
+
+	s->enc_mode = pjmedia_codec_amr_get_mode(ippc->def_bitrate);
+	if (s->enc_mode < 0)
+	    goto on_error;
+
+	s->enc_setting.amr_nb = ippc->pt == PJMEDIA_RTP_PT_AMR;
+	s->enc_setting.octet_aligned = 0;
+	s->enc_setting.reorder = PJ_TRUE;
+	s->enc_setting.CMR = 15;
+	
+	s->dec_setting.amr_nb = ippc->pt == PJMEDIA_RTP_PT_AMR;
+	s->dec_setting.octet_aligned = 0;
+	s->dec_setting.reorder = PJ_TRUE;
+    }
+#endif
+
     return PJ_SUCCESS;
 
@@ -1162,6 +1204,6 @@
 
 #if PJMEDIA_HAS_INTEL_IPP_CODEC_AMR
-	/* For AMR: put info (frametype, degraded, last frame) in the 
-	 * first byte 
+	/* For AMR: put info (frametype, degraded, last frame, mode) in the 
+	 * first two octets for payload packing.
 	 */
 	if (pt == PJMEDIA_RTP_PT_AMR || pt == PJMEDIA_RTP_PT_AMRWB) {
