From b75ebdeff0df04c54aad88ff4f016758e6a7972d Mon Sep 17 00:00:00 2001 From: Benny Prijono Date: Thu, 15 Mar 2007 21:56:33 +0000 Subject: Fixed ticket #178: Add flag in SDP negotiator to specify codec order preference (thanks Esbjörn Dominique) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit git-svn-id: http://svn.pjsip.org/repos/pjproject/branches/pjproject-0.5-stable@1071 74dad513-b988-da41-8d7b-12977e46ad98 --- pjmedia/include/pjmedia/config.h | 24 +++++++++++++++++ pjmedia/include/pjmedia/sdp_neg.h | 24 +++++++++++++++++ pjmedia/src/pjmedia/sdp_neg.c | 55 ++++++++++++++++++++++++++++----------- 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 @@ -275,6 +275,30 @@ #endif +/** + * 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 @@ -353,6 +353,30 @@ pjmedia_sdp_neg_create_w_remote_offer(pj_pool_t *pool, const pjmedia_sdp_session *remote, 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. * 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; jdesc.fmt_count; ++j) { + for (j=0; jdesc.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; jdesc.fmt_count; ++j) { - a = pjmedia_sdp_media_find_attr2(local, "rtpmap", - &local->desc.fmt[j]); + for (j=0; jdesc.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; jdesc.fmt_count; ++j) { - if (!pj_strcmp(&offer->desc.fmt[i], &local->desc.fmt[j])) { + for (j=0; jdesc.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; idesc.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; -- cgit v1.2.3