Changeset 4254 for pjproject/trunk/pjsip/src/pjsua-lib/pjsua_media.c
- Timestamp:
- Sep 14, 2012 4:06:29 AM (12 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
pjproject/trunk/pjsip/src/pjsua-lib/pjsua_media.c
r4245 r4254 2085 2085 2086 2086 2087 static void stop_media_stream(pjsua_call *call, unsigned med_idx) 2088 { 2089 pjsua_call_media *call_med = &call->media[med_idx]; 2090 2091 /* Check if stream does not exist */ 2092 if (med_idx >= call->med_cnt) 2093 return; 2094 2095 pj_log_push_indent(); 2096 2097 if (call_med->type == PJMEDIA_TYPE_AUDIO) { 2098 pjsua_aud_stop_stream(call_med); 2099 } 2100 2101 #if PJMEDIA_HAS_VIDEO 2102 else if (call_med->type == PJMEDIA_TYPE_VIDEO) { 2103 pjsua_vid_stop_stream(call_med); 2104 } 2105 #endif 2106 2107 PJ_LOG(4,(THIS_FILE, "Media stream call%02d:%d is destroyed", 2108 call->index, med_idx)); 2109 call_med->prev_state = call_med->state; 2110 call_med->state = PJSUA_CALL_MEDIA_NONE; 2111 2112 /* Try to sync recent changes to provisional media */ 2113 if (med_idx < call->med_prov_cnt && 2114 call->media_prov[med_idx].tp == call_med->tp) 2115 { 2116 pjsua_call_media *prov_med = &call->media_prov[med_idx]; 2117 2118 /* Media state */ 2119 prov_med->prev_state = call_med->prev_state; 2120 prov_med->state = call_med->state; 2121 2122 /* RTP seq/ts */ 2123 prov_med->rtp_tx_seq_ts_set = call_med->rtp_tx_seq_ts_set; 2124 prov_med->rtp_tx_seq = call_med->rtp_tx_seq; 2125 prov_med->rtp_tx_ts = call_med->rtp_tx_ts; 2126 2127 /* Stream */ 2128 if (call_med->type == PJMEDIA_TYPE_AUDIO) { 2129 prov_med->strm.a.conf_slot = call_med->strm.a.conf_slot; 2130 prov_med->strm.a.stream = call_med->strm.a.stream; 2131 } 2132 #if PJMEDIA_HAS_VIDEO 2133 else if (call_med->type == PJMEDIA_TYPE_VIDEO) { 2134 prov_med->strm.v.cap_win_id = call_med->strm.v.cap_win_id; 2135 prov_med->strm.v.rdr_win_id = call_med->strm.v.rdr_win_id; 2136 prov_med->strm.v.stream = call_med->strm.v.stream; 2137 } 2138 #endif 2139 } 2140 2141 pj_log_pop_indent(); 2142 } 2143 2087 2144 static void stop_media_session(pjsua_call_id call_id) 2088 2145 { … … 2090 2147 unsigned mi; 2091 2148 2092 pj_log_push_indent();2093 2094 2149 for (mi=0; mi<call->med_cnt; ++mi) { 2095 pjsua_call_media *call_med = &call->media[mi]; 2096 2097 if (call_med->type == PJMEDIA_TYPE_AUDIO) { 2098 pjsua_aud_stop_stream(call_med); 2099 } 2100 2101 #if PJMEDIA_HAS_VIDEO 2102 else if (call_med->type == PJMEDIA_TYPE_VIDEO) { 2103 pjsua_vid_stop_stream(call_med); 2104 } 2105 #endif 2106 2107 PJ_LOG(4,(THIS_FILE, "Media session call%02d:%d is destroyed", 2108 call_id, mi)); 2109 call_med->prev_state = call_med->state; 2110 call_med->state = PJSUA_CALL_MEDIA_NONE; 2111 2112 /* Try to sync recent changes to provisional media */ 2113 if (mi<call->med_prov_cnt && call->media_prov[mi].tp==call_med->tp) 2114 { 2115 pjsua_call_media *prov_med = &call->media_prov[mi]; 2116 2117 /* Media state */ 2118 prov_med->prev_state = call_med->prev_state; 2119 prov_med->state = call_med->state; 2120 2121 /* RTP seq/ts */ 2122 prov_med->rtp_tx_seq_ts_set = call_med->rtp_tx_seq_ts_set; 2123 prov_med->rtp_tx_seq = call_med->rtp_tx_seq; 2124 prov_med->rtp_tx_ts = call_med->rtp_tx_ts; 2125 2126 /* Stream */ 2127 if (call_med->type == PJMEDIA_TYPE_AUDIO) { 2128 prov_med->strm.a.conf_slot = call_med->strm.a.conf_slot; 2129 prov_med->strm.a.stream = call_med->strm.a.stream; 2130 } 2131 #if PJMEDIA_HAS_VIDEO 2132 else if (call_med->type == PJMEDIA_TYPE_VIDEO) { 2133 prov_med->strm.v.cap_win_id = call_med->strm.v.cap_win_id; 2134 prov_med->strm.v.rdr_win_id = call_med->strm.v.rdr_win_id; 2135 prov_med->strm.v.stream = call_med->strm.v.stream; 2136 } 2137 #endif 2138 } 2139 } 2140 2141 pj_log_pop_indent(); 2150 stop_media_stream(call, mi); 2151 } 2142 2152 } 2143 2153 … … 2187 2197 return PJ_SUCCESS; 2188 2198 } 2199 2200 2201 /* Match codec fmtp. This will compare the values and the order. */ 2202 static pj_bool_t match_codec_fmtp(const pjmedia_codec_fmtp *fmtp1, 2203 const pjmedia_codec_fmtp *fmtp2) 2204 { 2205 unsigned i; 2206 2207 if (fmtp1->cnt != fmtp2->cnt) 2208 return PJ_FALSE; 2209 2210 for (i = 0; i < fmtp1->cnt; ++i) { 2211 if (pj_stricmp(&fmtp1->param[i].name, &fmtp2->param[i].name)) 2212 return PJ_FALSE; 2213 if (pj_stricmp(&fmtp1->param[i].val, &fmtp2->param[i].val)) 2214 return PJ_FALSE; 2215 } 2216 2217 return PJ_TRUE; 2218 } 2219 2220 #if PJSUA_MEDIA_HAS_PJMEDIA || PJSUA_THIRD_PARTY_STREAM_HAS_GET_INFO 2221 2222 static pj_bool_t is_media_changed(const pjsua_call *call, 2223 unsigned med_idx, 2224 const pjsua_stream_info *new_si_) 2225 { 2226 const pjsua_call_media *call_med = &call->media[med_idx]; 2227 2228 /* Check for newly added media */ 2229 if (med_idx >= call->med_cnt) 2230 return PJ_TRUE; 2231 2232 /* Compare media type */ 2233 if (call_med->type != new_si_->type) 2234 return PJ_TRUE; 2235 2236 /* Audio update checks */ 2237 if (call_med->type == PJMEDIA_TYPE_AUDIO) { 2238 pjmedia_stream_info the_old_si; 2239 const pjmedia_stream_info *old_si = NULL; 2240 const pjmedia_stream_info *new_si = &new_si_->info.aud; 2241 const pjmedia_codec_info *old_ci = NULL; 2242 const pjmedia_codec_info *new_ci = &new_si->fmt; 2243 const pjmedia_codec_param *old_cp = NULL; 2244 const pjmedia_codec_param *new_cp = new_si->param; 2245 2246 /* Compare media direction */ 2247 if (call_med->dir != new_si->dir) 2248 return PJ_TRUE; 2249 2250 /* Get current active stream info */ 2251 if (call_med->strm.a.stream) { 2252 pjmedia_stream_get_info(call_med->strm.a.stream, &the_old_si); 2253 old_si = &the_old_si; 2254 old_ci = &old_si->fmt; 2255 old_cp = old_si->param; 2256 } else { 2257 /* The stream is inactive. */ 2258 return (new_si->dir != PJMEDIA_DIR_NONE); 2259 } 2260 2261 /* Compare remote RTP address */ 2262 if (pj_sockaddr_cmp(&old_si->rem_addr, &new_si->rem_addr)) 2263 return PJ_TRUE; 2264 2265 /* Compare codec info */ 2266 if (pj_stricmp(&old_ci->encoding_name, &new_ci->encoding_name) || 2267 old_ci->clock_rate != new_ci->clock_rate || 2268 old_ci->channel_cnt != new_ci->channel_cnt || 2269 old_si->rx_pt != new_si->rx_pt || 2270 old_si->tx_pt != new_si->tx_pt || 2271 old_si->rx_event_pt != new_si->tx_event_pt || 2272 old_si->tx_event_pt != new_si->tx_event_pt) 2273 { 2274 return PJ_TRUE; 2275 } 2276 2277 /* Compare codec param */ 2278 if (old_cp->setting.frm_per_pkt != new_cp->setting.frm_per_pkt || 2279 old_cp->setting.vad != new_cp->setting.vad || 2280 old_cp->setting.cng != new_cp->setting.cng || 2281 old_cp->setting.plc != new_cp->setting.plc || 2282 old_cp->setting.penh != new_cp->setting.penh || 2283 !match_codec_fmtp(&old_cp->setting.dec_fmtp, 2284 &new_cp->setting.dec_fmtp) || 2285 !match_codec_fmtp(&old_cp->setting.enc_fmtp, 2286 &new_cp->setting.enc_fmtp)) 2287 { 2288 return PJ_TRUE; 2289 } 2290 } 2291 2292 #if PJMEDIA_HAS_VIDEO 2293 else if (call_med->type == PJMEDIA_TYPE_VIDEO) { 2294 pjmedia_vid_stream_info the_old_si; 2295 const pjmedia_vid_stream_info *old_si = NULL; 2296 const pjmedia_vid_stream_info *new_si = &new_si_->info.vid; 2297 const pjmedia_vid_codec_info *old_ci = NULL; 2298 const pjmedia_vid_codec_info *new_ci = &new_si->codec_info; 2299 const pjmedia_vid_codec_param *old_cp = NULL; 2300 const pjmedia_vid_codec_param *new_cp = new_si->codec_param; 2301 2302 /* Compare media direction */ 2303 if (call_med->dir != new_si->dir) 2304 return PJ_TRUE; 2305 2306 /* Get current active stream info */ 2307 if (call_med->strm.v.stream) { 2308 pjmedia_vid_stream_get_info(call_med->strm.v.stream, &the_old_si); 2309 old_si = &the_old_si; 2310 old_ci = &old_si->codec_info; 2311 old_cp = old_si->codec_param; 2312 } else { 2313 /* The stream is inactive. */ 2314 return (new_si->dir != PJMEDIA_DIR_NONE); 2315 } 2316 2317 /* Compare remote RTP address */ 2318 if (pj_sockaddr_cmp(&old_si->rem_addr, &new_si->rem_addr)) 2319 return PJ_TRUE; 2320 2321 /* Compare codec info */ 2322 if (pj_stricmp(&old_ci->encoding_name, &new_ci->encoding_name) || 2323 old_si->rx_pt != new_si->rx_pt || 2324 old_si->tx_pt != new_si->tx_pt) 2325 { 2326 return PJ_TRUE; 2327 } 2328 2329 /* Compare codec param */ 2330 if (/* old_cp->enc_mtu != new_cp->enc_mtu || */ 2331 pj_memcmp(&old_cp->enc_fmt.det, &new_cp->enc_fmt.det, 2332 sizeof(pjmedia_video_format_detail)) || 2333 !match_codec_fmtp(&old_cp->dec_fmtp, &new_cp->dec_fmtp) || 2334 !match_codec_fmtp(&old_cp->enc_fmtp, &new_cp->enc_fmtp)) 2335 { 2336 return PJ_TRUE; 2337 } 2338 } 2339 2340 #endif 2341 2342 else { 2343 /* Just return PJ_TRUE for other media type */ 2344 return PJ_TRUE; 2345 } 2346 2347 return PJ_FALSE; 2348 } 2349 2350 #else /* PJSUA_MEDIA_HAS_PJMEDIA || PJSUA_THIRD_PARTY_STREAM_HAS_GET_INFO */ 2351 2352 static pj_bool_t is_media_changed(const pjsua_call *call, 2353 unsigned med_idx, 2354 const pjsua_stream_info *new_si_) 2355 { 2356 PJ_UNUSED_ARG(call); 2357 PJ_UNUSED_ARG(med_idx); 2358 PJ_UNUSED_ARG(new_si_); 2359 /* Always assume that media has been changed */ 2360 return PJ_TRUE; 2361 } 2362 2363 #endif /* PJSUA_MEDIA_HAS_PJMEDIA || PJSUA_THIRD_PARTY_STREAM_HAS_GET_INFO */ 2189 2364 2190 2365 … … 2217 2392 2218 2393 /* Destroy existing media session, if any. */ 2219 stop_media_session(call->index);2394 //stop_media_session(call->index); 2220 2395 2221 2396 /* Call media count must be at least equal to SDP media. Note that … … 2271 2446 for (mi=0; mi < call->med_prov_cnt; ++mi) { 2272 2447 pjsua_call_media *call_med = &call->media_prov[mi]; 2448 pj_bool_t media_changed = PJ_FALSE; 2273 2449 2274 2450 if (mi >= local_sdp->media_count || … … 2278 2454 * its re-offer. 2279 2455 */ 2456 2457 /* Stop stream */ 2458 stop_media_stream(call, mi); 2459 2460 /* Close the media transport */ 2280 2461 if (call_med->tp) { 2281 /* Close the media transport */2282 2462 pjsua_set_media_tp_state(call_med, PJSUA_MED_TP_NULL); 2283 2463 pjmedia_transport_close(call_med->tp); … … 2294 2474 } 2295 2475 2476 /* Apply media update action */ 2296 2477 if (call_med->type==PJMEDIA_TYPE_AUDIO) { 2297 2478 pjmedia_stream_info the_si, *si = &the_si; 2298 2299 status = pjmedia_stream_info_from_sdp(si, tmp_pool, pjsua_var.med_endpt, 2300 local_sdp, remote_sdp, mi); 2479 pjsua_stream_info stream_info; 2480 2481 status = pjmedia_stream_info_from_sdp( 2482 si, tmp_pool, pjsua_var.med_endpt, 2483 local_sdp, remote_sdp, mi); 2301 2484 if (status != PJ_SUCCESS) { 2302 2485 PJ_PERROR(1,(THIS_FILE, status, … … 2307 2490 } 2308 2491 2492 /* Check if this media is changed */ 2493 stream_info.type = PJMEDIA_TYPE_AUDIO; 2494 stream_info.info.aud = the_si; 2495 if (pjsua_var.media_cfg.no_smart_media_update || 2496 is_media_changed(call, mi, &stream_info)) 2497 { 2498 media_changed = PJ_TRUE; 2499 /* Stop the media */ 2500 stop_media_stream(call, mi); 2501 } else { 2502 PJ_LOG(4,(THIS_FILE, "Call %d: stream #%d (audio) unchanged.", 2503 call_id, mi)); 2504 } 2505 2309 2506 /* Check if no media is active */ 2310 2507 if (si->dir == PJMEDIA_DIR_NONE) { 2508 2311 2509 /* Update call media state and direction */ 2312 2510 call_med->state = PJSUA_CALL_MEDIA_NONE; … … 2336 2534 unsigned i; 2337 2535 for (i = 0; i < tp_info.specific_info_cnt; ++i) { 2338 if (tp_info.spc_info[i].type == PJMEDIA_TRANSPORT_TYPE_SRTP) 2536 if (tp_info.spc_info[i].type == 2537 PJMEDIA_TRANSPORT_TYPE_SRTP) 2339 2538 { 2340 2539 pjmedia_srtp_info *srtp_info = 2341 (pjmedia_srtp_info*)tp_info.spc_info[i].buffer;2540 (pjmedia_srtp_info*)tp_info.spc_info[i].buffer; 2342 2541 2343 2542 call_med->rem_srtp_use = srtp_info->peer_use; 2344 2543 break; 2345 2544 } 2545 } 2546 } 2547 2548 /* Update audio channel */ 2549 if (media_changed) { 2550 status = pjsua_aud_channel_update(call_med, 2551 call->inv->pool, si, 2552 local_sdp, remote_sdp); 2553 if (status != PJ_SUCCESS) { 2554 PJ_PERROR(1,(THIS_FILE, status, 2555 "pjsua_aud_channel_update() failed " 2556 "for call_id %d media %d", 2557 call_id, mi)); 2558 continue; 2346 2559 } 2347 2560 } … … 2357 2570 else 2358 2571 call_med->state = PJSUA_CALL_MEDIA_ACTIVE; 2359 }2360 2361 /* Call implementation */2362 status = pjsua_aud_channel_update(call_med, tmp_pool, si,2363 local_sdp, remote_sdp);2364 if (status != PJ_SUCCESS) {2365 PJ_PERROR(1,(THIS_FILE, status,2366 "pjsua_aud_channel_update() failed "2367 "for call_id %d media %d",2368 call_id, mi));2369 continue;2370 2572 } 2371 2573 … … 2414 2616 } else if (call_med->type==PJMEDIA_TYPE_VIDEO) { 2415 2617 pjmedia_vid_stream_info the_si, *si = &the_si; 2416 2417 status = pjmedia_vid_stream_info_from_sdp(si, tmp_pool, pjsua_var.med_endpt, 2418 local_sdp, remote_sdp, mi); 2618 pjsua_stream_info stream_info; 2619 2620 status = pjmedia_vid_stream_info_from_sdp( 2621 si, tmp_pool, pjsua_var.med_endpt, 2622 local_sdp, remote_sdp, mi); 2419 2623 if (status != PJ_SUCCESS) { 2420 2624 PJ_PERROR(1,(THIS_FILE, status, … … 2425 2629 } 2426 2630 2631 /* Check if this media is changed */ 2632 stream_info.type = PJMEDIA_TYPE_VIDEO; 2633 stream_info.info.vid = the_si; 2634 if (is_media_changed(call, mi, &stream_info)) { 2635 media_changed = PJ_TRUE; 2636 /* Stop the media */ 2637 stop_media_stream(call, mi); 2638 } else { 2639 PJ_LOG(4,(THIS_FILE, "Call %d: stream #%d (video) unchanged.", 2640 call_id, mi)); 2641 } 2642 2427 2643 /* Check if no media is active */ 2428 2644 if (si->dir == PJMEDIA_DIR_NONE) { 2645 2429 2646 /* Update call media state and direction */ 2430 2647 call_med->state = PJSUA_CALL_MEDIA_NONE; … … 2465 2682 } 2466 2683 2684 /* Update audio channel */ 2685 if (media_changed) { 2686 status = pjsua_vid_channel_update(call_med, 2687 call->inv->pool, si, 2688 local_sdp, remote_sdp); 2689 if (status != PJ_SUCCESS) { 2690 PJ_PERROR(1,(THIS_FILE, status, 2691 "pjsua_vid_channel_update() failed " 2692 "for call_id %d media %d", 2693 call_id, mi)); 2694 continue; 2695 } 2696 } 2697 2467 2698 /* Call media direction */ 2468 2699 call_med->dir = si->dir; … … 2475 2706 else 2476 2707 call_med->state = PJSUA_CALL_MEDIA_ACTIVE; 2477 }2478 2479 status = pjsua_vid_channel_update(call_med, tmp_pool, si,2480 local_sdp, remote_sdp);2481 if (status != PJ_SUCCESS) {2482 PJ_PERROR(1,(THIS_FILE, status,2483 "pjsua_vid_channel_update() failed "2484 "for call_id %d media %d",2485 call_id, mi));2486 continue;2487 2708 } 2488 2709
Note: See TracChangeset
for help on using the changeset viewer.