conference.c

来自「基于sip协议的网络电话源码」· C语言 代码 · 共 1,932 行 · 第 1/4 页

C
1,932
字号
	      max_ports));    /* Create and init conf structure. */    conf = pj_pool_zalloc(pool, sizeof(pjmedia_conf));    PJ_ASSERT_RETURN(conf, PJ_ENOMEM);    conf->ports = pj_pool_zalloc(pool, max_ports*sizeof(void*));    PJ_ASSERT_RETURN(conf->ports, PJ_ENOMEM);    conf->options = options;    conf->max_ports = max_ports;    conf->clock_rate = clock_rate;    conf->channel_count = channel_count;    conf->samples_per_frame = samples_per_frame;    conf->bits_per_sample = bits_per_sample;        /* Create and initialize the master port interface. */    conf->master_port = pj_pool_zalloc(pool, sizeof(pjmedia_port));    PJ_ASSERT_RETURN(conf->master_port, PJ_ENOMEM);        pjmedia_port_info_init(&conf->master_port->info, &name, SIGNATURE,			   clock_rate, channel_count, bits_per_sample,			   samples_per_frame);    conf->master_port->port_data.pdata = conf;    conf->master_port->port_data.ldata = 0;    conf->master_port->get_frame = &get_frame;    conf->master_port->put_frame = &put_frame;    conf->master_port->on_destroy = &destroy_port;    /* Create port zero for sound device. */    status = create_sound_port(pool, conf);    if (status != PJ_SUCCESS)	return status;    /* Create temporary buffer. */    conf->uns_buf = pj_pool_zalloc(pool, samples_per_frame *					 sizeof(conf->uns_buf[0]));    /* Create mutex. */    status = pj_mutex_create_recursive(pool, "conf", &conf->mutex);    if (status != PJ_SUCCESS)	return status;    /* If sound device was created, connect sound device to the     * master port.     */    if (conf->snd_dev_port) {	status = pjmedia_snd_port_connect( conf->snd_dev_port, 					   conf->master_port );	if (status != PJ_SUCCESS) {	    pjmedia_conf_destroy(conf);	    return status;	}    }    /* Done */    *p_conf = conf;    return PJ_SUCCESS;}/* * Pause sound device. */static pj_status_t pause_sound( pjmedia_conf *conf ){    /* Do nothing. */    PJ_UNUSED_ARG(conf);    return PJ_SUCCESS;}/* * Resume sound device. */static pj_status_t resume_sound( pjmedia_conf *conf ){    /* Do nothing. */    PJ_UNUSED_ARG(conf);    return PJ_SUCCESS;}/** * Destroy conference bridge. */PJ_DEF(pj_status_t) pjmedia_conf_destroy( pjmedia_conf *conf ){    PJ_ASSERT_RETURN(conf != NULL, PJ_EINVAL);    /* Destroy sound device port. */    if (conf->snd_dev_port) {	pjmedia_snd_port_destroy(conf->snd_dev_port);	conf->snd_dev_port = NULL;    }    /* Destroy mutex */    pj_mutex_destroy(conf->mutex);    return PJ_SUCCESS;}/* * Destroy the master port (will destroy the conference) */static pj_status_t destroy_port(pjmedia_port *this_port){    pjmedia_conf *conf = this_port->port_data.pdata;    return pjmedia_conf_destroy(conf);}/* * Get port zero interface. */PJ_DEF(pjmedia_port*) pjmedia_conf_get_master_port(pjmedia_conf *conf){    /* Sanity check. */    PJ_ASSERT_RETURN(conf != NULL, NULL);    /* Can only return port interface when PJMEDIA_CONF_NO_DEVICE was     * present in the option.     */    PJ_ASSERT_RETURN((conf->options & PJMEDIA_CONF_NO_DEVICE) != 0, NULL);        return conf->master_port;}/* * Set master port name. */PJ_DEF(pj_status_t) pjmedia_conf_set_port0_name(pjmedia_conf *conf,						const pj_str_t *name){    int len;    /* Sanity check. */    PJ_ASSERT_RETURN(conf != NULL && name != NULL, PJ_EINVAL);    len = name->slen;    if (len > sizeof(conf->master_name_buf))	len = sizeof(conf->master_name_buf);        if (len > 0) pj_memcpy(conf->master_name_buf, name->ptr, len);    conf->ports[0]->name.ptr = conf->master_name_buf;    conf->ports[0]->name.slen = len;    if (conf->master_port)	conf->master_port->info.name = conf->ports[0]->name;    return PJ_SUCCESS;}/* * Add stream port to the conference bridge. */PJ_DEF(pj_status_t) pjmedia_conf_add_port( pjmedia_conf *conf,					   pj_pool_t *pool,					   pjmedia_port *strm_port,					   const pj_str_t *port_name,					   unsigned *p_port ){    struct conf_port *conf_port;    unsigned index;    pj_status_t status;    PJ_ASSERT_RETURN(conf && pool && strm_port, PJ_EINVAL);    /* If port_name is not specified, use the port's name */    if (!port_name)	port_name = &strm_port->info.name;    /* For this version of PJMEDIA, port MUST have the same number of     * PCM channels.     */    if (strm_port->info.channel_count != conf->channel_count) {	pj_assert(!"Number of channels mismatch");	return PJMEDIA_ENCCHANNEL;    }    pj_mutex_lock(conf->mutex);    if (conf->port_cnt >= conf->max_ports) {	pj_assert(!"Too many ports");	pj_mutex_unlock(conf->mutex);	return PJ_ETOOMANY;    }    /* Find empty port in the conference bridge. */    for (index=0; index < conf->max_ports; ++index) {	if (conf->ports[index] == NULL)	    break;    }    pj_assert(index != conf->max_ports);    /* Create conf port structure. */    status = create_conf_port(pool, conf, strm_port, port_name, &conf_port);    if (status != PJ_SUCCESS) {	pj_mutex_unlock(conf->mutex);	return status;    }    /* Put the port. */    conf->ports[index] = conf_port;    conf->port_cnt++;    /* Done. */    if (p_port) {	*p_port = index;    }    pj_mutex_unlock(conf->mutex);    return PJ_SUCCESS;}/* * Add passive port. */PJ_DEF(pj_status_t) pjmedia_conf_add_passive_port( pjmedia_conf *conf,						   pj_pool_t *pool,						   const pj_str_t *name,						   unsigned clock_rate,						   unsigned channel_count,						   unsigned samples_per_frame,						   unsigned bits_per_sample,						   unsigned options,						   unsigned *p_slot,						   pjmedia_port **p_port ){    struct conf_port *conf_port;    pjmedia_port *port;    unsigned index;    pj_str_t tmp;    pj_status_t status;    PJ_ASSERT_RETURN(conf && pool, PJ_EINVAL);    /* For this version of PJMEDIA, port MUST have the same number of     * PCM channels.     */    if (channel_count != conf->channel_count) {	pj_assert(!"Number of channels mismatch");	return PJMEDIA_ENCCHANNEL;    }    /* For this version, options must be zero */    PJ_ASSERT_RETURN(options == 0, PJ_EINVAL);    PJ_UNUSED_ARG(options);    pj_mutex_lock(conf->mutex);    if (conf->port_cnt >= conf->max_ports) {	pj_assert(!"Too many ports");	pj_mutex_unlock(conf->mutex);	return PJ_ETOOMANY;    }    /* Find empty port in the conference bridge. */    for (index=0; index < conf->max_ports; ++index) {	if (conf->ports[index] == NULL)	    break;    }    pj_assert(index != conf->max_ports);    if (name == NULL) {	name = &tmp;	tmp.ptr = pj_pool_alloc(pool, 32);	tmp.slen = pj_ansi_snprintf(tmp.ptr, 32, "ConfPort#%d", index);    }    /* Create and initialize the media port structure. */    port = pj_pool_zalloc(pool, sizeof(pjmedia_port));    PJ_ASSERT_RETURN(port, PJ_ENOMEM);        pjmedia_port_info_init(&port->info, name, SIGNATURE_PORT,			   clock_rate, channel_count, bits_per_sample,			   samples_per_frame);    port->port_data.pdata = conf;    port->port_data.ldata = index;    port->get_frame = &get_frame_pasv;    port->put_frame = &put_frame;    port->on_destroy = NULL;        /* Create conf port structure. */    status = create_pasv_port(conf, pool, name, port, &conf_port);    if (status != PJ_SUCCESS) {	pj_mutex_unlock(conf->mutex);	return status;    }    /* Put the port. */    conf->ports[index] = conf_port;    conf->port_cnt++;    /* Done. */    if (p_slot)	*p_slot = index;    if (p_port)	*p_port = port;    pj_mutex_unlock(conf->mutex);    return PJ_SUCCESS;}/* * Change TX and RX settings for the port. */PJ_DECL(pj_status_t) pjmedia_conf_configure_port( pjmedia_conf *conf,						  unsigned slot,						  pjmedia_port_op tx,						  pjmedia_port_op rx){    struct conf_port *conf_port;    /* Check arguments */    PJ_ASSERT_RETURN(conf && slot<conf->max_ports, PJ_EINVAL);    /* Port must be valid. */    PJ_ASSERT_RETURN(conf->ports[slot] != NULL, PJ_EINVAL);    conf_port = conf->ports[slot];    if (tx != PJMEDIA_PORT_NO_CHANGE)	conf_port->tx_setting = tx;    if (rx != PJMEDIA_PORT_NO_CHANGE)	conf_port->rx_setting = rx;    return PJ_SUCCESS;}/* * Connect port. */PJ_DEF(pj_status_t) pjmedia_conf_connect_port( pjmedia_conf *conf,					       unsigned src_slot,					       unsigned sink_slot,					       int level ){    struct conf_port *src_port, *dst_port;    pj_bool_t start_sound = PJ_FALSE;    unsigned i;    /* Check arguments */    PJ_ASSERT_RETURN(conf && src_slot<conf->max_ports && 		     sink_slot<conf->max_ports, PJ_EINVAL);    /* Ports must be valid. */    PJ_ASSERT_RETURN(conf->ports[src_slot] != NULL, PJ_EINVAL);    PJ_ASSERT_RETURN(conf->ports[sink_slot] != NULL, PJ_EINVAL);    /* For now, level MUST be zero. */    PJ_ASSERT_RETURN(level == 0, PJ_EINVAL);    pj_mutex_lock(conf->mutex);    src_port = conf->ports[src_slot];    dst_port = conf->ports[sink_slot];    /* Check if connection has been made */    for (i=0; i<src_port->listener_cnt; ++i) {	if (src_port->listener_slots[i] == sink_slot)	    break;    }    if (i == src_port->listener_cnt) {	src_port->listener_slots[src_port->listener_cnt] = sink_slot;	++conf->connect_cnt;	++src_port->listener_cnt;	++dst_port->transmitter_cnt;	if (conf->connect_cnt == 1)	    start_sound = 1;	PJ_LOG(4,(THIS_FILE,"Port %d (%.*s) transmitting to port %d (%.*s)",		  src_slot,		  (int)src_port->name.slen,		  src_port->name.ptr,		  sink_slot,		  (int)dst_port->name.slen,		  dst_port->name.ptr));    }    pj_mutex_unlock(conf->mutex);    /* Sound device must be started without mutex, otherwise the     * sound thread will deadlock (?)     */    if (start_sound)	resume_sound(conf);    return PJ_SUCCESS;}/* * Disconnect port */PJ_DEF(pj_status_t) pjmedia_conf_disconnect_port( pjmedia_conf *conf,						  unsigned src_slot,						  unsigned sink_slot ){    struct conf_port *src_port, *dst_port;    unsigned i;    /* Check arguments */    PJ_ASSERT_RETURN(conf && src_slot<conf->max_ports && 		     sink_slot<conf->max_ports, PJ_EINVAL);    /* Ports must be valid. */    PJ_ASSERT_RETURN(conf->ports[src_slot] != NULL, PJ_EINVAL);    PJ_ASSERT_RETURN(conf->ports[sink_slot] != NULL, PJ_EINVAL);    pj_mutex_lock(conf->mutex);    src_port = conf->ports[src_slot];    dst_port = conf->ports[sink_slot];    /* Check if connection has been made */    for (i=0; i<src_port->listener_cnt; ++i) {	if (src_port->listener_slots[i] == sink_slot)	    break;    }    if (i != src_port->listener_cnt) {	pj_assert(src_port->listener_cnt > 0 && 		  src_port->listener_cnt < conf->max_ports);	pj_assert(dst_port->transmitter_cnt > 0 && 		  dst_port->transmitter_cnt < conf->max_ports);	pj_array_erase(src_port->listener_slots, sizeof(SLOT_TYPE), 		       src_port->listener_cnt, i);	--conf->connect_cnt;	--src_port->listener_cnt;	--dst_port->transmitter_cnt;	PJ_LOG(4,(THIS_FILE,		  "Port %d (%.*s) stop transmitting to port %d (%.*s)",		  src_slot,		  (int)src_port->name.slen,		  src_port->name.ptr,		  sink_slot,		  (int)dst_port->name.slen,		  dst_port->name.ptr));	    }    pj_mutex_unlock(conf->mutex);    if (conf->connect_cnt == 0) {	pause_sound(conf);    }    return PJ_SUCCESS;}/* * Get total number of ports connections currently set up in the bridge. */PJ_DECL(unsigned) pjmedia_conf_get_connect_count(pjmedia_conf *conf)

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?