diff --git a/CHANGES b/CHANGES
index 03b2f78bf72ba29e33cd3ae5e9ae26c09894e106..4e9df4fa58d704f1af1ebd0faeff6f1887520542 100644
--- a/CHANGES
+++ b/CHANGES
@@ -140,6 +140,13 @@ res_pjsip_endpoint_identifier_ip
    appropriate, as it now matches inbound requests on more than just IP
    address.
 
+res_rtp_asterisk
+-----------------
+ * The RTP layer of Asterisk now has support for RFC 5761: "Multiplexing RTP
+   Data and Control Packets on a Single Port." So far, the only channel driver
+   that supports this feature is chan_pjsip. You can set "rtcp_mux = yes" on
+   a PJSIP endpoint in pjsip.conf to enable the feature.
+
 ------------------------------------------------------------------------------
 --- Functionality changes from Asterisk 14.2.0 to Asterisk 14.3.0 ------------
 ------------------------------------------------------------------------------
diff --git a/UPGRADE.txt b/UPGRADE.txt
index 569cc9222742998769991f804db2b2eaeb26c7db..2275580cabd988c86f54413f790c1c873f1b91d1 100644
--- a/UPGRADE.txt
+++ b/UPGRADE.txt
@@ -23,9 +23,23 @@
 === UPGRADE-14.txt  -- Upgrade info for 13 to 14
 ===========================================================
 
-Build System:
- - The LOW_MEMORY compile option no longer disables inline API.  To disable
-   inline API you must use the DISABLE_INLINE option.
+From 14.3.0 to 14.4.0:
+
+res_rtp_asterisk:
+ - The RTP layer of Asterisk now has support for RFC 5761: "Multiplexing RTP
+   Data and Control Packets on a Single Port." So far, the only channel driver
+   that supports this feature is chan_pjsip. You can set "rtcp_mux = yes" on
+   a PJSIP endpoint in pjsip.conf to enable the feature.
+
+New in 14.0.0
+
+ARI:
+ - The policy for when to send "Dial" events has changed. Previously, "Dial"
+   events were sent on the calling channel's topic. However, starting in Asterisk
+   14, if there is no calling channel on which to send the event, the event is
+   instead sent on the called channel's topic. Note that for the ARI channels
+   resource's dial operation, this means that the "Dial" events will always be
+   sent on the called channel's topic.
 
 Queue:
  - When reloading the members of a queue, the members added dynamically (i.e.
diff --git a/contrib/ast-db-manage/config/versions/15db7b91a97a_add_rtcp_mux.py b/contrib/ast-db-manage/config/versions/15db7b91a97a_add_rtcp_mux.py
new file mode 100644
index 0000000000000000000000000000000000000000..50d3ee3389491782326eee107f29edeca44a9770
--- /dev/null
+++ b/contrib/ast-db-manage/config/versions/15db7b91a97a_add_rtcp_mux.py
@@ -0,0 +1,30 @@
+"""empty message
+
+Revision ID: 15db7b91a97a
+Revises: 465e70e8c337
+Create Date: 2017-03-08 16:56:38.108162
+
+"""
+
+# revision identifiers, used by Alembic.
+revision = '15db7b91a97a'
+down_revision = '465e70e8c337'
+
+from alembic import op
+import sqlalchemy as sa
+
+YESNO_NAME = 'yesno_values'
+YESNO_VALUES = ['yes', 'no']
+
+def upgrade():
+    ############################# Enums ##############################
+
+    # yesno_values have already been created, so use postgres enum object
+    # type to get around "already created" issue - works okay with mysql
+    yesno_values = ENUM(*YESNO_VALUES, name=YESNO_NAME, create_type=False)
+
+    op.add_column('ps_endpoints', sa.Column('rtcp_mux', yesno_values))
+
+
+def downgrade():
+    op.drop_column('ps_endpoints', 'rtcp_mux')
diff --git a/include/asterisk/res_pjsip.h b/include/asterisk/res_pjsip.h
index 09ace0775beab458dd85f2644d5626a90664eb94..fb045130700231675470855b73d34980a221b47e 100644
--- a/include/asterisk/res_pjsip.h
+++ b/include/asterisk/res_pjsip.h
@@ -676,6 +676,8 @@ struct ast_sip_endpoint_media_configuration {
 	unsigned int g726_non_standard;
 	/*! Bind the RTP instance to the media_address */
 	unsigned int bind_rtp_to_media_address;
+	/*! Use RTCP-MUX */
+	unsigned int rtcp_mux;
 };
 
 /*!
diff --git a/include/asterisk/res_pjsip_session.h b/include/asterisk/res_pjsip_session.h
index 26dd451a79b6534013773c99ac17fd75160ebd57..d4d3f705afdfef95ada66855dfd84ac127d4af29 100644
--- a/include/asterisk/res_pjsip_session.h
+++ b/include/asterisk/res_pjsip_session.h
@@ -85,6 +85,8 @@ struct ast_sip_session_media {
 	unsigned int remotely_held:1;
 	/*! \brief Stream is on hold by local side */
 	unsigned int locally_held:1;
+	/*! \brief Does remote support rtcp_mux */
+	unsigned int remote_rtcp_mux:1;
 	/*! \brief Stream type this session media handles */
 	char stream_type[1];
 };
diff --git a/include/asterisk/rtp_engine.h b/include/asterisk/rtp_engine.h
index c0ae331557266b101010e98dec815a3f995934da..6544e70a466c6c5f2e643b855bc4ea212366eed4 100644
--- a/include/asterisk/rtp_engine.h
+++ b/include/asterisk/rtp_engine.h
@@ -237,6 +237,15 @@ enum ast_rtp_instance_stat {
 	AST_RTP_INSTANCE_STAT_RXOCTETCOUNT,
 };
 
+enum ast_rtp_instance_rtcp {
+	/*! RTCP should not be sent/received */
+	AST_RTP_INSTANCE_RTCP_DISABLED = 0,
+	/*! RTCP should be sent/received based on standard port rules */
+	AST_RTP_INSTANCE_RTCP_STANDARD,
+	/*! RTCP should be sent/received on the same port as RTP */
+	AST_RTP_INSTANCE_RTCP_MUX,
+};
+
 /* Codes for RTP-specific data - not defined by our AST_FORMAT codes */
 /*! DTMF (RFC2833) */
 #define AST_RTP_DTMF                    (1 << 0)
@@ -447,6 +456,8 @@ struct ast_rtp_engine_ice {
 	void (*turn_request)(struct ast_rtp_instance *instance, enum ast_rtp_ice_component_type component,
 		enum ast_transport transport, const char *server, unsigned int port,
 		const char *username, const char *password);
+	/*! Callback to alter the number of ICE components on a session */
+	void (*change_components)(struct ast_rtp_instance *instance, int num_components);
 };
 
 /*! \brief DTLS setup types */
