Index: pjproject/trunk/aconfigure
===================================================================
--- pjproject/trunk/aconfigure	(revision 4330)
+++ pjproject/trunk/aconfigure	(revision 4331)
@@ -627,6 +627,11 @@
 silk_h_present
 ac_no_silk
+opencore_amrwb_dec_present
+opencore_amrwb_dec_h_present
+opencore_amrwb_enc_present
+opencore_amrwb_enc_h_present
 opencore_amrnb_present
 opencore_amrnb_h_present
+ac_no_opencore_amrwb
 ac_no_opencore_amrnb
 libcrypto_present
@@ -782,5 +787,7 @@
 enable_ssl
 with_opencore_amrnb
-enable_opencore_amrnb
+with_opencore_amr
+with_opencore_amrwbenc
+enable_opencore_amr
 with_silk
 enable_silk
@@ -1441,6 +1448,5 @@
   --disable-ssl           Exclude SSL support the build (default: autodetect)
 
-  --disable-opencore-amrnb
-                          Exclude OpenCORE AMR-NB support from the build
+  --disable-opencore-amr  Exclude OpenCORE AMR support from the build
                           (default: autodetect)
 
@@ -1475,5 +1481,9 @@
   --with-ssl=DIR          Specify alternate libssl prefix
   --with-opencore-amrnb=DIR
-                          Specify alternate libopencore-amrnb prefix
+                          This option is obsolete and replaced by
+                          --with-opencore-amr=DIR
+  --with-opencore-amr=DIR Specify alternate libopencore-amr prefix
+  --with-opencore-amrwbenc=DIR
+                          Specify alternate libvo-amrwbenc prefix
   --with-silk=DIR         Specify alternate SILK prefix
 
@@ -7110,36 +7120,68 @@
 # Check whether --with-opencore-amrnb was given.
 if test "${with_opencore_amrnb+set}" = set; then :
-  withval=$with_opencore_amrnb;
-else
-  with_opencore_amrnb=no
-
-fi
-
-
-if test "x$ac_cross_compile" != "x" -a "x$with_opencore_amrnb" = "xno"; then
-    enable_opencore_amrnb=no
-fi
-
-
-# Check whether --enable-opencore_amrnb was given.
-if test "${enable_opencore_amrnb+set}" = set; then :
-  enableval=$enable_opencore_amrnb;
-		if test "$enable_opencore_amrnb" = "no"; then
+  withval=$with_opencore_amrnb; as_fn_error $? "This option is obsolete and replaced by --with-opencore-amr=DIR" "$LINENO" 5
+fi
+
+
+
+# Check whether --with-opencore-amr was given.
+if test "${with_opencore_amr+set}" = set; then :
+  withval=$with_opencore_amr;
+else
+  with_opencore_amr=no
+
+fi
+
+
+if test "x$ac_cross_compile" != "x" -a "x$with_opencore_amr" = "xno"; then
+    enable_opencore_amr=no
+fi
+
+
+# Check whether --with-opencore-amrwbenc was given.
+if test "${with_opencore_amrwbenc+set}" = set; then :
+  withval=$with_opencore_amrwbenc;
+else
+  with_opencore_amrwbenc=no
+
+fi
+
+
+if test "x$ac_cross_compile" != "x" -a "x$with_opencore_amrwbenc" = "xno"; then
+    enable_opencore_amrwbenc=no
+fi
+
+
+
+
+# Check whether --enable-opencore_amr was given.
+if test "${enable_opencore_amr+set}" = set; then :
+  enableval=$enable_opencore_amr;
+		if test "$enable_opencore_amr" = "no"; then
 		 ac_no_opencore_amrnb=1
+		 ac_no_opencore_amrwb=1
 		 $as_echo "#define PJMEDIA_HAS_OPENCORE_AMRNB_CODEC 0" >>confdefs.h
 
-		 { $as_echo "$as_me:${as_lineno-$LINENO}: result: Checking if OpenCORE AMR-NB support is disabled... yes" >&5
-$as_echo "Checking if OpenCORE AMR-NB support is disabled... yes" >&6; }
+		 $as_echo "#define PJMEDIA_HAS_OPENCORE_AMRWB_CODEC 0" >>confdefs.h
+
+		 { $as_echo "$as_me:${as_lineno-$LINENO}: result: Checking if OpenCORE AMR support is disabled... yes" >&5
+$as_echo "Checking if OpenCORE AMR support is disabled... yes" >&6; }
 	        fi
 
 else
 
-		{ $as_echo "$as_me:${as_lineno-$LINENO}: result: checking for OpenCORE AMR-NB installations.." >&5
-$as_echo "checking for OpenCORE AMR-NB installations.." >&6; }
-                if test "x$with_opencore_amrnb" != "xno" -a "x$with_opencore_amrnb" != "x"; then
-                    CFLAGS="$CFLAGS -I$with_opencore_amrnb/include"
-                    LDFLAGS="$LDFLAGS -L$with_opencore_amrnb/lib"
-                    { $as_echo "$as_me:${as_lineno-$LINENO}: result: Using OpenCORE AMR-NB prefix... $with_opencore_amrnb" >&5
-$as_echo "Using OpenCORE AMR-NB prefix... $with_opencore_amrnb" >&6; }
+		{ $as_echo "$as_me:${as_lineno-$LINENO}: result: checking for OpenCORE AMR installations.." >&5
+$as_echo "checking for OpenCORE AMR installations.." >&6; }
+                if test "x$with_opencore_amr" != "xno" -a "x$with_opencore_amr" != "x"; then
+                    CFLAGS="$CFLAGS -I$with_opencore_amr/include"
+                    LDFLAGS="$LDFLAGS -L$with_opencore_amr/lib"
+                    { $as_echo "$as_me:${as_lineno-$LINENO}: result: Using OpenCORE AMR prefix... $with_opencore_amr" >&5
+$as_echo "Using OpenCORE AMR prefix... $with_opencore_amr" >&6; }
+                fi
+                if test "x$with_opencore_amrwbenc" != "xno" -a "x$with_opencore_amrwbenc" != "x"; then
+                    CFLAGS="$CFLAGS -I$with_opencore_amrwbenc/include"
+                    LDFLAGS="$LDFLAGS -L$with_opencore_amrwbenc/lib"
+                    { $as_echo "$as_me:${as_lineno-$LINENO}: result: Using OpenCORE AMRWB-enc prefix... $with_opencore_amrwbenc" >&5
+$as_echo "Using OpenCORE AMRWB-enc prefix... $with_opencore_amrwbenc" >&6; }
                 fi
 
@@ -7201,4 +7243,111 @@
 
 		fi
