Re: Please help - wav_writer writing silence when switch to 1 conference bridge PER call (following pjsua-lib-perf FAQ)

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Hi Bill. Thanks for the quick response.

I'm not sure if you saw it: my entire code is in one file called whole_app.c which is included in the gist (scroll to the bottom to see the file: https://gist.github.com/MikeLeonard/6b8b4986d6529ae751ebd2af5bf4d29f)

I'm using pjmedia_conf_add_port inside of on_stream_created, which (I think) adds the stream port (p_port) to the conference bridge (cd->conf) and saves the slot number into &cd->call_slot.

static void on_stream_created(pjsua_call_id call_id, 
                              pjmedia_stream *strm,
                              unsigned stream_idx, 
                              pjmedia_port **p_port){
log_message("RUNNING... on_stream_created\n");  
struct call_data *cd;
cd = (struct call_data*) pjsua_call_get_user_data(call_id);
if (!cd)
return;
pjmedia_conf_add_port(cd->conf, cd->pool, *p_port, NULL, &cd->call_slot);
}

Elsewhere in call_media_init which is called when the call state is 'CALLING', I'm running the following:
pjmedia_conf_connect_port(cd->conf, cd->call_slot, cd->writer_slot, 0); //flow audio from call to writer
pjmedia_conf_connect_port(cd->conf, cd->player_slot, cd->call_slot, 0); //flow wav reader audio to call
... to connect the call_slot to the writer_slot and the player_slot.

Do I need to make another connection? Perhaps to connect the master port and/or the null port to one or more of these? I'm afraid that I haven't been able to really get to grips with these two ports, I don't really understand what they are for. (I've just read that I need them when there's no sound device in order to drive the get_frame and put_frame callbacks - plus the FAQ uses them).

Thanks again for the help

Mike

.............................................................................................................................................................................
Also, I've just realised a potential problem: on_stream_created is called AFTER the call state is 'CALLING' (which calls my call_media_init function)... so I guess that call_media_init is trying to connect things to call_slot BEFORE call_slot is set by pjmedia_conf_add_port inside of on_stream_created. I couldn't really tell from the FAQ exactly where I should put these functions - do you know where I've gone wrong?

UPDATE: Nope. I've just tried changing it so that call_media_init is called when the MEDIA state is 'ACTIVE' instead of when the call state is CALLING, so that call_media_init is called after on_stream_created  (which calls pjmedia_conf_add_port(cd->conf, cd->pool, *p_port, NULL, &cd->call_slot)). However I get the same silence. 

Anyway, the cod has some print commands which show the order things run in, in case that's helpful to you:

/myapp sip:+447XXXXXXXX@xxxxxxxxxxxxxxxxxxxxxx >> log.txt
WARNING: no real random source present!
RUNNING... on_call_state
Call state is CALLING.
RUNNING... call_media_init      
RUNNING... on_call_state
RUNNING... on_stream_created       
RUNNING... on_call_media_state
Media state is ACTIVE.
RUNNING... on_call_state
RUNNING... on_call_state
RUNNING... on_call_state
Call state is CONFIRMED.
RUNNING... on_call_state
Call state is DISCONNECTED.
RUNNING... call_media_deinit
Called call_media_deinit.
RUNNING... on_stream_destroyed
^C


Thanks

Mike

On 4 October 2016 at 14:02, Bill Gardner <billg@xxxxxxxxxxxx> wrote:
Hi Mike,

I don't see any code that connects the stream port (codec, jitter, RTP, etc) to your conference bridge at call_slot. Is this done elsewhere?

Regards,

Bill




On 10/4/2016 7:30 AM, Michael Leonard wrote:
Hello everyone

Please help! My wav_writer is just writing silence (of the correct length) when trying to use pjsua-lib with 1 conference bridge per call, as explained in the FAQ here: https://trac.pjsip.org/repos/wiki/FAQ#pjsua-lib-perf. Note that when I use the default pjsua conference bridge everything works fine for me.

I've saved the code and a log file to a github public gist here: https://gist.github.com/MikeLeonard/6b8b4986d6529ae751ebd2af5bf4d29f
 
