Asterisk.org: Developer Documentation (28 Oct 2009)

Wed Oct 28 15:49:17 2009

## Asterisk developer's documentation

# rtp.h File Reference

Supports RTP and RTCP with Symmetric RTP support for NAT traversal. More...

`#include "asterisk/frame.h"`
`#include "asterisk/io.h"`
`#include "asterisk/sched.h"`
`#include "asterisk/channel.h"`
`#include <netinet/in.h>`

Include dependency graph for rtp.h:

This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

## Data Structures

struct | ast_rtp_protocol

## Defines

#define | AST_RTP_CISCO_DTMF (1 << 2)
#define | AST_RTP_CN (1 << 1)
#define | AST_RTP_DTMF (1 << 0)
#define | AST_RTP_MAX AST_RTP_CISCO_DTMF

## Typedefs

typedef int(* | ast_rtp_callback )(struct ast_rtp *rtp, struct ast_frame *f, void *data)

## Functions

int | ast_rtcp_fd (struct ast_rtp *rtp)
struct ast_frame * | ast_rtcp_read (struct ast_rtp *rtp)
int | ast_rtp_bridge (struct ast_channel *c0, struct ast_channel *c1, int flags, struct ast_frame **fo, struct ast_channel **rc, int timeoutms)
void | ast_rtp_destroy (struct ast_rtp *rtp)
int | ast_rtp_fd (struct ast_rtp *rtp)
void | ast_rtp_get_current_formats (struct ast_rtp *rtp, int *astFormats, int *nonAstFormats)
int | ast_rtp_get_peer (struct ast_rtp *rtp, struct sockaddr_in *them)
void | ast_rtp_get_us (struct ast_rtp *rtp, struct sockaddr_in *us)
void | ast_rtp_init (void)
int | ast_rtp_lookup_code (struct ast_rtp *rtp, int isAstFormat, int code)
char * | ast_rtp_lookup_mime_multiple (char *buf, int size, const int capability, const int isAstFormat)
char * | ast_rtp_lookup_mime_subtype (int isAstFormat, int code)
struct rtpPayloadType | ast_rtp_lookup_pt (struct ast_rtp *rtp, int pt)
struct ast_rtp * | ast_rtp_new (struct sched_context *sched, struct io_context *io, int rtcpenable, int callbackmode)
| Initializate a RTP session.
struct ast_rtp * | ast_rtp_new_with_bindaddr (struct sched_context *sched, struct io_context *io, int rtcpenable, int callbackmode, struct in_addr in)
| Initializate a RTP session using an in_addr structure.
void | ast_rtp_offered_from_local (struct ast_rtp *rtp, int local)
int | ast_rtp_proto_register (struct ast_rtp_protocol *proto)
void | ast_rtp_proto_unregister (struct ast_rtp_protocol *proto)
void | ast_rtp_pt_clear (struct ast_rtp *rtp)
void | ast_rtp_pt_default (struct ast_rtp *rtp)
struct ast_frame * | ast_rtp_read (struct ast_rtp *rtp)
void | ast_rtp_reload (void)
void | ast_rtp_reset (struct ast_rtp *rtp)
int | ast_rtp_sendcng (struct ast_rtp *rtp, int level)
int | ast_rtp_senddigit (struct ast_rtp *rtp, char digit)
void | ast_rtp_set_callback (struct ast_rtp *rtp, ast_rtp_callback callback)
void | ast_rtp_set_data (struct ast_rtp *rtp, void *data)
void | ast_rtp_set_m_type (struct ast_rtp *rtp, int pt)
void | ast_rtp_set_peer (struct ast_rtp *rtp, struct sockaddr_in *them)
void | ast_rtp_set_rtpmap_type (struct ast_rtp *rtp, int pt, char *mimeType, char *mimeSubtype)
void | ast_rtp_setnat (struct ast_rtp *rtp, int nat)
int | ast_rtp_settos (struct ast_rtp *rtp, int tos)
void | ast_rtp_stop (struct ast_rtp *rtp)
int | ast_rtp_write (struct ast_rtp *rtp, struct ast_frame *f)

## Detailed Description

Supports RTP and RTCP with Symmetric RTP support for NAT traversal.

RTP is defined in RFC 3550.

Definition in file rtp.h.

## Define Documentation

#define AST_RTP_CISCO_DTMF (1 << 2)

DTMF (Cisco Proprietary)

Definition at line 46 of file rtp.h.

Referenced by ast_rtp_read().

#define AST_RTP_CN (1 << 1)

'Comfort Noise' (RFC3389)

Definition at line 44 of file rtp.h.

Referenced by ast_rtp_read(), and ast_rtp_sendcng().

#define AST_RTP_DTMF (1 << 0)

DTMF (RFC2833)

Definition at line 42 of file rtp.h.

Referenced by add_noncodec_to_sdp(), add_sdp(), ast_rtp_read(), ast_rtp_senddigit(), check_user_full(), create_addr(), create_addr_from_peer(), oh323_alloc(), oh323_request(), process_sdp(), and sip_alloc().

#define AST_RTP_MAX AST_RTP_CISCO_DTMF

Maximum RTP-specific code

Definition at line 48 of file rtp.h.

Referenced by add_sdp(), and ast_rtp_lookup_mime_multiple().

## Typedef Documentation

typedef int(* ast_rtp_callback)(struct ast_rtp *rtp, struct ast_frame *f, void *data)

Definition at line 70 of file rtp.h.

## Function Documentation

int ast_rtcp_fd | ( | struct ast_rtp * | rtp | ) |

Definition at line 158 of file rtp.c.

References ast_rtp::rtcp, and ast_rtcp::s.

Referenced by sip_new().

    00159 {
    00160    if (rtp->rtcp)
    00161       return rtp->rtcp->s;
    00162    return -1;
    00163 }

struct ast_frame* ast_rtcp_read | ( | struct ast_rtp * | rtp | ) | `[read]`

Definition at line 370 of file rtp.c.

References AST_FRAME_NULL, ast_inet_ntoa(), ast_log(), CRASH, LOG_DEBUG, LOG_WARNING, ast_rtp::nat, option_debug, ast_rtp::rtcp, ast_rtcp::s, and ast_rtcp::them.

Referenced by sip_rtp_read().

    00371 {
    00372    static struct ast_frame null_frame = { AST_FRAME_NULL, };
    00373    socklen_t len;
    00374    int hdrlen = 8;
    00375    int res;
    00376    struct sockaddr_in sin;
    00377    unsigned int rtcpdata[1024];
    00378    char iabuf[INET_ADDRSTRLEN];
    00379
    00380    if (!rtp || !rtp->rtcp)
    00381       return &null_frame;
    00382
    00383    len = sizeof(sin);
    00384
    00385    res = recvfrom(rtp->rtcp->s, rtcpdata, sizeof(rtcpdata),
    00386                0, (struct sockaddr *)&sin, &len);
    00387
    00388    if (res < 0) {
    00389       if (errno == EBADF)
    00390          CRASH;
    00391       if (errno != EAGAIN) {
    00392          ast_log(LOG_WARNING, "RTP Read error: %s.  Hanging up now.\n", strerror(errno));
    00393          return NULL;
    00394       }
    00395       return &null_frame;
    00396    }
    00397
    00398    if (res < hdrlen) {
    00399       ast_log(LOG_WARNING, "RTP Read too short\n");
    00400       return &null_frame;
    00401    }
    00402
    00403    if (rtp->nat) {
    00404       /* Send to whoever sent to us */
    00405       if ((rtp->rtcp->them.sin_addr.s_addr != sin.sin_addr.s_addr) ||
    00406           (rtp->rtcp->them.sin_port != sin.sin_port)) {
    00407          memcpy(&rtp->rtcp->them, &sin, sizeof(rtp->rtcp->them));
    00408          if (option_debug || rtpdebug)
    00409             ast_log(LOG_DEBUG, "RTCP NAT: Got RTCP from other end. Now sending to address %s:%d\n", ast_inet_ntoa(iabuf, sizeof(iabuf), rtp->rtcp->them.sin_addr), ntohs(rtp->rtcp->them.sin_port));
    00410       }
    00411    }
    00412    if (option_debug)
    00413       ast_log(LOG_DEBUG, "Got RTCP report of %d bytes\n", res);
    00414    return &null_frame;
    00415 }

int ast_rtp_bridge | ( | struct ast_channel * | c0,
|  | struct ast_channel * | c1,
|  | int | flags,
|  | struct ast_frame ** | fo,
|  | struct ast_channel ** | rc,
|  | int | timeoutms |
| ) |  |  |

Definition at line 1539 of file rtp.c.

