]> git.ipfire.org Git - thirdparty/freeswitch.git/commitdiff
rework media code
authorAnthony Minessale <anthm@freeswitch.org>
Thu, 7 Nov 2013 22:48:00 +0000 (03:48 +0500)
committerAnthony Minessale <anthm@freeswitch.org>
Thu, 7 Nov 2013 22:48:00 +0000 (03:48 +0500)
14 files changed:
src/include/private/switch_core_pvt.h
src/include/switch_core_media.h
src/include/switch_frame.h
src/include/switch_rtp.h
src/mod/applications/mod_conference/mod_conference.c
src/mod/codecs/mod_vp8/mod_vp8.c
src/mod/endpoints/mod_sofia/mod_sofia.c
src/mod/endpoints/mod_sofia/rtp.c
src/mod/endpoints/mod_sofia/sofia.c
src/mod/endpoints/mod_sofia/sofia_glue.c
src/switch_core_io.c
src/switch_core_media.c
src/switch_rtp.c
src/switch_utils.c

index bff9b72a78af4caacc91e3496212d666e7040ae7..aa6adb67e9cf9fd58f598ca1baa131b918ace3be 100644 (file)
@@ -178,6 +178,7 @@ struct switch_core_session {
        switch_size_t recur_buffer_len;
 
        switch_media_handle_t *media_handle;
+       uint32_t decoder_errors;
 };
 
 struct switch_media_bug {
index 9641718f073523b4f9282f98baa1f3e479513de9..5c083101a98cfb5c283434de1a0c6d5e595be43c 100644 (file)
@@ -68,7 +68,6 @@ typedef enum {
        SCMF_RUNNING,
        SCMF_DISABLE_TRANSCODING,
        SCMF_AUTOFIX_TIMING,
-       SCMF_AUTOFIX_PT,
        SCMF_CODEC_GREEDY,
        SCMF_CODEC_SCROOGE,
        SCMF_DISABLE_HOLD,
@@ -81,6 +80,8 @@ typedef enum {
        SCMF_AUTOFLUSH,
        SCMF_REWRITE_TIMESTAMPS,
        SCMF_RTP_AUTOFLUSH_DURING_BRIDGE,
+       SCMF_MULTI_ANSWER_AUDIO,
+       SCMF_MULTI_ANSWER_VIDEO,
        SCMF_MAX
 } switch_core_media_flag_t;
 
@@ -156,6 +157,53 @@ typedef struct switch_core_media_params_s {
 
 } switch_core_media_params_t;
 
+typedef struct xpayload_map_s {
+       uint32_t pt;
+       uint32_t send_pt;
+       uint32_t rate;
+       uint32_t ptime;
+       switch_media_type_t type;
+       uint8_t negotiated;
+       char *name;
+       switch_sdp_type_t sdp_type;
+       unsigned long hash;
+       struct xpayload_map_s *next;
+} xpayload_map_t;
+
+typedef struct payload_map_s {
+       switch_media_type_t type;
+       switch_sdp_type_t sdp_type;
+       uint32_t ptime;
+       uint32_t rate;
+       uint8_t allocated;
+       uint8_t negotiated;
+       unsigned long hash;
+
+       char *rm_encoding;
+       char *iananame;
+       switch_payload_t pt;
+       unsigned long rm_rate;
+       unsigned long adv_rm_rate;
+       uint32_t codec_ms;
+       uint32_t bitrate;
+
+       char *rm_fmtp;
+
+       switch_payload_t agreed_pt;
+       switch_payload_t recv_pt;
+
+       char *fmtp_out;
+
+       char *remote_sdp_ip;
+       switch_port_t remote_sdp_port;
+
+       int channels;
+       int adv_channels;
+
+       struct payload_map_s *next;
+
+} payload_map_t;
+
 static inline const char *switch_media_type2str(switch_media_type_t type)
 {
        switch(type) {
@@ -216,7 +264,8 @@ SWITCH_DECLARE(switch_status_t) switch_core_media_activate_rtp(switch_core_sessi
 SWITCH_DECLARE(switch_status_t) switch_core_media_ext_address_lookup(switch_core_session_t *session, char **ip, switch_port_t *port, const char *sourceip);
 SWITCH_DECLARE(switch_status_t) switch_core_media_process_t38_passthru(switch_core_session_t *session, 
                                                                                                                                           switch_core_session_t *other_session, switch_t38_options_t *t38_options);
-SWITCH_DECLARE(void) switch_core_media_gen_local_sdp(switch_core_session_t *session, const char *ip, switch_port_t port, const char *sr, int force);
+SWITCH_DECLARE(void) switch_core_media_gen_local_sdp(switch_core_session_t *session, switch_sdp_type_t sdp_type, 
+                                                                                                        const char *ip, switch_port_t port, const char *sr, int force);
 SWITCH_DECLARE(void)switch_core_media_set_local_sdp(switch_core_session_t *session, const char *sdp_str, switch_bool_t dup);
 SWITCH_DECLARE(void) switch_core_media_patch_sdp(switch_core_session_t *session);
 SWITCH_DECLARE(void) switch_core_media_set_udptl_image_sdp(switch_core_session_t *session, switch_t38_options_t *t38_options, int insist);
@@ -232,7 +281,6 @@ SWITCH_DECLARE(void) switch_core_media_kill_socket(switch_core_session_t *sessio
 SWITCH_DECLARE(switch_status_t) switch_core_media_queue_rfc2833(switch_core_session_t *session, switch_media_type_t type, const switch_dtmf_t *dtmf);
 SWITCH_DECLARE(switch_status_t) switch_core_media_queue_rfc2833_in(switch_core_session_t *session, switch_media_type_t type, const switch_dtmf_t *dtmf);
 SWITCH_DECLARE(uint8_t) switch_core_media_ready(switch_core_session_t *session, switch_media_type_t type);
-SWITCH_DECLARE(void) switch_core_media_set_recv_pt(switch_core_session_t *session, switch_media_type_t type, switch_payload_t pt);
 SWITCH_DECLARE(void) switch_core_media_set_telephony_event(switch_core_session_t *session, switch_media_type_t type, switch_payload_t te);
 SWITCH_DECLARE(void) switch_core_media_set_telephony_recv_event(switch_core_session_t *session, switch_media_type_t type, switch_payload_t te);
 SWITCH_DECLARE(switch_rtp_stats_t *) switch_core_media_stats(switch_core_session_t *session, switch_media_type_t type, switch_memory_pool_t *pool);
@@ -257,6 +305,14 @@ SWITCH_DECLARE(void) switch_core_media_deinit(void);
 SWITCH_DECLARE(void) switch_core_media_set_stats(switch_core_session_t *session);
 SWITCH_DECLARE(void) switch_core_session_wake_video_thread(switch_core_session_t *session);
 SWITCH_DECLARE(void) switch_core_session_clear_crypto(switch_core_session_t *session);
+SWITCH_DECLARE(payload_map_t *) switch_core_media_add_payload_map(switch_core_session_t *session, 
+                                                                                                                                 switch_media_type_t type,
+                                                                                                                                 const char *name, 
+                                                                                                                                 switch_sdp_type_t sdp_type,
+                                                                                                                                 uint32_t pt, 
+                                                                                                                                 uint32_t rate, 
+                                                                                                                                 uint32_t ptime, 
+                                                                                                                                 uint8_t negotiated);
 
 SWITCH_END_EXTERN_C
 #endif
index 39ffb9ca6b2c9996bd174855796871c263e9c9d1..4e46b61d2f10e660a87485b0f5059161509f84c2 100644 (file)
@@ -37,6 +37,7 @@
 #define SWITCH_FRAME_H
 
 #include <switch.h>
+#include <switch_core_media.h>
 
 SWITCH_BEGIN_EXTERN_C
 /*! \brief An abstraction of a data frame */
@@ -71,6 +72,7 @@ SWITCH_BEGIN_EXTERN_C
        /*! frame flags */
        switch_frame_flag_t flags;
        void *user_data;
+       payload_map_t *pmap;
 };
 
 SWITCH_END_EXTERN_C
index bd509cc29ab2a2ed1a58862432fe41af16fba37d..ca0b3f3b8df7c4422c3c1d3066d35dc95b1bde26 100644 (file)
@@ -485,7 +485,6 @@ SWITCH_DECLARE(void) switch_rtp_set_private(switch_rtp_t *rtp_session, void *pri
 */
 SWITCH_DECLARE(void) switch_rtp_set_telephony_event(switch_rtp_t *rtp_session, switch_payload_t te);
 SWITCH_DECLARE(void) switch_rtp_set_telephony_recv_event(switch_rtp_t *rtp_session, switch_payload_t te);
-SWITCH_DECLARE(void) switch_rtp_set_recv_pt(switch_rtp_t *rtp_session, switch_payload_t pt);
 
 /*! 
   \brief Set the payload type for comfort noise
@@ -500,7 +499,7 @@ SWITCH_DECLARE(void) switch_rtp_set_cng_pt(switch_rtp_t *rtp_session, switch_pay
   \return the pointer to the private data
 */
 SWITCH_DECLARE(void *) switch_rtp_get_private(switch_rtp_t *rtp_session);
-
+SWITCH_DECLARE(switch_status_t) switch_rtp_set_payload_map(switch_rtp_t *rtp_session, payload_map_t **pmap);
 SWITCH_DECLARE(void) switch_rtp_intentional_bugs(switch_rtp_t *rtp_session, switch_rtp_bug_flag_t bugs);
 
 SWITCH_DECLARE(switch_rtp_stats_t *) switch_rtp_get_stats(switch_rtp_t *rtp_session, switch_memory_pool_t *pool);
index 8f3f1a81b896c99620ed110bc517bf03f50594a3..2d7a9df244c341f917e566e3e8d6dcda5e990401 100644 (file)
@@ -184,7 +184,8 @@ typedef enum {
        MFLAG_NOMOH = (1 << 19),
        MFLAG_VIDEO_BRIDGE = (1 << 20),
        MFLAG_INDICATE_MUTE_DETECT = (1 << 21),
-       MFLAG_PAUSE_RECORDING = (1 << 22)
+       MFLAG_PAUSE_RECORDING = (1 << 22),
+       MFLAG_ACK_VIDEO = (1 << 23)
 } member_flag_t;
 
 typedef enum {
@@ -1796,6 +1797,10 @@ static switch_status_t conference_add_member(conference_obj_t *conference, confe
 
                channel = switch_core_session_get_channel(member->session);
 
+               if (switch_channel_test_flag(channel, CF_VIDEO)) {
+                       switch_set_flag_locked(member, MFLAG_ACK_VIDEO);
+               }
+
                switch_channel_set_variable_printf(channel, "conference_member_id", "%d", member->id);
                switch_channel_set_variable_printf(channel, "conference_moderator", "%s", switch_test_flag(member, MFLAG_MOD) ? "true" : "false");
                switch_channel_set_variable(channel, "conference_recording", conference->record_filename);
@@ -2595,6 +2600,7 @@ static void *SWITCH_THREAD_FUNC conference_thread_run(switch_thread_t *thread, v
                                char *rfile = switch_channel_expand_variables(channel, conference->auto_record);
                                switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Auto recording file: %s\n", rfile);
                                launch_conference_record_thread(conference, rfile, SWITCH_TRUE);
+
                                if (rfile != conference->auto_record) {
                                        conference->record_filename = switch_core_strdup(conference->pool, rfile);
                                        switch_safe_free(rfile);
@@ -3639,6 +3645,12 @@ static void *SWITCH_THREAD_FUNC conference_loop_input(switch_thread_t *thread, v
                        break;
                }
 
+               if (switch_channel_test_flag(channel, CF_VIDEO) && !switch_test_flag(member, MFLAG_ACK_VIDEO)) {
+                       switch_set_flag_locked(member, MFLAG_ACK_VIDEO);
+                       switch_channel_clear_flag(channel, CF_VIDEO_ECHO);
+                       switch_core_session_refresh_video(member->session);
+               }
+
                /* if we have caller digits, feed them to the parser to find an action */
                if (switch_channel_has_dtmf(channel)) {
                        char dtmf[128] = "";
@@ -8410,8 +8422,8 @@ SWITCH_STANDARD_APP(conference_function)
        msg.from = __FILE__;
 
        /* Tell the channel we are going to be in a bridge */
-       msg.message_id = SWITCH_MESSAGE_INDICATE_BRIDGE;
-       switch_core_session_receive_message(session, &msg);
+       //msg.message_id = SWITCH_MESSAGE_INDICATE_BRIDGE;
+       //switch_core_session_receive_message(session, &msg);
 
        /* Run the conference loop */
        conference_loop_output(&member);
index 121b9ab0c97fd7d0d4858632850fecff586aaaa7..0fe64c72b8b9dbae4017b231edad876af82904ba 100644 (file)
@@ -83,9 +83,21 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_vp8_load)
        /* connect my internal structure to the blank pointer passed to me */
        *module_interface = switch_loadable_module_create_module_interface(pool, modname);
        SWITCH_ADD_CODEC(codec_interface, "VP8 Video (passthru)");
+
        switch_core_codec_add_implementation(pool, codec_interface,
                                                                                 SWITCH_CODEC_TYPE_VIDEO, 99, "VP8", NULL, 90000, 90000, 0,
                                                                                 0, 0, 0, 0, 1, 1, switch_vp8_init, switch_vp8_encode, switch_vp8_decode, switch_vp8_destroy);
+
+       SWITCH_ADD_CODEC(codec_interface, "red Video (passthru)");
+       switch_core_codec_add_implementation(pool, codec_interface,
+                                                                                SWITCH_CODEC_TYPE_VIDEO, 103, "red", NULL, 90000, 90000, 0,
+                                                                                0, 0, 0, 0, 1, 1, switch_vp8_init, switch_vp8_encode, switch_vp8_decode, switch_vp8_destroy);
+
+       SWITCH_ADD_CODEC(codec_interface, "ulpfec Video (passthru)");
+       switch_core_codec_add_implementation(pool, codec_interface,
+                                                                                SWITCH_CODEC_TYPE_VIDEO, 103, "ulpfec", NULL, 90000, 90000, 0,
+                                                                                0, 0, 0, 0, 1, 1, switch_vp8_init, switch_vp8_encode, switch_vp8_decode, switch_vp8_destroy);
+
        /* indicate that the module should continue to be loaded */
        return SWITCH_STATUS_SUCCESS;
 }
index 7286c5de1656b43205a0d5894a63a52822021ae8..dc6351799da41c78c976759198e5190d9a8742f3 100644 (file)
@@ -626,13 +626,14 @@ static switch_status_t sofia_answer_channel(switch_core_session_t *session)
 
                switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "3PCC-PROXY nomedia - sending ack\n");
                nua_ack(tech_pvt->nh,
-                       TAG_IF(!zstr(tech_pvt->user_via), SIPTAG_VIA_STR(tech_pvt->user_via)),
-                       SIPTAG_CONTACT_STR(tech_pvt->reply_contact),
-                       SOATAG_USER_SDP_STR(tech_pvt->mparams.local_sdp_str),
-                       SOATAG_REUSE_REJECTED(1),
-                       SOATAG_RTP_SELECT(1), SOATAG_ORDERED_USER(1), SOATAG_AUDIO_AUX("cn telephone-event"),
-                       TAG_IF(sofia_test_pflag(tech_pvt->profile, PFLAG_DISABLE_100REL), NUTAG_INCLUDE_EXTRA_SDP(1)),
-                       TAG_END());
+                               TAG_IF(!zstr(tech_pvt->user_via), SIPTAG_VIA_STR(tech_pvt->user_via)),
+                               SIPTAG_CONTACT_STR(tech_pvt->reply_contact),
+                               SOATAG_USER_SDP_STR(tech_pvt->mparams.local_sdp_str),
+                               SOATAG_REUSE_REJECTED(1),
+                               SOATAG_RTP_SELECT(1), 
+                               SOATAG_ORDERED_USER(1), SOATAG_AUDIO_AUX("cn telephone-event"),
+                               TAG_IF(sofia_test_pflag(tech_pvt->profile, PFLAG_DISABLE_100REL), NUTAG_INCLUDE_EXTRA_SDP(1)),
+                               TAG_END());
                sofia_clear_flag(tech_pvt, TFLAG_3PCC_INVITE); // all done
                sofia_set_flag_locked(tech_pvt, TFLAG_ANS);
                sofia_set_flag_locked(tech_pvt, TFLAG_SDP);
@@ -667,7 +668,7 @@ static switch_status_t sofia_answer_channel(switch_core_session_t *session)
                        tech_pvt->mparams.local_sdp_str = NULL;
 
                        switch_core_media_choose_port(tech_pvt->session, SWITCH_MEDIA_TYPE_AUDIO, 0);
-                       switch_core_media_gen_local_sdp(session, NULL, 0, NULL, 0);
+                       switch_core_media_gen_local_sdp(session, SDP_TYPE_RESPONSE, NULL, 0, NULL, 0);
                        } else {
                                switch_core_media_set_local_sdp(session, b_sdp, SWITCH_TRUE);
 
@@ -683,12 +684,14 @@ static switch_status_t sofia_answer_channel(switch_core_session_t *session)
                        if (!sofia_test_flag(tech_pvt, TFLAG_BYE)) {
                                char *extra_headers = sofia_glue_get_extra_headers(channel, SOFIA_SIP_RESPONSE_HEADER_PREFIX);
                                if (sofia_use_soa(tech_pvt)) {
+
                                        nua_respond(tech_pvt->nh, SIP_200_OK,
                                                                TAG_IF(is_proxy, NUTAG_AUTOANSWER(0)),
                                                                SIPTAG_CONTACT_STR(tech_pvt->profile->url),
                                                                SOATAG_USER_SDP_STR(tech_pvt->mparams.local_sdp_str),
                                                                TAG_IF(call_info, SIPTAG_CALL_INFO_STR(call_info)),
-                                                               SOATAG_REUSE_REJECTED(1), TAG_IF(is_proxy, SOATAG_RTP_SELECT(1)),
+                                                               SOATAG_REUSE_REJECTED(1), 
+                                                               SOATAG_RTP_SELECT(1),
                                                                SOATAG_ORDERED_USER(1), SOATAG_AUDIO_AUX("cn telephone-event"), NUTAG_INCLUDE_EXTRA_SDP(1),
                                                                TAG_IF(!zstr(extra_headers), SIPTAG_HEADER_STR(extra_headers)),
                                                                TAG_IF(switch_stristr("update_display", tech_pvt->x_freeswitch_support_remote),
@@ -762,7 +765,7 @@ static switch_status_t sofia_answer_channel(switch_core_session_t *session)
                        return status;
                }
 
-               switch_core_media_gen_local_sdp(session, NULL, 0, NULL, 0);
+               switch_core_media_gen_local_sdp(session, SDP_TYPE_RESPONSE, NULL, 0, NULL, 0);
                if (sofia_media_activate_rtp(tech_pvt) != SWITCH_STATUS_SUCCESS) {
                        switch_channel_hangup(channel, SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER);
                }
@@ -834,7 +837,7 @@ static switch_status_t sofia_answer_channel(switch_core_session_t *session)
                                                SOATAG_USER_SDP_STR(tech_pvt->mparams.local_sdp_str),
                                                SOATAG_REUSE_REJECTED(1), SOATAG_ORDERED_USER(1), SOATAG_AUDIO_AUX("cn telephone-event"),
                                                TAG_IF(sofia_test_pflag(tech_pvt->profile, PFLAG_DISABLE_100REL), NUTAG_INCLUDE_EXTRA_SDP(1)),
-                                               TAG_IF(is_proxy, SOATAG_RTP_SELECT(1)),
+                                               SOATAG_RTP_SELECT(1),
                                                TAG_IF(!zstr(extra_headers), SIPTAG_HEADER_STR(extra_headers)),
                                                TAG_IF(switch_stristr("update_display", tech_pvt->x_freeswitch_support_remote),
                                                           SIPTAG_HEADER_STR("X-FS-Support: " FREESWITCH_SUPPORT)), TAG_END());
@@ -1221,7 +1224,7 @@ static switch_status_t sofia_receive_message(switch_core_session_t *session, swi
                                switch_channel_set_flag(tech_pvt->channel, CF_SECURE);
                        }
 
-                       if (sofia_test_media_flag(tech_pvt->profile, SCMF_AUTOFIX_TIMING) || sofia_test_media_flag(tech_pvt->profile, SCMF_AUTOFIX_PT)) {
+                       if (sofia_test_media_flag(tech_pvt->profile, SCMF_AUTOFIX_TIMING)) {
                                switch_core_media_reset_autofix(tech_pvt->session, SWITCH_MEDIA_TYPE_AUDIO);
                        }
                }
@@ -1264,7 +1267,7 @@ static switch_status_t sofia_receive_message(switch_core_session_t *session, swi
                        ip = switch_channel_get_variable(channel, SWITCH_REMOTE_MEDIA_IP_VARIABLE);
                        port = switch_channel_get_variable(channel, SWITCH_REMOTE_MEDIA_PORT_VARIABLE);
                        if (ip && port) {
-                               switch_core_media_gen_local_sdp(session, ip, (switch_port_t)atoi(port), msg->string_arg, 1);
+                               switch_core_media_gen_local_sdp(session, SDP_TYPE_REQUEST, ip, (switch_port_t)atoi(port), msg->string_arg, 1);
                        }
 
                        if (!sofia_test_flag(tech_pvt, TFLAG_BYE)) {
@@ -1397,7 +1400,7 @@ static switch_status_t sofia_receive_message(switch_core_session_t *session, swi
                                        goto end_lock;
                                }
                        }
-                       switch_core_media_gen_local_sdp(session, NULL, 0, NULL, 1);
+                       switch_core_media_gen_local_sdp(session, SDP_TYPE_REQUEST, NULL, 0, NULL, 1);
 
                        if (send_invite) {
                                if (!switch_channel_test_flag(channel, CF_PROXY_MEDIA)) {
@@ -2081,7 +2084,7 @@ static switch_status_t sofia_receive_message(switch_core_session_t *session, swi
                                                switch_channel_hangup(channel, SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER);
                                                goto end_lock;
                                        }
-                                       switch_core_media_gen_local_sdp(session, NULL, 0, NULL, 0);
+                                       switch_core_media_gen_local_sdp(session, SDP_TYPE_RESPONSE, NULL, 0, NULL, 0);
                                        if (sofia_media_activate_rtp(tech_pvt) != SWITCH_STATUS_SUCCESS) {
                                                switch_channel_hangup(channel, SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER);
                                        }
index a34b8cfd7429d7335f9aae23551288808419bb6c..a1467f9647f69840bd003224faf0962b627e7098 100644 (file)
@@ -513,7 +513,7 @@ static switch_status_t channel_receive_event(switch_core_session_t *session, swi
                }
 
                switch_rtp_set_default_payload(tech_pvt->rtp_session, pt);
-               switch_rtp_set_recv_pt(tech_pvt->rtp_session, pt);
+               //switch_rtp_set_recv_pt(tech_pvt->rtp_session, pt);
        }
         
         if (compare_var(event, channel, kRFC2833PT)) {
index f2194487d49759bfc973dd30d3cd1fc203ab8f48..0a98cbf9830eb9d27b67118ec790848866b9ac79 100644 (file)
@@ -3743,7 +3743,7 @@ switch_status_t config_sofia(sofia_config_t reload, char *profile_name)
                                        sofia_set_pflag(profile, PFLAG_DISABLE_100REL);
                                        profile->auto_restart = 1;
                                        sofia_set_media_flag(profile, SCMF_AUTOFIX_TIMING);
-                                       sofia_set_media_flag(profile, SCMF_AUTOFIX_PT);
+                                       sofia_set_media_flag(profile, SCMF_RENEG_ON_REINVITE);
                                        sofia_set_media_flag(profile, SCMF_RTP_AUTOFLUSH_DURING_BRIDGE);
                                        profile->contact_user = SOFIA_DEFAULT_CONTACT_USER;
                                        sofia_set_pflag(profile, PFLAG_PASS_CALLEE_ID);
@@ -4381,12 +4381,6 @@ switch_status_t config_sofia(sofia_config_t reload, char *profile_name)
                                                } else {
                                                        sofia_clear_media_flag(profile, SCMF_AUTOFIX_TIMING);
                                                }
-                                       } else if (!strcasecmp(var, "rtp-autofix-pt")) {
-                                               if (switch_true(val)) {
-                                                       sofia_set_media_flag(profile, SCMF_AUTOFIX_PT);
-                                               } else {
-                                                       sofia_clear_media_flag(profile, SCMF_AUTOFIX_PT);
-                                               }
                                        } else if (!strcasecmp(var, "contact-user")) {
                                                profile->contact_user = switch_core_strdup(profile->pool, val);
                                        } else if (!strcasecmp(var, "nat-options-ping")) {
@@ -5250,7 +5244,7 @@ static void sofia_handle_sip_r_invite(switch_core_session_t *session, int status
 
                        sofia_update_callee_id(session, profile, sip, SWITCH_FALSE);
 
-                       if (sofia_test_media_flag(tech_pvt->profile, SCMF_AUTOFIX_TIMING) || sofia_test_media_flag(tech_pvt->profile, SCMF_AUTOFIX_PT)) {
+                       if (sofia_test_media_flag(tech_pvt->profile, SCMF_AUTOFIX_TIMING)) {
                                switch_core_media_reset_autofix(tech_pvt->session, SWITCH_MEDIA_TYPE_AUDIO);
                        }
 
@@ -6204,7 +6198,7 @@ static void sofia_handle_sip_i_state(switch_core_session_t *session, int status,
                                        } else {
                                                switch_channel_set_variable(channel, SWITCH_ENDPOINT_DISPOSITION_VARIABLE, "RECEIVED_NOSDP");
                                                switch_core_media_choose_port(tech_pvt->session, SWITCH_MEDIA_TYPE_AUDIO, 0);
-                                               switch_core_media_gen_local_sdp(session, NULL, 0, NULL, 0);
+                                               switch_core_media_gen_local_sdp(session, SDP_TYPE_RESPONSE, NULL, 0, NULL, 0);
                                                sofia_set_flag_locked(tech_pvt, TFLAG_3PCC);
                                                switch_channel_set_state(channel, CS_HIBERNATE);
                                                if (sofia_use_soa(tech_pvt)) {
@@ -6321,7 +6315,7 @@ static void sofia_handle_sip_i_state(switch_core_session_t *session, int status,
                                                                                goto done;
                                                                        }
                                                                }
-                                                               switch_core_media_gen_local_sdp(session, NULL, 0, NULL, 1);
+                                                               switch_core_media_gen_local_sdp(session, SDP_TYPE_RESPONSE, NULL, 0, NULL, 1);
 
                                                                if (sofia_use_soa(tech_pvt)) {
                                                                        nua_respond(tech_pvt->nh, SIP_200_OK,
@@ -6427,7 +6421,7 @@ static void sofia_handle_sip_i_state(switch_core_session_t *session, int status,
                                                        goto done;
                                                }
 
-                                               switch_core_media_gen_local_sdp(session, NULL, 0, NULL, 0);
+                                               switch_core_media_gen_local_sdp(session, SDP_TYPE_RESPONSE, NULL, 0, NULL, 0);
 
                                                if (sofia_media_activate_rtp(tech_pvt) != SWITCH_STATUS_SUCCESS) {
                                                        switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Reinvite RTP Error!\n");
@@ -6446,7 +6440,7 @@ static void sofia_handle_sip_i_state(switch_core_session_t *session, int status,
                                if (is_ok) {
 
                                        if (switch_core_session_local_crypto_key(tech_pvt->session, SWITCH_MEDIA_TYPE_AUDIO)) {
-                                               switch_core_media_gen_local_sdp(session, NULL, 0, NULL, 0);
+                                               switch_core_media_gen_local_sdp(session, SDP_TYPE_RESPONSE, NULL, 0, NULL, 0);
                                        }
                                        if (sofia_use_soa(tech_pvt)) {
                                                nua_respond(tech_pvt->nh, SIP_200_OK,
@@ -6486,7 +6480,7 @@ static void sofia_handle_sip_i_state(switch_core_session_t *session, int status,
                                if (switch_core_media_choose_port(tech_pvt->session, SWITCH_MEDIA_TYPE_AUDIO, 0) != SWITCH_STATUS_SUCCESS) {
                                        goto done;
                                }
-                               switch_core_media_gen_local_sdp(session, NULL, 0, NULL, 0);
+                               switch_core_media_gen_local_sdp(session, SDP_TYPE_RESPONSE, NULL, 0, NULL, 0);
 
                                switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Processing updated SDP\n");
                                switch_channel_set_flag(tech_pvt->channel, CF_REINVITE);
index 833a725d44c4c7477c6c7d9cc144e1094b9583ce..d5bbe14c55fd9cc320122c1f14ba3895ceb4bfdc 100644 (file)
@@ -752,7 +752,7 @@ switch_status_t sofia_glue_do_invite(switch_core_session_t *session)
        }
 
        if (!switch_channel_get_private(tech_pvt->channel, "t38_options") || zstr(tech_pvt->mparams.local_sdp_str)) {
-               switch_core_media_gen_local_sdp(session, NULL, 0, NULL, 0);
+               switch_core_media_gen_local_sdp(session, SDP_TYPE_REQUEST, NULL, 0, NULL, 0);
        }
 
        sofia_set_flag_locked(tech_pvt, TFLAG_READY);
index b1b42c7f1f2973a4ebb9f342574c7eb59c602c04..1a5a0469feb172349a8ba5025c475ed29c1e8eb9 100644 (file)
@@ -644,8 +644,15 @@ SWITCH_DECLARE(switch_status_t) switch_core_session_read_frame(switch_core_sessi
                        default:
                                switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Codec %s decoder error! [%d]\n",
                                                                  session->read_codec->codec_interface->interface_name, status);
-                               goto done;
+
+                               if (++session->decoder_errors < 10) {
+                                       status = SWITCH_STATUS_SUCCESS;
+                               } else {
+                                       goto done;
+                               }
                        }
+
+                       session->decoder_errors = 0;
                }
 
                if (session->bugs) {
index d18b648546fea2997a0a4e0e9111df5a5d616490..59eacde94c67410b88b1a967ee9a176bc4e123bc 100644 (file)
@@ -68,36 +68,7 @@ typedef struct secure_settings_s {
        char *remote_crypto_key;
 } switch_secure_settings_t;
 
-typedef struct codec_params_s {
-       char *rm_encoding;
-       char *iananame;
-       switch_payload_t pt;
-       unsigned long rm_rate;
-       unsigned long adv_rm_rate;
-       uint32_t codec_ms;
-       uint32_t bitrate;
 
-       char *rm_fmtp;
-
-       switch_payload_t agreed_pt;
-       switch_payload_t recv_pt;
-       char *fmtp_out;
-
-
-       char *remote_sdp_ip;
-       switch_port_t remote_sdp_port;
-
-       char *local_sdp_ip;
-       switch_port_t local_sdp_port;
-
-       char *adv_sdp_ip;
-       switch_port_t adv_sdp_port;
-       char *proxy_sdp_ip;
-       switch_port_t proxy_sdp_port;
-       int channels;
-       int adv_channels;
-
-} codec_params_t;
 
 struct media_helper {
        switch_core_session_t *session;
@@ -106,6 +77,7 @@ struct media_helper {
        int up;
 };
 
+
 typedef struct switch_rtp_engine_s {
        switch_secure_settings_t ssec;
        switch_media_type_t type;
@@ -130,12 +102,23 @@ typedef struct switch_rtp_engine_s {
        switch_port_t remote_rtcp_port;
        switch_rtp_bug_flag_t rtp_bugs;
 
+
+       char *local_sdp_ip;
+       switch_port_t local_sdp_port;
+       char *adv_sdp_ip;
+       switch_port_t adv_sdp_port;
+       char *proxy_sdp_ip;
+       switch_port_t proxy_sdp_port;
+
+
        /** ZRTP **/
        char *local_sdp_zrtp_hash;
        char *remote_sdp_zrtp_hash;
 
+       payload_map_t *cur_payload_map;
+       payload_map_t *payload_map;
+       payload_map_t *pmap_tail;
 
-       codec_params_t codec_params;
        uint32_t timestamp_send;
 
        char *cand_acl[SWITCH_MAX_CAND_ACL];
@@ -159,6 +142,8 @@ typedef struct switch_rtp_engine_s {
        switch_thread_t *media_thread;
        switch_mutex_t *read_mutex;
 
+       uint8_t reset_codec;
+       uint8_t codec_negotiated;
 } switch_rtp_engine_t;
 
 
@@ -442,11 +427,11 @@ SWITCH_DECLARE(switch_status_t) switch_core_media_process_t38_passthru(switch_co
        remote_host = switch_rtp_get_remote_host(a_engine->rtp_session);
        remote_port = switch_rtp_get_remote_port(a_engine->rtp_session);
        
-       a_engine->codec_params.remote_sdp_ip = switch_core_session_strdup(session, t38_options->remote_ip);
-       a_engine->codec_params.remote_sdp_port = t38_options->remote_port;
+       a_engine->cur_payload_map->remote_sdp_ip = switch_core_session_strdup(session, t38_options->remote_ip);
+       a_engine->cur_payload_map->remote_sdp_port = t38_options->remote_port;
                                                        
-       if (remote_host && remote_port && !strcmp(remote_host, a_engine->codec_params.remote_sdp_ip) && 
-               remote_port == a_engine->codec_params.remote_sdp_port) {
+       if (remote_host && remote_port && !strcmp(remote_host, a_engine->cur_payload_map->remote_sdp_ip) && 
+               remote_port == a_engine->cur_payload_map->remote_sdp_port) {
                switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, 
                                                  "Audio params are unchanged for %s.\n",
                                                  switch_channel_get_name(session->channel));
@@ -456,13 +441,13 @@ SWITCH_DECLARE(switch_status_t) switch_core_media_process_t38_passthru(switch_co
                switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, 
                                                  "Audio params changed for %s from %s:%d to %s:%d\n",
                                                  switch_channel_get_name(session->channel),
-                                                 remote_host, remote_port, a_engine->codec_params.remote_sdp_ip, a_engine->codec_params.remote_sdp_port);
+                                                 remote_host, remote_port, a_engine->cur_payload_map->remote_sdp_ip, a_engine->cur_payload_map->remote_sdp_port);
                        
-               switch_snprintf(tmp, sizeof(tmp), "%d", a_engine->codec_params.remote_sdp_port);
-               switch_channel_set_variable(session->channel, SWITCH_REMOTE_MEDIA_IP_VARIABLE, a_engine->codec_params.remote_sdp_ip);
+               switch_snprintf(tmp, sizeof(tmp), "%d", a_engine->cur_payload_map->remote_sdp_port);
+               switch_channel_set_variable(session->channel, SWITCH_REMOTE_MEDIA_IP_VARIABLE, a_engine->cur_payload_map->remote_sdp_ip);
                switch_channel_set_variable(session->channel, SWITCH_REMOTE_MEDIA_PORT_VARIABLE, tmp);
-               if (switch_rtp_set_remote_address(a_engine->rtp_session, a_engine->codec_params.remote_sdp_ip,
-                                                                                 a_engine->codec_params.remote_sdp_port, 0, SWITCH_TRUE, &err) != SWITCH_STATUS_SUCCESS) {
+               if (switch_rtp_set_remote_address(a_engine->rtp_session, a_engine->cur_payload_map->remote_sdp_ip,
+                                                                                 a_engine->cur_payload_map->remote_sdp_port, 0, SWITCH_TRUE, &err) != SWITCH_STATUS_SUCCESS) {
                        switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "AUDIO RTP REPORTS ERROR: [%s]\n", err);
                        switch_channel_hangup(session->channel, SWITCH_CAUSE_INCOMPATIBLE_DESTINATION);
                }
@@ -475,6 +460,81 @@ SWITCH_DECLARE(switch_status_t) switch_core_media_process_t38_passthru(switch_co
 }
 
 
+SWITCH_DECLARE(payload_map_t *) switch_core_media_add_payload_map(switch_core_session_t *session, 
+                                                                                                                                 switch_media_type_t type,
+                                                                                                                                 const char *name, 
+                                                                                                                                 switch_sdp_type_t sdp_type,
+                                                                                                                                 uint32_t pt, 
+                                                                                                                                 uint32_t rate, 
+                                                                                                                                 uint32_t ptime, 
+                                                                                                                                 uint8_t negotiated)
+{
+       payload_map_t *pmap;
+       int exists = 0;
+       switch_media_handle_t *smh;
+       switch_rtp_engine_t *engine;
+
+       switch_assert(session);
+
+       if (!(smh = session->media_handle)) {
+               return NULL;
+       }
+
+       engine = &smh->engines[type];
+
+       switch_mutex_lock(smh->mutex);
+
+
+       for (pmap = engine->payload_map; pmap && pmap->allocated; pmap = pmap->next) {
+               exists = (!strcasecmp(name, pmap->iananame) && rate == pmap->rate && pmap->ptime == ptime);
+               
+               if (exists) {
+                       break;
+               }
+       }
+
+
+       if (!exists) {
+               if (engine->payload_map && !engine->payload_map->allocated) {
+                       pmap = engine->payload_map;
+               } else {
+                       pmap = switch_core_alloc(session->pool, sizeof(*pmap));
+               }
+
+               pmap->sdp_type = sdp_type;
+               pmap->type = type;
+               pmap->iananame = switch_core_strdup(session->pool, name);
+               pmap->rm_encoding = pmap->iananame;
+               pmap->ptime = ptime;
+               pmap->rate = rate;
+       }
+
+       pmap->allocated = 1;
+       pmap->recv_pt = pt;
+
+       if (sdp_type == SDP_TYPE_REQUEST || !exists) {
+               pmap->pt = pt;
+       }
+
+       if (negotiated) {
+               pmap->negotiated = negotiated;
+       }
+
+       if (!exists) {
+               if (pmap == engine->payload_map) {
+                       engine->pmap_tail = pmap;
+               } else if (!engine->payload_map) {
+                       engine->payload_map = engine->pmap_tail = pmap;
+               } else {
+                       engine->pmap_tail->next = pmap;
+                       engine->pmap_tail = engine->pmap_tail->next;
+               }
+       }
+       
+       switch_mutex_unlock(smh->mutex);
+
+       return pmap;
+}
 
 
 
@@ -1058,8 +1118,6 @@ SWITCH_DECLARE(switch_status_t) switch_media_handle_create(switch_media_handle_t
 {
        switch_status_t status = SWITCH_STATUS_FALSE;
        switch_media_handle_t *smh = NULL;
-
-
        *smhp = NULL;
 
        if (zstr(params->sdp_username)) {
@@ -1069,6 +1127,8 @@ SWITCH_DECLARE(switch_status_t) switch_media_handle_create(switch_media_handle_t
 
        if ((session->media_handle = switch_core_session_alloc(session, (sizeof(*smh))))) {
                session->media_handle->session = session;
+
+
                *smhp = session->media_handle;
                switch_set_flag(session->media_handle, SMF_INIT);
                session->media_handle->media_flags[SCMF_RUNNING] = 1;
@@ -1079,6 +1139,7 @@ SWITCH_DECLARE(switch_status_t) switch_media_handle_create(switch_media_handle_t
                session->media_handle->mparams = params;
 
 
+
                switch_mutex_init(&session->media_handle->mutex, SWITCH_MUTEX_NESTED, switch_core_session_get_pool(session));
 
                session->media_handle->engines[SWITCH_MEDIA_TYPE_AUDIO].ssrc = 
@@ -1087,6 +1148,12 @@ SWITCH_DECLARE(switch_status_t) switch_media_handle_create(switch_media_handle_t
                session->media_handle->engines[SWITCH_MEDIA_TYPE_VIDEO].ssrc = 
                        (uint32_t) ((intptr_t) &session->media_handle->engines[SWITCH_MEDIA_TYPE_VIDEO] + (uint32_t) time(NULL) / 2);
 
+               session->media_handle->engines[SWITCH_MEDIA_TYPE_AUDIO].payload_map = switch_core_alloc(session->pool, sizeof(payload_map_t));
+               session->media_handle->engines[SWITCH_MEDIA_TYPE_AUDIO].cur_payload_map = session->media_handle->engines[SWITCH_MEDIA_TYPE_AUDIO].payload_map;
+               session->media_handle->engines[SWITCH_MEDIA_TYPE_VIDEO].payload_map = switch_core_alloc(session->pool, sizeof(payload_map_t));
+               session->media_handle->engines[SWITCH_MEDIA_TYPE_VIDEO].cur_payload_map = session->media_handle->engines[SWITCH_MEDIA_TYPE_VIDEO].payload_map;
+
+
                switch_channel_set_flag(session->channel, CF_DTLS_OK);
 
                status = SWITCH_STATUS_SUCCESS;
@@ -1242,6 +1309,7 @@ SWITCH_DECLARE(switch_status_t) switch_core_media_read_frame(switch_core_session
        switch_rtp_engine_t *engine;
        switch_status_t status;
        switch_media_handle_t *smh;
+       int do_cng = 0;
 
        switch_assert(session);
 
@@ -1299,6 +1367,85 @@ SWITCH_DECLARE(switch_status_t) switch_core_media_read_frame(switch_core_session
                        goto end;
                }
 
+               /* re-set codec if necessary */
+               if (engine->reset_codec > 0) {
+                       const char *val;
+                       int rtp_timeout_sec = 0;
+                       int rtp_hold_timeout_sec = 0;
+
+                       engine->reset_codec = 0;
+                                       
+                       if (switch_rtp_ready(engine->rtp_session)) {
+                               if (switch_core_media_set_codec(session, 1, 0) != SWITCH_STATUS_SUCCESS) {
+                                       *frame = NULL;
+                                       switch_goto_status(SWITCH_STATUS_GENERR, end);
+                               }
+
+                               if ((val = switch_channel_get_variable(session->channel, "rtp_timeout_sec"))) {
+                                       int v = atoi(val);
+                                       if (v >= 0) {
+                                               rtp_timeout_sec = v;
+                                       }
+                               }
+                               
+                               if ((val = switch_channel_get_variable(session->channel, "rtp_hold_timeout_sec"))) {
+                                       int v = atoi(val);
+                                       if (v >= 0) {
+                                               rtp_hold_timeout_sec = v;
+                                       }
+                               }
+
+                               if (rtp_timeout_sec) {
+                                       engine->max_missed_packets = (engine->read_impl.samples_per_second * rtp_timeout_sec) /
+                                               engine->read_impl.samples_per_packet;
+
+                                       switch_rtp_set_max_missed_packets(engine->rtp_session, engine->max_missed_packets);
+                                       if (!rtp_hold_timeout_sec) {
+                                               rtp_hold_timeout_sec = rtp_timeout_sec * 10;
+                                       }
+                               }
+
+                               if (rtp_hold_timeout_sec) {
+                                       engine->max_missed_hold_packets = (engine->read_impl.samples_per_second * rtp_hold_timeout_sec) /
+                                               engine->read_impl.samples_per_packet;
+                               }
+                       }
+
+                       
+                       if (session->read_resampler) {
+                               switch_mutex_lock(session->resample_mutex);
+                               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);
+                       }
+
+                       if (session->write_resampler) {
+                               switch_mutex_lock(session->resample_mutex);
+                               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_reset(session, 0, 0);
+
+
+                       engine->check_frames = 0;
+                       engine->last_ts = 0;
+
+                       switch_channel_audio_sync(session->channel);
+                       do_cng = 1;
+               }
+
+               if (do_cng) {
+                       /* return CNG for now */
+                       *frame = &engine->read_frame;
+                       switch_set_flag((*frame), SFF_CNG);
+                       (*frame)->datalen = engine->read_impl.encoded_bytes_per_packet;
+                       memset((*frame)->data, 0, (*frame)->datalen);
+                       switch_goto_status(SWITCH_STATUS_SUCCESS, end);
+               }
+                               
+
                /* Try to read an RTCP frame, if successful raise an event */
                if (switch_rtcp_zerocopy_read_frame(engine->rtp_session, &rtcp_frame) == SWITCH_STATUS_SUCCESS) {
                        switch_event_t *event;
@@ -1381,22 +1528,21 @@ SWITCH_DECLARE(switch_status_t) switch_core_media_read_frame(switch_core_session
                        switch_rtp_dequeue_dtmf(engine->rtp_session, &dtmf);
                        switch_channel_queue_dtmf(session->channel, &dtmf);
                }
-
+               
                if (engine->read_frame.datalen > 0) {
                        uint32_t bytes = 0;
                        int frames = 1;
 
+                       /* autofix timing */
                        if (!switch_test_flag((&engine->read_frame), SFF_CNG)) {
                                if (!engine->read_codec.implementation || !switch_core_codec_ready(&engine->read_codec)) {
                                        *frame = NULL;
                                        switch_goto_status(SWITCH_STATUS_GENERR, end);
                                }
+                               
+                               /* check for timing issues */
+                               if (smh->media_flags[SCMF_AUTOFIX_TIMING] && engine->check_frames < MAX_CODEC_CHECK_FRAMES) {
 
-                               /* check for timing or codec issues */
-                               if ((smh->media_flags[SCMF_AUTOFIX_TIMING] || smh->media_flags[SCMF_AUTOFIX_PT]) &&
-                                       engine->check_frames < MAX_CODEC_CHECK_FRAMES) {
-
-                                       int reset_codec = 0;
 
                                        engine->check_frames++;
 
@@ -1404,62 +1550,9 @@ SWITCH_DECLARE(switch_status_t) switch_core_media_read_frame(switch_core_session
                                                engine->check_frames = MAX_CODEC_CHECK_FRAMES;
                                                goto skip;
                                        }
-
-                                       /* autofix payload type */
-                                       if (smh->media_flags[SCMF_AUTOFIX_PT] &&
-                                               engine->read_frame.payload != smh->mparams->cng_pt &&
-                                               engine->read_frame.payload != smh->mparams->recv_te &&
-                                               engine->read_frame.payload != smh->mparams->te &&
-                                               engine->read_frame.payload != engine->codec_params.recv_pt &&
-                                               engine->read_frame.payload != engine->codec_params.agreed_pt &&
-                                               engine->read_frame.payload != engine->codec_params.pt) {
-
-                                               int i = 0;
-
-                                               switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_WARNING,
-                                                                                 "Invalid payload received (received %d, expecting %d). "
-                                                                                 "FS doesn't support multiple payload types in a single RTP session.\n",
-                                                                                 (int) engine->read_frame.payload, (int) engine->codec_params.agreed_pt);
-
-                                               /* search for payload type */
-                                               for (i = 0; i < smh->mparams->num_codecs; i++) {
-                                                       if (engine->read_frame.payload == smh->ianacodes[i]) {
-                                                               const switch_codec_implementation_t *imp = smh->codecs[i];
-
-                                                               switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_WARNING,
-                                                                                                 "Changing current codec to %s (payload type %d).\n",
-                                                                                                 imp->iananame, (int) engine->read_frame.payload);
-
-                                                               engine->codec_params.iananame = switch_core_session_strdup(smh->session, imp->iananame);
-                                                               engine->codec_params.pt = imp->ianacode;
-                                                               engine->codec_params.agreed_pt = imp->ianacode;
-                                                               engine->codec_params.recv_pt = imp->ianacode;
-                                                               engine->codec_params.rm_encoding = switch_core_session_strdup(smh->session, imp->iananame);
-                                                               engine->codec_params.rm_fmtp = NULL;
-                                                               engine->codec_params.rm_rate = imp->samples_per_second;
-                                                               engine->codec_params.adv_rm_rate = imp->samples_per_second;
-                                                               if (strcasecmp(imp->iananame, "g722")) {
-                                                                       engine->codec_params.rm_rate = imp->actual_samples_per_second;
-                                                               }
-                                                               engine->codec_params.codec_ms = imp->microseconds_per_packet / 1000;
-                                                               engine->codec_params.bitrate = imp->bits_per_second;
-                                                               engine->codec_params.channels = 1;
-
-                                                               /* mark to re-set codec */
-                                                               reset_codec = 1;
-                                                               break;
-                                                       }
-                                               }
-
-                                               if (!reset_codec) {
-                                                       switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_WARNING,
-                                                                                         "Could not change to payload type %d, ignoring...\n",
-                                                                                         (int) engine->read_frame.payload);
-                                               }
-
-                                       /* autofix timing */
-                                       } else if (smh->media_flags[SCMF_AUTOFIX_TIMING] && (engine->read_frame.datalen % 10) == 0) {
-
+                                       
+                                       if (smh->media_flags[SCMF_AUTOFIX_TIMING] && (engine->read_frame.datalen % 10) == 0) {
+                                               
                                                if (engine->last_ts && engine->read_frame.datalen != engine->read_impl.encoded_bytes_per_packet) {
 
                                                        uint32_t codec_ms = (int) (engine->read_frame.timestamp -
@@ -1478,7 +1571,7 @@ SWITCH_DECLARE(switch_status_t) switch_core_media_read_frame(switch_core_session
                                                        engine->last_codec_ms = codec_ms;
 
                                                        if (engine->mismatch_count > MAX_MISMATCH_FRAMES) {
-                                                               if (codec_ms != engine->codec_params.codec_ms) {
+                                                               if (codec_ms != engine->cur_payload_map->codec_ms) {
 
                                                                        if (codec_ms > 120) {   /* yeah right */
                                                                                switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_WARNING,
@@ -1491,20 +1584,20 @@ SWITCH_DECLARE(switch_status_t) switch_core_media_read_frame(switch_core_session
 
                                                                        engine->read_frame.datalen = 0;
 
-                                                                       if (codec_ms != engine->codec_params.codec_ms) {
+                                                                       if (codec_ms != engine->cur_payload_map->codec_ms) {
                                                                                switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_WARNING,
                                                                                                                  "Asynchronous PTIME not supported, changing our end from %d to %d\n",
-                                                                                                                 (int) engine->codec_params.codec_ms,
+                                                                                                                 (int) engine->cur_payload_map->codec_ms,
                                                                                                                  (int) codec_ms
                                                                                                                  );
 
                                                                                switch_channel_set_variable_printf(session->channel, "rtp_h_X-Broken-PTIME", "Adv=%d;Sent=%d",
-                                                                                                                                                  (int) engine->codec_params.codec_ms, (int) codec_ms);
+                                                                                                                                                  (int) engine->cur_payload_map->codec_ms, (int) codec_ms);
 
-                                                                               engine->codec_params.codec_ms = codec_ms;
+                                                                               engine->cur_payload_map->codec_ms = codec_ms;
 
                                                                                /* mark to re-set codec */
-                                                                               reset_codec = 2;
+                                                                               engine->reset_codec = 2;
                                                                        }
                                                                }
                                                        }
@@ -1520,58 +1613,48 @@ SWITCH_DECLARE(switch_status_t) switch_core_media_read_frame(switch_core_session
                                                engine->mismatch_count = 0;
                                                engine->last_ts = 0;
                                        }
+                               }
 
-                                       /* re-set codec if necessary */
-                                       if (reset_codec > 0) {
-                                               const char *val;
-                                               int rtp_timeout_sec = 0;
-                                               int rtp_hold_timeout_sec = 0;
+                               /* autofix payload type */
 
-                                               if (switch_rtp_ready(engine->rtp_session)) {
-                                                       if (switch_core_media_set_codec(session, 2, 0) != SWITCH_STATUS_SUCCESS) {
-                                                               *frame = NULL;
-                                                               switch_goto_status(SWITCH_STATUS_GENERR, end);
-                                                       }
-
-                                                       if ((val = switch_channel_get_variable(session->channel, "rtp_timeout_sec"))) {
-                                                               int v = atoi(val);
-                                                               if (v >= 0) {
-                                                                       rtp_timeout_sec = v;
-                                                               }
-                                                       }
+                               if (!engine->reset_codec &&
+                                       engine->codec_negotiated &&
+                                       engine->read_frame.payload != smh->mparams->cng_pt &&
+                                       engine->read_frame.payload != smh->mparams->recv_te &&
+                                       engine->read_frame.payload != smh->mparams->te &&
+                                       engine->read_frame.payload != engine->cur_payload_map->recv_pt &&
+                                       engine->read_frame.payload != engine->cur_payload_map->agreed_pt &&
+                                       engine->read_frame.payload != engine->cur_payload_map->pt) {
+                                       
+                                       payload_map_t *pmap;
+                                       
 
-                                                       if ((val = switch_channel_get_variable(session->channel, "rtp_hold_timeout_sec"))) {
-                                                               int v = atoi(val);
-                                                               if (v >= 0) {
-                                                                       rtp_hold_timeout_sec = v;
-                                                               }
-                                                       }
+                                       switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG,
+                                                                         "alternate payload received (received %d, expecting %d)\n",
+                                                                         (int) engine->read_frame.payload, (int) engine->cur_payload_map->agreed_pt);
 
-                                                       if (rtp_timeout_sec) {
-                                                               engine->max_missed_packets = (engine->read_impl.samples_per_second * rtp_timeout_sec) /
-                                                                       engine->read_impl.samples_per_packet;
 
-                                                               switch_rtp_set_max_missed_packets(engine->rtp_session, engine->max_missed_packets);
-                                                               if (!rtp_hold_timeout_sec) {
-                                                                       rtp_hold_timeout_sec = rtp_timeout_sec * 10;
-                                                               }
-                                                       }
+                                       /* search for payload type */
+                                       switch_mutex_lock(smh->mutex);
+                                       for (pmap = engine->cur_payload_map; pmap; pmap = pmap->next) {
+                                               if (engine->read_frame.payload == pmap->recv_pt) {
+                                                       engine->cur_payload_map = pmap;
 
-                                                       if (rtp_hold_timeout_sec) {
-                                                               engine->max_missed_hold_packets = (engine->read_impl.samples_per_second * rtp_hold_timeout_sec) /
-                                                                       engine->read_impl.samples_per_packet;
-                                                       }
+                                                       switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_WARNING,
+                                                                                         "Changing current codec to %s (payload type %d).\n",
+                                                                                         pmap->iananame, pmap->pt);
+                                                               
+                                                       /* mark to re-set codec */
+                                                       engine->reset_codec = 1;
+                                                       break;
                                                }
-
-                                               engine->check_frames = 0;
-                                               engine->last_ts = 0;
-
-                                               /* return CNG for now */
-                                               *frame = &engine->read_frame;
-                                               switch_set_flag((*frame), SFF_CNG);
-                                               (*frame)->datalen = engine->read_impl.encoded_bytes_per_packet;
-                                               memset((*frame)->data, 0, (*frame)->datalen);
-                                               switch_goto_status(SWITCH_STATUS_SUCCESS, end);
+                                       }
+                                       switch_mutex_unlock(smh->mutex);
+                               
+                                       if (!engine->reset_codec) {
+                                               switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_WARNING,
+                                                                                 "Could not change to payload type %d, ignoring...\n",
+                                                                                 (int) engine->read_frame.payload);
                                        }
                                }
 
@@ -1626,7 +1709,6 @@ SWITCH_DECLARE(switch_status_t) switch_core_media_write_frame(switch_core_sessio
 
        engine = &smh->engines[type];
 
-
        while (!(engine->read_codec.implementation && switch_rtp_ready(engine->rtp_session))) {
                if (switch_channel_ready(session->channel)) {
                        switch_yield(10000);
@@ -1736,7 +1818,7 @@ SWITCH_DECLARE(switch_status_t) switch_core_media_set_video_codec(switch_core_se
        v_engine = &smh->engines[SWITCH_MEDIA_TYPE_VIDEO];
 
 
-       if (!v_engine->codec_params.rm_encoding) {
+       if (!v_engine->codec_negotiated) {
                return SWITCH_STATUS_FALSE;
        }
 
@@ -1744,11 +1826,11 @@ SWITCH_DECLARE(switch_status_t) switch_core_media_set_video_codec(switch_core_se
                if (!force) {
                        return SWITCH_STATUS_SUCCESS;
                }
-               if (strcasecmp(v_engine->read_codec.implementation->iananame, v_engine->codec_params.rm_encoding) ||
-                       v_engine->read_codec.implementation->samples_per_second != v_engine->codec_params.rm_rate) {
+               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) {
 
                        switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Changing Codec from %s to %s\n",
-                                                         v_engine->read_codec.implementation->iananame, v_engine->codec_params.rm_encoding);
+                                                         v_engine->read_codec.implementation->iananame, v_engine->cur_payload_map->rm_encoding);
                        switch_core_codec_destroy(&v_engine->read_codec);
                        switch_core_codec_destroy(&v_engine->write_codec);
                } else {
@@ -1761,9 +1843,9 @@ SWITCH_DECLARE(switch_status_t) switch_core_media_set_video_codec(switch_core_se
 
 
        if (switch_core_codec_init(&v_engine->read_codec,
-                                                          v_engine->codec_params.rm_encoding,
-                                                          v_engine->codec_params.rm_fmtp,
-                                                          v_engine->codec_params.rm_rate,
+                                                          v_engine->cur_payload_map->rm_encoding,
+                                                          v_engine->cur_payload_map->rm_fmtp,
+                                                          v_engine->cur_payload_map->rm_rate,
                                                           0,
                                                           1,
                                                           SWITCH_CODEC_FLAG_ENCODE | SWITCH_CODEC_FLAG_DECODE,
@@ -1772,9 +1854,9 @@ SWITCH_DECLARE(switch_status_t) switch_core_media_set_video_codec(switch_core_se
                return SWITCH_STATUS_FALSE;
        } else {
                if (switch_core_codec_init(&v_engine->write_codec,
-                                                                  v_engine->codec_params.rm_encoding,
-                                                                  v_engine->codec_params.rm_fmtp,
-                                                                  v_engine->codec_params.rm_rate,
+                                                                  v_engine->cur_payload_map->rm_encoding,
+                                                                  v_engine->cur_payload_map->rm_fmtp,
+                                                                  v_engine->cur_payload_map->rm_rate,
                                                                   0,
                                                                   1,
                                                                   SWITCH_CODEC_FLAG_ENCODE | SWITCH_CODEC_FLAG_DECODE,
@@ -1782,22 +1864,22 @@ SWITCH_DECLARE(switch_status_t) switch_core_media_set_video_codec(switch_core_se
                        switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Can't load codec?\n");
                        return SWITCH_STATUS_FALSE;
                } else {
-                       v_engine->read_frame.rate = v_engine->codec_params.rm_rate;
+                       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",
-                                                         switch_channel_get_name(session->channel), v_engine->codec_params.rm_encoding, 
-                                                         v_engine->codec_params.rm_rate, v_engine->codec_params.codec_ms);
+                                                         switch_channel_get_name(session->channel), v_engine->cur_payload_map->rm_encoding, 
+                                                         v_engine->cur_payload_map->rm_rate, v_engine->cur_payload_map->codec_ms);
                        v_engine->read_frame.codec = &v_engine->read_codec;
 
                        v_engine->write_codec.fmtp_out = switch_core_session_strdup(session, v_engine->write_codec.fmtp_out);
 
-                       v_engine->write_codec.agreed_pt = v_engine->codec_params.agreed_pt;
-                       v_engine->read_codec.agreed_pt = v_engine->codec_params.agreed_pt;
+                       v_engine->write_codec.agreed_pt = v_engine->cur_payload_map->agreed_pt;
+                       v_engine->read_codec.agreed_pt = v_engine->cur_payload_map->agreed_pt;
                        switch_core_session_set_video_read_codec(session, &v_engine->read_codec);
                        switch_core_session_set_video_write_codec(session, &v_engine->write_codec);
 
 
                        switch_channel_set_variable_printf(session->channel, "rtp_last_video_codec_string", "%s@%dh", 
-                                                                                          v_engine->codec_params.rm_encoding, v_engine->codec_params.rm_rate);
+                                                                                          v_engine->cur_payload_map->rm_encoding, v_engine->cur_payload_map->rm_rate);
 
 
                        if (switch_rtp_ready(v_engine->rtp_session)) {
@@ -1806,25 +1888,18 @@ SWITCH_DECLARE(switch_status_t) switch_core_media_set_video_codec(switch_core_se
                                msg.from = __FILE__;
                                msg.message_id = SWITCH_MESSAGE_INDICATE_VIDEO_REFRESH_REQ;
 
-                               switch_rtp_set_default_payload(v_engine->rtp_session, v_engine->codec_params.agreed_pt);
+                               switch_rtp_set_default_payload(v_engine->rtp_session, v_engine->cur_payload_map->agreed_pt);
                                
-                               if (v_engine->codec_params.recv_pt != v_engine->codec_params.agreed_pt) {
-                                       switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, 
-                                                                         "%s Set video receive payload to %u\n", switch_channel_get_name(session->channel), v_engine->codec_params.recv_pt);
-                                       
-                                       switch_rtp_set_recv_pt(v_engine->rtp_session, v_engine->codec_params.recv_pt);
-                               } else {
-                                       switch_rtp_set_recv_pt(v_engine->rtp_session, v_engine->codec_params.agreed_pt);
-                               }
+                               //XX
 
                                switch_core_session_receive_message(session, &msg);
 
 
                        }
                        
-                       switch_channel_set_variable(session->channel, "rtp_use_video_codec_name", v_engine->codec_params.rm_encoding);
-                       switch_channel_set_variable(session->channel, "rtp_use_video_codec_fmtp", v_engine->codec_params.rm_fmtp);
-                       switch_channel_set_variable_printf(session->channel, "rtp_use_video_codec_rate", "%d", v_engine->codec_params.rm_rate);
+                       switch_channel_set_variable(session->channel, "rtp_use_video_codec_name", v_engine->cur_payload_map->rm_encoding);
+                       switch_channel_set_variable(session->channel, "rtp_use_video_codec_fmtp", v_engine->cur_payload_map->rm_fmtp);
+                       switch_channel_set_variable_printf(session->channel, "rtp_use_video_codec_rate", "%d", v_engine->cur_payload_map->rm_rate);
                        switch_channel_set_variable_printf(session->channel, "rtp_use_video_codec_ptime", "%d", 0);
 
                }
@@ -1848,7 +1923,7 @@ SWITCH_DECLARE(switch_status_t) switch_core_media_set_codec(switch_core_session_
        }
        a_engine = &smh->engines[SWITCH_MEDIA_TYPE_AUDIO];
 
-       if (!a_engine->codec_params.iananame) {
+       if (!a_engine->cur_payload_map->iananame) {
                switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "No audio codec available\n");
                switch_goto_status(SWITCH_STATUS_FALSE, end);
        }
@@ -1857,9 +1932,9 @@ 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->codec_params.rm_encoding) ||
-                       (uint32_t) a_engine->read_impl.microseconds_per_packet / 1000 != a_engine->codec_params.codec_ms ||
-                       a_engine->read_impl.samples_per_second != a_engine->codec_params.rm_rate ) {
+               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 ) {
                        
 
                        switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, 
@@ -1868,9 +1943,9 @@ SWITCH_DECLARE(switch_status_t) switch_core_media_set_codec(switch_core_session_
                                                          a_engine->read_impl.microseconds_per_packet / 1000,
                                                          a_engine->read_impl.samples_per_second,
 
-                                                         a_engine->codec_params.rm_encoding
-                                                         a_engine->codec_params.codec_ms,
-                                                         a_engine->codec_params.rm_rate);
+                                                         a_engine->cur_payload_map->iananame
+                                                         a_engine->cur_payload_map->codec_ms,
+                                                         a_engine->cur_payload_map->rm_rate);
                        
                        switch_yield(a_engine->read_impl.microseconds_per_packet);
                        switch_core_session_lock_codec_write(session);
@@ -1887,12 +1962,12 @@ SWITCH_DECLARE(switch_status_t) switch_core_media_set_codec(switch_core_session_
        }
 
        if (switch_core_codec_init_with_bitrate(&a_engine->read_codec,
-                                                                                       a_engine->codec_params.iananame,
-                                                                                       a_engine->codec_params.rm_fmtp,
-                                                                                       a_engine->codec_params.rm_rate,
-                                                                                       a_engine->codec_params.codec_ms,
-                                                                                       a_engine->codec_params.channels,
-                                                                                       a_engine->codec_params.bitrate,
+                                                                                       a_engine->cur_payload_map->iananame,
+                                                                                       a_engine->cur_payload_map->rm_fmtp,
+                                                                                       a_engine->cur_payload_map->rm_rate,
+                                                                                       a_engine->cur_payload_map->codec_ms,
+                                                                                       a_engine->cur_payload_map->channels,
+                                                                                       a_engine->cur_payload_map->bitrate,
                                                                                        SWITCH_CODEC_FLAG_ENCODE | SWITCH_CODEC_FLAG_DECODE | codec_flags,
                                                                                        NULL, 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");
@@ -1904,12 +1979,12 @@ SWITCH_DECLARE(switch_status_t) switch_core_media_set_codec(switch_core_session_
 
 
        if (switch_core_codec_init_with_bitrate(&a_engine->write_codec,
-                                                                                       a_engine->codec_params.iananame,
-                                                                                       a_engine->codec_params.rm_fmtp,
-                                                                                       a_engine->codec_params.rm_rate,
-                                                                                       a_engine->codec_params.codec_ms,
-                                                                                       a_engine->codec_params.channels,
-                                                                                       a_engine->codec_params.bitrate,
+                                                                                       a_engine->cur_payload_map->iananame,
+                                                                                       a_engine->cur_payload_map->rm_fmtp,
+                                                                                       a_engine->cur_payload_map->rm_rate,
+                                                                                       a_engine->cur_payload_map->codec_ms,
+                                                                                       a_engine->cur_payload_map->channels,
+                                                                                       a_engine->cur_payload_map->bitrate,
                                                                                        SWITCH_CODEC_FLAG_ENCODE | SWITCH_CODEC_FLAG_DECODE | codec_flags,
                                                                                        NULL, 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");
@@ -1919,12 +1994,12 @@ SWITCH_DECLARE(switch_status_t) switch_core_media_set_codec(switch_core_session_
 
        a_engine->write_codec.session = session;
 
-       switch_channel_set_variable(session->channel, "rtp_use_codec_name", a_engine->codec_params.iananame);
-       switch_channel_set_variable(session->channel, "rtp_use_codec_fmtp", a_engine->codec_params.rm_fmtp);
-       switch_channel_set_variable_printf(session->channel, "rtp_use_codec_rate", "%d", a_engine->codec_params.rm_rate);
-       switch_channel_set_variable_printf(session->channel, "rtp_use_codec_ptime", "%d", a_engine->codec_params.codec_ms);
+       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);
+       switch_channel_set_variable_printf(session->channel, "rtp_use_codec_ptime", "%d", a_engine->cur_payload_map->codec_ms);
        switch_channel_set_variable_printf(session->channel, "rtp_last_audio_codec_string", "%s@%dh@%di", 
-                                                                          a_engine->codec_params.iananame, a_engine->codec_params.rm_rate, a_engine->codec_params.codec_ms);
+                                                                          a_engine->cur_payload_map->iananame, a_engine->cur_payload_map->rm_rate, a_engine->cur_payload_map->codec_ms);
 
        switch_assert(a_engine->read_codec.implementation);
        switch_assert(a_engine->write_codec.implementation);
@@ -1946,7 +2021,7 @@ SWITCH_DECLARE(switch_status_t) switch_core_media_set_codec(switch_core_session_
                }
        }
 
-       a_engine->read_frame.rate = a_engine->codec_params.rm_rate;
+       a_engine->read_frame.rate = a_engine->cur_payload_map->rm_rate;
 
        if (!switch_core_codec_ready(&a_engine->read_codec)) {
                switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Can't load codec?\n");
@@ -1954,34 +2029,32 @@ SWITCH_DECLARE(switch_status_t) switch_core_media_set_codec(switch_core_session_
        }
 
        switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Set Codec %s %s/%ld %d ms %d samples %d bits\n",
-                                         switch_channel_get_name(session->channel), a_engine->codec_params.iananame, a_engine->codec_params.rm_rate, 
-                                         a_engine->codec_params.codec_ms,
+                                         switch_channel_get_name(session->channel), a_engine->cur_payload_map->iananame, a_engine->cur_payload_map->rm_rate, 
+                                         a_engine->cur_payload_map->codec_ms,
                                          a_engine->read_impl.samples_per_packet, a_engine->read_impl.bits_per_second);
        a_engine->read_frame.codec = &a_engine->read_codec;
 
-       a_engine->write_codec.agreed_pt = a_engine->codec_params.agreed_pt;
-       a_engine->read_codec.agreed_pt = a_engine->codec_params.agreed_pt;
+       a_engine->write_codec.agreed_pt = a_engine->cur_payload_map->agreed_pt;
+       a_engine->read_codec.agreed_pt = a_engine->cur_payload_map->agreed_pt;
 
        if (force != 2) {
                switch_core_session_set_real_read_codec(session, &a_engine->read_codec);
                switch_core_session_set_write_codec(session, &a_engine->write_codec);
        }
 
-       a_engine->codec_params.fmtp_out = switch_core_session_strdup(session, a_engine->write_codec.fmtp_out);
+       a_engine->cur_payload_map->fmtp_out = switch_core_session_strdup(session, a_engine->write_codec.fmtp_out);
 
        if (switch_rtp_ready(a_engine->rtp_session)) {
-               switch_rtp_set_default_payload(a_engine->rtp_session, a_engine->codec_params.pt);
-               switch_rtp_set_recv_pt(a_engine->rtp_session, a_engine->read_codec.agreed_pt);
+               switch_rtp_set_default_payload(a_engine->rtp_session, a_engine->cur_payload_map->pt);
        }
 
  end:
+
        if (resetting) {
                switch_core_session_unlock_codec_write(session);
                switch_core_session_unlock_codec_read(session);
        }
 
-       switch_core_media_set_video_codec(session, force);
-
        return status;
 }
 
@@ -2148,7 +2221,7 @@ static void check_ice(switch_media_handle_t *smh, switch_media_type_t type, sdp_
 #ifdef RTCP_MUX
                } else if (!strcasecmp(attr->a_name, "rtcp-mux")) {
                        engine->rtcp_mux = SWITCH_TRUE;
-                       engine->remote_rtcp_port = engine->codec_params.remote_sdp_port;
+                       engine->remote_rtcp_port = engine->cur_payload_map->remote_sdp_port;
                        got_rtcp_mux++;
 #endif
                } else if (!strcasecmp(attr->a_name, "candidate")) {
@@ -2317,7 +2390,7 @@ static void check_ice(switch_media_handle_t *smh, switch_media_type_t type, sdp_
 
        if (engine->ice_in.cands[engine->ice_in.chosen[0]][0].con_addr && engine->ice_in.cands[engine->ice_in.chosen[0]][0].con_port) {
                char tmp[80] = "";
-               engine->codec_params.remote_sdp_ip = switch_core_session_strdup(smh->session, (char *) engine->ice_in.cands[engine->ice_in.chosen[0]][0].con_addr);
+               engine->cur_payload_map->remote_sdp_ip = switch_core_session_strdup(smh->session, (char *) engine->ice_in.cands[engine->ice_in.chosen[0]][0].con_addr);
                switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(smh->session), SWITCH_LOG_NOTICE, 
                                                  "setting remote %s ice addr to %s:%d based on candidate\n", type2str(type),
                                                  engine->ice_in.cands[engine->ice_in.chosen[0]][0].con_addr, engine->ice_in.cands[engine->ice_in.chosen[0]][0].con_port);
@@ -2326,14 +2399,14 @@ static void check_ice(switch_media_handle_t *smh, switch_media_type_t type, sdp_
                engine->remote_rtp_ice_port = (switch_port_t) engine->ice_in.cands[engine->ice_in.chosen[0]][0].con_port;
                engine->remote_rtp_ice_addr = switch_core_session_strdup(smh->session, engine->ice_in.cands[engine->ice_in.chosen[0]][0].con_addr);
 
-               engine->codec_params.remote_sdp_ip = switch_core_session_strdup(smh->session, (char *) engine->ice_in.cands[engine->ice_in.chosen[0]][0].con_addr);
-               engine->codec_params.remote_sdp_port = (switch_port_t) engine->ice_in.cands[engine->ice_in.chosen[0]][0].con_port;
+               engine->cur_payload_map->remote_sdp_ip = switch_core_session_strdup(smh->session, (char *) engine->ice_in.cands[engine->ice_in.chosen[0]][0].con_addr);
+               engine->cur_payload_map->remote_sdp_port = (switch_port_t) engine->ice_in.cands[engine->ice_in.chosen[0]][0].con_port;
                if (engine->remote_rtcp_port) {
-                       engine->remote_rtcp_port = engine->codec_params.remote_sdp_port;
+                       engine->remote_rtcp_port = engine->cur_payload_map->remote_sdp_port;
                }
                                                                                                                                 
-               switch_snprintf(tmp, sizeof(tmp), "%d", engine->codec_params.remote_sdp_port);
-               switch_channel_set_variable(smh->session->channel, SWITCH_REMOTE_MEDIA_IP_VARIABLE, engine->codec_params.remote_sdp_ip);
+               switch_snprintf(tmp, sizeof(tmp), "%d", engine->cur_payload_map->remote_sdp_port);
+               switch_channel_set_variable(smh->session->channel, SWITCH_REMOTE_MEDIA_IP_VARIABLE, engine->cur_payload_map->remote_sdp_ip);
                switch_channel_set_variable(smh->session->channel, SWITCH_REMOTE_MEDIA_PORT_VARIABLE, tmp);                                     
        }
 
@@ -2461,6 +2534,41 @@ SWITCH_DECLARE(void) switch_core_session_set_ice(switch_core_session_t *session)
        smh->mparams->rtcp_video_interval_msec = "10000";
 }
 
+#define MAX_MATCHES 30
+struct matches {
+       const switch_codec_implementation_t *imp;
+       sdp_rtpmap_t *map;
+       int rate;
+       int codec_idx;
+};
+
+static void greedy_sort(switch_media_handle_t *smh, struct matches *matches, int m_idx, const switch_codec_implementation_t **codec_array, int total_codecs)
+{
+       int j = 0, f = 0, g;
+       struct matches mtmp[MAX_MATCHES] = { { 0 } };
+       for(j = 0; j < m_idx; j++) {
+               *&mtmp[j] = *&matches[j];
+                                       }
+       for (g = 0; g < smh->mparams->num_codecs && g < total_codecs; g++) {
+               const switch_codec_implementation_t *imp = codec_array[g];
+               
+               for(j = 0; j < m_idx; j++) {
+                       if (mtmp[j].imp == imp) {
+                               *&matches[f++] = *&mtmp[j];
+                       }
+               }
+       }
+}
+
+static void clear_pmaps(switch_rtp_engine_t *engine)
+{
+       payload_map_t *pmap;
+
+       for (pmap = engine->cur_payload_map; pmap && pmap->allocated; pmap = pmap->next) {
+               pmap->negotiated = 0;
+       }
+}
+
 //?
 SWITCH_DECLARE(uint8_t) switch_core_media_negotiate_sdp(switch_core_session_t *session, const char *r_sdp, uint8_t *proceed, switch_sdp_type_t sdp_type)
 {
@@ -2468,10 +2576,9 @@ SWITCH_DECLARE(uint8_t) switch_core_media_negotiate_sdp(switch_core_session_t *s
        switch_payload_t best_te = 0, te = 0, cng_pt = 0;
        sdp_media_t *m;
        sdp_attribute_t *attr;
-       int first = 0, last = 0;
        int ptime = 0, dptime = 0, maxptime = 0, dmaxptime = 0;
        int sendonly = 0, recvonly = 0;
-       int greedy = 0, x = 0, skip = 0, mine = 0;
+       int greedy = 0, x = 0, skip = 0;
        switch_channel_t *channel = switch_core_session_get_channel(session);
        const char *val;
        const char *crypto = NULL;
@@ -2487,8 +2594,13 @@ SWITCH_DECLARE(uint8_t) switch_core_media_negotiate_sdp(switch_core_session_t *s
        uint32_t near_rate = 0;
        const switch_codec_implementation_t *mimp = NULL, *near_match = NULL;
        sdp_rtpmap_t *mmap = NULL, *near_map = NULL;
+       struct matches matches[MAX_MATCHES] = { { 0 } };
+       struct matches near_matches[MAX_MATCHES] = { { 0 } };
        int codec_ms = 0;
+       uint32_t remote_codec_rate = 0, fmtp_remote_codec_rate = 0;
        const char *tmp;
+       int m_idx = 0;
+       int nm_idx = 0;
 
        switch_assert(session);
 
@@ -2516,6 +2628,10 @@ SWITCH_DECLARE(uint8_t) switch_core_media_negotiate_sdp(switch_core_session_t *s
                switch_channel_clear_flag(smh->session->channel, CF_DTLS);
        }
 
+       clear_pmaps(a_engine);
+       clear_pmaps(v_engine);
+
+
        if (proceed) *proceed = 1;
 
        greedy = !!switch_media_handle_test_media_flag(smh, SCMF_CODEC_GREEDY);
@@ -2655,6 +2771,7 @@ SWITCH_DECLARE(uint8_t) switch_core_media_negotiate_sdp(switch_core_session_t *s
        check_ice(smh, SWITCH_MEDIA_TYPE_AUDIO, sdp, NULL);
        check_ice(smh, SWITCH_MEDIA_TYPE_VIDEO, sdp, NULL);
 
+
        for (m = sdp->sdp_media; m; m = m->m_next) {
                sdp_connection_t *connection;
                switch_core_session_t *other_session;
@@ -2750,10 +2867,10 @@ SWITCH_DECLARE(uint8_t) switch_core_media_negotiate_sdp(switch_core_session_t *s
                                                switch_channel_set_variable(other_channel, "t38_broken_boolean", "true");
                                        }
                                        
-                                       a_engine->codec_params.remote_sdp_ip = switch_core_session_strdup(session, t38_options->remote_ip);
-                                       a_engine->codec_params.remote_sdp_port = t38_options->remote_port;
+                                       a_engine->cur_payload_map->remote_sdp_ip = switch_core_session_strdup(session, t38_options->remote_ip);
+                                       a_engine->cur_payload_map->remote_sdp_port = t38_options->remote_port;
 
-                                       if (remote_host && remote_port && !strcmp(remote_host, a_engine->codec_params.remote_sdp_ip) && remote_port == a_engine->codec_params.remote_sdp_port) {
+                                       if (remote_host && remote_port && !strcmp(remote_host, a_engine->cur_payload_map->remote_sdp_ip) && remote_port == a_engine->cur_payload_map->remote_sdp_port) {
                                                switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Audio params are unchanged for %s.\n",
                                                                                  switch_channel_get_name(session->channel));
                                        } else {
@@ -2761,14 +2878,14 @@ SWITCH_DECLARE(uint8_t) switch_core_media_negotiate_sdp(switch_core_session_t *s
 
                                                switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Audio params changed for %s from %s:%d to %s:%d\n",
                                                                                  switch_channel_get_name(session->channel),
-                                                                                 remote_host, remote_port, a_engine->codec_params.remote_sdp_ip, a_engine->codec_params.remote_sdp_port);
+                                                                                 remote_host, remote_port, a_engine->cur_payload_map->remote_sdp_ip, a_engine->cur_payload_map->remote_sdp_port);
                                                
-                                               switch_snprintf(tmp, sizeof(tmp), "%d", a_engine->codec_params.remote_sdp_port);
-                                               switch_channel_set_variable(session->channel, SWITCH_REMOTE_MEDIA_IP_VARIABLE, a_engine->codec_params.remote_sdp_ip);
+                                               switch_snprintf(tmp, sizeof(tmp), "%d", a_engine->cur_payload_map->remote_sdp_port);
+                                               switch_channel_set_variable(session->channel, SWITCH_REMOTE_MEDIA_IP_VARIABLE, a_engine->cur_payload_map->remote_sdp_ip);
                                                switch_channel_set_variable(session->channel, SWITCH_REMOTE_MEDIA_PORT_VARIABLE, tmp);
 
-                                               if (switch_rtp_set_remote_address(a_engine->rtp_session, a_engine->codec_params.remote_sdp_ip,
-                                                                                                                 a_engine->codec_params.remote_sdp_port, 0, SWITCH_TRUE, &err) != SWITCH_STATUS_SUCCESS) {
+                                               if (switch_rtp_set_remote_address(a_engine->rtp_session, a_engine->cur_payload_map->remote_sdp_ip,
+                                                                                                                 a_engine->cur_payload_map->remote_sdp_port, 0, SWITCH_TRUE, &err) != SWITCH_STATUS_SUCCESS) {
                                                        switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "AUDIO RTP REPORTS ERROR: [%s]\n", err);
                                                        switch_channel_hangup(channel, SWITCH_CAUSE_INCOMPATIBLE_DESTINATION);
                                                }
@@ -2855,13 +2972,12 @@ SWITCH_DECLARE(uint8_t) switch_core_media_negotiate_sdp(switch_core_session_t *s
                                break;
                        }
 
-               greed:
                        x = 0;
                        
-                       if (a_engine->codec_params.rm_encoding && !(switch_media_handle_test_media_flag(smh, SCMF_LIBERAL_DTMF) || 
+                       if (a_engine->cur_payload_map->rm_encoding && !(switch_media_handle_test_media_flag(smh, SCMF_LIBERAL_DTMF) || 
                                                                                                                switch_channel_test_flag(session->channel, CF_LIBERAL_DTMF))) { // && !switch_channel_test_flag(session->channel, CF_REINVITE)) {
-                               char *remote_host = a_engine->codec_params.remote_sdp_ip;
-                               switch_port_t remote_port = a_engine->codec_params.remote_sdp_port;
+                               char *remote_host = a_engine->cur_payload_map->remote_sdp_ip;
+                               switch_port_t remote_port = a_engine->cur_payload_map->remote_sdp_port;
                                int same = 0;
 
                                if (switch_rtp_ready(a_engine->rtp_session)) {
@@ -2871,9 +2987,9 @@ SWITCH_DECLARE(uint8_t) switch_core_media_negotiate_sdp(switch_core_session_t *s
 
                                for (map = m->m_rtpmaps; map; map = map->rm_next) {
                                        if ((zstr(map->rm_encoding) || (smh->mparams->ndlb & SM_NDLB_ALLOW_BAD_IANANAME)) && map->rm_pt < 96) {
-                                               match = (map->rm_pt == a_engine->codec_params.pt) ? 1 : 0;
+                                               match = (map->rm_pt == a_engine->cur_payload_map->pt) ? 1 : 0;
                                        } else {
-                                               match = strcasecmp(switch_str_nil(map->rm_encoding), a_engine->codec_params.iananame) ? 0 : 1;
+                                               match = strcasecmp(switch_str_nil(map->rm_encoding), a_engine->cur_payload_map->iananame) ? 0 : 1;
                                        }
 
                                        if (match && connection->c_address && remote_host && !strcmp(connection->c_address, remote_host) && m->m_port == remote_port) {
@@ -2887,7 +3003,7 @@ SWITCH_DECLARE(uint8_t) switch_core_media_negotiate_sdp(switch_core_session_t *s
                                if (same) {
                                        switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG,
                                                                          "Our existing sdp is still good [%s %s:%d], let's keep it.\n",
-                                                                         a_engine->codec_params.rm_encoding, a_engine->codec_params.remote_sdp_ip, a_engine->codec_params.remote_sdp_port);
+                                                                         a_engine->cur_payload_map->rm_encoding, a_engine->cur_payload_map->remote_sdp_ip, a_engine->cur_payload_map->remote_sdp_port);
                                        got_audio = 1;
                                } else {
                                        match = 0;
@@ -2896,17 +3012,22 @@ SWITCH_DECLARE(uint8_t) switch_core_media_negotiate_sdp(switch_core_session_t *s
                        }
 
                        for (map = m->m_rtpmaps; map; map = map->rm_next) {
+                               int32_t i;
                                const char *rm_encoding;
-                               
+                               uint32_t map_bit_rate = 0;
+                               switch_codec_fmtp_t codec_fmtp = { 0 };
+
                                if (!(rm_encoding = map->rm_encoding)) {
                                        rm_encoding = "";
                                }
-
-
+                               
+                               
                                if (!strcasecmp(rm_encoding, "telephone-event")) {
-                                       if (!best_te || map->rm_rate == a_engine->codec_params.rm_rate) {
+                                       if (!best_te || map->rm_rate == a_engine->cur_payload_map->rm_rate) {
                                                best_te = (switch_payload_t) map->rm_pt;
+                                               switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Set telephone-event payload to %u\n", best_te);
                                        }
+                                       continue;
                                }
                                
                                if (!switch_media_handle_test_media_flag(smh, SCMF_SUPPRESS_CNG) && !cng_pt && !strcasecmp(rm_encoding, "CN")) {
@@ -2915,36 +3036,18 @@ SWITCH_DECLARE(uint8_t) switch_core_media_negotiate_sdp(switch_core_session_t *s
                                                switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Set comfort noise payload to %u\n", cng_pt);
                                                switch_rtp_set_cng_pt(a_engine->rtp_session, smh->mparams->cng_pt);
                                        }
+                                       continue;
                                }
-
-                       }
-
-                       for (map = m->m_rtpmaps; map; map = map->rm_next) {
-                               int32_t i;
-                               const char *rm_encoding;
-                               uint32_t map_bit_rate = 0;
-                               switch_codec_fmtp_t codec_fmtp = { 0 };
-
+                               
+                               
                                if (x++ < skip) {
                                        continue;
                                }
 
-                               if (!(rm_encoding = map->rm_encoding)) {
-                                       rm_encoding = "";
-                               }
-                               
                                if (match) {
                                        continue;
                                }
 
-                               if (greedy) {
-                                       first = mine;
-                                       last = first + 1;
-                               } else {
-                                       first = 0;
-                                       last = smh->mparams->num_codecs;
-                               }
-
                                codec_ms = ptime;
 
                                if (maxptime && (!codec_ms || codec_ms > maxptime)) {
@@ -2961,6 +3064,10 @@ SWITCH_DECLARE(uint8_t) switch_core_media_negotiate_sdp(switch_core_session_t *s
                                        codec_ms = 30;
                                }
                                
+                               remote_codec_rate = map->rm_rate;
+                               fmtp_remote_codec_rate = 0;
+                               memset(&codec_fmtp, 0, sizeof(codec_fmtp));
+
                                if (zstr(map->rm_fmtp)) {
                                        if (!strcasecmp(map->rm_encoding, "ilbc")) {
                                                codec_ms = 30;
@@ -2977,27 +3084,32 @@ SWITCH_DECLARE(uint8_t) switch_core_media_negotiate_sdp(switch_core_session_t *s
                                                if (codec_fmtp.microseconds_per_packet) {
                                                        codec_ms = (codec_fmtp.microseconds_per_packet / 1000);
                                                }
+                                               if (codec_fmtp.actual_samples_per_second) {
+                                                       fmtp_remote_codec_rate = codec_fmtp.actual_samples_per_second;
+                                               }
                                        }
                                }
-
                                
-                               for (i = first; i < last && i < total_codecs; i++) {
+                               for (i = 0; i < smh->mparams->num_codecs && i < total_codecs; i++) {
                                        const switch_codec_implementation_t *imp = codec_array[i];
                                        uint32_t bit_rate = imp->bits_per_second;
                                        uint32_t codec_rate = imp->samples_per_second;
-                                       char *samp = NULL;
                                        
                                        if (imp->codec_type != SWITCH_CODEC_TYPE_AUDIO) {
                                                continue;
                                        }
 
                                        switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Audio Codec Compare [%s:%d:%u:%d:%u]/[%s:%d:%u:%d:%u]\n",
-                                                                         rm_encoding, map->rm_pt, (int) map->rm_rate, codec_ms, map_bit_rate,
+                                                                         rm_encoding, map->rm_pt, (int) remote_codec_rate, codec_ms, map_bit_rate,
                                                                          imp->iananame, imp->ianacode, codec_rate, imp->microseconds_per_packet / 1000, bit_rate);
                                        if ((zstr(map->rm_encoding) || (smh->mparams->ndlb & SM_NDLB_ALLOW_BAD_IANANAME)) && map->rm_pt < 96) {
                                                match = (map->rm_pt == imp->ianacode) ? 1 : 0;
                                        } else {
-                                               match = (!strcasecmp(rm_encoding, imp->iananame) && (map->rm_rate == codec_rate)) ? 1 : 0;
+                                               match = (!strcasecmp(rm_encoding, imp->iananame) && 
+                                                                (remote_codec_rate == codec_rate || fmtp_remote_codec_rate == imp->actual_samples_per_second)) ? 1 : 0;
+                                               if (fmtp_remote_codec_rate) {
+                                                       remote_codec_rate = fmtp_remote_codec_rate;
+                                               }
                                        }
 
                                        if (match && bit_rate && map_bit_rate && map_bit_rate != bit_rate && strcasecmp(map->rm_encoding, "ilbc") && 
@@ -3006,155 +3118,190 @@ SWITCH_DECLARE(uint8_t) switch_core_media_negotiate_sdp(switch_core_session_t *s
                                                match = 0;
                                        }
 
-                                       if (match && map->rm_rate && codec_rate && map->rm_rate != codec_rate && (!strcasecmp(map->rm_encoding, "pcma") || 
+                                       if (match && remote_codec_rate && codec_rate && remote_codec_rate != codec_rate && (!strcasecmp(map->rm_encoding, "pcma") || 
                                                                                                                                                                                          !strcasecmp(map->rm_encoding, "pcmu"))) {
                                                /* if the sampling rate is specified and doesn't match, this is not a codec match for G.711 */
                                                switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "sampling rates have to match for G.711\n");
                                                match = 0;
                                        }
                                        
-                                       if (!zstr(map->rm_fmtp)) {
-                                               samp = strstr(map->rm_fmtp, "samplerate=");
-                                       }
-                                       if (!strcasecmp(map->rm_encoding, "opus") && !strcasecmp(rm_encoding, imp->iananame) && samp) {
-                                               char *rate_str = samp + 11;
-
-                                               if (rate_str && *rate_str) {
-                                                       near_rate = atoi(rate_str);
-                                                       near_match = imp;
-                                                       near_map = mmap = map;
-                                                       match = 0;
-                                                       goto near_match;
-                                               }
-                                       }
-
                                        if (match) {
                                                if (scrooge) {
                                                        switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG,
                                                                                          "Bah HUMBUG! Sticking with %s@%uh@%ui\n",
                                                                                          imp->iananame, imp->samples_per_second, imp->microseconds_per_packet / 1000);
-                                               } else if ((ptime && codec_ms && codec_ms * 1000 != imp->microseconds_per_packet) || map->rm_rate != codec_rate) {
+                                               } else if ((ptime && codec_ms && codec_ms * 1000 != imp->microseconds_per_packet) || remote_codec_rate != codec_rate) {
                                                        /* ptime does not match */
                                                        match = 0;
+                                                       
+                                                       switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, 
+                                                                                         "Audio Codec Compare [%s:%d:%u:%d:%u] is saved as a near-match\n", 
+                                                                                         imp->iananame, imp->ianacode, codec_rate, imp->microseconds_per_packet / 1000, bit_rate);
 
-                                                       /* save first near_match */
-                                                       if (!near_match) {
-                                                               near_rate = map->rm_rate;
-                                                               near_match = imp;
-                                                               near_map = mmap = map;
+                                                       near_matches[nm_idx].codec_idx = i;
+                                                       near_matches[nm_idx].rate = remote_codec_rate;
+                                                       near_matches[nm_idx].imp = imp;
+                                                       near_matches[nm_idx].map = map;
+                                                       nm_idx++;
 
-                                                               if (switch_true(switch_channel_get_variable_dup(channel, "rtp_negotiate_near_match", SWITCH_FALSE, -1))) {
-                                                                       goto near_match;
-                                                               }
-                                                       }
                                                        continue;
                                                }
-                                               mimp = imp;
-                                               mmap = map;
-                                               break;
-                                       }
-                               }
 
-                               
-                               if (!match && greedy) {
-                                       skip++;
-                                       continue;
+                                               matches[m_idx].codec_idx = i;
+                                               matches[m_idx].rate = codec_rate;
+                                               matches[m_idx].imp = imp;
+                                               matches[m_idx].map = map;
+                                               m_idx++;
+
+                                               switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, 
+                                                                                 "Audio Codec Compare [%s:%d:%u:%d:%u] ++++ is saved as a match\n", 
+                                                                                 imp->iananame, imp->ianacode, codec_rate, imp->microseconds_per_packet / 1000, bit_rate);
+                                               
+                                               if (m_idx >= MAX_MATCHES) {
+                                                       break;
+                                               }
+
+                                               match = 0;
+                                       }
                                }
 
-                               if (match && mimp) {
+                               if (m_idx >= MAX_MATCHES) {
                                        break;
                                }
                        }
 
-               near_match:
+                       if (!m_idx && nm_idx) {
+                               int j;
 
-                       if (!match && near_match) {
-                               const switch_codec_implementation_t *search[1];
-                               char *prefs[1];
-                               char tmp[80];
-                               int num;
-                               
-                               switch_snprintf(tmp, sizeof(tmp), "%s@%uh@%ui", near_match->iananame, near_rate ? near_rate : near_match->samples_per_second,
-                                                               codec_ms);
-                               
-                               prefs[0] = tmp;
-                               num = switch_loadable_module_get_codecs_sorted(search, 1, prefs, 1);
+                               for(j = 0; j < nm_idx; j++) {
+                                       const switch_codec_implementation_t *search[1];
+                                       char *prefs[1];
+                                       char tmp[80];
+                                       int num;
+                                       const switch_codec_implementation_t *timp = NULL;
+
+                                       near_rate = near_matches[j].rate;
+                                       near_match = near_matches[j].imp;
+                                       near_map = near_matches[j].map;                                 
+                                       
+                                       switch_snprintf(tmp, sizeof(tmp), "%s@%uh@%ui", near_match->iananame, near_rate ? near_rate : near_match->samples_per_second,
+                                                                       codec_ms);
+                                       
+                                       prefs[0] = tmp;
+                                       num = switch_loadable_module_get_codecs_sorted(search, 1, prefs, 1);
                                
-                               if (num) {
-                                       mimp = search[0];
-                               } else {
-                                       mimp = near_match;
-                               }
+                                       if (num) {
+                                               timp = search[0];
+                                       } else {
+                                               timp = near_match;
+                                       }
                                
-                               if (!maxptime || mimp->microseconds_per_packet / 1000 <= maxptime) {
-                                       switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Substituting codec %s@%ui@%uh\n",
-                                                                         mimp->iananame, mimp->microseconds_per_packet / 1000, mimp->samples_per_second);
-                                       mmap = near_map;
-                                       match = 1;
-                               } else {
-                                       mimp = NULL;
-                                       mmap = NULL;
-                                       match = 0;
+                                       if (!maxptime || timp->microseconds_per_packet / 1000 <= maxptime) {
+                                               switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Substituting codec %s@%ui@%uh\n",
+                                                                                 timp->iananame, timp->microseconds_per_packet / 1000, timp->actual_samples_per_second);
+                                               match = 1;
+
+                                               matches[m_idx].codec_idx = near_matches[j].codec_idx;
+                                               matches[m_idx].rate = near_rate;
+                                               matches[m_idx].imp = timp;
+                                               matches[m_idx].map = near_map;
+                                               m_idx++;
+
+                                               break;
+                                       }
                                }
                        }
                        
-                       if (mimp && mmap) {
-                               char tmp[50];
-                               const char *mirror = switch_channel_get_variable(session->channel, "rtp_mirror_remote_audio_codec_payload");
+                       if (m_idx) {
+                               int j;
 
-                               a_engine->codec_params.rm_encoding = switch_core_session_strdup(session, (char *) mmap->rm_encoding);
-                               a_engine->codec_params.iananame = switch_core_session_strdup(session, (char *) mimp->iananame);
-                               a_engine->codec_params.pt = (switch_payload_t) mmap->rm_pt;
-                               a_engine->codec_params.rm_rate = mimp->samples_per_second;
-                               a_engine->codec_params.adv_rm_rate = mimp->samples_per_second;
-                               if (strcasecmp(mimp->iananame, "g722")) {
-                                       a_engine->codec_params.rm_rate = mimp->actual_samples_per_second;
-                               }
-                               a_engine->codec_params.codec_ms = mimp->microseconds_per_packet / 1000;
-                               a_engine->codec_params.bitrate = mimp->bits_per_second;
-                               a_engine->codec_params.channels = mmap->rm_params ? atoi(mmap->rm_params) : 1;
-
-                               if (!strcasecmp((char *) mmap->rm_encoding, "opus")) {
-                                       if (a_engine->codec_params.channels == 1) {
-                                               switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_WARNING, "Invalid SDP for opus.  Don't ask.. but it needs a /2\n");
-                                               a_engine->codec_params.adv_channels = 1;
-                                       } else {
-                                               a_engine->codec_params.adv_channels = 2; /* IKR ???*/
+                               if (greedy) { /* sort in favor of mine */
+                                       greedy_sort(smh, matches, m_idx, codec_array, total_codecs);
+                               }
+
+                               match = 1;
+                               a_engine->codec_negotiated = 1;
+                               
+                               for(j = 0; j < m_idx; j++) {
+                                       payload_map_t *pmap = switch_core_media_add_payload_map(session, 
+                                                                                                                                                       SWITCH_MEDIA_TYPE_AUDIO,
+                                                                                                                                                       matches[j].map->rm_encoding, 
+                                                                                                                                                       sdp_type, 
+                                                                                                                                                       matches[j].map->rm_pt,
+                                                                                                                                                       matches[j].imp->samples_per_second,
+                                                                                                                                                       matches[j].imp->microseconds_per_packet / 1000,
+                                                                                                                                                       SWITCH_TRUE);
+                                       mimp = matches[j].imp;
+                                       mmap = matches[j].map;
+                       
+                                       if (j == 0) {
+                                               a_engine->cur_payload_map = pmap;
                                        }
-                                       if (!zstr((char *) mmap->rm_fmtp) && switch_stristr("stereo=1", (char *) mmap->rm_fmtp)) {
-                                               a_engine->codec_params.channels = 2;
+                                               
+                                       pmap->rm_encoding = switch_core_session_strdup(session, (char *) mmap->rm_encoding);
+                                       pmap->iananame = switch_core_session_strdup(session, (char *) mimp->iananame);
+                                       pmap->pt = (switch_payload_t) mmap->rm_pt;
+                                       pmap->rm_rate = mimp->samples_per_second;
+                                       pmap->adv_rm_rate = mimp->samples_per_second;
+                                       if (strcasecmp(mimp->iananame, "g722")) {
+                                               pmap->rm_rate = mimp->actual_samples_per_second;
+                                       }
+                                       pmap->codec_ms = mimp->microseconds_per_packet / 1000;
+                                       pmap->bitrate = mimp->bits_per_second;
+                                       pmap->channels = mmap->rm_params ? atoi(mmap->rm_params) : 1;
+                                               
+                                       if (!strcasecmp((char *) mmap->rm_encoding, "opus")) {
+                                               if (pmap->channels == 1) {
+                                                       switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_WARNING, "Invalid SDP for opus.  Don't ask.. but it needs a /2\n");
+                                                       pmap->adv_channels = 1;
+                                               } else {
+                                                       pmap->adv_channels = 2; /* IKR ???*/
+                                               }
+                                               if (!zstr((char *) mmap->rm_fmtp) && switch_stristr("stereo=1", (char *) mmap->rm_fmtp)) {
+                                                       pmap->channels = 2;
+                                               } else {
+                                                       pmap->channels = 1;
+                                               }
                                        } else {
-                                               a_engine->codec_params.channels = 1;
+                                               pmap->adv_channels = pmap->channels;
                                        }
-                               } else {
-                                       a_engine->codec_params.adv_channels = a_engine->codec_params.channels;
+                                               
+                                       pmap->remote_sdp_ip = switch_core_session_strdup(session, (char *) connection->c_address);
+                                       pmap->remote_sdp_port = (switch_port_t) m->m_port;
+                                       pmap->rm_fmtp = switch_core_session_strdup(session, (char *) mmap->rm_fmtp);
+                                               
+                                       pmap->agreed_pt = (switch_payload_t) mmap->rm_pt;
+                                       smh->num_negotiated_codecs = 0;
+                                       smh->negotiated_codecs[smh->num_negotiated_codecs++] = mimp;
+                                       pmap->recv_pt = (switch_payload_t)mmap->rm_pt;
+                                               
                                }
-
-                               a_engine->codec_params.remote_sdp_ip = switch_core_session_strdup(session, (char *) connection->c_address);
-                               a_engine->codec_params.remote_sdp_port = (switch_port_t) m->m_port;
-                               a_engine->codec_params.rm_fmtp = switch_core_session_strdup(session, (char *) mmap->rm_fmtp);
+                       }
                                
-                               a_engine->codec_params.agreed_pt = (switch_payload_t) mmap->rm_pt;
-                               smh->num_negotiated_codecs = 0;
-                               smh->negotiated_codecs[smh->num_negotiated_codecs++] = mimp;
-                               switch_snprintf(tmp, sizeof(tmp), "%d", a_engine->codec_params.remote_sdp_port);
-                               switch_channel_set_variable(session->channel, SWITCH_REMOTE_MEDIA_IP_VARIABLE, a_engine->codec_params.remote_sdp_ip);
+                       if (match) {
+                               char tmp[50];
+                               const char *mirror = switch_channel_get_variable(session->channel, "rtp_mirror_remote_audio_codec_payload");
+                                               
+
+                               switch_snprintf(tmp, sizeof(tmp), "%d", a_engine->cur_payload_map->remote_sdp_port);
+                               switch_channel_set_variable(session->channel, SWITCH_REMOTE_MEDIA_IP_VARIABLE, a_engine->cur_payload_map->remote_sdp_ip);
                                switch_channel_set_variable(session->channel, SWITCH_REMOTE_MEDIA_PORT_VARIABLE, tmp);
-                               a_engine->codec_params.recv_pt = (switch_payload_t)mmap->rm_pt;
-                                       
+
+
                                if (!switch_true(mirror) && 
                                        switch_channel_direction(channel) == SWITCH_CALL_DIRECTION_OUTBOUND && 
                                        (!switch_channel_test_flag(session->channel, CF_REINVITE) || switch_media_handle_test_media_flag(smh, SCMF_RENEG_ON_REINVITE))) {
-                                       switch_core_media_get_offered_pt(session, mimp, &a_engine->codec_params.recv_pt);
+                                       switch_core_media_get_offered_pt(session, mimp, &a_engine->cur_payload_map->recv_pt);
                                }
-                                       
-                               switch_snprintf(tmp, sizeof(tmp), "%d", a_engine->codec_params.recv_pt);
+                               
+                               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 (match) {
-                               if (switch_core_media_set_codec(session, 1, smh->mparams->codec_flags) == SWITCH_STATUS_SUCCESS) {
+                               if (switch_core_codec_ready(&a_engine->read_codec)) {
+                                       a_engine->reset_codec = 1;
+                               }
+
+                               if (switch_core_media_set_codec(session, 0, smh->mparams->codec_flags) == SWITCH_STATUS_SUCCESS) {
                                        got_audio = 1;
                                        check_ice(smh, SWITCH_MEDIA_TYPE_AUDIO, sdp, m);
                                } else {
@@ -3205,25 +3352,24 @@ SWITCH_DECLARE(uint8_t) switch_core_media_negotiate_sdp(switch_core_session_t *s
                                }
                        }
 
-                       
-                       if (!match && greedy && mine < total_codecs) {
-                               mine++;
-                               skip = 0;
-                               goto greed;
-                       }
-
                } else if (m->m_type == sdp_media_video && m->m_port) {
                        sdp_rtpmap_t *map;
                        const char *rm_encoding;
                        const switch_codec_implementation_t *mimp = NULL;
                        int vmatch = 0, i;
+
+                       nm_idx = 0;
+                       m_idx = 0;
+                       memset(matches, 0, sizeof(matches[0]) * MAX_MATCHES);
+                       memset(near_matches, 0, sizeof(near_matches[0]) * MAX_MATCHES);
+
                        switch_channel_set_variable(session->channel, "video_possible", "true");
 
                        connection = sdp->sdp_connection;
                        if (m->m_connections) {
                                connection = m->m_connections;
                        }
-
+                       
                        if (!connection) {
                                switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Cannot find a c= line in the sdp at media or session level!\n");
                                match = 0;
@@ -3239,7 +3385,7 @@ SWITCH_DECLARE(uint8_t) switch_core_media_negotiate_sdp(switch_core_session_t *s
                                                }
                                        }
                                }
-
+                               
                                for (attr = m->m_attributes; attr; attr = attr->a_next) {
                                        if (!strcasecmp(attr->a_name, "framerate") && attr->a_value) {
                                                //framerate = atoi(attr->a_value);
@@ -3289,7 +3435,7 @@ SWITCH_DECLARE(uint8_t) switch_core_media_negotiate_sdp(switch_core_session_t *s
                                                switch_channel_test_flag(session->channel, CF_NOVIDEO)) {
                                                continue;
                                        }
-
+                                       
                                        switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Video Codec Compare [%s:%d]/[%s:%d]\n",
                                                                          rm_encoding, map->rm_pt, imp->iananame, imp->ianacode);
                                        if ((zstr(map->rm_encoding) || (smh->mparams->ndlb & SM_NDLB_ALLOW_BAD_IANANAME)) && map->rm_pt < 96) {
@@ -3300,56 +3446,89 @@ SWITCH_DECLARE(uint8_t) switch_core_media_negotiate_sdp(switch_core_session_t *s
 
 
                                        if (vmatch && (map->rm_rate == imp->samples_per_second)) {
-                                               mimp = imp;
-                                               break;
-                                       } else {
-                                               vmatch = 0;
+                                               matches[m_idx].imp = imp;
+                                               matches[m_idx].map = map;
+
+                                               switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Video Codec Compare [%s:%d] is saved as a match\n",
+                                                                                 imp->iananame, imp->ianacode);
+                                               m_idx++;
                                        }
+
+                                       vmatch = 0;
                                }
+                       }
 
-                               if (mimp) {
-                                       if ((v_engine->codec_params.rm_encoding = switch_core_session_strdup(session, (char *) rm_encoding))) {
-                                               char tmp[50];
-                                               const char *mirror = switch_channel_get_variable(session->channel, "rtp_mirror_remote_video_codec_payload");
+                       if (m_idx) {
+                               char tmp[50];
+                               const char *mirror = switch_channel_get_variable(session->channel, "rtp_mirror_remote_video_codec_payload");
+                               int j = 0;
 
-                                               v_engine->codec_params.pt = (switch_payload_t) map->rm_pt;
-                                               v_engine->codec_params.rm_rate = map->rm_rate;
-                                               v_engine->codec_params.codec_ms = mimp->microseconds_per_packet / 1000;
+                               if (greedy) { /* sort in favor of mine */
+                                       greedy_sort(smh, matches, m_idx, codec_array, total_codecs);
+                               }
 
+                               vmatch = 1;
+                               v_engine->codec_negotiated = 1;
 
-                                               v_engine->codec_params.remote_sdp_ip = switch_core_session_strdup(session, (char *) connection->c_address);
-                                               v_engine->codec_params.remote_sdp_port = (switch_port_t) m->m_port;
+                               for(j = 0; j < m_idx; j++) {
+                                       payload_map_t *pmap = switch_core_media_add_payload_map(session, 
+                                                                                                                                                       SWITCH_MEDIA_TYPE_VIDEO,
+                                                                                                                                                       matches[j].map->rm_encoding, 
+                                                                                                                                                       sdp_type, 
+                                                                                                                                                       matches[j].map->rm_pt,
+                                                                                                                                                       matches[j].imp->samples_per_second,
+                                                                                                                                                       matches[j].imp->microseconds_per_packet / 1000,
+                                                                                                                                                       SWITCH_TRUE);
+
+                                       if (j == 0) {
+                                               v_engine->cur_payload_map = pmap;
+                                       }
+                                       
+                                       mimp = matches[j].imp;
+                                       map = matches[j].map;
+                                       
+                                       pmap->rm_encoding = switch_core_session_strdup(session, (char *) map->rm_encoding);
+                                       pmap->pt = (switch_payload_t) map->rm_pt;
+                                       pmap->rm_rate = map->rm_rate;
+                                       pmap->codec_ms = mimp->microseconds_per_packet / 1000;
+
+
+                                       pmap->remote_sdp_ip = switch_core_session_strdup(session, (char *) connection->c_address);
+                                       pmap->remote_sdp_port = (switch_port_t) m->m_port;
                                                
-                                               v_engine->codec_params.rm_fmtp = switch_core_session_strdup(session, (char *) map->rm_fmtp);
-
-                                               v_engine->codec_params.agreed_pt = (switch_payload_t) map->rm_pt;
-                                               switch_snprintf(tmp, sizeof(tmp), "%d", v_engine->codec_params.remote_sdp_port);
-                                               switch_channel_set_variable(session->channel, SWITCH_REMOTE_VIDEO_IP_VARIABLE, v_engine->codec_params.remote_sdp_ip);
-                                               switch_channel_set_variable(session->channel, SWITCH_REMOTE_VIDEO_PORT_VARIABLE, tmp);
-                                               switch_channel_set_variable(session->channel, "rtp_video_fmtp", v_engine->codec_params.rm_fmtp);
-                                               switch_snprintf(tmp, sizeof(tmp), "%d", v_engine->codec_params.agreed_pt);
-                                               switch_channel_set_variable(session->channel, "rtp_video_pt", tmp);
-                                               switch_core_media_check_video_codecs(session);
-
-                                               v_engine->codec_params.recv_pt = (switch_payload_t)map->rm_pt;
+                                       pmap->rm_fmtp = switch_core_session_strdup(session, (char *) map->rm_fmtp);
+
+                                       pmap->agreed_pt = (switch_payload_t) map->rm_pt;
+                                       
+                                       pmap->recv_pt = (switch_payload_t)map->rm_pt;
                                                
-                                               if (!switch_true(mirror) && switch_channel_direction(channel) == SWITCH_CALL_DIRECTION_OUTBOUND) {
-                                                       switch_core_media_get_offered_pt(session, mimp, &v_engine->codec_params.recv_pt);
-                                               }
+                                       if (!switch_true(mirror) && switch_channel_direction(channel) == SWITCH_CALL_DIRECTION_OUTBOUND) {
+                                               switch_core_media_get_offered_pt(session, mimp, &pmap->recv_pt);
+                                       }
+                               }
 
-                                               switch_snprintf(tmp, sizeof(tmp), "%d", v_engine->codec_params.recv_pt);
-                                               switch_channel_set_variable(session->channel, "rtp_video_recv_pt", tmp);
-                                               if (!match && vmatch) match = 1;
+                               
+                               
+                               switch_snprintf(tmp, sizeof(tmp), "%d", v_engine->cur_payload_map->remote_sdp_port);
+                               switch_channel_set_variable(session->channel, SWITCH_REMOTE_VIDEO_IP_VARIABLE, v_engine->cur_payload_map->remote_sdp_ip);
+                               switch_channel_set_variable(session->channel, SWITCH_REMOTE_VIDEO_PORT_VARIABLE, tmp);
+                               switch_channel_set_variable(session->channel, "rtp_video_fmtp", v_engine->cur_payload_map->rm_fmtp);
+                               switch_snprintf(tmp, sizeof(tmp), "%d", v_engine->cur_payload_map->agreed_pt);
+                               switch_channel_set_variable(session->channel, "rtp_video_pt", tmp);
+                               switch_core_media_check_video_codecs(session);
+                               switch_snprintf(tmp, sizeof(tmp), "%d", v_engine->cur_payload_map->recv_pt);
+                               switch_channel_set_variable(session->channel, "rtp_video_recv_pt", tmp);
+                               if (!match && vmatch) match = 1;
 
-                                               check_ice(smh, SWITCH_MEDIA_TYPE_VIDEO, sdp, m);
-                                               //check_ice(smh, SWITCH_MEDIA_TYPE_VIDEO, sdp, NULL);
-                                               break;
-                                       } else {
-                                               vmatch = 0;
-                                       }
+                               if (switch_core_codec_ready(&v_engine->read_codec)) {
+                                       v_engine->reset_codec = 1;
+                               }
+
+                               if (switch_core_media_set_video_codec(session, 0) == SWITCH_STATUS_SUCCESS) {
+                                       check_ice(smh, SWITCH_MEDIA_TYPE_VIDEO, sdp, m);
                                }
+
                        }
-                       
                }
        }
 
@@ -3596,7 +3775,7 @@ static switch_status_t start_video_thread(switch_core_session_t *session)
 
        switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_NOTICE, "%s Starting Video thread\n", switch_core_session_get_name(session));
 
-       switch_rtp_set_default_payload(v_engine->rtp_session, v_engine->codec_params.agreed_pt);
+       switch_rtp_set_default_payload(v_engine->rtp_session, v_engine->cur_payload_map->agreed_pt);
        v_engine->mh.session = session;
        switch_threadattr_create(&thd_attr, pool);
        switch_threadattr_stacksize_set(thd_attr, SWITCH_THREAD_STACKSIZE);
@@ -3703,20 +3882,20 @@ SWITCH_DECLARE(switch_status_t) switch_core_media_proxy_remote_addr(switch_core_
                goto end;
        }
 
-       a_engine->codec_params.remote_sdp_ip = switch_core_session_strdup(session, rip);
-       a_engine->codec_params.remote_sdp_port = (switch_port_t) atoi(rp);
+       a_engine->cur_payload_map->remote_sdp_ip = switch_core_session_strdup(session, rip);
+       a_engine->cur_payload_map->remote_sdp_port = (switch_port_t) atoi(rp);
 
        if (*rvp) {
-               v_engine->codec_params.remote_sdp_ip = switch_core_session_strdup(session, rip);
-               v_engine->codec_params.remote_sdp_port = (switch_port_t) atoi(rvp);
+               v_engine->cur_payload_map->remote_sdp_ip = switch_core_session_strdup(session, rip);
+               v_engine->cur_payload_map->remote_sdp_port = (switch_port_t) atoi(rvp);
                switch_channel_set_flag(session->channel, CF_VIDEO_POSSIBLE);
                switch_channel_set_flag(session->channel, CF_VIDEO);
        }
 
-       if (v_engine->codec_params.remote_sdp_ip && v_engine->codec_params.remote_sdp_port) {
-               if (!strcmp(v_engine->codec_params.remote_sdp_ip, rip) && atoi(rvp) == v_engine->codec_params.remote_sdp_port) {
+       if (v_engine->cur_payload_map->remote_sdp_ip && v_engine->cur_payload_map->remote_sdp_port) {
+               if (!strcmp(v_engine->cur_payload_map->remote_sdp_ip, rip) && atoi(rvp) == v_engine->cur_payload_map->remote_sdp_port) {
                        switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Remote video address:port [%s:%d] has not changed.\n",
-                                                         v_engine->codec_params.remote_sdp_ip, v_engine->codec_params.remote_sdp_port);
+                                                         v_engine->cur_payload_map->remote_sdp_ip, v_engine->cur_payload_map->remote_sdp_port);
                } else {
                        switch_channel_set_flag(session->channel, CF_VIDEO_POSSIBLE);
                        switch_channel_set_flag(session->channel, CF_VIDEO);
@@ -3731,12 +3910,12 @@ SWITCH_DECLARE(switch_status_t) switch_core_media_proxy_remote_addr(switch_core_
                                }
 
                                
-                               if (switch_rtp_set_remote_address(v_engine->rtp_session, v_engine->codec_params.remote_sdp_ip,
-                                                                                                 v_engine->codec_params.remote_sdp_port, remote_rtcp_port, SWITCH_TRUE, &err) != SWITCH_STATUS_SUCCESS) {
+                               if (switch_rtp_set_remote_address(v_engine->rtp_session, v_engine->cur_payload_map->remote_sdp_ip,
+                                                                                                 v_engine->cur_payload_map->remote_sdp_port, remote_rtcp_port, SWITCH_TRUE, &err) != SWITCH_STATUS_SUCCESS) {
                                        switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "VIDEO RTP REPORTS ERROR: [%s]\n", err);
                                } else {
                                        switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "VIDEO RTP CHANGING DEST TO: [%s:%d]\n",
-                                                                         v_engine->codec_params.remote_sdp_ip, v_engine->codec_params.remote_sdp_port);
+                                                                         v_engine->cur_payload_map->remote_sdp_ip, v_engine->cur_payload_map->remote_sdp_port);
                                        if (!switch_media_handle_test_media_flag(smh, SCMF_DISABLE_RTP_AUTOADJ) && !switch_channel_test_flag(session->channel, CF_PROXY_MODE) &&
                                                !((val = switch_channel_get_variable(session->channel, "disable_rtp_auto_adjust")) && switch_true(val)) && 
                                                !switch_channel_test_flag(session->channel, CF_WEBRTC)) {
@@ -3745,7 +3924,7 @@ SWITCH_DECLARE(switch_status_t) switch_core_media_proxy_remote_addr(switch_core_
                                                start_video_thread(session);
                                
                                        }
-                                       if (switch_media_handle_test_media_flag(smh, SCMF_AUTOFIX_TIMING) || switch_media_handle_test_media_flag(smh, SCMF_AUTOFIX_PT)) {
+                                       if (switch_media_handle_test_media_flag(smh, SCMF_AUTOFIX_TIMING)) {
                                                v_engine->check_frames = 0;
                                        }
                                }
@@ -3759,9 +3938,9 @@ SWITCH_DECLARE(switch_status_t) switch_core_media_proxy_remote_addr(switch_core_
                const char *rport = NULL;
                switch_port_t remote_rtcp_port = 0;
 
-               if (remote_host && remote_port && !strcmp(remote_host, a_engine->codec_params.remote_sdp_ip) && remote_port == a_engine->codec_params.remote_sdp_port) {
+               if (remote_host && remote_port && !strcmp(remote_host, a_engine->cur_payload_map->remote_sdp_ip) && remote_port == a_engine->cur_payload_map->remote_sdp_port) {
                        switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Remote address:port [%s:%d] has not changed.\n",
-                                                         a_engine->codec_params.remote_sdp_ip, a_engine->codec_params.remote_sdp_port);
+                                                         a_engine->cur_payload_map->remote_sdp_ip, a_engine->cur_payload_map->remote_sdp_port);
                        switch_goto_status(SWITCH_STATUS_BREAK, end);
                }
 
@@ -3770,20 +3949,20 @@ SWITCH_DECLARE(switch_status_t) switch_core_media_proxy_remote_addr(switch_core_
                }
 
 
-               if (switch_rtp_set_remote_address(a_engine->rtp_session, a_engine->codec_params.remote_sdp_ip,
-                                                                                 a_engine->codec_params.remote_sdp_port, remote_rtcp_port, SWITCH_TRUE, &err) != SWITCH_STATUS_SUCCESS) {
+               if (switch_rtp_set_remote_address(a_engine->rtp_session, a_engine->cur_payload_map->remote_sdp_ip,
+                                                                                 a_engine->cur_payload_map->remote_sdp_port, remote_rtcp_port, SWITCH_TRUE, &err) != SWITCH_STATUS_SUCCESS) {
                        switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "AUDIO RTP REPORTS ERROR: [%s]\n", err);
                        status = SWITCH_STATUS_GENERR;
                } else {
                        switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "AUDIO RTP CHANGING DEST TO: [%s:%d]\n",
-                                                         a_engine->codec_params.remote_sdp_ip, a_engine->codec_params.remote_sdp_port);
+                                                         a_engine->cur_payload_map->remote_sdp_ip, a_engine->cur_payload_map->remote_sdp_port);
                        if (!switch_media_handle_test_media_flag(smh, SCMF_DISABLE_RTP_AUTOADJ) &&
                                !((val = switch_channel_get_variable(session->channel, "disable_rtp_auto_adjust")) && switch_true(val)) && 
                                !switch_channel_test_flag(session->channel, CF_WEBRTC)) {
                                /* Reactivate the NAT buster flag. */
                                switch_rtp_set_flag(a_engine->rtp_session, SWITCH_RTP_FLAG_AUTOADJ);
                        }
-                       if (switch_media_handle_test_media_flag(smh, SCMF_AUTOFIX_TIMING) || switch_media_handle_test_media_flag(smh, SCMF_AUTOFIX_PT)) {
+                       if (switch_media_handle_test_media_flag(smh, SCMF_AUTOFIX_TIMING)) {
                                a_engine->check_frames = 0;
                        }
                        status = SWITCH_STATUS_SUCCESS;
@@ -3930,31 +4109,31 @@ SWITCH_DECLARE(switch_status_t) switch_core_media_choose_port(switch_core_sessio
        /* Don't do anything if we're in proxy mode or if a (remote) port already has been found */
        if (!force) {
                if (switch_channel_test_flag(session->channel, CF_PROXY_MODE) ||
-                       switch_channel_test_flag(session->channel, CF_PROXY_MEDIA) || engine->codec_params.adv_sdp_port) {
+                       switch_channel_test_flag(session->channel, CF_PROXY_MEDIA) || engine->adv_sdp_port) {
                        return SWITCH_STATUS_SUCCESS;
                }
        }
 
        /* Release the local sdp port */
-       if (engine->codec_params.local_sdp_port) {
-               switch_rtp_release_port(smh->mparams->rtpip, engine->codec_params.local_sdp_port);
+       if (engine->local_sdp_port) {
+               switch_rtp_release_port(smh->mparams->rtpip, engine->local_sdp_port);
        }
 
        /* Request a local port from the core's allocator */
-       if (!(engine->codec_params.local_sdp_port = switch_rtp_request_port(smh->mparams->rtpip))) {
+       if (!(engine->local_sdp_port = switch_rtp_request_port(smh->mparams->rtpip))) {
                switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_CRIT, "No %s RTP ports available!\n", tstr);
                return SWITCH_STATUS_FALSE;
        }
 
-       engine->codec_params.local_sdp_ip = smh->mparams->rtpip;
+       engine->local_sdp_ip = smh->mparams->rtpip;
        
 
-       sdp_port = engine->codec_params.local_sdp_port;
+       sdp_port = engine->local_sdp_port;
 
        /* Check if NAT is detected  */
        if (!zstr(smh->mparams->remote_ip) && switch_core_media_check_nat(smh, smh->mparams->remote_ip)) {
                /* Yes, map the port through switch_nat */
-               switch_nat_add_mapping(engine->codec_params.local_sdp_port, SWITCH_NAT_UDP, &sdp_port, SWITCH_FALSE);
+               switch_nat_add_mapping(engine->local_sdp_port, SWITCH_NAT_UDP, &sdp_port, SWITCH_FALSE);
 
                switch_snprintf(vname, sizeof(vname), "rtp_adv_%s_ip", tstr);
                
@@ -3981,16 +4160,16 @@ SWITCH_DECLARE(switch_status_t) switch_core_media_choose_port(switch_core_sessio
                use_ip = smh->mparams->rtpip;
        }
 
-       engine->codec_params.adv_sdp_port = sdp_port;
-       engine->codec_params.adv_sdp_ip = smh->mparams->adv_sdp_audio_ip = smh->mparams->extrtpip = switch_core_session_strdup(session, use_ip);
+       engine->adv_sdp_port = sdp_port;
+       engine->adv_sdp_ip = smh->mparams->adv_sdp_audio_ip = smh->mparams->extrtpip = switch_core_session_strdup(session, use_ip);
 
 
        if (type == SWITCH_MEDIA_TYPE_AUDIO) {
-               switch_channel_set_variable(session->channel, SWITCH_LOCAL_MEDIA_IP_VARIABLE, engine->codec_params.local_sdp_ip);
+               switch_channel_set_variable(session->channel, SWITCH_LOCAL_MEDIA_IP_VARIABLE, engine->local_sdp_ip);
                switch_channel_set_variable_printf(session->channel, SWITCH_LOCAL_MEDIA_PORT_VARIABLE, "%d", sdp_port);
-               switch_channel_set_variable(session->channel, SWITCH_ADVERTISED_MEDIA_IP_VARIABLE, engine->codec_params.adv_sdp_ip);
+               switch_channel_set_variable(session->channel, SWITCH_ADVERTISED_MEDIA_IP_VARIABLE, engine->adv_sdp_ip);
        } else {
-               switch_channel_set_variable(session->channel, SWITCH_LOCAL_VIDEO_IP_VARIABLE, engine->codec_params.adv_sdp_ip);
+               switch_channel_set_variable(session->channel, SWITCH_LOCAL_VIDEO_IP_VARIABLE, engine->adv_sdp_ip);
                switch_channel_set_variable_printf(session->channel, SWITCH_LOCAL_VIDEO_PORT_VARIABLE, "%d", sdp_port);
        }
 
@@ -4041,28 +4220,28 @@ SWITCH_DECLARE(void) switch_core_media_deactivate_rtp(switch_core_session_t *ses
 
        if (v_engine->rtp_session) {
                switch_rtp_destroy(&v_engine->rtp_session);
-       } else if (v_engine->codec_params.local_sdp_port) {
-               switch_rtp_release_port(smh->mparams->rtpip, v_engine->codec_params.local_sdp_port);
+       } else if (v_engine->local_sdp_port) {
+               switch_rtp_release_port(smh->mparams->rtpip, v_engine->local_sdp_port);
        }
 
 
-       if (v_engine->codec_params.local_sdp_port > 0 && !zstr(smh->mparams->remote_ip) && 
+       if (v_engine->local_sdp_port > 0 && !zstr(smh->mparams->remote_ip) && 
                switch_core_media_check_nat(smh, smh->mparams->remote_ip)) {
-               switch_nat_del_mapping((switch_port_t) v_engine->codec_params.local_sdp_port, SWITCH_NAT_UDP);
-               switch_nat_del_mapping((switch_port_t) v_engine->codec_params.local_sdp_port + 1, SWITCH_NAT_UDP);
+               switch_nat_del_mapping((switch_port_t) v_engine->local_sdp_port, SWITCH_NAT_UDP);
+               switch_nat_del_mapping((switch_port_t) v_engine->local_sdp_port + 1, SWITCH_NAT_UDP);
        }
 
 
        if (a_engine->rtp_session) {
                switch_rtp_destroy(&a_engine->rtp_session);
-       } else if (a_engine->codec_params.local_sdp_port) {
-               switch_rtp_release_port(smh->mparams->rtpip, a_engine->codec_params.local_sdp_port);
+       } else if (a_engine->local_sdp_port) {
+               switch_rtp_release_port(smh->mparams->rtpip, a_engine->local_sdp_port);
        }
 
-       if (a_engine->codec_params.local_sdp_port > 0 && !zstr(smh->mparams->remote_ip) && 
+       if (a_engine->local_sdp_port > 0 && !zstr(smh->mparams->remote_ip) && 
                switch_core_media_check_nat(smh, smh->mparams->remote_ip)) {
-               switch_nat_del_mapping((switch_port_t) a_engine->codec_params.local_sdp_port, SWITCH_NAT_UDP);
-               switch_nat_del_mapping((switch_port_t) a_engine->codec_params.local_sdp_port + 1, SWITCH_NAT_UDP);
+               switch_nat_del_mapping((switch_port_t) a_engine->local_sdp_port, SWITCH_NAT_UDP);
+               switch_nat_del_mapping((switch_port_t) a_engine->local_sdp_port + 1, SWITCH_NAT_UDP);
        }
 
 }
@@ -4199,7 +4378,7 @@ SWITCH_DECLARE(switch_status_t) switch_core_media_activate_rtp(switch_core_sessi
        switch_media_handle_t *smh;
 
        switch_assert(session);
-
+       
        if (!(smh = session->media_handle)) {
                return SWITCH_STATUS_FALSE;
        }
@@ -4241,6 +4420,9 @@ SWITCH_DECLARE(switch_status_t) switch_core_media_activate_rtp(switch_core_sessi
                goto end;
        }
 
+       switch_core_media_set_video_codec(session, 0);
+
+
        memset(flags, 0, sizeof(flags));
        flags[SWITCH_RTP_FLAG_DATAWAIT]++;
 
@@ -4287,32 +4469,19 @@ SWITCH_DECLARE(switch_status_t) switch_core_media_activate_rtp(switch_core_sessi
                char *remote_host = switch_rtp_get_remote_host(a_engine->rtp_session);
                switch_port_t remote_port = switch_rtp_get_remote_port(a_engine->rtp_session);
 
-               if (remote_host && remote_port && !strcmp(remote_host, a_engine->codec_params.remote_sdp_ip) && remote_port == a_engine->codec_params.remote_sdp_port) {
+               if (remote_host && remote_port && !strcmp(remote_host, a_engine->cur_payload_map->remote_sdp_ip) && 
+                       remote_port == a_engine->cur_payload_map->remote_sdp_port) {
                        switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Audio params are unchanged for %s.\n",
                                                          switch_channel_get_name(session->channel));
-                       if (switch_rtp_ready(a_engine->rtp_session)) {
-                               if (a_engine->codec_params.recv_pt != a_engine->codec_params.agreed_pt) {
-                                       switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, 
-                                                                 "%s Set audio receive payload in Re-INVITE for non-matching dynamic PT to %u\n", 
-                                                                         switch_channel_get_name(session->channel), a_engine->codec_params.recv_pt);
-                               
-                                       switch_rtp_set_recv_pt(a_engine->rtp_session, a_engine->codec_params.recv_pt);
-                               } else {
-                                       switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, 
-                                                                 "%s Setting audio receive payload in Re-INVITE to %u\n", 
-                                                                         switch_channel_get_name(session->channel), a_engine->codec_params.recv_pt);
-                                       switch_rtp_set_recv_pt(a_engine->rtp_session, a_engine->codec_params.agreed_pt);
-                               }
-
-                       }
+                       //XX
                        goto video;
                } else {
                        switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Audio params changed for %s from %s:%d to %s:%d\n",
                                                          switch_channel_get_name(session->channel),
-                                                         remote_host, remote_port, a_engine->codec_params.remote_sdp_ip, a_engine->codec_params.remote_sdp_port);
+                                                         remote_host, remote_port, a_engine->cur_payload_map->remote_sdp_ip, a_engine->cur_payload_map->remote_sdp_port);
 
-                       switch_snprintf(tmp, sizeof(tmp), "%d", a_engine->codec_params.remote_sdp_port);
-                       switch_channel_set_variable(session->channel, SWITCH_REMOTE_MEDIA_IP_VARIABLE, a_engine->codec_params.remote_sdp_ip);
+                       switch_snprintf(tmp, sizeof(tmp), "%d", a_engine->cur_payload_map->remote_sdp_port);
+                       switch_channel_set_variable(session->channel, SWITCH_REMOTE_MEDIA_IP_VARIABLE, a_engine->cur_payload_map->remote_sdp_ip);
                        switch_channel_set_variable(session->channel, SWITCH_REMOTE_MEDIA_PORT_VARIABLE, tmp);
                }
        }
@@ -4320,30 +4489,18 @@ SWITCH_DECLARE(switch_status_t) switch_core_media_activate_rtp(switch_core_sessi
        if (!switch_channel_test_flag(session->channel, CF_PROXY_MEDIA)) {
                switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "AUDIO RTP [%s] %s port %d -> %s port %d codec: %u ms: %d\n",
                                                  switch_channel_get_name(session->channel),
-                                                 a_engine->codec_params.local_sdp_ip,
-                                                 a_engine->codec_params.local_sdp_port,
-                                                 a_engine->codec_params.remote_sdp_ip,
-                                                 a_engine->codec_params.remote_sdp_port, a_engine->codec_params.agreed_pt, a_engine->read_impl.microseconds_per_packet / 1000);
-
-               if (switch_rtp_ready(a_engine->rtp_session)) {
-                       switch_rtp_set_default_payload(a_engine->rtp_session, a_engine->codec_params.agreed_pt);
-
-                       if (a_engine->codec_params.recv_pt != a_engine->codec_params.agreed_pt) {
-                               switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, 
-                                                                 "%s Set audio receive payload to %u\n", switch_channel_get_name(session->channel), a_engine->codec_params.recv_pt);
-                               
-                               switch_rtp_set_recv_pt(a_engine->rtp_session, a_engine->codec_params.recv_pt);
-                       } else {
-                               switch_rtp_set_recv_pt(a_engine->rtp_session, a_engine->codec_params.agreed_pt);
-                       }
+                                                 a_engine->local_sdp_ip,
+                                                 a_engine->local_sdp_port,
+                                                 a_engine->cur_payload_map->remote_sdp_ip,
+                                                 a_engine->cur_payload_map->remote_sdp_port, a_engine->cur_payload_map->agreed_pt, a_engine->read_impl.microseconds_per_packet / 1000);
 
-               }
+               //XX
        }
 
-       switch_snprintf(tmp, sizeof(tmp), "%d", a_engine->codec_params.local_sdp_port);
-       switch_channel_set_variable(session->channel, SWITCH_LOCAL_MEDIA_IP_VARIABLE, a_engine->codec_params.local_sdp_ip);
+       switch_snprintf(tmp, sizeof(tmp), "%d", a_engine->local_sdp_port);
+       switch_channel_set_variable(session->channel, SWITCH_LOCAL_MEDIA_IP_VARIABLE, a_engine->local_sdp_ip);
        switch_channel_set_variable(session->channel, SWITCH_LOCAL_MEDIA_PORT_VARIABLE, tmp);
-       switch_channel_set_variable(session->channel, SWITCH_ADVERTISED_MEDIA_IP_VARIABLE, a_engine->codec_params.adv_sdp_ip);
+       switch_channel_set_variable(session->channel, SWITCH_ADVERTISED_MEDIA_IP_VARIABLE, a_engine->adv_sdp_ip);
 
        if (a_engine->rtp_session && switch_channel_test_flag(session->channel, CF_REINVITE)) {
                const char *rport = NULL;
@@ -4355,14 +4512,14 @@ SWITCH_DECLARE(switch_status_t) switch_core_media_activate_rtp(switch_core_sessi
                        }
                }
 
-               if (switch_rtp_set_remote_address(a_engine->rtp_session, a_engine->codec_params.remote_sdp_ip, a_engine->codec_params.remote_sdp_port,
+               if (switch_rtp_set_remote_address(a_engine->rtp_session, a_engine->cur_payload_map->remote_sdp_ip, a_engine->cur_payload_map->remote_sdp_port,
                                                                                  remote_rtcp_port, SWITCH_TRUE, &err) != SWITCH_STATUS_SUCCESS) {
                        switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "AUDIO RTP REPORTS ERROR: [%s]\n", err);
                } else {
                        switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "AUDIO RTP CHANGING DEST TO: [%s:%d]\n",
-                                                         a_engine->codec_params.remote_sdp_ip, a_engine->codec_params.remote_sdp_port);
+                                                         a_engine->cur_payload_map->remote_sdp_ip, a_engine->cur_payload_map->remote_sdp_port);
 
-                       if (switch_channel_test_flag(session->channel, CF_PROTO_HOLD) && strcmp(a_engine->codec_params.remote_sdp_ip, "0.0.0.0")) {
+                       if (switch_channel_test_flag(session->channel, CF_PROTO_HOLD) && strcmp(a_engine->cur_payload_map->remote_sdp_ip, "0.0.0.0")) {
                                switch_core_media_toggle_hold(session, 0);
                        }
 
@@ -4398,13 +4555,13 @@ SWITCH_DECLARE(switch_status_t) switch_core_media_activate_rtp(switch_core_sessi
                switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG,
                                                  "PROXY AUDIO RTP [%s] %s:%d->%s:%d codec: %u ms: %d\n",
                                                  switch_channel_get_name(session->channel),
-                                                 a_engine->codec_params.remote_sdp_ip,
-                                                 a_engine->codec_params.remote_sdp_port,
-                                                 a_engine->codec_params.remote_sdp_ip,
-                                                 a_engine->codec_params.remote_sdp_port, a_engine->codec_params.agreed_pt, a_engine->read_impl.microseconds_per_packet / 1000);
+                                                 a_engine->cur_payload_map->remote_sdp_ip,
+                                                 a_engine->cur_payload_map->remote_sdp_port,
+                                                 a_engine->cur_payload_map->remote_sdp_ip,
+                                                 a_engine->cur_payload_map->remote_sdp_port, a_engine->cur_payload_map->agreed_pt, a_engine->read_impl.microseconds_per_packet / 1000);
 
                if (switch_rtp_ready(a_engine->rtp_session)) {
-                       switch_rtp_set_default_payload(a_engine->rtp_session, a_engine->codec_params.agreed_pt);
+                       switch_rtp_set_default_payload(a_engine->rtp_session, a_engine->cur_payload_map->agreed_pt);
                }
 
        } else {
@@ -4416,14 +4573,19 @@ SWITCH_DECLARE(switch_status_t) switch_core_media_activate_rtp(switch_core_sessi
        }
 
        if (switch_channel_up(session->channel)) {
-               a_engine->rtp_session = switch_rtp_new(a_engine->codec_params.local_sdp_ip,
-                                                                                          a_engine->codec_params.local_sdp_port,
-                                                                                          a_engine->codec_params.remote_sdp_ip,
-                                                                                          a_engine->codec_params.remote_sdp_port,
-                                                                                          a_engine->codec_params.agreed_pt,
+
+               a_engine->rtp_session = switch_rtp_new(a_engine->local_sdp_ip,
+                                                                                          a_engine->local_sdp_port,
+                                                                                          a_engine->cur_payload_map->remote_sdp_ip,
+                                                                                          a_engine->cur_payload_map->remote_sdp_port,
+                                                                                          a_engine->cur_payload_map->agreed_pt,
                                                                                           a_engine->read_impl.samples_per_packet,
-                                                                                          a_engine->codec_params.codec_ms * 1000,
+                                                                                          a_engine->cur_payload_map->codec_ms * 1000,
                                                                                           flags, timer_name, &err, switch_core_session_get_pool(session));
+
+               if (switch_rtp_ready(a_engine->rtp_session)) {
+                       switch_rtp_set_payload_map(a_engine->rtp_session, &a_engine->payload_map);
+               }
        }
 
        if (switch_rtp_ready(a_engine->rtp_session)) {
@@ -4450,7 +4612,7 @@ SWITCH_DECLARE(switch_status_t) switch_core_media_activate_rtp(switch_core_sessi
 
                switch_channel_set_flag(session->channel, CF_FS_RTP);
 
-               switch_channel_set_variable_printf(session->channel, "rtp_use_pt", "%d", a_engine->codec_params.agreed_pt);
+               switch_channel_set_variable_printf(session->channel, "rtp_use_pt", "%d", a_engine->cur_payload_map->agreed_pt);
 
                if ((val = switch_channel_get_variable(session->channel, "rtp_enable_vad_in")) && switch_true(val)) {
                        vad_in = 1;
@@ -4680,12 +4842,7 @@ SWITCH_DECLARE(switch_status_t) switch_core_media_activate_rtp(switch_core_sessi
                        switch_channel_set_variable_printf(session->channel, "rtp_2833_recv_payload", "%d", smh->mparams->recv_te);
                }
 
-               if (a_engine->codec_params.recv_pt != a_engine->codec_params.agreed_pt) {
-                       switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, 
-                                                         "%s Set audio receive payload to %u\n", switch_channel_get_name(session->channel), a_engine->codec_params.recv_pt);
-
-                       switch_rtp_set_recv_pt(a_engine->rtp_session, a_engine->codec_params.recv_pt);
-               }
+               //XX
 
                if (switch_media_handle_test_media_flag(smh, SCMF_SUPPRESS_CNG) ||
                        ((val = switch_channel_get_variable(session->channel, "supress_cng")) && switch_true(val)) ||
@@ -4714,8 +4871,8 @@ SWITCH_DECLARE(switch_status_t) switch_core_media_activate_rtp(switch_core_sessi
 
                switch_core_session_apply_crypto(session, SWITCH_MEDIA_TYPE_AUDIO);
 
-               switch_snprintf(tmp, sizeof(tmp), "%d", a_engine->codec_params.remote_sdp_port);
-               switch_channel_set_variable(session->channel, SWITCH_REMOTE_MEDIA_IP_VARIABLE, a_engine->codec_params.remote_sdp_ip);
+               switch_snprintf(tmp, sizeof(tmp), "%d", a_engine->cur_payload_map->remote_sdp_port);
+               switch_channel_set_variable(session->channel, SWITCH_REMOTE_MEDIA_IP_VARIABLE, a_engine->cur_payload_map->remote_sdp_ip);
                switch_channel_set_variable(session->channel, SWITCH_REMOTE_MEDIA_PORT_VARIABLE, tmp);
 
 
@@ -4737,8 +4894,8 @@ SWITCH_DECLARE(switch_status_t) switch_core_media_activate_rtp(switch_core_sessi
                if (switch_channel_direction(session->channel) == SWITCH_CALL_DIRECTION_OUTBOUND) {
                        switch_core_media_check_video_codecs(session);
                }
-               
-               if (switch_channel_test_flag(session->channel, CF_VIDEO_POSSIBLE) && v_engine->codec_params.rm_encoding && v_engine->codec_params.remote_sdp_port) {
+
+               if (switch_channel_test_flag(session->channel, CF_VIDEO_POSSIBLE) && v_engine->cur_payload_map->rm_encoding && v_engine->cur_payload_map->remote_sdp_port) {
                        /******************************************************************************************/
                        if (v_engine->rtp_session && switch_channel_test_flag(session->channel, CF_REINVITE)) {
                                //const char *ip = switch_channel_get_variable(session->channel, SWITCH_LOCAL_MEDIA_IP_VARIABLE);
@@ -4748,14 +4905,14 @@ SWITCH_DECLARE(switch_status_t) switch_core_media_activate_rtp(switch_core_sessi
                                
 
 
-                               if (remote_host && remote_port && !strcmp(remote_host, v_engine->codec_params.remote_sdp_ip) && remote_port == v_engine->codec_params.remote_sdp_port) {
+                               if (remote_host && remote_port && !strcmp(remote_host, v_engine->cur_payload_map->remote_sdp_ip) && remote_port == v_engine->cur_payload_map->remote_sdp_port) {
                                        switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Video params are unchanged for %s.\n",
                                                                          switch_channel_get_name(session->channel));
                                        goto video_up;
                                } else {
                                        switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Video params changed for %s from %s:%d to %s:%d\n",
                                                                          switch_channel_get_name(session->channel),
-                                                                         remote_host, remote_port, v_engine->codec_params.remote_sdp_ip, v_engine->codec_params.remote_sdp_port);
+                                                                         remote_host, remote_port, v_engine->cur_payload_map->remote_sdp_ip, v_engine->cur_payload_map->remote_sdp_port);
                                }
                        }
 
@@ -4763,17 +4920,17 @@ SWITCH_DECLARE(switch_status_t) switch_core_media_activate_rtp(switch_core_sessi
                                if (switch_rtp_ready(v_engine->rtp_session)) {
                                        switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG,
                                                                          "VIDEO RTP [%s] %s port %d -> %s port %d codec: %u ms: %d\n", switch_channel_get_name(session->channel),
-                                                                         a_engine->codec_params.remote_sdp_ip, v_engine->codec_params.local_sdp_port, v_engine->codec_params.remote_sdp_ip,
-                                                                         v_engine->codec_params.remote_sdp_port, v_engine->codec_params.agreed_pt, 
+                                                                         a_engine->cur_payload_map->remote_sdp_ip, v_engine->local_sdp_port, v_engine->cur_payload_map->remote_sdp_ip,
+                                                                         v_engine->cur_payload_map->remote_sdp_port, v_engine->cur_payload_map->agreed_pt, 
                                                                          a_engine->read_impl.microseconds_per_packet / 1000);
 
                                        start_video_thread(session);
-                                       switch_rtp_set_default_payload(v_engine->rtp_session, v_engine->codec_params.agreed_pt);
+                                       switch_rtp_set_default_payload(v_engine->rtp_session, v_engine->cur_payload_map->agreed_pt);
                                }
                        }
                        
-                       switch_snprintf(tmp, sizeof(tmp), "%d", v_engine->codec_params.local_sdp_port);
-                       switch_channel_set_variable(session->channel, SWITCH_LOCAL_VIDEO_IP_VARIABLE, a_engine->codec_params.adv_sdp_ip);
+                       switch_snprintf(tmp, sizeof(tmp), "%d", v_engine->local_sdp_port);
+                       switch_channel_set_variable(session->channel, SWITCH_LOCAL_VIDEO_IP_VARIABLE, a_engine->adv_sdp_ip);
                        switch_channel_set_variable(session->channel, SWITCH_LOCAL_VIDEO_PORT_VARIABLE, tmp);
 
 
@@ -4790,12 +4947,12 @@ SWITCH_DECLARE(switch_status_t) switch_core_media_activate_rtp(switch_core_sessi
                                }
                                
                                if (switch_rtp_set_remote_address
-                                       (v_engine->rtp_session, v_engine->codec_params.remote_sdp_ip, v_engine->codec_params.remote_sdp_port, remote_rtcp_port, SWITCH_TRUE,
+                                       (v_engine->rtp_session, v_engine->cur_payload_map->remote_sdp_ip, v_engine->cur_payload_map->remote_sdp_port, remote_rtcp_port, SWITCH_TRUE,
                                         &err) != SWITCH_STATUS_SUCCESS) {
                                        switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "VIDEO RTP REPORTS ERROR: [%s]\n", err);
                                } else {
                                        switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "VIDEO RTP CHANGING DEST TO: [%s:%d]\n",
-                                                                         v_engine->codec_params.remote_sdp_ip, v_engine->codec_params.remote_sdp_port);
+                                                                         v_engine->cur_payload_map->remote_sdp_ip, v_engine->cur_payload_map->remote_sdp_port);
                                        if (!switch_media_handle_test_media_flag(smh, SCMF_DISABLE_RTP_AUTOADJ) && !switch_channel_test_flag(session->channel, CF_WEBRTC) &&
                                                !((val = switch_channel_get_variable(session->channel, "disable_rtp_auto_adjust")) && switch_true(val))) {
                                                /* Reactivate the NAT buster flag. */
@@ -4823,13 +4980,13 @@ SWITCH_DECLARE(switch_status_t) switch_core_media_activate_rtp(switch_core_sessi
                                switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG,
                                                                  "PROXY VIDEO RTP [%s] %s:%d->%s:%d codec: %u ms: %d\n",
                                                                  switch_channel_get_name(session->channel),
-                                                                 a_engine->codec_params.remote_sdp_ip,
-                                                                 v_engine->codec_params.local_sdp_port,
-                                                                 v_engine->codec_params.remote_sdp_ip,
-                                                                 v_engine->codec_params.remote_sdp_port, v_engine->codec_params.agreed_pt, v_engine->read_impl.microseconds_per_packet / 1000);
+                                                                 a_engine->cur_payload_map->remote_sdp_ip,
+                                                                 v_engine->local_sdp_port,
+                                                                 v_engine->cur_payload_map->remote_sdp_ip,
+                                                                 v_engine->cur_payload_map->remote_sdp_port, v_engine->cur_payload_map->agreed_pt, v_engine->read_impl.microseconds_per_packet / 1000);
 
                                if (switch_rtp_ready(v_engine->rtp_session)) {
-                                       switch_rtp_set_default_payload(v_engine->rtp_session, v_engine->codec_params.agreed_pt);
+                                       switch_rtp_set_default_payload(v_engine->rtp_session, v_engine->cur_payload_map->agreed_pt);
                                }
                        } else {
                                timer_name = smh->mparams->timer_name;
@@ -4846,7 +5003,7 @@ SWITCH_DECLARE(switch_status_t) switch_core_media_activate_rtp(switch_core_sessi
                        }
 
 
-                       if (!v_engine->codec_params.local_sdp_port) {
+                       if (!v_engine->local_sdp_port) {
                                switch_core_media_choose_port(session, SWITCH_MEDIA_TYPE_VIDEO, 1);
                        }
 
@@ -4869,31 +5026,32 @@ SWITCH_DECLARE(switch_status_t) switch_core_media_activate_rtp(switch_core_sessi
                        flags[SWITCH_RTP_FLAG_NOBLOCK] = 0;
                        flags[SWITCH_RTP_FLAG_VIDEO]++;
 
-                       v_engine->rtp_session = switch_rtp_new(a_engine->codec_params.local_sdp_ip,
-                                                                                                                v_engine->codec_params.local_sdp_port,
-                                                                                                                v_engine->codec_params.remote_sdp_ip,
-                                                                                                                v_engine->codec_params.remote_sdp_port,
-                                                                                                                v_engine->codec_params.agreed_pt,
+                       v_engine->rtp_session = switch_rtp_new(a_engine->local_sdp_ip,
+                                                                                                                v_engine->local_sdp_port,
+                                                                                                                v_engine->cur_payload_map->remote_sdp_ip,
+                                                                                                                v_engine->cur_payload_map->remote_sdp_port,
+                                                                                                                v_engine->cur_payload_map->agreed_pt,
                                                                                                                 1, 90000, flags, NULL, &err, switch_core_session_get_pool(session));
 
 
                        switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "%sVIDEO RTP [%s] %s:%d->%s:%d codec: %u ms: %d [%s]\n",
                                                          switch_channel_test_flag(session->channel, CF_PROXY_MEDIA) ? "PROXY " : "",
                                                          switch_channel_get_name(session->channel),
-                                                         a_engine->codec_params.remote_sdp_ip,
-                                                         v_engine->codec_params.local_sdp_port,
-                                                         v_engine->codec_params.remote_sdp_ip,
-                                                         v_engine->codec_params.remote_sdp_port, v_engine->codec_params.agreed_pt,
+                                                         a_engine->cur_payload_map->remote_sdp_ip,
+                                                         v_engine->local_sdp_port,
+                                                         v_engine->cur_payload_map->remote_sdp_ip,
+                                                         v_engine->cur_payload_map->remote_sdp_port, v_engine->cur_payload_map->agreed_pt,
                                                          0, switch_rtp_ready(v_engine->rtp_session) ? "SUCCESS" : err);
 
 
-                       if (switch_rtp_ready(v_engine->rtp_session)) {
-                               start_video_thread(session);
-                       }
-
                        if (switch_rtp_ready(v_engine->rtp_session)) {
                                const char *ssrc;
+
+                               switch_rtp_set_payload_map(v_engine->rtp_session, &v_engine->payload_map);
+
+                               start_video_thread(session);
                                switch_channel_set_flag(session->channel, CF_VIDEO);
+
                                if ((ssrc = switch_channel_get_variable(session->channel, "rtp_use_video_ssrc"))) {
                                        uint32_t ssrc_ul = (uint32_t) strtoul(ssrc, NULL, 10);
                                        switch_rtp_set_ssrc(v_engine->rtp_session, ssrc_ul);
@@ -5007,13 +5165,11 @@ SWITCH_DECLARE(switch_status_t) switch_core_media_activate_rtp(switch_core_sessi
                                
                                switch_rtp_intentional_bugs(v_engine->rtp_session, v_engine->rtp_bugs | smh->mparams->manual_video_rtp_bugs);
 
-                               if (v_engine->codec_params.recv_pt != v_engine->codec_params.agreed_pt) {
-                                       switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, 
-                                                                         "%s Set video receive payload to %u\n", switch_channel_get_name(session->channel), v_engine->codec_params.recv_pt);
-                                       switch_rtp_set_recv_pt(v_engine->rtp_session, v_engine->codec_params.recv_pt);
-                               }
+                               
+                               //XX
 
-                               switch_channel_set_variable_printf(session->channel, "rtp_use_video_pt", "%d", v_engine->codec_params.agreed_pt);
+
+                               switch_channel_set_variable_printf(session->channel, "rtp_use_video_pt", "%d", v_engine->cur_payload_map->agreed_pt);
                                v_engine->ssrc = switch_rtp_get_ssrc(v_engine->rtp_session);
                                switch_channel_set_variable_printf(session->channel, "rtp_use_video_ssrc", "%u", v_engine->ssrc);
 
@@ -5082,7 +5238,8 @@ static const char *get_media_profile_name(switch_core_session_t *session, int se
 //?
 static void generate_m(switch_core_session_t *session, char *buf, size_t buflen, 
                                           switch_port_t port, const char *family, const char *ip,
-                                          int cur_ptime, const char *append_audio, const char *sr, int use_cng, int cng_type, switch_event_t *map, int secure)
+                                          int cur_ptime, const char *append_audio, const char *sr, int use_cng, int cng_type, switch_event_t *map, int secure, 
+                                          switch_sdp_type_t sdp_type)
 {
        int i = 0;
        int rate;
@@ -5202,7 +5359,7 @@ static void generate_m(switch_core_session_t *session, char *buf, size_t buflen,
                                fmtp = check;
                        }
                }
-               
+
                if (smh->ianacodes[i] > 95 || switch_channel_test_flag(session->channel, CF_VERBOSE_SDP)) {
                        int channels = get_channels(imp->iananame, imp->number_of_channels);
 
@@ -5280,14 +5437,14 @@ static void generate_m(switch_core_session_t *session, char *buf, size_t buflen,
                                                ice_out->cands[0][0].con_addr, ice_out->cands[0][0].con_port
                                                );
 
-               if (!zstr(a_engine->codec_params.local_sdp_ip) && !zstr(ice_out->cands[0][0].con_addr) && 
-                       strcmp(a_engine->codec_params.local_sdp_ip, ice_out->cands[0][0].con_addr)
-                       && a_engine->codec_params.local_sdp_port != ice_out->cands[0][0].con_port) {
+               if (!zstr(a_engine->local_sdp_ip) && !zstr(ice_out->cands[0][0].con_addr) && 
+                       strcmp(a_engine->local_sdp_ip, ice_out->cands[0][0].con_addr)
+                       && a_engine->local_sdp_port != ice_out->cands[0][0].con_port) {
 
                        switch_snprintf(buf + strlen(buf), buflen - strlen(buf), "a=candidate:%s 1 %s %u %s %d typ srflx raddr %s rport %d generation 0\n", 
                                                        tmp2, ice_out->cands[0][0].transport, c2,
                                                        ice_out->cands[0][0].con_addr, ice_out->cands[0][0].con_port,
-                                                       a_engine->codec_params.local_sdp_ip, a_engine->codec_params.local_sdp_port
+                                                       a_engine->local_sdp_ip, a_engine->local_sdp_port
                                                        );
                }
 
@@ -5299,14 +5456,14 @@ static void generate_m(switch_core_session_t *session, char *buf, size_t buflen,
                                                        ice_out->cands[0][0].con_addr, ice_out->cands[0][0].con_port + (a_engine->rtcp_mux > 0 ? 0 : 1)
                                                        );
                        
-                       if (!zstr(a_engine->codec_params.local_sdp_ip) && !zstr(ice_out->cands[0][1].con_addr) && 
-                               strcmp(a_engine->codec_params.local_sdp_ip, ice_out->cands[0][1].con_addr)
-                               && a_engine->codec_params.local_sdp_port != ice_out->cands[0][1].con_port) {
+                       if (!zstr(a_engine->local_sdp_ip) && !zstr(ice_out->cands[0][1].con_addr) && 
+                               strcmp(a_engine->local_sdp_ip, ice_out->cands[0][1].con_addr)
+                               && a_engine->local_sdp_port != ice_out->cands[0][1].con_port) {
                                
                                switch_snprintf(buf + strlen(buf), buflen - strlen(buf), "a=candidate:%s 2 %s %u %s %d typ srflx raddr %s rport %d generation 0\n", 
                                                                tmp2, ice_out->cands[0][0].transport, c2,
                                                                ice_out->cands[0][0].con_addr, ice_out->cands[0][0].con_port + (a_engine->rtcp_mux > 0 ? 0 : 1),
-                                                               a_engine->codec_params.local_sdp_ip, a_engine->codec_params.local_sdp_port + (a_engine->rtcp_mux > 0 ? 0 : 1)
+                                                               a_engine->local_sdp_ip, a_engine->local_sdp_port + (a_engine->rtcp_mux > 0 ? 0 : 1)
                                                                );
                        }
                }
@@ -5458,7 +5615,7 @@ SWITCH_DECLARE(void)switch_core_media_set_local_sdp(switch_core_session_t *sessi
 
 //?
 #define SDPBUFLEN 65536
-SWITCH_DECLARE(void) switch_core_media_gen_local_sdp(switch_core_session_t *session, const char *ip, switch_port_t port, const char *sr, int force)
+SWITCH_DECLARE(void) switch_core_media_gen_local_sdp(switch_core_session_t *session, switch_sdp_type_t sdp_type, const char *ip, switch_port_t port, const char *sr, int force)
 {
        char *buf;
        int ptime = 0;
@@ -5486,6 +5643,7 @@ SWITCH_DECLARE(void) switch_core_media_gen_local_sdp(switch_core_session_t *sess
        switch_media_handle_t *smh;
        ice_t *ice_out;
        int vp8 = 0;
+       payload_map_t *pmap;
 
        switch_assert(session);
 
@@ -5528,7 +5686,7 @@ SWITCH_DECLARE(void) switch_core_media_gen_local_sdp(switch_core_session_t *sess
                }
        }
 
-       fmtp_out = a_engine->codec_params.fmtp_out;
+       fmtp_out = a_engine->cur_payload_map->fmtp_out;
        username = smh->mparams->sdp_username;
 
 
@@ -5543,26 +5701,40 @@ SWITCH_DECLARE(void) switch_core_media_gen_local_sdp(switch_core_session_t *sess
                smh->mparams->cng_pt = 0;
        }
 
+
        if (!smh->payload_space) {
                int i;
 
                smh->payload_space = 98;
 
-               for (i = 0; i < smh->mparams->num_codecs; i++) {
-                       const switch_codec_implementation_t *imp = smh->codecs[i];
-
-                       smh->ianacodes[i] = imp->ianacode;
-                       
-                       if (smh->ianacodes[i] > 64) {
-                               if (smh->mparams->dtmf_type == DTMF_2833 && smh->mparams->te > 95 && smh->mparams->te == smh->payload_space) {
-                                       smh->payload_space++;
-                               }
-                               if (!switch_media_handle_test_media_flag(smh, SCMF_SUPPRESS_CNG) &&
-                                       smh->mparams->cng_pt && use_cng  && smh->mparams->cng_pt == smh->payload_space) {
-                                       smh->payload_space++;
+               if (sdp_type == SDP_TYPE_REQUEST) {
+                       for (i = 0; i < smh->mparams->num_codecs; i++) {
+                               const switch_codec_implementation_t *imp = smh->codecs[i];
+                               
+                               smh->ianacodes[i] = imp->ianacode;
+                               
+                               if (smh->ianacodes[i] > 64) {
+                                       if (smh->mparams->dtmf_type == DTMF_2833 && smh->mparams->te > 95 && smh->mparams->te == smh->payload_space) {
+                                               smh->payload_space++;
+                                       }
+                                       if (!switch_media_handle_test_media_flag(smh, SCMF_SUPPRESS_CNG) &&
+                                               smh->mparams->cng_pt && use_cng  && smh->mparams->cng_pt == smh->payload_space) {
+                                               smh->payload_space++;
+                                       }
+                                       smh->ianacodes[i] = (switch_payload_t)smh->payload_space++;
                                }
-                               smh->ianacodes[i] = (switch_payload_t)smh->payload_space++;
+                               
+
+                               switch_core_media_add_payload_map(session,
+                                                                                                 imp->codec_type == SWITCH_CODEC_TYPE_AUDIO ? SWITCH_MEDIA_TYPE_AUDIO : SWITCH_MEDIA_TYPE_VIDEO,
+                                                                                                 imp->iananame,
+                                                                                                 sdp_type,
+                                                                                                 smh->ianacodes[i],
+                                                                                                 imp->samples_per_second,
+                                                                                                 imp->microseconds_per_packet / 1000,
+                                                                                                 SWITCH_FALSE);
                        }
+                               
                }
        }
 
@@ -5581,8 +5753,8 @@ SWITCH_DECLARE(void) switch_core_media_gen_local_sdp(switch_core_session_t *sess
        }
 
        if (!ip) {
-               if (!(ip = a_engine->codec_params.adv_sdp_ip)) {
-                       ip = a_engine->codec_params.proxy_sdp_ip;
+               if (!(ip = a_engine->adv_sdp_ip)) {
+                       ip = a_engine->proxy_sdp_ip;
                }
        }
 
@@ -5593,8 +5765,8 @@ SWITCH_DECLARE(void) switch_core_media_gen_local_sdp(switch_core_session_t *sess
        }
 
        if (!port) {
-               if (!(port = a_engine->codec_params.adv_sdp_port)) {
-                       port = a_engine->codec_params.proxy_sdp_port;
+               if (!(port = a_engine->adv_sdp_port)) {
+                       port = a_engine->proxy_sdp_port;
                }
        }
 
@@ -5604,7 +5776,7 @@ SWITCH_DECLARE(void) switch_core_media_gen_local_sdp(switch_core_session_t *sess
                return;
        }
 
-       if (!a_engine->codec_params.rm_encoding && (b_sdp = switch_channel_get_variable(session->channel, SWITCH_B_SDP_VARIABLE))) {
+       if (!a_engine->cur_payload_map->rm_encoding && (b_sdp = switch_channel_get_variable(session->channel, SWITCH_B_SDP_VARIABLE))) {
                switch_core_media_sdp_map(b_sdp, &map, &ptmap);
        }
 
@@ -5655,7 +5827,7 @@ SWITCH_DECLARE(void) switch_core_media_gen_local_sdp(switch_core_session_t *sess
        }
 
 
-       if (a_engine->codec_params.rm_encoding) {
+       if (a_engine->codec_negotiated) {
                /*
                switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), "m=audio %d RTP/%sAVP%s", 
                                                port, ((!zstr(local_audio_crypto_key) || switch_channel_test_flag(session->channel, CF_DTLS)) && 
@@ -5670,7 +5842,18 @@ SWITCH_DECLARE(void) switch_core_media_gen_local_sdp(switch_core_session_t *sess
                                                                                           ));
                
                
-               switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), " %d", a_engine->codec_params.pt);
+               switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), " %d", a_engine->cur_payload_map->pt);
+
+               
+               if (switch_media_handle_test_media_flag(smh, SCMF_MULTI_ANSWER_AUDIO)) {
+                       switch_mutex_lock(smh->mutex);
+                       for (pmap = a_engine->cur_payload_map; pmap && pmap->allocated; pmap = pmap->next) {
+                               if (pmap->pt != a_engine->cur_payload_map->pt) {
+                                       switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), " %d", pmap->pt);
+                               }
+                       }
+                       switch_mutex_unlock(smh->mutex);
+               }
 
                if ((smh->mparams->dtmf_type == DTMF_2833 || switch_media_handle_test_media_flag(smh, SCMF_LIBERAL_DTMF) || 
                         switch_channel_test_flag(session->channel, CF_LIBERAL_DTMF)) && smh->mparams->te > 95) {
@@ -5684,24 +5867,37 @@ SWITCH_DECLARE(void) switch_core_media_gen_local_sdp(switch_core_session_t *sess
                switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), "\n");
 
 
-               rate = a_engine->codec_params.adv_rm_rate;
+               rate = a_engine->cur_payload_map->adv_rm_rate;
 
-               if (!a_engine->codec_params.adv_channels) {
-                       a_engine->codec_params.adv_channels = get_channels(a_engine->codec_params.rm_encoding, 1);
+               if (!a_engine->cur_payload_map->adv_channels) {
+                       a_engine->cur_payload_map->adv_channels = get_channels(a_engine->cur_payload_map->rm_encoding, 1);
                }
-
-               if (a_engine->codec_params.adv_channels > 1) {
+               
+               if (a_engine->cur_payload_map->adv_channels > 1) {
                        switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), "a=rtpmap:%d %s/%d/%d\n", 
-                                                       a_engine->codec_params.agreed_pt, a_engine->codec_params.rm_encoding, rate, a_engine->codec_params.adv_channels);
+                                                       a_engine->cur_payload_map->agreed_pt, a_engine->cur_payload_map->rm_encoding, rate, a_engine->cur_payload_map->adv_channels);
                } else {
                        switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), "a=rtpmap:%d %s/%d\n", 
-                                                       a_engine->codec_params.agreed_pt, a_engine->codec_params.rm_encoding, rate);
+                                                       a_engine->cur_payload_map->agreed_pt, a_engine->cur_payload_map->rm_encoding, rate);
                }
 
                if (fmtp_out) {
-                       switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), "a=fmtp:%d %s\n", a_engine->codec_params.agreed_pt, fmtp_out);
+                       switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), "a=fmtp:%d %s\n", a_engine->cur_payload_map->agreed_pt, fmtp_out);
+               }
+
+               if (switch_media_handle_test_media_flag(smh, SCMF_MULTI_ANSWER_AUDIO)) {
+                       switch_mutex_lock(smh->mutex);
+                       for (pmap = a_engine->cur_payload_map; pmap && pmap->allocated; pmap = pmap->next) {
+                               if (pmap->pt != a_engine->cur_payload_map->pt) {
+                                       switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), "a=rtpmap:%d %s/%ld\n",
+                                                                       pmap->pt, pmap->iananame,
+                                                                       pmap->rate);
+                               }
+                       }
+                       switch_mutex_unlock(smh->mutex);
                }
 
+
                if (a_engine->read_codec.implementation && !ptime) {
                        ptime = a_engine->read_codec.implementation->microseconds_per_packet / 1000;
                }
@@ -5722,7 +5918,7 @@ SWITCH_DECLARE(void) switch_core_media_gen_local_sdp(switch_core_session_t *sess
                } else if (smh->mparams->cng_pt && use_cng) {
                        switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), "a=rtpmap:%d CN/8000\n", smh->mparams->cng_pt);
 
-                       if (!a_engine->codec_params.rm_encoding) {
+                       if (!a_engine->codec_negotiated) {
                                smh->mparams->cng_pt = 0;
                        }
                }
@@ -5795,14 +5991,14 @@ SWITCH_DECLARE(void) switch_core_media_gen_local_sdp(switch_core_session_t *sess
                                                        ice_out->cands[0][0].con_addr, ice_out->cands[0][0].con_port
                                                        );
 
-                       if (!zstr(a_engine->codec_params.local_sdp_ip) && !zstr(ice_out->cands[0][0].con_addr) && 
-                               strcmp(a_engine->codec_params.local_sdp_ip, ice_out->cands[0][0].con_addr)
-                               && a_engine->codec_params.local_sdp_port != ice_out->cands[0][0].con_port) {
+                       if (!zstr(a_engine->local_sdp_ip) && !zstr(ice_out->cands[0][0].con_addr) && 
+                               strcmp(a_engine->local_sdp_ip, ice_out->cands[0][0].con_addr)
+                               && a_engine->local_sdp_port != ice_out->cands[0][0].con_port) {
 
                                switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), "a=candidate:%s 1 %s %u %s %d typ srflx raddr %s rport %d generation 0\n", 
                                                                tmp2, ice_out->cands[0][0].transport, c3,
                                                                ice_out->cands[0][0].con_addr, ice_out->cands[0][0].con_port,
-                                                               a_engine->codec_params.local_sdp_ip, a_engine->codec_params.local_sdp_port
+                                                               a_engine->local_sdp_ip, a_engine->local_sdp_port
                                                                );
                        }
 
@@ -5817,14 +6013,14 @@ SWITCH_DECLARE(void) switch_core_media_gen_local_sdp(switch_core_session_t *sess
                                
 
                                
-                               if (!zstr(a_engine->codec_params.local_sdp_ip) && !zstr(ice_out->cands[0][0].con_addr) && 
-                                       strcmp(a_engine->codec_params.local_sdp_ip, ice_out->cands[0][0].con_addr)
-                                       && a_engine->codec_params.local_sdp_port != ice_out->cands[0][0].con_port) {                    
+                               if (!zstr(a_engine->local_sdp_ip) && !zstr(ice_out->cands[0][0].con_addr) && 
+                                       strcmp(a_engine->local_sdp_ip, ice_out->cands[0][0].con_addr)
+                                       && a_engine->local_sdp_port != ice_out->cands[0][0].con_port) {                 
                                        
                                        switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), "a=candidate:%s 2 %s %u %s %d typ srflx raddr %s rport %d generation 0\n", 
                                                                        tmp2, ice_out->cands[0][0].transport, c4,
                                                                        ice_out->cands[0][0].con_addr, ice_out->cands[0][0].con_port + (a_engine->rtcp_mux > 0 ? 0 : 1),
-                                                                       a_engine->codec_params.local_sdp_ip, a_engine->codec_params.local_sdp_port + (a_engine->rtcp_mux > 0 ? 0 : 1)
+                                                                       a_engine->local_sdp_ip, a_engine->local_sdp_port + (a_engine->rtcp_mux > 0 ? 0 : 1)
                                                                        );
                                }
                        }
@@ -5851,7 +6047,7 @@ SWITCH_DECLARE(void) switch_core_media_gen_local_sdp(switch_core_session_t *sess
                if (!switch_media_handle_test_media_flag(smh, SCMF_SUPPRESS_CNG) && smh->mparams->cng_pt && use_cng) {
                        cng_type = smh->mparams->cng_pt;
 
-                       if (!a_engine->codec_params.rm_encoding) {
+                       if (!a_engine->codec_negotiated) {
                                smh->mparams->cng_pt = 0;
                        }
                }
@@ -5865,7 +6061,7 @@ SWITCH_DECLARE(void) switch_core_media_gen_local_sdp(switch_core_session_t *sess
 
                        if ((!zstr(local_audio_crypto_key) && switch_channel_test_flag(session->channel, CF_SECURE)) || 
                                switch_channel_test_flag(session->channel, CF_DTLS)) {
-                               generate_m(session, buf, SDPBUFLEN, port, family, ip, 0, append_audio, sr, use_cng, cng_type, map, 1);
+                               generate_m(session, buf, SDPBUFLEN, port, family, ip, 0, append_audio, sr, use_cng, cng_type, map, 1, sdp_type);
                                bp = (buf + strlen(buf));
 
                                /* asterisk can't handle AVP and SAVP in sep streams, way to blow off the spec....*/
@@ -5876,7 +6072,7 @@ SWITCH_DECLARE(void) switch_core_media_gen_local_sdp(switch_core_session_t *sess
                        }
 
                        if (both) {
-                               generate_m(session, bp, SDPBUFLEN - strlen(buf), port, family, ip, 0, append_audio, sr, use_cng, cng_type, map, 0);
+                               generate_m(session, bp, SDPBUFLEN - strlen(buf), port, family, ip, 0, append_audio, sr, use_cng, cng_type, map, 0, sdp_type);
                        }
 
                } else {
@@ -5902,7 +6098,7 @@ SWITCH_DECLARE(void) switch_core_media_gen_local_sdp(switch_core_session_t *sess
                                        
                                        if ((!zstr(local_audio_crypto_key) && switch_channel_test_flag(session->channel, CF_SECURE)) || 
                                                switch_channel_test_flag(session->channel, CF_DTLS)) {
-                                               generate_m(session, bp, SDPBUFLEN - strlen(buf), port, family, ip, cur_ptime, append_audio, sr, use_cng, cng_type, map, 1);
+                                               generate_m(session, bp, SDPBUFLEN - strlen(buf), port, family, ip, cur_ptime, append_audio, sr, use_cng, cng_type, map, 1, sdp_type);
                                                bp = (buf + strlen(buf));
 
                                                /* asterisk can't handle AVP and SAVP in sep streams, way to blow off the spec....*/
@@ -5916,7 +6112,7 @@ SWITCH_DECLARE(void) switch_core_media_gen_local_sdp(switch_core_session_t *sess
                                        }
 
                                        if (both) {
-                                               generate_m(session, bp, SDPBUFLEN - strlen(buf), port, family, ip, cur_ptime, append_audio, sr, use_cng, cng_type, map, 0);
+                                               generate_m(session, bp, SDPBUFLEN - strlen(buf), port, family, ip, cur_ptime, append_audio, sr, use_cng, cng_type, map, 0, sdp_type);
                                        }
                                }
                                
@@ -5935,11 +6131,15 @@ SWITCH_DECLARE(void) switch_core_media_gen_local_sdp(switch_core_session_t *sess
                }
 
                
-               if (!v_engine->codec_params.local_sdp_port) {
+               if (!v_engine->local_sdp_port) {
                        switch_core_media_choose_port(session, SWITCH_MEDIA_TYPE_VIDEO, 0);
                }
 
-               if ((v_port = v_engine->codec_params.adv_sdp_port)) {
+               if (switch_channel_test_flag(session->channel, CF_WEBRTC)) {
+                       switch_media_handle_set_media_flag(smh, SCMF_MULTI_ANSWER_VIDEO);
+               }
+
+               if ((v_port = v_engine->adv_sdp_port)) {
 
                        if (switch_channel_test_flag(smh->session->channel, CF_ICE)) {
                                gen_ice(session, SWITCH_MEDIA_TYPE_VIDEO, ip, (switch_port_t)v_port);
@@ -5959,14 +6159,27 @@ SWITCH_DECLARE(void) switch_core_media_gen_local_sdp(switch_core_session_t *sess
                        
 
                        /*****************************/
-                       if (v_engine->codec_params.rm_encoding) {
+                       if (v_engine->codec_negotiated) {
+                               payload_map_t *pmap;
                                switch_core_media_set_video_codec(session, 0);
-                               switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), " %d", v_engine->codec_params.agreed_pt);
+                               switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), " %d", v_engine->cur_payload_map->agreed_pt);
+                               
+                               if (switch_media_handle_test_media_flag(smh, SCMF_MULTI_ANSWER_VIDEO)) {
+                                       switch_mutex_lock(smh->mutex);
+                                       for (pmap = v_engine->cur_payload_map; pmap && pmap->allocated; pmap = pmap->next) {
+                                               if (pmap->pt != v_engine->cur_payload_map->pt) {
+                                                       switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), " %d", pmap->pt);
+                                               }
+                                       }
+                                       switch_mutex_unlock(smh->mutex);
+                               }
+
                        } else if (smh->mparams->num_codecs) {
                                int i;
                                int already_did[128] = { 0 };
                                for (i = 0; i < smh->mparams->num_codecs; i++) {
                                        const switch_codec_implementation_t *imp = smh->codecs[i];
+                                       
 
                                        if (imp->codec_type != SWITCH_CODEC_TYPE_VIDEO) {
                                                continue;
@@ -5985,6 +6198,7 @@ SWITCH_DECLARE(void) switch_core_media_gen_local_sdp(switch_core_session_t *sess
                                        }
 
                                        switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), " %d", smh->ianacodes[i]);
+
                                        if (!ptime) {
                                                ptime = imp->microseconds_per_packet / 1000;
                                        }
@@ -5994,20 +6208,22 @@ SWITCH_DECLARE(void) switch_core_media_gen_local_sdp(switch_core_session_t *sess
                        switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), "\n");
 
                        
-                       if (v_engine->codec_params.rm_encoding) {
+                       if (v_engine->codec_negotiated) {
                                const char *of;
+                               payload_map_t *pmap;
 
-                               if (!strcasecmp(v_engine->codec_params.rm_encoding, "VP8")) {
-                                       vp8 = v_engine->codec_params.pt;
+                               if (!strcasecmp(v_engine->cur_payload_map->rm_encoding, "VP8")) {
+                                       vp8 = v_engine->cur_payload_map->pt;
                                }
 
-                               rate = v_engine->codec_params.rm_rate;
+                               rate = v_engine->cur_payload_map->rm_rate;
                                switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), "a=rtpmap:%d %s/%ld\n",
-                                                               v_engine->codec_params.pt, v_engine->codec_params.rm_encoding,
-                                                               v_engine->codec_params.rm_rate);
+                                                               v_engine->cur_payload_map->pt, v_engine->cur_payload_map->rm_encoding,
+                                                               v_engine->cur_payload_map->rm_rate);
+
 
                                if (switch_channel_test_flag(session->channel, CF_RECOVERING)) {
-                                       pass_fmtp = v_engine->codec_params.rm_fmtp;
+                                       pass_fmtp = v_engine->cur_payload_map->rm_fmtp;
                                } else {
 
                                        pass_fmtp = NULL;
@@ -6026,9 +6242,23 @@ SWITCH_DECLARE(void) switch_core_media_gen_local_sdp(switch_core_session_t *sess
                                }
 
                                if (pass_fmtp) {
-                                       switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), "a=fmtp:%d %s\n", v_engine->codec_params.pt, pass_fmtp);
+                                       switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), "a=fmtp:%d %s\n", v_engine->cur_payload_map->pt, pass_fmtp);
+                               }
+
+
+                               if (switch_media_handle_test_media_flag(smh, SCMF_MULTI_ANSWER_VIDEO)) {
+                                       switch_mutex_lock(smh->mutex);
+                                       for (pmap = v_engine->cur_payload_map; pmap && pmap->allocated; pmap = pmap->next) {
+                                               if (pmap->pt != v_engine->cur_payload_map->pt) {
+                                                       switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), "a=rtpmap:%d %s/%ld\n",
+                                                                                       pmap->pt, pmap->iananame, pmap->rate);
+                                                       
+                                               }
+                                       }
+                                       switch_mutex_unlock(smh->mutex);
                                }
 
+
                                if (append_video) {
                                        switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), "%s%s", append_video, end_of(append_video) == '\n' ? "" : "\n");
                                }
@@ -6169,14 +6399,14 @@ SWITCH_DECLARE(void) switch_core_media_gen_local_sdp(switch_core_session_t *sess
                                                                ice_out->cands[0][0].con_addr, ice_out->cands[0][0].con_port
                                                                );
 
-                               if (!zstr(v_engine->codec_params.local_sdp_ip) && !zstr(ice_out->cands[0][0].con_addr) && 
-                                       strcmp(v_engine->codec_params.local_sdp_ip, ice_out->cands[0][0].con_addr)
-                                       && v_engine->codec_params.local_sdp_port != ice_out->cands[0][0].con_port) {
+                               if (!zstr(v_engine->local_sdp_ip) && !zstr(ice_out->cands[0][0].con_addr) && 
+                                       strcmp(v_engine->local_sdp_ip, ice_out->cands[0][0].con_addr)
+                                       && v_engine->local_sdp_port != ice_out->cands[0][0].con_port) {
 
                                        switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), "a=candidate:%s 1 %s %u %s %d typ srflx raddr %s rport %d generation 0\n", 
                                                                        tmp2, ice_out->cands[0][0].transport, c3,
                                                                        ice_out->cands[0][0].con_addr, ice_out->cands[0][0].con_port,
-                                                                       v_engine->codec_params.local_sdp_ip, v_engine->codec_params.local_sdp_port
+                                                                       v_engine->local_sdp_ip, v_engine->local_sdp_port
                                                                        );
                                }
 
@@ -6190,14 +6420,14 @@ SWITCH_DECLARE(void) switch_core_media_gen_local_sdp(switch_core_session_t *sess
                                                                        );
                                        
                                        
-                                       if (!zstr(v_engine->codec_params.local_sdp_ip) && !zstr(ice_out->cands[0][1].con_addr) && 
-                                               strcmp(v_engine->codec_params.local_sdp_ip, ice_out->cands[0][1].con_addr)
-                                               && v_engine->codec_params.local_sdp_port != ice_out->cands[0][1].con_port) {
+                                       if (!zstr(v_engine->local_sdp_ip) && !zstr(ice_out->cands[0][1].con_addr) && 
+                                               strcmp(v_engine->local_sdp_ip, ice_out->cands[0][1].con_addr)
+                                               && v_engine->local_sdp_port != ice_out->cands[0][1].con_port) {
                                                
                                                switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), "a=candidate:%s 2 %s %u %s %d typ srflx generation 0\n", 
                                                                                tmp2, ice_out->cands[0][0].transport, c4,
                                                                                ice_out->cands[0][0].con_addr, ice_out->cands[0][0].con_port + (v_engine->rtcp_mux > 0 ? 0 : 1),
-                                                                               v_engine->codec_params.local_sdp_ip, v_engine->codec_params.local_sdp_port + (v_engine->rtcp_mux > 0 ? 0 : 1)
+                                                                               v_engine->local_sdp_ip, v_engine->local_sdp_port + (v_engine->rtcp_mux > 0 ? 0 : 1)
                                                                                );
                                        }
                                }
@@ -6273,10 +6503,10 @@ SWITCH_DECLARE(void) switch_core_media_absorb_sdp(switch_core_session_t *session
                                        }
 
                                        if (connection) {
-                                               a_engine->codec_params.proxy_sdp_ip = switch_core_session_strdup(session, connection->c_address);
+                                               a_engine->proxy_sdp_ip = switch_core_session_strdup(session, connection->c_address);
                                        }
-                                       a_engine->codec_params.proxy_sdp_port = (switch_port_t) m->m_port;
-                                       if (a_engine->codec_params.proxy_sdp_ip && a_engine->codec_params.proxy_sdp_port) {
+                                       a_engine->proxy_sdp_port = (switch_port_t) m->m_port;
+                                       if (a_engine->proxy_sdp_ip && a_engine->proxy_sdp_port) {
                                                break;
                                        }
                                }
@@ -6332,8 +6562,8 @@ SWITCH_DECLARE(void) switch_core_media_set_udptl_image_sdp(switch_core_session_t
 
 
        if (!ip) {
-               if (!(ip = a_engine->codec_params.adv_sdp_ip)) {
-                       ip = a_engine->codec_params.proxy_sdp_ip;
+               if (!(ip = a_engine->adv_sdp_ip)) {
+                       ip = a_engine->proxy_sdp_ip;
                }
        }
 
@@ -6343,8 +6573,8 @@ SWITCH_DECLARE(void) switch_core_media_set_udptl_image_sdp(switch_core_session_t
        }
 
        if (!port) {
-               if (!(port = a_engine->codec_params.adv_sdp_port)) {
-                       port = a_engine->codec_params.proxy_sdp_port;
+               if (!(port = a_engine->adv_sdp_port)) {
+                       port = a_engine->proxy_sdp_port;
                }
        }
 
@@ -6471,20 +6701,20 @@ SWITCH_DECLARE(void) switch_core_media_patch_sdp(switch_core_session_t *session)
                return;
        }
 
-       if (zstr(a_engine->codec_params.local_sdp_ip) || !a_engine->codec_params.local_sdp_port) {// || switch_channel_test_flag(session->channel, CF_PROXY_MEDIA)) {
+       if (zstr(a_engine->local_sdp_ip) || !a_engine->local_sdp_port) {// || switch_channel_test_flag(session->channel, CF_PROXY_MEDIA)) {
                if (switch_core_media_choose_port(session, SWITCH_MEDIA_TYPE_AUDIO, 1) != SWITCH_STATUS_SUCCESS) {
                        switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "%s I/O Error\n",
                                                          switch_channel_get_name(session->channel));
                        return;
                }
-               a_engine->codec_params.iananame = switch_core_session_strdup(session, "PROXY");
-               a_engine->codec_params.rm_rate = 8000;
-               a_engine->codec_params.adv_rm_rate = 8000;
-               a_engine->codec_params.codec_ms = 20;
+               a_engine->cur_payload_map->iananame = switch_core_session_strdup(session, "PROXY");
+               a_engine->cur_payload_map->rm_rate = 8000;
+               a_engine->cur_payload_map->adv_rm_rate = 8000;
+               a_engine->cur_payload_map->codec_ms = 20;
        }
 
        new_sdp = switch_core_session_alloc(session, len);
-       switch_snprintf(port_buf, sizeof(port_buf), "%u", a_engine->codec_params.local_sdp_port);
+       switch_snprintf(port_buf, sizeof(port_buf), "%u", a_engine->local_sdp_port);
 
 
        p = smh->mparams->local_sdp_str;
@@ -6504,15 +6734,15 @@ SWITCH_DECLARE(void) switch_core_media_patch_sdp(switch_core_session_t *session)
                        goto end;
                }
 
-               if (a_engine->codec_params.local_sdp_ip && !strncmp("c=IN IP", p, 7)) {
+               if (a_engine->local_sdp_ip && !strncmp("c=IN IP", p, 7)) {
                        strncpy(q, p, 7);
                        p += 7;
                        q += 7;
-                       strncpy(q, strchr(a_engine->codec_params.adv_sdp_ip, ':') ? "6 " : "4 ", 2);
+                       strncpy(q, strchr(a_engine->adv_sdp_ip, ':') ? "6 " : "4 ", 2);
                        p +=2;
                        q +=2;                  
-                       strncpy(q, a_engine->codec_params.adv_sdp_ip, strlen(a_engine->codec_params.adv_sdp_ip));
-                       q += strlen(a_engine->codec_params.adv_sdp_ip);
+                       strncpy(q, a_engine->adv_sdp_ip, strlen(a_engine->adv_sdp_ip));
+                       q += strlen(a_engine->adv_sdp_ip);
 
                        while (p && *p && ((*p >= '0' && *p <= '9') || *p == '.' || *p == ':' || (*p >= 'A' && *p <= 'F') || (*p >= 'a' && *p <= 'f'))) {
                                if (p >= pe) {
@@ -6623,11 +6853,11 @@ SWITCH_DECLARE(void) switch_core_media_patch_sdp(switch_core_session_t *session)
                } else if (!strncmp("m=video ", p, 8) && *(p + 8) != '0') {
                        if (!has_video) {
                                switch_core_media_choose_port(session, SWITCH_MEDIA_TYPE_VIDEO, 1);
-                               v_engine->codec_params.rm_encoding = "PROXY-VID";
-                               v_engine->codec_params.rm_rate = 90000;
-                               v_engine->codec_params.adv_rm_rate = 90000;
-                               v_engine->codec_params.codec_ms = 0;
-                               switch_snprintf(vport_buf, sizeof(vport_buf), "%u", v_engine->codec_params.adv_sdp_port);
+                               v_engine->cur_payload_map->rm_encoding = "PROXY-VID";
+                               v_engine->cur_payload_map->rm_rate = 90000;
+                               v_engine->cur_payload_map->adv_rm_rate = 90000;
+                               v_engine->cur_payload_map->codec_ms = 0;
+                               switch_snprintf(vport_buf, sizeof(vport_buf), "%u", v_engine->adv_sdp_port);
                                if (switch_channel_media_ready(session->channel) && !switch_rtp_ready(v_engine->rtp_session)) {
                                        switch_channel_set_flag(session->channel, CF_VIDEO_POSSIBLE);
                                        switch_channel_set_flag(session->channel, CF_REINVITE);
@@ -7055,9 +7285,9 @@ SWITCH_DECLARE(switch_status_t) switch_core_media_receive_message(switch_core_se
                        const char *ip = NULL, *port = NULL;
 
                        switch_channel_set_flag(session->channel, CF_PROXY_MODE);
-                       if (a_engine->codec_params.rm_encoding) {
-                               a_engine->codec_params.rm_encoding = NULL;
-                       }
+
+                       a_engine->codec_negotiated = 0;
+
                        switch_core_media_set_local_sdp(session, NULL, SWITCH_FALSE);
 
                        if (switch_true(switch_channel_get_variable(session->channel, "bypass_keep_codec"))) {
@@ -7072,7 +7302,7 @@ SWITCH_DECLARE(switch_status_t) switch_core_media_receive_message(switch_core_se
                                port = switch_channel_get_variable(other_channel, SWITCH_REMOTE_MEDIA_PORT_VARIABLE);
                                switch_core_session_rwunlock(other_session);
                                if (ip && port) {
-                                       switch_core_media_gen_local_sdp(session, ip, (switch_port_t)atoi(port), NULL, 1);
+                                       switch_core_media_gen_local_sdp(session, SDP_TYPE_REQUEST, ip, (switch_port_t)atoi(port), NULL, 1);
                                }
                        }
 
@@ -7109,19 +7339,18 @@ SWITCH_DECLARE(switch_status_t) switch_core_media_receive_message(switch_core_se
                                        switch_channel_set_variable(session->channel, "codec_string", msg->string_arg);
                                } else {
                                        switch_channel_set_variable_printf(session->channel, "codec_string", "=%s%s%s,%s", 
-                                                                                                          v_engine->codec_params.rm_encoding ? v_engine->codec_params.rm_encoding : "",
-                                                                                                          v_engine->codec_params.rm_encoding ? "," : "",
-                                                                                                          a_engine->codec_params.rm_encoding, msg->string_arg);                                        
+                                                                                                          v_engine->cur_payload_map->rm_encoding ? v_engine->cur_payload_map->rm_encoding : "",
+                                                                                                          v_engine->cur_payload_map->rm_encoding ? "," : "",
+                                                                                                          a_engine->cur_payload_map->rm_encoding, msg->string_arg);                                    
                                }
 
 
-
-                               a_engine->codec_params.rm_encoding = NULL;
-                               v_engine->codec_params.rm_encoding = NULL;
+                               a_engine->codec_negotiated = 0;
+                               v_engine->codec_negotiated = 0;
                                switch_channel_clear_flag(session->channel, CF_VIDEO_POSSIBLE);
                                switch_core_media_prepare_codecs(session, SWITCH_TRUE);
                                switch_core_media_check_video_codecs(session);
-                               switch_core_media_gen_local_sdp(session, NULL, 0, NULL, 1);
+                               switch_core_media_gen_local_sdp(session, SDP_TYPE_REQUEST, NULL, 0, NULL, 1);
                        }
 
                        switch_media_handle_set_media_flag(smh, SCMF_RENEG_ON_REINVITE);
@@ -7302,22 +7531,6 @@ SWITCH_DECLARE(void) switch_core_media_clear_rtp_flag(switch_core_session_t *ses
        }       
 }
 
-//?
-SWITCH_DECLARE(void) switch_core_media_set_recv_pt(switch_core_session_t *session, switch_media_type_t type, switch_payload_t pt)
-{
-       switch_media_handle_t *smh;
-
-       switch_assert(session);
-
-       if (!(smh = session->media_handle)) {
-               return;
-       }
-
-       if (switch_rtp_ready(smh->engines[type].rtp_session)) {
-               switch_rtp_set_recv_pt(smh->engines[type].rtp_session, pt);
-       }
-}
-
 //?
 SWITCH_DECLARE(void) switch_core_media_set_telephony_event(switch_core_session_t *session, switch_media_type_t type, switch_payload_t te)
 {
@@ -7694,7 +7907,7 @@ SWITCH_DECLARE(switch_status_t) switch_core_media_codec_chosen(switch_core_sessi
        
        engine = &smh->engines[type];
 
-       if (engine->codec_params.iananame) {
+       if (engine->cur_payload_map->iananame) {
                return SWITCH_STATUS_SUCCESS;
        }
 
@@ -7726,18 +7939,18 @@ SWITCH_DECLARE(void) switch_core_media_check_outgoing_proxy(switch_core_session_
 
        switch_channel_set_flag(session->channel, CF_PROXY_MEDIA);
        
-       a_engine->codec_params.iananame = switch_core_session_strdup(session, "PROXY");
-       a_engine->codec_params.rm_rate = 8000;
-       a_engine->codec_params.adv_rm_rate = 8000;
+       a_engine->cur_payload_map->iananame = switch_core_session_strdup(session, "PROXY");
+       a_engine->cur_payload_map->rm_rate = 8000;
+       a_engine->cur_payload_map->adv_rm_rate = 8000;
 
-       a_engine->codec_params.codec_ms = 20;
+       a_engine->cur_payload_map->codec_ms = 20;
        
        if (switch_stristr("m=video", r_sdp)) {
                switch_core_media_choose_port(session, SWITCH_MEDIA_TYPE_VIDEO, 1);
-               v_engine->codec_params.rm_encoding = "PROXY-VID";
-               v_engine->codec_params.rm_rate = 90000;
-               v_engine->codec_params.adv_rm_rate = 90000;
-               v_engine->codec_params.codec_ms = 0;
+               v_engine->cur_payload_map->rm_encoding = "PROXY-VID";
+               v_engine->cur_payload_map->rm_rate = 90000;
+               v_engine->cur_payload_map->adv_rm_rate = 90000;
+               v_engine->cur_payload_map->codec_ms = 0;
                switch_channel_set_flag(session->channel, CF_VIDEO);
                switch_channel_set_flag(session->channel, CF_VIDEO_POSSIBLE);
        }
@@ -7806,10 +8019,10 @@ SWITCH_DECLARE(void) switch_core_media_proxy_codec(switch_core_session_t *sessio
                        }
 
                        for (map = m->m_rtpmaps; map; map = map->rm_next) {
-                               a_engine->codec_params.iananame = switch_core_session_strdup(session, map->rm_encoding);
-                               a_engine->codec_params.rm_rate = map->rm_rate;
-                               a_engine->codec_params.adv_rm_rate = map->rm_rate;
-                               a_engine->codec_params.codec_ms = ptime;
+                               a_engine->cur_payload_map->iananame = switch_core_session_strdup(session, map->rm_encoding);
+                               a_engine->cur_payload_map->rm_rate = map->rm_rate;
+                               a_engine->cur_payload_map->adv_rm_rate = map->rm_rate;
+                               a_engine->cur_payload_map->codec_ms = ptime;
                                switch_core_media_set_codec(session, 0, smh->mparams->codec_flags);
                                break;
                        }
@@ -7856,9 +8069,8 @@ SWITCH_DECLARE (void) switch_core_media_recover_session(switch_core_session_t *s
        a_engine = &smh->engines[SWITCH_MEDIA_TYPE_AUDIO];
        v_engine = &smh->engines[SWITCH_MEDIA_TYPE_VIDEO];
 
-
-       a_engine->codec_params.iananame = a_engine->codec_params.rm_encoding = (char *) switch_channel_get_variable(session->channel, "rtp_use_codec_name");
-       a_engine->codec_params.rm_fmtp = (char *) switch_channel_get_variable(session->channel, "rtp_use_codec_fmtp");
+       a_engine->cur_payload_map->iananame = a_engine->cur_payload_map->rm_encoding = (char *) switch_channel_get_variable(session->channel, "rtp_use_codec_name");
+       a_engine->cur_payload_map->rm_fmtp = (char *) switch_channel_get_variable(session->channel, "rtp_use_codec_fmtp");
 
        if ((tmp = switch_channel_get_variable(session->channel, SWITCH_R_SDP_VARIABLE))) {
                smh->mparams->remote_sdp_str = switch_core_session_strdup(session, tmp);
@@ -7885,52 +8097,52 @@ SWITCH_DECLARE (void) switch_core_media_recover_session(switch_core_session_t *s
        }
 
        if ((tmp = switch_channel_get_variable(session->channel, "rtp_use_codec_rate"))) {
-               a_engine->codec_params.rm_rate = atoi(tmp);
-               a_engine->codec_params.adv_rm_rate = a_engine->codec_params.rm_rate;
+               a_engine->cur_payload_map->rm_rate = atoi(tmp);
+               a_engine->cur_payload_map->adv_rm_rate = a_engine->cur_payload_map->rm_rate;
        }
 
        if ((tmp = switch_channel_get_variable(session->channel, "rtp_use_codec_ptime"))) {
-               a_engine->codec_params.codec_ms = atoi(tmp);
+               a_engine->cur_payload_map->codec_ms = atoi(tmp);
        }
 
        if ((tmp = switch_channel_get_variable(session->channel, "rtp_use_pt"))) {
-               a_engine->codec_params.pt = a_engine->codec_params.agreed_pt = (switch_payload_t)atoi(tmp);
+               a_engine->cur_payload_map->pt = a_engine->cur_payload_map->agreed_pt = (switch_payload_t)atoi(tmp);
        }
 
        if ((tmp = switch_channel_get_variable(session->channel, "rtp_audio_recv_pt"))) {
-               a_engine->codec_params.recv_pt = a_engine->codec_params.agreed_pt = (switch_payload_t)atoi(tmp);;
+               a_engine->cur_payload_map->recv_pt = (switch_payload_t)atoi(tmp);
        }
                        
        switch_core_media_set_codec(session, 1, smh->mparams->codec_flags);
 
-       a_engine->codec_params.adv_sdp_ip = smh->mparams->extrtpip = (char *) ip;
-       a_engine->codec_params.adv_sdp_port = a_engine->codec_params.local_sdp_port = (switch_port_t)atoi(port);
+       a_engine->adv_sdp_ip = smh->mparams->extrtpip = (char *) ip;
+       a_engine->adv_sdp_port = a_engine->local_sdp_port = (switch_port_t)atoi(port);
 
        if (!zstr(ip)) {
-               a_engine->codec_params.local_sdp_ip = switch_core_session_strdup(session, ip);
-               smh->mparams->rtpip = a_engine->codec_params.local_sdp_ip;
+               a_engine->local_sdp_ip = switch_core_session_strdup(session, ip);
+               smh->mparams->rtpip = a_engine->local_sdp_ip;
        }
 
        if (!zstr(a_ip)) {
-               a_engine->codec_params.adv_sdp_ip = switch_core_session_strdup(session, a_ip);
+               a_engine->adv_sdp_ip = switch_core_session_strdup(session, a_ip);
        }
 
        if (r_ip && r_port) {
-               a_engine->codec_params.remote_sdp_ip = (char *) r_ip;
-               a_engine->codec_params.remote_sdp_port = (switch_port_t)atoi(r_port);
+               a_engine->cur_payload_map->remote_sdp_ip = (char *) r_ip;
+               a_engine->cur_payload_map->remote_sdp_port = (switch_port_t)atoi(r_port);
        }
 
        if (switch_channel_test_flag(session->channel, CF_VIDEO)) {
                if ((tmp = switch_channel_get_variable(session->channel, "rtp_use_video_pt"))) {
-                       v_engine->codec_params.pt = v_engine->codec_params.agreed_pt = (switch_payload_t)atoi(tmp);
+                       v_engine->cur_payload_map->pt = v_engine->cur_payload_map->agreed_pt = (switch_payload_t)atoi(tmp);
                }
                
                if ((tmp = switch_channel_get_variable(session->channel, "rtp_video_recv_pt"))) {
-                       v_engine->codec_params.recv_pt = a_engine->codec_params.agreed_pt = (switch_payload_t)atoi(tmp);;
+                       v_engine->cur_payload_map->recv_pt = (switch_payload_t)atoi(tmp);;
                }
 
-               v_engine->codec_params.rm_encoding = (char *) switch_channel_get_variable(session->channel, "rtp_use_video_codec_name");
-               v_engine->codec_params.rm_fmtp = (char *) switch_channel_get_variable(session->channel, "rtp_use_video_codec_fmtp");
+               v_engine->cur_payload_map->rm_encoding = (char *) switch_channel_get_variable(session->channel, "rtp_use_video_codec_name");
+               v_engine->cur_payload_map->rm_fmtp = (char *) switch_channel_get_variable(session->channel, "rtp_use_video_codec_fmtp");
 
                ip = switch_channel_get_variable(session->channel, SWITCH_LOCAL_VIDEO_IP_VARIABLE);
                port = switch_channel_get_variable(session->channel, SWITCH_LOCAL_VIDEO_PORT_VARIABLE);
@@ -7940,23 +8152,24 @@ SWITCH_DECLARE (void) switch_core_media_recover_session(switch_core_session_t *s
                switch_channel_set_flag(session->channel, CF_VIDEO_POSSIBLE);
 
                if ((tmp = switch_channel_get_variable(session->channel, "rtp_use_video_codec_rate"))) {
-                       v_engine->codec_params.rm_rate = atoi(tmp);
-                       v_engine->codec_params.adv_rm_rate = v_engine->codec_params.rm_rate;
+                       v_engine->cur_payload_map->rm_rate = atoi(tmp);
+                       v_engine->cur_payload_map->adv_rm_rate = v_engine->cur_payload_map->rm_rate;
                }
 
                if ((tmp = switch_channel_get_variable(session->channel, "rtp_use_video_codec_ptime"))) {
-                       v_engine->codec_params.codec_ms = atoi(tmp);
+                       v_engine->cur_payload_map->codec_ms = atoi(tmp);
                }
 
-               v_engine->codec_params.adv_sdp_port = v_engine->codec_params.local_sdp_port = (switch_port_t)atoi(port);
+               v_engine->adv_sdp_port = v_engine->local_sdp_port = (switch_port_t)atoi(port);
 
                if (r_ip && r_port) {
-                       v_engine->codec_params.remote_sdp_ip = (char *) r_ip;
-                       v_engine->codec_params.remote_sdp_port = (switch_port_t)atoi(r_port);
+                       v_engine->cur_payload_map->remote_sdp_ip = (char *) r_ip;
+                       v_engine->cur_payload_map->remote_sdp_port = (switch_port_t)atoi(r_port);
                }
        }
 
-       switch_core_media_gen_local_sdp(session, NULL, 0, NULL, 1);
+       switch_core_media_gen_local_sdp(session, SDP_TYPE_REQUEST, NULL, 0, NULL, 1);
+       switch_core_media_set_video_codec(session, 1);
 
        if (switch_core_media_activate_rtp(session) != SWITCH_STATUS_SUCCESS) {
                return;
@@ -7983,15 +8196,10 @@ SWITCH_DECLARE (void) switch_core_media_recover_session(switch_core_session_t *s
 
 
        if (switch_core_media_ready(session, SWITCH_MEDIA_TYPE_AUDIO)) {
-               switch_core_media_set_recv_pt(session, SWITCH_MEDIA_TYPE_AUDIO, a_engine->codec_params.recv_pt);
                switch_rtp_set_telephony_event(a_engine->rtp_session, smh->mparams->te);
                switch_rtp_set_telephony_recv_event(a_engine->rtp_session, smh->mparams->recv_te);
        }
 
-       if (switch_core_media_ready(session, SWITCH_MEDIA_TYPE_VIDEO)) {
-               switch_core_media_set_recv_pt(session, SWITCH_MEDIA_TYPE_VIDEO, v_engine->codec_params.recv_pt);
-       }
-
 }
 
 
index 4d644adf0c54a862328883b3dde997df0bfe4a08..a0e80013f05c4b56a022572bedec71df1a852c5e 100644 (file)
@@ -325,7 +325,6 @@ struct switch_rtp {
        int8_t sending_dtmf;
        uint8_t need_mark;
        switch_payload_t payload;
-       switch_payload_t rpayload;
        switch_rtp_invalid_handler_t invalid_handler;
        void *private_data;
        uint32_t ts;
@@ -398,6 +397,10 @@ struct switch_rtp {
        switch_size_t last_flush_packet_count;
        uint32_t interdigit_delay;
        switch_core_session_t *session;
+       payload_map_t **pmaps;
+       payload_map_t *pmap_tail;
+       int pmap_ttl;
+
 #ifdef ENABLE_ZRTP
        zrtp_session_t *zrtp_session;
        zrtp_profile_t *zrtp_profile;
@@ -1859,6 +1862,19 @@ SWITCH_DECLARE(switch_port_t) switch_rtp_request_port(const char *ip)
        return port;
 }
 
+SWITCH_DECLARE(switch_status_t) switch_rtp_set_payload_map(switch_rtp_t *rtp_session, payload_map_t **pmap)
+{
+
+       if (rtp_session) {
+               switch_mutex_lock(rtp_session->flag_mutex);
+               rtp_session->pmaps = pmap;
+               switch_mutex_unlock(rtp_session->flag_mutex);
+               return SWITCH_STATUS_SUCCESS;
+       }
+
+       return SWITCH_STATUS_FALSE;
+}
+
 SWITCH_DECLARE(void) switch_rtp_intentional_bugs(switch_rtp_t *rtp_session, switch_rtp_bug_flag_t bugs)
 {
        rtp_session->rtp_bugs = bugs;
@@ -2973,7 +2989,6 @@ SWITCH_DECLARE(switch_status_t) switch_rtp_create(switch_rtp_t **new_rtp_session
        rtp_session->recv_msg.header.cc = 0;
 
        rtp_session->payload = payload;
-       rtp_session->rpayload = payload;
 
        switch_rtp_set_interval(rtp_session, ms_per_packet, samples_per_interval);
        rtp_session->conf_samples_per_interval = samples_per_interval;
@@ -3164,11 +3179,6 @@ SWITCH_DECLARE(void) switch_rtp_set_telephony_recv_event(switch_rtp_t *rtp_sessi
        }
 }
 
-SWITCH_DECLARE(void) switch_rtp_set_recv_pt(switch_rtp_t *rtp_session, switch_payload_t pt)
-{
-       rtp_session->rpayload = pt;
-}
-
 
 SWITCH_DECLARE(void) switch_rtp_set_cng_pt(switch_rtp_t *rtp_session, switch_payload_t pt)
 {
@@ -4063,6 +4073,27 @@ static int jb_valid(switch_rtp_t *rtp_session)
        return 1;
 }
 
+static int check_recv_payload(switch_rtp_t *rtp_session)
+{
+       int ok = 0;
+
+       if (rtp_session->pmaps && *rtp_session->pmaps) {
+               payload_map_t *pmap;
+               switch_mutex_lock(rtp_session->flag_mutex);
+               for (pmap = *rtp_session->pmaps; pmap && pmap->allocated; pmap = pmap->next) {                                  
+                       if (!pmap->negotiated) {
+                               continue;
+                       }
+                       if (rtp_session->recv_msg.header.pt == pmap->pt) {
+                               ok = 1;
+                       }
+               }
+               switch_mutex_unlock(rtp_session->flag_mutex);
+       }
+
+       return ok;
+}
+
 #define return_cng_frame() do_cng = 1; goto timer_check
 
 static switch_status_t read_rtp_packet(switch_rtp_t *rtp_session, switch_size_t *bytes, switch_frame_flag_t *flags, switch_bool_t return_jb_packet)
@@ -4149,7 +4180,7 @@ static switch_status_t read_rtp_packet(switch_rtp_t *rtp_session, switch_size_t
        if (status == SWITCH_STATUS_SUCCESS && *bytes) { 
                if (rtp_session->flags[SWITCH_RTP_FLAG_RTCP_MUX]) { 
                        *flags &= ~SFF_RTCP;
-                       if (rtp_session->recv_msg.header.pt != rtp_session->rpayload && 
+                       if (!check_recv_payload(rtp_session)  && 
                                (!rtp_session->recv_te || rtp_session->recv_msg.header.pt != rtp_session->recv_te) &&
                                (!rtp_session->cng_pt || rtp_session->recv_msg.header.pt != rtp_session->cng_pt) &&
                                rtp_session->rtcp_recv_msg_p->header.version == 2 && 
@@ -4319,7 +4350,7 @@ static switch_status_t read_rtp_packet(switch_rtp_t *rtp_session, switch_size_t
                        
 #ifdef ENABLE_SRTP
                        if (rtp_session->flags[SWITCH_RTP_FLAG_SECURE_RECV] && rtp_session->recv_msg.header.version == 2 && 
-                               ((rtp_session->recv_msg.header.pt == rtp_session->rpayload) || 
+                               (check_recv_payload(rtp_session) || 
                                 (rtp_session->recv_te && rtp_session->recv_msg.header.pt == rtp_session->recv_te) || 
                                 (rtp_session->cng_pt && rtp_session->recv_msg.header.pt == rtp_session->cng_pt))) {
                                //if (rtp_session->flags[SWITCH_RTP_FLAG_SECURE_RECV] && (!rtp_session->ice.ice_user || rtp_session->recv_msg.header.version == 2)) {
@@ -4376,7 +4407,7 @@ static switch_status_t read_rtp_packet(switch_rtp_t *rtp_session, switch_size_t
                rtp_session->last_read_ts = ts;
        }
        
-       if (rtp_session->flags[SWITCH_RTP_FLAG_BYTESWAP] && rtp_session->recv_msg.header.pt == rtp_session->rpayload) {
+       if (rtp_session->flags[SWITCH_RTP_FLAG_BYTESWAP] && check_recv_payload(rtp_session)) {
                switch_swap_linear((int16_t *)RTP_BODY(rtp_session), (int) *bytes - rtp_header_len);
        }
 
@@ -4602,7 +4633,8 @@ static int using_ice(switch_rtp_t *rtp_session)
        return 0;
 }
 
-static int rtp_common_read(switch_rtp_t *rtp_session, switch_payload_t *payload_type, switch_frame_flag_t *flags, switch_io_flag_t io_flags)
+static int rtp_common_read(switch_rtp_t *rtp_session, switch_payload_t *payload_type, 
+                                                  payload_map_t **pmapP, switch_frame_flag_t *flags, switch_io_flag_t io_flags)
 {
        
        switch_channel_t *channel = NULL;
@@ -4969,11 +5001,33 @@ static int rtp_common_read(switch_rtp_t *rtp_session, switch_payload_t *payload_
                        !rtp_session->flags[SWITCH_RTP_FLAG_PROXY_MEDIA] && !rtp_session->flags[SWITCH_RTP_FLAG_UDPTL] &&
                        rtp_session->recv_msg.header.pt != 13 && 
                        rtp_session->recv_msg.header.pt != rtp_session->recv_te && 
-                       (!rtp_session->cng_pt || rtp_session->recv_msg.header.pt != rtp_session->cng_pt) && 
-                       rtp_session->recv_msg.header.pt != rtp_session->rpayload && 
-                       !(rtp_session->rtp_bugs & RTP_BUG_ACCEPT_ANY_PAYLOAD) && !(rtp_session->rtp_bugs & RTP_BUG_ACCEPT_ANY_PACKETS)) {
-                       /* drop frames of incorrect payload number and return CNG frame instead */
-                       return_cng_frame();                     
+                       (!rtp_session->cng_pt || rtp_session->recv_msg.header.pt != rtp_session->cng_pt)) {
+                       int accept_packet = 0;
+                       
+
+                       if (rtp_session->pmaps && *rtp_session->pmaps) {
+                               payload_map_t *pmap;
+                               switch_mutex_lock(rtp_session->flag_mutex);
+                               for (pmap = *rtp_session->pmaps; pmap && pmap->allocated; pmap = pmap->next) {                                  
+                                       if (!pmap->negotiated) {
+                                               continue;
+                                       }
+
+                                       if (rtp_session->recv_msg.header.pt == pmap->pt) {
+                                               accept_packet = 1;
+                                               if (pmapP) {
+                                                       *pmapP = pmap;
+                                               }
+                                       }
+                               }
+                               switch_mutex_unlock(rtp_session->flag_mutex);
+                       }
+                       
+                       if (!accept_packet &&
+                               !(rtp_session->rtp_bugs & RTP_BUG_ACCEPT_ANY_PAYLOAD) && !(rtp_session->rtp_bugs & RTP_BUG_ACCEPT_ANY_PACKETS)) {
+                               /* drop frames of incorrect payload number and return CNG frame instead */
+                               return_cng_frame();
+                       }
                }
 
                if (!bytes && (io_flags & SWITCH_IO_FLAG_NOBLOCK)) {
@@ -5085,7 +5139,7 @@ static int rtp_common_read(switch_rtp_t *rtp_session, switch_payload_t *payload_
 
                        if (rtp_session->flags[SWITCH_RTP_FLAG_UDPTL]) {
 #if 0
-                               if (rtp_session->recv_msg.header.version == 2 && rtp_session->recv_msg.header.pt == rtp_session->rpayload) {
+                               if (rtp_session->recv_msg.header.version == 2 && check_recv_payload(rtp_session)) {
                                        switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(rtp_session->session), SWITCH_LOG_WARNING, 
                                                                          "Ignoring udptl packet of size of %ld bytes that looks strikingly like a RTP packet.\n", (long)bytes);
                                        bytes = 0;
@@ -5335,7 +5389,7 @@ SWITCH_DECLARE(switch_status_t) switch_rtp_read(switch_rtp_t *rtp_session, void
                return SWITCH_STATUS_FALSE;
        }
 
-       bytes = rtp_common_read(rtp_session, payload_type, flags, io_flags);
+       bytes = rtp_common_read(rtp_session, payload_type, NULL, flags, io_flags);
 
        if (bytes < 0) {
                *datalen = 0;
@@ -5415,7 +5469,7 @@ SWITCH_DECLARE(switch_status_t) switch_rtp_zerocopy_read_frame(switch_rtp_t *rtp
                return SWITCH_STATUS_FALSE;
        }
 
-       bytes = rtp_common_read(rtp_session, &frame->payload, &frame->flags, io_flags);
+       bytes = rtp_common_read(rtp_session, &frame->payload, &frame->pmap, &frame->flags, io_flags);
 
        frame->data = RTP_BODY(rtp_session);
        frame->packet = &rtp_session->recv_msg;
@@ -5504,7 +5558,7 @@ SWITCH_DECLARE(switch_status_t) switch_rtp_zerocopy_read(switch_rtp_t *rtp_sessi
                return SWITCH_STATUS_FALSE;
        }
 
-       bytes = rtp_common_read(rtp_session, payload_type, flags, io_flags);
+       bytes = rtp_common_read(rtp_session, payload_type, NULL, flags, io_flags);
        *data = RTP_BODY(rtp_session);
 
        if (bytes < 0) {
@@ -6146,12 +6200,26 @@ SWITCH_DECLARE(int) switch_rtp_write_frame(switch_rtp_t *rtp_session, switch_fra
                rtp_session->stats.outbound.packet_count++;
        }
 
+       if (frame->pmap && rtp_session->pmaps && *rtp_session->pmaps && rtp_session->pmap_ttl > 1) {
+               payload_map_t *pmap;
+               switch_mutex_lock(rtp_session->flag_mutex);
+
+               for (pmap = *rtp_session->pmaps; pmap; pmap = pmap->next) {
+                       if (pmap->hash == frame->pmap->hash && !strcmp(pmap->iananame, frame->pmap->iananame)) {
+                               payload = pmap->recv_pt;
+                               break;
+                       }
+               }
+               switch_mutex_unlock(rtp_session->flag_mutex);
+       }
+
        if (fwd) {
                send_msg = frame->packet;
                len = frame->packetlen;
                ts = 0;
                // Trying this based on http://jira.freeswitch.org/browse/MODSOFIA-90
                //if (frame->codec && frame->codec->agreed_pt == frame->payload) {
+
                send_msg->header.pt = payload;
                //}
        } else {
index 0eb66f6a1b4e9ce069c53384fe93d5dc975bcfdb..12b417b40afcd03e7a338ddecc7b09b62ca2c847 100644 (file)
@@ -114,7 +114,7 @@ SWITCH_DECLARE(switch_status_t) switch_frame_dup(switch_frame_t *orig, switch_fr
 
        memcpy(new_frame->data, orig->data, orig->datalen);
        new_frame->codec = NULL;
-
+       new_frame->pmap = NULL;
        *clone = new_frame;
 
        return SWITCH_STATUS_SUCCESS;