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

rtp.c File Reference

#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <string.h>
#include <sys/time.h>
#include <signal.h>
#include <errno.h>
#include <unistd.h>
#include <netinet/in.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <fcntl.h>
#include <asterisk/rtp.h>
#include <asterisk/frame.h>
#include <asterisk/logger.h>
#include <asterisk/options.h>
#include <asterisk/channel.h>
#include <asterisk/acl.h>
#include <asterisk/channel_pvt.h>
#include <asterisk/config.h>

Include dependency graph for rtp.c:

Include dependency graph

Go to the source code of this file.

Data Structures

struct  rtpPayloadType
struct  ast_rtp
struct  ast_rtcp

Defines

#define RTP_MTU   1200
#define TYPE_HIGH   0x0
#define TYPE_LOW   0x1
#define TYPE_SILENCE   0x2
#define TYPE_DONTSEND   0x3
#define TYPE_MASK   0x3
#define MAX_RTP_PT   256
#define FLAG_3389_WARNING   (1 << 0)

Functions

int ast_rtp_fd (struct ast_rtp *rtp)
int ast_rtcp_fd (struct ast_rtp *rtp)
void ast_rtp_set_data (struct ast_rtp *rtp, void *data)
void ast_rtp_set_callback (struct ast_rtp *rtp, ast_rtp_callback callback)
void ast_rtp_setnat (struct ast_rtp *rtp, int nat)
ast_frameast_rtcp_read (struct ast_rtp *rtp)
ast_frameast_rtp_read (struct ast_rtp *rtp)
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)
void ast_rtp_get_current_formats (struct ast_rtp *rtp, int *astFormats, int *nonAstFormats)
rtpPayloadType ast_rtp_lookup_pt (struct ast_rtp *rtp, int pt)
int ast_rtp_lookup_code (struct ast_rtp *rtp, int isAstFormat, int code)
char * ast_rtp_lookup_mime_subtype (int isAstFormat, int code)
ast_rtpast_rtp_new (struct sched_context *sched, struct io_context *io, int rtcpenable, int callbackmode)
int ast_rtp_settos (struct ast_rtp *rtp, int tos)
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_stop (struct ast_rtp *rtp)
void ast_rtp_destroy (struct ast_rtp *rtp)
int ast_rtp_senddigit (struct ast_rtp *rtp, char digit)
int ast_rtp_write (struct ast_rtp *rtp, struct ast_frame *_f)
void ast_rtp_proto_unregister (struct ast_rtp_protocol *proto)
int ast_rtp_proto_register (struct ast_rtp_protocol *proto)
int ast_rtp_bridge (struct ast_channel *c0, struct ast_channel *c1, int flags, struct ast_frame **fo, struct ast_channel **rc)
void ast_rtp_reload (void)
void ast_rtp_init (void)


Define Documentation

#define FLAG_3389_WARNING   (1 << 0)
 

Definition at line 59 of file rtp.c.

#define MAX_RTP_PT   256
 

Definition at line 57 of file rtp.c.

Referenced by ast_rtp_get_current_formats(), ast_rtp_lookup_code(), ast_rtp_lookup_pt(), ast_rtp_pt_clear(), ast_rtp_pt_default(), ast_rtp_set_m_type(), and ast_rtp_set_rtpmap_type().

#define RTP_MTU   1200
 

Definition at line 38 of file rtp.c.

#define TYPE_DONTSEND   0x3
 

Definition at line 43 of file rtp.c.

#define TYPE_HIGH   0x0
 

Definition at line 40 of file rtp.c.

#define TYPE_LOW   0x1
 

Definition at line 41 of file rtp.c.

#define TYPE_MASK   0x3
 

Definition at line 44 of file rtp.c.

#define TYPE_SILENCE   0x2
 

Definition at line 42 of file rtp.c.


Function Documentation

int ast_rtcp_fd struct ast_rtp rtp  ) 
 

Definition at line 111 of file rtp.c.

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

00112 { 00113 if (rtp->rtcp) 00114 return rtp->rtcp->s; 00115 return -1; 00116 }

struct ast_frame* ast_rtcp_read struct ast_rtp rtp  ) 
 

Definition at line 328 of file rtp.c.

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

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

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 1265 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_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, and ast_channel_pvt::pvt.

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

void ast_rtp_destroy struct ast_rtp rtp  ) 
 

Definition at line 892 of file rtp.c.

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

00893 { 00894 if (rtp->smoother) 00895 ast_smoother_free(rtp->smoother); 00896 if (rtp->ioid) 00897 ast_io_remove(rtp->io, rtp->ioid); 00898 if (rtp->s > -1) 00899 close(rtp->s); 00900 if (rtp->rtcp) { 00901 close(rtp->rtcp->s); 00902 free(rtp->rtcp); 00903 } 00904 free(rtp); 00905 }