References ast_channel::_softhangup, AST_BRIDGE_COMPLETE, AST_BRIDGE_DTMF_CHANNEL_0, AST_BRIDGE_DTMF_CHANNEL_1, AST_BRIDGE_FAILED, AST_BRIDGE_FAILED_NOWARN, AST_BRIDGE_IGNORE_SIGS, AST_BRIDGE_RETRY, ast_check_hangup(), AST_CONTROL_HOLD, AST_CONTROL_UNHOLD, AST_CONTROL_VIDUPDATE, AST_FRAME_CONTROL, AST_FRAME_DTMF, AST_FRAME_VIDEO, AST_FRAME_VOICE, ast_frfree(), ast_indicate(), ast_inet_ntoa(), ast_log(), ast_mutex_lock(), ast_mutex_trylock(), ast_mutex_unlock(), ast_read(), ast_rtp_get_peer(), ast_test_flag, ast_waitfor_n(), ast_write(), FLAG_NAT_ACTIVE, ast_frame::frametype, ast_rtp_protocol::get_codec, get_proto(), ast_rtp_protocol::get_rtp_info, ast_rtp_protocol::get_vrtp_info, inaddrcmp(), ast_channel::lock, LOG_DEBUG, LOG_WARNING, ast_channel::masq, ast_channel::masqr, ast_channel::name, option_debug, ast_rtp_protocol::set_rtp_peer, ast_frame::subclass, and ast_channel::tech_pvt.

    01540 {
    01541    struct ast_frame *f;
    01542    struct ast_channel *who, *cs[3];
    01543    struct ast_rtp *p0, *p1;      /* Audio RTP Channels */
    01544    struct ast_rtp *vp0, *vp1;    /* Video RTP channels */
    01545    struct ast_rtp_protocol *pr0, *pr1;
    01546    struct sockaddr_in ac0, ac1;
    01547    struct sockaddr_in vac0, vac1;
    01548    struct sockaddr_in t0, t1;
    01549    struct sockaddr_in vt0, vt1;
    01550    char iabuf[INET_ADDRSTRLEN];
    01551
    01552    void *pvt0, *pvt1;
    01553    int codec0,codec1, oldcodec0, oldcodec1;
    01554
    01555    memset(&vt0, 0, sizeof(vt0));
    01556    memset(&vt1, 0, sizeof(vt1));
    01557    memset(&vac0, 0, sizeof(vac0));
    01558    memset(&vac1, 0, sizeof(vac1));
    01559
    01560    /* if need DTMF, cant native bridge */
    01561    if (flags & (AST_BRIDGE_DTMF_CHANNEL_0 | AST_BRIDGE_DTMF_CHANNEL_1))
    01562       return AST_BRIDGE_FAILED_NOWARN;
    01563
    01564    /* Lock channels */
    01565    ast_mutex_lock(&c0->lock);
    01566    while(ast_mutex_trylock(&c1->lock)) {
    01567       ast_mutex_unlock(&c0->lock);
    01568       usleep(1);
    01569       ast_mutex_lock(&c0->lock);
    01570    }
    01571
    01572    /* Find channel driver interfaces */
    01573    pr0 = get_proto(c0);
    01574    pr1 = get_proto(c1);
    01575    if (!pr0) {
    01576       ast_log(LOG_WARNING, "Can't find native functions for channel '%s'\n", c0->name);
    01577       ast_mutex_unlock(&c0->lock);
    01578       ast_mutex_unlock(&c1->lock);
    01579       return AST_BRIDGE_FAILED;
    01580    }
    01581    if (!pr1) {
    01582       ast_log(LOG_WARNING, "Can't find native functions for channel '%s'\n", c1->name);
    01583       ast_mutex_unlock(&c0->lock);
    01584       ast_mutex_unlock(&c1->lock);
    01585       return AST_BRIDGE_FAILED;
    01586    }
    01587
    01588    /* Get channel specific interface structures */
    01589    pvt0 = c0->tech_pvt;
    01590    pvt1 = c1->tech_pvt;
    01591
    01592    /* Get audio and video interface (if native bridge is possible) */
    01593    p0 = pr0->get_rtp_info(c0);
    01594    if (pr0->get_vrtp_info)
    01595       vp0 = pr0->get_vrtp_info(c0);
    01596    else
    01597       vp0 = NULL;
    01598    p1 = pr1->get_rtp_info(c1);
    01599    if (pr1->get_vrtp_info)
    01600       vp1 = pr1->get_vrtp_info(c1);
    01601    else
    01602       vp1 = NULL;
    01603
    01604    /* Check if bridge is still possible (In SIP canreinvite=no stops this, like NAT) */
    01605    if (!p0 || !p1) {
    01606       /* Somebody doesn't want to play... */
    01607       ast_mutex_unlock(&c0->lock);
    01608       ast_mutex_unlock(&c1->lock);
    01609       return AST_BRIDGE_FAILED_NOWARN;
    01610    }
    01611    /* Get codecs from both sides */
    01612    if (pr0->get_codec)
    01613       codec0 = pr0->get_codec(c0);
    01614    else
    01615       codec0 = 0;
    01616    if (pr1->get_codec)
    01617       codec1 = pr1->get_codec(c1);
    01618    else
    01619       codec1 = 0;
    01620    if (pr0->get_codec && pr1->get_codec) {
    01621       /* Hey, we can't do reinvite if both parties speak different codecs */
    01622       if (!(codec0 & codec1)) {
    01623          if (option_debug)
    01624             ast_log(LOG_DEBUG, "Channel codec0 = %d is not codec1 = %d, cannot native bridge in RTP.\n", codec0, codec1);
    01625          ast_mutex_unlock(&c0->lock);
    01626          ast_mutex_unlock(&c1->lock);
    01627          return AST_BRIDGE_FAILED_NOWARN;
    01628       }
    01629    }
    01630
    01631    /* Ok, we should be able to redirect the media. Start with one channel */
    01632    if (pr0->set_rtp_peer(c0, p1, vp1, codec1, ast_test_flag(p1, FLAG_NAT_ACTIVE)))
    01633       ast_log(LOG_WARNING, "Channel '%s' failed to talk to '%s'\n", c0->name, c1->name);
    01634    else {
    01635       /* Store RTP peer */
    01636       ast_rtp_get_peer(p1, &ac1);
    01637       if (vp1)
    01638          ast_rtp_get_peer(vp1, &vac1);
    01639    }
    01640    /* Then test the other channel */
    01641    if (pr1->set_rtp_peer(c1, p0, vp0, codec0, ast_test_flag(p0, FLAG_NAT_ACTIVE)))
    01642       ast_log(LOG_WARNING, "Channel '%s' failed to talk back to '%s'\n", c1->name, c0->name);
    01643    else {
    01644       /* Store RTP peer */
    01645       ast_rtp_get_peer(p0, &ac0);
    01646       if (vp0)
    01647          ast_rtp_get_peer(vp0, &vac0);
    01648    }
    01649    ast_mutex_unlock(&c0->lock);
    01650    ast_mutex_unlock(&c1->lock);
    01651    /* External RTP Bridge up, now loop and see if something happes that force us to take the
    01652       media back to Asterisk */
    01653    cs[0] = c0;
    01654    cs[1] = c1;
    01655    cs[2] = NULL;
    01656    oldcodec0 = codec0;
    01657    oldcodec1 = codec1;
    01658    for (;;) {
    01659       /* Check if something changed... */
    01660       if ((c0->tech_pvt != pvt0)  ||
    01661          (c1->tech_pvt != pvt1) ||
    01662          (c0->masq || c0->masqr || c1->masq || c1->masqr)) {
    01663             ast_log(LOG_DEBUG, "Oooh, something is weird, backing out\n");
    01664             if (c0->tech_pvt == pvt0) {
    01665                if (pr0->set_rtp_peer(c0, NULL, NULL, 0, 0))
    01666                   ast_log(LOG_WARNING, "Channel '%s' failed to break RTP bridge\n", c0->name);
    01667             }
    01668             if (c1->tech_pvt == pvt1) {
    01669                if (pr1->set_rtp_peer(c1, NULL, NULL, 0, 0))
    01670                   ast_log(LOG_WARNING, "Channel '%s' failed to break RTP bridge\n", c1->name);
    01671             }
    01672             return AST_BRIDGE_RETRY;
    01673       }
    01674       /* Now check if they have changed address */
    01675       ast_rtp_get_peer(p1, &t1);
    01676       ast_rtp_get_peer(p0, &t0);
    01677       if (pr0->get_codec)
    01678          codec0 = pr0->get_codec(c0);
    01679       if (pr1->get_codec)
    01680          codec1 = pr1->get_codec(c1);
    01681       if (vp1)
    01682          ast_rtp_get_peer(vp1, &vt1);
    01683       if (vp0)
    01684          ast_rtp_get_peer(vp0, &vt0);
    01685       if (inaddrcmp(&t1, &ac1) || (vp1 && inaddrcmp(&vt1, &vac1)) || (codec1 != oldcodec1)) {
    01686          if (option_debug > 1) {
    01687             ast_log(LOG_DEBUG, "Oooh, '%s' changed end address to %s:%d (format %d)\n",
    01688                c1->name, ast_inet_ntoa(iabuf, sizeof(iabuf), t1.sin_addr), ntohs(t1.sin_port), codec1);
    01689             ast_log(LOG_DEBUG, "Oooh, '%s' changed end vaddress to %s:%d (format %d)\n",
    01690                c1->name, ast_inet_ntoa(iabuf, sizeof(iabuf), vt1.sin_addr), ntohs(vt1.sin_port), codec1);
    01691             ast_log(LOG_DEBUG, "Oooh, '%s' was %s:%d/(format %d)\n",
    01692                c1->name, ast_inet_ntoa(iabuf, sizeof(iabuf), ac1.sin_addr), ntohs(ac1.sin_port), oldcodec1);
    01693             ast_log(LOG_DEBUG, "Oooh, '%s' was %s:%d/(format %d)\n",
    01694                c1->name, ast_inet_ntoa(iabuf, sizeof(iabuf), vac1.sin_addr), ntohs(vac1.sin_port), oldcodec1);
    01695          }
    01696          if (pr0->set_rtp_peer(c0, t1.sin_addr.s_addr ? p1 : NULL, vt1.sin_addr.s_addr ? vp1 : NULL, codec1, ast_test_flag(p1, FLAG_NAT_ACTIVE)))
    01697             ast_log(LOG_WARNING, "Channel '%s' failed to update to '%s'\n", c0->name, c1->name);
    01698          memcpy(&ac1, &t1, sizeof(ac1));
    01699          memcpy(&vac1, &vt1, sizeof(vac1));
    01700          oldcodec1 = codec1;
    01701       }
    01702       if (inaddrcmp(&t0, &ac0) || (vp0 && inaddrcmp(&vt0, &vac0))) {
    01703          if (option_debug) {
    01704             ast_log(LOG_DEBUG, "Oooh, '%s' changed end address to %s:%d (format %d)\n",
    01705                c0->name, ast_inet_ntoa(iabuf, sizeof(iabuf), t0.sin_addr), ntohs(t0.sin_port), codec0);
    01706             ast_log(LOG_DEBUG, "Oooh, '%s' was %s:%d/(format %d)\n",
    01707                c0->name, ast_inet_ntoa(iabuf, sizeof(iabuf), ac0.sin_addr), ntohs(ac0.sin_port), oldcodec0);
    01708          }
    01709          if (pr1->set_rtp_peer(c1, t0.sin_addr.s_addr ? p0 : NULL, vt0.sin_addr.s_addr ? vp0 : NULL, codec0, ast_test_flag(p0, FLAG_NAT_ACTIVE)))
    01710             ast_log(LOG_WARNING, "Channel '%s' failed to update to '%s'\n", c1->name, c0->name);
    01711          memcpy(&ac0, &t0, sizeof(ac0));
    01712          memcpy(&vac0, &vt0, sizeof(vac0));
    01713          oldcodec0 = codec0;
    01714       }
    01715       who = ast_waitfor_n(cs, 2, &timeoutms);
    01716       if (!who) {
    01717          if (!timeoutms) {
    01718             if (pr0->set_rtp_peer(c0, NULL, NULL, 0, 0))
    01719                ast_log(LOG_WARNING, "Channel '%s' failed to break RTP bridge\n", c0->name);
    01720             if (pr1->set_rtp_peer(c1, NULL, NULL, 0, 0))
    01721                ast_log(LOG_WARNING, "Channel '%s' failed to break RTP bridge\n", c1->name);
    01722             return AST_BRIDGE_RETRY;
    01723          }
    01724          if (option_debug)
    01725             ast_log(LOG_DEBUG, "Ooh, empty read...\n");
    01726          /* check for hangup / whentohangup */
    01727          if (ast_check_hangup(c0) || ast_check_hangup(c1))
    01728             break;
    01729          continue;
    01730       }
    01731       f = ast_read(who);
    01732       if (!f || ((f->frametype == AST_FRAME_DTMF) &&
    01733                (((who == c0) && (flags & AST_BRIDGE_DTMF_CHANNEL_0)) ||
    01734                 ((who == c1) && (flags & AST_BRIDGE_DTMF_CHANNEL_1))))) {
    01735          *fo = f;
    01736          *rc = who;
    01737          if (option_debug)
    01738             ast_log(LOG_DEBUG, "Oooh, got a %s\n", f ? "digit" : "hangup");
    01739          if ((c0->tech_pvt == pvt0) && (!c0->_softhangup)) {
    01740             if (pr0->set_rtp_peer(c0, NULL, NULL, 0, 0))
    01741                ast_log(LOG_WARNING, "Channel '%s' failed to break RTP bridge\n", c0->name);
    01742          }
    01743          if ((c1->tech_pvt == pvt1) && (!c1->_softhangup)) {
    01744             if (pr1->set_rtp_peer(c1, NULL, NULL, 0, 0))
    01745                ast_log(LOG_WARNING, "Channel '%s' failed to break RTP bridge\n", c1->name);
    01746          }
    01747          return AST_BRIDGE_COMPLETE;
    01748       } else if ((f->frametype == AST_FRAME_CONTROL) && !(flags & AST_BRIDGE_IGNORE_SIGS)) {
    01749          if ((f->subclass == AST_CONTROL_HOLD) || (f->subclass == AST_CONTROL_UNHOLD) ||
    01750              (f->subclass == AST_CONTROL_VIDUPDATE)) {
    01751             ast_indicate(who == c0 ? c1 : c0, f->subclass);
    01752             ast_frfree(f);
    01753          } else {
    01754             *fo = f;
    01755             *rc = who;
    01756             ast_log(LOG_DEBUG, "Got a FRAME_CONTROL (%d) frame on channel %s\n", f->subclass, who->name);
    01757             return AST_BRIDGE_COMPLETE;
    01758          }
    01759       } else {
    01760          if ((f->frametype == AST_FRAME_DTMF) ||
    01761             (f->frametype == AST_FRAME_VOICE) ||
    01762             (f->frametype == AST_FRAME_VIDEO)) {
    01763             /* Forward voice or DTMF frames if they happen upon us */
    01764             if (who == c0) {
    01765                ast_write(c1, f);
    01766             } else if (who == c1) {
    01767                ast_write(c0, f);
    01768             }
    01769          }
    01770          ast_frfree(f);
    01771       }
    01772       /* Swap priority not that it's a big deal at this point */
    01773       cs[2] = cs[0];
    01774       cs[0] = cs[1];
    01775       cs[1] = cs[2];
    01776
    01777    }
    01778
    01779    if (pr0->set_rtp_peer(c0, NULL, NULL, 0, 0))
    01780       ast_log(LOG_WARNING, "Channel '%s' failed to break RTP bridge\n", c0->name);
    01781    if (pr1->set_rtp_peer(c1, NULL, NULL, 0, 0))
    01782       ast_log(LOG_WARNING, "Channel '%s' failed to break RTP bridge\n", c1->name);
    01783
    01784    return AST_BRIDGE_FAILED;
    01785 }

