diff --git a/channels/chan_pjsip.c b/channels/chan_pjsip.c
index 2c111feebcddca82ee309a8bd25f662c3af32d84..5cb52a5b24cccd0ed6202a7137943b3371a98f8f 100644
--- a/channels/chan_pjsip.c
+++ b/channels/chan_pjsip.c
@@ -965,6 +965,8 @@ static int chan_pjsip_write_stream(struct ast_channel *ast, int stream_num, stru
 		break;
 	case AST_FRAME_CNG:
 		break;
+	case AST_FRAME_RTCP:
+		break;
 	default:
 		ast_log(LOG_WARNING, "Can't send %u type frames with PJSIP\n", frame->frametype);
 		break;
diff --git a/codecs/codec_speex.c b/codecs/codec_speex.c
index 0a93596206ccce44cfe155da796a1b1e6589741a..591fce9deb7fd9ddd976ecc7dd2e54ae9ac86251 100644
--- a/codecs/codec_speex.c
+++ b/codecs/codec_speex.c
@@ -372,6 +372,11 @@ static void lintospeex_feedback(struct ast_trans_pvt *pvt, struct ast_frame *fee
 	if(!exp_rtcp_fb)
 		return;
 
+	/* We only accept feedback information in the form of SR and RR reports */
+	if (feedback->subclass.integer != AST_RTP_RTCP_SR && feedback->subclass.integer != AST_RTP_RTCP_RR) {
+		return;
+	}
+
 	rtcp_report = (struct ast_rtp_rtcp_report *)feedback->data.ptr;
 	if (rtcp_report->reception_report_count == 0)
 		return;
diff --git a/include/asterisk/frame.h b/include/asterisk/frame.h
index eb6a6479a5d36b674e84e02c41474245b368031f..c3c0f88176cbafd31fa9a5ae54d0d4cb72bb3b55 100644
--- a/include/asterisk/frame.h
+++ b/include/asterisk/frame.h
@@ -127,7 +127,7 @@ enum ast_frame_type {
 	 * directly into bridges.
 	 */
 	AST_FRAME_BRIDGE_ACTION_SYNC,
-	/*! RTCP feedback */
+	/*! RTCP feedback (the subclass will contain the payload type) */
 	AST_FRAME_RTCP,
 };
 #define AST_FRAME_DTMF AST_FRAME_DTMF_END
diff --git a/include/asterisk/rtp_engine.h b/include/asterisk/rtp_engine.h
index 4e32d6b32f57fbdf0206df0ad480b9cf1a864a38..b552948d21cf21bfba5cf2115df4625cb91c50bf 100644
--- a/include/asterisk/rtp_engine.h
+++ b/include/asterisk/rtp_engine.h
@@ -292,6 +292,14 @@ struct ast_rtp_payload_type {
 #define AST_RTP_RTCP_SR 200
 /*! Receiver Report */
 #define AST_RTP_RTCP_RR 201
+/*! Payload Specific Feed Back (From RFC4585 also RFC5104) */
+#define AST_RTP_RTCP_PSFB    206
+
+/* Common RTCP feedback message types */
+/*! Full INTRA-frame Request (From RFC5104) */
+#define AST_RTP_RTCP_FMT_FIR	4
+/*! REMB Information (From draft-alvestrand-rmcat-remb-03) */
+#define AST_RTP_RTCP_FMT_REMB	15
 
 /*!
  * \since 12
@@ -327,6 +335,24 @@ struct ast_rtp_rtcp_report {
 	struct ast_rtp_rtcp_report_block *report_block[0];
 };
 
+/*!
+ * \since 15.4.0
+ * \brief A REMB feedback message (see draft-alvestrand-rmcat-remb-03 for details) */
+struct ast_rtp_rtcp_feedback_remb {
+	unsigned int br_exp;		/*!< Exponential scaling of the mantissa for the maximum total media bit rate value */
+	unsigned int br_mantissa;	/*!< The mantissa of the maximum total media bit rate */
+};
+
+/*!
+ * \since 15.4.0
+ * \brief An object that represents data received in a feedback report */
+struct ast_rtp_rtcp_feedback {
+	unsigned int fmt; /*!< The feedback message type */
+	union {
+		struct ast_rtp_rtcp_feedback_remb remb; /*!< REMB feedback information */
+	};
+};
+
 /*! Structure that represents statistics from an RTP instance */
 struct ast_rtp_instance_stats {
 	/*! Number of packets transmitted */
diff --git a/main/bridge_channel.c b/main/bridge_channel.c
index 89e55713fba96cb2edcd6349bc8d56fe1adb4d6b..3aac5eb254dfe0b9d88be1b2ea580ded2e22368a 100644
--- a/main/bridge_channel.c
+++ b/main/bridge_channel.c
@@ -653,7 +653,8 @@ static int bridge_channel_write_frame(struct ast_bridge_channel *bridge_channel,
 		case AST_FRAME_VIDEO:
 		case AST_FRAME_TEXT:
 		case AST_FRAME_IMAGE:
-			/* Media frames need to be mapped to an appropriate write stream */
+		case AST_FRAME_RTCP:
+			/* These frames need to be mapped to an appropriate write stream */
 			if (frame->stream_num < 0) {
 				/* Map to default stream */
 				frame->stream_num = -1;
diff --git a/main/channel.c b/main/channel.c
index 869b29f5efd4aa0f756b87887ddd6c377a8ff9e7..815d5dbfe5b8316daadb93c2f1ef7e3f9aabe5e1 100644
--- a/main/channel.c
+++ b/main/channel.c
@@ -4123,8 +4123,7 @@ static struct ast_frame *__ast_read(struct ast_channel *chan, int dropaudio, int
 			if (ast_channel_writetrans(chan)) {
 				ast_translate(ast_channel_writetrans(chan), f, 0);
 			}
-			ast_frfree(f);
-			f = &ast_null_frame;
+			break;
 		default:
 			/* Just pass it on! */
 			break;
@@ -5267,6 +5266,14 @@ int ast_write_stream(struct ast_channel *chan, int stream_num, struct ast_frame
 		/* Ignore these */
 		res = 0;
 		break;
+	case AST_FRAME_RTCP:
+		/* RTCP information is on a per-stream basis and only available on multistream capable channels */
+		if (ast_channel_tech(chan)->write_stream && stream) {
+			res = ast_channel_tech(chan)->write_stream(chan, ast_stream_get_position(stream), fr);
+		} else {
+			res = 0;
+		}
+		break;
 	default:
 		/* At this point, fr is the incoming frame and f is NULL.  Channels do
 		 * not expect to get NULL as a frame pointer and will segfault.  Hence,
diff --git a/res/res_rtp_asterisk.c b/res/res_rtp_asterisk.c
index d0e48240569e7278cf44267fe9f019a6b623e1b4..b010f6c51bdfd2988ba20d41aa9205ce92059fe8 100644
--- a/res/res_rtp_asterisk.c
+++ b/res/res_rtp_asterisk.c
@@ -106,7 +106,7 @@
 #define RTCP_PT_APP     204
 /* VP8: RTCP Feedback */
 /*! Payload Specific Feed Back (From RFC4585 also RFC5104) */
-#define RTCP_PT_PSFB    206
+#define RTCP_PT_PSFB    AST_RTP_RTCP_PSFB
 
 #define RTP_MTU		1200
 #define DTMF_SAMPLE_RATE_MS    8 /*!< DTMF samples per millisecond */
@@ -5185,6 +5185,7 @@ static const char *rtcp_payload_type2str(unsigned int pt)
 #define RTCP_SR_BLOCK_WORD_LENGTH 5
 #define RTCP_RR_BLOCK_WORD_LENGTH 6
 #define RTCP_HEADER_SSRC_LENGTH   2
+#define RTCP_FB_REMB_BLOCK_WORD_LENGTH 5
 
 static struct ast_frame *ast_rtcp_interpret(struct ast_rtp_instance *instance, const unsigned char *rtcpdata, size_t size, struct ast_sockaddr *addr)
 {
@@ -5266,6 +5267,7 @@ static struct ast_frame *ast_rtcp_interpret(struct ast_rtp_instance *instance, c
 		RAII_VAR(struct ast_rtp_rtcp_report *, rtcp_report, NULL, ao2_cleanup);
 		struct ast_rtp_instance *child;
 		struct ast_rtp *rtp;
+		struct ast_rtp_rtcp_feedback *feedback;
 
 		i = position;
 		first_word = ntohl(rtcpheader[i]);
@@ -5284,7 +5286,15 @@ static struct ast_frame *ast_rtcp_interpret(struct ast_rtp_instance *instance, c
 			min_length += (rc * RTCP_RR_BLOCK_WORD_LENGTH);
 			break;
 		case RTCP_PT_FUR:
+			break;
 		case RTCP_PT_PSFB:
+			switch (rc) {
+			case AST_RTP_RTCP_FMT_REMB:
+				min_length += RTCP_FB_REMB_BLOCK_WORD_LENGTH;
+				break;
+			default:
+				break;
+			}
 			break;
 		case RTCP_PT_SDES:
 		case RTCP_PT_BYE:
@@ -5493,6 +5503,7 @@ static struct ast_frame *ast_rtcp_interpret(struct ast_rtp_instance *instance, c
 			/* Return an AST_FRAME_RTCP frame with the ast_rtp_rtcp_report
 			 * object as a its data */
 			transport_rtp->f.frametype = AST_FRAME_RTCP;
+			transport_rtp->f.subclass.integer = pt;
 			transport_rtp->f.data.ptr = rtp->rtcp->frame_buf + AST_FRIENDLY_OFFSET;
 			memcpy(transport_rtp->f.data.ptr, rtcp_report, sizeof(struct ast_rtp_rtcp_report));
 			transport_rtp->f.datalen = sizeof(struct ast_rtp_rtcp_report);
@@ -5514,18 +5525,55 @@ static struct ast_frame *ast_rtcp_interpret(struct ast_rtp_instance *instance, c
 			f = &transport_rtp->f;
 			break;
 		case RTCP_PT_FUR:
-		/* Handle RTCP FIR as FUR */
+		/* Handle RTCP FUR as FIR by setting the format to 4 */
+			rc = AST_RTP_RTCP_FMT_FIR;
 		case RTCP_PT_PSFB:
-			if (rtcp_debug_test_addr(addr)) {
-				ast_verbose("Received an RTCP Fast Update Request\n");
+			switch (rc) {
+			case AST_RTP_RTCP_FMT_FIR:
+				if (rtcp_debug_test_addr(addr)) {
+					ast_verbose("Received an RTCP Fast Update Request\n");
+				}
+				transport_rtp->f.frametype = AST_FRAME_CONTROL;
+				transport_rtp->f.subclass.integer = AST_CONTROL_VIDUPDATE;
+				transport_rtp->f.datalen = 0;
+				transport_rtp->f.samples = 0;
+				transport_rtp->f.mallocd = 0;
+				transport_rtp->f.src = "RTP";
+				f = &transport_rtp->f;
+				break;
+			case AST_RTP_RTCP_FMT_REMB:
+				/* If REMB support is not enabled ignore this message */
+				if (!ast_rtp_instance_get_prop(instance, AST_RTP_PROPERTY_REMB)) {
+					break;
+				}
+
+				if (rtcp_debug_test_addr(addr)) {
+					ast_verbose("Received REMB report\n");
+				}
+				transport_rtp->f.frametype = AST_FRAME_RTCP;
+				transport_rtp->f.subclass.integer = pt;
+				transport_rtp->f.stream_num = rtp->stream_num;
+				transport_rtp->f.data.ptr = rtp->rtcp->frame_buf + AST_FRIENDLY_OFFSET;
+				feedback = transport_rtp->f.data.ptr;
+				feedback->fmt = rc;
+
+				/* We don't actually care about the SSRC information in the feedback message */
+				first_word = ntohl(rtcpheader[i + 2]);
+				feedback->remb.br_exp = (first_word >> 18) & ((1 << 6) - 1);
+				feedback->remb.br_mantissa = first_word & ((1 << 18) - 1);
+
+				transport_rtp->f.datalen = sizeof(struct ast_rtp_rtcp_feedback);
+				transport_rtp->f.offset = AST_FRIENDLY_OFFSET;
+				transport_rtp->f.samples = 0;
+				transport_rtp->f.mallocd = 0;
+				transport_rtp->f.delivery.tv_sec = 0;
+				transport_rtp->f.delivery.tv_usec = 0;
+				transport_rtp->f.src = "RTP";
+				f = &transport_rtp->f;
+				break;
+			default:
+				break;
 			}
-			transport_rtp->f.frametype = AST_FRAME_CONTROL;
-			transport_rtp->f.subclass.integer = AST_CONTROL_VIDUPDATE;
-			transport_rtp->f.datalen = 0;
-			transport_rtp->f.samples = 0;
-			transport_rtp->f.mallocd = 0;
-			transport_rtp->f.src = "RTP";
-			f = &transport_rtp->f;
 			break;
 		case RTCP_PT_SDES:
 			if (rtcp_debug_test_addr(addr)) {