Fixed #1294: New pjmedia_codec_register_audio_codecs() API to register all known codecs, and also added implementation to deregister all codecs when the media endpoint is destroyed

git-svn-id: https://svn.pjsip.org/repos/pjproject/branches/projects/2.0-dev@3661 74dad513-b988-da41-8d7b-12977e46ad98
diff --git a/pjmedia/build/Makefile b/pjmedia/build/Makefile
index 9ec72c7..902a963 100644
--- a/pjmedia/build/Makefile
+++ b/pjmedia/build/Makefile
@@ -109,7 +109,7 @@
 # Defines for building PJMEDIA-Codec library
 #
 export PJMEDIA_CODEC_SRCDIR = ../src/pjmedia-codec
-export PJMEDIA_CODEC_OBJS += ffmpeg_codecs.o \
+export PJMEDIA_CODEC_OBJS += audio_codecs.o ffmpeg_codecs.o \
 			h263_packetizer.o h264_packetizer.o \
 			$(OS_OBJS) $(M_OBJS) $(CC_OBJS) $(HOST_OBJS) \
 			ipp_codecs.o $(CODEC_OBJS)
diff --git a/pjmedia/include/pjmedia-codec.h b/pjmedia/include/pjmedia-codec.h
index 942d529..feea48f 100644
--- a/pjmedia/include/pjmedia-codec.h
+++ b/pjmedia/include/pjmedia-codec.h
@@ -25,6 +25,7 @@
  * @brief Include all codecs API in PJMEDIA-CODEC
  */
 
+#include <pjmedia-codec/audio_codecs.h>
 #include <pjmedia-codec/l16.h>
 #include <pjmedia-codec/ffmpeg_codecs.h>
 #include <pjmedia-codec/gsm.h>
diff --git a/pjmedia/include/pjmedia-codec/audio_codecs.h b/pjmedia/include/pjmedia-codec/audio_codecs.h
new file mode 100644
index 0000000..577075e
--- /dev/null
+++ b/pjmedia/include/pjmedia-codec/audio_codecs.h
@@ -0,0 +1,97 @@
+/* $Id$ */
+/* 
+ * Copyright (C) 2011-2011 Teluu Inc. (http://www.teluu.com)
+ *
+ * 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_ALL_CODECS_H__
+#define __PJMEDIA_CODEC_ALL_CODECS_H__
+
+/**
+ * @file pjmedia-codec/all_codecs.h
+ * @brief Helper function to register all codecs
+ */
+#include <pjmedia/endpoint.h>
+#include <pjmedia-codec/passthrough.h>
+
+
+PJ_BEGIN_DECL
+
+/**
+ * @defgroup PJMEDIA_CODEC_REGISTER_ALL Codec registration helper
+ * @ingroup PJMEDIA_CODEC_CODECS
+ * @brief Helper function to register all codecs
+ * @{
+ *
+ * Helper function to register all codecs that are implemented in
+ * PJMEDIA-CODEC library.
+ */
+
+/**
+ * Codec configuration. Call #pjmedia_audio_codec_config_default() to initialize
+ * this structure with the default values.
+ */
+typedef struct pjmedia_audio_codec_config
+{
+    /** Speex codec settings. See #pjmedia_codec_speex_init() for more info */
+    struct {
+	unsigned	option;		/**< Bitmask of options.	*/
+	unsigned	quality;	/**< Codec quality.		*/
+	unsigned	complexity;	/**< Codec complexity.		*/
+    } speex;
+
+    /** iLBC settings */
+    struct {
+	unsigned	mode;		/**< iLBC mode.			*/
+    } ilbc;
+
+    /** Passthrough */
+    struct {
+	pjmedia_codec_passthrough_setting setting; /**< Passthrough	*/
+    } passthrough;
+
+} pjmedia_audio_codec_config;
+
+
+/**
+ * Initialize pjmedia_audio_codec_config structure with default values.
+ *
+ * @param cfg		The codec config to be initialized.
+ */
+PJ_DECL(void) pjmedia_audio_codec_config_default(pjmedia_audio_codec_config *cfg);
+
+/**
+ * Register all known audio codecs implemented in PJMEDA-CODEC library to the
+ * specified media endpoint.
+ *
+ * @param endpt		The media endpoint.
+ * @param c		Optional codec configuration, or NULL to use default
+ * 			values.
+ *
+ * @return		PJ_SUCCESS on success or the appropriate error code.
+ */
+PJ_DECL(pj_status_t)
+pjmedia_codec_register_audio_codecs(pjmedia_endpt *endpt,
+                                    const pjmedia_audio_codec_config *c);
+
+
+/**
+ * @}  PJMEDIA_CODEC_REGISTER_ALL
+ */
+
+
+PJ_END_DECL
+
+#endif	/* __PJMEDIA_CODEC_ALL_CODECS_H__ */
diff --git a/pjmedia/include/pjmedia/codec.h b/pjmedia/include/pjmedia/codec.h
index f8705a6..5ba385b 100644
--- a/pjmedia/include/pjmedia/codec.h
+++ b/pjmedia/include/pjmedia/codec.h
@@ -552,6 +552,13 @@
     pj_status_t (*dealloc_codec)(pjmedia_codec_factory *factory, 
 				 pjmedia_codec *codec );
 
