Changeset 3334


Ignore:
Timestamp:
Oct 5, 2010 4:32:04 PM (11 years ago)
Author:
nanang
Message:

Fix #1143:

  • Fixed no audio bug when pjsua with SRTP optional-with-duplicated-offer calls pjsua with SRTP disabled, by updating active media index after SDP negotiation done.
  • Fixed bug in generating SDP, pjsua_media_channel_create_sdp(), by making sure all media in the SDP candidate are aligned with current active SDP before calling pjmedia_transport_encode_sdp().
  • Fixed bug in modifying SDP for call hold, the media index to be modified was hardcoded to 0, should be active media index.
  • Added python tests for calls with SRTP optional-with-duplicated-offer.
Location:
pjproject/trunk
Files:
7 added
2 edited

Legend:

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

    r3330 r3334  
    35813581                                           pjmedia_sdp_session *sdp) 
    35823582{ 
     3583    pjmedia_sdp_media *m; 
     3584 
    35833585    /* Call-hold is done by set the media direction to 'sendonly'  
    35843586     * (PJMEDIA_DIR_ENCODING), except when current media direction is  
     
    35923594     *  configuration to use c=0.0.0.0 for call hold. 
    35933595     */ 
     3596 
     3597    m = sdp->media[call->audio_idx]; 
     3598 
    35943599    if (call->call_hold_type == PJSUA_CALL_HOLD_TYPE_RFC2543) { 
    35953600        pjmedia_sdp_conn *conn; 
     
    35973602 
    35983603        /* Get SDP media connection line */ 
    3599         conn = sdp->media[0]->conn; 
     3604        conn = m->conn; 
    36003605        if (!conn) 
    36013606            conn = sdp->conn; 
     
    36053610 
    36063611        /* Remove existing directions attributes */ 
    3607         pjmedia_sdp_media_remove_all_attr(sdp->media[0], "sendrecv"); 
    3608         pjmedia_sdp_media_remove_all_attr(sdp->media[0], "sendonly"); 
    3609         pjmedia_sdp_media_remove_all_attr(sdp->media[0], "recvonly"); 
    3610         pjmedia_sdp_media_remove_all_attr(sdp->media[0], "inactive"); 
     3612        pjmedia_sdp_media_remove_all_attr(m, "sendrecv"); 
     3613        pjmedia_sdp_media_remove_all_attr(m, "sendonly"); 
     3614        pjmedia_sdp_media_remove_all_attr(m, "recvonly"); 
     3615        pjmedia_sdp_media_remove_all_attr(m, "inactive"); 
    36113616 
    36123617        /* Add inactive attribute */ 
    36133618        attr = pjmedia_sdp_attr_create(pool, "inactive", NULL); 
    3614         pjmedia_sdp_media_add_attr(sdp->media[0], attr); 
     3619        pjmedia_sdp_media_add_attr(m, attr); 
    36153620 
    36163621 
     
    36193624 
    36203625        /* Remove existing directions attributes */ 
    3621         pjmedia_sdp_media_remove_all_attr(sdp->media[0], "sendrecv"); 
    3622         pjmedia_sdp_media_remove_all_attr(sdp->media[0], "sendonly"); 
    3623         pjmedia_sdp_media_remove_all_attr(sdp->media[0], "recvonly"); 
    3624         pjmedia_sdp_media_remove_all_attr(sdp->media[0], "inactive"); 
     3626        pjmedia_sdp_media_remove_all_attr(m, "sendrecv"); 
     3627        pjmedia_sdp_media_remove_all_attr(m, "sendonly"); 
     3628        pjmedia_sdp_media_remove_all_attr(m, "recvonly"); 
     3629        pjmedia_sdp_media_remove_all_attr(m, "inactive"); 
    36253630 
    36263631        if (call->media_dir & PJMEDIA_DIR_ENCODING) { 
    36273632            /* Add sendonly attribute */ 
    36283633            attr = pjmedia_sdp_attr_create(pool, "sendonly", NULL); 
    3629             pjmedia_sdp_media_add_attr(sdp->media[0], attr); 
     3634            pjmedia_sdp_media_add_attr(m, attr); 
    36303635        } else { 
    36313636            /* Add inactive attribute */ 
    36323637            attr = pjmedia_sdp_attr_create(pool, "inactive", NULL); 
    3633             pjmedia_sdp_media_add_attr(sdp->media[0], attr); 
     3638            pjmedia_sdp_media_add_attr(m, attr); 
    36343639        } 
    36353640    } 
     
    36733678{ 
    36743679    pjsua_call *call; 
    3675     pjmedia_sdp_conn *conn; 
     3680    pjmedia_sdp_conn *conn = NULL; 
    36763681    pjmedia_sdp_session *answer; 
    36773682    pj_status_t status; 
     
    36813686    call = (pjsua_call*) inv->dlg->mod_data[pjsua_var.mod.id]; 
    36823687 
    3683     conn = offer->media[0]->conn; 
     3688    if (call->audio_idx < (int)offer->media_count) 
     3689        conn = offer->media[call->audio_idx]->conn; 
     3690 
    36843691    if (!conn) 
    36853692        conn = offer->conn; 
  • pjproject/trunk/pjsip/src/pjsua-lib/pjsua_media.c

    r3313 r3334  
    11151115 
    11161116 
     1117static int find_audio_index(const pjmedia_sdp_session *sdp,  
     1118                            pj_bool_t prefer_srtp) 
     1119{ 
     1120    unsigned i; 
     1121    int audio_idx = -1; 
     1122 
     1123    for (i=0; i<sdp->media_count; ++i) { 
     1124        const pjmedia_sdp_media *m = sdp->media[i]; 
     1125 
     1126        /* Skip if media is not audio */ 
     1127        if (pj_stricmp2(&m->desc.media, "audio") != 0) 
     1128            continue; 
     1129 
     1130        /* Skip if media is disabled */ 
     1131        if (m->desc.port == 0) 
     1132            continue; 
     1133 
     1134        /* Skip if transport is not supported */ 
     1135        if (pj_stricmp2(&m->desc.transport, "RTP/AVP") != 0 && 
     1136            pj_stricmp2(&m->desc.transport, "RTP/SAVP") != 0) 
     1137        { 
     1138            continue; 
     1139        } 
     1140 
     1141        if (audio_idx == -1) { 
     1142            audio_idx = i; 
     1143        } else { 
     1144            /* We've found multiple candidates. This could happen 
     1145             * e.g. when remote is offering both RTP/SAVP and RTP/AVP, 
     1146             * or when remote for some reason offers two audio. 
     1147             */ 
     1148 
     1149            if (prefer_srtp && 
     1150                pj_stricmp2(&m->desc.transport, "RTP/SAVP")==0) 
     1151            { 
     1152                /* Prefer RTP/SAVP when our media transport is SRTP */ 
     1153                audio_idx = i; 
     1154                break; 
     1155            } else if (!prefer_srtp && 
     1156                       pj_stricmp2(&m->desc.transport, "RTP/AVP")==0) 
     1157            { 
     1158                /* Prefer RTP/AVP when our media transport is NOT SRTP */ 
     1159                audio_idx = i; 
     1160            } 
     1161        } 
     1162    } 
     1163 
     1164    return audio_idx; 
     1165} 
     1166 
     1167 
    11171168pj_status_t pjsua_media_channel_init(pjsua_call_id call_id, 
    11181169                                     pjsip_role_e role, 
     
    11871238 
    11881239    /* Find out which media line in SDP that we support. If we are offerer, 
    1189      * audio will be at index 0 in SDP.  
     1240     * audio will be initialized at index 0 in SDP.  
    11901241     */ 
    1191     if (rem_sdp == 0) { 
     1242    if (rem_sdp == NULL) { 
    11921243        call->audio_idx = 0; 
    11931244    }  
    11941245    /* Otherwise find out the candidate audio media line in SDP */ 
    11951246    else { 
    1196         unsigned i; 
    11971247        pj_bool_t srtp_active; 
    11981248 
     
    12061256        pj_assert(rem_sdp->media_count != 0); 
    12071257 
    1208         for (i=0; i<rem_sdp->media_count; ++i) { 
    1209             const pjmedia_sdp_media *m = rem_sdp->media[i]; 
    1210  
    1211             /* Skip if media is not audio */ 
    1212             if (pj_stricmp2(&m->desc.media, "audio") != 0) 
    1213                 continue; 
    1214  
    1215             /* Skip if media is disabled */ 
    1216             if (m->desc.port == 0) 
    1217                 continue; 
    1218  
    1219             /* Skip if transport is not supported */ 
    1220             if (pj_stricmp2(&m->desc.transport, "RTP/AVP") != 0 && 
    1221                 pj_stricmp2(&m->desc.transport, "RTP/SAVP") != 0) 
    1222             { 
    1223                 continue; 
    1224             } 
    1225  
    1226             if (call->audio_idx == -1) { 
    1227                 call->audio_idx = i; 
    1228             } else { 
    1229                 /* We've found multiple candidates. This could happen 
    1230                  * e.g. when remote is offering both RTP/AVP and RTP/AVP, 
    1231                  * or when remote for some reason offers two audio. 
    1232                  */ 
    1233  
    1234                 if (srtp_active && 
    1235                     pj_stricmp2(&m->desc.transport, "RTP/SAVP")==0) 
    1236                 { 
    1237                     /* Prefer RTP/SAVP when our media transport is SRTP */ 
    1238                     call->audio_idx = i; 
    1239                 } else if (!srtp_active && 
    1240                            pj_stricmp2(&m->desc.transport, "RTP/AVP")==0) 
    1241                 { 
    1242                     /* Prefer RTP/AVP when our media transport is NOT SRTP */ 
    1243                     call->audio_idx = i; 
    1244                 } 
    1245             } 
    1246         } 
     1258        call->audio_idx = find_audio_index(rem_sdp, srtp_active); 
    12471259    } 
    12481260 
     
    12801292    pjmedia_transport_info tpinfo; 
    12811293    pjsua_call *call = &pjsua_var.calls[call_id]; 
     1294    pjmedia_sdp_neg_state sdp_neg_state = PJMEDIA_SDP_NEG_STATE_NULL; 
    12821295    pj_status_t status; 
    12831296 
     
    13041317    } 
    13051318 
     1319    /* Get SDP negotiator state */ 
     1320    if (call->inv && call->inv->neg) 
     1321        sdp_neg_state = pjmedia_sdp_neg_get_state(call->inv->neg); 
     1322 
    13061323    /* Get media socket info */ 
    13071324    pjmedia_transport_info_init(&tpinfo); 
     
    13161333    } 
    13171334 
    1318     /* If we're answering and the selected media is not the first media 
     1335    /* If we're answering or updating the session with a new offer, 
     1336     * and the selected media is not the first media 
    13191337     * in SDP, then fill in the unselected media with with zero port.  
    13201338     * Otherwise we'll crash in transport_encode_sdp() because the media 
    13211339     * lines are not aligned between offer and answer. 
    13221340     */ 
    1323     if (rem_sdp && call->audio_idx != 0) { 
     1341    if (call->audio_idx != 0 &&  
     1342        (rem_sdp || sdp_neg_state==PJMEDIA_SDP_NEG_STATE_DONE)) 
     1343    { 
    13241344        unsigned i; 
    1325  
    1326         for (i=0; i<rem_sdp->media_count; ++i) { 
    1327             const pjmedia_sdp_media *rem_m = rem_sdp->media[i]; 
     1345        const pjmedia_sdp_session *ref_sdp = rem_sdp; 
     1346 
     1347        if (!ref_sdp) { 
     1348            /* We are updating session with a new offer */ 
     1349            status = pjmedia_sdp_neg_get_active_local(call->inv->neg, 
     1350                                                      &ref_sdp); 
     1351            pj_assert(status == PJ_SUCCESS); 
     1352        } 
     1353 
     1354        for (i=0; i<ref_sdp->media_count; ++i) { 
     1355            const pjmedia_sdp_media *ref_m = ref_sdp->media[i]; 
    13281356            pjmedia_sdp_media *m; 
    13291357 
     
    13311359                continue; 
    13321360 
    1333             m = pjmedia_sdp_media_clone_deactivate(pool, rem_m); 
     1361            m = pjmedia_sdp_media_clone_deactivate(pool, ref_m); 
    13341362            if (i==sdp->media_count) 
    13351363                sdp->media[sdp->media_count++] = m; 
     
    13931421                pjmedia_sdp_media_find_attr2(m, "crypto", NULL) != NULL) 
    13941422            { 
    1395                 pjmedia_sdp_media *new_m; 
    1396  
    1397                 /* Duplicate this media and apply secured transport */ 
    1398                 new_m = pjmedia_sdp_media_clone(pool, m); 
    1399                 pj_strdup2(pool, &new_m->desc.transport, "RTP/SAVP"); 
    1400  
    1401                 /* Remove the "crypto" attribute in the unsecured media */ 
    1402                 pjmedia_sdp_media_remove_all_attr(m, "crypto"); 
    1403  
    1404                 /* Insert the new media before the unsecured media */ 
    1405                 if (sdp->media_count < PJMEDIA_MAX_SDP_MEDIA) { 
    1406                     pj_array_insert(sdp->media, sizeof(new_m),  
    1407                                     sdp->media_count, i, &new_m); 
    1408                     ++sdp->media_count; 
    1409                     ++i; 
     1423                if (i == (unsigned)call->audio_idx &&  
     1424                    sdp_neg_state == PJMEDIA_SDP_NEG_STATE_DONE) 
     1425                { 
     1426                    /* This is a session update, and peer has chosen the 
     1427                     * unsecured version, so let's make this unsecured too. 
     1428                     */ 
     1429                    pjmedia_sdp_media_remove_all_attr(m, "crypto"); 
     1430                } else { 
     1431                    /* This is new offer, duplicate media so we'll have 
     1432                     * secured (with "RTP/SAVP" transport) and and unsecured 
     1433                     * versions. 
     1434                     */ 
     1435                    pjmedia_sdp_media *new_m; 
     1436 
     1437                    /* Duplicate this media and apply secured transport */ 
     1438                    new_m = pjmedia_sdp_media_clone(pool, m); 
     1439                    pj_strdup2(pool, &new_m->desc.transport, "RTP/SAVP"); 
     1440 
     1441                    /* Remove the "crypto" attribute in the unsecured media */ 
     1442                    pjmedia_sdp_media_remove_all_attr(m, "crypto"); 
     1443 
     1444                    /* Insert the new media before the unsecured media */ 
     1445                    if (sdp->media_count < PJMEDIA_MAX_SDP_MEDIA) { 
     1446                        pj_array_insert(sdp->media, sizeof(new_m),  
     1447                                        sdp->media_count, i, &new_m); 
     1448                        ++sdp->media_count; 
     1449                        ++i; 
     1450                    } 
    14101451                } 
    14111452            } 
     
    15391580        return status; 
    15401581 
     1582    /* Update audio index from the negotiated SDP */ 
     1583    call->audio_idx = find_audio_index(local_sdp, PJ_TRUE); 
     1584 
    15411585    /* Find which session is audio */ 
    15421586    PJ_ASSERT_RETURN(call->audio_idx != -1, PJ_EBUG); 
     
    15841628        status = pjmedia_transport_media_start(call->med_tp,  
    15851629                                               call->inv->pool_prov, 
    1586                                                local_sdp, remote_sdp, 0); 
     1630                                               local_sdp, remote_sdp, 
     1631                                               call->audio_idx); 
    15871632        if (status != PJ_SUCCESS) 
    15881633            return status; 
Note: See TracChangeset for help on using the changeset viewer.