diff --git a/CHANGES b/CHANGES
index f4c5148a74e09bea920f7ee0ff820667360111c8..2131fee3ca8e0bbdeac95641d4be835e5c42a779 100644
--- a/CHANGES
+++ b/CHANGES
@@ -49,6 +49,15 @@ cel_radius
  * To fix a memory leak the syslog channel is now empty if it has not been set
    and used by a syslog channel in the logger.
 
+RTP
+------------------
+ * New setting "rtp_pt_dynamic = 35" in asterisk.conf:
+   Normally the Dynamic RTP Payload Type numbers are 96-127, which allow just 32
+   formats. To avoid the message "No Dynamic RTP mapping available", the range
+   was changed to 35-63,96-127. This is allowed by RFC 3551 section 3. However,
+   when you use more than 32 formats and calls are not accepted by a remote
+   implementation, please report this and go back to rtp_pt_dynamic = 96.
+
 ------------------------------------------------------------------------------
 --- Functionality changes from Asterisk 14.1.0 to Asterisk 14.2.0 ----------
 ------------------------------------------------------------------------------
diff --git a/configs/samples/asterisk.conf.sample b/configs/samples/asterisk.conf.sample
index 6d6d2f0bb137c4ea5129c1b82287c0e9de7deda4..e13a944b06ac029aae04e4a1fbd4b9f73326703b 100644
--- a/configs/samples/asterisk.conf.sample
+++ b/configs/samples/asterisk.conf.sample
@@ -97,6 +97,14 @@ documentation_language = en_US	; Set the language you want documentation
 				; This is currently is used by DUNDi and
 				; Exchanging Device and Mailbox State
 				; using protocols: XMPP, Corosync and PJSIP.
+;rtp_pt_dynamic = 35		; Normally the Dynamic RTP Payload Type numbers
+				; are 96-127, which allow just 32 formats. The
+				; starting point 35 enables the range 35-63 and
+				; allows 29 additional formats. When you use
+				; more than 32 formats in the dynamic range and
+				; calls are not accepted by a remote
+				; implementation, please report this and go
+				; back to value 96.
 
 ; Changing the following lines may compromise your security.
 ;[files]
diff --git a/include/asterisk/options.h b/include/asterisk/options.h
index e2709f9188f0b3362d18146bfbaf37e38d474626..345bacf6c58de95173464ce80f5b0c9bd0bb1fde 100644
--- a/include/asterisk/options.h
+++ b/include/asterisk/options.h
@@ -155,6 +155,8 @@ extern int dahdi_chan_name_len;
 
 extern int ast_language_is_prefix;
 
+extern unsigned int ast_option_rtpptdynamic;
+
 #if defined(__cplusplus) || defined(c_plusplus)
 }
 #endif