+    /**
+     * This callback will be called to deinitialize and destroy this factory.
+     *
+     * @param factory	The codec factory.
+     */
+    pj_status_t (*destroy)(void);
+
 } pjmedia_codec_factory_op;
 
 
@@ -723,10 +730,11 @@
 /**
  * Unregister codec factory from the codec manager. This will also
  * remove all the codecs registered by the codec factory from the
- * codec manager's list of supported codecs.
+ * codec manager's list of supported codecs. This function should
+ * only be called by the codec implementers and not by application.
  *
- * @param mgr	    The codec manager instance. Application can get the
- *		    instance by calling #pjmedia_endpt_get_codec_mgr().
+ * @param mgr	    The codec manager instance, use
+ * 			#pjmedia_endpt_get_codec_mgr().
  * @param factory   The codec factory to be unregistered.
  *
  * @return	    PJ_SUCCESS on success.
diff --git a/pjmedia/src/pjmedia-codec/audio_codecs.c b/pjmedia/src/pjmedia-codec/audio_codecs.c
new file mode 100644
index 0000000..a9e0700
--- /dev/null
+++ b/pjmedia/src/pjmedia-codec/audio_codecs.c
@@ -0,0 +1,112 @@
+/* $Id$ */
+/* 
+ * Copyright (C) 2011-2011 Teluu Inc. (http://www.teluu.com)
+ *
+ * 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 
+ */
+#include <pjmedia-codec.h>
+#include <pjmedia/g711.h>
+
+PJ_DEF(void) pjmedia_audio_codec_config_default(pjmedia_audio_codec_config*cfg)
+{
+    pj_bzero(cfg, sizeof(*cfg));
+    cfg->speex.option = 0;
+    cfg->speex.quality = PJMEDIA_CODEC_SPEEX_DEFAULT_QUALITY;
+    cfg->speex.complexity = PJMEDIA_CODEC_SPEEX_DEFAULT_COMPLEXITY;
+    cfg->ilbc.mode = 30;
+    cfg->passthrough.setting.ilbc_mode = cfg->ilbc.mode;
+}
+
+PJ_DEF(pj_status_t)
+pjmedia_codec_register_audio_codecs(pjmedia_endpt *endpt,
+                                    const pjmedia_audio_codec_config *c)
+{
+    pjmedia_audio_codec_config default_cfg;
+    pj_status_t status;
+
+    PJ_ASSERT_RETURN(endpt, PJ_EINVAL);
+    if (!c) {
+	pjmedia_audio_codec_config_default(&default_cfg);
+	c = &default_cfg;
+    }
+
+    PJ_ASSERT_RETURN(c->ilbc.mode==20 || c->ilbc.mode==30, PJ_EINVAL);
+
+#if PJMEDIA_HAS_PASSTHROUGH_CODECS
+    status = pjmedia_codec_passthrough_init2(endpt, &c->passthough.ilbc);
+    if (status != PJ_SUCCESS)
+	return status;
+#endif
+
+#if PJMEDIA_HAS_SPEEX_CODEC
+    /* Register speex. */
+    status = pjmedia_codec_speex_init(endpt, c->speex.option,
+				      c->speex.quality,
+				      c->speex.complexity);
+    if (status != PJ_SUCCESS)
+	return status;
+#endif
+
+#if PJMEDIA_HAS_ILBC_CODEC
+    /* Register iLBC. */
+    status = pjmedia_codec_ilbc_init( endpt, c->ilbc.mode);
+    if (status != PJ_SUCCESS)
+	return status;
+#endif /* PJMEDIA_HAS_ILBC_CODEC */
+
+#if PJMEDIA_HAS_GSM_CODEC
+    /* Register GSM */
+    status = pjmedia_codec_gsm_init(endpt);
+    if (status != PJ_SUCCESS)
+	return status;
+#endif /* PJMEDIA_HAS_GSM_CODEC */
+
+#if PJMEDIA_HAS_G711_CODEC
+    /* Register PCMA and PCMU */
+    status = pjmedia_codec_g711_init(endpt);
+    if (status != PJ_SUCCESS)
+	return status;
+#endif	/* PJMEDIA_HAS_G711_CODEC */
+
+#if PJMEDIA_HAS_G722_CODEC
+    status = pjmedia_codec_g722_init(endpt );
+    if (status != PJ_SUCCESS)
+	return status;
+#endif  /* PJMEDIA_HAS_G722_CODEC */
+
+#if PJMEDIA_HAS_INTEL_IPP
+    /* Register IPP codecs */
+    status = pjmedia_codec_ipp_init(endpt);
+    if (status != PJ_SUCCESS)
+	return status;
+#endif /* PJMEDIA_HAS_INTEL_IPP */
+
+#if PJMEDIA_HAS_G7221_CODEC
+    /* Register G722.1 codecs */
+    status = pjmedia_codec_g7221_init(endpt);
+    if (status != PJ_SUCCESS)
+	return status;
+#endif /* PJMEDIA_HAS_G7221_CODEC */
+
+#if PJMEDIA_HAS_L16_CODEC
+    /* Register L16 family codecs */
+    status = pjmedia_codec_l16_init(endpt, 0);
+    if (status != PJ_SUCCESS)
+	return status;
+#endif	/* PJMEDIA_HAS_L16_CODEC */
+
+    return PJ_SUCCESS;
+}
+
diff --git a/pjmedia/src/pjmedia-codec/g722.c b/pjmedia/src/pjmedia-codec/g722.c
index 5b43a61..6ff31ef 100644
--- a/pjmedia/src/pjmedia-codec/g722.c
+++ b/pjmedia/src/pjmedia-codec/g722.c
@@ -122,7 +122,8 @@
     &g722_default_attr,
     &g722_enum_codecs,
     &g722_alloc_codec,
