Загрузка данных
static pj_status_t create_conf_port( pj_pool_t *parent_pool,pjmedia_conf *conf, pjmedia_port *port,const pj_str_t *name, struct conf_port **p_conf_port)
{
struct conf_port *conf_port = NULL;
pj_pool_t *pool = NULL;
char pname[PJ_MAX_OBJ_NAME];
pj_status_t status = PJ_SUCCESS;
/* Make sure pool name is NULL terminated */
pj_assert(name);
pj_ansi_strxcpy2(pname, name, sizeof(pname));
/* Create own pool */
pool = pj_pool_create(parent_pool->factory, pname, 500, 500, NULL);
if (!pool)
return PJ_ENOMEM;
/* Create port. */
conf_port = PJ_POOL_ZALLOC_T(pool, struct conf_port);
PJ_ASSERT_ON_FAIL(conf_port, {pj_pool_release(pool); return PJ_ENOMEM;});
conf_port->pool = pool;
/* Increment port ref count to avoid premature destroy due to
* asynchronous port removal.
*/
if (port) {
if (!port->grp_lock) {
/* Create group lock if it does not have one */
pjmedia_port_init_grp_lock(port, pool, NULL);
}
pj_grp_lock_add_ref(port->grp_lock);
/* Pool may be used for creating port's group lock and the group lock
* may be used by app, so pool destroy must be done via handler.
*/
status = pj_grp_lock_add_handler(port->grp_lock, NULL, conf_port,
&conf_port_on_destroy);
}
/* Set name */
pj_strdup_with_null(pool, &conf_port->name, name);
/* Default has tx and rx enabled. */
conf_port->rx_setting = PJMEDIA_PORT_ENABLE;
conf_port->tx_setting = PJMEDIA_PORT_ENABLE;
/* Default level adjustment is 128 (which means no adjustment) */
conf_port->tx_adj_level = NORMAL_LEVEL;
conf_port->rx_adj_level = NORMAL_LEVEL;
/* Create transmit flag array */
conf_port->listener_slots = (SLOT_TYPE*) pj_pool_zalloc(pool,
conf->max_ports * sizeof(SLOT_TYPE));
PJ_ASSERT_ON_FAIL(conf_port->listener_slots,
{status = PJ_ENOMEM; goto on_return;});
/* Create adjustment level array */
conf_port->listener_adj_level = (unsigned *) pj_pool_zalloc(pool,
conf->max_ports * sizeof(unsigned));
PJ_ASSERT_ON_FAIL(conf_port->listener_adj_level,
{status = PJ_ENOMEM; goto on_return;});
printf("%s(%d) port=%p\n",__FUNCTION__,__LINE__,port);
/* Save some port's infos, for convenience. */
if (port) {
pjmedia_audio_format_detail *afd;
afd = pjmedia_format_get_audio_format_detail(&port->info.fmt, 1);
conf_port->port = port;
conf_port->clock_rate = afd->clock_rate;
conf_port->samples_per_frame = PJMEDIA_AFD_SPF(afd);
conf_port->channel_count = afd->channel_count;
printf("%s(%d) clock_rate=%u samples_per_frame=%u channel_count=%u\n",__FUNCTION__,__LINE__,afd->clock_rate,PJMEDIA_AFD_SPF(afd),afd->channel_count);
#ifndef MY_CODE
conf->clock_rate = conf_port->clock_rate;
conf->channel_count = conf_port->channel_count;
conf->samples_per_frame = conf_port->samples_per_frame;
#endif
} else {
conf_port->port = NULL;
conf_port->clock_rate = conf->clock_rate;
conf_port->samples_per_frame = conf->samples_per_frame;
conf_port->channel_count = conf->channel_count;
}
/* Create adjustment level buffer. */
conf_port->adj_level_buf = (pj_int16_t*) pj_pool_zalloc(pool,
conf->samples_per_frame * sizeof(pj_int16_t));
PJ_ASSERT_ON_FAIL(conf_port->adj_level_buf,
{status = PJ_ENOMEM; goto on_return;});
/* If port's clock rate is different than conference's clock rate,
* create a resample sessions.
*/
if (conf_port->clock_rate != conf->clock_rate) {
pj_bool_t high_quality;
pj_bool_t large_filter;
high_quality = ((conf->options & PJMEDIA_CONF_USE_LINEAR)==0);
large_filter = ((conf->options & PJMEDIA_CONF_SMALL_FILTER)==0);
#ifndef MY_CODE
//high_quality = 0;
//large_filter = 0;
printf("%s(%d) high_quality=%d large_filter=%d Rate_in:%u Rate_out:%u samples_per_frame=%u\n",__FUNCTION__,__LINE__,high_quality,large_filter,conf_port->clock_rate,conf->clock_rate,conf->samples_per_frame * conf_port->clock_rate /conf->clock_rate);
#endif
/* Create resample for rx buffer. */
status = pjmedia_resample_create( pool,
high_quality,
large_filter,
conf->channel_count,
conf_port->clock_rate,/* Rate in */
conf->clock_rate, /* Rate out */
conf->samples_per_frame *
conf_port->clock_rate /
conf->clock_rate,
&conf_port->rx_resample);
if (status != PJ_SUCCESS)
goto on_return;
/* Create resample for tx buffer. */
status = pjmedia_resample_create(pool,
high_quality,
large_filter,
conf->channel_count,
conf->clock_rate, /* Rate in */
conf_port->clock_rate, /* Rate out */
conf->samples_per_frame,
&conf_port->tx_resample);
if (status != PJ_SUCCESS)
goto on_return;
}
/*
* Initialize rx and tx buffer, only when port's samples per frame or
* port's clock rate or channel number is different then the conference
* bridge settings.
*/
printf("%s(%d) conf_port(IN):\n",__FUNCTION__,__LINE__);
printf("clock_rate=%u channel_count=%u samples_per_frame=%u\n",conf_port->clock_rate,conf_port->channel_count,conf_port->samples_per_frame);
printf("%s(%d) conf(OUT):\n",__FUNCTION__,__LINE__);
printf("clock_rate=%u channel_count=%u samples_per_frame=%u\n",conf->clock_rate,conf->channel_count,conf->samples_per_frame);
if (conf_port->clock_rate != conf->clock_rate ||
conf_port->channel_count != conf->channel_count ||
conf_port->samples_per_frame != conf->samples_per_frame)
{
unsigned port_ptime, conf_ptime, buff_ptime;
port_ptime = conf_port->samples_per_frame / conf_port->channel_count *
1000 / conf_port->clock_rate;
conf_ptime = conf->samples_per_frame / conf->channel_count *
1000 / conf->clock_rate;
/* Check compatibility of sample rate and ptime.
* Some combinations result in a fractional number of samples per frame
* which we do not support.
* One such case would be for example 10ms @ 22050Hz which would yield
* 220.5 samples per frame.
*/
if (0 != (port_ptime * conf_port->clock_rate *
conf_port->channel_count % 1000))
{
PJ_LOG(3,(THIS_FILE,
"Cannot create conf port: incompatible sample rate/ptime"));
status = PJMEDIA_ENOTCOMPATIBLE;
goto on_return;
}
/* Calculate the size (in ptime) for the port buffer according to
* this formula:
* - if either ptime is an exact multiple of the other, then use
* the larger ptime (e.g. 20ms and 40ms, use 40ms).
* - if not, then the ptime is sum of both ptimes (e.g. 20ms
* and 30ms, use 50ms)
*/
if (port_ptime > conf_ptime) {
buff_ptime = port_ptime;
if (port_ptime % conf_ptime)
buff_ptime += conf_ptime;
} else {
buff_ptime = conf_ptime;
if (conf_ptime % port_ptime)
buff_ptime += port_ptime;
}
/* Create RX buffer. */
//conf_port->rx_buf_cap = (unsigned)(conf_port->samples_per_frame +
// conf->samples_per_frame *
// conf_port->clock_rate * 1.0 /
// conf->clock_rate + 0.5);
conf_port->rx_buf_cap = conf_port->clock_rate * buff_ptime / 1000;
if (conf_port->channel_count > conf->channel_count)
conf_port->rx_buf_cap *= conf_port->channel_count;
else
conf_port->rx_buf_cap *= conf->channel_count;
conf_port->rx_buf_count = 0;
conf_port->rx_buf = (pj_int16_t*)
pj_pool_alloc(pool, conf_port->rx_buf_cap *
sizeof(conf_port->rx_buf[0]));
PJ_ASSERT_ON_FAIL(conf_port->rx_buf,
{status = PJ_ENOMEM; goto on_return;});
/* Create TX buffer. */
conf_port->tx_buf_cap = conf_port->rx_buf_cap;
conf_port->tx_buf_count = 0;
conf_port->tx_buf = (pj_int16_t*)
pj_pool_alloc(pool, conf_port->tx_buf_cap *
sizeof(conf_port->tx_buf[0]));
PJ_ASSERT_ON_FAIL(conf_port->tx_buf,
{status = PJ_ENOMEM; goto on_return;});
}
/* Create mix buffer. */
conf_port->mix_buf = (pj_int32_t*)
pj_pool_zalloc(pool, conf->samples_per_frame *
sizeof(conf_port->mix_buf[0]));
PJ_ASSERT_ON_FAIL(conf_port->mix_buf,
{status = PJ_ENOMEM; goto on_return;});
conf_port->last_mix_adj = NORMAL_LEVEL;
/* Done */
*p_conf_port = conf_port;
on_return:
if (status != PJ_SUCCESS) {
/* Destroy resample if this conf port has it. */
if (conf_port && conf_port->rx_resample)
pjmedia_resample_destroy(conf_port->rx_resample);
if (conf_port && conf_port->tx_resample)
pjmedia_resample_destroy(conf_port->tx_resample);
if (port && port->grp_lock) {
pj_grp_lock_dec_ref(port->grp_lock);
} else if (pool) {
pj_pool_release(pool);
}
}
return status;
}