diff --git a/include/asterisk/rtp_engine.h b/include/asterisk/rtp_engine.h
index a40472e9d5e418a75f080b21191e020522794e67..017bb7b7acd19a4470d48076e58ff8adea893903 100644
--- a/include/asterisk/rtp_engine.h
+++ b/include/asterisk/rtp_engine.h
@@ -84,6 +84,9 @@ extern "C" {
 /*! First dynamic RTP payload type */
 #define AST_RTP_PT_FIRST_DYNAMIC 96
 
+/*! Last reassignable RTP payload type */
+#define AST_RTP_PT_LAST_REASSIGN 63
+
 /*! Maximum number of generations */
 #define AST_RED_MAX_GENERATION 5
 
diff --git a/main/asterisk.c b/main/asterisk.c
index 56fc107dba07332dc5d2d25919367ea7daf0bf5a..be6c7cc3242c72b8ba767b46daeef2c9efd25d10 100644
--- a/main/asterisk.c
+++ b/main/asterisk.c
@@ -248,6 +248,7 @@ int daemon(int, int);  /* defined in libresolv of all places */
 #include "asterisk/format_cache.h"
 #include "asterisk/media_cache.h"
 #include "asterisk/astdb.h"
+#include "asterisk/options.h"
 
 #include "../defaults.h"
 
@@ -336,6 +337,7 @@ unsigned int option_dtmfminduration;		/*!< Minimum duration of DTMF. */
 #if defined(HAVE_SYSINFO)
 long option_minmemfree;				/*!< Minimum amount of free system memory - stop accepting calls if free memory falls below this watermark */
 #endif
+unsigned int ast_option_rtpptdynamic;
 
 /*! @} */
 
@@ -599,6 +601,19 @@ static char *handle_show_settings(struct ast_cli_entry *e, int cmd, struct ast_c
 	ast_cli(a->fd, "  Generic PLC:                 %s\n", ast_test_flag(&ast_options, AST_OPT_FLAG_GENERIC_PLC) ? "Enabled" : "Disabled");
 	ast_cli(a->fd, "  Min DTMF duration::          %u\n", option_dtmfminduration);
 
+	if (ast_option_rtpptdynamic == AST_RTP_PT_LAST_REASSIGN) {
+		ast_cli(a->fd, "  RTP dynamic payload types:   %u,%u-%u\n",
+		        ast_option_rtpptdynamic,
+		        AST_RTP_PT_FIRST_DYNAMIC, AST_RTP_MAX_PT - 1);
+	} else if (ast_option_rtpptdynamic < AST_RTP_PT_LAST_REASSIGN) {
+		ast_cli(a->fd, "  RTP dynamic payload types:   %u-%u,%u-%u\n",
+		        ast_option_rtpptdynamic, AST_RTP_PT_LAST_REASSIGN,
+		        AST_RTP_PT_FIRST_DYNAMIC, AST_RTP_MAX_PT - 1);
+	} else {
+		ast_cli(a->fd, "  RTP dynamic payload types:   %u-%u\n",
+		        AST_RTP_PT_FIRST_DYNAMIC, AST_RTP_MAX_PT - 1);
+	}
+
 	ast_cli(a->fd, "\n* Subsystems\n");
 	ast_cli(a->fd, "  -------------\n");
 	ast_cli(a->fd, "  Manager (AMI):               %s\n", check_manager_enabled() ? "Enabled" : "Disabled");
@@ -3464,6 +3479,7 @@ static void ast_readconfig(void)
 
 	/* Set default value */
 	option_dtmfminduration = AST_MIN_DTMF_DURATION;
+	ast_option_rtpptdynamic = 35;
 
 	/* init with buildtime config */
 	ast_copy_string(cfg_paths.config_dir, DEFAULT_CONFIG_DIR, sizeof(cfg_paths.config_dir));
@@ -3619,6 +3635,11 @@ static void ast_readconfig(void)
 			if (sscanf(v->value, "%30u", &option_dtmfminduration) != 1) {
 				option_dtmfminduration = AST_MIN_DTMF_DURATION;
 			}
+		/* http://www.iana.org/assignments/rtp-parameters
+		 * RTP dynamic payload types start at 96 normally; extend down to 0 */
+		} else if (!strcasecmp(v->name, "rtp_pt_dynamic")) {
+			ast_parse_arg(v->value, PARSE_UINT32|PARSE_IN_RANGE,
+			              &ast_option_rtpptdynamic, 0, AST_RTP_PT_FIRST_DYNAMIC);
 		} else if (!strcasecmp(v->name, "maxcalls")) {
 			if ((sscanf(v->value, "%30d", &ast_option_maxcalls) != 1) || (ast_option_maxcalls < 0)) {
 				ast_option_maxcalls = 0;
diff --git a/main/rtp_engine.c b/main/rtp_engine.c
index c9d228c5677f6cfc688fcc79b8eacea14123c029..4fc1414f0089a93280adc5705d1b6bfcc55460b6 100644
--- a/main/rtp_engine.c
+++ b/main/rtp_engine.c
@@ -143,23 +143,36 @@
 
 #include "asterisk.h"
 
-#include <math.h>
-
-#include "asterisk/channel.h"
-#include "asterisk/frame.h"
-#include "asterisk/module.h"
-#include "asterisk/rtp_engine.h"
+#include <math.h>                       /* for sqrt, MAX */
+#include <sched.h>                      /* for sched_yield */
+#include <sys/time.h>                   /* for timeval */
+#include <time.h>                       /* for time_t */
+
+#include "asterisk/_private.h"          /* for ast_rtp_engine_init prototype */
+#include "asterisk/astobj2.h"           /* for ao2_cleanup, ao2_ref, etc */
+#include "asterisk/channel.h"           /* for ast_channel_name, etc */
+#include "asterisk/codec.h"             /* for ast_codec_media_type2str, etc */
+#include "asterisk/format.h"            /* for ast_format_cmp, etc */
+#include "asterisk/format_cache.h"      /* for ast_format_adpcm, etc */
+#include "asterisk/format_cap.h"        /* for ast_format_cap_alloc, etc */
+#include "asterisk/json.h"              /* for ast_json_ref, etc */
+#include "asterisk/linkedlists.h"       /* for ast_rtp_engine::<anonymous>, etc */
+#include "asterisk/lock.h"              /* for ast_rwlock_unlock, etc */
+#include "asterisk/logger.h"            /* for ast_log, ast_debug, etc */
 #include "asterisk/manager.h"
-#include "asterisk/options.h"
-#include "asterisk/astobj2.h"
-#include "asterisk/pbx.h"
-#include "asterisk/translate.h"
-#include "asterisk/netsock2.h"
-#include "asterisk/_private.h"
-#include "asterisk/framehook.h"
-#include "asterisk/stasis.h"
-#include "asterisk/json.h"
-#include "asterisk/stasis_channels.h"
+#include "asterisk/module.h"            /* for ast_module_unref, etc */
+#include "asterisk/netsock2.h"          /* for ast_sockaddr_copy, etc */
+#include "asterisk/options.h"           /* for ast_option_rtpptdynamic */
+#include "asterisk/pbx.h"               /* for pbx_builtin_setvar_helper */
+#include "asterisk/res_srtp.h"          /* for ast_srtp_res */
+#include "asterisk/rtp_engine.h"        /* for ast_rtp_codecs, etc */
+#include "asterisk/stasis.h"            /* for stasis_message_data, etc */
+#include "asterisk/stasis_channels.h"   /* for ast_channel_stage_snapshot, etc */
+#include "asterisk/strings.h"           /* for ast_str_append, etc */
+#include "asterisk/time.h"              /* for ast_tvdiff_ms, ast_tvnow */
+#include "asterisk/translate.h"         /* for ast_translate_available_formats */
+#include "asterisk/utils.h"             /* for ast_free, ast_strdup, etc */
+#include "asterisk/vector.h"            /* for AST_VECTOR_GET, etc */
 
 struct ast_srtp_res *res_srtp = NULL;
 struct ast_srtp_policy_res *res_srtp_policy = NULL;
@@ -2301,6 +2314,48 @@ static void add_static_payload(int map, struct ast_format *format, int rtp_code)
 			}
 		}
 
+		/* http://www.iana.org/assignments/rtp-parameters
+		 * RFC 3551, Section 3: "[...] applications which need to define more
+		 * than 32 dynamic payload types MAY bind codes below 96, in which case
+		 * it is RECOMMENDED that unassigned payload type numbers be used
+		 * first". Updated by RFC 5761, Section 4: "[...] values in the range
+		 * 64-95 MUST NOT be used [to avoid conflicts with RTCP]". Summaries:
+		 * https://tools.ietf.org/html/draft-roach-mmusic-unified-plan#section-3.2.1.2
+		 * https://tools.ietf.org/html/draft-wu-avtcore-dynamic-pt-usage#section-3
+		 */
+		if (map < 0) {
+			for (x = MAX(ast_option_rtpptdynamic, 35); x <= AST_RTP_PT_LAST_REASSIGN; ++x) {
+				if (!static_RTP_PT[x]) {
+					map = x;
+					break;
+				}
+			}
+		}
+		/* Yet, reusing mappings below 35 is not supported in Asterisk because
+		 * when Compact Headers are activated, no rtpmap is send for those below
+		 * 35. If you want to use 35 and below
+		 * A) do not use Compact Headers,
+		 * B) remove that code in chan_sip/res_pjsip, or
+		 * C) add a flag that this RTP Payload Type got reassigned dynamically
+		 *    and requires a rtpmap even with Compact Headers enabled.
+		 */
+		if (map < 0) {
+			for (x = MAX(ast_option_rtpptdynamic, 20); x < 35; ++x) {
+				if (!static_RTP_PT[x]) {
+					map = x;
+					break;
+				}
+			}
+		}
+		if (map < 0) {
+			for (x = MAX(ast_option_rtpptdynamic, 0); x < 20; ++x) {
+				if (!static_RTP_PT[x]) {
+					map = x;
+					break;
+				}
+			}
+		}
+
 		if (map < 0) {
 			if (format) {
 				ast_log(LOG_WARNING, "No Dynamic RTP mapping available for format %s\n",