Media Project Phase2: SILK 8khz-24khz, SLINEAR 8khz-192khz, SPEEX 32khz, hd audio...
[asterisk/asterisk.git] / res / res_rtp_asterisk.c
index b896d64..b2004ef 100644 (file)
@@ -35,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"
@@ -45,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"
@@ -87,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
@@ -132,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 */
-       format_t lasttxformat;
-       format_t 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). */
@@ -161,15 +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 sockaddr_in alt_rtp_address; /*!<Alternate remote address information */
+       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;
 };
@@ -187,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*/
@@ -253,25 +251,27 @@ struct rtp_red {
 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 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_alt_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 = {
@@ -280,6 +280,7 @@ static struct ast_rtp_engine asterisk_rtp_engine = {
        .destroy = ast_rtp_destroy,
        .dtmf_begin = ast_rtp_dtmf_begin,
        .dtmf_end = ast_rtp_dtmf_end,
+       .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,
@@ -295,47 +296,34 @@ 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 1;
+       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 sockaddr *sa, socklen_t *salen, int rtcp)
+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 = recvfrom(rtcp ? rtp->rtcp->s : rtp->s, buf, size, flags, sa, salen)) < 0) {
+       if ((len = ast_recvfrom(rtcp ? rtp->rtcp->s : rtp->s, buf, size, flags, sa)) < 0) {
           return len;
        }
 
@@ -346,17 +334,17 @@ static int __rtp_recvfrom(struct ast_rtp_instance *instance, void *buf, size_t s
        return len;
 }
 
-static int rtcp_recvfrom(struct ast_rtp_instance *instance, void *buf, size_t size, int flags, struct sockaddr *sa, socklen_t *salen)
+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, salen, 1);
+       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 sockaddr *sa, socklen_t *salen)
+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, salen, 0);
+       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 sockaddr *sa, socklen_t salen, int rtcp)
+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;
@@ -367,22 +355,22 @@ static int __rtp_sendto(struct ast_rtp_instance *instance, void *buf, size_t siz
           return -1;
        }
 
-       return sendto(rtcp ? rtp->rtcp->s : rtp->s, temp, len, flags, sa, salen);
+       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 sockaddr *sa, socklen_t salen)
+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, salen, 1);
+       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 sockaddr *sa, socklen_t salen)
+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, salen, 0);
+       return __rtp_sendto(instance, buf, size, flags, sa, 0);
 }
 
-static int rtp_get_rate(format_t subclass)
+static int rtp_get_rate(struct ast_format *format)
 {
-       return (subclass == AST_FORMAT_G722) ? 8000 : ast_format_rate(subclass);
+       return (format->id == AST_FORMAT_G722) ? 8000 : ast_format_rate(format);
 }
 
 static unsigned int ast_rtcp_calc_interval(struct ast_rtp *rtp)
@@ -423,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) {
@@ -445,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;
@@ -461,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;
@@ -473,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;
                }
 
@@ -538,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;
@@ -546,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;
        }
 
@@ -567,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;
@@ -581,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 = rtp_sendto(instance, (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;
@@ -607,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;
@@ -615,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;
        }
 
@@ -627,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 = rtp_sendto(instance, (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 */
@@ -647,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;
        }
 
@@ -680,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);
@@ -690,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 = rtp_sendto(instance, (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);
                }
        }
 
@@ -711,6 +711,11 @@ static int ast_rtp_dtmf_end(struct ast_rtp_instance *instance, char digit)
        return 0;
 }
 
+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);
@@ -725,12 +730,24 @@ static void ast_rtp_update_source(struct ast_rtp_instance *instance)
 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;
@@ -785,10 +802,10 @@ static int ast_rtcp_write_rr(struct ast_rtp_instance *instance)
 
        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;
@@ -841,7 +858,7 @@ static int ast_rtcp_write_rr(struct ast_rtp_instance *instance)
        rtcpheader[(len/4)+2] = htonl(0x01 << 24);              /* Empty for the moment */
        len += 12;
 
-       res = rtcp_sendto(instance, (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));
@@ -852,13 +869,12 @@ static int ast_rtcp_write_rr(struct ast_rtp_instance *instance)
 
        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,
@@ -888,11 +904,10 @@ static int ast_rtcp_write_sr(struct ast_rtp_instance *instance)
        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;
@@ -941,9 +956,11 @@ static int ast_rtcp_write_sr(struct ast_rtp_instance *instance)
        rtcpheader[(len/4)+2] = htonl(0x01 << 24);                    /* Empty for the moment */
        len += 12;
 
