Main Page | Alphabetical List | Data Structures | File List | Data Fields | Globals

rtp.h File Reference

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

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

ast_rtpast_rtp_new (struct sched_context *sched, struct io_context *io, int rtcpenable, int callbackmode)
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)
ast_frameast_rtp_read (struct ast_rtp *rtp)
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)
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_get_current_formats (struct ast_rtp *rtp, int *astFormats, int *nonAstFormats)
char * ast_rtp_lookup_mime_subtype (int isAstFormat, int code)
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.

Referenced by ast_rtp_read().

#define AST_RTP_CN   (1 << 1)
 

'Comfort Noise' (RFC3389) Definition at line 32 of file rtp.h.

Referenced by ast_rtp_read().

#define AST_RTP_DTMF   (1 << 0)
 

DTMF (RFC2833) Definition at line 30 of file rtp.h.

Referenced by ast_rtp_read().

#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.

Referenced by ast_rtp_set_callback().


Function Documentation

int ast_rtcp_fd struct ast_rtp rtp  ) 
 

Definition at line 115 of file rtp.c.

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

00116 { 00117 if (rtp->rtcp) 00118 return rtp->rtcp->s; 00119 return -1; 00120 }

struct ast_frame* ast_rtcp_read struct ast_rtp rtp  ) 
 

Definition at line 333 of file rtp.c.

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

