- Timestamp:
- Oct 5, 2010 4:32:04 PM (14 years ago)
- Location:
- pjproject/trunk
- Files:
-
- 7 added
- 2 edited
Legend:
- Unmodified
- Added
- Removed
-
pjproject/trunk/pjsip/src/pjsua-lib/pjsua_call.c
r3330 r3334 3581 3581 pjmedia_sdp_session *sdp) 3582 3582 { 3583 pjmedia_sdp_media *m; 3584 3583 3585 /* Call-hold is done by set the media direction to 'sendonly' 3584 3586 * (PJMEDIA_DIR_ENCODING), except when current media direction is … … 3592 3594 * configuration to use c=0.0.0.0 for call hold. 3593 3595 */ 3596 3597 m = sdp->media[call->audio_idx]; 3598 3594 3599 if (call->call_hold_type == PJSUA_CALL_HOLD_TYPE_RFC2543) { 3595 3600 pjmedia_sdp_conn *conn; … … 3597 3602 3598 3603 /* Get SDP media connection line */ 3599 conn = sdp->media[0]->conn;3604 conn = m->conn; 3600 3605 if (!conn) 3601 3606 conn = sdp->conn; … … 3605 3610 3606 3611 /* 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"); 3611 3616 3612 3617 /* Add inactive attribute */ 3613 3618 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); 3615 3620 3616 3621 … … 3619 3624 3620 3625 /* 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"); 3625 3630 3626 3631 if (call->media_dir & PJMEDIA_DIR_ENCODING) { 3627 3632 /* Add sendonly attribute */ 3628 3633 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); 3630 3635 } else { 3631 3636 /* Add inactive attribute */ 3632 3637 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); 3634 3639 } 3635 3640 } … … 3673 3678 { 3674 3679 pjsua_call *call; 3675 pjmedia_sdp_conn *conn ;3680 pjmedia_sdp_conn *conn = NULL; 3676 3681 pjmedia_sdp_session *answer; 3677 3682 pj_status_t status; … … 3681 3686 call = (pjsua_call*) inv->dlg->mod_data[pjsua_var.mod.id]; 3682 3687 3683 conn = offer->media[0]->conn; 3688 if (call->audio_idx < (int)offer->media_count) 3689 conn = offer->media[call->audio_idx]->conn; 3690 3684 3691 if (!conn) 3685 3692 conn = offer->conn; -
pjproject/trunk/pjsip/src/pjsua-lib/pjsua_media.c
r3313 r3334 1115 1115 1116 1116 1117 static 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 1117 1168 pj_status_t pjsua_media_channel_init(pjsua_call_id call_id, 1118 1169 pjsip_role_e role, … … 1187 1238 1188 1239 /* 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. 1190 1241 */ 1191 if (rem_sdp == 0) {1242 if (rem_sdp == NULL) { 1192 1243 call->audio_idx = 0; 1193 1244 } 1194 1245 /* Otherwise find out the candidate audio media line in SDP */ 1195 1246 else { 1196 unsigned i;1197 1247 pj_bool_t srtp_active; 1198 1248 … … 1206 1256 pj_assert(rem_sdp->media_count != 0); 1207 1257 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); 1247 1259 } 1248 1260 … … 1280 1292 pjmedia_transport_info tpinfo; 1281 1293 pjsua_call *call = &pjsua_var.calls[call_id]; 1294 pjmedia_sdp_neg_state sdp_neg_state = PJMEDIA_SDP_NEG_STATE_NULL; 1282 1295 pj_status_t status; 1283 1296 … … 1304 1317 } 1305 1318 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 1306 1323 /* Get media socket info */ 1307 1324 pjmedia_transport_info_init(&tpinfo); … … 1316 1333 } 1317 1334 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 1319 1337 * in SDP, then fill in the unselected media with with zero port. 1320 1338 * Otherwise we'll crash in transport_encode_sdp() because the media 1321 1339 * lines are not aligned between offer and answer. 1322 1340 */ 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 { 1324 1344 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]; 1328 1356 pjmedia_sdp_media *m; 1329 1357 … … 1331 1359 continue; 1332 1360 1333 m = pjmedia_sdp_media_clone_deactivate(pool, re m_m);1361 m = pjmedia_sdp_media_clone_deactivate(pool, ref_m); 1334 1362 if (i==sdp->media_count) 1335 1363 sdp->media[sdp->media_count++] = m; … … 1393 1421 pjmedia_sdp_media_find_attr2(m, "crypto", NULL) != NULL) 1394 1422 { 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 } 1410 1451 } 1411 1452 } … … 1539 1580 return status; 1540 1581 1582 /* Update audio index from the negotiated SDP */ 1583 call->audio_idx = find_audio_index(local_sdp, PJ_TRUE); 1584 1541 1585 /* Find which session is audio */ 1542 1586 PJ_ASSERT_RETURN(call->audio_idx != -1, PJ_EBUG); … … 1584 1628 status = pjmedia_transport_media_start(call->med_tp, 1585 1629 call->inv->pool_prov, 1586 local_sdp, remote_sdp, 0); 1630 local_sdp, remote_sdp, 1631 call->audio_idx); 1587 1632 if (status != PJ_SUCCESS) 1588 1633 return status;
Note: See TracChangeset
for help on using the changeset viewer.