Fixed ticket #183: Add flag in SDP negotiator to specify codec order preference (thanks Esbjorn Dominique)
git-svn-id: https://svn.pjsip.org/repos/pjproject/trunk@1072 74dad513-b988-da41-8d7b-12977e46ad98
This commit is contained in:
parent
9de76b7020
commit
a38e78df75
|
@ -279,6 +279,30 @@
|
||||||
#endif
|
#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).
|
* Support for sending and decoding RTCP port in SDP (RFC 3605).
|
||||||
* Default is yes.
|
* Default is yes.
|
||||||
|
|
|
@ -353,6 +353,30 @@ pjmedia_sdp_neg_create_w_remote_offer(pj_pool_t *pool,
|
||||||
const pjmedia_sdp_session *remote,
|
const pjmedia_sdp_session *remote,
|
||||||
pjmedia_sdp_neg **p_neg);
|
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.
|
* Get SDP negotiator state.
|
||||||
*
|
*
|
||||||
|
|
|
@ -31,6 +31,7 @@
|
||||||
struct pjmedia_sdp_neg
|
struct pjmedia_sdp_neg
|
||||||
{
|
{
|
||||||
pjmedia_sdp_neg_state state; /**< Negotiator state. */
|
pjmedia_sdp_neg_state state; /**< Negotiator state. */
|
||||||
|
pj_bool_t prefer_remote_codec_order;
|
||||||
pj_bool_t has_remote_answer;
|
pj_bool_t has_remote_answer;
|
||||||
pj_bool_t answer_was_remote;
|
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);
|
PJ_ASSERT_RETURN(neg != NULL, PJ_ENOMEM);
|
||||||
|
|
||||||
neg->state = PJMEDIA_SDP_NEG_STATE_LOCAL_OFFER;
|
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->initial_sdp = pjmedia_sdp_session_clone(pool, local);
|
||||||
neg->neg_local_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));
|
neg = pj_pool_zalloc(pool, sizeof(pjmedia_sdp_neg));
|
||||||
PJ_ASSERT_RETURN(neg != NULL, PJ_ENOMEM);
|
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);
|
neg->neg_remote_sdp = pjmedia_sdp_session_clone(pool, remote);
|
||||||
|
|
||||||
if (initial) {
|
if (initial) {
|
||||||
|
@ -140,6 +143,20 @@ pjmedia_sdp_neg_create_w_remote_offer(pj_pool_t *pool,
|
||||||
return PJ_SUCCESS;
|
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.
|
* Get SDP negotiator state.
|
||||||
*/
|
*/
|
||||||
|
@ -667,7 +684,8 @@ static pj_status_t process_answer(pj_pool_t *pool,
|
||||||
/* Try to match offer with answer. */
|
/* Try to match offer with answer. */
|
||||||
static pj_status_t match_offer(pj_pool_t *pool,
|
static pj_status_t match_offer(pj_pool_t *pool,
|
||||||
const pjmedia_sdp_media *offer,
|
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)
|
pjmedia_sdp_media **p_answer)
|
||||||
{
|
{
|
||||||
unsigned i;
|
unsigned i;
|
||||||
|
@ -710,12 +728,12 @@ static pj_status_t match_offer(pj_pool_t *pool,
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
/* Find matching codec in local descriptor. */
|
/* 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;
|
unsigned p;
|
||||||
p = pj_strtoul(&local->desc.fmt[j]);
|
p = pj_strtoul(&preanswer->desc.fmt[j]);
|
||||||
if (p == pt && pj_isdigit(*local->desc.fmt[j].ptr)) {
|
if (p == pt && pj_isdigit(*preanswer->desc.fmt[j].ptr)) {
|
||||||
found_matching_codec = 1;
|
found_matching_codec = 1;
|
||||||
pt_answer[pt_answer_count++] = local->desc.fmt[j];
|
pt_answer[pt_answer_count++] = preanswer->desc.fmt[j];
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -753,9 +771,9 @@ static pj_status_t match_offer(pj_pool_t *pool,
|
||||||
/* Find paylaod in our initial SDP with matching
|
/* Find paylaod in our initial SDP with matching
|
||||||
* encoding name and clock rate.
|
* encoding name and clock rate.
|
||||||
*/
|
*/
|
||||||
for (j=0; j<local->desc.fmt_count; ++j) {
|
for (j=0; j<preanswer->desc.fmt_count; ++j) {
|
||||||
a = pjmedia_sdp_media_find_attr2(local, "rtpmap",
|
a = pjmedia_sdp_media_find_attr2(preanswer, "rtpmap",
|
||||||
&local->desc.fmt[j]);
|
&preanswer->desc.fmt[j]);
|
||||||
if (a) {
|
if (a) {
|
||||||
pjmedia_sdp_rtpmap lr;
|
pjmedia_sdp_rtpmap lr;
|
||||||
pjmedia_sdp_attr_get_rtpmap(a, &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;
|
found_matching_codec = 1;
|
||||||
else
|
else
|
||||||
found_matching_telephone_event = 1;
|
found_matching_telephone_event = 1;
|
||||||
pt_answer[pt_answer_count++] = local->desc.fmt[j];
|
pt_answer[pt_answer_count++] = preanswer->desc.fmt[j];
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -791,11 +809,11 @@ static pj_status_t match_offer(pj_pool_t *pool,
|
||||||
if (found_matching_other)
|
if (found_matching_other)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
for (j=0; j<local->desc.fmt_count; ++j) {
|
for (j=0; j<preanswer->desc.fmt_count; ++j) {
|
||||||
if (!pj_strcmp(&offer->desc.fmt[i], &local->desc.fmt[j])) {
|
if (!pj_strcmp(&offer->desc.fmt[i], &preanswer->desc.fmt[j])) {
|
||||||
/* Match */
|
/* Match */
|
||||||
found_matching_other = 1;
|
found_matching_other = 1;
|
||||||
pt_answer[pt_answer_count++] = local->desc.fmt[j];
|
pt_answer[pt_answer_count++] = preanswer->desc.fmt[j];
|
||||||
break;
|
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
|
* Build the answer by cloning from local media, but rearrange the payload
|
||||||
* to suit the offer.
|
* 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) {
|
for (i=0; i<pt_answer_count; ++i) {
|
||||||
unsigned j;
|
unsigned j;
|
||||||
for (j=i; j<answer->desc.fmt_count; ++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. */
|
/* Create complete answer for remote's offer. */
|
||||||
static pj_status_t create_answer( pj_pool_t *pool,
|
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 *initial,
|
||||||
const pjmedia_sdp_session *offer,
|
const pjmedia_sdp_session *offer,
|
||||||
pjmedia_sdp_session **p_answer)
|
pjmedia_sdp_session **p_answer)
|
||||||
|
@ -914,7 +933,12 @@ static pj_status_t create_answer( pj_pool_t *pool,
|
||||||
media_used[j] == 0)
|
media_used[j] == 0)
|
||||||
{
|
{
|
||||||
/* See if it has matching codec. */
|
/* 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) {
|
if (status == PJ_SUCCESS) {
|
||||||
/* Mark media as used. */
|
/* Mark media as used. */
|
||||||
media_used[j] = 1;
|
media_used[j] = 1;
|
||||||
|
@ -991,7 +1015,8 @@ PJ_DEF(pj_status_t) pjmedia_sdp_neg_negotiate( pj_pool_t *pool,
|
||||||
} else {
|
} else {
|
||||||
pjmedia_sdp_session *answer = NULL;
|
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);
|
&answer);
|
||||||
if (status == PJ_SUCCESS) {
|
if (status == PJ_SUCCESS) {
|
||||||
pj_uint32_t active_ver;
|
pj_uint32_t active_ver;
|
||||||
|
|
Loading…
Reference in New Issue