summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNanang Izzuddin <nanang@teluu.com>2010-01-26 15:29:23 +0000
committerNanang Izzuddin <nanang@teluu.com>2010-01-26 15:29:23 +0000
commit5900f75534e21f750e370ec230aec3d6cd58b850 (patch)
tree7fc83b5af3a016da146bcd3a468c1b02cbcb6522
parent3b0e3817784670d13b0f0a62e28047e56c81042b (diff)
Ticket #1028:
- Added new API pjmedia_codec_mgr_set_default_param() to set/update default codec parameter and implemented pjsua_codec_set_param() based on it. - Added mutex in codec manager to protect states manipulations. - Modified API pjmedia_codec_mgr_init() to add pool factory param. - Added new API pjmedia_codec_mgr_destroy(). - Updated passthrough codec AMR to regard peer's mode-set setting. - Fixed VAS audio device to apply AMR encoding bitrate setting. - Fixed IPP codec codec_open() to update AMR bitrate info (for stream) when AMR encoding bitrate is not using the default, e.g: requested by peer via format param 'mode-set' in SDP. git-svn-id: http://svn.pjsip.org/repos/pjproject/trunk@3074 74dad513-b988-da41-8d7b-12977e46ad98
-rw-r--r--pjmedia/src/pjmedia-audiodev/symb_vas_dev.cpp4
-rw-r--r--pjmedia/src/pjmedia-codec/ipp_codecs.c3
-rw-r--r--pjmedia/src/pjmedia-codec/passthrough.c61
-rw-r--r--pjmedia/src/pjmedia/codec.c216
-rw-r--r--pjmedia/src/pjmedia/endpoint.c3
-rw-r--r--pjsip/include/pjsua-lib/pjsua.h3
-rw-r--r--pjsip/src/pjsua-lib/pjsua_media.c29
7 files changed, 300 insertions, 19 deletions
diff --git a/pjmedia/src/pjmedia-audiodev/symb_vas_dev.cpp b/pjmedia/src/pjmedia-audiodev/symb_vas_dev.cpp
index 776fdbf8..ae9b43c6 100644
--- a/pjmedia/src/pjmedia-audiodev/symb_vas_dev.cpp
+++ b/pjmedia/src/pjmedia-audiodev/symb_vas_dev.cpp
@@ -491,6 +491,10 @@ TInt CPjAudioEngine::StartRec()
}
break;
+ case EAMR_NB:
+ enc_fmt_if->SetBitRate(setting_.mode);
+ break;
+
default:
break;
}
diff --git a/pjmedia/src/pjmedia-codec/ipp_codecs.c b/pjmedia/src/pjmedia-codec/ipp_codecs.c
index aaf1142f..a8b73180 100644
--- a/pjmedia/src/pjmedia-codec/ipp_codecs.c
+++ b/pjmedia/src/pjmedia-codec/ipp_codecs.c
@@ -1195,6 +1195,9 @@ static pj_status_t ipp_codec_open( pjmedia_codec *codec,
(s->enc_setting.amr_nb?"":"-WB"),
s->enc_mode,
codec_data->info->params.modes.bitrate));
+
+ /* Return back bitrate info to application */
+ attr->info.avg_bps = codec_data->info->params.modes.bitrate;
}
#endif
diff --git a/pjmedia/src/pjmedia-codec/passthrough.c b/pjmedia/src/pjmedia-codec/passthrough.c
index 06e4de69..f6a6e119 100644
--- a/pjmedia/src/pjmedia-codec/passthrough.c
+++ b/pjmedia/src/pjmedia-codec/passthrough.c
@@ -24,6 +24,7 @@
#include <pjmedia/port.h>
#include <pj/assert.h>
#include <pj/log.h>
+#include <pj/math.h>
#include <pj/pool.h>
#include <pj/string.h>
#include <pj/os.h>
@@ -680,13 +681,18 @@ static pj_status_t codec_open( pjmedia_codec *codec,
if (desc->pt == PJMEDIA_RTP_PT_AMR || desc->pt == PJMEDIA_RTP_PT_AMRWB) {
amr_settings_t *s;
pj_uint8_t octet_align = 0;
- const pj_str_t STR_FMTP_OCTET_ALIGN = {"octet-align", 11};
+ pj_int8_t enc_mode;
+
+ enc_mode = pjmedia_codec_amr_get_mode(attr->info.avg_bps);
+ pj_assert(enc_mode >= 0 && enc_mode <= 8);
/* Fetch octet-align setting. It should be fine to fetch only
* the decoder, since encoder & decoder must use the same setting
* (RFC 4867 section 8.3.1).
*/
for (i = 0; i < attr->setting.dec_fmtp.cnt; ++i) {
+ const pj_str_t STR_FMTP_OCTET_ALIGN = {"octet-align", 11};
+
if (pj_stricmp(&attr->setting.dec_fmtp.param[i].name,
&STR_FMTP_OCTET_ALIGN) == 0)
{
@@ -696,10 +702,56 @@ static pj_status_t codec_open( pjmedia_codec *codec,
}
}
+ for (i = 0; i < attr->setting.enc_fmtp.cnt; ++i) {
+ /* mode-set, 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.
+ */
+ 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;
+
+ p = pj_strbuf(&attr->setting.enc_fmtp.param[i].val);
+ l = pj_strlen(&attr->setting.enc_fmtp.param[i].val);
+
+ while (l--) {
+ if ((desc->pt==PJMEDIA_RTP_PT_AMR && *p>='0' && *p<='7') ||
+ (desc->pt==PJMEDIA_RTP_PT_AMRWB && *p>='0' && *p<='8'))
+ {
+ pj_int8_t tmp = (pj_int8_t)(*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;
+ }
+
+ if (diff == 99)
+ return PJMEDIA_CODEC_EFAILED;
+
+ enc_mode = (pj_int8_t)(enc_mode + diff);
+
+ break;
+ }
+ }
+
s = PJ_POOL_ZALLOC_T(pool, amr_settings_t);
codec_data->codec_setting = s;
- s->enc_mode = pjmedia_codec_amr_get_mode(desc->def_bitrate);
+ s->enc_mode = enc_mode;
if (s->enc_mode < 0)
return PJMEDIA_CODEC_EINMODE;
@@ -715,6 +767,11 @@ static pj_status_t codec_open( pjmedia_codec *codec,
s->dec_setting.reorder = PJ_FALSE; /* Note this! passthrough codec
doesn't do sensitivity bits
reordering */
+
+ /* Return back bitrate info to application */
+ attr->info.avg_bps = s->enc_setting.amr_nb?
+ pjmedia_codec_amrnb_bitrates[s->enc_mode]:
+ pjmedia_codec_amrwb_bitrates[s->enc_mode];
}
#endif
diff --git a/pjmedia/src/pjmedia/codec.c b/pjmedia/src/pjmedia/codec.c
index 708f06e8..d65ede4e 100644
--- a/pjmedia/src/pjmedia/codec.c
+++ b/pjmedia/src/pjmedia/codec.c
@@ -22,13 +22,19 @@
#include <pj/array.h>
#include <pj/assert.h>
#include <pj/log.h>
-#include <pj/pool.h>
#include <pj/string.h>
#define THIS_FILE "codec.c"
+/* Definition of default codecs parameters */
+struct pjmedia_codec_default_param
+{
+ pj_pool_t *pool;
+ pjmedia_codec_param *param;
+};
+
/* Sort codecs in codec manager based on priorities */
static void sort_codecs(pjmedia_codec_mgr *mgr);
@@ -37,13 +43,56 @@ static void sort_codecs(pjmedia_codec_mgr *mgr);
/*
* Initialize codec manager.
*/
-PJ_DEF(pj_status_t) pjmedia_codec_mgr_init (pjmedia_codec_mgr *mgr)
+PJ_DEF(pj_status_t) pjmedia_codec_mgr_init (pjmedia_codec_mgr *mgr,
+ pj_pool_factory *pf)
{
- PJ_ASSERT_RETURN(mgr, PJ_EINVAL);
+ pj_status_t status;
+
+ PJ_ASSERT_RETURN(mgr && pf, PJ_EINVAL);
+ /* Init codec manager */
+ pj_bzero(mgr, sizeof(pjmedia_codec_mgr));
+ mgr->pf = pf;
pj_list_init (&mgr->factory_list);
mgr->codec_cnt = 0;
+ /* Create pool */
+ mgr->pool = pj_pool_create(mgr->pf, "codec-mgr", 256, 256, NULL);
+
+ /* Create mutex */
+ status = pj_mutex_create_recursive(mgr->pool, "codec-mgr", &mgr->mutex);
+ if (status != PJ_SUCCESS)
+ return status;
+
+ return PJ_SUCCESS;
+}
+
+/*
+ * Initialize codec manager.
+ */
+PJ_DEF(pj_status_t) pjmedia_codec_mgr_destroy (pjmedia_codec_mgr *mgr)
+{
+ unsigned i;
+
+ PJ_ASSERT_RETURN(mgr, PJ_EINVAL);
+
+ /* Cleanup all pools of all codec default params */
+ for (i=0; i<mgr->codec_cnt; ++i) {
+ if (mgr->codec_desc[i].param) {
+ pj_assert(mgr->codec_desc[i].param->pool);
+ pj_pool_release(mgr->codec_desc[i].param->pool);
+ }
+ }
+
+ /* Destroy mutex */
+ pj_mutex_destroy(mgr->mutex);
+
+ /* Release pool */
+ pj_pool_release(mgr->pool);
+
+ /* Just for safety, set codec manager states to zero */
+ pj_bzero(mgr, sizeof(pjmedia_codec_mgr));
+
return PJ_SUCCESS;
}
@@ -65,11 +114,14 @@ PJ_DEF(pj_status_t) pjmedia_codec_mgr_register_factory( pjmedia_codec_mgr *mgr,
status = factory->op->enum_info(factory, &count, info);
if (status != PJ_SUCCESS)
return status;
-
+
+ pj_mutex_lock(mgr->mutex);
/* Check codec count */
- if (count + mgr->codec_cnt > PJ_ARRAY_SIZE(mgr->codec_desc))
+ if (count + mgr->codec_cnt > PJ_ARRAY_SIZE(mgr->codec_desc)) {
+ pj_mutex_unlock(mgr->mutex);
return PJ_ETOOMANY;
+ }
/* Save the codecs */
@@ -92,6 +144,7 @@ PJ_DEF(pj_status_t) pjmedia_codec_mgr_register_factory( pjmedia_codec_mgr *mgr,
/* Add factory to the list */
pj_list_push_back(&mgr->factory_list, factory);
+ pj_mutex_unlock(mgr->mutex);
return PJ_SUCCESS;
}
@@ -107,9 +160,13 @@ PJ_DEF(pj_status_t) pjmedia_codec_mgr_unregister_factory(
unsigned i;
PJ_ASSERT_RETURN(mgr && factory, PJ_EINVAL);
+ pj_mutex_lock(mgr->mutex);
+
/* Factory must be registered. */
- PJ_ASSERT_RETURN(pj_list_find_node(&mgr->factory_list, factory)==factory,
- PJ_ENOTFOUND);
+ if (pj_list_find_node(&mgr->factory_list, factory) != factory) {
+ pj_mutex_unlock(mgr->mutex);
+ return PJ_ENOTFOUND;
+ }
/* Erase factory from the factory list */
pj_list_erase(factory);
@@ -121,7 +178,13 @@ PJ_DEF(pj_status_t) pjmedia_codec_mgr_unregister_factory(
for (i=0; i<mgr->codec_cnt; ) {
if (mgr->codec_desc[i].factory == factory) {
+ /* Release pool of codec default param */
+ if (mgr->codec_desc[i].param) {
+ pj_assert(mgr->codec_desc[i].param->pool);
+ pj_pool_release(mgr->codec_desc[i].param->pool);
+ }
+ /* Remove the codec from array of codec descriptions */
pj_array_erase(mgr->codec_desc, sizeof(mgr->codec_desc[0]),
mgr->codec_cnt, i);
--mgr->codec_cnt;
@@ -131,6 +194,7 @@ PJ_DEF(pj_status_t) pjmedia_codec_mgr_unregister_factory(
}
}
+ pj_mutex_unlock(mgr->mutex);
return PJ_SUCCESS;
}
@@ -148,6 +212,8 @@ PJ_DEF(pj_status_t) pjmedia_codec_mgr_enum_codecs(pjmedia_codec_mgr *mgr,
PJ_ASSERT_RETURN(mgr && count && codecs, PJ_EINVAL);
+ pj_mutex_lock(mgr->mutex);
+
if (*count > mgr->codec_cnt)
*count = mgr->codec_cnt;
@@ -162,6 +228,8 @@ PJ_DEF(pj_status_t) pjmedia_codec_mgr_enum_codecs(pjmedia_codec_mgr *mgr,
prio[i] = mgr->codec_desc[i].prio;
}
+ pj_mutex_unlock(mgr->mutex);
+
return PJ_SUCCESS;
}
@@ -177,13 +245,19 @@ PJ_DEF(pj_status_t) pjmedia_codec_mgr_get_codec_info( pjmedia_codec_mgr *mgr,
PJ_ASSERT_RETURN(mgr && p_info && pt>=0 && pt < 96, PJ_EINVAL);
+ pj_mutex_lock(mgr->mutex);
+
for (i=0; i<mgr->codec_cnt; ++i) {
if (mgr->codec_desc[i].info.pt == pt) {
*p_info = &mgr->codec_desc[i].info;
+
+ pj_mutex_unlock(mgr->mutex);
return PJ_SUCCESS;
}
}
+ pj_mutex_unlock(mgr->mutex);
+
return PJMEDIA_CODEC_EUNSUP;
}
@@ -230,6 +304,8 @@ PJ_DEF(pj_status_t) pjmedia_codec_mgr_find_codecs_by_id( pjmedia_codec_mgr *mgr,
PJ_ASSERT_RETURN(mgr && codec_id && count && *count, PJ_EINVAL);
+ pj_mutex_lock(mgr->mutex);
+
for (i=0; i<mgr->codec_cnt; ++i) {
if (codec_id->slen == 0 ||
@@ -250,6 +326,8 @@ PJ_DEF(pj_status_t) pjmedia_codec_mgr_find_codecs_by_id( pjmedia_codec_mgr *mgr,
}
+ pj_mutex_unlock(mgr->mutex);
+
*count = found;
return found ? PJ_SUCCESS : PJ_ENOTFOUND;
@@ -313,6 +391,8 @@ PJ_DEF(pj_status_t) pjmedia_codec_mgr_set_codec_priority(
PJ_ASSERT_RETURN(mgr && codec_id, PJ_EINVAL);
+ pj_mutex_lock(mgr->mutex);
+
/* Update the priorities of affected codecs */
for (i=0; i<mgr->codec_cnt; ++i)
{
@@ -325,12 +405,15 @@ PJ_DEF(pj_status_t) pjmedia_codec_mgr_set_codec_priority(
}
}
- if (!found)
+ if (!found) {
+ pj_mutex_unlock(mgr->mutex);
return PJ_ENOTFOUND;
+ }
/* Re-sort codecs */
sort_codecs(mgr);
-
+
+ pj_mutex_unlock(mgr->mutex);
return PJ_SUCCESS;
}
@@ -350,20 +433,25 @@ PJ_DEF(pj_status_t) pjmedia_codec_mgr_alloc_codec(pjmedia_codec_mgr *mgr,
*p_codec = NULL;
+ pj_mutex_lock(mgr->mutex);
+
factory = mgr->factory_list.next;
while (factory != &mgr->factory_list) {
if ( (*factory->op->test_alloc)(factory, info) == PJ_SUCCESS ) {
status = (*factory->op->alloc_codec)(factory, info, p_codec);
- if (status == PJ_SUCCESS)
+ if (status == PJ_SUCCESS) {
+ pj_mutex_unlock(mgr->mutex);
return PJ_SUCCESS;
+ }
}
factory = factory->next;
}
+ pj_mutex_unlock(mgr->mutex);
return PJMEDIA_CODEC_EUNSUP;
}
@@ -378,9 +466,36 @@ PJ_DEF(pj_status_t) pjmedia_codec_mgr_get_default_param( pjmedia_codec_mgr *mgr,
{
pjmedia_codec_factory *factory;
pj_status_t status;
+ pjmedia_codec_id codec_id;
+ struct pjmedia_codec_desc *codec_desc = NULL;
+ unsigned i;
PJ_ASSERT_RETURN(mgr && info && param, PJ_EINVAL);
+ if (!pjmedia_codec_info_to_id(info, (char*)&codec_id, sizeof(codec_id)))
+ return PJ_EINVAL;
+
+ pj_mutex_lock(mgr->mutex);
+
+ /* First, lookup default param in codec desc */
+ for (i=0; i < mgr->codec_cnt; ++i) {
+ if (pj_ansi_stricmp(codec_id, mgr->codec_desc[i].id) == 0) {
+ codec_desc = &mgr->codec_desc[i];
+ break;
+ }
+ }
+
+ /* If we found the codec and its default param is set, return it */
+ if (codec_desc && codec_desc->param) {
+ pj_assert(codec_desc->param->param);
+ pj_memcpy(param, codec_desc->param->param,
+ sizeof(pjmedia_codec_param));
+
+ pj_mutex_unlock(mgr->mutex);
+ return PJ_SUCCESS;
+ }
+
+ /* Otherwise query the default param from codec factory */
factory = mgr->factory_list.next;
while (factory != &mgr->factory_list) {
@@ -392,6 +507,7 @@ PJ_DEF(pj_status_t) pjmedia_codec_mgr_get_default_param( pjmedia_codec_mgr *mgr,
if (param->info.max_bps < param->info.avg_bps)
param->info.max_bps = param->info.avg_bps;
+ pj_mutex_unlock(mgr->mutex);
return PJ_SUCCESS;
}
@@ -400,12 +516,92 @@ PJ_DEF(pj_status_t) pjmedia_codec_mgr_get_default_param( pjmedia_codec_mgr *mgr,
factory = factory->next;
}
+ pj_mutex_unlock(mgr->mutex);
+
return PJMEDIA_CODEC_EUNSUP;
}
/*
+ * Set default codec parameter.
+ */
+PJ_DEF(pj_status_t) pjmedia_codec_mgr_set_default_param(
+ pjmedia_codec_mgr *mgr,
+ const pjmedia_codec_info *info,
+ const pjmedia_codec_param *param )
+{
+ unsigned i;
+ pjmedia_codec_id codec_id;
+ pj_pool_t *pool;
+ struct pjmedia_codec_desc *codec_desc = NULL;
+ pjmedia_codec_default_param *p;
+
+ PJ_ASSERT_RETURN(mgr && info, PJ_EINVAL);
+
+ if (!pjmedia_codec_info_to_id(info, (char*)&codec_id, sizeof(codec_id)))
+ return PJ_EINVAL;
+
+ pj_mutex_lock(mgr->mutex);
+
+ /* Lookup codec desc */
+ for (i=0; i < mgr->codec_cnt; ++i) {
+ if (pj_ansi_stricmp(codec_id, mgr->codec_desc[i].id) == 0) {
+ codec_desc = &mgr->codec_desc[i];
+ break;
+ }
+ }
+
+ /* Codec not found */
+ if (!codec_desc) {
+ pj_mutex_unlock(mgr->mutex);
+ return PJMEDIA_CODEC_EUNSUP;
+ }
+
+ /* If codec param is previously set, release codec param pool */
+ if (codec_desc->param) {
+ pj_assert(codec_desc->param->pool);
+ pj_pool_release(codec_desc->param->pool);
+ codec_desc->param = NULL;
+ }
+
+ /* When param is set to NULL, i.e: setting default codec param to library
+ * default setting, just return PJ_SUCCESS.
+ */
+ if (NULL == param) {
+ pj_mutex_unlock(mgr->mutex);
+ return PJ_SUCCESS;
+ }
+
+ /* Instantiate and initialize codec param */
+ pool = pj_pool_create(mgr->pf, (char*)codec_id, 256, 256, NULL);
+ codec_desc->param = PJ_POOL_ZALLOC_T(pool, pjmedia_codec_default_param);
+ p = codec_desc->param;
+ p->pool = pool;
+ p->param = PJ_POOL_ZALLOC_T(pool, pjmedia_codec_param);
+
+ /* Update codec param */
+ pj_memcpy(p->param, param, sizeof(pjmedia_codec_param));
+ for (i = 0; i < param->setting.dec_fmtp.cnt; ++i) {
+ pj_strdup(pool, &p->param->setting.dec_fmtp.param[i].name,
+ &param->setting.dec_fmtp.param[i].name);
+ pj_strdup(pool, &p->param->setting.dec_fmtp.param[i].val,
+ &param->setting.dec_fmtp.param[i].val);
+ }
+ for (i = 0; i < param->setting.dec_fmtp.cnt; ++i) {
+ pj_strdup(pool, &p->param->setting.dec_fmtp.param[i].name,
+ &param->setting.dec_fmtp.param[i].name);
+ pj_strdup(pool, &p->param->setting.dec_fmtp.param[i].val,
+ &param->setting.dec_fmtp.param[i].val);
+ }
+
+ pj_mutex_unlock(mgr->mutex);
+
+ return PJ_SUCCESS;
+}
+
+
+/*
* Dealloc codec.
*/
PJ_DEF(pj_status_t) pjmedia_codec_mgr_dealloc_codec(pjmedia_codec_mgr *mgr,
diff --git a/pjmedia/src/pjmedia/endpoint.c b/pjmedia/src/pjmedia/endpoint.c
index a3e988d5..8840589d 100644
--- a/pjmedia/src/pjmedia/endpoint.c
+++ b/pjmedia/src/pjmedia/endpoint.c
@@ -127,7 +127,7 @@ PJ_DEF(pj_status_t) pjmedia_endpt_create(pj_pool_factory *pf,
goto on_error;
/* Init codec manager. */
- status = pjmedia_codec_mgr_init(&endpt->codec_mgr);
+ status = pjmedia_codec_mgr_init(&endpt->codec_mgr, endpt->pf);
if (status != PJ_SUCCESS)
goto on_error;
@@ -172,6 +172,7 @@ on_error:
if (endpt->ioqueue && endpt->own_ioqueue)
pj_ioqueue_destroy(endpt->ioqueue);
+ pjmedia_codec_mgr_destroy(&endpt->codec_mgr);
pjmedia_aud_subsys_shutdown();
pj_pool_release(pool);
return status;
diff --git a/pjsip/include/pjsua-lib/pjsua.h b/pjsip/include/pjsua-lib/pjsua.h
index 44ce9f0f..ecafb25d 100644
--- a/pjsip/include/pjsua-lib/pjsua.h
+++ b/pjsip/include/pjsua-lib/pjsua.h
@@ -4483,7 +4483,8 @@ PJ_DECL(pj_status_t) pjsua_codec_get_param( const pj_str_t *codec_id,
* Set codec parameters.
*
* @param codec_id Codec ID.
- * @param param Codec parameter to set.
+ * @param param Codec parameter to set. Set to NULL to reset
+ * codec parameter to library default settings.
*
* @return PJ_SUCCESS on success, or the appropriate error code.
*/
diff --git a/pjsip/src/pjsua-lib/pjsua_media.c b/pjsip/src/pjsua-lib/pjsua_media.c
index 3a6bb04f..234833b6 100644
--- a/pjsip/src/pjsua-lib/pjsua_media.c
+++ b/pjsip/src/pjsua-lib/pjsua_media.c
@@ -3054,11 +3054,30 @@ PJ_DEF(pj_status_t) pjsua_codec_get_param( const pj_str_t *codec_id,
/*
* Set codec parameters.
*/
-PJ_DEF(pj_status_t) pjsua_codec_set_param( const pj_str_t *id,
+PJ_DEF(pj_status_t) pjsua_codec_set_param( const pj_str_t *codec_id,
const pjmedia_codec_param *param)
{
- PJ_UNUSED_ARG(id);
- PJ_UNUSED_ARG(param);
- PJ_TODO(set_codec_param);
- return PJ_SUCCESS;
+ const pjmedia_codec_info *info[2];
+ pjmedia_codec_mgr *codec_mgr;
+ unsigned count = 2;
+ pj_status_t status;
+
+ codec_mgr = pjmedia_endpt_get_codec_mgr(pjsua_var.med_endpt);
+
+ status = pjmedia_codec_mgr_find_codecs_by_id(codec_mgr, codec_id,
+ &count, info, NULL);
+ if (status != PJ_SUCCESS)
+ return status;
+
+ /* Codec ID should be specific, except for G.722.1 */
+ if (count > 1 &&
+ pj_strnicmp2(codec_id, "G7221/16", 8) != 0 &&
+ pj_strnicmp2(codec_id, "G7221/32", 8) != 0)
+ {
+ pj_assert(!"Codec ID is not specific");
+ return PJ_ETOOMANY;
+ }
+
+ status = pjmedia_codec_mgr_set_default_param(codec_mgr, info[0], param);
+ return status;
}