I'm attempting to make a simple objective C wrapper by exposing the high level C/C++ API. For a proof of concept, I've implemented the simple SIP UA example given at
http://svn.pjsip.org/repos/pjproject/trunk/pjsip-apps/src/samples/simple_pjsua.c
I can get as far as the creating the SIP user account (pjsua_acc_add function below)
- (void) registerWithSipServer {
/* Register to SIP server by creating SIP account. */
pjsua_acc_config a_cfg;
pjsua_acc_id acc_id;
pj_status_t status;
pjsua_acc_config_default(&a_cfg);
a_cfg.id = pj_str("sip:" SIP_USER "#" SIP_DOMAIN);
a_cfg.reg_uri = pj_str("sip:" SIP_DOMAIN);
a_cfg.cred_count = 1;
a_cfg.cred_info[0].realm = pj_str(SIP_DOMAIN);
a_cfg.cred_info[0].scheme = pj_str("digest");
a_cfg.cred_info[0].username = pj_str(SIP_USER);
a_cfg.cred_info[0].data_type = PJSIP_CRED_DATA_PLAIN_PASSWD;
a_cfg.cred_info[0].data = pj_str(SIP_PASSWD);
status = pjsua_acc_add(&a_cfg, PJ_TRUE, &acc_id);
if (status != PJ_SUCCESS) {
NSLog(#"Failed to start PJSUA");
}
}
but when I try and add it, I get an assertion
11:59:07.083 endpoint ..Request msg REGISTER/cseq=1665
(tdta0xbb15200) created. Assertion failed: (mod_stateful_util.id !=
-1), function pjsip_endpt_send_request, file ../src/pjsip/sip_util_statefull.c, line 99.
Tracking that down line 99 in sip_util_statefull.c we get the function
PJ_ASSERT_RETURN(mod_stateful_util.id != -1, PJ_EINVALIDOP);
I've tried to figure out why this fails but have so far come unstuck. Anybody else attempted this?
Related
I've been working to migrate an older Core MIDI sending implementation to send MIDI 1.0 messages using Apple's newer UMP-aware MIDI Event List API methods.
I've figured out code that runs and should output MIDI clock messages, but when I send it with MIDISendEventList(...) I see nothing being output from my MIDI interface; there's also no error returned from that method to indicate what the problem is.
Here is the code I'm using:
const ByteCount clockMessageSize = 1;
const UInt32 clockMessage[clockMessageSize] = { (UInt32)0xF8 }; // MIDI clock tick
const MIDITimeStamp timeStamp = mach_absolute_time();
MIDIEventList clockMessageEventList = {};
MIDIEventPacket* clockMessageEventListEndPacket = nullptr;
clockMessageEventListEndPacket = MIDIEventListInit(&clockMessageEventList, kMIDIProtocol_1_0);
clockMessageEventListEndPacket = MIDIEventListAdd(&clockMessageEventList, sizeof(MIDIEventList::packet), clockMessageEventListEndPacket, timeStamp, clockMessageSize, clockMessage);
for (NSUInteger endpointRefIndex = 0; endpointRefIndex < endPointRefsCount; ++endpointRefIndex) {
MIDIObjectRef destinationEndpoint = endPointRefs[endpointRefIndex];
OSStatus midiSendError = MIDISendEventList(outputPortRef, destinationEndpoint, &clockMessageEventList);
if (midiSendError != noErr) {
printf("MIDISendEventList error: %i", (int)midiSendError);
}
}
Inspecting clockMessageEventList.packet after it has been configured but before it is sent shows:
(248, 0, 0, [... all zeros to index 63])
Does anyone know where I'm going wrong?
Implement audio call using pjsip working proper but not working video call.
i applied following changes :
//Sip init
pj_status_t sip_startup(app_config_t *app_config)
{
pjsua_config cfg;
pjsua_config_default (&cfg);
cfg.cb.on_incoming_call = &on_incoming_call;
cfg.cb.on_call_media_state = &on_call_media_state;
cfg.cb.on_call_state = &on_call_state;
cfg.cb.on_reg_state2 = &on_reg_state2;
cfg.cb.on_call_media_event = &on_call_media_event;
// Init the logging config structure
pjsua_logging_config log_cfg;
pjsua_logging_config_default(&log_cfg);
log_cfg.console_level = 4;
// Init PJ Media
pjsua_media_config me_cfg;
pjsua_media_config_default(&me_cfg);
// Init the pjsua
status = pjsua_init(&cfg, &log_cfg, &me_cfg);
if (status != PJ_SUCCESS) error_exit("Error in pjsua_init()", status);
}
//following code add when apply sip connection
pjsua_call_setting _call_setting;
pjsua_call_setting_default(&_call_setting);
_call_setting.aud_cnt = 1;
_call_setting.vid_cnt = 1;
//when press call button from app call this funtion for video call.
pj_status_t sip_dial(pjsua_acc_id acc_id, const char *number,
pjsua_call_id *call_id)
{
pj_status_t status;
pj_str_t uri = pj_str(destUri);
status = pjsua_call_make_call(_acc_id, &uri, &(_call_setting),
NULL, NULL, NULL);
if (status != PJ_SUCCESS)
error_exit("Error making call", status);
}
//Apply changes related to video code
static void on_call_media_state(pjsua_call_id call_id)
{
pjsua_call_info ci;
unsigned mi;
pjsua_call_get_info(call_id, &ci);
sip_ring_stop([SharedAppDelegate.aVoipManager pjsipConfig]);
if(ci.media_status == PJMEDIA_TYPE_VIDEO)
{
NSLog(#"windows id : %d",ci.media[mi].stream.vid.win_in);
NSLog(#"media id : %d",mi);
if (ci.media_status != PJSUA_CALL_MEDIA_ACTIVE)
return;
[[XCPjsua sharedXCPjsua]
displayWindow:ci.media[mi].stream.vid.win_in];
}
}
i applied above code but not place video call using pjsip.
Any one have idea or steps related to video call then please help me.
Thank you
This subject is too large, I think you need to refine your questions to a smaller more specific question if you wish to get a good answer.
Make sure you have read and understood the pjsip video support:
PJSip Video_Users_Guide
PJSIP IOS Video Support
I would look for what other people have done (even if it's on another platform, e.g. Android, Windows, etc.) and the look into the pjsip pjsua sample which I believe has video support but I'm not sure if it support ios video.
Get a known good examples of pjsip video calls going so you know that it looks like and what the logs look like when it works.
Then try against your ios code against the known good example clients to see where they differ. If you can't figure it out at least you should have enough info to be able to ask a more specific question about a specific situation that is not working for you.
I am working on audio and video call feature in my application I got success to make call as a audio but I am stuck on video calling. For video calling I am using following code.
pjsua_call_setting opt;
pjsua_call_setting_default(&opt);
opt.aud_cnt = 1;
opt.vid_cnt = 1;
char *destUri = "sip:XXXXXX#sipserver";
pj_status_t status;
pj_str_t uri = pj_str(destUri);
status = pjsua_call_make_call(voipManager._sip_acc_id, &uri,&opt,
NULL, NULL, NULL);
if (status != PJ_SUCCESS)
NSLog(#"%d",status);
else
NSLog(#"%d",status);
When the pjsua_call_make_call function is perform it shows me the error which is:
Assertion failed: (opt->vid_cnt == 0), function apply_call_setting, file ../src/pjsua-lib/pjsua_call.c, line 606.
You must build the lib for video support.
To enable video, append this into config_site.h:
#define PJMEDIA_HAS_VIDEO 1
What you are getting is assertion error for checking video support
I am working on with pjsip for iOS, I have configured the pjsip and able to register and reregister for specific time interval, but there is a scenario where I want to change the pjsip account details at the time of re register with new details but I havent found anything on google which can guide how to change it.
If someone have a idea about this please guide me through how to change the pjsua_acc_config details at time of re registration, I get the method call at the time of re registration.
static void on_reg_state2(pjsua_acc_id acc_id, pjsua_reg_info *info) {
PJ_LOG(3,(__FILE__, "%s: Account %d Reason %.*s Status %d code %d CurrentOp %d",
__FUNCTION__, acc_id, info->cbparam->reason.slen, info->cbparam->reason.ptr,
info->cbparam->status,info->cbparam->code, info->cbparam->regc));
}
get account configuration for account id, and set the fields to whatever required in on_reg_state2 function.
if (pjsua_acc_is_valid(acc_id))
{
pjsua_acc_set_default(acc_id);
pjsua_acc_config acc_cfg;
pj_status_t status;
pjsua_acc_config_default(&acc_cfg);
acc_cfg.id = pj_str(id);
acc_cfg.reg_uri = pj_str(registrar);
acc_cfg.cred_count = 1;
acc_cfg.cred_info[0].scheme = pj_str("Digest");
acc_cfg.cred_info[0].realm = pj_str(realm);
acc_cfg.cred_info[0].username = pj_str(uname);
acc_cfg.cred_info[0].data_type = 0;
acc_cfg.cred_info[0].data = pj_str(passwd);
acc_cfg.publish_enabled = PJ_TRUE;
}
Its like same as re register.
remove current account and add new one
if (_sip_acc_id != PJSUA_INVALID_ID){
// pjsua_acc_info info;
// pjsua_acc_get_info(_sip_acc_id, &info);
//
// if (info.has_registration){
pj_status_t statusDelete = pjsua_acc_del(_sip_acc_id);
if (statusDelete != PJ_SUCCESS)
{
pjsua_perror(THIS_FILE, "Error removing new account", status);
[app displayParameterError: #"Error removing new account."];
}
// }
}
status = pjsua_acc_add(&acc_cfg, PJ_TRUE, &_sip_acc_id);
if (status != PJ_SUCCESS)
{
pjsua_perror(THIS_FILE, "Error adding new account", status);
[app displayParameterError: #"Error adding new account."];
}
This is guide for recomendationabout PJSIP You can click this PJSIP
When I am on sip call, sometimes I want to send dtmf digits.
To do this I created a custom dial pad which when a key is pressed should play a sound of that key, but it is not playing that sound during a sip call (when there is no call, sound is played).
These sounds are played with functions from AudioToolbox.h library (AudioServicesPlaySystemSound(soundID)).
Is there some property that I need to set up in pjsip (pjsua) or in AudioToolbox library to enable a sound be played during a sip call?
I know this is possible (Bria has this, Groundwire also, not sure if they are using pjsip to implement sip).
This answer is combination of code snippets from these two links: PJSUA-API Media Manipulation and pjsipDll_PlayWav.cpp.
When pjsua makes a call it is using ports (conference ports) for transferring media from/to the call destination to your device speaker. You can have multiple ports opened at the same moment.
So what we are going to do to play our keypad button click sound is to open one more port and play a sound (in this case it is a wav file, and as you can notice there are also a pjsua function for streaming avi files).
To do this we are going to use this function:
pj_status_t pjsua_conf_connect (pjsua_conf_port_id source, pjsua_conf_port_id sink)
where our sink port is our device speaker port, in this case (and mostly) it is 0.
All functions below are added to pjsua_app.c file.
Before the place where they are used in the Objective-C class you have to add a line like this:
pj_status_t play_sound_during_call(pj_str_t sound_file);
To play a sound here is the function:
pj_status_t play_sound_during_call(pj_str_t sound_file)
{
pjsua_player_id player_id;
pj_status_t status;
status = pjsua_player_create(&sound_file, 0, &player_id);
if (status != PJ_SUCCESS)
return status;
pjmedia_port *player_media_port;
status = pjsua_player_get_port(player_id, &player_media_port);
if (status != PJ_SUCCESS)
{
return status;
}
pj_pool_t *pool = pjsua_pool_create("my_eof_data", 512, 512);
struct pjsua_player_eof_data *eof_data = PJ_POOL_ZALLOC_T(pool, struct pjsua_player_eof_data);
eof_data->pool = pool;
eof_data->player_id = player_id;
pjmedia_wav_player_set_eof_cb(player_media_port, eof_data, &on_pjsua_wav_file_end_callback);
status = pjsua_conf_connect(pjsua_player_get_conf_port(player_id), 0);
if (status != PJ_SUCCESS)
{
return status;
}
return status;
}
And here is the callback function that listens when your wav file reading (playing) has ended:
struct pjsua_player_eof_data
{
pj_pool_t *pool;
pjsua_player_id player_id;
};
static PJ_DEF(pj_status_t) on_pjsua_wav_file_end_callback(pjmedia_port* media_port, void* args)
{
pj_status_t status;
struct pjsua_player_eof_data *eof_data = (struct pjsua_player_eof_data *)args;
status = pjsua_player_destroy(eof_data->player_id);
PJ_LOG(3,(THIS_FILE, "End of Wav File, media_port: %d", media_port));
if (status == PJ_SUCCESS)
{
return -1;// Here it is important to return a value other than PJ_SUCCESS
//Check link below
}
return PJ_SUCCESS;
}
The reason why the pjmedia_wav_player_set_eof_cb callback function should return a value other then PJ_SUCCESS is because the documentation here pjmedia_wav_player_set_eof_cb says:
Note that if the application destroys the file port in the callback, it must return non-PJ_SUCCESS here.