+
+
+
+
+		ac_fn_c_check_header_mongrel "$LINENO" "vo-amrwbenc/enc_if.h" "ac_cv_header_vo_amrwbenc_enc_if_h" "$ac_includes_default"
+if test "x$ac_cv_header_vo_amrwbenc_enc_if_h" = xyes; then :
+  opencore_amrwb_enc_h_present=1
+fi
+
+
+		ac_fn_c_check_header_mongrel "$LINENO" "opencore-amrwb/dec_if.h" "ac_cv_header_opencore_amrwb_dec_if_h" "$ac_includes_default"
+if test "x$ac_cv_header_opencore_amrwb_dec_if_h" = xyes; then :
+  opencore_amrwb_dec_h_present=1
+fi
+
+
+		{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for D_IF_init in -lopencore-amrwb" >&5
+$as_echo_n "checking for D_IF_init in -lopencore-amrwb... " >&6; }
+if ${ac_cv_lib_opencore_amrwb_D_IF_init+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  ac_check_lib_save_LIBS=$LIBS
+LIBS="-lopencore-amrwb  $LIBS"
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+/* Override any GCC internal prototype to avoid an error.
+   Use char because int might match the return type of a GCC
+   builtin and then its argument prototype would still apply.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+char D_IF_init ();
+int
+main ()
+{
+return D_IF_init ();
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+  ac_cv_lib_opencore_amrwb_D_IF_init=yes
+else
+  ac_cv_lib_opencore_amrwb_D_IF_init=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_opencore_amrwb_D_IF_init" >&5
+$as_echo "$ac_cv_lib_opencore_amrwb_D_IF_init" >&6; }
+if test "x$ac_cv_lib_opencore_amrwb_D_IF_init" = xyes; then :
+  opencore_amrwb_dec_present=1 && LIBS="$LIBS -lopencore-amrwb"
+fi
+
+		{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for E_IF_init in -lvo-amrwbenc" >&5
+$as_echo_n "checking for E_IF_init in -lvo-amrwbenc... " >&6; }
+if ${ac_cv_lib_vo_amrwbenc_E_IF_init+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  ac_check_lib_save_LIBS=$LIBS
+LIBS="-lvo-amrwbenc  $LIBS"
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+/* Override any GCC internal prototype to avoid an error.
+   Use char because int might match the return type of a GCC
+   builtin and then its argument prototype would still apply.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+char E_IF_init ();
+int
+main ()
+{
+return E_IF_init ();
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+  ac_cv_lib_vo_amrwbenc_E_IF_init=yes
+else
+  ac_cv_lib_vo_amrwbenc_E_IF_init=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_vo_amrwbenc_E_IF_init" >&5
+$as_echo "$ac_cv_lib_vo_amrwbenc_E_IF_init" >&6; }
+if test "x$ac_cv_lib_vo_amrwbenc_E_IF_init" = xyes; then :
+  opencore_amrwb_enc_present=1 && LIBS="$LIBS -lvo-amrwbenc"
+fi
+
+		if test "x$opencore_amrwb_enc_h_present" = "x1" -a "x$opencore_amrwb_dec_h_present" = "x1" -a "x$opencore_amrwb_enc_present" = "x1" -a "x$opencore_amrwb_dec_present" = "x1"; then
+	        	{ $as_echo "$as_me:${as_lineno-$LINENO}: result: OpenCORE AMR-WB library found, AMR-WB support enabled" >&5
+$as_echo "OpenCORE AMR-WB library found, AMR-WB support enabled" >&6; }
+	        	$as_echo "#define PJMEDIA_HAS_OPENCORE_AMRWB_CODEC 1" >>confdefs.h
+
+		else
+			ac_no_opencore_amrwb=1
+			$as_echo "#define PJMEDIA_HAS_OPENCORE_AMRWB_CODEC 0" >>confdefs.h
+
+		fi
+
 
 fi
Index: pjproject/trunk/aconfigure.ac
===================================================================
--- pjproject/trunk/aconfigure.ac	(revision 4330)
+++ pjproject/trunk/aconfigure.ac	(revision 4331)
@@ -1321,37 +1321,67 @@
 	      ])
 
-dnl # opencore-amrnb alt prefix
+dnl # Obsolete option --with-opencore-amrnb
 AC_ARG_WITH(opencore-amrnb,
     AC_HELP_STRING([--with-opencore-amrnb=DIR],
-		   [Specify alternate libopencore-amrnb prefix]),
+		   [This option is obsolete and replaced by --with-opencore-amr=DIR]),
+    [AC_MSG_ERROR(This option is obsolete and replaced by --with-opencore-amr=DIR)],
+    []
+    )
+
+dnl # opencore-amr alt prefix
+AC_ARG_WITH(opencore-amr,
+    AC_HELP_STRING([--with-opencore-amr=DIR],
+		   [Specify alternate libopencore-amr prefix]),
     [],
-    [with_opencore_amrnb=no]
+    [with_opencore_amr=no]
     )
 
-dnl # Do not use default opencore-amrnb installation if we are cross-compiling
-if test "x$ac_cross_compile" != "x" -a "x$with_opencore_amrnb" = "xno"; then
-    enable_opencore_amrnb=no
+dnl # Do not use default opencore-amr installation if we are cross-compiling
+if test "x$ac_cross_compile" != "x" -a "x$with_opencore_amr" = "xno"; then
+    enable_opencore_amr=no
 fi
 
-dnl # Include opencore-amrnb support
+dnl # vo-amrwbenc alt prefix
+AC_ARG_WITH(opencore-amrwbenc,
+    AC_HELP_STRING([--with-opencore-amrwbenc=DIR],
+		   [Specify alternate libvo-amrwbenc prefix]),
+    [],
+    [with_opencore_amrwbenc=no]
+    )
+
+dnl # Do not use default vo-amrwbenc installation if we are cross-compiling
+if test "x$ac_cross_compile" != "x" -a "x$with_opencore_amrwbenc" = "xno"; then
+    enable_opencore_amrwbenc=no
+fi
+
+
+dnl # Include opencore-amr support
 AC_SUBST(ac_no_opencore_amrnb)
-AC_ARG_ENABLE(opencore_amrnb,
-	      AC_HELP_STRING([--disable-opencore-amrnb],
-			     [Exclude OpenCORE AMR-NB support from the build (default: autodetect)])
+AC_SUBST(ac_no_opencore_amrwb)
+AC_ARG_ENABLE(opencore_amr,
+	      AC_HELP_STRING([--disable-opencore-amr],
+			     [Exclude OpenCORE AMR support from the build (default: autodetect)])
 	      ,
 	      [
-		if test "$enable_opencore_amrnb" = "no"; then
+		if test "$enable_opencore_amr" = "no"; then
 		 [ac_no_opencore_amrnb=1]
+		 [ac_no_opencore_amrwb=1]
 		 AC_DEFINE(PJMEDIA_HAS_OPENCORE_AMRNB_CODEC,0)
-		 AC_MSG_RESULT([Checking if OpenCORE AMR-NB support is disabled... yes])
+		 AC_DEFINE(PJMEDIA_HAS_OPENCORE_AMRWB_CODEC,0)
+		 AC_MSG_RESULT([Checking if OpenCORE AMR support is disabled... yes])
 	        fi
 	      ],
 	      [
-		AC_MSG_RESULT([checking for OpenCORE AMR-NB installations..])
-                if test "x$with_opencore_amrnb" != "xno" -a "x$with_opencore_amrnb" != "x"; then
-                    CFLAGS="$CFLAGS -I$with_opencore_amrnb/include"
-                    LDFLAGS="$LDFLAGS -L$with_opencore_amrnb/lib"
-                    AC_MSG_RESULT([Using OpenCORE AMR-NB prefix... $with_opencore_amrnb])
-                fi                
+		AC_MSG_RESULT([checking for OpenCORE AMR installations..])
+                if test "x$with_opencore_amr" != "xno" -a "x$with_opencore_amr" != "x"; then
+                    CFLAGS="$CFLAGS -I$with_opencore_amr/include"
+                    LDFLAGS="$LDFLAGS -L$with_opencore_amr/lib"
+                    AC_MSG_RESULT([Using OpenCORE AMR prefix... $with_opencore_amr])
+                fi
+                if test "x$with_opencore_amrwbenc" != "xno" -a "x$with_opencore_amrwbenc" != "x"; then
+                    CFLAGS="$CFLAGS -I$with_opencore_amrwbenc/include"
+                    LDFLAGS="$LDFLAGS -L$with_opencore_amrwbenc/lib"
+                    AC_MSG_RESULT([Using OpenCORE AMRWB-enc prefix... $with_opencore_amrwbenc])
+                fi
 		AC_SUBST(opencore_amrnb_h_present)
 		AC_SUBST(opencore_amrnb_present)
@@ -1365,4 +1395,20 @@
 			AC_DEFINE(PJMEDIA_HAS_OPENCORE_AMRNB_CODEC,0)
 		fi
+		AC_SUBST(opencore_amrwb_enc_h_present)
+		AC_SUBST(opencore_amrwb_enc_present)
+		AC_SUBST(opencore_amrwb_dec_h_present)
+		AC_SUBST(opencore_amrwb_dec_present)
+		AC_CHECK_HEADER(vo-amrwbenc/enc_if.h,[opencore_amrwb_enc_h_present=1])
+		AC_CHECK_HEADER(opencore-amrwb/dec_if.h,[opencore_amrwb_dec_h_present=1])
+		AC_CHECK_LIB(opencore-amrwb,D_IF_init,[opencore_amrwb_dec_present=1 && LIBS="$LIBS -lopencore-amrwb"])
+		AC_CHECK_LIB(vo-amrwbenc,E_IF_init,[opencore_amrwb_enc_present=1 && LIBS="$LIBS -lvo-amrwbenc"])
+		if test "x$opencore_amrwb_enc_h_present" = "x1" -a "x$opencore_amrwb_dec_h_present" = "x1" -a "x$opencore_amrwb_enc_present" = "x1" -a "x$opencore_amrwb_dec_present" = "x1"; then
+	        	AC_MSG_RESULT([OpenCORE AMR-WB library found, AMR-WB support enabled])
+	        	AC_DEFINE(PJMEDIA_HAS_OPENCORE_AMRWB_CODEC,1)
+		else
+			[ac_no_opencore_amrwb=1]
+			AC_DEFINE(PJMEDIA_HAS_OPENCORE_AMRWB_CODEC,0)
+		fi
+
 	      ])
 
Index: pjproject/trunk/pjmedia/build/Makefile
===================================================================
--- pjproject/trunk/pjmedia/build/Makefile	(revision 4330)
+++ pjproject/trunk/pjmedia/build/Makefile	(revision 4331)
@@ -114,5 +114,5 @@
 			h263_packetizer.o h264_packetizer.o \
 			$(OS_OBJS) $(M_OBJS) $(CC_OBJS) $(HOST_OBJS) \
-			ipp_codecs.o opencore_amrnb.o silk.o $(CODEC_OBJS) \
+			ipp_codecs.o opencore_amr.o silk.o $(CODEC_OBJS) \
                         g7221_sdp_match.o amr_sdp_match.o
 export PJMEDIA_CODEC_CFLAGS += $(_CFLAGS) $(GSM_CFLAGS) $(SPEEX_CFLAGS) \
Index: pjproject/trunk/pjmedia/build/os-auto.mak.in
===================================================================
--- pjproject/trunk/pjmedia/build/os-auto.mak.in	(revision 4330)
+++ pjproject/trunk/pjmedia/build/os-auto.mak.in	(revision 4331)
@@ -59,4 +59,5 @@
 AC_NO_G7221_CODEC=@ac_no_g7221_codec@
 AC_NO_OPENCORE_AMRNB=@ac_no_opencore_amrnb@
+AC_NO_OPENCORE_AMRWB=@ac_no_opencore_amrwb@
 
 export CODEC_OBJS=
@@ -114,5 +115,13 @@
 export CFLAGS += -DPJMEDIA_HAS_OPENCORE_AMRNB_CODEC=0
 else
-export CODEC_OBJS += opencore_amrnb.o
+export CODEC_OBJS += opencore_amr.o
+endif
+
+ifeq ($(AC_NO_OPENCORE_AMRWB),1)
+export CFLAGS += -DPJMEDIA_HAS_OPENCORE_AMRWB_CODEC=0
+else
+ifeq ($(AC_NO_OPENCORE_AMRNB),1)
+export CODEC_OBJS += opencore_amr.o
+endif
 endif
 
Index: pjproject/trunk/pjmedia/include/pjmedia-codec.h
===================================================================
--- pjproject/trunk/pjmedia/include/pjmedia-codec.h	(revision 4330)
+++ pjproject/trunk/pjmedia/include/pjmedia-codec.h	(revision 4331)
@@ -35,5 +35,5 @@
 #include <pjmedia-codec/g7221.h>
 #include <pjmedia-codec/ipp_codecs.h>
-#include <pjmedia-codec/opencore_amrnb.h>
+#include <pjmedia-codec/opencore_amr.h>
 #include <pjmedia-codec/passthrough.h>
 #include <pjmedia-codec/silk.h>
Index: pjproject/trunk/pjmedia/include/pjmedia-codec/config.h
===================================================================
--- pjproject/trunk/pjmedia/include/pjmedia-codec/config.h	(revision 4330)
+++ pjproject/trunk/pjmedia/include/pjmedia-codec/config.h	(revision 4331)
@@ -324,6 +324,16 @@
 
 /**
+ * Enable OpenCORE AMR-WB codec.
+ * See https://trac.pjsip.org/repos/ticket/1608 for some info.
+ *
+ * Default: 0
+ */
+#ifndef PJMEDIA_HAS_OPENCORE_AMRWB_CODEC
+#   define PJMEDIA_HAS_OPENCORE_AMRWB_CODEC	0
+#endif
+
+/**
  * Link with libopencore-amrXX via pragma comment on Visual Studio.
- * This option only makes sense if PJMEDIA_HAS_OPENCORE_AMRNB_CODEC
+ * This option only makes sense if PJMEDIA_HAS_OPENCORE_AMRNB/WB_CODEC
  * is enabled.
  *
@@ -336,5 +346,5 @@
 /**
  * Link with libopencore-amrXX.a that has been produced with gcc.
- * This option only makes sense if PJMEDIA_HAS_OPENCORE_AMRNB_CODEC
+ * This option only makes sense if PJMEDIA_HAS_OPENCORE_AMRNB/WB_CODEC
  * and PJMEDIA_AUTO_LINK_OPENCORE_AMR_LIBS are enabled.
  *
Index: pjproject/trunk/pjmedia/include/pjmedia-codec/config_auto.h.in
===================================================================
--- pjproject/trunk/pjmedia/include/pjmedia-codec/config_auto.h.in	(revision 4330)
+++ pjproject/trunk/pjmedia/include/pjmedia-codec/config_auto.h.in	(revision 4331)
@@ -75,4 +75,9 @@
 #endif
 
+/* OpenCORE AMR-WB codec */
+#ifndef PJMEDIA_HAS_OPENCORE_AMRWB_CODEC
+#undef PJMEDIA_HAS_OPENCORE_AMRWB_CODEC
+#endif
+
 /* SILK codec */
 #ifndef PJMEDIA_HAS_SILK_CODEC
Index: pjproject/trunk/pjmedia/include/pjmedia-codec/opencore_amr.h
===================================================================
--- pjproject/trunk/pjmedia/include/pjmedia-codec/opencore_amr.h	(revision 4331)
+++ pjproject/trunk/pjmedia/include/pjmedia-codec/opencore_amr.h	(revision 4331)
@@ -0,0 +1,119 @@
+/* $Id$ */
+/*
+ * Copyright (C) 2011-2013 Teluu Inc. (http://www.teluu.com)
+ * Copyright (C) 2011 Dan Arrhenius <dan@keystream.se>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+#ifndef __PJMEDIA_CODEC_OPENCORE_AMR_H__
+#define __PJMEDIA_CODEC_OPENCORE_AMR_H__
+
+#include <pjmedia-codec/types.h>
+
+/**
+ * @defgroup PJMED_OC_AMR OpenCORE AMR Codec
+ * @ingroup PJMEDIA_CODEC_CODECS
+ * @brief AMRCodec wrapper for OpenCORE AMR codec
+ * @{
+ */
+
+PJ_BEGIN_DECL
+
+/**
+ * Settings. Use #pjmedia_codec_opencore_amrnb/wb_set_config() to
+ * activate.
+ */
+typedef struct pjmedia_codec_amr_config
+{
+    /**
+     * Control whether to use octent align.
+     */
+    pj_bool_t octet_align;
+
+    /**
+     * Set the bitrate.
+     */
+    unsigned bitrate;
+
+} pjmedia_codec_amr_config;
+
+typedef pjmedia_codec_amr_config pjmedia_codec_amrnb_config;
+typedef pjmedia_codec_amr_config pjmedia_codec_amrwb_config;
+
+/**
+ * Initialize and register AMR-NB codec factory to pjmedia endpoint.
+ *
+ * @param endpt	The pjmedia endpoint.
+ *
+ * @return	PJ_SUCCESS on success.
+ */
+PJ_DECL(pj_status_t) pjmedia_codec_opencore_amrnb_init(pjmedia_endpt* endpt);
+
+/**
+ * Unregister AMR-NB codec factory from pjmedia endpoint and deinitialize
+ * the OpenCORE codec library.
+ *
+ * @return	PJ_SUCCESS on success.
+ */
+PJ_DECL(pj_status_t) pjmedia_codec_opencore_amrnb_deinit(void);
+
+
+/**
+ * Set AMR-NB parameters.
+ *
+ * @param cfg	The settings;
+ *
+ * @return	PJ_SUCCESS on success.
+ */
+PJ_DECL(pj_status_t) pjmedia_codec_opencore_amrnb_set_config(
+				const pjmedia_codec_amrnb_config* cfg);
+
+/**
+ * Initialize and register AMR-WB codec factory to pjmedia endpoint.
+ *
+ * @param endpt	The pjmedia endpoint.
+ *
+ * @return	PJ_SUCCESS on success.
+ */
+PJ_DECL(pj_status_t) pjmedia_codec_opencore_amrwb_init(pjmedia_endpt* endpt);
+
+/**
+ * Unregister AMR-WB codec factory from pjmedia endpoint and deinitialize
+ * the OpenCORE codec library.
+ *
+ * @return	PJ_SUCCESS on success.
+ */
+PJ_DECL(pj_status_t) pjmedia_codec_opencore_amrwb_deinit(void);
+
+
+/**
+ * Set AMR-WB parameters.
+ *
+ * @param cfg	The settings;
+ *
+ * @return	PJ_SUCCESS on success.
+ */
+PJ_DECL(pj_status_t) pjmedia_codec_opencore_amrwb_set_config(
+                                        const pjmedia_codec_amrwb_config* cfg);
+
+PJ_END_DECL
+
+
+/**
+ * @}
+ */
+
+#endif	/* __PJMEDIA_CODEC_OPENCORE_AMRNB_H__ */
+
Index: pjproject/trunk/pjmedia/include/pjmedia-codec/opencore_amrnb.h
===================================================================
--- pjproject/trunk/pjmedia/include/pjmedia-codec/opencore_amrnb.h	(revision 4330)
+++ 	(revision )
@@ -1,89 +1,0 @@
-/* $Id$ */
-/*
- * Copyright (C) 2011 Teluu Inc. (http://www.teluu.com)
- * Copyright (C) 2011 Dan Arrhenius <dan@keystream.se>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- */
-#ifndef __PJMEDIA_CODEC_OPENCORE_AMRNB_H__
-#define __PJMEDIA_CODEC_OPENCORE_AMRNB_H__
-
-#include <pjmedia-codec/types.h>
-
-/**
- * @defgroup PJMED_OC_AMRNB OpenCORE AMR-NB Codec
- * @ingroup PJMEDIA_CODEC_CODECS
- * @brief AMRCodec wrapper for OpenCORE AMR-NB codec
- * @{
- */
-
-PJ_BEGIN_DECL
-
-/**
- * Settings. Use #pjmedia_codec_opencore_amrnb_set_config() to
- * activate.
- */
-typedef struct pjmedia_codec_amrnb_config
-{
-    /**
-     * Control whether to use octent align.
-     */
-    pj_bool_t octet_align;
-
-    /**
-     * Set the bitrate.
-     */
-    unsigned bitrate;
-
-} pjmedia_codec_amrnb_config;
-
-
-/**
- * Initialize and register AMR-NB codec factory to pjmedia endpoint.
- *
- * @param endpt	The pjmedia endpoint.
- *
- * @return	PJ_SUCCESS on success.
- */
-PJ_DECL(pj_status_t) pjmedia_codec_opencore_amrnb_init(pjmedia_endpt* endpt);
-
-/**
- * Unregister AMR-NB codec factory from pjmedia endpoint and deinitialize
- * the OpenCORE codec library.
- *
- * @return	PJ_SUCCESS on success.
- */
-PJ_DECL(pj_status_t) pjmedia_codec_opencore_amrnb_deinit(void);
-
-
-/**
- * Set AMR-NB parameters.
- *
- * @param cfg	The settings;
- *
- * @return	PJ_SUCCESS on success.
- */
-PJ_DECL(pj_status_t) pjmedia_codec_opencore_amrnb_set_config(
-				const pjmedia_codec_amrnb_config* cfg);
-
-PJ_END_DECL
-
-
-/**
- * @}
- */
-
-#endif	/* __PJMEDIA_CODEC_OPENCORE_AMRNB_H__ */
-
Index: pjproject/trunk/pjmedia/src/pjmedia-codec/audio_codecs.c
===================================================================
--- pjproject/trunk/pjmedia/src/pjmedia-codec/audio_codecs.c	(revision 4330)
+++ pjproject/trunk/pjmedia/src/pjmedia-codec/audio_codecs.c	(revision 4331)
@@ -114,4 +114,11 @@
 	return status;
 #endif
+    
+#if PJMEDIA_HAS_OPENCORE_AMRWB_CODEC
+    /* Register OpenCORE AMR-WB */
+    status = pjmedia_codec_opencore_amrwb_init(endpt);
+    if (status != PJ_SUCCESS)
+	return status;
+#endif
 
 #if PJMEDIA_HAS_SILK_CODEC
Index: pjproject/trunk/pjmedia/src/pjmedia-codec/opencore_amr.c
===================================================================
--- pjproject/trunk/pjmedia/src/pjmedia-codec/opencore_amr.c	(revision 4331)
+++ pjproject/trunk/pjmedia/src/pjmedia-codec/opencore_amr.c	(revision 4331)
@@ -0,0 +1,1023 @@
+/* $Id$ */
+/* 
+ * Copyright (C) 2011-2013 Teluu Inc. (http://www.teluu.com)
+ * Copyright (C) 2011 Dan Arrhenius <dan@keystream.se>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA 
+ */
+
+/* 
+ * AMR codec implementation with OpenCORE AMR library
+ */
+#include <pjmedia-codec/g722.h>
+#include <pjmedia-codec/amr_sdp_match.h>
+#include <pjmedia/codec.h>
+#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/log.h>
+#include <pj/pool.h>
+#include <pj/string.h>
+#include <pj/os.h>
+#include <pj/math.h>
+
+#if defined(PJMEDIA_HAS_OPENCORE_AMRNB_CODEC) && \
+    (PJMEDIA_HAS_OPENCORE_AMRNB_CODEC != 0)
+#define USE_AMRNB
+#endif
+
+#if defined(PJMEDIA_HAS_OPENCORE_AMRWB_CODEC) && \
+    (PJMEDIA_HAS_OPENCORE_AMRWB_CODEC != 0)
+#define USE_AMRWB
+#endif
+
+#if defined(USE_AMRNB) || defined(USE_AMRWB)
+
+#ifdef USE_AMRNB
+#include <opencore-amrnb/interf_enc.h>
+#include <opencore-amrnb/interf_dec.h>
+#endif
+
+#ifdef USE_AMRWB
+#include <vo-amrwbenc/enc_if.h>
+#include <opencore-amrwb/dec_if.h>
+#endif
+
+#include <pjmedia-codec/amr_helper.h>
+#include <pjmedia-codec/opencore_amr.h>
+
+#define THIS_FILE "opencore_amr.c"
+
+/* Tracing */
+#define PJ_TRACE    0
+
+#if PJ_TRACE
+#   define TRACE_(expr)	PJ_LOG(4,expr)
+#else
+#   define TRACE_(expr)
+#endif
+
+/* Use PJMEDIA PLC */
+#define USE_PJMEDIA_PLC	    1
+
+#define FRAME_LENGTH_MS     20
+
+
+/* Prototypes for AMR factory */
+static pj_status_t amr_test_alloc(pjmedia_codec_factory *factory, 
+				   const pjmedia_codec_info *id );
+static pj_status_t amr_default_attr(pjmedia_codec_factory *factory, 
+				     const pjmedia_codec_info *id, 
+				     pjmedia_codec_param *attr );
+static pj_status_t amr_enum_codecs(pjmedia_codec_factory *factory, 
+				    unsigned *count, 
+				    pjmedia_codec_info codecs[]);
+static pj_status_t amr_alloc_codec(pjmedia_codec_factory *factory, 
+				    const pjmedia_codec_info *id, 
+				    pjmedia_codec **p_codec);
+static pj_status_t amr_dealloc_codec(pjmedia_codec_factory *factory, 
+				      pjmedia_codec *codec );
+
+/* Prototypes for AMR implementation. */
+static pj_status_t  amr_codec_init(pjmedia_codec *codec, 
+				    pj_pool_t *pool );
+static pj_status_t  amr_codec_open(pjmedia_codec *codec, 
+				    pjmedia_codec_param *attr );
+static pj_status_t  amr_codec_close(pjmedia_codec *codec );
+static pj_status_t  amr_codec_modify(pjmedia_codec *codec, 
+				      const pjmedia_codec_param *attr );
+static pj_status_t  amr_codec_parse(pjmedia_codec *codec,
+				     void *pkt,
+				     pj_size_t pkt_size,
+				     const pj_timestamp *ts,
+				     unsigned *frame_cnt,
+				     pjmedia_frame frames[]);
+static pj_status_t  amr_codec_encode(pjmedia_codec *codec, 
+				      const struct pjmedia_frame *input,
+				      unsigned output_buf_len, 
+				      struct pjmedia_frame *output);
+static pj_status_t  amr_codec_decode(pjmedia_codec *codec, 
+				      const struct pjmedia_frame *input,
+				      unsigned output_buf_len, 
+				      struct pjmedia_frame *output);
+static pj_status_t  amr_codec_recover(pjmedia_codec *codec,
+				      unsigned output_buf_len,
+				      struct pjmedia_frame *output);
+
+
+
+/* Definition for AMR codec operations. */
+static pjmedia_codec_op amr_op = 
+{
+    &amr_codec_init,
+    &amr_codec_open,
+    &amr_codec_close,
+    &amr_codec_modify,
+    &amr_codec_parse,
+    &amr_codec_encode,
+    &amr_codec_decode,
+    &amr_codec_recover
+};
+
+/* Definition for AMR codec factory operations. */
+static pjmedia_codec_factory_op amr_factory_op =
+{
+    &amr_test_alloc,
+    &amr_default_attr,
+    &amr_enum_codecs,
+    &amr_alloc_codec,
+    &amr_dealloc_codec,
+    &pjmedia_codec_opencore_amrnb_deinit
+};
+
+
+/* AMR factory */
+static struct amr_codec_factory
+{
+    pjmedia_codec_factory    base;
+    pjmedia_endpt	    *endpt;
+    pj_pool_t		    *pool;
+    pj_bool_t                init[2];
+} amr_codec_factory;
+
+
+/* AMR codec private data. */
+struct amr_data
+{
+    pj_pool_t		*pool;
+    unsigned             clock_rate;
+    void		*encoder;
+    void		*decoder;
+    pj_bool_t		 plc_enabled;
+    pj_bool_t		 vad_enabled;
+    int			 enc_mode;
+    pjmedia_codec_amr_pack_setting enc_setting;
+    pjmedia_codec_amr_pack_setting dec_setting;
+#if USE_PJMEDIA_PLC
+    pjmedia_plc		*plc;
+#endif
+    pj_timestamp	 last_tx;
+};
+
+/* Index for AMR tables. */
+enum
+{
+    IDX_AMR_NB,	/* Index for narrowband.    */
+    IDX_AMR_WB	/* Index for wideband.      */
+};
+
+static pjmedia_codec_amr_config def_config[2] =
+{{ /* AMR-NB */
+    PJ_FALSE,	    /* octet align	*/
+    5900	    /* bitrate		*/
+ },
+ { /* AMR-WB */
+    PJ_FALSE,	    /* octet align	*/
+    12650	    /* bitrate		*/
+ }};
+
+static const pj_uint16_t* amr_bitrates[2] =
+    {pjmedia_codec_amrnb_bitrates, pjmedia_codec_amrwb_bitrates};
+
+
+/*
+ * Initialize and register AMR codec factory to pjmedia endpoint.
+ */
+static pj_status_t amr_init( pjmedia_endpt *endpt )
+{
+    pjmedia_codec_mgr *codec_mgr;
+    pj_str_t codec_name;
+    pj_status_t status;
+
+    if (amr_codec_factory.pool != NULL)
+	return PJ_SUCCESS;
+
+    /* Create AMR codec factory. */
+    amr_codec_factory.base.op = &amr_factory_op;
+    amr_codec_factory.base.factory_data = NULL;
+    amr_codec_factory.endpt = endpt;
+
+    amr_codec_factory.pool = pjmedia_endpt_create_pool(endpt, "amr", 1000, 
+						       1000);
+    if (!amr_codec_factory.pool)
+	return PJ_ENOMEM;
+
+    /* Get the codec manager. */
+    codec_mgr = pjmedia_endpt_get_codec_mgr(endpt);
+    if (!codec_mgr) {
+	status = PJ_EINVALIDOP;
+	goto on_error;
+    }
+
+    /* Register format match callback. */
+    pj_cstr(&codec_name, "AMR");
+    status = pjmedia_sdp_neg_register_fmt_match_cb(
+					&codec_name,
+					&pjmedia_codec_amr_match_sdp);
+    if (status != PJ_SUCCESS)
+	goto on_error;
+
+    /* Register codec factory to endpoint. */
+    status = pjmedia_codec_mgr_register_factory(codec_mgr, 
+						&amr_codec_factory.base);
+    if (status != PJ_SUCCESS)
+	goto on_error;
+
+    /* Done. */
+    return PJ_SUCCESS;
+
+on_error:
+    pj_pool_release(amr_codec_factory.pool);
+    amr_codec_factory.pool = NULL;
+    return status;
+}
+
+PJ_DEF(pj_status_t) pjmedia_codec_opencore_amrnb_init( pjmedia_endpt *endpt )
+{
+    amr_codec_factory.init[IDX_AMR_NB] = PJ_TRUE;
+    
+    return amr_init(endpt);
+}
+
+PJ_DEF(pj_status_t) pjmedia_codec_opencore_amrwb_init( pjmedia_endpt *endpt )
+{
+    amr_codec_factory.init[IDX_AMR_WB] = PJ_TRUE;
+    
+    return amr_init(endpt);    
+}
+
+
+/*
+ * Unregister AMR codec factory from pjmedia endpoint and deinitialize
+ * the AMR codec library.
+ */
+static pj_status_t amr_deinit(void)
+{
+    pjmedia_codec_mgr *codec_mgr;
+    pj_status_t status;
+
+    if (amr_codec_factory.init[IDX_AMR_NB] ||
+        amr_codec_factory.init[IDX_AMR_WB])
+    {
+        return PJ_SUCCESS;
+    }
+    
+    if (amr_codec_factory.pool == NULL)
+	return PJ_SUCCESS;
+
+    /* Get the codec manager. */
+    codec_mgr = pjmedia_endpt_get_codec_mgr(amr_codec_factory.endpt);
+    if (!codec_mgr) {
+	pj_pool_release(amr_codec_factory.pool);
+	amr_codec_factory.pool = NULL;
+	return PJ_EINVALIDOP;
+    }
+
+    /* Unregister AMR codec factory. */
+    status = pjmedia_codec_mgr_unregister_factory(codec_mgr,
+						  &amr_codec_factory.base);
+    
+    /* Destroy pool. */
+    pj_pool_release(amr_codec_factory.pool);
+    amr_codec_factory.pool = NULL;
+    
+    return status;
+}
+
+PJ_DEF(pj_status_t) pjmedia_codec_opencore_amrnb_deinit(void)
+{
+    amr_codec_factory.init[IDX_AMR_NB] = PJ_FALSE;
+    
+    return amr_deinit();
+}
+
+PJ_DEF(pj_status_t) pjmedia_codec_opencore_amrwb_deinit(void)
+{
+    amr_codec_factory.init[IDX_AMR_WB] = PJ_FALSE;
+    
+    return amr_deinit();
+}
+
+static pj_status_t
+amr_set_config(unsigned idx, const pjmedia_codec_amr_config *config)
+{
+    unsigned nbitrates;
+
+    def_config[idx] = *config;
+
+    /* Normalize bitrate. */
+    nbitrates = PJ_ARRAY_SIZE(amr_bitrates[idx]);
+    if (def_config[idx].bitrate < amr_bitrates[idx][0]) {
+	def_config[idx].bitrate = amr_bitrates[idx][0];
+    } else if (def_config[idx].bitrate > amr_bitrates[idx][nbitrates-1]) {
+	def_config[idx].bitrate = amr_bitrates[idx][nbitrates-1];
+    } else
+    {
+	unsigned i;
+	
+	for (i = 0; i < nbitrates; ++i) {
+	    if (def_config[idx].bitrate <= amr_bitrates[idx][i])
+		break;
+	}
+	def_config[idx].bitrate = amr_bitrates[idx][i];
+    }
+
+    return PJ_SUCCESS;
+}
+
+PJ_DEF(pj_status_t) pjmedia_codec_opencore_amrnb_set_config(
+                                    const pjmedia_codec_amrnb_config *config)
+{
+    return amr_set_config(IDX_AMR_NB, (const pjmedia_codec_amr_config *)config);
+}
+
+PJ_DEF(pj_status_t) pjmedia_codec_opencore_amrwb_set_config(
+                                    const pjmedia_codec_amrwb_config *config)
+{
+    return amr_set_config(IDX_AMR_WB, (const pjmedia_codec_amr_config *)config);
+}
+
+/*
+ * Check if factory can allocate the specified codec.
+ */
+static pj_status_t amr_test_alloc( pjmedia_codec_factory *factory, 
+				   const pjmedia_codec_info *info )
+{
+    const pj_str_t amr_tag = { "AMR", 3};
+    const pj_str_t amrwb_tag = { "AMR-WB", 6};
+    PJ_UNUSED_ARG(factory);
+
+    /* Type MUST be audio. */
+    if (info->type != PJMEDIA_TYPE_AUDIO)
+	return PJMEDIA_CODEC_EUNSUP;
+    
+    /* Check payload type. */
+    if (info->pt != PJMEDIA_RTP_PT_AMR && info->pt != PJMEDIA_RTP_PT_AMRWB)
+	return PJMEDIA_CODEC_EUNSUP;
+    
+    /* Check encoding name. */
+    if (pj_stricmp(&info->encoding_name, &amr_tag) != 0 &&
+        pj_stricmp(&info->encoding_name, &amrwb_tag) != 0)
+    {
+	return PJMEDIA_CODEC_EUNSUP;
+    }
+    
+    /* Check clock-rate */
+    if ((info->clock_rate == 8000 && amr_codec_factory.init[IDX_AMR_NB]) ||
+        (info->clock_rate == 16000 && amr_codec_factory.init[IDX_AMR_WB]))
+    {
+        return PJ_SUCCESS;
+    }
+
+    /* Unsupported or disabled. */
+    return PJMEDIA_CODEC_EUNSUP;
+}
+
+/*
+ * Generate default attribute.
+ */
+static pj_status_t amr_default_attr( pjmedia_codec_factory *factory, 
+				     const pjmedia_codec_info *id, 
+				     pjmedia_codec_param *attr )
+{
+    unsigned idx;
+    
+    PJ_UNUSED_ARG(factory);
+
+    idx = (id->clock_rate <= 8000? IDX_AMR_NB: IDX_AMR_WB);
+    pj_bzero(attr, sizeof(pjmedia_codec_param));
+    attr->info.clock_rate = (id->clock_rate <= 8000? 8000: 16000);
+    attr->info.channel_cnt = 1;
+    attr->info.avg_bps = def_config[idx].bitrate;
+    attr->info.max_bps = amr_bitrates[idx][PJ_ARRAY_SIZE(amr_bitrates[idx])-1];
+    attr->info.pcm_bits_per_sample = 16;
+    attr->info.frm_ptime = 20;
+    attr->info.pt = (pj_uint8_t)id->pt;
+
+    attr->setting.frm_per_pkt = 2;
+    attr->setting.vad = 1;
+    attr->setting.plc = 1;
+
+    if (def_config[idx].octet_align) {
+	attr->setting.dec_fmtp.cnt = 1;
+	attr->setting.dec_fmtp.param[0].name = pj_str("octet-align");
+	attr->setting.dec_fmtp.param[0].val = pj_str("1");
+    }
+
+    /* Default all other flag bits disabled. */
+
+    return PJ_SUCCESS;
+}
+
+
+/*
+ * Enum codecs supported by this factory (i.e. AMR-NB and AMR-WB).
+ */
+static pj_status_t amr_enum_codecs( pjmedia_codec_factory *factory, 
+				    unsigned *count, 
+				    pjmedia_codec_info codecs[])
+{
+    PJ_UNUSED_ARG(factory);
+    PJ_ASSERT_RETURN(codecs && *count > 0, PJ_EINVAL);
+
+    *count = 0;
+
+    if (amr_codec_factory.init[IDX_AMR_NB]) {
+        pj_bzero(&codecs[*count], sizeof(pjmedia_codec_info));
+        codecs[*count].encoding_name = pj_str("AMR");
+        codecs[*count].pt = PJMEDIA_RTP_PT_AMR;
+        codecs[*count].type = PJMEDIA_TYPE_AUDIO;
+        codecs[*count].clock_rate = 8000;
+        codecs[*count].channel_cnt = 1;
+        (*count)++;
+    }
+    
+    if (amr_codec_factory.init[IDX_AMR_NB]) {
+        pj_bzero(&codecs[*count], sizeof(pjmedia_codec_info));
+        codecs[*count].encoding_name = pj_str("AMR-WB");
+        codecs[*count].pt = PJMEDIA_RTP_PT_AMRWB;
+        codecs[*count].type = PJMEDIA_TYPE_AUDIO;
+        codecs[*count].clock_rate = 16000;
+        codecs[*count].channel_cnt = 1;
+        (*count)++;
+    }
+
+    return PJ_SUCCESS;
+}
+
+
+/*
+ * Allocate a new AMR codec instance.
+ */
+static pj_status_t amr_alloc_codec( pjmedia_codec_factory *factory, 
+				    const pjmedia_codec_info *id,
+				    pjmedia_codec **p_codec)
+{
+    pj_pool_t *pool;
+    pjmedia_codec *codec;
+    struct amr_data *amr_data;
+    pj_status_t status;
+
+    PJ_ASSERT_RETURN(factory && id && p_codec, PJ_EINVAL);
+    PJ_ASSERT_RETURN(factory == &amr_codec_factory.base, PJ_EINVAL);
+
+    pool = pjmedia_endpt_create_pool(amr_codec_factory.endpt, "amr-inst", 
+				     512, 512);
+
+    codec = PJ_POOL_ZALLOC_T(pool, pjmedia_codec);
+    PJ_ASSERT_RETURN(codec != NULL, PJ_ENOMEM);
+    codec->op = &amr_op;
+    codec->factory = factory;
+
+    amr_data = PJ_POOL_ZALLOC_T(pool, struct amr_data);
+    codec->codec_data = amr_data;
+    amr_data->pool = pool;
+
+#if USE_PJMEDIA_PLC
+    /* Create PLC */
+    status = pjmedia_plc_create(pool, id->clock_rate,
+                                id->clock_rate * FRAME_LENGTH_MS / 1000, 0,
+                                &amr_data->plc);
+    if (status != PJ_SUCCESS) {
+	return status;
+    }
+#else
+    PJ_UNUSED_ARG(status);
+#endif
+    *p_codec = codec;
+    return PJ_SUCCESS;
+}
+
+
+/*
+ * Free codec.
+ */
+static pj_status_t amr_dealloc_codec( pjmedia_codec_factory *factory, 
+				      pjmedia_codec *codec )
+{
+    struct amr_data *amr_data;
+
+    PJ_ASSERT_RETURN(factory && codec, PJ_EINVAL);
+    PJ_ASSERT_RETURN(factory == &amr_codec_factory.base, PJ_EINVAL);
+
+    amr_data = (struct amr_data*) codec->codec_data;
+
+    /* Close codec, if it's not closed. */
+    amr_codec_close(codec);
+
+    pj_pool_release(amr_data->pool);
+    amr_data = NULL;
+
+    return PJ_SUCCESS;
+}
+
+/*
+ * Init codec.
+ */
+static pj_status_t amr_codec_init( pjmedia_codec *codec, 
+				   pj_pool_t *pool )
+{
+    PJ_UNUSED_ARG(codec);
+    PJ_UNUSED_ARG(pool);
+    return PJ_SUCCESS;
+}
+
+
+/*
+ * Open codec.
+ */
+static pj_status_t amr_codec_open( pjmedia_codec *codec, 
+				   pjmedia_codec_param *attr )
+{
+    struct amr_data *amr_data = (struct amr_data*) codec->codec_data;
+    pjmedia_codec_amr_pack_setting *setting;
+    unsigned i;
+    pj_uint8_t octet_align = 0;
+    pj_int8_t enc_mode;
+    const pj_str_t STR_FMTP_OCTET_ALIGN = {"octet-align", 11};
+    unsigned idx;
+
+    PJ_ASSERT_RETURN(codec && attr, PJ_EINVAL);
+    PJ_ASSERT_RETURN(amr_data != NULL, PJ_EINVALIDOP);
+
+    idx = (attr->info.clock_rate <= 8000? IDX_AMR_NB: IDX_AMR_WB);
+    enc_mode = pjmedia_codec_amr_get_mode(attr->info.avg_bps);
+    pj_assert(enc_mode >= 0 &&
+              enc_mode < PJ_ARRAY_SIZE(amr_bitrates[idx]));
+
+    /* Check octet-align */
+    for (i = 0; i < attr->setting.dec_fmtp.cnt; ++i) {
+	if (pj_stricmp(&attr->setting.dec_fmtp.param[i].name, 
+		       &STR_FMTP_OCTET_ALIGN) == 0)
+	{
+	    octet_align = (pj_uint8_t)
+			  (pj_strtoul(&attr->setting.dec_fmtp.param[i].val));
+	    break;
+	}
+    }
+
+    /* Check mode-set */
+    for (i = 0; i < attr->setting.enc_fmtp.cnt; ++i) {
+	const pj_str_t STR_FMTP_MODE_SET = {"mode-set", 8};
+        
+	if (pj_stricmp(&attr->setting.enc_fmtp.param[i].name, 
+		       &STR_FMTP_MODE_SET) == 0)
+	{
+	    const char *p;
+	    pj_size_t l;
+	    pj_int8_t diff = 99;
+
+	    /* Encoding mode is chosen based on local default mode setting:
+	     * - if local default mode is included in the mode-set, use it
+	     * - otherwise, find the closest mode to local default mode;
+	     *   if there are two closest modes, prefer to use the higher
+	     *   one, e.g: local default mode is 4, the mode-set param
+	     *   contains '2,3,5,6', then 5 will be chosen.
+	     */
+	    p = pj_strbuf(&attr->setting.enc_fmtp.param[i].val);
+	    l = pj_strlen(&attr->setting.enc_fmtp.param[i].val);
+	    while (l--) {
+		if (*p>='0' &&
+                    *p<=('0'+PJ_ARRAY_SIZE(amr_bitrates[idx])-1))
+                {
+		    pj_int8_t tmp = *p - '0' - enc_mode;
+
+		    if (PJ_ABS(diff) > PJ_ABS(tmp) || 
+			(PJ_ABS(diff) == PJ_ABS(tmp) && tmp > diff))
+		    {
+			diff = tmp;
+			if (diff == 0) break;
+		    }
+		}
+		++p;
+	    }
+	    PJ_ASSERT_RETURN(diff != 99, PJMEDIA_CODEC_EFAILED);
+
+	    enc_mode = enc_mode + diff;
+
+	    break;
+	}
+    }
+
+    amr_data->clock_rate = attr->info.clock_rate;
+    amr_data->vad_enabled = (attr->setting.vad != 0);
+    amr_data->plc_enabled = (attr->setting.plc != 0);
+    amr_data->enc_mode = enc_mode;
+
+    if (idx == IDX_AMR_NB) {
+#ifdef USE_AMRNB
+        amr_data->encoder = Encoder_Interface_init(amr_data->vad_enabled);
+#endif
+    } else {
+#ifdef USE_AMRWB
+        amr_data->encoder = E_IF_init();
+#endif
+    }
+    if (amr_data->encoder == NULL) {
+	TRACE_((THIS_FILE, "Encoder initialization failed"));
+	amr_codec_close(codec);
+	return PJMEDIA_CODEC_EFAILED;
+    }
+    setting = &amr_data->enc_setting;
+    pj_bzero(setting, sizeof(pjmedia_codec_amr_pack_setting));
+    setting->amr_nb = (idx == IDX_AMR_NB? 1: 0);
+    setting->reorder = 0;
+    setting->octet_aligned = octet_align;
+    setting->cmr = 15;
+
+    if (idx == IDX_AMR_NB) {
+#ifdef USE_AMRNB
+        amr_data->decoder = Decoder_Interface_init();
+#endif
+    } else {
+#ifdef USE_AMRWB
+        amr_data->decoder = D_IF_init();
+#endif
+    }
+    if (amr_data->decoder == NULL) {
+	TRACE_((THIS_FILE, "Decoder initialization failed"));
+	amr_codec_close(codec);
+	return PJMEDIA_CODEC_EFAILED;
+    }
+    setting = &amr_data->dec_setting;
+    pj_bzero(setting, sizeof(pjmedia_codec_amr_pack_setting));
+    setting->amr_nb = (idx == IDX_AMR_NB? 1: 0);
+    setting->reorder = 0;
+    setting->octet_aligned = octet_align;
+
+    TRACE_((THIS_FILE, "AMR codec allocated: clockrate=%d vad=%d, plc=%d,"
+                       " bitrate=%d", amr_data->clock_rate,
+			amr_data->vad_enabled, amr_data->plc_enabled, 
+			amr_bitrates[idx][amr_data->enc_mode]));
+    return PJ_SUCCESS;
+}
+
+
+/*
+ * Close codec.
+ */
+static pj_status_t amr_codec_close( pjmedia_codec *codec )
+{
+    struct amr_data *amr_data;
+
+    PJ_ASSERT_RETURN(codec, PJ_EINVAL);
+
+    amr_data = (struct amr_data*) codec->codec_data;
+    PJ_ASSERT_RETURN(amr_data != NULL, PJ_EINVALIDOP);
+
+    if (amr_data->encoder) {
+        if (amr_data->enc_setting.amr_nb) {
+#ifdef USE_AMRNB
+            Encoder_Interface_exit(amr_data->encoder);
+#endif
+        } else {
+#ifdef USE_AMRWB
+            E_IF_exit(amr_data->encoder);
+#endif
+        }
+        amr_data->encoder = NULL;
+    }
+
+    if (amr_data->decoder) {
+        if (amr_data->dec_setting.amr_nb) {
+#ifdef USE_AMRNB
+            Decoder_Interface_exit(amr_data->decoder);
+#endif
+        } else {
+#ifdef USE_AMRWB
+            D_IF_exit(amr_data->decoder);
+#endif
+        }
+        amr_data->decoder = NULL;
+    }
+    
+    TRACE_((THIS_FILE, "AMR codec closed"));
+    return PJ_SUCCESS;
+}
+
+
+/*
+ * Modify codec settings.
+ */
+static pj_status_t amr_codec_modify( pjmedia_codec *codec, 
+				     const pjmedia_codec_param *attr )
+{
+    struct amr_data *amr_data = (struct amr_data*) codec->codec_data;
+    pj_bool_t prev_vad_state;
+
+    pj_assert(amr_data != NULL);
+    pj_assert(amr_data->encoder != NULL && amr_data->decoder != NULL);
+
+    prev_vad_state = amr_data->vad_enabled;
+    amr_data->vad_enabled = (attr->setting.vad != 0);
+    amr_data->plc_enabled = (attr->setting.plc != 0);
+
+    if (amr_data->enc_setting.amr_nb &&
+        prev_vad_state != amr_data->vad_enabled)
+    {
+	/* Reinit AMR encoder to update VAD setting */
+	TRACE_((THIS_FILE, "Reiniting AMR encoder to update VAD setting."));
+#ifdef USE_AMRNB
+        Encoder_Interface_exit(amr_data->encoder);
+        amr_data->encoder = Encoder_Interface_init(amr_data->vad_enabled);
+#endif
+        if (amr_data->encoder == NULL) {
+	    TRACE_((THIS_FILE, "Encoder_Interface_init() failed"));
+	    amr_codec_close(codec);
+	    return PJMEDIA_CODEC_EFAILED;
+	}
+    }
+
+    TRACE_((THIS_FILE, "AMR codec modified: vad=%d, plc=%d",
+			amr_data->vad_enabled, amr_data->plc_enabled));
+    return PJ_SUCCESS;
+}
+
+
+/*
+ * Get frames in the packet.
+ */
+static pj_status_t amr_codec_parse( pjmedia_codec *codec,
+				    void *pkt,
+				    pj_size_t pkt_size,
+				    const pj_timestamp *ts,
+				    unsigned *frame_cnt,
+				    pjmedia_frame frames[])
+{
+    struct amr_data *amr_data = (struct amr_data*) codec->codec_data;
+    pj_uint8_t cmr;
+    pj_status_t status;
+    unsigned idx = (amr_data->enc_setting.amr_nb? 0: 1);
+
+    status = pjmedia_codec_amr_parse(pkt, pkt_size, ts, &amr_data->dec_setting,
+				     frames, frame_cnt, &cmr);
+    if (status != PJ_SUCCESS)
+	return status;
+
+    /* Check for Change Mode Request. */
+    if (cmr < PJ_ARRAY_SIZE(amr_bitrates[idx]) && amr_data->enc_mode != cmr) {
+	amr_data->enc_mode = cmr;
+	TRACE_((THIS_FILE, "AMR encoder switched mode to %d (%dbps)",
+                amr_data->enc_mode, 
+                amr_bitrates[idx][amr_data->enc_mode]));
+    }
+
+    return PJ_SUCCESS;
+}
+
+
+/*
+ * Encode frame.
+ */
+static pj_status_t amr_codec_encode( pjmedia_codec *codec, 
+				     const struct pjmedia_frame *input,
+				     unsigned output_buf_len, 
+				     struct pjmedia_frame *output)
+{
+    struct amr_data *amr_data = (struct amr_data*) codec->codec_data;
+    unsigned char *bitstream;
+    pj_int16_t *speech;
+    unsigned nsamples, samples_per_frame;
+    enum {MAX_FRAMES_PER_PACKET = 16};
+    pjmedia_frame frames[MAX_FRAMES_PER_PACKET];
+    pj_uint8_t *p;
+    unsigned i, out_size = 0, nframes = 0;
+    pj_size_t payload_len;
+    unsigned dtx_cnt, sid_cnt;
+    pj_status_t status;
+    int size;
+
+    pj_assert(amr_data != NULL);
+    PJ_ASSERT_RETURN(input && output, PJ_EINVAL);
+
+    nsamples = input->size >> 1;
+    samples_per_frame = amr_data->clock_rate * FRAME_LENGTH_MS / 1000;
+    PJ_ASSERT_RETURN(nsamples % samples_per_frame == 0, 
+		     PJMEDIA_CODEC_EPCMFRMINLEN);
+
+    nframes = nsamples / samples_per_frame;
+    PJ_ASSERT_RETURN(nframes <= MAX_FRAMES_PER_PACKET, 
+		     PJMEDIA_CODEC_EFRMTOOSHORT);
+
+    /* Encode the frames */
+    speech = (pj_int16_t*)input->buf;
+    bitstream = (unsigned char*)output->buf;
+    while (nsamples >= samples_per_frame) {
+        if (amr_data->enc_setting.amr_nb) {
+#ifdef USE_AMRNB
+            size = Encoder_Interface_Encode (amr_data->encoder,
+                                             amr_data->enc_mode,
+                                             speech, bitstream, 0);
+#endif
+        } else {
+#ifdef USE_AMRWB
+            size = E_IF_encode (amr_data->encoder, amr_data->enc_mode,
+                                speech, bitstream, 0);
+#endif
+        }
+	if (size == 0) {
+	    output->size = 0;
+	    output->buf = NULL;
+	    output->type = PJMEDIA_FRAME_TYPE_NONE;
+	    TRACE_((THIS_FILE, "AMR encode() failed"));
+	    return PJMEDIA_CODEC_EFAILED;
+	}
+	nsamples -= samples_per_frame;
+	speech += samples_per_frame;
+	bitstream += size;
+	out_size += size;
+	TRACE_((THIS_FILE, "AMR encode(): mode=%d, size=%d",
+		amr_data->enc_mode, out_size));
+    }
+
+    /* Pack payload */
+    p = (pj_uint8_t*)output->buf + output_buf_len - out_size;
+    pj_memmove(p, output->buf, out_size);
+    dtx_cnt = sid_cnt = 0;
+    for (i = 0; i < nframes; ++i) {
+	pjmedia_codec_amr_bit_info *info = (pjmedia_codec_amr_bit_info*)
+					   &frames[i].bit_info;
+	info->frame_type = (pj_uint8_t)((*p >> 3) & 0x0F);
+	info->good_quality = (pj_uint8_t)((*p >> 2) & 0x01);
+	info->mode = (pj_int8_t)amr_data->enc_mode;
+	info->start_bit = 0;
+	frames[i].buf = p + 1;
+        if (amr_data->enc_setting.amr_nb) {
+            frames[i].size = (info->frame_type <= 8)?
+                             pjmedia_codec_amrnb_framelen[info->frame_type] : 0;
+        } else {
+            frames[i].size = (info->frame_type <= 9)?
+                             pjmedia_codec_amrwb_framelen[info->frame_type] : 0;
+        }
+	p += frames[i].size + 1;
+
+	/* Count the number of SID and DTX frames */
+	if (info->frame_type == 15) /* DTX*/
+	    ++dtx_cnt;
+	else if (info->frame_type == 8) /* SID */
+	    ++sid_cnt;
+    }
+
+    /* VA generates DTX frames as DTX+SID frames switching quickly and it
+     * seems that the SID frames occur too often (assuming the purpose is 
+     * only for keeping NAT alive?). So let's modify the behavior a bit.
+     * Only an SID frame will be sent every PJMEDIA_CODEC_MAX_SILENCE_PERIOD
+     * milliseconds.
+     */
+    if (sid_cnt + dtx_cnt == nframes) {
+	pj_int32_t dtx_duration;
+
+	dtx_duration = pj_timestamp_diff32(&amr_data->last_tx, 
+					   &input->timestamp);
+	if (PJMEDIA_CODEC_MAX_SILENCE_PERIOD == -1 ||
+	    dtx_duration < PJMEDIA_CODEC_MAX_SILENCE_PERIOD*
+                           amr_data->clock_rate/1000)
+	{
+	    output->size = 0;
+	    output->type = PJMEDIA_FRAME_TYPE_NONE;
+	    output->timestamp = input->timestamp;
+	    return PJ_SUCCESS;
+	}
+    }
+
+    payload_len = output_buf_len;
+
+    status = pjmedia_codec_amr_pack(frames, nframes, &amr_data->enc_setting,
+				    output->buf, &payload_len);
+    if (status != PJ_SUCCESS) {
+	output->size = 0;
+	output->buf = NULL;
+	output->type = PJMEDIA_FRAME_TYPE_NONE;
+	TRACE_((THIS_FILE, "Failed to pack AMR payload, status=%d", status));
+	return status;
+    }
+
+    output->size = payload_len;
+    output->type = PJMEDIA_FRAME_TYPE_AUDIO;
+    output->timestamp = input->timestamp;
+
+    amr_data->last_tx = input->timestamp;
+
+    return PJ_SUCCESS;
+}
+
+
+/*
+ * Decode frame.
+ */
+static pj_status_t amr_codec_decode( pjmedia_codec *codec, 
+				     const struct pjmedia_frame *input,
+				     unsigned output_buf_len, 
+				     struct pjmedia_frame *output)
+{
+    struct amr_data *amr_data = (struct amr_data*) codec->codec_data;
+    pjmedia_frame input_;
+    pjmedia_codec_amr_bit_info *info;
+    unsigned out_size;
+    /* AMR decoding buffer: AMR max frame size + 1 byte header. */
+    unsigned char bitstream[61];
+
+    pj_assert(amr_data != NULL);
+    PJ_ASSERT_RETURN(input && output, PJ_EINVAL);
+
+    out_size = amr_data->clock_rate * FRAME_LENGTH_MS / 1000 * 2;
+    if (output_buf_len < out_size)
+	return PJMEDIA_CODEC_EPCMTOOSHORT;
+
+    input_.buf = &bitstream[1];
+    /* AMR max frame size */
+    input_.size = (amr_data->dec_setting.amr_nb? 31: 60);
+    pjmedia_codec_amr_predecode(input, &amr_data->dec_setting, &input_);
+    info = (pjmedia_codec_amr_bit_info*)&input_.bit_info;
+
+    /* VA AMR decoder requires frame info in the first byte. */
+    bitstream[0] = (info->frame_type << 3) | (info->good_quality << 2);
+
+    TRACE_((THIS_FILE, "AMR decode(): mode=%d, ft=%d, size=%d",
+	    info->mode, info->frame_type, input_.size));
+
+    /* Decode */
+    if (amr_data->dec_setting.amr_nb) {
+#ifdef USE_AMRNB
+        Decoder_Interface_Decode(amr_data->decoder, bitstream,
+                                 (pj_int16_t*)output->buf, 0);
+#endif
+    } else {
+#ifdef USE_AMRWB
+        D_IF_decode(amr_data->decoder, bitstream,
+                    (pj_int16_t*)output->buf, 0);
+#endif
+    }
+
+    output->size = out_size;
+    output->type = PJMEDIA_FRAME_TYPE_AUDIO;
+    output->timestamp = input->timestamp;
+
+#if USE_PJMEDIA_PLC
+    if (amr_data->plc_enabled)
+	pjmedia_plc_save(amr_data->plc, (pj_int16_t*)output->buf);
+#endif
+
+    return PJ_SUCCESS;
+}
+
+
+/*
+ * Recover lost frame.
+ */
+#if USE_PJMEDIA_PLC
+/*
+ * Recover lost frame.
+ */
+static pj_status_t  amr_codec_recover( pjmedia_codec *codec,
+				       unsigned output_buf_len,
+				       struct pjmedia_frame *output)
+{
+    struct amr_data *amr_data = codec->codec_data;
+    unsigned out_size = amr_data->clock_rate * FRAME_LENGTH_MS / 1000 * 2;
+
+    TRACE_((THIS_FILE, "amr_codec_recover"));
+
+    PJ_ASSERT_RETURN(amr_data->plc_enabled, PJ_EINVALIDOP);
+
+    PJ_ASSERT_RETURN(output_buf_len >= out_size,  PJMEDIA_CODEC_EPCMTOOSHORT);
+
+    pjmedia_plc_generate(amr_data->plc, (pj_int16_t*)output->buf);
+
+    output->size = out_size;
+    output->type = PJMEDIA_FRAME_TYPE_AUDIO;
+    
+    return PJ_SUCCESS;
+}
+#endif
+
+#if defined(_MSC_VER) && PJMEDIA_AUTO_LINK_OPENCORE_AMR_LIBS
+#   if PJMEDIA_OPENCORE_AMR_BUILT_WITH_GCC
+#       ifdef USE_AMRNB
+#           pragma comment( lib, "libopencore-amrnb.a")
+#       endif
+#       ifdef USE_AMRWB
+#           pragma comment( lib, "libopencore-amrwb.a")
+#           pragma comment( lib, "libvo-amrwbenc.a")
+#       endif
+#   else
+#       error Unsupported OpenCORE AMR library, fix here
+#   endif
+#endif
+
+#endif
Index: pjproject/trunk/pjmedia/src/pjmedia-codec/opencore_amrnb.c
===================================================================
--- pjproject/trunk/pjmedia/src/pjmedia-codec/opencore_amrnb.c	(revision 4330)
+++ 	(revision )
@@ -1,831 +1,0 @@
-/* $Id$ */
-/* 
- * Copyright (C) 2011 Teluu Inc. (http://www.teluu.com)
- * Copyright (C) 2011 Dan Arrhenius <dan@keystream.se>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA 
- */
-
-/* 
- * AMR-NB codec implementation with OpenCORE AMRNB library
- */
-#include <pjmedia-codec/g722.h>
-#include <pjmedia-codec/amr_sdp_match.h>
-#include <pjmedia/codec.h>
-#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/log.h>
-#include <pj/pool.h>
-#include <pj/string.h>
-#include <pj/os.h>
-#include <pj/math.h>
-
-#if defined(PJMEDIA_HAS_OPENCORE_AMRNB_CODEC) && \
-    (PJMEDIA_HAS_OPENCORE_AMRNB_CODEC != 0)
-
-#include <opencore-amrnb/interf_enc.h>
-#include <opencore-amrnb/interf_dec.h>
-#include <pjmedia-codec/amr_helper.h>
-#include <pjmedia-codec/opencore_amrnb.h>
-
-#define THIS_FILE "opencore_amrnb.c"
-
-/* Tracing */
-#define PJ_TRACE    0
-
-#if PJ_TRACE
-#   define TRACE_(expr)	PJ_LOG(4,expr)
-#else
-#   define TRACE_(expr)
-#endif
-
-/* Use PJMEDIA PLC */
-#define USE_PJMEDIA_PLC	    1
-
-
-
-/* Prototypes for AMR-NB factory */
-static pj_status_t amr_test_alloc(pjmedia_codec_factory *factory, 
-				   const pjmedia_codec_info *id );
-static pj_status_t amr_default_attr(pjmedia_codec_factory *factory, 
-				     const pjmedia_codec_info *id, 
-				     pjmedia_codec_param *attr );
-static pj_status_t amr_enum_codecs(pjmedia_codec_factory *factory, 
-				    unsigned *count, 
-				    pjmedia_codec_info codecs[]);
-static pj_status_t amr_alloc_codec(pjmedia_codec_factory *factory, 
-				    const pjmedia_codec_info *id, 
-				    pjmedia_codec **p_codec);
-static pj_status_t amr_dealloc_codec(pjmedia_codec_factory *factory, 
-				      pjmedia_codec *codec );
-
-/* Prototypes for AMR-NB implementation. */
-static pj_status_t  amr_codec_init(pjmedia_codec *codec, 
-				    pj_pool_t *pool );
-static pj_status_t  amr_codec_open(pjmedia_codec *codec, 
-				    pjmedia_codec_param *attr );
-static pj_status_t  amr_codec_close(pjmedia_codec *codec );
-static pj_status_t  amr_codec_modify(pjmedia_codec *codec, 
-				      const pjmedia_codec_param *attr );
-static pj_status_t  amr_codec_parse(pjmedia_codec *codec,
-				     void *pkt,
-				     pj_size_t pkt_size,
-				     const pj_timestamp *ts,
-				     unsigned *frame_cnt,
-				     pjmedia_frame frames[]);
-static pj_status_t  amr_codec_encode(pjmedia_codec *codec, 
-				      const struct pjmedia_frame *input,
-				      unsigned output_buf_len, 
-				      struct pjmedia_frame *output);
-static pj_status_t  amr_codec_decode(pjmedia_codec *codec, 
-				      const struct pjmedia_frame *input,
-				      unsigned output_buf_len, 
-				      struct pjmedia_frame *output);
-static pj_status_t  amr_codec_recover(pjmedia_codec *codec,
-				      unsigned output_buf_len,
-				      struct pjmedia_frame *output);
-
-
-
-/* Definition for AMR-NB codec operations. */
-static pjmedia_codec_op amr_op = 
-{
-    &amr_codec_init,
-    &amr_codec_open,
-    &amr_codec_close,
-    &amr_codec_modify,
-    &amr_codec_parse,
-    &amr_codec_encode,
-    &amr_codec_decode,
-    &amr_codec_recover
-};
-
-/* Definition for AMR-NB codec factory operations. */
-static pjmedia_codec_factory_op amr_factory_op =
-{
-    &amr_test_alloc,
-    &amr_default_attr,
-    &amr_enum_codecs,
-    &amr_alloc_codec,
-    &amr_dealloc_codec,
-    &pjmedia_codec_opencore_amrnb_deinit
-};
-
-
-/* AMR-NB factory */
-static struct amr_codec_factory
-{
-    pjmedia_codec_factory    base;
-    pjmedia_endpt	    *endpt;
-    pj_pool_t		    *pool;
-} amr_codec_factory;
-
-
-/* AMR-NB codec private data. */
-struct amr_data
-{
-    pj_pool_t		*pool;
-    void		*encoder;
-    void		*decoder;
-    pj_bool_t		 plc_enabled;
-    pj_bool_t		 vad_enabled;
-    int			 enc_mode;
-    pjmedia_codec_amr_pack_setting enc_setting;
-    pjmedia_codec_amr_pack_setting dec_setting;
-#if USE_PJMEDIA_PLC
-    pjmedia_plc		*plc;
-#endif
-    pj_timestamp	 last_tx;
-};
-
-static pjmedia_codec_amrnb_config def_config =
-{
-    PJ_FALSE,	    /* octet align	*/
-    5900	    /* bitrate		*/
-};
-
-
-
-/*
- * Initialize and register AMR-NB codec factory to pjmedia endpoint.
- */
-PJ_DEF(pj_status_t) pjmedia_codec_opencore_amrnb_init( pjmedia_endpt *endpt )
-{
-    pjmedia_codec_mgr *codec_mgr;
-    pj_str_t codec_name;
-    pj_status_t status;
-
-    if (amr_codec_factory.pool != NULL)
-	return PJ_SUCCESS;
-
-    /* Create AMR-NB codec factory. */
-    amr_codec_factory.base.op = &amr_factory_op;
-    amr_codec_factory.base.factory_data = NULL;
-    amr_codec_factory.endpt = endpt;
-
-    amr_codec_factory.pool = pjmedia_endpt_create_pool(endpt, "amrnb", 1000, 
-						       1000);
-    if (!amr_codec_factory.pool)
-	return PJ_ENOMEM;
-
-    /* Get the codec manager. */
-    codec_mgr = pjmedia_endpt_get_codec_mgr(endpt);
-    if (!codec_mgr) {
-	status = PJ_EINVALIDOP;
-	goto on_error;
-    }
-
-    /* Register format match callback. */
-    pj_cstr(&codec_name, "AMR");
-    status = pjmedia_sdp_neg_register_fmt_match_cb(
-					&codec_name,
-					&pjmedia_codec_amr_match_sdp);
-    if (status != PJ_SUCCESS)
-	goto on_error;
-
-    /* Register codec factory to endpoint. */
-    status = pjmedia_codec_mgr_register_factory(codec_mgr, 
-						&amr_codec_factory.base);
-    if (status != PJ_SUCCESS)
-	goto on_error;
-
-    /* Done. */
-    return PJ_SUCCESS;
-
-on_error:
-    pj_pool_release(amr_codec_factory.pool);
-    amr_codec_factory.pool = NULL;
-    return status;
-}
-
-
-/*
- * Unregister AMR-NB codec factory from pjmedia endpoint and deinitialize
- * the AMR-NB codec library.
- */
-PJ_DEF(pj_status_t) pjmedia_codec_opencore_amrnb_deinit(void)
-{
-    pjmedia_codec_mgr *codec_mgr;
-    pj_status_t status;
-
-    if (amr_codec_factory.pool == NULL)
-	return PJ_SUCCESS;
-
-    /* Get the codec manager. */
-    codec_mgr = pjmedia_endpt_get_codec_mgr(amr_codec_factory.endpt);
-    if (!codec_mgr) {
-	pj_pool_release(amr_codec_factory.pool);
-	amr_codec_factory.pool = NULL;
-	return PJ_EINVALIDOP;
-    }
-
-    /* Unregister AMR-NB codec factory. */
-    status = pjmedia_codec_mgr_unregister_factory(codec_mgr,
-						  &amr_codec_factory.base);
-    
-    /* Destroy pool. */
-    pj_pool_release(amr_codec_factory.pool);
-    amr_codec_factory.pool = NULL;
-    
-    return status;
-}
-
-
-PJ_DEF(pj_status_t) pjmedia_codec_opencore_amrnb_set_config(
-			    const pjmedia_codec_amrnb_config *config)
-{
-    unsigned nbitrates;
-
-
-    def_config = *config;
-
-    /* Normalize bitrate. */
-    nbitrates = PJ_ARRAY_SIZE(pjmedia_codec_amrnb_bitrates);
-    if (def_config.bitrate < pjmedia_codec_amrnb_bitrates[0])
-	def_config.bitrate = pjmedia_codec_amrnb_bitrates[0];
-    else if (def_config.bitrate > pjmedia_codec_amrnb_bitrates[nbitrates-1])
-	def_config.bitrate = pjmedia_codec_amrnb_bitrates[nbitrates-1];
-    else
-    {
-	unsigned i;
-	
-	for (i = 0; i < nbitrates; ++i) {
-	    if (def_config.bitrate <= pjmedia_codec_amrnb_bitrates[i])
-		break;
-	}
-	def_config.bitrate = pjmedia_codec_amrnb_bitrates[i];
-    }
-
-    return PJ_SUCCESS;
-}
-
-/* 
- * Check if factory can allocate the specified codec. 
- */
-static pj_status_t amr_test_alloc( pjmedia_codec_factory *factory, 
-				   const pjmedia_codec_info *info )
-{
-    PJ_UNUSED_ARG(factory);
-
-    /* Check payload type. */
-    if (info->pt != PJMEDIA_RTP_PT_AMR)
-	return PJMEDIA_CODEC_EUNSUP;
-
-    /* Ignore the rest, since it's static payload type. */
-
-    return PJ_SUCCESS;
-}
-
-/*
- * Generate default attribute.
- */
-static pj_status_t amr_default_attr( pjmedia_codec_factory *factory, 
-				     const pjmedia_codec_info *id, 
-				     pjmedia_codec_param *attr )
-{
-    PJ_UNUSED_ARG(factory);
-    PJ_UNUSED_ARG(id);
-
-    pj_bzero(attr, sizeof(pjmedia_codec_param));
-    attr->info.clock_rate = 8000;
-    attr->info.channel_cnt = 1;
-    attr->info.avg_bps = def_config.bitrate;
-    attr->info.max_bps = pjmedia_codec_amrnb_bitrates[7];
-    attr->info.pcm_bits_per_sample = 16;
-    attr->info.frm_ptime = 20;
-    attr->info.pt = PJMEDIA_RTP_PT_AMR;
-
-    attr->setting.frm_per_pkt = 2;
-    attr->setting.vad = 1;
-    attr->setting.plc = 1;
-
-    if (def_config.octet_align) {
-	attr->setting.dec_fmtp.cnt = 1;
-	attr->setting.dec_fmtp.param[0].name = pj_str("octet-align");
-	attr->setting.dec_fmtp.param[0].val = pj_str("1");
-    }
-
-    /* Default all other flag bits disabled. */
-
-    return PJ_SUCCESS;
-}
-
-
-/*
- * Enum codecs supported by this factory (i.e. only AMR-NB!).
- */
-static pj_status_t amr_enum_codecs( pjmedia_codec_factory *factory, 
-				    unsigned *count, 
-				    pjmedia_codec_info codecs[])
-{
-    PJ_UNUSED_ARG(factory);
-    PJ_ASSERT_RETURN(codecs && *count > 0, PJ_EINVAL);
-
-    pj_bzero(&codecs[0], sizeof(pjmedia_codec_info));
-    codecs[0].encoding_name = pj_str("AMR");
-    codecs[0].pt = PJMEDIA_RTP_PT_AMR;
-    codecs[0].type = PJMEDIA_TYPE_AUDIO;
-    codecs[0].clock_rate = 8000;
-    codecs[0].channel_cnt = 1;
-
-    *count = 1;
-
-    return PJ_SUCCESS;
-}
-
-
-/*
- * Allocate a new AMR-NB codec instance.
- */
-static pj_status_t amr_alloc_codec( pjmedia_codec_factory *factory, 
-				    const pjmedia_codec_info *id,
-				    pjmedia_codec **p_codec)
-{
-    pj_pool_t *pool;
-    pjmedia_codec *codec;
-    struct amr_data *amr_data;
-    pj_status_t status;
-
-    PJ_ASSERT_RETURN(factory && id && p_codec, PJ_EINVAL);
-    PJ_ASSERT_RETURN(factory == &amr_codec_factory.base, PJ_EINVAL);
-
-    pool = pjmedia_endpt_create_pool(amr_codec_factory.endpt, "amrnb-inst", 
-				     512, 512);
-
-    codec = PJ_POOL_ZALLOC_T(pool, pjmedia_codec);
-    PJ_ASSERT_RETURN(codec != NULL, PJ_ENOMEM);
-    codec->op = &amr_op;
-    codec->factory = factory;
-
-    amr_data = PJ_POOL_ZALLOC_T(pool, struct amr_data);
-    codec->codec_data = amr_data;
-    amr_data->pool = pool;
-
-#if USE_PJMEDIA_PLC
-    /* Create PLC */
-    status = pjmedia_plc_create(pool, 8000, 160, 0, &amr_data->plc);
-    if (status != PJ_SUCCESS) {
-	return status;
-    }
-#else
-    PJ_UNUSED_ARG(status);
-#endif
-    *p_codec = codec;
-    return PJ_SUCCESS;
-}
-
-
-/*
- * Free codec.
- */
-static pj_status_t amr_dealloc_codec( pjmedia_codec_factory *factory, 
-				      pjmedia_codec *codec )
-{
-    struct amr_data *amr_data;
-
-    PJ_ASSERT_RETURN(factory && codec, PJ_EINVAL);
-    PJ_ASSERT_RETURN(factory == &amr_codec_factory.base, PJ_EINVAL);
-
-    amr_data = (struct amr_data*) codec->codec_data;
-
-    /* Close codec, if it's not closed. */
-    amr_codec_close(codec);
-
-    pj_pool_release(amr_data->pool);
-    amr_data = NULL;
-
-    return PJ_SUCCESS;
-}
-
-/*
- * Init codec.
- */
-static pj_status_t amr_codec_init( pjmedia_codec *codec, 
-				   pj_pool_t *pool )
-{
-    PJ_UNUSED_ARG(codec);
-    PJ_UNUSED_ARG(pool);
-    return PJ_SUCCESS;
-}
-
-
-/*
- * Open codec.
- */
-static pj_status_t amr_codec_open( pjmedia_codec *codec, 
-				   pjmedia_codec_param *attr )
-{
-    struct amr_data *amr_data = (struct amr_data*) codec->codec_data;
-    pjmedia_codec_amr_pack_setting *setting;
-    unsigned i;
-    pj_uint8_t octet_align = 0;
-    pj_int8_t enc_mode;
-    const pj_str_t STR_FMTP_OCTET_ALIGN = {"octet-align", 11};
-
-    PJ_ASSERT_RETURN(codec && attr, PJ_EINVAL);
-    PJ_ASSERT_RETURN(amr_data != NULL, PJ_EINVALIDOP);
-
-    enc_mode = pjmedia_codec_amr_get_mode(attr->info.avg_bps);
-    pj_assert(enc_mode >= 0 && enc_mode <= 7);
-
-    /* Check octet-align */
-    for (i = 0; i < attr->setting.dec_fmtp.cnt; ++i) {
-	if (pj_stricmp(&attr->setting.dec_fmtp.param[i].name, 
-		       &STR_FMTP_OCTET_ALIGN) == 0)
-	{
-	    octet_align = (pj_uint8_t)
-			  (pj_strtoul(&attr->setting.dec_fmtp.param[i].val));
-	    break;
-	}
-    }
-
-    /* Check mode-set */
-    for (i = 0; i < attr->setting.enc_fmtp.cnt; ++i) {
-	const pj_str_t STR_FMTP_MODE_SET = {"mode-set", 8};
-        
-	if (pj_stricmp(&attr->setting.enc_fmtp.param[i].name, 
-		       &STR_FMTP_MODE_SET) == 0)
-	{
-	    const char *p;
-	    pj_size_t l;
-	    pj_int8_t diff = 99;
-
-	    /* Encoding mode is chosen based on local default mode setting:
-	     * - if local default mode is included in the mode-set, use it
-	     * - otherwise, find the closest mode to local default mode;
-	     *   if there are two closest modes, prefer to use the higher
-	     *   one, e.g: local default mode is 4, the mode-set param
-	     *   contains '2,3,5,6', then 5 will be chosen.
-	     */
-	    p = pj_strbuf(&attr->setting.enc_fmtp.param[i].val);
-	    l = pj_strlen(&attr->setting.enc_fmtp.param[i].val);
-	    while (l--) {
-		if (*p>='0' && *p<='7') {
-		    pj_int8_t tmp = *p - '0' - enc_mode;
-
-		    if (PJ_ABS(diff) > PJ_ABS(tmp) || 
-			(PJ_ABS(diff) == PJ_ABS(tmp) && tmp > diff))
-		    {
-			diff = tmp;
-			if (diff == 0) break;
-		    }
-		}
-		++p;
-	    }
-	    PJ_ASSERT_RETURN(diff != 99, PJMEDIA_CODEC_EFAILED);
-
-	    enc_mode = enc_mode + diff;
-
-	    break;
-	}
-    }
-
-    amr_data->vad_enabled = (attr->setting.vad != 0);
-    amr_data->plc_enabled = (attr->setting.plc != 0);
-    amr_data->enc_mode = enc_mode;
-
-    amr_data->encoder = Encoder_Interface_init(amr_data->vad_enabled);
-    if (amr_data->encoder == NULL) {
-	TRACE_((THIS_FILE, "Encoder_Interface_init() failed"));
-	amr_codec_close(codec);
-	return PJMEDIA_CODEC_EFAILED;
-    }
-    setting = &amr_data->enc_setting;
-    pj_bzero(setting, sizeof(pjmedia_codec_amr_pack_setting));
-    setting->amr_nb = 1;
-    setting->reorder = 0;
-    setting->octet_aligned = octet_align;
-    setting->cmr = 15;
-
-    amr_data->decoder = Decoder_Interface_init();
-    if (amr_data->decoder == NULL) {
-	TRACE_((THIS_FILE, "Decoder_Interface_init() failed"));
-	amr_codec_close(codec);
-	return PJMEDIA_CODEC_EFAILED;
-    }
-    setting = &amr_data->dec_setting;
-    pj_bzero(setting, sizeof(pjmedia_codec_amr_pack_setting));
-    setting->amr_nb = 1;
-    setting->reorder = 0;
-    setting->octet_aligned = octet_align;
-
-    TRACE_((THIS_FILE, "AMR-NB codec allocated: vad=%d, plc=%d, bitrate=%d",
-			amr_data->vad_enabled, amr_data->plc_enabled, 
-			pjmedia_codec_amrnb_bitrates[amr_data->enc_mode]));
-    return PJ_SUCCESS;
-}
-
-
-/*
- * Close codec.
- */
-static pj_status_t amr_codec_close( pjmedia_codec *codec )
-{
-    struct amr_data *amr_data;
-
-    PJ_ASSERT_RETURN(codec, PJ_EINVAL);
-
-    amr_data = (struct amr_data*) codec->codec_data;
-    PJ_ASSERT_RETURN(amr_data != NULL, PJ_EINVALIDOP);
-
-    if (amr_data->encoder) {
-        Encoder_Interface_exit(amr_data->encoder);
-        amr_data->encoder = NULL;
-    }
-
-    if (amr_data->decoder) {
-        Decoder_Interface_exit(amr_data->decoder);
-        amr_data->decoder = NULL;
-    }
-    
-    TRACE_((THIS_FILE, "AMR-NB codec closed"));
-    return PJ_SUCCESS;
-}
-
-
-/*
- * Modify codec settings.
- */
-static pj_status_t amr_codec_modify( pjmedia_codec *codec, 
-				     const pjmedia_codec_param *attr )
-{
-    struct amr_data *amr_data = (struct amr_data*) codec->codec_data;
-    pj_bool_t prev_vad_state;
-
-    pj_assert(amr_data != NULL);
-    pj_assert(amr_data->encoder != NULL && amr_data->decoder != NULL);
-
-    prev_vad_state = amr_data->vad_enabled;
-    amr_data->vad_enabled = (attr->setting.vad != 0);
-    amr_data->plc_enabled = (attr->setting.plc != 0);
-
-    if (prev_vad_state != amr_data->vad_enabled) {
-	/* Reinit AMR encoder to update VAD setting */
-	TRACE_((THIS_FILE, "Reiniting AMR encoder to update VAD setting."));
-        Encoder_Interface_exit(amr_data->encoder);
-        amr_data->encoder = Encoder_Interface_init(amr_data->vad_enabled);
-        if (amr_data->encoder == NULL) {
-	    TRACE_((THIS_FILE, "Encoder_Interface_init() failed"));
-	    amr_codec_close(codec);
-	    return PJMEDIA_CODEC_EFAILED;
-	}
-    }
-
-    TRACE_((THIS_FILE, "AMR-NB codec modified: vad=%d, plc=%d",
-			amr_data->vad_enabled, amr_data->plc_enabled));
-    return PJ_SUCCESS;
-}
-
-
-/*
- * Get frames in the packet.
- */
-static pj_status_t amr_codec_parse( pjmedia_codec *codec,
-				    void *pkt,
-				    pj_size_t pkt_size,
-				    const pj_timestamp *ts,
-				    unsigned *frame_cnt,
-				    pjmedia_frame frames[])
-{
-    struct amr_data *amr_data = (struct amr_data*) codec->codec_data;
-    pj_uint8_t cmr;
-    pj_status_t status;
-
-    status = pjmedia_codec_amr_parse(pkt, pkt_size, ts, &amr_data->dec_setting,
-				     frames, frame_cnt, &cmr);
-    if (status != PJ_SUCCESS)
-	return status;
-
-    /* Check for Change Mode Request. */
-    if (cmr <= 7 && amr_data->enc_mode != cmr) {
-	amr_data->enc_mode = cmr;
-	TRACE_((THIS_FILE, "AMR-NB encoder switched mode to %d (%dbps)",
-			    amr_data->enc_mode, 
-			    pjmedia_codec_amrnb_bitrates[amr_data->enc_mode]));
-    }
-
-    return PJ_SUCCESS;
-}
-
-
-/*
- * Encode frame.
- */
-static pj_status_t amr_codec_encode( pjmedia_codec *codec, 
-				     const struct pjmedia_frame *input,
-				     unsigned output_buf_len, 
-				     struct pjmedia_frame *output)
-{
-    struct amr_data *amr_data = (struct amr_data*) codec->codec_data;
-    unsigned char *bitstream;
-    pj_int16_t *speech;
-    unsigned nsamples, samples_per_frame;
-    enum {MAX_FRAMES_PER_PACKET = 16};
-    pjmedia_frame frames[MAX_FRAMES_PER_PACKET];
-    pj_uint8_t *p;
-    unsigned i, out_size = 0, nframes = 0;
-    pj_size_t payload_len;
-    unsigned dtx_cnt, sid_cnt;
-    pj_status_t status;
-    int size;
-
-    pj_assert(amr_data != NULL);
-    PJ_ASSERT_RETURN(input && output, PJ_EINVAL);
-
-    nsamples = input->size >> 1;
-    samples_per_frame = 160;
-    PJ_ASSERT_RETURN(nsamples % samples_per_frame == 0, 
-		     PJMEDIA_CODEC_EPCMFRMINLEN);
-
-    nframes = nsamples / samples_per_frame;
-    PJ_ASSERT_RETURN(nframes <= MAX_FRAMES_PER_PACKET, 
-		     PJMEDIA_CODEC_EFRMTOOSHORT);
-
-    /* Encode the frames */
-    speech = (pj_int16_t*)input->buf;
-    bitstream = (unsigned char*)output->buf;
-    while (nsamples >= samples_per_frame) {
-        size = Encoder_Interface_Encode (amr_data->encoder, amr_data->enc_mode,
-                                         speech, bitstream, 0);
-	if (size == 0) {
-	    output->size = 0;
-	    output->buf = NULL;
-	    output->type = PJMEDIA_FRAME_TYPE_NONE;
-	    TRACE_((THIS_FILE, "AMR-NB encode() failed"));
-	    return PJMEDIA_CODEC_EFAILED;
-	}
-	nsamples -= 160;
-	speech += samples_per_frame;
-	bitstream += size;
-	out_size += size;
-	TRACE_((THIS_FILE, "AMR-NB encode(): mode=%d, size=%d",
-		amr_data->enc_mode, out_size));
-    }
-
-    /* Pack payload */
-    p = (pj_uint8_t*)output->buf + output_buf_len - out_size;
-    pj_memmove(p, output->buf, out_size);
-    dtx_cnt = sid_cnt = 0;
-    for (i = 0; i < nframes; ++i) {
-	pjmedia_codec_amr_bit_info *info = (pjmedia_codec_amr_bit_info*)
-					   &frames[i].bit_info;
-	info->frame_type = (pj_uint8_t)((*p >> 3) & 0x0F);
-	info->good_quality = (pj_uint8_t)((*p >> 2) & 0x01);
-	info->mode = (pj_int8_t)amr_data->enc_mode;
-	info->start_bit = 0;
-	frames[i].buf = p + 1;
-	frames[i].size = (info->frame_type <= 8)? 
-			 pjmedia_codec_amrnb_framelen[info->frame_type] : 0;
-	p += frames[i].size + 1;
-
-	/* Count the number of SID and DTX frames */
-	if (info->frame_type == 15) /* DTX*/
-	    ++dtx_cnt;
-	else if (info->frame_type == 8) /* SID */
-	    ++sid_cnt;
-    }
-
-    /* VA generates DTX frames as DTX+SID frames switching quickly and it
-     * seems that the SID frames occur too often (assuming the purpose is 
-     * only for keeping NAT alive?). So let's modify the behavior a bit.
-     * Only an SID frame will be sent every PJMEDIA_CODEC_MAX_SILENCE_PERIOD
-     * milliseconds.
-     */
-    if (sid_cnt + dtx_cnt == nframes) {
-	pj_int32_t dtx_duration;
-
-	dtx_duration = pj_timestamp_diff32(&amr_data->last_tx, 
-					   &input->timestamp);
-	if (PJMEDIA_CODEC_MAX_SILENCE_PERIOD == -1 ||
-	    dtx_duration < PJMEDIA_CODEC_MAX_SILENCE_PERIOD*8000/1000) 
-	{
-	    output->size = 0;
-	    output->type = PJMEDIA_FRAME_TYPE_NONE;
-	    output->timestamp = input->timestamp;
-	    return PJ_SUCCESS;
-	}
-    }
-
-    payload_len = output_buf_len;
-
-    status = pjmedia_codec_amr_pack(frames, nframes, &amr_data->enc_setting,
-				    output->buf, &payload_len);
-    if (status != PJ_SUCCESS) {
-	output->size = 0;
-	output->buf = NULL;
-	output->type = PJMEDIA_FRAME_TYPE_NONE;
-	TRACE_((THIS_FILE, "Failed to pack AMR payload, status=%d", status));
-	return status;
-    }
-
-    output->size = payload_len;
-    output->type = PJMEDIA_FRAME_TYPE_AUDIO;
-    output->timestamp = input->timestamp;
-
-    amr_data->last_tx = input->timestamp;
-
-    return PJ_SUCCESS;
-}
-
-
-/*
- * Decode frame.
- */
-static pj_status_t amr_codec_decode( pjmedia_codec *codec, 
-				     const struct pjmedia_frame *input,
-				     unsigned output_buf_len, 
-				     struct pjmedia_frame *output)
-{
-    struct amr_data *amr_data = (struct amr_data*) codec->codec_data;
-    pjmedia_frame input_;
-    pjmedia_codec_amr_bit_info *info;
-    /* VA AMR-NB decoding buffer: AMR-NB max frame size + 1 byte header. */
-    unsigned char bitstream[32];
-
-    pj_assert(amr_data != NULL);
-    PJ_ASSERT_RETURN(input && output, PJ_EINVAL);
-
-    if (output_buf_len < 320)
-	return PJMEDIA_CODEC_EPCMTOOSHORT;
-
-    input_.buf = &bitstream[1];
-    input_.size = 31; /* AMR-NB max frame size */
-    pjmedia_codec_amr_predecode(input, &amr_data->dec_setting, &input_);
-    info = (pjmedia_codec_amr_bit_info*)&input_.bit_info;
-
-    /* VA AMRNB decoder requires frame info in the first byte. */
-    bitstream[0] = (info->frame_type << 3) | (info->good_quality << 2);
-
-    TRACE_((THIS_FILE, "AMR-NB decode(): mode=%d, ft=%d, size=%d",
-	    info->mode, info->frame_type, input_.size));
-
-    /* Decode */
-    Decoder_Interface_Decode(amr_data->decoder, bitstream,
-                             (pj_int16_t*)output->buf, 0);
-
-    output->size = 320;
-    output->type = PJMEDIA_FRAME_TYPE_AUDIO;
-    output->timestamp = input->timestamp;
-
-#if USE_PJMEDIA_PLC
-    if (amr_data->plc_enabled)
-	pjmedia_plc_save(amr_data->plc, (pj_int16_t*)output->buf);
-#endif
-
-    return PJ_SUCCESS;
-}
-
-
-/*
- * Recover lost frame.
- */
-#if USE_PJMEDIA_PLC
-/*
- * Recover lost frame.
- */
-static pj_status_t  amr_codec_recover( pjmedia_codec *codec,
-				       unsigned output_buf_len,
-				       struct pjmedia_frame *output)
-{
-    struct amr_data *amr_data = codec->codec_data;
-
-    TRACE_((THIS_FILE, "amr_codec_recover"));
-
-    PJ_ASSERT_RETURN(amr_data->plc_enabled, PJ_EINVALIDOP);
-
-    PJ_ASSERT_RETURN(output_buf_len >= 320,  PJMEDIA_CODEC_EPCMTOOSHORT);
-
-    pjmedia_plc_generate(amr_data->plc, (pj_int16_t*)output->buf);
-
-    output->size = 320;
-    output->type = PJMEDIA_FRAME_TYPE_AUDIO;
-    
-    return PJ_SUCCESS;
-}
-#endif
-
-#if defined(_MSC_VER) && PJMEDIA_AUTO_LINK_OPENCORE_AMR_LIBS
-#  if PJMEDIA_OPENCORE_AMR_BUILT_WITH_GCC
-#   pragma comment( lib, "libopencore-amrnb.a")
-#  else
-#   error Unsupported OpenCORE AMR library, fix here
-#  endif
-#endif
-
-#endif
Index: pjproject/trunk/pjmedia/src/test/mips_test.c
===================================================================
--- pjproject/trunk/pjmedia/src/test/mips_test.c	(revision 4330)
+++ pjproject/trunk/pjmedia/src/test/mips_test.c	(revision 4331)
@@ -944,4 +944,21 @@
 #endif	/* PJMEDIA_HAS_OPENCORE_AMRNB_CODEC */
 
+#if PJMEDIA_HAS_OPENCORE_AMRWB_CODEC
+/* AMR-WB benchmark benchmark */
+static pjmedia_port* amrwb_encode_decode(pj_pool_t *pool,
+                                         unsigned clock_rate,
+                                         unsigned channel_count,
+                                         unsigned samples_per_frame,
+                                         unsigned flags,
+                                         struct test_entry *te)
+{
+    return codec_encode_decode(pool, "AMR/16000",
+			       &pjmedia_codec_opencore_amrwb_init,
+			       &pjmedia_codec_opencore_amrwb_deinit,
+			       clock_rate, channel_count,
+			       samples_per_frame, flags, te);
+}
+#endif	/* PJMEDIA_HAS_OPENCORE_AMRWB_CODEC */
+
 #if defined(PJMEDIA_HAS_L16_CODEC) && PJMEDIA_HAS_L16_CODEC!=0
 static pj_status_t init_l16_default(pjmedia_endpt *endpt)
@@ -2025,5 +2042,22 @@
 			 samples_per_frame, flags, te);
 }