00334 { 00335 static struct ast_frame null_frame = { AST_FRAME_NULL, }; 00336 int len; 00337 int hdrlen = 8; 00338 int res; 00339 struct sockaddr_in sin; 00340 unsigned int rtcpdata[1024]; 00341 char iabuf[INET_ADDRSTRLEN]; 00342 00343 if (!rtp->rtcp) 00344 return &null_frame; 00345 00346 len = sizeof(sin); 00347 00348 res = recvfrom(rtp->rtcp->s, rtcpdata, sizeof(rtcpdata), 00349 0, (struct sockaddr *)&sin, &len); 00350 00351 if (res < 0) { 00352 if (errno == EAGAIN) 00353 ast_log(LOG_NOTICE, "RTP: Received packet with bad UDP checksum\n"); 00354 else 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->them, &sin, sizeof(rtp->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 1288 of file rtp.c.

References AST_BRIDGE_DTMF_CHANNEL_0, AST_BRIDGE_DTMF_CHANNEL_1, ast_check_hangup(), AST_FRAME_DTMF, AST_FRAME_VIDEO, AST_FRAME_VOICE, ast_frfree(), ast_inet_ntoa(), ast_log(), ast_mutex_lock, ast_mutex_unlock, ast_read(), ast_rtp_get_peer(), ast_waitfor_n(), ast_write(), ast_frame::frametype, ast_channel::lock, LOG_DEBUG, LOG_WARNING, ast_channel::name, ast_channel_pvt::pvt, and ast_channel::pvt.

01289 { 01290 struct ast_frame *f; 01291 struct ast_channel *who, *cs[3]; 01292 struct ast_rtp *p0, *p1; 01293 struct ast_rtp *vp0, *vp1; 01294 struct ast_rtp_protocol *pr0, *pr1; 01295 struct sockaddr_in ac0, ac1; 01296 struct sockaddr_in vac0, vac1; 01297 struct sockaddr_in t0, t1; 01298 struct sockaddr_in vt0, vt1; 01299 char iabuf[INET_ADDRSTRLEN]; 01300 01301 void *pvt0, *pvt1; 01302 int to; 01303 int codec0,codec1, oldcodec0, oldcodec1; 01304 01305 memset(&vt0, 0, sizeof(vt0)); 01306 memset(&vt1, 0, sizeof(vt1)); 01307 memset(&vac0, 0, sizeof(vac0)); 01308 memset(&vac1, 0, sizeof(vac1)); 01309 01310 /* if need DTMF, cant native bridge */ 01311 if (flags & (AST_BRIDGE_DTMF_CHANNEL_0 | AST_BRIDGE_DTMF_CHANNEL_1)) 01312 return -2; 01313 ast_mutex_lock(&c0->lock); 01314 ast_mutex_lock(&c1->lock); 01315 pr0 = get_proto(c0); 01316 pr1 = get_proto(c1); 01317 if (!pr0) { 01318 ast_log(LOG_WARNING, "Can't find native functions for channel '%s'\n", c0->name); 01319 ast_mutex_unlock(&c0->lock); 01320 ast_mutex_unlock(&c1->lock); 01321 return -1; 01322 } 01323 if (!pr1) { 01324 ast_log(LOG_WARNING, "Can't find native functions for channel '%s'\n", c1->name); 01325 ast_mutex_unlock(&c0->lock); 01326 ast_mutex_unlock(&c1->lock); 01327 return -1; 01328 } 01329 pvt0 = c0->pvt->pvt; 01330 pvt1 = c1->pvt->pvt; 01331 p0 = pr0->get_rtp_info(c0); 01332 if (pr0->get_vrtp_info) 01333 vp0 = pr0->get_vrtp_info(c0); 01334 else 01335 vp0 = NULL; 01336 p1 = pr1->get_rtp_info(c1); 01337 if (pr1->get_vrtp_info) 01338 vp1 = pr1->get_vrtp_info(c1); 01339 else 01340 vp1 = NULL; 01341 if (!p0 || !p1) { 01342 /* Somebody doesn't want to play... */ 01343 ast_mutex_unlock(&c0->lock); 01344 ast_mutex_unlock(&c1->lock); 01345 return -2; 01346 } 01347 if (pr0->get_codec) 01348 codec0 = pr0->get_codec(c0); 01349 else 01350 codec0 = 0; 01351 if (pr1->get_codec) 01352 codec1 = pr1->get_codec(c1); 01353 else 01354 codec1 = 0; 01355 if (pr0->get_codec && pr1->get_codec) { 01356 /* Hey, we can't do reinvite if both parties speak diffrent codecs */ 01357 if (!(codec0 & codec1)) { 01358 ast_log(LOG_WARNING, "codec0 = %d is not codec1 = %d, cannot native bridge.\n",codec0,codec1); 01359 ast_mutex_unlock(&c0->lock); 01360 ast_mutex_unlock(&c1->lock); 01361 return -2; 01362 } 01363 } 01364 if (pr0->set_rtp_peer(c0, p1, vp1, codec1)) 01365 ast_log(LOG_WARNING, "Channel '%s' failed to talk to '%s'\n", c0->name, c1->name); 01366 else { 01367 /* Store RTP peer */ 01368 ast_rtp_get_peer(p1, &ac1); 01369 if (vp1) 01370 ast_rtp_get_peer(vp1, &vac1); 01371 } 01372 if (pr1->set_rtp_peer(c1, p0, vp0, codec0)) 01373 ast_log(LOG_WARNING, "Channel '%s' failed to talk back to '%s'\n", c1->name, c0->name); 01374 else { 01375 /* Store RTP peer */ 01376 ast_rtp_get_peer(p0, &ac0); 01377 if (vp0) 01378 ast_rtp_get_peer(vp0, &vac0); 01379 } 01380 ast_mutex_unlock(&c0->lock); 01381 ast_mutex_unlock(&c1->lock); 01382 cs[0] = c0; 01383 cs[1] = c1; 01384 cs[2] = NULL; 01385 oldcodec0 = codec0; 01386 oldcodec1 = codec1; 01387 for (;;) { 01388 if ((c0->pvt->pvt != pvt0) || 01389 (c1->pvt->pvt != pvt1) || 01390 (c0->masq || c0->masqr || c1->masq || c1->masqr)) { 01391 ast_log(LOG_DEBUG, "Oooh, something is weird, backing out\n"); 01392 if (c0->pvt->pvt == pvt0) { 01393 if (pr0->set_rtp_peer(c0, NULL, NULL, 0)) 01394 ast_log(LOG_WARNING, "Channel '%s' failed to revert\n", c0->name); 01395 } 01396 if (c1->pvt->pvt == pvt1) { 01397 if (pr1->set_rtp_peer(c1, NULL, NULL, 0)) 01398 ast_log(LOG_WARNING, "Channel '%s' failed to revert back\n", c1->name); 01399 } 01400 /* Tell it to try again later */ 01401 return -3; 01402 } 01403 to = -1; 01404 ast_rtp_get_peer(p1, &t1); 01405 ast_rtp_get_peer(p0, &t0); 01406 if (pr0->get_codec) 01407 codec0 = pr0->get_codec(c0); 01408 if (pr1->get_codec) 01409 codec1 = pr1->get_codec(c1); 01410 if (vp1) 01411 ast_rtp_get_peer(vp1, &vt1); 01412 if (vp0) 01413 ast_rtp_get_peer(vp0, &vt0); 01414 if (inaddrcmp(&t1, &ac1) || (vp1 && inaddrcmp(&vt1, &vac1)) || (codec1 != oldcodec1)) { 01415 ast_log(LOG_DEBUG, "Oooh, '%s' changed end address to %s:%d (format %d)\n", 01416 c1->name, ast_inet_ntoa(iabuf, sizeof(iabuf), t1.sin_addr), ntohs(t1.sin_port), codec1); 01417 ast_log(LOG_DEBUG, "Oooh, '%s' changed end vaddress to %s:%d (format %d)\n", 01418 c1->name, ast_inet_ntoa(iabuf, sizeof(iabuf), vt1.sin_addr), ntohs(vt1.sin_port), codec1); 01419 ast_log(LOG_DEBUG, "Oooh, '%s' was %s:%d/(format %d)\n", 01420 c1->name, ast_inet_ntoa(iabuf, sizeof(iabuf), ac1.sin_addr), ntohs(ac1.sin_port), oldcodec1); 01421 ast_log(LOG_DEBUG, "Oooh, '%s' wasv %s:%d/(format %d)\n", 01422 c1->name, ast_inet_ntoa(iabuf, sizeof(iabuf), vac1.sin_addr), ntohs(vac1.sin_port), oldcodec1); 01423 if (pr0->set_rtp_peer(c0, t1.sin_addr.s_addr ? p1 : NULL, vt1.sin_addr.s_addr ? vp1 : NULL, codec1)) 01424 ast_log(LOG_WARNING, "Channel '%s' failed to update to '%s'\n", c0->name, c1->name); 01425 memcpy(&ac1, &t1, sizeof(ac1)); 01426 memcpy(&vac1, &vt1, sizeof(vac1)); 01427 oldcodec1 = codec1; 01428 } 01429 if (inaddrcmp(&t0, &ac0) || (vp0 && inaddrcmp(&vt0, &vac0))) { 01430 ast_log(LOG_DEBUG, "Oooh, '%s' changed end address to %s:%d (format %d)\n", 01431 c0->name, ast_inet_ntoa(iabuf, sizeof(iabuf), t0.sin_addr), ntohs(t0.sin_port), codec0); 01432 ast_log(LOG_DEBUG, "Oooh, '%s' was %s:%d/(format %d)\n", 01433 c0->name, ast_inet_ntoa(iabuf, sizeof(iabuf), ac0.sin_addr), ntohs(ac0.sin_port), oldcodec0); 01434 if (pr1->set_rtp_peer(c1, t0.sin_addr.s_addr ? p0 : NULL, vt0.sin_addr.s_addr ? vp0 : NULL, codec0)) 01435 ast_log(LOG_WARNING, "Channel '%s' failed to update to '%s'\n", c1->name, c0->name); 01436 memcpy(&ac0, &t0, sizeof(ac0)); 01437 memcpy(&vac0, &vt0, sizeof(vac0)); 01438 oldcodec0 = codec0; 01439 } 01440 who = ast_waitfor_n(cs, 2, &to); 01441 if (!who) { 01442 ast_log(LOG_DEBUG, "Ooh, empty read...\n"); 01443 /* check for hagnup / whentohangup */ 01444 if (ast_check_hangup(c0) || ast_check_hangup(c1)) 01445 break; 01446 continue; 01447 } 01448 f = ast_read(who); 01449 if (!f || ((f->frametype == AST_FRAME_DTMF) && 01450 (((who == c0) && (flags & AST_BRIDGE_DTMF_CHANNEL_0)) || 01451 ((who == c1) && (flags & AST_BRIDGE_DTMF_CHANNEL_1))))) { 01452 *fo = f; 01453 *rc = who; 01454 ast_log(LOG_DEBUG, "Oooh, got a %s\n", f ? "digit" : "hangup"); 01455 if ((c0->pvt->pvt == pvt0) && (!c0->_softhangup)) { 01456 if (pr0->set_rtp_peer(c0, NULL, NULL, 0)) 01457 ast_log(LOG_WARNING, "Channel '%s' failed to revert\n", c0->name); 01458 } 01459 if ((c1->pvt->pvt == pvt1) && (!c1->_softhangup)) { 01460 if (pr1->set_rtp_peer(c1, NULL, NULL, 0)) 01461 ast_log(LOG_WARNING, "Channel '%s' failed to revert back\n", c1->name); 01462 } 01463 /* That's all we needed */ 01464 return 0; 01465 } else { 01466 if ((f->frametype == AST_FRAME_DTMF) || 01467 (f->frametype == AST_FRAME_VOICE) || 01468 (f->frametype == AST_FRAME_VIDEO)) { 01469 /* Forward voice or DTMF frames if they happen upon us */ 01470 if (who == c0) { 01471 ast_write(c1, f); 01472 } else if (who == c1) { 01473 ast_write(c0, f); 01474 } 01475 } 01476 ast_frfree(f); 01477 } 01478 /* Swap priority not that it's a big deal at this point */ 01479 cs[2] = cs[0]; 01480 cs[0] = cs[1]; 01481 cs[1] = cs[2]; 01482 01483 } 01484 return -1; 01485 }

void ast_rtp_destroy struct ast_rtp rtp  ) 
 

Definition at line 912 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.

00913 { 00914 if (rtp->smoother) 00915 ast_smoother_free(rtp->smoother); 00916 if (rtp->ioid) 00917 ast_io_remove(rtp->io, rtp->ioid); 00918 if (rtp->s > -1) 00919 close(rtp->s); 00920 if (rtp->rtcp) { 00921 close(rtp->rtcp->s); 00922 free(rtp->rtcp); 00923 } 00924 free(rtp); 00925 }

int ast_rtp_fd struct ast_rtp rtp  ) 
 

Definition at line 110 of file rtp.c.

References ast_rtp::s.

00111 { 00112 return rtp->s; 00113 }

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

Definition at line 683 of file rtp.c.

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

00684 { 00685 int pt; 00686 00687 *astFormats = *nonAstFormats = 0; 00688 for (pt = 0; pt < MAX_RTP_PT; ++pt) { 00689 if (rtp->current_RTP_PT[pt].isAstFormat) { 00690 *astFormats |= rtp->current_RTP_PT[pt].code; 00691 } else { 00692 *nonAstFormats |= rtp->current_RTP_PT[pt].code; 00693 } 00694 } 00695 }

void ast_rtp_get_peer struct ast_rtp rtp,
struct sockaddr_in *  them
 

Definition at line 890 of file rtp.c.

References ast_rtp::them.

Referenced by ast_rtp_bridge().

00891 { 00892 them->sin_family = AF_INET; 00893 them->sin_port = rtp->them.sin_port; 00894 them->sin_addr = rtp->them.sin_addr; 00895 }

void ast_rtp_get_us struct ast_rtp rtp,
struct sockaddr_in *  us
 

Definition at line 897 of file rtp.c.

References ast_rtp::us.

00898 { 00899 memcpy(us, &rtp->us, sizeof(rtp->us)); 00900 }

void ast_rtp_init void   ) 
 

