Discussion:
handle mutiple media flows simultaneously
vopjessie
2008-09-02 09:43:00 UTC
Permalink
Hi All, my program is designed to be able to receive two calls simultaneously (in different threads). When an inbound comes in, my program plays audio data stored in memory to the caller. It works well when there is only one inbound. However, when two inbounds come in simultaneously, the sound quality heard by both callers is so poor that can be considered as noises. When one of the inbound calls has hung up, the sound quality on the other connected inbound call becomes good again. Could someone tell me what I am doing wrong?


Thanks a lot!

Jessica

My code is included as follows:

// add port of the channel and the port of the audio buffer to the conference bridge if((pjmedia_conf_add_port(*(sipChannel->getPlayConf()), //pjmedia_conf *conf, sipChannel->getPlayPool(), //pj_pool_t *pool, portChannel, //pjmedia_port *strm_port, NULL,//const pj_str_t *name, &slotChannel//unsigned *p_slot) ) == PJ_SUCCESS) && (pjmedia_conf_add_port(*(sipChannel->getPlayConf()), //pjmedia_conf *conf, sipChannel->getPlayPool(), //pj_pool_t *pool, portBuffer, //pjmedia_port *strm_port, NULL,//const pj_str_t *name, &slotBuffer//unsigned *p_slot) ) == PJ_SUCCESS) && // connect audio and channel ports (pjmedia_conf_connect_port(*(sipChannel->getPlayConf()), slotBuffer,
slotChannel, 0) == PJ_SUCCESS) && (pjmedia_conf_adjust_tx_level(*(sipChannel->getPlayConf()), slotChannel, SIP_ADJUST_LEVEL) == PJ_SUCCESS) && (pjmedia_conf_adjust_rx_level(*(sipChannel->getPlayConf()), slotBuffer, SIP_ADJUST_LEVEL) == PJ_SUCCESS) && // register call back (pjmedia_mem_player_set_eof_cb(portBuffer, sipChannel, &fillPlayBuffer) == PJ_SUCCESS)) { pj_status_t status = -1; // create master port if((sipChannel->getSipStatus().compare("CONFIRMED") == 0) && (status=pjmedia_master_port_create(sipChannel->getPlayPool(), portNull, pjmedia_conf_get_master_port(*(sipChannel->getPlayConf())), 0, sipChannel->getPlayMasterPort()
)) == PJ_SUCCESS) // start the master port status = pjmedia_master_port_start(*(sipChannel->getPlayMasterPort()));}

_________________________________________________________________
ÐÂÄê»»ÐÂÑÕ£¬¿ìÀŽ×±°ç×ÔŒºµÄMSNžøÐÄÒǵÄTAÒ»žöŸªÏ²£¡
http://im.live.cn/emoticons/?ID=18
Nanang Izzuddin
2008-09-02 11:27:52 UTC
Permalink
Hi,

Is there single memplayer instance for each call or shared by all
calls? Just in case you are using single memplayer instance for all
calls, but creating many conf ports for it.

Btw, in which callback is above code called? why does it always create
master port?

Regards,
nanang
Post by vopjessie
Hi All, my program is designed to be able to receive two calls
simultaneously (in different threads). When an inbound comes in, my program
plays audio data stored in memory to the caller. It works well when there is
only one inbound. However, when two inbounds come in simultaneously, the
sound quality heard by both callers is so poor that can be considered as
noises. When one of the inbound calls has hung up, the sound quality on the
other connected inbound call becomes good again. Could someone tell me what
I am doing wrong?
Thanks a lot!
Jessica
// add port of the channel and the port of the audio buffer to the
conference bridge
if((pjmedia_conf_add_port(*(sipChannel->getPlayConf()),
//pjmedia_conf *conf,
sipChannel->getPlayPool(), //pj_pool_t *pool,
portChannel, //pjmedia_port *strm_port,
NULL,//const pj_str_t *name,
&slotChannel//unsigned *p_slot)
) == PJ_SUCCESS) &&
(pjmedia_conf_add_port(*(sipChannel->getPlayConf()),
//pjmedia_conf *conf,
sipChannel->getPlayPool(), //pj_pool_t *pool,
portBuffer, //pjmedia_port *strm_port,
NULL,//const pj_str_t *name,
&slotBuffer//unsigned *p_slot)
) == PJ_SUCCESS) &&
// connect audio and channel ports
(pjmedia_conf_connect_port(*(sipChannel->getPlayConf()),
slotBuffer,
slotChannel,
0) == PJ_SUCCESS) &&
(pjmedia_conf_adjust_tx_level(*(sipChannel->getPlayConf()),
slotChannel, SIP_ADJUST_LEVEL) == PJ_SUCCESS) &&
(pjmedia_conf_adjust_rx_level(*(sipChannel->getPlayConf()),
slotBuffer, SIP_ADJUST_LEVEL) == PJ_SUCCESS) &&
// register call back
(pjmedia_mem_player_set_eof_cb(portBuffer,
sipChannel, &fillPlayBuffer) == PJ_SUCCESS))
{
pj_status_t status = -1;
// create master port
if((sipChannel->getSipStatus().compare("CONFIRMED")
== 0) &&
(status=pjmedia_master_port_create(sipChannel->getPlayPool(),
portNull,
pjmedia_conf_get_master_port(*(sipChannel->getPlayConf())),
0,
sipChannel->getPlayMasterPort()
)) == PJ_SUCCESS)
// start the master port
status =
pjmedia_master_port_start(*(sipChannel->getPlayMasterPort()));
}
________________________________
"七件武器,七种完美" 立刻体验!
_______________________________________________
Visit our blog: http://blog.pjsip.org
pjsip mailing list
http://lists.pjsip.org/mailman/listinfo/pjsip_lists.pjsip.org
_______________________________________________
Visit our blog: http://blog.pjsip.org

