diff --git a/src/include/private/switch_core_pvt.h b/src/include/private/switch_core_pvt.h index bff9b72a78..aa6adb67e9 100644 --- a/src/include/private/switch_core_pvt.h +++ b/src/include/private/switch_core_pvt.h @@ -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 { diff --git a/src/include/switch_core_media.h b/src/include/switch_core_media.h index 9641718f07..5c083101a9 100644 --- a/src/include/switch_core_media.h +++ b/src/include/switch_core_media.h @@ -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 diff --git a/src/include/switch_frame.h b/src/include/switch_frame.h index 39ffb9ca6b..4e46b61d2f 100644 --- a/src/include/switch_frame.h +++ b/src/include/switch_frame.h @@ -37,6 +37,7 @@ #define SWITCH_FRAME_H #include +#include 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 diff --git a/src/include/switch_rtp.h b/src/include/switch_rtp.h index bd509cc29a..ca0b3f3b8d 100644 --- a/src/include/switch_rtp.h +++ b/src/include/switch_rtp.h @@ -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); diff --git a/src/mod/applications/mod_conference/mod_conference.c b/src/mod/applications/mod_conference/mod_conference.c index 8f3f1a81b8..2d7a9df244 100644 --- a/src/mod/applications/mod_conference/mod_conference.c +++ b/src/mod/applications/mod_conference/mod_conference.c @@ -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); diff --git a/src/mod/codecs/mod_vp8/mod_vp8.c b/src/mod/codecs/mod_vp8/mod_vp8.c index 121b9ab0c9..0fe64c72b8 100644 --- a/src/mod/codecs/mod_vp8/mod_vp8.c +++ b/src/mod/codecs/mod_vp8/mod_vp8.c @@ -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; } diff --git a/src/mod/endpoints/mod_sofia/mod_sofia.c b/src/mod/endpoints/mod_sofia/mod_sofia.c index 7286c5de16..dc6351799d 100644 --- a/src/mod/endpoints/mod_sofia/mod_sofia.c +++ b/src/mod/endpoints/mod_sofia/mod_sofia.c @@ -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); } diff --git a/src/mod/endpoints/mod_sofia/rtp.c b/src/mod/endpoints/mod_sofia/rtp.c index a34b8cfd74..a1467f9647 100644 --- a/src/mod/endpoints/mod_sofia/rtp.c +++ b/src/mod/endpoints/mod_sofia/rtp.c @@ -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)) { diff --git a/src/mod/endpoints/mod_sofia/sofia.c b/src/mod/endpoints/mod_sofia/sofia.c index f2194487d4..0a98cbf983 100644 --- a/src/mod/endpoints/mod_sofia/sofia.c +++ b/src/mod/endpoints/mod_sofia/sofia.c @@ -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); diff --git a/src/mod/endpoints/mod_sofia/sofia_glue.c b/src/mod/endpoints/mod_sofia/sofia_glue.c index 833a725d44..d5bbe14c55 100644 --- a/src/mod/endpoints/mod_sofia/sofia_glue.c +++ b/src/mod/endpoints/mod_sofia/sofia_glue.c @@ -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); diff --git a/src/switch_core_io.c b/src/switch_core_io.c index b1b42c7f1f..1a5a0469fe 100644 --- a/src/switch_core_io.c +++ b/src/switch_core_io.c @@ -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) { diff --git a/src/switch_core_media.c b/src/switch_core_media.c index d18b648546..59eacde94c 100644 --- a/src/switch_core_media.c +++ b/src/switch_core_media.c @@ -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 (!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_timeout_sec"))) { - int v = atoi(val); - if (v >= 0) { - rtp_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 ((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; + /* 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; - 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; - } + 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; + + 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 && greedy) { - skip++; - continue; - } - - 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; + 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); - switch_snprintf(tmp, sizeof(tmp), "%s@%uh@%ui", near_match->iananame, near_rate ? near_rate : near_match->samples_per_second, - codec_ms); + if (num) { + timp = search[0]; + } else { + timp = near_match; + } - prefs[0] = tmp; - num = switch_loadable_module_get_codecs_sorted(search, 1, prefs, 1); - - if (num) { - mimp = search[0]; - } else { - mimp = 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 (!zstr((char *) mmap->rm_fmtp) && switch_stristr("stereo=1", (char *) mmap->rm_fmtp)) { - a_engine->codec_params.channels = 2; - } else { - a_engine->codec_params.channels = 1; - } - } else { - a_engine->codec_params.adv_channels = a_engine->codec_params.channels; + if (greedy) { /* sort in favor of mine */ + greedy_sort(smh, matches, m_idx, codec_array, total_codecs); } - 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); + match = 1; + a_engine->codec_negotiated = 1; - 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); - 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); + 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; + } + + 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 { + pmap->adv_channels = pmap->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; + } - - switch_snprintf(tmp, sizeof(tmp), "%d", a_engine->codec_params.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) { + 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); + + + 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->cur_payload_map->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 (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++; } - } - 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"); - - 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; - - - 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; - - 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; - - 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); - } - - 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; - - check_ice(smh, SWITCH_MEDIA_TYPE_VIDEO, sdp, m); - //check_ice(smh, SWITCH_MEDIA_TYPE_VIDEO, sdp, NULL); - break; - } else { - vmatch = 0; - } + vmatch = 0; } } - + + if (m_idx) { + char tmp[50]; + const char *mirror = switch_channel_get_variable(session->channel, "rtp_mirror_remote_video_codec_payload"); + int j = 0; + + if (greedy) { /* sort in favor of mine */ + greedy_sort(smh, matches, m_idx, codec_array, total_codecs); + } + + vmatch = 1; + v_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_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; + + 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, &pmap->recv_pt); + } + } + + + + 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; + + 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); + 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); - 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); - } - - } + //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]; + 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] = 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++; + 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); - } - } diff --git a/src/switch_rtp.c b/src/switch_rtp.c index 4d644adf0c..a0e80013f0 100644 --- a/src/switch_rtp.c +++ b/src/switch_rtp.c @@ -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 { diff --git a/src/switch_utils.c b/src/switch_utils.c index 0eb66f6a1b..12b417b40a 100644 --- a/src/switch_utils.c +++ b/src/switch_utils.c @@ -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;