diff options
author | Nanang Izzuddin <nanang@teluu.com> | 2011-12-01 09:06:14 +0000 |
---|---|---|
committer | Nanang Izzuddin <nanang@teluu.com> | 2011-12-01 09:06:14 +0000 |
commit | fb7ffe37b9ca728f0d3f6bf57b937e114d2f9161 (patch) | |
tree | bf3d2bd71b21ee29d72fd4bb99af186d8b18f064 /pjsip/src/pjsua-lib/pjsua_media.c | |
parent | 9ad8beaa148c78e04a2aac3c5ad6d85567d31b01 (diff) |
Re #1419, implement media count manipulation per call basis:
- moved the media count setting from account setting to call setting
- introduced pjsua_call_setting, to be used by pjsua_call_make_call() and some new APIs: pjsua_call_answer2(), pjsua_call_reinvite2(), pjsua_call_update2()
git-svn-id: http://svn.pjsip.org/repos/pjproject/trunk@3891 74dad513-b988-da41-8d7b-12977e46ad98
Diffstat (limited to 'pjsip/src/pjsua-lib/pjsua_media.c')
-rw-r--r-- | pjsip/src/pjsua-lib/pjsua_media.c | 211 |
1 files changed, 138 insertions, 73 deletions
diff --git a/pjsip/src/pjsua-lib/pjsua_media.c b/pjsip/src/pjsua-lib/pjsua_media.c index 8fe57a11..138f4808 100644 --- a/pjsip/src/pjsua-lib/pjsua_media.c +++ b/pjsip/src/pjsua-lib/pjsua_media.c @@ -1157,15 +1157,18 @@ static void sort_media(const pjmedia_sdp_session *sdp, const pj_str_t *type, pjmedia_srtp_use use_srtp, pj_uint8_t midx[], - unsigned *p_count) + unsigned *p_count, + unsigned *p_total_count) { unsigned i; unsigned count = 0; int score[PJSUA_MAX_CALL_MEDIA]; pj_assert(*p_count >= PJSUA_MAX_CALL_MEDIA); + pj_assert(*p_total_count >= PJSUA_MAX_CALL_MEDIA); *p_count = 0; + *p_total_count = 0; for (i=0; i<PJSUA_MAX_CALL_MEDIA; ++i) score[i] = 1; @@ -1238,10 +1241,11 @@ static void sort_media(const pjmedia_sdp_session *sdp, /* Don't put media with negative score, that media is unacceptable * for us. */ - if (score[best] >= 0) { - midx[*p_count] = (pj_uint8_t)best; + midx[i] = (pj_uint8_t)best; + if (score[best] >= 0) (*p_count)++; - } + if (score[best] > -22000) + (*p_total_count)++; score[best] = -22000; @@ -1588,11 +1592,13 @@ pj_status_t pjsua_media_channel_init(pjsua_call_id call_id, pjsua_acc *acc = &pjsua_var.acc[call->acc_id]; pj_uint8_t maudidx[PJSUA_MAX_CALL_MEDIA]; unsigned maudcnt = PJ_ARRAY_SIZE(maudidx); + unsigned mtotaudcnt = PJ_ARRAY_SIZE(maudidx); pj_uint8_t mvididx[PJSUA_MAX_CALL_MEDIA]; unsigned mvidcnt = PJ_ARRAY_SIZE(mvididx); - pjmedia_type media_types[PJSUA_MAX_CALL_MEDIA]; + unsigned mtotvidcnt = PJ_ARRAY_SIZE(mvididx); unsigned mi; pj_bool_t pending_med_tp = PJ_FALSE; + pj_bool_t reinit = PJ_FALSE; pj_status_t status; PJ_UNUSED_ARG(role); @@ -1614,7 +1620,12 @@ pj_status_t pjsua_media_channel_init(pjsua_call_id call_id, return status; } - PJ_LOG(4,(THIS_FILE, "Call %d: initializing media..", call_id)); + if (call->inv && call->inv->state == PJSIP_INV_STATE_CONFIRMED) + reinit = PJ_TRUE; + + PJ_LOG(4,(THIS_FILE, "Call %d: %sinitializing media..", + call_id, (reinit?"re-":"") )); + pj_log_push_indent(); #if DISABLED_FOR_TICKET_1185 @@ -1629,13 +1640,10 @@ pj_status_t pjsua_media_channel_init(pjsua_call_id call_id, } #endif + /* Get media count for each media type */ if (rem_sdp) { sort_media(rem_sdp, &STR_AUDIO, acc->cfg.use_srtp, - maudidx, &maudcnt); - // Don't apply media count limitation until SDP negotiation is done. - //if (maudcnt > acc->cfg.max_audio_cnt) - // maudcnt = acc->cfg.max_audio_cnt; - + maudidx, &maudcnt, &mtotaudcnt); if (maudcnt==0) { /* Expecting audio in the offer */ if (sip_err_code) *sip_err_code = PJSIP_SC_NOT_ACCEPTABLE_HERE; @@ -1646,35 +1654,98 @@ pj_status_t pjsua_media_channel_init(pjsua_call_id call_id, #if PJMEDIA_HAS_VIDEO sort_media(rem_sdp, &STR_VIDEO, acc->cfg.use_srtp, - mvididx, &mvidcnt); - // Don't apply media count limitation until SDP negotiation is done. - //if (mvidcnt > acc->cfg.max_video_cnt) - //mvidcnt = acc->cfg.max_video_cnt; + mvididx, &mvidcnt, &mtotvidcnt); #else - mvidcnt = 0; + mvidcnt = mtotvidcnt = 0; + PJ_UNUSED_ARG(STR_VIDEO); #endif /* Update media count only when remote add any media, this media count - * must never decrease. + * must never decrease. Also note that we shouldn't apply the media + * count setting (of the call setting) before the SDP negotiation. */ if (call->med_cnt < rem_sdp->media_count) call->med_cnt = PJ_MIN(rem_sdp->media_count, PJSUA_MAX_CALL_MEDIA); + call->rem_offerer = PJ_TRUE; + call->rem_aud_cnt = maudcnt; + call->rem_vid_cnt = mvidcnt; + } else { - maudcnt = acc->cfg.max_audio_cnt; - for (mi=0; mi<maudcnt; ++mi) { - maudidx[mi] = (pj_uint8_t)mi; - media_types[mi] = PJMEDIA_TYPE_AUDIO; - } + + /* If call already established, calculate media count from current + * local active SDP and call setting. Otherwise, calculate media + * count from the call setting only. + */ + if (reinit) { + pjmedia_sdp_session *sdp; + + status = pjmedia_sdp_neg_get_active_local(call->inv->neg, &sdp); + pj_assert(status == PJ_SUCCESS); + + sort_media(sdp, &STR_AUDIO, acc->cfg.use_srtp, + maudidx, &maudcnt, &mtotaudcnt); + pj_assert(maudcnt > 0); + + sort_media(sdp, &STR_VIDEO, acc->cfg.use_srtp, + mvididx, &mvidcnt, &mtotvidcnt); + + /* Call setting may add or remove media. Adding media is done by + * enabling any disabled/port-zeroed media first, then adding new + * media whenever needed. Removing media is done by disabling + * media with the lowest 'quality'. + */ + + /* Check if we need to add new audio */ + if (maudcnt < call->opt.audio_cnt && + mtotaudcnt < call->opt.audio_cnt) + { + for (mi = 0; mi < call->opt.audio_cnt - mtotaudcnt; ++mi) + maudidx[maudcnt++] = (pj_uint8_t)call->med_cnt++; + + mtotaudcnt = call->opt.audio_cnt; + } + maudcnt = call->opt.audio_cnt; + + /* Check if we need to add new video */ + if (mvidcnt < call->opt.video_cnt && + mtotvidcnt < call->opt.video_cnt) + { + for (mi = 0; mi < call->opt.video_cnt - mtotvidcnt; ++mi) + mvididx[mvidcnt++] = (pj_uint8_t)call->med_cnt++; + + mtotvidcnt = call->opt.video_cnt; + } + mvidcnt = call->opt.video_cnt; + + } else { + + maudcnt = mtotaudcnt = call->opt.audio_cnt; + for (mi=0; mi<maudcnt; ++mi) { + maudidx[mi] = (pj_uint8_t)mi; + } + mvidcnt = mtotvidcnt = call->opt.video_cnt; + for (mi=0; mi<mvidcnt; ++mi) { + mvididx[mi] = (pj_uint8_t)(maudcnt + mi); + } + call->med_cnt = maudcnt + mvidcnt; + + /* Need to publish supported media? */ + if (call->opt.flag & PJSUA_CALL_INCLUDE_DISABLED_MEDIA) { + if (mtotaudcnt == 0) { + mtotaudcnt = 1; + maudidx[0] = (pj_uint8_t)call->med_cnt++; + } #if PJMEDIA_HAS_VIDEO - mvidcnt = acc->cfg.max_video_cnt; - for (mi=0; mi<mvidcnt; ++mi) { - media_types[maudcnt + mi] = PJMEDIA_TYPE_VIDEO; + if (mtotvidcnt == 0) { + mtotvidcnt = 1; + mvididx[0] = (pj_uint8_t)call->med_cnt++; + } +#endif + } } -#else - mvidcnt = 0; -#endif - call->med_cnt = maudcnt + mvidcnt; + + call->rem_offerer = PJ_FALSE; } if (call->med_cnt == 0) { @@ -1702,28 +1773,22 @@ pj_status_t pjsua_media_channel_init(pjsua_call_id call_id, for (mi=0; mi < call->med_cnt; ++mi) { pjsua_call_media *call_med = &call->media[mi]; pj_bool_t enabled = PJ_FALSE; - pjmedia_type media_type = PJMEDIA_TYPE_NONE; - - if (rem_sdp) { - if (mi >= rem_sdp->media_count) { - /* Media has been removed in remote re-offer */ - media_type = call_med->type; - } else if (!pj_stricmp(&rem_sdp->media[mi]->desc.media, &STR_AUDIO)) { - media_type = PJMEDIA_TYPE_AUDIO; - if (pj_memchr(maudidx, mi, maudcnt * sizeof(maudidx[0]))) { - enabled = PJ_TRUE; - } + pjmedia_type media_type = PJMEDIA_TYPE_UNKNOWN; + + if (pj_memchr(maudidx, mi, mtotaudcnt * sizeof(maudidx[0]))) { + media_type = PJMEDIA_TYPE_AUDIO; + if (call->opt.audio_cnt && + pj_memchr(maudidx, mi, maudcnt * sizeof(maudidx[0]))) + { + enabled = PJ_TRUE; } - else if (!pj_stricmp(&rem_sdp->media[mi]->desc.media, &STR_VIDEO)) { - media_type = PJMEDIA_TYPE_VIDEO; - if (pj_memchr(mvididx, mi, mvidcnt * sizeof(mvididx[0]))) { - enabled = PJ_TRUE; - } + } else if (pj_memchr(mvididx, mi, mtotvidcnt * sizeof(mvididx[0]))) { + media_type = PJMEDIA_TYPE_VIDEO; + if (call->opt.video_cnt && + pj_memchr(mvididx, mi, mvidcnt * sizeof(mvididx[0]))) + { + enabled = PJ_TRUE; } - - } else { - enabled = PJ_TRUE; - media_type = media_types[mi]; } if (enabled) { @@ -1807,6 +1872,12 @@ on_error: return status; } + +/* Create SDP based on the current media channel. Note that, this function + * will not modify the media channel, so when receiving new offer or + * updating media count (via call setting), media channel must be reinit'd + * (using pjsua_media_channel_init()) first before calling this function. + */ pj_status_t pjsua_media_channel_create_sdp(pjsua_call_id call_id, pj_pool_t *pool, const pjmedia_sdp_session *rem_sdp, @@ -1824,6 +1895,8 @@ pj_status_t pjsua_media_channel_create_sdp(pjsua_call_id call_id, if (pjsua_get_state() != PJSUA_STATE_RUNNING) return PJ_EBUSY; +#if 0 + // This function should not really change the media channel. if (rem_sdp) { /* If this is a re-offer, let's re-initialize media as remote may * add or remove media @@ -1836,24 +1909,6 @@ pj_status_t pjsua_media_channel_create_sdp(pjsua_call_id call_id, if (status != PJ_SUCCESS) return status; } - -#if 0 - pjsua_acc *acc = &pjsua_var.acc[call->acc_id]; - pj_uint8_t maudidx[PJSUA_MAX_CALL_MEDIA]; - unsigned maudcnt = PJ_ARRAY_SIZE(maudidx); - - sort_media(rem_sdp, &STR_AUDIO, acc->cfg.use_srtp, - maudidx, &maudcnt); - - if (maudcnt==0) { - /* Expecting audio in the offer */ - if (sip_err_code) *sip_err_code = PJSIP_SC_NOT_ACCEPTABLE_HERE; - pjsua_media_channel_deinit(call_id); - return PJSIP_ERRNO_FROM_SIP_STATUS(PJSIP_SC_NOT_ACCEPTABLE_HERE); - } - - call->audio_idx = maudidx[0]; -#endif } else { /* Audio is first in our offer, by convention */ // The audio_idx should not be changed here, as this function may be @@ -1861,6 +1916,7 @@ pj_status_t pjsua_media_channel_create_sdp(pjsua_call_id call_id, // can be anywhere. //call->audio_idx = 0; } +#endif #if 0 // Since r3512, old-style hold should have got transport, created by @@ -2084,6 +2140,8 @@ pj_status_t pjsua_media_channel_create_sdp(pjsua_call_id call_id, } #endif + call->rem_offerer = (rem_sdp != NULL); + *p_sdp = sdp; return PJ_SUCCESS; } @@ -2463,8 +2521,10 @@ pj_status_t pjsua_media_channel_update(pjsua_call_id call_id, const pj_str_t STR_VIDEO = { "video", 5 }; pj_uint8_t maudidx[PJSUA_MAX_CALL_MEDIA]; unsigned maudcnt = PJ_ARRAY_SIZE(maudidx); + unsigned mtotaudcnt = PJ_ARRAY_SIZE(maudidx); pj_uint8_t mvididx[PJSUA_MAX_CALL_MEDIA]; unsigned mvidcnt = PJ_ARRAY_SIZE(mvididx); + unsigned mtotvidcnt = PJ_ARRAY_SIZE(mvididx); pj_bool_t need_renego_sdp = PJ_FALSE; if (pjsua_get_state() != PJSUA_STATE_RUNNING) @@ -2484,22 +2544,27 @@ pj_status_t pjsua_media_channel_update(pjsua_call_id call_id, /* Reset audio_idx first */ call->audio_idx = -1; - /* Apply maximum audio/video count of the account */ + /* Sort audio/video based on "quality" */ sort_media(local_sdp, &STR_AUDIO, acc->cfg.use_srtp, - maudidx, &maudcnt); + maudidx, &maudcnt, &mtotaudcnt); #if PJMEDIA_HAS_VIDEO sort_media(local_sdp, &STR_VIDEO, acc->cfg.use_srtp, - mvididx, &mvidcnt); + mvididx, &mvidcnt, &mtotvidcnt); #else PJ_UNUSED_ARG(STR_VIDEO); mvidcnt = 0; #endif - if (maudcnt > acc->cfg.max_audio_cnt || mvidcnt > acc->cfg.max_video_cnt) + + /* Applying media count limitation. Note that in generating SDP answer, + * no media count limitation applied, as we didn't know yet which media + * would pass the SDP negotiation. + */ + if (maudcnt > call->opt.audio_cnt || mvidcnt > call->opt.video_cnt) { pjmedia_sdp_session *local_sdp2; - maudcnt = PJ_MIN(maudcnt, acc->cfg.max_audio_cnt); - mvidcnt = PJ_MIN(mvidcnt, acc->cfg.max_video_cnt); + maudcnt = PJ_MIN(maudcnt, call->opt.audio_cnt); + mvidcnt = PJ_MIN(mvidcnt, call->opt.video_cnt); local_sdp2 = pjmedia_sdp_session_clone(tmp_pool, local_sdp); for (mi=0; mi < local_sdp2->media_count; ++mi) { |