int ast_rtp_fd struct ast_rtp rtp  ) 
 

Definition at line 106 of file rtp.c.

References ast_rtp::s.

00107 { 00108 return rtp->s; 00109 }

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

Definition at line 672 of file rtp.c.

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

00673 { 00674 int pt; 00675 00676 *astFormats = *nonAstFormats = 0; 00677 for (pt = 0; pt < MAX_RTP_PT; ++pt) { 00678 if (rtp->current_RTP_PT[pt].isAstFormat) { 00679 *astFormats |= rtp->current_RTP_PT[pt].code; 00680 } else { 00681 *nonAstFormats |= rtp->current_RTP_PT[pt].code; 00682 } 00683 } 00684 }

void ast_rtp_get_peer struct ast_rtp rtp,
struct sockaddr_in *  them
 

Definition at line 870 of file rtp.c.

References ast_rtp::them.

Referenced by ast_rtp_bridge().

00871 { 00872 them->sin_family = AF_INET; 00873 them->sin_port = rtp->them.sin_port; 00874 them->sin_addr = rtp->them.sin_addr; 00875 }

void ast_rtp_get_us struct ast_rtp rtp,
struct sockaddr_in *  us
 

Definition at line 877 of file rtp.c.

References ast_rtp::us.

00878 { 00879 memcpy(us, &rtp->us, sizeof(rtp->us)); 00880 }

void ast_rtp_init void   ) 
 

Definition at line 1496 of file rtp.c.

References ast_rtp_reload().

Referenced by main().

01497 { 01498 ast_rtp_reload(); 01499 }

int ast_rtp_lookup_code struct ast_rtp rtp,
int  isAstFormat,
int  code
 

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