diff --git a/res/res_pjsip.c b/res/res_pjsip.c
index e1800e2deaf011db0dd84a90621aa6243e5c6776..f4df4983640bef951f1994c0616e93a31e8dd5be 100644
--- a/res/res_pjsip.c
+++ b/res/res_pjsip.c
@@ -950,6 +950,16 @@
 						to the receiving one.
 					</para></description>
 				</configOption>
+				<configOption name="rtcp_mux" default="no">
+					<synopsis>Enable RFC 5761 RTCP multiplexing on the RTP port</synopsis>
+					<description><para>
+						With this option enabled, Asterisk will attempt to negotiate the use of the "rtcp-mux"
+						attribute on all media streams. This will result in RTP and RTCP being sent and received
+						on the same port. This shifts the demultiplexing logic to the application rather than
+						the transport layer. This option is useful when interoperating with WebRTC endpoints
+						since they mandate this option's use.
+					</para></description>
+				</configOption>
 			</configObject>
 			<configObject name="auth">
 				<synopsis>Authentication type</synopsis>
diff --git a/res/res_pjsip/pjsip_configuration.c b/res/res_pjsip/pjsip_configuration.c
index 1111664dc3e3d38ae395c0bdaea4bbf83b5ff831..c8ff42708bd3a338c74c9a7fd7248d36ee6c738c 100644
--- a/res/res_pjsip/pjsip_configuration.c
+++ b/res/res_pjsip/pjsip_configuration.c
@@ -1937,6 +1937,7 @@ int ast_res_pjsip_initialize_configuration(void)
 	ast_sorcery_object_field_register_custom(sip_sorcery, "endpoint", "contact_user", "", contact_user_handler, contact_user_to_str, NULL, 0, 0);
 	ast_sorcery_object_field_register(sip_sorcery, "endpoint", "preferred_codec_only", "no", OPT_BOOL_T, 1, FLDSET(struct ast_sip_endpoint, preferred_codec_only));
 	ast_sorcery_object_field_register(sip_sorcery, "endpoint", "asymmetric_rtp_codec", "no", OPT_BOOL_T, 1, FLDSET(struct ast_sip_endpoint, asymmetric_rtp_codec));
+	ast_sorcery_object_field_register(sip_sorcery, "endpoint", "rtcp_mux", "no", OPT_BOOL_T, 1, FLDSET(struct ast_sip_endpoint, media.rtcp_mux));
 
 	if (ast_sip_initialize_sorcery_transport()) {
 		ast_log(LOG_ERROR, "Failed to register SIP transport support with sorcery\n");
diff --git a/res/res_pjsip_sdp_rtp.c b/res/res_pjsip_sdp_rtp.c
index e32d2b65f8d91b9e59f2b0094033d5a12334d21e..9f39256e56eb981d36df090edb7c83e8a9536141 100644
--- a/res/res_pjsip_sdp_rtp.c
+++ b/res/res_pjsip_sdp_rtp.c
@@ -169,6 +169,23 @@ static int rtp_check_timeout(const void *data)
 	return 0;
 }
 