pjsip mailing list
***@lists.pjsip.org
http://lists.pjsip.org/
vopjessie
2008-09-02 12:43:29 UTC
Permalink
Hi Nanang, thanks a lot for your message. Let me include more code in this message. The code i put here is called only once for each inbound. For example, when the first inbound comes in, the code is called once in thread A; when the second inbound comes in, the code is called once again in thread B. Am i doing something wrong here?


thanks a lot!

-Jessica

if(pjmedia_conf_create(sipChannel->getPlayPool(), SIP_CONNECTION_PORT_COUNT, //unsigned max_slots, PCMU_CLOCK_RATE, //unsigned sampling_rate, PCMU_CHANNEL_COUNT, //unsigned channel_count, PCMU_SAMPES_PER_FRAME, //unsigned samples_per_frame, PCMU_BITS_PER_SAMPE, //unsigned bits_per_sample, PJMEDIA_CONF_NO_DEVICE, //unsigned options, sipChannel->getPlayConf()//pjmedia_conf ** p_conf ) == PJ_SUCCESS) && // create port for audio buffer (pjmedia_mem_player_create(sipChannel->getPlayPool(),// pj_pool_t * pool, sipChannel->getPlayFrame()->buf,//const void * buffer, sipChannel->getPlayFrame()->size,//pj_size_t size, PCMU_CLOCK_RATE,//unsigned clock_rate, PCMU_CHANNEL_CO
UNT,//unsigned channel_count, PCMU_SAMPES_PER_FRAME,//unsigned samples_per_frame, PCMU_BITS_PER_SAMPE,//unsigned bits_per_sample, NULL,//unsigned options, &portBuffer//pjmedia_port ** p_port ) == PJ_SUCCESS) &&
// add port of the channel and the port of the audio buffer to the conference bridge (pjmedia_conf_add_port(*(sipChannel->getPlayConf()), //pjmedia_conf *conf, sipChannel->getPlayPool(), //pj_pool_t *pool, portChannel, //pjmedia_port *strm_port, NULL,//const pj_str_t *name, &slotChannel//unsigned *p_slot) ) == PJ_SUCCESS) && (pjmedia_conf_add_port(*(sipChannel->getPlayConf()), //pjmedia_conf *conf, sipChannel->getPlayPool(), //pj_pool_t *pool, portBuffer, //pjmedia_port *strm_port, NULL,//const pj_str_t *name, &slotBuffer//unsigned *p_slot) ) == PJ_SUCCESS) && // connect audio and channel ports (pjmedia_conf_connect_port(*(sipChannel->getPlayConf()), slotBuffer,
slotChannel, 0) == PJ_SUCCESS) && (pjmedia_conf_adjust_tx_level(*(sipChannel->getPlayConf()), slotChannel, SIP_ADJUST_LEVEL) == PJ_SUCCESS) && (pjmedia_conf_adjust_rx_level(*(sipChannel->getPlayConf()), slotBuffer, SIP_ADJUST_LEVEL) == PJ_SUCCESS) && // register call back (pjmedia_mem_player_set_eof_cb(portBuffer, sipChannel, &fillPlayBuffer) == PJ_SUCCESS)) { if(sipChannel->getDeviceManager() != NULL) { pj_status_t status = -1; // create master port if((sipChannel->getSipStatus().compare("CONFIRMED") == 0) && (status=pjmedia_master_port_create(sipChannel->getPlayPool(), portNull, pjmedia_conf_get_master_port(*(sipChannel->getPlayConf())), 0,
sipChannel->getPlayMasterPort() )) == PJ_SUCCESS) // start the master port status = pjmedia_master_port_start(*(sipChannel->getPlayMasterPort()));}> Date: Tue, 2 Sep 2008 18:27:52 +0700> From: ***@pjsip.org> To: ***@lists.pjsip.org> Subject: Re: [pjsip] handle mutiple media flows simultaneously> > Hi,> > Is there single memplayer instance for each call or shared by all> calls? Just in case you are using single memplayer instance for all> calls, but creating many conf ports for it.> > Btw, in which callback is above code called? why does it always create> master port?> > Regards,> nanang> > > On 02/09/2008, vopjessie <***@hotmail.com> wrote:> > Hi All, my program is designed to be able to receive two calls> > simultaneously (in different
threads). When an inbound comes in, my program> > plays audio data stored in memory to the caller. It works well when there is> > only one inbound. However, when two inbounds come in simultaneously, the> > sound quality heard by both callers is so poor that can be considered as> > noises. When one of the inbound calls has hung up, the sound quality on the> > other connected inbound call becomes good again. Could someone tell me what> > I am doing wrong?> >> >> > Thanks a lot!> >> > Jessica> >> > My code is included as follows:> >> > // add port of the channel and the port of the audio buffer to the> > conference bridge> >> > if((pjmedia_conf_add_port(*(sipChannel->getPlayConf()),> > //pjmedia_conf *conf,> > sipChannel->getPlayPool(), //pj_pool_t *pool,> > portChannel, //pjmedia_port *st
rm_port,> > NULL,//const pj_str_t *name,> > &slotChannel//unsigned *p_slot)> > ) == PJ_SUCCESS) &&> > (pjmedia_conf_add_port(*(sipChannel->getPlayConf()),> > //pjmedia_conf *conf,> > sipChannel->getPlayPool(), //pj_pool_t *pool,> > portBuffer, //pjmedia_port *strm_port,> > NULL,//const pj_str_t *name,> > &slotBuffer//unsigned *p_slot)> > ) == PJ_SUCCESS) &&> > // connect audio and channel ports> >> > (pjmedia_conf_connect_port(*(sipChannel->getPlayConf()),> > slotBuffer,> > slotChannel,> > 0) == PJ_SUCCESS) &&> >> > (pjmedia_conf_adjust_tx_level(*(sipChannel->getPlayConf()),> > slotChannel, SIP_ADJUST_LEVEL) == PJ_SUCCESS) &&> >> > (pjmedia_conf_adjust_rx_level(*(sipChannel->getPlayConf()),> > slotBuffer, SIP_ADJUST_LEVEL) == PJ_SUCCESS) &&> > // register call back> > (pjmedia_mem_player
_set_eof_cb(portBuffer,> > sipChannel, &fillPlayBuffer) == PJ_SUCCESS))> > {> > pj_status_t status = -1;> > // create master port> >> > if((sipChannel->getSipStatus().compare("CONFIRMED")> > == 0) &&> >> > (status=pjmedia_master_port_create(sipChannel->getPlayPool(),> > portNull,> >> > pjmedia_conf_get_master_port(*(sipChannel->getPlayConf())),> > 0,> > sipChannel->getPlayMasterPort()> > )) == PJ_SUCCESS)> > // start the master port> > status => > pjmedia_master_port_start(*(sipChannel->getPlayMasterPort()));> > }> >> >> > ________________________________> > "ÆߌþÎäÆ÷£¬ÆßÖÖÍêÃÀ" Á¢¿ÌÌåÑ飡> > _______________________________________________> > Visit our blog: http://blog.pjsip.org> >> > pjsip mailing list> > ***@lists.pjsip.org> > http://lists.pjsip.org/mailman/listinfo/pjsip_lists.pjsi
p.org> >> >> _______________________________________________> Visit our blog: http://blog.pjsip.org> > pjsip mailing list> ***@lists.pjsip.org> http://lists.pjsip.org/mailman/listinfo/pjsip_lists.pjsip.org
_________________________________________________________________
MSN ÖÐÎÄÍø£¬×îÐÂʱÉÐÉú»î×ÊѶ£¬°×ÁìŸÛŒ¯ÃÅ»§¡£
http://cn.msn.com
Nanang Izzuddin
2008-09-02 14:18:50 UTC
Permalink
Hi,

Well, basically the code supposed to work as long as sipChannel
variables are managed correctly (e.g: sipChannel->getPlayConf() in
creating conf seems risky) and no shared variable used for each call
(e.g: sipChannel->*() should return different pointer for each call).
I think it is impossible to pin point the exact problem location only
with such code snippet (and I wouldn't prefer to see more code snippet
either).

Just an opinion, I don't see any advantage of creating conf bridge for
each call, since it's just wasting resources (and perhaps increasing
code complexity). So I would suggest you an alternative design:
- For all calls: a shared conference bridge driven by master port/null audio.
- For each call: just create a separate memplayer port, add conf port
for memplayer port & portChannel port to the shared conference bridge,
and connect them.