Definition at line 1520 of file rtp.c.

References ast_rtp_reload().

Referenced by main().

01521 { 01522 ast_rtp_reload(); 01523 }

int ast_rtp_lookup_code struct ast_rtp rtp,
int  isAstFormat,
int  code
 

Definition at line 714 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_write().

00714 { 00715 int pt; 00716 00717 00718 if (isAstFormat == rtp->rtp_lookup_code_cache_isAstFormat && 00719 code == rtp->rtp_lookup_code_cache_code) { 00720 /* Use our cached mapping, to avoid the overhead of the loop below */ 00721 return rtp->rtp_lookup_code_cache_result; 00722 } 00723 00724 /* Check the dynamic list first */ 00725 for (pt = 0; pt < MAX_RTP_PT; ++pt) { 00726 if (rtp->current_RTP_PT[pt].code == code && 00727 rtp->current_RTP_PT[pt].isAstFormat == isAstFormat) { 00728 rtp->rtp_lookup_code_cache_isAstFormat = isAstFormat; 00729 rtp->rtp_lookup_code_cache_code = code; 00730 rtp->rtp_lookup_code_cache_result = pt; 00731 return pt; 00732 } 00733 } 00734 00735 /* Then the static list */ 00736 for (pt = 0; pt < MAX_RTP_PT; ++pt) { 00737 if (static_RTP_PT[pt].code == code && 00738 static_RTP_PT[pt].isAstFormat == isAstFormat) { 00739 rtp->rtp_lookup_code_cache_isAstFormat = isAstFormat; 00740 rtp->rtp_lookup_code_cache_code = code; 00741 rtp->rtp_lookup_code_cache_result = pt; 00742 return pt; 00743 } 00744 } 00745 return -1; 00746 }

