#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_rtp * | ast_rtp_new (struct sched_context *sched, struct io_context *io, int rtcpenable, int callbackmode) |
| ast_rtp * | ast_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_frame * | ast_rtp_read (struct ast_rtp *rtp) |
| ast_frame * | ast_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_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) |
| 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) |
|
|
DTMF (Cisco Proprietary) Definition at line 34 of file rtp.h. Referenced by ast_rtp_read(). |
|
|
'Comfort Noise' (RFC3389) Definition at line 32 of file rtp.h. Referenced by ast_rtp_read(). |
|
|
DTMF (RFC2833) Definition at line 30 of file rtp.h. Referenced by ast_rtp_read(), and ast_rtp_senddigit(). |
|
|
Maximum RTP-specific code |
|
|
|
|
|
Definition at line 119 of file rtp.c. References ast_rtp::rtcp, and ast_rtcp::s.
|
|
|
Definition at line 335 of file rtp.c. References AST_FRAME_NULL, ast_inet_ntoa(), ast_log(), CRASH, LOG_DEBUG, LOG_WARNING, ast_rtp::nat, option_debug, ast_rtp::rtcp, ast_rtcp::s, ast_rtp::them, and ast_rtcp::them. 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->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->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 }
|
|
||||||||||||||||||||||||
|
Definition at line 1351 of file rtp.c. References ast_channel::_softhangup, 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_trylock, ast_mutex_unlock, ast_read(), ast_rtp_get_peer(), ast_waitfor_n(), ast_write(), ast_frame::frametype, ast_rtp_protocol::get_codec, ast_rtp_protocol::get_rtp_info, ast_rtp_protocol::get_vrtp_info, ast_channel::lock, LOG_DEBUG, LOG_WARNING, ast_channel::masq, ast_channel::masqr, ast_channel::name, ast_channel_pvt::pvt, ast_channel::pvt, and ast_rtp_protocol::set_rtp_peer. 01352 { 01353 struct ast_frame *f; 01354 struct ast_channel *who, *cs[3]; 01355 struct ast_rtp *p0, *p1; 01356 struct ast_rtp *vp0, *vp1; 01357 struct ast_rtp_protocol *pr0, *pr1; 01358 struct sockaddr_in ac0, ac1; 01359 struct sockaddr_in vac0, vac1; 01360 struct sockaddr_in t0, t1; 01361 struct sockaddr_in vt0, vt1; 01362 char iabuf[INET_ADDRSTRLEN]; 01363 01364 void *pvt0, *pvt1; 01365 int to; 01366 int codec0,codec1, oldcodec0, oldcodec1; 01367 01368 memset(&vt0, 0, sizeof(vt0)); 01369 memset(&vt1, 0, sizeof(vt1)); 01370 memset(&vac0, 0, sizeof(vac0)); 01371 memset(&vac1, 0, sizeof(vac1)); 01372 01373 /* if need DTMF, cant native bridge */ 01374 if (flags & (AST_BRIDGE_DTMF_CHANNEL_0 | AST_BRIDGE_DTMF_CHANNEL_1)) 01375 return -2; 01376 ast_mutex_lock(&c0->lock); 01377 while(ast_mutex_trylock(&c1->lock)) { 01378 ast_mutex_unlock(&c0->lock); 01379 usleep(1); 01380 ast_mutex_lock(&c0->lock); 01381 } 01382 pr0 = get_proto(c0); 01383 pr1 = get_proto(c1); 01384 if (!pr0) { 01385 ast_log(LOG_WARNING, "Can't find native functions for channel '%s'\n", c0->name); 01386 ast_mutex_unlock(&c0->lock); 01387 ast_mutex_unlock(&c1->lock); 01388 return -1; 01389 } 01390 if (!pr1) { 01391 ast_log(LOG_WARNING, "Can't find native functions for channel '%s'\n", c1->name); 01392 ast_mutex_unlock(&c0->lock); 01393 ast_mutex_unlock(&c1->lock); 01394 return -1; 01395 } 01396 pvt0 = c0->pvt->pvt; 01397 pvt1 = c1->pvt->pvt; 01398 p0 = pr0->get_rtp_info(c0); 01399 if (pr0->get_vrtp_info) 01400 vp0 = pr0->get_vrtp_info(c0); 01401 else 01402 vp0 = NULL; 01403 p1 = pr1->get_rtp_info(c1); 01404 if (pr1->get_vrtp_info) 01405 vp1 = pr1->get_vrtp_info(c1); 01406 else 01407 vp1 = NULL; 01408 if (!p0 || !p1) { 01409 /* Somebody doesn't want to play... */ 01410 ast_mutex_unlock(&c0->lock); 01411 ast_mutex_unlock(&c1->lock); 01412 return -2; 01413 } 01414 if (pr0->get_codec) 01415 codec0 = pr0->get_codec(c0); 01416 else 01417 codec0 = 0; 01418 if (pr1->get_codec) 01419 codec1 = pr1->get_codec(c1); 01420 else 01421 codec1 = 0; 01422 if (pr0->get_codec && pr1->get_codec) { 01423 /* Hey, we can't do reinvite if both parties speak diffrent codecs */ 01424 if (!(codec0 & codec1)) { 01425 ast_log(LOG_WARNING, "codec0 = %d is not codec1 = %d, cannot native bridge.\n",codec0,codec1); 01426 ast_mutex_unlock(&c0->lock); 01427 ast_mutex_unlock(&c1->lock); 01428 return -2; 01429 } 01430 } 01431 if (pr0->set_rtp_peer(c0, p1, vp1, codec1)) 01432 ast_log(LOG_WARNING, "Channel '%s' failed to talk to '%s'\n", c0->name, c1->name); 01433 else { 01434 /* Store RTP peer */ 01435 ast_rtp_get_peer(p1, &ac1); 01436 if (vp1) 01437 ast_rtp_get_peer(vp1, &vac1); 01438 } 01439 if (pr1->set_rtp_peer(c1, p0, vp0, codec0)) 01440 ast_log(LOG_WARNING, "Channel '%s' failed to talk back to '%s'\n", c1->name, c0->name); 01441 else { 01442 /* Store RTP peer */ 01443 ast_rtp_get_peer(p0, &ac0); 01444 if (vp0) 01445 ast_rtp_get_peer(vp0, &vac0); 01446 } 01447 ast_mutex_unlock(&c0->lock); 01448 ast_mutex_unlock(&c1->lock); 01449 cs[0] = c0; 01450 cs[1] = c1; 01451 cs[2] = NULL; 01452 oldcodec0 = codec0; 01453 oldcodec1 = codec1; 01454 for (;;) { 01455 if ((c0->pvt->pvt != pvt0) || 01456 (c1->pvt->pvt != pvt1) || 01457 (c0->masq || c0->masqr || c1->masq || c1->masqr)) { 01458 ast_log(LOG_DEBUG, "Oooh, something is weird, backing out\n"); 01459 if (c0->pvt->pvt == pvt0) { 01460 if (pr0->set_rtp_peer(c0, NULL, NULL, 0)) 01461 ast_log(LOG_WARNING, "Channel '%s' failed to revert\n", c0->name); 01462 } 01463 if (c1->pvt->pvt == pvt1) { 01464 if (pr1->set_rtp_peer(c1, NULL, NULL, 0)) 01465 ast_log(LOG_WARNING, "Channel '%s' failed to revert back\n", c1->name); 01466 } 01467 /* Tell it to try again later */ 01468 return -3; 01469 } 01470 to = -1; 01471 ast_rtp_get_peer(p1, &t1); 01472 ast_rtp_get_peer(p0, &t0); 01473 if (pr0->get_codec) 01474 codec0 = pr0->get_codec(c0); 01475 if (pr1->get_codec) 01476 codec1 = pr1->get_codec(c1); 01477 if (vp1) 01478 ast_rtp_get_peer(vp1, &vt1); 01479 if (vp0) 01480 ast_rtp_get_peer(vp0, &vt0); 01481 if (inaddrcmp(&t1, &ac1) || (vp1 && inaddrcmp(&vt1, &vac1)) || (codec1 != oldcodec1)) { 01482 ast_log(LOG_DEBUG, "Oooh, '%s' changed end address to %s:%d (format %d)\n", 01483 c1->name, ast_inet_ntoa(iabuf, sizeof(iabuf), t1.sin_addr), ntohs(t1.sin_port), codec1); 01484 ast_log(LOG_DEBUG, "Oooh, '%s' changed end vaddress to %s:%d (format %d)\n", 01485 c1->name, ast_inet_ntoa(iabuf, sizeof(iabuf), vt1.sin_addr), ntohs(vt1.sin_port), codec1); 01486 ast_log(LOG_DEBUG, "Oooh, '%s' was %s:%d/(format %d)\n", 01487 c1->name, ast_inet_ntoa(iabuf, sizeof(iabuf), ac1.sin_addr), ntohs(ac1.sin_port), oldcodec1); 01488 ast_log(LOG_DEBUG, "Oooh, '%s' wasv %s:%d/(format %d)\n", 01489 c1->name, ast_inet_ntoa(iabuf, sizeof(iabuf), vac1.sin_addr), ntohs(vac1.sin_port), oldcodec1); 01490 if (pr0->set_rtp_peer(c0, t1.sin_addr.s_addr ? p1 : NULL, vt1.sin_addr.s_addr ? vp1 : NULL, codec1)) 01491 ast_log(LOG_WARNING, "Channel '%s' failed to update to '%s'\n", c0->name, c1->name); 01492 memcpy(&ac1, &t1, sizeof(ac1)); 01493 memcpy(&vac1, &vt1, sizeof(vac1)); 01494 oldcodec1 = codec1; 01495 } 01496 if (inaddrcmp(&t0, &ac0) || (vp0 && inaddrcmp(&vt0, &vac0))) { 01497 ast_log(LOG_DEBUG, "Oooh, '%s' changed end address to %s:%d (format %d)\n", 01498 c0->name, ast_inet_ntoa(iabuf, sizeof(iabuf), t0.sin_addr), ntohs(t0.sin_port), codec0); 01499 ast_log(LOG_DEBUG, "Oooh, '%s' was %s:%d/(format %d)\n", 01500 c0->name, ast_inet_ntoa(iabuf, sizeof(iabuf), ac0.sin_addr), ntohs(ac0.sin_port), oldcodec0); 01501 if (pr1->set_rtp_peer(c1, t0.sin_addr.s_addr ? p0 : NULL, vt0.sin_addr.s_addr ? vp0 : NULL, codec0)) 01502 ast_log(LOG_WARNING, "Channel '%s' failed to update to '%s'\n", c1->name, c0->name); 01503 memcpy(&ac0, &t0, sizeof(ac0)); 01504 memcpy(&vac0, &vt0, sizeof(vac0)); 01505 oldcodec0 = codec0; 01506 } 01507 who = ast_waitfor_n(cs, 2, &to); 01508 if (!who) { 01509 ast_log(LOG_DEBUG, "Ooh, empty read...\n"); 01510 /* check for hagnup / whentohangup */ 01511 if (ast_check_hangup(c0) || ast_check_hangup(c1)) 01512 break; 01513 continue; 01514 } 01515 f = ast_read(who); 01516 if (!f || ((f->frametype == AST_FRAME_DTMF) && 01517 (((who == c0) && (flags & AST_BRIDGE_DTMF_CHANNEL_0)) || 01518 ((who == c1) && (flags & AST_BRIDGE_DTMF_CHANNEL_1))))) { 01519 *fo = f; 01520 *rc = who; 01521 ast_log(LOG_DEBUG, "Oooh, got a %s\n", f ? "digit" : "hangup"); 01522 if ((c0->pvt->pvt == pvt0) && (!c0->_softhangup)) { 01523 if (pr0->set_rtp_peer(c0, NULL, NULL, 0)) 01524 ast_log(LOG_WARNING, "Channel '%s' failed to revert\n", c0->name); 01525 } 01526 if ((c1->pvt->pvt == pvt1) && (!c1->_softhangup)) { 01527 if (pr1->set_rtp_peer(c1, NULL, NULL, 0)) 01528 ast_log(LOG_WARNING, "Channel '%s' failed to revert back\n", c1->name); 01529 } 01530 /* That's all we needed */ 01531 return 0; 01532 } else { 01533 if ((f->frametype == AST_FRAME_DTMF) || 01534 (f->frametype == AST_FRAME_VOICE) || 01535 (f->frametype == AST_FRAME_VIDEO)) { 01536 /* Forward voice or DTMF frames if they happen upon us */ 01537 if (who == c0) { 01538 ast_write(c1, f); 01539 } else if (who == c1) { 01540 ast_write(c0, f); 01541 } 01542 } 01543 ast_frfree(f); 01544 } 01545 /* Swap priority not that it's a big deal at this point */ 01546 cs[2] = cs[0]; 01547 cs[0] = cs[1]; 01548 cs[1] = cs[2]; 01549 01550 } 01551 return -1; 01552 }
|
|
|
Definition at line 958 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. 00959 { 00960 if (rtp->smoother) 00961 ast_smoother_free(rtp->smoother); 00962 if (rtp->ioid) 00963 ast_io_remove(rtp->io, rtp->ioid); 00964 if (rtp->s > -1) 00965 close(rtp->s); 00966 if (rtp->rtcp) { 00967 close(rtp->rtcp->s); 00968 free(rtp->rtcp); 00969 } 00970 free(rtp); 00971 }
|
|
|
Definition at line 114 of file rtp.c. References ast_rtp::s. 00115 { 00116 return rtp->s; 00117 }
|
|
||||||||||||||||
|
Definition at line 717 of file rtp.c. References rtpPayloadType::code, ast_rtp::current_RTP_PT, and rtpPayloadType::isAstFormat. 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 }
|
|
||||||||||||
|
Definition at line 936 of file rtp.c. References ast_rtp::them. Referenced by ast_rtp_bridge(). 00937 { 00938 them->sin_family = AF_INET; 00939 them->sin_port = rtp->them.sin_port; 00940 them->sin_addr = rtp->them.sin_addr; 00941 }
|
|
||||||||||||
|
Definition at line 943 of file rtp.c. References ast_rtp::us.
|
|
|
Definition at line 1598 of file rtp.c. References ast_rtp_reload(). Referenced by main(). 01599 { 01600 ast_rtp_reload(); 01601 }
|
|
||||||||||||||||
|
Definition at line 756 of file rtp.c. References rtpPayloadType::code, ast_rtp::current_RTP_PT, rtpPayloadType::isAstFormat, 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_senddigit(), and ast_rtp_write(). 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 }
|
|
||||||||||||
|
Definition at line 790 of file rtp.c. References rtpPayloadType::code, and payloadType. 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 }
|
|
||||||||||||
|
Definition at line 738 of file rtp.c. References rtpPayloadType::code, and rtpPayloadType::isAstFormat. Referenced by ast_rtp_read(). 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 }
|
|
||||||||||||||||||||
|
Definition at line 911 of file rtp.c. References ast_rtp_new_with_bindaddr(). 00912 { 00913 struct in_addr ia; 00914 memset(&ia, 0, sizeof(ia)); 00915 return ast_rtp_new_with_bindaddr(sched, io, rtcpenable, callbackmode, ia); 00916 }
|
|
||||||||||||||||||||||||
|
Definition at line 835 of file rtp.c. References ast_io_add(), AST_IO_IN, ast_log(), ast_rtp_pt_default(), free, ast_rtp::io, ast_rtp::ioid, LOG_WARNING, malloc, ast_rtp::rtcp, ast_rtcp::s, ast_rtp::s, ast_rtp::sched, ast_rtp::seqno, ast_rtp::ssrc, ast_rtp::them, ast_rtcp::us, and ast_rtp::us. Referenced by ast_rtp_new(). 00836 { 00837 struct ast_rtp *rtp; 00838 int x; 00839 int first; 00840 int startplace; 00841 rtp = malloc(sizeof(struct ast_rtp)); 00842 if (!rtp) 00843 return NULL; 00844 memset(rtp, 0, sizeof(struct ast_rtp)); 00845 rtp->them.sin_family = AF_INET; 00846 rtp->us.sin_family = AF_INET; 00847 rtp->s = rtp_socket(); 00848 rtp->ssrc = rand(); 00849 rtp->seqno = rand() & 0xffff; 00850 if (rtp->s < 0) { 00851 free(rtp); 00852 ast_log(LOG_WARNING, "Unable to allocate socket: %s\n", strerror(errno)); 00853 return NULL; 00854 } 00855 if (sched && rtcpenable) { 00856 rtp->sched = sched; 00857 rtp->rtcp = ast_rtcp_new(); 00858 } 00859 /* Find us a place */ 00860 x = (rand() % (rtpend-rtpstart)) + rtpstart; 00861 x = x & ~1; 00862 startplace = x; 00863 for (;;) { 00864 /* Must be an even port number by RTP spec */ 00865 rtp->us.sin_port = htons(x); 00866 rtp->us.sin_addr = addr; 00867 if (rtp->rtcp) 00868 rtp->rtcp->us.sin_port = htons(x + 1); 00869 if (!(first = bind(rtp->s, (struct sockaddr *)&rtp->us, sizeof(rtp->us))) && 00870 (!rtp->rtcp || !bind(rtp->rtcp->s, (struct sockaddr *)&rtp->rtcp->us, sizeof(rtp->rtcp->us)))) 00871 break; 00872 if (!first) { 00873 /* Primary bind succeeded! Gotta recreate it */ 00874 close(rtp->s); 00875 rtp->s = rtp_socket(); 00876 } 00877 if (errno != EADDRINUSE) { 00878 ast_log(LOG_WARNING, "Unexpected bind error: %s\n", strerror(errno)); 00879 close(rtp->s); 00880 if (rtp->rtcp) { 00881 close(rtp->rtcp->s); 00882 free(rtp->rtcp); 00883 } 00884 free(rtp); 00885 return NULL; 00886 } 00887 x += 2; 00888 if (x > rtpend) 00889 x = (rtpstart + 1) & ~1; 00890 if (x == startplace) { 00891 ast_log(LOG_WARNING, "No RTP ports remaining\n"); 00892 close(rtp->s); 00893 if (rtp->rtcp) { 00894 close(rtp->rtcp->s); 00895 free(rtp->rtcp); 00896 } 00897 free(rtp); 00898 return NULL; 00899 } 00900 } 00901 if (io && sched && callbackmode) { 00902 /* Operate this one in a callback mode */ 00903 rtp->sched = sched; 00904 rtp->io = io; 00905 rtp->ioid = ast_io_add(rtp->io, rtp->s, rtpread, AST_IO_IN, rtp); 00906 } 00907 ast_rtp_pt_default(rtp); 00908 return rtp; 00909 }
|
|
||||||||||||
|
Definition at line 731 of file rtp.c. References ast_log(), LOG_WARNING, and ast_rtp::rtp_offered_from_local. 00731 { 00732 if (rtp) 00733 rtp->rtp_offered_from_local = local; 00734 else 00735 ast_log(LOG_WARNING, "rtp structure is null\n"); 00736 }
|
|
|
Definition at line 1322 of file rtp.c. References ast_log(), LOG_WARNING, ast_rtp_protocol::next, and ast_rtp_protocol::type. 01323 { 01324 struct ast_rtp_protocol *cur; 01325 cur = protos; 01326 while(cur) { 01327 if (cur->type == proto->type) { 01328 ast_log(LOG_WARNING, "Tried to register same protocol '%s' twice\n", cur->type); 01329 return -1; 01330 } 01331 cur = cur->next; 01332 } 01333 proto->next = protos; 01334 protos = proto; 01335 return 0; 01336 }
|
|
|
Definition at line 1304 of file rtp.c. References ast_rtp_protocol::next. 01305 { 01306 struct ast_rtp_protocol *cur, *prev; 01307 cur = protos; 01308 prev = NULL; 01309 while(cur) { 01310 if (cur == proto) { 01311 if (prev) 01312 prev->next = proto->next; 01313 else 01314 protos = proto->next; 01315 return; 01316 } 01317 prev = cur; 01318 cur = cur->next; 01319 } 01320 }
|
|
|
Definition at line 659 of file rtp.c. References rtpPayloadType::code, ast_rtp::current_RTP_PT, rtpPayloadType::isAstFormat, ast_rtp::rtp_lookup_code_cache_code, ast_rtp::rtp_lookup_code_cache_isAstFormat, and ast_rtp::rtp_lookup_code_cache_result. 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 }
|
|
|
Definition at line 673 of file rtp.c. References rtpPayloadType::code, ast_rtp::current_RTP_PT, rtpPayloadType::isAstFormat, 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(). 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 }
|
|
|
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_LPC10, AST_FORMAT_MAX_AUDIO, AST_FORMAT_SLINEAR, AST_FORMAT_SPEEX, AST_FORMAT_ULAW, ast_frame_byteswap_be, 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 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 }
|
|
|
Definition at line 1554 of file rtp.c. References ast_destroy(), ast_false(), ast_load(), ast_log(), ast_variable_retrieve(), ast_verbose(), LOG_WARNING, option_verbose, and VERBOSE_PREFIX_2. Referenced by ast_module_reload(), ast_rtp_init(), and main(). 01555 { 01556 struct ast_config *cfg; 01557 char *s; 01558 rtpstart = 5000; 01559 rtpend = 31000; 01560 cfg = ast_load("rtp.conf"); 01561 if (cfg) { 01562 if ((s = ast_variable_retrieve(cfg, "general", "rtpstart"))) { 01563 rtpstart = atoi(s); 01564 if (rtpstart < 1024) 01565 rtpstart = 1024; 01566 if (rtpstart > 65535) 01567 rtpstart = 65535; 01568 } 01569 if ((s = ast_variable_retrieve(cfg, "general", "rtpend"))) { 01570 rtpend = atoi(s); 01571 if (rtpend < 1024) 01572 rtpend = 1024; 01573 if (rtpend > 65535) 01574 rtpend = 65535; 01575 } 01576 if ((s = ast_variable_retrieve(cfg, "general", "rtpchecksums"))) { 01577 #ifdef SO_NO_CHECK 01578 if (ast_false(s)) 01579 nochecksums = 1; 01580 else 01581 nochecksums = 0; 01582 #else 01583 if (ast_false(s)) 01584 ast_log(LOG_WARNING, "Disabling RTP checksums is not supported on this operating system!\n"); 01585 #endif 01586 } 01587 ast_destroy(cfg); 01588 } 01589 if (rtpstart >= rtpend) { 01590 ast_log(LOG_WARNING, "Unreasonable values for RTP start/end\n"); 01591 rtpstart = 5000; 01592 rtpend = 31000; 01593 } 01594 if (option_verbose > 1) 01595 ast_verbose(VERBOSE_PREFIX_2 "RTP Allocating from port range %d -> %d\n", rtpstart, rtpend); 01596 }
|
|
||||||||||||
|
Definition at line 999 of file rtp.c. References ast_inet_ntoa(), ast_log(), AST_RTP_DTMF, ast_rtp_lookup_code(), ast_rtp::dtmfmute, ast_rtp::lastts, LOG_NOTICE, LOG_WARNING, ast_rtp::s, ast_rtp::seqno, ast_rtp::ssrc, and ast_rtp::them. 01000 { 01001 unsigned int *rtpheader; 01002 int hdrlen = 12; 01003 int res; 01004 int x; 01005 int payload; 01006 char data[256]; 01007 char iabuf[INET_ADDRSTRLEN]; 01008 01009 if ((digit <= '9') && (digit >= '0')) 01010 digit -= '0'; 01011 else if (digit == '*') 01012 digit = 10; 01013 else if (digit == '#') 01014 digit = 11; 01015 else if ((digit >= 'A') && (digit <= 'D')) 01016 digit = digit - 'A' + 12; 01017 else if ((digit >= 'a') && (digit <= 'd')) 01018 digit = digit - 'a' + 12; 01019 else { 01020 ast_log(LOG_WARNING, "Don't know how to represent '%c'\n", digit); 01021 return -1; 01022 } 01023 payload = ast_rtp_lookup_code(rtp, 0, AST_RTP_DTMF); 01024 01025 /* If we have no peer, return immediately */ 01026 if (!rtp->them.sin_addr.s_addr) 01027 return 0; 01028 01029 gettimeofday(&rtp->dtmfmute, NULL); 01030 rtp->dtmfmute.tv_usec += (500 * 1000); 01031 if (rtp->dtmfmute.tv_usec > 1000000) { 01032 rtp->dtmfmute.tv_usec -= 1000000; 01033 rtp->dtmfmute.tv_sec += 1; 01034 } 01035 01036 /* Get a pointer to the header */ 01037 rtpheader = (unsigned int *)data; 01038 rtpheader[0] = htonl((2 << 30) | (1 << 23) | (payload << 16) | (rtp->seqno++)); 01039 rtpheader[1] = htonl(rtp->lastts); 01040 rtpheader[2] = htonl(rtp->ssrc); 01041 rtpheader[3] = htonl((digit << 24) | (0xa << 16) | (0)); 01042 for (x=0;x<6;x++) { 01043 if (rtp->them.sin_port && rtp->them.sin_addr.s_addr) { 01044 res = sendto(rtp->s, (void *)rtpheader, hdrlen + 4, 0, (struct sockaddr *)&rtp->them, sizeof(rtp->them)); 01045 if (res <0) 01046 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)); 01047 #if 0 01048 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)); 01049 #endif 01050 } 01051 if (x == 2) { 01052 /* Clear marker bit and increment seqno */ 01053 rtpheader[0] = htonl((2 << 30) | (payload << 16) | (rtp->seqno++)); 01054 /* Make duration 800 (100ms) */ 01055 rtpheader[3] |= htonl((800)); 01056 /* Set the End bit for the last 3 */ 01057 rtpheader[3] |= htonl((1 << 23)); 01058 } else if ( x < 5) { 01059 rtpheader[0] = htonl((2 << 30) | (payload << 16) | (rtp->seqno++)); 01060 } 01061 } 01062 return 0; 01063 }
|
|
||||||||||||
|
Definition at line 167 of file rtp.c. References ast_rtp::callback. 00168 { 00169 rtp->callback = callback; 00170 }
|
|
||||||||||||
|
Definition at line 162 of file rtp.c. References ast_rtp::data. 00163 { 00164 rtp->data = data; 00165 }
|
|
||||||||||||
|
Definition at line 690 of file rtp.c. References rtpPayloadType::code, and ast_rtp::current_RTP_PT. 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 }
|
|
||||||||||||
|
Definition at line 926 of file rtp.c. References ast_rtp::rtcp, ast_rtcp::them, and ast_rtp::them. 00927 { 00928 rtp->them.sin_port = them->sin_port; 00929 rtp->them.sin_addr = them->sin_addr; 00930 if (rtp->rtcp) { 00931 rtp->rtcp->them.sin_port = htons(ntohs(them->sin_port) + 1); 00932 rtp->rtcp->them.sin_addr = them->sin_addr; 00933 } 00934 }
|
|
||||||||||||||||||||
|
Definition at line 700 of file rtp.c. References ast_rtp::current_RTP_PT, subtype, and type. 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 }
|
|
||||||||||||
|
Definition at line 172 of file rtp.c. References ast_rtp::nat. 00173 { 00174 rtp->nat = nat; 00175 }
|
|
||||||||||||
|
Definition at line 918 of file rtp.c. References ast_log(), LOG_WARNING, and ast_rtp::s. 00919 { 00920 int res; 00921 if ((res = setsockopt(rtp->s, IPPROTO_IP, IP_TOS, &tos, sizeof(tos)))) 00922 ast_log(LOG_WARNING, "Unable to set TOS to %d\n", tos); 00923 return res; 00924 }
|
|
|
Definition at line 948 of file rtp.c. References ast_rtp::rtcp, ast_rtcp::them, and ast_rtp::them. 00949 { 00950 memset(&rtp->them.sin_addr, 0, sizeof(rtp->them.sin_addr)); 00951 memset(&rtp->them.sin_port, 0, sizeof(rtp->them.sin_port)); 00952 if (rtp->rtcp) { 00953 memset(&rtp->rtcp->them.sin_addr, 0, sizeof(rtp->them.sin_addr)); 00954 memset(&rtp->rtcp->them.sin_port, 0, sizeof(rtp->them.sin_port)); 00955 } 00956 }
|
|
||||||||||||
|
Definition at line 1161 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_LPC10, AST_FORMAT_SLINEAR, 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_feed_be, AST_SMOOTHER_FLAG_G729, ast_smoother_free(), ast_smoother_new(), ast_smoother_read(), ast_smoother_set_flags(), ast_frame::datalen, ast_frame::frametype, ast_rtp::lasttxformat, LOG_DEBUG, LOG_WARNING, ast_frame::offset, ast_rtp::smoother, ast_frame::subclass, and ast_rtp::them. 01162 { 01163 struct ast_frame *f; 01164 int codec; 01165 int hdrlen = 12; 01166 int subclass; 01167 01168 01169 /* If we have no peer, return immediately */ 01170 if (!rtp->them.sin_addr.s_addr) 01171 return 0; 01172 01173 /* If there is no data length, return immediately */ 01174 if (!_f->datalen) 01175 return 0; 01176 01177 /* Make sure we have enough space for RTP header */ 01178 if ((_f->frametype != AST_FRAME_VOICE) && (_f->frametype != AST_FRAME_VIDEO)) { 01179 ast_log(LOG_WARNING, "RTP can only send voice\n"); 01180 return -1; 01181 } 01182 01183 subclass = _f->subclass; 01184 if (_f->frametype == AST_FRAME_VIDEO) 01185 subclass &= ~0x1; 01186 01187 codec = ast_rtp_lookup_code(rtp, 1, subclass); 01188 if (codec < 0) { 01189 ast_log(LOG_WARNING, "Don't know how to send format %s packets with RTP\n", ast_getformatname(_f->subclass)); 01190 return -1; 01191 } 01192 01193 if (rtp->lasttxformat != subclass) { 01194 /* New format, reset the smoother */ 01195 ast_log(LOG_DEBUG, "Ooh, format changed from %s to %s\n", ast_getformatname(rtp->lasttxformat), ast_getformatname(subclass)); 01196 rtp->lasttxformat = subclass; 01197 if (rtp->smoother) 01198 ast_smoother_free(rtp->smoother); 01199 rtp->smoother = NULL; 01200 } 01201 01202 01203 switch(subclass) { 01204 case AST_FORMAT_SLINEAR: 01205 if (!rtp->smoother) { 01206 rtp->smoother = ast_smoother_new(320); 01207 } 01208 if (!rtp->smoother) { 01209 ast_log(LOG_WARNING, "Unable to create smoother :(\n"); 01210 return -1; 01211 } 01212 ast_smoother_feed_be(rtp->smoother, _f); 01213 01214 while((f = ast_smoother_read(rtp->smoother))) 01215 ast_rtp_raw_write(rtp, f, codec); 01216 break; 01217 case AST_FORMAT_ULAW: 01218 case AST_FORMAT_ALAW: 01219 if (!rtp->smoother) { 01220 rtp->smoother = ast_smoother_new(160); 01221 } 01222 if (!rtp->smoother) { 01223 ast_log(LOG_WARNING, "Unable to create smoother :(\n"); 01224 return -1; 01225 } 01226 ast_smoother_feed(rtp->smoother, _f); 01227 01228 while((f = ast_smoother_read(rtp->smoother))) 01229 ast_rtp_raw_write(rtp, f, codec); 01230 break; 01231 case AST_FORMAT_ADPCM: 01232 case AST_FORMAT_G726: 01233 if (!rtp->smoother) { 01234 rtp->smoother = ast_smoother_new(80); 01235 } 01236 if (!rtp->smoother) { 01237 ast_log(LOG_WARNING, "Unable to create smoother :(\n"); 01238 return -1; 01239 } 01240 ast_smoother_feed(rtp->smoother, _f); 01241 01242 while((f = ast_smoother_read(rtp->smoother))) 01243 ast_rtp_raw_write(rtp, f, codec); 01244 break; 01245 case AST_FORMAT_G729A: 01246 if (!rtp->smoother) { 01247 rtp->smoother = ast_smoother_new(20); 01248 if (rtp->smoother) 01249 ast_smoother_set_flags(rtp->smoother, AST_SMOOTHER_FLAG_G729); 01250 } 01251 if (!rtp->smoother) { 01252 ast_log(LOG_WARNING, "Unable to create g729 smoother :(\n"); 01253 return -1; 01254 } 01255 ast_smoother_feed(rtp->smoother, _f); 01256 01257 while((f = ast_smoother_read(rtp->smoother))) 01258 ast_rtp_raw_write(rtp, f, codec); 01259 break; 01260 case AST_FORMAT_GSM: 01261 if (!rtp->smoother) { 01262 rtp->smoother = ast_smoother_new(33); 01263 } 01264 if (!rtp->smoother) { 01265 ast_log(LOG_WARNING, "Unable to create GSM smoother :(\n"); 01266 return -1; 01267 } 01268 ast_smoother_feed(rtp->smoother, _f); 01269 while((f = ast_smoother_read(rtp->smoother))) 01270 ast_rtp_raw_write(rtp, f, codec); 01271 break; 01272 case AST_FORMAT_ILBC: 01273 if (!rtp->smoother) { 01274 rtp->smoother = ast_smoother_new(50); 01275 } 01276 if (!rtp->smoother) { 01277 ast_log(LOG_WARNING, "Unable to create ILBC smoother :(\n"); 01278 return -1; 01279 } 01280 ast_smoother_feed(rtp->smoother, _f); 01281 while((f = ast_smoother_read(rtp->smoother))) 01282 ast_rtp_raw_write(rtp, f, codec); 01283 break; 01284 default: 01285 ast_log(LOG_WARNING, "Not sure about sending format %s packets\n", ast_getformatname(subclass)); 01286 /* fall through to... */ 01287 case AST_FORMAT_H261: 01288 case AST_FORMAT_H263: 01289 case AST_FORMAT_G723_1: 01290 case AST_FORMAT_LPC10: 01291 case AST_FORMAT_SPEEX: 01292 /* Don't buffer outgoing frames; send them one-per-packet: */ 01293 if (_f->offset < hdrlen) { 01294 f = ast_frdup(_f); 01295 } else { 01296 f = _f; 01297 } 01298 ast_rtp_raw_write(rtp, f, codec); 01299 } 01300 01301 return 0; 01302 }
|
1.4.4