-    &g722_dealloc_codec
+    &g722_dealloc_codec,
+    &pjmedia_codec_g722_deinit
 };
 
 /* G722 factory */
diff --git a/pjmedia/src/pjmedia-codec/g7221.c b/pjmedia/src/pjmedia-codec/g7221.c
index dc23cbf..549ad39 100644
--- a/pjmedia/src/pjmedia-codec/g7221.c
+++ b/pjmedia/src/pjmedia-codec/g7221.c
@@ -115,7 +115,8 @@
     &default_attr,
     &enum_codecs,
     &alloc_codec,
-    &dealloc_codec
+    &dealloc_codec,
+    &pjmedia_codec_g7221_deinit
 };
 
 
diff --git a/pjmedia/src/pjmedia-codec/gsm.c b/pjmedia/src/pjmedia-codec/gsm.c
index 83593d6..276223c 100644
--- a/pjmedia/src/pjmedia-codec/gsm.c
+++ b/pjmedia/src/pjmedia-codec/gsm.c
@@ -117,7 +117,8 @@
     &gsm_default_attr,
     &gsm_enum_codecs,
     &gsm_alloc_codec,
-    &gsm_dealloc_codec
+    &gsm_dealloc_codec,
+    &pjmedia_codec_gsm_deinit
 };
 
 /* GSM factory */
diff --git a/pjmedia/src/pjmedia-codec/ilbc.c b/pjmedia/src/pjmedia-codec/ilbc.c
index 8bf10fb..1bbbd3f 100644
--- a/pjmedia/src/pjmedia-codec/ilbc.c
+++ b/pjmedia/src/pjmedia-codec/ilbc.c
@@ -113,7 +113,8 @@
     &ilbc_default_attr,
     &ilbc_enum_codecs,
     &ilbc_alloc_codec,
-    &ilbc_dealloc_codec
+    &ilbc_dealloc_codec,
+    &pjmedia_codec_ilbc_deinit
 };
 
 /* iLBC factory */
diff --git a/pjmedia/src/pjmedia-codec/ipp_codecs.c b/pjmedia/src/pjmedia-codec/ipp_codecs.c
index 360d9b1..3761065 100644
--- a/pjmedia/src/pjmedia-codec/ipp_codecs.c
+++ b/pjmedia/src/pjmedia-codec/ipp_codecs.c
@@ -103,7 +103,8 @@
     &ipp_default_attr,
     &ipp_enum_codecs,
     &ipp_alloc_codec,
-    &ipp_dealloc_codec
+    &ipp_dealloc_codec,
+    &pjmedia_codec_ipp_deinit
 };
 
 /* IPP codecs factory */
