提交 c70f4a20 authored 作者: Anthony Minessale's avatar Anthony Minessale

nut 'n honey

git-svn-id: http://svn.freeswitch.org/svn/freeswitch/trunk@16110 d0543943-73ff-0310-b7d9-9358b9ac24b2
上级 49b8cfa1
......@@ -175,7 +175,8 @@ typedef enum {
CFLAG_ANSWERED = (1 << 5),
CFLAG_BRIDGE_TO = (1 << 6),
CFLAG_WAIT_MOD = (1 << 7),
CFLAG_VID_FLOOR = (1 << 8)
CFLAG_VID_FLOOR = (1 << 8),
CFLAG_WASTE_BANDWIDTH = (1 << 9)
} conf_flag_t;
typedef enum {
......@@ -297,6 +298,7 @@ typedef struct conference_obj {
uint32_t eflags;
uint32_t verbose_events;
int end_count;
uint32_t relationship_total;
} conference_obj_t;
/* Relationship with another member */
......@@ -571,7 +573,11 @@ static conference_relationship_t *member_add_relationship(conference_member_t *m
rel->id = id;
lock_member(member);
switch_mutex_lock(member->conference->member_mutex);
member->conference->relationship_total++;
switch_mutex_unlock(member->conference->member_mutex);
rel->next = member->relationships;
member->relationships = rel;
unlock_member(member);
......@@ -599,6 +605,11 @@ static switch_status_t member_del_relationship(conference_member_t *member, uint
} else {
member->relationships = rel->next;
}
switch_mutex_lock(member->conference->member_mutex);
member->conference->relationship_total--;
switch_mutex_unlock(member->conference->member_mutex);
}
last = rel;
}
......@@ -970,6 +981,9 @@ static void *SWITCH_THREAD_FUNC conference_thread_run(switch_thread_t *thread, v
switch_event_t *event;
uint8_t *file_frame;
uint8_t *async_file_frame;
int16_t *bptr;
int x;
int32_t z = 0;
file_frame = switch_core_alloc(conference->pool, SWITCH_RECOMMENDED_BUFFER_SIZE);
async_file_frame = switch_core_alloc(conference->pool, SWITCH_RECOMMENDED_BUFFER_SIZE);
......@@ -1111,7 +1125,7 @@ static void *SWITCH_THREAD_FUNC conference_thread_run(switch_thread_t *thread, v
for (x = 0; x < file_sample_len; x++) {
int32_t z;
int16_t *bptr, *muxed;
int16_t *muxed;
muxed = (int16_t *) file_frame;
bptr = (int16_t *) async_file_frame;
......@@ -1127,99 +1141,183 @@ static void *SWITCH_THREAD_FUNC conference_thread_run(switch_thread_t *thread, v
}
}
if (ready || has_file_data) {
/* Build a muxed frame for every member that contains the mixed audio of everyone else */
if (switch_test_flag(conference, CFLAG_WASTE_BANDWIDTH) && !has_file_data) {
file_sample_len = bytes / 2;
if (conference->comfort_noise_level) {
switch_generate_sln_silence((int16_t *) file_frame, file_sample_len, conference->comfort_noise_level);
} else {
memset(file_frame, 255, bytes);
}
has_file_data = 1;
}
if (!conference->relationship_total) {
/* If there are no relationships meaning (user x can specificly not speal to and/or hear user y), use a more efficient muxing technique. */
if (ready || has_file_data) {
/* Use more bits in the main_frame to preserve the exact sum of the audio samples. */
int main_frame[SWITCH_RECOMMENDED_BUFFER_SIZE / 2] = { 0 };
int16_t write_frame[SWITCH_RECOMMENDED_BUFFER_SIZE / 2] = { 0 };
for (omember = conference->members; omember; omember = omember->next) {
/* Init the main frame with file data if there is any. */
bptr = (int16_t *) file_frame;
if (has_file_data && file_sample_len) {
uint32_t sample_bytes = file_sample_len * 2;
memcpy(omember->mux_frame, file_frame, sample_bytes);
if (sample_bytes < bytes) {
if (conference->comfort_noise_level) {
switch_generate_sln_silence((int16_t *) omember->mux_frame + sample_bytes,
(bytes - sample_bytes) / 2, conference->comfort_noise_level);
for (x = 0; x < bytes / 2; x++) {
if (x <= file_sample_len) {
main_frame[x] = (int32_t) bptr[x];
} else {
memset(omember->mux_frame + sample_bytes, 255, bytes - sample_bytes);
main_frame[x] = 255;
}
}
} else {
if (conference->comfort_noise_level) {
switch_generate_sln_silence((int16_t *) omember->mux_frame, bytes / 2, conference->comfort_noise_level);
} else {
memset(omember->mux_frame, 255, bytes);
}
/* Copy audio from every member known to be producing audio into the main frame. */
for (omember = conference->members; omember; omember = omember->next) {
if (!(switch_test_flag(omember, MFLAG_RUNNING) && switch_test_flag(omember, MFLAG_HAS_AUDIO))) {
continue;
}
bptr = (int16_t *) omember->frame;
for (x = 0; x < omember->read / 2; x++) {
main_frame[x] += (int32_t) bptr[x];
}
}
for (imember = conference->members; imember; imember = imember->next) {
uint32_t x;
int16_t *bptr, *muxed;
if (imember == omember || !imember->read) {
/* Don't add audio from yourself or if you didn't read any */
/* Create write frame once per member who is not deaf for each sample in the main frame
check if our audio is involved and if so, subtract it from the sample so we don't hear ourselves.
Since main frame was 32 bit int, we did not lose any detail, now that we have to convert to 16 bit we can
cut it off at the min and max range if need be and write the frame to the output buffer.
*/
for (omember = conference->members; omember; omember = omember->next) {
switch_size_t ok = 1;
if (!switch_test_flag(omember, MFLAG_RUNNING)) {
continue;
}
/* If they are not supposed to talk to us then don't let them */
if (omember->relationships) {
conference_relationship_t *rel;
if (!switch_test_flag(omember, MFLAG_CAN_HEAR) && !switch_test_flag(omember, MFLAG_WASTE_BANDWIDTH)
&& !switch_test_flag(conference, CFLAG_WASTE_BANDWIDTH)) {
continue;
}
bptr = (int16_t *) omember->frame;
for (x = 0; x < bytes / 2; x++) {
z = main_frame[x];
/* bptr[x] represents my own contribution to this audio sample */
if (switch_test_flag(omember, MFLAG_HAS_AUDIO) && x <= omember->read / 2) {
z -= (int32_t) bptr[x];
}
/* Now we can convert to 16 bit.*/
switch_normalize_to_16bit(z);
write_frame[x] = (int16_t) z;
}
switch_mutex_lock(omember->audio_out_mutex);
ok = switch_buffer_write(omember->mux_buffer, write_frame, bytes);
switch_mutex_unlock(omember->audio_out_mutex);
if (!ok) {
goto end;
}
}
if ((rel = member_get_relationship(omember, imember))) {
if (!switch_test_flag(rel, RFLAG_CAN_HEAR)) {
continue;
}
} else {
if (ready || has_file_data) {
/* Build a muxed frame for every member that contains the mixed audio of everyone else */
for (omember = conference->members; omember; omember = omember->next) {
if (has_file_data && file_sample_len) {
uint32_t sample_bytes = file_sample_len * 2;
memcpy(omember->mux_frame, file_frame, sample_bytes);
if (sample_bytes < bytes) {
if (conference->comfort_noise_level) {
switch_generate_sln_silence((int16_t *) omember->mux_frame + sample_bytes,
(bytes - sample_bytes) / 2, conference->comfort_noise_level);
} else {
memset(omember->mux_frame + sample_bytes, 255, bytes - sample_bytes);
}
}
} else {
if (conference->comfort_noise_level) {
switch_generate_sln_silence((int16_t *) omember->mux_frame, bytes / 2, conference->comfort_noise_level);
} else {
memset(omember->mux_frame, 255, bytes);
}
}
for (imember = conference->members; imember; imember = imember->next) {
uint32_t x;
int16_t *muxed;
if (imember == omember || !imember->read) {
/* Don't add audio from yourself or if you didn't read any */
continue;
}
/* If we are not supposed to hear them then don't let it happen */
if (imember->relationships) {
conference_relationship_t *rel;
/* If they are not supposed to talk to us then don't let them */
if (omember->relationships) {
conference_relationship_t *rel;
if ((rel = member_get_relationship(imember, omember))) {
if (!switch_test_flag(rel, RFLAG_CAN_SPEAK)) {
continue;
if ((rel = member_get_relationship(omember, imember))) {
if (!switch_test_flag(rel, RFLAG_CAN_HEAR)) {
continue;
}
}
}
/* If we are not supposed to hear them then don't let it happen */
if (imember->relationships) {
conference_relationship_t *rel;
if ((rel = member_get_relationship(imember, omember))) {
if (!switch_test_flag(rel, RFLAG_CAN_SPEAK)) {
continue;
}
}
}
}
#if 0
if (nt && conference->not_talking_buf_len && !switch_test_flag(omember, MFLAG_HAS_AUDIO)) {
memcpy(omember->mux_frame, conference->not_talking_buf, conference->not_talking_buf_len);
continue;
}
if (nt && conference->not_talking_buf_len && !switch_test_flag(omember, MFLAG_HAS_AUDIO)) {
memcpy(omember->mux_frame, conference->not_talking_buf, conference->not_talking_buf_len);
continue;
}
#endif
bptr = (int16_t *) imember->frame;
muxed = (int16_t *) omember->mux_frame;
bptr = (int16_t *) imember->frame;
muxed = (int16_t *) omember->mux_frame;
for (x = 0; x < imember->read / 2; x++) {
int32_t z = muxed[x] + bptr[x];
switch_normalize_to_16bit(z);
muxed[x] = (int16_t) z;
}
for (x = 0; x < imember->read / 2; x++) {
int32_t z = muxed[x] + bptr[x];
switch_normalize_to_16bit(z);
muxed[x] = (int16_t) z;
}
#if 0
if (total - ready > 1) {
conference->not_talking_buf_len = imember->read;
if (!conference->not_talking_buf) {
conference->not_talking_buf = switch_core_alloc(conference->pool, imember->read + 128);
if (total - ready > 1) {
conference->not_talking_buf_len = imember->read;
if (!conference->not_talking_buf) {
conference->not_talking_buf = switch_core_alloc(conference->pool, imember->read + 128);
}
memcpy(conference->not_talking_buf, muxed, conference->not_talking_buf_len);
nt++;
}
memcpy(conference->not_talking_buf, muxed, conference->not_talking_buf_len);
nt++;
}
#endif
}
}
}
if (bytes) {
/* Go back and write each member his dedicated copy of the audio frame that does not contain his own audio. */
for (imember = conference->members; imember; imember = imember->next) {
if (switch_test_flag(imember, MFLAG_RUNNING)) {
switch_size_t ok = 1;
switch_mutex_lock(imember->audio_out_mutex);
ok = switch_buffer_write(imember->mux_buffer, imember->mux_frame, bytes);
switch_mutex_unlock(imember->audio_out_mutex);
if (!ok) {
goto end;
if (bytes) {
/* Go back and write each member his dedicated copy of the audio frame that does not contain his own audio. */
for (imember = conference->members; imember; imember = imember->next) {
if (switch_test_flag(imember, MFLAG_RUNNING)) {
switch_size_t ok = 1;
switch_mutex_lock(imember->audio_out_mutex);
ok = switch_buffer_write(imember->mux_buffer, imember->mux_frame, bytes);
switch_mutex_unlock(imember->audio_out_mutex);
if (!ok) {
goto end;
}
}
}
}
}
}
if (conference->async_fnode && conference->async_fnode->done) {
switch_memory_pool_t *pool;
switch_core_file_close(&conference->async_fnode->fh);
......@@ -2367,7 +2465,7 @@ static void conference_loop_output(conference_member_t *member)
}
switch_mutex_unlock(member->audio_out_mutex);
} else {
} else if (!switch_test_flag(member->conference, CFLAG_WASTE_BANDWIDTH)) {
if (switch_test_flag(member, MFLAG_WASTE_BANDWIDTH)) {
if (member->conference->comfort_noise_level) {
switch_generate_sln_silence(write_frame.data, samples, member->conference->comfort_noise_level);
......@@ -4800,6 +4898,8 @@ static void set_cflags(const char *flags, uint32_t *f)
*f |= CFLAG_WAIT_MOD;
} else if (!strcasecmp(argv[i], "video-floor-only")) {
*f |= CFLAG_VID_FLOOR;
} else if (!strcasecmp(argv[i], "waste-bandwidth")) {
*f |= CFLAG_WASTE_BANDWIDTH;
}
}
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论