00701 { 00702 int pt; 00703 00704 /* Looks up an RTP code out of our *static* outbound list */ 00705 00706 if (isAstFormat == rtp->rtp_lookup_code_cache_isAstFormat && 00707 code == rtp->rtp_lookup_code_cache_code) { 00708 // Use our cached mapping, to avoid the overhead of the loop below 00709 return rtp->rtp_lookup_code_cache_result; 00710 } 00711 00712 /* Check the dynamic list first */ 00713 for (pt = 0; pt < MAX_RTP_PT; ++pt) { 00714 if (rtp->current_RTP_PT[pt].code == code && 00715 rtp->current_RTP_PT[pt].isAstFormat == isAstFormat) { 00716 rtp->rtp_lookup_code_cache_isAstFormat = isAstFormat; 00717 rtp->rtp_lookup_code_cache_code = code; 00718 rtp->rtp_lookup_code_cache_result = pt; 00719 return pt; 00720 } 00721 } 00722 00723 /* Then the static list */ 00724 for (pt = 0; pt < MAX_RTP_PT; ++pt) { 00725 if (static_RTP_PT[pt].code == code && 00726 static_RTP_PT[pt].isAstFormat == isAstFormat) { 00727 rtp->rtp_lookup_code_cache_isAstFormat = isAstFormat; 00728 rtp->rtp_lookup_code_cache_code = code; 00729 rtp->rtp_lookup_code_cache_result = pt; 00730 return pt; 00731 } 00732 } 00733 return -1; 00734 }

char* ast_rtp_lookup_mime_subtype int  isAstFormat,
int  code
 

Definition at line 736 of file rtp.c.

00736 { 00737 int i; 00738 00739 for (i = 0; i < sizeof mimeTypes/sizeof mimeTypes[0]; ++i) { 00740 if (mimeTypes[i].payloadType.code == code && 00741 mimeTypes[i].payloadType.isAstFormat == isAstFormat) { 00742 return mimeTypes[i].subtype; 00743 } 00744 } 00745 return ""; 00746 }

struct rtpPayloadType ast_rtp_lookup_pt struct ast_rtp rtp,
int  pt
 

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

00687 { 00688 struct rtpPayloadType result; 00689 if (pt < 0 || pt > MAX_RTP_PT) { 00690 result.isAstFormat = result.code = 0; 00691 return result; // bogus payload type 00692 } 00693 /* Start with the negotiated codecs */ 00694 result = rtp->current_RTP_PT[pt]; 00695 /* If it doesn't exist, check our static RTP type list, just in case */ 00696 if (!result.code) 00697 result = static_RTP_PT[pt]; 00698 return result; 00699 }

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

Definition at line 777 of file rtp.c.

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

00778 { 00779 struct ast_rtp *rtp; 00780 int x; 00781 int first; 00782 int startplace; 00783 rtp = malloc(sizeof(struct ast_rtp)); 00784 if (!rtp) 00785 return NULL; 00786 memset(rtp, 0, sizeof(struct ast_rtp)); 00787 rtp->them.sin_family = AF_INET; 00788 rtp->us.sin_family = AF_INET; 00789 rtp->s = rtp_socket(); 00790 rtp->ssrc = rand(); 00791 rtp->seqno = rand() & 0xffff; 00792 if (rtp->s < 0) { 00793 free(rtp); 00794 ast_log(LOG_WARNING, "Unable to allocate socket: %s\n", strerror(errno)); 00795 return NULL; 00796 } 00797 if (sched && rtcpenable) { 00798 rtp->sched = sched; 00799 rtp->rtcp = ast_rtcp_new(); 00800 } 00801 /* Find us a place */ 00802 x = (rand() % (rtpend-rtpstart)) + rtpstart; 00803 x = x & ~1; 00804 startplace = x; 00805 for (;;) { 00806 /* Must be an even port number by RTP spec */ 00807 rtp->us.sin_port = htons(x); 00808 if (rtp->rtcp) 00809 rtp->rtcp->us.sin_port = htons(x + 1); 00810 if (!(first = bind(rtp->s, (struct sockaddr *)&rtp->us, sizeof(rtp->us))) && 00811 (!rtp->rtcp || !bind(rtp->rtcp->s, (struct sockaddr *)&rtp->rtcp->us, sizeof(rtp->rtcp->us)))) 00812 break; 00813 if (!first) { 00814 /* Primary bind succeeded! Gotta recreate it */ 00815 close(rtp->s); 00816 rtp->s = rtp_socket(); 00817 } 00818 if (errno != EADDRINUSE) { 00819 ast_log(LOG_WARNING, "Unexpected bind error: %s\n", strerror(errno)); 00820 close(rtp->s); 00821 if (rtp->rtcp) { 00822 close(rtp->rtcp->s); 00823 free(rtp->rtcp); 00824 } 00825 free(rtp); 00826 return NULL; 00827 } 00828 x += 2; 00829 if (x > rtpend) 00830 x = (rtpstart + 1) & ~1; 00831 if (x == startplace) { 00832 ast_log(LOG_WARNING, "No RTP ports remaining\n"); 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 } 00842 if (io && sched && callbackmode) { 00843 /* Operate this one in a callback mode */ 00844 rtp->sched = sched; 00845 rtp->io = io; 00846 rtp->ioid = ast_io_add(rtp->io, rtp->s, rtpread, AST_IO_IN, rtp); 00847 } 00848 ast_rtp_pt_default(rtp); 00849 return rtp; 00850 }

int ast_rtp_proto_register struct ast_rtp_protocol proto  ) 
 

Definition at line 1236 of file rtp.c.

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

01237 { 01238 struct ast_rtp_protocol *cur; 01239 cur = protos; 01240 while(cur) { 01241 if (cur->type == proto->type) { 01242 ast_log(LOG_WARNING, "Tried to register same protocol '%s' twice\n", cur->type); 01243 return -1; 01244 } 01245 cur = cur->next; 01246 } 01247 proto->next = protos; 01248 protos = proto; 01249 return 0; 01250 }

void ast_rtp_proto_unregister struct ast_rtp_protocol proto  ) 
 

Definition at line 1218 of file rtp.c.

References ast_rtp_protocol::next.

01219 { 01220 struct ast_rtp_protocol *cur, *prev; 01221 cur = protos; 01222 prev = NULL; 01223 while(cur) { 01224 if (cur == proto) { 01225 if (prev) 01226 prev->next = proto->next; 01227 else 01228 protos = proto->next; 01229 return; 01230 } 01231 prev = cur; 01232 cur = cur->next; 01233 } 01234 }

void ast_rtp_pt_clear struct ast_rtp rtp  ) 
 

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

00615 { 00616 int i; 00617 00618 for (i = 0; i < MAX_RTP_PT; ++i) { 00619 rtp->current_RTP_PT[i].isAstFormat = 0; 00620 rtp->current_RTP_PT[i].code = 0; 00621 } 00622 00623 rtp->rtp_lookup_code_cache_isAstFormat = 0; 00624 rtp->rtp_lookup_code_cache_code = 0; 00625 rtp->rtp_lookup_code_cache_result = 0; 00626 }

void ast_rtp_pt_default struct ast_rtp rtp  ) 
 

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

00629 { 00630 int i; 00631 /* Initialize to default payload types */ 00632 for (i = 0; i < MAX_RTP_PT; ++i) { 00633 rtp->current_RTP_PT[i].isAstFormat = static_RTP_PT[i].isAstFormat; 00634 rtp->current_RTP_PT[i].code = static_RTP_PT[i].code; 00635 } 00636 00637 rtp->rtp_lookup_code_cache_isAstFormat = 0; 00638 rtp->rtp_lookup_code_cache_code = 0; 00639 rtp->rtp_lookup_code_cache_result = 0; 00640 }

struct ast_frame* ast_rtp_read struct ast_rtp rtp  ) 
 

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

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

