#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 49 of file rtp.h. Referenced by ast_rtp_set_callback(). |
|
|
Definition at line 119 of file rtp.c. References ast_rtp::rtcp, and ast_rtcp::s.
|
|
|
Definition at line 326 of file rtp.c. References ast_inet_ntoa(), ast_log(), CRASH, LOG_DEBUG, LOG_NOTICE, and LOG_WARNING.
00327 {
00328 static struct ast_frame null_frame = { AST_FRAME_NULL, };
00329 int len;
00330 int hdrlen = 8;
00331 int res;
00332 struct sockaddr_in sin;
00333 unsigned int rtcpdata[1024];
00334 char iabuf[INET_ADDRSTRLEN];
00335
00336 if (!rtp->rtcp)
00337 return &null_frame;
00338
00339 len = sizeof(sin);
00340
00341 res = recvfrom(rtp->rtcp->s, rtcpdata, sizeof(rtcpdata),
00342 0, (struct sockaddr *)&sin, &len);
00343
00344 if (res < 0) {
00345 if (errno == EAGAIN)
00346 ast_log(LOG_NOTICE, "RTP: Received packet with bad UDP checksum\n");
00347 else
00348 ast_log(LOG_WARNING, "RTP Read error: %s\n", strerror(errno));
00349 if (errno == EBADF)
00350 CRASH;
00351 return &null_frame;
00352 }
00353
00354 if (res < hdrlen) {
00355 ast_log(LOG_WARNING, "RTP Read too short\n");
00356 return &null_frame;
00357 }
00358
00359 if (rtp->nat) {
00360 /* Send to whoever sent to us */
00361 if ((rtp->rtcp->them.sin_addr.s_addr != sin.sin_addr.s_addr) ||
00362 (rtp->rtcp->them.sin_port != sin.sin_port)) {
00363 memcpy(&rtp->them, &sin, sizeof(rtp->them));
00364 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));
00365 }
00366 }
00367 if (option_debug)
00368 ast_log(LOG_DEBUG, "Got RTCP report of %d bytes\n", res);
00369 return &null_frame;
00370 }
|
|
||||||||||||||||||||||||
|
Definition at line 1318 of file rtp.c. References ast_channel::_softhangup, AST_BRIDGE_DTMF_CHANNEL_0, AST_BRIDGE_DTMF_CHANNEL_1, ast_check_hangup(), ast_frfree(), 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.
01319 {
01320 struct ast_frame *f;
01321 struct ast_channel *who, *cs[3];
01322 struct ast_rtp *p0, *p1;
01323 struct ast_rtp *vp0, *vp1;
01324 struct ast_rtp_protocol *pr0, *pr1;
01325 struct sockaddr_in ac0, ac1;
01326 struct sockaddr_in vac0, vac1;
01327 struct sockaddr_in t0, t1;
01328 struct sockaddr_in vt0, vt1;
01329 char iabuf[INET_ADDRSTRLEN];
01330
01331 void *pvt0, *pvt1;
01332 int to;
01333 int codec0,codec1, oldcodec0, oldcodec1;
01334
01335 memset(&vt0, 0, sizeof(vt0));
01336 memset(&vt1, 0, sizeof(vt1));
01337 memset(&vac0, 0, sizeof(vac0));
01338 memset(&vac1, 0, sizeof(vac1));
01339
01340 /* if need DTMF, cant native bridge */
01341 if (flags & (AST_BRIDGE_DTMF_CHANNEL_0 | AST_BRIDGE_DTMF_CHANNEL_1))
01342 return -2;
01343 ast_mutex_lock(&c0->lock);
01344 while(ast_mutex_trylock(&c1->lock)) {
01345 ast_mutex_unlock(&c0->lock);
01346 usleep(1);
01347 ast_mutex_lock(&c0->lock);
01348 }
01349 pr0 = get_proto(c0);
01350 pr1 = get_proto(c1);
01351 if (!pr0) {
01352 ast_log(LOG_WARNING, "Can't find native functions for channel '%s'\n", c0->name);
01353 ast_mutex_unlock(&c0->lock);
01354 ast_mutex_unlock(&c1->lock);
01355 return -1;
01356 }
01357 if (!pr1) {
01358 ast_log(LOG_WARNING, "Can't find native functions for channel '%s'\n", c1->name);
01359 ast_mutex_unlock(&c0->lock);
01360 ast_mutex_unlock(&c1->lock);
01361 return -1;
01362 }
01363 pvt0 = c0->pvt->pvt;
01364 pvt1 = c1->pvt->pvt;
01365 p0 = pr0->get_rtp_info(c0);
01366 if (pr0->get_vrtp_info)
01367 vp0 = pr0->get_vrtp_info(c0);
01368 else
01369 vp0 = NULL;
01370 p1 = pr1->get_rtp_info(c1);
01371 if (pr1->get_vrtp_info)
01372 vp1 = pr1->get_vrtp_info(c1);
01373 else
01374 vp1 = NULL;
01375 if (!p0 || !p1) {
01376 /* Somebody doesn't want to play... */
01377 ast_mutex_unlock(&c0->lock);
01378 ast_mutex_unlock(&c1->lock);
01379 return -2;
01380 }
01381 if (pr0->get_codec)
01382 codec0 = pr0->get_codec(c0);
01383 else
01384 codec0 = 0;
01385 if (pr1->get_codec)
01386 codec1 = pr1->get_codec(c1);
01387 else
01388 codec1 = 0;
01389 if (pr0->get_codec && pr1->get_codec) {
01390 /* Hey, we can't do reinvite if both parties speak diffrent codecs */
01391 if (!(codec0 & codec1)) {
01392 ast_log(LOG_WARNING, "codec0 = %d is not codec1 = %d, cannot native bridge.\n",codec0,codec1);
01393 ast_mutex_unlock(&c0->lock);
01394 ast_mutex_unlock(&c1->lock);
01395 return -2;
01396 }
01397 }
01398 if (pr0->set_rtp_peer(c0, p1, vp1, codec1))
01399 ast_log(LOG_WARNING, "Channel '%s' failed to talk to '%s'\n", c0->name, c1->name);
01400 else {
01401 /* Store RTP peer */
01402 ast_rtp_get_peer(p1, &ac1);
01403 if (vp1)
01404 ast_rtp_get_peer(vp1, &vac1);
01405 }
01406 if (pr1->set_rtp_peer(c1, p0, vp0, codec0))
01407 ast_log(LOG_WARNING, "Channel '%s' failed to talk back to '%s'\n", c1->name, c0->name);
01408 else {
01409 /* Store RTP peer */
01410 ast_rtp_get_peer(p0, &ac0);
01411 if (vp0)
01412 ast_rtp_get_peer(vp0, &vac0);
01413 }
01414 ast_mutex_unlock(&c0->lock);
01415 ast_mutex_unlock(&c1->lock);
01416 cs[0] = c0;
01417 cs[1] = c1;
01418 cs[2] = NULL;
01419 oldcodec0 = codec0;
01420 oldcodec1 = codec1;
01421 for (;;) {
01422 if ((c0->pvt->pvt != pvt0) ||
01423 (c1->pvt->pvt != pvt1) ||
01424 (c0->masq || c0->masqr || c1->masq || c1->masqr)) {
01425 ast_log(LOG_DEBUG, "Oooh, something is weird, backing out\n");
01426 if (c0->pvt->pvt == pvt0) {
01427 if (pr0->set_rtp_peer(c0, NULL, NULL, 0))
01428 ast_log(LOG_WARNING, "Channel '%s' failed to revert\n", c0->name);
01429 }
01430 if (c1->pvt->pvt == pvt1) {
01431 if (pr1->set_rtp_peer(c1, NULL, NULL, 0))
01432 ast_log(LOG_WARNING, "Channel '%s' failed to revert back\n", c1->name);
01433 }
01434 /* Tell it to try again later */
01435 return -3;
01436 }
01437 to = -1;
01438 ast_rtp_get_peer(p1, &t1);
01439 ast_rtp_get_peer(p0, &t0);
01440 if (pr0->get_codec)
01441 codec0 = pr0->get_codec(c0);
01442 if (pr1->get_codec)
01443 codec1 = pr1->get_codec(c1);
01444 if (vp1)
01445 ast_rtp_get_peer(vp1, &vt1);
01446 if (vp0)
01447 ast_rtp_get_peer(vp0, &vt0);
01448 if (inaddrcmp(&t1, &ac1) || (vp1 && inaddrcmp(&vt1, &vac1)) || (codec1 != oldcodec1)) {
01449 ast_log(LOG_DEBUG, "Oooh, '%s' changed end address to %s:%d (format %d)\n",
01450 c1->name, ast_inet_ntoa(iabuf, sizeof(iabuf), t1.sin_addr), ntohs(t1.sin_port), codec1);
01451 ast_log(LOG_DEBUG, "Oooh, '%s' changed end vaddress to %s:%d (format %d)\n",
01452 c1->name, ast_inet_ntoa(iabuf, sizeof(iabuf), vt1.sin_addr), ntohs(vt1.sin_port), codec1);
01453 ast_log(LOG_DEBUG, "Oooh, '%s' was %s:%d/(format %d)\n",
01454 c1->name, ast_inet_ntoa(iabuf, sizeof(iabuf), ac1.sin_addr), ntohs(ac1.sin_port), oldcodec1);
01455 ast_log(LOG_DEBUG, "Oooh, '%s' wasv %s:%d/(format %d)\n",
01456 c1->name, ast_inet_ntoa(iabuf, sizeof(iabuf), vac1.sin_addr), ntohs(vac1.sin_port), oldcodec1);
01457 if (pr0->set_rtp_peer(c0, t1.sin_addr.s_addr ? p1 : NULL, vt1.sin_addr.s_addr ? vp1 : NULL, codec1))
01458 ast_log(LOG_WARNING, "Channel '%s' failed to update to '%s'\n", c0->name, c1->name);
01459 memcpy(&ac1, &t1, sizeof(ac1));
01460 memcpy(&vac1, &vt1, sizeof(vac1));
01461 oldcodec1 = codec1;
01462 }
01463 if (inaddrcmp(&t0, &ac0) || (vp0 && inaddrcmp(&vt0, &vac0))) {
01464 ast_log(LOG_DEBUG, "Oooh, '%s' changed end address to %s:%d (format %d)\n",
01465 c0->name, ast_inet_ntoa(iabuf, sizeof(iabuf), t0.sin_addr), ntohs(t0.sin_port), codec0);
01466 ast_log(LOG_DEBUG, "Oooh, '%s' was %s:%d/(format %d)\n",
01467 c0->name, ast_inet_ntoa(iabuf, sizeof(iabuf), ac0.sin_addr), ntohs(ac0.sin_port), oldcodec0);
01468 if (pr1->set_rtp_peer(c1, t0.sin_addr.s_addr ? p0 : NULL, vt0.sin_addr.s_addr ? vp0 : NULL, codec0))
01469 ast_log(LOG_WARNING, "Channel '%s' failed to update to '%s'\n", c1->name, c0->name);
01470 memcpy(&ac0, &t0, sizeof(ac0));
01471 memcpy(&vac0, &vt0, sizeof(vac0));
01472 oldcodec0 = codec0;
01473 }
01474 who = ast_waitfor_n(cs, 2, &to);
01475 if (!who) {
01476 ast_log(LOG_DEBUG, "Ooh, empty read...\n");
01477 /* check for hagnup / whentohangup */
01478 if (ast_check_hangup(c0) || ast_check_hangup(c1))
01479 break;
01480 continue;
01481 }
01482 f = ast_read(who);
01483 if (!f || ((f->frametype == AST_FRAME_DTMF) &&
01484 (((who == c0) && (flags & AST_BRIDGE_DTMF_CHANNEL_0)) ||
01485 ((who == c1) && (flags & AST_BRIDGE_DTMF_CHANNEL_1))))) {
01486 *fo = f;
01487 *rc = who;
01488 ast_log(LOG_DEBUG, "Oooh, got a %s\n", f ? "digit" : "hangup");
01489 if ((c0->pvt->pvt == pvt0) && (!c0->_softhangup)) {
01490 if (pr0->set_rtp_peer(c0, NULL, NULL, 0))
01491 ast_log(LOG_WARNING, "Channel '%s' failed to revert\n", c0->name);
01492 }
01493 if ((c1->pvt->pvt == pvt1) && (!c1->_softhangup)) {
01494 if (pr1->set_rtp_peer(c1, NULL, NULL, 0))
01495 ast_log(LOG_WARNING, "Channel '%s' failed to revert back\n", c1->name);
01496 }
01497 /* That's all we needed */
01498 return 0;
01499 } else {
01500 if ((f->frametype == AST_FRAME_DTMF) ||
01501 (f->frametype == AST_FRAME_VOICE) ||
01502 (f->frametype == AST_FRAME_VIDEO)) {
01503 /* Forward voice or DTMF frames if they happen upon us */
01504 if (who == c0) {
01505 ast_write(c1, f);
01506 } else if (who == c1) {
01507 ast_write(c0, f);
01508 }
01509 }
01510 ast_frfree(f);
01511 }
01512 /* Swap priority not that it's a big deal at this point */
01513 cs[2] = cs[0];
01514 cs[0] = cs[1];
01515 cs[1] = cs[2];
01516
01517 }
01518 return -1;
01519 }
|
|
|
Definition at line 935 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.
|
|
|
Definition at line 114 of file rtp.c. References ast_rtp::s.
00115 {
00116 return rtp->s;
00117 }
|
|
||||||||||||||||
|
Definition at line 693 of file rtp.c. References rtpPayloadType::code, ast_rtp::current_RTP_PT, and rtpPayloadType::isAstFormat.
00694 {
00695 int pt;
00696
00697 *astFormats = *nonAstFormats = 0;
00698 for (pt = 0; pt < MAX_RTP_PT; ++pt) {
00699 if (rtp->current_RTP_PT[pt].isAstFormat) {
00700 *astFormats |= rtp->current_RTP_PT[pt].code;
00701 } else {
00702 *nonAstFormats |= rtp->current_RTP_PT[pt].code;
00703 }
00704 }
00705 }
|
|
||||||||||||
|
Definition at line 913 of file rtp.c. References ast_rtp::them. Referenced by ast_rtp_bridge().
|
|
||||||||||||
|
Definition at line 920 of file rtp.c. References ast_rtp::us.
|
|
|
Definition at line 1568 of file rtp.c. References ast_rtp_reload(). Referenced by main().
01569 {
01570 ast_rtp_reload();
01571 }
|
|
||||||||||||||||
|
Definition at line 732 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().
00732 {
00733 int pt;
00734
00735
00736 if (isAstFormat == rtp->rtp_lookup_code_cache_isAstFormat &&
00737 code == rtp->rtp_lookup_code_cache_code) {
00738 /* Use our cached mapping, to avoid the overhead of the loop below */
00739 return rtp->rtp_lookup_code_cache_result;
00740 }
00741
00742 /* Check the dynamic list first */
00743 for (pt = 0; pt < MAX_RTP_PT; ++pt) {
00744 if (rtp->current_RTP_PT[pt].code == code &&
00745 rtp->current_RTP_PT[pt].isAstFormat == isAstFormat) {
00746 rtp->rtp_lookup_code_cache_isAstFormat = isAstFormat;
00747 rtp->rtp_lookup_code_cache_code = code;
00748 rtp->rtp_lookup_code_cache_result = pt;
00749 return pt;
00750 }
00751 }
00752
00753 /* Then the static list */
00754 for (pt = 0; pt < MAX_RTP_PT; ++pt) {
00755 if (static_RTP_PT[pt].code == code &&
00756 static_RTP_PT[pt].isAstFormat == isAstFormat) {
00757 rtp->rtp_lookup_code_cache_isAstFormat = isAstFormat;
00758 rtp->rtp_lookup_code_cache_code = code;
00759 rtp->rtp_lookup_code_cache_result = pt;
00760 return pt;
00761 }
00762 }
00763 return -1;
00764 }
|
|
||||||||||||
|
Definition at line 766 of file rtp.c.
00766 {
00767 int i;
00768
00769 for (i = 0; i < sizeof mimeTypes/sizeof mimeTypes[0]; ++i) {
00770 if (mimeTypes[i].payloadType.code == code &&
00771 mimeTypes[i].payloadType.isAstFormat == isAstFormat) {
00772 return mimeTypes[i].subtype;
00773 }
00774 }
00775 return "";
00776 }
|
|
||||||||||||
|
Definition at line 714 of file rtp.c. References rtpPayloadType::code, and rtpPayloadType::isAstFormat. Referenced by ast_rtp_read().
00715 {
00716 struct rtpPayloadType result;
00717
00718 result.isAstFormat = result.code = 0;
00719 if (pt < 0 || pt > MAX_RTP_PT) {
00720 return result; /* bogus payload type */
00721 }
00722 /* Start with the negotiated codecs */
00723 if (!rtp->rtp_offered_from_local)
00724 result = rtp->current_RTP_PT[pt];
00725 /* If it doesn't exist, check our static RTP type list, just in case */
00726 if (!result.code)
00727 result = static_RTP_PT[pt];
00728 return result;
00729 }
|
|
||||||||||||||||||||
|
Definition at line 888 of file rtp.c. References ast_rtp_new_with_bindaddr().
00889 {
00890 struct in_addr ia;
00891 memset(&ia, 0, sizeof(ia));
00892 return ast_rtp_new_with_bindaddr(sched, io, rtcpenable, callbackmode, ia);
00893 }
|
|
||||||||||||||||||||||||
|
Definition at line 812 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().
00813 {
00814 struct ast_rtp *rtp;
00815 int x;
00816 int first;
00817 int startplace;
00818 rtp = malloc(sizeof(struct ast_rtp));
00819 if (!rtp)
00820 return NULL;
00821 memset(rtp, 0, sizeof(struct ast_rtp));
00822 rtp->them.sin_family = AF_INET;
00823 rtp->us.sin_family = AF_INET;
00824 rtp->s = rtp_socket();
00825 rtp->ssrc = rand();
00826 rtp->seqno = rand() & 0xffff;
00827 if (rtp->s < 0) {
00828 free(rtp);
00829 ast_log(LOG_WARNING, "Unable to allocate socket: %s\n", strerror(errno));
00830 return NULL;
00831 }
00832 if (sched && rtcpenable) {
00833 rtp->sched = sched;
00834 rtp->rtcp = ast_rtcp_new();
00835 }
00836 /* Find us a place */
00837 x = (rand() % (rtpend-rtpstart)) + rtpstart;
00838 x = x & ~1;
00839 startplace = x;
00840 for (;;) {
00841 /* Must be an even port number by RTP spec */
00842 rtp->us.sin_port = htons(x);
00843 rtp->us.sin_addr = addr;
00844 if (rtp->rtcp)
00845 rtp->rtcp->us.sin_port = htons(x + 1);
00846 if (!(first = bind(rtp->s, (struct sockaddr *)&rtp->us, sizeof(rtp->us))) &&
00847 (!rtp->rtcp || !bind(rtp->rtcp->s, (struct sockaddr *)&rtp->rtcp->us, sizeof(rtp->rtcp->us))))
00848 break;
00849 if (!first) {
00850 /* Primary bind succeeded! Gotta recreate it */
00851 close(rtp->s);
00852 rtp->s = rtp_socket();
00853 }
00854 if (errno != EADDRINUSE) {
00855 ast_log(LOG_WARNING, "Unexpected bind error: %s\n", strerror(errno));
00856 close(rtp->s);
00857 if (rtp->rtcp) {
00858 close(rtp->rtcp->s);
00859 free(rtp->rtcp);
00860 }
00861 free(rtp);
00862 return NULL;
00863 }
00864 x += 2;
00865 if (x > rtpend)
00866 x = (rtpstart + 1) & ~1;
00867 if (x == startplace) {
00868 ast_log(LOG_WARNING, "No RTP ports remaining\n");
00869 close(rtp->s);
00870 if (rtp->rtcp) {
00871 close(rtp->rtcp->s);
00872 free(rtp->rtcp);
00873 }
00874 free(rtp);
00875 return NULL;
00876 }
00877 }
00878 if (io && sched && callbackmode) {
00879 /* Operate this one in a callback mode */
00880 rtp->sched = sched;
00881 rtp->io = io;
00882 rtp->ioid = ast_io_add(rtp->io, rtp->s, rtpread, AST_IO_IN, rtp);
00883 }
00884 ast_rtp_pt_default(rtp);
00885 return rtp;
00886 }
|
|
||||||||||||
|
Definition at line 707 of file rtp.c. References ast_log(), LOG_WARNING, and ast_rtp::rtp_offered_from_local.
00707 {
00708 if (rtp)
00709 rtp->rtp_offered_from_local = local;
00710 else
00711 ast_log(LOG_WARNING, "rtp structure is null\n");
00712 }
|
|
|
Definition at line 1289 of file rtp.c. References ast_log(), LOG_WARNING, ast_rtp_protocol::next, and ast_rtp_protocol::type.
01290 {
01291 struct ast_rtp_protocol *cur;
01292 cur = protos;
01293 while(cur) {
01294 if (cur->type == proto->type) {
01295 ast_log(LOG_WARNING, "Tried to register same protocol '%s' twice\n", cur->type);
01296 return -1;
01297 }
01298 cur = cur->next;
01299 }
01300 proto->next = protos;
01301 protos = proto;
01302 return 0;
01303 }
|
|
|
Definition at line 1271 of file rtp.c. References ast_rtp_protocol::next.
01272 {
01273 struct ast_rtp_protocol *cur, *prev;
01274 cur = protos;
01275 prev = NULL;
01276 while(cur) {
01277 if (cur == proto) {
01278 if (prev)
01279 prev->next = proto->next;
01280 else
01281 protos = proto->next;
01282 return;
01283 }
01284 prev = cur;
01285 cur = cur->next;
01286 }
01287 }
|
|
|
Definition at line 635 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.
00636 {
00637 int i;
00638
00639 for (i = 0; i < MAX_RTP_PT; ++i) {
00640 rtp->current_RTP_PT[i].isAstFormat = 0;
00641 rtp->current_RTP_PT[i].code = 0;
00642 }
00643
00644 rtp->rtp_lookup_code_cache_isAstFormat = 0;
00645 rtp->rtp_lookup_code_cache_code = 0;
00646 rtp->rtp_lookup_code_cache_result = 0;
00647 }
|
|
|
Definition at line 649 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().
00650 {
00651 int i;
00652 /* Initialize to default payload types */
00653 for (i = 0; i < MAX_RTP_PT; ++i) {
00654 rtp->current_RTP_PT[i].isAstFormat = static_RTP_PT[i].isAstFormat;
00655 rtp->current_RTP_PT[i].code = static_RTP_PT[i].code;
00656 }
00657
00658 rtp->rtp_lookup_code_cache_isAstFormat = 0;
00659 rtp->rtp_lookup_code_cache_code = 0;
00660 rtp->rtp_lookup_code_cache_result = 0;
00661 }
|
|
|
Definition at line 394 of file rtp.c. References 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_frame::frametype, rtpPayloadType::isAstFormat, LOG_DEBUG, LOG_NOTICE, LOG_WARNING, ast_frame::mallocd, ast_frame::offset, ast_frame::samples, ast_frame::src, and ast_frame::subclass.
00395 {
00396 int res;
00397 struct sockaddr_in sin;
00398 int len;
00399 unsigned int seqno;
00400 int payloadtype;
00401 int hdrlen = 12;
00402 int mark;
00403 int ext;
00404 char iabuf[INET_ADDRSTRLEN];
00405 unsigned int timestamp;
00406 unsigned int *rtpheader;
00407 static struct ast_frame *f, null_frame = { AST_FRAME_NULL, };
00408 struct rtpPayloadType rtpPT;
00409
00410 len = sizeof(sin);
00411
00412 /* Cache where the header will go */
00413 res = recvfrom(rtp->s, rtp->rawdata + AST_FRIENDLY_OFFSET, sizeof(rtp->rawdata) - AST_FRIENDLY_OFFSET,
00414 0, (struct sockaddr *)&sin, &len);
00415
00416
00417 rtpheader = (unsigned int *)(rtp->rawdata + AST_FRIENDLY_OFFSET);
00418 if (res < 0) {
00419 if (errno == EAGAIN)
00420 ast_log(LOG_NOTICE, "RTP: Received packet with bad UDP checksum\n");
00421 else
00422 ast_log(LOG_WARNING, "RTP Read error: %s\n", strerror(errno));
00423 if (errno == EBADF)
00424 CRASH;
00425 return &null_frame;
00426 }
00427 if (res < hdrlen) {
00428 ast_log(LOG_WARNING, "RTP Read too short\n");
00429 return &null_frame;
00430 }
00431
00432 /* Ignore if the other side hasn't been given an address
00433 yet. */
00434 if (!rtp->them.sin_addr.s_addr || !rtp->them.sin_port)
00435 return &null_frame;
00436
00437 if (rtp->nat) {
00438 /* Send to whoever sent to us */
00439 if ((rtp->them.sin_addr.s_addr != sin.sin_addr.s_addr) ||
00440 (rtp->them.sin_port != sin.sin_port)) {
00441 memcpy(&rtp->them, &sin, sizeof(rtp->them));
00442 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));
00443 }
00444 }
00445
00446 /* Get fields */
00447 seqno = ntohl(rtpheader[0]);
00448 payloadtype = (seqno & 0x7f0000) >> 16;
00449 mark = seqno & (1 << 23);
00450 ext = seqno & (1 << 28);
00451 seqno &= 0xffff;
00452 timestamp = ntohl(rtpheader[1]);
00453 if (ext) {
00454 /* RTP Extension present */
00455 hdrlen += 4;
00456 hdrlen += (ntohl(rtpheader[3]) & 0xffff) << 2;
00457 }
00458
00459 if (res < hdrlen) {
00460 ast_log(LOG_WARNING, "RTP Read too short (%d, expecting %d)\n", res, hdrlen);
00461 return &null_frame;
00462 }
00463
00464 #if 0
00465 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);
00466 #endif
00467 rtpPT = ast_rtp_lookup_pt(rtp, payloadtype);
00468 if (!rtpPT.isAstFormat) {
00469 /* This is special in-band data that's not one of our codecs */
00470 if (rtpPT.code == AST_RTP_DTMF) {
00471 /* It's special -- rfc2833 process it */
00472 if (rtp->lasteventseqn <= seqno) {
00473 f = process_rfc2833(rtp, rtp->rawdata + AST_FRIENDLY_OFFSET + hdrlen, res - hdrlen);
00474 rtp->lasteventseqn = seqno;
00475 }
00476 if (f) return f; else return &null_frame;
00477 } else if (rtpPT.code == AST_RTP_CISCO_DTMF) {
00478 /* It's really special -- process it the Cisco way */
00479 if (rtp->lasteventseqn <= seqno) {
00480 f = process_cisco_dtmf(rtp, rtp->rawdata + AST_FRIENDLY_OFFSET + hdrlen, res - hdrlen);
00481 rtp->lasteventseqn = seqno;
00482 }
00483 if (f) return f; else return &null_frame;
00484 } else if (rtpPT.code == AST_RTP_CN) {
00485 /* Comfort Noise */
00486 f = process_rfc3389(rtp, rtp->rawdata + AST_FRIENDLY_OFFSET + hdrlen, res - hdrlen);
00487 if (f) return f; else return &null_frame;
00488 } else {
00489 ast_log(LOG_NOTICE, "Unknown RTP codec %d received\n", payloadtype);
00490 return &null_frame;
00491 }
00492 }
00493 rtp->f.subclass = rtpPT.code;
00494 if (rtp->f.subclass < AST_FORMAT_MAX_AUDIO)
00495 rtp->f.frametype = AST_FRAME_VOICE;
00496 else
00497 rtp->f.frametype = AST_FRAME_VIDEO;
00498 rtp->lastrxformat = rtp->f.subclass;
00499
00500 if (!rtp->lastrxts)
00501 rtp->lastrxts = timestamp;
00502
00503 if (rtp->dtmfcount) {
00504 #if 0
00505 printf("dtmfcount was %d\n", rtp->dtmfcount);
00506 #endif
00507 rtp->dtmfcount -= (timestamp - rtp->lastrxts);
00508 if (rtp->dtmfcount < 0)
00509 rtp->dtmfcount = 0;
00510 #if 0
00511 if (dtmftimeout != rtp->dtmfcount)
00512 printf("dtmfcount is %d\n", rtp->dtmfcount);
00513 #endif
00514 }
00515 rtp->lastrxts = timestamp;
00516
00517 /* Send any pending DTMF */
00518 if (rtp->resp && !rtp->dtmfcount) {
00519 ast_log(LOG_DEBUG, "Sending pending DTMF\n");
00520 return send_dtmf(rtp);
00521 }
00522 rtp->f.mallocd = 0;
00523 rtp->f.datalen = res - hdrlen;
00524 rtp->f.data = rtp->rawdata + hdrlen + AST_FRIENDLY_OFFSET;
00525 rtp->f.offset = hdrlen + AST_FRIENDLY_OFFSET;
00526 if (rtp->f.subclass < AST_FORMAT_MAX_AUDIO) {
00527 switch(rtp->f.subclass) {
00528 case AST_FORMAT_ULAW:
00529 case AST_FORMAT_ALAW:
00530 rtp->f.samples = rtp->f.datalen;
00531 break;
00532 case AST_FORMAT_SLINEAR:
00533 rtp->f.samples = rtp->f.datalen / 2;
00534 break;
00535 case AST_FORMAT_GSM:
00536 rtp->f.samples = 160 * (rtp->f.datalen / 33);
00537 break;
00538 case AST_FORMAT_ILBC:
00539 rtp->f.samples = 240 * (rtp->f.datalen / 50);
00540 break;
00541 case AST_FORMAT_ADPCM:
00542 case AST_FORMAT_G726:
00543 rtp->f.samples = rtp->f.datalen * 2;
00544 break;
00545 case AST_FORMAT_G729A:
00546 rtp->f.samples = rtp->f.datalen * 8;
00547 break;
00548 case AST_FORMAT_G723_1:
00549 rtp->f.samples = g723_samples(rtp->f.data, rtp->f.datalen);
00550 break;
00551 case AST_FORMAT_SPEEX:
00552 /* assumes that the RTP packet contained one Speex frame */
00553 rtp->f.samples = 160;
00554 break;
00555 case AST_FORMAT_LPC10:
00556 rtp->f.samples = 22 * 8;
00557 rtp->f.samples += (((char *)(rtp->f.data))[7] & 0x1) * 8;
00558 break;
00559 default:
00560 ast_log(LOG_NOTICE, "Unable to calculate samples for format %s\n", ast_getformatname(rtp->f.subclass));
00561 break;
00562 }
00563 calc_rxstamp(&rtp->f.delivery, rtp, timestamp, mark);
00564 } else {
00565 /* Video -- samples is # of samples vs. 90000 */
00566 if (!rtp->lastividtimestamp)
00567 rtp->lastividtimestamp = timestamp;
00568 rtp->f.samples = timestamp - rtp->lastividtimestamp;
00569 rtp->lastividtimestamp = timestamp;
00570 rtp->f.delivery.tv_sec = 0;
00571 rtp->f.delivery.tv_usec = 0;
00572 if (mark)
00573 rtp->f.subclass |= 0x1;
00574
00575 }
00576 rtp->f.src = "RTP";
00577 return &rtp->f;
00578 }
|
|
|
Definition at line 1521 of file rtp.c. References ast_destroy(), ast_load(), ast_log(), ast_true(), ast_variable_retrieve(), ast_verbose(), LOG_WARNING, s, and VERBOSE_PREFIX_2. Referenced by ast_module_reload(), ast_rtp_init(), and main().
01522 {
01523 struct ast_config *cfg;
01524 char *s;
01525 rtpstart = 5000;
01526 rtpend = 31000;
01527 #ifdef SO_NO_CHECK
01528 checksums = 1;
01529 #endif
01530 cfg = ast_load("rtp.conf");
01531 if (cfg) {
01532 if ((s = ast_variable_retrieve(cfg, "general", "rtpstart"))) {
01533 rtpstart = atoi(s);
01534 if (rtpstart < 1024)
01535 rtpstart = 1024;
01536 if (rtpstart > 65535)
01537 rtpstart = 65535;
01538 }
01539 if ((s = ast_variable_retrieve(cfg, "general", "rtpend"))) {
01540 rtpend = atoi(s);
01541 if (rtpend < 1024)
01542 rtpend = 1024;
01543 if (rtpend > 65535)
01544 rtpend = 65535;
01545 }
01546 if ((s = ast_variable_retrieve(cfg, "general", "rtpchecksums"))) {
01547 #ifdef SO_NO_CHECK
01548 if (ast_true(s))
01549 checksums = 1;
01550 else
01551 checksums = 0;
01552 #else
01553 if (ast_true(s))
01554 ast_log(LOG_WARNING, "Disabling RTP checksums is not supported on this operating system!\n");
01555 #endif
01556 }
01557 ast_destroy(cfg);
01558 }
01559 if (rtpstart >= rtpend) {
01560 ast_log(LOG_WARNING, "Unreasonable values for RTP start/end\n");
01561 rtpstart = 5000;
01562 rtpend = 31000;
01563 }
01564 if (option_verbose > 1)
01565 ast_verbose(VERBOSE_PREFIX_2 "RTP Allocating from port range %d -> %d\n", rtpstart, rtpend);
01566 }
|
|
||||||||||||
|
Definition at line 976 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.
00977 {
00978 unsigned int *rtpheader;
00979 int hdrlen = 12;
00980 int res;
00981 int ms;
00982 int x;
00983 int payload;
00984 char data[256];
00985 char iabuf[INET_ADDRSTRLEN];
00986
00987 if ((digit <= '9') && (digit >= '0'))
00988 digit -= '0';
00989 else if (digit == '*')
00990 digit = 10;
00991 else if (digit == '#')
00992 digit = 11;
00993 else if ((digit >= 'A') && (digit <= 'D'))
00994 digit = digit - 'A' + 12;
00995 else if ((digit >= 'a') && (digit <= 'd'))
00996 digit = digit - 'a' + 12;
00997 else {
00998 ast_log(LOG_WARNING, "Don't know how to represent '%c'\n", digit);
00999 return -1;
01000 }
01001 payload = ast_rtp_lookup_code(rtp, 0, AST_RTP_DTMF);
01002
01003 /* If we have no peer, return immediately */
01004 if (!rtp->them.sin_addr.s_addr)
01005 return 0;
01006
01007 gettimeofday(&rtp->dtmfmute, NULL);
01008 rtp->dtmfmute.tv_usec += (500 * 1000);
01009 if (rtp->dtmfmute.tv_usec > 1000000) {
01010 rtp->dtmfmute.tv_usec -= 1000000;
01011 rtp->dtmfmute.tv_sec += 1;
01012 }
01013
01014 ms = calc_txstamp(rtp, NULL);
01015 /* Default prediction */
01016 rtp->lastts = rtp->lastts + ms * 8;
01017
01018 /* Get a pointer to the header */
01019 rtpheader = (unsigned int *)data;
01020 rtpheader[0] = htonl((2 << 30) | (1 << 23) | (payload << 16) | (rtp->seqno++));
01021 rtpheader[1] = htonl(rtp->lastts);
01022 rtpheader[2] = htonl(rtp->ssrc);
01023 rtpheader[3] = htonl((digit << 24) | (0xa << 16) | (0));
01024 for (x=0;x<4;x++) {
01025 if (rtp->them.sin_port && rtp->them.sin_addr.s_addr) {
01026 res = sendto(rtp->s, (void *)rtpheader, hdrlen + 4, 0, (struct sockaddr *)&rtp->them, sizeof(rtp->them));
01027 if (res <0)
01028 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));
01029 #if 0
01030 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));
01031 #endif
01032 }
01033 if (x ==0) {
01034 /* Clear marker bit and increment seqno */
01035 rtpheader[0] = htonl((2 << 30) | (payload << 16) | (rtp->seqno++));
01036 /* Make duration 800 (100ms) */
01037 rtpheader[3] |= htonl((800));
01038 /* Set the End bit for the last 3 */
01039 rtpheader[3] |= htonl((1 << 23));
01040 }
01041 }
01042 return 0;
01043 }
|
|
||||||||||||
|
Definition at line 167 of file rtp.c. References ast_rtp_callback, and 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 666 of file rtp.c. References rtpPayloadType::code, and ast_rtp::current_RTP_PT.
00666 {
00667 if (pt < 0 || pt > MAX_RTP_PT) return; /* bogus payload type */
00668
00669 if (static_RTP_PT[pt].code != 0) {
00670 rtp->current_RTP_PT[pt] = static_RTP_PT[pt];
00671 }
00672 }
|
|
||||||||||||
|
Definition at line 903 of file rtp.c. References ast_rtp::rtcp, ast_rtcp::them, and ast_rtp::them.
|
|
||||||||||||||||||||
|
Definition at line 676 of file rtp.c. References ast_rtp::current_RTP_PT, subtype, and type.
00677 {
00678 int i;
00679
00680 if (pt < 0 || pt > MAX_RTP_PT) return; /* bogus payload type */
00681
00682 for (i = 0; i < sizeof mimeTypes/sizeof mimeTypes[0]; ++i) {
00683 if (strcasecmp(mimeSubtype, mimeTypes[i].subtype) == 0 &&
00684 strcasecmp(mimeType, mimeTypes[i].type) == 0) {
00685 rtp->current_RTP_PT[pt] = mimeTypes[i].payloadType;
00686 return;
00687 }
00688 }
00689 }
|
|
||||||||||||
|
Definition at line 172 of file rtp.c. References ast_rtp::nat.
00173 {
00174 rtp->nat = nat;
00175 }
|
|
||||||||||||
|
Definition at line 895 of file rtp.c. References ast_log(), LOG_WARNING, and ast_rtp::s.
00896 {
00897 int res;
00898 if ((res = setsockopt(rtp->s, IPPROTO_IP, IP_TOS, &tos, sizeof(tos))))
00899 ast_log(LOG_WARNING, "Unable to set TOS to %d\n", tos);
00900 return res;
00901 }
|
|
|
Definition at line 925 of file rtp.c. References ast_rtp::rtcp, ast_rtcp::them, and ast_rtp::them.
00926 {
00927 memset(&rtp->them.sin_addr, 0, sizeof(rtp->them.sin_addr));
00928 memset(&rtp->them.sin_port, 0, sizeof(rtp->them.sin_port));
00929 if (rtp->rtcp) {
00930 memset(&rtp->rtcp->them.sin_addr, 0, sizeof(rtp->them.sin_addr));
00931 memset(&rtp->rtcp->them.sin_port, 0, sizeof(rtp->them.sin_port));
00932 }
00933 }
|
|
||||||||||||
|
Definition at line 1141 of file rtp.c. References ast_frdup(), ast_getformatname(), ast_log(), ast_rtp_lookup_code(), ast_smoother_feed(), 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.
01142 {
01143 struct ast_frame *f;
01144 int codec;
01145 int hdrlen = 12;
01146 int subclass;
01147
01148
01149 /* If we have no peer, return immediately */
01150 if (!rtp->them.sin_addr.s_addr)
01151 return 0;
01152
01153 /* If there is no data length, return immediately */
01154 if (!_f->datalen)
01155 return 0;
01156
01157 /* Make sure we have enough space for RTP header */
01158 if ((_f->frametype != AST_FRAME_VOICE) && (_f->frametype != AST_FRAME_VIDEO)) {
01159 ast_log(LOG_WARNING, "RTP can only send voice\n");
01160 return -1;
01161 }
01162
01163 subclass = _f->subclass;
01164 if (_f->frametype == AST_FRAME_VIDEO)
01165 subclass &= ~0x1;
01166
01167 codec = ast_rtp_lookup_code(rtp, 1, subclass);
01168 if (codec < 0) {
01169 ast_log(LOG_WARNING, "Don't know how to send format %s packets with RTP\n", ast_getformatname(_f->subclass));
01170 return -1;
01171 }
01172
01173 if (rtp->lasttxformat != subclass) {
01174 /* New format, reset the smoother */
01175 ast_log(LOG_DEBUG, "Ooh, format changed from %s to %s\n", ast_getformatname(rtp->lasttxformat), ast_getformatname(subclass));
01176 rtp->lasttxformat = subclass;
01177 if (rtp->smoother)
01178 ast_smoother_free(rtp->smoother);
01179 rtp->smoother = NULL;
01180 }
01181
01182
01183 switch(subclass) {
01184 case AST_FORMAT_ULAW:
01185 case AST_FORMAT_ALAW:
01186 if (!rtp->smoother) {
01187 rtp->smoother = ast_smoother_new(160);
01188 }
01189 if (!rtp->smoother) {
01190 ast_log(LOG_WARNING, "Unable to create smoother :(\n");
01191 return -1;
01192 }
01193 ast_smoother_feed(rtp->smoother, _f);
01194
01195 while((f = ast_smoother_read(rtp->smoother)))
01196 ast_rtp_raw_write(rtp, f, codec);
01197 break;
01198 case AST_FORMAT_ADPCM:
01199 case AST_FORMAT_G726:
01200 if (!rtp->smoother) {
01201 rtp->smoother = ast_smoother_new(80);
01202 }
01203 if (!rtp->smoother) {
01204 ast_log(LOG_WARNING, "Unable to create smoother :(\n");
01205 return -1;
01206 }
01207 ast_smoother_feed(rtp->smoother, _f);
01208
01209 while((f = ast_smoother_read(rtp->smoother)))
01210 ast_rtp_raw_write(rtp, f, codec);
01211 break;
01212 case AST_FORMAT_G729A:
01213 if (!rtp->smoother) {
01214 rtp->smoother = ast_smoother_new(20);
01215 if (rtp->smoother)
01216 ast_smoother_set_flags(rtp->smoother, AST_SMOOTHER_FLAG_G729);
01217 }
01218 if (!rtp->smoother) {
01219 ast_log(LOG_WARNING, "Unable to create g729 smoother :(\n");
01220 return -1;
01221 }
01222 ast_smoother_feed(rtp->smoother, _f);
01223
01224 while((f = ast_smoother_read(rtp->smoother)))
01225 ast_rtp_raw_write(rtp, f, codec);
01226 break;
01227 case AST_FORMAT_GSM:
01228 if (!rtp->smoother) {
01229 rtp->smoother = ast_smoother_new(33);
01230 }
01231 if (!rtp->smoother) {
01232 ast_log(LOG_WARNING, "Unable to create GSM smoother :(\n");
01233 return -1;
01234 }
01235 ast_smoother_feed(rtp->smoother, _f);
01236 while((f = ast_smoother_read(rtp->smoother)))
01237 ast_rtp_raw_write(rtp, f, codec);
01238 break;
01239 case AST_FORMAT_ILBC:
01240 if (!rtp->smoother) {
01241 rtp->smoother = ast_smoother_new(50);
01242 }
01243 if (!rtp->smoother) {
01244 ast_log(LOG_WARNING, "Unable to create ILBC smoother :(\n");
01245 return -1;
01246 }
01247 ast_smoother_feed(rtp->smoother, _f);
01248 while((f = ast_smoother_read(rtp->smoother)))
01249 ast_rtp_raw_write(rtp, f, codec);
01250 break;
01251 default:
01252 ast_log(LOG_WARNING, "Not sure about sending format %s packets\n", ast_getformatname(subclass));
01253 /* fall through to... */
01254 case AST_FORMAT_H261:
01255 case AST_FORMAT_H263:
01256 case AST_FORMAT_G723_1:
01257 case AST_FORMAT_LPC10:
01258 case AST_FORMAT_SPEEX:
01259 /* Don't buffer outgoing frames; send them one-per-packet: */
01260 if (_f->offset < hdrlen) {
01261 f = ast_frdup(_f);
01262 } else {
01263 f = _f;
01264 }
01265 ast_rtp_raw_write(rtp, f, codec);
01266 }
01267
01268 return 0;
01269 }
|
1.2.15