Ignore:
Timestamp:
Jun 27, 2008 9:19:44 PM (16 years ago)
Author:
bennylp
Message:

Fix handling of multiple media lines in the incoming SDP offer. Now pjsua-lib will be able to select the best media line to handle

File:
1 edited

Legend:

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

    r2074 r2079  
    852852                                     int *sip_err_code) 
    853853{ 
    854     enum { MEDIA_IDX = 0 }; 
    855854    pjsua_call *call = &pjsua_var.calls[call_id]; 
    856855    pj_status_t status; 
     
    859858    pjsua_acc *acc = &pjsua_var.acc[call->acc_id]; 
    860859    pjmedia_srtp_setting srtp_opt; 
    861     pjmedia_transport *srtp; 
     860    pjmedia_transport *srtp = NULL; 
    862861#endif 
    863862 
     
    915914#endif 
    916915 
     916    /* Find out which media line in SDP that we support. If we are offerer, 
     917     * audio will be at index 0 in SDP.  
     918     */ 
     919    if (rem_sdp == 0) { 
     920        call->audio_idx = 0; 
     921    }  
     922    /* Otherwise find out the candidate audio media line in SDP */ 
     923    else { 
     924        unsigned i; 
     925        pj_bool_t srtp_active; 
     926 
     927#if defined(PJMEDIA_HAS_SRTP) && (PJMEDIA_HAS_SRTP != 0) 
     928        srtp_active = acc->cfg.use_srtp && srtp != NULL; 
     929#else 
     930        srtp_active = PJ_FALSE; 
     931#endif 
     932 
     933        /* Media count must have been checked */ 
     934        pj_assert(rem_sdp->media_count != 0); 
     935 
     936        for (i=0; i<rem_sdp->media_count; ++i) { 
     937            const pjmedia_sdp_media *m = rem_sdp->media[i]; 
     938 
     939            /* Skip if media is not audio */ 
     940            if (pj_stricmp2(&m->desc.media, "audio") != 0) 
     941                continue; 
     942 
     943            /* Skip if media is disabled */ 
     944            if (m->desc.port == 0) 
     945                continue; 
     946 
     947            /* Skip if transport is not supported */ 
     948            if (pj_stricmp2(&m->desc.transport, "RTP/AVP") != 0 && 
     949                pj_stricmp2(&m->desc.transport, "RTP/SAVP") != 0) 
     950            { 
     951                continue; 
     952            } 
     953 
     954            if (call->audio_idx == -1) { 
     955                call->audio_idx = i; 
     956            } else { 
     957                /* We've found multiple candidates. This could happen 
     958                 * e.g. when remote is offering both RTP/AVP and RTP/AVP, 
     959                 * or when remote for some reason offers two audio. 
     960                 */ 
     961 
     962                if (srtp_active && 
     963                    pj_stricmp2(&m->desc.transport, "RTP/SAVP")==0) 
     964                { 
     965                    /* Prefer RTP/SAVP when our media transport is SRTP */ 
     966                    call->audio_idx = i; 
     967                } else if (!srtp_active && 
     968                           pj_stricmp2(&m->desc.transport, "RTP/AVP")==0) 
     969                { 
     970                    /* Prefer RTP/AVP when our media transport is NOT SRTP */ 
     971                    call->audio_idx = i; 
     972                } 
     973            } 
     974        } 
     975    } 
     976 
     977    /* Reject offer if we couldn't find a good m=audio line in offer */ 
     978    if (call->audio_idx < 0) { 
     979        if (sip_err_code) *sip_err_code = PJSIP_SC_NOT_ACCEPTABLE; 
     980        pjsua_media_channel_deinit(call_id); 
     981        return PJSIP_ERRNO_FROM_SIP_STATUS(PJSIP_SC_NOT_ACCEPTABLE); 
     982    } 
     983 
     984    PJ_LOG(4,(THIS_FILE, "Media index %d selected for call %d", 
     985              call->audio_idx, call->index)); 
     986 
    917987    /* Create the media transport */ 
    918988    status = pjmedia_transport_media_create(call->med_tp, tmp_pool, 0, 
    919                                             rem_sdp, MEDIA_IDX); 
     989                                            rem_sdp, call->audio_idx); 
    920990    if (status != PJ_SUCCESS) { 
    921991        if (sip_err_code) *sip_err_code = PJSIP_SC_NOT_ACCEPTABLE; 
     
    9341004                                           int *sip_status_code) 
    9351005{ 
    936     enum { MAX_MEDIA = 1, MEDIA_IDX = 0 }; 
     1006    enum { MAX_MEDIA = 1 }; 
    9371007    pjmedia_sdp_session *sdp; 
    9381008    pjmedia_transport_info tpinfo; 
     
    9461016        return PJ_EBUSY; 
    9471017    } 
     1018 
     1019    /* Media index must have been determined before */ 
     1020    pj_assert(call->audio_idx != -1); 
    9481021 
    9491022    /* Create media if it's not created. This could happen when call is 
     
    9711044    } 
    9721045 
     1046    /* If we're answering and the selected media is not the first media 
     1047     * in SDP, then fill in the unselected media with with zero port.  
     1048     * Otherwise we'll crash in transport_encode_sdp() because the media 
     1049     * lines are not aligned between offer and answer. 
     1050     */ 
     1051    if (rem_sdp && call->audio_idx != 0) { 
     1052        unsigned i; 
     1053 
     1054        for (i=0; i<rem_sdp->media_count; ++i) { 
     1055            const pjmedia_sdp_media *rem_m = rem_sdp->media[i]; 
     1056            pjmedia_sdp_media *m; 
     1057            const pjmedia_sdp_attr *a; 
     1058 
     1059            if ((int)i == call->audio_idx) 
     1060                continue; 
     1061 
     1062            m = PJ_POOL_ZALLOC_T(pool, pjmedia_sdp_media); 
     1063            pj_strdup(pool, &m->desc.media, &rem_m->desc.media); 
     1064            pj_strdup(pool, &m->desc.transport, &rem_m->desc.transport); 
     1065            m->desc.port = 0; 
     1066 
     1067            /* Add one format, copy from the offer. And copy the corresponding 
     1068             * rtpmap and fmtp attributes too. 
     1069             */ 
     1070            m->desc.fmt_count = 1; 
     1071            pj_strdup(pool, &m->desc.fmt[0], &rem_m->desc.fmt[0]); 
     1072            if ((a=pjmedia_sdp_attr_find2(rem_m->attr_count, rem_m->attr, 
     1073                                          "rtpmap", &m->desc.fmt[0])) != NULL) 
     1074            { 
     1075                m->attr[m->attr_count++] = pjmedia_sdp_attr_clone(pool, a); 
     1076            } 
     1077            if ((a=pjmedia_sdp_attr_find2(rem_m->attr_count, rem_m->attr, 
     1078                                          "fmtp", &m->desc.fmt[0])) != NULL) 
     1079            { 
     1080                m->attr[m->attr_count++] = pjmedia_sdp_attr_clone(pool, a); 
     1081            } 
     1082 
     1083            if (i==sdp->media_count) 
     1084                sdp->media[sdp->media_count++] = m; 
     1085            else { 
     1086                pj_array_insert(sdp->media, sizeof(sdp->media[0]), 
     1087                                sdp->media_count, i, &m); 
     1088                ++sdp->media_count; 
     1089            } 
     1090        } 
     1091    } 
     1092 
    9731093    /* Add NAT info in the SDP */ 
    9741094    if (pjsua_var.ua_cfg.nat_type_in_sdp) { 
     
    9971117    /* Give the SDP to media transport */ 
    9981118    status = pjmedia_transport_encode_sdp(call->med_tp, pool, sdp, rem_sdp,  
    999                                           MEDIA_IDX); 
     1119                                          call->audio_idx); 
    10001120    if (status != PJ_SUCCESS) { 
    10011121        if (sip_status_code) *sip_status_code = PJSIP_SC_NOT_ACCEPTABLE; 
     
    10791199                                       const pjmedia_sdp_session *remote_sdp) 
    10801200{ 
    1081     unsigned i; 
    10821201    int prev_media_st = 0; 
    10831202    pjsua_call *call = &pjsua_var.calls[call_id]; 
     
    11001219        return status; 
    11011220 
    1102     /* Find which session is audio (we only support audio for now) */ 
    1103     for (i=0; i < sess_info.stream_cnt; ++i) { 
    1104         if (sess_info.stream_info[i].type == PJMEDIA_TYPE_AUDIO && 
    1105             (sess_info.stream_info[i].proto == PJMEDIA_TP_PROTO_RTP_AVP || 
    1106              sess_info.stream_info[i].proto == PJMEDIA_TP_PROTO_RTP_SAVP)) 
    1107         { 
    1108             si = &sess_info.stream_info[i]; 
    1109             break; 
    1110         } 
    1111     } 
    1112  
    1113     if (si == NULL) { 
    1114         /* Not found */ 
    1115         return PJMEDIA_EINVALIMEDIATYPE; 
    1116     } 
    1117  
     1221    /* Find which session is audio */ 
     1222    PJ_ASSERT_RETURN(call->audio_idx != -1, PJ_EBUG); 
     1223    PJ_ASSERT_RETURN(call->audio_idx < (int)sess_info.stream_cnt, PJ_EBUG); 
     1224    si = &sess_info.stream_info[call->audio_idx]; 
    11181225     
    11191226    /* Reset session info with only one media stream */ 
Note: See TracChangeset for help on using the changeset viewer.