void ast_rtp_destroy | ( | struct ast_rtp * | rtp | ) |

Definition at line 1105 of file rtp.c.

References ast_io_remove(), ast_smoother_free(), free, ast_rtp::io, ast_rtp::ioid, ast_rtp::rtcp, ast_rtcp::s, ast_rtp::s, and ast_rtp::smoother.

Referenced by __oh323_destroy(), __sip_destroy(), cleanup_connection(), destroy_endpoint(), mgcp_hangup(), skinny_hangup(), start_rtp(), and unalloc_sub().

    01106 {
    01107    if (rtp->smoother)
    01108       ast_smoother_free(rtp->smoother);
    01109    if (rtp->ioid)
    01110       ast_io_remove(rtp->io, rtp->ioid);
    01111    if (rtp->s > -1)
    01112       close(rtp->s);
    01113    if (rtp->rtcp) {
    01114       close(rtp->rtcp->s);
    01115       free(rtp->rtcp);
    01116    }
    01117    free(rtp);
    01118 }

int ast_rtp_fd | ( | struct ast_rtp * | rtp | ) |

Definition at line 153 of file rtp.c.

References ast_rtp::s.

Referenced by __oh323_new(), mgcp_new(), sip_new(), skinny_new(), and start_rtp().

    00154 {
    00155    return rtp->s;
    00156 }

void ast_rtp_get_current_formats | ( | struct ast_rtp * | rtp,
|  | int * | astFormats,
|  | int * | nonAstFormats |
| ) |  |  |

Definition at line 782 of file rtp.c.

References rtpPayloadType::code, ast_rtp::current_RTP_PT, rtpPayloadType::isAstFormat, and MAX_RTP_PT.

Referenced by process_sdp().

    00783                                                    {
    00784    int pt;
    00785
    00786    *astFormats = *nonAstFormats = 0;
    00787    for (pt = 0; pt < MAX_RTP_PT; ++pt) {
    00788       if (rtp->current_RTP_PT[pt].isAstFormat) {
    00789          *astFormats |= rtp->current_RTP_PT[pt].code;
    00790       } else {
    00791          *nonAstFormats |= rtp->current_RTP_PT[pt].code;
    00792       }
    00793    }
    00794 }

int ast_rtp_get_peer | ( | struct ast_rtp * | rtp,
|  | struct sockaddr_in * | them |
| ) |  |  |

Definition at line 1057 of file rtp.c.

References ast_rtp::them.

Referenced by add_sdp(), ast_rtp_bridge(), do_monitor(), oh323_set_rtp_peer(), sip_set_rtp_peer(), and transmit_modify_with_sdp().

    01058 {
    01059    if ((them->sin_family != AF_INET) ||
    01060        (them->sin_port != rtp->them.sin_port) ||
    01061        (them->sin_addr.s_addr != rtp->them.sin_addr.s_addr)) {
    01062       them->sin_family = AF_INET;
    01063       them->sin_port = rtp->them.sin_port;
    01064       them->sin_addr = rtp->them.sin_addr;
    01065       return 1;
    01066    }
    01067    return 0;
    01068 }

void ast_rtp_get_us | ( | struct ast_rtp * | rtp,
|  | struct sockaddr_in * | us |
| ) |  |  |

Definition at line 1070 of file rtp.c.

References ast_rtp::us.

Referenced by add_sdp(), external_rtp_create(), handle_message(), and oh323_set_rtp_peer().

    01071 {
    01072    memcpy(us, &rtp->us, sizeof(rtp->us));
    01073 }

void ast_rtp_init | ( | void |  | ) |

Definition at line 1913 of file rtp.c.

References ast_cli_register(), and ast_rtp_reload().

Referenced by main().

    01914 {
    01915    ast_cli_register(&cli_debug);
    01916    ast_cli_register(&cli_debug_ip);
    01917    ast_cli_register(&cli_no_debug);
    01918    ast_rtp_reload();
    01919 }

int ast_rtp_lookup_code | ( | struct ast_rtp * | rtp,
|  | int | isAstFormat,
|  | int | code |
| ) |  |  |

Definition at line 822 of file rtp.c.

References rtpPayloadType::code, ast_rtp::current_RTP_PT, rtpPayloadType::isAstFormat, MAX_RTP_PT, ast_rtp::rtp_lookup_code_cache_code, ast_rtp::rtp_lookup_code_cache_isAstFormat, and ast_rtp::rtp_lookup_code_cache_result.

Referenced by add_codec_to_sdp(), add_noncodec_to_sdp(), add_sdp(), ast_rtp_sendcng(), ast_rtp_senddigit(), and ast_rtp_write().

    00822                                                                                     {
    00823
    00824    int pt;
    00825
    00826    if (isAstFormat == rtp->rtp_lookup_code_cache_isAstFormat &&
    00827       code == rtp->rtp_lookup_code_cache_code) {
    00828
    00829       /* Use our cached mapping, to avoid the overhead of the loop below */
    00830       return rtp->rtp_lookup_code_cache_result;
    00831    }
    00832
    00833    /* Check the dynamic list first */
    00834    for (pt = 0; pt < MAX_RTP_PT; ++pt) {
    00835       if (rtp->current_RTP_PT[pt].code == code && rtp->current_RTP_PT[pt].isAstFormat == isAstFormat) {
    00836          rtp->rtp_lookup_code_cache_isAstFormat = isAstFormat;
    00837          rtp->rtp_lookup_code_cache_code = code;
    00838          rtp->rtp_lookup_code_cache_result = pt;
    00839          return pt;
    00840       }
    00841    }
    00842
    00843    /* Then the static list */
    00844    for (pt = 0; pt < MAX_RTP_PT; ++pt) {
    00845       if (static_RTP_PT[pt].code == code && static_RTP_PT[pt].isAstFormat == isAstFormat) {
    00846          rtp->rtp_lookup_code_cache_isAstFormat = isAstFormat;
    00847          rtp->rtp_lookup_code_cache_code = code;
    00848          rtp->rtp_lookup_code_cache_result = pt;
    00849          return pt;
    00850       }
    00851    }
    00852    return -1;
    00853 }