I would *really* appreciate it if someone could look through call_media_init function I've written (also pasted below) and tell me what I'm doing wrong. 

If it takes someone a lot of time I'd be happy to buy them a coffee (or amazon voucher!) to say thank you.

Thanks very much in advance

Mike





More information:
..................................................................................................................................................
**I think I've ruled out problems with my setup
- I'm trying to create a server that makes calls to a regular mobile or landline from a server (ie no voip phone so no sound device), and records the speech of the receiver to a wav file.

  I'm running this on ubuntu, inside a docker container, on a macbook, and am making an outbound call to a mobile number via a twilio sip trunk. I'm also compiling this using C++ (because I need various C++ libraries for what I have in mind once I get the basics working). 

The above setup ALL works fine - I modified samples/simple_pjsua.c and got a wav_writer and a wav_player working no problem with the default pjsua conference bridge. So I'm pretty sure the problem is with how I've tried to follow the pjsua-lib-perf FAQ. 


**I can't see any issues in the log file, and I've confirmed the key 'on_' callbacks all definitely run
- The log file prints out the following - which to me looks like I've connected the right ports, but I don't really understand this to be honest I've just be copying examples: 
09:59:05.565            APP  .......Call 0 state=CALLING
09:59:05.572   wav_writer.c  .......File writer 'testingtesting.wav' created: samp.rate=16000, bufsize=4KB
09:59:05.572   conference.c  .......Port 0 (Master/sound) transmitting to port 1 (testingtesting.wav)
09:59:05.579   wav_player.c  .......File player 'message.wav' created: samp.rate=16000, ch=1, bufsize=4KB, filesize=56KB
09:59:05.579   conference.c  .......Port 2 (message.wav) transmitting to port 0 (Master/sound) 

- I'm just trying one call at the moment - I haven't tried multiple calls yet.

- I've confirmed that the key callbacks all run: on_call_state, on_call_media_state, on_stream_created and on_stream_destroyed
- I've added lots of "if (status != PJ_SUCCESS) {pjsua_perror(THIS_FILE, "STATUS ERROR: ", status);}" into the code, but don't get any "STATUS ERROR" messages in the log.


**A wav file is indeed written
- ...it just contains silence. It seems to be silence of the length of the call however. 

I've also tried looping back the audio, and playing a wav file to the receiver, but I just get silence. These all work in my basic samples/simple_pjsua.c version with the default pjsua conference bridge.


..................................................................................................................................................
Key piece of code... see github public gist for full code + log file https://gist.github.com/MikeLeonard/6b8b4986d6529ae751ebd2af5bf4d29f

struct call_data {
  pj_pool_t           *pool;
  pjmedia_conf        *conf;
  pjmedia_port        *cport;
  pjmedia_port        *null;
  pjmedia_port        *writer;
  pjmedia_port        *player;
  pjmedia_master_port *m;
  unsigned int                  call_slot;
  unsigned int                  writer_slot;
  unsigned int                  player_slot;
};

