rtp.h File Reference

#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_DTMF   (1 << 0)
#define AST_RTP_CN   (1 << 1)
#define AST_RTP_CISCO_DTMF   (1 << 2)
#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

struct ast_rtpast_rtp_new (struct sched_context *sched, struct io_context *io, int rtcpenable, int callbackmode)
struct ast_rtpast_rtp_new_with_bindaddr (struct sched_context *sched, struct io_context *io, int rtcpenable, int callbackmode, struct in_addr in)
void ast_rtp_set_peer (struct ast_rtp *rtp, struct sockaddr_in *them)
void 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_destroy (struct ast_rtp *rtp)
void ast_rtp_set_callback (struct ast_rtp *rtp, ast_rtp_callback callback)
void ast_rtp_set_data (struct ast_rtp *rtp, void *data)
int ast_rtp_write (struct ast_rtp *rtp, struct ast_frame *f)
struct ast_frameast_rtp_read (struct ast_rtp *rtp)
struct ast_frameast_rtcp_read (struct ast_rtp *rtp)
int ast_rtp_fd (struct ast_rtp *rtp)
int ast_rtcp_fd (struct ast_rtp *rtp)
int ast_rtp_senddigit (struct ast_rtp *rtp, char digit)
int ast_rtp_settos (struct ast_rtp *rtp, int tos)
void ast_rtp_pt_clear (struct ast_rtp *rtp)
void ast_rtp_pt_default (struct ast_rtp *rtp)
void ast_rtp_set_m_type (struct ast_rtp *rtp, int pt)
void ast_rtp_set_rtpmap_type (struct ast_rtp *rtp, int pt, char *mimeType, char *mimeSubtype)
struct rtpPayloadType ast_rtp_lookup_pt (struct ast_rtp *rtp, int pt)
int ast_rtp_lookup_code (struct ast_rtp *rtp, int isAstFormat, int code)
void ast_rtp_offered_from_local (struct ast_rtp *rtp, int local)
void ast_rtp_get_current_formats (struct ast_rtp *rtp, int *astFormats, int *nonAstFormats)
char * ast_rtp_lookup_mime_subtype (int isAstFormat, int code)
char * ast_rtp_lookup_mime_multiple (char *buf, int size, const int capability, const int isAstFormat)
void ast_rtp_setnat (struct ast_rtp *rtp, int nat)
int ast_rtp_bridge (struct ast_channel *c0, struct ast_channel *c1, int flags, struct ast_frame **fo, struct ast_channel **rc)
int ast_rtp_proto_register (struct ast_rtp_protocol *proto)
void ast_rtp_proto_unregister (struct ast_rtp_protocol *proto)
void ast_rtp_stop (struct ast_rtp *rtp)
void ast_rtp_init (void)
void ast_rtp_reload (void)


Define Documentation

#define AST_RTP_CISCO_DTMF   (1 << 2)

DTMF (Cisco Proprietary)

Definition at line 34 of file rtp.h.

#define AST_RTP_CN   (1 << 1)

'Comfort Noise' (RFC3389)

Definition at line 32 of file rtp.h.

#define AST_RTP_DTMF   (1 << 0)

DTMF (RFC2833)

Definition at line 30 of file rtp.h.

#define AST_RTP_MAX   AST_RTP_CISCO_DTMF

Maximum RTP-specific code

Definition at line 36 of file rtp.h.


Typedef Documentation

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

Definition at line 49 of file rtp.h.


Function Documentation

int ast_rtcp_fd ( struct ast_rtp rtp  ) 

Definition at line 119 of file rtp.c.

00120 {
00121    if (rtp->rtcp)
00122       return rtp->rtcp->s;
00123    return -1;
00124 }

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

Definition at line 335 of file rtp.c.

00336 {
00337    static struct ast_frame null_frame = { AST_FRAME_NULL, };
00338    int len;
00339    int hdrlen = 8;
00340    int res;
00341    struct sockaddr_in sin;
00342    unsigned int rtcpdata[1024];
00343    char iabuf[INET_ADDRSTRLEN];
00344    
00345    if (!rtp || !rtp->rtcp)
00346       return &null_frame;
00347 
00348    len = sizeof(sin);
00349    
00350    res = recvfrom(rtp->rtcp->s, rtcpdata, sizeof(rtcpdata),
00351                0, (struct sockaddr *)&sin, &len);
00352    
00353    if (res < 0) {
00354       if (errno != EAGAIN)
00355          ast_log(LOG_WARNING, "RTP Read error: %s\n", strerror(errno));
00356       if (errno == EBADF)
00357          CRASH;
00358       return &null_frame;
00359    }
00360 
00361    if (res < hdrlen) {
00362       ast_log(LOG_WARNING, "RTP Read too short\n");
00363       return &null_frame;
00364    }
00365 
00366    if (rtp->nat) {
00367       /* Send to whoever sent to us */
00368       if ((rtp->rtcp->them.sin_addr.s_addr != sin.sin_addr.s_addr) ||
00369           (rtp->rtcp->them.sin_port != sin.sin_port)) {
00370          memcpy(&rtp->rtcp->them, &sin, sizeof(rtp->rtcp->them));
00371          ast_log(LOG_DEBUG, "RTP NAT: Using address %s:%d\n", ast_inet_ntoa(iabuf, sizeof(iabuf), rtp->rtcp->them.sin_addr), ntohs(rtp->rtcp->them.sin_port));
00372       }
00373    }
00374    if (option_debug)
00375       ast_log(LOG_DEBUG, "Got RTCP report of %d bytes\n", res);
00376    return &null_frame;
00377 }

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

Definition at line 1386 of file rtp.c.