char* ast_rtp_lookup_mime_multiple | ( | char * | buf,
|  | int | size,
|  | const int | capability,
|  | const int | isAstFormat |
| ) |  |  |

Definition at line 867 of file rtp.c.

References ast_rtp_lookup_mime_subtype(), AST_RTP_MAX, format, and name.

Referenced by process_sdp().

    00868 {
    00869    int format;
    00870    unsigned len;
    00871    char *end = buf;
    00872    char *start = buf;
    00873
    00874    if (!buf || !size)
    00875       return NULL;
    00876
    00877    snprintf(end, size, "0x%x (", capability);
    00878
    00879    len = strlen(end);
    00880    end += len;
    00881    size -= len;
    00882    start = end;
    00883
    00884    for (format = 1; format < AST_RTP_MAX; format <<= 1) {
    00885       if (capability & format) {
    00886          const char *name = ast_rtp_lookup_mime_subtype(isAstFormat, format);
    00887          snprintf(end, size, "%s|", name);
    00888          len = strlen(end);
    00889          end += len;
    00890          size -= len;
    00891       }
    00892    }
    00893
    00894    if (start == end)
    00895       snprintf(start, size, "nothing)");
    00896    else if (size > 1)
    00897       *(end -1) = ')';
    00898
    00899    return buf;
    00900 }

char* ast_rtp_lookup_mime_subtype | ( | int | isAstFormat,
|  | int | code |
| ) |  |  |

Definition at line 855 of file rtp.c.

References rtpPayloadType::code, mimeTypes, and payloadType.

Referenced by add_codec_to_sdp(), add_noncodec_to_sdp(), add_sdp(), ast_rtp_lookup_mime_multiple(), transmit_connect_with_sdp(), and transmit_modify_with_sdp().

    00855                                                                          {
    00856
    00857    int i;
    00858
    00859    for (i = 0; i < sizeof mimeTypes/sizeof mimeTypes[0]; ++i) {
    00860    if (mimeTypes[i].payloadType.code == code && mimeTypes[i].payloadType.isAstFormat == isAstFormat) {
    00861             return mimeTypes[i].subtype;
    00862       }
    00863    }
    00864    return "";
    00865 }

struct rtpPayloadType ast_rtp_lookup_pt | ( | struct ast_rtp * | rtp,
|  | int | pt |
| ) |  |  | `[read]`

Definition at line 803 of file rtp.c.

References rtpPayloadType::code, rtpPayloadType::isAstFormat, and MAX_RTP_PT.

Referenced by ast_rtp_read(), and setup_rtp_connection().

    00804 {
    00805    struct rtpPayloadType result;
    00806
    00807    result.isAstFormat = result.code = 0;
    00808    if (pt < 0 || pt > MAX_RTP_PT)
    00809       return result; /* bogus payload type */
    00810
    00811    /* Start with the negotiated codecs */
    00812    if (!rtp->rtp_offered_from_local)
    00813       result = rtp->current_RTP_PT[pt];
    00814
    00815    /* If it doesn't exist, check our static RTP type list, just in case */
    00816    if (!result.code)
    00817       result = static_RTP_PT[pt];
    00818    return result;
    00819 }

struct ast_rtp* ast_rtp_new | ( | struct sched_context * | sched,
|  | struct io_context * | io,
|  | int | rtcpenable,
|  | int | callbackmode |
| ) |  |  | `[read]`

Initializate a RTP session.

Parameters:

  | sched |
  | io |
  | rtcpenable |
  | callbackmode |

Returns:
  A representation (structure) of an RTP session.

Definition at line 1029 of file rtp.c.

References ast_rtp_new_with_bindaddr().

Referenced by start_rtp().

    01030 {
    01031    struct in_addr ia;
    01032
    01033    memset(&ia, 0, sizeof(ia));
    01034    return ast_rtp_new_with_bindaddr(sched, io, rtcpenable, callbackmode, ia);
    01035 }

struct ast_rtp* ast_rtp_new_with_bindaddr | ( | struct sched_context * | sched,
|  | struct io_context * | io,
|  | int | rtcpenable,
|  | int | callbackmode,
|  | struct in_addr | in |
| ) |  |  | `[read]`

Initializate a RTP session using an in_addr structure.

This fuction gets called by ast_rtp_new().

Parameters:

  | sched |
  | io |
  | rtcpenable |
  | callbackmode |
  | in |

Returns:
  A representation (structure) of an RTP session.

Definition at line 940 of file rtp.c.

References ast_io_add(), AST_IO_IN, ast_log(), ast_rtcp_new(), ast_rtp_pt_default(), free, ast_rtp::io, ast_rtp::ioid, LOG_ERROR, malloc, ast_rtp::rtcp, rtp_socket(), rtpread(), ast_rtcp::s, ast_rtp::s, ast_rtp::sched, ast_rtp::seqno, ast_rtp::ssrc, ast_rtp::them, ast_rtcp::us, and ast_rtp::us.

Referenced by ast_rtp_new(), oh323_alloc(), sip_alloc(), and start_rtp().

    00941 {
    00942    struct ast_rtp *rtp;
    00943    int x;
    00944    int first;
    00945    int startplace;
    00946    rtp = malloc(sizeof(struct ast_rtp));
    00947    if (!rtp)
    00948       return NULL;
    00949    memset(rtp, 0, sizeof(struct ast_rtp));
    00950    rtp->them.sin_family = AF_INET;
    00951    rtp->us.sin_family = AF_INET;
    00952    rtp->s = rtp_socket();
    00953    rtp->ssrc = rand();
    00954    rtp->seqno = rand() & 0xffff;
    00955    if (rtp->s < 0) {
    00956       free(rtp);
    00957       ast_log(LOG_ERROR, "Unable to allocate socket: %s\n", strerror(errno));
    00958       return NULL;
    00959    }
    00960    if (sched && rtcpenable) {
    00961       rtp->sched = sched;
    00962       rtp->rtcp = ast_rtcp_new();
    00963    }
    00964
    00965    /* Select a random port number in the range of possible RTP */
    00966    x = (rand() % (rtpend-rtpstart)) + rtpstart;
    00967    x = x & ~1;
    00968    /* Save it for future references. */
    00969    startplace = x;
    00970    /* Iterate tring to bind that port and incrementing it otherwise untill a port was found or no ports are available. */
    00971    for (;;) {
    00972       /* Must be an even port number by RTP spec */
    00973       rtp->us.sin_port = htons(x);
    00974       rtp->us.sin_addr = addr;
    00975       /* If there's rtcp, initialize it as well. */
    00976       if (rtp->rtcp) {
    00977          rtp->rtcp->us.sin_addr = addr;
    00978          rtp->rtcp->us.sin_port = htons(x + 1);
    00979       }
    00980       /* Try to bind it/them. */
    00981       if (!(first = bind(rtp->s, (struct sockaddr *)&rtp->us, sizeof(rtp->us))) &&
    00982          (!rtp->rtcp || !bind(rtp->rtcp->s, (struct sockaddr *)&rtp->rtcp->us, sizeof(rtp->rtcp->us))))
    00983          break;
    00984       if (!first) {
    00985          /* Primary bind succeeded! Gotta recreate it */
    00986          close(rtp->s);
    00987          rtp->s = rtp_socket();
    00988       }
    00989       if (errno != EADDRINUSE) {
    00990          /* We got an error that wasn't expected, abort! */
    00991          ast_log(LOG_ERROR, "Unexpected bind error: %s\n", strerror(errno));
    00992          close(rtp->s);
    00993          if (rtp->rtcp) {
    00994             close(rtp->rtcp->s);
    00995             free(rtp->rtcp);
    00996          }
    00997          free(rtp);
    00998          return NULL;
    00999       }
    01000       /* The port was used, increment it (by two). */
    01001       x += 2;
    01002       /* Did we go over the limit ? */
    01003       if (x > rtpend)
    01004          /* then, start from the begingig. */
    01005          x = (rtpstart + 1) & ~1;
    01006       /* Check if we reached the place were we started. */
    01007       if (x == startplace) {
    01008          /* If so, there's no ports available. */
    01009          ast_log(LOG_ERROR, "No RTP ports remaining. Can't setup media stream for this call.\n");
    01010          close(rtp->s);
    01011          if (rtp->rtcp) {
    01012             close(rtp->rtcp->s);
    01013             free(rtp->rtcp);
    01014          }
    01015          free(rtp);
    01016          return NULL;
    01017       }
    01018    }
    01019    if (io && sched && callbackmode) {
    01020       /* Operate this one in a callback mode */
    01021       rtp->sched = sched;
    01022       rtp->io = io;
    01023       rtp->ioid = ast_io_add(rtp->io, rtp->s, rtpread, AST_IO_IN, rtp);
    01024    }
    01025    ast_rtp_pt_default(rtp);
    01026    return rtp;
    01027 }

void ast_rtp_offered_from_local | ( | struct ast_rtp * | rtp,
|  | int | local |
| ) |  |  |

Definition at line 796 of file rtp.c.

References ast_log(), LOG_WARNING, and ast_rtp::rtp_offered_from_local.

Referenced by transmit_connect_with_sdp(), transmit_invite(), transmit_modify_with_sdp(), transmit_reinvite_with_sdp(), and transmit_response_with_sdp().

    00796                                                                 {
    00797    if (rtp)
    00798       rtp->rtp_offered_from_local = local;
    00799    else
    00800       ast_log(LOG_WARNING, "rtp structure is null\n");
    00801 }

int ast_rtp_proto_register | ( | struct ast_rtp_protocol * | proto | ) |

Definition at line 1505 of file rtp.c.

References ast_log(), LOG_WARNING, ast_rtp_protocol::next, and ast_rtp_protocol::type.

