summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBenny Prijono <bennylp@teluu.com>2007-03-15 21:56:33 +0000
committerBenny Prijono <bennylp@teluu.com>2007-03-15 21:56:33 +0000
commitb75ebdeff0df04c54aad88ff4f016758e6a7972d (patch)
treea36a7a62ecf71fc572ec7f0201a63704cbe483a1
parentb7476fba0e67d9fc9de79dfbf277879813f8f1b0 (diff)
Fixed ticket #178: Add flag in SDP negotiator to specify codec order preference (thanks Esbjörn Dominique)
git-svn-id: http://svn.pjsip.org/repos/pjproject/branches/pjproject-0.5-stable@1071 74dad513-b988-da41-8d7b-12977e46ad98
-rw-r--r--pjmedia/include/pjmedia/config.h24
-rw-r--r--pjmedia/include/pjmedia/sdp_neg.h24
-rw-r--r--pjmedia/src/pjmedia/sdp_neg.c55
3 files changed, 88 insertions, 15 deletions
diff --git a/pjmedia/include/pjmedia/config.h b/pjmedia/include/pjmedia/config.h
index 0e79848f..ab8e45c4 100644
--- a/pjmedia/include/pjmedia/config.h
+++ b/pjmedia/include/pjmedia/config.h
@@ -276,6 +276,30 @@
/**
+ * This specifies the behavior of the SDP negotiator when responding to an
+ * offer, whether it should rather use the codec preference as set by
+ * remote, or should it rather use the codec preference as specified by
+ * local endpoint.
+ *
+ * For example, suppose incoming call has codec order "8 0 3", while
+ * local codec order is "3 0 8". If remote codec order is preferable,
+ * the selected codec will be 8, while if local codec order is preferable,
+ * the selected codec will be 3.
+ *
+ * If set to non-zero, the negotiator will use the codec order as specified
+ * by remote in the offer.
+ *
+ * Note that this behavior can be changed during run-time by calling
+ * pjmedia_sdp_neg_set_prefer_remote_codec_order().
+ *
+ * Default is 1 (to maintain backward compatibility)
+ */
+#ifndef PJMEDIA_SDP_NEG_PREFER_REMOTE_CODEC_ORDER
+# define PJMEDIA_SDP_NEG_PREFER_REMOTE_CODEC_ORDER 1
+#endif
+
+
+/**
* Support for sending and decoding RTCP port in SDP (RFC 3605).
* Default is yes.
*/
diff --git a/pjmedia/include/pjmedia/sdp_neg.h b/pjmedia/include/pjmedia/sdp_neg.h
index e3bce9cd..3f8481da 100644
--- a/pjmedia/include/pjmedia/sdp_neg.h
+++ b/pjmedia/include/pjmedia/sdp_neg.h
@@ -354,6 +354,30 @@ pjmedia_sdp_neg_create_w_remote_offer(pj_pool_t *pool,
pjmedia_sdp_neg **p_neg);
/**
+ * This specifies the behavior of the SDP negotiator when responding to an
+ * offer, whether it should rather use the codec preference as set by
+ * remote, or should it rather use the codec preference as specified by
+ * local endpoint.
+ *
+ * For example, suppose incoming call has codec order "8 0 3", while
+ * local codec order is "3 0 8". If remote codec order is preferable,
+ * the selected codec will be 8, while if local codec order is preferable,
+ * the selected codec will be 3.
+ *
+ * By default, the value in PJMEDIA_SDP_NEG_PREFER_REMOTE_CODEC_ORDER will
+ * be used.
+ *
+ * @param neg The SDP negotiator instance.
+ * @param prefer_remote If non-zero, the negotiator will use the codec
+ * order as specified in remote offer. If zero, it
+ * will prefer to use the local codec order.
+ */
+PJ_DECL(pj_status_t)
+pjmedia_sdp_neg_set_prefer_remote_codec_order(pjmedia_sdp_neg *neg,
+ pj_bool_t prefer_remote);
+
+
+/**
* Get SDP negotiator state.
*
* @param neg The SDP negotiator instance.
diff --git a/pjmedia/src/pjmedia/sdp_neg.c b/pjmedia/src/pjmedia/sdp_neg.c
index 40918f7c..612941b1 100644
--- a/pjmedia/src/pjmedia/sdp_neg.c
+++ b/pjmedia/src/pjmedia/sdp_neg.c
@@ -31,6 +31,7 @@
struct pjmedia_sdp_neg
{
pjmedia_sdp_neg_state state; /**< Negotiator state. */
+ pj_bool_t prefer_remote_codec_order;
pj_bool_t has_remote_answer;
pj_bool_t answer_was_remote;
@@ -86,6 +87,7 @@ pjmedia_sdp_neg_create_w_local_offer( pj_pool_t *pool,
PJ_ASSERT_RETURN(neg != NULL, PJ_ENOMEM);
neg->state = PJMEDIA_SDP_NEG_STATE_LOCAL_OFFER;
+ neg->prefer_remote_codec_order = PJMEDIA_SDP_NEG_PREFER_REMOTE_CODEC_ORDER;
neg->initial_sdp = pjmedia_sdp_session_clone(pool, local);
neg->neg_local_sdp = pjmedia_sdp_session_clone(pool, local);
@@ -119,6 +121,7 @@ pjmedia_sdp_neg_create_w_remote_offer(pj_pool_t *pool,
neg = pj_pool_zalloc(pool, sizeof(pjmedia_sdp_neg));
PJ_ASSERT_RETURN(neg != NULL, PJ_ENOMEM);
+ neg->prefer_remote_codec_order = PJMEDIA_SDP_NEG_PREFER_REMOTE_CODEC_ORDER;
neg->neg_remote_sdp = pjmedia_sdp_session_clone(pool, remote);
if (initial) {
@@ -140,6 +143,20 @@ pjmedia_sdp_neg_create_w_remote_offer(pj_pool_t *pool,
return PJ_SUCCESS;
}
+
+/*
+ * Set codec order preference.
+ */
+PJ_DEF(pj_status_t)
+pjmedia_sdp_neg_set_prefer_remote_codec_order(pjmedia_sdp_neg *neg,
+ pj_bool_t prefer_remote)
+{
+ PJ_ASSERT_RETURN(neg, PJ_EINVAL);
+ neg->prefer_remote_codec_order = prefer_remote;
+ return PJ_SUCCESS;
+}
+
+
/*
* Get SDP negotiator state.
*/
@@ -667,7 +684,8 @@ static pj_status_t process_answer(pj_pool_t *pool,
/* Try to match offer with answer. */
static pj_status_t match_offer(pj_pool_t *pool,
const pjmedia_sdp_media *offer,
- const pjmedia_sdp_media *local,
+ const pjmedia_sdp_media *preanswer,
+ const pjmedia_sdp_media *orig_local,
pjmedia_sdp_media **p_answer)
{
unsigned i;
@@ -710,12 +728,12 @@ static pj_status_t match_offer(pj_pool_t *pool,
continue;
/* Find matching codec in local descriptor. */
- for (j=0; j<local->desc.fmt_count; ++j) {
+ for (j=0; j<preanswer->desc.fmt_count; ++j) {
unsigned p;
- p = pj_strtoul(&local->desc.fmt[j]);
- if (p == pt && pj_isdigit(*local->desc.fmt[j].ptr)) {
+ p = pj_strtoul(&preanswer->desc.fmt[j]);
+ if (p == pt && pj_isdigit(*preanswer->desc.fmt[j].ptr)) {
found_matching_codec = 1;
- pt_answer[pt_answer_count++] = local->desc.fmt[j];
+ pt_answer[pt_answer_count++] = preanswer->desc.fmt[j];
break;
}
}
@@ -753,9 +771,9 @@ static pj_status_t match_offer(pj_pool_t *pool,
/* Find paylaod in our initial SDP with matching
* encoding name and clock rate.
*/
- for (j=0; j<local->desc.fmt_count; ++j) {
- a = pjmedia_sdp_media_find_attr2(local, "rtpmap",
- &local->desc.fmt[j]);
+ for (j=0; j<preanswer->desc.fmt_count; ++j) {
+ a = pjmedia_sdp_media_find_attr2(preanswer, "rtpmap",
+ &preanswer->desc.fmt[j]);
if (a) {
pjmedia_sdp_rtpmap lr;
pjmedia_sdp_attr_get_rtpmap(a, &lr);
@@ -773,7 +791,7 @@ static pj_status_t match_offer(pj_pool_t *pool,
found_matching_codec = 1;
else
found_matching_telephone_event = 1;
- pt_answer[pt_answer_count++] = local->desc.fmt[j];
+ pt_answer[pt_answer_count++] = preanswer->desc.fmt[j];
break;
}
}
@@ -791,11 +809,11 @@ static pj_status_t match_offer(pj_pool_t *pool,
if (found_matching_other)
continue;
- for (j=0; j<local->desc.fmt_count; ++j) {
- if (!pj_strcmp(&offer->desc.fmt[i], &local->desc.fmt[j])) {
+ for (j=0; j<preanswer->desc.fmt_count; ++j) {
+ if (!pj_strcmp(&offer->desc.fmt[i], &preanswer->desc.fmt[j])) {
/* Match */
found_matching_other = 1;
- pt_answer[pt_answer_count++] = local->desc.fmt[j];
+ pt_answer[pt_answer_count++] = preanswer->desc.fmt[j];
break;
}
}
@@ -823,7 +841,7 @@ static pj_status_t match_offer(pj_pool_t *pool,
* Build the answer by cloning from local media, but rearrange the payload
* to suit the offer.
*/
- answer = pjmedia_sdp_media_clone(pool, local);
+ answer = pjmedia_sdp_media_clone(pool, orig_local);
for (i=0; i<pt_answer_count; ++i) {
unsigned j;
for (j=i; j<answer->desc.fmt_count; ++j) {
@@ -867,6 +885,7 @@ static pj_status_t match_offer(pj_pool_t *pool,
/* Create complete answer for remote's offer. */
static pj_status_t create_answer( pj_pool_t *pool,
+ pj_bool_t prefer_remote_codec_order,
const pjmedia_sdp_session *initial,
const pjmedia_sdp_session *offer,
pjmedia_sdp_session **p_answer)
@@ -914,7 +933,12 @@ static pj_status_t create_answer( pj_pool_t *pool,
media_used[j] == 0)
{
/* See if it has matching codec. */
- status = match_offer(pool, om, im, &am);
+ if (prefer_remote_codec_order) {
+ status = match_offer(pool, om, im, im, &am);
+ } else {
+ status = match_offer(pool, im, om, im, &am);
+ }
+
if (status == PJ_SUCCESS) {
/* Mark media as used. */
media_used[j] = 1;
@@ -991,7 +1015,8 @@ PJ_DEF(pj_status_t) pjmedia_sdp_neg_negotiate( pj_pool_t *pool,
} else {
pjmedia_sdp_session *answer = NULL;
- status = create_answer(pool, neg->neg_local_sdp, neg->neg_remote_sdp,
+ status = create_answer(pool, neg->prefer_remote_codec_order,
+ neg->neg_local_sdp, neg->neg_remote_sdp,
&answer);
if (status == PJ_SUCCESS) {
pj_uint32_t active_ver;