-#endif	/* PJMEDIA_HAS_OPENCORE_AMRNB_CODEC */ 
+#endif	/* PJMEDIA_HAS_OPENCORE_AMRNB_CODEC */
+
+/* AMR-WB stream */
+#if PJMEDIA_HAS_OPENCORE_AMRWB_CODEC
+static pjmedia_port* create_stream_amrwb( pj_pool_t *pool,
+                                         unsigned clock_rate,
+                                         unsigned channel_count,
+                                         unsigned samples_per_frame,
+                                         unsigned flags,
+                                         struct test_entry *te)
+{
+    return create_stream(pool, "AMR/16000", &pjmedia_codec_opencore_amrwb_init,
+			 &pjmedia_codec_opencore_amrwb_deinit,
+			 PJ_FALSE, PJ_FALSE, PJ_FALSE,
+			 clock_rate, channel_count,
+			 samples_per_frame, flags, te);
+}
+#endif	/* PJMEDIA_HAS_OPENCORE_AMRWB_CODEC */
 
 /***************************************************************************/
@@ -2420,4 +2454,7 @@
 	{ "codec encode/decode - AMR-NB", OP_PUT, K8, &amr_encode_decode},
 #endif
+#if PJMEDIA_HAS_OPENCORE_AMRWB_CODEC
+	{ "codec encode/decode - AMR-WB", OP_PUT, K16, &amrwb_encode_decode},
+#endif
 #if PJMEDIA_HAS_L16_CODEC
 	{ "codec encode/decode - L16/8000/1", OP_PUT, K8, &l16_8_encode_decode},
@@ -2448,4 +2485,7 @@
 	{ "stream TX/RX - AMR-NB", OP_PUT_GET, K8, &create_stream_amr},
 #endif
+#if PJMEDIA_HAS_OPENCORE_AMRWB_CODEC
+	{ "stream TX/RX - AMR-WB", OP_PUT_GET, K16, &create_stream_amrwb},
+#endif
     };
 
