visual-c++sippjsippjsua2

Video call using PJSUA


I'm using pjsua to create a video call from a monitor to a phone. I'm able to establish an audio call without problem, but if I try to establish a video call (vid_cnt=1), I'm getting an error.

My purpose is to get and save the audio and video of the phone.

This is my configuration:

void hard_account_config(pjsua_acc_config& acc_cfg, pjsua_transport_id transport_tcp) {
    pjsua_acc_config_default(&acc_cfg);
    
    acc_cfg.ka_interval = 15;

    // VIDEO
    acc_cfg.vid_in_auto_show = PJ_TRUE;
    acc_cfg.vid_out_auto_transmit = PJ_TRUE;
    acc_cfg.vid_cap_dev = VideoCaptureDeviceId();
        acc_cfg.vid_wnd_flags = PJMEDIA_VID_DEV_WND_BORDER | PJMEDIA_VID_DEV_WND_RESIZABLE;

    acc_cfg.reg_timeout = 300;
    acc_cfg.use_srtp = PJMEDIA_SRTP_DISABLED;

    pjsua_srtp_opt_default(&acc_cfg.srtp_opt);

    acc_cfg.ice_cfg_use = PJSUA_ICE_CONFIG_USE_CUSTOM;
    acc_cfg.ice_cfg.enable_ice = PJ_FALSE;
    acc_cfg.allow_via_rewrite = PJ_FALSE;
    acc_cfg.allow_sdp_nat_rewrite = acc_cfg.allow_via_rewrite;
    acc_cfg.allow_contact_rewrite = acc_cfg.allow_via_rewrite ? 2 : PJ_FALSE;
    acc_cfg.publish_enabled = PJ_TRUE;
    
    acc_cfg.transport_id = transport_tcp;

    acc_cfg.cred_count = 1;
    acc_cfg.cred_info[0].username = pj_string(USER);
    acc_cfg.cred_info[0].realm = pj_string("*");
    acc_cfg.cred_info[0].scheme = pj_string("Digest");
    acc_cfg.cred_info[0].data_type = PJSIP_CRED_DATA_PLAIN_PASSWD;
    acc_cfg.cred_info[0].data = pj_string(PASS);
}

Once registration is completed, I run the following code:

prn("=== Test Call ===");
pj_str_t uri = pj_string("sip:" + call_target + "@" + SERVER);

pjsua_call_id call_id;
pjsua_call_setting call_setting;
pjsua_call_setting_default(&call_setting);
call_setting.flag = 0;
call_setting.vid_cnt = PJMEDIA_HAS_VIDEO ? 1 : 0;

pjsua_msg_data msg_data;
pjsua_msg_data_init(&msg_data);
pj_status_t status = pjsua_call_make_call(acc_id, &uri, &call_setting, NULL, &msg_data, &call_id);
if (status != PJ_SUCCESS) { 
    prn("Error trying: pjsua_call_make_call"); 
    return;
}

I know that PJMEDIA_HAS_VIDEO is equal to 1 on the conf_site.h and pjsua_call_make_call return PJ_SUCCESS.

I've seen that if I have headphones connected, there is no problem. But if I disconnect them, the following error is shown: #pjsua_aud.c ..Error retrieving default audio device parameters: Unable to find default audio device (PJMEDIA_EAUD_NODEFDEV) [status=420006] If I connect the headphones, I enable the video and run my code, the following error is shown: #pjsua_media.c ......pjsua_vid_channel_update() failed for call_id 0 media 1: Unable to find default video device (PJMEDIA_EVID_NODEFDEV)

So, using PJSUA it is necessary to have audio and video devices on the monitor and phone? Should I create virtual ports if I don't have the devices?


Solution

  • You can use the following code to get a list of audio/video devices in PJSUA, which will most likely provide you with a loopback device (among others).

      pjmedia_aud_dev_info audio_device[64];
      unsigned int audio_device_cnt = 64;
      status = pjsua_enum_aud_devs(audio_device, &audio_device_cnt);
      printf("There are %d audio devices\n", audio_device_cnt);
      for (int i = 0; i < audio_device_cnt; i++) {
          printf("%d: %s\n", i, audio_device[i].name);
      }
    
      pjmedia_vid_dev_info video_device[64];
      unsigned int video_device_cnt = 64;
      status = pjsua_vid_enum_devs(video_device, &video_device_cnt);
      printf("There are %d video devices\n", video_device_cnt);
      for (int i = 0; i < video_device_cnt; i++) {
          printf("%d: %s\n", i, video_device[i].name);
      }
    

    I have not personally tried capturing a loopback audio device but for video, PJSUA provides an internal colorbar generator (Colorbar generator in this list), which you can use.

    Once you find the indices of loopback or dummy audio/video devices you want to use, you can set them by using

    pjsua_set_snd_dev(<YOUR DUMMY CAPTURE DEVICE>, <YOUR DUMMY PLAYBACK DEVICE>);   
    
    acc_cfg.vid_cap_dev = <YOUR VIDEO CAPTURE DEVICE>;