char* ast_rtp_lookup_mime_subtype int  isAstFormat,
int  code
 

Definition at line 748 of file rtp.c.

00748 { 00749 int i; 00750 00751 for (i = 0; i < sizeof mimeTypes/sizeof mimeTypes[0]; ++i) { 00752 if (mimeTypes[i].payloadType.code == code && 00753 mimeTypes[i].payloadType.isAstFormat == isAstFormat) { 00754 return mimeTypes[i].subtype; 00755 } 00756 } 00757 return ""; 00758 }

struct rtpPayloadType ast_rtp_lookup_pt struct ast_rtp rtp,
int  pt
 

Definition at line 697 of file rtp.c.

References ast_rtp_lookup_pt(), rtpPayloadType::code, rtpPayloadType::isAstFormat, and MAX_RTP_PT.

Referenced by ast_rtp_lookup_pt(), and ast_rtp_read().

00698 { 00699 struct rtpPayloadType result; 00700 00701 if (pt < 0 || pt > MAX_RTP_PT) { 00702 result.isAstFormat = result.code = 0; 00703 return result; /* bogus payload type */ 00704 } 00705 /* Start with the negotiated codecs */ 00706 result = rtp->current_RTP_PT[pt]; 00707 /* If it doesn't exist, check our static RTP type list, just in case */ 00708 if (!result.code) 00709 result = static_RTP_PT[pt]; 00710 return result; 00711 }

struct ast_rtp* ast_rtp_new struct sched_context sched,
struct io_context io,
int  rtcpenable,
int  callbackmode
 

Definition at line 865 of file rtp.c.

References ast_rtp_new_with_bindaddr().

00866 { 00867 struct in_addr ia; 00868 memset(&ia, 0, sizeof(ia)); 00869 return ast_rtp_new_with_bindaddr(sched, io, rtcpenable, callbackmode, ia); 00870 }

struct ast_rtp* ast_rtp_new_with_bindaddr struct sched_context sched,
struct io_context io,
int  rtcpenable,
int  callbackmode,
struct in_addr  in
 

Definition at line 789 of file rtp.c.

References ast_io_add(), AST_IO_IN, ast_log(), ast_rtp_pt_default(), free, LOG_WARNING, and malloc.

Referenced by ast_rtp_new().

