Michael Leonard
2016-10-04 11:30:53 UTC
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);
}
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);
}