01387 {
01388    struct ast_frame *f;
01389    struct ast_channel *who, *cs[3];
01390    struct ast_rtp *p0, *p1;
01391    struct ast_rtp *vp0, *vp1;
01392    struct ast_rtp_protocol *pr0, *pr1;
01393    struct sockaddr_in ac0, ac1;
01394    struct sockaddr_in vac0, vac1;
01395    struct sockaddr_in t0, t1;
01396    struct sockaddr_in vt0, vt1;
01397    char iabuf[INET_ADDRSTRLEN];
01398    
01399    void *pvt0, *pvt1;
01400    int to;
01401    int codec0,codec1, oldcodec0, oldcodec1;
01402    
01403    memset(&vt0, 0, sizeof(vt0));
01404    memset(&vt1, 0, sizeof(vt1));
01405    memset(&vac0, 0, sizeof(vac0));
01406    memset(&vac1, 0, sizeof(vac1));
01407 
01408    /* if need DTMF, cant native bridge */
01409    if (flags & (AST_BRIDGE_DTMF_CHANNEL_0 | AST_BRIDGE_DTMF_CHANNEL_1))
01410       return -2;
01411    ast_mutex_lock(&c0->lock);
01412    while(ast_mutex_trylock(&c1->lock)) {
01413       ast_mutex_unlock(&c0->lock);
01414       usleep(1);
01415       ast_mutex_lock(&c0->lock);
01416    }
01417    pr0 = get_proto(c0);
01418    pr1 = get_proto(c1);
01419    if (!pr0) {
01420       ast_log(LOG_WARNING, "Can't find native functions for channel '%s'\n", c0->name);
01421       ast_mutex_unlock(&c0->lock);
01422       ast_mutex_unlock(&c1->lock);
01423       return -1;
01424    }
01425    if (!pr1) {
01426       ast_log(LOG_WARNING, "Can't find native functions for channel '%s'\n", c1->name);
01427       ast_mutex_unlock(&c0->lock);
01428       ast_mutex_unlock(&c1->lock);
01429       return -1;
01430    }
01431    pvt0 = c0->pvt->pvt;
01432    pvt1 = c1->pvt->pvt;
01433    p0 = pr0->get_rtp_info(c0);
01434    if (pr0->get_vrtp_info)
01435       vp0 = pr0->get_vrtp_info(c0);
01436    else
01437       vp0 = NULL;
01438    p1 = pr1->get_rtp_info(c1);
01439    if (pr1->get_vrtp_info)
01440       vp1 = pr1->get_vrtp_info(c1);
01441    else
01442       vp1 = NULL;
01443    if (!p0 || !p1) {
01444       /* Somebody doesn't want to play... */
01445       ast_mutex_unlock(&c0->lock);
01446       ast_mutex_unlock(&c1->lock);
01447       return -2;
01448    }
01449    if (pr0->get_codec)
01450       codec0 = pr0->get_codec(c0);
01451    else
01452       codec0 = 0;
01453    if (pr1->get_codec)
01454       codec1 = pr1->get_codec(c1);
01455    else
01456       codec1 = 0;
01457    if (pr0->get_codec && pr1->get_codec) {
01458       /* Hey, we can't do reinvite if both parties speak diffrent codecs */
01459       if (!(codec0 & codec1)) {
01460          ast_log(LOG_WARNING, "codec0 = %d is not codec1 = %d, cannot native bridge.\n",codec0,codec1);
01461          ast_mutex_unlock(&c0->lock);
01462          ast_mutex_unlock(&c1->lock);
01463          return -2;
01464       }
01465    }
01466    if (pr0->set_rtp_peer(c0, p1, vp1, codec1)) 
01467       ast_log(LOG_WARNING, "Channel '%s' failed to talk to '%s'\n", c0->name, c1->name);
01468    else {
01469       /* Store RTP peer */
01470       ast_rtp_get_peer(p1, &ac1);
01471       if (vp1)
01472          ast_rtp_get_peer(vp1, &vac1);
01473    }
01474    if (pr1->set_rtp_peer(c1, p0, vp0, codec0))
01475       ast_log(LOG_WARNING, "Channel '%s' failed to talk back to '%s'\n", c1->name, c0->name);
01476    else {
01477       /* Store RTP peer */
01478       ast_rtp_get_peer(p0, &ac0);
01479       if (vp0)
01480          ast_rtp_get_peer(vp0, &vac0);
01481    }
01482    ast_mutex_unlock(&c0->lock);
01483    ast_mutex_unlock(&c1->lock);
01484    cs[0] = c0;
01485    cs[1] = c1;
01486    cs[2] = NULL;
01487    oldcodec0 = codec0;
01488    oldcodec1 = codec1;
01489    for (;;) {
01490       if ((c0->pvt->pvt != pvt0)  ||
01491          (c1->pvt->pvt != pvt1) ||
01492          (c0->masq || c0->masqr || c1->masq || c1->masqr)) {
01493             ast_log(LOG_DEBUG, "Oooh, something is weird, backing out\n");
01494             if (c0->pvt->pvt == pvt0) {
01495                if (pr0->set_rtp_peer(c0, NULL, NULL, 0)) 
01496                   ast_log(LOG_WARNING, "Channel '%s' failed to revert\n", c0->name);
01497             }
01498             if (c1->pvt->pvt == pvt1) {
01499                if (pr1->set_rtp_peer(c1, NULL, NULL, 0)) 
01500                   ast_log(LOG_WARNING, "Channel '%s' failed to revert back\n", c1->name);
01501             }
01502             /* Tell it to try again later */
01503             return -3;
01504       }
01505       to = -1;
01506       ast_rtp_get_peer(p1, &t1);
01507       ast_rtp_get_peer(p0, &t0);
01508       if (pr0->get_codec)
01509          codec0 = pr0->get_codec(c0);
01510       if (pr1->get_codec)
01511          codec1 = pr1->get_codec(c1);
01512       if (vp1)
01513          ast_rtp_get_peer(vp1, &vt1);
01514       if (vp0)
01515          ast_rtp_get_peer(vp0, &vt0);
01516       if (inaddrcmp(&t1, &ac1) || (vp1 && inaddrcmp(&vt1, &vac1)) || (codec1 != oldcodec1)) {
01517          ast_log(LOG_DEBUG, "Oooh, '%s' changed end address to %s:%d (format %d)\n", 
01518             c1->name, ast_inet_ntoa(iabuf, sizeof(iabuf), t1.sin_addr), ntohs(t1.sin_port), codec1);
01519          ast_log(LOG_DEBUG, "Oooh, '%s' changed end vaddress to %s:%d (format %d)\n", 
01520             c1->name, ast_inet_ntoa(iabuf, sizeof(iabuf), vt1.sin_addr), ntohs(vt1.sin_port), codec1);
01521          ast_log(LOG_DEBUG, "Oooh, '%s' was %s:%d/(format %d)\n", 
01522             c1->name, ast_inet_ntoa(iabuf, sizeof(iabuf), ac1.sin_addr), ntohs(ac1.sin_port), oldcodec1);
01523          ast_log(LOG_DEBUG, "Oooh, '%s' wasv %s:%d/(format %d)\n", 
01524             c1->name, ast_inet_ntoa(iabuf, sizeof(iabuf), vac1.sin_addr), ntohs(vac1.sin_port), oldcodec1);
01525          if (pr0->set_rtp_peer(c0, t1.sin_addr.s_addr ? p1 : NULL, vt1.sin_addr.s_addr ? vp1 : NULL, codec1)) 
01526             ast_log(LOG_WARNING, "Channel '%s' failed to update to '%s'\n", c0->name, c1->name);
01527          memcpy(&ac1, &t1, sizeof(ac1));
01528          memcpy(&vac1, &vt1, sizeof(vac1));
01529          oldcodec1 = codec1;
01530       }
01531       if (inaddrcmp(&t0, &ac0) || (vp0 && inaddrcmp(&vt0, &vac0))) {
01532          ast_log(LOG_DEBUG, "Oooh, '%s' changed end address to %s:%d (format %d)\n", 
01533             c0->name, ast_inet_ntoa(iabuf, sizeof(iabuf), t0.sin_addr), ntohs(t0.sin_port), codec0);
01534          ast_log(LOG_DEBUG, "Oooh, '%s' was %s:%d/(format %d)\n", 
01535             c0->name, ast_inet_ntoa(iabuf, sizeof(iabuf), ac0.sin_addr), ntohs(ac0.sin_port), oldcodec0);
01536          if (pr1->set_rtp_peer(c1, t0.sin_addr.s_addr ? p0 : NULL, vt0.sin_addr.s_addr ? vp0 : NULL, codec0))
01537             ast_log(LOG_WARNING, "Channel '%s' failed to update to '%s'\n", c1->name, c0->name);
01538          memcpy(&ac0, &t0, sizeof(ac0));
01539          memcpy(&vac0, &vt0, sizeof(vac0));
01540          oldcodec0 = codec0;
01541       }
01542       who = ast_waitfor_n(cs, 2, &to);
01543       if (!who) {
01544          ast_log(LOG_DEBUG, "Ooh, empty read...\n");
01545          /* check for hagnup / whentohangup */
01546          if (ast_check_hangup(c0) || ast_check_hangup(c1))
01547             break;
01548          continue;
01549       }
01550       f = ast_read(who);
01551       if (!f || ((f->frametype == AST_FRAME_DTMF) &&
01552                (((who == c0) && (flags & AST_BRIDGE_DTMF_CHANNEL_0)) || 
01553                 ((who == c1) && (flags & AST_BRIDGE_DTMF_CHANNEL_1))))) {
01554          *fo = f;
01555          *rc = who;
01556          ast_log(LOG_DEBUG, "Oooh, got a %s\n", f ? "digit" : "hangup");
01557          if ((c0->pvt->pvt == pvt0) && (!c0->_softhangup)) {
01558             if (pr0->set_rtp_peer(c0, NULL, NULL, 0)) 
01559                ast_log(LOG_WARNING, "Channel '%s' failed to revert\n", c0->name);
01560          }
01561          if ((c1->pvt->pvt == pvt1) && (!c1->_softhangup)) {
01562             if (pr1->set_rtp_peer(c1, NULL, NULL, 0)) 
01563                ast_log(LOG_WARNING, "Channel '%s' failed to revert back\n", c1->name);
01564          }
01565          /* That's all we needed */
01566          return 0;
01567       } else {
01568          if ((f->frametype == AST_FRAME_DTMF) || 
01569             (f->frametype == AST_FRAME_VOICE) || 
01570             (f->frametype == AST_FRAME_VIDEO)) {
01571             /* Forward voice or DTMF frames if they happen upon us */
01572             if (who == c0) {
01573                ast_write(c1, f);
01574             } else if (who == c1) {
01575                ast_write(c0, f);
01576             }
01577          }
01578          ast_frfree(f);
01579       }
01580       /* Swap priority not that it's a big deal at this point */
01581       cs[2] = cs[0];
01582       cs[0] = cs[1];
01583       cs[1] = cs[2];
01584       
01585    }
01586    return -1;
01587 }

