From 4fe8aecbfb3f96de4a8b7afddc1c22b61d771370 Mon Sep 17 00:00:00 2001 From: Andrey Volk Date: Mon, 27 Jul 2020 21:41:13 +0400 Subject: [PATCH] [Core] Make switch_core_media_set_codec() and switch_core_media_set_video_codec() thread-safe so there is no race when a session's codec is initiated by different threads simultaneously. --- src/include/private/switch_core_pvt.h | 1 + src/switch_core_media.c | 27 +++++++++++++++++++-------- src/switch_core_session.c | 1 + 3 files changed, 21 insertions(+), 8 deletions(-) diff --git a/src/include/private/switch_core_pvt.h b/src/include/private/switch_core_pvt.h index c3478f109e..68a8d9c463 100644 --- a/src/include/private/switch_core_pvt.h +++ b/src/include/private/switch_core_pvt.h @@ -132,6 +132,7 @@ struct switch_core_session { switch_mutex_t *mutex; switch_mutex_t *stack_count_mutex; switch_mutex_t *resample_mutex; + switch_mutex_t *codec_init_mutex; switch_mutex_t *codec_read_mutex; switch_mutex_t *codec_write_mutex; switch_mutex_t *video_codec_read_mutex; diff --git a/src/switch_core_media.c b/src/switch_core_media.c index 4778edbf8c..8173996e3d 100644 --- a/src/switch_core_media.c +++ b/src/switch_core_media.c @@ -3587,24 +3587,27 @@ static void switch_core_session_parse_codec_settings(switch_core_session_t *sess //? SWITCH_DECLARE(switch_status_t) switch_core_media_set_video_codec(switch_core_session_t *session, int force) { + switch_status_t status = SWITCH_STATUS_SUCCESS; switch_media_handle_t *smh; switch_rtp_engine_t *v_engine; switch_assert(session); + switch_mutex_lock(session->codec_init_mutex); + if (!(smh = session->media_handle)) { - return SWITCH_STATUS_FALSE; + switch_goto_status(SWITCH_STATUS_FALSE, end); } v_engine = &smh->engines[SWITCH_MEDIA_TYPE_VIDEO]; if (!v_engine->codec_negotiated) { - return SWITCH_STATUS_FALSE; + switch_goto_status(SWITCH_STATUS_FALSE, end); } if (v_engine->read_codec.implementation && switch_core_codec_ready(&v_engine->read_codec)) { if (!force) { - return SWITCH_STATUS_SUCCESS; + switch_goto_status(SWITCH_STATUS_SUCCESS, end); } if (strcasecmp(v_engine->read_codec.implementation->iananame, v_engine->cur_payload_map->rm_encoding) || v_engine->read_codec.implementation->samples_per_second != v_engine->cur_payload_map->rm_rate) { @@ -3616,7 +3619,7 @@ SWITCH_DECLARE(switch_status_t) switch_core_media_set_video_codec(switch_core_se } else { switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Already using %s\n", v_engine->read_codec.implementation->iananame); - return SWITCH_STATUS_SUCCESS; + switch_goto_status(SWITCH_STATUS_SUCCESS, end); } } @@ -3632,7 +3635,7 @@ SWITCH_DECLARE(switch_status_t) switch_core_media_set_video_codec(switch_core_se SWITCH_CODEC_FLAG_ENCODE | SWITCH_CODEC_FLAG_DECODE, &v_engine->codec_settings, switch_core_session_get_pool(session)) != SWITCH_STATUS_SUCCESS) { switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Can't load codec?\n"); - return SWITCH_STATUS_FALSE; + switch_goto_status(SWITCH_STATUS_FALSE, end); } else { if (switch_core_codec_init(&v_engine->write_codec, v_engine->cur_payload_map->rm_encoding, @@ -3644,7 +3647,7 @@ SWITCH_DECLARE(switch_status_t) switch_core_media_set_video_codec(switch_core_se SWITCH_CODEC_FLAG_ENCODE | SWITCH_CODEC_FLAG_DECODE, &v_engine->codec_settings, switch_core_session_get_pool(session)) != SWITCH_STATUS_SUCCESS) { switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Can't load codec?\n"); - return SWITCH_STATUS_FALSE; + switch_goto_status(SWITCH_STATUS_FALSE, end); } else { v_engine->read_frame.rate = v_engine->cur_payload_map->rm_rate; switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Set VIDEO Codec %s %s/%ld %d ms\n", @@ -3685,7 +3688,11 @@ SWITCH_DECLARE(switch_status_t) switch_core_media_set_video_codec(switch_core_se switch_channel_set_variable_printf(session->channel, "rtp_use_video_codec_ptime", "%d", 0); } } - return SWITCH_STATUS_SUCCESS; + +end: + switch_mutex_unlock(session->codec_init_mutex); + + return status; } @@ -3698,9 +3705,11 @@ SWITCH_DECLARE(switch_status_t) switch_core_media_set_codec(switch_core_session_ switch_rtp_engine_t *a_engine; switch_assert(session); + + switch_mutex_lock(session->codec_init_mutex); if (!(smh = session->media_handle)) { - return SWITCH_STATUS_FALSE; + switch_goto_status(SWITCH_STATUS_FALSE, end); } a_engine = &smh->engines[SWITCH_MEDIA_TYPE_AUDIO]; @@ -3865,6 +3874,8 @@ SWITCH_DECLARE(switch_status_t) switch_core_media_set_codec(switch_core_session_ switch_core_session_unlock_codec_read(session); } + switch_mutex_unlock(session->codec_init_mutex); + return status; } static void clear_ice(switch_core_session_t *session, switch_media_type_t type) diff --git a/src/switch_core_session.c b/src/switch_core_session.c index ca58566b2f..36cf62f111 100644 --- a/src/switch_core_session.c +++ b/src/switch_core_session.c @@ -2417,6 +2417,7 @@ SWITCH_DECLARE(switch_core_session_t *) switch_core_session_request_uuid(switch_ switch_mutex_init(&session->mutex, SWITCH_MUTEX_NESTED, session->pool); switch_mutex_init(&session->stack_count_mutex, SWITCH_MUTEX_NESTED, session->pool); switch_mutex_init(&session->resample_mutex, SWITCH_MUTEX_NESTED, session->pool); + switch_mutex_init(&session->codec_init_mutex, SWITCH_MUTEX_NESTED, session->pool); switch_mutex_init(&session->codec_read_mutex, SWITCH_MUTEX_NESTED, session->pool); switch_mutex_init(&session->codec_write_mutex, SWITCH_MUTEX_NESTED, session->pool); switch_mutex_init(&session->video_codec_read_mutex, SWITCH_MUTEX_NESTED, session->pool);