Referenced by load_module(), and unload_module().

    01506 {
    01507    struct ast_rtp_protocol *cur;
    01508    cur = protos;
    01509    while(cur) {
    01510       if (cur->type == proto->type) {
    01511          ast_log(LOG_WARNING, "Tried to register same protocol '%s' twice\n", cur->type);
    01512          return -1;
    01513       }
    01514       cur = cur->next;
    01515    }
    01516    proto->next = protos;
    01517    protos = proto;
    01518    return 0;
    01519 }

void ast_rtp_proto_unregister | ( | struct ast_rtp_protocol * | proto | ) |

Definition at line 1485 of file rtp.c.

References ast_rtp_protocol::next.

Referenced by unload_module().

    01486 {
    01487    struct ast_rtp_protocol *cur, *prev;
    01488
    01489    cur = protos;
    01490    prev = NULL;
    01491    while(cur) {
    01492       if (cur == proto) {
    01493          if (prev)
    01494             prev->next = proto->next;
    01495          else
    01496             protos = proto->next;
    01497          return;
    01498       }
    01499       prev = cur;
    01500       cur = cur->next;
    01501    }
    01502 }

void ast_rtp_pt_clear | ( | struct ast_rtp * | rtp | ) |

Definition at line 719 of file rtp.c.

References rtpPayloadType::code, ast_rtp::current_RTP_PT, rtpPayloadType::isAstFormat, MAX_RTP_PT, ast_rtp::rtp_lookup_code_cache_code, ast_rtp::rtp_lookup_code_cache_isAstFormat, and ast_rtp::rtp_lookup_code_cache_result.

Referenced by process_sdp().

    00720 {
    00721    int i;
    00722    if (!rtp)
    00723       return;
    00724
    00725    for (i = 0; i < MAX_RTP_PT; ++i) {
    00726       rtp->current_RTP_PT[i].isAstFormat = 0;
    00727       rtp->current_RTP_PT[i].code = 0;
    00728    }
    00729
    00730    rtp->rtp_lookup_code_cache_isAstFormat = 0;
    00731    rtp->rtp_lookup_code_cache_code = 0;
    00732    rtp->rtp_lookup_code_cache_result = 0;
    00733 }

void ast_rtp_pt_default | ( | struct ast_rtp * | rtp | ) |

Definition at line 735 of file rtp.c.

References rtpPayloadType::code, ast_rtp::current_RTP_PT, rtpPayloadType::isAstFormat, MAX_RTP_PT, ast_rtp::rtp_lookup_code_cache_code, ast_rtp::rtp_lookup_code_cache_isAstFormat, and ast_rtp::rtp_lookup_code_cache_result.

Referenced by ast_rtp_new_with_bindaddr().

    00736 {
    00737    int i;
    00738
    00739    /* Initialize to default payload types */
    00740    for (i = 0; i < MAX_RTP_PT; ++i) {
    00741       rtp->current_RTP_PT[i].isAstFormat = static_RTP_PT[i].isAstFormat;
    00742       rtp->current_RTP_PT[i].code = static_RTP_PT[i].code;
    00743    }
    00744
    00745    rtp->rtp_lookup_code_cache_isAstFormat = 0;
    00746    rtp->rtp_lookup_code_cache_code = 0;
    00747    rtp->rtp_lookup_code_cache_result = 0;
    00748 }

struct ast_frame* ast_rtp_read | ( | struct ast_rtp * | rtp | ) | `[read]`

Definition at line 428 of file rtp.c.

References ast_codec_get_samples(), AST_FORMAT_MAX_AUDIO, AST_FORMAT_SLINEAR, ast_frame_byteswap_be, AST_FRAME_NULL, AST_FRAME_VIDEO, AST_FRAME_VOICE, AST_FRIENDLY_OFFSET, ast_inet_ntoa(), ast_log(), AST_RTP_CISCO_DTMF, AST_RTP_CN, AST_RTP_DTMF, ast_rtp_lookup_pt(), ast_set_flag, ast_verbose(), calc_rxstamp(), rtpPayloadType::code, CRASH, ast_frame::data, ast_frame::datalen, ast_frame::delivery, ast_rtp::dtmfcount, ast_rtp::f, FLAG_NAT_ACTIVE, ast_frame::frametype, rtpPayloadType::isAstFormat, ast_rtp::lasteventseqn, ast_rtp::lastividtimestamp, ast_rtp::lastrxformat, ast_rtp::lastrxts, LOG_DEBUG, LOG_NOTICE, LOG_WARNING, ast_frame::mallocd, ast_rtp::nat, ast_frame::offset, option_debug, process_cisco_dtmf(), process_rfc2833(), process_rfc3389(), ast_rtp::rawdata, ast_rtp::resp, rtp_debug_test_addr(), ast_rtp::rxseqno, ast_rtp::rxssrc, ast_rtp::s, ast_frame::samples, send_dtmf(), ast_frame::src, ast_frame::subclass, and ast_rtp::them.