void ast_rtp_reload void   ) 
 

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

01464 { 01465 struct ast_config *cfg; 01466 char *s; 01467 rtpstart = 5000; 01468 rtpend = 31000; 01469 cfg = ast_load("rtp.conf"); 01470 if (cfg) { 01471 if ((s = ast_variable_retrieve(cfg, "general", "rtpstart"))) { 01472 rtpstart = atoi(s); 01473 if (rtpstart < 1024) 01474 rtpstart = 1024; 01475 if (rtpstart > 65535) 01476 rtpstart = 65535; 01477 } 01478 if ((s = ast_variable_retrieve(cfg, "general", "rtpend"))) { 01479 rtpend = atoi(s); 01480 if (rtpend < 1024) 01481 rtpend = 1024; 01482 if (rtpend > 65535) 01483 rtpend = 65535; 01484 } 01485 ast_destroy(cfg); 01486 } 01487 if (rtpstart >= rtpend) { 01488 ast_log(LOG_WARNING, "Unreasonable values for RTP start/end\n"); 01489 rtpstart = 5000; 01490 rtpend = 31000; 01491 } 01492 if (option_verbose > 1) 01493 ast_verbose(VERBOSE_PREFIX_2 "RTP Allocating from port range %d -> %d\n", rtpstart, rtpend); 01494 }

int ast_rtp_senddigit struct ast_rtp rtp,
char  digit
 

Definition at line 932 of file rtp.c.

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