00790 { 00791 struct ast_rtp *rtp; 00792 int x; 00793 int first; 00794 int startplace; 00795 rtp = malloc(sizeof(struct ast_rtp)); 00796 if (!rtp) 00797 return NULL; 00798 memset(rtp, 0, sizeof(struct ast_rtp)); 00799 rtp->them.sin_family = AF_INET; 00800 rtp->us.sin_family = AF_INET; 00801 rtp->s = rtp_socket(); 00802 rtp->ssrc = rand(); 00803 rtp->seqno = rand() & 0xffff; 00804 if (rtp->s < 0) { 00805 free(rtp); 00806 ast_log(LOG_WARNING, "Unable to allocate socket: %s\n", strerror(errno)); 00807 return NULL; 00808 } 00809 if (sched && rtcpenable) { 00810 rtp->sched = sched; 00811 rtp->rtcp = ast_rtcp_new(); 00812 } 00813 /* Find us a place */ 00814 x = (rand() % (rtpend-rtpstart)) + rtpstart; 00815 x = x & ~1; 00816 startplace = x; 00817 for (;;) { 00818 /* Must be an even port number by RTP spec */ 00819 rtp->us.sin_port = htons(x); 00820 rtp->us.sin_addr = addr; 00821 if (rtp->rtcp) 00822 rtp->rtcp->us.sin_port = htons(x + 1); 00823 if (!(first = bind(rtp->s, (struct sockaddr *)&rtp->us, sizeof(rtp->us))) && 00824 (!rtp->rtcp || !bind(rtp->rtcp->s, (struct sockaddr *)&rtp->rtcp->us, sizeof(rtp->rtcp->us)))) 00825 break; 00826 if (!first) { 00827 /* Primary bind succeeded! Gotta recreate it */ 00828 close(rtp->s); 00829 rtp->s = rtp_socket(); 00830 } 00831 if (errno != EADDRINUSE) { 00832 ast_log(LOG_WARNING, "Unexpected bind error: %s\n", strerror(errno)); 00833 close(rtp->s); 00834 if (rtp->rtcp) { 00835 close(rtp->rtcp->s); 00836 free(rtp->rtcp); 00837 } 00838 free(rtp); 00839 return NULL; 00840 } 00841 x += 2; 00842 if (x > rtpend) 00843 x = (rtpstart + 1) & ~1; 00844 if (x == startplace) { 00845 ast_log(LOG_WARNING, "No RTP ports remaining\n"); 00846 close(rtp->s); 00847 if (rtp->rtcp) { 00848 close(rtp->rtcp->s); 00849 free(rtp->rtcp); 00850 } 00851 free(rtp); 00852 return NULL; 00853 } 00854 } 00855 if (io && sched && callbackmode) { 00856 /* Operate this one in a callback mode */ 00857 rtp->sched = sched; 00858 rtp->io = io; 00859 rtp->ioid = ast_io_add(rtp->io, rtp->s, rtpread, AST_IO_IN, rtp); 00860 } 00861 ast_rtp_pt_default(rtp); 00862 return rtp; 00863 }

int ast_rtp_proto_register struct ast_rtp_protocol proto  ) 
 

Definition at line 1259 of file rtp.c.

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

01260 { 01261 struct ast_rtp_protocol *cur; 01262 cur = protos; 01263 while(cur) { 01264 if (cur->type == proto->type) { 01265 ast_log(LOG_WARNING, "Tried to register same protocol '%s' twice\n", cur->type); 01266 return -1; 01267 } 01268 cur = cur->next; 01269 } 01270 proto->next = protos; 01271 protos = proto; 01272 return 0; 01273 }

void ast_rtp_proto_unregister struct ast_rtp_protocol proto  ) 
 

Definition at line 1241 of file rtp.c.

References ast_rtp_protocol::next.

01242 { 01243 struct ast_rtp_protocol *cur, *prev; 01244 cur = protos; 01245 prev = NULL; 01246 while(cur) { 01247 if (cur == proto) { 01248 if (prev) 01249 prev->next = proto->next; 01250 else 01251 protos = proto->next; 01252 return; 01253 } 01254 prev = cur; 01255 cur = cur->next; 01256 } 01257 }

void ast_rtp_pt_clear struct ast_rtp rtp  ) 
 

Definition at line 625 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.

00626 { 00627 int i; 00628 00629 for (i = 0; i < MAX_RTP_PT; ++i) { 00630 rtp->current_RTP_PT[i].isAstFormat = 0; 00631 rtp->current_RTP_PT[i].code = 0; 00632 } 00633 00634 rtp->rtp_lookup_code_cache_isAstFormat = 0; 00635 rtp->rtp_lookup_code_cache_code = 0; 00636 rtp->rtp_lookup_code_cache_result = 0; 00637 }

void ast_rtp_pt_default struct ast_rtp rtp  ) 
 

Definition at line 639 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().

00640 { 00641 int i; 00642 /* Initialize to default payload types */ 00643 for (i = 0; i < MAX_RTP_PT; ++i) { 00644 rtp->current_RTP_PT[i].isAstFormat = static_RTP_PT[i].isAstFormat; 00645 rtp->current_RTP_PT[i].code = static_RTP_PT[i].code; 00646 } 00647 00648 rtp->rtp_lookup_code_cache_isAstFormat = 0; 00649 rtp->rtp_lookup_code_cache_code = 0; 00650 rtp->rtp_lookup_code_cache_result = 0; 00651 }

