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 Mike,

Yes I noticed the github link but didn't dig that far. :-)

Null port and master port are needed to drive the conference bridge and all media flow but I forget the details. I recall using a null sound device connected to the bridge master port, not sure if this paradigm has changed. Given the WAV file is created and has the right amount of silence, then it seems that media is flowing, so that's good. I'd consider doing the port connections when the media state goes active, instead of when call state is "CALLING" which is premature. Seems you already figured that out. The empty WAV would be explained by connecting it to the wrong port or connecting them the wrong way (check those connect calls for source and dest).

I assume the called device is not getting any playback audio either?

You might learn something by enabling the logging in the conference bridge. I think you have to change a macro and it will generate lots of log info per packet. Not sure what else to suggest.

Regards,

Bill




On 10/4/2016 9:59 AM, Michael Leonard wrote:
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:

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
_______________________________________________
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