00933 { 00934 unsigned int *rtpheader; 00935 int hdrlen = 12; 00936 int res; 00937 int ms; 00938 int x; 00939 char data[256]; 00940 00941 if ((digit <= '9') && (digit >= '0')) 00942 digit -= '0'; 00943 else if (digit == '*') 00944 digit = 10; 00945 else if (digit == '#') 00946 digit = 11; 00947 else if ((digit >= 'A') && (digit <= 'D')) 00948 digit = digit - 'A' + 12; 00949 else if ((digit >= 'a') && (digit <= 'd')) 00950 digit = digit - 'a' + 12; 00951 else { 00952 ast_log(LOG_WARNING, "Don't know how to represent '%c'\n", digit); 00953 return -1; 00954 } 00955 00956 00957 /* If we have no peer, return immediately */ 00958 if (!rtp->them.sin_addr.s_addr) 00959 return 0; 00960 00961 gettimeofday(&rtp->dtmfmute, NULL); 00962 rtp->dtmfmute.tv_usec += (500 * 1000); 00963 if (rtp->dtmfmute.tv_usec > 1000000) { 00964 rtp->dtmfmute.tv_usec -= 1000000; 00965 rtp->dtmfmute.tv_sec += 1; 00966 } 00967 00968 ms = calc_txstamp(rtp, NULL); 00969 /* Default prediction */ 00970 rtp->lastts = rtp->lastts + ms * 8; 00971 00972 /* Get a pointer to the header */ 00973 rtpheader = (unsigned int *)data; 00974 rtpheader[0] = htonl((2 << 30) | (1 << 23) | (101 << 16) | (rtp->seqno++)); 00975 rtpheader[1] = htonl(rtp->lastts); 00976 rtpheader[2] = htonl(rtp->ssrc); 00977 rtpheader[3] = htonl((digit << 24) | (0xa << 16) | (0)); 00978 for (x=0;x<4;x++) { 00979 if (rtp->them.sin_port && rtp->them.sin_addr.s_addr) { 00980 res = sendto(rtp->s, (void *)rtpheader, hdrlen + 4, 0, (struct sockaddr *)&rtp->them, sizeof(rtp->them)); 00981 if (res <0) 00982 ast_log(LOG_NOTICE, "RTP Transmission error to %s:%d: %s\n", inet_ntoa(rtp->them.sin_addr), ntohs(rtp->them.sin_port), strerror(errno)); 00983 #if 0 00984 printf("Sent %d bytes of RTP data to %s:%d\n", res, inet_ntoa(rtp->them.sin_addr), ntohs(rtp->them.sin_port)); 00985 #endif 00986 } 00987 if (x ==0) { 00988 /* Clear marker bit and increment seqno */ 00989 rtpheader[0] = htonl((2 << 30) | (101 << 16) | (rtp->seqno++)); 00990 /* Make duration 800 (100ms) */ 00991 rtpheader[3] |= htonl((800)); 00992 /* Set the End bit for the last 3 */ 00993 rtpheader[3] |= htonl((1 << 23)); 00994 } 00995 } 00996 return 0; 00997 }

void ast_rtp_set_callback struct ast_rtp rtp,
ast_rtp_callback  callback
 

Definition at line 159 of file rtp.c.

References ast_rtp_callback, and ast_rtp::callback.

00160 { 00161 rtp->callback = callback; 00162 }

void ast_rtp_set_data struct ast_rtp rtp,
void *  data
 

Definition at line 154 of file rtp.c.

References ast_rtp::data.

00155 { 00156 rtp->data = data; 00157 }

void ast_rtp_set_m_type struct ast_rtp rtp,
int  pt
 

Definition at line 645 of file rtp.c.

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

00645 { 00646 if (pt < 0 || pt > MAX_RTP_PT) return; // bogus payload type 00647 00648 if (static_RTP_PT[pt].code != 0) { 00649 rtp->current_RTP_PT[pt] = static_RTP_PT[pt]; 00650 } 00651 }

void ast_rtp_set_peer struct ast_rtp rtp,
struct sockaddr_in *  them
 

Definition at line 860 of file rtp.c.

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

00861 { 00862 rtp->them.sin_port = them->sin_port; 00863 rtp->them.sin_addr = them->sin_addr; 00864 if (rtp->rtcp) { 00865 rtp->rtcp->them.sin_port = htons(ntohs(them->sin_port) + 1); 00866 rtp->rtcp->them.sin_addr = them->sin_addr; 00867 } 00868 }

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

Definition at line 655 of file rtp.c.

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

00656 { 00657 int i; 00658 00659 if (pt < 0 || pt > MAX_RTP_PT) return; // bogus payload type 00660 00661 for (i = 0; i < sizeof mimeTypes/sizeof mimeTypes[0]; ++i) { 00662 if (strcasecmp(mimeSubtype, mimeTypes[i].subtype) == 0 && 00663 strcasecmp(mimeType, mimeTypes[i].type) == 0) { 00664 rtp->current_RTP_PT[pt] = mimeTypes[i].payloadType; 00665 return; 00666 } 00667 } 00668 }

void ast_rtp_setnat struct ast_rtp rtp,
int  nat
 

Definition at line 164 of file rtp.c.

References ast_rtp::nat.

00165 { 00166 rtp->nat = nat; 00167 }

int ast_rtp_settos struct ast_rtp rtp,
int  tos
 

Definition at line 852 of file rtp.c.

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

00853 { 00854 int res; 00855 if ((res = setsockopt(rtp->s, IPPROTO_IP, IP_TOS, &tos, sizeof(tos)))) 00856 ast_log(LOG_WARNING, "Unable to set TOS to %d\n", tos); 00857 return res; 00858 }

void ast_rtp_stop struct ast_rtp rtp  ) 
 

Definition at line 882 of file rtp.c.

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

00883 { 00884 memset(&rtp->them.sin_addr, 0, sizeof(rtp->them.sin_addr)); 00885 memset(&rtp->them.sin_port, 0, sizeof(rtp->them.sin_port)); 00886 if (rtp->rtcp) { 00887 memset(&rtp->rtcp->them.sin_addr, 0, sizeof(rtp->them.sin_addr)); 00888 memset(&rtp->rtcp->them.sin_port, 0, sizeof(rtp->them.sin_port)); 00889 } 00890 }

int ast_rtp_write struct ast_rtp rtp,
struct ast_frame _f
 

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

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


Variable Documentation

struct rtpPayloadType payloadType
 

Definition at line 563 of file rtp.c.

char* subtype
 

Definition at line 565 of file rtp.c.

Referenced by ast_rtp_set_rtpmap_type().

char* type
 

Definition at line 564 of file rtp.c.

Referenced by __ast_request_and_dial(), ast_channel_register(), ast_channel_register_ex(), ast_channel_unregister(), ast_pbx_outgoing_app(), ast_pbx_outgoing_exten(), ast_readfile(), ast_request(), ast_request_and_dial(), ast_rtp_set_rtpmap_type(), ast_search_dns(), ast_writefile(), and ast_writestream().


Generated on Sat Jun 12 16:41:45 2004 for Asterisk by doxygen 1.3.7