Media Project Phase2: SILK 8khz-24khz, SLINEAR 8khz-192khz, SPEEX 32khz, hd audio...
[asterisk/asterisk.git] / res / res_rtp_asterisk.c
index a6a4f3c..b2004ef 100644 (file)
@@ -24,6 +24,8 @@
  * \author Mark Spencer <markster@digium.com>
  *
  * \note RTP is defined in RFC 3550.
+ *
+ * \ingroup rtp_engines
  */
 
 #include "asterisk.h"
@@ -33,7 +35,6 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
 #include <sys/time.h>
 #include <signal.h>
 #include <fcntl.h>
-#include <math.h>
 
 #include "asterisk/stun.h"
 #include "asterisk/pbx.h"
@@ -43,7 +44,6 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
 #include "asterisk/config.h"
 #include "asterisk/lock.h"
 #include "asterisk/utils.h"
-#include "asterisk/netsock.h"
 #include "asterisk/cli.h"
 #include "asterisk/manager.h"
 #include "asterisk/unaligned.h"
@@ -76,6 +76,7 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
 
 #define ZFONE_PROFILE_ID 0x505a
 
+extern struct ast_srtp_res *res_srtp;
 static int dtmftimeout = DEFAULT_DTMF_TIMEOUT;
 
 static int rtpstart = DEFAULT_RTP_START;                       /*!< First port for RTP sessions (set in rtp.conf) */
@@ -84,8 +85,8 @@ static int rtpdebug;                  /*!< Are we debugging? */
 static int rtcpdebug;                  /*!< Are we debugging RTCP? */
 static int rtcpstats;                  /*!< Are we debugging RTCP? */
 static int rtcpinterval = RTCP_DEFAULT_INTERVALMS; /*!< Time between rtcp reports in millisecs */
-static struct sockaddr_in rtpdebugaddr;        /*!< Debug packets to/from this host */
-static struct sockaddr_in rtcpdebugaddr;       /*!< Debug RTCP packets to/from this host */
+static struct ast_sockaddr rtpdebugaddr;       /*!< Debug packets to/from this host */
+static struct ast_sockaddr rtcpdebugaddr;      /*!< Debug RTCP packets to/from this host */
 #ifdef SO_NO_CHECK
 static int nochecksums;
 #endif