Referenced by mgcp_rtp_read(), oh323_rtp_read(), rtpread(), sip_rtp_read(), and skinny_rtp_read().

    00429 {
    00430    int res;
    00431    struct sockaddr_in sin;
    00432    socklen_t len;
    00433    unsigned int seqno;
    00434    int version;
    00435    int payloadtype;
    00436    int hdrlen = 12;
    00437    int padding;
    00438    int mark;
    00439    int ext;
    00440    int cc;
    00441    int x;
    00442    char iabuf[INET_ADDRSTRLEN];
    00443    unsigned int ssrc;
    00444    unsigned int timestamp;
    00445    unsigned int *rtpheader;
    00446    struct ast_frame *f;
    00447    static struct ast_frame null_frame = { AST_FRAME_NULL, };
    00448    struct rtpPayloadType rtpPT;
    00449
    00450    len = sizeof(sin);
    00451
    00452    /* Cache where the header will go */
    00453    res = recvfrom(rtp->s, rtp->rawdata + AST_FRIENDLY_OFFSET, sizeof(rtp->rawdata) - AST_FRIENDLY_OFFSET,
    00454                0, (struct sockaddr *)&sin, &len);
    00455
    00456
    00457    rtpheader = (unsigned int *)(rtp->rawdata + AST_FRIENDLY_OFFSET);
    00458    if (res < 0) {
    00459       if (errno == EBADF)
    00460          CRASH;
    00461       if (errno != EAGAIN) {
    00462          ast_log(LOG_WARNING, "RTP Read error: %s.  Hanging up now.\n", strerror(errno));
    00463          return NULL;
    00464       }
    00465       return &null_frame;
    00466    }
    00467    if (res < hdrlen) {
    00468       ast_log(LOG_WARNING, "RTP Read too short\n");
    00469       return &null_frame;
    00470    }
    00471
    00472    /* Ignore if the other side hasn't been given an address
    00473       yet.  */
    00474    if (!rtp->them.sin_addr.s_addr || !rtp->them.sin_port)
    00475       return &null_frame;
    00476
    00477    if (rtp->nat) {
    00478       /* Send to whoever sent to us */
    00479       if ((rtp->them.sin_addr.s_addr != sin.sin_addr.s_addr) ||
    00480           (rtp->them.sin_port != sin.sin_port)) {
    00481          memcpy(&rtp->them, &sin, sizeof(rtp->them));
    00482          rtp->rxseqno = 0;
    00483          ast_set_flag(rtp, FLAG_NAT_ACTIVE);
    00484          if (option_debug || rtpdebug)
    00485             ast_log(LOG_DEBUG, "RTP NAT: Got audio from other end. Now sending to address %s:%d\n", ast_inet_ntoa(iabuf, sizeof(iabuf), rtp->them.sin_addr), ntohs(rtp->them.sin_port));
    00486       }
    00487    }
    00488
    00489    /* Get fields */
    00490    seqno = ntohl(rtpheader[0]);
    00491
    00492    /* Check RTP version */
    00493    version = (seqno & 0xC0000000) >> 30;
    00494    if (version != 2)
    00495       return &null_frame;
    00496
    00497    payloadtype = (seqno & 0x7f0000) >> 16;
    00498    padding = seqno & (1 << 29);
    00499    mark = seqno & (1 << 23);
    00500    ext = seqno & (1 << 28);
    00501    cc = (seqno & 0xF000000) >> 24;
    00502    seqno &= 0xffff;
    00503    timestamp = ntohl(rtpheader[1]);
    00504    ssrc = ntohl(rtpheader[2]);
    00505
    00506    if (!mark && rtp->rxssrc && rtp->rxssrc != ssrc) {
    00507       if (option_debug || rtpdebug)
    00508          ast_log(LOG_DEBUG, "Forcing Marker bit, because SSRC has changed\n");
    00509       mark = 1;
    00510    }
    00511
    00512    rtp->rxssrc = ssrc;
    00513
    00514    if (padding) {
    00515       /* Remove padding bytes */
    00516       res -= rtp->rawdata[AST_FRIENDLY_OFFSET + res - 1];
    00517    }
    00518
    00519    if (cc) {
    00520       /* CSRC fields present */
    00521       hdrlen += cc*4;
    00522    }
    00523
    00524    if (ext) {
    00525       /* RTP Extension present */
    00526       hdrlen += (ntohl(rtpheader[hdrlen/4]) & 0xffff) << 2;
    00527       hdrlen += 4;
    00528    }
    00529
    00530    if (res < hdrlen) {
    00531       ast_log(LOG_WARNING, "RTP Read too short (%d, expecting %d)\n", res, hdrlen);
    00532       return &null_frame;
    00533    }
    00534
    00535    if(rtp_debug_test_addr(&sin))
    00536       ast_verbose("Got RTP packet from %s:%u (type %d, seq %u, ts %u, len %d)\n"
    00537          , ast_inet_ntoa(iabuf, sizeof(iabuf), sin.sin_addr), ntohs(sin.sin_port), payloadtype, seqno, timestamp,res - hdrlen);
    00538
    00539    rtpPT = ast_rtp_lookup_pt(rtp, payloadtype);
    00540    if (!rtpPT.isAstFormat) {
    00541       /* This is special in-band data that's not one of our codecs */
    00542       if (rtpPT.code == AST_RTP_DTMF) {
    00543          /* It's special -- rfc2833 process it */
    00544          if(rtp_debug_test_addr(&sin)) {
    00545             unsigned char *data;
    00546             unsigned int event;
    00547             unsigned int event_end;
    00548             unsigned int duration;
    00549             data = rtp->rawdata + AST_FRIENDLY_OFFSET + hdrlen;
    00550             event = ntohl(*((unsigned int *)(data)));
    00551             event >>= 24;
    00552             event_end = ntohl(*((unsigned int *)(data)));
    00553             event_end <<= 8;
    00554             event_end >>= 24;
    00555             duration = ntohl(*((unsigned int *)(data)));
    00556             duration &= 0xFFFF;
    00557             ast_verbose("Got rfc2833 RTP packet from %s:%d (type %d, seq %d, ts %d, len %d, mark %d, event %08x, end %d, duration %d) \n", ast_inet_ntoa(iabuf, sizeof(iabuf), sin.sin_addr), ntohs(sin.sin_port), payloadtype, seqno, timestamp, res - hdrlen, (mark?1:0), event, ((event_end & 0x80)?1:0), duration);
    00558          }
    00559          if (rtp->lasteventseqn <= seqno || rtp->resp == 0 || (rtp->lasteventseqn >= 65530 && seqno <= 6)) {
    00560             f = process_rfc2833(rtp, rtp->rawdata + AST_FRIENDLY_OFFSET + hdrlen, res - hdrlen, seqno);
    00561             rtp->lasteventseqn = seqno;
    00562          } else
    00563             f = NULL;
    00564          if (f)
    00565             return f;
    00566          else
    00567             return &null_frame;
    00568       } else if (rtpPT.code == AST_RTP_CISCO_DTMF) {
    00569          /* It's really special -- process it the Cisco way */
    00570          if (rtp->lasteventseqn <= seqno || rtp->resp == 0 || (rtp->lasteventseqn >= 65530 && seqno <= 6)) {
    00571             f = process_cisco_dtmf(rtp, rtp->rawdata + AST_FRIENDLY_OFFSET + hdrlen, res - hdrlen);
    00572             rtp->lasteventseqn = seqno;
    00573          } else
    00574             f = NULL;
    00575             if (f)
    00576             return f;
    00577          else
    00578             return &null_frame;
    00579       } else if (rtpPT.code == AST_RTP_CN) {
    00580          /* Comfort Noise */
    00581          f = process_rfc3389(rtp, rtp->rawdata + AST_FRIENDLY_OFFSET + hdrlen, res - hdrlen);
    00582          if (f)
    00583             return f;
    00584          else
    00585             return &null_frame;
    00586       } else {
    00587          ast_log(LOG_NOTICE, "Unknown RTP codec %d received\n", payloadtype);
    00588          return &null_frame;
    00589       }
    00590    }
    00591    rtp->f.subclass = rtpPT.code;
    00592    if (rtp->f.subclass < AST_FORMAT_MAX_AUDIO)
    00593       rtp->f.frametype = AST_FRAME_VOICE;
    00594    else
    00595       rtp->f.frametype = AST_FRAME_VIDEO;
    00596    rtp->lastrxformat = rtp->f.subclass;
    00597
    00598    if (!rtp->lastrxts)
    00599       rtp->lastrxts = timestamp;
    00600
    00601    if (rtp->rxseqno) {
    00602       for (x=rtp->rxseqno + 1; x < seqno; x++) {
    00603          /* Queue empty frames */
    00604          rtp->f.mallocd = 0;
    00605          rtp->f.datalen = 0;
    00606          rtp->f.data = NULL;
    00607          rtp->f.offset = 0;
    00608          rtp->f.samples = 0;
    00609          rtp->f.src = "RTPMissedFrame";
    00610       }
    00611    }
    00612    rtp->rxseqno = seqno;
    00613
    00614    if (rtp->dtmfcount) {
    00615 #if 0
    00616       printf("dtmfcount was %d\n", rtp->dtmfcount);
    00617 #endif
    00618       rtp->dtmfcount -= (timestamp - rtp->lastrxts);
    00619       if (rtp->dtmfcount < 0)
    00620          rtp->dtmfcount = 0;
    00621 #if 0
    00622       if (dtmftimeout != rtp->dtmfcount)
    00623          printf("dtmfcount is %d\n", rtp->dtmfcount);
    00624 #endif
    00625    }
    00626    rtp->lastrxts = timestamp;
    00627
    00628    /* Send any pending DTMF */
    00629    if (rtp->resp && !rtp->dtmfcount) {
    00630       if (option_debug)
    00631          ast_log(LOG_DEBUG, "Sending pending DTMF\n");
    00632       return send_dtmf(rtp);
    00633    }
    00634    rtp->f.mallocd = 0;
    00635    rtp->f.datalen = res - hdrlen;
    00636    rtp->f.data = rtp->rawdata + hdrlen + AST_FRIENDLY_OFFSET;
    00637    rtp->f.offset = hdrlen + AST_FRIENDLY_OFFSET;
    00638    if (rtp->f.subclass < AST_FORMAT_MAX_AUDIO) {
    00639       rtp->f.samples = ast_codec_get_samples(&rtp->f);
    00640       if (rtp->f.subclass == AST_FORMAT_SLINEAR)
    00641          ast_frame_byteswap_be(&rtp->f);
    00642       calc_rxstamp(&rtp->f.delivery, rtp, timestamp, mark);
    00643    } else {
    00644       /* Video -- samples is # of samples vs. 90000 */
    00645       if (!rtp->lastividtimestamp)
    00646          rtp->lastividtimestamp = timestamp;
    00647       rtp->f.samples = timestamp - rtp->lastividtimestamp;
    00648       rtp->lastividtimestamp = timestamp;
    00649       rtp->f.delivery.tv_sec = 0;
    00650       rtp->f.delivery.tv_usec = 0;
    00651       if (mark)
    00652          rtp->f.subclass |= 0x1;
    00653
    00654    }
    00655    rtp->f.src = "RTP";
    00656    return &rtp->f;
    00657 }

void ast_rtp_reload | ( | void |  | ) |

Definition at line 1857 of file rtp.c.

References ast_config_destroy(), ast_config_load(), ast_false(), ast_log(), ast_variable_retrieve(), ast_verbose(), cfg, DEFAULT_DTMF_TIMEOUT, LOG_WARNING, option_verbose, s, and VERBOSE_PREFIX_2.

Referenced by ast_module_reload(), ast_rtp_init(), and main().

    01858 {
    01859    struct ast_config *cfg;
    01860    char *s;
    01861
    01862    rtpstart = 5000;
    01863    rtpend = 31000;
    01864    dtmftimeout = DEFAULT_DTMF_TIMEOUT;
    01865    cfg = ast_config_load("rtp.conf");
    01866    if (cfg) {
    01867       if ((s = ast_variable_retrieve(cfg, "general", "rtpstart"))) {
    01868          rtpstart = atoi(s);
    01869          if (rtpstart < 1024)
    01870             rtpstart = 1024;
    01871          if (rtpstart > 65535)
    01872             rtpstart = 65535;
    01873       }
    01874       if ((s = ast_variable_retrieve(cfg, "general", "rtpend"))) {
    01875          rtpend = atoi(s);
    01876          if (rtpend < 1024)
    01877             rtpend = 1024;
    01878          if (rtpend > 65535)
    01879             rtpend = 65535;
    01880       }
    01881       if ((s = ast_variable_retrieve(cfg, "general", "rtpchecksums"))) {
    01882 #ifdef SO_NO_CHECK
    01883          if (ast_false(s))
    01884             nochecksums = 1;
    01885          else
    01886             nochecksums = 0;
    01887 #else
    01888          if (ast_false(s))
    01889             ast_log(LOG_WARNING, "Disabling RTP checksums is not supported on this operating system!\n");
    01890 #endif
    01891       }
    01892       if ((s = ast_variable_retrieve(cfg, "general", "dtmftimeout"))) {
    01893          dtmftimeout = atoi(s);
    01894          if ((dtmftimeout < 0) || (dtmftimeout > 20000)) {
    01895             ast_log(LOG_WARNING, "DTMF timeout of '%d' outside range, using default of '%d' instead\n",
    01896                dtmftimeout, DEFAULT_DTMF_TIMEOUT);
    01897             dtmftimeout = DEFAULT_DTMF_TIMEOUT;
    01898          };
    01899       }
    01900       ast_config_destroy(cfg);
    01901    }
    01902    if (rtpstart >= rtpend) {
    01903       ast_log(LOG_WARNING, "Unreasonable values for RTP start/end port in rtp.conf\n");
    01904       rtpstart = 5000;
    01905       rtpend = 31000;
    01906    }
    01907    if (option_verbose > 1)
    01908       ast_verbose(VERBOSE_PREFIX_2 "RTP Allocating from port range %d -> %d\n", rtpstart, rtpend);
    01909
    01910 }

void ast_rtp_reset | ( | struct ast_rtp * | rtp | ) |

Definition at line 1085 of file rtp.c.

References ast_rtp::dtmfcount, ast_rtp::dtmfduration, ast_rtp::dtmfmute, ast_rtp::lastdigitts, ast_rtp::lasteventendseqn, ast_rtp::lasteventseqn, ast_rtp::lastividtimestamp, ast_rtp::lastovidtimestamp, ast_rtp::lastrxformat, ast_rtp::lastrxts, ast_rtp::lastts, ast_rtp::lasttxformat, ast_rtp::rxcore, ast_rtp::rxseqno, ast_rtp::seqno, and ast_rtp::txcore.

    01086 {
    01087    memset(&rtp->rxcore, 0, sizeof(rtp->rxcore));
    01088    memset(&rtp->txcore, 0, sizeof(rtp->txcore));
    01089    memset(&rtp->dtmfmute, 0, sizeof(rtp->dtmfmute));
    01090    rtp->lastts = 0;
    01091    rtp->lastdigitts = 0;
    01092    rtp->lastrxts = 0;
    01093    rtp->lastividtimestamp = 0;
    01094    rtp->lastovidtimestamp = 0;
    01095    rtp->lasteventseqn = 0;
    01096    rtp->lasteventendseqn = 0;
    01097    rtp->lasttxformat = 0;
    01098    rtp->lastrxformat = 0;
    01099    rtp->dtmfcount = 0;
    01100    rtp->dtmfduration = 0;
    01101    rtp->seqno = 0;
    01102    rtp->rxseqno = 0;
    01103 }

