- Timestamp:
- Jul 7, 2011 7:46:33 AM (13 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
pjproject/branches/projects/2.0-dev/pjsip-apps/src/pjsua/pjsua_app.c
r3519 r3609 312 312 puts (" --extra-audio Add one more audio stream"); 313 313 314 #if PJ MEDIA_HAS_VIDEO314 #if PJSUA_HAS_VIDEO 315 315 puts (""); 316 316 puts ("Video Options:"); … … 2646 2646 } 2647 2647 2648 /* General processing for media state. "mi" is the media index */ 2649 static void on_call_generic_media_state(pjsua_call_info *ci, unsigned mi, 2650 pj_bool_t *has_error) 2651 { 2652 const char *status_name[] = { 2653 "None", 2654 "Active", 2655 "Local hold", 2656 "Remote hold", 2657 "Error" 2658 }; 2659 2660 pj_assert(ci->media[mi].status <= PJ_ARRAY_SIZE(status_name)); 2661 pj_assert(PJSUA_CALL_MEDIA_ERROR == 4); 2662 2663 PJ_LOG(4,(THIS_FILE, "Call %d media %d [type=%s], status is %s", 2664 ci->id, mi, pjmedia_type_name(ci->media[mi].type), 2665 status_name[ci->media[mi].status])); 2666 } 2667 2668 /* Process audio media state. "mi" is the media index. */ 2669 static void on_call_audio_state(pjsua_call_info *ci, unsigned mi, 2670 pj_bool_t *has_error) 2671 { 2672 /* Stop ringback */ 2673 ring_stop(ci->id); 2674 2675 /* Connect ports appropriately when media status is ACTIVE or REMOTE HOLD, 2676 * otherwise we should NOT connect the ports. 2677 */ 2678 if (ci->media[mi].status == PJSUA_CALL_MEDIA_ACTIVE || 2679 ci->media[mi].status == PJSUA_CALL_MEDIA_REMOTE_HOLD) 2680 { 2681 pj_bool_t connect_sound = PJ_TRUE; 2682 pjsua_conf_port_id call_conf_slot; 2683 2684 call_conf_slot = ci->media[mi].stream.aud.conf_slot; 2685 2686 /* Loopback sound, if desired */ 2687 if (app_config.auto_loop) { 2688 pjsua_conf_connect(call_conf_slot, call_conf_slot); 2689 connect_sound = PJ_FALSE; 2690 } 2691 2692 /* Automatically record conversation, if desired */ 2693 if (app_config.auto_rec && app_config.rec_port != PJSUA_INVALID_ID) { 2694 pjsua_conf_connect(call_conf_slot, app_config.rec_port); 2695 } 2696 2697 /* Stream a file, if desired */ 2698 if ((app_config.auto_play || app_config.auto_play_hangup) && 2699 app_config.wav_port != PJSUA_INVALID_ID) 2700 { 2701 pjsua_conf_connect(app_config.wav_port, call_conf_slot); 2702 connect_sound = PJ_FALSE; 2703 } 2704 2705 /* Put call in conference with other calls, if desired */ 2706 if (app_config.auto_conf) { 2707 pjsua_call_id call_ids[PJSUA_MAX_CALLS]; 2708 unsigned call_cnt=PJ_ARRAY_SIZE(call_ids); 2709 unsigned i; 2710 2711 /* Get all calls, and establish media connection between 2712 * this call and other calls. 2713 */ 2714 pjsua_enum_calls(call_ids, &call_cnt); 2715 2716 for (i=0; i<call_cnt; ++i) { 2717 if (call_ids[i] == ci->id) 2718 continue; 2719 2720 if (!pjsua_call_has_media(call_ids[i])) 2721 continue; 2722 2723 pjsua_conf_connect(call_conf_slot, 2724 pjsua_call_get_conf_port(call_ids[i])); 2725 pjsua_conf_connect(pjsua_call_get_conf_port(call_ids[i]), 2726 call_conf_slot); 2727 2728 /* Automatically record conversation, if desired */ 2729 if (app_config.auto_rec && app_config.rec_port != PJSUA_INVALID_ID) { 2730 pjsua_conf_connect(pjsua_call_get_conf_port(call_ids[i]), 2731 app_config.rec_port); 2732 } 2733 2734 } 2735 2736 /* Also connect call to local sound device */ 2737 connect_sound = PJ_TRUE; 2738 } 2739 2740 /* Otherwise connect to sound device */ 2741 if (connect_sound) { 2742 pjsua_conf_connect(call_conf_slot, 0); 2743 pjsua_conf_connect(0, call_conf_slot); 2744 2745 /* Automatically record conversation, if desired */ 2746 if (app_config.auto_rec && app_config.rec_port != PJSUA_INVALID_ID) { 2747 pjsua_conf_connect(call_conf_slot, app_config.rec_port); 2748 pjsua_conf_connect(0, app_config.rec_port); 2749 } 2750 } 2751 } 2752 } 2753 2754 /* Process video media state. "mi" is the media index. */ 2755 static void on_call_video_state(pjsua_call_info *ci, unsigned mi, 2756 pj_bool_t *has_error) 2757 { 2758 } 2648 2759 2649 2760 /* … … 2655 2766 { 2656 2767 pjsua_call_info call_info; 2768 unsigned mi; 2769 pj_bool_t has_error = PJ_FALSE; 2657 2770 2658 2771 pjsua_call_get_info(call_id, &call_info); 2659 2772 2660 /* Stop ringback */ 2661 ring_stop(call_id); 2662 2663 /* Connect ports appropriately when media status is ACTIVE or REMOTE HOLD, 2664 * otherwise we should NOT connect the ports. 2665 */ 2666 if (call_info.media_status == PJSUA_CALL_MEDIA_ACTIVE || 2667 call_info.media_status == PJSUA_CALL_MEDIA_REMOTE_HOLD) 2668 { 2669 pj_bool_t connect_sound = PJ_TRUE; 2670 2671 /* Loopback sound, if desired */ 2672 if (app_config.auto_loop) { 2673 pjsua_conf_connect(call_info.conf_slot, call_info.conf_slot); 2674 connect_sound = PJ_FALSE; 2773 for (mi=0; mi<call_info.media_cnt; ++mi) { 2774 on_call_generic_media_state(&call_info, mi, &has_error); 2775 2776 switch (call_info.media[mi].type) { 2777 case PJMEDIA_TYPE_AUDIO: 2778 on_call_audio_state(&call_info, mi, &has_error); 2779 break; 2780 case PJMEDIA_TYPE_VIDEO: 2781 on_call_video_state(&call_info, mi, &has_error); 2782 break; 2675 2783 } 2676 2677 /* Automatically record conversation, if desired */ 2678 if (app_config.auto_rec && app_config.rec_port != PJSUA_INVALID_ID) { 2679 pjsua_conf_connect(call_info.conf_slot, app_config.rec_port); 2680 } 2681 2682 /* Stream a file, if desired */ 2683 if ((app_config.auto_play || app_config.auto_play_hangup) && 2684 app_config.wav_port != PJSUA_INVALID_ID) 2685 { 2686 pjsua_conf_connect(app_config.wav_port, call_info.conf_slot); 2687 connect_sound = PJ_FALSE; 2688 } 2689 2690 /* Put call in conference with other calls, if desired */ 2691 if (app_config.auto_conf) { 2692 pjsua_call_id call_ids[PJSUA_MAX_CALLS]; 2693 unsigned call_cnt=PJ_ARRAY_SIZE(call_ids); 2694 unsigned i; 2695 2696 /* Get all calls, and establish media connection between 2697 * this call and other calls. 2698 */ 2699 pjsua_enum_calls(call_ids, &call_cnt); 2700 2701 for (i=0; i<call_cnt; ++i) { 2702 if (call_ids[i] == call_id) 2703 continue; 2704 2705 if (!pjsua_call_has_media(call_ids[i])) 2706 continue; 2707 2708 pjsua_conf_connect(call_info.conf_slot, 2709 pjsua_call_get_conf_port(call_ids[i])); 2710 pjsua_conf_connect(pjsua_call_get_conf_port(call_ids[i]), 2711 call_info.conf_slot); 2712 2713 /* Automatically record conversation, if desired */ 2714 if (app_config.auto_rec && app_config.rec_port != PJSUA_INVALID_ID) { 2715 pjsua_conf_connect(pjsua_call_get_conf_port(call_ids[i]), 2716 app_config.rec_port); 2717 } 2718 2719 } 2720 2721 /* Also connect call to local sound device */ 2722 connect_sound = PJ_TRUE; 2723 } 2724 2725 /* Otherwise connect to sound device */ 2726 if (connect_sound) { 2727 pjsua_conf_connect(call_info.conf_slot, 0); 2728 pjsua_conf_connect(0, call_info.conf_slot); 2729 2730 /* Automatically record conversation, if desired */ 2731 if (app_config.auto_rec && app_config.rec_port != PJSUA_INVALID_ID) { 2732 pjsua_conf_connect(call_info.conf_slot, app_config.rec_port); 2733 pjsua_conf_connect(0, app_config.rec_port); 2734 } 2735 } 2736 } 2737 2738 /* Handle media status */ 2739 switch (call_info.media_status) { 2740 case PJSUA_CALL_MEDIA_ACTIVE: 2741 PJ_LOG(3,(THIS_FILE, "Media for call %d is active", call_id)); 2742 break; 2743 2744 case PJSUA_CALL_MEDIA_LOCAL_HOLD: 2745 PJ_LOG(3,(THIS_FILE, "Media for call %d is suspended (hold) by local", 2746 call_id)); 2747 break; 2748 2749 case PJSUA_CALL_MEDIA_REMOTE_HOLD: 2750 PJ_LOG(3,(THIS_FILE, 2751 "Media for call %d is suspended (hold) by remote", 2752 call_id)); 2753 break; 2754 2755 case PJSUA_CALL_MEDIA_ERROR: 2756 PJ_LOG(3,(THIS_FILE, 2757 "Media has reported error, disconnecting call")); 2758 { 2759 pj_str_t reason = pj_str("ICE negotiation failed"); 2760 pjsua_call_hangup(call_id, 500, &reason, NULL); 2761 } 2762 break; 2763 2764 case PJSUA_CALL_MEDIA_NONE: 2765 PJ_LOG(3,(THIS_FILE, 2766 "Media for call %d is inactive", 2767 call_id)); 2768 break; 2769 2770 default: 2771 pj_assert(!"Unhandled media status"); 2772 break; 2784 } 2785 2786 if (has_error) { 2787 pj_str_t reason = pj_str("Media failed"); 2788 pjsua_call_hangup(call_id, 500, &reason, NULL); 2773 2789 } 2774 2790 } … … 3256 3272 puts("| | V Adjust audio Volume | f Save config |"); 3257 3273 puts("| S Send arbitrary REQUEST | Cp Codec priorities | |"); 3258 puts("+------------------------------+--------------------------+-------------------+"); 3274 puts("+-----------------------------------------------------------------------------+"); 3275 #if PJSUA_HAS_VIDEO 3276 puts("| Video: \"vid help\" for more info |"); 3277 puts("+-----------------------------------------------------------------------------+"); 3278 #endif 3259 3279 puts("| q QUIT L ReLoad sleep MS echo [0|1|txt] n: detect NAT type |"); 3260 3280 puts("+=============================================================================+"); … … 3272 3292 } 3273 3293 3294 /* Help screen for video */ 3295 static void vid_show_help(void) 3296 { 3297 #if PJSUA_HAS_VIDEO 3298 puts("+=============================================================================+"); 3299 puts("| Video commands: |"); 3300 puts("| |"); 3301 puts("| vid help Show this help screen |"); 3302 puts("| vid call rx on|off Enable/disable incoming video for current call |"); 3303 puts("| vid call tx on|off Enable/disable video tx for current call |"); 3304 puts("| vid dev list List all video devices |"); 3305 puts("| vid dev refresh Refresh video device list |"); 3306 puts("| vid dev prev on|off ID Enable/disable preview for specified device ID |"); 3307 puts("| vid codec list List video codecs |"); 3308 puts("| vid codec prio PT PRIO Set codec with pt PT priority to PRIO |"); 3309 puts("| vid win list List all active video windows |"); 3310 puts("| vid win show|hide ID Show/hide the specified video window ID |"); 3311 puts("| vid win move ID X Y Move window ID to position X,Y |"); 3312 puts("| vid win resize ID w h Resize window ID to the specified width, height |"); 3313 puts("+=============================================================================+"); 3314 #endif 3315 } 3274 3316 3275 3317 /* … … 3550 3592 } 3551 3593 3552 #if PJ MEDIA_HAS_VIDEO3594 #if PJSUA_HAS_VIDEO 3553 3595 puts(""); 3554 3596 printf("List of video codecs:\n"); … … 3592 3634 status = pjsua_codec_set_priority(pj_cstr(&id, codec), 3593 3635 (pj_uint8_t)new_prio); 3594 #if PJ MEDIA_HAS_VIDEO3636 #if PJSUA_HAS_VIDEO 3595 3637 if (status != PJ_SUCCESS) { 3596 3638 status = pjsua_vid_codec_set_priority(pj_cstr(&id, codec), … … 3601 3643 pjsua_perror(THIS_FILE, "Error setting codec priority", status); 3602 3644 } 3645 3646 3647 #if PJSUA_HAS_VIDEO 3648 static void vid_print_dev(int id, const pjmedia_vid_dev_info *vdi, 3649 const char *title) 3650 { 3651 char capnames[120]; 3652 char formats[120]; 3653 const char *dirname; 3654 unsigned i; 3655 3656 if (vdi->dir == PJMEDIA_DIR_CAPTURE_RENDER) { 3657 dirname = "capture, render"; 3658 } else if (vdi->dir == PJMEDIA_DIR_CAPTURE) { 3659 dirname = "capture"; 3660 } else { 3661 dirname = "render"; 3662 } 3663 3664 3665 capnames[0] = '\0'; 3666 for (i=0; i<sizeof(int)*8 && (1 << i) < PJMEDIA_VID_DEV_CAP_MAX; ++i) { 3667 if (vdi->caps & (1 << i)) { 3668 const char *capname = pjmedia_vid_dev_cap_name(1 << i, NULL); 3669 if (capname) { 3670 if (*capnames) 3671 strcat(capnames, ", "); 3672 strncat(capnames, capname, 3673 sizeof(capnames)-strlen(capnames)-1); 3674 } 3675 } 3676 } 3677 3678 formats[0] = '\0'; 3679 for (i=0; i<vdi->fmt_cnt; ++i) { 3680 const pjmedia_video_format_info *vfi = 3681 pjmedia_get_video_format_info(NULL, vdi->fmt[i].id); 3682 if (vfi) { 3683 if (*formats) 3684 strcat(formats, ", "); 3685 strncat(formats, vfi->name, sizeof(formats)-strlen(formats)-1); 3686 } 3687 } 3688 3689 PJ_LOG(3,(THIS_FILE, "%3d %s [%s][%s] %s", id, vdi->name, vdi->driver, 3690 dirname, title)); 3691 PJ_LOG(3,(THIS_FILE, " Supported capabilities: %s", capnames)); 3692 PJ_LOG(3,(THIS_FILE, " Supported formats: %s", formats)); 3693 } 3694 3695 static void vid_list_devs(void) 3696 { 3697 unsigned i, count; 3698 pjmedia_vid_dev_info vdi; 3699 pj_status_t status; 3700 3701 PJ_LOG(3,(THIS_FILE, "Video device list:")); 3702 count = pjsua_vid_dev_count(); 3703 if (count == 0) { 3704 PJ_LOG(3,(THIS_FILE, " - no device detected -")); 3705 return; 3706 } else { 3707 PJ_LOG(3,(THIS_FILE, "%d device(s) detected:", count)); 3708 } 3709 3710 status = pjsua_vid_dev_get_info(PJMEDIA_VID_DEFAULT_RENDER_DEV, &vdi); 3711 if (status == PJ_SUCCESS) 3712 vid_print_dev(PJMEDIA_VID_DEFAULT_RENDER_DEV, &vdi, 3713 "(default renderer device)"); 3714 3715 status = pjsua_vid_dev_get_info(PJMEDIA_VID_DEFAULT_CAPTURE_DEV, &vdi); 3716 if (status == PJ_SUCCESS) 3717 vid_print_dev(PJMEDIA_VID_DEFAULT_CAPTURE_DEV, &vdi, 3718 "(default capture device)"); 3719 3720 for (i=0; i<count; ++i) { 3721 status = pjsua_vid_dev_get_info(i, &vdi); 3722 if (status == PJ_SUCCESS) 3723 vid_print_dev(i, &vdi, ""); 3724 } 3725 } 3726 3727 static void vid_handle_menu(char *menuin) 3728 { 3729 char *argv[8]; 3730 int argc = 0; 3731 3732 /* Tokenize */ 3733 argv[argc] = strtok(menuin, " \t\r\n"); 3734 while (argv[argc] && *argv[argc]) { 3735 argc++; 3736 argv[argc] = strtok(NULL, " \t\r\n"); 3737 } 3738 3739 if (strcmp(argv[1], "help")==0 || argc == 1) { 3740 vid_show_help(); 3741 } else if (strcmp(argv[1], "call")==0) { 3742 pj_bool_t tx = (strcmp(argv[2], "tx") == 0); 3743 pj_bool_t on = (strcmp(argv[3], "on") == 0); 3744 3745 PJ_TODO(vid_enable_disable_video_on_call); 3746 PJ_LOG(1,(THIS_FILE, "Not implemented")); 3747 } else if (strcmp(argv[1], "dev")==0) { 3748 if (strcmp(argv[2], "list")==0) { 3749 vid_list_devs(); 3750 } else if (strcmp(argv[2], "refresh")==0) { 3751 pjmedia_vid_dev_refresh(); 3752 } else if (strcmp(argv[2], "prev")==0) { 3753 if (argc != 5) { 3754 goto on_error; 3755 } else { 3756 pj_bool_t on = (strcmp(argv[3], "on") == 0); 3757 int dev_id = atoi(argv[4]); 3758 if (on) { 3759 pjsua_vid_preview_start(dev_id, NULL); 3760 } else { 3761 pjsua_vid_preview_stop(dev_id); 3762 } 3763 } 3764 } else 3765 goto on_error; 3766 } else if (strcmp(argv[1], "win")==0) { 3767 if (argc==3 && strcmp(argv[2], "list")==0) { 3768 PJ_LOG(1,(THIS_FILE, "Not implemented")); 3769 PJ_TODO(vid_list_window); 3770 } else if (argc==4 && (strcmp(argv[2], "show")==0 || 3771 strcmp(argv[2], "hide")==0)) 3772 { 3773 pj_bool_t show = (strcmp(argv[2], "show")==0); 3774 pjsua_vid_win_id wid = atoi(argv[3]); 3775 3776 pjsua_vid_win_set_show(wid, show); 3777 3778 } else if (argc==6 && strcmp(argv[2], "move")==0) { 3779 pjsua_vid_win_id wid = atoi(argv[3]); 3780 pjmedia_coord pos; 3781 3782 pos.x = atoi(argv[4]); 3783 pos.y = atoi(argv[4]); 3784 pjsua_vid_win_set_pos(wid, &pos); 3785 3786 } else if (argc==6 && strcmp(argv[2], "resize")==0) { 3787 pjsua_vid_win_id wid = atoi(argv[3]); 3788 pjmedia_rect_size size; 3789 3790 size.w = atoi(argv[4]); 3791 size.h = atoi(argv[4]); 3792 pjsua_vid_win_set_size(wid, &size); 3793 } else 3794 goto on_error; 3795 } else if (strcmp(argv[1], "codec")==0) { 3796 pjmedia_vid_codec_info ci[PJMEDIA_CODEC_MGR_MAX_CODECS]; 3797 unsigned prio[PJMEDIA_CODEC_MGR_MAX_CODECS]; 3798 unsigned count = PJMEDIA_CODEC_MGR_MAX_CODECS; 3799 pj_status_t status; 3800 3801 if (argc==3 && strcmp(argv[2], "list")==0) { 3802 status = pjmedia_vid_codec_mgr_enum_codecs(NULL, &count, ci, prio); 3803 if (status != PJ_SUCCESS) { 3804 PJ_PERROR(1,(THIS_FILE, status, "Error enumerating codecs")); 3805 } else { 3806 unsigned i; 3807 PJ_LOG(3,(THIS_FILE, "Found %d video codecs:", count)); 3808 PJ_LOG(3,(THIS_FILE, " PT Prio Name")); 3809 PJ_LOG(3,(THIS_FILE, "-------------------------")); 3810 for (i=0; i<count; ++i) { 3811 PJ_LOG(3,(THIS_FILE, "% 3d % 3d %.*s", ci[i].pt, prio[i], 3812 (int)ci[i].encoding_name.slen, 3813 ci[i].encoding_name.ptr)); 3814 } 3815 } 3816 } else if (argc==5 && strcmp(argv[2], "prio")==0) { 3817 int pt = atoi(argv[3]); 3818 int prio = atoi(argv[4]); 3819 const pjmedia_vid_codec_info *pci; 3820 3821 status = pjmedia_vid_codec_mgr_get_codec_info(NULL, pt, &pci); 3822 if (status != PJ_SUCCESS) { 3823 PJ_PERROR(1,(THIS_FILE, status, "Unable to find codec")); 3824 } else { 3825 char codec_id[40]; 3826 if (pjmedia_vid_codec_info_to_id(pci, codec_id, 3827 sizeof(codec_id)) == NULL) 3828 { 3829 PJ_PERROR(1,(THIS_FILE, status, "Unable to get codec id")); 3830 } else { 3831 pj_str_t cid = pj_str(codec_id); 3832 status = pjsua_vid_codec_set_priority(&cid, 3833 (pj_uint8_t)prio); 3834 } 3835 } 3836 3837 } else 3838 goto on_error; 3839 } else 3840 goto on_error; 3841 3842 return; 3843 3844 on_error: 3845 PJ_LOG(1,(THIS_FILE, "Invalid command, use 'vid help'")); 3846 } 3847 3848 #endif /* PJSUA_HAS_VIDEO */ 3603 3849 3604 3850 … … 4032 4278 4033 4279 case 'v': 4034 /* 4035 * Send re-INVITE (to release hold, etc). 4036 */ 4280 #if PJSUA_HAS_VIDEO 4281 if (menuin[1]=='i' && menuin[2]=='d' && menuin[3]==' ') { 4282 4283 vid_handle_menu(menuin); 4284 4285 } else 4286 #endif 4037 4287 if (current_call != -1) { 4038 4288 /* 4289 * re-INVITE 4290 */ 4039 4291 pjsua_call_reinvite(current_call, PJ_TRUE, NULL); 4040 4292 … … 5090 5342 for (i=0; i<app_config.codec_dis_cnt; ++i) { 5091 5343 pjsua_codec_set_priority(&app_config.codec_dis[i],PJMEDIA_CODEC_PRIO_DISABLED); 5092 #if PJ MEDIA_HAS_VIDEO5344 #if PJSUA_HAS_VIDEO 5093 5345 pjsua_vid_codec_set_priority(&app_config.codec_dis[i],PJMEDIA_CODEC_PRIO_DISABLED); 5094 5346 #endif … … 5099 5351 pjsua_codec_set_priority(&app_config.codec_arg[i], 5100 5352 (pj_uint8_t)(PJMEDIA_CODEC_PRIO_NORMAL+i+9)); 5101 #if PJ MEDIA_HAS_VIDEO5353 #if PJSUA_HAS_VIDEO 5102 5354 pjsua_vid_codec_set_priority(&app_config.codec_arg[i], 5103 5355 (pj_uint8_t)(PJMEDIA_CODEC_PRIO_NORMAL+i+9)); … … 5138 5390 } 5139 5391 5140 #if PJ MEDIA_HAS_VIDEO5392 #if PJSUA_HAS_VIDEO 5141 5393 if (app_config.vcapture_dev != PJSUA_INVALID_ID || 5142 5394 app_config.vrender_dev != PJSUA_INVALID_ID) 5143 5395 { 5144 status = pjsua_vid_set_dev(app_config.vcapture_dev, 5145 app_config.vrender_dev); 5396 //status = pjsua_vid_set_dev(app_config.vcapture_dev, 5397 // app_config.vrender_dev); 5398 PJ_TODO(vid_implement_pjsua_vid_set_dev); 5146 5399 if (status != PJ_SUCCESS) 5147 5400 goto on_error;
Note: See TracChangeset
for help on using the changeset viewer.