Changeset 5939 for pjproject/trunk/pjsip/src/pjsua-lib/pjsua_vid.c
- Timestamp:
- Mar 5, 2019 6:23:02 AM (5 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
pjproject/trunk/pjsip/src/pjsua-lib/pjsua_vid.c
r5842 r5939 27 27 28 28 #define ENABLE_EVENT 1 29 #define VID_TEE_MAX_PORT (PJSUA_MAX_CALLS + 1)30 29 31 30 #define PJSUA_SHOW_WINDOW 1 … … 66 65 PJ_PERROR(1,(THIS_FILE, status, 67 66 "Error creating PJMEDIA video codec manager")); 67 goto on_error; 68 } 69 70 status = pjmedia_vid_conf_create(pjsua_var.pool, NULL, 71 &pjsua_var.vid_conf); 72 if (status != PJ_SUCCESS) { 73 PJ_PERROR(1,(THIS_FILE, status, 74 "Error creating PJMEDIA video conference bridge")); 68 75 goto on_error; 69 76 } … … 139 146 pjsua_var.win[i].pool = NULL; 140 147 } 148 } 149 150 if (pjsua_var.vid_conf) { 151 pjmedia_vid_conf_destroy(pjsua_var.vid_conf); 152 pjsua_var.vid_conf = NULL; 141 153 } 142 154 … … 515 527 } 516 528 529 /* 530 * Get video conference slot ID of the specified capture device. 531 */ 532 PJ_DEF(pjsua_conf_port_id) pjsua_vid_preview_get_vid_conf_port( 533 pjmedia_vid_dev_index id) 534 { 535 pjsua_vid_win_id wid; 536 pjsua_vid_win *w; 537 538 wid = vid_preview_get_win(id, PJ_TRUE); 539 if (wid == PJSUA_INVALID_ID) 540 return PJSUA_INVALID_ID; 541 542 w = &pjsua_var.win[wid]; 543 return w->cap_slot; 544 } 545 546 517 547 PJ_DEF(void) pjsua_vid_win_reset(pjsua_vid_win_id wid) 518 548 { … … 528 558 529 559 /* Allocate and initialize pjsua video window: 530 * - If the type is preview , video capture, tee, and render531 * will be instantiated .532 * - If the type is stream , only rendererwill be created.560 * - If the type is preview: capture port and render port 561 * will be instantiated, and connected via conf. 562 * - If the type is stream: only render port will be created. 533 563 */ 534 564 static pj_status_t create_vid_win(pjsua_vid_win_type type, … … 673 703 674 704 /* Create capture video port */ 675 vp_param.active = PJ_ TRUE;705 vp_param.active = PJ_FALSE; 676 706 vp_param.vidparam.dir = PJMEDIA_DIR_CAPTURE; 677 707 … … 703 733 fmt = &fmt_; 704 734 705 /* Create video tee */ 706 status = pjmedia_vid_tee_create(w->pool, fmt, VID_TEE_MAX_PORT, 707 &w->tee); 708 if (status != PJ_SUCCESS) 709 goto on_error; 710 711 /* Connect capturer to the video tee */ 712 status = pjmedia_vid_port_connect(w->vp_cap, w->tee, PJ_FALSE); 735 /* Register capturer to the video conf */ 736 status = pjsua_vid_conf_add_port( 737 w->pool, 738 pjmedia_vid_port_get_passive_port(w->vp_cap), 739 NULL, &w->cap_slot); 713 740 if (status != PJ_SUCCESS) 714 741 goto on_error; … … 739 766 goto on_error; 740 767 741 vp_param.active = (w->type == PJSUA_WND_TYPE_STREAM);768 vp_param.active = PJ_FALSE; 742 769 vp_param.vidparam.dir = PJMEDIA_DIR_RENDER; 743 770 vp_param.vidparam.fmt = *fmt; … … 756 783 goto on_error; 757 784 758 /* For preview window, connect capturer & renderer (via tee) */ 785 /* Register renderer to the video conf */ 786 status = pjsua_vid_conf_add_port( 787 w->pool, 788 pjmedia_vid_port_get_passive_port(w->vp_rend), 789 NULL, &w->rend_slot); 790 if (status != PJ_SUCCESS) 791 goto on_error; 792 793 /* For preview window, connect capturer & renderer (via conf) */ 759 794 if (w->type == PJSUA_WND_TYPE_PREVIEW) { 760 pjmedia_port *rend_port; 761 762 rend_port = pjmedia_vid_port_get_passive_port(w->vp_rend); 763 status = pjmedia_vid_tee_add_dst_port2(w->tee, 0, rend_port); 795 status = pjsua_vid_conf_connect(w->cap_slot, w->rend_slot, NULL); 764 796 if (status != PJ_SUCCESS) 765 797 goto on_error; … … 799 831 800 832 if (w->vp_cap) { 833 pjsua_vid_conf_remove_port(w->cap_slot); 801 834 pjmedia_event_unsubscribe(NULL, &call_media_on_event, NULL, 802 835 w->vp_cap); 803 836 pjmedia_vid_port_stop(w->vp_cap); 804 pjmedia_vid_port_disconnect(w->vp_cap);805 837 pjmedia_vid_port_destroy(w->vp_cap); 806 838 } 807 839 if (w->vp_rend) { 840 pjsua_vid_conf_remove_port(w->rend_slot); 808 841 pjmedia_event_unsubscribe(NULL, &call_media_on_event, NULL, 809 842 w->vp_rend); … … 811 844 pjmedia_vid_port_destroy(w->vp_rend); 812 845 } 813 if (w->tee) {814 pjmedia_port_destroy(w->tee);815 }816 846 pjsua_vid_win_reset(wid); 817 847 … … 850 880 call_med->strm.v.rdr_dev = acc->cfg.vid_rend_dev; 851 881 call_med->strm.v.cap_dev = acc->cfg.vid_cap_dev; 882 call_med->strm.v.strm_dec_slot = PJSUA_INVALID_ID; 883 call_med->strm.v.strm_enc_slot = PJSUA_INVALID_ID; 852 884 if (call_med->strm.v.rdr_dev == PJMEDIA_VID_DEFAULT_RENDER_DEV) { 853 885 pjmedia_vid_dev_info info; … … 979 1011 pj_log_push_indent(); 980 1012 1013 /* Retrieve stream decoding port */ 981 1014 status = pjmedia_vid_stream_get_port(call_med->strm.v.stream, 982 1015 PJMEDIA_DIR_DECODING, … … 1010 1043 #endif 1011 1044 1012 /* Connect renderer to stream */ 1013 status = pjmedia_vid_port_connect(w->vp_rend, media_port, 1014 PJ_FALSE); 1045 /* Register renderer to stream events */ 1046 pjmedia_vid_port_subscribe_event(w->vp_rend, media_port); 1047 1048 /* Register stream decoding to conf, using tmp_pool should be fine 1049 * as bridge will create its own pool (using tmp_pool factory). 1050 */ 1051 status = pjsua_vid_conf_add_port(tmp_pool, media_port, NULL, 1052 &call_med->strm.v.strm_dec_slot); 1053 if (status != PJ_SUCCESS) { 1054 pj_log_pop_indent(); 1055 goto on_error; 1056 } 1057 1058 /* Connect stream to renderer (via conf) */ 1059 status = pjsua_vid_conf_connect(call_med->strm.v.strm_dec_slot, 1060 w->rend_slot, NULL); 1015 1061 if (status != PJ_SUCCESS) { 1016 1062 pj_log_pop_indent(); … … 1042 1088 pj_log_push_indent(); 1043 1089 1090 /* Retrieve stream encoding port */ 1044 1091 status = pjmedia_vid_stream_get_port(call_med->strm.v.stream, 1045 1092 PJMEDIA_DIR_ENCODING, … … 1079 1126 #endif 1080 1127 1081 /* Connect stream to capturer (via video window tee) */ 1082 status = pjmedia_vid_tee_add_dst_port2(w->tee, 0, media_port); 1128 /* Register stream encoding to conf, using tmp_pool should be fine 1129 * as bridge will create its own pool (using tmp_pool factory). 1130 */ 1131 status = pjsua_vid_conf_add_port(tmp_pool, media_port, NULL, 1132 &call_med->strm.v.strm_enc_slot); 1133 if (status != PJ_SUCCESS) { 1134 pj_log_pop_indent(); 1135 goto on_error; 1136 } 1137 1138 /* Connect capturer to stream encoding (via conf) */ 1139 status = pjsua_vid_conf_connect(w->cap_slot, 1140 call_med->strm.v.strm_enc_slot, 1141 NULL); 1083 1142 if (status != PJ_SUCCESS) { 1084 1143 pj_log_pop_indent(); … … 1133 1192 pj_log_push_indent(); 1134 1193 1194 /* Unregister video stream ports (encode+decode) from conference */ 1195 pjsua_vid_conf_remove_port(call_med->strm.v.strm_enc_slot); 1196 pjsua_vid_conf_remove_port(call_med->strm.v.strm_dec_slot); 1197 1135 1198 pjmedia_vid_stream_send_rtcp_bye(strm); 1136 1199 1137 1200 if (call_med->strm.v.cap_win_id != PJSUA_INVALID_ID) { 1138 pjmedia_port *media_port;1139 1201 pjsua_vid_win *w = &pjsua_var.win[call_med->strm.v.cap_win_id]; 1140 pj_status_t status; 1141 1142 /* Stop the capture before detaching stream and unsubscribing event */ 1143 pjmedia_vid_port_stop(w->vp_cap); 1144 1145 /* Disconnect video stream from capture device */ 1146 status = pjmedia_vid_stream_get_port(call_med->strm.v.stream, 1147 PJMEDIA_DIR_ENCODING, 1148 &media_port); 1149 if (status == PJ_SUCCESS) { 1150 pjmedia_vid_tee_remove_dst_port(w->tee, media_port); 1151 } 1152 1153 /* Unsubscribe event */ 1202 1203 /* Unsubscribe event */ 1154 1204 pjmedia_event_unsubscribe(NULL, &call_media_on_event, call_med, 1155 1205 w->vp_cap); 1156 1206 1157 /* Re-start capture again, if it is used by other stream */ 1158 if (w->ref_cnt > 1) 1159 pjmedia_vid_port_start(w->vp_cap); 1160 1207 /* Decrement ref count of preview video window */ 1161 1208 dec_vid_win(call_med->strm.v.cap_win_id); 1162 1209 call_med->strm.v.cap_win_id = PJSUA_INVALID_ID; … … 1166 1213 pjsua_vid_win *w = &pjsua_var.win[call_med->strm.v.rdr_win_id]; 1167 1214 1168 /* Stop the render before unsubscribing event */1215 /* Unsubscribe event, but stop the render first */ 1169 1216 pjmedia_vid_port_stop(w->vp_rend); 1170 1217 pjmedia_event_unsubscribe(NULL, &call_media_on_event, call_med, 1171 1218 w->vp_rend); 1172 1219 1220 /* Decrement ref count of stream video window */ 1173 1221 dec_vid_win(call_med->strm.v.rdr_win_id); 1174 1222 call_med->strm.v.rdr_win_id = PJSUA_INVALID_ID; … … 1432 1480 1433 1481 wi->rdr_dev = vparam.rend_id; 1482 wi->slot_id = w->rend_slot; 1434 1483 wi->hwnd = vparam.window; 1435 1484 wi->show = !vparam.window_hide; … … 2043 2092 w->preview_cap_id = cap_dev; 2044 2093 call_med->strm.v.cap_dev = cap_dev; 2094 /* Yay, change capturer done! */ 2045 2095 return PJ_SUCCESS; 2046 2096 } 2047 2097 2048 /* No it doesn't support fast switching. Do slow switching then.. */ 2098 /* Oh no, it doesn't support fast switching. Do normal change then, 2099 * i.e: remove the old and create a new capture. 2100 */ 2049 2101 status = pjmedia_vid_stream_get_port(call_med->strm.v.stream, 2050 2102 PJMEDIA_DIR_ENCODING, &media_port); … … 2055 2107 w->vp_cap); 2056 2108 2057 /* temporarily disconnect while we operate on the tee. */ 2058 pjmedia_vid_port_disconnect(w->vp_cap); 2059 2060 /* = Detach stream port from the old capture device's tee = */ 2061 status = pjmedia_vid_tee_remove_dst_port(w->tee, media_port); 2062 if (status != PJ_SUCCESS) { 2063 /* Something wrong, assume that media_port has been removed 2064 * and continue. 2065 */ 2066 PJ_PERROR(4,(THIS_FILE, status, 2067 "Warning: call %d: unable to remove video from tee", 2068 call->index)); 2069 } 2070 2071 /* Reconnect again immediately. We're done with w->tee */ 2072 pjmedia_vid_port_connect(w->vp_cap, w->tee, PJ_FALSE); 2109 /* Disconnect the old capture device to stream encoding port */ 2110 status = pjsua_vid_conf_disconnect(w->cap_slot, 2111 call_med->strm.v.strm_enc_slot); 2112 if (status != PJ_SUCCESS) 2113 return status; 2114 2073 2115 2074 2116 /* = Attach stream port to the new capture device = */ … … 2098 2140 inc_vid_win(new_wid); 2099 2141 new_w = &pjsua_var.win[new_wid]; 2100 2101 /* Connect stream to capturer (via video window tee) */2102 status = pjmedia_vid_tee_add_dst_port2(new_w->tee, 0, media_port);2103 if (status != PJ_SUCCESS)2104 goto on_error;2105 2142 2106 2143 if (new_w->vp_rend) { … … 2123 2160 } 2124 2161 2162 /* Connect capturer to stream encoding port (via conf) */ 2163 status = pjsua_vid_conf_connect(new_w->cap_slot, 2164 call_med->strm.v.strm_enc_slot, 2165 NULL); 2166 if (status != PJ_SUCCESS) 2167 goto on_error; 2168 2125 2169 /* Finally */ 2126 2170 call_med->strm.v.cap_dev = cap_dev; … … 2139 2183 pjmedia_event_unsubscribe(NULL, &call_media_on_event, call_med, 2140 2184 new_w->vp_cap); 2141 /* Disconnect media port from the new capturer */ 2142 pjmedia_vid_tee_remove_dst_port(new_w->tee, media_port); 2185 2143 2186 /* Release the new capturer */ 2144 2187 dec_vid_win(new_wid); … … 2146 2189 2147 2190 /* Revert back to the old capturer */ 2148 pjmedia_vid_port_disconnect(w->vp_cap); 2149 status = pjmedia_vid_tee_add_dst_port2(w->tee, 0, media_port); 2150 pjmedia_vid_port_connect(w->vp_cap, w->tee, PJ_FALSE); 2191 status = pjsua_vid_conf_connect(w->cap_slot, 2192 call_med->strm.v.strm_enc_slot, NULL); 2151 2193 if (status != PJ_SUCCESS) 2152 2194 return status; … … 2372 2414 } 2373 2415 2416 2417 /***************************************************************************** 2418 * Video conference 2419 */ 2420 2421 /* 2422 * Get current number of active ports in the bridge. 2423 */ 2424 PJ_DEF(unsigned) pjsua_vid_conf_get_active_ports(void) 2425 { 2426 return pjmedia_vid_conf_get_port_count(pjsua_var.vid_conf); 2427 } 2428 2429 2430 /* 2431 * Enumerate all video conference ports. 2432 */ 2433 PJ_DEF(pj_status_t) pjsua_vid_conf_enum_ports( pjsua_conf_port_id id[], 2434 unsigned *count) 2435 { 2436 return pjmedia_vid_conf_enum_ports(pjsua_var.vid_conf, 2437 (unsigned*)id, count); 2438 } 2439 2440 2441 /* 2442 * Get information about the specified video conference port 2443 */ 2444 PJ_DEF(pj_status_t) pjsua_vid_conf_get_port_info( 2445 pjsua_conf_port_id port_id, 2446 pjsua_vid_conf_port_info *info) 2447 { 2448 pjmedia_vid_conf_port_info cinfo; 2449 unsigned i; 2450 pj_status_t status; 2451 2452 status = pjmedia_vid_conf_get_port_info(pjsua_var.vid_conf, 2453 (unsigned)port_id, &cinfo); 2454 if (status != PJ_SUCCESS) 2455 return status; 2456 2457 pj_bzero(info, sizeof(*info)); 2458 info->slot_id = port_id; 2459 info->name = cinfo.name; 2460 pjmedia_format_copy(&info->format, &cinfo.format); 2461 2462 /* Build array of listeners */ 2463 info->listener_cnt = cinfo.listener_cnt; 2464 for (i=0; i<cinfo.listener_cnt; ++i) { 2465 info->listeners[i] = cinfo.listener_slots[i]; 2466 } 2467 2468 /* Build array of transmitters */ 2469 info->transmitter_cnt = cinfo.transmitter_cnt; 2470 for (i=0; i<cinfo.transmitter_cnt; ++i) { 2471 info->transmitters[i] = cinfo.transmitter_slots[i]; 2472 } 2473 2474 return PJ_SUCCESS; 2475 2476 } 2477 2478 2479 /* 2480 * Add arbitrary video media port to PJSUA's video conference bridge. 2481 */ 2482 PJ_DEF(pj_status_t) pjsua_vid_conf_add_port( pj_pool_t *pool, 2483 pjmedia_port *port, 2484 const void *param, 2485 pjsua_conf_port_id *p_id) 2486 { 2487 pj_status_t status; 2488 2489 PJ_UNUSED_ARG(param); 2490 2491 status = pjmedia_vid_conf_add_port(pjsua_var.vid_conf, pool, 2492 port, NULL, NULL, (unsigned*)p_id); 2493 if (status != PJ_SUCCESS) { 2494 if (p_id) 2495 *p_id = PJSUA_INVALID_ID; 2496 } 2497 2498 return status; 2499 } 2500 2501 2502 /* 2503 * Remove arbitrary slot from the video conference bridge. 2504 */ 2505 PJ_DEF(pj_status_t) pjsua_vid_conf_remove_port(pjsua_conf_port_id id) 2506 { 2507 return pjmedia_vid_conf_remove_port(pjsua_var.vid_conf, (unsigned)id); 2508 } 2509 2510 2511 /* 2512 * Establish unidirectional video flow from souce to sink. 2513 */ 2514 PJ_DEF(pj_status_t) pjsua_vid_conf_connect( pjsua_conf_port_id source, 2515 pjsua_conf_port_id sink, 2516 const void *param) 2517 { 2518 PJ_UNUSED_ARG(param); 2519 return pjmedia_vid_conf_connect_port(pjsua_var.vid_conf, source, sink, 2520 NULL); 2521 } 2522 2523 2524 /* 2525 * Disconnect video flow from the source to destination port. 2526 */ 2527 PJ_DEF(pj_status_t) pjsua_vid_conf_disconnect(pjsua_conf_port_id source, 2528 pjsua_conf_port_id sink) 2529 { 2530 return pjmedia_vid_conf_disconnect_port(pjsua_var.vid_conf, source, sink); 2531 } 2532 2533 /* 2534 * Get the video window associated with the call. 2535 */ 2536 PJ_DEF(pjsua_vid_win_id) pjsua_call_get_vid_win(pjsua_call_id call_id) 2537 { 2538 pjsua_call *call; 2539 pjsua_vid_win_id wid = PJSUA_INVALID_ID; 2540 unsigned i; 2541 2542 PJ_ASSERT_RETURN(call_id>=0 && call_id<(int)pjsua_var.ua_cfg.max_calls, 2543 PJ_EINVAL); 2544 2545 /* Use PJSUA_LOCK() instead of acquire_call(): 2546 * https://trac.pjsip.org/repos/ticket/1371 2547 */ 2548 PJSUA_LOCK(); 2549 2550 if (!pjsua_call_is_active(call_id)) 2551 goto on_return; 2552 2553 call = &pjsua_var.calls[call_id]; 2554 for (i = 0; i < call->med_cnt; ++i) { 2555 if (call->media[i].type == PJMEDIA_TYPE_VIDEO && 2556 (call->media[i].dir & PJMEDIA_DIR_DECODING)) 2557 { 2558 wid = call->media[i].strm.v.rdr_win_id; 2559 break; 2560 } 2561 } 2562 2563 on_return: 2564 PJSUA_UNLOCK(); 2565 2566 return wid; 2567 } 2568 2569 2570 /* 2571 * Get the video conference port identification associated with the call. 2572 */ 2573 PJ_DEF(pjsua_conf_port_id) pjsua_call_get_vid_conf_port( 2574 pjsua_call_id call_id, 2575 pjmedia_dir dir) 2576 { 2577 pjsua_call *call; 2578 pjsua_conf_port_id port_id = PJSUA_INVALID_ID; 2579 unsigned i; 2580 2581 PJ_ASSERT_RETURN(call_id>=0 && call_id<(int)pjsua_var.ua_cfg.max_calls, 2582 PJ_EINVAL); 2583 PJ_ASSERT_RETURN(dir==PJMEDIA_DIR_ENCODING || dir==PJMEDIA_DIR_DECODING, 2584 PJ_EINVAL); 2585 2586 /* Use PJSUA_LOCK() instead of acquire_call(): 2587 * https://trac.pjsip.org/repos/ticket/1371 2588 */ 2589 PJSUA_LOCK(); 2590 2591 if (!pjsua_call_is_active(call_id)) 2592 goto on_return; 2593 2594 call = &pjsua_var.calls[call_id]; 2595 for (i = 0; i < call->med_cnt; ++i) { 2596 if (call->media[i].type == PJMEDIA_TYPE_VIDEO && 2597 (call->media[i].dir & dir)) 2598 { 2599 port_id = (dir==PJMEDIA_DIR_ENCODING)? 2600 call->media[i].strm.v.strm_enc_slot : 2601 call->media[i].strm.v.strm_dec_slot; 2602 break; 2603 } 2604 } 2605 2606 on_return: 2607 PJSUA_UNLOCK(); 2608 2609 return port_id; 2610 } 2611 2612 2374 2613 #endif /* PJSUA_HAS_VIDEO */ 2375 2614
Note: See TracChangeset
for help on using the changeset viewer.