void ast_rtp_destroy ( struct ast_rtp rtp  ) 

Definition at line 993 of file rtp.c.

00994 {
00995    if (rtp->smoother)
00996       ast_smoother_free(rtp->smoother);
00997    if (rtp->ioid)
00998       ast_io_remove(rtp->io, rtp->ioid);
00999    if (rtp->s > -1)
01000       close(rtp->s);
01001    if (rtp->rtcp) {
01002       close(rtp->rtcp->s);
01003       free(rtp->rtcp);
01004    }
01005    free(rtp);
01006 }

int ast_rtp_fd ( struct ast_rtp rtp  ) 

Definition at line 114 of file rtp.c.

00115 {
00116    return rtp->s;
00117 }

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

Definition at line 717 of file rtp.c.

00718                                                    {
00719   int pt;
00720 
00721   *astFormats = *nonAstFormats = 0;
00722   for (pt = 0; pt < MAX_RTP_PT; ++pt) {
00723     if (rtp->current_RTP_PT[pt].isAstFormat) {
00724       *astFormats |= rtp->current_RTP_PT[pt].code;
00725     } else {
00726       *nonAstFormats |= rtp->current_RTP_PT[pt].code;
00727     }
00728   }
00729 }

void ast_rtp_get_peer ( struct ast_rtp rtp,
struct sockaddr_in *  them 
)

Definition at line 971 of file rtp.c.

00972 {
00973    them->sin_family = AF_INET;
00974    them->sin_port = rtp->them.sin_port;
00975    them->sin_addr = rtp->them.sin_addr;
00976 }

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

Definition at line 978 of file rtp.c.

00979 {
00980    memcpy(us, &rtp->us, sizeof(rtp->us));
00981 }

void ast_rtp_init ( void   ) 

Definition at line 1633 of file rtp.c.

01634 {
01635    ast_rtp_reload();
01636 }

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

Definition at line 756 of file rtp.c.

00756                                                                                     {
00757   int pt;
00758 
00759 
00760   if (isAstFormat == rtp->rtp_lookup_code_cache_isAstFormat &&
00761       code == rtp->rtp_lookup_code_cache_code) {
00762     /* Use our cached mapping, to avoid the overhead of the loop below */
00763     return rtp->rtp_lookup_code_cache_result;
00764   }
00765 
00766    /* Check the dynamic list first */
00767   for (pt = 0; pt < MAX_RTP_PT; ++pt) {
00768     if (rtp->current_RTP_PT[pt].code == code &&
00769       rtp->current_RTP_PT[pt].isAstFormat == isAstFormat) {
00770       rtp->rtp_lookup_code_cache_isAstFormat = isAstFormat;
00771       rtp->rtp_lookup_code_cache_code = code;
00772       rtp->rtp_lookup_code_cache_result = pt;
00773       return pt;
00774     }
00775   }
00776 
00777    /* Then the static list */
00778   for (pt = 0; pt < MAX_RTP_PT; ++pt) {
00779     if (static_RTP_PT[pt].code == code &&
00780       static_RTP_PT[pt].isAstFormat == isAstFormat) {
00781       rtp->rtp_lookup_code_cache_isAstFormat = isAstFormat;
00782       rtp->rtp_lookup_code_cache_code = code;
00783       rtp->rtp_lookup_code_cache_result = pt;
00784       return pt;
00785     }
00786   }
00787   return -1;
00788 }

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