FYI, pjsua-lib also uses a single conference bridge to handle multiple
calls simultaneously. (Btw, why not just using pjsua-lib for your app,
it should be simpler).

Moreover, I don't think you need to create separate thread for each
call to prepare the media ports, just a normal function seems to be
enough.

Regards,
nanang
Post by vopjessie
Hi Nanang, thanks a lot for your message. Let me include more code in this
message. The code i put here is called only once for each inbound. For
example, when the first inbound comes in, the code is called once in thread
A; when the second inbound comes in, the code is called once again in thread
B. Am i doing something wrong here?
thanks a lot!
-Jessica
if(pjmedia_conf_create(sipChannel->getPlayPool(),
SIP_CONNECTION_PORT_COUNT, //unsigned max_slots,
PCMU_CLOCK_RATE, //unsigned sampling_rate,
PCMU_CHANNEL_COUNT, //unsigned channel_count,
PCMU_SAMPES_PER_FRAME, //unsigned samples_per_frame,
PCMU_BITS_PER_SAMPE, //unsigned bits_per_sample,
PJMEDIA_CONF_NO_DEVICE, //unsigned options,
sipChannel->getPlayConf()//pjmedia_conf ** p_conf
) == PJ_SUCCESS) &&
// create port for audio buffer
(pjmedia_mem_player_create(sipChannel->getPlayPool(),//
pj_pool_t * pool,
sipChannel->getPlayFrame()->buf,//const void *
buffer,
sipChannel->getPlayFrame()->size,//pj_size_t
size,
PCMU_CLOCK_RATE,//unsigned clock_rate,
PCMU_CHANNEL_COUNT,//unsigned channel_count,
PCMU_SAMPES_PER_FRAME,//unsigned
samples_per_frame,
PCMU_BITS_PER_SAMPE,//unsigned bits_per_sample,
NULL,//unsigned options,
&portBuffer//pjmedia_port ** p_port
) == PJ_SUCCESS) &&
// add port of the channel and the port of the audio buffer to the
conference bridge
(pjmedia_conf_add_port(*(sipChannel->getPlayConf()),
//pjmedia_conf *conf,
sipChannel->getPlayPool(), //pj_pool_t *pool,
portChannel, //pjmedia_port *strm_port,
NULL,//const pj_str_t *name,
&slotChannel//unsigned *p_slot)
) == PJ_SUCCESS) &&
(pjmedia_conf_add_port(*(sipChannel->getPlayConf()),
//pjmedia_conf *conf,
sipChannel->getPlayPool(), //pj_pool_t *pool,
portBuffer, //pjmedia_port *strm_port,
NULL,//const pj_str_t *name,
&slotBuffer//unsigned *p_slot)
) == PJ_SUCCESS) &&
// connect audio and channel ports
(pjmedia_conf_connect_port(*(sipChannel->getPlayConf()),
slotBuffer,
slotChannel,
0) == PJ_SUCCESS) &&
(pjmedia_conf_adjust_tx_level(*(sipChannel->getPlayConf()),
slotChannel, SIP_ADJUST_LEVEL) == PJ_SUCCESS) &&
(pjmedia_conf_adjust_rx_level(*(sipChannel->getPlayConf()),
slotBuffer, SIP_ADJUST_LEVEL) == PJ_SUCCESS) &&
// register call back
(pjmedia_mem_player_set_eof_cb(portBuffer,
sipChannel, &fillPlayBuffer) == PJ_SUCCESS))
{
if(sipChannel->getDeviceManager() != NULL)
{
pj_status_t status = -1;
// create master port
if((sipChannel->getSipStatus().compare("CONFIRMED")
== 0) &&
(status=pjmedia_master_port_create(sipChannel->getPlayPool(),
portNull,
pjmedia_conf_get_master_port(*(sipChannel->getPlayConf())),
0,
sipChannel->getPlayMasterPort()
)) == PJ_SUCCESS)
// start the master port
status =
pjmedia_master_port_start(*(sipChannel->getPlayMasterPort()));
}
Post by vopjessie
Date: Tue, 2 Sep 2008 18:27:52 +0700
Subject: Re: [pjsip] handle mutiple media flows simultaneously
Hi,
Is there single memplayer instance for each call or shared by all
calls? Just in case you are using single memplayer instance for all
calls, but creating many conf ports for it.
Btw, in which callback is above code called? why does it always create
master port?
Regards,
nanang
Post by vopjessie
Hi All, my program is designed to be able to receive two calls
simultaneously (in different threads). When an inbound comes in, my
program
Post by vopjessie
Post by vopjessie
plays audio data stored in memory to the caller. It works well when
there is
Post by vopjessie
Post by vopjessie
only one inbound. However, when two inbounds come in simultaneously, the
sound quality heard by both callers is so poor that can be considered as
noises. When one of the inbound calls has hung up, the sound quality on
the
Post by vopjessie
Post by vopjessie
other connected inbound call becomes good again. Could someone tell me
what
Post by vopjessie
Post by vopjessie
I am doing wrong?
Thanks a lot!
Jessica
// add port of the channel and the port of the audio buffer to the
conference bridge
if((pjmedia_conf_add_port(*(sipChannel->getPlayConf()),
//pjmedia_conf *conf,
sipChannel->getPlayPool(), //pj_pool_t *pool,
portChannel, //pjmedia_port *strm_port,
NULL,//const pj_str_t *name,
&slotChannel//unsigned *p_slot)
) == PJ_SUCCESS) &&
(pjmedia_conf_add_port(*(sipChannel->getPlayConf()),
//pjmedia_conf *conf,
sipChannel->getPlayPool(), //pj_pool_t *pool,
portBuffer, //pjmedia_port *strm_port,
NULL,//const pj_str_t *name,
&slotBuffer//unsigned *p_slot)
) == PJ_SUCCESS) &&
// connect audio and channel ports
(pjmedia_conf_connect_port(*(sipChannel->getPlayConf()),
Post by vopjessie
Post by vopjessie
slotBuffer,
slotChannel,
0) == PJ_SUCCESS) &&
(pjmedia_conf_adjust_tx_level(*(sipChannel->getPlayConf()),
Post by vopjessie
Post by vopjessie
slotChannel, SIP_ADJUST_LEVEL) == PJ_SUCCESS) &&
(pjmedia_conf_adjust_rx_level(*(sipChannel->getPlayConf()),
Post by vopjessie
Post by vopjessie
slotBuffer, SIP_ADJUST_LEVEL) == PJ_SUCCESS) &&
// register call back
(pjmedia_mem_player_set_eof_cb(portBuffer,
sipChannel, &fillPlayBuffer) == PJ_SUCCESS))
{
pj_status_t status = -1;
// create master port
if((sipChannel->getSipStatus().compare("CONFIRMED")
== 0) &&
(status=pjmedia_master_port_create(sipChannel->getPlayPool(),
Post by vopjessie
Post by vopjessie
portNull,
pjmedia_conf_get_master_port(*(sipChannel->getPlayConf())),
Post by vopjessie
Post by vopjessie
0,
sipChannel->getPlayMasterPort()
)) == PJ_SUCCESS)
// start the master port
status =
pjmedia_master_port_start(*(sipChannel->getPlayMasterPort()));
Post by vopjessie
Post by vopjessie
}
________________________________
"七件武器,七种完美" 立刻体验!
_______________________________________________
Visit our blog: http://blog.pjsip.org
pjsip mailing list
http://lists.pjsip.org/mailman/listinfo/pjsip_lists.pjsip.org
Post by vopjessie
_______________________________________________
Visit our blog: http://blog.pjsip.org
pjsip mailing list
http://lists.pjsip.org/mailman/listinfo/pjsip_lists.pjsip.org
________________________________
轻松把Hotmail下载到本地,试试 Windows Live Mail。 立即尝试!
_______________________________________________
Visit our blog: http://blog.pjsip.org
pjsip mailing list
http://lists.pjsip.org/mailman/listinfo/pjsip_lists.pjsip.org
_______________________________________________
Visit our blog: http://blog.pjsip.org

pjsip mailing list
***@lists.pjsip.org
http://lists.pjsip.org/mailman/listinfo/pjsip_

Loading...