-       res =rtcp_sendto(instance, (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;
        }
@@ -955,7 +972,7 @@ static int ast_rtcp_write_sr(struct ast_rtp_instance *instance)
        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);
@@ -968,7 +985,7 @@ static int ast_rtcp_write_sr(struct ast_rtp_instance *instance)
                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"
@@ -980,7 +997,7 @@ static int ast_rtcp_write_sr(struct ast_rtp_instance *instance)
                                            "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,
@@ -1019,10 +1036,10 @@ 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, };
-       int rate = rtp_get_rate(frame->subclass.codec) / 1000;
+       struct ast_sockaddr remote_address = { {0,} };
+       int rate = rtp_get_rate(&frame->subclass.format) / 1000;
 
-       if (frame->subclass.codec == AST_FORMAT_G722) {
+       if (frame->subclass.format.id == AST_FORMAT_G722) {
                frame->samples /= 2;
        }
 
@@ -1046,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.codec & 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;
@@ -1094,7 +1111,7 @@ static int ast_rtp_raw_write(struct ast_rtp_instance *instance, struct ast_frame
        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);
 
@@ -1102,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 = rtp_sendto(instance, (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 {
@@ -1122,8 +1143,9 @@ static int ast_rtp_raw_write(struct ast_rtp_instance *instance, struct ast_frame
                }
 
                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);
                }
        }
 
@@ -1172,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, };
-       format_t 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;
        }
@@ -1203,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.codec;
-       if (frame->frametype == AST_FRAME_VIDEO) {
-               subclass &= ~0x1LL;
-       }
-       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.codec));
+       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;
@@ -1224,11 +1245,13 @@ 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:
@@ -1239,13 +1262,13 @@ static int ast_rtp_write(struct ast_rtp_instance *instance, struct ast_frame *fr
                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 %s ms: %d len: %d\n", ast_getformatname(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: %s ms: %d len: %d\n", ast_getformatname(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));
                        }
                }
        }
@@ -1293,7 +1316,7 @@ static void calc_rxstamp(struct timeval *tv, struct ast_rtp *rtp, unsigned int t
        double d;
        double dtv;
        double prog;
-       int rate = rtp_get_rate(rtp->f.subclass.codec);
+       int rate = rtp_get_rate(&rtp->f.subclass.format);
 
        double normdev_rxjitter_current;
        if ((!rtp->rxcore.tv_sec && !rtp->rxcore.tv_usec) || mark) {
@@ -1341,17 +1364,19 @@ static void calc_rxstamp(struct timeval *tv, struct ast_rtp *rtp, unsigned int t
 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.integer = AST_CONTROL_FLASH;
@@ -1368,10 +1393,10 @@ static struct ast_frame *create_dtmf_frame(struct ast_rtp_instance *instance, en
        return &rtp->f;
 }
 
-static void 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, struct frame_list *frames)
+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;
@@ -1388,12 +1413,13 @@ static void process_dtmf_rfc2833(struct ast_rtp_instance *instance, unsigned cha
        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 */
@@ -1409,7 +1435,7 @@ static void process_dtmf_rfc2833(struct ast_rtp_instance *instance, unsigned cha
                resp = 'X';
        } else {
                /* Not a supported event */
-               ast_log(LOG_DEBUG, "Ignoring RTP 2833 Event: %08x. Not a DTMF Digit.\n", event);
+               ast_debug(1, "Ignoring RTP 2833 Event: %08x. Not a DTMF Digit.\n", event);
                return;
        }
 
@@ -1453,7 +1479,7 @@ static void process_dtmf_rfc2833(struct ast_rtp_instance *instance, unsigned cha
                        if ((rtp->lastevent != seqno) && rtp->resp) {
                                rtp->dtmf_duration = new_duration;
                                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.codec)), ast_tv(0, 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);
@@ -1464,7 +1490,7 @@ static void process_dtmf_rfc2833(struct ast_rtp_instance *instance, unsigned cha
                        if (rtp->resp && rtp->resp != resp) {
                                /* Another digit already began. End it */
                                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.codec)), ast_tv(0, 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);
@@ -1492,7 +1518,7 @@ static void process_dtmf_rfc2833(struct ast_rtp_instance *instance, unsigned cha
        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;
@@ -1539,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;
@@ -1561,17 +1587,17 @@ static struct ast_frame *process_dtmf_cisco(struct ast_rtp_instance *instance, u
                }
        } else if ((rtp->resp == resp) && !power) {
                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 ? (rtp_get_rate(rtp->lastrxformat) / 1000) : 8);
+               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 * (rtp->lastrxformat ? (rtp_get_rate(rtp->lastrxformat) / 1000) : 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);
 
@@ -1579,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 %" PRId64 " (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);
        }
 
@@ -1615,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 = rtcp_recvfrom(instance, 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));
@@ -1636,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));
                }
        }
 
