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 + -
显示快捷键?