static void call_media_init(pjsua_call_id call_id){
log_message("RUNNING... call_media_init\n");

pj_pool_t *pool;
struct call_data *cd;
pj_status_t status;

pool = pjsua_pool_create("mycall", 4000, 4000);
cd = PJ_POOL_ZALLOC_T(pool, struct call_data);
cd->pool = pool;

pjsua_call_set_user_data(call_id, (void*)cd);

pjsua_media_config media_cfg;
pjsua_media_config_default(&media_cfg);
status = pjmedia_conf_create(
cd->pool, 
media_cfg.max_media_ports,  //max media ports
media_cfg.clock_rate,
media_cfg.channel_count,
media_cfg.clock_rate * media_cfg.channel_count * media_cfg.audio_frame_ptime / 1000, //mconf_cfg.samples_per_frame,
16, //mconf_cfg.bits_per_sample,
PJMEDIA_CONF_NO_DEVICE | PJMEDIA_CONF_NO_MIC,  //options
&cd->conf //pointer to conference bridge instance
);
if (status != PJ_SUCCESS) {pjsua_perror(THIS_FILE, "STATUS ERROR: ", status);}
cd->cport = pjmedia_conf_get_master_port(cd->conf);
status = pjmedia_null_port_create(
cd->pool,
media_cfg.clock_rate,
media_cfg.channel_count,
media_cfg.clock_rate * media_cfg.channel_count * media_cfg.audio_frame_ptime / 1000, //mconf_cfg.samples_per_frame,
16, //mconf_cfg.bits_per_sample,
&cd->null);
if (status != PJ_SUCCESS) {pjsua_perror(THIS_FILE, "STATUS ERROR: ", status);}
status = pjmedia_master_port_create(cd->pool, cd->null, cd->cport, 0, &cd->m);
if (status != PJ_SUCCESS) {pjsua_perror(THIS_FILE, "STATUS ERROR: ", status);}
status = pjmedia_master_port_start(cd->m);
if (status != PJ_SUCCESS) {pjsua_perror(THIS_FILE, "STATUS ERROR: ", status);}
   //todo(mike) handle errors, see pjsua_aud.c





   /* wav writer */
status = pjmedia_wav_writer_port_create(
cd->pool, 
"testingtesting.wav", //path
media_cfg.clock_rate,
media_cfg.channel_count,
media_cfg.clock_rate * media_cfg.channel_count * media_cfg.audio_frame_ptime / 1000, //mconf_cfg.samples_per_frame,
16, //mconf_cfg.bits_per_sample,
0, //options
0, //buf_size defaults to 4kb if set to 0
&cd->writer //yes this should be a pjmedia_port **
); 
if (status != PJ_SUCCESS) {pjsua_perror(THIS_FILE, "STATUS ERROR: ", status);}
status = pjmedia_conf_add_port(cd->conf, cd->pool, cd->writer, NULL, &cd->writer_slot);
if (status != PJ_SUCCESS) {
pjsua_perror(THIS_FILE, "STATUS ERROR: ", status);
pjmedia_port_destroy(cd->writer);
}

pjmedia_conf_connect_port(cd->conf, cd->call_slot, cd->writer_slot, 0);





/* wav player */
status = pjmedia_wav_player_port_create(
cd->pool, 
"message.wav",
media_cfg.audio_frame_ptime,
0, 
0, 
&cd->player  //yes this should be a pjmedia_port **
);
    if (status != PJ_SUCCESS) {pjsua_perror(THIS_FILE, "STATUS ERROR: ", status);}

status = pjmedia_conf_add_port(cd->conf, cd->pool, cd->player, NULL, &cd->player_slot);
if (status != PJ_SUCCESS) {
pjsua_perror(THIS_FILE, "STATUS ERROR: ", status);
pjmedia_port_destroy(cd->player);
}

pjmedia_conf_connect_port(cd->conf, cd->player_slot, cd->call_slot, 0);



//uncomment to loop back remote audio (also doesn't work)
//pjmedia_conf_connect_port(cd->conf, cd->call_slot, cd->call_slot, 0);
}


_______________________________________________
Visit our blog: http://blog.pjsip.org

pjsip mailing list
pjsip@xxxxxxxxxxxxxxx
http://lists.pjsip.org/mailman/listinfo/pjsip_lists.pjsip.org


_______________________________________________
Visit our blog: http://blog.pjsip.org

pjsip mailing list
pjsip@xxxxxxxxxxxxxxx
http://lists.pjsip.org/mailman/listinfo/pjsip_lists.pjsip.org


_______________________________________________
Visit our blog: http://blog.pjsip.org

pjsip mailing list
pjsip@xxxxxxxxxxxxxxx
http://lists.pjsip.org/mailman/listinfo/pjsip_lists.pjsip.org

[Index of Archives]     [Asterisk Users]     [Asterisk App Development]     [Linux ARM Kernel]     [Linux ARM]     [Linux Omap]     [Fedora ARM]     [IETF Annouce]     [Security]     [Bugtraq]     [Linux]     [Linux OMAP]     [Linux MIPS]     [Linux API]
  Powered by Linux