struct ast_frame* ast_rtp_read struct ast_rtp rtp  ) 
 

Definition at line 401 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_ILBC, AST_FORMAT_MAX_AUDIO, AST_FORMAT_SLINEAR, AST_FORMAT_SPEEX, AST_FORMAT_ULAW, AST_FRAME_NULL, AST_FRAME_VIDEO, AST_FRAME_VOICE, AST_FRIENDLY_OFFSET, ast_getformatname(), ast_inet_ntoa(), ast_log(), AST_RTP_CISCO_DTMF, AST_RTP_CN, AST_RTP_DTMF, ast_rtp_lookup_pt(), rtpPayloadType::code, CRASH, ast_frame::data, ast_frame::datalen, ast_frame::delivery, ast_rtp::dtmfcount, ast_rtp::f, 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, ast_rtp::rawdata, ast_rtp::resp, ast_rtp::s, ast_frame::samples, ast_frame::src, ast_frame::subclass, and ast_rtp::them.

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

void ast_rtp_reload void   ) 
 

Definition at line 1487 of file rtp.c.

References ast_destroy(), ast_load(), ast_log(), ast_variable_retrieve(), ast_verbose(), LOG_WARNING, option_verbose, s, and VERBOSE_PREFIX_2.

Referenced by ast_module_reload(), and ast_rtp_init().

01488 { 01489 struct ast_config *cfg; 01490 char *s; 01491 rtpstart = 5000; 01492 rtpend = 31000; 01493 cfg = ast_load("rtp.conf"); 01494 if (cfg) { 01495 if ((s = ast_variable_retrieve(cfg, "general", "rtpstart"))) { 01496 rtpstart = atoi(s); 01497 if (rtpstart < 1024) 01498 rtpstart = 1024; 01499 if (rtpstart > 65535) 01500 rtpstart = 65535; 01501 } 01502 if ((s = ast_variable_retrieve(cfg, "general", "rtpend"))) { 01503 rtpend = atoi(s); 01504 if (rtpend < 1024) 01505 rtpend = 1024; 01506 if (rtpend > 65535) 01507 rtpend = 65535; 01508 } 01509 ast_destroy(cfg); 01510 } 01511 if (rtpstart >= rtpend) { 01512 ast_log(LOG_WARNING, "Unreasonable values for RTP start/end\n"); 01513 rtpstart = 5000; 01514 rtpend = 31000; 01515 } 01516 if (option_verbose > 1) 01517 ast_verbose(VERBOSE_PREFIX_2 "RTP Allocating from port range %d -> %d\n", rtpstart, rtpend); 01518 }

int ast_rtp_senddigit struct ast_rtp rtp,
char  digit
 

Definition at line 953 of file rtp.c.

References ast_inet_ntoa(), ast_log(), ast_rtp::dtmfmute, ast_rtp::lastts, LOG_NOTICE, LOG_WARNING, ast_rtp::s, ast_rtp::seqno, ast_rtp::ssrc, and ast_rtp::them.

