conference.c
来自「基于sip协议的网络电话源码」· C语言 代码 · 共 1,932 行 · 第 1/4 页
C
1,932 行
{ return conf->connect_cnt;}/* * Remove the specified port. */PJ_DEF(pj_status_t) pjmedia_conf_remove_port( pjmedia_conf *conf, unsigned port ){ struct conf_port *conf_port; unsigned i; /* Check arguments */ PJ_ASSERT_RETURN(conf && port < conf->max_ports, PJ_EINVAL); /* Port must be valid. */ PJ_ASSERT_RETURN(conf->ports[port] != NULL, PJ_EINVAL); /* Suspend the sound devices. * Don't want to remove port while port is being accessed by sound * device's threads! */ pj_mutex_lock(conf->mutex); conf_port = conf->ports[port]; conf_port->tx_setting = PJMEDIA_PORT_DISABLE; conf_port->rx_setting = PJMEDIA_PORT_DISABLE; /* Remove this port from transmit array of other ports. */ for (i=0; i<conf->max_ports; ++i) { unsigned j; conf_port = conf->ports[i]; if (!conf_port) continue; if (conf_port->listener_cnt == 0) continue; for (j=0; j<conf_port->listener_cnt; ++j) { if (conf_port->listener_slots[j] == port) { pj_array_erase(conf_port->listener_slots, sizeof(SLOT_TYPE), conf_port->listener_cnt, j); --conf->connect_cnt; --conf_port->listener_cnt; break; } } } /* Update conf's connection count. */ conf_port = conf->ports[port]; conf->connect_cnt -= conf_port->listener_cnt; /* Remove the port. */ conf->ports[port] = NULL; --conf->port_cnt; pj_mutex_unlock(conf->mutex); /* Stop sound if there's no connection. */ if (conf->connect_cnt == 0) { pause_sound(conf); } return PJ_SUCCESS;}/* * Enum ports. */PJ_DEF(pj_status_t) pjmedia_conf_enum_ports( pjmedia_conf *conf, unsigned ports[], unsigned *p_count ){ unsigned i, count=0; PJ_ASSERT_RETURN(conf && p_count && ports, PJ_EINVAL); for (i=0; i<conf->max_ports && count<*p_count; ++i) { if (!conf->ports[i]) continue; ports[count++] = i; } *p_count = count; return PJ_SUCCESS;}/* * Get port info */PJ_DEF(pj_status_t) pjmedia_conf_get_port_info( pjmedia_conf *conf, unsigned slot, pjmedia_conf_port_info *info){ 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]; info->slot = slot; info->name = conf_port->name; info->tx_setting = conf_port->tx_setting; info->rx_setting = conf_port->rx_setting; info->listener_cnt = conf_port->listener_cnt; info->listener_slots = conf_port->listener_slots; info->clock_rate = conf_port->clock_rate; info->channel_count = conf->channel_count; info->samples_per_frame = conf_port->samples_per_frame; info->bits_per_sample = conf->bits_per_sample; info->tx_adj_level = conf_port->tx_adj_level - NORMAL_LEVEL; info->rx_adj_level = conf_port->rx_adj_level - NORMAL_LEVEL; return PJ_SUCCESS;}PJ_DEF(pj_status_t) pjmedia_conf_get_ports_info(pjmedia_conf *conf, unsigned *size, pjmedia_conf_port_info info[]){ unsigned i, count=0; PJ_ASSERT_RETURN(conf && size && info, PJ_EINVAL); for (i=0; i<conf->max_ports && count<*size; ++i) { if (!conf->ports[i]) continue; pjmedia_conf_get_port_info(conf, i, &info[count]); ++count; } *size = count; return PJ_SUCCESS;}/* * Get signal level. */PJ_DEF(pj_status_t) pjmedia_conf_get_signal_level( pjmedia_conf *conf, unsigned slot, unsigned *tx_level, unsigned *rx_level){ 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_level != NULL) { *tx_level = conf_port->tx_level; } if (rx_level != NULL) *rx_level = conf_port->rx_level; return PJ_SUCCESS;}/* * Adjust RX level of individual port. */PJ_DEF(pj_status_t) pjmedia_conf_adjust_rx_level( pjmedia_conf *conf, unsigned slot, int adj_level ){ 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); /* Value must be from -128 to +127 */ /* Disabled, you can put more than +127, at your own risk: PJ_ASSERT_RETURN(adj_level >= -128 && adj_level <= 127, PJ_EINVAL); */ PJ_ASSERT_RETURN(adj_level >= -128, PJ_EINVAL); conf_port = conf->ports[slot]; /* Set normalized adjustment level. */ conf_port->rx_adj_level = adj_level + NORMAL_LEVEL; return PJ_SUCCESS;}/* * Adjust TX level of individual port. */PJ_DEF(pj_status_t) pjmedia_conf_adjust_tx_level( pjmedia_conf *conf, unsigned slot, int adj_level ){ 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); /* Value must be from -128 to +127 */ /* Disabled, you can put more than +127,, at your own risk: PJ_ASSERT_RETURN(adj_level >= -128 && adj_level <= 127, PJ_EINVAL); */ PJ_ASSERT_RETURN(adj_level >= -128, PJ_EINVAL); conf_port = conf->ports[slot]; /* Set normalized adjustment level. */ conf_port->tx_adj_level = adj_level + NORMAL_LEVEL; return PJ_SUCCESS;}/* Convert signed 16bit pcm sample to unsigned 16bit sample */static pj_uint16_t pcm2unsigned(pj_int32_t pcm){ return (pj_uint16_t)(pcm + 32768);}/* Convert unsigned 16bit sample to signed 16bit pcm sample */static pj_int16_t unsigned2pcm(pj_uint32_t uns){ return (pj_int16_t)(uns - 32768);}/* * Read from port. */static pj_status_t read_port( pjmedia_conf *conf, struct conf_port *cport, pj_int16_t *frame, pj_size_t count, pjmedia_frame_type *type ){ pj_assert(count == conf->samples_per_frame); TRACE_((THIS_FILE, "read_port %.*s: count=%d", (int)cport->name.slen, cport->name.ptr, count)); /* If port's samples per frame and sampling rate matches conference * bridge's settings, get the frame directly from the port. */ if (cport->rx_buf_cap == 0) { pjmedia_frame f; pj_status_t status; f.buf = frame; f.size = count * BYTES_PER_SAMPLE; TRACE_((THIS_FILE, " get_frame %.*s: count=%d", (int)cport->name.slen, cport->name.ptr, count)); status = pjmedia_port_get_frame(cport->port, &f); *type = f.type; return status; } else { /* * If we don't have enough samples in rx_buf, read from the port * first. Remember that rx_buf may be in different clock rate! */ while (cport->rx_buf_count < count * 1.0 * cport->clock_rate / conf->clock_rate) { pjmedia_frame f; pj_status_t status; f.buf = cport->rx_buf + cport->rx_buf_count; f.size = cport->samples_per_frame * BYTES_PER_SAMPLE; TRACE_((THIS_FILE, " get_frame, count=%d", cport->samples_per_frame)); status = pjmedia_port_get_frame(cport->port, &f); if (status != PJ_SUCCESS) { /* Fatal error! */ return status; } if (f.type != PJMEDIA_FRAME_TYPE_AUDIO) { TRACE_((THIS_FILE, " get_frame returned non-audio")); pjmedia_zero_samples( cport->rx_buf + cport->rx_buf_count, cport->samples_per_frame); } cport->rx_buf_count += cport->samples_per_frame; TRACE_((THIS_FILE, " rx buffer size is now %d", cport->rx_buf_count)); pj_assert(cport->rx_buf_count <= cport->rx_buf_cap); } /* * If port's clock_rate is different, resample. * Otherwise just copy. */ if (cport->clock_rate != conf->clock_rate) { unsigned src_count; TRACE_((THIS_FILE, " resample, input count=%d", pjmedia_resample_get_input_size(cport->rx_resample))); pjmedia_resample_run( cport->rx_resample,cport->rx_buf, frame); src_count = (unsigned)(count * 1.0 * cport->clock_rate / conf->clock_rate); cport->rx_buf_count -= src_count; if (cport->rx_buf_count) { pjmedia_copy_samples(cport->rx_buf, cport->rx_buf+src_count, cport->rx_buf_count); } TRACE_((THIS_FILE, " rx buffer size is now %d", cport->rx_buf_count)); } else { pjmedia_copy_samples(frame, cport->rx_buf, count); cport->rx_buf_count -= count; if (cport->rx_buf_count) { pjmedia_copy_samples(cport->rx_buf, cport->rx_buf+count, cport->rx_buf_count); } } } return PJ_SUCCESS;}/* * Write the mixed signal to the port. */static pj_status_t write_port(pjmedia_conf *conf, struct conf_port *cport, const pj_timestamp *timestamp, pjmedia_frame_type *frm_type){ pj_int16_t *buf; unsigned j, ts; pj_status_t status; *frm_type = PJMEDIA_FRAME_TYPE_AUDIO; /* If port is muted or nobody is transmitting to this port, * transmit NULL frame. */ if (cport->tx_setting == PJMEDIA_PORT_MUTE || cport->transmitter_cnt==0) { pjmedia_frame frame; /* Adjust the timestamp */ frame.timestamp.u64 = timestamp->u64 * cport->clock_rate / conf->clock_rate; frame.type = PJMEDIA_FRAME_TYPE_NONE; frame.buf = NULL; frame.size = 0; if (cport->port && cport->port->put_frame) { pjmedia_port_put_frame(cport->port, &frame); } cport->tx_level = 0; *frm_type = PJMEDIA_FRAME_TYPE_NONE; return PJ_SUCCESS; } else if (cport->src_level==0) { pjmedia_frame frame; /* If silence is transmitted to this port, transmit silence * PCM frame (otherwise if we transmit NULL frame, nothing will * be written to WAV port). This would work with stream too * since stream has it's own silence detector. */ pjmedia_zero_samples((pj_int16_t*)cport->mix_buf, cport->samples_per_frame); /* Adjust the timestamp */ frame.timestamp.u64 = timestamp->u64 * cport->clock_rate / conf->clock_rate; frame.type = PJMEDIA_FRAME_TYPE_NONE; frame.buf = (void*)cport->mix_buf; frame.size = (cport->samples_per_frame << 1); if (cport->port && cport->port->put_frame) { pjmedia_port_put_frame(cport->port, &frame); } cport->tx_level = 0; *frm_type = PJMEDIA_FRAME_TYPE_NONE; return PJ_SUCCESS; } else if (cport->tx_setting != PJMEDIA_PORT_ENABLE) { cport->tx_level = 0; *frm_type = PJMEDIA_FRAME_TYPE_NONE; return PJ_SUCCESS; } buf = (pj_int16_t*)cport->mix_buf; /* This is the convention set in get_frame(). For optimization purpose, * if we only have one transmitter transmitting to this port, then * the transmitter will directly copy the original 16bit frame to * mix_buf. */ if (cport->transmitter_cnt==1 && cport->src_cnt == 1) { /* But still see if we need to adjust the level */ if (cport->tx_adj_level != NORMAL_LEVEL) { pj_int16_t *input = buf; pj_int32_t adj = cport->tx_adj_level; for (j=0; j<conf->samples_per_frame; ++j) { pj_int32_t itemp; /* For the level adjustment, we need to store the sample to * a temporary 32bit integer value to avoid overflowing the * 16bit sample storage. */ itemp = input[j]; /*itemp = itemp * adj / NORMAL_LEVEL; */ itemp = (itemp * adj) >> 7; /* Clip the signal if it's too loud */ if (itemp > 32767) itemp = 32767; else if (itemp < -32768) itemp = -32768; input[j] = (pj_int16_t) itemp; } } } /* If there are sources in the mix buffer, convert the mixed samples * to the mixed samples itself. This is possible because mixed sample * is 32bit. * * In addition to this process, if we need to change the level of * TX signal, we adjust is here too. */ else if (cport->tx_adj_level != NORMAL_LEVEL && cport->src_level) { pj_int32_t adj_level = cport->tx_adj_level; /* We need to adjust signal level. */ for (j=0; j<conf->samples_per_frame; ++j) { pj_int32_t itemp;
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?