+/*!
+ * \brief Enable RTCP on an RTP session.
+ */
+static void enable_rtcp(struct ast_sip_session *session, struct ast_sip_session_media *session_media,
+	const struct pjmedia_sdp_media *remote_media)
+{
+	enum ast_rtp_instance_rtcp rtcp_type;
+
+	if (session->endpoint->media.rtcp_mux && session_media->remote_rtcp_mux) {
+		rtcp_type = AST_RTP_INSTANCE_RTCP_MUX;
+	} else {
+		rtcp_type = AST_RTP_INSTANCE_RTCP_STANDARD;
+	}
+
+	ast_rtp_instance_set_prop(session_media->rtp, AST_RTP_PROPERTY_RTCP, rtcp_type);
+}
+
 /*! \brief Internal function which creates an RTP instance */
 static int create_rtp(struct ast_sip_session *session, struct ast_sip_session_media *session_media)
 {
@@ -186,7 +203,6 @@ static int create_rtp(struct ast_sip_session *session, struct ast_sip_session_me
 		return -1;
 	}
 
-	ast_rtp_instance_set_prop(session_media->rtp, AST_RTP_PROPERTY_RTCP, 1);
 	ast_rtp_instance_set_prop(session_media->rtp, AST_RTP_PROPERTY_NAT, session->endpoint->media.rtp.symmetric);
 
 	if (!session->endpoint->media.rtp.ice_support && (ice = ast_rtp_instance_get_ice(session_media->rtp))) {
@@ -569,6 +585,13 @@ static void process_ice_attributes(struct ast_sip_session *session, struct ast_s
 			continue;
 		}
 
+		if (session->endpoint->media.rtcp_mux && session_media->remote_rtcp_mux && candidate.id > 1) {
+			/* Remote side may have offered RTP and RTCP candidates. However, if we're using RTCP MUX,
+			 * then we should ignore RTCP candidates.
+			 */
+			continue;
+		}
+
 		candidate.foundation = foundation;
 		candidate.transport = transport;
 
@@ -865,6 +888,26 @@ static int setup_media_encryption(struct ast_sip_session *session,
 	return 0;
 }
 
+static void set_ice_components(struct ast_sip_session *session, struct ast_sip_session_media *session_media)
+{
+	struct ast_rtp_engine_ice *ice;
+
+	ast_assert(session_media->rtp != NULL);
+
+	ice = ast_rtp_instance_get_ice(session_media->rtp);
+	if (!session->endpoint->media.rtp.ice_support || !ice) {
+		return;
+	}
+
+	if (session->endpoint->media.rtcp_mux && session_media->remote_rtcp_mux) {
+		/* We both support RTCP mux. Only one ICE component necessary */
+		ice->change_components(session_media->rtp, 1);
+	} else {
+		/* They either don't support RTCP mux or we don't know if they do yet. */
+		ice->change_components(session_media->rtp, 2);
+	}
+}
+
 /*! \brief Function which negotiates an incoming media stream */
 static int negotiate_incoming_sdp_stream(struct ast_sip_session *session, struct ast_sip_session_media *session_media,
 					 const struct pjmedia_sdp_session *sdp, const struct pjmedia_sdp_media *stream)
@@ -909,6 +952,11 @@ static int negotiate_incoming_sdp_stream(struct ast_sip_session *session, struct
 		return -1;
 	}
 
+	session_media->remote_rtcp_mux = (pjmedia_sdp_media_find_attr2(stream, "rtcp-mux", NULL) != NULL);
+	set_ice_components(session, session_media);
+
+	enable_rtcp(session, session_media, stream);
+
 	res = setup_media_encryption(session, session_media, sdp, stream);
 	if (res) {
 		if (!session->endpoint->media.rtp.encryption_optimistic ||
@@ -1087,6 +1135,9 @@ static int create_outgoing_sdp_stream(struct ast_sip_session *session, struct as
 		return -1;
 	}
 
+	set_ice_components(session, session_media);
+	enable_rtcp(session, session_media, NULL);
+
 	if (!(media = pj_pool_zalloc(pool, sizeof(struct pjmedia_sdp_media))) ||
 		!(media->conn = pj_pool_zalloc(pool, sizeof(struct pjmedia_sdp_conn)))) {
 		return -1;
@@ -1250,6 +1301,12 @@ static int create_outgoing_sdp_stream(struct ast_sip_session *session, struct as
 	attr->name = !session_media->locally_held ? STR_SENDRECV : STR_SENDONLY;
 	media->attr[media->attr_count++] = attr;
 
+	/* If we've got rtcp-mux enabled, just unconditionally offer it in all SDPs */
+	if (session->endpoint->media.rtcp_mux) {
+		attr = pjmedia_sdp_attr_create(pool, "rtcp-mux", NULL);
+		pjmedia_sdp_attr_add(&media->attr_count, media->attr, attr);
+	}
+
 	/* Add the media stream to the SDP */
 	sdp->media[sdp->media_count++] = media;
 
@@ -1284,6 +1341,11 @@ static int apply_negotiated_sdp_stream(struct ast_sip_session *session, struct a
 		return -1;
 	}
 
+	session_media->remote_rtcp_mux = (pjmedia_sdp_media_find_attr2(remote_stream, "rtcp-mux", NULL) != NULL);
+	set_ice_components(session, session_media);
+
+	enable_rtcp(session, session_media, remote_stream);
+
 	res = setup_media_encryption(session, session_media, remote, remote_stream);
 	if (!session->endpoint->media.rtp.encryption_optimistic && res) {
 		/* If optimistic encryption is disabled and crypto should have been enabled but was not
@@ -1315,7 +1377,9 @@ static int apply_negotiated_sdp_stream(struct ast_sip_session *session, struct a
 		return -1;
 	}
 	ast_channel_set_fd(session->channel, fdno, ast_rtp_instance_fd(session_media->rtp, 0));
-	ast_channel_set_fd(session->channel, fdno + 1, ast_rtp_instance_fd(session_media->rtp, 1));
+	if (!session->endpoint->media.rtcp_mux || !session_media->remote_rtcp_mux) {
+		ast_channel_set_fd(session->channel, fdno + 1, ast_rtp_instance_fd(session_media->rtp, 1));
+	}
 
 	/* If ICE support is enabled find all the needed attributes */
 	process_ice_attributes(session, session_media, remote, remote_stream);
diff --git a/res/res_rtp_asterisk.c b/res/res_rtp_asterisk.c
index 28ddeca4206ab4e56c8ddb9d44f989e883945caa..a67bc8135b48da2cafd2436c8e289f7ff3cc1f0e 100644
--- a/res/res_rtp_asterisk.c
+++ b/res/res_rtp_asterisk.c
@@ -329,6 +329,7 @@ struct ast_rtp {
 	struct ao2_container *ice_active_remote_candidates;   /*!< The remote ICE candidates */
 	struct ao2_container *ice_proposed_remote_candidates; /*!< Incoming remote ICE candidates for new session */
 	struct ast_sockaddr ice_original_rtp_addr;            /*!< rtp address that ICE started on first session */
+	unsigned int ice_num_components; /*!< The number of ICE components */
 #endif
 
 #ifdef HAVE_OPENSSL_SRTP
@@ -417,6 +418,9 @@ struct ast_rtcp {
 	 * own address every time
 	 */
 	char *local_addr_str;
+	enum ast_rtp_instance_rtcp type;
+	/* Buffer for frames created during RTCP interpretation */
+	unsigned char frame_buf[512 + AST_FRIENDLY_OFFSET];
 };
 
 struct rtp_red {
@@ -658,6 +662,22 @@ static int ice_reset_session(struct ast_rtp_instance *instance)
 		pj_ice_sess_change_role(rtp->ice, role);
 	}
 
+	/* If we only have one component now, and we previously set up TURN for RTCP,
+	 * we need to destroy that TURN socket.
+	 */
+	if (rtp->ice_num_components == 1 && rtp->turn_rtcp) {
+		struct timeval wait = ast_tvadd(ast_tvnow(), ast_samp2tv(TURN_STATE_WAIT_TIME, 1000));
+		struct timespec ts = { .tv_sec = wait.tv_sec, .tv_nsec = wait.tv_usec * 1000, };
+
+		ast_mutex_lock(&rtp->lock);
+		pj_turn_sock_destroy(rtp->turn_rtcp);
+		rtp->turn_state = PJ_TURN_STATE_NULL;
+		while (rtp->turn_state != PJ_TURN_STATE_DESTROYING) {
+			ast_cond_timedwait(&rtp->cond, &rtp->lock, &ts);
+		}
+		ast_mutex_unlock(&rtp->lock);
+	}
+
 	return res;
 }
 
@@ -773,11 +793,12 @@ static void ast_rtp_ice_start(struct ast_rtp_instance *instance)
 		ast_log(LOG_WARNING, "No RTP candidates; skipping ICE checklist (%p)\n", instance);
 	}
 
-	if (!has_rtcp) {
+	/* If we're only dealing with one ICE component, then we don't care about the lack of RTCP candidates */
+	if (!has_rtcp && rtp->ice_num_components > 1) {
 		ast_log(LOG_WARNING, "No RTCP candidates; skipping ICE checklist (%p)\n", instance);
 	}
 
-	if (has_rtp && has_rtcp) {
+	if (has_rtp && (has_rtcp || rtp->ice_num_components == 1)) {
 		pj_status_t res = pj_ice_sess_create_check_list(rtp->ice, &ufrag, &passwd, cand_cnt, &candidates[0]);
 		char reason[80];
 
@@ -1269,6 +1290,21 @@ static char *generate_random_string(char *buf, size_t size)
         return buf;
 }
 
+static void ast_rtp_ice_change_components(struct ast_rtp_instance *instance, int num_components)
+{
+	struct ast_rtp *rtp = ast_rtp_instance_get_data(instance);
+
+	/* Don't do anything if ICE is unsupported or if we're not changing the
+	 * number of components
+	 */
+	if (!icesupport || !rtp->ice || rtp->ice_num_components == num_components) {
+		return;
+	}
+
+	rtp->ice_num_components = num_components;
+	ice_reset_session(instance);
+}
+
 /* ICE RTP Engine interface declaration */
 static struct ast_rtp_engine_ice ast_rtp_ice = {
 	.set_authentication = ast_rtp_ice_set_authentication,
@@ -1281,6 +1317,7 @@ static struct ast_rtp_engine_ice ast_rtp_ice = {
 	.ice_lite = ast_rtp_ice_lite,
 	.set_role = ast_rtp_ice_set_role,
 	.turn_request = ast_rtp_ice_turn_request,
+	.change_components = ast_rtp_ice_change_components,
 };
 #endif
 
@@ -1540,6 +1577,7 @@ static int ast_rtp_dtls_active(struct ast_rtp_instance *instance)
 static void ast_rtp_dtls_stop(struct ast_rtp_instance *instance)
 {
 	struct ast_rtp *rtp = ast_rtp_instance_get_data(instance);
+	int rtcp_dtls_unique = (rtp->dtls.ssl != rtp->rtcp->dtls.ssl);
 
 	dtls_srtp_stop_timeout_timer(instance, rtp, 0);
 
@@ -1557,7 +1595,7 @@ static void ast_rtp_dtls_stop(struct ast_rtp_instance *instance)
 	if (rtp->rtcp) {
 		dtls_srtp_stop_timeout_timer(instance, rtp, 1);
 
-		if (rtp->rtcp->dtls.ssl) {
+		if (rtp->rtcp->dtls.ssl && rtcp_dtls_unique) {
 			SSL_free(rtp->rtcp->dtls.ssl);
 			rtp->rtcp->dtls.ssl = NULL;
 			ast_mutex_destroy(&rtp->rtcp->dtls.lock);
@@ -1785,7 +1823,7 @@ static void ast_rtp_on_ice_complete(pj_ice_sess *ice, pj_status_t status)
 #ifdef HAVE_OPENSSL_SRTP
 	dtls_perform_handshake(instance, &rtp->dtls, 0);
 
-	if (rtp->rtcp) {
+	if (rtp->rtcp && rtp->rtcp->type == AST_RTP_INSTANCE_RTCP_STANDARD) {
 		dtls_perform_handshake(instance, &rtp->rtcp->dtls, 1);
 	}
 #endif
@@ -2025,7 +2063,7 @@ static int dtls_srtp_renegotiate(const void *data)
 	SSL_do_handshake(rtp->dtls.ssl);
 	dtls_srtp_check_pending(instance, rtp, 0);
 
-	if (rtp->rtcp && rtp->rtcp->dtls.ssl) {
+	if (rtp->rtcp && rtp->rtcp->dtls.ssl && rtp->rtcp->dtls.ssl != rtp->dtls.ssl) {
 		SSL_renegotiate(rtp->rtcp->dtls.ssl);
 		SSL_do_handshake(rtp->rtcp->dtls.ssl);
 		dtls_srtp_check_pending(instance, rtp, 1);
@@ -2616,7 +2654,7 @@ static int ice_create(struct ast_rtp_instance *instance, struct ast_sockaddr *ad
 	passwd = pj_str(rtp->local_passwd);
 
 	/* Create an ICE session for ICE negotiation */
-	if (pj_ice_sess_create(&stun_config, NULL, PJ_ICE_SESS_ROLE_UNKNOWN, 2,
+	if (pj_ice_sess_create(&stun_config, NULL, PJ_ICE_SESS_ROLE_UNKNOWN, rtp->ice_num_components,
 			&ast_rtp_ice_sess_cb, &ufrag, &passwd, NULL, &rtp->ice) == PJ_SUCCESS) {
 		/* Make this available for the callbacks */
 		rtp->ice->user_data = instance;
@@ -2625,9 +2663,10 @@ static int ice_create(struct ast_rtp_instance *instance, struct ast_sockaddr *ad
 		rtp_add_candidates_to_ice(instance, rtp, addr, port, AST_RTP_ICE_COMPONENT_RTP,
 			TRANSPORT_SOCKET_RTP);
 
-		/* Only add the RTCP candidates to ICE when replacing the session. New sessions
+		/* Only add the RTCP candidates to ICE when replacing the session and if
+		 * the ICE session contains more than just an RTP component. New sessions
 		 * handle this in a separate part of the setup phase */
-		if (replace && rtp->rtcp) {
+		if (replace && rtp->rtcp && rtp->ice_num_components > 1) {
 			rtp_add_candidates_to_ice(instance, rtp, &rtp->rtcp->us,
 				ast_sockaddr_port(&rtp->rtcp->us), AST_RTP_ICE_COMPONENT_RTCP,
 				TRANSPORT_SOCKET_RTCP);
@@ -2712,6 +2751,7 @@ static int ast_rtp_new(struct ast_rtp_instance *instance,
 #ifdef HAVE_PJPROJECT
 	/* Create an ICE session for ICE negotiation */
 	if (icesupport) {
+		rtp->ice_num_components = 2;
 		ast_debug(3, "Creating ICE session %s (%d) for RTP instance '%p'\n", ast_sockaddr_stringify(addr), x, instance);
 		if (ice_create(instance, addr, x, 0)) {
 			ast_log(LOG_NOTICE, "Failed to start ICE session\n");
@@ -2721,7 +2761,6 @@ static int ast_rtp_new(struct ast_rtp_instance *instance,
 		}
 	}
 #endif
-
 	/* Record any information we may need */
 	rtp->sched = sched;
 
@@ -4150,63 +4189,21 @@ static void update_lost_stats(struct ast_rtp *rtp, unsigned int lost_packets)
 	rtp->rtcp->reported_normdev_lost = reported_normdev_lost_current;
 }
 
-static struct ast_frame *ast_rtcp_read(struct ast_rtp_instance *instance)
+static struct ast_frame *ast_rtcp_interpret(struct ast_rtp_instance *instance, const unsigned char *rtcpdata, size_t size, struct ast_sockaddr *addr)
 {
 	struct ast_rtp *rtp = ast_rtp_instance_get_data(instance);
-	struct ast_sockaddr addr;
-	unsigned char rtcpdata[8192 + AST_FRIENDLY_OFFSET];
-	unsigned int *rtcpheader = (unsigned int *)(rtcpdata + AST_FRIENDLY_OFFSET);
-	int res, packetwords, position = 0;
+	unsigned int *rtcpheader = (unsigned int *)(rtcpdata);
+	int packetwords, position = 0;
 	int report_counter = 0;
 	struct ast_rtp_rtcp_report_block *report_block;
 	struct ast_frame *f = &ast_null_frame;
 
-	/* Read in RTCP data from the socket */
-	if ((res = rtcp_recvfrom(instance, rtcpdata + AST_FRIENDLY_OFFSET,
-				sizeof(rtcpdata) - AST_FRIENDLY_OFFSET,
-				0, &addr)) < 0) {
-		ast_assert(errno != EBADF);
-		if (errno != EAGAIN) {
-			ast_log(LOG_WARNING, "RTCP Read error: %s.  Hanging up.\n",
-				(errno) ? strerror(errno) : "Unspecified");
-			return NULL;
-		}
-		return &ast_null_frame;
-	}
-
-	/* If this was handled by the ICE session don't do anything further */
-	if (!res) {
-		return &ast_null_frame;
-	}
-
-	if (!*(rtcpdata + AST_FRIENDLY_OFFSET)) {
-		struct sockaddr_in addr_tmp;
-		struct ast_sockaddr addr_v4;
-
-		if (ast_sockaddr_is_ipv4(&addr)) {
-			ast_sockaddr_to_sin(&addr, &addr_tmp);
-		} else if (ast_sockaddr_ipv4_mapped(&addr, &addr_v4)) {
-			ast_debug(1, "Using IPv6 mapped address %s for STUN\n",
-				  ast_sockaddr_stringify(&addr));
-			ast_sockaddr_to_sin(&addr_v4, &addr_tmp);
-		} else {
-			ast_debug(1, "Cannot do STUN for non IPv4 address %s\n",
-				  ast_sockaddr_stringify(&addr));
-			return &ast_null_frame;
-		}
-		if ((ast_stun_handle_packet(rtp->rtcp->s, &addr_tmp, rtcpdata + AST_FRIENDLY_OFFSET, res, NULL, NULL) == AST_STUN_ACCEPT)) {
-			ast_sockaddr_from_sin(&addr, &addr_tmp);
-			ast_sockaddr_copy(&rtp->rtcp->them, &addr);
-		}
-		return &ast_null_frame;
-	}
-
-	packetwords = res / 4;
+	packetwords = size / 4;
 
 	if (ast_rtp_instance_get_prop(instance, AST_RTP_PROPERTY_NAT)) {
 		/* Send to whoever sent to us */
-		if (ast_sockaddr_cmp(&rtp->rtcp->them, &addr)) {
-			ast_sockaddr_copy(&rtp->rtcp->them, &addr);
+		if (ast_sockaddr_cmp(&rtp->rtcp->them, addr)) {
+			ast_sockaddr_copy(&rtp->rtcp->them, addr);
 			if (rtpdebug) {
 				ast_debug(0, "RTCP NAT: Got RTCP from other end. Now sending to address %s\n",
 					  ast_sockaddr_stringify(&rtp->rtcp->them));
@@ -4214,7 +4211,7 @@ static struct ast_frame *ast_rtcp_read(struct ast_rtp_instance *instance)
 		}
 	}
 
-	ast_debug(1, "Got RTCP report of %d bytes\n", res);
+	ast_debug(1, "Got RTCP report of %zu bytes\n", size);
 
 	while (position < packetwords) {
 		int i, pt, rc;
@@ -4242,9 +4239,9 @@ static struct ast_frame *ast_rtcp_read(struct ast_rtp_instance *instance)
 			return &ast_null_frame;
 		}
 
-		if (rtcp_debug_test_addr(&addr)) {
+		if (rtcp_debug_test_addr(addr)) {
 			ast_verbose("\n\nGot RTCP from %s\n",
-				    ast_sockaddr_stringify(&addr));
+				    ast_sockaddr_stringify(addr));
 			ast_verbose("PT: %d(%s)\n", pt, (pt == RTCP_PT_SR) ? "Sender Report" :
 							(pt == RTCP_PT_RR) ? "Receiver Report" :
 							(pt == RTCP_PT_FUR) ? "H.261 FUR" : "Unknown");
@@ -4267,7 +4264,7 @@ static struct ast_frame *ast_rtcp_read(struct ast_rtp_instance *instance)
 					(unsigned int)ntohl(rtcpheader[i + 1]),
 					&rtcp_report->sender_information.ntp_timestamp);
 			rtcp_report->sender_information.rtp_timestamp = ntohl(rtcpheader[i + 2]);
-			if (rtcp_debug_test_addr(&addr)) {
+			if (rtcp_debug_test_addr(addr)) {
 				ast_verbose("NTP timestamp: %u.%06u\n",
 						(unsigned int)rtcp_report->sender_information.ntp_timestamp.tv_sec,
 						(unsigned int)rtcp_report->sender_information.ntp_timestamp.tv_usec);
@@ -4299,7 +4296,7 @@ static struct ast_frame *ast_rtcp_read(struct ast_rtp_instance *instance)
 				report_block->dlsr = ntohl(rtcpheader[i + 5]);
 				if (report_block->lsr
 					&& update_rtt_stats(rtp, report_block->lsr, report_block->dlsr)
-					&& rtcp_debug_test_addr(&addr)) {
+					&& rtcp_debug_test_addr(addr)) {
 					struct timeval now;
 					unsigned int lsr_now, lsw, msw;
 					gettimeofday(&now, NULL);
@@ -4316,7 +4313,7 @@ static struct ast_frame *ast_rtcp_read(struct ast_rtp_instance *instance)
 				update_lost_stats(rtp, report_block->lost_count.packets);
 				rtp->rtcp->reported_jitter_count++;
 
-				if (rtcp_debug_test_addr(&addr)) {
+				if (rtcp_debug_test_addr(addr)) {
 					ast_verbose("  Fraction lost: %d\n", report_block->lost_count.fraction);
 					ast_verbose("  Packets lost so far: %u\n", report_block->lost_count.packets);
 					ast_verbose("  Highest sequence number: %u\n", report_block->highest_seq_no & 0x0000ffff);
@@ -4344,7 +4341,7 @@ static struct ast_frame *ast_rtcp_read(struct ast_rtp_instance *instance)
 			/* Return an AST_FRAME_RTCP frame with the ast_rtp_rtcp_report
 			 * object as a its data */
 			rtp->f.frametype = AST_FRAME_RTCP;
-			rtp->f.data.ptr = rtp->rawdata + AST_FRIENDLY_OFFSET;
+			rtp->f.data.ptr = rtp->rtcp->frame_buf + AST_FRIENDLY_OFFSET;
 			memcpy(rtp->f.data.ptr, rtcp_report, sizeof(struct ast_rtp_rtcp_report));
 			rtp->f.datalen = sizeof(struct ast_rtp_rtcp_report);
 			if (rc > 0) {
@@ -4367,7 +4364,7 @@ static struct ast_frame *ast_rtcp_read(struct ast_rtp_instance *instance)
 		case RTCP_PT_FUR:
 		/* Handle RTCP FIR as FUR */
 		case RTCP_PT_PSFB:
-			if (rtcp_debug_test_addr(&addr)) {
+			if (rtcp_debug_test_addr(addr)) {
 				ast_verbose("Received an RTCP Fast Update Request\n");
 			}
 			rtp->f.frametype = AST_FRAME_CONTROL;
@@ -4379,13 +4376,13 @@ static struct ast_frame *ast_rtcp_read(struct ast_rtp_instance *instance)
 			f = &rtp->f;
 			break;
 		case RTCP_PT_SDES:
-			if (rtcp_debug_test_addr(&addr)) {
+			if (rtcp_debug_test_addr(addr)) {
 				ast_verbose("Received an SDES from %s\n",
 					    ast_sockaddr_stringify(&rtp->rtcp->them));
 			}
 			break;
 		case RTCP_PT_BYE:
-			if (rtcp_debug_test_addr(&addr)) {
+			if (rtcp_debug_test_addr(addr)) {
 				ast_verbose("Received a BYE from %s\n",
 					    ast_sockaddr_stringify(&rtp->rtcp->them));
 			}
@@ -4400,6 +4397,58 @@ static struct ast_frame *ast_rtcp_read(struct ast_rtp_instance *instance)
 	rtp->rtcp->rtcp_info = 1;
 
 	return f;
+
+}
+
+static struct ast_frame *ast_rtcp_read(struct ast_rtp_instance *instance)
+{
+	struct ast_rtp *rtp = ast_rtp_instance_get_data(instance);
+	struct ast_sockaddr addr;
+	unsigned char rtcpdata[8192 + AST_FRIENDLY_OFFSET];
+	unsigned char *read_area = rtcpdata + AST_FRIENDLY_OFFSET;
+	size_t read_area_size = sizeof(rtcpdata) - AST_FRIENDLY_OFFSET;
+	int res;
+
+	/* Read in RTCP data from the socket */
+	if ((res = rtcp_recvfrom(instance, read_area, read_area_size,
+				0, &addr)) < 0) {
+		ast_assert(errno != EBADF);
+		if (errno != EAGAIN) {
+			ast_log(LOG_WARNING, "RTCP Read error: %s.  Hanging up.\n",
+				(errno) ? strerror(errno) : "Unspecified");
+			return NULL;
+		}
+		return &ast_null_frame;
+	}
+
+	/* If this was handled by the ICE session don't do anything further */
+	if (!res) {
+		return &ast_null_frame;
+	}
+
+	if (!*(read_area)) {
+		struct sockaddr_in addr_tmp;
+		struct ast_sockaddr addr_v4;
+
+		if (ast_sockaddr_is_ipv4(&addr)) {
+			ast_sockaddr_to_sin(&addr, &addr_tmp);
+		} else if (ast_sockaddr_ipv4_mapped(&addr, &addr_v4)) {
+			ast_debug(1, "Using IPv6 mapped address %s for STUN\n",
+				  ast_sockaddr_stringify(&addr));
+			ast_sockaddr_to_sin(&addr_v4, &addr_tmp);
+		} else {
+			ast_debug(1, "Cannot do STUN for non IPv4 address %s\n",
+				  ast_sockaddr_stringify(&addr));
+			return &ast_null_frame;
+		}
+		if ((ast_stun_handle_packet(rtp->rtcp->s, &addr_tmp, read_area, res, NULL, NULL) == AST_STUN_ACCEPT)) {
+			ast_sockaddr_from_sin(&addr, &addr_tmp);
+			ast_sockaddr_copy(&rtp->rtcp->them, &addr);
+		}
+		return &ast_null_frame;
+	}
+
+	return ast_rtcp_interpret(instance, read_area, read_area_size, &addr);
 }
 
 static int bridge_p2p_rtp_write(struct ast_rtp_instance *instance, unsigned int *rtpheader, int len, int hdrlen)
@@ -4507,19 +4556,54 @@ static int bridge_p2p_rtp_write(struct ast_rtp_instance *instance, unsigned int
 	return 0;
 }
 
+static int rtcp_mux(struct ast_rtp *rtp, const unsigned char *packet)
+{
+	uint8_t version;
+	uint8_t pt;
+	uint8_t m;
+
+	if (!rtp->rtcp || rtp->rtcp->type != AST_RTP_INSTANCE_RTCP_MUX) {
+		return 0;
+	}
+
+	version = (packet[0] & 0XC0) >> 6;
+	if (version == 0) {
+		/* version 0 indicates this is a STUN packet and shouldn't
+		 * be interpreted as a possible RTCP packet
+		 */
+		return 0;
+	}
+
+	/* The second octet of a packet will be one of the following:
+	 * For RTP: The marker bit (1 bit) and the RTP payload type (7 bits)
+	 * For RTCP: The payload type (8)
+	 *
+	 * RTP has a forbidden range of payload types (64-95) since these
+	 * will conflict with RTCP payload numbers if the marker bit is set.
+	 */
+	m = packet[1] & 0x80;
+	pt = packet[1] & 0x7F;
+	if (m && pt >= 64 && pt <= 95) {
+		return 1;
+	}
+	return 0;
+}
+
 static struct ast_frame *ast_rtp_read(struct ast_rtp_instance *instance, int rtcp)
 {
 	struct ast_rtp *rtp = ast_rtp_instance_get_data(instance);
 	struct ast_sockaddr addr;
 	int res, hdrlen = 12, version, payloadtype, padding, mark, ext, cc, prev_seqno;
-	unsigned int *rtpheader = (unsigned int*)(rtp->rawdata + AST_FRIENDLY_OFFSET), seqno, ssrc, timestamp;
+	unsigned char *read_area = rtp->rawdata + AST_FRIENDLY_OFFSET;
+	size_t read_area_size = sizeof(rtp->rawdata) - AST_FRIENDLY_OFFSET;
+	unsigned int *rtpheader = (unsigned int*)(read_area), seqno, ssrc, timestamp;
 	RAII_VAR(struct ast_rtp_payload_type *, payload, NULL, ao2_cleanup);
 	struct ast_sockaddr remote_address = { {0,} };
 	struct frame_list frames;
 
 	/* If this is actually RTCP let's hop on over and handle it */
 	if (rtcp) {
-		if (rtp->rtcp) {
+		if (rtp->rtcp && rtp->rtcp->type == AST_RTP_INSTANCE_RTCP_STANDARD) {
 			return ast_rtcp_read(instance);
 		}
 		return &ast_null_frame;
@@ -4531,8 +4615,7 @@ static struct ast_frame *ast_rtp_read(struct ast_rtp_instance *instance, int rtc
 	}
 
 	/* Actually read in the data from the socket */
-	if ((res = rtp_recvfrom(instance, rtp->rawdata + AST_FRIENDLY_OFFSET,
-				sizeof(rtp->rawdata) - AST_FRIENDLY_OFFSET, 0,
+	if ((res = rtp_recvfrom(instance, read_area, read_area_size, 0,
 				&addr)) < 0) {
 		ast_assert(errno != EBADF);
 		if (errno != EAGAIN) {
@@ -4548,12 +4631,17 @@ static struct ast_frame *ast_rtp_read(struct ast_rtp_instance *instance, int rtc
 		return &ast_null_frame;
 	}
 
+	/* This could be a multiplexed RTCP packet. If so, be sure to interpret it correctly */
+	if (rtcp_mux(rtp, read_area)) {
+		return ast_rtcp_interpret(instance, read_area, read_area_size, &addr);
+	}
+
 	/* Make sure the data that was read in is actually enough to make up an RTP packet */
 	if (res < hdrlen) {
 		/* If this is a keepalive containing only nulls, don't bother with a warning */
 		int i;
 		for (i = 0; i < res; ++i) {
-			if (rtp->rawdata[AST_FRIENDLY_OFFSET + i] != '\0') {
+			if (read_area[i] != '\0') {
 				ast_log(LOG_WARNING, "RTP Read too short\n");
 				return &ast_null_frame;
 			}
@@ -4580,7 +4668,7 @@ static struct ast_frame *ast_rtp_read(struct ast_rtp_instance *instance, int rtc
 				  ast_sockaddr_stringify(&addr));
 			return &ast_null_frame;
 		}
-		if ((ast_stun_handle_packet(rtp->s, &addr_tmp, rtp->rawdata + AST_FRIENDLY_OFFSET, res, NULL, NULL) == AST_STUN_ACCEPT) &&
+		if ((ast_stun_handle_packet(rtp->s, &addr_tmp, read_area, res, NULL, NULL) == AST_STUN_ACCEPT) &&
 		    ast_sockaddr_isnull(&remote_address)) {
 			ast_sockaddr_from_sin(&addr, &addr_tmp);
 			ast_rtp_instance_set_remote_address(instance, &addr);
@@ -4629,7 +4717,7 @@ static struct ast_frame *ast_rtp_read(struct ast_rtp_instance *instance, int rtc
 			/* do not update the originally given address, but only the remote */
 			ast_rtp_instance_set_incoming_source_address(instance, &addr);
 			ast_sockaddr_copy(&remote_address, &addr);
-			if (rtp->rtcp) {
+			if (rtp->rtcp && rtp->rtcp->type == AST_RTP_INSTANCE_RTCP_STANDARD) {
 				ast_sockaddr_copy(&rtp->rtcp->them, &addr);
 				ast_sockaddr_set_port(&rtp->rtcp->them, ast_sockaddr_port(&addr) + 1);
 			}
@@ -4696,7 +4784,7 @@ static struct ast_frame *ast_rtp_read(struct ast_rtp_instance *instance, int rtc
 
 	/* Remove any padding bytes that may be present */
 	if (padding) {
-		res -= rtp->rawdata[AST_FRIENDLY_OFFSET + res - 1];
+		res -= read_area[res - 1];
 	}
 
 	/* Skip over any CSRC fields */
@@ -4770,11 +4858,11 @@ static struct ast_frame *ast_rtp_read(struct ast_rtp_instance *instance, int rtc
 			 * by passing the pointer to the frame list to it so that the method
 			 * can append frames to the list as needed.
 			 */
-			process_dtmf_rfc2833(instance, rtp->rawdata + AST_FRIENDLY_OFFSET + hdrlen, res - hdrlen, seqno, timestamp, &addr, payloadtype, mark, &frames);
+			process_dtmf_rfc2833(instance, read_area + hdrlen, res - hdrlen, seqno, timestamp, &addr, payloadtype, mark, &frames);
 		} else if (payload->rtp_code == AST_RTP_CISCO_DTMF) {
-			f = process_dtmf_cisco(instance, rtp->rawdata + AST_FRIENDLY_OFFSET + hdrlen, res - hdrlen, seqno, timestamp, &addr, payloadtype, mark);
+			f = process_dtmf_cisco(instance, read_area + hdrlen, res - hdrlen, seqno, timestamp, &addr, payloadtype, mark);
 		} else if (payload->rtp_code == AST_RTP_CN) {
-			f = process_cn_rfc3389(instance, rtp->rawdata + AST_FRIENDLY_OFFSET + hdrlen, res - hdrlen, seqno, timestamp, &addr, payloadtype, mark);
+			f = process_cn_rfc3389(instance, read_area + hdrlen, res - hdrlen, seqno, timestamp, &addr, payloadtype, mark);
 		} else {
 			ast_log(LOG_NOTICE, "Unknown RTP codec %d received from '%s'\n",
 				payloadtype,
@@ -4830,7 +4918,7 @@ static struct ast_frame *ast_rtp_read(struct ast_rtp_instance *instance, int rtc
 	rtp->f.src = "RTP";
 	rtp->f.mallocd = 0;
 	rtp->f.datalen = res - hdrlen;
-	rtp->f.data.ptr = rtp->rawdata + hdrlen + AST_FRIENDLY_OFFSET;
+	rtp->f.data.ptr = read_area + hdrlen;
 	rtp->f.offset = hdrlen + AST_FRIENDLY_OFFSET;
 	rtp->f.seqno = seqno;
 
@@ -4941,19 +5029,29 @@ static void ast_rtp_prop_set(struct ast_rtp_instance *instance, enum ast_rtp_pro
 		if (value) {
 			struct ast_sockaddr local_addr;
 
-			if (rtp->rtcp) {
+			if (rtp->rtcp && rtp->rtcp->type == value) {
 				ast_debug(1, "Ignoring duplicate RTCP property on RTP instance '%p'\n", instance);
 				return;
 			}
-			/* Setup RTCP to be activated on the next RTP write */
-			if (!(rtp->rtcp = ast_calloc(1, sizeof(*rtp->rtcp)))) {
-				return;
+
+			if (!rtp->rtcp) {
+				rtp->rtcp = ast_calloc(1, sizeof(*rtp->rtcp));
+				if (!rtp->rtcp) {
+					return;
+				}
+				rtp->rtcp->s = -1;
+				rtp->rtcp->dtls.timeout_timer = -1;
+				rtp->rtcp->schedid = -1;
 			}
 
+			rtp->rtcp->type = value;
+
 			/* Grab the IP address and port we are going to use */
 			ast_rtp_instance_get_local_address(instance, &rtp->rtcp->us);
-			ast_sockaddr_set_port(&rtp->rtcp->us,
-					      ast_sockaddr_port(&rtp->rtcp->us) + 1);
+			if (value == AST_RTP_INSTANCE_RTCP_STANDARD) {
+				ast_sockaddr_set_port(&rtp->rtcp->us,
+					ast_sockaddr_port(&rtp->rtcp->us) + 1);
+			}
 
 			ast_sockaddr_copy(&local_addr, &rtp->rtcp->us);
 			if (!ast_find_ourip(&local_addr, &rtp->rtcp->us, 0)) {
@@ -4963,6 +5061,7 @@ static void ast_rtp_prop_set(struct ast_rtp_instance *instance, enum ast_rtp_pro
 				ast_sockaddr_copy(&local_addr, &rtp->rtcp->us);
 			}
 
+			ast_free(rtp->rtcp->local_addr_str);
 			rtp->rtcp->local_addr_str = ast_strdup(ast_sockaddr_stringify(&local_addr));
 			if (!rtp->rtcp->local_addr_str) {
 				ast_free(rtp->rtcp);
@@ -4970,43 +5069,67 @@ static void ast_rtp_prop_set(struct ast_rtp_instance *instance, enum ast_rtp_pro
 				return;
 			}
 
-			if ((rtp->rtcp->s =
-			     create_new_socket("RTCP",
-					       ast_sockaddr_is_ipv4(&rtp->rtcp->us) ?
-					       AF_INET :
-					       ast_sockaddr_is_ipv6(&rtp->rtcp->us) ?
-					       AF_INET6 : -1)) < 0) {
-				ast_debug(1, "Failed to create a new socket for RTCP on instance '%p'\n", instance);
-				ast_free(rtp->rtcp->local_addr_str);
-				ast_free(rtp->rtcp);
-				rtp->rtcp = NULL;
-				return;
-			}
-
-			/* Try to actually bind to the IP address and port we are going to use for RTCP, if this fails we have to bail out */
-			if (ast_bind(rtp->rtcp->s, &rtp->rtcp->us)) {
-				ast_debug(1, "Failed to setup RTCP on RTP instance '%p'\n", instance);
-				close(rtp->rtcp->s);
-				ast_free(rtp->rtcp->local_addr_str);
-				ast_free(rtp->rtcp);
-				rtp->rtcp = NULL;
-				return;
-			}
-
-			ast_debug(1, "Setup RTCP on RTP instance '%p'\n", instance);
-			rtp->rtcp->schedid = -1;
+			if (value == AST_RTP_INSTANCE_RTCP_STANDARD) {
+				/* We're either setting up RTCP from scratch or
+				 * switching from MUX. Either way, we won't have
+				 * a socket set up, and we need to set it up
+				 */
+				if ((rtp->rtcp->s =
+				     create_new_socket("RTCP",
+						       ast_sockaddr_is_ipv4(&rtp->rtcp->us) ?
+						       AF_INET :
+						       ast_sockaddr_is_ipv6(&rtp->rtcp->us) ?
+						       AF_INET6 : -1)) < 0) {
+					ast_debug(1, "Failed to create a new socket for RTCP on instance '%p'\n", instance);
+					ast_free(rtp->rtcp->local_addr_str);
+					ast_free(rtp->rtcp);
+					rtp->rtcp = NULL;
+					return;
+				}
 
+				/* Try to actually bind to the IP address and port we are going to use for RTCP, if this fails we have to bail out */
+				if (ast_bind(rtp->rtcp->s, &rtp->rtcp->us)) {
+					ast_debug(1, "Failed to setup RTCP on RTP instance '%p'\n", instance);
+					close(rtp->rtcp->s);
+					ast_free(rtp->rtcp->local_addr_str);
+					ast_free(rtp->rtcp);
+					rtp->rtcp = NULL;
+					return;
+				}
 #ifdef HAVE_PJPROJECT
-			if (rtp->ice) {
-				rtp_add_candidates_to_ice(instance, rtp, &rtp->rtcp->us, ast_sockaddr_port(&rtp->rtcp->us), AST_RTP_ICE_COMPONENT_RTCP, TRANSPORT_SOCKET_RTCP);
-			}
+				if (rtp->ice) {
+					rtp_add_candidates_to_ice(instance, rtp, &rtp->rtcp->us, ast_sockaddr_port(&rtp->rtcp->us), AST_RTP_ICE_COMPONENT_RTCP, TRANSPORT_SOCKET_RTCP);
+				}
 #endif
-
 #ifdef HAVE_OPENSSL_SRTP
-			rtp->rtcp->dtls.timeout_timer = -1;
-			dtls_setup_rtcp(instance);
+				dtls_setup_rtcp(instance);
 #endif
+			} else {
+				struct ast_sockaddr addr;
+				/* RTCPMUX uses the same socket as RTP. If we were previously using standard RTCP
+				 * then close the socket we previously created.
+				 *
+				 * It may seem as though there is a possible race condition here where we might try
+				 * to close the RTCP socket while it is being used to send data. However, this is not
+				 * a problem in practice since setting and adjusting of RTCP properties happens prior
+				 * to activating RTP. It is not until RTP is activated that timers start for RTCP
+				 * transmission
+				 */
+				if (rtp->rtcp->s > -1) {
+					close(rtp->rtcp->s);
+				}
+				rtp->rtcp->s = rtp->s;
+				ast_rtp_instance_get_remote_address(instance, &addr);
+				ast_sockaddr_copy(&rtp->rtcp->them, &addr);
+#ifdef HAVE_OPENSSL_SRTP
+				if (rtp->rtcp->dtls.ssl) {
+					SSL_free(rtp->rtcp->dtls.ssl);
+				}
+				rtp->rtcp->dtls.ssl = rtp->dtls.ssl;
+#endif
+			}
 
+			ast_debug(1, "Setup RTCP on RTP instance '%p'\n", instance);
 			return;
 		} else {
 			if (rtp->rtcp) {
@@ -5021,9 +5144,11 @@ static void ast_rtp_prop_set(struct ast_rtp_instance *instance, enum ast_rtp_pro
 					}
 					rtp->rtcp->schedid = -1;
 				}
-				close(rtp->rtcp->s);
+				if (rtp->rtcp->s > -1 && rtp->rtcp->s != rtp->s) {
+					close(rtp->rtcp->s);
+				}
 #ifdef HAVE_OPENSSL_SRTP
-				if (rtp->rtcp->dtls.ssl) {
+				if (rtp->rtcp->dtls.ssl && rtp->rtcp->dtls.ssl != rtp->dtls.ssl) {
 					SSL_free(rtp->rtcp->dtls.ssl);
 				}
 #endif
@@ -5065,10 +5190,12 @@ static void ast_rtp_remote_address_set(struct ast_rtp_instance *instance, struct
 		ast_debug(1, "Setting RTCP address on RTP instance '%p'\n", instance);
 		ast_sockaddr_copy(&rtp->rtcp->them, addr);
 		if (!ast_sockaddr_isnull(addr)) {
-			ast_sockaddr_set_port(&rtp->rtcp->them, ast_sockaddr_port(addr) + 1);
+			if (rtp->rtcp->type == AST_RTP_INSTANCE_RTCP_STANDARD) {
+				ast_sockaddr_set_port(&rtp->rtcp->them, ast_sockaddr_port(addr) + 1);
 
-			/* Update the local RTCP address with what is being used */
-			ast_sockaddr_set_port(&local, ast_sockaddr_port(&local) + 1);
+				/* Update the local RTCP address with what is being used */
+				ast_sockaddr_set_port(&local, ast_sockaddr_port(&local) + 1);
+			}
 			ast_sockaddr_copy(&rtp->rtcp->us, &local);
 
 			ast_free(rtp->rtcp->local_addr_str);
@@ -5356,7 +5483,7 @@ static int ast_rtp_activate(struct ast_rtp_instance *instance)
 
 	dtls_perform_handshake(instance, &rtp->dtls, 0);
 
-	if (rtp->rtcp) {
+	if (rtp->rtcp && rtp->rtcp->type == AST_RTP_INSTANCE_RTCP_STANDARD) {
 		dtls_perform_handshake(instance, &rtp->rtcp->dtls, 1);
 	}