Ignore:
Timestamp:
Jul 14, 2015 8:38:29 AM (9 years ago)
Author:
nanang
Message:

Re #1864: fixed assert and crash when remote remove and add back media lines in SDP:

  • reverted back r5124 (of this ticket) and r4373 (of #1626)
  • applied another fix for #1626 as in described in the ticket desc
  • also fixed a related add/remove media issue:
    • we send an offer with 2 audio and 1 video in SDP
    • remote answers with only 1 audio in SDP
    • when we send a re-offer/re-INVITE, we have 5 media lines in our SDP (3 audio + 2 video, note 1 audio and 1 video are disabled)
    • call settings are actually maintained (2 active audio + 1 active video), just better to avoid the additional disabled media.
File:
1 edited

Legend:

Unmodified
Added
Removed
  • pjproject/trunk/pjsip/src/pjsua-lib/pjsua_media.c

    r5127 r5135  
    11401140} 
    11411141 
     1142 
     1143/* Go through the list of media in the call, find acceptable media, and 
     1144 * sort them based on the "quality" of the media, and store the indexes 
     1145 * in the specified array. Media with the best quality will be listed 
     1146 * first in the array. 
     1147 */ 
     1148static void sort_media2(const pjsua_call_media *call_med, 
     1149                        unsigned call_med_cnt, 
     1150                        pjmedia_type type, 
     1151                        pj_uint8_t midx[], 
     1152                        unsigned *p_count, 
     1153                        unsigned *p_total_count) 
     1154{ 
     1155    unsigned i; 
     1156    unsigned count = 0; 
     1157    int score[PJSUA_MAX_CALL_MEDIA]; 
     1158 
     1159    pj_assert(*p_count >= PJSUA_MAX_CALL_MEDIA); 
     1160    pj_assert(*p_total_count >= PJSUA_MAX_CALL_MEDIA); 
     1161 
     1162    *p_count = 0; 
     1163    *p_total_count = 0; 
     1164    for (i=0; i<PJSUA_MAX_CALL_MEDIA; ++i) 
     1165        score[i] = 1; 
     1166 
     1167    /* Score each media */ 
     1168    for (i=0; i<call_med_cnt && count<PJSUA_MAX_CALL_MEDIA; ++i) { 
     1169 
     1170        /* Skip different media */ 
     1171        if (call_med[i].type != type) { 
     1172            score[count++] = -22000; 
     1173            continue; 
     1174        } 
     1175 
     1176        /* Is it active? */ 
     1177        if (!call_med[i].tp) { 
     1178            score[i] -= 10; 
     1179        } 
     1180 
     1181        ++count; 
     1182    } 
     1183 
     1184    /* Created sorted list based on quality */ 
     1185    for (i=0; i<count; ++i) { 
     1186        unsigned j; 
     1187        int best = 0; 
     1188 
     1189        for (j=1; j<count; ++j) { 
     1190            if (score[j] > score[best]) 
     1191                best = j; 
     1192        } 
     1193        /* Don't put media with negative score, that media is unacceptable 
     1194         * for us. 
     1195         */ 
     1196        midx[i] = (pj_uint8_t)best; 
     1197        if (score[best] >= 0) 
     1198            (*p_count)++; 
     1199        if (score[best] > -22000) 
     1200            (*p_total_count)++; 
     1201 
     1202        score[best] = -22000; 
     1203 
     1204    } 
     1205} 
     1206 
     1207 
    11421208/* Callback to receive media events */ 
    11431209pj_status_t call_media_on_event(pjmedia_event *event, 
     
    15291595 
    15301596 
    1531 /* If idx == 0, clean up media transports in provisional media that 
    1532  * is not used by call media, else clean up media transports starting 
    1533  * from index idx that have been removed by remote. 
     1597/* Clean up media transports in provisional media that is not used by 
     1598 * call media. 
    15341599 */ 
    1535 static void media_prov_clean_up(pjsua_call_id call_id, int idx) 
     1600void pjsua_media_prov_clean_up(pjsua_call_id call_id) 
    15361601{ 
    15371602    pjsua_call *call = &pjsua_var.calls[call_id]; 
    15381603    unsigned i; 
    15391604 
    1540     if (idx > 0 || call->med_prov_cnt > call->med_cnt) { 
     1605    if (call->med_prov_cnt > call->med_cnt) { 
    15411606        PJ_LOG(4,(THIS_FILE, "Call %d: cleaning up provisional media, " 
    15421607                             "prov_med_cnt=%d, med_cnt=%d", 
    1543                              call_id, (idx == 0? call->med_prov_cnt: idx), 
    1544                              call->med_cnt)); 
    1545     } 
    1546  
    1547     for (i = idx; i < call->med_prov_cnt; ++i) { 
     1608                             call_id, call->med_prov_cnt, call->med_cnt)); 
     1609    } 
     1610 
     1611    for (i = 0; i < call->med_prov_cnt; ++i) { 
    15481612        pjsua_call_media *call_med = &call->media_prov[i]; 
    15491613        unsigned j; 
     
    15541618 
    15551619        for (j = 0; j < call->med_cnt; ++j) { 
    1556             if (idx == 0 && call->media[j].tp == call_med->tp) { 
     1620            if (call->media[j].tp == call_med->tp) { 
    15571621                used = PJ_TRUE; 
    15581622                break; 
     
    15721636     
    15731637    call->med_prov_cnt = 0; 
    1574 } 
    1575  
    1576 void pjsua_media_prov_clean_up(pjsua_call_id call_id) 
    1577 { 
    1578     media_prov_clean_up(call_id, 0); 
    15791638} 
    15801639 
     
    16651724    /* Get media count for each media type */ 
    16661725    if (rem_sdp) { 
     1726 
     1727        /* We are sending answer, check media count for each media type 
     1728         * from the remote SDP. 
     1729         */ 
    16671730        sort_media(rem_sdp, &STR_AUDIO, acc->cfg.use_srtp, 
    16681731                   maudidx, &maudcnt, &mtotaudcnt); 
     
    16961759    } else { 
    16971760 
    1698         /* If call already established, calculate media count from current  
    1699          * local active SDP and call setting. Otherwise, calculate media 
    1700          * count from the call setting only. 
     1761        /* If call is already established, adjust the existing call media list 
     1762         * to media count setting in call setting, e.g: re-enable/disable/add 
     1763         * media from existing media. 
     1764         * Otherwise, apply media count from the call setting directly. 
    17011765         */ 
    17021766        if (reinit) { 
    1703             const pjmedia_sdp_session *sdp; 
    1704  
    1705             status = pjmedia_sdp_neg_get_active_local(call->inv->neg, &sdp); 
    1706             pj_assert(status == PJ_SUCCESS); 
    1707  
    1708             sort_media(sdp, &STR_AUDIO, acc->cfg.use_srtp, 
    1709                        maudidx, &maudcnt, &mtotaudcnt); 
     1767 
     1768            /* We are sending reoffer, check media count for each media type 
     1769             * from the existing call media list. 
     1770             */ 
     1771            sort_media2(call->media_prov, call->med_prov_cnt, 
     1772                        PJMEDIA_TYPE_AUDIO, maudidx, &maudcnt, &mtotaudcnt); 
    17101773            pj_assert(maudcnt > 0); 
    17111774 
    1712             sort_media(sdp, &STR_VIDEO, acc->cfg.use_srtp, 
    1713                       mvididx, &mvidcnt, &mtotvidcnt); 
     1775            sort_media2(call->media_prov, call->med_prov_cnt, 
     1776                        PJMEDIA_TYPE_VIDEO, mvididx, &mvidcnt, &mtotvidcnt); 
    17141777 
    17151778            /* Call setting may add or remove media. Adding media is done by 
     
    18561919            } 
    18571920 
    1858             /* Put media type just for info */ 
    1859             call_med->type = media_type; 
     1921            /* Put media type just for info if not yet defined */ 
     1922            if (call_med->type == PJMEDIA_TYPE_NONE) 
     1923                call_med->type = media_type; 
    18601924        } 
    18611925    } 
     
    19922056        if (rem_sdp && mi >= rem_sdp->media_count) { 
    19932057            /* Remote might have removed some media lines. */ 
    1994             for (i = rem_sdp->media_count; i < call->med_prov_cnt; ++i) { 
    1995                 stop_media_stream(call, i); 
    1996             } 
    1997             media_prov_clean_up(call->index, rem_sdp->media_count); 
    1998             call->med_prov_cnt = rem_sdp->media_count; 
     2058            /* Note that we must not modify the current active media 
     2059             * (e.g: stop stream, close/cleanup media transport), as if 
     2060             * SDP nego fails, the current active media should be maintained. 
     2061             * Also note that our media count should never decrease, even when 
     2062             * remote removed some media lines. 
     2063             */ 
    19992064            break; 
    20002065        } 
     
    29903055              sizeof(call->media_prov[0]) * call->med_prov_cnt); 
    29913056 
    2992     /* Perform SDP re-negotiation if needed. */ 
     3057    /* Perform SDP re-negotiation if some media have just got disabled 
     3058     * in this function due to media count limit settings. 
     3059     */ 
    29933060    if (got_media && need_renego_sdp) { 
    29943061        pjmedia_sdp_neg *neg = call->inv->neg; 
Note: See TracChangeset for help on using the changeset viewer.