@@ -1660,13 +1687,14 @@ 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]);
@@ -1685,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]));
@@ -1735,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",
@@ -1784,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));
@@ -1796,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"
@@ -1808,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],
@@ -1821,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"
@@ -1832,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],
@@ -1847,7 +1875,7 @@ 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.integer = AST_CONTROL_VIDUPDATE;
@@ -1858,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);
@@ -1884,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;
@@ -1894,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;
        }
 
@@ -1915,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 = rtp_sendto(instance1, (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;
@@ -1936,12 +1982,11 @@ 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 */
@@ -1958,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 = rtp_recvfrom(instance, 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));
@@ -1975,16 +2022,22 @@ 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)) {
+               if (ast_sockaddr_cmp(&rtp->strict_rtp_address, &addr)) {
                        /* Hmm, not the strict addres. Perhaps we're getting audio from the alternate? */
-                       if ((rtp->alt_rtp_address.sin_addr.s_addr == sin.sin_addr.s_addr) && (rtp->alt_rtp_address.sin_port == sin.sin_port)) {
+                       if (!ast_sockaddr_cmp(&rtp->alt_rtp_address, &addr)) {
                                /* ooh, we did! You're now the new expected address, son! */
-                               rtp->strict_rtp_address = sin;
+                               ast_sockaddr_copy(&rtp->strict_rtp_address,
+                                                 &addr);
                        } else  {
-                               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));
+                               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;
                        }
                }
@@ -1996,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));
                }
        }
 
@@ -2049,7 +2105,7 @@ static struct ast_frame *ast_rtp_read(struct ast_rtp_instance *instance, int rtc
                };
 
                if (!mark) {
-                       if (option_debug || rtpdebug) {
+                       if (rtpdebug) {
                                ast_debug(1, "Forcing Marker bit, because SSRC has changed\n");
                        }
                        mark = 1;
@@ -2097,7 +2153,7 @@ 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, instance);
        }
@@ -2111,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);
@@ -2121,18 +2178,20 @@ 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) {
+               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, &sin, payloadtype, mark, &frames);
-               } 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);
+                       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));
                }
 
                if (f) {
@@ -2147,8 +2206,9 @@ static struct ast_frame *ast_rtp_read(struct ast_rtp_instance *instance, int rtc
                return &ast_null_frame;
        }
 
-       rtp->lastrxformat = rtp->f.subclass.codec = payload.code;
-       rtp->f.frametype = (rtp->f.subclass.codec & AST_FORMAT_AUDIO_MASK) ? AST_FRAME_VOICE : (rtp->f.subclass.codec & 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;
 
@@ -2158,7 +2218,7 @@ static struct ast_frame *ast_rtp_read(struct ast_rtp_instance *instance, int rtc
                if (rtp->resp) {
                        struct ast_frame *f;
                        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.codec)), ast_tv(0, 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;
                        AST_LIST_INSERT_TAIL(&frames, f, frame_list);
@@ -2175,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.codec == 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);
@@ -2185,7 +2245,7 @@ static struct ast_frame *ast_rtp_read(struct ast_rtp_instance *instance, int rtc
                *data = 0xBD;
        }
 
-       if (rtp->f.subclass.codec == 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;
@@ -2194,7 +2254,7 @@ 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.codec = 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;
@@ -2232,17 +2292,17 @@ static struct ast_frame *ast_rtp_read(struct ast_rtp_instance *instance, int rtc
                }
        }
 
-       if (rtp->f.subclass.codec & 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.codec == AST_FORMAT_SLINEAR) || (rtp->f.subclass.codec == AST_FORMAT_SLINEAR16)) {
+               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 / (rtp_get_rate(rtp->f.subclass.codec) / 1000);
-               rtp->f.len = rtp->f.samples / ((ast_format_rate(rtp->f.subclass.codec) / 1000));
-       } else if (rtp->f.subclass.codec & 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;
@@ -2250,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.codec |= 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)
@@ -2283,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);
@@ -2319,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;
@@ -2338,14 +2403,14 @@ 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 sockaddr_in *sin)
+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
         */
-       rtp->alt_rtp_address = *sin;
+       ast_sockaddr_copy(&rtp->alt_rtp_address, addr);
 
        return;
 }
@@ -2373,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.codec = 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;
@@ -2485,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);
@@ -2506,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 = ast_strdupa(a->argv[4]);
-
-       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 = ast_strdupa(a->argv[4]);
-
-       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;
 }
@@ -2773,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,
                );