Definition at line 802 of file rtp.c.

00803 {
00804    int format;
00805    unsigned len;
00806    char *end = buf;
00807    char *start = buf;
00808 
00809    if (!buf || !size)
00810       return NULL;
00811 
00812    snprintf(end, size, "0x%x (", capability);
00813 
00814    len = strlen(end);
00815    end += len;
00816    size -= len;
00817    start = end;
00818 
00819    for (format = 1; format < AST_RTP_MAX; format <<= 1) {
00820       if (capability & format) {
00821          const char *name = ast_rtp_lookup_mime_subtype(isAstFormat, format);
00822          snprintf(end, size, "%s|", name);
00823          len = strlen(end);
00824          end += len;
00825          size -= len;
00826       }
00827    }
00828 
00829    if (start == end)
00830       snprintf(start, size, "nothing)"); 
00831    else if (size > 1)
00832       *(end -1) = ')';
00833    
00834    return buf;
00835  }

char* ast_rtp_lookup_mime_subtype ( int  isAstFormat,
int  code 
)

Definition at line 790 of file rtp.c.

00790                                                                          {
00791   int i;
00792 
00793   for (i = 0; i < sizeof mimeTypes/sizeof mimeTypes[0]; ++i) {
00794     if (mimeTypes[i].payloadType.code == code &&
00795    mimeTypes[i].payloadType.isAstFormat == isAstFormat) {
00796       return mimeTypes[i].subtype;
00797     }
00798   }
00799   return "";
00800 }

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

Definition at line 738 of file rtp.c.

00739 {
00740   struct rtpPayloadType result;
00741 
00742   result.isAstFormat = result.code = 0;
00743   if (pt < 0 || pt > MAX_RTP_PT) {
00744     return result; /* bogus payload type */
00745   }
00746   /* Start with the negotiated codecs */
00747   if (!rtp->rtp_offered_from_local)
00748     result = rtp->current_RTP_PT[pt];
00749   /* If it doesn't exist, check our static RTP type list, just in case */
00750   if (!result.code) 
00751     result = static_RTP_PT[pt];
00752   return result;
00753 }

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

Definition at line 946 of file rtp.c.

00947 {
00948    struct in_addr ia;
00949    memset(&ia, 0, sizeof(ia));
00950    return ast_rtp_new_with_bindaddr(sched, io, rtcpenable, callbackmode, ia);
00951 }

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]

Definition at line 870 of file rtp.c.

00871 {
00872    struct ast_rtp *rtp;
00873    int x;
00874    int first;
00875    int startplace;
00876    rtp = malloc(sizeof(struct ast_rtp));
00877    if (!rtp)
00878       return NULL;
00879    memset(rtp, 0, sizeof(struct ast_rtp));
00880    rtp->them.sin_family = AF_INET;
00881    rtp->us.sin_family = AF_INET;
00882    rtp->s = rtp_socket();
00883    rtp->ssrc = rand();
00884    rtp->seqno = rand() & 0xffff;
00885    if (rtp->s < 0) {
00886       free(rtp);
00887       ast_log(LOG_WARNING, "Unable to allocate socket: %s\n", strerror(errno));
00888       return NULL;
00889    }
00890    if (sched && rtcpenable) {
00891       rtp->sched = sched;
00892       rtp->rtcp = ast_rtcp_new();
00893    }
00894    /* Find us a place */
00895    x = (rand() % (rtpend-rtpstart)) + rtpstart;
00896    x = x & ~1;
00897    startplace = x;
00898    for (;;) {
00899       /* Must be an even port number by RTP spec */
00900       rtp->us.sin_port = htons(x);
00901       rtp->us.sin_addr = addr;
00902       if (rtp->rtcp)
00903          rtp->rtcp->us.sin_port = htons(x + 1);
00904       if (!(first = bind(rtp->s, (struct sockaddr *)&rtp->us, sizeof(rtp->us))) &&
00905          (!rtp->rtcp || !bind(rtp->rtcp->s, (struct sockaddr *)&rtp->rtcp->us, sizeof(rtp->rtcp->us))))
00906          break;
00907       if (!first) {
00908          /* Primary bind succeeded! Gotta recreate it */
00909          close(rtp->s);
00910          rtp->s = rtp_socket();
00911       }
00912       if (errno != EADDRINUSE) {
00913          ast_log(LOG_WARNING, "Unexpected bind error: %s\n", strerror(errno));
00914          close(rtp->s);
00915          if (rtp->rtcp) {
00916             close(rtp->rtcp->s);
00917             free(rtp->rtcp);
00918          }
00919          free(rtp);
00920          return NULL;
00921       }
00922       x += 2;
00923       if (x > rtpend)
00924          x = (rtpstart + 1) & ~1;
00925       if (x == startplace) {
00926          ast_log(LOG_WARNING, "No RTP ports remaining\n");
00927          close(rtp->s);
00928          if (rtp->rtcp) {
00929             close(rtp->rtcp->s);
00930             free(rtp->rtcp);
00931          }
00932          free(rtp);
00933          return NULL;
00934       }
00935    }
00936    if (io && sched && callbackmode) {
00937       /* Operate this one in a callback mode */
00938       rtp->sched = sched;
00939       rtp->io = io;
00940       rtp->ioid = ast_io_add(rtp->io, rtp->s, rtpread, AST_IO_IN, rtp);
00941    }
00942    ast_rtp_pt_default(rtp);
00943    return rtp;
00944 }

void ast_rtp_offered_from_local ( struct ast_rtp rtp,
int  local 
)

Definition at line 731 of file rtp.c.

00731                                                                 {
00732   if (rtp)
00733     rtp->rtp_offered_from_local = local;
00734   else
00735     ast_log(LOG_WARNING, "rtp structure is null\n");
00736 }

int ast_rtp_proto_register ( struct ast_rtp_protocol proto  ) 

Definition at line 1357 of file rtp.c.

