diff --git a/src/include/switch_types.h b/src/include/switch_types.h index 9dfe04b5eb..338b4c4956 100644 --- a/src/include/switch_types.h +++ b/src/include/switch_types.h @@ -1013,6 +1013,7 @@ typedef enum { SWITCH_MESSAGE_ANSWER_EVENT, SWITCH_MESSAGE_PROGRESS_EVENT, SWITCH_MESSAGE_RING_EVENT, + SWITCH_MESSAGE_RESAMPLE_EVENT, SWITCH_MESSAGE_INVALID } switch_core_session_message_types_t; @@ -1407,6 +1408,7 @@ typedef enum { CF_VIDEO_PAUSE, CF_BYPASS_MEDIA_AFTER_HOLD, CF_HANGUP_HELD, + CF_CONFERENCE_RESET_MEDIA, /* WARNING: DO NOT ADD ANY FLAGS BELOW THIS LINE */ /* IF YOU ADD NEW ONES CHECK IF THEY SHOULD PERSIST OR ZERO THEM IN switch_core_session.c switch_core_session_request_xml() */ CF_FLAG_MAX diff --git a/src/mod/applications/mod_conference/mod_conference.c b/src/mod/applications/mod_conference/mod_conference.c index 9c6c2419d9..4e67b99041 100644 --- a/src/mod/applications/mod_conference/mod_conference.c +++ b/src/mod/applications/mod_conference/mod_conference.c @@ -485,6 +485,7 @@ struct conference_member { switch_thread_t *input_thread; cJSON *json; cJSON *status_field; + uint8_t loop_loop; }; typedef enum { @@ -3659,7 +3660,7 @@ static void *SWITCH_THREAD_FUNC conference_loop_input(switch_thread_t *thread, v switch_frame_t *read_frame = NULL; uint32_t hangover = 40, hangunder = 5, hangover_hits = 0, hangunder_hits = 0, diff_level = 400; switch_core_session_t *session = member->session; - uint32_t flush_len; + uint32_t flush_len, loops = 0; if (switch_core_session_read_lock(session) != SWITCH_STATUS_SUCCESS) { goto end; @@ -3922,6 +3923,18 @@ static void *SWITCH_THREAD_FUNC conference_loop_input(switch_thread_t *thread, v member->last_score = member->score; } + if (switch_channel_test_flag(member->channel, CF_CONFERENCE_RESET_MEDIA)) { + switch_channel_clear_flag(member->channel, CF_CONFERENCE_RESET_MEDIA); + if (++loops > 500) { + member->loop_loop = 1; + + if (setup_media(member, member->conference)) { + break; + } + } + + } + /* skip frames that are not actual media or when we are muted or silent */ if ((switch_test_flag(member, MFLAG_TALKING) || member->energy_level == 0 || switch_test_flag(member->conference, CFLAG_AUDIO_ALWAYS)) && switch_test_flag(member, MFLAG_CAN_SPEAK) && !switch_test_flag(member->conference, CFLAG_WAIT_MOD) @@ -4072,7 +4085,7 @@ static void launch_conference_loop_input(conference_member_t *member, switch_mem { switch_threadattr_t *thd_attr = NULL; - if (member == NULL) + if (member == NULL || member->input_thread) return; switch_threadattr_create(&thd_attr, pool); @@ -4116,7 +4129,7 @@ static void conference_loop_output(conference_member_t *member) call_list = NULL; cp = NULL; - + member->loop_loop = 0; switch_assert(member->conference != NULL); @@ -4229,7 +4242,7 @@ static void conference_loop_output(conference_member_t *member) /* Fair WARNING, If you expect the caller to hear anything or for digit handling to be processed, */ /* you better not block this thread loop for more than the duration of member->conference->timer_name! */ - while (switch_test_flag(member, MFLAG_RUNNING) && switch_test_flag(member, MFLAG_ITHREAD) + while (!member->loop_loop && switch_test_flag(member, MFLAG_RUNNING) && switch_test_flag(member, MFLAG_ITHREAD) && switch_channel_ready(channel)) { switch_event_t *event; int use_timer = 0; @@ -4429,15 +4442,21 @@ static void conference_loop_output(conference_member_t *member) end: - switch_clear_flag_locked(member, MFLAG_RUNNING); + if (!member->loop_loop) { + switch_clear_flag_locked(member, MFLAG_RUNNING); - /* Wait for the input thread to end */ - if (member->input_thread) { - switch_thread_join(&st, member->input_thread); + /* Wait for the input thread to end */ + if (member->input_thread) { + switch_thread_join(&st, member->input_thread); + } } switch_core_timer_destroy(&timer); + if (member->loop_loop) { + return; + } + switch_log_printf(SWITCH_CHANNEL_CHANNEL_LOG(channel), SWITCH_LOG_DEBUG, "Channel leaving conference, cause: %s\n", switch_channel_cause2str(switch_channel_get_cause(channel))); @@ -8006,10 +8025,14 @@ static int setup_media(conference_member_t *member, conference_obj_t *conference switch_codec_implementation_t read_impl = { 0 }; switch_core_session_get_read_impl(member->session, &read_impl); - switch_core_session_reset(member->session, SWITCH_TRUE, SWITCH_FALSE); - if (switch_core_codec_ready(&member->read_codec)) { switch_core_codec_destroy(&member->read_codec); + memset(&member->read_codec, 0, sizeof(&member->read_codec)); + } + + if (switch_core_codec_ready(&member->write_codec)) { + switch_core_codec_destroy(&member->write_codec); + memset(&member->write_codec, 0, sizeof(&member->write_codec)); } if (member->read_resampler) { @@ -8640,7 +8663,10 @@ SWITCH_STANDARD_APP(conference_function) switch_core_session_receive_message(session, &msg); /* Run the conference loop */ - conference_loop_output(&member); + do { + conference_loop_output(&member); + } while (member.loop_loop); + switch_channel_set_private(channel, "_conference_autocall_list_", NULL); /* Tell the channel we are no longer going to be in a bridge */ diff --git a/src/switch_core_io.c b/src/switch_core_io.c index c290d9175f..4c7b7fd8b8 100644 --- a/src/switch_core_io.c +++ b/src/switch_core_io.c @@ -599,6 +599,7 @@ SWITCH_DECLARE(switch_status_t) switch_core_session_read_frame(switch_core_sessi case SWITCH_STATUS_RESAMPLE: if (!session->read_resampler) { switch_mutex_lock(session->resample_mutex); + status = switch_resample_create(&session->read_resampler, read_frame->codec->implementation->actual_samples_per_second, session->read_impl.actual_samples_per_second, @@ -610,6 +611,13 @@ SWITCH_DECLARE(switch_status_t) switch_core_session_read_frame(switch_core_sessi switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Unable to allocate resampler\n"); status = SWITCH_STATUS_FALSE; goto done; + } else { + switch_core_session_message_t msg = { 0 }; + msg.numeric_arg = 1; + msg.message_id = SWITCH_MESSAGE_RESAMPLE_EVENT; + switch_core_session_receive_message(session, &msg); + + switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_NOTICE, "Activating read resampler\n"); } } case SWITCH_STATUS_SUCCESS: @@ -636,6 +644,14 @@ SWITCH_DECLARE(switch_status_t) switch_core_session_read_frame(switch_core_sessi switch_resample_destroy(&session->read_resampler); switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_NOTICE, "Deactivating read resampler\n"); switch_mutex_unlock(session->resample_mutex); + + { + switch_core_session_message_t msg = { 0 }; + msg.numeric_arg = 0; + msg.message_id = SWITCH_MESSAGE_RESAMPLE_EVENT; + switch_core_session_receive_message(session, &msg); + } + } status = SWITCH_STATUS_SUCCESS; @@ -1199,6 +1215,13 @@ SWITCH_DECLARE(switch_status_t) switch_core_session_write_frame(switch_core_sess switch_mutex_unlock(session->resample_mutex); if (status != SWITCH_STATUS_SUCCESS) { goto done; + } else { + switch_core_session_message_t msg = { 0 }; + msg.numeric_arg = 1; + msg.message_id = SWITCH_MESSAGE_RESAMPLE_EVENT; + switch_core_session_receive_message(session, &msg); + + switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_NOTICE, "Activating write resampler\n"); } } break; @@ -1226,6 +1249,14 @@ SWITCH_DECLARE(switch_status_t) switch_core_session_write_frame(switch_core_sess switch_resample_destroy(&session->write_resampler); switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_NOTICE, "Deactivating write resampler\n"); switch_mutex_unlock(session->resample_mutex); + + { + switch_core_session_message_t msg = { 0 }; + msg.numeric_arg = 0; + msg.message_id = SWITCH_MESSAGE_RESAMPLE_EVENT; + switch_core_session_receive_message(session, &msg); + } + } write_frame = frame; status = SWITCH_STATUS_SUCCESS; @@ -1497,6 +1528,14 @@ SWITCH_DECLARE(switch_status_t) switch_core_session_write_frame(switch_core_sess if (status != SWITCH_STATUS_SUCCESS) { goto done; + } else { + switch_core_session_message_t msg = { 0 }; + msg.numeric_arg = 1; + msg.message_id = SWITCH_MESSAGE_RESAMPLE_EVENT; + switch_core_session_receive_message(session, &msg); + + + switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_NOTICE, "Activating write resampler\n"); } } break; @@ -1511,12 +1550,23 @@ SWITCH_DECLARE(switch_status_t) switch_core_session_write_frame(switch_core_sess break; case SWITCH_STATUS_NOOP: if (session->write_resampler) { + switch_core_session_message_t msg = { 0 }; + int ok = 0; + switch_mutex_lock(session->resample_mutex); - if (session->write_resampler) { + if (session->write_resampler) { switch_resample_destroy(&session->write_resampler); switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_NOTICE, "Deactivating write resampler\n"); + ok = 1; } switch_mutex_unlock(session->resample_mutex); + + if (ok) { + msg.numeric_arg = 0; + msg.message_id = SWITCH_MESSAGE_RESAMPLE_EVENT; + switch_core_session_receive_message(session, &msg); + } + } enc_frame->codec = session->write_codec; enc_frame->samples = enc_frame->datalen / sizeof(int16_t); diff --git a/src/switch_core_media.c b/src/switch_core_media.c index db6d6497af..0b8b66747c 100644 --- a/src/switch_core_media.c +++ b/src/switch_core_media.c @@ -7479,6 +7479,14 @@ SWITCH_DECLARE(switch_status_t) switch_core_media_receive_message(switch_core_se switch (msg->message_id) { + case SWITCH_MESSAGE_RESAMPLE_EVENT: + { + if (switch_channel_test_flag(session->channel, CF_CONFERENCE)) { + switch_channel_set_flag(session->channel, CF_CONFERENCE_RESET_MEDIA); + } + } + break; + case SWITCH_MESSAGE_INDICATE_VIDEO_REFRESH_REQ: { if (v_engine->rtp_session) { diff --git a/src/switch_core_session.c b/src/switch_core_session.c index 028f745457..03b57fd788 100644 --- a/src/switch_core_session.c +++ b/src/switch_core_session.c @@ -754,6 +754,7 @@ static const char *message_names[] = { "ANSWER_EVENT", "PROGRESS_EVENT", "RING_EVENT", + "RESAMPLE_EVENT", "INVALID" };