Changeset 3609


Ignore:
Timestamp:
Jul 7, 2011 7:46:33 AM (9 years ago)
Author:
bennylp
Message:

Initial commit re #1263 (PJSUA-LIB Video API):

  • API designed and reviewed (pjsua.h)
  • Implemented these APIs and added to pjsua sample application:
    • video device enums API
    • video capture preview API
  • refactoring in PJSUA-LIB:
    • video stuffs go to pjsua_vid.c
    • call dump goes to pjsua_dump.c

We're still missing:

  • video call API implementation
  • media info and statistic API implementation
Location:
pjproject/branches/projects/2.0-dev
Files:
2 added
7 edited

Legend:

Unmodified
Added
Removed
  • pjproject/branches/projects/2.0-dev/pjsip-apps/src/pjsua/pjsua_app.c

    r3519 r3609  
    312312    puts  ("  --extra-audio       Add one more audio stream"); 
    313313 
    314 #if PJMEDIA_HAS_VIDEO 
     314#if PJSUA_HAS_VIDEO 
    315315    puts  (""); 
    316316    puts  ("Video Options:"); 
     
    26462646} 
    26472647 
     2648/* General processing for media state. "mi" is the media index */ 
     2649static 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. */ 
     2669static 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. */ 
     2755static void on_call_video_state(pjsua_call_info *ci, unsigned mi, 
     2756                                pj_bool_t *has_error) 
     2757{ 
     2758} 
    26482759 
    26492760/* 
     
    26552766{ 
    26562767    pjsua_call_info call_info; 
     2768    unsigned mi; 
     2769    pj_bool_t has_error = PJ_FALSE; 
    26572770 
    26582771    pjsua_call_get_info(call_id, &call_info); 
    26592772 
    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; 
    26752783        } 
    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); 
    27732789    } 
    27742790} 
     
    32563272    puts("|                              |  V  Adjust audio Volume  |  f  Save config   |"); 
    32573273    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 
    32593279    puts("|  q  QUIT   L  ReLoad   sleep MS   echo [0|1|txt]     n: detect NAT type     |"); 
    32603280    puts("+=============================================================================+"); 
     
    32723292} 
    32733293 
     3294/* Help screen for video */ 
     3295static 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} 
    32743316 
    32753317/* 
     
    35503592    } 
    35513593 
    3552 #if PJMEDIA_HAS_VIDEO 
     3594#if PJSUA_HAS_VIDEO 
    35533595    puts(""); 
    35543596    printf("List of video codecs:\n"); 
     
    35923634    status = pjsua_codec_set_priority(pj_cstr(&id, codec),  
    35933635                                      (pj_uint8_t)new_prio); 
    3594 #if PJMEDIA_HAS_VIDEO 
     3636#if PJSUA_HAS_VIDEO 
    35953637    if (status != PJ_SUCCESS) { 
    35963638        status = pjsua_vid_codec_set_priority(pj_cstr(&id, codec),  
     
    36013643        pjsua_perror(THIS_FILE, "Error setting codec priority", status); 
    36023644} 
     3645 
     3646 
     3647#if PJSUA_HAS_VIDEO 
     3648static 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 
     3695static 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 
     3727static 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 
     3844on_error: 
     3845    PJ_LOG(1,(THIS_FILE, "Invalid command, use 'vid help'")); 
     3846} 
     3847 
     3848#endif /* PJSUA_HAS_VIDEO */ 
    36033849 
    36043850 
     
    40324278 
    40334279        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 
    40374287            if (current_call != -1) { 
    4038                  
     4288                /* 
     4289                 * re-INVITE 
     4290                 */ 
    40394291                pjsua_call_reinvite(current_call, PJ_TRUE, NULL); 
    40404292 
     
    50905342    for (i=0; i<app_config.codec_dis_cnt; ++i) { 
    50915343        pjsua_codec_set_priority(&app_config.codec_dis[i],PJMEDIA_CODEC_PRIO_DISABLED); 
    5092 #if PJMEDIA_HAS_VIDEO 
     5344#if PJSUA_HAS_VIDEO 
    50935345        pjsua_vid_codec_set_priority(&app_config.codec_dis[i],PJMEDIA_CODEC_PRIO_DISABLED); 
    50945346#endif 
     
    50995351        pjsua_codec_set_priority(&app_config.codec_arg[i], 
    51005352                                 (pj_uint8_t)(PJMEDIA_CODEC_PRIO_NORMAL+i+9)); 
    5101 #if PJMEDIA_HAS_VIDEO 
     5353#if PJSUA_HAS_VIDEO 
    51025354        pjsua_vid_codec_set_priority(&app_config.codec_arg[i], 
    51035355                                     (pj_uint8_t)(PJMEDIA_CODEC_PRIO_NORMAL+i+9)); 
     
    51385390    } 
    51395391 
    5140 #if PJMEDIA_HAS_VIDEO 
     5392#if PJSUA_HAS_VIDEO 
    51415393    if (app_config.vcapture_dev != PJSUA_INVALID_ID || 
    51425394        app_config.vrender_dev  != PJSUA_INVALID_ID)  
    51435395    { 
    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); 
    51465399        if (status != PJ_SUCCESS) 
    51475400            goto on_error; 
  • pjproject/branches/projects/2.0-dev/pjsip/build/Makefile

    r3457 r3609  
    7676export PJSUA_LIB_OBJS += $(OS_OBJS) $(M_OBJS) $(CC_OBJS) $(HOST_OBJS) \ 
    7777                        pjsua_acc.o pjsua_call.o pjsua_core.o \ 
    78                         pjsua_im.o pjsua_media.o pjsua_pres.o 
     78                        pjsua_im.o pjsua_media.o pjsua_pres.o \ 
     79                        pjsua_dump.o pjsua_vid.o 
    7980export PJSUA_LIB_CFLAGS += $(_CFLAGS) $(PJ_VIDEO_CFLAGS) 
    8081 
  • pjproject/branches/projects/2.0-dev/pjsip/include/pjsua-lib/pjsua.h

    r3500 r3609  
    325325#endif 
    326326 
     327/** 
     328 * Is video enabled. 
     329 */ 
     330#ifndef PJSUA_HAS_VIDEO 
     331#   define PJSUA_HAS_VIDEO              PJMEDIA_HAS_VIDEO 
     332#endif 
    327333 
    328334/** 
     
    24392445     * Maximum number of simultaneous active video streams to be allowed 
    24402446     * for calls on this account. Setting this to zero will disable video 
    2441      * in calls on this account. 
    2442      * 
    2443      * Default: 0 
     2447     * in calls on this account, regardless of other video settings. 
     2448     * 
     2449     * Default: 1 
    24442450     */ 
    24452451    unsigned         max_video_cnt; 
     2452 
     2453    /** 
     2454     * Specify whether incoming video should be shown to screen by default. 
     2455     * This applies to incoming call (INVITE), incoming re-INVITE, and 
     2456     * incoming UPDATE requests. 
     2457     * 
     2458     * Regardless of this setting, application can detect incoming video 
     2459     * by implementing \a on_call_media_state() callback and enumerating 
     2460     * the media stream(s) with #pjsua_call_get_info(). Once incoming 
     2461     * video is recognised, application may retrieve the window associated 
     2462     * with the incoming video and show or hide it with 
     2463     * #pjsua_vid_win_set_show(). 
     2464     * 
     2465     * Default: PJ_FALSE 
     2466     */ 
     2467    pj_bool_t        vid_in_auto_show; 
     2468 
     2469    /** 
     2470     * Specify whether outgoing video should be activated by default when 
     2471     * making outgoing calls and/or when incoming video is detected. This 
     2472     * applies to incoming and outgoing calls, incoming re-INVITE, and 
     2473     * incoming UPDATE. If the setting is non-zero, outgoing video 
     2474     * transmission will be started as soon as response to these requests 
     2475     * is sent (or received). 
     2476     * 
     2477     * Regardless of the value of this setting, application can start and 
     2478     * stop outgoing video transmission with #pjsua_call_set_vid_out(). 
     2479     * 
     2480     * Default: PJ_FALSE 
     2481     */ 
     2482    pj_bool_t        vid_out_auto_transmit; 
     2483 
     2484    /** 
     2485     * Specify the default capture device to be used by this account. If 
     2486     * \a vid_out_auto_transmit is enabled, this device will be used for 
     2487     * capturing video. 
     2488     * 
     2489     * Default: PJMEDIA_VID_DEFAULT_CAPTURE_DEV 
     2490     */ 
     2491    pjmedia_vid_dev_index vid_cap_dev; 
     2492 
     2493    /** 
     2494     * Specify the default rendering device to be used by this account. 
     2495     * 
     2496     * Default: PJMEDIA_VID_DEFAULT_RENDER_DEV 
     2497     */ 
     2498    pjmedia_vid_dev_index vid_rend_dev; 
    24462499 
    24472500    /** 
     
    29763029#endif 
    29773030 
     3031/** 
     3032 * Maximum active video windows 
     3033 */ 
     3034#ifndef PJSUA_MAX_VID_WINS 
     3035#   define PJSUA_MAX_VID_WINS       16 
     3036#endif 
     3037 
     3038/** 
     3039 * Video window ID. 
     3040 */ 
     3041typedef int pjsua_vid_win_id; 
    29783042 
    29793043 
     
    30843148            /** Audio stream */ 
    30853149            struct { 
    3086                 pjsua_conf_port_id   conf_slot; /**< The conference port 
    3087                                                      number for the call.   */ 
    3088             } audio; 
     3150                /** The conference port number for the call.  */ 
     3151                pjsua_conf_port_id   conf_slot; 
     3152            } aud; 
    30893153 
    30903154            /** Video stream */ 
    30913155            struct { 
    3092                 pjmedia_vid_port    *capturer;  /**< Video capturer.        */ 
    3093                 pjmedia_vid_port    *renderer;  /**< Video renderer.        */ 
    3094             } video; 
     3156                /** 
     3157                 * The window id for incoming video, if any, or 
     3158                 * PJSUA_INVALID_ID. 
     3159                 */ 
     3160                pjsua_vid_win_id     win_in; 
     3161 
     3162                /** The video capture device for outgoing transmission, 
     3163                 *  if any, or PJMEDIA_VID_INVALID_DEV 
     3164                 */ 
     3165                pjmedia_vid_dev_index   cap_dev; 
     3166 
     3167            } vid; 
    30953168        } stream; 
    30963169 
     
    31183191 
    31193192 
     3193/** 
     3194 * Media stream info. 
     3195 */ 
     3196typedef struct pjsua_stream_info 
     3197{ 
     3198    /** Media type of this stream. */ 
     3199    pjmedia_type type; 
     3200 
     3201    /** Stream info (union). */ 
     3202    union { 
     3203        /** Audio stream info */ 
     3204        pjmedia_stream_info     aud; 
     3205 
     3206        /** Video stream info */ 
     3207        pjmedia_vid_stream_info vid; 
     3208    } info; 
     3209 
     3210} pjsua_stream_info; 
     3211 
     3212 
     3213/** 
     3214 * Media stream statistic. 
     3215 */ 
     3216typedef struct pjsua_stream_stat 
     3217{ 
     3218    /** RTCP statistic. */ 
     3219    pjmedia_rtcp_stat   rtcp; 
     3220 
     3221    /** Jitter buffer statistic. */ 
     3222    pjmedia_jb_state    jbuf; 
     3223 
     3224} pjsua_stream_stat; 
     3225 
    31203226 
    31213227/** 
     
    31913297 
    31923298 
    3193 #if DISABLED_FOR_TICKET_1185 
    3194 /** 
    3195  * Retrieve the media session associated with this call. Note that the media 
    3196  * session may not be available depending on the current call's media status 
    3197  * (the pjsua_call_media_status information in pjsua_call_info). Application 
    3198  * may use the media session to retrieve more detailed information about the 
    3199  * call's media. 
     3299/** 
     3300 * Get the conference port identification associated with the call. 
    32003301 * 
    32013302 * @param call_id       Call identification. 
    32023303 * 
    3203  * @return              Call media session. 
    3204  */ 
    3205 PJ_DECL(pjmedia_session*) pjsua_call_get_media_session(pjsua_call_id call_id); 
    3206  
    3207 /** 
    3208  * Retrieve the media transport instance that is used for this call.  
    3209  * Application may use the media transport to query more detailed information 
    3210  * about the media transport. 
    3211  * 
    3212  * @param cid           Call identification (the call_id). 
    3213  * 
    3214  * @return              Call media transport. 
    3215  */ 
    3216 PJ_DECL(pjmedia_transport*) pjsua_call_get_media_transport(pjsua_call_id cid); 
    3217 #endif /* DISABLED_FOR_TICKET_1185 */ 
    3218  
    3219 /** 
    3220  * Get the conference port identification associated with the call. 
    3221  * 
    3222  * @param call_id       Call identification. 
    3223  * 
    3224  * @return              Conference port ID, or PJSUA_INVALID_ID when the  
     3304 * @return              Conference port ID, or PJSUA_INVALID_ID when the 
    32253305 *                      media has not been established or is not active. 
    32263306 */ 
     
    35713651                                     unsigned maxlen, 
    35723652                                     const char *indent); 
     3653 
     3654/** 
     3655 * Get the media stream index of the default video stream in the call. 
     3656 * Typically this will just retrieve the stream index of the first 
     3657 * activated video stream in the call. 
     3658 * 
     3659 * @param call_id       Call identification. 
     3660 * 
     3661 * @return              The media stream index or -1 if no video stream 
     3662 *                      is present in the call. 
     3663 */ 
     3664PJ_DECL(int) pjsua_call_get_vid_stream_idx(pjsua_call_id call_id); 
     3665 
     3666/** 
     3667 * Start, stop, and/or manipulate video transmission for the specified 
     3668 * call. This would trigger a re-INVITE or UPDATE to be sent for the 
     3669 * call. This function may add, remove, or modify existing video media 
     3670 * stream, depending on the media index specified (the \a med_idx argument). 
     3671 * 
     3672 * To add a new or edit existing video stream (for transmission), specify 
     3673 * a valid video capture device ID or PJMEDIA_VID_DEFAULT_CAPTURE_DEV in 
     3674 * the \a cap_dev argument. If \a med_idx is set to default stream (-1), 
     3675 * then the function will modify existing video stream if one exists, or 
     3676 * add a new one if it doesn't. If \a med_idx is set to a specific stream 
     3677 * index, the function will modify that video stream. Otherwise if \a med_idx 
     3678 * is set to value larger than the current media count, a new video stream 
     3679 * will be added to the call. 
     3680 * 
     3681 * To remove an existing video stream, specify PJMEDIA_VID_INVALID_DEV in 
     3682 * \a cap_dev argument. If \a med_idx is set to default stream (-1), this 
     3683 * will remove the default/first video stream in the call, otherwise 
     3684 * application can put a specific value to request removal of that particular 
     3685 * video stream. 
     3686 * 
     3687 * @param call_id       Call identification. 
     3688 * @param med_idx       The media stream index. Currently the value MUST 
     3689 *                      be -1 to denote the default video stream in the 
     3690 *                      call. 
     3691 * @param cap_dev       To add or modify existing video media stream, 
     3692 *                      specify PJMEDIA_VID_DEFAULT_CAPTURE_DEV to use 
     3693 *                      the default capture device as configured in the 
     3694 *                      account, or specify a specific capture device ID. 
     3695 *                      To disable an existing video stream, specify 
     3696 *                      PJMEDIA_VID_INVALID_DEV for this parameter. 
     3697 * 
     3698 * @return              PJ_SUCCESS on success or the appropriate error. 
     3699 */ 
     3700PJ_DECL(pj_status_t) pjsua_call_set_vid_out(pjsua_call_id call_id, 
     3701                                            int med_idx, 
     3702                                            pjmedia_vid_dev_index cap_dev); 
     3703 
     3704/** 
     3705 * Get media stream info for the specified media index. 
     3706 * 
     3707 * @param call_id       The call identification. 
     3708 * @param med_idx       Media stream index. 
     3709 * @param psi           To be filled with the stream info. 
     3710 * 
     3711 * @return              PJ_SUCCESS on success or the appropriate error. 
     3712 */ 
     3713PJ_DECL(pj_status_t) pjsua_call_get_stream_info(pjsua_call_id call_id, 
     3714                                                unsigned med_idx, 
     3715                                                pjsua_stream_info *psi); 
     3716 
     3717/** 
     3718 *  Get media stream statistic for the specified media index. 
     3719 * 
     3720 * @param call_id       The call identification. 
     3721 * @param med_idx       Media stream index. 
     3722 * @param psi           To be filled with the stream statistic. 
     3723 * 
     3724 * @return              PJ_SUCCESS on success or the appropriate error. 
     3725 */ 
     3726PJ_DECL(pj_status_t) pjsua_call_get_stream_stat(pjsua_call_id call_id, 
     3727                                                unsigned med_idx, 
     3728                                                pjsua_stream_stat *stat); 
     3729 
     3730/** 
     3731 * Get media transport info for the specified media index. 
     3732 * 
     3733 * @param call_id       The call identification. 
     3734 * @param med_idx       Media stream index. 
     3735 * @param t             To be filled with the transport info. 
     3736 * 
     3737 * @return              PJ_SUCCESS on success or the appropriate error. 
     3738 */ 
     3739PJ_DECL(pj_status_t) pjsua_call_get_transport_info(pjsua_call_id call_id, 
     3740                                                   unsigned med_idx, 
     3741                                                   pjmedia_transport_info *t); 
     3742 
     3743 
    35733744 
    35743745/** 
     
    44484619 
    44494620 
    4450  
    4451  
    44524621/** 
    44534622 * Get maxinum number of conference ports. 
     
    49405109 
    49415110/***************************************************************************** 
    4942  * Video devices. 
    4943  */ 
    4944  
    4945 /** 
    4946  * Enum all video devices installed in the system. 
    4947  * 
    4948  * @param info          Array of info to be initialized. 
    4949  * @param count         On input, specifies max elements in the array. 
    4950  *                      On return, it contains actual number of elements 
    4951  *                      that have been initialized. 
    4952  * 
    4953  * @return              PJ_SUCCESS on success, or the appropriate error code. 
    4954  */ 
    4955 PJ_DECL(pj_status_t) pjsua_vid_enum_devs(pjmedia_vid_dev_info info[], 
    4956                                          unsigned *count); 
    4957  
    4958  
    4959 /** 
    4960  * Get currently active video devices. If video devices has not been created 
    4961  * (for example when pjsua_start() is not called), it is possible that 
    4962  * the function returns PJ_SUCCESS with -1 as device IDs. 
    4963  * 
    4964  * @param capture_dev   On return it will be filled with device ID of the  
    4965  *                      capture device. 
    4966  * @param render_dev    On return it will be filled with device ID of the  
    4967  *                      device ID of the render device. 
    4968  * 
    4969  * @return              PJ_SUCCESS on success, or the appropriate error code. 
    4970  */ 
    4971 PJ_DECL(pj_status_t) pjsua_vid_get_dev(int *capture_dev, int *render_dev); 
    4972  
    4973  
    4974 /** 
    4975  * Select video device for the next video sessions. 
    4976  * 
    4977  * @param capture_dev   Device ID of the capture device. 
    4978  * @param render_dev    Device ID of the render device. 
    4979  * 
    4980  * @return              PJ_SUCCESS on success, or the appropriate error code. 
    4981  */ 
    4982 PJ_DECL(pj_status_t) pjsua_vid_set_dev(int capture_dev, int render_dev); 
    4983  
    4984  
    4985 /** 
    4986  * Configure video device setting to the video device being used. If video  
    4987  * device is currently active, the function will forward the setting to the 
    4988  * video device instance to be applied immediately, if it supports it.  
    4989  * 
    4990  * The setting will be saved for future opening of the video device, if the  
    4991  * "keep" argument is set to non-zero. If the video device is currently 
    4992  * inactive, and the "keep" argument is false, this function will return 
    4993  * error. 
    4994  *  
    4995  * Note that in case the setting is kept for future use, it will be applied 
    4996  * to any devices, even when application has changed the video device to be 
    4997  * used. 
    4998  * 
    4999  * See also #pjmedia_vid_dev_stream_set_cap() for more information about 
    5000  * setting an video device capability. 
    5001  * 
    5002  * @param cap           The video device setting to change. 
    5003  * @param pval          Pointer to value. Please see #pjmedia_vid_dev_cap 
    5004  *                      documentation about the type of value to be  
    5005  *                      supplied for each setting. 
    5006  * @param keep          Specify whether the setting is to be kept for future 
    5007  *                      use. 
    5008  * 
    5009  * @return              PJ_SUCCESS on success or the appropriate error code. 
    5010  */ 
    5011 PJ_DECL(pj_status_t) pjsua_vid_set_setting(pjmedia_vid_dev_cap cap, 
    5012                                            const void *pval, 
    5013                                            pj_bool_t keep); 
    5014  
    5015 /** 
    5016  * Retrieve a video device setting. If video device is currently active, 
    5017  * the function will forward the request to the video device. If video device 
    5018  * is currently inactive, and if application had previously set the setting 
    5019  * and mark the setting as kept, then that setting will be returned. 
    5020  * Otherwise, this function will return error. 
    5021  * 
    5022  * @param cap           The video device setting to retrieve. 
    5023  * @param pval          Pointer to receive the value.  
    5024  *                      Please see #pjmedia_vid_dev_cap documentation about 
    5025  *                      the type of value to be supplied for each setting. 
    5026  * 
    5027  * @return              PJ_SUCCESS on success or the appropriate error code. 
    5028  */ 
    5029 PJ_DECL(pj_status_t) pjsua_vid_get_setting(pjmedia_vid_dev_cap cap, 
    5030                                            void *pval); 
    5031  
    5032  
    5033 /***************************************************************************** 
    50345111 * Codecs. 
    50355112 */ 
     
    50885165                                            const pjmedia_codec_param *param); 
    50895166 
    5090 /***************************************************************************** 
    5091  * Video codecs. 
    5092  */ 
    5093  
    5094 /** 
    5095  * Enum all supported video codecs in the system. 
    5096  * 
    5097  * @param id            Array of ID to be initialized. 
    5098  * @param count         On input, specifies max elements in the array. 
    5099  *                      On return, it contains actual number of elements 
    5100  *                      that have been initialized. 
    5101  * 
    5102  * @return              PJ_SUCCESS on success, or the appropriate error code. 
    5103  */ 
    5104 PJ_DECL(pj_status_t) pjsua_vid_enum_codecs( pjsua_codec_info id[], 
    5105                                             unsigned *count ); 
    5106  
    5107  
    5108 /** 
    5109  * Change video codec priority. 
    5110  * 
    5111  * @param codec_id      Codec ID, which is a string that uniquely identify 
    5112  *                      the codec (such as "H263/90000"). Please see pjsua 
    5113  *                      manual or pjmedia codec reference for details. 
    5114  * @param priority      Codec priority, 0-255, where zero means to disable 
    5115  *                      the codec. 
    5116  * 
    5117  * @return              PJ_SUCCESS on success, or the appropriate error code. 
    5118  */ 
    5119 PJ_DECL(pj_status_t) pjsua_vid_codec_set_priority( const pj_str_t *codec_id, 
    5120                                                    pj_uint8_t priority ); 
    5121  
    5122  
    5123 /** 
    5124  * Get video codec parameters. 
    5125  * 
    5126  * @param codec_id      Codec ID. 
    5127  * @param param         Structure to receive video codec parameters. 
    5128  * 
    5129  * @return              PJ_SUCCESS on success, or the appropriate error code. 
    5130  */ 
    5131 PJ_DECL(pj_status_t) pjsua_vid_codec_get_param( 
    5132                                         const pj_str_t *codec_id, 
    5133                                         pjmedia_vid_codec_param *param); 
    5134  
    5135  
    5136 /** 
    5137  * Set video codec parameters. 
    5138  * 
    5139  * @param codec_id      Codec ID. 
    5140  * @param param         Codec parameter to set. Set to NULL to reset 
    5141  *                      codec parameter to library default settings. 
    5142  * 
    5143  * @return              PJ_SUCCESS on success, or the appropriate error code. 
    5144  */ 
    5145 PJ_DECL(pj_status_t) pjsua_vid_codec_set_param(  
    5146                                         const pj_str_t *codec_id, 
    5147                                         const pjmedia_vid_codec_param *param); 
    5148  
    51495167 
    51505168#if DISABLED_FOR_TICKET_1185 
     
    51595177 * @return              PJ_SUCCESS on success, or the appropriate error code. 
    51605178 */ 
    5161 PJ_DECL(pj_status_t)  
     5179PJ_DECL(pj_status_t) 
    51625180pjsua_media_transports_create(const pjsua_transport_config *cfg); 
    51635181 
     
    51765194 * @return              PJ_SUCCESS on success, or the appropriate error code. 
    51775195 */ 
    5178 PJ_DECL(pj_status_t)  
     5196PJ_DECL(pj_status_t) 
    51795197pjsua_media_transports_attach( pjsua_media_transport tp[], 
    51805198                               unsigned count, 
     
    51835201 
    51845202 
     5203/* end of MEDIA API */ 
    51855204/** 
    51865205 * @} 
     
    51885207 
    51895208 
    5190  
     5209/***************************************************************************** 
     5210 * VIDEO API 
     5211 */ 
     5212 
     5213 
     5214/** 
     5215 * @defgroup PJSUA_LIB_VIDEO PJSUA-API Video 
     5216 * @ingroup PJSUA_LIB 
     5217 * @brief Video support 
     5218 * @{ 
     5219 */ 
     5220 
     5221/* 
     5222 * Video devices API 
     5223 */ 
     5224 
     5225/** 
     5226 * Get the number of video devices installed in the system. 
     5227 * 
     5228 * @return              The number of devices. 
     5229 */ 
     5230PJ_DECL(unsigned) pjsua_vid_dev_count(void); 
     5231 
     5232/** 
     5233 * Retrieve the video device info for the specified device index. 
     5234 * 
     5235 * @param id            The device index. 
     5236 * @param vdi           Device info to be initialized. 
     5237 * 
     5238 * @return              PJ_SUCCESS on success, or the appropriate error code. 
     5239 */ 
     5240PJ_DECL(pj_status_t) pjsua_vid_dev_get_info(pjmedia_vid_dev_index id, 
     5241                                            pjmedia_vid_dev_info *vdi); 
     5242 
     5243/** 
     5244 * Enum all video devices installed in the system. 
     5245 * 
     5246 * @param info          Array of info to be initialized. 
     5247 * @param count         On input, specifies max elements in the array. 
     5248 *                      On return, it contains actual number of elements 
     5249 *                      that have been initialized. 
     5250 * 
     5251 * @return              PJ_SUCCESS on success, or the appropriate error code. 
     5252 */ 
     5253PJ_DECL(pj_status_t) pjsua_vid_enum_devs(pjmedia_vid_dev_info info[], 
     5254                                         unsigned *count); 
     5255 
     5256 
     5257/* 
     5258 * Video preview API 
     5259 */ 
     5260 
     5261/** 
     5262 * Parameters for starting video preview with pjsua_vid_preview_start(). 
     5263 * Application should initialize this structure with 
     5264 * pjsua_vid_preview_param_default(). 
     5265 */ 
     5266typedef struct pjsua_vid_preview_param 
     5267{ 
     5268    /** 
     5269     * Device ID for the video renderer to be used for rendering the 
     5270     * capture stream for preview. 
     5271     */ 
     5272    pjmedia_vid_dev_index       rend_id; 
     5273} pjsua_vid_preview_param; 
     5274 
     5275 
     5276/** 
     5277 * Start video preview window for the specified capture device. 
     5278 * 
     5279 * @param id            The capture device ID where its preview will be 
     5280 *                      started. 
     5281 * @param prm           Optional video preview parameters. Specify NULL 
     5282 *                      to use default values. 
     5283 * 
     5284 * @return              PJ_SUCCESS on success, or the appropriate error code. 
     5285 */ 
     5286PJ_DECL(pj_status_t) pjsua_vid_preview_start(pjmedia_vid_dev_index id, 
     5287                                             pjsua_vid_preview_param *prm); 
     5288 
     5289/** 
     5290 * Get the preview window handle associated with the capture device, if any. 
     5291 * 
     5292 * @param id            The capture device ID. 
     5293 * 
     5294 * @return              The window ID of the preview window for the 
     5295 *                      specified capture device ID, or NULL if preview 
     5296 *                      does not exist. 
     5297 */ 
     5298PJ_DECL(pjsua_vid_win_id) pjsua_vid_preview_get_win(pjmedia_vid_dev_index id); 
     5299 
     5300/** 
     5301 * Stop video preview. 
     5302 * 
     5303 * @param id            The capture device ID. 
     5304 * 
     5305 * @return              PJ_SUCCESS on success, or the appropriate error code. 
     5306 */ 
     5307PJ_DECL(pj_status_t) pjsua_vid_preview_stop(pjmedia_vid_dev_index id); 
     5308 
     5309 
     5310/* 
     5311 * Video window manipulation API. 
     5312 */ 
     5313 
     5314/** 
     5315 * This structure describes video window info. 
     5316 */ 
     5317typedef struct pjsua_vid_win_info 
     5318{ 
     5319    /** 
     5320     * Window show status. The window is hidden if false. 
     5321     */ 
     5322    pj_bool_t   show; 
     5323 
     5324    /** 
     5325     * Window position. 
     5326     */ 
     5327    pjmedia_coord pos; 
     5328 
     5329    /** 
     5330     * Window size. 
     5331     */ 
     5332    pjmedia_rect_size size; 
     5333 
     5334} pjsua_vid_win_info; 
     5335 
     5336 
     5337/** 
     5338 * Get window info. 
     5339 * 
     5340 * @param wid           The video window ID. 
     5341 * @param wi            The video window info to be initialized. 
     5342 * 
     5343 * @return              PJ_SUCCESS on success, or the appropriate error code. 
     5344 */ 
     5345PJ_DECL(pj_status_t) pjsua_vid_win_get_info(pjsua_vid_win_id wid, 
     5346                                            pjsua_vid_win_info *wi); 
     5347 
     5348/** 
     5349 * Show or hide window. 
     5350 * 
     5351 * @param wid           The video window ID. 
     5352 * @param show          Set to PJ_TRUE to show the window, PJ_FALSE to 
     5353 *                      hide the window. 
     5354 * 
     5355 * @return              PJ_SUCCESS on success, or the appropriate error code. 
     5356 */ 
     5357PJ_DECL(pj_status_t) pjsua_vid_win_set_show(pjsua_vid_win_id wid, 
     5358                                            pj_bool_t show); 
     5359 
     5360/** 
     5361 * Set video window position. 
     5362 * 
     5363 * @param wid           The video window ID. 
     5364 * @param pos           The window position. 
     5365 * 
     5366 * @return              PJ_SUCCESS on success, or the appropriate error code. 
     5367 */ 
     5368PJ_DECL(pj_status_t) pjsua_vid_win_set_pos(pjsua_vid_win_id wid, 
     5369                                           const pjmedia_coord *pos); 
     5370 
     5371/** 
     5372 * Resize window. 
     5373 * 
     5374 * @param wid           The video window ID. 
     5375 * @param size          The new window size. 
     5376 * 
     5377 * @return              PJ_SUCCESS on success, or the appropriate error code. 
     5378 */ 
     5379PJ_DECL(pj_status_t) pjsua_vid_win_set_size(pjsua_vid_win_id wid, 
     5380                                            const pjmedia_rect_size *size); 
     5381 
     5382 
     5383 
     5384/* 
     5385 * Video codecs API 
     5386 */ 
     5387 
     5388/** 
     5389 * Enum all supported video codecs in the system. 
     5390 * 
     5391 * @param id            Array of ID to be initialized. 
     5392 * @param count         On input, specifies max elements in the array. 
     5393 *                      On return, it contains actual number of elements 
     5394 *                      that have been initialized. 
     5395 * 
     5396 * @return              PJ_SUCCESS on success, or the appropriate error code. 
     5397 */ 
     5398PJ_DECL(pj_status_t) pjsua_vid_enum_codecs( pjsua_codec_info id[], 
     5399                                            unsigned *count ); 
     5400 
     5401 
     5402/** 
     5403 * Change video codec priority. 
     5404 * 
     5405 * @param codec_id      Codec ID, which is a string that uniquely identify 
     5406 *                      the codec (such as "H263/90000"). Please see pjsua 
     5407 *                      manual or pjmedia codec reference for details. 
     5408 * @param priority      Codec priority, 0-255, where zero means to disable 
     5409 *                      the codec. 
     5410 * 
     5411 * @return              PJ_SUCCESS on success, or the appropriate error code. 
     5412 */ 
     5413PJ_DECL(pj_status_t) pjsua_vid_codec_set_priority( const pj_str_t *codec_id, 
     5414                                                   pj_uint8_t priority ); 
     5415 
     5416 
     5417/** 
     5418 * Get video codec parameters. 
     5419 * 
     5420 * @param codec_id      Codec ID. 
     5421 * @param param         Structure to receive video codec parameters. 
     5422 * 
     5423 * @return              PJ_SUCCESS on success, or the appropriate error code. 
     5424 */ 
     5425PJ_DECL(pj_status_t) pjsua_vid_codec_get_param( 
     5426                                        const pj_str_t *codec_id, 
     5427                                        pjmedia_vid_codec_param *param); 
     5428 
     5429 
     5430/** 
     5431 * Set video codec parameters. 
     5432 * 
     5433 * @param codec_id      Codec ID. 
     5434 * @param param         Codec parameter to set. Set to NULL to reset 
     5435 *                      codec parameter to library default settings. 
     5436 * 
     5437 * @return              PJ_SUCCESS on success, or the appropriate error code. 
     5438 */ 
     5439PJ_DECL(pj_status_t) pjsua_vid_codec_set_param(  
     5440                                        const pj_str_t *codec_id, 
     5441                                        const pjmedia_vid_codec_param *param); 
     5442 
     5443 
     5444 
     5445/* end of VIDEO API */ 
    51915446/** 
    51925447 * @} 
    51935448 */ 
    51945449 
     5450 
     5451/** 
     5452 * @} 
     5453 */ 
     5454 
    51955455PJ_END_DECL 
    51965456 
  • pjproject/branches/projects/2.0-dev/pjsip/include/pjsua-lib/pjsua_internal.h

    r3560 r3609  
    304304} pjsua_stun_resolve; 
    305305 
     306typedef enum pjsua_vid_win_type 
     307{ 
     308    PJSUA_WND_TYPE_NONE, 
     309    PJSUA_WND_TYPE_PREVIEW, 
     310    PJSUA_WND_TYPE_STREAM 
     311} pjsua_vid_win_type; 
     312 
     313typedef struct pjsua_vid_win 
     314{ 
     315    pjsua_vid_win_type           type;          /**< Type.              */ 
     316    pj_pool_t                   *pool;          /**< Own pool.          */ 
     317    pjsua_call_id                call_id;       /**< Owner call or -1   */ 
     318    pjmedia_vid_port            *vp_cap;        /**< Capture vidport.   */ 
     319    pjmedia_vid_port            *vp_rend;       /**< Renderer vidport   */ 
     320    pjmedia_vid_dev_index        preview_cap_id;/* Capture dev id       */ 
     321} pjsua_vid_win; 
    306322 
    307323/** 
     
    398414    unsigned             rec_cnt;   /**< Number of file recorders.      */ 
    399415    pjsua_file_data      recorder[PJSUA_MAX_RECORDERS];/**< Array of recs.*/ 
     416 
     417    /* Video windows */ 
     418#if PJSUA_HAS_VIDEO 
     419    pjsua_vid_win        win[PJSUA_MAX_VID_WINS]; /**< Array of windows */ 
     420#endif 
    400421}; 
    401422 
     
    632653                char *buf, pj_size_t size); 
    633654 
     655/* 
     656 * Video 
     657 */ 
     658pj_status_t pjsua_vid_subsys_init(void); 
     659pj_status_t pjsua_vid_subsys_start(void); 
     660pj_status_t pjsua_vid_subsys_destroy(void); 
     661 
     662PJ_INLINE(void) pjsua_vid_win_reset(pjsua_vid_win_id wid) 
     663{ 
     664#if PJSUA_HAS_VIDEO 
     665    pjsua_vid_win *w = &pjsua_var.win[wid]; 
     666    pj_pool_t *pool = w->pool; 
     667 
     668    pj_bzero(w, sizeof(*w)); 
     669    if (pool) pj_pool_reset(pool); 
     670    w->call_id = PJSUA_INVALID_ID; 
     671    w->pool = pool; 
     672    w->preview_cap_id = PJMEDIA_VID_INVALID_DEV; 
     673#endif 
     674} 
     675 
    634676 
    635677PJ_END_DECL 
  • pjproject/branches/projects/2.0-dev/pjsip/src/pjsua-lib/pjsua_call.c

    r3573 r3609  
    11171117 
    11181118 
    1119 #if DISABLED_FOR_TICKET_1185 
    1120 /* 
    1121  * Retrieve the media session associated with this call. 
    1122  */ 
    1123 PJ_DEF(pjmedia_session*) pjsua_call_get_media_session(pjsua_call_id call_id) 
    1124 { 
    1125     PJ_ASSERT_RETURN(call_id>=0 && call_id<(int)pjsua_var.ua_cfg.max_calls,  
    1126                      NULL); 
    1127     return pjsua_var.calls[call_id].session; 
    1128 } 
    1129  
    1130  
    1131 /* 
    1132  * Retrieve the media transport instance that is used for this call. 
    1133  */ 
    1134 PJ_DEF(pjmedia_transport*) pjsua_call_get_media_transport(pjsua_call_id cid) 
    1135 { 
    1136     PJ_ASSERT_RETURN(cid>=0 && cid<(int)pjsua_var.ua_cfg.max_calls,  
    1137                      NULL); 
    1138     return pjsua_var.calls[cid].tp; 
    1139 } 
    1140 #endif /* Removed in 2.0 */ 
    1141  
    11421119/* Acquire lock to the specified call_id */ 
    11431120pj_status_t acquire_call(const char *title, 
     
    13371314 
    13381315        if (call_med->type == PJMEDIA_TYPE_AUDIO) { 
    1339             info->media[info->media_cnt].stream.audio.conf_slot =  
     1316            info->media[info->media_cnt].stream.aud.conf_slot = 
    13401317                                                call_med->strm.a.conf_slot; 
    13411318        } else if (call_med->type == PJMEDIA_TYPE_VIDEO) { 
    1342             info->media[info->media_cnt].stream.video.capturer = 
    1343                                                 call_med->strm.v.capturer; 
    1344             info->media[info->media_cnt].stream.video.renderer = 
    1345                                                 call_med->strm.v.renderer; 
     1319            PJ_TODO(vid_fill_in_call_info); 
     1320            info->media[info->media_cnt].stream.vid.win_in = PJSUA_INVALID_ID; 
     1321            info->media[info->media_cnt].stream.vid.cap_dev = 
     1322                    PJMEDIA_VID_INVALID_DEV; 
    13461323        } else { 
    13471324            continue; 
     
    21832160} 
    21842161 
    2185  
    2186 const char *good_number(char *buf, pj_int32_t val) 
    2187 { 
    2188     if (val < 1000) { 
    2189         pj_ansi_sprintf(buf, "%d", val); 
    2190     } else if (val < 1000000) { 
    2191         pj_ansi_sprintf(buf, "%d.%dK",  
    2192                         val / 1000, 
    2193                         (val % 1000) / 100); 
    2194     } else { 
    2195         pj_ansi_sprintf(buf, "%d.%02dM",  
    2196                         val / 1000000, 
    2197                         (val % 1000000) / 10000); 
    2198     } 
    2199  
    2200     return buf; 
    2201 } 
    2202  
    2203 static unsigned dump_media_stat(const char *indent,  
    2204                                 char *buf, unsigned maxlen, 
    2205                                 const pjmedia_rtcp_stat *stat, 
    2206                                 const char *rx_info, const char *tx_info) 
    2207 { 
    2208     char last_update[64]; 
    2209     char packets[32], bytes[32], ipbytes[32], avg_bps[32], avg_ipbps[32]; 
    2210     pj_time_val media_duration, now; 
    2211     char *p = buf, *end = buf+maxlen; 
    2212     int len; 
    2213  
    2214     if (stat->rx.update_cnt == 0) 
    2215         strcpy(last_update, "never"); 
    2216     else { 
    2217         pj_gettimeofday(&now); 
    2218         PJ_TIME_VAL_SUB(now, stat->rx.update); 
    2219         sprintf(last_update, "%02ldh:%02ldm:%02ld.%03lds ago", 
    2220                 now.sec / 3600, 
    2221                 (now.sec % 3600) / 60, 
    2222                 now.sec % 60, 
    2223                 now.msec); 
    2224     } 
    2225  
    2226     pj_gettimeofday(&media_duration); 
    2227     PJ_TIME_VAL_SUB(media_duration, stat->start); 
    2228     if (PJ_TIME_VAL_MSEC(media_duration) == 0) 
    2229         media_duration.msec = 1; 
    2230  
    2231     len = pj_ansi_snprintf(p, end-p, 
    2232            "%s     RX %s last update:%s\n" 
    2233            "%s        total %spkt %sB (%sB +IP hdr) @avg=%sbps/%sbps\n" 
    2234            "%s        pkt loss=%d (%3.1f%%), discrd=%d (%3.1f%%), dup=%d (%2.1f%%), reord=%d (%3.1f%%)\n" 
    2235            "%s              (msec)    min     avg     max     last    dev\n" 
    2236            "%s        loss period: %7.3f %7.3f %7.3f %7.3f %7.3f\n" 
    2237            "%s        jitter     : %7.3f %7.3f %7.3f %7.3f %7.3f\n" 
    2238 #if defined(PJMEDIA_RTCP_STAT_HAS_RAW_JITTER) && PJMEDIA_RTCP_STAT_HAS_RAW_JITTER!=0 
    2239            "%s        raw jitter : %7.3f %7.3f %7.3f %7.3f %7.3f\n" 
    2240 #endif 
    2241 #if defined(PJMEDIA_RTCP_STAT_HAS_IPDV) && PJMEDIA_RTCP_STAT_HAS_IPDV!=0 
    2242            "%s        IPDV       : %7.3f %7.3f %7.3f %7.3f %7.3f\n" 
    2243 #endif 
    2244            "%s", 
    2245            indent, 
    2246            rx_info? rx_info : "", 
    2247            last_update, 
    2248  
    2249            indent, 
    2250            good_number(packets, stat->rx.pkt), 
    2251            good_number(bytes, stat->rx.bytes), 
    2252            good_number(ipbytes, stat->rx.bytes + stat->rx.pkt * 40), 
    2253            good_number(avg_bps, (pj_int32_t)((pj_int64_t)stat->rx.bytes * 8 * 1000 / PJ_TIME_VAL_MSEC(media_duration))), 
    2254            good_number(avg_ipbps, (pj_int32_t)(((pj_int64_t)stat->rx.bytes + stat->rx.pkt * 40) * 8 * 1000 / PJ_TIME_VAL_MSEC(media_duration))), 
    2255            indent, 
    2256            stat->rx.loss, 
    2257            (stat->rx.loss? stat->rx.loss * 100.0 / (stat->rx.pkt + stat->rx.loss) : 0), 
    2258            stat->rx.discard,  
    2259            (stat->rx.discard? stat->rx.discard * 100.0 / (stat->rx.pkt + stat->rx.loss) : 0), 
    2260            stat->rx.dup,  
    2261            (stat->rx.dup? stat->rx.dup * 100.0 / (stat->rx.pkt + stat->rx.loss) : 0), 
    2262            stat->rx.reorder,  
    2263            (stat->rx.reorder? stat->rx.reorder * 100.0 / (stat->rx.pkt + stat->rx.loss) : 0), 
    2264            indent, indent, 
    2265            stat->rx.loss_period.min / 1000.0,  
    2266            stat->rx.loss_period.mean / 1000.0,  
    2267            stat->rx.loss_period.max / 1000.0, 
    2268            stat->rx.loss_period.last / 1000.0, 
    2269            pj_math_stat_get_stddev(&stat->rx.loss_period) / 1000.0, 
    2270            indent, 
    2271            stat->rx.jitter.min / 1000.0, 
    2272            stat->rx.jitter.mean / 1000.0, 
    2273            stat->rx.jitter.max / 1000.0, 
    2274            stat->rx.jitter.last / 1000.0, 
    2275            pj_math_stat_get_stddev(&stat->rx.jitter) / 1000.0, 
    2276 #if defined(PJMEDIA_RTCP_STAT_HAS_RAW_JITTER) && PJMEDIA_RTCP_STAT_HAS_RAW_JITTER!=0 
    2277            indent, 
    2278            stat->rx_raw_jitter.min / 1000.0, 
    2279            stat->rx_raw_jitter.mean / 1000.0, 
    2280            stat->rx_raw_jitter.max / 1000.0, 
    2281            stat->rx_raw_jitter.last / 1000.0, 
    2282            pj_math_stat_get_stddev(&stat->rx_raw_jitter) / 1000.0, 
    2283 #endif 
    2284 #if defined(PJMEDIA_RTCP_STAT_HAS_IPDV) && PJMEDIA_RTCP_STAT_HAS_IPDV!=0 
    2285            indent, 
    2286            stat->rx_ipdv.min / 1000.0, 
    2287            stat->rx_ipdv.mean / 1000.0, 
    2288            stat->rx_ipdv.max / 1000.0, 
    2289            stat->rx_ipdv.last / 1000.0, 
    2290            pj_math_stat_get_stddev(&stat->rx_ipdv) / 1000.0, 
    2291 #endif 
    2292            "" 
    2293            ); 
    2294  
    2295     if (len < 1 || len > end-p) { 
    2296         *p = '\0'; 
    2297         return (p-buf); 
    2298     } 
    2299     p += len; 
    2300  
    2301     if (stat->tx.update_cnt == 0) 
    2302         strcpy(last_update, "never"); 
    2303     else { 
    2304         pj_gettimeofday(&now); 
    2305         PJ_TIME_VAL_SUB(now, stat->tx.update); 
    2306         sprintf(last_update, "%02ldh:%02ldm:%02ld.%03lds ago", 
    2307                 now.sec / 3600, 
    2308                 (now.sec % 3600) / 60, 
    2309                 now.sec % 60, 
    2310                 now.msec); 
    2311     } 
    2312  
    2313     len = pj_ansi_snprintf(p, end-p, 
    2314            "%s     TX %s last update:%s\n" 
    2315            "%s        total %spkt %sB (%sB +IP hdr) @avg %sbps/%sbps\n" 
    2316            "%s        pkt loss=%d (%3.1f%%), dup=%d (%3.1f%%), reorder=%d (%3.1f%%)\n" 
    2317            "%s              (msec)    min     avg     max     last    dev \n" 
    2318            "%s        loss period: %7.3f %7.3f %7.3f %7.3f %7.3f\n" 
    2319            "%s        jitter     : %7.3f %7.3f %7.3f %7.3f %7.3f\n", 
    2320            indent, 
    2321            tx_info, 
    2322            last_update, 
    2323  
    2324            indent, 
    2325            good_number(packets, stat->tx.pkt), 
    2326            good_number(bytes, stat->tx.bytes), 
    2327            good_number(ipbytes, stat->tx.bytes + stat->tx.pkt * 40), 
    2328            good_number(avg_bps, (pj_int32_t)((pj_int64_t)stat->tx.bytes * 8 * 1000 / PJ_TIME_VAL_MSEC(media_duration))), 
    2329            good_number(avg_ipbps, (pj_int32_t)(((pj_int64_t)stat->tx.bytes + stat->tx.pkt * 40) * 8 * 1000 / PJ_TIME_VAL_MSEC(media_duration))), 
    2330  
    2331            indent, 
    2332            stat->tx.loss, 
    2333            (stat->tx.loss? stat->tx.loss * 100.0 / (stat->tx.pkt + stat->tx.loss) : 0), 
    2334            stat->tx.dup,  
    2335            (stat->tx.dup? stat->tx.dup * 100.0 / (stat->tx.pkt + stat->tx.loss) : 0), 
    2336            stat->tx.reorder,  
    2337            (stat->tx.reorder? stat->tx.reorder * 100.0 / (stat->tx.pkt + stat->tx.loss) : 0), 
    2338  
    2339            indent, indent, 
    2340            stat->tx.loss_period.min / 1000.0,  
    2341            stat->tx.loss_period.mean / 1000.0,  
    2342            stat->tx.loss_period.max / 1000.0, 
    2343            stat->tx.loss_period.last / 1000.0, 
    2344            pj_math_stat_get_stddev(&stat->tx.loss_period) / 1000.0, 
    2345            indent, 
    2346            stat->tx.jitter.min / 1000.0, 
    2347            stat->tx.jitter.mean / 1000.0, 
    2348            stat->tx.jitter.max / 1000.0, 
    2349            stat->tx.jitter.last / 1000.0, 
    2350            pj_math_stat_get_stddev(&stat->tx.jitter) / 1000.0 
    2351            ); 
    2352  
    2353     if (len < 1 || len > end-p) { 
    2354         *p = '\0'; 
    2355         return (p-buf); 
    2356     } 
    2357     p += len; 
    2358  
    2359     len = pj_ansi_snprintf(p, end-p, 
    2360            "%s     RTT msec      : %7.3f %7.3f %7.3f %7.3f %7.3f\n", 
    2361            indent, 
    2362            stat->rtt.min / 1000.0, 
    2363            stat->rtt.mean / 1000.0, 
    2364            stat->rtt.max / 1000.0, 
    2365            stat->rtt.last / 1000.0, 
    2366            pj_math_stat_get_stddev(&stat->rtt) / 1000.0 
    2367            ); 
    2368     if (len < 1 || len > end-p) { 
    2369         *p = '\0'; 
    2370         return (p-buf); 
    2371     } 
    2372     p += len; 
    2373  
    2374     return (p-buf); 
    2375 } 
    2376  
    2377  
    2378 /* Dump media session */ 
    2379 static void dump_media_session(const char *indent,  
    2380                                char *buf, unsigned maxlen, 
    2381                                pjsua_call *call) 
    2382 { 
    2383     unsigned i; 
    2384     char *p = buf, *end = buf+maxlen; 
    2385     int len; 
    2386  
    2387     for (i=0; i<call->med_cnt; ++i) { 
    2388         pjsua_call_media *call_med = &call->media[i]; 
    2389         pjmedia_rtcp_stat stat; 
    2390         pj_bool_t has_stat; 
    2391         pjmedia_transport_info tp_info; 
    2392         char rem_addr_buf[80]; 
    2393         char codec_info[32] = {'0'}; 
    2394         char rx_info[80] = {'\0'}; 
    2395         char tx_info[80] = {'\0'}; 
    2396         const char *rem_addr; 
    2397         const char *dir_str; 
    2398         const char *media_type_str; 
    2399  
    2400         switch (call_med->type) { 
    2401         case PJMEDIA_TYPE_AUDIO: 
    2402             media_type_str = "audio"; 
    2403             break; 
    2404         case PJMEDIA_TYPE_VIDEO: 
    2405             media_type_str = "video"; 
    2406             break; 
    2407         case PJMEDIA_TYPE_APPLICATION: 
    2408             media_type_str = "application"; 
    2409             break; 
    2410         default: 
    2411             media_type_str = "unknown"; 
    2412             break; 
    2413         } 
    2414  
    2415         /* Check if the stream is deactivated */ 
    2416         if (call_med->tp == NULL || 
    2417             (!call_med->strm.a.stream && !call_med->strm.v.stream)) 
    2418         { 
    2419             len = pj_ansi_snprintf(p, end-p, 
    2420                       "%s #%d %s deactivated\n", 
    2421                       indent, i, media_type_str); 
    2422             if (len < 1 || len > end-p) { 
    2423                 *p = '\0'; 
    2424                 return; 
    2425             } 
    2426  
    2427             p += len; 
    2428             continue; 
    2429         } 
    2430  
    2431         pjmedia_transport_info_init(&tp_info); 
    2432         pjmedia_transport_get_info(call_med->tp, &tp_info); 
    2433  
    2434         // rem_addr will contain actual address of RTP originator, instead of 
    2435         // remote RTP address specified by stream which is fetched from the SDP. 
    2436         // Please note that we are assuming only one stream per call. 
    2437         //rem_addr = pj_sockaddr_print(&info.stream_info[i].rem_addr, 
    2438         //                           rem_addr_buf, sizeof(rem_addr_buf), 3); 
    2439         if (pj_sockaddr_has_addr(&tp_info.src_rtp_name)) { 
    2440             rem_addr = pj_sockaddr_print(&tp_info.src_rtp_name, rem_addr_buf,  
    2441                                          sizeof(rem_addr_buf), 3); 
    2442         } else { 
    2443             pj_ansi_snprintf(rem_addr_buf, sizeof(rem_addr_buf), "-"); 
    2444             rem_addr = rem_addr_buf; 
    2445         } 
    2446  
    2447         if (call_med->dir == PJMEDIA_DIR_NONE) { 
    2448             /* To handle when the stream that is currently being paused 
    2449              * (http://trac.pjsip.org/repos/ticket/1079) 
    2450              */ 
    2451             dir_str = "inactive"; 
    2452         } else if (call_med->dir == PJMEDIA_DIR_ENCODING) 
    2453             dir_str = "sendonly"; 
    2454         else if (call_med->dir == PJMEDIA_DIR_DECODING) 
    2455             dir_str = "recvonly"; 
    2456         else if (call_med->dir == PJMEDIA_DIR_ENCODING_DECODING) 
    2457             dir_str = "sendrecv"; 
    2458         else 
    2459             dir_str = "inactive"; 
    2460  
    2461         if (call_med->type == PJMEDIA_TYPE_AUDIO) { 
    2462             pjmedia_stream *stream = call_med->strm.a.stream; 
    2463             pjmedia_stream_info info; 
    2464  
    2465             pjmedia_stream_get_stat(stream, &stat); 
    2466             has_stat = PJ_TRUE; 
    2467  
    2468             pjmedia_stream_get_info(stream, &info); 
    2469             pj_ansi_snprintf(codec_info, sizeof(codec_info), " %.*s @%dkHz", 
    2470                              (int)info.fmt.encoding_name.slen, 
    2471                              info.fmt.encoding_name.ptr, 
    2472                              info.fmt.clock_rate / 1000); 
    2473             pj_ansi_snprintf(rx_info, sizeof(rx_info), "pt=%d,", 
    2474                              info.fmt.pt); 
    2475             pj_ansi_snprintf(tx_info, sizeof(tx_info), "pt=%d, ptime=%d,", 
    2476                              info.tx_pt, 
    2477                              info.param->setting.frm_per_pkt* 
    2478                              info.param->info.frm_ptime); 
    2479         } else if (call_med->type == PJMEDIA_TYPE_VIDEO) { 
    2480             pjmedia_vid_stream *stream = call_med->strm.v.stream; 
    2481             pjmedia_vid_stream_info info; 
    2482  
    2483             pjmedia_vid_stream_get_stat(stream, &stat); 
    2484             has_stat = PJ_TRUE; 
    2485  
    2486             pjmedia_vid_stream_get_info(stream, &info); 
    2487             pj_ansi_snprintf(codec_info, sizeof(codec_info), " %.*s", 
    2488                              (int)info.codec_info.encoding_name.slen, 
    2489                              info.codec_info.encoding_name.ptr); 
    2490             if (call_med->dir & PJMEDIA_DIR_DECODING) { 
    2491                 pjmedia_video_format_detail *vfd; 
    2492                 vfd = pjmedia_format_get_video_format_detail( 
    2493                                         &info.codec_param->dec_fmt, PJ_TRUE); 
    2494                 pj_ansi_snprintf(rx_info, sizeof(rx_info), 
    2495                                  "pt=%d, size=%dx%d, fps=%.2f,", 
    2496                                  info.rx_pt, 
    2497                                  vfd->size.w, vfd->size.h, 
    2498                                  vfd->fps.num*1.0/vfd->fps.denum); 
    2499             } 
    2500             if (call_med->dir & PJMEDIA_DIR_ENCODING) { 
    2501                 pjmedia_video_format_detail *vfd; 
    2502                 vfd = pjmedia_format_get_video_format_detail( 
    2503                                         &info.codec_param->enc_fmt, PJ_TRUE); 
    2504                 pj_ansi_snprintf(tx_info, sizeof(tx_info), 
    2505                                  "pt=%d, size=%dx%d, fps=%.2f,", 
    2506                                  info.tx_pt, 
    2507                                  vfd->size.w, vfd->size.h, 
    2508                                  vfd->fps.num*1.0/vfd->fps.denum); 
    2509             } 
    2510         } else { 
    2511             has_stat = PJ_FALSE; 
    2512         } 
    2513  
    2514         len = pj_ansi_snprintf(p, end-p, 
    2515                   "%s  #%d %s%s, %s, peer=%s\n", 
    2516                   indent, 
    2517                   call_med->idx, 
    2518                   media_type_str, 
    2519                   codec_info, 
    2520                   dir_str, 
    2521                   rem_addr); 
    2522         if (len < 1 || len > end-p) { 
    2523             *p = '\0'; 
    2524             return; 
    2525         } 
    2526         p += len; 
    2527  
    2528         /* Get and ICE SRTP status */ 
    2529         if (call_med->tp) { 
    2530             pjmedia_transport_info tp_info; 
    2531  
    2532             pjmedia_transport_info_init(&tp_info); 
    2533             pjmedia_transport_get_info(call_med->tp, &tp_info); 
    2534             if (tp_info.specific_info_cnt > 0) { 
    2535                 unsigned j; 
    2536                 for (j = 0; j < tp_info.specific_info_cnt; ++j) { 
    2537                     if (tp_info.spc_info[j].type == PJMEDIA_TRANSPORT_TYPE_SRTP) 
    2538                     { 
    2539                         pjmedia_srtp_info *srtp_info = 
    2540                                     (pjmedia_srtp_info*) tp_info.spc_info[j].buffer; 
    2541  
    2542                         len = pj_ansi_snprintf(p, end-p, 
    2543                                                "   %s  SRTP status: %s Crypto-suite: %s", 
    2544                                                indent, 
    2545                                                (srtp_info->active?"Active":"Not active"), 
    2546                                                srtp_info->tx_policy.name.ptr); 
    2547                         if (len > 0 && len < end-p) { 
    2548                             p += len; 
    2549                             *p++ = '\n'; 
    2550                             *p = '\0'; 
    2551                         } 
    2552                     } else if (tp_info.spc_info[j].type==PJMEDIA_TRANSPORT_TYPE_ICE) { 
    2553                         const pjmedia_ice_transport_info *ii; 
    2554  
    2555                         ii = (const pjmedia_ice_transport_info*) 
    2556                              tp_info.spc_info[j].buffer; 
    2557  
    2558                         len = pj_ansi_snprintf(p, end-p, 
    2559                                                "   %s  ICE role: %s, state: %s, comp_cnt: %u", 
    2560                                                indent, 
    2561                                                pj_ice_sess_role_name(ii->role), 
    2562                                                pj_ice_strans_state_name(ii->sess_state), 
    2563                                                ii->comp_cnt); 
    2564                         if (len > 0 && len < end-p) { 
    2565                             p += len; 
    2566                             *p++ = '\n'; 
    2567                             *p = '\0'; 
    2568                         } 
    2569                     } 
    2570                 } 
    2571             } 
    2572         } 
    2573  
    2574  
    2575         if (has_stat) { 
    2576             len = dump_media_stat(indent, p, end-p, &stat, 
    2577                                   rx_info, tx_info); 
    2578             p += len; 
    2579         } 
    2580  
    2581 #if defined(PJMEDIA_HAS_RTCP_XR) && (PJMEDIA_HAS_RTCP_XR != 0) 
    2582 #   define SAMPLES_TO_USEC(usec, samples, clock_rate) \ 
    2583         do { \ 
    2584             if (samples <= 4294) \ 
    2585                 usec = samples * 1000000 / clock_rate; \ 
    2586             else { \ 
    2587                 usec = samples * 1000 / clock_rate; \ 
    2588                 usec *= 1000; \ 
    2589             } \ 
    2590         } while(0) 
    2591  
    2592 #   define PRINT_VOIP_MTC_VAL(s, v) \ 
    2593         if (v == 127) \ 
    2594             sprintf(s, "(na)"); \ 
    2595         else \ 
    2596             sprintf(s, "%d", v) 
    2597  
    2598 #   define VALIDATE_PRINT_BUF() \ 
    2599         if (len < 1 || len > end-p) { *p = '\0'; return; } \ 
    2600         p += len; *p++ = '\n'; *p = '\0' 
    2601  
    2602  
    2603         if (call_med->type == PJMEDIA_TYPE_AUDIO) { 
    2604             pjmedia_stream_info info; 
    2605             char last_update[64]; 
    2606             char loss[16], dup[16]; 
    2607             char jitter[80]; 
    2608             char toh[80]; 
    2609             char plc[16], jba[16], jbr[16]; 
    2610             char signal_lvl[16], noise_lvl[16], rerl[16]; 
    2611             char r_factor[16], ext_r_factor[16], mos_lq[16], mos_cq[16]; 
    2612             pjmedia_rtcp_xr_stat xr_stat; 
    2613             unsigned clock_rate; 
    2614             pj_time_val now; 
    2615  
    2616             if (pjmedia_stream_get_stat_xr(call_med->strm.a.stream, 
    2617                                            &xr_stat) != PJ_SUCCESS) 
    2618             { 
    2619                 continue; 
    2620             } 
    2621  
    2622             if (pjmedia_stream_get_info(call_med->strm.a.stream, &info) 
    2623                     != PJ_SUCCESS) 
    2624             { 
    2625                 continue; 
    2626             } 
    2627  
    2628             clock_rate = info.fmt.clock_rate; 
    2629             pj_gettimeofday(&now); 
    2630  
    2631             len = pj_ansi_snprintf(p, end-p, "\n%s  Extended reports:", indent); 
    2632             VALIDATE_PRINT_BUF(); 
    2633  
    2634             /* Statistics Summary */ 
    2635             len = pj_ansi_snprintf(p, end-p, "%s   Statistics Summary", indent); 
    2636             VALIDATE_PRINT_BUF(); 
    2637  
    2638             if (xr_stat.rx.stat_sum.l) 
    2639                 sprintf(loss, "%d", xr_stat.rx.stat_sum.lost); 
    2640             else 
    2641                 sprintf(loss, "(na)"); 
    2642  
    2643             if (xr_stat.rx.stat_sum.d) 
    2644                 sprintf(dup, "%d", xr_stat.rx.stat_sum.dup); 
    2645             else 
    2646                 sprintf(dup, "(na)"); 
    2647  
    2648             if (xr_stat.rx.stat_sum.j) { 
    2649                 unsigned jmin, jmax, jmean, jdev; 
    2650  
    2651                 SAMPLES_TO_USEC(jmin, xr_stat.rx.stat_sum.jitter.min,  
    2652                                 clock_rate); 
    2653                 SAMPLES_TO_USEC(jmax, xr_stat.rx.stat_sum.jitter.max,  
    2654                                 clock_rate); 
    2655                 SAMPLES_TO_USEC(jmean, xr_stat.rx.stat_sum.jitter.mean,  
    2656                                 clock_rate); 
    2657                 SAMPLES_TO_USEC(jdev,  
    2658                                pj_math_stat_get_stddev(&xr_stat.rx.stat_sum.jitter), 
    2659                                clock_rate); 
    2660                 sprintf(jitter, "%7.3f %7.3f %7.3f %7.3f",  
    2661                         jmin/1000.0, jmean/1000.0, jmax/1000.0, jdev/1000.0); 
    2662             } else 
    2663                 sprintf(jitter, "(report not available)"); 
    2664  
    2665             if (xr_stat.rx.stat_sum.t) { 
    2666                 sprintf(toh, "%11d %11d %11d %11d",  
    2667                         xr_stat.rx.stat_sum.toh.min, 
    2668                         xr_stat.rx.stat_sum.toh.mean, 
    2669                         xr_stat.rx.stat_sum.toh.max, 
    2670                         pj_math_stat_get_stddev(&xr_stat.rx.stat_sum.toh)); 
    2671             } else 
    2672                 sprintf(toh, "(report not available)"); 
    2673  
    2674             if (xr_stat.rx.stat_sum.update.sec == 0) 
    2675                 strcpy(last_update, "never"); 
    2676             else { 
    2677                 pj_gettimeofday(&now); 
    2678                 PJ_TIME_VAL_SUB(now, xr_stat.rx.stat_sum.update); 
    2679                 sprintf(last_update, "%02ldh:%02ldm:%02ld.%03lds ago", 
    2680                         now.sec / 3600, 
    2681                         (now.sec % 3600) / 60, 
    2682                         now.sec % 60, 
    2683                         now.msec); 
    2684             } 
    2685  
    2686             len = pj_ansi_snprintf(p, end-p,  
    2687                     "%s     RX last update: %s\n" 
    2688                     "%s        begin seq=%d, end seq=%d\n" 
    2689                     "%s        pkt loss=%s, dup=%s\n" 
    2690                     "%s              (msec)    min     avg     max     dev\n" 
    2691                     "%s        jitter     : %s\n" 
    2692                     "%s        toh        : %s", 
    2693                     indent, last_update, 
    2694                     indent, 
    2695                     xr_stat.rx.stat_sum.begin_seq, xr_stat.rx.stat_sum.end_seq, 
    2696                     indent, loss, dup, 
    2697                     indent,  
    2698                     indent, jitter, 
    2699                     indent, toh 
    2700                     ); 
    2701             VALIDATE_PRINT_BUF(); 
    2702  
    2703             if (xr_stat.tx.stat_sum.l) 
    2704                 sprintf(loss, "%d", xr_stat.tx.stat_sum.lost); 
    2705             else 
    2706                 sprintf(loss, "(na)"); 
    2707  
    2708             if (xr_stat.tx.stat_sum.d) 
    2709                 sprintf(dup, "%d", xr_stat.tx.stat_sum.dup); 
    2710             else 
    2711                 sprintf(dup, "(na)"); 
    2712  
    2713             if (xr_stat.tx.stat_sum.j) { 
    2714                 unsigned jmin, jmax, jmean, jdev; 
    2715  
    2716                 SAMPLES_TO_USEC(jmin, xr_stat.tx.stat_sum.jitter.min,  
    2717                                 clock_rate); 
    2718                 SAMPLES_TO_USEC(jmax, xr_stat.tx.stat_sum.jitter.max,  
    2719                                 clock_rate); 
    2720                 SAMPLES_TO_USEC(jmean, xr_stat.tx.stat_sum.jitter.mean,  
    2721                                 clock_rate); 
    2722                 SAMPLES_TO_USEC(jdev,  
    2723                                pj_math_stat_get_stddev(&xr_stat.tx.stat_sum.jitter), 
    2724                                clock_rate); 
    2725                 sprintf(jitter, "%7.3f %7.3f %7.3f %7.3f",  
    2726                         jmin/1000.0, jmean/1000.0, jmax/1000.0, jdev/1000.0); 
    2727             } else 
    2728                 sprintf(jitter, "(report not available)"); 
    2729  
    2730             if (xr_stat.tx.stat_sum.t) { 
    2731                 sprintf(toh, "%11d %11d %11d %11d",  
    2732                         xr_stat.tx.stat_sum.toh.min, 
    2733                         xr_stat.tx.stat_sum.toh.mean, 
    2734                         xr_stat.tx.stat_sum.toh.max, 
    2735                         pj_math_stat_get_stddev(&xr_stat.rx.stat_sum.toh)); 
    2736             } else 
    2737                 sprintf(toh,    "(report not available)"); 
    2738  
    2739             if (xr_stat.tx.stat_sum.update.sec == 0) 
    2740                 strcpy(last_update, "never"); 
    2741             else { 
    2742                 pj_gettimeofday(&now); 
    2743                 PJ_TIME_VAL_SUB(now, xr_stat.tx.stat_sum.update); 
    2744                 sprintf(last_update, "%02ldh:%02ldm:%02ld.%03lds ago", 
    2745                         now.sec / 3600, 
    2746                         (now.sec % 3600) / 60, 
    2747                         now.sec % 60, 
    2748                         now.msec); 
    2749             } 
    2750  
    2751             len = pj_ansi_snprintf(p, end-p,  
    2752                     "%s     TX last update: %s\n" 
    2753                     "%s        begin seq=%d, end seq=%d\n" 
    2754                     "%s        pkt loss=%s, dup=%s\n" 
    2755                     "%s              (msec)    min     avg     max     dev\n" 
    2756                     "%s        jitter     : %s\n" 
    2757                     "%s        toh        : %s", 
    2758                     indent, last_update, 
    2759                     indent, 
    2760                     xr_stat.tx.stat_sum.begin_seq, xr_stat.tx.stat_sum.end_seq, 
    2761                     indent, loss, dup, 
    2762                     indent, 
    2763                     indent, jitter, 
    2764                     indent, toh 
    2765                     ); 
    2766             VALIDATE_PRINT_BUF(); 
    2767  
    2768  
    2769             /* VoIP Metrics */ 
    2770             len = pj_ansi_snprintf(p, end-p, "%s   VoIP Metrics", indent); 
    2771             VALIDATE_PRINT_BUF(); 
    2772  
    2773             PRINT_VOIP_MTC_VAL(signal_lvl, xr_stat.rx.voip_mtc.signal_lvl); 
    2774             PRINT_VOIP_MTC_VAL(noise_lvl, xr_stat.rx.voip_mtc.noise_lvl); 
    2775             PRINT_VOIP_MTC_VAL(rerl, xr_stat.rx.voip_mtc.rerl); 
    2776             PRINT_VOIP_MTC_VAL(r_factor, xr_stat.rx.voip_mtc.r_factor); 
    2777             PRINT_VOIP_MTC_VAL(ext_r_factor, xr_stat.rx.voip_mtc.ext_r_factor); 
    2778             PRINT_VOIP_MTC_VAL(mos_lq, xr_stat.rx.voip_mtc.mos_lq); 
    2779             PRINT_VOIP_MTC_VAL(mos_cq, xr_stat.rx.voip_mtc.mos_cq); 
    2780  
    2781             switch ((xr_stat.rx.voip_mtc.rx_config>>6) & 3) { 
    2782                 case PJMEDIA_RTCP_XR_PLC_DIS: 
    2783                     sprintf(plc, "DISABLED"); 
    2784                     break; 
    2785                 case PJMEDIA_RTCP_XR_PLC_ENH: 
    2786                     sprintf(plc, "ENHANCED"); 
    2787                     break; 
    2788                 case PJMEDIA_RTCP_XR_PLC_STD: 
    2789                     sprintf(plc, "STANDARD"); 
    2790                     break; 
    2791                 case PJMEDIA_RTCP_XR_PLC_UNK: 
    2792                 default: 
    2793                     sprintf(plc, "UNKNOWN"); 
    2794                     break; 
    2795             } 
    2796  
    2797             switch ((xr_stat.rx.voip_mtc.rx_config>>4) & 3) { 
    2798                 case PJMEDIA_RTCP_XR_JB_FIXED: 
    2799                     sprintf(jba, "FIXED"); 
    2800                     break; 
    2801                 case PJMEDIA_RTCP_XR_JB_ADAPTIVE: 
    2802                     sprintf(jba, "ADAPTIVE"); 
    2803                     break; 
    2804                 default: 
    2805                     sprintf(jba, "UNKNOWN"); 
    2806                     break; 
    2807             } 
    2808  
    2809             sprintf(jbr, "%d", xr_stat.rx.voip_mtc.rx_config & 0x0F); 
    2810  
    2811             if (xr_stat.rx.voip_mtc.update.sec == 0) 
    2812                 strcpy(last_update, "never"); 
    2813             else { 
    2814                 pj_gettimeofday(&now); 
    2815                 PJ_TIME_VAL_SUB(now, xr_stat.rx.voip_mtc.update); 
    2816                 sprintf(last_update, "%02ldh:%02ldm:%02ld.%03lds ago", 
    2817                         now.sec / 3600, 
    2818                         (now.sec % 3600) / 60, 
    2819                         now.sec % 60, 
    2820                         now.msec); 
    2821             } 
    2822  
    2823             len = pj_ansi_snprintf(p, end-p,  
    2824                     "%s     RX last update: %s\n" 
    2825                     "%s        packets    : loss rate=%d (%.2f%%), discard rate=%d (%.2f%%)\n" 
    2826                     "%s        burst      : density=%d (%.2f%%), duration=%d%s\n" 
    2827                     "%s        gap        : density=%d (%.2f%%), duration=%d%s\n" 
    2828                     "%s        delay      : round trip=%d%s, end system=%d%s\n" 
    2829                     "%s        level      : signal=%s%s, noise=%s%s, RERL=%s%s\n" 
    2830                     "%s        quality    : R factor=%s, ext R factor=%s\n" 
    2831                     "%s                     MOS LQ=%s, MOS CQ=%s\n" 
    2832                     "%s        config     : PLC=%s, JB=%s, JB rate=%s, Gmin=%d\n" 
    2833                     "%s        JB delay   : cur=%d%s, max=%d%s, abs max=%d%s", 
    2834                     indent, 
    2835                     last_update, 
    2836                     /* packets */ 
    2837                     indent, 
    2838                     xr_stat.rx.voip_mtc.loss_rate, xr_stat.rx.voip_mtc.loss_rate*100.0/256, 
    2839                     xr_stat.rx.voip_mtc.discard_rate, xr_stat.rx.voip_mtc.discard_rate*100.0/256, 
    2840                     /* burst */ 
    2841                     indent, 
    2842                     xr_stat.rx.voip_mtc.burst_den, xr_stat.rx.voip_mtc.burst_den*100.0/256, 
    2843                     xr_stat.rx.voip_mtc.burst_dur, "ms", 
    2844                     /* gap */ 
    2845                     indent, 
    2846                     xr_stat.rx.voip_mtc.gap_den, xr_stat.rx.voip_mtc.gap_den*100.0/256, 
    2847                     xr_stat.rx.voip_mtc.gap_dur, "ms", 
    2848                     /* delay */ 
    2849                     indent, 
    2850                     xr_stat.rx.voip_mtc.rnd_trip_delay, "ms", 
    2851                     xr_stat.rx.voip_mtc.end_sys_delay, "ms", 
    2852                     /* level */ 
    2853                     indent, 
    2854                     signal_lvl, "dB", 
    2855                     noise_lvl, "dB", 
    2856                     rerl, "", 
    2857                     /* quality */ 
    2858                     indent, 
    2859                     r_factor, ext_r_factor,  
    2860                     indent, 
    2861                     mos_lq, mos_cq, 
    2862                     /* config */ 
    2863                     indent, 
    2864                     plc, jba, jbr, xr_stat.rx.voip_mtc.gmin, 
    2865                     /* JB delay */ 
    2866                     indent, 
    2867                     xr_stat.rx.voip_mtc.jb_nom, "ms", 
    2868                     xr_stat.rx.voip_mtc.jb_max, "ms", 
    2869                     xr_stat.rx.voip_mtc.jb_abs_max, "ms" 
    2870                     ); 
    2871             VALIDATE_PRINT_BUF(); 
    2872  
    2873             PRINT_VOIP_MTC_VAL(signal_lvl, xr_stat.tx.voip_mtc.signal_lvl); 
    2874             PRINT_VOIP_MTC_VAL(noise_lvl, xr_stat.tx.voip_mtc.noise_lvl); 
    2875             PRINT_VOIP_MTC_VAL(rerl, xr_stat.tx.voip_mtc.rerl); 
    2876             PRINT_VOIP_MTC_VAL(r_factor, xr_stat.tx.voip_mtc.r_factor); 
    2877             PRINT_VOIP_MTC_VAL(ext_r_factor, xr_stat.tx.voip_mtc.ext_r_factor); 
    2878             PRINT_VOIP_MTC_VAL(mos_lq, xr_stat.tx.voip_mtc.mos_lq); 
    2879             PRINT_VOIP_MTC_VAL(mos_cq, xr_stat.tx.voip_mtc.mos_cq); 
    2880  
    2881             switch ((xr_stat.tx.voip_mtc.rx_config>>6) & 3) { 
    2882                 case PJMEDIA_RTCP_XR_PLC_DIS: 
    2883                     sprintf(plc, "DISABLED"); 
    2884                     break; 
    2885                 case PJMEDIA_RTCP_XR_PLC_ENH: 
    2886                     sprintf(plc, "ENHANCED"); 
    2887                     break; 
    2888                 case PJMEDIA_RTCP_XR_PLC_STD: 
    2889                     sprintf(plc, "STANDARD"); 
    2890                     break; 
    2891                 case PJMEDIA_RTCP_XR_PLC_UNK: 
    2892                 default: 
    2893                     sprintf(plc, "unknown"); 
    2894                     break; 
    2895             } 
    2896  
    2897             switch ((xr_stat.tx.voip_mtc.rx_config>>4) & 3) { 
    2898                 case PJMEDIA_RTCP_XR_JB_FIXED: 
    2899                     sprintf(jba, "FIXED"); 
    2900                     break; 
    2901                 case PJMEDIA_RTCP_XR_JB_ADAPTIVE: 
    2902                     sprintf(jba, "ADAPTIVE"); 
    2903                     break; 
    2904                 default: 
    2905                     sprintf(jba, "unknown"); 
    2906                     break; 
    2907             } 
    2908  
    2909             sprintf(jbr, "%d", xr_stat.tx.voip_mtc.rx_config & 0x0F); 
    2910  
    2911             if (xr_stat.tx.voip_mtc.update.sec == 0) 
    2912                 strcpy(last_update, "never"); 
    2913             else { 
    2914                 pj_gettimeofday(&now); 
    2915                 PJ_TIME_VAL_SUB(now, xr_stat.tx.voip_mtc.update); 
    2916                 sprintf(last_update, "%02ldh:%02ldm:%02ld.%03lds ago", 
    2917                         now.sec / 3600, 
    2918                         (now.sec % 3600) / 60, 
    2919                         now.sec % 60, 
    2920                         now.msec); 
    2921             } 
    2922  
    2923             len = pj_ansi_snprintf(p, end-p,  
    2924                     "%s     TX last update: %s\n" 
    2925                     "%s        packets    : loss rate=%d (%.2f%%), discard rate=%d (%.2f%%)\n" 
    2926                     "%s        burst      : density=%d (%.2f%%), duration=%d%s\n" 
    2927                     "%s        gap        : density=%d (%.2f%%), duration=%d%s\n" 
    2928                     "%s        delay      : round trip=%d%s, end system=%d%s\n" 
    2929                     "%s        level      : signal=%s%s, noise=%s%s, RERL=%s%s\n" 
    2930                     "%s        quality    : R factor=%s, ext R factor=%s\n" 
    2931                     "%s                     MOS LQ=%s, MOS CQ=%s\n" 
    2932                     "%s        config     : PLC=%s, JB=%s, JB rate=%s, Gmin=%d\n" 
    2933                     "%s        JB delay   : cur=%d%s, max=%d%s, abs max=%d%s", 
    2934                     indent, 
    2935                     last_update, 
    2936                     /* pakcets */ 
    2937                     indent, 
    2938                     xr_stat.tx.voip_mtc.loss_rate, xr_stat.tx.voip_mtc.loss_rate*100.0/256, 
    2939                     xr_stat.tx.voip_mtc.discard_rate, xr_stat.tx.voip_mtc.discard_rate*100.0/256, 
    2940                     /* burst */ 
    2941                     indent, 
    2942                     xr_stat.tx.voip_mtc.burst_den, xr_stat.tx.voip_mtc.burst_den*100.0/256, 
    2943                     xr_stat.tx.voip_mtc.burst_dur, "ms", 
    2944                     /* gap */ 
    2945                     indent, 
    2946                     xr_stat.tx.voip_mtc.gap_den, xr_stat.tx.voip_mtc.gap_den*100.0/256, 
    2947                     xr_stat.tx.voip_mtc.gap_dur, "ms", 
    2948                     /* delay */ 
    2949                     indent, 
    2950                     xr_stat.tx.voip_mtc.rnd_trip_delay, "ms", 
    2951                     xr_stat.tx.voip_mtc.end_sys_delay, "ms", 
    2952                     /* level */ 
    2953                     indent, 
    2954                     signal_lvl, "dB", 
    2955                     noise_lvl, "dB", 
    2956                     rerl, "", 
    2957                     /* quality */ 
    2958                     indent, 
    2959                     r_factor, ext_r_factor,  
    2960                     indent, 
    2961                     mos_lq, mos_cq, 
    2962                     /* config */ 
    2963                     indent, 
    2964                     plc, jba, jbr, xr_stat.tx.voip_mtc.gmin, 
    2965                     /* JB delay */ 
    2966                     indent, 
    2967                     xr_stat.tx.voip_mtc.jb_nom, "ms", 
    2968                     xr_stat.tx.voip_mtc.jb_max, "ms", 
    2969                     xr_stat.tx.voip_mtc.jb_abs_max, "ms" 
    2970                     ); 
    2971             VALIDATE_PRINT_BUF(); 
    2972  
    2973  
    2974             /* RTT delay (by receiver side) */ 
    2975             len = pj_ansi_snprintf(p, end-p,  
    2976                     "%s   RTT (from recv)      min     avg     max     last    dev", 
    2977                     indent); 
    2978             VALIDATE_PRINT_BUF(); 
    2979             len = pj_ansi_snprintf(p, end-p,  
    2980                     "%s     RTT msec      : %7.3f %7.3f %7.3f %7.3f %7.3f",  
    2981                     indent, 
    2982                     xr_stat.rtt.min / 1000.0, 
    2983                     xr_stat.rtt.mean / 1000.0, 
    2984                     xr_stat.rtt.max / 1000.0, 
    2985                     xr_stat.rtt.last / 1000.0, 
    2986                     pj_math_stat_get_stddev(&xr_stat.rtt) / 1000.0 
    2987                    ); 
    2988             VALIDATE_PRINT_BUF(); 
    2989         } /* if audio */; 
    2990 #endif 
    2991  
    2992     } 
    2993 } 
    2994  
    2995  
    2996 /* Print call info */ 
    2997 void print_call(const char *title, 
    2998                 int call_id,  
    2999                 char *buf, pj_size_t size) 
    3000 { 
    3001     int len; 
    3002     pjsip_inv_session *inv = pjsua_var.calls[call_id].inv; 
    3003     pjsip_dialog *dlg = inv->dlg; 
    3004     char userinfo[128]; 
    3005  
    3006     /* Dump invite sesion info. */ 
    3007  
    3008     len = pjsip_hdr_print_on(dlg->remote.info, userinfo, sizeof(userinfo)); 
    3009     if (len < 0) 
    3010         pj_ansi_strcpy(userinfo, "<--uri too long-->"); 
    3011     else 
    3012         userinfo[len] = '\0'; 
    3013      
    3014     len = pj_ansi_snprintf(buf, size, "%s[%s] %s", 
    3015                            title, 
    3016                            pjsip_inv_state_name(inv->state), 
    3017                            userinfo); 
    3018     if (len < 1 || len >= (int)size) { 
    3019         pj_ansi_strcpy(buf, "<--uri too long-->"); 
    3020         len = 18; 
    3021     } else 
    3022         buf[len] = '\0'; 
    3023 } 
    3024  
    3025  
    3026 /* 
    3027  * Dump call and media statistics to string. 
    3028  */ 
    3029 PJ_DEF(pj_status_t) pjsua_call_dump( pjsua_call_id call_id,  
    3030                                      pj_bool_t with_media,  
    3031                                      char *buffer,  
    3032                                      unsigned maxlen, 
    3033                                      const char *indent) 
    3034 { 
    3035     pjsua_call *call; 
    3036     pjsip_dialog *dlg; 
    3037     pj_time_val duration, res_delay, con_delay; 
    3038     char tmp[128]; 
    3039     char *p, *end; 
    3040     pj_status_t status; 
    3041     int len; 
    3042  
    3043     PJ_ASSERT_RETURN(call_id>=0 && call_id<(int)pjsua_var.ua_cfg.max_calls, 
    3044                      PJ_EINVAL); 
    3045  
    3046     status = acquire_call("pjsua_call_dump()", call_id, &call, &dlg); 
    3047     if (status != PJ_SUCCESS) 
    3048         return status; 
    3049  
    3050     *buffer = '\0'; 
    3051     p = buffer; 
    3052     end = buffer + maxlen; 
    3053     len = 0; 
    3054  
    3055     print_call(indent, call_id, tmp, sizeof(tmp)); 
    3056      
    3057     len = pj_ansi_strlen(tmp); 
    3058     pj_ansi_strcpy(buffer, tmp); 
    3059  
    3060     p += len; 
    3061     *p++ = '\r'; 
    3062     *p++ = '\n'; 
    3063  
    3064     /* Calculate call duration */ 
    3065     if (call->conn_time.sec != 0) { 
    3066         pj_gettimeofday(&duration); 
    3067         PJ_TIME_VAL_SUB(duration, call->conn_time); 
    3068         con_delay = call->conn_time; 
    3069         PJ_TIME_VAL_SUB(con_delay, call->start_time); 
    3070     } else { 
    3071         duration.sec = duration.msec = 0; 
    3072         con_delay.sec = con_delay.msec = 0; 
    3073     } 
    3074  
    3075     /* Calculate first response delay */ 
    3076     if (call->res_time.sec != 0) { 
    3077         res_delay = call->res_time; 
    3078         PJ_TIME_VAL_SUB(res_delay, call->start_time); 
    3079     } else { 
    3080         res_delay.sec = res_delay.msec = 0; 
    3081     } 
    3082  
    3083     /* Print duration */ 
    3084     len = pj_ansi_snprintf(p, end-p,  
    3085                            "%s  Call time: %02dh:%02dm:%02ds, " 
    3086                            "1st res in %d ms, conn in %dms", 
    3087                            indent, 
    3088                            (int)(duration.sec / 3600), 
    3089                            (int)((duration.sec % 3600)/60), 
    3090                            (int)(duration.sec % 60), 
    3091                            (int)PJ_TIME_VAL_MSEC(res_delay),  
    3092                            (int)PJ_TIME_VAL_MSEC(con_delay)); 
    3093      
    3094     if (len > 0 && len < end-p) { 
    3095         p += len; 
    3096         *p++ = '\n'; 
    3097         *p = '\0'; 
    3098     } 
    3099  
    3100     /* Dump session statistics */ 
    3101     if (with_media && pjsua_call_has_media(call_id)) 
    3102         dump_media_session(indent, p, end-p, call); 
    3103  
    3104     pjsip_dlg_dec_lock(dlg); 
    3105  
    3106     return PJ_SUCCESS; 
    3107 } 
    31082162 
    31092163/* Proto */ 
  • pjproject/branches/projects/2.0-dev/pjsip/src/pjsua-lib/pjsua_core.c

    r3471 r3609  
    6868 
    6969    pjsua_config_default(&pjsua_var.ua_cfg); 
     70 
     71    for (i=0; i<PJSUA_MAX_VID_WINS; ++i) { 
     72        pjsua_vid_win_reset(i); 
     73    } 
    7074} 
    7175 
     
    176180    cfg->ka_data = pj_str("\r\n"); 
    177181    cfg->max_audio_cnt = 1; 
     182    cfg->vid_cap_dev = PJMEDIA_VID_DEFAULT_CAPTURE_DEV; 
     183    cfg->vid_rend_dev = PJMEDIA_VID_DEFAULT_RENDER_DEV; 
    178184    pjsua_transport_config_default(&cfg->rtp_cfg); 
    179185    cfg->use_srtp = pjsua_var.ua_cfg.use_srtp; 
  • pjproject/branches/projects/2.0-dev/pjsip/src/pjsua-lib/pjsua_media.c

    r3579 r3609  
    276276#endif  /* PJMEDIA_HAS_L16_CODEC */ 
    277277 
    278 #if PJMEDIA_HAS_VIDEO 
    279     status = pjmedia_video_format_mgr_create(pjsua_var.pool, 64, 0, NULL); 
    280     if (status != PJ_SUCCESS) { 
    281         pjsua_perror(THIS_FILE, "Error creating PJMEDIA video format manager", 
    282                      status); 
    283         return status; 
    284     } 
    285  
    286     status = pjmedia_converter_mgr_create(pjsua_var.pool, NULL); 
    287     if (status != PJ_SUCCESS) { 
    288         pjsua_perror(THIS_FILE, "Error creating PJMEDIA converter manager", 
    289                      status); 
    290         return status; 
    291     } 
    292  
    293     status = pjmedia_vid_codec_mgr_create(pjsua_var.pool, NULL); 
    294     if (status != PJ_SUCCESS) { 
    295         pjsua_perror(THIS_FILE, "Error creating PJMEDIA video codec manager", 
    296                      status); 
    297         return status; 
    298     } 
    299  
    300     status = pjmedia_vid_dev_subsys_init(&pjsua_var.cp.factory); 
    301     if (status != PJ_SUCCESS) { 
    302         pjsua_perror(THIS_FILE, "Error creating PJMEDIA video subsystem", 
    303                      status); 
    304         return status; 
    305     } 
    306 #endif 
    307  
    308 #if PJMEDIA_HAS_VIDEO && PJMEDIA_HAS_FFMPEG_CODEC 
    309     /* Init ffmpeg video codecs */ 
    310     status = pjmedia_codec_ffmpeg_init(NULL, &pjsua_var.cp.factory); 
    311     if (status != PJ_SUCCESS) { 
    312         pjsua_perror(THIS_FILE, "Error initializing ffmpeg library", 
    313                      status); 
    314         return status; 
    315     } 
    316 #endif 
    317278 
    318279    /* Save additional conference bridge parameters for future 
     
    337298    } 
    338299         
    339  
    340300    /* Init conference bridge. */ 
    341301    status = pjmedia_conf_create(pjsua_var.pool,  
     
    375335#endif 
    376336 
     337    /* Video */ 
     338#if PJMEDIA_HAS_VIDEO 
     339    status = pjsua_vid_subsys_init(); 
     340    if (status != PJ_SUCCESS) 
     341        return status; 
     342#endif 
     343 
    377344    return PJ_SUCCESS; 
    378345} 
     
    472439    pj_timer_entry_init(&pjsua_var.snd_idle_timer, PJ_FALSE, NULL, 
    473440                        &close_snd_timer_cb); 
     441 
     442    /* Video */ 
     443#if PJMEDIA_HAS_VIDEO 
     444    status = pjsua_vid_subsys_start(); 
     445    if (status != PJ_SUCCESS) 
     446        return status; 
     447#endif 
    474448 
    475449    /* Perform NAT detection */ 
     
    539513    if (pjsua_var.med_endpt) { 
    540514 
    541         /* Videodev */ 
    542515#       if PJMEDIA_HAS_VIDEO 
    543             pjmedia_vid_dev_subsys_shutdown(); 
     516            pjsua_vid_subsys_destroy(); 
    544517#       endif 
    545  
    546         /* ffmpeg */ 
    547 #       if PJMEDIA_HAS_VIDEO && PJMEDIA_HAS_FFMPEG_CODEC 
    548             pjmedia_codec_ffmpeg_deinit(); 
    549 #       endif 
    550  
    551518        /* Shutdown all codecs: */ 
    552519#       if PJMEDIA_HAS_SPEEX_CODEC 
     
    39383905 
    39393906 
    3940 #if PJMEDIA_HAS_VIDEO 
    3941  
    3942 /***************************************************************************** 
    3943  * Video codecs. 
    3944  */ 
    3945  
    3946 /* 
    3947  * Enum all supported video codecs in the system. 
    3948  */ 
    3949 PJ_DEF(pj_status_t) pjsua_vid_enum_codecs( pjsua_codec_info id[], 
    3950                                            unsigned *p_count ) 
    3951 { 
    3952     pjmedia_vid_codec_info info[32]; 
    3953     unsigned i, j, count, prio[32]; 
    3954     pj_status_t status; 
    3955  
    3956     count = PJ_ARRAY_SIZE(info); 
    3957     status = pjmedia_vid_codec_mgr_enum_codecs(NULL, &count, info, prio); 
    3958     if (status != PJ_SUCCESS) { 
    3959         *p_count = 0; 
    3960         return status; 
    3961     } 
    3962  
    3963     for (i=0, j=0; i<count && j<*p_count; ++i) { 
    3964         if (info[i].has_rtp_pack) { 
    3965             pj_bzero(&id[j], sizeof(pjsua_codec_info)); 
    3966  
    3967             pjmedia_vid_codec_info_to_id(&info[i], id[j].buf_, sizeof(id[j].buf_)); 
    3968             id[j].codec_id = pj_str(id[j].buf_); 
    3969             id[j].priority = (pj_uint8_t) prio[i]; 
    3970              
    3971             if (id[j].codec_id.slen < sizeof(id[j].buf_)) { 
    3972                 id[j].desc.ptr = id[j].codec_id.ptr + id[j].codec_id.slen + 1; 
    3973                 pj_strncpy(&id[j].desc, &info[i].encoding_desc, 
    3974                            sizeof(id[j].buf_) - id[j].codec_id.slen - 1); 
    3975             } 
    3976  
    3977             ++j; 
    3978         } 
    3979     } 
    3980  
    3981     *p_count = j; 
    3982  
    3983     return PJ_SUCCESS; 
    3984 } 
    3985  
    3986  
    3987 /* 
    3988  * Change video codec priority. 
    3989  */ 
    3990 PJ_DEF(pj_status_t) pjsua_vid_codec_set_priority( const pj_str_t *codec_id, 
    3991                                                   pj_uint8_t priority ) 
    3992 { 
    3993     const pj_str_t all = { NULL, 0 }; 
    3994  
    3995     if (codec_id->slen==1 && *codec_id->ptr=='*') 
    3996         codec_id = &all; 
    3997  
    3998     return pjmedia_vid_codec_mgr_set_codec_priority(NULL, codec_id, 
    3999                                                     priority); 
    4000 } 
    4001  
    4002  
    4003 /* 
    4004  * Get video codec parameters. 
    4005  */ 
    4006 PJ_DEF(pj_status_t) pjsua_vid_codec_get_param( 
    4007                                         const pj_str_t *codec_id, 
    4008                                         pjmedia_vid_codec_param *param) 
    4009 { 
    4010     const pj_str_t all = { NULL, 0 }; 
    4011     const pjmedia_vid_codec_info *info; 
    4012     unsigned count = 1; 
    4013     pj_status_t status; 
    4014  
    4015     if (codec_id->slen==1 && *codec_id->ptr=='*') 
    4016         codec_id = &all; 
    4017  
    4018     status = pjmedia_vid_codec_mgr_find_codecs_by_id(NULL, codec_id, 
    4019                                                      &count, &info, NULL); 
    4020     if (status != PJ_SUCCESS) 
    4021         return status; 
    4022  
    4023     if (count != 1) 
    4024         return (count > 1? PJ_ETOOMANY : PJ_ENOTFOUND); 
    4025  
    4026     status = pjmedia_vid_codec_mgr_get_default_param(NULL, info, param); 
    4027     return status; 
    4028 } 
    4029  
    4030  
    4031 /* 
    4032  * Set video codec parameters. 
    4033  */ 
    4034 PJ_DEF(pj_status_t) pjsua_vid_codec_set_param(  
    4035                                         const pj_str_t *codec_id, 
    4036                                         const pjmedia_vid_codec_param *param) 
    4037 { 
    4038     const pjmedia_vid_codec_info *info[2]; 
    4039     unsigned count = 2; 
    4040     pj_status_t status; 
    4041  
    4042     status = pjmedia_vid_codec_mgr_find_codecs_by_id(NULL, codec_id, 
    4043                                                      &count, info, NULL); 
    4044     if (status != PJ_SUCCESS) 
    4045         return status; 
    4046  
    4047     /* Codec ID should be specific */ 
    4048     if (count > 1) { 
    4049         pj_assert(!"Codec ID is not specific"); 
    4050         return PJ_ETOOMANY; 
    4051     } 
    4052  
    4053     status = pjmedia_vid_codec_mgr_set_default_param(NULL, pjsua_var.pool, 
    4054                                                      info[0], param); 
    4055     return status; 
    4056 } 
    4057  
    4058  
    4059 /***************************************************************************** 
    4060  * Video devices. 
    4061  */ 
    4062  
    4063 /* 
    4064  * Enum all video devices installed in the system. 
    4065  */ 
    4066 PJ_DEF(pj_status_t) pjsua_vid_enum_devs(pjmedia_vid_dev_info info[], 
    4067                                         unsigned *count) 
    4068 { 
    4069     unsigned i, dev_count; 
    4070  
    4071     dev_count = pjmedia_vid_dev_count(); 
    4072      
    4073     if (dev_count > *count) dev_count = *count; 
    4074  
    4075     for (i=0; i<dev_count; ++i) { 
    4076         pj_status_t status; 
    4077  
    4078         status = pjmedia_vid_dev_get_info(i, &info[i]); 
    4079         if (status != PJ_SUCCESS) 
    4080             return status; 
    4081     } 
    4082  
    4083     *count = dev_count; 
    4084  
    4085     return PJ_SUCCESS; 
    4086 } 
    4087  
    4088  
    4089 /* 
    4090  * Get currently active video devices. 
    4091  */ 
    4092 PJ_DEF(pj_status_t) pjsua_vid_get_dev(int *capture_dev, int *render_dev) 
    4093 { 
    4094     if (capture_dev) 
    4095         *capture_dev = pjsua_var.vcap_dev; 
    4096     if (render_dev) 
    4097         *render_dev = pjsua_var.vrdr_dev; 
    4098  
    4099     return PJ_SUCCESS; 
    4100 } 
    4101  
    4102  
    4103 /* 
    4104  * Select video device for the next video sessions. 
    4105  */ 
    4106 PJ_DEF(pj_status_t) pjsua_vid_set_dev(int capture_dev, int render_dev) 
    4107 { 
    4108     pjmedia_vid_dev_info info; 
    4109     pj_status_t status; 
    4110  
    4111     if (capture_dev < 0) 
    4112         capture_dev = PJMEDIA_VID_DEFAULT_CAPTURE_DEV; 
    4113     if (render_dev < 0) 
    4114         render_dev = PJMEDIA_VID_DEFAULT_RENDER_DEV; 
    4115  
    4116     status = pjmedia_vid_dev_get_info(capture_dev, &info); 
    4117     if (status != PJ_SUCCESS) 
    4118         return status; 
    4119  
    4120     status = pjmedia_vid_dev_get_info(render_dev, &info); 
    4121     if (status != PJ_SUCCESS) 
    4122         return status; 
    4123  
    4124     pjsua_var.vcap_dev = capture_dev; 
    4125     pjsua_var.vrdr_dev = render_dev; 
    4126  
    4127     return PJ_SUCCESS; 
    4128 } 
    4129  
    4130  
    4131 /* 
    4132  * Configure video device setting to the video device being used. 
    4133  */ 
    4134 PJ_DEF(pj_status_t) pjsua_vid_set_setting(pjmedia_vid_dev_cap cap, 
    4135                                           const void *pval, 
    4136                                           pj_bool_t keep) 
    4137 { 
    4138     PJ_UNUSED_ARG(cap); 
    4139     PJ_UNUSED_ARG(pval); 
    4140     PJ_UNUSED_ARG(keep); 
    4141     return PJ_ENOTSUP; 
    4142 } 
    4143  
    4144  
    4145 /* 
    4146  * Retrieve a video device setting. 
    4147  */ 
    4148 PJ_DEF(pj_status_t) pjsua_vid_get_setting(pjmedia_vid_dev_cap cap, 
    4149                                           void *pval) 
    4150 { 
    4151     PJ_UNUSED_ARG(cap); 
    4152     PJ_UNUSED_ARG(pval); 
    4153     return PJ_ENOTSUP; 
    4154 } 
    4155  
    4156 #endif /* PJMEDIA_HAS_VIDEO */ 
Note: See TracChangeset for help on using the changeset viewer.