]> git.ipfire.org Git - thirdparty/freeswitch.git/commitdiff
FS-8677 #resolve [Crash (possible memory corruption) after codec change]
authorAnthony Minessale <anthm@freeswitch.org>
Wed, 23 Dec 2015 22:03:35 +0000 (16:03 -0600)
committerAnthony Minessale <anthm@freeswitch.org>
Wed, 6 Jan 2016 16:10:14 +0000 (10:10 -0600)
src/include/switch_core_media.h
src/include/switch_rtp.h
src/mod/applications/mod_conference/conference_loop.c
src/mod/applications/mod_conference/conference_member.c
src/mod/applications/mod_conference/mod_conference.h
src/switch_channel.c
src/switch_core_media.c
src/switch_ivr_bridge.c
src/switch_rtp.c

index c8ddcf2c621018d9177ff7614ca773fd3fca7d8c..c021d0a90e81914b5e9b60fbe240e79087358cf1 100644 (file)
@@ -342,7 +342,8 @@ SWITCH_DECLARE(switch_file_handle_t *) switch_core_media_get_video_file(switch_c
 SWITCH_DECLARE(switch_bool_t) switch_core_session_in_video_thread(switch_core_session_t *session);
 SWITCH_DECLARE(switch_bool_t) switch_core_media_check_dtls(switch_core_session_t *session, switch_media_type_t type);
 SWITCH_DECLARE(switch_status_t) switch_core_media_set_outgoing_bitrate(switch_core_session_t *session, switch_media_type_t type, uint32_t bitrate);
-
+SWITCH_DECLARE(switch_status_t) switch_core_media_reset_jb(switch_core_session_t *session, switch_media_type_t type);
+                                                                                                                               
 SWITCH_END_EXTERN_C
 #endif
 /* For Emacs:
index 2c5dce8f586180d920594c610d80f195c19013a9..3fdd1ed325d18a04c19eade4181b523d827c8541 100644 (file)
@@ -269,6 +269,7 @@ SWITCH_DECLARE(switch_rtp_t *) switch_rtp_new(const char *rx_host,
 SWITCH_DECLARE(switch_status_t) switch_rtp_set_remote_address(switch_rtp_t *rtp_session, const char *host, switch_port_t port, switch_port_t remote_rtcp_port,
                                                                                                                          switch_bool_t change_adv_addr, const char **err);
 
+SWITCH_DECLARE(void) switch_rtp_reset_jb(switch_rtp_t *rtp_session);
 SWITCH_DECLARE(char *) switch_rtp_get_remote_host(switch_rtp_t *rtp_session);
 SWITCH_DECLARE(switch_port_t) switch_rtp_get_remote_port(switch_rtp_t *rtp_session);
 SWITCH_DECLARE(void) switch_rtp_reset_media_timer(switch_rtp_t *rtp_session);
index c31fb6ddcd9489052025d46cd7e43990d0880992..ed2d54bf12e09a2d666512098ca1397003bcd036 100644 (file)
@@ -746,15 +746,24 @@ void *SWITCH_THREAD_FUNC conference_loop_input(switch_thread_t *thread, void *ob
                }
 
                if (switch_channel_test_flag(member->channel, CF_CONFERENCE_RESET_MEDIA)) {
+                       member->reset_media = 10;
+                       switch_channel_audio_sync(member->channel);
                        switch_channel_clear_flag(member->channel, CF_CONFERENCE_RESET_MEDIA);
-                       member->loop_loop = 1;
-                               
+               }
+
+               if (member->reset_media) {
+                       if (--member->reset_media > 0) {
+                               goto do_continue;
+                       }
+
                        if (conference_member_setup_media(member, member->conference)) {
                                switch_mutex_unlock(member->read_mutex);
                                break;
                        }
+
+                       member->loop_loop = 1;
                        
-                       goto do_continue;
+                       goto do_continue;                       
                }
 
                if (switch_test_flag(read_frame, SFF_CNG)) {
@@ -1199,10 +1208,10 @@ void conference_loop_output(conference_member_t *member)
                uint32_t mux_used = 0;
 
 
-               if (switch_channel_test_flag(member->channel, CF_CONFERENCE_RESET_MEDIA)) {
-                       switch_cond_next();
-                       continue;
-               }
+               //if (member->reset_media || switch_channel_test_flag(member->channel, CF_CONFERENCE_RESET_MEDIA)) {
+               //      switch_cond_next();
+               //      continue;
+               //}
 
                switch_mutex_lock(member->write_mutex);
 
index 9f3fd8a89f37bccfcec429a4ba9f000bc9590bd1..827812d16204fa950ab0f410bf15f7166c700181 100644 (file)
@@ -1620,13 +1620,7 @@ int conference_member_setup_media(conference_member_t *member, conference_obj_t
 
        switch_mutex_lock(member->audio_out_mutex);
 
-       if (!member->orig_read_impl.samples_per_second) {
-               switch_core_session_get_read_impl(member->session, &member->orig_read_impl);
-               member->native_rate = read_impl.samples_per_second;
-       }
-
-       read_impl = member->orig_read_impl;
-
+       switch_core_session_get_read_impl(member->session, &read_impl);
 
        if (switch_core_codec_ready(&member->read_codec)) {
                switch_core_codec_destroy(&member->read_codec);
@@ -1642,6 +1636,9 @@ int conference_member_setup_media(conference_member_t *member, conference_obj_t
                switch_resample_destroy(&member->read_resampler);
        }
 
+       switch_core_session_get_read_impl(member->session, &member->orig_read_impl);
+       member->native_rate = member->orig_read_impl.samples_per_second;
+
        /* Setup a Signed Linear codec for reading audio. */
        if (switch_core_codec_init(&member->read_codec,
                                                           "L16",
index 0554bfd53c42452c79a810b535c9ada6306cfb99..d4a03cfb2e71bd6ee9d280125560f6316999d453 100644 (file)
@@ -769,6 +769,7 @@ struct conference_member {
        int max_bw_in;
        int force_bw_in;
        int max_bw_out;
+       int reset_media;
 };
 
 typedef enum {
index 1b8f1e894e79431842a33b5cf89d9af9578edf32..8a7a5ceab78d0c82f36e179f6c0ce0ad45b7b1a6 100644 (file)
@@ -350,27 +350,36 @@ SWITCH_DECLARE(switch_channel_callstate_t) switch_channel_str2callstate(const ch
 SWITCH_DECLARE(void) switch_channel_perform_audio_sync(switch_channel_t *channel, const char *file, const char *func, int line)
 {
        if (switch_channel_media_up(channel)) {
-               switch_core_session_message_t msg = { 0 };
-               msg.message_id = SWITCH_MESSAGE_INDICATE_AUDIO_SYNC;
-               msg.from = channel->name;
-               msg._file = file;
-               msg._func = func;
-               msg._line = line;
-               switch_core_session_receive_message(channel->session, &msg);
+               switch_core_session_message_t *msg = NULL;
+
+               msg = switch_core_session_alloc(channel->session, sizeof(*msg));
+               MESSAGE_STAMP_FFL(msg);
+               msg->message_id = SWITCH_MESSAGE_INDICATE_AUDIO_SYNC;
+               msg->from = channel->name;
+               msg->_file = file;
+               msg->_func = func;
+               msg->_line = line;
+
+               switch_core_session_queue_message(channel->session, msg);
        }
 }
 
 
 SWITCH_DECLARE(void) switch_channel_perform_video_sync(switch_channel_t *channel, const char *file, const char *func, int line)
 {
+
        if (switch_channel_media_up(channel)) {
-               switch_core_session_message_t msg = { 0 };
-               msg.message_id = SWITCH_MESSAGE_INDICATE_VIDEO_SYNC;
-               msg.from = channel->name;
-               msg._file = file;
-               msg._func = func;
-               msg._line = line;
-               switch_core_session_receive_message(channel->session, &msg);
+               switch_core_session_message_t *msg = NULL;
+
+               msg = switch_core_session_alloc(channel->session, sizeof(*msg));
+               MESSAGE_STAMP_FFL(msg);
+               msg->message_id = SWITCH_MESSAGE_INDICATE_VIDEO_SYNC;
+               msg->from = channel->name;
+               msg->_file = file;
+               msg->_func = func;
+               msg->_line = line;
+
+               switch_core_session_queue_message(channel->session, msg);
        }
 }
 
index 2456925ce90c754f14bc25b0ae4a156f62dc0bb0..6513eb9a66553f130db87c04bffba45e0a034c8d 100644 (file)
@@ -2120,6 +2120,10 @@ SWITCH_DECLARE(switch_status_t) switch_core_media_read_frame(switch_core_session
                return SWITCH_STATUS_FALSE;
        }
 
+       if (switch_channel_test_flag(session->channel, CF_LEG_HOLDING)) {
+               return SWITCH_STATUS_INUSE;
+       }
+       
        if (smh->read_mutex[type] && switch_mutex_trylock(smh->read_mutex[type]) != SWITCH_STATUS_SUCCESS) {
                /* return CNG, another thread is already reading  */
                switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG1, "%s is already being read for %s\n", 
@@ -2180,7 +2184,7 @@ SWITCH_DECLARE(switch_status_t) switch_core_media_read_frame(switch_core_session
                                if (type == SWITCH_MEDIA_TYPE_VIDEO) {
                                        switch_core_media_set_video_codec(session, 1);
                                } else {
-                                       if (switch_core_media_set_codec(session, 1, 0) != SWITCH_STATUS_SUCCESS) {
+                                       if (switch_core_media_set_codec(session, 1, smh->mparams->codec_flags) != SWITCH_STATUS_SUCCESS) {
                                                *frame = NULL;
                                                switch_goto_status(SWITCH_STATUS_GENERR, end);
                                        }
@@ -2777,6 +2781,7 @@ SWITCH_DECLARE(switch_status_t) switch_core_media_set_codec(switch_core_session_
                if (!force) {
                        switch_goto_status(SWITCH_STATUS_SUCCESS, end);
                }
+
                if (strcasecmp(a_engine->read_impl.iananame, a_engine->cur_payload_map->iananame) ||
                        (uint32_t) a_engine->read_impl.microseconds_per_packet / 1000 != a_engine->cur_payload_map->codec_ms ||
                        a_engine->read_impl.samples_per_second != a_engine->cur_payload_map->rm_rate ) {
@@ -2802,7 +2807,7 @@ SWITCH_DECLARE(switch_status_t) switch_core_media_set_codec(switch_core_session_
                                                          "Changing Codec from %s@%dms@%dhz to %s@%dms@%luhz\n",
                                                          a_engine->read_impl.iananame, 
                                                          a_engine->read_impl.microseconds_per_packet / 1000,
-                                                         a_engine->read_impl.samples_per_second,
+                                                         a_engine->read_impl.actual_samples_per_second,
 
                                                          a_engine->cur_payload_map->iananame, 
                                                          a_engine->cur_payload_map->codec_ms,
@@ -2860,6 +2865,11 @@ SWITCH_DECLARE(switch_status_t) switch_core_media_set_codec(switch_core_session_
 
        a_engine->write_codec.session = session;
 
+       if (switch_rtp_ready(a_engine->rtp_session)) {
+               switch_channel_audio_sync(session->channel);
+               switch_rtp_reset_jb(a_engine->rtp_session);
+       }
+
        switch_channel_set_variable(session->channel, "rtp_use_codec_name", a_engine->cur_payload_map->iananame);
        switch_channel_set_variable(session->channel, "rtp_use_codec_fmtp", a_engine->cur_payload_map->rm_fmtp);
        switch_channel_set_variable_printf(session->channel, "rtp_use_codec_rate", "%d", a_engine->cur_payload_map->rm_rate);
@@ -4383,24 +4393,28 @@ SWITCH_DECLARE(uint8_t) switch_core_media_negotiate_sdp(switch_core_session_t *s
                                switch_snprintf(tmp, sizeof(tmp), "%d", a_engine->cur_payload_map->recv_pt);
                                switch_channel_set_variable(session->channel, "rtp_audio_recv_pt", tmp);
 
-                               if (switch_core_codec_ready(&a_engine->read_codec) && 
-                                       (strcasecmp(matches[0].imp->iananame, a_engine->read_codec.implementation->iananame) || 
-                                        matches[0].imp->microseconds_per_packet != a_engine->read_codec.implementation->microseconds_per_packet ||
-                                        matches[0].imp->samples_per_second != a_engine->read_codec.implementation->samples_per_second
-                                        )) {
+                               if (a_engine->read_impl.iananame) {
+                                       if (!switch_core_codec_ready(&a_engine->read_codec) || 
+                                               ((strcasecmp(matches[0].imp->iananame, a_engine->read_impl.iananame) || 
+                                                 matches[0].imp->microseconds_per_packet != a_engine->read_impl.microseconds_per_packet ||
+                                                 matches[0].imp->samples_per_second != a_engine->read_impl.samples_per_second
+                                                 ))) {
 
-                                       a_engine->reset_codec = 1;
+                                               a_engine->reset_codec = 1;
+                                       }
+                               } else if (switch_core_media_set_codec(session, 0, smh->mparams->codec_flags) != SWITCH_STATUS_SUCCESS) {
+                                       match = 0;
                                }
 
-                               if (switch_core_media_set_codec(session, 0, smh->mparams->codec_flags) == SWITCH_STATUS_SUCCESS) {
+                               if (match) {
                                        if (check_ice(smh, SWITCH_MEDIA_TYPE_AUDIO, sdp, m) == SWITCH_STATUS_FALSE) {
                                                match = 0;
+                                               got_audio = 0;
                                        } else {
                                                got_audio = 1;
-                                       }
-                               } else {
-                                       match = 0;
+                                       }                               
                                }
+
                        }
 
                        for (map = m->m_rtpmaps; map; map = map->rm_next) {
@@ -8919,6 +8933,28 @@ SWITCH_DECLARE(switch_status_t) switch_core_media_set_outgoing_bitrate(switch_co
        return status;
 }
 
+//?
+SWITCH_DECLARE(switch_status_t) switch_core_media_reset_jb(switch_core_session_t *session, switch_media_type_t type)
+{
+       switch_media_handle_t *smh;
+       switch_rtp_engine_t *engine;
+
+       switch_assert(session);
+
+       if (!(smh = session->media_handle)) {
+               return SWITCH_STATUS_FALSE;
+       }
+
+       engine = &smh->engines[type];
+
+       if (switch_rtp_ready(engine->rtp_session)) {
+               switch_rtp_reset_jb(engine->rtp_session);
+               return SWITCH_STATUS_SUCCESS;
+       }
+
+       return SWITCH_STATUS_FALSE;
+}
+
 //?
 SWITCH_DECLARE(switch_status_t) switch_core_media_receive_message(switch_core_session_t *session, switch_core_session_message_t *msg)
 {
@@ -8943,6 +8979,11 @@ SWITCH_DECLARE(switch_status_t) switch_core_media_receive_message(switch_core_se
 
        case SWITCH_MESSAGE_RESAMPLE_EVENT:
                {
+                       if (switch_rtp_ready(a_engine->rtp_session)) {
+                               switch_channel_audio_sync(session->channel);
+                               switch_rtp_reset_jb(a_engine->rtp_session);
+                       }
+                       
                        if (switch_channel_test_flag(session->channel, CF_CONFERENCE)) {
                                switch_channel_set_flag(session->channel, CF_CONFERENCE_RESET_MEDIA);
                        }
@@ -9211,12 +9252,14 @@ SWITCH_DECLARE(switch_status_t) switch_core_media_receive_message(switch_core_se
        case SWITCH_MESSAGE_INDICATE_AUDIO_SYNC:
                if (switch_rtp_ready(a_engine->rtp_session)) {
                        rtp_flush_read_buffer(a_engine->rtp_session, SWITCH_RTP_FLUSH_ONCE);
+                       switch_rtp_reset_jb(a_engine->rtp_session);
                }
                goto end;
 
        case SWITCH_MESSAGE_INDICATE_VIDEO_SYNC:
                if (switch_rtp_ready(v_engine->rtp_session)) {
                        switch_rtp_flush(v_engine->rtp_session);
+                       switch_rtp_reset_jb(v_engine->rtp_session);
                }
                goto end;
        case SWITCH_MESSAGE_INDICATE_3P_MEDIA:
index 5e8a5a50be1f4bbb6ee75e65e39f6eb81aa096fd..cdebd44558cbc2b61e16a39341da7a53920409cc 100644 (file)
@@ -694,7 +694,7 @@ static void *audio_bridge_thread(switch_thread_t *thread, void *obj)
                                continue;
                        }
 
-                       if (status != SWITCH_STATUS_BREAK && !switch_channel_test_flag(chan_a, CF_HOLD)) {
+                       if (status != SWITCH_STATUS_BREAK && !switch_channel_test_flag(chan_a, CF_HOLD) && !switch_channel_test_flag(chan_b, CF_LEG_HOLDING)) {
                                if (switch_core_session_write_frame(session_b, read_frame, SWITCH_IO_FLAG_NONE, stream_id) != SWITCH_STATUS_SUCCESS) {
                                        switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session_a), SWITCH_LOG_DEBUG,
                                                                          "%s ending bridge by request from write function\n", switch_channel_get_name(chan_b));
index 811ff437e82edc60eecd1038cc17e50ff0da9384..5646b8e86e9c09ad511921530892a4132c7a3546 100644 (file)
@@ -2740,6 +2740,15 @@ SWITCH_DECLARE(void) switch_rtp_set_max_missed_packets(switch_rtp_t *rtp_session
        rtp_session->max_missed_packets = max;
 }
 
+SWITCH_DECLARE(void) switch_rtp_reset_jb(switch_rtp_t *rtp_session)
+{
+       if (switch_rtp_ready(rtp_session)) {
+               if (rtp_session->jb) {
+                       switch_jb_reset(rtp_session->jb);
+               }
+       }
+}
+
 SWITCH_DECLARE(void) switch_rtp_reset_vb(switch_rtp_t *rtp_session)
 {
        if (rtp_session->vb) {