01358 {
01359    struct ast_rtp_protocol *cur;
01360    cur = protos;
01361    while(cur) {
01362       if (cur->type == proto->type) {
01363          ast_log(LOG_WARNING, "Tried to register same protocol '%s' twice\n", cur->type);
01364          return -1;
01365       }
01366       cur = cur->next;
01367    }
01368    proto->next = protos;
01369    protos = proto;
01370    return 0;
01371 }

void ast_rtp_proto_unregister ( struct ast_rtp_protocol proto  ) 

Definition at line 1339 of file rtp.c.

01340 {
01341    struct ast_rtp_protocol *cur, *prev;
01342    cur = protos;
01343    prev = NULL;
01344    while(cur) {
01345       if (cur == proto) {
01346          if (prev)
01347             prev->next = proto->next;
01348          else
01349             protos = proto->next;
01350          return;
01351       }
01352       prev = cur;
01353       cur = cur->next;
01354    }
01355 }

void ast_rtp_pt_clear ( struct ast_rtp rtp  ) 

Definition at line 659 of file rtp.c.

00660 {
00661   int i;
00662 
00663   for (i = 0; i < MAX_RTP_PT; ++i) {
00664     rtp->current_RTP_PT[i].isAstFormat = 0;
00665     rtp->current_RTP_PT[i].code = 0;
00666   }
00667 
00668   rtp->rtp_lookup_code_cache_isAstFormat = 0;
00669   rtp->rtp_lookup_code_cache_code = 0;
00670   rtp->rtp_lookup_code_cache_result = 0;
00671 }

void ast_rtp_pt_default ( struct ast_rtp rtp  ) 

Definition at line 673 of file rtp.c.

00674 {
00675   int i;
00676   /* Initialize to default payload types */
00677   for (i = 0; i < MAX_RTP_PT; ++i) {
00678     rtp->current_RTP_PT[i].isAstFormat = static_RTP_PT[i].isAstFormat;
00679     rtp->current_RTP_PT[i].code = static_RTP_PT[i].code;
00680   }
00681 
00682   rtp->rtp_lookup_code_cache_isAstFormat = 0;
00683   rtp->rtp_lookup_code_cache_code = 0;
00684   rtp->rtp_lookup_code_cache_result = 0;
00685 }

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

Definition at line 401 of file rtp.c.