@@ -129,8 +130,8 @@ struct ast_rtp {
        unsigned int cycles;            /*!< Shifted count of sequence number cycles */
        double rxjitter;                /*!< Interarrival jitter at the moment */
        double rxtransit;               /*!< Relative transit time for previous packet */
-       int lasttxformat;
-       int lastrxformat;
+       struct ast_format lasttxformat;
+       struct ast_format lastrxformat;
 
        int rtptimeout;                 /*!< RTP timeout time (negative or zero means disabled, negative value means temporarily disabled) */
        int rtpholdtimeout;             /*!< RTP timeout when on hold (negative or zero means disabled, negative value means temporarily disabled). */
@@ -158,14 +159,15 @@ struct ast_rtp {
        int *ioid;
        unsigned short seqno;           /*!< Sequence number, RFC 3550, page 13. */
        unsigned short rxseqno;
-       struct sched_context *sched;
+       struct ast_sched_context *sched;
        struct io_context *io;
        void *data;
        struct ast_rtcp *rtcp;
        struct ast_rtp *bridged;        /*!< Who we are Packet bridged to */
 
        enum strict_rtp_state strict_rtp_state; /*!< Current state that strict RTP protection is in */
-       struct sockaddr_in strict_rtp_address;  /*!< Remote address information for strict RTP purposes */
+       struct ast_sockaddr strict_rtp_address;  /*!< Remote address information for strict RTP purposes */
+       struct ast_sockaddr alt_rtp_address; /*!<Alternate remote address information */
 
        struct rtp_red *red;
 };
@@ -183,8 +185,8 @@ struct ast_rtp {
 struct ast_rtcp {
        int rtcp_info;
        int s;                          /*!< Socket */
-       struct sockaddr_in us;          /*!< Socket representation of the local endpoint. */
-       struct sockaddr_in them;        /*!< Socket representation of the remote endpoint. */
+       struct ast_sockaddr us;         /*!< Socket representation of the local endpoint. */
+       struct ast_sockaddr them;       /*!< Socket representation of the remote endpoint. */
        unsigned int soc;               /*!< What they told us */
        unsigned int spc;               /*!< What they told us */
        unsigned int themrxlsr;         /*!< The middle 32 bits of the NTP timestamp in the last received SR*/
@@ -246,24 +248,30 @@ struct rtp_red {
        long int prev_ts;
 };
 
+AST_LIST_HEAD_NOLOCK(frame_list, ast_frame);
+
 /* Forward Declarations */
-static int ast_rtp_new(struct ast_rtp_instance *instance, struct sched_context *sched, struct sockaddr_in *sin, void *data);
+static int ast_rtp_new(struct ast_rtp_instance *instance, struct ast_sched_context *sched, struct ast_sockaddr *addr, void *data);
 static int ast_rtp_destroy(struct ast_rtp_instance *instance);
 static int ast_rtp_dtmf_begin(struct ast_rtp_instance *instance, char digit);
 static int ast_rtp_dtmf_end(struct ast_rtp_instance *instance, char digit);
-static void ast_rtp_new_source(struct ast_rtp_instance *instance);
+static int ast_rtp_dtmf_end_with_duration(struct ast_rtp_instance *instance, char digit, unsigned int duration);
+static void ast_rtp_update_source(struct ast_rtp_instance *instance);
+static void ast_rtp_change_source(struct ast_rtp_instance *instance);
 static int ast_rtp_write(struct ast_rtp_instance *instance, struct ast_frame *frame);
 static struct ast_frame *ast_rtp_read(struct ast_rtp_instance *instance, int rtcp);
 static void ast_rtp_prop_set(struct ast_rtp_instance *instance, enum ast_rtp_property property, int value);
 static int ast_rtp_fd(struct ast_rtp_instance *instance, int rtcp);
-static void ast_rtp_remote_address_set(struct ast_rtp_instance *instance, struct sockaddr_in *sin);
+static void ast_rtp_remote_address_set(struct ast_rtp_instance *instance, struct ast_sockaddr *addr);
+static void ast_rtp_alt_remote_address_set(struct ast_rtp_instance *instance, struct ast_sockaddr *addr);
 static int rtp_red_init(struct ast_rtp_instance *instance, int buffer_time, int *payloads, int generations);
 static int rtp_red_buffer(struct ast_rtp_instance *instance, struct ast_frame *frame);
 static int ast_rtp_local_bridge(struct ast_rtp_instance *instance0, struct ast_rtp_instance *instance1);
 static int ast_rtp_get_stat(struct ast_rtp_instance *instance, struct ast_rtp_instance_stats *stats, enum ast_rtp_instance_stat stat);
 static int ast_rtp_dtmf_compatible(struct ast_channel *chan0, struct ast_rtp_instance *instance0, struct ast_channel *chan1, struct ast_rtp_instance *instance1);
-static void ast_rtp_stun_request(struct ast_rtp_instance *instance, struct sockaddr_in *suggestion, const char *username);
+static void ast_rtp_stun_request(struct ast_rtp_instance *instance, struct ast_sockaddr *suggestion, const char *username);
 static void ast_rtp_stop(struct ast_rtp_instance *instance);
+static int ast_rtp_qos_set(struct ast_rtp_instance *instance, int tos, int cos, const char* desc);
 
 /* RTP Engine Declaration */
 static struct ast_rtp_engine asterisk_rtp_engine = {
@@ -272,12 +280,15 @@ static struct ast_rtp_engine asterisk_rtp_engine = {
        .destroy = ast_rtp_destroy,
        .dtmf_begin = ast_rtp_dtmf_begin,
        .dtmf_end = ast_rtp_dtmf_end,
-       .new_source = ast_rtp_new_source,
+       .dtmf_end_with_duration = ast_rtp_dtmf_end_with_duration,
+       .update_source = ast_rtp_update_source,
+       .change_source = ast_rtp_change_source,
        .write = ast_rtp_write,
        .read = ast_rtp_read,
        .prop_set = ast_rtp_prop_set,
        .fd = ast_rtp_fd,
        .remote_address_set = ast_rtp_remote_address_set,
+       .alt_remote_address_set = ast_rtp_alt_remote_address_set,
        .red_init = rtp_red_init,
        .red_buffer = rtp_red_buffer,
        .local_bridge = ast_rtp_local_bridge,
@@ -285,38 +296,81 @@ static struct ast_rtp_engine asterisk_rtp_engine = {
        .dtmf_compatible = ast_rtp_dtmf_compatible,
        .stun_request = ast_rtp_stun_request,
        .stop = ast_rtp_stop,
+       .qos = ast_rtp_qos_set,
 };
 
-static inline int rtp_debug_test_addr(struct sockaddr_in *addr)
+static inline int rtp_debug_test_addr(struct ast_sockaddr *addr)
 {
        if (!rtpdebug) {
                return 0;
        }
 
-       if (rtpdebugaddr.sin_addr.s_addr) {
-               if (((ntohs(rtpdebugaddr.sin_port) != 0)
-                    && (rtpdebugaddr.sin_port != addr->sin_port))
-                   || (rtpdebugaddr.sin_addr.s_addr != addr->sin_addr.s_addr))
-                       return 0;
-       }
-
-       return 1;
+       return ast_sockaddr_isnull(&rtpdebugaddr) ? 1 : ast_sockaddr_cmp(&rtpdebugaddr, addr) == 0;
 }
 
-static inline int rtcp_debug_test_addr(struct sockaddr_in *addr)
+static inline int rtcp_debug_test_addr(struct ast_sockaddr *addr)
 {
        if (!rtcpdebug) {
                return 0;
        }
 
-       if (rtcpdebugaddr.sin_addr.s_addr) {
-               if (((ntohs(rtcpdebugaddr.sin_port) != 0)
-                    && (rtcpdebugaddr.sin_port != addr->sin_port))
-                   || (rtcpdebugaddr.sin_addr.s_addr != addr->sin_addr.s_addr))
-                       return 0;
+       return ast_sockaddr_isnull(&rtcpdebugaddr) ? 1 : ast_sockaddr_cmp(&rtcpdebugaddr, addr) == 0;
+}
+
+static int __rtp_recvfrom(struct ast_rtp_instance *instance, void *buf, size_t size, int flags, struct ast_sockaddr *sa, int rtcp)
+{
+       int len;
+       struct ast_rtp *rtp = ast_rtp_instance_get_data(instance);
+       struct ast_srtp *srtp = ast_rtp_instance_get_srtp(instance);
+
+       if ((len = ast_recvfrom(rtcp ? rtp->rtcp->s : rtp->s, buf, size, flags, sa)) < 0) {
+          return len;
        }
 
-       return 1;
+       if (res_srtp && srtp && res_srtp->unprotect(srtp, buf, &len, rtcp) < 0) {
+          return -1;
+       }
+
+       return len;
+}
+
+static int rtcp_recvfrom(struct ast_rtp_instance *instance, void *buf, size_t size, int flags, struct ast_sockaddr *sa)
+{
+       return __rtp_recvfrom(instance, buf, size, flags, sa, 1);
+}
+
+static int rtp_recvfrom(struct ast_rtp_instance *instance, void *buf, size_t size, int flags, struct ast_sockaddr *sa)
+{
+       return __rtp_recvfrom(instance, buf, size, flags, sa, 0);
+}
+
+static int __rtp_sendto(struct ast_rtp_instance *instance, void *buf, size_t size, int flags, struct ast_sockaddr *sa, int rtcp)
+{
+       int len = size;
+       void *temp = buf;
+       struct ast_rtp *rtp = ast_rtp_instance_get_data(instance);
+       struct ast_srtp *srtp = ast_rtp_instance_get_srtp(instance);
+
+       if (res_srtp && srtp && res_srtp->protect(srtp, &temp, &len, rtcp) < 0) {
+          return -1;
+       }
+
+       return ast_sendto(rtcp ? rtp->rtcp->s : rtp->s, temp, len, flags, sa);
+}
+
+static int rtcp_sendto(struct ast_rtp_instance *instance, void *buf, size_t size, int flags, struct ast_sockaddr *sa)
+{
+       return __rtp_sendto(instance, buf, size, flags, sa, 1);
+}
+
+static int rtp_sendto(struct ast_rtp_instance *instance, void *buf, size_t size, int flags, struct ast_sockaddr *sa)
+{
+       return __rtp_sendto(instance, buf, size, flags, sa, 0);
+}
+
+static int rtp_get_rate(struct ast_format *format)
+{
+       return (format->id == AST_FORMAT_G722) ? 8000 : ast_format_rate(format);
 }
 
 static unsigned int ast_rtcp_calc_interval(struct ast_rtp *rtp)
@@ -357,9 +411,9 @@ static double stddev_compute(double stddev, double sample, double normdev, doubl
 #undef SQUARE
 }
 
-static int create_new_socket(const char *type)
+static int create_new_socket(const char *type, int af)
 {
-       int sock = socket(AF_INET, SOCK_DGRAM, 0);
+       int sock = socket(af, SOCK_DGRAM, 0);
 
        if (sock < 0) {
                if (!type) {
@@ -379,7 +433,9 @@ static int create_new_socket(const char *type)
        return sock;
 }
 
-static int ast_rtp_new(struct ast_rtp_instance *instance, struct sched_context *sched, struct sockaddr_in *sin, void *data)
+static int ast_rtp_new(struct ast_rtp_instance *instance,
+                      struct ast_sched_context *sched, struct ast_sockaddr *addr,
+                      void *data)
 {
        struct ast_rtp *rtp = NULL;
        int x, startplace;
@@ -395,7 +451,10 @@ static int ast_rtp_new(struct ast_rtp_instance *instance, struct sched_context *
        rtp->strict_rtp_state = (strictrtp ? STRICT_RTP_LEARN : STRICT_RTP_OPEN);
 
        /* Create a new socket for us to listen on and use */
-       if ((rtp->s = create_new_socket("RTP")) < 0) {
+       if ((rtp->s =
+            create_new_socket("RTP",
+                              ast_sockaddr_is_ipv4(addr) ? AF_INET  :
+                              ast_sockaddr_is_ipv6(addr) ? AF_INET6 : -1)) < 0) {
                ast_debug(1, "Failed to create a new socket for RTP instance '%p'\n", instance);
                ast_free(rtp);
                return -1;
@@ -407,11 +466,11 @@ static int ast_rtp_new(struct ast_rtp_instance *instance, struct sched_context *
        startplace = x;
 
        for (;;) {
-               sin->sin_port = htons(x);
+               ast_sockaddr_set_port(addr, x);
                /* Try to bind, this will tell us whether the port is available or not */
-               if (!bind(rtp->s, (struct sockaddr *)sin, sizeof(*sin))) {
+               if (!ast_bind(rtp->s, addr)) {
                        ast_debug(1, "Allocated port %d for RTP instance '%p'\n", x, instance);
-                       ast_rtp_instance_set_local_address(instance, sin);
+                       ast_rtp_instance_set_local_address(instance, addr);
                        break;
                }
 
@@ -472,7 +531,7 @@ static int ast_rtp_destroy(struct ast_rtp_instance *instance)
 static int ast_rtp_dtmf_begin(struct ast_rtp_instance *instance, char digit)
 {
        struct ast_rtp *rtp = ast_rtp_instance_get_data(instance);
-       struct sockaddr_in remote_address = { 0, };
+       struct ast_sockaddr remote_address = { {0,} };
        int hdrlen = 12, res = 0, i = 0, payload = 101;
        char data[256];
        unsigned int *rtpheader = (unsigned int*)data;
@@ -480,7 +539,7 @@ static int ast_rtp_dtmf_begin(struct ast_rtp_instance *instance, char digit)
        ast_rtp_instance_get_remote_address(instance, &remote_address);
 
        /* If we have no remote address information bail out now */
-       if (!remote_address.sin_addr.s_addr || !remote_address.sin_port) {
+       if (ast_sockaddr_isnull(&remote_address)) {
                return -1;
        }
 
@@ -501,7 +560,7 @@ static int ast_rtp_dtmf_begin(struct ast_rtp_instance *instance, char digit)
        }
 
        /* Grab the payload that they expect the RFC2833 packet to be received in */
-       payload = ast_rtp_codecs_payload_code(ast_rtp_instance_get_codecs(instance), 0, AST_RTP_DTMF);
+       payload = ast_rtp_codecs_payload_code(ast_rtp_instance_get_codecs(instance), 0, NULL, AST_RTP_DTMF);
 
        rtp->dtmfmute = ast_tvadd(ast_tvnow(), ast_tv(0, 500000));
        rtp->send_duration = 160;
@@ -515,15 +574,16 @@ static int ast_rtp_dtmf_begin(struct ast_rtp_instance *instance, char digit)
        /* Actually send the packet */
        for (i = 0; i < 2; i++) {
                rtpheader[3] = htonl((digit << 24) | (0xa << 16) | (rtp->send_duration));
-               res = sendto(rtp->s, (void *) rtpheader, hdrlen + 4, 0, (struct sockaddr *) &remote_address, sizeof(remote_address));
+               res = rtp_sendto(instance, (void *) rtpheader, hdrlen + 4, 0, &remote_address);
                if (res < 0) {
-                       ast_log(LOG_ERROR, "RTP Transmission error to %s:%u: %s\n",
-                               ast_inet_ntoa(remote_address.sin_addr), ntohs(remote_address.sin_port), strerror(errno));
+                       ast_log(LOG_ERROR, "RTP Transmission error to %s: %s\n",
+                               ast_sockaddr_stringify(&remote_address),
+                               strerror(errno));
                }
                if (rtp_debug_test_addr(&remote_address)) {
-                       ast_verbose("Sent RTP DTMF packet to %s:%u (type %-2.2d, seq %-6.6u, ts %-6.6u, len %-6.6u)\n",
-                                   ast_inet_ntoa(remote_address.sin_addr),
-                                   ntohs(remote_address.sin_port), payload, rtp->seqno, rtp->lastdigitts, res - hdrlen);
+                       ast_verbose("Sent RTP DTMF packet to %s (type %-2.2d, seq %-6.6u, ts %-6.6u, len %-6.6u)\n",
+                                   ast_sockaddr_stringify(&remote_address),
+                                   payload, rtp->seqno, rtp->lastdigitts, res - hdrlen);
                }
                rtp->seqno++;
                rtp->send_duration += 160;
@@ -541,7 +601,7 @@ static int ast_rtp_dtmf_begin(struct ast_rtp_instance *instance, char digit)
 static int ast_rtp_dtmf_continuation(struct ast_rtp_instance *instance)
 {
        struct ast_rtp *rtp = ast_rtp_instance_get_data(instance);
-       struct sockaddr_in remote_address = { 0, };
+       struct ast_sockaddr remote_address = { {0,} };
        int hdrlen = 12, res = 0;
        char data[256];
        unsigned int *rtpheader = (unsigned int*)data;
@@ -549,7 +609,7 @@ static int ast_rtp_dtmf_continuation(struct ast_rtp_instance *instance)
        ast_rtp_instance_get_remote_address(instance, &remote_address);
 
        /* Make sure we know where the other side is so we can send them the packet */
-       if (!remote_address.sin_addr.s_addr || !remote_address.sin_port) {
+       if (ast_sockaddr_isnull(&remote_address)) {
                return -1;
        }
 
@@ -561,17 +621,17 @@ static int ast_rtp_dtmf_continuation(struct ast_rtp_instance *instance)
        rtpheader[0] = htonl((2 << 30) | (rtp->send_payload << 16) | (rtp->seqno));
 
        /* Boom, send it on out */
-       res = sendto(rtp->s, (void *) rtpheader, hdrlen + 4, 0, (struct sockaddr *) &remote_address, sizeof(remote_address));
+       res = rtp_sendto(instance, (void *) rtpheader, hdrlen + 4, 0, &remote_address);
        if (res < 0) {
-               ast_log(LOG_ERROR, "RTP Transmission error to %s:%d: %s\n",
-                       ast_inet_ntoa(remote_address.sin_addr),
-                       ntohs(remote_address.sin_port), strerror(errno));
+               ast_log(LOG_ERROR, "RTP Transmission error to %s: %s\n",
+                       ast_sockaddr_stringify(&remote_address),
+                       strerror(errno));
        }
 
        if (rtp_debug_test_addr(&remote_address)) {
-               ast_verbose("Sent RTP DTMF packet to %s:%u (type %-2.2d, seq %-6.6u, ts %-6.6u, len %-6.6u)\n",
-                           ast_inet_ntoa(remote_address.sin_addr),
-                           ntohs(remote_address.sin_port), rtp->send_payload, rtp->seqno, rtp->lastdigitts, res - hdrlen);
+               ast_verbose("Sent RTP DTMF packet to %s (type %-2.2d, seq %-6.6u, ts %-6.6u, len %-6.6u)\n",
+                           ast_sockaddr_stringify(&remote_address),
+                           rtp->send_payload, rtp->seqno, rtp->lastdigitts, res - hdrlen);
        }
 
        /* And now we increment some values for the next time we swing by */
@@ -581,18 +641,19 @@ static int ast_rtp_dtmf_continuation(struct ast_rtp_instance *instance)
        return 0;
 }
 
-static int ast_rtp_dtmf_end(struct ast_rtp_instance *instance, char digit)
+static int ast_rtp_dtmf_end_with_duration(struct ast_rtp_instance *instance, char digit, unsigned int duration)
 {
        struct ast_rtp *rtp = ast_rtp_instance_get_data(instance);
-       struct sockaddr_in remote_address = { 0, };
+       struct ast_sockaddr remote_address = { {0,} };
        int hdrlen = 12, res = 0, i = 0;
        char data[256];
        unsigned int *rtpheader = (unsigned int*)data;
+       unsigned int measured_samples;
 
        ast_rtp_instance_get_remote_address(instance, &remote_address);
 
        /* Make sure we know where the remote side is so we can send them the packet we construct */
-       if (!remote_address.sin_addr.s_addr || !remote_address.sin_port) {
+       if (ast_sockaddr_isnull(&remote_address)) {
                return -1;
        }
 
@@ -614,6 +675,11 @@ static int ast_rtp_dtmf_end(struct ast_rtp_instance *instance, char digit)
 
        rtp->dtmfmute = ast_tvadd(ast_tvnow(), ast_tv(0, 500000));
 
+       if (duration > 0 && (measured_samples = duration * rtp_get_rate(&rtp->f.subclass.format) / 1000) > rtp->send_duration) {
+               ast_debug(2, "Adjusting final end duration from %u to %u\n", rtp->send_duration, measured_samples);
+               rtp->send_duration = measured_samples;
+       }
+
        /* Construct the packet we are going to send */
        rtpheader[0] = htonl((2 << 30) | (1 << 23) | (rtp->send_payload << 16) | (rtp->seqno));
        rtpheader[1] = htonl(rtp->lastdigitts);
@@ -624,16 +690,16 @@ static int ast_rtp_dtmf_end(struct ast_rtp_instance *instance, char digit)
 
        /* Send it 3 times, that's the magical number */
        for (i = 0; i < 3; i++) {
-               res = sendto(rtp->s, (void *) rtpheader, hdrlen + 4, 0, (struct sockaddr *) &remote_address, sizeof(remote_address));
+               res = rtp_sendto(instance, (void *) rtpheader, hdrlen + 4, 0, &remote_address);
                if (res < 0) {
-                       ast_log(LOG_ERROR, "RTP Transmission error to %s:%d: %s\n",
-                               ast_inet_ntoa(remote_address.sin_addr),
-                               ntohs(remote_address.sin_port), strerror(errno));
+                       ast_log(LOG_ERROR, "RTP Transmission error to %s: %s\n",
+                               ast_sockaddr_stringify(&remote_address),
+                               strerror(errno));
                }
                if (rtp_debug_test_addr(&remote_address)) {
-                       ast_verbose("Sent RTP DTMF packet to %s:%u (type %-2.2d, seq %-6.6u, ts %-6.6u, len %-6.6u)\n",
-                                   ast_inet_ntoa(remote_address.sin_addr),
-                                   ntohs(remote_address.sin_port), rtp->send_payload, rtp->seqno, rtp->lastdigitts, res - hdrlen);
+                       ast_verbose("Sent RTP DTMF packet to %s (type %-2.2d, seq %-6.6u, ts %-6.6u, len %-6.6u)\n",
+                                   ast_sockaddr_stringify(&remote_address),
+                                   rtp->send_payload, rtp->seqno, rtp->lastdigitts, res - hdrlen);
                }
        }
 
@@ -645,13 +711,45 @@ static int ast_rtp_dtmf_end(struct ast_rtp_instance *instance, char digit)
        return 0;
 }
 
-static void ast_rtp_new_source(struct ast_rtp_instance *instance)
+static int ast_rtp_dtmf_end(struct ast_rtp_instance *instance, char digit)
+{
+       return ast_rtp_dtmf_end_with_duration(instance, digit, 0);
+}
+
+static void ast_rtp_update_source(struct ast_rtp_instance *instance)
+{
+       struct ast_rtp *rtp = ast_rtp_instance_get_data(instance);
+
+       /* We simply set this bit so that the next packet sent will have the marker bit turned on */
+       ast_set_flag(rtp, FLAG_NEED_MARKER_BIT);
+       ast_debug(3, "Setting the marker bit due to a source update\n");
+
+       return;
+}
+
+static void ast_rtp_change_source(struct ast_rtp_instance *instance)
 {
        struct ast_rtp *rtp = ast_rtp_instance_get_data(instance);
+       struct ast_srtp *srtp = ast_rtp_instance_get_srtp(instance);
+       unsigned int ssrc = ast_random();
+
+       if (!rtp->lastts) {
+               ast_debug(3, "Not changing SSRC since we haven't sent any RTP yet\n");
+               return;
+       }
 
        /* We simply set this bit so that the next packet sent will have the marker bit turned on */
        ast_set_flag(rtp, FLAG_NEED_MARKER_BIT);
 
+       ast_debug(3, "Changing ssrc from %u to %u due to a source change\n", rtp->ssrc, ssrc);
+
+       if (srtp) {
+               ast_debug(3, "Changing ssrc for SRTP from %u to %u\n", rtp->ssrc, ssrc);
+               res_srtp->change_source(srtp, rtp->ssrc, ssrc);
+       }
+
+       rtp->ssrc = ssrc;
+
        return;
 }
 
@@ -685,9 +783,9 @@ static void timeval2ntp(struct timeval tv, unsigned int *msw, unsigned int *lsw)
 }
 
 /*! \brief Send RTCP recipient's report */
-static int ast_rtcp_write_rr(const void *data)
+static int ast_rtcp_write_rr(struct ast_rtp_instance *instance)
 {
-       struct ast_rtp *rtp = (struct ast_rtp *)data;
+       struct ast_rtp *rtp = ast_rtp_instance_get_data(instance);
        int res;
        int len = 32;
        unsigned int lost;
@@ -704,10 +802,10 @@ static int ast_rtcp_write_rr(const void *data)
 
        double rxlost_current;
 
-       if (!rtp || !rtp->rtcp || (&rtp->rtcp->them.sin_addr == 0))
+       if (!rtp || !rtp->rtcp)
                return 0;
 
-       if (!rtp->rtcp->them.sin_addr.s_addr) {
+       if (ast_sockaddr_isnull(&rtp->rtcp->them)) {
                ast_log(LOG_ERROR, "RTCP RR transmission error, rtcp halted\n");
                AST_SCHED_DEL(rtp->sched, rtp->rtcp->schedid);
                return 0;
@@ -760,7 +858,7 @@ static int ast_rtcp_write_rr(const void *data)
        rtcpheader[(len/4)+2] = htonl(0x01 << 24);              /* Empty for the moment */
        len += 12;
 
-       res = sendto(rtp->rtcp->s, (unsigned int *)rtcpheader, len, 0, (struct sockaddr *)&rtp->rtcp->them, sizeof(rtp->rtcp->them));
+       res = rtcp_sendto(instance, (unsigned int *)rtcpheader, len, 0, &rtp->rtcp->them);
 
        if (res < 0) {
                ast_log(LOG_ERROR, "RTCP RR transmission error, rtcp halted: %s\n",strerror(errno));
@@ -771,13 +869,12 @@ static int ast_rtcp_write_rr(const void *data)
 
        rtp->rtcp->rr_count++;
        if (rtcp_debug_test_addr(&rtp->rtcp->them)) {
-               ast_verbose("\n* Sending RTCP RR to %s:%d\n"
+               ast_verbose("\n* Sending RTCP RR to %s\n"
                        "  Our SSRC: %u\nTheir SSRC: %u\niFraction lost: %d\nCumulative loss: %u\n"
                        "  IA jitter: %.4f\n"
                        "  Their last SR: %u\n"
                            "  DLSR: %4.4f (sec)\n\n",
-                           ast_inet_ntoa(rtp->rtcp->them.sin_addr),
-                           ntohs(rtp->rtcp->them.sin_port),
+                           ast_sockaddr_stringify(&rtp->rtcp->them),
                            rtp->ssrc, rtp->themssrc, fraction, lost,
                            rtp->rxjitter,
                            rtp->rtcp->themrxlsr,
@@ -788,9 +885,9 @@ static int ast_rtcp_write_rr(const void *data)
 }
 
 /*! \brief Send RTCP sender's report */
-static int ast_rtcp_write_sr(const void *data)
+static int ast_rtcp_write_sr(struct ast_rtp_instance *instance)
 {
-       struct ast_rtp *rtp = (struct ast_rtp *)data;
+       struct ast_rtp *rtp = ast_rtp_instance_get_data(instance);
        int res;
        int len = 0;
        struct timeval now;
@@ -807,11 +904,10 @@ static int ast_rtcp_write_sr(const void *data)
        struct timeval dlsr;
        char bdata[512];
 
-       /* Commented condition is always not NULL if rtp->rtcp is not NULL */
-       if (!rtp || !rtp->rtcp/* || (&rtp->rtcp->them.sin_addr == 0)*/)
+       if (!rtp || !rtp->rtcp)
                return 0;
 
-       if (!rtp->rtcp->them.sin_addr.s_addr) {  /* This'll stop rtcp for this rtp session */
+       if (ast_sockaddr_isnull(&rtp->rtcp->them)) {  /* This'll stop rtcp for this rtp session */
                ast_verbose("RTCP SR transmission error, rtcp halted\n");
                AST_SCHED_DEL(rtp->sched, rtp->rtcp->schedid);
                return 0;
@@ -860,9 +956,11 @@ static int ast_rtcp_write_sr(const void *data)
        rtcpheader[(len/4)+2] = htonl(0x01 << 24);                    /* Empty for the moment */
        len += 12;
 
-       res = sendto(rtp->rtcp->s, (unsigned int *)rtcpheader, len, 0, (struct sockaddr *)&rtp->rtcp->them, sizeof(rtp->rtcp->them));
+       res = rtcp_sendto(instance, (unsigned int *)rtcpheader, len, 0, &rtp->rtcp->them);
        if (res < 0) {
-               ast_log(LOG_ERROR, "RTCP SR transmission error to %s:%d, rtcp halted %s\n",ast_inet_ntoa(rtp->rtcp->them.sin_addr), ntohs(rtp->rtcp->them.sin_port), strerror(errno));
+               ast_log(LOG_ERROR, "RTCP SR transmission error to %s, rtcp halted %s\n",
+                       ast_sockaddr_stringify(&rtp->rtcp->them),
+                       strerror(errno));
                AST_SCHED_DEL(rtp->sched, rtp->rtcp->schedid);
                return 0;
        }
@@ -874,7 +972,7 @@ static int ast_rtcp_write_sr(const void *data)
        rtp->rtcp->lastsrtxcount = rtp->txcount;
 
        if (rtcp_debug_test_addr(&rtp->rtcp->them)) {
-               ast_verbose("* Sent RTCP SR to %s:%d\n", ast_inet_ntoa(rtp->rtcp->them.sin_addr), ntohs(rtp->rtcp->them.sin_port));
+               ast_verbose("* Sent RTCP SR to %s\n", ast_sockaddr_stringify(&rtp->rtcp->them));
                ast_verbose("  Our SSRC: %u\n", rtp->ssrc);
                ast_verbose("  Sent(NTP): %u.%010u\n", (unsigned int)now.tv_sec, (unsigned int)now.tv_usec*4096);
                ast_verbose("  Sent(RTP): %u\n", rtp->lastts);
@@ -887,7 +985,7 @@ static int ast_rtcp_write_sr(const void *data)
                ast_verbose("  Their last SR: %u\n", rtp->rtcp->themrxlsr);
                ast_verbose("  DLSR: %4.4f (sec)\n\n", (double)(ntohl(rtcpheader[12])/65536.0));
        }
-       manager_event(EVENT_FLAG_REPORTING, "RTCPSent", "To %s:%d\r\n"
+       manager_event(EVENT_FLAG_REPORTING, "RTCPSent", "To %s\r\n"
                                            "OurSSRC: %u\r\n"
                                            "SentNTP: %u.%010u\r\n"
                                            "SentRTP: %u\r\n"
@@ -899,7 +997,7 @@ static int ast_rtcp_write_sr(const void *data)
                                            "IAJitter: %.4f\r\n"
                                            "TheirLastSR: %u\r\n"
                      "DLSR: %4.4f (sec)\r\n",
-                     ast_inet_ntoa(rtp->rtcp->them.sin_addr), ntohs(rtp->rtcp->them.sin_port),
+                     ast_sockaddr_stringify(&rtp->rtcp->them),
                      rtp->ssrc,
                      (unsigned int)now.tv_sec, (unsigned int)now.tv_usec*4096,
                      rtp->lastts,
@@ -918,16 +1016,17 @@ static int ast_rtcp_write_sr(const void *data)
  * RR is sent if we have not sent any rtp packets in the previous interval */
 static int ast_rtcp_write(const void *data)
 {
-       struct ast_rtp *rtp = (struct ast_rtp *)data;
+       struct ast_rtp_instance *instance = (struct ast_rtp_instance *) data;
+       struct ast_rtp *rtp = ast_rtp_instance_get_data(instance);
        int res;
 
        if (!rtp || !rtp->rtcp)
                return 0;
 
        if (rtp->txcount > rtp->rtcp->lastsrtxcount)
-               res = ast_rtcp_write_sr(data);
+               res = ast_rtcp_write_sr(instance);
        else
-               res = ast_rtcp_write_rr(data);
+               res = ast_rtcp_write_rr(instance);
 
        return res;
 }
@@ -937,7 +1036,12 @@ static int ast_rtp_raw_write(struct ast_rtp_instance *instance, struct ast_frame
        struct ast_rtp *rtp = ast_rtp_instance_get_data(instance);
        int pred, mark = 0;
        unsigned int ms = calc_txstamp(rtp, &frame->delivery);
-       struct sockaddr_in remote_address = { 0, };
+       struct ast_sockaddr remote_address = { {0,} };
+       int rate = rtp_get_rate(&frame->subclass.format) / 1000;
+
+       if (frame->subclass.format.id == AST_FORMAT_G722) {
+               frame->samples /= 2;
+       }
 
        if (rtp->sending_digit) {
                return 0;
@@ -947,7 +1051,7 @@ static int ast_rtp_raw_write(struct ast_rtp_instance *instance, struct ast_frame
                pred = rtp->lastts + frame->samples;
 
                /* Re-calculate last TS */
-               rtp->lastts = rtp->lastts + ms * 8;
+               rtp->lastts = rtp->lastts + ms * rate;
                if (ast_tvzero(frame->delivery)) {
                        /* If this isn't an absolute delivery time, Check if it is close to our prediction,
                           and if so, go with our prediction */
@@ -959,7 +1063,7 @@ static int ast_rtp_raw_write(struct ast_rtp_instance *instance, struct ast_frame
                        }
                }
        } else if (frame->frametype == AST_FRAME_VIDEO) {
-               mark = frame->subclass & 0x1;
+               mark = ast_format_get_video_mark(&frame->subclass.format);
                pred = rtp->lastovidtimestamp + frame->samples;
                /* Re-calculate last TS */
                rtp->lastts = rtp->lastts + ms * 90;
@@ -1001,13 +1105,13 @@ static int ast_rtp_raw_write(struct ast_rtp_instance *instance, struct ast_frame
        }
 
        if (ast_test_flag(frame, AST_FRFLAG_HAS_TIMING_INFO)) {
-               rtp->lastts = frame->ts * 8;
+               rtp->lastts = frame->ts * rate;
        }
 
        ast_rtp_instance_get_remote_address(instance, &remote_address);
 
        /* If we know the remote address construct a packet and send it out */
-       if (remote_address.sin_port && remote_address.sin_addr.s_addr) {
+       if (!ast_sockaddr_isnull(&remote_address)) {
                int hdrlen = 12, res;
                unsigned char *rtpheader = (unsigned char *)(frame->data.ptr - hdrlen);
 
@@ -1015,13 +1119,17 @@ static int ast_rtp_raw_write(struct ast_rtp_instance *instance, struct ast_frame
                put_unaligned_uint32(rtpheader + 4, htonl(rtp->lastts));
                put_unaligned_uint32(rtpheader + 8, htonl(rtp->ssrc));
 
-               if ((res = sendto(rtp->s, (void *)rtpheader, frame->datalen + hdrlen, 0, (struct sockaddr *)&remote_address, sizeof(remote_address))) < 0) {
+               if ((res = rtp_sendto(instance, (void *)rtpheader, frame->datalen + hdrlen, 0, &remote_address)) < 0) {
                        if (!ast_rtp_instance_get_prop(instance, AST_RTP_PROPERTY_NAT) || (ast_rtp_instance_get_prop(instance, AST_RTP_PROPERTY_NAT) && (ast_test_flag(rtp, FLAG_NAT_ACTIVE) == FLAG_NAT_ACTIVE))) {
-                               ast_debug(1, "RTP Transmission error of packet %d to %s:%d: %s\n", rtp->seqno, ast_inet_ntoa(remote_address.sin_addr), ntohs(remote_address.sin_port), strerror(errno));
+                               ast_debug(1, "RTP Transmission error of packet %d to %s: %s\n",
+                                         rtp->seqno,
+                                         ast_sockaddr_stringify(&remote_address),
+                                         strerror(errno));
                        } else if (((ast_test_flag(rtp, FLAG_NAT_ACTIVE) == FLAG_NAT_INACTIVE) || rtpdebug) && !ast_test_flag(rtp, FLAG_NAT_INACTIVE_NOWARN)) {
                                /* Only give this error message once if we are not RTP debugging */
-                               if (option_debug || rtpdebug)
-                                       ast_debug(0, "RTP NAT: Can't write RTP to private address %s:%d, waiting for other end to send audio...\n", ast_inet_ntoa(remote_address.sin_addr), ntohs(remote_address.sin_port));
+                               if (rtpdebug)
+                                       ast_debug(0, "RTP NAT: Can't write RTP to private address %s, waiting for other end to send audio...\n",
+                                                 ast_sockaddr_stringify(&remote_address));
                                ast_set_flag(rtp, FLAG_NAT_INACTIVE_NOWARN);
                        }
                } else {
@@ -1030,13 +1138,14 @@ static int ast_rtp_raw_write(struct ast_rtp_instance *instance, struct ast_frame
 
                        if (rtp->rtcp && rtp->rtcp->schedid < 1) {
                                ast_debug(1, "Starting RTCP transmission on RTP instance '%p'\n", instance);
-                               rtp->rtcp->schedid = ast_sched_add(rtp->sched, ast_rtcp_calc_interval(rtp), ast_rtcp_write, rtp);
+                               rtp->rtcp->schedid = ast_sched_add(rtp->sched, ast_rtcp_calc_interval(rtp), ast_rtcp_write, instance);
                        }
                }
 
                if (rtp_debug_test_addr(&remote_address)) {
-                       ast_verbose("Sent RTP packet to      %s:%u (type %-2.2d, seq %-6.6u, ts %-6.6u, len %-6.6u)\n",
-                                   ast_inet_ntoa(remote_address.sin_addr), ntohs(remote_address.sin_port), codec, rtp->seqno, rtp->lastts, res - hdrlen);
+                       ast_verbose("Sent RTP packet to      %s (type %-2.2d, seq %-6.6u, ts %-6.6u, len %-6.6u)\n",
+                                   ast_sockaddr_stringify(&remote_address),
+                                   codec, rtp->seqno, rtp->lastts, res - hdrlen);
                }
        }
 
@@ -1085,13 +1194,14 @@ static struct ast_frame *red_t140_to_red(struct rtp_red *red) {
 static int ast_rtp_write(struct ast_rtp_instance *instance, struct ast_frame *frame)
 {
        struct ast_rtp *rtp = ast_rtp_instance_get_data(instance);
-       struct sockaddr_in remote_address = { 0, };
-       int codec, subclass;
+       struct ast_sockaddr remote_address = { {0,} };
+       struct ast_format subclass;
+       int codec;
 
        ast_rtp_instance_get_remote_address(instance, &remote_address);
 
        /* If we don't actually know the remote address don't even bother doing anything */
-       if (!remote_address.sin_addr.s_addr) {
+       if (ast_sockaddr_isnull(&remote_address)) {
                ast_debug(1, "No remote address on RTP instance '%p' so dropping frame\n", instance);
                return 0;
        }
@@ -1116,19 +1226,17 @@ static int ast_rtp_write(struct ast_rtp_instance *instance, struct ast_frame *fr
        }
 
        /* Grab the subclass and look up the payload we are going to use */
-       subclass = frame->subclass;
-       if (frame->frametype == AST_FRAME_VIDEO) {
-               subclass &= ~0x1;
-       }
-       if ((codec = ast_rtp_codecs_payload_code(ast_rtp_instance_get_codecs(instance), 1, subclass)) < 0) {
-               ast_log(LOG_WARNING, "Don't know how to send format %s packets with RTP\n", ast_getformatname(frame->subclass));
+       ast_format_copy(&subclass, &frame->subclass.format);
+       if ((codec = ast_rtp_codecs_payload_code(ast_rtp_instance_get_codecs(instance), 1, &subclass, 0)) < 0) {
+               ast_log(LOG_WARNING, "Don't know how to send format %s packets with RTP\n", ast_getformatname(&frame->subclass.format));
                return -1;
        }
 
        /* Oh dear, if the format changed we will have to set up a new smoother */
-       if (rtp->lasttxformat != subclass) {
-               ast_debug(1, "Ooh, format changed from %s to %s\n", ast_getformatname(rtp->lasttxformat), ast_getformatname(subclass));
+       if (ast_format_cmp(&rtp->lasttxformat, &subclass) == AST_FORMAT_CMP_NOT_EQUAL) {
+               ast_debug(1, "Ooh, format changed from %s to %s\n", ast_getformatname(&rtp->lasttxformat), ast_getformatname(&subclass));
                rtp->lasttxformat = subclass;
+               ast_format_copy(&rtp->lasttxformat, &subclass);
                if (rtp->smoother) {
                        ast_smoother_free(rtp->smoother);
                        rtp->smoother = NULL;
@@ -1137,26 +1245,30 @@ 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) {
-               struct ast_format_list fmt = ast_codec_pref_getsize(&ast_rtp_instance_get_codecs(instance)->pref, subclass);
+               struct ast_format_list fmt = ast_codec_pref_getsize(&ast_rtp_instance_get_codecs(instance)->pref, &subclass);
 
-               switch (subclass) {
+               switch (subclass.id) {
                case AST_FORMAT_SPEEX:
+               case AST_FORMAT_SPEEX16:
+               case AST_FORMAT_SPEEX32:
+               case AST_FORMAT_SILK:
                case AST_FORMAT_G723_1:
                case AST_FORMAT_SIREN7:
                case AST_FORMAT_SIREN14:
+               case AST_FORMAT_G719:
                        /* these are all frame-based codecs and cannot be safely run through
                           a smoother */
                        break;
                default:
                        if (fmt.inc_ms) {
                                if (!(rtp->smoother = ast_smoother_new((fmt.cur_ms * fmt.fr_len) / fmt.inc_ms))) {
-                                       ast_log(LOG_WARNING, "Unable to create smoother: format %d ms: %d len: %d\n", subclass, fmt.cur_ms, ((fmt.cur_ms * fmt.fr_len) / fmt.inc_ms));
+                                       ast_log(LOG_WARNING, "Unable to create smoother: format %s ms: %d len: %d\n", ast_getformatname(&subclass), fmt.cur_ms, ((fmt.cur_ms * fmt.fr_len) / fmt.inc_ms));
                                        return -1;
                                }
                                if (fmt.flags) {
                                        ast_smoother_set_flags(rtp->smoother, fmt.flags);
                                }
-                               ast_debug(1, "Created smoother: format: %d ms: %d len: %d\n", subclass, fmt.cur_ms, ((fmt.cur_ms * fmt.fr_len) / fmt.inc_ms));
+                               ast_debug(1, "Created smoother: format: %s ms: %d len: %d\n", ast_getformatname(&subclass), fmt.cur_ms, ((fmt.cur_ms * fmt.fr_len) / fmt.inc_ms));
                        }
                }
        }
@@ -1172,11 +1284,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)) {
-                       if (f->subclass == AST_FORMAT_G722) {
-                               f->samples /= 2;
-                       }
-
-                       ast_rtp_raw_write(instance, f, codec);
+                               ast_rtp_raw_write(instance, f, codec);
                }
        } else {
                int hdrlen = 12;
@@ -1202,11 +1310,13 @@ static int ast_rtp_write(struct ast_rtp_instance *instance, struct ast_frame *fr
 static void calc_rxstamp(struct timeval *tv, struct ast_rtp *rtp, unsigned int timestamp, int mark)
 {
        struct timeval now;
+       struct timeval tmp;
        double transit;
        double current_time;
        double d;
        double dtv;
        double prog;
+       int rate = rtp_get_rate(&rtp->f.subclass.format);
 
        double normdev_rxjitter_current;
        if ((!rtp->rxcore.tv_sec && !rtp->rxcore.tv_usec) || mark) {
@@ -1214,26 +1324,18 @@ static void calc_rxstamp(struct timeval *tv, struct ast_rtp *rtp, unsigned int t
                rtp->drxcore = (double) rtp->rxcore.tv_sec + (double) rtp->rxcore.tv_usec / 1000000;
                /* map timestamp to a real time */
                rtp->seedrxts = timestamp; /* Their RTP timestamp started with this */
-               rtp->rxcore.tv_sec -= timestamp / 8000;
-               rtp->rxcore.tv_usec -= (timestamp % 8000) * 125;
+               tmp = ast_samp2tv(timestamp, rate);
+               rtp->rxcore = ast_tvsub(rtp->rxcore, tmp);
                /* Round to 0.1ms for nice, pretty timestamps */
                rtp->rxcore.tv_usec -= rtp->rxcore.tv_usec % 100;
-               if (rtp->rxcore.tv_usec < 0) {
-                       /* Adjust appropriately if necessary */
-                       rtp->rxcore.tv_usec += 1000000;
-                       rtp->rxcore.tv_sec -= 1;
-               }
        }
 
        gettimeofday(&now,NULL);
        /* rxcore is the mapping between the RTP timestamp and _our_ real time from gettimeofday() */
-       tv->tv_sec = rtp->rxcore.tv_sec + timestamp / 8000;
-       tv->tv_usec = rtp->rxcore.tv_usec + (timestamp % 8000) * 125;
-       if (tv->tv_usec >= 1000000) {
-               tv->tv_usec -= 1000000;
-               tv->tv_sec += 1;
-       }
-       prog = (double)((timestamp-rtp->seedrxts)/8000.);
+       tmp = ast_samp2tv(timestamp, rate);
+       *tv = ast_tvadd(rtp->rxcore, tmp);
+
+       prog = (double)((timestamp-rtp->seedrxts)/(float)(rate));
        dtv = (double)rtp->drxcore + (double)(prog);
        current_time = (double)now.tv_sec + (double)now.tv_usec/1000000;
        transit = current_time - dtv;
@@ -1259,39 +1361,42 @@ static void calc_rxstamp(struct timeval *tv, struct ast_rtp *rtp, unsigned int t
        }
 }
 
-static struct ast_frame *send_dtmf(struct ast_rtp_instance *instance, enum ast_frame_type type, int compensate)
+static struct ast_frame *create_dtmf_frame(struct ast_rtp_instance *instance, enum ast_frame_type type, int compensate)
 {
        struct ast_rtp *rtp = ast_rtp_instance_get_data(instance);
-       struct sockaddr_in remote_address = { 0, };
+       struct ast_sockaddr remote_address = { {0,} };
 
        ast_rtp_instance_get_remote_address(instance, &remote_address);
 
        if (((compensate && type == AST_FRAME_DTMF_END) || (type == AST_FRAME_DTMF_BEGIN)) && ast_tvcmp(ast_tvnow(), rtp->dtmfmute) < 0) {
-               ast_debug(1, "Ignore potential DTMF echo from '%s'\n", ast_inet_ntoa(remote_address.sin_addr));
+               ast_debug(1, "Ignore potential DTMF echo from '%s'\n",
+                         ast_sockaddr_stringify(&remote_address));
                rtp->resp = 0;
                rtp->dtmfsamples = 0;
                return &ast_null_frame;
        }
-       ast_debug(1, "Sending dtmf: %d (%c), at %s\n", rtp->resp, rtp->resp, ast_inet_ntoa(remote_address.sin_addr));
+       ast_debug(1, "Sending dtmf: %d (%c), at %s\n", rtp->resp, rtp->resp,
+                 ast_sockaddr_stringify(&remote_address));
        if (rtp->resp == 'X') {
                rtp->f.frametype = AST_FRAME_CONTROL;
-               rtp->f.subclass = AST_CONTROL_FLASH;
+               rtp->f.subclass.integer = AST_CONTROL_FLASH;
        } else {
                rtp->f.frametype = type;
-               rtp->f.subclass = rtp->resp;
+               rtp->f.subclass.integer = rtp->resp;
        }
        rtp->f.datalen = 0;
        rtp->f.samples = 0;
        rtp->f.mallocd = 0;
        rtp->f.src = "RTP";
+       AST_LIST_NEXT(&rtp->f, frame_list) = NULL;
 
        return &rtp->f;
 }
 
-static struct ast_frame *process_dtmf_rfc2833(struct ast_rtp_instance *instance, unsigned char *data, int len, unsigned int seqno, unsigned int timestamp, struct sockaddr_in *sin, int payloadtype, int mark)
+static void process_dtmf_rfc2833(struct ast_rtp_instance *instance, unsigned char *data, int len, unsigned int seqno, unsigned int timestamp, struct ast_sockaddr *addr, int payloadtype, int mark, struct frame_list *frames)
 {
        struct ast_rtp *rtp = ast_rtp_instance_get_data(instance);
-       struct sockaddr_in remote_address = { 0, };
+       struct ast_sockaddr remote_address = { {0,} };
        unsigned int event, event_end, samples;
        char resp = 0;
        struct ast_frame *f = NULL;
@@ -1308,12 +1413,13 @@ static struct ast_frame *process_dtmf_rfc2833(struct ast_rtp_instance *instance,
        samples &= 0xFFFF;
 
        if (rtp_debug_test_addr(&remote_address)) {
-               ast_verbose("Got  RTP RFC2833 from   %s:%u (type %-2.2d, seq %-6.6u, ts %-6.6u, len %-6.6u, mark %d, event %08x, end %d, duration %-5.5d) \n", ast_inet_ntoa(remote_address.sin_addr),
-                           ntohs(remote_address.sin_port), payloadtype, seqno, timestamp, len, (mark?1:0), event, ((event_end & 0x80)?1:0), samples);
+               ast_verbose("Got  RTP RFC2833 from   %s (type %-2.2d, seq %-6.6u, ts %-6.6u, len %-6.6u, mark %d, event %08x, end %d, duration %-5.5d) \n",
+                           ast_sockaddr_stringify(&remote_address),
+                           payloadtype, seqno, timestamp, len, (mark?1:0), event, ((event_end & 0x80)?1:0), samples);
        }
 
        /* Print out debug if turned on */
-       if (rtpdebug || option_debug > 2)
+       if (rtpdebug)
                ast_debug(0, "- RTP 2833 Event: %08x (len = %d)\n", event, len);
 
        /* Figure out what digit was pressed */
@@ -1329,17 +1435,18 @@ static struct ast_frame *process_dtmf_rfc2833(struct ast_rtp_instance *instance,
                resp = 'X';
        } else {
                /* Not a supported event */
-               ast_log(LOG_DEBUG, "Ignoring RTP 2833 Event: %08x. Not a DTMF Digit.\n", event);
-               return &ast_null_frame;
+               ast_debug(1, "Ignoring RTP 2833 Event: %08x. Not a DTMF Digit.\n", event);
+               return;
        }
 
        if (ast_rtp_instance_get_prop(instance, AST_RTP_PROPERTY_DTMF_COMPENSATE)) {
                if ((rtp->lastevent != timestamp) || (rtp->resp && rtp->resp != resp)) {
                        rtp->resp = resp;
                        rtp->dtmf_timeout = 0;
-                       f = send_dtmf(instance, AST_FRAME_DTMF_END, ast_rtp_instance_get_prop(instance, AST_RTP_PROPERTY_DTMF_COMPENSATE));
+                       f = ast_frdup(create_dtmf_frame(instance, AST_FRAME_DTMF_END, ast_rtp_instance_get_prop(instance, AST_RTP_PROPERTY_DTMF_COMPENSATE)));
                        f->len = 0;
                        rtp->lastevent = timestamp;
+                       AST_LIST_INSERT_TAIL(frames, f, frame_list);
                }
        } else {
                /*  The duration parameter measures the complete
@@ -1355,24 +1462,38 @@ static struct ast_frame *process_dtmf_rfc2833(struct ast_rtp_instance *instance,
                }
                new_duration = (new_duration & ~0xFFFF) | samples;
 
+               /* The second portion of this check is to not mistakenly
+                * stop accepting DTMF if the seqno rolls over beyond
+                * 65535.
+                */
+               if (rtp->lastevent > seqno && rtp->lastevent - seqno < 50) {
+                       /* Out of order frame. Processing this can cause us to
+                        * improperly duplicate incoming DTMF, so just drop
+                        * this.
+                        */
+                       return;
+               }
+
                if (event_end & 0x80) {
                        /* End event */
                        if ((rtp->lastevent != seqno) && rtp->resp) {
                                rtp->dtmf_duration = new_duration;
-                               f = send_dtmf(instance, AST_FRAME_DTMF_END, 0);
-                               f->len = ast_tvdiff_ms(ast_samp2tv(rtp->dtmf_duration, 8000), ast_tv(0, 0));
+                               f = ast_frdup(create_dtmf_frame(instance, AST_FRAME_DTMF_END, 0));
+                               f->len = ast_tvdiff_ms(ast_samp2tv(rtp->dtmf_duration, rtp_get_rate(&f->subclass.format)), ast_tv(0, 0));
                                rtp->resp = 0;
                                rtp->dtmf_duration = rtp->dtmf_timeout = 0;
+                               AST_LIST_INSERT_TAIL(frames, f, frame_list);
                        }
                } else {
                        /* Begin/continuation */
 
                        if (rtp->resp && rtp->resp != resp) {
                                /* Another digit already began. End it */
-                               f = send_dtmf(instance, AST_FRAME_DTMF_END, 0);
-                               f->len = ast_tvdiff_ms(ast_samp2tv(rtp->dtmf_duration, 8000), ast_tv(0, 0));
+                               f = ast_frdup(create_dtmf_frame(instance, AST_FRAME_DTMF_END, 0));
+                               f->len = ast_tvdiff_ms(ast_samp2tv(rtp->dtmf_duration, rtp_get_rate(&f->subclass.format)), ast_tv(0, 0));
                                rtp->resp = 0;
                                rtp->dtmf_duration = rtp->dtmf_timeout = 0;
+                               AST_LIST_INSERT_TAIL(frames, f, frame_list);
                        }
 
                        if (rtp->resp) {
@@ -1381,8 +1502,9 @@ static struct ast_frame *process_dtmf_rfc2833(struct ast_rtp_instance *instance,
                        } else {
                                /* New digit began */
                                rtp->resp = resp;
-                               f = send_dtmf(instance, AST_FRAME_DTMF_BEGIN, 0);
+                               f = ast_frdup(create_dtmf_frame(instance, AST_FRAME_DTMF_BEGIN, 0));
                                rtp->dtmf_duration = samples;
+                               AST_LIST_INSERT_TAIL(frames, f, frame_list);
                        }
 
                        rtp->dtmf_timeout = timestamp + rtp->dtmf_duration + dtmftimeout;
@@ -1393,10 +1515,10 @@ static struct ast_frame *process_dtmf_rfc2833(struct ast_rtp_instance *instance,
 
        rtp->dtmfsamples = samples;
 
-       return f;
+       return;
 }
 
-static struct ast_frame *process_dtmf_cisco(struct ast_rtp_instance *instance, unsigned char *data, int len, unsigned int seqno, unsigned int timestamp, struct sockaddr_in *sin, int payloadtype, int mark)
+static struct ast_frame *process_dtmf_cisco(struct ast_rtp_instance *instance, unsigned char *data, int len, unsigned int seqno, unsigned int timestamp, struct ast_sockaddr *addr, int payloadtype, int mark)
 {
        struct ast_rtp *rtp = ast_rtp_instance_get_data(instance);
        unsigned int event, flags, power;
@@ -1443,7 +1565,7 @@ static struct ast_frame *process_dtmf_cisco(struct ast_rtp_instance *instance, u
        power = data[2];
        event = data[3] & 0x1f;
 
-       if (option_debug > 2 || rtpdebug)
+       if (rtpdebug)
                ast_debug(0, "Cisco DTMF Digit: %02x (len=%d, seq=%d, flags=%02x, power=%d, history count=%d)\n", event, len, seq, flags, power, (len - 4) / 2);
        if (event < 10) {
                resp = '0' + event;
@@ -1460,21 +1582,22 @@ static struct ast_frame *process_dtmf_cisco(struct ast_rtp_instance *instance, u
                rtp->resp = resp;
                /* Why we should care on DTMF compensation at reception? */
                if (ast_rtp_instance_get_prop(instance, AST_RTP_PROPERTY_DTMF_COMPENSATE)) {
-                       f = send_dtmf(instance, AST_FRAME_DTMF_BEGIN, 0);
+                       f = create_dtmf_frame(instance, AST_FRAME_DTMF_BEGIN, 0);
                        rtp->dtmfsamples = 0;
                }
        } else if ((rtp->resp == resp) && !power) {
-               f = send_dtmf(instance, AST_FRAME_DTMF_END, ast_rtp_instance_get_prop(instance, AST_RTP_PROPERTY_DTMF_COMPENSATE));
-               f->samples = rtp->dtmfsamples * 8;
+               f = create_dtmf_frame(instance, AST_FRAME_DTMF_END, ast_rtp_instance_get_prop(instance, AST_RTP_PROPERTY_DTMF_COMPENSATE));
+               f->samples = rtp->dtmfsamples * (rtp->lastrxformat.id ? (rtp_get_rate(&rtp->lastrxformat) / 1000) : 8);
                rtp->resp = 0;
        } else if (rtp->resp == resp)
-               rtp->dtmfsamples += 20 * 8;
+               rtp->dtmfsamples += 20 * (rtp->lastrxformat.id ? (rtp_get_rate(&rtp->lastrxformat) / 1000) : 8);
+
        rtp->dtmf_timeout = 0;
 
        return f;
 }
 
-static struct ast_frame *process_cn_rfc3389(struct ast_rtp_instance *instance, unsigned char *data, int len, unsigned int seqno, unsigned int timestamp, struct sockaddr_in *sin, int payloadtype, int mark)
+static struct ast_frame *process_cn_rfc3389(struct ast_rtp_instance *instance, unsigned char *data, int len, unsigned int seqno, unsigned int timestamp, struct ast_sockaddr *addr, int payloadtype, int mark)
 {
        struct ast_rtp *rtp = ast_rtp_instance_get_data(instance);
 
@@ -1482,15 +1605,15 @@ static struct ast_frame *process_cn_rfc3389(struct ast_rtp_instance *instance, u
           totally help us out becuase we don't have an engine to keep it going and we are not
           guaranteed to have it every 20ms or anything */
        if (rtpdebug)
-               ast_debug(0, "- RTP 3389 Comfort noise event: Level %d (len = %d)\n", rtp->lastrxformat, len);
+               ast_debug(0, "- RTP 3389 Comfort noise event: Level %d (len = %d)\n", (int) rtp->lastrxformat.id, len);
 
        if (ast_test_flag(rtp, FLAG_3389_WARNING)) {
-               struct sockaddr_in remote_address = { 0, };
+               struct ast_sockaddr remote_address = { {0,} };
 
                ast_rtp_instance_get_remote_address(instance, &remote_address);
 
-               ast_log(LOG_NOTICE, "Comfort noise support incomplete in Asterisk (RFC 3389). Please turn off on client if possible. Client IP: %s\n",
-                       ast_inet_ntoa(remote_address.sin_addr));
+               ast_log(LOG_NOTICE, "Comfort noise support incomplete in Asterisk (RFC 3389). Please turn off on client if possible. Client address: %s\n",
+                       ast_sockaddr_stringify(&remote_address));
                ast_set_flag(rtp, FLAG_3389_WARNING);
        }
 
@@ -1508,8 +1631,7 @@ static struct ast_frame *process_cn_rfc3389(struct ast_rtp_instance *instance, u
                rtp->f.datalen = 0;
        }
        rtp->f.frametype = AST_FRAME_CNG;
-       rtp->f.subclass = data[0] & 0x7f;
-       rtp->f.datalen = len - 1;
+       rtp->f.subclass.integer = data[0] & 0x7f;
        rtp->f.samples = 0;
        rtp->f.delivery.tv_usec = rtp->f.delivery.tv_sec = 0;
 
@@ -1519,15 +1641,16 @@ static struct ast_frame *process_cn_rfc3389(struct ast_rtp_instance *instance, u
 static struct ast_frame *ast_rtcp_read(struct ast_rtp_instance *instance)
 {
        struct ast_rtp *rtp = ast_rtp_instance_get_data(instance);
-       struct sockaddr_in sin;
-       socklen_t len = sizeof(sin);
+       struct ast_sockaddr addr;
        unsigned int rtcpdata[8192 + AST_FRIENDLY_OFFSET];
        unsigned int *rtcpheader = (unsigned int *)(rtcpdata + AST_FRIENDLY_OFFSET);
        int res, packetwords, position = 0;
        struct ast_frame *f = &ast_null_frame;
 
        /* Read in RTCP data from the socket */
-       if ((res = recvfrom(rtp->rtcp->s, rtcpdata + AST_FRIENDLY_OFFSET, sizeof(rtcpdata) - sizeof(unsigned int) * AST_FRIENDLY_OFFSET, 0, (struct sockaddr *)&sin, &len)) < 0) {
+       if ((res = rtcp_recvfrom(instance, rtcpdata + AST_FRIENDLY_OFFSET,
+                               sizeof(rtcpdata) - sizeof(unsigned int) * AST_FRIENDLY_OFFSET,
+                               0, &addr)) < 0) {
                ast_assert(errno != EBADF);
                if (errno != EAGAIN) {
                        ast_log(LOG_WARNING, "RTCP Read error: %s.  Hanging up.\n", strerror(errno));
@@ -1540,11 +1663,11 @@ static struct ast_frame *ast_rtcp_read(struct ast_rtp_instance *instance)
 
        if (ast_rtp_instance_get_prop(instance, AST_RTP_PROPERTY_NAT)) {
                /* Send to whoever sent to us */
-               if ((rtp->rtcp->them.sin_addr.s_addr != sin.sin_addr.s_addr) ||
-                   (rtp->rtcp->them.sin_port != sin.sin_port)) {
-                       memcpy(&rtp->rtcp->them, &sin, sizeof(rtp->rtcp->them));
-                       if (option_debug || rtpdebug)
-                               ast_debug(0, "RTCP NAT: Got RTCP from other end. Now sending to address %s:%d\n", ast_inet_ntoa(rtp->rtcp->them.sin_addr), ntohs(rtp->rtcp->them.sin_port));
+               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));
                }
        }
 
@@ -1564,19 +1687,24 @@ static struct ast_frame *ast_rtcp_read(struct ast_rtp_instance *instance)
                length &= 0xffff;
 
                if ((i + length) > packetwords) {
-                       if (option_debug || rtpdebug)
-                               ast_log(LOG_DEBUG, "RTCP Read too short\n");
+                       if (rtpdebug)
+                               ast_debug(1, "RTCP Read too short\n");
                        return &ast_null_frame;
                }
 
-               if (rtcp_debug_test_addr(&sin)) {
-                       ast_verbose("\n\nGot RTCP from %s:%d\n", ast_inet_ntoa(sin.sin_addr), ntohs(sin.sin_port));
+               if (rtcp_debug_test_addr(&addr)) {
+                       ast_verbose("\n\nGot RTCP from %s\n",
+                                   ast_sockaddr_stringify(&addr));
                        ast_verbose("PT: %d(%s)\n", pt, (pt == 200) ? "Sender Report" : (pt == 201) ? "Receiver Report" : (pt == 192) ? "H.261 FUR" : "Unknown");
                        ast_verbose("Reception reports: %d\n", rc);
                        ast_verbose("SSRC of sender: %u\n", rtcpheader[i + 1]);
                }
 
                i += 2; /* Advance past header and ssrc */
+               if (rc == 0 && pt == RTCP_PT_RR) {      /* We're receiving a receiver report with no reports, which is ok */
+                       position += (length + 1);
+                       continue;
+               }
 
                switch (pt) {
                case RTCP_PT_SR:
@@ -1585,7 +1713,7 @@ static struct ast_frame *ast_rtcp_read(struct ast_rtp_instance *instance)
                        rtp->rtcp->soc = ntohl(rtcpheader[i + 4]);
                        rtp->rtcp->themrxlsr = ((ntohl(rtcpheader[i]) & 0x0000ffff) << 16) | ((ntohl(rtcpheader[i + 1]) & 0xffff0000) >> 16); /* Going to LSR in RR*/
 
-                       if (rtcp_debug_test_addr(&sin)) {
+                       if (rtcp_debug_test_addr(&addr)) {
                                ast_verbose("NTP timestamp: %lu.%010lu\n", (unsigned long) ntohl(rtcpheader[i]), (unsigned long) ntohl(rtcpheader[i + 1]) * 4096);
                                ast_verbose("RTP timestamp: %lu\n", (unsigned long) ntohl(rtcpheader[i + 2]));
                                ast_verbose("SPC: %lu\tSOC: %lu\n", (unsigned long) ntohl(rtcpheader[i + 3]), (unsigned long) ntohl(rtcpheader[i + 4]));
@@ -1635,7 +1763,7 @@ static struct ast_frame *ast_rtcp_read(struct ast_rtp_instance *instance)
                                        rtp->rtcp->normdevrtt = normdevrtt_current;
 
                                        rtp->rtcp->rtt_count++;
-                               } else if (rtcp_debug_test_addr(&sin)) {
+                               } else if (rtcp_debug_test_addr(&addr)) {
                                        ast_verbose("Internal RTCP NTP clock skew detected: "
                                                           "lsr=%u, now=%u, dlsr=%u (%d:%03dms), "
                                                    "diff=%d\n",
@@ -1684,7 +1812,7 @@ static struct ast_frame *ast_rtcp_read(struct ast_rtp_instance *instance)
 
                        rtp->rtcp->reported_jitter_count++;
 
-                       if (rtcp_debug_test_addr(&sin)) {
+                       if (rtcp_debug_test_addr(&addr)) {
                                ast_verbose("  Fraction lost: %ld\n", (((long) ntohl(rtcpheader[i + 1]) & 0xff000000) >> 24));
                                ast_verbose("  Packets lost so far: %d\n", rtp->rtcp->reported_lost);
                                ast_verbose("  Highest sequence number: %ld\n", (long) (ntohl(rtcpheader[i + 2]) & 0xffff));
@@ -1696,7 +1824,7 @@ static struct ast_frame *ast_rtcp_read(struct ast_rtp_instance *instance)
                                        ast_verbose("  RTT: %lu(sec)\n", (unsigned long) rtt);
                        }
                        if (rtt) {
-                               manager_event(EVENT_FLAG_REPORTING, "RTCPReceived", "From %s:%d\r\n"
+                               manager_event(EVENT_FLAG_REPORTING, "RTCPReceived", "From %s\r\n"
                                                                    "PT: %d(%s)\r\n"
                                                                    "ReceptionReports: %d\r\n"
                                                                    "SenderSSRC: %u\r\n"
@@ -1708,7 +1836,7 @@ static struct ast_frame *ast_rtcp_read(struct ast_rtp_instance *instance)
                                                                    "LastSR: %lu.%010lu\r\n"
                                                                    "DLSR: %4.4f(sec)\r\n"
                                              "RTT: %llu(sec)\r\n",
-                                             ast_inet_ntoa(sin.sin_addr), ntohs(sin.sin_port),
+                                             ast_sockaddr_stringify(&addr),
                                              pt, (pt == 200) ? "Sender Report" : (pt == 201) ? "Receiver Report" : (pt == 192) ? "H.261 FUR" : "Unknown",
                                              rc,
                                              rtcpheader[i + 1],
@@ -1721,7 +1849,7 @@ static struct ast_frame *ast_rtcp_read(struct ast_rtp_instance *instance)
                                              ntohl(rtcpheader[i + 5])/65536.0,
                                              (unsigned long long)rtt);
                        } else {
-                               manager_event(EVENT_FLAG_REPORTING, "RTCPReceived", "From %s:%d\r\n"
+                               manager_event(EVENT_FLAG_REPORTING, "RTCPReceived", "From %s\r\n"
                                                                    "PT: %d(%s)\r\n"
                                                                    "ReceptionReports: %d\r\n"
                                                                    "SenderSSRC: %u\r\n"
@@ -1732,7 +1860,7 @@ static struct ast_frame *ast_rtcp_read(struct ast_rtp_instance *instance)
                                                                    "IAJitter: %u\r\n"
                                                                    "LastSR: %lu.%010lu\r\n"
                                              "DLSR: %4.4f(sec)\r\n",
-                                             ast_inet_ntoa(sin.sin_addr), ntohs(sin.sin_port),
+                                             ast_sockaddr_stringify(&addr),
                                              pt, (pt == 200) ? "Sender Report" : (pt == 201) ? "Receiver Report" : (pt == 192) ? "H.261 FUR" : "Unknown",
                                              rc,
                                              rtcpheader[i + 1],
@@ -1747,10 +1875,10 @@ static struct ast_frame *ast_rtcp_read(struct ast_rtp_instance *instance)
                        }
                        break;
                case RTCP_PT_FUR:
-                       if (rtcp_debug_test_addr(&sin))
+                       if (rtcp_debug_test_addr(&addr))
                                ast_verbose("Received an RTCP Fast Update Request\n");
                        rtp->f.frametype = AST_FRAME_CONTROL;
-                       rtp->f.subclass = AST_CONTROL_VIDUPDATE;
+                       rtp->f.subclass.integer = AST_CONTROL_VIDUPDATE;
                        rtp->f.datalen = 0;
                        rtp->f.samples = 0;
                        rtp->f.mallocd = 0;
@@ -1758,15 +1886,18 @@ 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(&sin))
-                               ast_verbose("Received an SDES from %s:%d\n", ast_inet_ntoa(rtp->rtcp->them.sin_addr), ntohs(rtp->rtcp->them.sin_port));
+                       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(&sin))
-                               ast_verbose("Received a BYE from %s:%d\n", ast_inet_ntoa(rtp->rtcp->them.sin_addr), ntohs(rtp->rtcp->them.sin_port));
+                       if (rtcp_debug_test_addr(&addr))
+                               ast_verbose("Received a BYE from %s\n",
+                                           ast_sockaddr_stringify(&rtp->rtcp->them));
                        break;
                default:
-                       ast_debug(1, "Unknown RTCP packet (pt=%d) received from %s:%d\n", pt, ast_inet_ntoa(rtp->rtcp->them.sin_addr), ntohs(rtp->rtcp->them.sin_port));
+                       ast_debug(1, "Unknown RTCP packet (pt=%d) received from %s\n",
+                                 pt, ast_sockaddr_stringify(&rtp->rtcp->them));
                        break;
                }
                position += (length + 1);
@@ -1784,7 +1915,7 @@ static int bridge_p2p_rtp_write(struct ast_rtp_instance *instance, unsigned int
        int res = 0, payload = 0, bridged_payload = 0, mark;
        struct ast_rtp_payload_type payload_type;
        int reconstruct = ntohl(rtpheader[0]);
-       struct sockaddr_in remote_address = { 0, };
+       struct ast_sockaddr remote_address = { {0,} };
 
        /* Get fields from packet */
        payload = (reconstruct & 0x7f0000) >> 16;
@@ -1794,10 +1925,11 @@ static int bridge_p2p_rtp_write(struct ast_rtp_instance *instance, unsigned int
        payload_type = ast_rtp_codecs_payload_lookup(ast_rtp_instance_get_codecs(instance), payload);
 
        /* Otherwise adjust bridged payload to match */
-       bridged_payload = ast_rtp_codecs_payload_code(ast_rtp_instance_get_codecs(instance1), payload_type.asterisk_format, payload_type.code);
+       bridged_payload = ast_rtp_codecs_payload_code(ast_rtp_instance_get_codecs(instance1), payload_type.asterisk_format, &payload_type.format, payload_type.rtp_code);
 
        /* If the payload coming in is not one of the negotiated ones then send it to the core, this will cause formats to change and the bridge to break */
-       if (!(ast_rtp_instance_get_codecs(instance1)->payloads[bridged_payload].code)) {
+       if (!(ast_rtp_instance_get_codecs(instance1)->payloads[bridged_payload].rtp_code) &&
+       !(ast_rtp_instance_get_codecs(instance1)->payloads[bridged_payload].asterisk_format)) {
                return -1;
        }
 
@@ -1815,19 +1947,33 @@ static int bridge_p2p_rtp_write(struct ast_rtp_instance *instance, unsigned int
 
        ast_rtp_instance_get_remote_address(instance1, &remote_address);
 
+       if (ast_sockaddr_isnull(&remote_address)) {
+               ast_debug(1, "Remote address is null, most likely RTP has been stopped\n");
+               return 0;
+       }
+
        /* Send the packet back out */
-       res = sendto(bridged->s, (void *)rtpheader, len, 0, (struct sockaddr *)&remote_address, sizeof(remote_address));
+       res = rtp_sendto(instance1, (void *)rtpheader, len, 0, &remote_address);
        if (res < 0) {
                if (!ast_rtp_instance_get_prop(instance1, AST_RTP_PROPERTY_NAT) || (ast_rtp_instance_get_prop(instance1, AST_RTP_PROPERTY_NAT) && (ast_test_flag(bridged, FLAG_NAT_ACTIVE) == FLAG_NAT_ACTIVE))) {
-                       ast_debug(1, "RTP Transmission error of packet to %s:%d: %s\n", ast_inet_ntoa(remote_address.sin_addr), ntohs(remote_address.sin_port), strerror(errno));
+                       ast_log(LOG_WARNING,
+                               "RTP Transmission error of packet to %s: %s\n",
+                               ast_sockaddr_stringify(&remote_address),
+                               strerror(errno));
                } else if (((ast_test_flag(bridged, FLAG_NAT_ACTIVE) == FLAG_NAT_INACTIVE) || rtpdebug) && !ast_test_flag(bridged, FLAG_NAT_INACTIVE_NOWARN)) {
                        if (option_debug || rtpdebug)
-                               ast_debug(0, "RTP NAT: Can't write RTP to private address %s:%d, waiting for other end to send audio...\n", ast_inet_ntoa(remote_address.sin_addr), ntohs(remote_address.sin_port));
+                               ast_log(LOG_WARNING,
+                                       "RTP NAT: Can't write RTP to private "
+                                       "address %s, waiting for other end to "
+                                       "send audio...\n",
+                                       ast_sockaddr_stringify(&remote_address));
                        ast_set_flag(bridged, FLAG_NAT_INACTIVE_NOWARN);
                }
                return 0;
        } else if (rtp_debug_test_addr(&remote_address)) {
-               ast_verbose("Sent RTP P2P packet to %s:%u (type %-2.2d, len %-6.6u)\n", ast_inet_ntoa(remote_address.sin_addr), ntohs(remote_address.sin_port), bridged_payload, len - hdrlen);
+               ast_verbose("Sent RTP P2P packet to %s (type %-2.2d, len %-6.6u)\n",
+                           ast_sockaddr_stringify(&remote_address),
+                           bridged_payload, len - hdrlen);
        }
 
        return 0;
@@ -1836,12 +1982,12 @@ static int bridge_p2p_rtp_write(struct ast_rtp_instance *instance, unsigned int
 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 sockaddr_in sin;
-       socklen_t len = sizeof(sin);
+       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;
        struct ast_rtp_payload_type payload;
-       struct sockaddr_in remote_address = { 0, };
+       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) {
@@ -1857,7 +2003,9 @@ static struct ast_frame *ast_rtp_read(struct ast_rtp_instance *instance, int rtc
        }
 
        /* Actually read in the data from the socket */
-       if ((res = recvfrom(rtp->s, rtp->rawdata + AST_FRIENDLY_OFFSET, sizeof(rtp->rawdata) - AST_FRIENDLY_OFFSET, 0, (struct sockaddr*)&sin, &len)) < 0) {
+       if ((res = rtp_recvfrom(instance, rtp->rawdata + AST_FRIENDLY_OFFSET,
+                               sizeof(rtp->rawdata) - AST_FRIENDLY_OFFSET, 0,
+                               &addr)) < 0) {
                ast_assert(errno != EBADF);
                if (errno != EAGAIN) {
                        ast_log(LOG_WARNING, "RTP Read error: %s. Hanging up.\n", strerror(errno));
@@ -1874,12 +2022,24 @@ static struct ast_frame *ast_rtp_read(struct ast_rtp_instance *instance, int rtc
 
        /* If strict RTP protection is enabled see if we need to learn the remote address or if we need to drop the packet */
        if (rtp->strict_rtp_state == STRICT_RTP_LEARN) {
-               memcpy(&rtp->strict_rtp_address, &sin, sizeof(rtp->strict_rtp_address));
+               ast_sockaddr_copy(&rtp->strict_rtp_address, &addr);
                rtp->strict_rtp_state = STRICT_RTP_CLOSED;
        } else if (rtp->strict_rtp_state == STRICT_RTP_CLOSED) {
-               if ((rtp->strict_rtp_address.sin_addr.s_addr != sin.sin_addr.s_addr) || (rtp->strict_rtp_address.sin_port != sin.sin_port)) {
-                       ast_debug(1, "Received RTP packet from %s:%d, dropping due to strict RTP protection. Expected it to be from %s:%d\n", ast_inet_ntoa(sin.sin_addr), ntohs(sin.sin_port), ast_inet_ntoa(rtp->strict_rtp_address.sin_addr), ntohs(rtp->strict_rtp_address.sin_port));
-                       return &ast_null_frame;
+               if (ast_sockaddr_cmp(&rtp->strict_rtp_address, &addr)) {
+                       /* Hmm, not the strict addres. Perhaps we're getting audio from the alternate? */
+                       if (!ast_sockaddr_cmp(&rtp->alt_rtp_address, &addr)) {
+                               /* ooh, we did! You're now the new expected address, son! */
+                               ast_sockaddr_copy(&rtp->strict_rtp_address,
+                                                 &addr);
+                       } else  {
+                               const char *real_addr = ast_strdupa(ast_sockaddr_stringify(&addr));
+                               const char *expected_addr = ast_strdupa(ast_sockaddr_stringify(&rtp->strict_rtp_address));
+
+                               ast_debug(1, "Received RTP packet from %s, dropping due to strict RTP protection. Expected it to be from %s\n",
+                                               real_addr, expected_addr);
+
+                               return &ast_null_frame;
+                       }
                }
        }
 
@@ -1889,27 +2049,30 @@ static struct ast_frame *ast_rtp_read(struct ast_rtp_instance *instance, int rtc
        ast_rtp_instance_get_remote_address(instance, &remote_address);
 
        if (!(version = (seqno & 0xC0000000) >> 30)) {
-               if ((ast_stun_handle_packet(rtp->s, &sin, rtp->rawdata + AST_FRIENDLY_OFFSET, res, NULL, NULL) == AST_STUN_ACCEPT) &&
-                   (!remote_address.sin_port && !remote_address.sin_addr.s_addr)) {
-                       ast_rtp_instance_set_remote_address(instance, &sin);
+               struct sockaddr_in addr_tmp;
+               ast_sockaddr_to_sin(&addr, &addr_tmp);
+               if ((ast_stun_handle_packet(rtp->s, &addr_tmp, rtp->rawdata + AST_FRIENDLY_OFFSET, 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);
                }
                return &ast_null_frame;
        }
 
        /* If symmetric RTP is enabled see if the remote side is not what we expected and change where we are sending audio */
        if (ast_rtp_instance_get_prop(instance, AST_RTP_PROPERTY_NAT)) {
-               if ((remote_address.sin_addr.s_addr != sin.sin_addr.s_addr) ||
-                   (remote_address.sin_port != sin.sin_port)) {
-                       ast_rtp_instance_set_remote_address(instance, &sin);
-                       memcpy(&remote_address, &sin, sizeof(remote_address));
+               if (ast_sockaddr_cmp(&remote_address, &addr)) {
+                       ast_rtp_instance_set_remote_address(instance, &addr);
+                       ast_sockaddr_copy(&remote_address, &addr);
                        if (rtp->rtcp) {
-                               memcpy(&rtp->rtcp->them, &sin, sizeof(rtp->rtcp->them));
-                               rtp->rtcp->them.sin_port = htons(ntohs(sin.sin_port)+1);
+                               ast_sockaddr_copy(&rtp->rtcp->them, &addr);
+                               ast_sockaddr_set_port(&rtp->rtcp->them, ast_sockaddr_port(&addr) + 1);
                        }
                        rtp->rxseqno = 0;
                        ast_set_flag(rtp, FLAG_NAT_ACTIVE);
-                       if (option_debug || rtpdebug)
-                               ast_debug(0, "RTP NAT: Got audio from other end. Now sending to address %s:%d\n", ast_inet_ntoa(remote_address.sin_addr), ntohs(remote_address.sin_port));
+                       if (rtpdebug)
+                               ast_debug(0, "RTP NAT: Got audio from other end. Now sending to address %s\n",
+                                         ast_sockaddr_stringify(&remote_address));
                }
        }
 
@@ -1933,14 +2096,27 @@ static struct ast_frame *ast_rtp_read(struct ast_rtp_instance *instance, int rtc
        timestamp = ntohl(rtpheader[1]);
        ssrc = ntohl(rtpheader[2]);
 
-       /* Force a marker bit if the SSRC changes */
-       if (!mark && rtp->rxssrc && rtp->rxssrc != ssrc) {
-               if (option_debug || rtpdebug) {
-                       ast_debug(1, "Forcing Marker bit, because SSRC has changed\n");
+       AST_LIST_HEAD_INIT_NOLOCK(&frames);
+       /* Force a marker bit and change SSRC if the SSRC changes */
+       if (rtp->rxssrc && rtp->rxssrc != ssrc) {
+               struct ast_frame *f, srcupdate = {
+                       AST_FRAME_CONTROL,
+                       .subclass.integer = AST_CONTROL_SRCCHANGE,
+               };
+
+               if (!mark) {
+                       if (rtpdebug) {
+                               ast_debug(1, "Forcing Marker bit, because SSRC has changed\n");
+                       }
+                       mark = 1;
                }
-               mark = 1;
+
+               f = ast_frisolate(&srcupdate);
+               AST_LIST_INSERT_TAIL(&frames, f, frame_list);
        }
 
+       rtp->rxssrc = ssrc;
+
        /* Remove any padding bytes that may be present */
        if (padding) {
                res -= rtp->rawdata[AST_FRIENDLY_OFFSET + res - 1];
@@ -1968,7 +2144,7 @@ static struct ast_frame *ast_rtp_read(struct ast_rtp_instance *instance, int rtc
        /* Make sure after we potentially mucked with the header length that it is once again valid */
        if (res < hdrlen) {
                ast_log(LOG_WARNING, "RTP Read too short (%d, expecting %d\n", res, hdrlen);
-               return &ast_null_frame;
+               return AST_LIST_FIRST(&frames) ? AST_LIST_FIRST(&frames) : &ast_null_frame;
        }
 
        rtp->rxcount++;
@@ -1977,9 +2153,9 @@ static struct ast_frame *ast_rtp_read(struct ast_rtp_instance *instance, int rtc
        }
 
        /* Do not schedule RR if RTCP isn't run */
-       if (rtp->rtcp && rtp->rtcp->them.sin_addr.s_addr && rtp->rtcp->schedid < 1) {
+       if (rtp->rtcp && !ast_sockaddr_isnull(&rtp->rtcp->them) && rtp->rtcp->schedid < 1) {
                /* Schedule transmission of Receiver Report */
-               rtp->rtcp->schedid = ast_sched_add(rtp->sched, ast_rtcp_calc_interval(rtp), ast_rtcp_write, rtp);
+               rtp->rtcp->schedid = ast_sched_add(rtp->sched, ast_rtcp_calc_interval(rtp), ast_rtcp_write, instance);
        }
        if ((int)rtp->lastrxseqno - (int)seqno  > 100) /* if so it would indicate that the sender cycled; allow for misordering */
                rtp->cycles += RTP_SEQ_MOD;
@@ -1991,9 +2167,10 @@ static struct ast_frame *ast_rtp_read(struct ast_rtp_instance *instance, int rtc
                rtp->themssrc = ntohl(rtpheader[2]); /* Record their SSRC to put in future RR */
        }
 
-       if (rtp_debug_test_addr(&sin)) {
-               ast_verbose("Got  RTP packet from    %s:%u (type %-2.2d, seq %-6.6u, ts %-6.6u, len %-6.6u)\n",
-                           ast_inet_ntoa(sin.sin_addr), ntohs(sin.sin_port), payloadtype, seqno, timestamp,res - hdrlen);
+       if (rtp_debug_test_addr(&addr)) {
+               ast_verbose("Got  RTP packet from    %s (type %-2.2d, seq %-6.6u, ts %-6.6u, len %-6.6u)\n",
+                           ast_sockaddr_stringify(&addr),
+                           payloadtype, seqno, timestamp,res - hdrlen);
        }
 
        payload = ast_rtp_codecs_payload_lookup(ast_rtp_instance_get_codecs(instance), payloadtype);
@@ -2001,22 +2178,37 @@ static struct ast_frame *ast_rtp_read(struct ast_rtp_instance *instance, int rtc
        /* If the payload is not actually an Asterisk one but a special one pass it off to the respective handler */
        if (!payload.asterisk_format) {
                struct ast_frame *f = NULL;
-
-               if (payload.code == AST_RTP_DTMF) {
-                       f = process_dtmf_rfc2833(instance, rtp->rawdata + AST_FRIENDLY_OFFSET + hdrlen, res - hdrlen, seqno, timestamp, &sin, payloadtype, mark);
-               } else if (payload.code == AST_RTP_CISCO_DTMF) {
-                       f = process_dtmf_cisco(instance, rtp->rawdata + AST_FRIENDLY_OFFSET + hdrlen, res - hdrlen, seqno, timestamp, &sin, payloadtype, mark);
-               } else if (payload.code == AST_RTP_CN) {
-                       f = process_cn_rfc3389(instance, rtp->rawdata + AST_FRIENDLY_OFFSET + hdrlen, res - hdrlen, seqno, timestamp, &sin, payloadtype, mark);
+               if (payload.rtp_code == AST_RTP_DTMF) {
+                       /* process_dtmf_rfc2833 may need to return multiple frames. We do this
+                        * 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);
+               } 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);
+               } 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);
                } else {
-                       ast_log(LOG_NOTICE, "Unknown RTP codec %d received from '%s'\n", payloadtype, ast_inet_ntoa(remote_address.sin_addr));
+                       ast_log(LOG_NOTICE, "Unknown RTP codec %d received from '%s'\n",
+                               payloadtype,
+                               ast_sockaddr_stringify(&remote_address));
                }
 
-               return f ? f : &ast_null_frame;
+               if (f) {
+                       AST_LIST_INSERT_TAIL(&frames, f, frame_list);
+               }
+               /* Even if no frame was returned by one of the above methods,
+                * we may have a frame to return in our frame list
+                */
+               if (!AST_LIST_EMPTY(&frames)) {
+                       return AST_LIST_FIRST(&frames);
+               }
+               return &ast_null_frame;
        }
 
-       rtp->lastrxformat = rtp->f.subclass = payload.code;
-       rtp->f.frametype = (rtp->f.subclass & AST_FORMAT_AUDIO_MASK) ? AST_FRAME_VOICE : (rtp->f.subclass & AST_FORMAT_VIDEO_MASK) ? AST_FRAME_VIDEO : AST_FRAME_TEXT;
+       ast_format_copy(&rtp->lastrxformat, &payload.format);
+       ast_format_copy(&rtp->f.subclass.format, &payload.format);
+       rtp->f.frametype = (AST_FORMAT_GET_TYPE(rtp->f.subclass.format.id) == AST_FORMAT_TYPE_AUDIO) ? AST_FRAME_VOICE : (AST_FORMAT_GET_TYPE(rtp->f.subclass.format.id) == AST_FORMAT_TYPE_VIDEO) ? AST_FRAME_VIDEO : AST_FRAME_TEXT;
 
        rtp->rxseqno = seqno;
 
@@ -2025,11 +2217,12 @@ static struct ast_frame *ast_rtp_read(struct ast_rtp_instance *instance, int rtc
 
                if (rtp->resp) {
                        struct ast_frame *f;
-                       f = send_dtmf(instance, AST_FRAME_DTMF_END, 0);
-                       f->len = ast_tvdiff_ms(ast_samp2tv(rtp->dtmf_duration, 8000), ast_tv(0, 0));
+                       f = create_dtmf_frame(instance, AST_FRAME_DTMF_END, 0);
+                       f->len = ast_tvdiff_ms(ast_samp2tv(rtp->dtmf_duration, rtp_get_rate(&f->subclass.format)), ast_tv(0, 0));
                        rtp->resp = 0;
                        rtp->dtmf_timeout = rtp->dtmf_duration = 0;
-                       return f;
+                       AST_LIST_INSERT_TAIL(&frames, f, frame_list);
+                       return AST_LIST_FIRST(&frames);
                }
        }
 
@@ -2042,7 +2235,7 @@ static struct ast_frame *ast_rtp_read(struct ast_rtp_instance *instance, int rtc
        rtp->f.offset = hdrlen + AST_FRIENDLY_OFFSET;
        rtp->f.seqno = seqno;
 
-       if (rtp->f.subclass == AST_FORMAT_T140 && (int)seqno - (prev_seqno+1) > 0 && (int)seqno - (prev_seqno+1) < 10) {
+       if (rtp->f.subclass.format.id == AST_FORMAT_T140 && (int)seqno - (prev_seqno+1) > 0 && (int)seqno - (prev_seqno+1) < 10) {
                unsigned char *data = rtp->f.data.ptr;
 
                memmove(rtp->f.data.ptr+3, rtp->f.data.ptr, rtp->f.datalen);
@@ -2052,7 +2245,7 @@ static struct ast_frame *ast_rtp_read(struct ast_rtp_instance *instance, int rtc
                *data = 0xBD;
        }
 
-       if (rtp->f.subclass == AST_FORMAT_T140RED) {
+       if (rtp->f.subclass.format.id == AST_FORMAT_T140RED) {
                unsigned char *data = rtp->f.data.ptr;
                unsigned char *header_end;
                int num_generations;
@@ -2061,8 +2254,11 @@ static struct ast_frame *ast_rtp_read(struct ast_rtp_instance *instance, int rtc
                int diff =(int)seqno - (prev_seqno+1); /* if diff = 0, no drop*/
                int x;
 
-               rtp->f.subclass = AST_FORMAT_T140;
+               ast_format_set(&rtp->f.subclass.format, AST_FORMAT_T140, 0);
                header_end = memchr(data, ((*data) & 0x7f), rtp->f.datalen);
+               if (header_end == NULL) {
+                       return AST_LIST_FIRST(&frames) ? AST_LIST_FIRST(&frames) : &ast_null_frame;
+               }
                header_end++;
 
                header_length = header_end - data;
@@ -2074,7 +2270,7 @@ static struct ast_frame *ast_rtp_read(struct ast_rtp_instance *instance, int rtc
                                len += data[x * 4 + 3];
 
                        if (!(rtp->f.datalen - len))
-                               return &ast_null_frame;
+                               return AST_LIST_FIRST(&frames) ? AST_LIST_FIRST(&frames) : &ast_null_frame;
 
                        rtp->f.data.ptr += len;
                        rtp->f.datalen -= len;
@@ -2096,16 +2292,17 @@ static struct ast_frame *ast_rtp_read(struct ast_rtp_instance *instance, int rtc
                }
        }
 
-       if (rtp->f.subclass & AST_FORMAT_AUDIO_MASK) {
+       if (AST_FORMAT_GET_TYPE(rtp->f.subclass.format.id) == AST_FORMAT_TYPE_AUDIO) {
                rtp->f.samples = ast_codec_get_samples(&rtp->f);
-               if (rtp->f.subclass == AST_FORMAT_SLINEAR)
+               if (ast_format_is_slinear(&rtp->f.subclass.format)) {
                        ast_frame_byteswap_be(&rtp->f);
+               }
                calc_rxstamp(&rtp->f.delivery, rtp, timestamp, mark);
                /* Add timing data to let ast_generic_bridge() put the frame into a jitterbuf */
                ast_set_flag(&rtp->f, AST_FRFLAG_HAS_TIMING_INFO);
-               rtp->f.ts = timestamp / 8;
-               rtp->f.len = rtp->f.samples / ((ast_format_rate(rtp->f.subclass) / 1000));
-       } else if (rtp->f.subclass & AST_FORMAT_VIDEO_MASK) {
+               rtp->f.ts = timestamp / (rtp_get_rate(&rtp->f.subclass.format) / 1000);
+               rtp->f.len = rtp->f.samples / ((ast_format_rate(&rtp->f.subclass.format) / 1000));
+       } else if (AST_FORMAT_GET_TYPE(rtp->f.subclass.format.id) == AST_FORMAT_TYPE_VIDEO) {
                /* Video -- samples is # of samples vs. 90000 */
                if (!rtp->lastividtimestamp)
                        rtp->lastividtimestamp = timestamp;
@@ -2113,13 +2310,8 @@ static struct ast_frame *ast_rtp_read(struct ast_rtp_instance *instance, int rtc
                rtp->lastividtimestamp = timestamp;
                rtp->f.delivery.tv_sec = 0;
                rtp->f.delivery.tv_usec = 0;
-               /* Pass the RTP marker bit as bit 0 in the subclass field.
-                * This is ok because subclass is actually a bitmask, and
-                * the low bits represent audio formats, that are not
-                * involved here since we deal with video.
-                */
-               if (mark)
-                       rtp->f.subclass |= 0x1;
+               /* Pass the RTP marker bit as bit */
+               ast_format_set_video_mark(&rtp->f.subclass.format);
        } else {
                /* TEXT -- samples is # of samples vs. 1000 */
                if (!rtp->lastitexttimestamp)
@@ -2130,7 +2322,8 @@ static struct ast_frame *ast_rtp_read(struct ast_rtp_instance *instance, int rtc
                rtp->f.delivery.tv_usec = 0;
        }
 
-       return &rtp->f;
+       AST_LIST_INSERT_TAIL(&frames, &rtp->f, frame_list);
+       return AST_LIST_FIRST(&frames);
 }
 
 static void ast_rtp_prop_set(struct ast_rtp_instance *instance, enum ast_rtp_property property, int value)
@@ -2145,19 +2338,26 @@ static void ast_rtp_prop_set(struct ast_rtp_instance *instance, enum ast_rtp_pro
                if (!(rtp->rtcp = ast_calloc(1, sizeof(*rtp->rtcp)))) {
                        return;
                }
-               if ((rtp->rtcp->s = create_new_socket("RTCP")) < 0) {
+
+               /* 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 ((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);
                        rtp->rtcp = NULL;
                        return;
                }
 
-               /* Grab the IP address and port we are going to use */
-               ast_rtp_instance_get_local_address(instance, &rtp->rtcp->us);
-               rtp->rtcp->us.sin_port = htons(ntohs(rtp->rtcp->us.sin_port) + 1);
-
                /* 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 (bind(rtp->rtcp->s, (struct sockaddr*)&rtp->rtcp->us, sizeof(rtp->rtcp->us))) {
+               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);
@@ -2181,14 +2381,17 @@ static int ast_rtp_fd(struct ast_rtp_instance *instance, int rtcp)
        return rtcp ? (rtp->rtcp ? rtp->rtcp->s : -1) : rtp->s;
 }
 
-static void ast_rtp_remote_address_set(struct ast_rtp_instance *instance, struct sockaddr_in *sin)
+static void ast_rtp_remote_address_set(struct ast_rtp_instance *instance, struct ast_sockaddr *addr)
 {
        struct ast_rtp *rtp = ast_rtp_instance_get_data(instance);
 
        if (rtp->rtcp) {
                ast_debug(1, "Setting RTCP address on RTP instance '%p'\n", instance);
-               memcpy(&rtp->rtcp->them, sin, sizeof(rtp->rtcp->them));
-               rtp->rtcp->them.sin_port = htons(ntohs(sin->sin_port) + 1);
+               ast_sockaddr_copy(&rtp->rtcp->them, addr);
+               if (!ast_sockaddr_isnull(addr)) {
+                       ast_sockaddr_set_port(&rtp->rtcp->them,
+                                             ast_sockaddr_port(addr) + 1);
+               }
        }
 
        rtp->rxseqno = 0;
@@ -2200,6 +2403,18 @@ static void ast_rtp_remote_address_set(struct ast_rtp_instance *instance, struct
        return;
 }
 
+static void ast_rtp_alt_remote_address_set(struct ast_rtp_instance *instance, struct ast_sockaddr *addr)
+{
+       struct ast_rtp *rtp = ast_rtp_instance_get_data(instance);
+
+       /* No need to futz with rtp->rtcp here because ast_rtcp_read is already able to adjust if receiving
+        * RTCP from an "unexpected" source
+        */
+       ast_sockaddr_copy(&rtp->alt_rtp_address, addr);
+
+       return;
+}
+
 /*! \brief Write t140 redundacy frame
  * \param data primary data to be buffered
  */
@@ -2223,7 +2438,7 @@ static int rtp_red_init(struct ast_rtp_instance *instance, int buffer_time, int
        }
 
        rtp->red->t140.frametype = AST_FRAME_TEXT;
-       rtp->red->t140.subclass = AST_FORMAT_T140RED;
+       ast_format_set(&rtp->red->t140.subclass.format, AST_FORMAT_T140RED, 0);
        rtp->red->t140.data.ptr = &rtp->red->buf_data;
 
        rtp->red->t140.ts = 0;
@@ -2335,17 +2550,20 @@ static int ast_rtp_dtmf_compatible(struct ast_channel *chan0, struct ast_rtp_ins
                 (!chan0->tech->send_digit_begin != !chan1->tech->send_digit_begin)) ? 0 : 1);
 }
 
-static void ast_rtp_stun_request(struct ast_rtp_instance *instance, struct sockaddr_in *suggestion, const char *username)
+static void ast_rtp_stun_request(struct ast_rtp_instance *instance, struct ast_sockaddr *suggestion, const char *username)
 {
        struct ast_rtp *rtp = ast_rtp_instance_get_data(instance);
+       struct sockaddr_in suggestion_tmp;
 
-       ast_stun_request(rtp->s, suggestion, username, NULL);
+       ast_sockaddr_to_sin(suggestion, &suggestion_tmp);
+       ast_stun_request(rtp->s, &suggestion_tmp, username, NULL);
+       ast_sockaddr_from_sin(suggestion, &suggestion_tmp);
 }
 
 static void ast_rtp_stop(struct ast_rtp_instance *instance)
 {
        struct ast_rtp *rtp = ast_rtp_instance_get_data(instance);
-       struct sockaddr_in sin = { 0, };
+       struct ast_sockaddr addr = { {0,} };
 
        if (rtp->rtcp) {
                AST_SCHED_DEL(rtp->sched, rtp->rtcp->schedid);
@@ -2356,71 +2574,45 @@ static void ast_rtp_stop(struct ast_rtp_instance *instance)
                rtp->red = NULL;
        }
 
-       ast_rtp_instance_set_remote_address(instance, &sin);
+       ast_rtp_instance_set_remote_address(instance, &addr);
        if (rtp->rtcp) {
-               memset(&rtp->rtcp->them.sin_addr, 0, sizeof(rtp->rtcp->them.sin_addr));
-               memset(&rtp->rtcp->them.sin_port, 0, sizeof(rtp->rtcp->them.sin_port));
+               ast_sockaddr_setnull(&rtp->rtcp->them);
        }
 
        ast_set_flag(rtp, FLAG_NEED_MARKER_BIT);
 }
 
+static int ast_rtp_qos_set(struct ast_rtp_instance *instance, int tos, int cos, const char *desc)
+{
+       struct ast_rtp *rtp = ast_rtp_instance_get_data(instance);
+
+       return ast_set_qos(rtp->s, tos, cos, desc);
+}
+
 static char *rtp_do_debug_ip(struct ast_cli_args *a)
 {
-       struct hostent *hp;
-       struct ast_hostent ahp;
-       int port = 0;
-       char *p, *arg;
-
-       arg = a->argv[3];
-       p = strstr(arg, ":");
-       if (p) {
-               *p = '\0';
-               p++;
-               port = atoi(p);
-       }
-       hp = ast_gethostbyname(arg, &ahp);
-       if (hp == NULL) {
+       char *arg = ast_strdupa(a->argv[4]);
+
+       if (!ast_sockaddr_parse(&rtpdebugaddr, arg, 0)) {
                ast_cli(a->fd, "Lookup failed for '%s'\n", arg);
                return CLI_FAILURE;
        }
-       rtpdebugaddr.sin_family = AF_INET;
-       memcpy(&rtpdebugaddr.sin_addr, hp->h_addr, sizeof(rtpdebugaddr.sin_addr));
-       rtpdebugaddr.sin_port = htons(port);
-       if (port == 0)
-               ast_cli(a->fd, "RTP Debugging Enabled for IP: %s\n", ast_inet_ntoa(rtpdebugaddr.sin_addr));
-       else
-               ast_cli(a->fd, "RTP Debugging Enabled for IP: %s:%d\n", ast_inet_ntoa(rtpdebugaddr.sin_addr), port);
+       ast_cli(a->fd, "RTP Debugging Enabled for address: %s\n",
+               ast_sockaddr_stringify(&rtpdebugaddr));
        rtpdebug = 1;
        return CLI_SUCCESS;
 }
 
 static char *rtcp_do_debug_ip(struct ast_cli_args *a)
 {
-       struct hostent *hp;
-       struct ast_hostent ahp;
-       int port = 0;
-       char *p, *arg;
-
-       arg = a->argv[3];
-       p = strstr(arg, ":");
-       if (p) {
-               *p = '\0';
-               p++;
-               port = atoi(p);
-       }
-       hp = ast_gethostbyname(arg, &ahp);
-       if (hp == NULL) {
+       char *arg = ast_strdupa(a->argv[4]);
+
+       if (!ast_sockaddr_parse(&rtcpdebugaddr, arg, 0)) {
                ast_cli(a->fd, "Lookup failed for '%s'\n", arg);
                return CLI_FAILURE;
        }
-       rtcpdebugaddr.sin_family = AF_INET;
-       memcpy(&rtcpdebugaddr.sin_addr, hp->h_addr, sizeof(rtcpdebugaddr.sin_addr));
-       rtcpdebugaddr.sin_port = htons(port);
-       if (port == 0)
-               ast_cli(a->fd, "RTCP Debugging Enabled for IP: %s\n", ast_inet_ntoa(rtcpdebugaddr.sin_addr));
-       else
-               ast_cli(a->fd, "RTCP Debugging Enabled for IP: %s:%d\n", ast_inet_ntoa(rtcpdebugaddr.sin_addr), port);
+       ast_cli(a->fd, "RTCP Debugging Enabled for address: %s\n",
+               ast_sockaddr_stringify(&rtcpdebugaddr));
        rtcpdebug = 1;
        return CLI_SUCCESS;
 }
@@ -2623,8 +2815,9 @@ static int unload_module(void)
        return 0;
 }
 
-AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_DEFAULT, "Asterisk RTP Stack",
+AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_LOAD_ORDER, "Asterisk RTP Stack",
                .load = load_module,
                .unload = unload_module,
                .reload = reload_module,
+               .load_pri = AST_MODPRI_CHANNEL_DEPEND,
                );