int ast_rtp_sendcng | ( | struct ast_rtp * | rtp,
|  | int | level |
| ) |  |  |

Definition at line 1221 of file rtp.c.

References ast_inet_ntoa(), ast_log(), AST_RTP_CN, ast_rtp_lookup_code(), ast_tvadd(), ast_verbose(), ast_rtp::dtmfmute, ast_rtp::lastts, LOG_ERROR, rtp_debug_test_addr(), ast_rtp::s, ast_rtp::seqno, ast_rtp::ssrc, and ast_rtp::them.

Referenced by do_monitor().

    01222 {
    01223    unsigned int *rtpheader;
    01224    int hdrlen = 12;
    01225    int res;
    01226    int payload;
    01227    char data[256];
    01228    char iabuf[INET_ADDRSTRLEN];
    01229    level = 127 - (level & 0x7f);
    01230    payload = ast_rtp_lookup_code(rtp, 0, AST_RTP_CN);
    01231
    01232    /* If we have no peer, return immediately */
    01233    if (!rtp->them.sin_addr.s_addr)
    01234       return 0;
    01235
    01236    rtp->dtmfmute = ast_tvadd(ast_tvnow(), ast_tv(0, 500000));
    01237
    01238    /* Get a pointer to the header */
    01239    rtpheader = (unsigned int *)data;
    01240    rtpheader[0] = htonl((2 << 30) | (1 << 23) | (payload << 16) | (rtp->seqno++));
    01241    rtpheader[1] = htonl(rtp->lastts);
    01242    rtpheader[2] = htonl(rtp->ssrc);
    01243    data[12] = level;
    01244    if (rtp->them.sin_port && rtp->them.sin_addr.s_addr) {
    01245       res = sendto(rtp->s, (void *)rtpheader, hdrlen + 1, 0, (struct sockaddr *)&rtp->them, sizeof(rtp->them));
    01246       if (res <0)
    01247          ast_log(LOG_ERROR, "RTP Comfort Noise Transmission error to %s:%d: %s\n", ast_inet_ntoa(iabuf, sizeof(iabuf), rtp->them.sin_addr), ntohs(rtp->them.sin_port), strerror(errno));
    01248       if(rtp_debug_test_addr(&rtp->them))
    01249          ast_verbose("Sent Comfort Noise RTP packet to %s:%d (type %d, seq %d, ts %d, len %d)\n"
    01250                , ast_inet_ntoa(iabuf, sizeof(iabuf), rtp->them.sin_addr), ntohs(rtp->them.sin_port), payload, rtp->seqno, rtp->lastts,res - hdrlen);
    01251
    01252    }
    01253    return 0;
    01254 }

int ast_rtp_senddigit | ( | struct ast_rtp * | rtp,
|  | char | digit |
| ) |  |  |

Definition at line 1139 of file rtp.c.

References ast_inet_ntoa(), ast_log(), AST_RTP_DTMF, ast_rtp_lookup_code(), ast_tvadd(), ast_verbose(), ast_rtp::dtmfmute, ast_rtp::lastdigitts, LOG_ERROR, LOG_WARNING, rtp_debug_test_addr(), ast_rtp::s, ast_rtp::seqno, ast_rtp::ssrc, and ast_rtp::them.

Referenced by oh323_digit(), and sip_senddigit().

    01140 {
    01141    unsigned int *rtpheader;
    01142    int hdrlen = 12;
    01143    int res;
    01144    int x;
    01145    int payload;
    01146    char data[256];
    01147    char iabuf[INET_ADDRSTRLEN];
    01148
    01149    if ((digit <= '9') && (digit >= '0'))
    01150       digit -= '0';
    01151    else if (digit == '*')
    01152       digit = 10;
    01153    else if (digit == '#')
    01154       digit = 11;
    01155    else if ((digit >= 'A') && (digit <= 'D'))
    01156       digit = digit - 'A' + 12;
    01157    else if ((digit >= 'a') && (digit <= 'd'))
    01158       digit = digit - 'a' + 12;
    01159    else {
    01160       ast_log(LOG_WARNING, "Don't know how to represent '%c'\n", digit);
    01161       return -1;
    01162    }
    01163    payload = ast_rtp_lookup_code(rtp, 0, AST_RTP_DTMF);
    01164
    01165    /* If we have no peer, return immediately */
    01166    if (!rtp->them.sin_addr.s_addr)
    01167       return 0;
    01168
    01169    rtp->dtmfmute = ast_tvadd(ast_tvnow(), ast_tv(0, 500000));
    01170
    01171    /* Get a pointer to the header */
    01172    rtpheader = (unsigned int *)data;
    01173    rtpheader[0] = htonl((2 << 30) | (1 << 23) | (payload << 16) | (rtp->seqno));
    01174    rtpheader[1] = htonl(rtp->lastdigitts);
    01175    rtpheader[2] = htonl(rtp->ssrc);
    01176    rtpheader[3] = htonl((digit << 24) | (0xa << 16) | (0));
    01177    for (x = 0; x < 6; x++) {
    01178       if (rtp->them.sin_port && rtp->them.sin_addr.s_addr) {
    01179          res = sendto(rtp->s, (void *) rtpheader, hdrlen + 4, 0, (struct sockaddr *) &rtp->them, sizeof(rtp->them));
    01180          if (res < 0)
    01181             ast_log(LOG_ERROR, "RTP Transmission error to %s:%d: %s\n",
    01182                ast_inet_ntoa(iabuf, sizeof(iabuf), rtp->them.sin_addr),
    01183                ntohs(rtp->them.sin_port), strerror(errno));
    01184          if (rtp_debug_test_addr(&rtp->them))
    01185             ast_verbose("Sent RTP packet to %s:%d (type %d, seq %u, ts %u, len %u)\n",
    01186                    ast_inet_ntoa(iabuf, sizeof(iabuf), rtp->them.sin_addr),
    01187                    ntohs(rtp->them.sin_port), payload, rtp->seqno, rtp->lastdigitts, res - hdrlen);
    01188       }
    01189       /* Sequence number of last two end packets does not get incremented */
    01190       if (x < 3)
    01191          rtp->seqno++;
    01192       /* Clear marker bit and set seqno */
    01193       rtpheader[0] = htonl((2 << 30) | (payload << 16) | (rtp->seqno));
    01194       /* For the last three packets, set the duration and the end bit */
    01195       if (x == 2) {
    01196 #if 0
    01197          /* No, this is wrong...  Do not increment lastdigitts, that's not according
    01198             to the RFC, as best we can determine */
    01199          rtp->lastdigitts++; /* or else the SPA3000 will click instead of beeping... */
    01200          rtpheader[1] = htonl(rtp->lastdigitts);
    01201 #endif
    01202          /* Make duration 800 (100ms) */
    01203          rtpheader[3] |= htonl((800));
    01204          /* Set the End bit */
    01205          rtpheader[3] |= htonl((1 << 23));
    01206       }
    01207    }
    01208    /* Increment the digit timestamp by 120ms, to ensure that digits
    01209       sent sequentially with no intervening non-digit packets do not
    01210       get sent with the same timestamp, and that sequential digits
    01211       have some 'dead air' in between them
    01212    */
    01213    rtp->lastdigitts += 960;
    01214    /* Increment the sequence number to reflect the last packet
    01215       that was sent
    01216    */
    01217    rtp->seqno++;
    01218    return 0;
    01219 }

void ast_rtp_set_callback | ( | struct ast_rtp * | rtp,
|  | ast_rtp_callback | callback |
| ) |  |  |

Definition at line 170 of file rtp.c.

References ast_rtp::callback.

Referenced by start_rtp().

    00171 {
    00172    rtp->callback = callback;
    00173 }

void ast_rtp_set_data | ( | struct ast_rtp * | rtp,
|  | void * | data |
| ) |  |  |

Definition at line 165 of file rtp.c.

References ast_rtp::data.

Referenced by start_rtp().

    00166 {
    00167    rtp->data = data;
    00168 }

void ast_rtp_set_m_type | ( | struct ast_rtp * | rtp,
|  | int | pt |
| ) |  |  |

Definition at line 753 of file rtp.c.

References rtpPayloadType::code, ast_rtp::current_RTP_PT, and MAX_RTP_PT.

Referenced by process_sdp().

    00753                                                      {
    00754    if (pt < 0 || pt > MAX_RTP_PT)
    00755       return; /* bogus payload type */
    00756
    00757    if (static_RTP_PT[pt].code != 0) {
    00758       rtp->current_RTP_PT[pt] = static_RTP_PT[pt];
    00759    }
    00760 }

void ast_rtp_set_peer | ( | struct ast_rtp * | rtp,
|  | struct sockaddr_in * | them |
| ) |  |  |

Definition at line 1046 of file rtp.c.

References ast_rtp::rtcp, ast_rtp::rxseqno, ast_rtcp::them, and ast_rtp::them.

Referenced by handle_message(), process_sdp(), and setup_rtp_connection().

    01047 {
    01048    rtp->them.sin_port = them->sin_port;
    01049    rtp->them.sin_addr = them->sin_addr;
    01050    if (rtp->rtcp) {
    01051       rtp->rtcp->them.sin_port = htons(ntohs(them->sin_port) + 1);
    01052       rtp->rtcp->them.sin_addr = them->sin_addr;
    01053    }
    01054    rtp->rxseqno = 0;
    01055 }

void ast_rtp_set_rtpmap_type | ( | struct ast_rtp * | rtp,
|  | int | pt,
|  | char * | mimeType,
|  | char * | mimeSubtype |
| ) |  |  |

Definition at line 764 of file rtp.c.

