#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_CISCO_DTMF (1 << 2) |
| #define | AST_RTP_CN (1 << 1) |
| #define | AST_RTP_DTMF (1 << 0) |
| #define | AST_RTP_MAX AST_RTP_CISCO_DTMF |
Typedefs | |
| typedef int(* | ast_rtp_callback )(struct ast_rtp *rtp, struct ast_frame *f, void *data) |
Functions | |
| int | ast_rtcp_fd (struct ast_rtp *rtp) |
| struct ast_frame * | ast_rtcp_read (struct ast_rtp *rtp) |
| int | ast_rtp_bridge (struct ast_channel *c0, struct ast_channel *c1, int flags, struct ast_frame **fo, struct ast_channel **rc, int timeoutms) |
| void | ast_rtp_destroy (struct ast_rtp *rtp) |
| int | ast_rtp_fd (struct ast_rtp *rtp) |
| void | ast_rtp_get_current_formats (struct ast_rtp *rtp, int *astFormats, int *nonAstFormats) |
| int | ast_rtp_get_peer (struct ast_rtp *rtp, struct sockaddr_in *them) |
| void | ast_rtp_get_us (struct ast_rtp *rtp, struct sockaddr_in *us) |
| void | ast_rtp_init (void) |
| int | ast_rtp_lookup_code (struct ast_rtp *rtp, int isAstFormat, int code) |
| char * | ast_rtp_lookup_mime_multiple (char *buf, int size, const int capability, const int isAstFormat) |
| char * | ast_rtp_lookup_mime_subtype (int isAstFormat, int code) |
| struct rtpPayloadType | ast_rtp_lookup_pt (struct ast_rtp *rtp, int pt) |
| struct ast_rtp * | ast_rtp_new (struct sched_context *sched, struct io_context *io, int rtcpenable, int callbackmode) |
| Initializate a RTP session. | |
| struct ast_rtp * | ast_rtp_new_with_bindaddr (struct sched_context *sched, struct io_context *io, int rtcpenable, int callbackmode, struct in_addr in) |
| Initializate a RTP session using an in_addr structure. | |
| void | ast_rtp_offered_from_local (struct ast_rtp *rtp, int local) |
| int | ast_rtp_proto_register (struct ast_rtp_protocol *proto) |
| void | ast_rtp_proto_unregister (struct ast_rtp_protocol *proto) |
| void | ast_rtp_pt_clear (struct ast_rtp *rtp) |
| void | ast_rtp_pt_default (struct ast_rtp *rtp) |
| struct ast_frame * | ast_rtp_read (struct ast_rtp *rtp) |
| void | ast_rtp_reload (void) |
| void | ast_rtp_reset (struct ast_rtp *rtp) |
| int | ast_rtp_sendcng (struct ast_rtp *rtp, int level) |
| int | ast_rtp_senddigit (struct ast_rtp *rtp, char digit) |
| void | ast_rtp_set_callback (struct ast_rtp *rtp, ast_rtp_callback callback) |
| void | ast_rtp_set_data (struct ast_rtp *rtp, void *data) |
| void | ast_rtp_set_m_type (struct ast_rtp *rtp, int pt) |
| void | ast_rtp_set_peer (struct ast_rtp *rtp, struct sockaddr_in *them) |
| void | ast_rtp_set_rtpmap_type (struct ast_rtp *rtp, int pt, char *mimeType, char *mimeSubtype) |
| void | ast_rtp_setnat (struct ast_rtp *rtp, int nat) |
| int | ast_rtp_settos (struct ast_rtp *rtp, int tos) |
| void | ast_rtp_stop (struct ast_rtp *rtp) |
| int | ast_rtp_write (struct ast_rtp *rtp, struct ast_frame *f) |
RTP is defined in RFC 3550.
Definition in file rtp.h.
| #define AST_RTP_CISCO_DTMF (1 << 2) |
| #define AST_RTP_CN (1 << 1) |
'Comfort Noise' (RFC3389)
Definition at line 44 of file rtp.h.
Referenced by ast_rtp_read(), and ast_rtp_sendcng().
| #define AST_RTP_DTMF (1 << 0) |
DTMF (RFC2833)
Definition at line 42 of file rtp.h.
Referenced by add_noncodec_to_sdp(), add_sdp(), ast_rtp_read(), ast_rtp_senddigit(), check_user_full(), create_addr(), create_addr_from_peer(), oh323_alloc(), oh323_request(), process_sdp(), and sip_alloc().
| #define AST_RTP_MAX AST_RTP_CISCO_DTMF |
Maximum RTP-specific code
Definition at line 48 of file rtp.h.
Referenced by add_sdp(), and ast_rtp_lookup_mime_multiple().
| typedef int(* ast_rtp_callback)(struct ast_rtp *rtp, struct ast_frame *f, void *data) |
| int ast_rtcp_fd | ( | struct ast_rtp * | rtp | ) |
Definition at line 158 of file rtp.c.
References ast_rtp::rtcp, and ast_rtcp::s.
Referenced by sip_new().
Definition at line 370 of file rtp.c.
References AST_FRAME_NULL, ast_inet_ntoa(), ast_log(), CRASH, LOG_DEBUG, LOG_WARNING, ast_rtp::nat, option_debug, ast_rtp::rtcp, ast_rtcp::s, and ast_rtcp::them.
Referenced by sip_rtp_read().
00371 { 00372 static struct ast_frame null_frame = { AST_FRAME_NULL, }; 00373 socklen_t len; 00374 int hdrlen = 8; 00375 int res; 00376 struct sockaddr_in sin; 00377 unsigned int rtcpdata[1024]; 00378 char iabuf[INET_ADDRSTRLEN]; 00379 00380 if (!rtp || !rtp->rtcp) 00381 return &null_frame; 00382 00383 len = sizeof(sin); 00384 00385 res = recvfrom(rtp->rtcp->s, rtcpdata, sizeof(rtcpdata), 00386 0, (struct sockaddr *)&sin, &len); 00387 00388 if (res < 0) { 00389 if (errno == EBADF) 00390 CRASH; 00391 if (errno != EAGAIN) { 00392 ast_log(LOG_WARNING, "RTP Read error: %s. Hanging up now.\n", strerror(errno)); 00393 return NULL; 00394 } 00395 return &null_frame; 00396 } 00397 00398 if (res < hdrlen) { 00399 ast_log(LOG_WARNING, "RTP Read too short\n"); 00400 return &null_frame; 00401 } 00402 00403 if (rtp->nat) { 00404 /* Send to whoever sent to us */ 00405 if ((rtp->rtcp->them.sin_addr.s_addr != sin.sin_addr.s_addr) || 00406 (rtp->rtcp->them.sin_port != sin.sin_port)) { 00407 memcpy(&rtp->rtcp->them, &sin, sizeof(rtp->rtcp->them)); 00408 if (option_debug || rtpdebug) 00409 ast_log(LOG_DEBUG, "RTCP NAT: Got RTCP from other end. Now sending to address %s:%d\n", ast_inet_ntoa(iabuf, sizeof(iabuf), rtp->rtcp->them.sin_addr), ntohs(rtp->rtcp->them.sin_port)); 00410 } 00411 } 00412 if (option_debug) 00413 ast_log(LOG_DEBUG, "Got RTCP report of %d bytes\n", res); 00414 return &null_frame; 00415 }
| int ast_rtp_bridge | ( | struct ast_channel * | c0, | |
| struct ast_channel * | c1, | |||
| int | flags, | |||
| struct ast_frame ** | fo, | |||
| struct ast_channel ** | rc, | |||
| int | timeoutms | |||
| ) |
Definition at line 1539 of file rtp.c.
References ast_channel::_softhangup, AST_BRIDGE_COMPLETE, AST_BRIDGE_DTMF_CHANNEL_0, AST_BRIDGE_DTMF_CHANNEL_1, AST_BRIDGE_FAILED, AST_BRIDGE_FAILED_NOWARN, AST_BRIDGE_IGNORE_SIGS, AST_BRIDGE_RETRY, ast_check_hangup(), AST_CONTROL_HOLD, AST_CONTROL_UNHOLD, AST_CONTROL_VIDUPDATE, AST_FRAME_CONTROL, AST_FRAME_DTMF, AST_FRAME_VIDEO, AST_FRAME_VOICE, ast_frfree(), ast_indicate(), ast_inet_ntoa(), ast_log(), ast_mutex_lock(), ast_mutex_trylock(), ast_mutex_unlock(), ast_read(), ast_rtp_get_peer(), ast_test_flag, ast_waitfor_n(), ast_write(), FLAG_NAT_ACTIVE, ast_frame::frametype, ast_rtp_protocol::get_codec, get_proto(), ast_rtp_protocol::get_rtp_info, ast_rtp_protocol::get_vrtp_info, inaddrcmp(), ast_channel::lock, LOG_DEBUG, LOG_WARNING, ast_channel::masq, ast_channel::masqr, ast_channel::name, option_debug, ast_rtp_protocol::set_rtp_peer, ast_frame::subclass, and ast_channel::tech_pvt.
01540 { 01541 struct ast_frame *f; 01542 struct ast_channel *who, *cs[3]; 01543 struct ast_rtp *p0, *p1; /* Audio RTP Channels */ 01544 struct ast_rtp *vp0, *vp1; /* Video RTP channels */ 01545 struct ast_rtp_protocol *pr0, *pr1; 01546 struct sockaddr_in ac0, ac1; 01547 struct sockaddr_in vac0, vac1; 01548 struct sockaddr_in t0, t1; 01549 struct sockaddr_in vt0, vt1; 01550 char iabuf[INET_ADDRSTRLEN]; 01551 01552 void *pvt0, *pvt1; 01553 int codec0,codec1, oldcodec0, oldcodec1; 01554 01555 memset(&vt0, 0, sizeof(vt0)); 01556 memset(&vt1, 0, sizeof(vt1)); 01557 memset(&vac0, 0, sizeof(vac0)); 01558 memset(&vac1, 0, sizeof(vac1)); 01559 01560 /* if need DTMF, cant native bridge */ 01561 if (flags & (AST_BRIDGE_DTMF_CHANNEL_0 | AST_BRIDGE_DTMF_CHANNEL_1)) 01562 return AST_BRIDGE_FAILED_NOWARN; 01563 01564 /* Lock channels */ 01565 ast_mutex_lock(&c0->lock); 01566 while(ast_mutex_trylock(&c1->lock)) { 01567 ast_mutex_unlock(&c0->lock); 01568 usleep(1); 01569 ast_mutex_lock(&c0->lock); 01570 } 01571 01572 /* Find channel driver interfaces */ 01573 pr0 = get_proto(c0); 01574 pr1 = get_proto(c1); 01575 if (!pr0) { 01576 ast_log(LOG_WARNING, "Can't find native functions for channel '%s'\n", c0->name); 01577 ast_mutex_unlock(&c0->lock); 01578 ast_mutex_unlock(&c1->lock); 01579 return AST_BRIDGE_FAILED; 01580 } 01581 if (!pr1) { 01582 ast_log(LOG_WARNING, "Can't find native functions for channel '%s'\n", c1->name); 01583 ast_mutex_unlock(&c0->lock); 01584 ast_mutex_unlock(&c1->lock); 01585 return AST_BRIDGE_FAILED; 01586 } 01587 01588 /* Get channel specific interface structures */ 01589 pvt0 = c0->tech_pvt; 01590 pvt1 = c1->tech_pvt; 01591 01592 /* Get audio and video interface (if native bridge is possible) */ 01593 p0 = pr0->get_rtp_info(c0); 01594 if (pr0->get_vrtp_info) 01595 vp0 = pr0->get_vrtp_info(c0); 01596 else 01597 vp0 = NULL; 01598 p1 = pr1->get_rtp_info(c1); 01599 if (pr1->get_vrtp_info) 01600 vp1 = pr1->get_vrtp_info(c1); 01601 else 01602 vp1 = NULL; 01603 01604 /* Check if bridge is still possible (In SIP canreinvite=no stops this, like NAT) */ 01605 if (!p0 || !p1) { 01606 /* Somebody doesn't want to play... */ 01607 ast_mutex_unlock(&c0->lock); 01608 ast_mutex_unlock(&c1->lock); 01609 return AST_BRIDGE_FAILED_NOWARN; 01610 } 01611 /* Get codecs from both sides */ 01612 if (pr0->get_codec) 01613 codec0 = pr0->get_codec(c0); 01614 else 01615 codec0 = 0; 01616 if (pr1->get_codec) 01617 codec1 = pr1->get_codec(c1); 01618 else 01619 codec1 = 0; 01620 if (pr0->get_codec && pr1->get_codec) { 01621 /* Hey, we can't do reinvite if both parties speak different codecs */ 01622 if (!(codec0 & codec1)) { 01623 if (option_debug) 01624 ast_log(LOG_DEBUG, "Channel codec0 = %d is not codec1 = %d, cannot native bridge in RTP.\n", codec0, codec1); 01625 ast_mutex_unlock(&c0->lock); 01626 ast_mutex_unlock(&c1->lock); 01627 return AST_BRIDGE_FAILED_NOWARN; 01628 } 01629 } 01630 01631 /* Ok, we should be able to redirect the media. Start with one channel */ 01632 if (pr0->set_rtp_peer(c0, p1, vp1, codec1, ast_test_flag(p1, FLAG_NAT_ACTIVE))) 01633 ast_log(LOG_WARNING, "Channel '%s' failed to talk to '%s'\n", c0->name, c1->name); 01634 else { 01635 /* Store RTP peer */ 01636 ast_rtp_get_peer(p1, &ac1); 01637 if (vp1) 01638 ast_rtp_get_peer(vp1, &vac1); 01639 } 01640 /* Then test the other channel */ 01641 if (pr1->set_rtp_peer(c1, p0, vp0, codec0, ast_test_flag(p0, FLAG_NAT_ACTIVE))) 01642 ast_log(LOG_WARNING, "Channel '%s' failed to talk back to '%s'\n", c1->name, c0->name); 01643 else { 01644 /* Store RTP peer */ 01645 ast_rtp_get_peer(p0, &ac0); 01646 if (vp0) 01647 ast_rtp_get_peer(vp0, &vac0); 01648 } 01649 ast_mutex_unlock(&c0->lock); 01650 ast_mutex_unlock(&c1->lock); 01651 /* External RTP Bridge up, now loop and see if something happes that force us to take the 01652 media back to Asterisk */ 01653 cs[0] = c0; 01654 cs[1] = c1; 01655 cs[2] = NULL; 01656 oldcodec0 = codec0; 01657 oldcodec1 = codec1; 01658 for (;;) { 01659 /* Check if something changed... */ 01660 if ((c0->tech_pvt != pvt0) || 01661 (c1->tech_pvt != pvt1) || 01662 (c0->masq || c0->masqr || c1->masq || c1->masqr)) { 01663 ast_log(LOG_DEBUG, "Oooh, something is weird, backing out\n"); 01664 if (c0->tech_pvt == pvt0) { 01665 if (pr0->set_rtp_peer(c0, NULL, NULL, 0, 0)) 01666 ast_log(LOG_WARNING, "Channel '%s' failed to break RTP bridge\n", c0->name); 01667 } 01668 if (c1->tech_pvt == pvt1) { 01669 if (pr1->set_rtp_peer(c1, NULL, NULL, 0, 0)) 01670 ast_log(LOG_WARNING, "Channel '%s' failed to break RTP bridge\n", c1->name); 01671 } 01672 return AST_BRIDGE_RETRY; 01673 } 01674 /* Now check if they have changed address */ 01675 ast_rtp_get_peer(p1, &t1); 01676 ast_rtp_get_peer(p0, &t0); 01677 if (pr0->get_codec) 01678 codec0 = pr0->get_codec(c0); 01679 if (pr1->get_codec) 01680 codec1 = pr1->get_codec(c1); 01681 if (vp1) 01682 ast_rtp_get_peer(vp1, &vt1); 01683 if (vp0) 01684 ast_rtp_get_peer(vp0, &vt0); 01685 if (inaddrcmp(&t1, &ac1) || (vp1 && inaddrcmp(&vt1, &vac1)) || (codec1 != oldcodec1)) { 01686 if (option_debug > 1) { 01687 ast_log(LOG_DEBUG, "Oooh, '%s' changed end address to %s:%d (format %d)\n", 01688 c1->name, ast_inet_ntoa(iabuf, sizeof(iabuf), t1.sin_addr), ntohs(t1.sin_port), codec1); 01689 ast_log(LOG_DEBUG, "Oooh, '%s' changed end vaddress to %s:%d (format %d)\n", 01690 c1->name, ast_inet_ntoa(iabuf, sizeof(iabuf), vt1.sin_addr), ntohs(vt1.sin_port), codec1); 01691 ast_log(LOG_DEBUG, "Oooh, '%s' was %s:%d/(format %d)\n", 01692 c1->name, ast_inet_ntoa(iabuf, sizeof(iabuf), ac1.sin_addr), ntohs(ac1.sin_port), oldcodec1); 01693 ast_log(LOG_DEBUG, "Oooh, '%s' was %s:%d/(format %d)\n", 01694 c1->name, ast_inet_ntoa(iabuf, sizeof(iabuf), vac1.sin_addr), ntohs(vac1.sin_port), oldcodec1); 01695 } 01696 if (pr0->set_rtp_peer(c0, t1.sin_addr.s_addr ? p1 : NULL, vt1.sin_addr.s_addr ? vp1 : NULL, codec1, ast_test_flag(p1, FLAG_NAT_ACTIVE))) 01697 ast_log(LOG_WARNING, "Channel '%s' failed to update to '%s'\n", c0->name, c1->name); 01698 memcpy(&ac1, &t1, sizeof(ac1)); 01699 memcpy(&vac1, &vt1, sizeof(vac1)); 01700 oldcodec1 = codec1; 01701 } 01702 if (inaddrcmp(&t0, &ac0) || (vp0 && inaddrcmp(&vt0, &vac0))) { 01703 if (option_debug) { 01704 ast_log(LOG_DEBUG, "Oooh, '%s' changed end address to %s:%d (format %d)\n", 01705 c0->name, ast_inet_ntoa(iabuf, sizeof(iabuf), t0.sin_addr), ntohs(t0.sin_port), codec0); 01706 ast_log(LOG_DEBUG, "Oooh, '%s' was %s:%d/(format %d)\n", 01707 c0->name, ast_inet_ntoa(iabuf, sizeof(iabuf), ac0.sin_addr), ntohs(ac0.sin_port), oldcodec0); 01708 } 01709 if (pr1->set_rtp_peer(c1, t0.sin_addr.s_addr ? p0 : NULL, vt0.sin_addr.s_addr ? vp0 : NULL, codec0, ast_test_flag(p0, FLAG_NAT_ACTIVE))) 01710 ast_log(LOG_WARNING, "Channel '%s' failed to update to '%s'\n", c1->name, c0->name); 01711 memcpy(&ac0, &t0, sizeof(ac0)); 01712 memcpy(&vac0, &vt0, sizeof(vac0)); 01713 oldcodec0 = codec0; 01714 } 01715 who = ast_waitfor_n(cs, 2, &timeoutms); 01716 if (!who) { 01717 if (!timeoutms) { 01718 if (pr0->set_rtp_peer(c0, NULL, NULL, 0, 0)) 01719 ast_log(LOG_WARNING, "Channel '%s' failed to break RTP bridge\n", c0->name); 01720 if (pr1->set_rtp_peer(c1, NULL, NULL, 0, 0)) 01721 ast_log(LOG_WARNING, "Channel '%s' failed to break RTP bridge\n", c1->name); 01722 return AST_BRIDGE_RETRY; 01723 } 01724 if (option_debug) 01725 ast_log(LOG_DEBUG, "Ooh, empty read...\n"); 01726 /* check for hangup / whentohangup */ 01727 if (ast_check_hangup(c0) || ast_check_hangup(c1)) 01728 break; 01729 continue; 01730 } 01731 f = ast_read(who); 01732 if (!f || ((f->frametype == AST_FRAME_DTMF) && 01733 (((who == c0) && (flags & AST_BRIDGE_DTMF_CHANNEL_0)) || 01734 ((who == c1) && (flags & AST_BRIDGE_DTMF_CHANNEL_1))))) { 01735 *fo = f; 01736 *rc = who; 01737 if (option_debug) 01738 ast_log(LOG_DEBUG, "Oooh, got a %s\n", f ? "digit" : "hangup"); 01739 if ((c0->tech_pvt == pvt0) && (!c0->_softhangup)) { 01740 if (pr0->set_rtp_peer(c0, NULL, NULL, 0, 0)) 01741 ast_log(LOG_WARNING, "Channel '%s' failed to break RTP bridge\n", c0->name); 01742 } 01743 if ((c1->tech_pvt == pvt1) && (!c1->_softhangup)) { 01744 if (pr1->set_rtp_peer(c1, NULL, NULL, 0, 0)) 01745 ast_log(LOG_WARNING, "Channel '%s' failed to break RTP bridge\n", c1->name); 01746 } 01747 return AST_BRIDGE_COMPLETE; 01748 } else if ((f->frametype == AST_FRAME_CONTROL) && !(flags & AST_BRIDGE_IGNORE_SIGS)) { 01749 if ((f->subclass == AST_CONTROL_HOLD) || (f->subclass == AST_CONTROL_UNHOLD) || 01750 (f->subclass == AST_CONTROL_VIDUPDATE)) { 01751 ast_indicate(who == c0 ? c1 : c0, f->subclass); 01752 ast_frfree(f); 01753 } else { 01754 *fo = f; 01755 *rc = who; 01756 ast_log(LOG_DEBUG, "Got a FRAME_CONTROL (%d) frame on channel %s\n", f->subclass, who->name); 01757 return AST_BRIDGE_COMPLETE; 01758 } 01759 } else { 01760 if ((f->frametype == AST_FRAME_DTMF) || 01761 (f->frametype == AST_FRAME_VOICE) || 01762 (f->frametype == AST_FRAME_VIDEO)) { 01763 /* Forward voice or DTMF frames if they happen upon us */ 01764 if (who == c0) { 01765 ast_write(c1, f); 01766 } else if (who == c1) { 01767 ast_write(c0, f); 01768 } 01769 } 01770 ast_frfree(f); 01771 } 01772 /* Swap priority not that it's a big deal at this point */ 01773 cs[2] = cs[0]; 01774 cs[0] = cs[1]; 01775 cs[1] = cs[2]; 01776 01777 } 01778 01779 if (pr0->set_rtp_peer(c0, NULL, NULL, 0, 0)) 01780 ast_log(LOG_WARNING, "Channel '%s' failed to break RTP bridge\n", c0->name); 01781 if (pr1->set_rtp_peer(c1, NULL, NULL, 0, 0)) 01782 ast_log(LOG_WARNING, "Channel '%s' failed to break RTP bridge\n", c1->name); 01783 01784 return AST_BRIDGE_FAILED; 01785 }
| void ast_rtp_destroy | ( | struct ast_rtp * | rtp | ) |
Definition at line 1105 of file rtp.c.
References ast_io_remove(), ast_smoother_free(), free, ast_rtp::io, ast_rtp::ioid, ast_rtp::rtcp, ast_rtcp::s, ast_rtp::s, and ast_rtp::smoother.
Referenced by __oh323_destroy(), __sip_destroy(), cleanup_connection(), destroy_endpoint(), mgcp_hangup(), skinny_hangup(), start_rtp(), and unalloc_sub().
01106 { 01107 if (rtp->smoother) 01108 ast_smoother_free(rtp->smoother); 01109 if (rtp->ioid) 01110 ast_io_remove(rtp->io, rtp->ioid); 01111 if (rtp->s > -1) 01112 close(rtp->s); 01113 if (rtp->rtcp) { 01114 close(rtp->rtcp->s); 01115 free(rtp->rtcp); 01116 } 01117 free(rtp); 01118 }
| int ast_rtp_fd | ( | struct ast_rtp * | rtp | ) |
Definition at line 153 of file rtp.c.
References ast_rtp::s.
Referenced by __oh323_new(), mgcp_new(), sip_new(), skinny_new(), and start_rtp().
00154 { 00155 return rtp->s; 00156 }
| void ast_rtp_get_current_formats | ( | struct ast_rtp * | rtp, | |
| int * | astFormats, | |||
| int * | nonAstFormats | |||
| ) |
Definition at line 782 of file rtp.c.
References rtpPayloadType::code, ast_rtp::current_RTP_PT, rtpPayloadType::isAstFormat, and MAX_RTP_PT.
Referenced by process_sdp().
00783 { 00784 int pt; 00785 00786 *astFormats = *nonAstFormats = 0; 00787 for (pt = 0; pt < MAX_RTP_PT; ++pt) { 00788 if (rtp->current_RTP_PT[pt].isAstFormat) { 00789 *astFormats |= rtp->current_RTP_PT[pt].code; 00790 } else { 00791 *nonAstFormats |= rtp->current_RTP_PT[pt].code; 00792 } 00793 } 00794 }
| int ast_rtp_get_peer | ( | struct ast_rtp * | rtp, | |
| struct sockaddr_in * | them | |||
| ) |
Definition at line 1057 of file rtp.c.
References ast_rtp::them.
Referenced by add_sdp(), ast_rtp_bridge(), do_monitor(), oh323_set_rtp_peer(), sip_set_rtp_peer(), and transmit_modify_with_sdp().
01058 { 01059 if ((them->sin_family != AF_INET) || 01060 (them->sin_port != rtp->them.sin_port) || 01061 (them->sin_addr.s_addr != rtp->them.sin_addr.s_addr)) { 01062 them->sin_family = AF_INET; 01063 them->sin_port = rtp->them.sin_port; 01064 them->sin_addr = rtp->them.sin_addr; 01065 return 1; 01066 } 01067 return 0; 01068 }
| void ast_rtp_get_us | ( | struct ast_rtp * | rtp, | |
| struct sockaddr_in * | us | |||
| ) |
Definition at line 1070 of file rtp.c.
References ast_rtp::us.
Referenced by add_sdp(), external_rtp_create(), handle_message(), and oh323_set_rtp_peer().
| void ast_rtp_init | ( | void | ) |
Definition at line 1913 of file rtp.c.
References ast_cli_register(), and ast_rtp_reload().
Referenced by main().
01914 { 01915 ast_cli_register(&cli_debug); 01916 ast_cli_register(&cli_debug_ip); 01917 ast_cli_register(&cli_no_debug); 01918 ast_rtp_reload(); 01919 }
| int ast_rtp_lookup_code | ( | struct ast_rtp * | rtp, | |
| int | isAstFormat, | |||
| int | code | |||
| ) |
Definition at line 822 of file rtp.c.
References rtpPayloadType::code, ast_rtp::current_RTP_PT, rtpPayloadType::isAstFormat, MAX_RTP_PT, ast_rtp::rtp_lookup_code_cache_code, ast_rtp::rtp_lookup_code_cache_isAstFormat, and ast_rtp::rtp_lookup_code_cache_result.
Referenced by add_codec_to_sdp(), add_noncodec_to_sdp(), add_sdp(), ast_rtp_sendcng(), ast_rtp_senddigit(), and ast_rtp_write().
00822 { 00823 00824 int pt; 00825 00826 if (isAstFormat == rtp->rtp_lookup_code_cache_isAstFormat && 00827 code == rtp->rtp_lookup_code_cache_code) { 00828 00829 /* Use our cached mapping, to avoid the overhead of the loop below */ 00830 return rtp->rtp_lookup_code_cache_result; 00831 } 00832 00833 /* Check the dynamic list first */ 00834 for (pt = 0; pt < MAX_RTP_PT; ++pt) { 00835 if (rtp->current_RTP_PT[pt].code == code && rtp->current_RTP_PT[pt].isAstFormat == isAstFormat) { 00836 rtp->rtp_lookup_code_cache_isAstFormat = isAstFormat; 00837 rtp->rtp_lookup_code_cache_code = code; 00838 rtp->rtp_lookup_code_cache_result = pt; 00839 return pt; 00840 } 00841 } 00842 00843 /* Then the static list */ 00844 for (pt = 0; pt < MAX_RTP_PT; ++pt) { 00845 if (static_RTP_PT[pt].code == code && static_RTP_PT[pt].isAstFormat == isAstFormat) { 00846 rtp->rtp_lookup_code_cache_isAstFormat = isAstFormat; 00847 rtp->rtp_lookup_code_cache_code = code; 00848 rtp->rtp_lookup_code_cache_result = pt; 00849 return pt; 00850 } 00851 } 00852 return -1; 00853 }
| char* ast_rtp_lookup_mime_multiple | ( | char * | buf, | |
| int | size, | |||
| const int | capability, | |||
| const int | isAstFormat | |||
| ) |
Definition at line 867 of file rtp.c.
References ast_rtp_lookup_mime_subtype(), AST_RTP_MAX, format, and name.
Referenced by process_sdp().
00868 { 00869 int format; 00870 unsigned len; 00871 char *end = buf; 00872 char *start = buf; 00873 00874 if (!buf || !size) 00875 return NULL; 00876 00877 snprintf(end, size, "0x%x (", capability); 00878 00879 len = strlen(end); 00880 end += len; 00881 size -= len; 00882 start = end; 00883 00884 for (format = 1; format < AST_RTP_MAX; format <<= 1) { 00885 if (capability & format) { 00886 const char *name = ast_rtp_lookup_mime_subtype(isAstFormat, format); 00887 snprintf(end, size, "%s|", name); 00888 len = strlen(end); 00889 end += len; 00890 size -= len; 00891 } 00892 } 00893 00894 if (start == end) 00895 snprintf(start, size, "nothing)"); 00896 else if (size > 1) 00897 *(end -1) = ')'; 00898 00899 return buf; 00900 }
| char* ast_rtp_lookup_mime_subtype | ( | int | isAstFormat, | |
| int | code | |||
| ) |
Definition at line 855 of file rtp.c.
References rtpPayloadType::code, mimeTypes, and payloadType.
Referenced by add_codec_to_sdp(), add_noncodec_to_sdp(), add_sdp(), ast_rtp_lookup_mime_multiple(), transmit_connect_with_sdp(), and transmit_modify_with_sdp().
00855 { 00856 00857 int i; 00858 00859 for (i = 0; i < sizeof mimeTypes/sizeof mimeTypes[0]; ++i) { 00860 if (mimeTypes[i].payloadType.code == code && mimeTypes[i].payloadType.isAstFormat == isAstFormat) { 00861 return mimeTypes[i].subtype; 00862 } 00863 } 00864 return ""; 00865 }
| struct rtpPayloadType ast_rtp_lookup_pt | ( | struct ast_rtp * | rtp, | |
| int | pt | |||
| ) | [read] |
Definition at line 803 of file rtp.c.
References rtpPayloadType::code, rtpPayloadType::isAstFormat, and MAX_RTP_PT.
Referenced by ast_rtp_read(), and setup_rtp_connection().
00804 { 00805 struct rtpPayloadType result; 00806 00807 result.isAstFormat = result.code = 0; 00808 if (pt < 0 || pt > MAX_RTP_PT) 00809 return result; /* bogus payload type */ 00810 00811 /* Start with the negotiated codecs */ 00812 if (!rtp->rtp_offered_from_local) 00813 result = rtp->current_RTP_PT[pt]; 00814 00815 /* If it doesn't exist, check our static RTP type list, just in case */ 00816 if (!result.code) 00817 result = static_RTP_PT[pt]; 00818 return result; 00819 }
| struct ast_rtp* ast_rtp_new | ( | struct sched_context * | sched, | |
| struct io_context * | io, | |||
| int | rtcpenable, | |||
| int | callbackmode | |||
| ) | [read] |
Initializate a RTP session.
| sched | ||
| io | ||
| rtcpenable | ||
| callbackmode |
Definition at line 1029 of file rtp.c.
References ast_rtp_new_with_bindaddr().
Referenced by start_rtp().
01030 { 01031 struct in_addr ia; 01032 01033 memset(&ia, 0, sizeof(ia)); 01034 return ast_rtp_new_with_bindaddr(sched, io, rtcpenable, callbackmode, ia); 01035 }
| struct ast_rtp* ast_rtp_new_with_bindaddr | ( | struct sched_context * | sched, | |
| struct io_context * | io, | |||
| int | rtcpenable, | |||
| int | callbackmode, | |||
| struct in_addr | in | |||
| ) | [read] |
Initializate a RTP session using an in_addr structure.
This fuction gets called by ast_rtp_new().
| sched | ||
| io | ||
| rtcpenable | ||
| callbackmode | ||
| in |
Definition at line 940 of file rtp.c.
References ast_io_add(), AST_IO_IN, ast_log(), ast_rtcp_new(), ast_rtp_pt_default(), free, ast_rtp::io, ast_rtp::ioid, LOG_ERROR, malloc, ast_rtp::rtcp, rtp_socket(), rtpread(), ast_rtcp::s, ast_rtp::s, ast_rtp::sched, ast_rtp::seqno, ast_rtp::ssrc, ast_rtp::them, ast_rtcp::us, and ast_rtp::us.
Referenced by ast_rtp_new(), oh323_alloc(), sip_alloc(), and start_rtp().
00941 { 00942 struct ast_rtp *rtp; 00943 int x; 00944 int first; 00945 int startplace; 00946 rtp = malloc(sizeof(struct ast_rtp)); 00947 if (!rtp) 00948 return NULL; 00949 memset(rtp, 0, sizeof(struct ast_rtp)); 00950 rtp->them.sin_family = AF_INET; 00951 rtp->us.sin_family = AF_INET; 00952 rtp->s = rtp_socket(); 00953 rtp->ssrc = rand(); 00954 rtp->seqno = rand() & 0xffff; 00955 if (rtp->s < 0) { 00956 free(rtp); 00957 ast_log(LOG_ERROR, "Unable to allocate socket: %s\n", strerror(errno)); 00958 return NULL; 00959 } 00960 if (sched && rtcpenable) { 00961 rtp->sched = sched; 00962 rtp->rtcp = ast_rtcp_new(); 00963 } 00964 00965 /* Select a random port number in the range of possible RTP */ 00966 x = (rand() % (rtpend-rtpstart)) + rtpstart; 00967 x = x & ~1; 00968 /* Save it for future references. */ 00969 startplace = x; 00970 /* Iterate tring to bind that port and incrementing it otherwise untill a port was found or no ports are available. */ 00971 for (;;) { 00972 /* Must be an even port number by RTP spec */ 00973 rtp->us.sin_port = htons(x); 00974 rtp->us.sin_addr = addr; 00975 /* If there's rtcp, initialize it as well. */ 00976 if (rtp->rtcp) { 00977 rtp->rtcp->us.sin_addr = addr; 00978 rtp->rtcp->us.sin_port = htons(x + 1); 00979 } 00980 /* Try to bind it/them. */ 00981 if (!(first = bind(rtp->s, (struct sockaddr *)&rtp->us, sizeof(rtp->us))) && 00982 (!rtp->rtcp || !bind(rtp->rtcp->s, (struct sockaddr *)&rtp->rtcp->us, sizeof(rtp->rtcp->us)))) 00983 break; 00984 if (!first) { 00985 /* Primary bind succeeded! Gotta recreate it */ 00986 close(rtp->s); 00987 rtp->s = rtp_socket(); 00988 } 00989 if (errno != EADDRINUSE) { 00990 /* We got an error that wasn't expected, abort! */ 00991 ast_log(LOG_ERROR, "Unexpected bind error: %s\n", strerror(errno)); 00992 close(rtp->s); 00993 if (rtp->rtcp) { 00994 close(rtp->rtcp->s); 00995 free(rtp->rtcp); 00996 } 00997 free(rtp); 00998 return NULL; 00999 } 01000 /* The port was used, increment it (by two). */ 01001 x += 2; 01002 /* Did we go over the limit ? */ 01003 if (x > rtpend) 01004 /* then, start from the begingig. */ 01005 x = (rtpstart + 1) & ~1; 01006 /* Check if we reached the place were we started. */ 01007 if (x == startplace) { 01008 /* If so, there's no ports available. */ 01009 ast_log(LOG_ERROR, "No RTP ports remaining. Can't setup media stream for this call.\n"); 01010 close(rtp->s); 01011 if (rtp->rtcp) { 01012 close(rtp->rtcp->s); 01013 free(rtp->rtcp); 01014 } 01015 free(rtp); 01016 return NULL; 01017 } 01018 } 01019 if (io && sched && callbackmode) { 01020 /* Operate this one in a callback mode */ 01021 rtp->sched = sched; 01022 rtp->io = io; 01023 rtp->ioid = ast_io_add(rtp->io, rtp->s, rtpread, AST_IO_IN, rtp); 01024 } 01025 ast_rtp_pt_default(rtp); 01026 return rtp; 01027 }
| void ast_rtp_offered_from_local | ( | struct ast_rtp * | rtp, | |
| int | local | |||
| ) |
Definition at line 796 of file rtp.c.
References ast_log(), LOG_WARNING, and ast_rtp::rtp_offered_from_local.
Referenced by transmit_connect_with_sdp(), transmit_invite(), transmit_modify_with_sdp(), transmit_reinvite_with_sdp(), and transmit_response_with_sdp().
00796 { 00797 if (rtp) 00798 rtp->rtp_offered_from_local = local; 00799 else 00800 ast_log(LOG_WARNING, "rtp structure is null\n"); 00801 }
| int ast_rtp_proto_register | ( | struct ast_rtp_protocol * | proto | ) |
Definition at line 1505 of file rtp.c.
References ast_log(), LOG_WARNING, ast_rtp_protocol::next, and ast_rtp_protocol::type.
Referenced by load_module(), and unload_module().
01506 { 01507 struct ast_rtp_protocol *cur; 01508 cur = protos; 01509 while(cur) { 01510 if (cur->type == proto->type) { 01511 ast_log(LOG_WARNING, "Tried to register same protocol '%s' twice\n", cur->type); 01512 return -1; 01513 } 01514 cur = cur->next; 01515 } 01516 proto->next = protos; 01517 protos = proto; 01518 return 0; 01519 }
| void ast_rtp_proto_unregister | ( | struct ast_rtp_protocol * | proto | ) |
Definition at line 1485 of file rtp.c.
References ast_rtp_protocol::next.
Referenced by unload_module().
01486 { 01487 struct ast_rtp_protocol *cur, *prev; 01488 01489 cur = protos; 01490 prev = NULL; 01491 while(cur) { 01492 if (cur == proto) { 01493 if (prev) 01494 prev->next = proto->next; 01495 else 01496 protos = proto->next; 01497 return; 01498 } 01499 prev = cur; 01500 cur = cur->next; 01501 } 01502 }
| void ast_rtp_pt_clear | ( | struct ast_rtp * | rtp | ) |
Definition at line 719 of file rtp.c.
References rtpPayloadType::code, ast_rtp::current_RTP_PT, rtpPayloadType::isAstFormat, MAX_RTP_PT, ast_rtp::rtp_lookup_code_cache_code, ast_rtp::rtp_lookup_code_cache_isAstFormat, and ast_rtp::rtp_lookup_code_cache_result.
Referenced by process_sdp().
00720 { 00721 int i; 00722 if (!rtp) 00723 return; 00724 00725 for (i = 0; i < MAX_RTP_PT; ++i) { 00726 rtp->current_RTP_PT[i].isAstFormat = 0; 00727 rtp->current_RTP_PT[i].code = 0; 00728 } 00729 00730 rtp->rtp_lookup_code_cache_isAstFormat = 0; 00731 rtp->rtp_lookup_code_cache_code = 0; 00732 rtp->rtp_lookup_code_cache_result = 0; 00733 }
| void ast_rtp_pt_default | ( | struct ast_rtp * | rtp | ) |
Definition at line 735 of file rtp.c.
References rtpPayloadType::code, ast_rtp::current_RTP_PT, rtpPayloadType::isAstFormat, MAX_RTP_PT, ast_rtp::rtp_lookup_code_cache_code, ast_rtp::rtp_lookup_code_cache_isAstFormat, and ast_rtp::rtp_lookup_code_cache_result.
Referenced by ast_rtp_new_with_bindaddr().
00736 { 00737 int i; 00738 00739 /* Initialize to default payload types */ 00740 for (i = 0; i < MAX_RTP_PT; ++i) { 00741 rtp->current_RTP_PT[i].isAstFormat = static_RTP_PT[i].isAstFormat; 00742 rtp->current_RTP_PT[i].code = static_RTP_PT[i].code; 00743 } 00744 00745 rtp->rtp_lookup_code_cache_isAstFormat = 0; 00746 rtp->rtp_lookup_code_cache_code = 0; 00747 rtp->rtp_lookup_code_cache_result = 0; 00748 }
Definition at line 428 of file rtp.c.
References ast_codec_get_samples(), AST_FORMAT_MAX_AUDIO, AST_FORMAT_SLINEAR, ast_frame_byteswap_be, AST_FRAME_NULL, AST_FRAME_VIDEO, AST_FRAME_VOICE, AST_FRIENDLY_OFFSET, ast_inet_ntoa(), ast_log(), AST_RTP_CISCO_DTMF, AST_RTP_CN, AST_RTP_DTMF, ast_rtp_lookup_pt(), ast_set_flag, ast_verbose(), calc_rxstamp(), rtpPayloadType::code, CRASH, ast_frame::data, ast_frame::datalen, ast_frame::delivery, ast_rtp::dtmfcount, ast_rtp::f, FLAG_NAT_ACTIVE, ast_frame::frametype, rtpPayloadType::isAstFormat, ast_rtp::lasteventseqn, ast_rtp::lastividtimestamp, ast_rtp::lastrxformat, ast_rtp::lastrxts, LOG_DEBUG, LOG_NOTICE, LOG_WARNING, ast_frame::mallocd, ast_rtp::nat, ast_frame::offset, option_debug, process_cisco_dtmf(), process_rfc2833(), process_rfc3389(), ast_rtp::rawdata, ast_rtp::resp, rtp_debug_test_addr(), ast_rtp::rxseqno, ast_rtp::rxssrc, ast_rtp::s, ast_frame::samples, send_dtmf(), ast_frame::src, ast_frame::subclass, and ast_rtp::them.
Referenced by mgcp_rtp_read(), oh323_rtp_read(), rtpread(), sip_rtp_read(), and skinny_rtp_read().
00429 { 00430 int res; 00431 struct sockaddr_in sin; 00432 socklen_t len; 00433 unsigned int seqno; 00434 int version; 00435 int payloadtype; 00436 int hdrlen = 12; 00437 int padding; 00438 int mark; 00439 int ext; 00440 int cc; 00441 int x; 00442 char iabuf[INET_ADDRSTRLEN]; 00443 unsigned int ssrc; 00444 unsigned int timestamp; 00445 unsigned int *rtpheader; 00446 struct ast_frame *f; 00447 static struct ast_frame null_frame = { AST_FRAME_NULL, }; 00448 struct rtpPayloadType rtpPT; 00449 00450 len = sizeof(sin); 00451 00452 /* Cache where the header will go */ 00453 res = recvfrom(rtp->s, rtp->rawdata + AST_FRIENDLY_OFFSET, sizeof(rtp->rawdata) - AST_FRIENDLY_OFFSET, 00454 0, (struct sockaddr *)&sin, &len); 00455 00456 00457 rtpheader = (unsigned int *)(rtp->rawdata + AST_FRIENDLY_OFFSET); 00458 if (res < 0) { 00459 if (errno == EBADF) 00460 CRASH; 00461 if (errno != EAGAIN) { 00462 ast_log(LOG_WARNING, "RTP Read error: %s. Hanging up now.\n", strerror(errno)); 00463 return NULL; 00464 } 00465 return &null_frame; 00466 } 00467 if (res < hdrlen) { 00468 ast_log(LOG_WARNING, "RTP Read too short\n"); 00469 return &null_frame; 00470 } 00471 00472 /* Ignore if the other side hasn't been given an address 00473 yet. */ 00474 if (!rtp->them.sin_addr.s_addr || !rtp->them.sin_port) 00475 return &null_frame; 00476 00477 if (rtp->nat) { 00478 /* Send to whoever sent to us */ 00479 if ((rtp->them.sin_addr.s_addr != sin.sin_addr.s_addr) || 00480 (rtp->them.sin_port != sin.sin_port)) { 00481 memcpy(&rtp->them, &sin, sizeof(rtp->them)); 00482 rtp->rxseqno = 0; 00483 ast_set_flag(rtp, FLAG_NAT_ACTIVE); 00484 if (option_debug || rtpdebug) 00485 ast_log(LOG_DEBUG, "RTP NAT: Got audio from other end. Now sending to address %s:%d\n", ast_inet_ntoa(iabuf, sizeof(iabuf), rtp->them.sin_addr), ntohs(rtp->them.sin_port)); 00486 } 00487 } 00488 00489 /* Get fields */ 00490 seqno = ntohl(rtpheader[0]); 00491 00492 /* Check RTP version */ 00493 version = (seqno & 0xC0000000) >> 30; 00494 if (version != 2) 00495 return &null_frame; 00496 00497 payloadtype = (seqno & 0x7f0000) >> 16; 00498 padding = seqno & (1 << 29); 00499 mark = seqno & (1 << 23); 00500 ext = seqno & (1 << 28); 00501 cc = (seqno & 0xF000000) >> 24; 00502 seqno &= 0xffff; 00503 timestamp = ntohl(rtpheader[1]); 00504 ssrc = ntohl(rtpheader[2]); 00505 00506 if (!mark && rtp->rxssrc && rtp->rxssrc != ssrc) { 00507 if (option_debug || rtpdebug) 00508 ast_log(LOG_DEBUG, "Forcing Marker bit, because SSRC has changed\n"); 00509 mark = 1; 00510 } 00511 00512 rtp->rxssrc = ssrc; 00513 00514 if (padding) { 00515 /* Remove padding bytes */ 00516 res -= rtp->rawdata[AST_FRIENDLY_OFFSET + res - 1]; 00517 } 00518 00519 if (cc) { 00520 /* CSRC fields present */ 00521 hdrlen += cc*4; 00522 } 00523 00524 if (ext) { 00525 /* RTP Extension present */ 00526 hdrlen += (ntohl(rtpheader[hdrlen/4]) & 0xffff) << 2; 00527 hdrlen += 4; 00528 } 00529 00530 if (res < hdrlen) { 00531 ast_log(LOG_WARNING, "RTP Read too short (%d, expecting %d)\n", res, hdrlen); 00532 return &null_frame; 00533 } 00534 00535 if(rtp_debug_test_addr(&sin)) 00536 ast_verbose("Got RTP packet from %s:%u (type %d, seq %u, ts %u, len %d)\n" 00537 , ast_inet_ntoa(iabuf, sizeof(iabuf), sin.sin_addr), ntohs(sin.sin_port), payloadtype, seqno, timestamp,res - hdrlen); 00538 00539 rtpPT = ast_rtp_lookup_pt(rtp, payloadtype); 00540 if (!rtpPT.isAstFormat) { 00541 /* This is special in-band data that's not one of our codecs */ 00542 if (rtpPT.code == AST_RTP_DTMF) { 00543 /* It's special -- rfc2833 process it */ 00544 if(rtp_debug_test_addr(&sin)) { 00545 unsigned char *data; 00546 unsigned int event; 00547 unsigned int event_end; 00548 unsigned int duration; 00549 data = rtp->rawdata + AST_FRIENDLY_OFFSET + hdrlen; 00550 event = ntohl(*((unsigned int *)(data))); 00551 event >>= 24; 00552 event_end = ntohl(*((unsigned int *)(data))); 00553 event_end <<= 8; 00554 event_end >>= 24; 00555 duration = ntohl(*((unsigned int *)(data))); 00556 duration &= 0xFFFF; 00557 ast_verbose("Got rfc2833 RTP packet from %s:%d (type %d, seq %d, ts %d, len %d, mark %d, event %08x, end %d, duration %d) \n", ast_inet_ntoa(iabuf, sizeof(iabuf), sin.sin_addr), ntohs(sin.sin_port), payloadtype, seqno, timestamp, res - hdrlen, (mark?1:0), event, ((event_end & 0x80)?1:0), duration); 00558 } 00559 if (rtp->lasteventseqn <= seqno || rtp->resp == 0 || (rtp->lasteventseqn >= 65530 && seqno <= 6)) { 00560 f = process_rfc2833(rtp, rtp->rawdata + AST_FRIENDLY_OFFSET + hdrlen, res - hdrlen, seqno); 00561 rtp->lasteventseqn = seqno; 00562 } else 00563 f = NULL; 00564 if (f) 00565 return f; 00566 else 00567 return &null_frame; 00568 } else if (rtpPT.code == AST_RTP_CISCO_DTMF) { 00569 /* It's really special -- process it the Cisco way */ 00570 if (rtp->lasteventseqn <= seqno || rtp->resp == 0 || (rtp->lasteventseqn >= 65530 && seqno <= 6)) { 00571 f = process_cisco_dtmf(rtp, rtp->rawdata + AST_FRIENDLY_OFFSET + hdrlen, res - hdrlen); 00572 rtp->lasteventseqn = seqno; 00573 } else 00574 f = NULL; 00575 if (f) 00576 return f; 00577 else 00578 return &null_frame; 00579 } else if (rtpPT.code == AST_RTP_CN) { 00580 /* Comfort Noise */ 00581 f = process_rfc3389(rtp, rtp->rawdata + AST_FRIENDLY_OFFSET + hdrlen, res - hdrlen); 00582 if (f) 00583 return f; 00584 else 00585 return &null_frame; 00586 } else { 00587 ast_log(LOG_NOTICE, "Unknown RTP codec %d received\n", payloadtype); 00588 return &null_frame; 00589 } 00590 } 00591 rtp->f.subclass = rtpPT.code; 00592 if (rtp->f.subclass < AST_FORMAT_MAX_AUDIO) 00593 rtp->f.frametype = AST_FRAME_VOICE; 00594 else 00595 rtp->f.frametype = AST_FRAME_VIDEO; 00596 rtp->lastrxformat = rtp->f.subclass; 00597 00598 if (!rtp->lastrxts) 00599 rtp->lastrxts = timestamp; 00600 00601 if (rtp->rxseqno) { 00602 for (x=rtp->rxseqno + 1; x < seqno; x++) { 00603 /* Queue empty frames */ 00604 rtp->f.mallocd = 0; 00605 rtp->f.datalen = 0; 00606 rtp->f.data = NULL; 00607 rtp->f.offset = 0; 00608 rtp->f.samples = 0; 00609 rtp->f.src = "RTPMissedFrame"; 00610 } 00611 } 00612 rtp->rxseqno = seqno; 00613 00614 if (rtp->dtmfcount) { 00615 #if 0 00616 printf("dtmfcount was %d\n", rtp->dtmfcount); 00617 #endif 00618 rtp->dtmfcount -= (timestamp - rtp->lastrxts); 00619 if (rtp->dtmfcount < 0) 00620 rtp->dtmfcount = 0; 00621 #if 0 00622 if (dtmftimeout != rtp->dtmfcount) 00623 printf("dtmfcount is %d\n", rtp->dtmfcount); 00624 #endif 00625 } 00626 rtp->lastrxts = timestamp; 00627 00628 /* Send any pending DTMF */ 00629 if (rtp->resp && !rtp->dtmfcount) { 00630 if (option_debug) 00631 ast_log(LOG_DEBUG, "Sending pending DTMF\n"); 00632 return send_dtmf(rtp); 00633 } 00634 rtp->f.mallocd = 0; 00635 rtp->f.datalen = res - hdrlen; 00636 rtp->f.data = rtp->rawdata + hdrlen + AST_FRIENDLY_OFFSET; 00637 rtp->f.offset = hdrlen + AST_FRIENDLY_OFFSET; 00638 if (rtp->f.subclass < AST_FORMAT_MAX_AUDIO) { 00639 rtp->f.samples = ast_codec_get_samples(&rtp->f); 00640 if (rtp->f.subclass == AST_FORMAT_SLINEAR) 00641 ast_frame_byteswap_be(&rtp->f); 00642 calc_rxstamp(&rtp->f.delivery, rtp, timestamp, mark); 00643 } else { 00644 /* Video -- samples is # of samples vs. 90000 */ 00645 if (!rtp->lastividtimestamp) 00646 rtp->lastividtimestamp = timestamp; 00647 rtp->f.samples = timestamp - rtp->lastividtimestamp; 00648 rtp->lastividtimestamp = timestamp; 00649 rtp->f.delivery.tv_sec = 0; 00650 rtp->f.delivery.tv_usec = 0; 00651 if (mark) 00652 rtp->f.subclass |= 0x1; 00653 00654 } 00655 rtp->f.src = "RTP"; 00656 return &rtp->f; 00657 }
| void ast_rtp_reload | ( | void | ) |
Definition at line 1857 of file rtp.c.
References ast_config_destroy(), ast_config_load(), ast_false(), ast_log(), ast_variable_retrieve(), ast_verbose(), cfg, DEFAULT_DTMF_TIMEOUT, LOG_WARNING, option_verbose, s, and VERBOSE_PREFIX_2.
Referenced by ast_module_reload(), ast_rtp_init(), and main().
01858 { 01859 struct ast_config *cfg; 01860 char *s; 01861 01862 rtpstart = 5000; 01863 rtpend = 31000; 01864 dtmftimeout = DEFAULT_DTMF_TIMEOUT; 01865 cfg = ast_config_load("rtp.conf"); 01866 if (cfg) { 01867 if ((s = ast_variable_retrieve(cfg, "general", "rtpstart"))) { 01868 rtpstart = atoi(s); 01869 if (rtpstart < 1024) 01870 rtpstart = 1024; 01871 if (rtpstart > 65535) 01872 rtpstart = 65535; 01873 } 01874 if ((s = ast_variable_retrieve(cfg, "general", "rtpend"))) { 01875 rtpend = atoi(s); 01876 if (rtpend < 1024) 01877 rtpend = 1024; 01878 if (rtpend > 65535) 01879 rtpend = 65535; 01880 } 01881 if ((s = ast_variable_retrieve(cfg, "general", "rtpchecksums"))) { 01882 #ifdef SO_NO_CHECK 01883 if (ast_false(s)) 01884 nochecksums = 1; 01885 else 01886 nochecksums = 0; 01887 #else 01888 if (ast_false(s)) 01889 ast_log(LOG_WARNING, "Disabling RTP checksums is not supported on this operating system!\n"); 01890 #endif 01891 } 01892 if ((s = ast_variable_retrieve(cfg, "general", "dtmftimeout"))) { 01893 dtmftimeout = atoi(s); 01894 if ((dtmftimeout < 0) || (dtmftimeout > 20000)) { 01895 ast_log(LOG_WARNING, "DTMF timeout of '%d' outside range, using default of '%d' instead\n", 01896 dtmftimeout, DEFAULT_DTMF_TIMEOUT); 01897 dtmftimeout = DEFAULT_DTMF_TIMEOUT; 01898 }; 01899 } 01900 ast_config_destroy(cfg); 01901 } 01902 if (rtpstart >= rtpend) { 01903 ast_log(LOG_WARNING, "Unreasonable values for RTP start/end port in rtp.conf\n"); 01904 rtpstart = 5000; 01905 rtpend = 31000; 01906 } 01907 if (option_verbose > 1) 01908 ast_verbose(VERBOSE_PREFIX_2 "RTP Allocating from port range %d -> %d\n", rtpstart, rtpend); 01909 01910 }
| void ast_rtp_reset | ( | struct ast_rtp * | rtp | ) |
Definition at line 1085 of file rtp.c.
References ast_rtp::dtmfcount, ast_rtp::dtmfduration, ast_rtp::dtmfmute, ast_rtp::lastdigitts, ast_rtp::lasteventendseqn, ast_rtp::lasteventseqn, ast_rtp::lastividtimestamp, ast_rtp::lastovidtimestamp, ast_rtp::lastrxformat, ast_rtp::lastrxts, ast_rtp::lastts, ast_rtp::lasttxformat, ast_rtp::rxcore, ast_rtp::rxseqno, ast_rtp::seqno, and ast_rtp::txcore.
01086 { 01087 memset(&rtp->rxcore, 0, sizeof(rtp->rxcore)); 01088 memset(&rtp->txcore, 0, sizeof(rtp->txcore)); 01089 memset(&rtp->dtmfmute, 0, sizeof(rtp->dtmfmute)); 01090 rtp->lastts = 0; 01091 rtp->lastdigitts = 0; 01092 rtp->lastrxts = 0; 01093 rtp->lastividtimestamp = 0; 01094 rtp->lastovidtimestamp = 0; 01095 rtp->lasteventseqn = 0; 01096 rtp->lasteventendseqn = 0; 01097 rtp->lasttxformat = 0; 01098 rtp->lastrxformat = 0; 01099 rtp->dtmfcount = 0; 01100 rtp->dtmfduration = 0; 01101 rtp->seqno = 0; 01102 rtp->rxseqno = 0; 01103 }
| int ast_rtp_sendcng | ( | struct ast_rtp * | rtp, | |
| int | level | |||
| ) |
Definition at line 1221 of file rtp.c.
References ast_inet_ntoa(), ast_log(), AST_RTP_CN, ast_rtp_lookup_code(), ast_tvadd(), ast_verbose(), ast_rtp::dtmfmute, ast_rtp::lastts, LOG_ERROR, rtp_debug_test_addr(), ast_rtp::s, ast_rtp::seqno, ast_rtp::ssrc, and ast_rtp::them.
Referenced by do_monitor().
01222 { 01223 unsigned int *rtpheader; 01224 int hdrlen = 12; 01225 int res; 01226 int payload; 01227 char data[256]; 01228 char iabuf[INET_ADDRSTRLEN]; 01229 level = 127 - (level & 0x7f); 01230 payload = ast_rtp_lookup_code(rtp, 0, AST_RTP_CN); 01231 01232 /* If we have no peer, return immediately */ 01233 if (!rtp->them.sin_addr.s_addr) 01234 return 0; 01235 01236 rtp->dtmfmute = ast_tvadd(ast_tvnow(), ast_tv(0, 500000)); 01237 01238 /* Get a pointer to the header */ 01239 rtpheader = (unsigned int *)data; 01240 rtpheader[0] = htonl((2 << 30) | (1 << 23) | (payload << 16) | (rtp->seqno++)); 01241 rtpheader[1] = htonl(rtp->lastts); 01242 rtpheader[2] = htonl(rtp->ssrc); 01243 data[12] = level; 01244 if (rtp->them.sin_port && rtp->them.sin_addr.s_addr) { 01245 res = sendto(rtp->s, (void *)rtpheader, hdrlen + 1, 0, (struct sockaddr *)&rtp->them, sizeof(rtp->them)); 01246 if (res <0) 01247 ast_log(LOG_ERROR, "RTP Comfort Noise Transmission error to %s:%d: %s\n", ast_inet_ntoa(iabuf, sizeof(iabuf), rtp->them.sin_addr), ntohs(rtp->them.sin_port), strerror(errno)); 01248 if(rtp_debug_test_addr(&rtp->them)) 01249 ast_verbose("Sent Comfort Noise RTP packet to %s:%d (type %d, seq %d, ts %d, len %d)\n" 01250 , ast_inet_ntoa(iabuf, sizeof(iabuf), rtp->them.sin_addr), ntohs(rtp->them.sin_port), payload, rtp->seqno, rtp->lastts,res - hdrlen); 01251 01252 } 01253 return 0; 01254 }
| int ast_rtp_senddigit | ( | struct ast_rtp * | rtp, | |
| char | digit | |||
| ) |
Definition at line 1139 of file rtp.c.
References ast_inet_ntoa(), ast_log(), AST_RTP_DTMF, ast_rtp_lookup_code(), ast_tvadd(), ast_verbose(), ast_rtp::dtmfmute, ast_rtp::lastdigitts, LOG_ERROR, LOG_WARNING, rtp_debug_test_addr(), ast_rtp::s, ast_rtp::seqno, ast_rtp::ssrc, and ast_rtp::them.
Referenced by oh323_digit(), and sip_senddigit().
01140 { 01141 unsigned int *rtpheader; 01142 int hdrlen = 12; 01143 int res; 01144 int x; 01145 int payload; 01146 char data[256]; 01147 char iabuf[INET_ADDRSTRLEN]; 01148 01149 if ((digit <= '9') && (digit >= '0')) 01150 digit -= '0'; 01151 else if (digit == '*') 01152 digit = 10; 01153 else if (digit == '#') 01154 digit = 11; 01155 else if ((digit >= 'A') && (digit <= 'D')) 01156 digit = digit - 'A' + 12; 01157 else if ((digit >= 'a') && (digit <= 'd')) 01158 digit = digit - 'a' + 12; 01159 else { 01160 ast_log(LOG_WARNING, "Don't know how to represent '%c'\n", digit); 01161 return -1; 01162 } 01163 payload = ast_rtp_lookup_code(rtp, 0, AST_RTP_DTMF); 01164 01165 /* If we have no peer, return immediately */ 01166 if (!rtp->them.sin_addr.s_addr) 01167 return 0; 01168 01169 rtp->dtmfmute = ast_tvadd(ast_tvnow(), ast_tv(0, 500000)); 01170 01171 /* Get a pointer to the header */ 01172 rtpheader = (unsigned int *)data; 01173 rtpheader[0] = htonl((2 << 30) | (1 << 23) | (payload << 16) | (rtp->seqno)); 01174 rtpheader[1] = htonl(rtp->lastdigitts); 01175 rtpheader[2] = htonl(rtp->ssrc); 01176 rtpheader[3] = htonl((digit << 24) | (0xa << 16) | (0)); 01177 for (x = 0; x < 6; x++) { 01178 if (rtp->them.sin_port && rtp->them.sin_addr.s_addr) { 01179 res = sendto(rtp->s, (void *) rtpheader, hdrlen + 4, 0, (struct sockaddr *) &rtp->them, sizeof(rtp->them)); 01180 if (res < 0) 01181 ast_log(LOG_ERROR, "RTP Transmission error to %s:%d: %s\n", 01182 ast_inet_ntoa(iabuf, sizeof(iabuf), rtp->them.sin_addr), 01183 ntohs(rtp->them.sin_port), strerror(errno)); 01184 if (rtp_debug_test_addr(&rtp->them)) 01185 ast_verbose("Sent RTP packet to %s:%d (type %d, seq %u, ts %u, len %u)\n", 01186 ast_inet_ntoa(iabuf, sizeof(iabuf), rtp->them.sin_addr), 01187 ntohs(rtp->them.sin_port), payload, rtp->seqno, rtp->lastdigitts, res - hdrlen); 01188 } 01189 /* Sequence number of last two end packets does not get incremented */ 01190 if (x < 3) 01191 rtp->seqno++; 01192 /* Clear marker bit and set seqno */ 01193 rtpheader[0] = htonl((2 << 30) | (payload << 16) | (rtp->seqno)); 01194 /* For the last three packets, set the duration and the end bit */ 01195 if (x == 2) { 01196 #if 0 01197 /* No, this is wrong... Do not increment lastdigitts, that's not according 01198 to the RFC, as best we can determine */ 01199 rtp->lastdigitts++; /* or else the SPA3000 will click instead of beeping... */ 01200 rtpheader[1] = htonl(rtp->lastdigitts); 01201 #endif 01202 /* Make duration 800 (100ms) */ 01203 rtpheader[3] |= htonl((800)); 01204 /* Set the End bit */ 01205 rtpheader[3] |= htonl((1 << 23)); 01206 } 01207 } 01208 /* Increment the digit timestamp by 120ms, to ensure that digits 01209 sent sequentially with no intervening non-digit packets do not 01210 get sent with the same timestamp, and that sequential digits 01211 have some 'dead air' in between them 01212 */ 01213 rtp->lastdigitts += 960; 01214 /* Increment the sequence number to reflect the last packet 01215 that was sent 01216 */ 01217 rtp->seqno++; 01218 return 0; 01219 }
| void ast_rtp_set_callback | ( | struct ast_rtp * | rtp, | |
| ast_rtp_callback | callback | |||
| ) |
Definition at line 170 of file rtp.c.
References ast_rtp::callback.
Referenced by start_rtp().
00171 { 00172 rtp->callback = callback; 00173 }
| void ast_rtp_set_data | ( | struct ast_rtp * | rtp, | |
| void * | data | |||
| ) |
Definition at line 165 of file rtp.c.
References ast_rtp::data.
Referenced by start_rtp().
00166 { 00167 rtp->data = data; 00168 }
| void ast_rtp_set_m_type | ( | struct ast_rtp * | rtp, | |
| int | pt | |||
| ) |
Definition at line 753 of file rtp.c.
References rtpPayloadType::code, ast_rtp::current_RTP_PT, and MAX_RTP_PT.
Referenced by process_sdp().
00753 { 00754 if (pt < 0 || pt > MAX_RTP_PT) 00755 return; /* bogus payload type */ 00756 00757 if (static_RTP_PT[pt].code != 0) { 00758 rtp->current_RTP_PT[pt] = static_RTP_PT[pt]; 00759 } 00760 }
| void ast_rtp_set_peer | ( | struct ast_rtp * | rtp, | |
| struct sockaddr_in * | them | |||
| ) |
Definition at line 1046 of file rtp.c.
References ast_rtp::rtcp, ast_rtp::rxseqno, ast_rtcp::them, and ast_rtp::them.
Referenced by handle_message(), process_sdp(), and setup_rtp_connection().
01047 { 01048 rtp->them.sin_port = them->sin_port; 01049 rtp->them.sin_addr = them->sin_addr; 01050 if (rtp->rtcp) { 01051 rtp->rtcp->them.sin_port = htons(ntohs(them->sin_port) + 1); 01052 rtp->rtcp->them.sin_addr = them->sin_addr; 01053 } 01054 rtp->rxseqno = 0; 01055 }
| void ast_rtp_set_rtpmap_type | ( | struct ast_rtp * | rtp, | |
| int | pt, | |||
| char * | mimeType, | |||
| char * | mimeSubtype | |||
| ) |
Definition at line 764 of file rtp.c.
References ast_rtp::current_RTP_PT, MAX_RTP_PT, mimeTypes, subtype, and type.
Referenced by process_sdp(), and set_dtmf_payload().
00765 { 00766 int i; 00767 00768 if (pt < 0 || pt > MAX_RTP_PT) 00769 return; /* bogus payload type */ 00770 00771 for (i = 0; i < sizeof mimeTypes/sizeof mimeTypes[0]; ++i) { 00772 if (strcasecmp(mimeSubtype, mimeTypes[i].subtype) == 0 && 00773 strcasecmp(mimeType, mimeTypes[i].type) == 0) { 00774 rtp->current_RTP_PT[pt] = mimeTypes[i].payloadType; 00775 return; 00776 } 00777 } 00778 }
| void ast_rtp_setnat | ( | struct ast_rtp * | rtp, | |
| int | nat | |||
| ) |
Definition at line 175 of file rtp.c.
References ast_rtp::nat.
Referenced by check_user_full(), create_addr(), create_addr_from_peer(), oh323_request(), oh323_rtp_read(), sip_alloc(), and start_rtp().
| int ast_rtp_settos | ( | struct ast_rtp * | rtp, | |
| int | tos | |||
| ) |
Definition at line 1037 of file rtp.c.
References ast_log(), LOG_WARNING, and ast_rtp::s.
Referenced by oh323_alloc(), and sip_alloc().
01038 { 01039 int res; 01040 01041 if ((res = setsockopt(rtp->s, IPPROTO_IP, IP_TOS, &tos, sizeof(tos)))) 01042 ast_log(LOG_WARNING, "Unable to set TOS to %d\n", tos); 01043 return res; 01044 }
| void ast_rtp_stop | ( | struct ast_rtp * | rtp | ) |
Definition at line 1075 of file rtp.c.
References ast_rtp::rtcp, ast_rtcp::them, and ast_rtp::them.
Referenced by handle_request_bye(), handle_request_cancel(), handle_response(), and process_sdp().
01076 { 01077 memset(&rtp->them.sin_addr, 0, sizeof(rtp->them.sin_addr)); 01078 memset(&rtp->them.sin_port, 0, sizeof(rtp->them.sin_port)); 01079 if (rtp->rtcp) { 01080 memset(&rtp->rtcp->them.sin_addr, 0, sizeof(rtp->them.sin_addr)); 01081 memset(&rtp->rtcp->them.sin_port, 0, sizeof(rtp->them.sin_port)); 01082 } 01083 }
Definition at line 1337 of file rtp.c.
References AST_FORMAT_ADPCM, AST_FORMAT_ALAW, AST_FORMAT_G723_1, AST_FORMAT_G726, AST_FORMAT_G729A, AST_FORMAT_GSM, AST_FORMAT_H261, AST_FORMAT_H263, AST_FORMAT_H263_PLUS, AST_FORMAT_ILBC, AST_FORMAT_LPC10, AST_FORMAT_SLINEAR, AST_FORMAT_SPEEX, AST_FORMAT_ULAW, AST_FRAME_VIDEO, AST_FRAME_VOICE, ast_frdup(), ast_frfree(), ast_getformatname(), ast_log(), ast_rtp_lookup_code(), ast_rtp_raw_write(), ast_smoother_feed, ast_smoother_feed_be, AST_SMOOTHER_FLAG_G729, ast_smoother_free(), ast_smoother_new(), ast_smoother_read(), ast_smoother_set_flags(), ast_frame::datalen, ast_frame::frametype, ast_rtp::lasttxformat, LOG_DEBUG, LOG_WARNING, ast_frame::offset, option_debug, ast_rtp::smoother, ast_frame::subclass, and ast_rtp::them.
Referenced by mgcp_write(), oh323_write(), sip_write(), and skinny_write().
01338 { 01339 struct ast_frame *f; 01340 int codec; 01341 int hdrlen = 12; 01342 int subclass; 01343 01344 01345 /* If we have no peer, return immediately */ 01346 if (!rtp->them.sin_addr.s_addr) 01347 return 0; 01348 01349 /* If there is no data length, return immediately */ 01350 if (!_f->datalen) 01351 return 0; 01352 01353 /* Make sure we have enough space for RTP header */ 01354 if ((_f->frametype != AST_FRAME_VOICE) && (_f->frametype != AST_FRAME_VIDEO)) { 01355 ast_log(LOG_WARNING, "RTP can only send voice\n"); 01356 return -1; 01357 } 01358 01359 subclass = _f->subclass; 01360 if (_f->frametype == AST_FRAME_VIDEO) 01361 subclass &= ~0x1; 01362 01363 codec = ast_rtp_lookup_code(rtp, 1, subclass); 01364 if (codec < 0) { 01365 ast_log(LOG_WARNING, "Don't know how to send format %s packets with RTP\n", ast_getformatname(_f->subclass)); 01366 return -1; 01367 } 01368 01369 if (rtp->lasttxformat != subclass) { 01370 /* New format, reset the smoother */ 01371 if (option_debug) 01372 ast_log(LOG_DEBUG, "Ooh, format changed from %s to %s\n", ast_getformatname(rtp->lasttxformat), ast_getformatname(subclass)); 01373 rtp->lasttxformat = subclass; 01374 if (rtp->smoother) 01375 ast_smoother_free(rtp->smoother); 01376 rtp->smoother = NULL; 01377 } 01378 01379 01380 switch(subclass) { 01381 case AST_FORMAT_SLINEAR: 01382 if (!rtp->smoother) { 01383 rtp->smoother = ast_smoother_new(320); 01384 } 01385 if (!rtp->smoother) { 01386 ast_log(LOG_WARNING, "Unable to create smoother :(\n"); 01387 return -1; 01388 } 01389 ast_smoother_feed_be(rtp->smoother, _f); 01390 01391 while((f = ast_smoother_read(rtp->smoother))) 01392 ast_rtp_raw_write(rtp, f, codec); 01393 break; 01394 case AST_FORMAT_ULAW: 01395 case AST_FORMAT_ALAW: 01396 if (!rtp->smoother) { 01397 rtp->smoother = ast_smoother_new(160); 01398 } 01399 if (!rtp->smoother) { 01400 ast_log(LOG_WARNING, "Unable to create smoother :(\n"); 01401 return -1; 01402 } 01403 ast_smoother_feed(rtp->smoother, _f); 01404 01405 while((f = ast_smoother_read(rtp->smoother))) 01406 ast_rtp_raw_write(rtp, f, codec); 01407 break; 01408 case AST_FORMAT_ADPCM: 01409 case AST_FORMAT_G726: 01410 if (!rtp->smoother) { 01411 rtp->smoother = ast_smoother_new(80); 01412 } 01413 if (!rtp->smoother) { 01414 ast_log(LOG_WARNING, "Unable to create smoother :(\n"); 01415 return -1; 01416 } 01417 ast_smoother_feed(rtp->smoother, _f); 01418 01419 while((f = ast_smoother_read(rtp->smoother))) 01420 ast_rtp_raw_write(rtp, f, codec); 01421 break; 01422 case AST_FORMAT_G729A: 01423 if (!rtp->smoother) { 01424 rtp->smoother = ast_smoother_new(20); 01425 if (rtp->smoother) 01426 ast_smoother_set_flags(rtp->smoother, AST_SMOOTHER_FLAG_G729); 01427 } 01428 if (!rtp->smoother) { 01429 ast_log(LOG_WARNING, "Unable to create g729 smoother :(\n"); 01430 return -1; 01431 } 01432 ast_smoother_feed(rtp->smoother, _f); 01433 01434 while((f = ast_smoother_read(rtp->smoother))) 01435 ast_rtp_raw_write(rtp, f, codec); 01436 break; 01437 case AST_FORMAT_GSM: 01438 if (!rtp->smoother) { 01439 rtp->smoother = ast_smoother_new(33); 01440 } 01441 if (!rtp->smoother) { 01442 ast_log(LOG_WARNING, "Unable to create GSM smoother :(\n"); 01443 return -1; 01444 } 01445 ast_smoother_feed(rtp->smoother, _f); 01446 while((f = ast_smoother_read(rtp->smoother))) 01447 ast_rtp_raw_write(rtp, f, codec); 01448 break; 01449 case AST_FORMAT_ILBC: 01450 if (!rtp->smoother) { 01451 rtp->smoother = ast_smoother_new(50); 01452 } 01453 if (!rtp->smoother) { 01454 ast_log(LOG_WARNING, "Unable to create ILBC smoother :(\n"); 01455 return -1; 01456 } 01457 ast_smoother_feed(rtp->smoother, _f); 01458 while((f = ast_smoother_read(rtp->smoother))) 01459 ast_rtp_raw_write(rtp, f, codec); 01460 break; 01461 default: 01462 ast_log(LOG_WARNING, "Not sure about sending format %s packets\n", ast_getformatname(subclass)); 01463 /* fall through to... */ 01464 case AST_FORMAT_H261: 01465 case AST_FORMAT_H263: 01466 case AST_FORMAT_H263_PLUS: 01467 case AST_FORMAT_G723_1: 01468 case AST_FORMAT_LPC10: 01469 case AST_FORMAT_SPEEX: 01470 /* Don't buffer outgoing frames; send them one-per-packet: */ 01471 if (_f->offset < hdrlen) { 01472 f = ast_frdup(_f); 01473 } else { 01474 f = _f; 01475 } 01476 ast_rtp_raw_write(rtp, f, codec); 01477 if (f != _f) 01478 ast_frfree(f); 01479 } 01480 01481 return 0; 01482 }
1.5.6