00954 { 00955 unsigned int *rtpheader; 00956 int hdrlen = 12; 00957 int res; 00958 int ms; 00959 int x; 00960 char data[256]; 00961 char iabuf[INET_ADDRSTRLEN]; 00962 00963 if ((digit <= '9') && (digit >= '0')) 00964 digit -= '0'; 00965 else if (digit == '*') 00966 digit = 10; 00967 else if (digit == '#') 00968 digit = 11; 00969 else if ((digit >= 'A') && (digit <= 'D')) 00970 digit = digit - 'A' + 12; 00971 else if ((digit >= 'a') && (digit <= 'd')) 00972 digit = digit - 'a' + 12; 00973 else { 00974 ast_log(LOG_WARNING, "Don't know how to represent '%c'\n", digit); 00975 return -1; 00976 } 00977 00978 00979 /* If we have no peer, return immediately */ 00980 if (!rtp->them.sin_addr.s_addr) 00981 return 0; 00982 00983 gettimeofday(&rtp->dtmfmute, NULL); 00984 rtp->dtmfmute.tv_usec += (500 * 1000); 00985 if (rtp->dtmfmute.tv_usec > 1000000) { 00986 rtp->dtmfmute.tv_usec -= 1000000; 00987 rtp->dtmfmute.tv_sec += 1; 00988 } 00989 00990 ms = calc_txstamp(rtp, NULL); 00991 /* Default prediction */ 00992 rtp->lastts = rtp->lastts + ms * 8; 00993 00994 /* Get a pointer to the header */ 00995 rtpheader = (unsigned int *)data; 00996 rtpheader[0] = htonl((2 << 30) | (1 << 23) | (101 << 16) | (rtp->seqno++)); 00997 rtpheader[1] = htonl(rtp->lastts); 00998 rtpheader[2] = htonl(rtp->ssrc); 00999 rtpheader[3] = htonl((digit << 24) | (0xa << 16) | (0)); 01000 for (x=0;x<4;x++) { 01001 if (rtp->them.sin_port && rtp->them.sin_addr.s_addr) { 01002 res = sendto(rtp->s, (void *)rtpheader, hdrlen + 4, 0, (struct sockaddr *)&rtp->them, sizeof(rtp->them)); 01003 if (res <0) 01004 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)); 01005 #if 0 01006 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)); 01007 #endif 01008 } 01009 if (x ==0) { 01010 /* Clear marker bit and increment seqno */ 01011 rtpheader[0] = htonl((2 << 30) | (101 << 16) | (rtp->seqno++)); 01012 /* Make duration 800 (100ms) */ 01013 rtpheader[3] |= htonl((800)); 01014 /* Set the End bit for the last 3 */ 01015 rtpheader[3] |= htonl((1 << 23)); 01016 } 01017 } 01018 return 0; 01019 }

void ast_rtp_set_callback struct ast_rtp rtp,
ast_rtp_callback  callback
 

Definition at line 163 of file rtp.c.

References ast_rtp_callback, and ast_rtp::callback.

00164 { 00165 rtp->callback = callback; 00166 }

void ast_rtp_set_data struct ast_rtp rtp,
void *  data
 

Definition at line 158 of file rtp.c.

References ast_rtp::data.

00159 { 00160 rtp->data = data; 00161 }

void ast_rtp_set_m_type struct ast_rtp rtp,
int  pt
 

Definition at line 656 of file rtp.c.

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

00656 { 00657 if (pt < 0 || pt > MAX_RTP_PT) return; /* bogus payload type */ 00658 00659 if (static_RTP_PT[pt].code != 0) { 00660 rtp->current_RTP_PT[pt] = static_RTP_PT[pt]; 00661 } 00662 }

void ast_rtp_set_peer struct ast_rtp rtp,
struct sockaddr_in *  them
 

Definition at line 880 of file rtp.c.

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

00881 { 00882 rtp->them.sin_port = them->sin_port; 00883 rtp->them.sin_addr = them->sin_addr; 00884 if (rtp->rtcp) { 00885 rtp->rtcp->them.sin_port = htons(ntohs(them->sin_port) + 1); 00886 rtp->rtcp->them.sin_addr = them->sin_addr; 00887 } 00888 }

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

Definition at line 666 of file rtp.c.

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

00667 { 00668 int i; 00669 00670 if (pt < 0 || pt > MAX_RTP_PT) return; /* bogus payload type */ 00671 00672 for (i = 0; i < sizeof mimeTypes/sizeof mimeTypes[0]; ++i) { 00673 if (strcasecmp(mimeSubtype, mimeTypes[i].subtype) == 0 && 00674 strcasecmp(mimeType, mimeTypes[i].type) == 0) { 00675 rtp->current_RTP_PT[pt] = mimeTypes[i].payloadType; 00676 return; 00677 } 00678 } 00679 }

void ast_rtp_setnat struct ast_rtp rtp,
int  nat
 

Definition at line 168 of file rtp.c.

References ast_rtp::nat.

00169 { 00170 rtp->nat = nat; 00171 }

int ast_rtp_settos struct ast_rtp rtp,
int  tos
 

Definition at line 872 of file rtp.c.

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

00873 { 00874 int res; 00875 if ((res = setsockopt(rtp->s, IPPROTO_IP, IP_TOS, &tos, sizeof(tos)))) 00876 ast_log(LOG_WARNING, "Unable to set TOS to %d\n", tos); 00877 return res; 00878 }

void ast_rtp_stop struct ast_rtp rtp  ) 
 

Definition at line 902 of file rtp.c.

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

00903 { 00904 memset(&rtp->them.sin_addr, 0, sizeof(rtp->them.sin_addr)); 00905 memset(&rtp->them.sin_port, 0, sizeof(rtp->them.sin_port)); 00906 if (rtp->rtcp) { 00907 memset(&rtp->rtcp->them.sin_addr, 0, sizeof(rtp->them.sin_addr)); 00908 memset(&rtp->rtcp->them.sin_port, 0, sizeof(rtp->them.sin_port)); 00909 } 00910 }

int ast_rtp_write struct ast_rtp rtp,
struct ast_frame f
 

Definition at line 1112 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_ILBC, AST_FORMAT_SPEEX, AST_FORMAT_ULAW, AST_FRAME_VIDEO, AST_FRAME_VOICE, ast_frdup(), ast_getformatname(), ast_log(), ast_rtp_lookup_code(), ast_smoother_feed(), 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, ast_rtp::smoother, ast_frame::subclass, and ast_rtp::them.