00402 {
00403    int res;
00404    struct sockaddr_in sin;
00405    int len;
00406    unsigned int seqno;
00407    int version;
00408    int payloadtype;
00409    int hdrlen = 12;
00410    int padding;
00411    int mark;
00412    int ext;
00413    char iabuf[INET_ADDRSTRLEN];
00414    unsigned int timestamp;
00415    unsigned int *rtpheader;
00416    static struct ast_frame *f, null_frame = { AST_FRAME_NULL, };
00417    struct rtpPayloadType rtpPT;
00418    
00419    len = sizeof(sin);
00420    
00421    /* Cache where the header will go */
00422    res = recvfrom(rtp->s, rtp->rawdata + AST_FRIENDLY_OFFSET, sizeof(rtp->rawdata) - AST_FRIENDLY_OFFSET,
00423                0, (struct sockaddr *)&sin, &len);
00424 
00425 
00426    rtpheader = (unsigned int *)(rtp->rawdata + AST_FRIENDLY_OFFSET);
00427    if (res < 0) {
00428       if (errno != EAGAIN)
00429          ast_log(LOG_WARNING, "RTP Read error: %s\n", strerror(errno));
00430       if (errno == EBADF)
00431          CRASH;
00432       return &null_frame;
00433    }
00434    if (res < hdrlen) {
00435       ast_log(LOG_WARNING, "RTP Read too short\n");
00436       return &null_frame;
00437    }
00438 
00439    /* Ignore if the other side hasn't been given an address
00440       yet.  */
00441    if (!rtp->them.sin_addr.s_addr || !rtp->them.sin_port)
00442       return &null_frame;
00443 
00444    if (rtp->nat) {
00445       /* Send to whoever sent to us */
00446       if ((rtp->them.sin_addr.s_addr != sin.sin_addr.s_addr) ||
00447           (rtp->them.sin_port != sin.sin_port)) {
00448          memcpy(&rtp->them, &sin, sizeof(rtp->them));
00449          ast_log(LOG_DEBUG, "RTP NAT: Using address %s:%d\n", ast_inet_ntoa(iabuf, sizeof(iabuf), rtp->them.sin_addr), ntohs(rtp->them.sin_port));
00450       }
00451    }
00452 
00453    /* Get fields */
00454    seqno = ntohl(rtpheader[0]);
00455 
00456    /* Check RTP version */
00457    version = (seqno & 0xC0000000) >> 30;
00458    if (version != 2)
00459       return &null_frame;
00460    
00461    payloadtype = (seqno & 0x7f0000) >> 16;
00462    padding = seqno & (1 << 29);
00463    mark = seqno & (1 << 23);
00464    ext = seqno & (1 << 28);
00465    seqno &= 0xffff;
00466    timestamp = ntohl(rtpheader[1]);
00467    
00468    if (padding) {
00469       /* Remove padding bytes */
00470       res -= rtp->rawdata[AST_FRIENDLY_OFFSET + res - 1];
00471    }
00472    
00473    if (ext) {
00474       /* RTP Extension present */
00475       hdrlen += 4;
00476       hdrlen += (ntohl(rtpheader[3]) & 0xffff) << 2;
00477    }
00478 
00479    if (res < hdrlen) {
00480       ast_log(LOG_WARNING, "RTP Read too short (%d, expecting %d)\n", res, hdrlen);
00481       return &null_frame;
00482    }
00483 
00484 #if 0
00485    printf("Got RTP packet from %s:%d (type %d, seq %d, ts %d, len = %d)\n", ast_inet_ntoa(iabuf, sizeof(iabuf), sin.sin_addr), ntohs(sin.sin_port), payloadtype, seqno, timestamp,res - hdrlen);
00486 #endif   
00487    rtpPT = ast_rtp_lookup_pt(rtp, payloadtype);
00488    if (!rtpPT.isAstFormat) {
00489      /* This is special in-band data that's not one of our codecs */
00490      if (rtpPT.code == AST_RTP_DTMF) {
00491        /* It's special -- rfc2833 process it */
00492        if (rtp->lasteventseqn <= seqno || rtp->resp == 0 || (rtp->lasteventseqn >= 65530 && seqno <= 6)) {
00493          f = process_rfc2833(rtp, rtp->rawdata + AST_FRIENDLY_OFFSET + hdrlen, res - hdrlen);
00494          rtp->lasteventseqn = seqno;
00495        } else f = NULL;
00496        if (f) return f; else return &null_frame;
00497      } else if (rtpPT.code == AST_RTP_CISCO_DTMF) {
00498        /* It's really special -- process it the Cisco way */
00499        if (rtp->lasteventseqn <= seqno || rtp->resp == 0 || (rtp->lasteventseqn >= 65530 && seqno <= 6)) {
00500          f = process_cisco_dtmf(rtp, rtp->rawdata + AST_FRIENDLY_OFFSET + hdrlen, res - hdrlen);
00501          rtp->lasteventseqn = seqno;
00502        } else f = NULL;
00503        if (f) return f; else return &null_frame;
00504      } else if (rtpPT.code == AST_RTP_CN) {
00505        /* Comfort Noise */
00506        f = process_rfc3389(rtp, rtp->rawdata + AST_FRIENDLY_OFFSET + hdrlen, res - hdrlen);
00507        if (f) return f; else return &null_frame;
00508      } else {
00509        ast_log(LOG_NOTICE, "Unknown RTP codec %d received\n", payloadtype);
00510        return &null_frame;
00511      }
00512    }
00513    rtp->f.subclass = rtpPT.code;
00514    if (rtp->f.subclass < AST_FORMAT_MAX_AUDIO)
00515       rtp->f.frametype = AST_FRAME_VOICE;
00516    else
00517       rtp->f.frametype = AST_FRAME_VIDEO;
00518    rtp->lastrxformat = rtp->f.subclass;
00519 
00520    if (!rtp->lastrxts)
00521       rtp->lastrxts = timestamp;
00522 
00523    if (rtp->dtmfcount) {
00524 #if 0
00525       printf("dtmfcount was %d\n", rtp->dtmfcount);
00526 #endif      
00527       rtp->dtmfcount -= (timestamp - rtp->lastrxts);
00528       if (rtp->dtmfcount < 0)
00529          rtp->dtmfcount = 0;
00530 #if 0
00531       if (dtmftimeout != rtp->dtmfcount)
00532          printf("dtmfcount is %d\n", rtp->dtmfcount);
00533 #endif
00534    }
00535    rtp->lastrxts = timestamp;
00536 
00537    /* Send any pending DTMF */
00538    if (rtp->resp && !rtp->dtmfcount) {
00539       ast_log(LOG_DEBUG, "Sending pending DTMF\n");
00540       return send_dtmf(rtp);
00541    }
00542    rtp->f.mallocd = 0;
00543    rtp->f.datalen = res - hdrlen;
00544    rtp->f.data = rtp->rawdata + hdrlen + AST_FRIENDLY_OFFSET;
00545    rtp->f.offset = hdrlen + AST_FRIENDLY_OFFSET;
00546    if (rtp->f.subclass < AST_FORMAT_MAX_AUDIO) {
00547       switch(rtp->f.subclass) {
00548       case AST_FORMAT_ULAW:
00549       case AST_FORMAT_ALAW:
00550          rtp->f.samples = rtp->f.datalen;
00551          break;
00552       case AST_FORMAT_SLINEAR:
00553          rtp->f.samples = rtp->f.datalen / 2;
00554          ast_frame_byteswap_be(&rtp->f);
00555          break;
00556       case AST_FORMAT_GSM:
00557          rtp->f.samples = 160 * (rtp->f.datalen / 33);
00558          break;
00559       case AST_FORMAT_ILBC:
00560          rtp->f.samples = 240 * (rtp->f.datalen / 50);
00561          break;
00562       case AST_FORMAT_ADPCM:
00563       case AST_FORMAT_G726:
00564          rtp->f.samples = rtp->f.datalen * 2;
00565          break;
00566       case AST_FORMAT_G729A:
00567          rtp->f.samples = rtp->f.datalen * 8;
00568          break;
00569       case AST_FORMAT_G723_1:
00570          rtp->f.samples = g723_samples(rtp->f.data, rtp->f.datalen);
00571          break;
00572       case AST_FORMAT_SPEEX:
00573          /* assumes that the RTP packet contained one Speex frame */
00574            rtp->f.samples = 160;
00575          break;
00576       case AST_FORMAT_LPC10:
00577           rtp->f.samples = 22 * 8;
00578          rtp->f.samples += (((char *)(rtp->f.data))[7] & 0x1) * 8;
00579          break;
00580       default:
00581          ast_log(LOG_NOTICE, "Unable to calculate samples for format %s\n", ast_getformatname(rtp->f.subclass));
00582          break;
00583       }
00584       calc_rxstamp(&rtp->f.delivery, rtp, timestamp, mark);
00585    } else {
00586       /* Video -- samples is # of samples vs. 90000 */
00587       if (!rtp->lastividtimestamp)
00588          rtp->lastividtimestamp = timestamp;
00589       rtp->f.samples = timestamp - rtp->lastividtimestamp;
00590       rtp->lastividtimestamp = timestamp;
00591       rtp->f.delivery.tv_sec = 0;
00592       rtp->f.delivery.tv_usec = 0;
00593       if (mark)
00594          rtp->f.subclass |= 0x1;
00595       
00596    }
00597    rtp->f.src = "RTP";
00598    return &rtp->f;
00599 }

void ast_rtp_reload ( void   ) 

Definition at line 1589 of file rtp.c.

01590 {
01591    struct ast_config *cfg;
01592    char *s;
01593    rtpstart = 5000;
01594    rtpend = 31000;
01595    cfg = ast_load("rtp.conf");
01596    if (cfg) {
01597       if ((s = ast_variable_retrieve(cfg, "general", "rtpstart"))) {
01598          rtpstart = atoi(s);
01599          if (rtpstart < 1024)
01600             rtpstart = 1024;
01601          if (rtpstart > 65535)
01602             rtpstart = 65535;
01603       }
01604       if ((s = ast_variable_retrieve(cfg, "general", "rtpend"))) {
01605          rtpend = atoi(s);
01606          if (rtpend < 1024)
01607             rtpend = 1024;
01608          if (rtpend > 65535)
01609             rtpend = 65535;
01610       }
01611       if ((s = ast_variable_retrieve(cfg, "general", "rtpchecksums"))) {
01612 #ifdef SO_NO_CHECK
01613          if (ast_false(s))
01614             nochecksums = 1;
01615          else
01616             nochecksums = 0;
01617 #else
01618          if (ast_false(s))
01619             ast_log(LOG_WARNING, "Disabling RTP checksums is not supported on this operating system!\n");
01620 #endif
01621       }
01622       ast_destroy(cfg);
01623    }
01624    if (rtpstart >= rtpend) {
01625       ast_log(LOG_WARNING, "Unreasonable values for RTP start/end\n");
01626       rtpstart = 5000;
01627       rtpend = 31000;
01628    }
01629    if (option_verbose > 1)
01630       ast_verbose(VERBOSE_PREFIX_2 "RTP Allocating from port range %d -> %d\n", rtpstart, rtpend);
01631 }