References ast_rtp::current_RTP_PT, MAX_RTP_PT, mimeTypes, subtype, and type.

Referenced by process_sdp(), and set_dtmf_payload().

    00765                                              {
    00766    int i;
    00767
    00768    if (pt < 0 || pt > MAX_RTP_PT)
    00769          return; /* bogus payload type */
    00770
    00771    for (i = 0; i < sizeof mimeTypes/sizeof mimeTypes[0]; ++i) {
    00772       if (strcasecmp(mimeSubtype, mimeTypes[i].subtype) == 0 &&
    00773            strcasecmp(mimeType, mimeTypes[i].type) == 0) {
    00774          rtp->current_RTP_PT[pt] = mimeTypes[i].payloadType;
    00775       return;
    00776       }
    00777    }
    00778 }

void ast_rtp_setnat | ( | struct ast_rtp * | rtp,
|  | int | nat |
| ) |  |  |

Definition at line 175 of file rtp.c.

References ast_rtp::nat.

Referenced by check_user_full(), create_addr(), create_addr_from_peer(), oh323_request(), oh323_rtp_read(), sip_alloc(), and start_rtp().

    00176 {
    00177    rtp->nat = nat;
    00178 }

int ast_rtp_settos | ( | struct ast_rtp * | rtp,
|  | int | tos |
| ) |  |  |

Definition at line 1037 of file rtp.c.

References ast_log(), LOG_WARNING, and ast_rtp::s.

Referenced by oh323_alloc(), and sip_alloc().

    01038 {
    01039    int res;
    01040
    01041    if ((res = setsockopt(rtp->s, IPPROTO_IP, IP_TOS, &tos, sizeof(tos))))
    01042       ast_log(LOG_WARNING, "Unable to set TOS to %d\n", tos);
    01043    return res;
    01044 }

void ast_rtp_stop | ( | struct ast_rtp * | rtp | ) |

Definition at line 1075 of file rtp.c.

References ast_rtp::rtcp, ast_rtcp::them, and ast_rtp::them.

Referenced by handle_request_bye(), handle_request_cancel(), handle_response(), and process_sdp().

    01076 {
    01077    memset(&rtp->them.sin_addr, 0, sizeof(rtp->them.sin_addr));
    01078    memset(&rtp->them.sin_port, 0, sizeof(rtp->them.sin_port));
    01079    if (rtp->rtcp) {
    01080       memset(&rtp->rtcp->them.sin_addr, 0, sizeof(rtp->them.sin_addr));
    01081       memset(&rtp->rtcp->them.sin_port, 0, sizeof(rtp->them.sin_port));
    01082    }
    01083 }

int ast_rtp_write | ( | struct ast_rtp * | rtp,
|  | struct ast_frame * | f |
| ) |  |  |

Definition at line 1337 of file rtp.c.

References AST_FORMAT_ADPCM, AST_FORMAT_ALAW, AST_FORMAT_G723_1, AST_FORMAT_G726, AST_FORMAT_G729A, AST_FORMAT_GSM, AST_FORMAT_H261, AST_FORMAT_H263, AST_FORMAT_H263_PLUS, AST_FORMAT_ILBC, AST_FORMAT_LPC10, AST_FORMAT_SLINEAR, AST_FORMAT_SPEEX, AST_FORMAT_ULAW, AST_FRAME_VIDEO, AST_FRAME_VOICE, ast_frdup(), ast_frfree(), ast_getformatname(), ast_log(), ast_rtp_lookup_code(), ast_rtp_raw_write(), ast_smoother_feed, ast_smoother_feed_be, AST_SMOOTHER_FLAG_G729, ast_smoother_free(), ast_smoother_new(), ast_smoother_read(), ast_smoother_set_flags(), ast_frame::datalen, ast_frame::frametype, ast_rtp::lasttxformat, LOG_DEBUG, LOG_WARNING, ast_frame::offset, option_debug, ast_rtp::smoother, ast_frame::subclass, and ast_rtp::them.

Referenced by mgcp_write(), oh323_write(), sip_write(), and skinny_write().

    01338 {
    01339    struct ast_frame *f;
    01340    int codec;
    01341    int hdrlen = 12;
    01342    int subclass;
    01343
    01344
    01345    /* If we have no peer, return immediately */
    01346    if (!rtp->them.sin_addr.s_addr)
    01347       return 0;
    01348
    01349    /* If there is no data length, return immediately */
    01350    if (!_f->datalen)
    01351       return 0;
    01352
    01353    /* Make sure we have enough space for RTP header */
    01354    if ((_f->frametype != AST_FRAME_VOICE) && (_f->frametype != AST_FRAME_VIDEO)) {
    01355       ast_log(LOG_WARNING, "RTP can only send voice\n");
    01356       return -1;
    01357    }
    01358
    01359    subclass = _f->subclass;
    01360    if (_f->frametype == AST_FRAME_VIDEO)
    01361       subclass &= ~0x1;
    01362
    01363    codec = ast_rtp_lookup_code(rtp, 1, subclass);
    01364    if (codec < 0) {
    01365       ast_log(LOG_WARNING, "Don't know how to send format %s packets with RTP\n", ast_getformatname(_f->subclass));
    01366       return -1;
    01367    }
    01368
    01369    if (rtp->lasttxformat != subclass) {
    01370       /* New format, reset the smoother */
    01371       if (option_debug)
    01372          ast_log(LOG_DEBUG, "Ooh, format changed from %s to %s\n", ast_getformatname(rtp->lasttxformat), ast_getformatname(subclass));
    01373       rtp->lasttxformat = subclass;
    01374       if (rtp->smoother)
    01375          ast_smoother_free(rtp->smoother);
    01376       rtp->smoother = NULL;
    01377    }
    01378
    01379
    01380    switch(subclass) {
    01381    case AST_FORMAT_SLINEAR:
    01382       if (!rtp->smoother) {
    01383          rtp->smoother = ast_smoother_new(320);
    01384       }
    01385       if (!rtp->smoother) {
    01386          ast_log(LOG_WARNING, "Unable to create smoother :(\n");
    01387          return -1;
    01388       }
    01389       ast_smoother_feed_be(rtp->smoother, _f);
    01390
    01391       while((f = ast_smoother_read(rtp->smoother)))
    01392          ast_rtp_raw_write(rtp, f, codec);
    01393       break;
    01394    case AST_FORMAT_ULAW:
    01395    case AST_FORMAT_ALAW:
    01396       if (!rtp->smoother) {
    01397          rtp->smoother = ast_smoother_new(160);
    01398       }
    01399       if (!rtp->smoother) {
    01400          ast_log(LOG_WARNING, "Unable to create smoother :(\n");
    01401          return -1;
    01402       }
    01403       ast_smoother_feed(rtp->smoother, _f);
    01404
    01405       while((f = ast_smoother_read(rtp->smoother)))
    01406          ast_rtp_raw_write(rtp, f, codec);
    01407       break;
    01408    case AST_FORMAT_ADPCM:
    01409    case AST_FORMAT_G726:
    01410       if (!rtp->smoother) {
    01411          rtp->smoother = ast_smoother_new(80);
    01412       }
    01413       if (!rtp->smoother) {
    01414          ast_log(LOG_WARNING, "Unable to create smoother :(\n");
    01415          return -1;
    01416       }
    01417       ast_smoother_feed(rtp->smoother, _f);
    01418
    01419       while((f = ast_smoother_read(rtp->smoother)))
    01420          ast_rtp_raw_write(rtp, f, codec);
    01421       break;
    01422    case AST_FORMAT_G729A:
    01423       if (!rtp->smoother) {
    01424          rtp->smoother = ast_smoother_new(20);
    01425          if (rtp->smoother)
    01426             ast_smoother_set_flags(rtp->smoother, AST_SMOOTHER_FLAG_G729);
    01427       }
    01428       if (!rtp->smoother) {
    01429          ast_log(LOG_WARNING, "Unable to create g729 smoother :(\n");
    01430          return -1;
    01431       }
    01432       ast_smoother_feed(rtp->smoother, _f);
    01433
    01434       while((f = ast_smoother_read(rtp->smoother)))
    01435          ast_rtp_raw_write(rtp, f, codec);
    01436       break;
    01437    case AST_FORMAT_GSM:
    01438       if (!rtp->smoother) {
    01439          rtp->smoother = ast_smoother_new(33);
    01440       }
    01441       if (!rtp->smoother) {
    01442          ast_log(LOG_WARNING, "Unable to create GSM smoother :(\n");
    01443          return -1;
    01444       }
    01445       ast_smoother_feed(rtp->smoother, _f);
    01446       while((f = ast_smoother_read(rtp->smoother)))
    01447          ast_rtp_raw_write(rtp, f, codec);
    01448       break;
    01449    case AST_FORMAT_ILBC:
    01450       if (!rtp->smoother) {
    01451          rtp->smoother = ast_smoother_new(50);
    01452       }
    01453       if (!rtp->smoother) {
    01454          ast_log(LOG_WARNING, "Unable to create ILBC smoother :(\n");
    01455          return -1;
    01456       }
    01457       ast_smoother_feed(rtp->smoother, _f);
    01458       while((f = ast_smoother_read(rtp->smoother)))
    01459          ast_rtp_raw_write(rtp, f, codec);
    01460       break;
    01461    default:
    01462       ast_log(LOG_WARNING, "Not sure about sending format %s packets\n", ast_getformatname(subclass));
    01463       /* fall through to... */
    01464    case AST_FORMAT_H261:
    01465    case AST_FORMAT_H263:
    01466    case AST_FORMAT_H263_PLUS:
    01467    case AST_FORMAT_G723_1:
    01468    case AST_FORMAT_LPC10:
    01469    case AST_FORMAT_SPEEX:
    01470            /* Don't buffer outgoing frames; send them one-per-packet: */
    01471       if (_f->offset < hdrlen) {
    01472          f = ast_frdup(_f);
    01473       } else {
    01474          f = _f;
    01475       }
    01476       ast_rtp_raw_write(rtp, f, codec);
    01477       if (f != _f)
    01478          ast_frfree(f);
    01479    }
    01480
    01481    return 0;
    01482 }