diff --git a/pjmedia/src/pjmedia-codec/l16.c b/pjmedia/src/pjmedia-codec/l16.c
index 1704d2c..5fe5de0 100644
--- a/pjmedia/src/pjmedia-codec/l16.c
+++ b/pjmedia/src/pjmedia-codec/l16.c
@@ -112,7 +112,8 @@
     &l16_default_attr,
     &l16_enum_codecs,
     &l16_alloc_codec,
-    &l16_dealloc_codec
+    &l16_dealloc_codec,
+    &pjmedia_codec_l16_deinit
 };
 
 /* L16 factory private data */
diff --git a/pjmedia/src/pjmedia-codec/passthrough.c b/pjmedia/src/pjmedia-codec/passthrough.c
index cbaffa9..8926393 100644
--- a/pjmedia/src/pjmedia-codec/passthrough.c
+++ b/pjmedia/src/pjmedia-codec/passthrough.c
@@ -98,7 +98,8 @@
     &default_attr,
     &enum_codecs,
     &alloc_codec,
-    &dealloc_codec
+    &dealloc_codec,
+    &pjmedia_codec_passthrough_deinit
 };
 
 /* Passthrough codecs factory */
diff --git a/pjmedia/src/pjmedia-codec/speex_codec.c b/pjmedia/src/pjmedia-codec/speex_codec.c
index 08c45b2..3f4b3d4 100644
--- a/pjmedia/src/pjmedia-codec/speex_codec.c
+++ b/pjmedia/src/pjmedia-codec/speex_codec.c
@@ -99,7 +99,8 @@
     &spx_default_attr,
     &spx_enum_codecs,
     &spx_alloc_codec,
-    &spx_dealloc_codec
+    &spx_dealloc_codec,
+    &pjmedia_codec_speex_deinit
 };
 
 /* Index to Speex parameter. */