int ast_rtp_senddigit ( struct ast_rtp rtp,
char  digit 
)

Definition at line 1034 of file rtp.c.

01035 {
01036    unsigned int *rtpheader;
01037    int hdrlen = 12;
01038    int res;
01039    int x;
01040    int payload;
01041    char data[256];
01042    char iabuf[INET_ADDRSTRLEN];
01043 
01044    if ((digit <= '9') && (digit >= '0'))
01045       digit -= '0';
01046    else if (digit == '*')
01047       digit = 10;
01048    else if (digit == '#')
01049       digit = 11;
01050    else if ((digit >= 'A') && (digit <= 'D')) 
01051       digit = digit - 'A' + 12;
01052    else if ((digit >= 'a') && (digit <= 'd')) 
01053       digit = digit - 'a' + 12;
01054    else {
01055       ast_log(LOG_WARNING, "Don't know how to represent '%c'\n", digit);
01056       return -1;
01057    }
01058    payload = ast_rtp_lookup_code(rtp, 0, AST_RTP_DTMF);
01059 
01060    /* If we have no peer, return immediately */ 
01061    if (!rtp->them.sin_addr.s_addr)
01062       return 0;
01063 
01064    gettimeofday(&rtp->dtmfmute, NULL);
01065    rtp->dtmfmute.tv_usec += (500 * 1000);
01066    if (rtp->dtmfmute.tv_usec > 1000000) {
01067       rtp->dtmfmute.tv_usec -= 1000000;
01068       rtp->dtmfmute.tv_sec += 1;
01069    }
01070    
01071    /* Get a pointer to the header */
01072    rtpheader = (unsigned int *)data;
01073    rtpheader[0] = htonl((2 << 30) | (1 << 23) | (payload << 16) | (rtp->seqno++));
01074    rtpheader[1] = htonl(rtp->lastts);
01075    rtpheader[2] = htonl(rtp->ssrc); 
01076    rtpheader[3] = htonl((digit << 24) | (0xa << 16) | (0));
01077    for (x=0;x<6;x++) {
01078       if (rtp->them.sin_port && rtp->them.sin_addr.s_addr) {
01079          res = sendto(rtp->s, (void *)rtpheader, hdrlen + 4, 0, (struct sockaddr *)&rtp->them, sizeof(rtp->them));
01080          if (res <0) 
01081             ast_log(LOG_NOTICE, "RTP Transmission error to %s:%d: %s\n", ast_inet_ntoa(iabuf, sizeof(iabuf), rtp->them.sin_addr), ntohs(rtp->them.sin_port), strerror(errno));
01082    #if 0
01083       printf("Sent %d bytes of RTP data to %s:%d\n", res, ast_inet_ntoa(iabuf, sizeof(iabuf), rtp->them.sin_addr), ntohs(rtp->them.sin_port));
01084    #endif      
01085       }
01086       if (x == 2) {
01087          /* Clear marker bit and increment seqno */
01088          rtpheader[0] = htonl((2 << 30)  | (payload << 16) | (rtp->seqno++));
01089          /* Make duration 800 (100ms) */
01090          rtpheader[3] |= htonl((800));
01091          /* Set the End bit for the last 3 */
01092          rtpheader[3] |= htonl((1 << 23));
01093       } else if ( x < 5) {
01094          rtpheader[0] = htonl((2 << 30) | (payload << 16) | (rtp->seqno++));
01095       }
01096    }
01097    return 0;
01098 }

void ast_rtp_set_callback ( struct ast_rtp rtp,
ast_rtp_callback  callback 
)

Definition at line 167 of file rtp.c.

00168 {
00169    rtp->callback = callback;
00170 }

void ast_rtp_set_data ( struct ast_rtp rtp,
void *  data 
)

Definition at line 162 of file rtp.c.

00163 {
00164    rtp->data = data;
00165 }

void ast_rtp_set_m_type ( struct ast_rtp rtp,
int  pt 
)

Definition at line 690 of file rtp.c.

00690                                                      {
00691   if (pt < 0 || pt > MAX_RTP_PT) return; /* bogus payload type */
00692 
00693   if (static_RTP_PT[pt].code != 0) {
00694     rtp->current_RTP_PT[pt] = static_RTP_PT[pt];
00695   }
00696 } 

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

Definition at line 961 of file rtp.c.

00962 {
00963    rtp->them.sin_port = them->sin_port;
00964    rtp->them.sin_addr = them->sin_addr;
00965    if (rtp->rtcp) {
00966       rtp->rtcp->them.sin_port = htons(ntohs(them->sin_port) + 1);
00967       rtp->rtcp->them.sin_addr = them->sin_addr;
00968    }
00969 }

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

Definition at line 700 of file rtp.c.

00701                                              {
00702   int i;
00703 
00704   if (pt < 0 || pt > MAX_RTP_PT) return; /* bogus payload type */
00705 
00706   for (i = 0; i < sizeof mimeTypes/sizeof mimeTypes[0]; ++i) {
00707     if (strcasecmp(mimeSubtype, mimeTypes[i].subtype) == 0 &&
00708    strcasecmp(mimeType, mimeTypes[i].type) == 0) {
00709       rtp->current_RTP_PT[pt] = mimeTypes[i].payloadType;
00710       return;
00711     }
00712   }
00713 } 

void ast_rtp_setnat ( struct ast_rtp rtp,
int  nat 
)

Definition at line 172 of file rtp.c.

00173 {
00174    rtp->nat = nat;
00175 }

int ast_rtp_settos ( struct ast_rtp rtp,
int  tos 
)

Definition at line 953 of file rtp.c.

00954 {
00955    int res;
00956    if ((res = setsockopt(rtp->s, IPPROTO_IP, IP_TOS, &tos, sizeof(tos)))) 
00957       ast_log(LOG_WARNING, "Unable to set TOS to %d\n", tos);
00958    return res;
00959 }

void ast_rtp_stop ( struct ast_rtp rtp  ) 

