diff --git a/include/asterisk/codec.h b/include/asterisk/codec.h
index 2f5756cd14f2043936a5d167c4a6bec832f66364..79798acd085b89a1966dad4659b2c21f92464c44 100644
--- a/include/asterisk/codec.h
+++ b/include/asterisk/codec.h
@@ -76,6 +76,8 @@ struct ast_codec {
 	int (*get_length)(unsigned int samples);
 	/*! \brief Whether the media can be smoothed or not */
 	unsigned int smooth;
+	/*! \brief Flags to be passed to the smoother */
+	unsigned int smoother_flags;
 	/*! \brief The module that registered this codec */
 	struct ast_module *mod;
 };
diff --git a/include/asterisk/format.h b/include/asterisk/format.h
index b01592d16e9a3197a7cf62441f06f37247c21d84..0bad96dccc1b9b5fe70ac13b9ef32bed3b35ed2d 100644
--- a/include/asterisk/format.h
+++ b/include/asterisk/format.h
@@ -355,6 +355,17 @@ const char *ast_format_get_codec_name(const struct ast_format *format);
  */
 int ast_format_can_be_smoothed(const struct ast_format *format);
 
+/*!
+ * \since 13.17.0
+ *
+ * \brief Get smoother flags for this format
+ *
+ * \param format The media format
+ *
+ * \return smoother flags for the provided format
+ */
+int ast_format_get_smoother_flags(const struct ast_format *format);
+
 /*!
  * \brief Get the media type of a format
  *
diff --git a/include/asterisk/smoother.h b/include/asterisk/smoother.h
index e63aa77bd684ca8c6324373a337d25f7a672ec83..65ac88921fa86998db662d0443c580f318b53c18 100644
--- a/include/asterisk/smoother.h
+++ b/include/asterisk/smoother.h
@@ -33,6 +33,7 @@ extern "C" {
 
 #define AST_SMOOTHER_FLAG_G729		(1 << 0)
 #define AST_SMOOTHER_FLAG_BE		(1 << 1)
+#define AST_SMOOTHER_FLAG_FORCED	(1 << 2)
 
 /*! \name AST_Smoother
 */
diff --git a/main/codec_builtin.c b/main/codec_builtin.c
index 3320900c2e34f9a1e897284cb09458c20ddf0735..32ec12d3d428fcd69ddff73ea7533c58b166f8f5 100644
--- a/main/codec_builtin.c
+++ b/main/codec_builtin.c
@@ -36,6 +36,7 @@
 #include "asterisk/format.h"
 #include "asterisk/format_cache.h"
 #include "asterisk/frame.h"
+#include "asterisk/smoother.h"
 
 int __ast_codec_register_with_format(struct ast_codec *codec, const char *format_name,
 	struct ast_module *mod);
