Adjust core and add video caps to mod_conference with video follow audio (first cut)
git-svn-id: http://svn.freeswitch.org/svn/freeswitch/trunk@10314 d0543943-73ff-0310-b7d9-9358b9ac24b2
This commit is contained in:
parent
44093523f7
commit
49f353b74e
|
@ -1678,8 +1678,8 @@ SWITCH_DECLARE(uint32_t) switch_core_max_dtmf_duration(uint32_t duration);
|
|||
SWITCH_DECLARE(uint32_t) switch_core_default_dtmf_duration(uint32_t duration);
|
||||
SWITCH_DECLARE(switch_status_t) switch_console_set_complete(const char *string);
|
||||
SWITCH_DECLARE(switch_status_t) switch_console_set_alias(const char *string);
|
||||
|
||||
SWITCH_DECLARE(int) switch_system(const char *cmd, switch_bool_t wait);
|
||||
SWITCH_DECLARE(void) switch_cond_yield(uint32_t ms);
|
||||
|
||||
///\}
|
||||
|
||||
|
|
|
@ -110,6 +110,8 @@ SWITCH_DECLARE(switch_port_t) switch_rtp_set_end_port(switch_port_t port);
|
|||
*/
|
||||
SWITCH_DECLARE(switch_port_t) switch_rtp_request_port(const char *ip);
|
||||
SWITCH_DECLARE(void) switch_rtp_release_port(const char *ip, switch_port_t port);
|
||||
|
||||
SWITCH_DECLARE(void) switch_rtp_change_interval(switch_rtp_t *rtp_session, uint32_t ms_per_packet, uint32_t samples_per_interval);
|
||||
/*!
|
||||
\brief create a new RTP session handle
|
||||
\param new_rtp_session a poiter to aim at the new session
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -686,6 +686,38 @@ static switch_status_t sofia_read_frame(switch_core_session_t *session, switch_f
|
|||
*frame = NULL;
|
||||
return SWITCH_STATUS_GENERR;
|
||||
}
|
||||
|
||||
|
||||
if (tech_pvt->check_frames < 50) {
|
||||
if (tech_pvt->last_ts && tech_pvt->read_frame.datalen != tech_pvt->read_codec.implementation->encoded_bytes_per_packet) {
|
||||
switch_size_t codec_ms = (int)(tech_pvt->read_frame.timestamp -
|
||||
tech_pvt->last_ts) / (tech_pvt->read_codec.implementation->samples_per_second / 1000);
|
||||
|
||||
if ((codec_ms % 10) != 0) {
|
||||
tech_pvt->check_frames = 50;
|
||||
} else {
|
||||
if (switch_rtp_ready(tech_pvt->rtp_session) && codec_ms != tech_pvt->codec_ms) {
|
||||
tech_pvt->codec_ms = codec_ms;
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Changing codec ptime to %d\n", tech_pvt->codec_ms);
|
||||
switch_core_codec_destroy(&tech_pvt->read_codec);
|
||||
switch_core_codec_destroy(&tech_pvt->write_codec);
|
||||
if (sofia_glue_tech_set_codec(tech_pvt, 2) != SWITCH_STATUS_SUCCESS) {
|
||||
*frame = NULL;
|
||||
return SWITCH_STATUS_GENERR;
|
||||
}
|
||||
|
||||
switch_rtp_change_interval(tech_pvt->rtp_session,
|
||||
tech_pvt->read_codec.implementation->samples_per_packet,
|
||||
tech_pvt->codec_ms * 1000);
|
||||
}
|
||||
|
||||
}
|
||||
tech_pvt->check_frames++;
|
||||
tech_pvt->last_ts = tech_pvt->read_frame.timestamp;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if ((bytes = tech_pvt->read_codec.implementation->encoded_bytes_per_packet)) {
|
||||
frames = (tech_pvt->read_frame.datalen / bytes);
|
||||
}
|
||||
|
|
|
@ -505,6 +505,8 @@ struct private_object {
|
|||
int got_bye;
|
||||
int hold_laps;
|
||||
switch_thread_id_t locker;
|
||||
switch_size_t last_ts;
|
||||
uint32_t check_frames;
|
||||
};
|
||||
|
||||
struct callback_t {
|
||||
|
@ -708,3 +710,4 @@ void sofia_reg_send_reboot(sofia_profile_t *profile, const char *user, const cha
|
|||
void sofia_glue_restart_all_profiles(void);
|
||||
void sofia_glue_toggle_hold(private_object_t *tech_pvt, int sendonly);
|
||||
const char * sofia_state_string(int state);
|
||||
switch_status_t sofia_glue_tech_set_codec(private_object_t *tech_pvt, int force);
|
||||
|
|
|
@ -182,6 +182,7 @@ void sofia_glue_set_local_sdp(private_object_t *tech_pvt, const char *ip, uint32
|
|||
} else {
|
||||
switch_snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), "a=silenceSupp:off - - - -\n");
|
||||
}
|
||||
|
||||
if (ptime) {
|
||||
switch_snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), "a=ptime:%d\n", ptime);
|
||||
}
|
||||
|
@ -1535,7 +1536,7 @@ switch_status_t sofia_glue_tech_set_codec(private_object_t *tech_pvt, int force)
|
|||
return SWITCH_STATUS_SUCCESS;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (switch_core_codec_init(&tech_pvt->read_codec,
|
||||
tech_pvt->iananame,
|
||||
tech_pvt->rm_fmtp,
|
||||
|
@ -1576,8 +1577,11 @@ switch_status_t sofia_glue_tech_set_codec(private_object_t *tech_pvt, int force)
|
|||
tech_pvt->write_codec.agreed_pt = tech_pvt->agreed_pt;
|
||||
tech_pvt->read_codec.agreed_pt = tech_pvt->agreed_pt;
|
||||
|
||||
switch_core_session_set_read_codec(tech_pvt->session, &tech_pvt->read_codec);
|
||||
switch_core_session_set_write_codec(tech_pvt->session, &tech_pvt->write_codec);
|
||||
if (force != 2) {
|
||||
switch_core_session_set_read_codec(tech_pvt->session, &tech_pvt->read_codec);
|
||||
switch_core_session_set_write_codec(tech_pvt->session, &tech_pvt->write_codec);
|
||||
}
|
||||
|
||||
tech_pvt->fmtp_out = switch_core_session_strdup(tech_pvt->session, tech_pvt->write_codec.fmtp_out);
|
||||
|
||||
if (switch_rtp_ready(tech_pvt->rtp_session)) {
|
||||
|
|
|
@ -754,6 +754,22 @@ SWITCH_DECLARE(switch_status_t) switch_rtp_add_crypto_key(switch_rtp_t *rtp_sess
|
|||
return SWITCH_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
SWITCH_DECLARE(void) switch_rtp_change_interval(switch_rtp_t *rtp_session, uint32_t ms_per_packet, uint32_t samples_per_interval)
|
||||
{
|
||||
rtp_session->ms_per_packet = ms_per_packet;
|
||||
rtp_session->samples_per_interval = rtp_session->conf_samples_per_interval = samples_per_interval;
|
||||
|
||||
if (rtp_session->timer_name) {
|
||||
if (rtp_session->timer.timer_interface) {
|
||||
switch_core_timer_destroy(&rtp_session->timer);
|
||||
}
|
||||
switch_core_timer_init(&rtp_session->timer, rtp_session->timer_name, ms_per_packet / 1000, samples_per_interval, rtp_session->pool);
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG,
|
||||
"RE-Starting timer [%s] %d bytes per %dms\n", rtp_session->timer_name, samples_per_interval, ms_per_packet);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
SWITCH_DECLARE(switch_status_t) switch_rtp_create(switch_rtp_t **new_rtp_session,
|
||||
switch_payload_t payload,
|
||||
uint32_t samples_per_interval,
|
||||
|
@ -816,14 +832,14 @@ SWITCH_DECLARE(switch_status_t) switch_rtp_create(switch_rtp_t **new_rtp_session
|
|||
rtp_session->ms_per_packet = ms_per_packet;
|
||||
rtp_session->samples_per_interval = rtp_session->conf_samples_per_interval = samples_per_interval;
|
||||
|
||||
if (timer_name && !strcasecmp(timer_name, "none")) {
|
||||
timer_name = NULL;
|
||||
}
|
||||
|
||||
if (switch_test_flag(rtp_session, SWITCH_RTP_FLAG_USE_TIMER) && switch_strlen_zero(timer_name)) {
|
||||
timer_name = "soft";
|
||||
}
|
||||
|
||||
if (!switch_strlen_zero(timer_name) && !strcasecmp(timer_name, "none")) {
|
||||
timer_name = NULL;
|
||||
}
|
||||
|
||||
if (!switch_strlen_zero(timer_name)) {
|
||||
rtp_session->timer_name = switch_core_strdup(pool, timer_name);
|
||||
switch_set_flag_locked(rtp_session, SWITCH_RTP_FLAG_USE_TIMER);
|
||||
|
@ -838,6 +854,7 @@ SWITCH_DECLARE(switch_status_t) switch_rtp_create(switch_rtp_t **new_rtp_session
|
|||
switch_clear_flag_locked(rtp_session, SWITCH_RTP_FLAG_USE_TIMER);
|
||||
}
|
||||
} else {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Not using a timer\n");
|
||||
switch_clear_flag_locked(rtp_session, SWITCH_RTP_FLAG_USE_TIMER);
|
||||
switch_clear_flag_locked(rtp_session, SWITCH_RTP_FLAG_NOBLOCK);
|
||||
}
|
||||
|
@ -1260,6 +1277,10 @@ static int rtp_common_read(switch_rtp_t *rtp_session, switch_payload_t *payload_
|
|||
while (switch_rtp_ready(rtp_session)) {
|
||||
int do_cng = 0;
|
||||
|
||||
if (rtp_session->timer.interval) {
|
||||
switch_core_timer_next(&rtp_session->timer);
|
||||
}
|
||||
|
||||
bytes = sizeof(rtp_msg_t);
|
||||
status = switch_socket_recvfrom(rtp_session->from_addr, rtp_session->sock_input, 0, (void *) &rtp_session->recv_msg, &bytes);
|
||||
|
||||
|
@ -1268,6 +1289,8 @@ static int rtp_common_read(switch_rtp_t *rtp_session, switch_payload_t *payload_
|
|||
goto end;
|
||||
}
|
||||
|
||||
check = !bytes;
|
||||
|
||||
if (switch_test_flag(rtp_session, SWITCH_RTP_FLAG_BREAK)) {
|
||||
switch_clear_flag_locked(rtp_session, SWITCH_RTP_FLAG_BREAK);
|
||||
do_2833(rtp_session);
|
||||
|
@ -1319,36 +1342,22 @@ static int rtp_common_read(switch_rtp_t *rtp_session, switch_payload_t *payload_
|
|||
rtp_session->missed_count = 0;
|
||||
|
||||
if (rtp_session->recv_msg.header.pt && (rtp_session->recv_msg.header.pt == rtp_session->cng_pt || rtp_session->recv_msg.header.pt == 13)) {
|
||||
if (++rtp_session->cng_count == 1) {
|
||||
return_cng_frame();
|
||||
}
|
||||
continue;
|
||||
} else {
|
||||
rtp_session->cng_count = 0;
|
||||
}
|
||||
return_cng_frame();
|
||||
}
|
||||
}
|
||||
|
||||
if (!bytes && (io_flags & SWITCH_IO_FLAG_NOBLOCK)) {
|
||||
return_cng_frame();
|
||||
}
|
||||
|
||||
|
||||
if (rtp_session->timer.interval) {
|
||||
check = (uint8_t) (switch_core_timer_check(&rtp_session->timer, SWITCH_TRUE) == SWITCH_STATUS_SUCCESS);
|
||||
if (bytes) {
|
||||
switch_core_timer_sync(&rtp_session->timer);
|
||||
} else {
|
||||
if (check && switch_test_flag(rtp_session, SWITCH_RTP_FLAG_AUTO_CNG) &&
|
||||
rtp_session->timer.samplecount >= (rtp_session->last_write_samplecount + (rtp_session->samples_per_interval * 50))) {
|
||||
uint8_t data[10] = { 0 };
|
||||
switch_frame_flag_t frame_flags = SFF_NONE;
|
||||
data[0] = 65;
|
||||
rtp_session->cn++;
|
||||
rtp_common_write(rtp_session, NULL, (void *) data, 2, rtp_session->cng_pt, 0, &frame_flags);
|
||||
}
|
||||
}
|
||||
} else if (bytes) {
|
||||
check++;
|
||||
|
||||
if (check && switch_test_flag(rtp_session, SWITCH_RTP_FLAG_AUTO_CNG) &&
|
||||
rtp_session->timer.samplecount >= (rtp_session->last_write_samplecount + (rtp_session->samples_per_interval * 50))) {
|
||||
uint8_t data[10] = { 0 };
|
||||
switch_frame_flag_t frame_flags = SFF_NONE;
|
||||
data[0] = 65;
|
||||
rtp_session->cn++;
|
||||
rtp_common_write(rtp_session, NULL, (void *) data, 2, rtp_session->cng_pt, 0, &frame_flags);
|
||||
}
|
||||
|
||||
if (check || bytes) {
|
||||
|
@ -1527,8 +1536,6 @@ static int rtp_common_read(switch_rtp_t *rtp_session, switch_payload_t *payload_
|
|||
bytes = jb_frame->dlen + rtp_header_len;
|
||||
rtp_session->recv_msg.header.ts = htonl(jb_frame->ts);
|
||||
} else if (!bytes && switch_test_flag(rtp_session, SWITCH_RTP_FLAG_USE_TIMER)) { /* We're late! We're Late! */
|
||||
|
||||
|
||||
if (!switch_test_flag(rtp_session, SWITCH_RTP_FLAG_NOBLOCK) && status == SWITCH_STATUS_BREAK) {
|
||||
switch_yield(1000);
|
||||
continue;
|
||||
|
@ -1556,7 +1563,9 @@ static int rtp_common_read(switch_rtp_t *rtp_session, switch_payload_t *payload_
|
|||
|
||||
do_continue:
|
||||
|
||||
switch_yield(sleep_mss);
|
||||
if (!bytes && !rtp_session->timer.interval) {
|
||||
switch_yield(sleep_mss);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
|
|
@ -46,6 +46,7 @@ static switch_memory_pool_t *module_pool = NULL;
|
|||
static struct {
|
||||
int32_t RUNNING;
|
||||
int32_t STARTED;
|
||||
int32_t use_cond_yield;
|
||||
switch_mutex_t *mutex;
|
||||
} globals;
|
||||
|
||||
|
@ -76,6 +77,8 @@ struct timer_matrix {
|
|||
switch_size_t tick;
|
||||
uint32_t count;
|
||||
uint32_t roll;
|
||||
switch_mutex_t *mutex;
|
||||
switch_thread_cond_t *cond;
|
||||
};
|
||||
typedef struct timer_matrix timer_matrix_t;
|
||||
|
||||
|
@ -103,6 +106,25 @@ static int MONO = 0;
|
|||
#endif
|
||||
|
||||
|
||||
static void do_yield(switch_interval_time_t t)
|
||||
{
|
||||
#if defined(HAVE_CLOCK_NANOSLEEP) && defined(SWITCH_USE_CLOCK_FUNCS)
|
||||
struct timespec ts;
|
||||
ts.tv_sec = t / APR_USEC_PER_SEC;
|
||||
ts.tv_nsec = (t % APR_USEC_PER_SEC) * 1000;
|
||||
|
||||
clock_nanosleep(CLOCK_REALTIME, 0, &ts, NULL);
|
||||
|
||||
#elif defined(HAVE_USLEEP)
|
||||
usleep(t);
|
||||
#elif defined(WIN32)
|
||||
Sleep((DWORD) ((t) / 1000));
|
||||
#else
|
||||
apr_sleep(t);
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
SWITCH_DECLARE(void) switch_time_set_monotonic(switch_bool_t enable)
|
||||
{
|
||||
MONO = enable ? 1 : 0;
|
||||
|
@ -139,6 +161,11 @@ SWITCH_DECLARE(void) switch_time_sync(void)
|
|||
SWITCH_DECLARE(void) switch_sleep(switch_interval_time_t t)
|
||||
{
|
||||
|
||||
if (globals.use_cond_yield == 1) {
|
||||
switch_cond_yield((t) / 1000);
|
||||
return;
|
||||
}
|
||||
|
||||
#if defined(HAVE_USLEEP)
|
||||
usleep(t);
|
||||
#elif defined(WIN32)
|
||||
|
@ -166,13 +193,29 @@ SWITCH_DECLARE(void) switch_sleep(switch_interval_time_t t)
|
|||
|
||||
}
|
||||
|
||||
|
||||
SWITCH_DECLARE(void) switch_cond_yield(uint32_t ms)
|
||||
{
|
||||
if (!ms) return;
|
||||
|
||||
if (globals.use_cond_yield != 1) {
|
||||
do_yield(ms * 1000);
|
||||
}
|
||||
|
||||
while(globals.RUNNING == 1 && globals.use_cond_yield == 1 && ms--) {
|
||||
switch_mutex_lock(TIMER_MATRIX[1].mutex);
|
||||
switch_thread_cond_wait(TIMER_MATRIX[1].cond, TIMER_MATRIX[1].mutex);
|
||||
switch_mutex_unlock(TIMER_MATRIX[1].mutex);
|
||||
}
|
||||
}
|
||||
|
||||
static switch_status_t timer_init(switch_timer_t *timer)
|
||||
{
|
||||
timer_private_t *private_info;
|
||||
int sanity = 0;
|
||||
|
||||
while (globals.STARTED == 0) {
|
||||
switch_yield(100000);
|
||||
do_yield(100000);
|
||||
if (++sanity == 10) {
|
||||
break;
|
||||
}
|
||||
|
@ -187,6 +230,10 @@ static switch_status_t timer_init(switch_timer_t *timer)
|
|||
timeBeginPeriod(1);
|
||||
#endif
|
||||
switch_mutex_lock(globals.mutex);
|
||||
if (!TIMER_MATRIX[timer->interval].mutex) {
|
||||
switch_mutex_init(&TIMER_MATRIX[timer->interval].mutex, SWITCH_MUTEX_NESTED, module_pool);
|
||||
switch_thread_cond_create(&TIMER_MATRIX[timer->interval].cond, module_pool);
|
||||
}
|
||||
TIMER_MATRIX[timer->interval].count++;
|
||||
switch_mutex_unlock(globals.mutex);
|
||||
timer->private_info = private_info;
|
||||
|
@ -252,13 +299,21 @@ static switch_status_t timer_sync(switch_timer_t *timer)
|
|||
static switch_status_t timer_next(switch_timer_t *timer)
|
||||
{
|
||||
timer_private_t *private_info = timer->private_info;
|
||||
|
||||
timer_step(timer);
|
||||
|
||||
#if 1
|
||||
while (globals.RUNNING == 1 && private_info->ready && TIMER_MATRIX[timer->interval].tick < private_info->reference) {
|
||||
check_roll();
|
||||
switch_yield(1000);
|
||||
switch_mutex_lock(TIMER_MATRIX[timer->interval].mutex);
|
||||
switch_thread_cond_wait(TIMER_MATRIX[timer->interval].cond, TIMER_MATRIX[timer->interval].mutex);
|
||||
switch_mutex_unlock(TIMER_MATRIX[timer->interval].mutex);
|
||||
}
|
||||
#else
|
||||
while (globals.RUNNING == 1 && private_info->ready && TIMER_MATRIX[timer->interval].tick < private_info->reference) {
|
||||
check_roll();
|
||||
do_yield(1000);
|
||||
}
|
||||
#endif
|
||||
|
||||
if (globals.RUNNING == 1) {
|
||||
return SWITCH_STATUS_SUCCESS;
|
||||
|
@ -340,7 +395,7 @@ SWITCH_MODULE_RUNTIME_FUNCTION(softtimer_runtime)
|
|||
runtime.initiated = runtime.reference;
|
||||
break;
|
||||
}
|
||||
switch_yield(STEP_MIC);
|
||||
do_yield(STEP_MIC);
|
||||
last = ts;
|
||||
}
|
||||
}
|
||||
|
@ -349,8 +404,15 @@ SWITCH_MODULE_RUNTIME_FUNCTION(softtimer_runtime)
|
|||
last = 0;
|
||||
fwd_errs = rev_errs = 0;
|
||||
|
||||
|
||||
switch_mutex_init(&TIMER_MATRIX[1].mutex, SWITCH_MUTEX_NESTED, module_pool);
|
||||
switch_thread_cond_create(&TIMER_MATRIX[1].cond, module_pool);
|
||||
|
||||
globals.use_cond_yield = globals.RUNNING == 1;
|
||||
|
||||
while (globals.RUNNING == 1) {
|
||||
runtime.reference += STEP_MIC;
|
||||
|
||||
while ((ts = time_now(runtime.offset)) < runtime.reference) {
|
||||
if (ts < last) {
|
||||
if (MONO) {
|
||||
|
@ -368,7 +430,7 @@ SWITCH_MODULE_RUNTIME_FUNCTION(softtimer_runtime)
|
|||
} else {
|
||||
rev_errs = 0;
|
||||
}
|
||||
switch_yield(STEP_MIC);
|
||||
do_yield(STEP_MIC);
|
||||
last = ts;
|
||||
}
|
||||
|
||||
|
@ -413,11 +475,28 @@ SWITCH_MODULE_RUNTIME_FUNCTION(softtimer_runtime)
|
|||
tick = 0;
|
||||
}
|
||||
|
||||
TIMER_MATRIX[1].tick++;
|
||||
if (switch_mutex_trylock(TIMER_MATRIX[1].mutex) == SWITCH_STATUS_SUCCESS) {
|
||||
switch_thread_cond_broadcast(TIMER_MATRIX[1].cond);
|
||||
switch_mutex_unlock(TIMER_MATRIX[1].mutex);
|
||||
}
|
||||
if (TIMER_MATRIX[1].tick == MAX_TICK) {
|
||||
TIMER_MATRIX[1].tick = 0;
|
||||
TIMER_MATRIX[1].roll++;
|
||||
}
|
||||
|
||||
|
||||
if ((current_ms % MS_PER_TICK) == 0) {
|
||||
for (x = MS_PER_TICK; x <= MAX_ELEMENTS; x += MS_PER_TICK) {
|
||||
if ((current_ms % x) == 0) {
|
||||
if (TIMER_MATRIX[x].count) {
|
||||
TIMER_MATRIX[x].tick++;
|
||||
#if 1
|
||||
if (TIMER_MATRIX[x].mutex && switch_mutex_trylock(TIMER_MATRIX[x].mutex) == SWITCH_STATUS_SUCCESS) {
|
||||
switch_thread_cond_broadcast(TIMER_MATRIX[x].cond);
|
||||
switch_mutex_unlock(TIMER_MATRIX[x].mutex);
|
||||
}
|
||||
#endif
|
||||
if (TIMER_MATRIX[x].tick == MAX_TICK) {
|
||||
TIMER_MATRIX[x].tick = 0;
|
||||
TIMER_MATRIX[x].roll++;
|
||||
|
@ -431,10 +510,22 @@ SWITCH_MODULE_RUNTIME_FUNCTION(softtimer_runtime)
|
|||
}
|
||||
}
|
||||
|
||||
globals.use_cond_yield = 0;
|
||||
|
||||
for (x = MS_PER_TICK; x <= MAX_ELEMENTS; x += MS_PER_TICK) {
|
||||
if (TIMER_MATRIX[x].mutex && switch_mutex_trylock(TIMER_MATRIX[x].mutex) == SWITCH_STATUS_SUCCESS) {
|
||||
switch_thread_cond_broadcast(TIMER_MATRIX[x].cond);
|
||||
switch_mutex_unlock(TIMER_MATRIX[x].mutex);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
switch_mutex_lock(globals.mutex);
|
||||
globals.RUNNING = 0;
|
||||
switch_mutex_unlock(globals.mutex);
|
||||
|
||||
|
||||
|
||||
return SWITCH_STATUS_TERM;
|
||||
}
|
||||
|
||||
|
@ -641,14 +732,13 @@ SWITCH_MODULE_LOAD_FUNCTION(softtimer_load)
|
|||
|
||||
SWITCH_MODULE_SHUTDOWN_FUNCTION(softtimer_shutdown)
|
||||
{
|
||||
|
||||
if (globals.RUNNING) {
|
||||
if (globals.RUNNING == 1) {
|
||||
switch_mutex_lock(globals.mutex);
|
||||
globals.RUNNING = -1;
|
||||
switch_mutex_unlock(globals.mutex);
|
||||
|
||||
while (globals.RUNNING) {
|
||||
switch_yield(10000);
|
||||
while (globals.RUNNING == -1) {
|
||||
do_yield(10000);
|
||||
}
|
||||
}
|
||||
#if defined(WIN32)
|
||||
|
|
Loading…
Reference in New Issue