Definition at line 983 of file rtp.c.

00984 {
00985    memset(&rtp->them.sin_addr, 0, sizeof(rtp->them.sin_addr));
00986    memset(&rtp->them.sin_port, 0, sizeof(rtp->them.sin_port));
00987    if (rtp->rtcp) {
00988       memset(&rtp->rtcp->them.sin_addr, 0, sizeof(rtp->them.sin_addr));
00989       memset(&rtp->rtcp->them.sin_port, 0, sizeof(rtp->them.sin_port));
00990    }
00991 }

int ast_rtp_write ( struct ast_rtp rtp,
struct ast_frame f 
)

Definition at line 1196 of file rtp.c.

01197 {
01198    struct ast_frame *f;
01199    int codec;
01200    int hdrlen = 12;
01201    int subclass;
01202    
01203 
01204    /* If we have no peer, return immediately */ 
01205    if (!rtp->them.sin_addr.s_addr)
01206       return 0;
01207 
01208    /* If there is no data length, return immediately */
01209    if (!_f->datalen) 
01210       return 0;
01211    
01212    /* Make sure we have enough space for RTP header */
01213    if ((_f->frametype != AST_FRAME_VOICE) && (_f->frametype != AST_FRAME_VIDEO)) {
01214       ast_log(LOG_WARNING, "RTP can only send voice\n");
01215       return -1;
01216    }
01217 
01218    subclass = _f->subclass;
01219    if (_f->frametype == AST_FRAME_VIDEO)
01220       subclass &= ~0x1;
01221 
01222    codec = ast_rtp_lookup_code(rtp, 1, subclass);
01223    if (codec < 0) {
01224       ast_log(LOG_WARNING, "Don't know how to send format %s packets with RTP\n", ast_getformatname(_f->subclass));
01225       return -1;
01226    }
01227 
01228    if (rtp->lasttxformat != subclass) {
01229       /* New format, reset the smoother */
01230       ast_log(LOG_DEBUG, "Ooh, format changed from %s to %s\n", ast_getformatname(rtp->lasttxformat), ast_getformatname(subclass));
01231       rtp->lasttxformat = subclass;
01232       if (rtp->smoother)
01233          ast_smoother_free(rtp->smoother);
01234       rtp->smoother = NULL;
01235    }
01236 
01237 
01238    switch(subclass) {
01239    case AST_FORMAT_SLINEAR:
01240       if (!rtp->smoother) {
01241          rtp->smoother = ast_smoother_new(320);
01242       }
01243       if (!rtp->smoother) {
01244          ast_log(LOG_WARNING, "Unable to create smoother :(\n");
01245          return -1;
01246       }
01247       ast_smoother_feed_be(rtp->smoother, _f);
01248       
01249       while((f = ast_smoother_read(rtp->smoother)))
01250          ast_rtp_raw_write(rtp, f, codec);
01251       break;
01252    case AST_FORMAT_ULAW:
01253    case AST_FORMAT_ALAW:
01254       if (!rtp->smoother) {
01255          rtp->smoother = ast_smoother_new(160);
01256       }
01257       if (!rtp->smoother) {
01258          ast_log(LOG_WARNING, "Unable to create smoother :(\n");
01259          return -1;
01260       }
01261       ast_smoother_feed(rtp->smoother, _f);
01262       
01263       while((f = ast_smoother_read(rtp->smoother)))
01264          ast_rtp_raw_write(rtp, f, codec);
01265       break;
01266    case AST_FORMAT_ADPCM:
01267    case AST_FORMAT_G726:
01268       if (!rtp->smoother) {
01269          rtp->smoother = ast_smoother_new(80);
01270       }
01271       if (!rtp->smoother) {
01272          ast_log(LOG_WARNING, "Unable to create smoother :(\n");
01273          return -1;
01274       }
01275       ast_smoother_feed(rtp->smoother, _f);
01276       
01277       while((f = ast_smoother_read(rtp->smoother)))
01278          ast_rtp_raw_write(rtp, f, codec);
01279       break;
01280    case AST_FORMAT_G729A:
01281       if (!rtp->smoother) {
01282          rtp->smoother = ast_smoother_new(20);
01283          if (rtp->smoother)
01284             ast_smoother_set_flags(rtp->smoother, AST_SMOOTHER_FLAG_G729);
01285       }
01286       if (!rtp->smoother) {
01287          ast_log(LOG_WARNING, "Unable to create g729 smoother :(\n");
01288          return -1;
01289       }
01290       ast_smoother_feed(rtp->smoother, _f);
01291       
01292       while((f = ast_smoother_read(rtp->smoother)))
01293          ast_rtp_raw_write(rtp, f, codec);
01294       break;
01295    case AST_FORMAT_GSM:
01296       if (!rtp->smoother) {
01297          rtp->smoother = ast_smoother_new(33);
01298       }
01299       if (!rtp->smoother) {
01300          ast_log(LOG_WARNING, "Unable to create GSM smoother :(\n");
01301          return -1;
01302       }
01303       ast_smoother_feed(rtp->smoother, _f);
01304       while((f = ast_smoother_read(rtp->smoother)))
01305          ast_rtp_raw_write(rtp, f, codec);
01306       break;
01307    case AST_FORMAT_ILBC:
01308       if (!rtp->smoother) {
01309          rtp->smoother = ast_smoother_new(50);
01310       }
01311       if (!rtp->smoother) {
01312          ast_log(LOG_WARNING, "Unable to create ILBC smoother :(\n");
01313          return -1;
01314       }
01315       ast_smoother_feed(rtp->smoother, _f);
01316       while((f = ast_smoother_read(rtp->smoother)))
01317          ast_rtp_raw_write(rtp, f, codec);
01318       break;
01319    default: 
01320       ast_log(LOG_WARNING, "Not sure about sending format %s packets\n", ast_getformatname(subclass));
01321       /* fall through to... */
01322    case AST_FORMAT_H261:
01323    case AST_FORMAT_H263:
01324    case AST_FORMAT_G723_1:
01325    case AST_FORMAT_LPC10:
01326    case AST_FORMAT_SPEEX:
01327            /* Don't buffer outgoing frames; send them one-per-packet: */
01328       if (_f->offset < hdrlen) {
01329          f = ast_frdup(_f);
01330       } else {
01331          f = _f;
01332       }
01333       ast_rtp_raw_write(rtp, f, codec);
01334    }
01335       
01336    return 0;
01337 }


Generated on Wed Oct 28 17:01:01 2009 for Asterisk by  doxygen 1.5.6