@@ -288,6 +289,7 @@ static struct ast_codec slin8 = {
 	.samples_count = slin_samples,
 	.get_length = slin_length,
 	.smooth = 1,
+	.smoother_flags = AST_SMOOTHER_FLAG_BE | AST_SMOOTHER_FLAG_FORCED,
 };
 
 static struct ast_codec slin12 = {
@@ -302,6 +304,7 @@ static struct ast_codec slin12 = {
 	.samples_count = slin_samples,
 	.get_length = slin_length,
 	.smooth = 1,
+	.smoother_flags = AST_SMOOTHER_FLAG_BE | AST_SMOOTHER_FLAG_FORCED,
 };
 
 static struct ast_codec slin16 = {
@@ -316,6 +319,7 @@ static struct ast_codec slin16 = {
 	.samples_count = slin_samples,
 	.get_length = slin_length,
 	.smooth = 1,
+	.smoother_flags = AST_SMOOTHER_FLAG_BE | AST_SMOOTHER_FLAG_FORCED,
 };
 
 static struct ast_codec slin24 = {
@@ -330,6 +334,7 @@ static struct ast_codec slin24 = {
 	.samples_count = slin_samples,
 	.get_length = slin_length,
 	.smooth = 1,
+	.smoother_flags = AST_SMOOTHER_FLAG_BE | AST_SMOOTHER_FLAG_FORCED,
 };
 
 static struct ast_codec slin32 = {
@@ -344,6 +349,7 @@ static struct ast_codec slin32 = {
 	.samples_count = slin_samples,
 	.get_length = slin_length,
 	.smooth = 1,
+	.smoother_flags = AST_SMOOTHER_FLAG_BE | AST_SMOOTHER_FLAG_FORCED,
 };
 
 static struct ast_codec slin44 = {
@@ -358,6 +364,7 @@ static struct ast_codec slin44 = {
 	.samples_count = slin_samples,
 	.get_length = slin_length,
 	.smooth = 1,
+	.smoother_flags = AST_SMOOTHER_FLAG_BE | AST_SMOOTHER_FLAG_FORCED,
 };
 
 static struct ast_codec slin48 = {
@@ -372,6 +379,7 @@ static struct ast_codec slin48 = {
 	.samples_count = slin_samples,
 	.get_length = slin_length,
 	.smooth = 1,
+	.smoother_flags = AST_SMOOTHER_FLAG_BE | AST_SMOOTHER_FLAG_FORCED,
 };
 
 static struct ast_codec slin96 = {
@@ -386,6 +394,7 @@ static struct ast_codec slin96 = {
 	.samples_count = slin_samples,
 	.get_length = slin_length,
 	.smooth = 1,
+	.smoother_flags = AST_SMOOTHER_FLAG_BE | AST_SMOOTHER_FLAG_FORCED,
 };
 
 static struct ast_codec slin192 = {
@@ -400,6 +409,7 @@ static struct ast_codec slin192 = {
 	.samples_count = slin_samples,
 	.get_length = slin_length,
 	.smooth = 1,
+	.smoother_flags = AST_SMOOTHER_FLAG_BE | AST_SMOOTHER_FLAG_FORCED,
 };
 
 static int lpc10_samples(struct ast_frame *frame)
diff --git a/main/format.c b/main/format.c
index 5ae5ad98623bd60bb4e56d4599850d5961d01509..09e736cf5f49017583b8a757517efe0a76328941 100644
--- a/main/format.c
+++ b/main/format.c
@@ -391,6 +391,11 @@ int ast_format_can_be_smoothed(const struct ast_format *format)
 	return format->codec->smooth;
 }
 
+int ast_format_get_smoother_flags(const struct ast_format *format)
+{
+	return format->codec->smoother_flags;
+}
+
 enum ast_media_type ast_format_get_type(const struct ast_format *format)
 {
 	return format->codec->type;
diff --git a/res/res_rtp_asterisk.c b/res/res_rtp_asterisk.c
index 18987cee9eb95daffab57eb4fbea0ac197fb7076..c120fc1452eb98e1be3cbba8ba3d76ecc791bfe1 100644
--- a/res/res_rtp_asterisk.c
+++ b/res/res_rtp_asterisk.c
@@ -3747,7 +3747,7 @@ static int ast_rtcp_write(const void *data)
 }
 
 /*! \pre instance is locked */
-static int ast_rtp_raw_write(struct ast_rtp_instance *instance, struct ast_frame *frame, int codec)
+static int rtp_raw_write(struct ast_rtp_instance *instance, struct ast_frame *frame, int codec)
 {
 	struct ast_rtp *rtp = ast_rtp_instance_get_data(instance);
 	int pred, mark = 0;
@@ -4016,10 +4016,10 @@ static int ast_rtp_write(struct ast_rtp_instance *instance, struct ast_frame *fr
 
 	/* If no smoother is present see if we have to set one up */
 	if (!rtp->smoother && ast_format_can_be_smoothed(format)) {
+		unsigned int smoother_flags = ast_format_get_smoother_flags(format);
 		unsigned int framing_ms = ast_rtp_codecs_get_framing(ast_rtp_instance_get_codecs(instance));
-		int is_slinear = ast_format_cache_is_slinear(format);
 
-		if (!framing_ms && is_slinear) {
+		if (!framing_ms && (smoother_flags & AST_SMOOTHER_FLAG_FORCED)) {
 			framing_ms = ast_format_get_default_ms(format);
 		}
 
@@ -4030,9 +4030,7 @@ static int ast_rtp_write(struct ast_rtp_instance *instance, struct ast_frame *fr
 					ast_format_get_name(format), framing_ms, ast_format_get_minimum_bytes(format));
 				return -1;
 			}
-			if (is_slinear) {
-				ast_smoother_set_flags(rtp->smoother, AST_SMOOTHER_FLAG_BE);
-			}
+			ast_smoother_set_flags(rtp->smoother, smoother_flags);
 		}
 	}
 
@@ -4047,7 +4045,7 @@ static int ast_rtp_write(struct ast_rtp_instance *instance, struct ast_frame *fr
 		}
 
 		while ((f = ast_smoother_read(rtp->smoother)) && (f->data.ptr)) {
-				ast_rtp_raw_write(instance, f, codec);
+				rtp_raw_write(instance, f, codec);
 		}
 	} else {
 		int hdrlen = 12;
@@ -4059,7 +4057,7 @@ static int ast_rtp_write(struct ast_rtp_instance *instance, struct ast_frame *fr
 			f = frame;
 		}
 		if (f->data.ptr) {
-			ast_rtp_raw_write(instance, f, codec);
+			rtp_raw_write(instance, f, codec);
 		}
 		if (f != frame) {
 			ast_frfree(f);
diff --git a/res/res_rtp_multicast.c b/res/res_rtp_multicast.c
index 42de11f65e8239fbcd3e0e065c4ff6755a981552..14176da413ad697fcec73873e1d312196e555303 100644
--- a/res/res_rtp_multicast.c
+++ b/res/res_rtp_multicast.c
@@ -54,6 +54,7 @@
 #include "asterisk/format_cache.h"
 #include "asterisk/multicast_rtp.h"
 #include "asterisk/app.h"
+#include "asterisk/smoother.h"
 
 /*! Command value used for Linksys paging to indicate we are starting */
 #define LINKSYS_MCAST_STARTCMD 6
@@ -95,6 +96,7 @@ struct multicast_rtp {
 	uint16_t seqno;
 	unsigned int lastts;	
 	struct timeval txcore;
+	struct ast_smoother *smoother;
 };
 
 enum {
@@ -395,6 +397,10 @@ static int multicast_rtp_destroy(struct ast_rtp_instance *instance)
 		multicast_send_control_packet(instance, multicast, LINKSYS_MCAST_STOPCMD);
 	}
 
+	if (multicast->smoother) {
+		ast_smoother_free(multicast->smoother);
+	}
+
 	close(multicast->socket);
 
 	ast_free(multicast);
@@ -402,43 +408,24 @@ static int multicast_rtp_destroy(struct ast_rtp_instance *instance)
 	return 0;
 }
 
-/*! \brief Function called to broadcast some audio on a multicast instance */
-static int multicast_rtp_write(struct ast_rtp_instance *instance, struct ast_frame *frame)
+static int rtp_raw_write(struct ast_rtp_instance *instance, struct ast_frame *frame, int codec)
 {
 	struct multicast_rtp *multicast = ast_rtp_instance_get_data(instance);
-	struct ast_frame *f = frame;
-	struct ast_sockaddr remote_address;
-	int hdrlen = 12, res = 0, codec;
-	unsigned char *rtpheader;
 	unsigned int ms = calc_txstamp(multicast, &frame->delivery);
+	unsigned char *rtpheader;
+	struct ast_sockaddr remote_address = { {0,} };
 	int rate = rtp_get_rate(frame->subclass.format) / 1000;
+	int hdrlen = 12;
 
-	/* We only accept audio, nothing else */
-	if (frame->frametype != AST_FRAME_VOICE) {
-		return 0;
-	}
-
-	/* Grab the actual payload number for when we create the RTP packet */
-	codec = ast_rtp_codecs_payload_code_tx(ast_rtp_instance_get_codecs(instance),
-		1, frame->subclass.format, 0);
-	if (codec < 0) {
-		return -1;
-	}
-
-	/* If we do not have space to construct an RTP header duplicate the frame so we get some */
-	if (frame->offset < hdrlen) {
-		f = ast_frdup(frame);
-	}
-	
-	/* Calucate last TS */
+	/* Calculate last TS */
 	multicast->lastts = multicast->lastts + ms * rate;
-	
+
 	/* Construct an RTP header for our packet */
-	rtpheader = (unsigned char *)(f->data.ptr - hdrlen);
+	rtpheader = (unsigned char *)(frame->data.ptr - hdrlen);
 	put_unaligned_uint32(rtpheader, htonl((2 << 30) | (codec << 16) | (multicast->seqno)));
-	
-	if (ast_test_flag(f, AST_FRFLAG_HAS_TIMING_INFO)) {
-		put_unaligned_uint32(rtpheader + 4, htonl(f->ts * 8));
+
+	if (ast_test_flag(frame, AST_FRFLAG_HAS_TIMING_INFO)) {
+		put_unaligned_uint32(rtpheader + 4, htonl(frame->ts * 8));
 	} else {
 		put_unaligned_uint32(rtpheader + 4, htonl(multicast->lastts));
 	}
@@ -451,19 +438,86 @@ static int multicast_rtp_write(struct ast_rtp_instance *instance, struct ast_fra
 	/* Finally send it out to the eager phones listening for us */
 	ast_rtp_instance_get_remote_address(instance, &remote_address);
 
-	if (ast_sendto(multicast->socket, (void *) rtpheader, f->datalen + hdrlen, 0, &remote_address) < 0) {
+	if (ast_sendto(multicast->socket, (void *) rtpheader, frame->datalen + hdrlen, 0, &remote_address) < 0) {
 		ast_log(LOG_ERROR, "Multicast RTP Transmission error to %s: %s\n",
 			ast_sockaddr_stringify(&remote_address),
 			strerror(errno));
-		res = -1;
+		return -1;
 	}
 
-	/* If we were forced to duplicate the frame free the new one */
-	if (frame != f) {
-		ast_frfree(f);
+	return 0;
+}
+
+/*! \brief Function called to broadcast some audio on a multicast instance */
+static int multicast_rtp_write(struct ast_rtp_instance *instance, struct ast_frame *frame)
+{
+	struct multicast_rtp *multicast = ast_rtp_instance_get_data(instance);
+	struct ast_format *format;
+	struct ast_frame *f;
+	int codec;
+
+	/* We only accept audio, nothing else */
+	if (frame->frametype != AST_FRAME_VOICE) {
+		return 0;
 	}
 
-	return res;
+	/* Grab the actual payload number for when we create the RTP packet */
+	codec = ast_rtp_codecs_payload_code_tx(ast_rtp_instance_get_codecs(instance),
+		1, frame->subclass.format, 0);
+	if (codec < 0) {
+		return -1;
+	}
+
+	format = frame->subclass.format;
+	if (!multicast->smoother && ast_format_can_be_smoothed(format)) {
+		unsigned int smoother_flags = ast_format_get_smoother_flags(format);
+		unsigned int framing_ms = ast_rtp_codecs_get_framing(ast_rtp_instance_get_codecs(instance));
+
+		if (!framing_ms && (smoother_flags & AST_SMOOTHER_FLAG_FORCED)) {
+			framing_ms = ast_format_get_default_ms(format);
+		}
+
+		if (framing_ms) {
+			multicast->smoother = ast_smoother_new((framing_ms * ast_format_get_minimum_bytes(format)) / ast_format_get_minimum_ms(format));
+			if (!multicast->smoother) {
+				ast_log(LOG_WARNING, "Unable to create smoother: format %s ms: %u len %u\n",
+						ast_format_get_name(format), framing_ms, ast_format_get_minimum_bytes(format));
+				return -1;
+			}
+			ast_smoother_set_flags(multicast->smoother, smoother_flags);
+		}
+	}
+
+	if (multicast->smoother) {
+		if (ast_smoother_test_flag(multicast->smoother, AST_SMOOTHER_FLAG_BE)) {
+			ast_smoother_feed_be(multicast->smoother, frame);
+		} else {
+			ast_smoother_feed(multicast->smoother, frame);
+		}
+
+		while ((f = ast_smoother_read(multicast->smoother)) && f->data.ptr) {
+			rtp_raw_write(instance, f, codec);
+		}
+	} else {
+		int hdrlen = 12;
+
+		/* If we do not have space to construct an RTP header duplicate the frame so we get some */
+		if (frame->offset < hdrlen) {
+			f = ast_frdup(frame);
+		} else {
+			f = frame;
+		}
+
+		if (f->data.ptr) {
+			rtp_raw_write(instance, f, codec);
+		}
+
+		if (f != frame) {
+			ast_frfree(f);
+		}
+	}
+
+	return 0;
 }
 
 /*! \brief Function called to read from a multicast instance */