diff --git a/pjmedia/src/pjmedia/codec.c b/pjmedia/src/pjmedia/codec.c
index 323b0f5..d0dc4e1 100644
--- a/pjmedia/src/pjmedia/codec.c
+++ b/pjmedia/src/pjmedia/codec.c
@@ -72,10 +72,19 @@
  */
 PJ_DEF(pj_status_t) pjmedia_codec_mgr_destroy (pjmedia_codec_mgr *mgr)
 {
+    pjmedia_codec_factory *factory;
     unsigned i;
 
     PJ_ASSERT_RETURN(mgr, PJ_EINVAL);
 
+    /* Destroy all factories in the list */
+    factory = mgr->factory_list.next;
+    while (factory != &mgr->factory_list) {
+	pjmedia_codec_factory *next = factory->next;
+	(*factory->op->destroy)();
+	factory = next;
+    }
+
     /* Cleanup all pools of all codec default params */
     for (i=0; i<mgr->codec_cnt; ++i) {
 	if (mgr->codec_desc[i].param) {
@@ -111,6 +120,13 @@
 
     PJ_ASSERT_RETURN(mgr && factory, PJ_EINVAL);
 
+    /* Since 2.0 we require codec factory to implement "destroy" op. Please
+     * see: https://trac.pjsip.org/repos/ticket/1294
+     *
+     * Really! Please do see it.
+     */
+    PJ_ASSERT_RETURN(factory->op->destroy != NULL, PJ_ENOTSUP);
+
     /* Enum codecs */
     count = PJ_ARRAY_SIZE(info);
     status = factory->op->enum_info(factory, &count, info);
diff --git a/pjmedia/src/pjmedia/g711.c b/pjmedia/src/pjmedia/g711.c
index 11e5d41..8059c07 100644
--- a/pjmedia/src/pjmedia/g711.c
+++ b/pjmedia/src/pjmedia/g711.c
@@ -111,7 +111,8 @@
     &g711_default_attr,
     &g711_enum_codecs,
     &g711_alloc_codec,
-    &g711_dealloc_codec
+    &g711_dealloc_codec,
+    &pjmedia_codec_g711_deinit
 };
 
 /* G711 factory private data */
diff --git a/pjsip-apps/src/samples/encdec.c b/pjsip-apps/src/samples/encdec.c
index 119ffab..b059dae 100644
--- a/pjsip-apps/src/samples/encdec.c
+++ b/pjsip-apps/src/samples/encdec.c
@@ -238,21 +238,7 @@
     CHECK( pjmedia_endpt_create(&cp.factory, NULL, 1, &mept) );
 
     /* Register all codecs */
-#if PJMEDIA_HAS_G711_CODEC
-    CHECK( pjmedia_codec_g711_init(mept) );
-#endif
-#if PJMEDIA_HAS_GSM_CODEC
-    CHECK( pjmedia_codec_gsm_init(mept) );
-#endif
-#if PJMEDIA_HAS_ILBC_CODEC
-    CHECK( pjmedia_codec_ilbc_init(mept, 30) );
-#endif
-#if PJMEDIA_HAS_SPEEX_CODEC
-    CHECK( pjmedia_codec_speex_init(mept, 0, 5, 5) );
-#endif
-#if PJMEDIA_HAS_G722_CODEC
-    CHECK( pjmedia_codec_g722_init(mept) );
-#endif
+    CHECK( pjmedia_codec_register_audio_codecs(mept, NULL) );
 
     pj_gettimeofday(&t0);
     status = enc_dec_test(argv[1], argv[2], argv[3]);
diff --git a/pjsip-apps/src/samples/jbsim.c b/pjsip-apps/src/samples/jbsim.c
index 9ab6ce5..34fa75f 100644
--- a/pjsip-apps/src/samples/jbsim.c
+++ b/pjsip-apps/src/samples/jbsim.c
@@ -472,31 +472,7 @@
     }
 
     /* Register codecs */
-#if defined(PJMEDIA_HAS_GSM_CODEC) && PJMEDIA_HAS_GSM_CODEC != 0
-    pjmedia_codec_gsm_init(g_app.endpt);
-#endif
-#if defined(PJMEDIA_HAS_G711_CODEC) && PJMEDIA_HAS_G711_CODEC!=0
-    pjmedia_codec_g711_init(g_app.endpt);
-#endif
-#if defined(PJMEDIA_HAS_SPEEX_CODEC) && PJMEDIA_HAS_SPEEX_CODEC!=0
-    pjmedia_codec_speex_init(g_app.endpt, 0, PJMEDIA_CODEC_SPEEX_DEFAULT_QUALITY,
-			     PJMEDIA_CODEC_SPEEX_DEFAULT_COMPLEXITY);
-#endif
-#if defined(PJMEDIA_HAS_G722_CODEC) && (PJMEDIA_HAS_G722_CODEC != 0)
-    pjmedia_codec_g722_init(g_app.endpt);
-#endif
-#if defined(PJMEDIA_HAS_ILBC_CODEC) && PJMEDIA_HAS_ILBC_CODEC != 0
-    /* Init ILBC with mode=20 to make the losts occur at the same
-     * places as other codecs.
-     */
-    pjmedia_codec_ilbc_init(g_app.endpt, 20);
-#endif
-#if defined(PJMEDIA_HAS_INTEL_IPP) && PJMEDIA_HAS_INTEL_IPP != 0
-    pjmedia_codec_ipp_init(g_app.endpt);
-#endif
-#if defined(PJMEDIA_HAS_L16_CODEC) && PJMEDIA_HAS_L16_CODEC != 0
-    pjmedia_codec_l16_init(g_app.endpt, 0);
-#endif
+    pjmedia_codec_register_audio_codecs(g_app.endpt, NULL);
 
     /* Create the loop transport */
     status = pjmedia_transport_loop_create(g_app.endpt, &g_app.loop);
diff --git a/pjsip-apps/src/samples/pcaputil.c b/pjsip-apps/src/samples/pcaputil.c
index 6d1dde6..3139746 100644
--- a/pjsip-apps/src/samples/pcaputil.c
+++ b/pjsip-apps/src/samples/pcaputil.c
@@ -228,29 +228,7 @@
     pj_status_t status;
 
     /* Initialize all codecs */
-#if PJMEDIA_HAS_SPEEX_CODEC
-    T( pjmedia_codec_speex_init(app.mept, 0, 10, 10) );
-#endif /* PJMEDIA_HAS_SPEEX_CODEC */
-
-#if PJMEDIA_HAS_ILBC_CODEC
-    T( pjmedia_codec_ilbc_init(app.mept, 30) );
-#endif /* PJMEDIA_HAS_ILBC_CODEC */
-
-#if PJMEDIA_HAS_GSM_CODEC
-    T( pjmedia_codec_gsm_init(app.mept) );
-#endif /* PJMEDIA_HAS_GSM_CODEC */
-
-#if PJMEDIA_HAS_G711_CODEC
-    T( pjmedia_codec_g711_init(app.mept) );
-#endif	/* PJMEDIA_HAS_G711_CODEC */
-
-#if PJMEDIA_HAS_G722_CODEC
-    T( pjmedia_codec_g722_init(app.mept) );
-#endif	/* PJMEDIA_HAS_G722_CODEC */
-
-#if PJMEDIA_HAS_L16_CODEC
-    T( pjmedia_codec_l16_init(app.mept, 0) );
-#endif	/* PJMEDIA_HAS_L16_CODEC */
+    T( pjmedia_codec_register_audio_codecs(app.mept, NULL) );
 
     /* Create SRTP transport is needed */
 #if PJMEDIA_HAS_SRTP
diff --git a/pjsip-apps/src/samples/pjsip-perf.c b/pjsip-apps/src/samples/pjsip-perf.c
index ac8a552..f01d9ac 100644
--- a/pjsip-apps/src/samples/pjsip-perf.c
+++ b/pjsip-apps/src/samples/pjsip-perf.c
@@ -928,18 +928,7 @@
 
 
     /* Must register all codecs to be supported */
-#if defined(PJMEDIA_HAS_G711_CODEC) && PJMEDIA_HAS_G711_CODEC!=0
-    pjmedia_codec_g711_init(app.med_endpt);
-#endif
-#if defined(PJMEDIA_HAS_GSM_CODEC) && PJMEDIA_HAS_GSM_CODEC!=0
-    pjmedia_codec_gsm_init(app.med_endpt);
-#endif
-#if defined(PJMEDIA_HAS_SPEEX_CODEC) && PJMEDIA_HAS_SPEEX_CODEC!=0
-    pjmedia_codec_speex_init(app.med_endpt, PJMEDIA_SPEEX_NO_UWB, 3, 3);
-#endif
-#if defined(PJMEDIA_HAS_G722_CODEC) && PJMEDIA_HAS_G722_CODEC!=0
-    pjmedia_codec_g722_init(app.med_endpt);
-#endif
+    pjmedia_codec_register_audio_codecs(app.med_endpt, NULL);
 
     /* Init dummy socket addresses */
     app.skinfo_cnt = 0;
diff --git a/pjsip-apps/src/samples/streamutil.c b/pjsip-apps/src/samples/streamutil.c
index 7d990d7..53b32a1 100644
--- a/pjsip-apps/src/samples/streamutil.c
+++ b/pjsip-apps/src/samples/streamutil.c
@@ -100,37 +100,7 @@
  */
 static pj_status_t init_codecs(pjmedia_endpt *med_endpt)
 {
-    pj_status_t status;
-
-    /* To suppress warning about unused var when all codecs are disabled */
-    PJ_UNUSED_ARG(status);
-
-#if defined(PJMEDIA_HAS_G711_CODEC) && PJMEDIA_HAS_G711_CODEC!=0
-    status = pjmedia_codec_g711_init(med_endpt);
-    PJ_ASSERT_RETURN(status == PJ_SUCCESS, status);
-#endif
-
-#if defined(PJMEDIA_HAS_GSM_CODEC) && PJMEDIA_HAS_GSM_CODEC!=0
-    status = pjmedia_codec_gsm_init(med_endpt);
-    PJ_ASSERT_RETURN(status == PJ_SUCCESS, status);
-#endif
-
-#if defined(PJMEDIA_HAS_SPEEX_CODEC) && PJMEDIA_HAS_SPEEX_CODEC!=0
-    status = pjmedia_codec_speex_init(med_endpt, 0, -1, -1);
-    PJ_ASSERT_RETURN(status == PJ_SUCCESS, status);
-#endif
-
-#if defined(PJMEDIA_HAS_G722_CODEC) && PJMEDIA_HAS_G722_CODEC!=0
-    status = pjmedia_codec_g722_init(med_endpt);
-    PJ_ASSERT_RETURN(status == PJ_SUCCESS, status);
-#endif
-
-#if defined(PJMEDIA_HAS_L16_CODEC) && PJMEDIA_HAS_L16_CODEC!=0
-    status = pjmedia_codec_l16_init(med_endpt, 0);
-    PJ_ASSERT_RETURN(status == PJ_SUCCESS, status);
-#endif
-
-    return PJ_SUCCESS;
+    return pjmedia_codec_register_audio_codecs(med_endpt, NULL);
 }
 
 
diff --git a/pjsip/src/pjsua-lib/pjsua_media.c b/pjsip/src/pjsua-lib/pjsua_media.c
index 2413681..fcf15e0 100644
--- a/pjsip/src/pjsua-lib/pjsua_media.c
+++ b/pjsip/src/pjsua-lib/pjsua_media.c
@@ -66,6 +66,7 @@
 {
     pj_str_t codec_id = {NULL, 0};
     unsigned opt;
+    pjmedia_audio_codec_config codec_cfg;
     pj_status_t status;
 
     /* To suppress warning about unused var when all codecs are disabled */
@@ -112,86 +113,13 @@
 	return status;
     }
 
-    /* Register all codecs */
-
-#if PJMEDIA_HAS_SPEEX_CODEC
-    /* Register speex. */
-    status = pjmedia_codec_speex_init(pjsua_var.med_endpt,  
-				      0, 
-				      pjsua_var.media_cfg.quality,  
-				      -1);
-    if (status != PJ_SUCCESS) {
-	pjsua_perror(THIS_FILE, "Error initializing Speex codec",
-		     status);
-	return status;
-    }
-
-    /* Set speex/16000 to higher priority*/
-    codec_id = pj_str("speex/16000");
-    pjmedia_codec_mgr_set_codec_priority( 
-	pjmedia_endpt_get_codec_mgr(pjsua_var.med_endpt),
-	&codec_id, PJMEDIA_CODEC_PRIO_NORMAL+2);
-
-    /* Set speex/8000 to next higher priority*/
-    codec_id = pj_str("speex/8000");
-    pjmedia_codec_mgr_set_codec_priority( 
-	pjmedia_endpt_get_codec_mgr(pjsua_var.med_endpt),
-	&codec_id, PJMEDIA_CODEC_PRIO_NORMAL+1);
-
-
-
-#endif /* PJMEDIA_HAS_SPEEX_CODEC */
-
-#if PJMEDIA_HAS_ILBC_CODEC
-    /* Register iLBC. */
-    status = pjmedia_codec_ilbc_init( pjsua_var.med_endpt, 
-				      pjsua_var.media_cfg.ilbc_mode);
-    if (status != PJ_SUCCESS) {
-	pjsua_perror(THIS_FILE, "Error initializing iLBC codec",
-		     status);
-	return status;
-    }
-#endif /* PJMEDIA_HAS_ILBC_CODEC */
-
-#if PJMEDIA_HAS_GSM_CODEC
-    /* Register GSM */
-    status = pjmedia_codec_gsm_init(pjsua_var.med_endpt);
-    if (status != PJ_SUCCESS) {
-	pjsua_perror(THIS_FILE, "Error initializing GSM codec",
-		     status);
-	return status;
-    }
-#endif /* PJMEDIA_HAS_GSM_CODEC */
-
-#if PJMEDIA_HAS_G711_CODEC
-    /* Register PCMA and PCMU */
-    status = pjmedia_codec_g711_init(pjsua_var.med_endpt);
-    if (status != PJ_SUCCESS) {
-	pjsua_perror(THIS_FILE, "Error initializing G711 codec",
-		     status);
-	return status;
-    }
-#endif	/* PJMEDIA_HAS_G711_CODEC */
-
-#if PJMEDIA_HAS_G722_CODEC
-    status = pjmedia_codec_g722_init( pjsua_var.med_endpt );
-    if (status != PJ_SUCCESS) {
-	pjsua_perror(THIS_FILE, "Error initializing G722 codec",
-		     status);
-	return status;
-    }
-#endif  /* PJMEDIA_HAS_G722_CODEC */
-
-#if PJMEDIA_HAS_INTEL_IPP
-    /* Register IPP codecs */
-    status = pjmedia_codec_ipp_init(pjsua_var.med_endpt);
-    if (status != PJ_SUCCESS) {
-	pjsua_perror(THIS_FILE, "Error initializing IPP codecs",
-		     status);
-	return status;
-    }
-
-#endif /* PJMEDIA_HAS_INTEL_IPP */
+    /*
+     * Register all codecs
+     */
+    pjmedia_audio_codec_config_default(&codec_cfg);
+    codec_cfg.speex.quality = pjsua_var.media_cfg.quality;
+    codec_cfg.speex.complexity = -1;
+    codec_cfg.ilbc.mode = pjsua_var.media_cfg.ilbc_mode;
 
 #if PJMEDIA_HAS_PASSTHROUGH_CODECS
     /* Register passthrough codecs */
@@ -199,7 +127,6 @@
 	unsigned aud_idx;
 	unsigned ext_fmt_cnt = 0;
 	pjmedia_format ext_fmts[32];
-	pjmedia_codec_passthrough_setting setting;
 
 	/* List extended formats supported by audio devices */
 	for (aud_idx = 0; aud_idx < pjmedia_aud_dev_count(); ++aud_idx) {
@@ -236,36 +163,31 @@
 	}
 
 	/* Init the passthrough codec with supported formats only */
-	setting.fmt_cnt = ext_fmt_cnt;
-	setting.fmts = ext_fmts;
-	setting.ilbc_mode = cfg->ilbc_mode;
-	status = pjmedia_codec_passthrough_init2(pjsua_var.med_endpt, &setting);
-	if (status != PJ_SUCCESS) {
-	    pjsua_perror(THIS_FILE, "Error initializing passthrough codecs",
-			 status);
-	    return status;
-	}
+	codec_cfg.passthrough.setting.fmt_cnt = ext_fmt_cnt;
+	codec_cfg.passthrough.setting.fmts = ext_fmts;
+	codec_cfg.passthrough.setting.ilbc_mode = cfg->ilbc_mode;
     }
 #endif /* PJMEDIA_HAS_PASSTHROUGH_CODECS */
 
