Changeset 3664 for pjproject/trunk/pjsip-apps/src/pjsua/pjsua_app.c
- Timestamp:
- Jul 19, 2011 3:42:28 AM (13 years ago)
- Location:
- pjproject/trunk
- Files:
-
- 2 edited
Legend:
- Unmodified
- Added
- Removed
-
pjproject/trunk
- Property svn:mergeinfo changed
-
pjproject/trunk/pjsip-apps/src/pjsua/pjsua_app.c
r3553 r3664 125 125 pjmedia_port *ring_port; 126 126 127 int vcapture_dev, vrender_dev; 127 128 } app_config; 128 129 … … 137 138 static pj_str_t uri_arg; 138 139 139 static char some_buf[1024 * 3]; 140 #if defined(PJMEDIA_HAS_RTCP_XR) && (PJMEDIA_HAS_RTCP_XR != 0) 141 # define SOME_BUF_SIZE (1024 * 10) 142 #else 143 # define SOME_BUF_SIZE (1024 * 3) 144 #endif 145 146 static char some_buf[SOME_BUF_SIZE]; 140 147 141 148 #ifdef STEREO_DEMO … … 195 202 puts (" --no-color Disable colorful logging"); 196 203 puts (" --light-bg Use dark colors for light background (default is dark bg)"); 204 puts (" --no-stderr Disable stderr"); 197 205 198 206 puts (""); … … 268 276 269 277 puts (""); 270 puts (" MediaOptions:");278 puts ("Audio Options:"); 271 279 puts (" --add-codec=name Manually add codec (default is to enable all)"); 272 280 puts (" --dis-codec=name Disable codec (can be specified multiple times)"); … … 302 310 puts (" --no-tones Disable audible tones"); 303 311 puts (" --jb-max-size Specify jitter buffer maximum size, in frames (default=-1)"); 312 puts (" --extra-audio Add one more audio stream"); 313 314 #if PJSUA_HAS_VIDEO 315 puts (""); 316 puts ("Video Options:"); 317 puts (" --video Enable video"); 318 puts (" --vcapture-dev=id Video capture device ID (default=-1)"); 319 puts (" --vrender-dev=id Video render device ID (default=-1)"); 320 #endif 304 321 305 322 puts (""); … … 377 394 for (i=0; i<PJ_ARRAY_SIZE(cfg->buddy_cfg); ++i) 378 395 pjsua_buddy_config_default(&cfg->buddy_cfg[i]); 396 397 cfg->vcapture_dev = PJSUA_INVALID_ID; 398 cfg->vrender_dev = PJSUA_INVALID_ID; 379 399 } 380 400 … … 510 530 int option_index; 511 531 enum { OPT_CONFIG_FILE=127, OPT_LOG_FILE, OPT_LOG_LEVEL, OPT_APP_LOG_LEVEL, 512 OPT_LOG_APPEND, OPT_COLOR, OPT_NO_COLOR, OPT_LIGHT_BG, 532 OPT_LOG_APPEND, OPT_COLOR, OPT_NO_COLOR, OPT_LIGHT_BG, OPT_NO_STDERR, 513 533 OPT_HELP, OPT_VERSION, OPT_NULL_AUDIO, OPT_SND_AUTO_CLOSE, 514 534 OPT_LOCAL_PORT, OPT_IP_ADDR, OPT_PROXY, OPT_OUTBOUND_PROXY, … … 542 562 OPT_AUTO_UPDATE_NAT,OPT_USE_COMPACT_FORM,OPT_DIS_CODEC, 543 563 OPT_NO_FORCE_LR, 544 OPT_TIMER, OPT_TIMER_SE, OPT_TIMER_MIN_SE 564 OPT_TIMER, OPT_TIMER_SE, OPT_TIMER_MIN_SE, 565 OPT_VIDEO, OPT_EXTRA_AUDIO, 566 OPT_VCAPTURE_DEV, OPT_VRENDER_DEV, 545 567 }; 546 568 struct pj_getopt_option long_options[] = { … … 553 575 { "no-color", 0, 0, OPT_NO_COLOR}, 554 576 { "light-bg", 0, 0, OPT_LIGHT_BG}, 577 { "no-stderr", 0, 0, OPT_NO_STDERR}, 555 578 { "help", 0, 0, OPT_HELP}, 556 579 { "version", 0, 0, OPT_VERSION}, … … 661 684 { "timer-min-se", 1, 0, OPT_TIMER_MIN_SE}, 662 685 { "outb-rid", 1, 0, OPT_OUTB_RID}, 686 { "video", 0, 0, OPT_VIDEO}, 687 { "extra-audio",0, 0, OPT_EXTRA_AUDIO}, 688 { "vcapture-dev", 1, 0, OPT_VCAPTURE_DEV}, 689 { "vrender-dev", 1, 0, OPT_VRENDER_DEV}, 663 690 { NULL, 0, 0, 0} 664 691 }; … … 751 778 pj_log_set_color(5, 0); 752 779 pj_log_set_color(77, 0); 780 break; 781 782 case OPT_NO_STDERR: 783 freopen("/dev/null", "w", stderr); 753 784 break; 754 785 … … 1418 1449 cfg->udp_cfg.qos_params.dscp_val = 0x18; 1419 1450 break; 1451 case OPT_VIDEO: 1452 ++cur_acc->max_video_cnt; 1453 cur_acc->vid_in_auto_show = PJ_TRUE; 1454 cur_acc->vid_out_auto_transmit = PJ_TRUE; 1455 PJ_TODO(implement_pjsua_option_for_vid_auto_show_and_transmit); 1456 break; 1457 case OPT_EXTRA_AUDIO: 1458 ++cur_acc->max_audio_cnt; 1459 break; 1460 1461 case OPT_VCAPTURE_DEV: 1462 cfg->vcapture_dev = atoi(pj_optarg); 1463 cur_acc->vid_cap_dev = cfg->vcapture_dev; 1464 break; 1465 1466 case OPT_VRENDER_DEV: 1467 cfg->vrender_dev = atoi(pj_optarg); 1468 cur_acc->vid_rend_dev = cfg->vrender_dev; 1469 break; 1470 1420 1471 default: 1421 1472 PJ_LOG(1,(THIS_FILE, … … 1662 1713 if (acc_cfg->mwi_enabled) 1663 1714 pj_strcat2(result, "--mwi\n"); 1715 1716 /* Video & extra audio */ 1717 for (i=0; i<acc_cfg->max_video_cnt; ++i) { 1718 pj_strcat2(result, "--video\n"); 1719 } 1720 for (i=1; i<acc_cfg->max_audio_cnt; ++i) { 1721 pj_strcat2(result, "--extra-audio\n"); 1722 } 1664 1723 } 1665 1724 … … 1986 2045 } 1987 2046 2047 if (config->vcapture_dev != PJSUA_INVALID_ID) { 2048 pj_ansi_sprintf(line, "--vcapture-dev %d\n", config->vcapture_dev); 2049 pj_strcat2(&cfg, line); 2050 } 2051 if (config->vrender_dev != PJSUA_INVALID_ID) { 2052 pj_ansi_sprintf(line, "--vrender-dev %d\n", config->vrender_dev); 2053 pj_strcat2(&cfg, line); 2054 } 1988 2055 1989 2056 /* ptime */ … … 2585 2652 } 2586 2653 2654 /* General processing for media state. "mi" is the media index */ 2655 static void on_call_generic_media_state(pjsua_call_info *ci, unsigned mi, 2656 pj_bool_t *has_error) 2657 { 2658 const char *status_name[] = { 2659 "None", 2660 "Active", 2661 "Local hold", 2662 "Remote hold", 2663 "Error" 2664 }; 2665 2666 pj_assert(ci->media[mi].status <= PJ_ARRAY_SIZE(status_name)); 2667 pj_assert(PJSUA_CALL_MEDIA_ERROR == 4); 2668 2669 PJ_LOG(4,(THIS_FILE, "Call %d media %d [type=%s], status is %s", 2670 ci->id, mi, pjmedia_type_name(ci->media[mi].type), 2671 status_name[ci->media[mi].status])); 2672 } 2673 2674 /* Process audio media state. "mi" is the media index. */ 2675 static void on_call_audio_state(pjsua_call_info *ci, unsigned mi, 2676 pj_bool_t *has_error) 2677 { 2678 /* Stop ringback */ 2679 ring_stop(ci->id); 2680 2681 /* Connect ports appropriately when media status is ACTIVE or REMOTE HOLD, 2682 * otherwise we should NOT connect the ports. 2683 */ 2684 if (ci->media[mi].status == PJSUA_CALL_MEDIA_ACTIVE || 2685 ci->media[mi].status == PJSUA_CALL_MEDIA_REMOTE_HOLD) 2686 { 2687 pj_bool_t connect_sound = PJ_TRUE; 2688 pjsua_conf_port_id call_conf_slot; 2689 2690 call_conf_slot = ci->media[mi].stream.aud.conf_slot; 2691 2692 /* Loopback sound, if desired */ 2693 if (app_config.auto_loop) { 2694 pjsua_conf_connect(call_conf_slot, call_conf_slot); 2695 connect_sound = PJ_FALSE; 2696 } 2697 2698 /* Automatically record conversation, if desired */ 2699 if (app_config.auto_rec && app_config.rec_port != PJSUA_INVALID_ID) { 2700 pjsua_conf_connect(call_conf_slot, app_config.rec_port); 2701 } 2702 2703 /* Stream a file, if desired */ 2704 if ((app_config.auto_play || app_config.auto_play_hangup) && 2705 app_config.wav_port != PJSUA_INVALID_ID) 2706 { 2707 pjsua_conf_connect(app_config.wav_port, call_conf_slot); 2708 connect_sound = PJ_FALSE; 2709 } 2710 2711 /* Put call in conference with other calls, if desired */ 2712 if (app_config.auto_conf) { 2713 pjsua_call_id call_ids[PJSUA_MAX_CALLS]; 2714 unsigned call_cnt=PJ_ARRAY_SIZE(call_ids); 2715 unsigned i; 2716 2717 /* Get all calls, and establish media connection between 2718 * this call and other calls. 2719 */ 2720 pjsua_enum_calls(call_ids, &call_cnt); 2721 2722 for (i=0; i<call_cnt; ++i) { 2723 if (call_ids[i] == ci->id) 2724 continue; 2725 2726 if (!pjsua_call_has_media(call_ids[i])) 2727 continue; 2728 2729 pjsua_conf_connect(call_conf_slot, 2730 pjsua_call_get_conf_port(call_ids[i])); 2731 pjsua_conf_connect(pjsua_call_get_conf_port(call_ids[i]), 2732 call_conf_slot); 2733 2734 /* Automatically record conversation, if desired */ 2735 if (app_config.auto_rec && app_config.rec_port != PJSUA_INVALID_ID) { 2736 pjsua_conf_connect(pjsua_call_get_conf_port(call_ids[i]), 2737 app_config.rec_port); 2738 } 2739 2740 } 2741 2742 /* Also connect call to local sound device */ 2743 connect_sound = PJ_TRUE; 2744 } 2745 2746 /* Otherwise connect to sound device */ 2747 if (connect_sound) { 2748 pjsua_conf_connect(call_conf_slot, 0); 2749 pjsua_conf_connect(0, call_conf_slot); 2750 2751 /* Automatically record conversation, if desired */ 2752 if (app_config.auto_rec && app_config.rec_port != PJSUA_INVALID_ID) { 2753 pjsua_conf_connect(call_conf_slot, app_config.rec_port); 2754 pjsua_conf_connect(0, app_config.rec_port); 2755 } 2756 } 2757 } 2758 } 2759 2760 /* Process video media state. "mi" is the media index. */ 2761 static void on_call_video_state(pjsua_call_info *ci, unsigned mi, 2762 pj_bool_t *has_error) 2763 { 2764 } 2587 2765 2588 2766 /* … … 2594 2772 { 2595 2773 pjsua_call_info call_info; 2774 unsigned mi; 2775 pj_bool_t has_error = PJ_FALSE; 2596 2776 2597 2777 pjsua_call_get_info(call_id, &call_info); 2598 2778 2599 /* Stop ringback */ 2600 ring_stop(call_id); 2601 2602 /* Connect ports appropriately when media status is ACTIVE or REMOTE HOLD, 2603 * otherwise we should NOT connect the ports. 2604 */ 2605 if (call_info.media_status == PJSUA_CALL_MEDIA_ACTIVE || 2606 call_info.media_status == PJSUA_CALL_MEDIA_REMOTE_HOLD) 2607 { 2608 pj_bool_t connect_sound = PJ_TRUE; 2609 2610 /* Loopback sound, if desired */ 2611 if (app_config.auto_loop) { 2612 pjsua_conf_connect(call_info.conf_slot, call_info.conf_slot); 2613 connect_sound = PJ_FALSE; 2779 for (mi=0; mi<call_info.media_cnt; ++mi) { 2780 on_call_generic_media_state(&call_info, mi, &has_error); 2781 2782 switch (call_info.media[mi].type) { 2783 case PJMEDIA_TYPE_AUDIO: 2784 on_call_audio_state(&call_info, mi, &has_error); 2785 break; 2786 case PJMEDIA_TYPE_VIDEO: 2787 on_call_video_state(&call_info, mi, &has_error); 2788 break; 2614 2789 } 2615 2616 /* Automatically record conversation, if desired */ 2617 if (app_config.auto_rec && app_config.rec_port != PJSUA_INVALID_ID) { 2618 pjsua_conf_connect(call_info.conf_slot, app_config.rec_port); 2619 } 2620 2621 /* Stream a file, if desired */ 2622 if ((app_config.auto_play || app_config.auto_play_hangup) && 2623 app_config.wav_port != PJSUA_INVALID_ID) 2624 { 2625 pjsua_conf_connect(app_config.wav_port, call_info.conf_slot); 2626 connect_sound = PJ_FALSE; 2627 } 2628 2629 /* Put call in conference with other calls, if desired */ 2630 if (app_config.auto_conf) { 2631 pjsua_call_id call_ids[PJSUA_MAX_CALLS]; 2632 unsigned call_cnt=PJ_ARRAY_SIZE(call_ids); 2633 unsigned i; 2634 2635 /* Get all calls, and establish media connection between 2636 * this call and other calls. 2637 */ 2638 pjsua_enum_calls(call_ids, &call_cnt); 2639 2640 for (i=0; i<call_cnt; ++i) { 2641 if (call_ids[i] == call_id) 2642 continue; 2643 2644 if (!pjsua_call_has_media(call_ids[i])) 2645 continue; 2646 2647 pjsua_conf_connect(call_info.conf_slot, 2648 pjsua_call_get_conf_port(call_ids[i])); 2649 pjsua_conf_connect(pjsua_call_get_conf_port(call_ids[i]), 2650 call_info.conf_slot); 2651 2652 /* Automatically record conversation, if desired */ 2653 if (app_config.auto_rec && app_config.rec_port != PJSUA_INVALID_ID) { 2654 pjsua_conf_connect(pjsua_call_get_conf_port(call_ids[i]), 2655 app_config.rec_port); 2656 } 2657 2658 } 2659 2660 /* Also connect call to local sound device */ 2661 connect_sound = PJ_TRUE; 2662 } 2663 2664 /* Otherwise connect to sound device */ 2665 if (connect_sound) { 2666 pjsua_conf_connect(call_info.conf_slot, 0); 2667 pjsua_conf_connect(0, call_info.conf_slot); 2668 2669 /* Automatically record conversation, if desired */ 2670 if (app_config.auto_rec && app_config.rec_port != PJSUA_INVALID_ID) { 2671 pjsua_conf_connect(call_info.conf_slot, app_config.rec_port); 2672 pjsua_conf_connect(0, app_config.rec_port); 2673 } 2674 } 2675 } 2676 2677 /* Handle media status */ 2678 switch (call_info.media_status) { 2679 case PJSUA_CALL_MEDIA_ACTIVE: 2680 PJ_LOG(3,(THIS_FILE, "Media for call %d is active", call_id)); 2681 break; 2682 2683 case PJSUA_CALL_MEDIA_LOCAL_HOLD: 2684 PJ_LOG(3,(THIS_FILE, "Media for call %d is suspended (hold) by local", 2685 call_id)); 2686 break; 2687 2688 case PJSUA_CALL_MEDIA_REMOTE_HOLD: 2689 PJ_LOG(3,(THIS_FILE, 2690 "Media for call %d is suspended (hold) by remote", 2691 call_id)); 2692 break; 2693 2694 case PJSUA_CALL_MEDIA_ERROR: 2695 PJ_LOG(3,(THIS_FILE, 2696 "Media has reported error, disconnecting call")); 2697 { 2698 pj_str_t reason = pj_str("ICE negotiation failed"); 2699 pjsua_call_hangup(call_id, 500, &reason, NULL); 2700 } 2701 break; 2702 2703 case PJSUA_CALL_MEDIA_NONE: 2704 PJ_LOG(3,(THIS_FILE, 2705 "Media for call %d is inactive", 2706 call_id)); 2707 break; 2708 2709 default: 2710 pj_assert(!"Unhandled media status"); 2711 break; 2790 } 2791 2792 if (has_error) { 2793 pj_str_t reason = pj_str("Media failed"); 2794 pjsua_call_hangup(call_id, 500, &reason, NULL); 2712 2795 } 2713 2796 } … … 3050 3133 PJ_PERROR(1,(THIS_FILE, status, 3051 3134 "ICE keep alive failure for transport %d", index)); 3135 } 3136 3137 /* 3138 * Notification on sound device operation. 3139 */ 3140 static pj_status_t on_snd_dev_operation(int operation) 3141 { 3142 PJ_LOG(3,(THIS_FILE, "Turning sound device %s", (operation? "ON":"OFF"))); 3143 return PJ_SUCCESS; 3144 } 3145 3146 /* Callback on media events */ 3147 static void on_call_media_event(pjsua_call_id call_id, 3148 unsigned med_idx, 3149 pjmedia_event *event) 3150 { 3151 char event_name[5]; 3152 PJ_LOG(4,(THIS_FILE, "Event %s", 3153 pjmedia_fourcc_name(event->type, event_name))); 3052 3154 } 3053 3155 … … 3194 3296 puts("| dq Dump curr. call quality | cd Disconnect port | dc Dump config |"); 3195 3297 puts("| | V Adjust audio Volume | f Save config |"); 3196 puts("| S Send arbitrary REQUEST | Cp Codec priorities | f Save config |"); 3197 puts("+------------------------------+--------------------------+-------------------+"); 3298 puts("| S Send arbitrary REQUEST | Cp Codec priorities | |"); 3299 puts("+-----------------------------------------------------------------------------+"); 3300 #if PJSUA_HAS_VIDEO 3301 puts("| Video: \"vid help\" for more info |"); 3302 puts("+-----------------------------------------------------------------------------+"); 3303 #endif 3198 3304 puts("| q QUIT L ReLoad sleep MS echo [0|1|txt] n: detect NAT type |"); 3199 3305 puts("+=============================================================================+"); … … 3211 3317 } 3212 3318 3319 /* Help screen for video */ 3320 static void vid_show_help(void) 3321 { 3322 #if PJSUA_HAS_VIDEO 3323 puts("+=============================================================================+"); 3324 puts("| Video commands: |"); 3325 puts("| |"); 3326 puts("| vid help Show this help screen |"); 3327 puts("| vid call rx on|off N Enable/disable video rx for stream N in curr call |"); 3328 puts("| vid call tx on|off N Enable/disable video tx for stream N in curr call |"); 3329 puts("| vid call add Add video stream for current call |"); 3330 puts("| vid call enable/disable N Enable/disable stream #N in current call |"); 3331 puts("| vid call set-cap N ID Set capture dev ID for stream #N in current call |"); 3332 puts("| vid dev list List all video devices |"); 3333 puts("| vid dev refresh Refresh video device list |"); 3334 puts("| vid dev prev on|off ID Enable/disable preview for specified device ID |"); 3335 puts("| vid codec list List video codecs |"); 3336 puts("| vid codec prio PT PRIO Set codec with pt PT priority to PRIO |"); 3337 puts("| vid win list List all active video windows |"); 3338 puts("| vid win show|hide ID Show/hide the specified video window ID |"); 3339 puts("| vid win move ID X Y Move window ID to position X,Y |"); 3340 puts("| vid win resize ID w h Resize window ID to the specified width, height |"); 3341 puts("+=============================================================================+"); 3342 #endif 3343 } 3213 3344 3214 3345 /* … … 3482 3613 pj_status_t status; 3483 3614 3484 printf("List of codecs:\n"); 3485 3615 printf("List of audio codecs:\n"); 3486 3616 pjsua_enum_codecs(c, &count); 3487 3617 for (i=0; i<count; ++i) { … … 3490 3620 } 3491 3621 3622 #if PJSUA_HAS_VIDEO 3492 3623 puts(""); 3493 puts("Enter codec id and its new priority " 3494 "(e.g. \"speex/16000 200\"), empty to cancel:"); 3624 printf("List of video codecs:\n"); 3625 pjsua_vid_enum_codecs(c, &count); 3626 for (i=0; i<count; ++i) { 3627 printf(" %d\t%.*s%s%.*s\n", c[i].priority, 3628 (int)c[i].codec_id.slen, 3629 c[i].codec_id.ptr, 3630 c[i].desc.slen? " - ":"", 3631 (int)c[i].desc.slen, 3632 c[i].desc.ptr); 3633 } 3634 #endif 3635 3636 puts(""); 3637 puts("Enter codec id and its new priority (e.g. \"speex/16000 200\", ""\"H263 200\"),"); 3638 puts("or empty to cancel."); 3495 3639 3496 3640 printf("Codec name (\"*\" for all) and priority: "); … … 3518 3662 status = pjsua_codec_set_priority(pj_cstr(&id, codec), 3519 3663 (pj_uint8_t)new_prio); 3664 #if PJSUA_HAS_VIDEO 3665 if (status != PJ_SUCCESS) { 3666 status = pjsua_vid_codec_set_priority(pj_cstr(&id, codec), 3667 (pj_uint8_t)new_prio); 3668 } 3669 #endif 3520 3670 if (status != PJ_SUCCESS) 3521 3671 pjsua_perror(THIS_FILE, "Error setting codec priority", status); 3522 3672 } 3673 3674 3675 #if PJSUA_HAS_VIDEO 3676 static void vid_print_dev(int id, const pjmedia_vid_dev_info *vdi, 3677 const char *title) 3678 { 3679 char capnames[120]; 3680 char formats[120]; 3681 const char *dirname; 3682 unsigned i; 3683 3684 if (vdi->dir == PJMEDIA_DIR_CAPTURE_RENDER) { 3685 dirname = "capture, render"; 3686 } else if (vdi->dir == PJMEDIA_DIR_CAPTURE) { 3687 dirname = "capture"; 3688 } else { 3689 dirname = "render"; 3690 } 3691 3692 3693 capnames[0] = '\0'; 3694 for (i=0; i<sizeof(int)*8 && (1 << i) < PJMEDIA_VID_DEV_CAP_MAX; ++i) { 3695 if (vdi->caps & (1 << i)) { 3696 const char *capname = pjmedia_vid_dev_cap_name(1 << i, NULL); 3697 if (capname) { 3698 if (*capnames) 3699 strcat(capnames, ", "); 3700 strncat(capnames, capname, 3701 sizeof(capnames)-strlen(capnames)-1); 3702 } 3703 } 3704 } 3705 3706 formats[0] = '\0'; 3707 for (i=0; i<vdi->fmt_cnt; ++i) { 3708 const pjmedia_video_format_info *vfi = 3709 pjmedia_get_video_format_info(NULL, vdi->fmt[i].id); 3710 if (vfi) { 3711 if (*formats) 3712 strcat(formats, ", "); 3713 strncat(formats, vfi->name, sizeof(formats)-strlen(formats)-1); 3714 } 3715 } 3716 3717 PJ_LOG(3,(THIS_FILE, "%3d %s [%s][%s] %s", id, vdi->name, vdi->driver, 3718 dirname, title)); 3719 PJ_LOG(3,(THIS_FILE, " Supported capabilities: %s", capnames)); 3720 PJ_LOG(3,(THIS_FILE, " Supported formats: %s", formats)); 3721 } 3722 3723 static void vid_list_devs(void) 3724 { 3725 unsigned i, count; 3726 pjmedia_vid_dev_info vdi; 3727 pj_status_t status; 3728 3729 PJ_LOG(3,(THIS_FILE, "Video device list:")); 3730 count = pjsua_vid_dev_count(); 3731 if (count == 0) { 3732 PJ_LOG(3,(THIS_FILE, " - no device detected -")); 3733 return; 3734 } else { 3735 PJ_LOG(3,(THIS_FILE, "%d device(s) detected:", count)); 3736 } 3737 3738 status = pjsua_vid_dev_get_info(PJMEDIA_VID_DEFAULT_RENDER_DEV, &vdi); 3739 if (status == PJ_SUCCESS) 3740 vid_print_dev(PJMEDIA_VID_DEFAULT_RENDER_DEV, &vdi, 3741 "(default renderer device)"); 3742 3743 status = pjsua_vid_dev_get_info(PJMEDIA_VID_DEFAULT_CAPTURE_DEV, &vdi); 3744 if (status == PJ_SUCCESS) 3745 vid_print_dev(PJMEDIA_VID_DEFAULT_CAPTURE_DEV, &vdi, 3746 "(default capture device)"); 3747 3748 for (i=0; i<count; ++i) { 3749 status = pjsua_vid_dev_get_info(i, &vdi); 3750 if (status == PJ_SUCCESS) 3751 vid_print_dev(i, &vdi, ""); 3752 } 3753 } 3754 3755 static void vid_handle_menu(char *menuin) 3756 { 3757 char *argv[8]; 3758 int argc = 0; 3759 3760 /* Tokenize */ 3761 argv[argc] = strtok(menuin, " \t\r\n"); 3762 while (argv[argc] && *argv[argc]) { 3763 argc++; 3764 argv[argc] = strtok(NULL, " \t\r\n"); 3765 } 3766 3767 if (strcmp(argv[1], "help")==0 || argc == 1) { 3768 vid_show_help(); 3769 } else if (strcmp(argv[1], "call")==0) { 3770 pjsua_call_vid_strm_op_param param; 3771 3772 if (argc == 5 && strcmp(argv[2], "rx")==0) { 3773 pjsua_stream_info si; 3774 pj_bool_t on = (strcmp(argv[3], "on") == 0); 3775 3776 param.med_idx = atoi(argv[4]); 3777 if (pjsua_call_get_stream_info(current_call, param.med_idx, &si) || 3778 si.type != PJMEDIA_TYPE_VIDEO) 3779 { 3780 PJ_PERROR(1,(THIS_FILE, PJ_EINVAL, "Invalid stream")); 3781 return; 3782 } 3783 3784 if (on) param.dir = (si.info.vid.dir | PJMEDIA_DIR_DECODING); 3785 else param.dir = (si.info.vid.dir & PJMEDIA_DIR_ENCODING); 3786 3787 pjsua_call_set_vid_strm(current_call, PJSUA_CALL_VID_STRM_CHANGE_DIR, ¶m); 3788 } 3789 else if (argc == 5 && strcmp(argv[2], "tx")==0) { 3790 pj_bool_t on = (strcmp(argv[3], "on") == 0); 3791 pjsua_call_vid_strm_op op = on? PJSUA_CALL_VID_STRM_START_TRANSMIT : 3792 PJSUA_CALL_VID_STRM_STOP_TRANSMIT; 3793 3794 param.med_idx = atoi(argv[4]); 3795 3796 pjsua_call_set_vid_strm(current_call, op, ¶m); 3797 } 3798 else if (argc == 3 && strcmp(argv[2], "add")==0) { 3799 pjsua_call_set_vid_strm(current_call, PJSUA_CALL_VID_STRM_ADD, NULL); 3800 } 3801 else if (argc >= 3 && 3802 (strcmp(argv[2], "disable")==0 || strcmp(argv[2], "enable")==0)) 3803 { 3804 pj_bool_t enable = (strcmp(argv[2], "enable") == 0); 3805 pjsua_call_vid_strm_op op = enable? PJSUA_CALL_VID_STRM_CHANGE_DIR : 3806 PJSUA_CALL_VID_STRM_REMOVE; 3807 3808 param.med_idx = argc >= 4? atoi(argv[3]) : -1; 3809 param.dir = PJMEDIA_DIR_ENCODING_DECODING; 3810 pjsua_call_set_vid_strm(current_call, op, ¶m); 3811 } 3812 else if (argc >= 3 && strcmp(argv[2], "set-cap")==0) { 3813 param.med_idx = argc >= 4? atoi(argv[3]) : -1; 3814 param.cap_dev = argc >= 5? atoi(argv[4]) : PJMEDIA_VID_DEFAULT_CAPTURE_DEV; 3815 pjsua_call_set_vid_strm(current_call, PJSUA_CALL_VID_STRM_CHANGE_CAP_DEV, ¶m); 3816 } else 3817 goto on_error; 3818 } else if (argc >= 3 && strcmp(argv[1], "dev")==0) { 3819 if (strcmp(argv[2], "list")==0) { 3820 vid_list_devs(); 3821 } else if (strcmp(argv[2], "refresh")==0) { 3822 pjmedia_vid_dev_refresh(); 3823 } else if (strcmp(argv[2], "prev")==0) { 3824 if (argc != 5) { 3825 goto on_error; 3826 } else { 3827 pj_bool_t on = (strcmp(argv[3], "on") == 0); 3828 int dev_id = atoi(argv[4]); 3829 if (on) { 3830 pjsua_vid_preview_start(dev_id, NULL); 3831 } else { 3832 pjsua_vid_preview_stop(dev_id); 3833 } 3834 } 3835 } else 3836 goto on_error; 3837 } else if (strcmp(argv[1], "win")==0) { 3838 if (argc==3 && strcmp(argv[2], "list")==0) { 3839 pjsua_vid_win_id wids[PJSUA_MAX_VID_WINS]; 3840 unsigned i, cnt = PJ_ARRAY_SIZE(wids); 3841 3842 pjsua_vid_enum_wins(wids, &cnt); 3843 3844 PJ_LOG(3,(THIS_FILE, "Found %d video windows:", cnt)); 3845 PJ_LOG(3,(THIS_FILE, "WID show pos size")); 3846 PJ_LOG(3,(THIS_FILE, "------------------------------")); 3847 for (i = 0; i < cnt; ++i) { 3848 pjsua_vid_win_info wi; 3849 pjsua_vid_win_get_info(wids[i], &wi); 3850 PJ_LOG(3,(THIS_FILE, "%3d %c (%d,%d) %dx%d", 3851 wids[i], (wi.show?'Y':'N'), wi.pos.x, wi.pos.y, 3852 wi.size.w, wi.size.h)); 3853 } 3854 } else if (argc==4 && (strcmp(argv[2], "show")==0 || 3855 strcmp(argv[2], "hide")==0)) 3856 { 3857 pj_bool_t show = (strcmp(argv[2], "show")==0); 3858 pjsua_vid_win_id wid = atoi(argv[3]); 3859 pjsua_vid_win_set_show(wid, show); 3860 } else if (argc==6 && strcmp(argv[2], "move")==0) { 3861 pjsua_vid_win_id wid = atoi(argv[3]); 3862 pjmedia_coord pos; 3863 3864 pos.x = atoi(argv[4]); 3865 pos.y = atoi(argv[5]); 3866 pjsua_vid_win_set_pos(wid, &pos); 3867 } else if (argc==6 && strcmp(argv[2], "resize")==0) { 3868 pjsua_vid_win_id wid = atoi(argv[3]); 3869 pjmedia_rect_size size; 3870 3871 size.w = atoi(argv[4]); 3872 size.h = atoi(argv[5]); 3873 pjsua_vid_win_set_size(wid, &size); 3874 } else 3875 goto on_error; 3876 } else if (strcmp(argv[1], "codec")==0) { 3877 pjmedia_vid_codec_info ci[PJMEDIA_CODEC_MGR_MAX_CODECS]; 3878 unsigned prio[PJMEDIA_CODEC_MGR_MAX_CODECS]; 3879 unsigned count = PJMEDIA_CODEC_MGR_MAX_CODECS; 3880 pj_status_t status; 3881 3882 if (argc==3 && strcmp(argv[2], "list")==0) { 3883 status = pjmedia_vid_codec_mgr_enum_codecs(NULL, &count, ci, prio); 3884 if (status != PJ_SUCCESS) { 3885 PJ_PERROR(1,(THIS_FILE, status, "Error enumerating codecs")); 3886 } else { 3887 unsigned i; 3888 PJ_LOG(3,(THIS_FILE, "Found %d video codecs:", count)); 3889 PJ_LOG(3,(THIS_FILE, " PT Prio Name")); 3890 PJ_LOG(3,(THIS_FILE, "-------------------------")); 3891 for (i=0; i<count; ++i) { 3892 PJ_LOG(3,(THIS_FILE, "% 3d % 3d %.*s", ci[i].pt, prio[i], 3893 (int)ci[i].encoding_name.slen, 3894 ci[i].encoding_name.ptr)); 3895 } 3896 } 3897 } else if (argc==5 && strcmp(argv[2], "prio")==0) { 3898 int pt = atoi(argv[3]); 3899 int prio = atoi(argv[4]); 3900 const pjmedia_vid_codec_info *pci; 3901 3902 status = pjmedia_vid_codec_mgr_get_codec_info(NULL, pt, &pci); 3903 if (status != PJ_SUCCESS) { 3904 PJ_PERROR(1,(THIS_FILE, status, "Unable to find codec")); 3905 } else { 3906 char codec_id[40]; 3907 if (pjmedia_vid_codec_info_to_id(pci, codec_id, 3908 sizeof(codec_id)) == NULL) 3909 { 3910 PJ_PERROR(1,(THIS_FILE, status, "Unable to get codec id")); 3911 } else { 3912 pj_str_t cid = pj_str(codec_id); 3913 status = pjsua_vid_codec_set_priority(&cid, 3914 (pj_uint8_t)prio); 3915 } 3916 } 3917 3918 } else 3919 goto on_error; 3920 } else 3921 goto on_error; 3922 3923 return; 3924 3925 on_error: 3926 PJ_LOG(1,(THIS_FILE, "Invalid command, use 'vid help'")); 3927 } 3928 3929 #endif /* PJSUA_HAS_VIDEO */ 3523 3930 3524 3931 … … 3893 4300 acc_cfg.cred_info[0].data = pj_str(passwd); 3894 4301 4302 acc_cfg.rtp_cfg = app_config.rtp_cfg; 4303 3895 4304 status = pjsua_acc_add(&acc_cfg, PJ_TRUE, NULL); 3896 4305 if (status != PJ_SUCCESS) { … … 3950 4359 3951 4360 case 'v': 3952 /* 3953 * Send re-INVITE (to release hold, etc). 3954 */ 4361 #if PJSUA_HAS_VIDEO 4362 if (menuin[1]=='i' && menuin[2]=='d' && menuin[3]==' ') { 4363 4364 vid_handle_menu(menuin); 4365 4366 } else 4367 #endif 3955 4368 if (current_call != -1) { 3956 4369 /* 4370 * re-INVITE 4371 */ 3957 4372 pjsua_call_reinvite(current_call, PJ_TRUE, NULL); 3958 4373 … … 4512 4927 } 4513 4928 4929 /* 4930 * A simple registrar, invoked by default_mod_on_rx_request() 4931 */ 4932 static void simple_registrar(pjsip_rx_data *rdata) 4933 { 4934 pjsip_tx_data *tdata; 4935 const pjsip_expires_hdr *exp; 4936 const pjsip_hdr *h; 4937 unsigned cnt = 0; 4938 pjsip_generic_string_hdr *srv; 4939 pj_status_t status; 4940 4941 status = pjsip_endpt_create_response(pjsua_get_pjsip_endpt(), 4942 rdata, 200, NULL, &tdata); 4943 if (status != PJ_SUCCESS) 4944 return; 4945 4946 exp = pjsip_msg_find_hdr(rdata->msg_info.msg, PJSIP_H_EXPIRES, NULL); 4947 4948 h = rdata->msg_info.msg->hdr.next; 4949 while (h != &rdata->msg_info.msg->hdr) { 4950 if (h->type == PJSIP_H_CONTACT) { 4951 const pjsip_contact_hdr *c = (const pjsip_contact_hdr*)h; 4952 int e = c->expires; 4953 4954 if (e < 0) { 4955 if (exp) 4956 e = exp->ivalue; 4957 else 4958 e = 3600; 4959 } 4960 4961 if (e > 0) { 4962 pjsip_contact_hdr *nc = pjsip_hdr_clone(tdata->pool, h); 4963 nc->expires = e; 4964 pjsip_msg_add_hdr(tdata->msg, (pjsip_hdr*)nc); 4965 ++cnt; 4966 } 4967 } 4968 h = h->next; 4969 } 4970 4971 srv = pjsip_generic_string_hdr_create(tdata->pool, NULL, NULL); 4972 srv->name = pj_str("Server"); 4973 srv->hvalue = pj_str("pjsua simple registrar"); 4974 pjsip_msg_add_hdr(tdata->msg, (pjsip_hdr*)srv); 4975 4976 pjsip_endpt_send_response2(pjsua_get_pjsip_endpt(), 4977 rdata, tdata, NULL, NULL); 4978 } 4979 4980 4981 4514 4982 /***************************************************************************** 4515 4983 * A simple module to handle otherwise unhandled request. We will register … … 4525 4993 4526 4994 /* Don't respond to ACK! */ 4527 if (pjsip_method_cmp(&rdata->msg_info.msg->line.req.method, 4995 if (pjsip_method_cmp(&rdata->msg_info.msg->line.req.method, 4528 4996 &pjsip_ack_method) == 0) 4529 4997 return PJ_TRUE; 4998 4999 /* Simple registrar */ 5000 if (pjsip_method_cmp(&rdata->msg_info.msg->line.req.method, 5001 &pjsip_register_method) == 0) 5002 { 5003 simple_registrar(rdata); 5004 return PJ_TRUE; 5005 } 4530 5006 4531 5007 /* Create basic response. */ … … 4652 5128 app_config.cfg.cb.on_transport_state = &on_transport_state; 4653 5129 app_config.cfg.cb.on_ice_transport_error = &on_ice_transport_error; 5130 app_config.cfg.cb.on_snd_dev_operation = &on_snd_dev_operation; 5131 app_config.cfg.cb.on_call_media_event = &on_call_media_event; 4654 5132 app_config.log_cfg.cb = log_cb; 4655 5133 … … 4930 5408 /* Add accounts */ 4931 5409 for (i=0; i<app_config.acc_cnt; ++i) { 5410 app_config.acc_cfg[i].rtp_cfg = app_config.rtp_cfg; 4932 5411 status = pjsua_acc_add(&app_config.acc_cfg[i], PJ_TRUE, NULL); 4933 5412 if (status != PJ_SUCCESS) … … 4946 5425 for (i=0; i<app_config.codec_dis_cnt; ++i) { 4947 5426 pjsua_codec_set_priority(&app_config.codec_dis[i],PJMEDIA_CODEC_PRIO_DISABLED); 5427 #if PJSUA_HAS_VIDEO 5428 pjsua_vid_codec_set_priority(&app_config.codec_dis[i],PJMEDIA_CODEC_PRIO_DISABLED); 5429 #endif 4948 5430 } 4949 5431 … … 4952 5434 pjsua_codec_set_priority(&app_config.codec_arg[i], 4953 5435 (pj_uint8_t)(PJMEDIA_CODEC_PRIO_NORMAL+i+9)); 5436 #if PJSUA_HAS_VIDEO 5437 pjsua_vid_codec_set_priority(&app_config.codec_arg[i], 5438 (pj_uint8_t)(PJMEDIA_CODEC_PRIO_NORMAL+i+9)); 5439 #endif 4954 5440 } 4955 5441 … … 4961 5447 if (app_config.ipv6) 4962 5448 status = create_ipv6_media_transports(); 5449 #if DISABLED_FOR_TICKET_1185 4963 5450 else 4964 5451 status = pjsua_media_transports_create(&app_config.rtp_cfg); 5452 #endif 4965 5453 #endif 4966 5454 if (status != PJ_SUCCESS) … … 4984 5472 goto on_error; 4985 5473 } 5474 5475 #if PJSUA_HAS_VIDEO 5476 if (app_config.vcapture_dev != PJSUA_INVALID_ID || 5477 app_config.vrender_dev != PJSUA_INVALID_ID) 5478 { 5479 //status = pjsua_vid_set_dev(app_config.vcapture_dev, 5480 // app_config.vrender_dev); 5481 PJ_TODO(vid_implement_pjsua_vid_set_dev); 5482 if (status != PJ_SUCCESS) 5483 goto on_error; 5484 } 5485 #endif 4986 5486 4987 5487 return PJ_SUCCESS; … … 5297 5797 } 5298 5798 5799 #if DISABLED_FOR_TICKET_1185 5299 5800 return pjsua_media_transports_attach(tp, i, PJ_TRUE); 5300 } 5301 5801 #else 5802 return PJ_ENOTSUP; 5803 #endif 5804 } 5805
Note: See TracChangeset
for help on using the changeset viewer.