summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNanang Izzuddin <nanang@teluu.com>2010-01-27 11:48:31 +0000
committerNanang Izzuddin <nanang@teluu.com>2010-01-27 11:48:31 +0000
commitb4363f43a76411dcdbe60917d6ffe2d168cec3a2 (patch)
tree40bf7ba236ca1456a5d47360b711936d87d44011
parent67983fb24f15e72df308c0e52f7055f38c09615c (diff)
Ticket #1028: Recommit r3074 with updated codec.h.
git-svn-id: http://svn.pjsip.org/repos/pjproject/trunk@3078 74dad513-b988-da41-8d7b-12977e46ad98
-rw-r--r--pjmedia/include/pjmedia/codec.h79
-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.c49
-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
8 files changed, 356 insertions, 30 deletions
diff --git a/pjmedia/include/pjmedia/codec.h b/pjmedia/include/pjmedia/codec.h
index f0dd77a6..67df9f58 100644
--- a/pjmedia/include/pjmedia/codec.h
+++ b/pjmedia/include/pjmedia/codec.h
@@ -28,6 +28,7 @@
#include <pjmedia/port.h>
#include <pj/list.h>
+#include <pj/pool.h>
PJ_BEGIN_DECL
@@ -244,20 +245,26 @@ typedef struct pjmedia_codec_info
/**
* Structure of codec specific parameters which contains name=value pairs.
* The codec specific parameters are to be used with SDP according to
- * the standards (e.g: RFC 3555).
+ * the standards (e.g: RFC 3555) in SDP 'a=fmtp' attribute.
*/
typedef struct pjmedia_codec_fmtp
{
- pj_uint8_t cnt;
+ pj_uint8_t cnt; /**< Number of parameters. */
struct param {
- pj_str_t name;
- pj_str_t val;
- } param [PJMEDIA_CODEC_MAX_FMTP_CNT];
+ pj_str_t name; /**< Parameter name. */
+ pj_str_t val; /**< Parameter value. */
+ } param [PJMEDIA_CODEC_MAX_FMTP_CNT]; /**< The parameters. */
} pjmedia_codec_fmtp;
/**
- * Detailed codec attributes used both to configure a codec and to query
- * the capability of codec factories.
+ * Detailed codec attributes used in configuring a codec and in querying
+ * the capability of codec factories. Default attributes of any codecs could
+ * be queried using #pjmedia_codec_mgr_get_default_param() and modified
+ * using #pjmedia_codec_mgr_set_default_param().
+ *
+ * Please note that codec parameter also contains SDP specific setting,
+ * #dec_fmtp and #enc_fmtp, which may need to be set appropriately based on
+ * the effective setting. See each codec documentation for more detail.
*/
typedef struct pjmedia_codec_param
{
@@ -628,6 +635,11 @@ typedef enum pjmedia_codec_priority
typedef char pjmedia_codec_id[32];
+/**
+ * Opaque declaration of default codecs parameters.
+ */
+typedef struct pjmedia_codec_default_param pjmedia_codec_default_param;
+
/**
* Codec manager maintains array of these structs for each supported
* codec.
@@ -638,6 +650,8 @@ struct pjmedia_codec_desc
pjmedia_codec_id id; /**< Fully qualified name */
pjmedia_codec_priority prio; /**< Priority. */
pjmedia_codec_factory *factory; /**< The factory. */
+ pjmedia_codec_default_param *param; /**< Default codecs
+ parameters. */
};
@@ -648,14 +662,23 @@ struct pjmedia_codec_desc
*/
typedef struct pjmedia_codec_mgr
{
+ /** Media endpoint instance. */
+ pj_pool_factory *pf;
+
+ /** Codec manager pool. */
+ pj_pool_t *pool;
+
+ /** Codec manager mutex. */
+ pj_mutex_t *mutex;
+
/** List of codec factories registered to codec manager. */
- pjmedia_codec_factory factory_list;
+ pjmedia_codec_factory factory_list;
- /** Number of supported codesc. */
- unsigned codec_cnt;
+ /** Number of supported codecs. */
+ unsigned codec_cnt;
/** Array of codec descriptor. */
- struct pjmedia_codec_desc codec_desc[PJMEDIA_CODEC_MGR_MAX_CODECS];
+ struct pjmedia_codec_desc codec_desc[PJMEDIA_CODEC_MGR_MAX_CODECS];
} pjmedia_codec_mgr;
@@ -666,10 +689,23 @@ typedef struct pjmedia_codec_mgr
* endpoint's initialization code.
*
* @param mgr Codec manager instance.
+ * @param pf Pool factory instance.
+ *
+ * @return PJ_SUCCESS on success.
+ */
+PJ_DECL(pj_status_t) pjmedia_codec_mgr_init(pjmedia_codec_mgr *mgr,
+ pj_pool_factory *pf);
+
+
+/**
+ * Destroy codec manager. Normally this function is called by pjmedia
+ * endpoint's deinitialization code.
+ *
+ * @param mgr Codec manager instance.
*
* @return PJ_SUCCESS on success.
*/
-PJ_DECL(pj_status_t) pjmedia_codec_mgr_init(pjmedia_codec_mgr *mgr);
+PJ_DECL(pj_status_t) pjmedia_codec_mgr_destroy(pjmedia_codec_mgr *mgr);
/**
@@ -821,6 +857,25 @@ pjmedia_codec_mgr_get_default_param( pjmedia_codec_mgr *mgr,
const pjmedia_codec_info *info,
pjmedia_codec_param *param );
+
+/**
+ * Set default codec param for the specified codec info.
+ *
+ * @param mgr The codec manager instance. Application can get the
+ * instance by calling #pjmedia_endpt_get_codec_mgr().
+ * @param info The codec info, which default parameter's is being
+ * updated.
+ * @param param The new default codec parameter. Set to NULL to reset
+ * codec parameter to library default settings.
+ *
+ * @return PJ_SUCCESS on success.
+ */
+PJ_DECL(pj_status_t)
+pjmedia_codec_mgr_set_default_param( pjmedia_codec_mgr *mgr,
+ const pjmedia_codec_info *info,
+ const pjmedia_codec_param *param );
+
+
/**
* Request the codec manager to allocate one instance of codec with the
* specified codec info. The codec will enumerate all codec factories
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..bcd8f81a 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>
@@ -696,10 +697,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;
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;
}