-#if PJMEDIA_HAS_G7221_CODEC
-    /* Register G722.1 codecs */
-    status = pjmedia_codec_g7221_init(pjsua_var.med_endpt);
+    /* Register all codecs */
+    status = pjmedia_codec_register_audio_codecs(pjsua_var.med_endpt,
+                                                 &codec_cfg);
     if (status != PJ_SUCCESS) {
-	pjsua_perror(THIS_FILE, "Error initializing G722.1 codec",
-		     status);
+	PJ_PERROR(1,(THIS_FILE, status, "Error registering codecs"));
 	return status;
     }
-#endif /* PJMEDIA_HAS_G7221_CODEC */
 
-#if PJMEDIA_HAS_L16_CODEC
-    /* Register L16 family codecs, but disable all */
-    status = pjmedia_codec_l16_init(pjsua_var.med_endpt, 0);
-    if (status != PJ_SUCCESS) {
-	pjsua_perror(THIS_FILE, "Error initializing L16 codecs",
-		     status);
-	return status;
-    }
+    /* Set speex/16000 to higher priority*/
+    codec_id = pj_str("speex/16000");
+    pjmedia_codec_mgr_set_codec_priority(
+	pjmedia_endpt_get_codec_mgr(pjsua_var.med_endpt),
+	&codec_id, PJMEDIA_CODEC_PRIO_NORMAL+2);
+
+    /* Set speex/8000 to next higher priority*/
+    codec_id = pj_str("speex/8000");
+    pjmedia_codec_mgr_set_codec_priority(
+	pjmedia_endpt_get_codec_mgr(pjsua_var.med_endpt),
+	&codec_id, PJMEDIA_CODEC_PRIO_NORMAL+1);
 
     /* Disable ALL L16 codecs */
     codec_id = pj_str("L16");