01113 { 01114 struct ast_frame *f; 01115 int codec; 01116 int hdrlen = 12; 01117 int subclass; 01118 01119 01120 /* If we have no peer, return immediately */ 01121 if (!rtp->them.sin_addr.s_addr) 01122 return 0; 01123 01124 /* If there is no data length, return immediately */ 01125 if (!_f->datalen) 01126 return 0; 01127 01128 /* Make sure we have enough space for RTP header */ 01129 if ((_f->frametype != AST_FRAME_VOICE) && (_f->frametype != AST_FRAME_VIDEO)) { 01130 ast_log(LOG_WARNING, "RTP can only send voice\n"); 01131 return -1; 01132 } 01133 01134 subclass = _f->subclass; 01135 if (_f->frametype == AST_FRAME_VIDEO) 01136 subclass &= ~0x1; 01137 01138 codec = ast_rtp_lookup_code(rtp, 1, subclass); 01139 if (codec < 0) { 01140 ast_log(LOG_WARNING, "Don't know how to send format %s packets with RTP\n", ast_getformatname(_f->subclass)); 01141 return -1; 01142 } 01143 01144 if (rtp->lasttxformat != subclass) { 01145 /* New format, reset the smoother */ 01146 ast_log(LOG_DEBUG, "Ooh, format changed from %s to %s\n", ast_getformatname(rtp->lasttxformat), ast_getformatname(subclass)); 01147 rtp->lasttxformat = subclass; 01148 if (rtp->smoother) 01149 ast_smoother_free(rtp->smoother); 01150 rtp->smoother = NULL; 01151 } 01152 01153 01154 switch(subclass) { 01155 case AST_FORMAT_ULAW: 01156 case AST_FORMAT_ALAW: 01157 if (!rtp->smoother) { 01158 rtp->smoother = ast_smoother_new(160); 01159 } 01160 if (!rtp->smoother) { 01161 ast_log(LOG_WARNING, "Unable to create smoother :(\n"); 01162 return -1; 01163 } 01164 ast_smoother_feed(rtp->smoother, _f); 01165 01166 while((f = ast_smoother_read(rtp->smoother))) 01167 ast_rtp_raw_write(rtp, f, codec); 01168 break; 01169 case AST_FORMAT_ADPCM: 01170 case AST_FORMAT_G726: 01171 if (!rtp->smoother) { 01172 rtp->smoother = ast_smoother_new(80); 01173 } 01174 if (!rtp->smoother) { 01175 ast_log(LOG_WARNING, "Unable to create smoother :(\n"); 01176 return -1; 01177 } 01178 ast_smoother_feed(rtp->smoother, _f); 01179 01180 while((f = ast_smoother_read(rtp->smoother))) 01181 ast_rtp_raw_write(rtp, f, codec); 01182 break; 01183 case AST_FORMAT_G729A: 01184 if (!rtp->smoother) { 01185 rtp->smoother = ast_smoother_new(20); 01186 if (rtp->smoother) 01187 ast_smoother_set_flags(rtp->smoother, AST_SMOOTHER_FLAG_G729); 01188 } 01189 if (!rtp->smoother) { 01190 ast_log(LOG_WARNING, "Unable to create g729 smoother :(\n"); 01191 return -1; 01192 } 01193 ast_smoother_feed(rtp->smoother, _f); 01194 01195 while((f = ast_smoother_read(rtp->smoother))) 01196 ast_rtp_raw_write(rtp, f, codec); 01197 break; 01198 case AST_FORMAT_GSM: 01199 if (!rtp->smoother) { 01200 rtp->smoother = ast_smoother_new(33); 01201 } 01202 if (!rtp->smoother) { 01203 ast_log(LOG_WARNING, "Unable to create GSM smoother :(\n"); 01204 return -1; 01205 } 01206 ast_smoother_feed(rtp->smoother, _f); 01207 while((f = ast_smoother_read(rtp->smoother))) 01208 ast_rtp_raw_write(rtp, f, codec); 01209 break; 01210 case AST_FORMAT_ILBC: 01211 if (!rtp->smoother) { 01212 rtp->smoother = ast_smoother_new(50); 01213 } 01214 if (!rtp->smoother) { 01215 ast_log(LOG_WARNING, "Unable to create ILBC smoother :(\n"); 01216 return -1; 01217 } 01218 ast_smoother_feed(rtp->smoother, _f); 01219 while((f = ast_smoother_read(rtp->smoother))) 01220 ast_rtp_raw_write(rtp, f, codec); 01221 break; 01222 default: 01223 ast_log(LOG_WARNING, "Not sure about sending format %s packets\n", ast_getformatname(subclass)); 01224 /* fall through to... */ 01225 case AST_FORMAT_H261: 01226 case AST_FORMAT_H263: 01227 case AST_FORMAT_G723_1: 01228 case AST_FORMAT_SPEEX: 01229 /* Don't buffer outgoing frames; send them one-per-packet: */ 01230 if (_f->offset < hdrlen) { 01231 f = ast_frdup(_f); 01232 } else { 01233 f = _f; 01234 } 01235 ast_rtp_raw_write(rtp, f, codec); 01236 } 01237 01238 return 0; 01239 }


Generated on Tue Aug 17 16:13:56 2004 for Asterisk by doxygen 1.3.8