@@ -273,8 +195,6 @@
 	pjmedia_endpt_get_codec_mgr(pjsua_var.med_endpt),
 	&codec_id, PJMEDIA_CODEC_PRIO_DISABLED);
 
-#endif	/* PJMEDIA_HAS_L16_CODEC */
-
 
     /* Save additional conference bridge parameters for future
      * reference.
@@ -518,38 +438,6 @@
 #	if PJMEDIA_HAS_VIDEO
 	    pjsua_vid_subsys_destroy();
 #	endif
-	/* Shutdown all codecs: */
-#	if PJMEDIA_HAS_SPEEX_CODEC
-	    pjmedia_codec_speex_deinit();
-#	endif /* PJMEDIA_HAS_SPEEX_CODEC */
-
-#	if PJMEDIA_HAS_GSM_CODEC
-	    pjmedia_codec_gsm_deinit();
-#	endif /* PJMEDIA_HAS_GSM_CODEC */
-
-#	if PJMEDIA_HAS_G711_CODEC
-	    pjmedia_codec_g711_deinit();
-#	endif	/* PJMEDIA_HAS_G711_CODEC */
-
-#	if PJMEDIA_HAS_G722_CODEC
-	    pjmedia_codec_g722_deinit();
-#	endif	/* PJMEDIA_HAS_G722_CODEC */
-
-#	if PJMEDIA_HAS_INTEL_IPP
-	    pjmedia_codec_ipp_deinit();
-#	endif	/* PJMEDIA_HAS_INTEL_IPP */
-
-#	if PJMEDIA_HAS_PASSTHROUGH_CODECS
-	    pjmedia_codec_passthrough_deinit();
-#	endif /* PJMEDIA_HAS_PASSTHROUGH_CODECS */
-
-#	if PJMEDIA_HAS_G7221_CODEC
-	    pjmedia_codec_g7221_deinit();
-#	endif /* PJMEDIA_HAS_G7221_CODEC */
-
-#	if PJMEDIA_HAS_L16_CODEC
-	    pjmedia_codec_l16_deinit();
-#	endif	/* PJMEDIA_HAS_L16_CODEC */
 
 	pjmedia_endpt_destroy(pjsua_var.med_endpt);
 	pjsua_var.med_endpt = NULL;