Wed Mar 3 23:06:59 2010

Asterisk developer's documentation


rtp.h File Reference

Supports RTP and RTCP with Symmetric RTP support for NAT traversal. More...

#include "asterisk/network.h"
#include "asterisk/frame.h"
#include "asterisk/io.h"
#include "asterisk/sched.h"
#include "asterisk/channel.h"
#include "asterisk/linkedlists.h"
Include dependency graph for rtp.h:
This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Data Structures

struct  ast_rtp_protocol
 This is the structure that binds a channel (SIP/Jingle/H.323) to the RTP subsystem. More...
struct  ast_rtp_quality
 RTCP quality report storage. More...

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
#define FLAG_3389_WARNING   (1 << 0)
#define MAX_RTP_PT   256
#define RED_MAX_GENERATION   5

Typedefs

typedef int(* ast_rtp_callback )(struct ast_rtp *rtp, struct ast_frame *f, void *data)

Enumerations

enum  ast_rtp_get_result { AST_RTP_GET_FAILED = 0, AST_RTP_TRY_PARTIAL, AST_RTP_TRY_NATIVE }
enum  ast_rtp_options { AST_RTP_OPT_G726_NONSTANDARD = (1 << 0) }
enum  ast_rtp_qos_vars {
  AST_RTP_TXCOUNT, AST_RTP_RXCOUNT, AST_RTP_TXJITTER, AST_RTP_RXJITTER,
  AST_RTP_RXPLOSS, AST_RTP_TXPLOSS, AST_RTP_RTT
}
 

Variables used in ast_rtcp_get function.

More...
enum  ast_rtp_quality_type { RTPQOS_SUMMARY = 0, RTPQOS_JITTER, RTPQOS_LOSS, RTPQOS_RTT }

Functions

int ast_rtcp_fd (struct ast_rtp *rtp)
struct ast_frameast_rtcp_read (struct ast_rtp *rtp)
int ast_rtcp_send_h261fur (void *data)
 Send an H.261 fast update request. Some devices need this rather than the XML message in SIP.
size_t ast_rtp_alloc_size (void)
 Get the amount of space required to hold an RTP session.
int ast_rtp_bridge (struct ast_channel *c0, struct ast_channel *c1, int flags, struct ast_frame **fo, struct ast_channel **rc, int timeoutms)
 The RTP bridge.
int ast_rtp_codec_getformat (int pt)
 get format from predefined dynamic payload format
struct ast_codec_prefast_rtp_codec_getpref (struct ast_rtp *rtp)
 Get codec preference.
void ast_rtp_codec_setpref (struct ast_rtp *rtp, struct ast_codec_pref *prefs)
 Set codec preference.
void ast_rtp_destroy (struct ast_rtp *rtp)
int ast_rtp_early_bridge (struct ast_channel *c0, struct ast_channel *c1)
 If possible, create an early bridge directly between the devices without having to send a re-invite later.
int ast_rtp_fd (struct ast_rtp *rtp)
struct ast_rtpast_rtp_get_bridged (struct ast_rtp *rtp)
void ast_rtp_get_current_formats (struct ast_rtp *rtp, int *astFormats, int *nonAstFormats)
 Return the union of all of the codecs that were set by rtp_set...() calls They're returned as two distinct sets: AST_FORMATs, and AST_RTPs.
int ast_rtp_get_peer (struct ast_rtp *rtp, struct sockaddr_in *them)
int ast_rtp_get_qos (struct ast_rtp *rtp, const char *qos, char *buf, unsigned int buflen)
 Get QOS stats on a RTP channel.
unsigned int ast_rtp_get_qosvalue (struct ast_rtp *rtp, enum ast_rtp_qos_vars value)
 Return RTP and RTCP QoS values.
char * ast_rtp_get_quality (struct ast_rtp *rtp, struct ast_rtp_quality *qual, enum ast_rtp_quality_type qtype)
 Return RTCP quality string.
int ast_rtp_get_rtpholdtimeout (struct ast_rtp *rtp)
 Get rtp hold timeout.
int ast_rtp_get_rtpkeepalive (struct ast_rtp *rtp)
 Get RTP keepalive interval.
int ast_rtp_get_rtptimeout (struct ast_rtp *rtp)
 Get rtp timeout.
void ast_rtp_get_us (struct ast_rtp *rtp, struct sockaddr_in *us)
int ast_rtp_getnat (struct ast_rtp *rtp)
void ast_rtp_init (void)
 Initialize the RTP system in Asterisk.
int ast_rtp_lookup_code (struct ast_rtp *rtp, int isAstFormat, int code)
 Looks up an RTP code out of our *static* outbound list.
char * ast_rtp_lookup_mime_multiple (char *buf, size_t size, const int capability, const int isAstFormat, enum ast_rtp_options options)
 Build a string of MIME subtype names from a capability list.
const char * ast_rtp_lookup_mime_subtype (int isAstFormat, int code, enum ast_rtp_options options)
 Mapping an Asterisk code into a MIME subtype (string):.
struct rtpPayloadType ast_rtp_lookup_pt (struct ast_rtp *rtp, int pt)
 Mapping between RTP payload format codes and Asterisk codes:.
int ast_rtp_make_compatible (struct ast_channel *dest, struct ast_channel *src, int media)
struct ast_rtpast_rtp_new (struct sched_context *sched, struct io_context *io, int rtcpenable, int callbackmode)
 Initializate a RTP session.
void ast_rtp_new_init (struct ast_rtp *rtp)
 Initialize a new RTP structure.
void ast_rtp_new_source (struct ast_rtp *rtp)
struct ast_rtpast_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.
int ast_rtp_proto_register (struct ast_rtp_protocol *proto)
 Register an RTP channel client.
void ast_rtp_proto_unregister (struct ast_rtp_protocol *proto)
 Unregister an RTP channel client.
void ast_rtp_pt_clear (struct ast_rtp *rtp)
 Setting RTP payload types from lines in a SDP description:.
void ast_rtp_pt_copy (struct ast_rtp *dest, struct ast_rtp *src)
 Copy payload types between RTP structures.
void ast_rtp_pt_default (struct ast_rtp *rtp)
 Set payload types to defaults.
struct ast_frameast_rtp_read (struct ast_rtp *rtp)
int ast_rtp_reload (void)
void ast_rtp_reset (struct ast_rtp *rtp)
int ast_rtp_sendcng (struct ast_rtp *rtp, int level)
 generate comfort noice (CNG)
int ast_rtp_senddigit_begin (struct ast_rtp *rtp, char digit)
 Send begin frames for DTMF.
int ast_rtp_senddigit_end (struct ast_rtp *rtp, char digit)
 Send end packets for DTMF.
void ast_rtp_set_alt_peer (struct ast_rtp *rtp, struct sockaddr_in *alt)
 set potential alternate source for RTP media
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)
 Activate payload type.
void ast_rtp_set_peer (struct ast_rtp *rtp, struct sockaddr_in *them)
void ast_rtp_set_rtpholdtimeout (struct ast_rtp *rtp, int timeout)
 Set rtp hold timeout.
void ast_rtp_set_rtpkeepalive (struct ast_rtp *rtp, int period)
 set RTP keepalive interval
int ast_rtp_set_rtpmap_type (struct ast_rtp *rtp, int pt, char *mimeType, char *mimeSubtype, enum ast_rtp_options options)
 Initiate payload type to a known MIME media type for a codec.
void ast_rtp_set_rtptimeout (struct ast_rtp *rtp, int timeout)
 Set rtp timeout.
void ast_rtp_set_rtptimers_onhold (struct ast_rtp *rtp)
void ast_rtp_set_vars (struct ast_channel *chan, struct ast_rtp *rtp)
 Set RTPAUDIOQOS(...) variables on a channel when it is being hung up.
void ast_rtp_setdtmf (struct ast_rtp *rtp, int dtmf)
 Indicate whether this RTP session is carrying DTMF or not.
void ast_rtp_setdtmfcompensate (struct ast_rtp *rtp, int compensate)
 Compensate for devices that send RFC2833 packets all at once.
void ast_rtp_setnat (struct ast_rtp *rtp, int nat)
int ast_rtp_setqos (struct ast_rtp *rtp, int tos, int cos, char *desc)
void ast_rtp_setstun (struct ast_rtp *rtp, int stun_enable)
 Enable STUN capability.
void ast_rtp_stop (struct ast_rtp *rtp)
void ast_rtp_stun_request (struct ast_rtp *rtp, struct sockaddr_in *suggestion, const char *username)
 Send STUN request for an RTP socket Deprecated, this is just a wrapper for ast_rtp_stun_request().
void ast_rtp_unset_m_type (struct ast_rtp *rtp, int pt)
 clear payload type
int ast_rtp_write (struct ast_rtp *rtp, struct ast_frame *f)
int ast_stun_request (int s, struct sockaddr_in *dst, const char *username, struct sockaddr_in *answer)
 Generic STUN request send a generic stun request to the server specified.
void red_buffer_t140 (struct ast_rtp *rtp, struct ast_frame *f)
 Buffer t.140 data.
int rtp_red_init (struct ast_rtp *rtp, int ti, int *pt, int num_gen)
 Initalize t.140 redudancy.

Detailed Description

Supports RTP and RTCP with Symmetric RTP support for NAT traversal.

RTP is defined in RFC 3550.

Definition in file rtp.h.


Define Documentation

#define AST_RTP_CISCO_DTMF   (1 << 2)

DTMF (Cisco Proprietary)

Definition at line 47 of file rtp.h.

Referenced by ast_rtp_read().

#define AST_RTP_CN   (1 << 1)

'Comfort Noise' (RFC3389)

Definition at line 45 of file rtp.h.

Referenced by ast_rtp_read(), and ast_rtp_sendcng().

#define AST_RTP_DTMF   (1 << 0)
#define AST_RTP_MAX   AST_RTP_CISCO_DTMF

Maximum RTP-specific code

Definition at line 49 of file rtp.h.

Referenced by add_sdp(), and ast_rtp_lookup_mime_multiple().

#define FLAG_3389_WARNING   (1 << 0)

Definition at line 57 of file rtp.h.

#define MAX_RTP_PT   256
#define RED_MAX_GENERATION   5

T.140 Redundancy Maxium number of generations

Definition at line 55 of file rtp.h.

Referenced by process_sdp().


Typedef Documentation

typedef int(* ast_rtp_callback)(struct ast_rtp *rtp, struct ast_frame *f, void *data)

RTP callback structure

Definition at line 124 of file rtp.h.


Enumeration Type Documentation

Enumerator:
AST_RTP_GET_FAILED 

Failed to find the RTP structure

AST_RTP_TRY_PARTIAL 

RTP structure exists but true native bridge can not occur so try partial

AST_RTP_TRY_NATIVE 

RTP structure exists and native bridge can occur

Definition at line 63 of file rtp.h.

00063                         {
00064    /*! Failed to find the RTP structure */
00065    AST_RTP_GET_FAILED = 0,
00066    /*! RTP structure exists but true native bridge can not occur so try partial */
00067    AST_RTP_TRY_PARTIAL,
00068    /*! RTP structure exists and native bridge can occur */
00069    AST_RTP_TRY_NATIVE,
00070 };

Enumerator:
AST_RTP_OPT_G726_NONSTANDARD 

Definition at line 59 of file rtp.h.

00059                      {
00060    AST_RTP_OPT_G726_NONSTANDARD = (1 << 0),
00061 };

Variables used in ast_rtcp_get function.

Enumerator:
AST_RTP_TXCOUNT 
AST_RTP_RXCOUNT 
AST_RTP_TXJITTER 
AST_RTP_RXJITTER 
AST_RTP_RXPLOSS 
AST_RTP_TXPLOSS 
AST_RTP_RTT 

Definition at line 73 of file rtp.h.

00073                       {
00074    AST_RTP_TXCOUNT,
00075    AST_RTP_RXCOUNT,
00076    AST_RTP_TXJITTER,
00077    AST_RTP_RXJITTER,
00078    AST_RTP_RXPLOSS,
00079    AST_RTP_TXPLOSS,
00080    AST_RTP_RTT
00081 };

Enumerator:
RTPQOS_SUMMARY 
RTPQOS_JITTER 
RTPQOS_LOSS 
RTPQOS_RTT 

Definition at line 103 of file rtp.h.

00103                           {
00104    RTPQOS_SUMMARY = 0,
00105    RTPQOS_JITTER,
00106    RTPQOS_LOSS,
00107    RTPQOS_RTT
00108 };


Function Documentation

int ast_rtcp_fd ( struct ast_rtp rtp  ) 

Definition at line 728 of file rtp.c.

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

Referenced by __oh323_new(), __oh323_rtp_create(), __oh323_update_info(), gtalk_new(), jingle_new(), sip_new(), start_rtp(), and unistim_new().

00729 {
00730    if (rtp->rtcp)
00731       return rtp->rtcp->s;
00732    return -1;
00733 }

struct ast_frame* ast_rtcp_read ( struct ast_rtp rtp  )  [read]

Definition at line 1174 of file rtp.c.

References ast_rtcp::accumulated_transit, ast_rtcp::altthem, ast_assert, AST_CONTROL_VIDUPDATE, ast_debug, AST_FRAME_CONTROL, AST_FRIENDLY_OFFSET, ast_inet_ntoa(), ast_log(), ast_null_frame, ast_verbose, ast_frame::datalen, errno, EVENT_FLAG_REPORTING, ast_rtp::f, f, ast_frame::frametype, len(), LOG_DEBUG, LOG_WARNING, ast_frame::mallocd, manager_event, ast_rtcp::maxrtt, ast_rtcp::minrtt, ast_rtp::nat, normdev_compute(), ast_rtcp::normdevrtt, option_debug, ast_rtcp::reported_jitter, ast_rtcp::reported_jitter_count, ast_rtcp::reported_lost, ast_rtcp::reported_maxjitter, ast_rtcp::reported_maxlost, ast_rtcp::reported_minjitter, ast_rtcp::reported_minlost, ast_rtcp::reported_normdev_jitter, ast_rtcp::reported_normdev_lost, ast_rtcp::reported_stdev_jitter, ast_rtcp::reported_stdev_lost, ast_rtp::rtcp, rtcp_debug_test_addr(), ast_rtcp::rtcp_info, RTCP_PT_BYE, RTCP_PT_FUR, RTCP_PT_RR, RTCP_PT_SDES, RTCP_PT_SR, ast_rtcp::rtt, ast_rtcp::rtt_count, ast_rtcp::rxlsr, ast_rtcp::s, ast_frame::samples, ast_rtcp::soc, ast_rtcp::spc, ast_frame::src, stddev_compute(), ast_rtcp::stdevrtt, ast_frame::subclass, ast_rtcp::them, ast_rtcp::themrxlsr, and timeval2ntp().

Referenced by oh323_read(), sip_rtp_read(), skinny_rtp_read(), and unistim_rtp_read().

01175 {
01176    socklen_t len;
01177    int position, i, packetwords;
01178    int res;
01179    struct sockaddr_in sock_in;
01180    unsigned int rtcpdata[8192 + AST_FRIENDLY_OFFSET];
01181    unsigned int *rtcpheader;
01182    int pt;
01183    struct timeval now;
01184    unsigned int length;
01185    int rc;
01186    double rttsec;
01187    uint64_t rtt = 0;
01188    unsigned int dlsr;
01189    unsigned int lsr;
01190    unsigned int msw;
01191    unsigned int lsw;
01192    unsigned int comp;
01193    struct ast_frame *f = &ast_null_frame;
01194    
01195    double reported_jitter;
01196    double reported_normdev_jitter_current;
01197    double normdevrtt_current;
01198    double reported_lost;
01199    double reported_normdev_lost_current;
01200 
01201    if (!rtp || !rtp->rtcp)
01202       return &ast_null_frame;
01203 
01204    len = sizeof(sock_in);
01205    
01206    res = recvfrom(rtp->rtcp->s, rtcpdata + AST_FRIENDLY_OFFSET, sizeof(rtcpdata) - sizeof(unsigned int) * AST_FRIENDLY_OFFSET,
01207                0, (struct sockaddr *)&sock_in, &len);
01208    rtcpheader = (unsigned int *)(rtcpdata + AST_FRIENDLY_OFFSET);
01209    
01210    if (res < 0) {
01211       ast_assert(errno != EBADF);
01212       if (errno != EAGAIN) {
01213          ast_log(LOG_WARNING, "RTCP Read error: %s.  Hanging up.\n", strerror(errno));
01214          return NULL;
01215       }
01216       return &ast_null_frame;
01217    }
01218 
01219    packetwords = res / 4;
01220    
01221    if (rtp->nat) {
01222       /* Send to whoever sent to us */
01223       if (((rtp->rtcp->them.sin_addr.s_addr != sock_in.sin_addr.s_addr) ||
01224           (rtp->rtcp->them.sin_port != sock_in.sin_port)) && 
01225           ((rtp->rtcp->altthem.sin_addr.s_addr != sock_in.sin_addr.s_addr) || 
01226           (rtp->rtcp->altthem.sin_port != sock_in.sin_port))) {
01227          memcpy(&rtp->rtcp->them, &sock_in, sizeof(rtp->rtcp->them));
01228          if (option_debug || rtpdebug)
01229             ast_debug(0, "RTCP NAT: Got RTCP from other end. Now sending to address %s:%d\n", ast_inet_ntoa(rtp->rtcp->them.sin_addr), ntohs(rtp->rtcp->them.sin_port));
01230       }
01231    }
01232 
01233    ast_debug(1, "Got RTCP report of %d bytes\n", res);
01234 
01235    /* Process a compound packet */
01236    position = 0;
01237    while (position < packetwords) {
01238       i = position;
01239       length = ntohl(rtcpheader[i]);
01240       pt = (length & 0xff0000) >> 16;
01241       rc = (length & 0x1f000000) >> 24;
01242       length &= 0xffff;
01243  
01244       if ((i + length) > packetwords) {
01245          if (option_debug || rtpdebug)
01246             ast_log(LOG_DEBUG, "RTCP Read too short\n");
01247          return &ast_null_frame;
01248       }
01249       
01250       if (rtcp_debug_test_addr(&sock_in)) {
01251          ast_verbose("\n\nGot RTCP from %s:%d\n", ast_inet_ntoa(sock_in.sin_addr), ntohs(sock_in.sin_port));
01252          ast_verbose("PT: %d(%s)\n", pt, (pt == 200) ? "Sender Report" : (pt == 201) ? "Receiver Report" : (pt == 192) ? "H.261 FUR" : "Unknown");
01253          ast_verbose("Reception reports: %d\n", rc);
01254          ast_verbose("SSRC of sender: %u\n", rtcpheader[i + 1]);
01255       }
01256  
01257       i += 2; /* Advance past header and ssrc */
01258       
01259       switch (pt) {
01260       case RTCP_PT_SR:
01261          gettimeofday(&rtp->rtcp->rxlsr,NULL); /* To be able to populate the dlsr */
01262          rtp->rtcp->spc = ntohl(rtcpheader[i+3]);
01263          rtp->rtcp->soc = ntohl(rtcpheader[i + 4]);
01264          rtp->rtcp->themrxlsr = ((ntohl(rtcpheader[i]) & 0x0000ffff) << 16) | ((ntohl(rtcpheader[i + 1]) & 0xffff0000) >> 16); /* Going to LSR in RR*/
01265  
01266          if (rtcp_debug_test_addr(&sock_in)) {
01267             ast_verbose("NTP timestamp: %lu.%010lu\n", (unsigned long) ntohl(rtcpheader[i]), (unsigned long) ntohl(rtcpheader[i + 1]) * 4096);
01268             ast_verbose("RTP timestamp: %lu\n", (unsigned long) ntohl(rtcpheader[i + 2]));
01269             ast_verbose("SPC: %lu\tSOC: %lu\n", (unsigned long) ntohl(rtcpheader[i + 3]), (unsigned long) ntohl(rtcpheader[i + 4]));
01270          }
01271          i += 5;
01272          if (rc < 1)
01273             break;
01274          /* Intentional fall through */
01275       case RTCP_PT_RR:
01276          /* Don't handle multiple reception reports (rc > 1) yet */
01277          /* Calculate RTT per RFC */
01278          gettimeofday(&now, NULL);
01279          timeval2ntp(now, &msw, &lsw);
01280          if (ntohl(rtcpheader[i + 4]) && ntohl(rtcpheader[i + 5])) { /* We must have the LSR && DLSR */
01281             comp = ((msw & 0xffff) << 16) | ((lsw & 0xffff0000) >> 16);
01282             lsr = ntohl(rtcpheader[i + 4]);
01283             dlsr = ntohl(rtcpheader[i + 5]);
01284             rtt = comp - lsr - dlsr;
01285 
01286             /* Convert end to end delay to usec (keeping the calculation in 64bit space)
01287                sess->ee_delay = (eedelay * 1000) / 65536; */
01288             if (rtt < 4294) {
01289                 rtt = (rtt * 1000000) >> 16;
01290             } else {
01291                 rtt = (rtt * 1000) >> 16;
01292                 rtt *= 1000;
01293             }
01294             rtt = rtt / 1000.;
01295             rttsec = rtt / 1000.;
01296             rtp->rtcp->rtt = rttsec;
01297 
01298             if (comp - dlsr >= lsr) {
01299                rtp->rtcp->accumulated_transit += rttsec;
01300 
01301                if (rtp->rtcp->rtt_count == 0) 
01302                   rtp->rtcp->minrtt = rttsec;
01303 
01304                if (rtp->rtcp->maxrtt<rttsec)
01305                   rtp->rtcp->maxrtt = rttsec;
01306 
01307                if (rtp->rtcp->minrtt>rttsec)
01308                   rtp->rtcp->minrtt = rttsec;
01309 
01310                normdevrtt_current = normdev_compute(rtp->rtcp->normdevrtt, rttsec, rtp->rtcp->rtt_count);
01311 
01312                rtp->rtcp->stdevrtt = stddev_compute(rtp->rtcp->stdevrtt, rttsec, rtp->rtcp->normdevrtt, normdevrtt_current, rtp->rtcp->rtt_count);
01313 
01314                rtp->rtcp->normdevrtt = normdevrtt_current;
01315 
01316                rtp->rtcp->rtt_count++;
01317             } else if (rtcp_debug_test_addr(&sock_in)) {
01318                ast_verbose("Internal RTCP NTP clock skew detected: "
01319                         "lsr=%u, now=%u, dlsr=%u (%d:%03dms), "
01320                         "diff=%d\n",
01321                         lsr, comp, dlsr, dlsr / 65536,
01322                         (dlsr % 65536) * 1000 / 65536,
01323                         dlsr - (comp - lsr));
01324             }
01325          }
01326 
01327          rtp->rtcp->reported_jitter = ntohl(rtcpheader[i + 3]);
01328          reported_jitter = (double) rtp->rtcp->reported_jitter;
01329 
01330          if (rtp->rtcp->reported_jitter_count == 0) 
01331             rtp->rtcp->reported_minjitter = reported_jitter;
01332 
01333          if (reported_jitter < rtp->rtcp->reported_minjitter) 
01334             rtp->rtcp->reported_minjitter = reported_jitter;
01335 
01336          if (reported_jitter > rtp->rtcp->reported_maxjitter) 
01337             rtp->rtcp->reported_maxjitter = reported_jitter;
01338 
01339          reported_normdev_jitter_current = normdev_compute(rtp->rtcp->reported_normdev_jitter, reported_jitter, rtp->rtcp->reported_jitter_count);
01340 
01341          rtp->rtcp->reported_stdev_jitter = stddev_compute(rtp->rtcp->reported_stdev_jitter, reported_jitter, rtp->rtcp->reported_normdev_jitter, reported_normdev_jitter_current, rtp->rtcp->reported_jitter_count);
01342 
01343          rtp->rtcp->reported_normdev_jitter = reported_normdev_jitter_current;
01344 
01345          rtp->rtcp->reported_lost = ntohl(rtcpheader[i + 1]) & 0xffffff;
01346 
01347          reported_lost = (double) rtp->rtcp->reported_lost;
01348 
01349          /* using same counter as for jitter */
01350          if (rtp->rtcp->reported_jitter_count == 0)
01351             rtp->rtcp->reported_minlost = reported_lost;
01352 
01353          if (reported_lost < rtp->rtcp->reported_minlost)
01354             rtp->rtcp->reported_minlost = reported_lost;
01355 
01356          if (reported_lost > rtp->rtcp->reported_maxlost) 
01357             rtp->rtcp->reported_maxlost = reported_lost;
01358 
01359          reported_normdev_lost_current = normdev_compute(rtp->rtcp->reported_normdev_lost, reported_lost, rtp->rtcp->reported_jitter_count);
01360 
01361          rtp->rtcp->reported_stdev_lost = stddev_compute(rtp->rtcp->reported_stdev_lost, reported_lost, rtp->rtcp->reported_normdev_lost, reported_normdev_lost_current, rtp->rtcp->reported_jitter_count);
01362 
01363          rtp->rtcp->reported_normdev_lost = reported_normdev_lost_current;
01364 
01365          rtp->rtcp->reported_jitter_count++;
01366 
01367          if (rtcp_debug_test_addr(&sock_in)) {
01368             ast_verbose("  Fraction lost: %ld\n", (((long) ntohl(rtcpheader[i + 1]) & 0xff000000) >> 24));
01369             ast_verbose("  Packets lost so far: %d\n", rtp->rtcp->reported_lost);
01370             ast_verbose("  Highest sequence number: %ld\n", (long) (ntohl(rtcpheader[i + 2]) & 0xffff));
01371             ast_verbose("  Sequence number cycles: %ld\n", (long) (ntohl(rtcpheader[i + 2]) & 0xffff) >> 16);
01372             ast_verbose("  Interarrival jitter: %u\n", rtp->rtcp->reported_jitter);
01373             ast_verbose("  Last SR(our NTP): %lu.%010lu\n",(unsigned long) ntohl(rtcpheader[i + 4]) >> 16,((unsigned long) ntohl(rtcpheader[i + 4]) << 16) * 4096);
01374             ast_verbose("  DLSR: %4.4f (sec)\n",ntohl(rtcpheader[i + 5])/65536.0);
01375             if (rtt)
01376                ast_verbose("  RTT: %lu(sec)\n", (unsigned long) rtt);
01377          }
01378 
01379          if (rtt) {
01380             manager_event(EVENT_FLAG_REPORTING, "RTCPReceived", "From: %s:%d\r\n"
01381                             "PT: %d(%s)\r\n"
01382                             "ReceptionReports: %d\r\n"
01383                             "SenderSSRC: %u\r\n"
01384                             "FractionLost: %ld\r\n"
01385                             "PacketsLost: %d\r\n"
01386                             "HighestSequence: %ld\r\n"
01387                             "SequenceNumberCycles: %ld\r\n"
01388                             "IAJitter: %u\r\n"
01389                             "LastSR: %lu.%010lu\r\n"
01390                             "DLSR: %4.4f(sec)\r\n"
01391                             "RTT: %llu(sec)\r\n",
01392                             ast_inet_ntoa(sock_in.sin_addr), ntohs(sock_in.sin_port),
01393                             pt, (pt == 200) ? "Sender Report" : (pt == 201) ? "Receiver Report" : (pt == 192) ? "H.261 FUR" : "Unknown",
01394                             rc,
01395                             rtcpheader[i + 1],
01396                             (((long) ntohl(rtcpheader[i + 1]) & 0xff000000) >> 24),
01397                             rtp->rtcp->reported_lost,
01398                             (long) (ntohl(rtcpheader[i + 2]) & 0xffff),
01399                             (long) (ntohl(rtcpheader[i + 2]) & 0xffff) >> 16,
01400                             rtp->rtcp->reported_jitter,
01401                             (unsigned long) ntohl(rtcpheader[i + 4]) >> 16, ((unsigned long) ntohl(rtcpheader[i + 4]) << 16) * 4096,
01402                             ntohl(rtcpheader[i + 5])/65536.0,
01403                             (unsigned long long)rtt);
01404          } else {
01405             manager_event(EVENT_FLAG_REPORTING, "RTCPReceived", "From: %s:%d\r\n"
01406                             "PT: %d(%s)\r\n"
01407                             "ReceptionReports: %d\r\n"
01408                             "SenderSSRC: %u\r\n"
01409                             "FractionLost: %ld\r\n"
01410                             "PacketsLost: %d\r\n"
01411                             "HighestSequence: %ld\r\n"
01412                             "SequenceNumberCycles: %ld\r\n"
01413                             "IAJitter: %u\r\n"
01414                             "LastSR: %lu.%010lu\r\n"
01415                             "DLSR: %4.4f(sec)\r\n",
01416                             ast_inet_ntoa(sock_in.sin_addr), ntohs(sock_in.sin_port),
01417                             pt, (pt == 200) ? "Sender Report" : (pt == 201) ? "Receiver Report" : (pt == 192) ? "H.261 FUR" : "Unknown",
01418                             rc,
01419                             rtcpheader[i + 1],
01420                             (((long) ntohl(rtcpheader[i + 1]) & 0xff000000) >> 24),
01421                             rtp->rtcp->reported_lost,
01422                             (long) (ntohl(rtcpheader[i + 2]) & 0xffff),
01423                             (long) (ntohl(rtcpheader[i + 2]) & 0xffff) >> 16,
01424                             rtp->rtcp->reported_jitter,
01425                             (unsigned long) ntohl(rtcpheader[i + 4]) >> 16,
01426                             ((unsigned long) ntohl(rtcpheader[i + 4]) << 16) * 4096,
01427                             ntohl(rtcpheader[i + 5])/65536.0);
01428          }
01429          break;
01430       case RTCP_PT_FUR:
01431          if (rtcp_debug_test_addr(&sock_in))
01432             ast_verbose("Received an RTCP Fast Update Request\n");
01433          rtp->f.frametype = AST_FRAME_CONTROL;
01434          rtp->f.subclass = AST_CONTROL_VIDUPDATE;
01435          rtp->f.datalen = 0;
01436          rtp->f.samples = 0;
01437          rtp->f.mallocd = 0;
01438          rtp->f.src = "RTP";
01439          f = &rtp->f;
01440          break;
01441       case RTCP_PT_SDES:
01442          if (rtcp_debug_test_addr(&sock_in))
01443             ast_verbose("Received an SDES from %s:%d\n", ast_inet_ntoa(rtp->rtcp->them.sin_addr), ntohs(rtp->rtcp->them.sin_port));
01444          break;
01445       case RTCP_PT_BYE:
01446          if (rtcp_debug_test_addr(&sock_in))
01447             ast_verbose("Received a BYE from %s:%d\n", ast_inet_ntoa(rtp->rtcp->them.sin_addr), ntohs(rtp->rtcp->them.sin_port));
01448          break;
01449       default:
01450          ast_debug(1, "Unknown RTCP packet (pt=%d) received from %s:%d\n", pt, ast_inet_ntoa(rtp->rtcp->them.sin_addr), ntohs(rtp->rtcp->them.sin_port));
01451          break;
01452       }
01453       position += (length + 1);
01454    }
01455    rtp->rtcp->rtcp_info = 1;  
01456    return f;
01457 }

int ast_rtcp_send_h261fur ( void *  data  ) 

Send an H.261 fast update request. Some devices need this rather than the XML message in SIP.

Definition at line 3258 of file rtp.c.

References ast_rtcp_write(), ast_rtp::rtcp, and ast_rtcp::sendfur.

03259 {
03260    struct ast_rtp *rtp = data;
03261    int res;
03262 
03263    rtp->rtcp->sendfur = 1;
03264    res = ast_rtcp_write(data);
03265    
03266    return res;
03267 }

size_t ast_rtp_alloc_size ( void   ) 

Get the amount of space required to hold an RTP session.

Returns:
number of bytes required

Definition at line 499 of file rtp.c.

Referenced by process_sdp().

00500 {
00501    return sizeof(struct ast_rtp);
00502 }

int ast_rtp_bridge ( struct ast_channel c0,
struct ast_channel c1,
int  flags,
struct ast_frame **  fo,
struct ast_channel **  rc,
int  timeoutms 
)

The RTP bridge.

Definition at line 4346 of file rtp.c.

References AST_BRIDGE_DTMF_CHANNEL_0, AST_BRIDGE_DTMF_CHANNEL_1, AST_BRIDGE_FAILED, AST_BRIDGE_FAILED_NOWARN, ast_channel_lock, ast_channel_trylock, ast_channel_unlock, ast_check_hangup(), ast_codec_pref_getsize(), ast_debug, ast_log(), AST_RTP_GET_FAILED, AST_RTP_TRY_NATIVE, AST_RTP_TRY_PARTIAL, ast_set_flag, ast_test_flag, ast_verb, bridge_native_loop(), bridge_p2p_loop(), ast_format_list::cur_ms, FLAG_HAS_DTMF, FLAG_P2P_NEED_DTMF, ast_rtp_protocol::get_codec, get_proto(), ast_rtp_protocol::get_rtp_info, ast_rtp_protocol::get_trtp_info, ast_rtp_protocol::get_vrtp_info, LOG_WARNING, ast_rtp::pref, ast_channel::rawreadformat, ast_channel::rawwriteformat, ast_channel_tech::send_digit_begin, ast_channel::tech, and ast_channel::tech_pvt.

04347 {
04348    struct ast_rtp *p0 = NULL, *p1 = NULL;    /* Audio RTP Channels */
04349    struct ast_rtp *vp0 = NULL, *vp1 = NULL;  /* Video RTP channels */
04350    struct ast_rtp *tp0 = NULL, *tp1 = NULL;  /* Text RTP channels */
04351    struct ast_rtp_protocol *pr0 = NULL, *pr1 = NULL;
04352    enum ast_rtp_get_result audio_p0_res = AST_RTP_GET_FAILED, video_p0_res = AST_RTP_GET_FAILED, text_p0_res = AST_RTP_GET_FAILED;
04353    enum ast_rtp_get_result audio_p1_res = AST_RTP_GET_FAILED, video_p1_res = AST_RTP_GET_FAILED, text_p1_res = AST_RTP_GET_FAILED;
04354    enum ast_bridge_result res = AST_BRIDGE_FAILED;
04355    int codec0 = 0, codec1 = 0;
04356    void *pvt0 = NULL, *pvt1 = NULL;
04357 
04358    /* Lock channels */
04359    ast_channel_lock(c0);
04360    while (ast_channel_trylock(c1)) {
04361       ast_channel_unlock(c0);
04362       usleep(1);
04363       ast_channel_lock(c0);
04364    }
04365 
04366    /* Ensure neither channel got hungup during lock avoidance */
04367    if (ast_check_hangup(c0) || ast_check_hangup(c1)) {
04368       ast_log(LOG_WARNING, "Got hangup while attempting to bridge '%s' and '%s'\n", c0->name, c1->name);
04369       ast_channel_unlock(c0);
04370       ast_channel_unlock(c1);
04371       return AST_BRIDGE_FAILED;
04372    }
04373       
04374    /* Find channel driver interfaces */
04375    if (!(pr0 = get_proto(c0))) {
04376       ast_log(LOG_WARNING, "Can't find native functions for channel '%s'\n", c0->name);
04377       ast_channel_unlock(c0);
04378       ast_channel_unlock(c1);
04379       return AST_BRIDGE_FAILED;
04380    }
04381    if (!(pr1 = get_proto(c1))) {
04382       ast_log(LOG_WARNING, "Can't find native functions for channel '%s'\n", c1->name);
04383       ast_channel_unlock(c0);
04384       ast_channel_unlock(c1);
04385       return AST_BRIDGE_FAILED;
04386    }
04387 
04388    /* Get channel specific interface structures */
04389    pvt0 = c0->tech_pvt;
04390    pvt1 = c1->tech_pvt;
04391 
04392    /* Get audio and video interface (if native bridge is possible) */
04393    audio_p0_res = pr0->get_rtp_info(c0, &p0);
04394    video_p0_res = pr0->get_vrtp_info ? pr0->get_vrtp_info(c0, &vp0) : AST_RTP_GET_FAILED;
04395    text_p0_res = pr0->get_trtp_info ? pr0->get_trtp_info(c0, &vp0) : AST_RTP_GET_FAILED;
04396    audio_p1_res = pr1->get_rtp_info(c1, &p1);
04397    video_p1_res = pr1->get_vrtp_info ? pr1->get_vrtp_info(c1, &vp1) : AST_RTP_GET_FAILED;
04398    text_p1_res = pr1->get_trtp_info ? pr1->get_trtp_info(c1, &vp1) : AST_RTP_GET_FAILED;
04399 
04400    /* If we are carrying video, and both sides are not reinviting... then fail the native bridge */
04401    if (video_p0_res != AST_RTP_GET_FAILED && (audio_p0_res != AST_RTP_TRY_NATIVE || video_p0_res != AST_RTP_TRY_NATIVE))
04402       audio_p0_res = AST_RTP_GET_FAILED;
04403    if (video_p1_res != AST_RTP_GET_FAILED && (audio_p1_res != AST_RTP_TRY_NATIVE || video_p1_res != AST_RTP_TRY_NATIVE))
04404       audio_p1_res = AST_RTP_GET_FAILED;
04405 
04406    /* Check if a bridge is possible (partial/native) */
04407    if (audio_p0_res == AST_RTP_GET_FAILED || audio_p1_res == AST_RTP_GET_FAILED) {
04408       /* Somebody doesn't want to play... */
04409       ast_channel_unlock(c0);
04410       ast_channel_unlock(c1);
04411       return AST_BRIDGE_FAILED_NOWARN;
04412    }
04413 
04414    /* If we need to feed DTMF frames into the core then only do a partial native bridge */
04415    if (ast_test_flag(p0, FLAG_HAS_DTMF) && (flags & AST_BRIDGE_DTMF_CHANNEL_0)) {
04416       ast_set_flag(p0, FLAG_P2P_NEED_DTMF);
04417       audio_p0_res = AST_RTP_TRY_PARTIAL;
04418    }
04419 
04420    if (ast_test_flag(p1, FLAG_HAS_DTMF) && (flags & AST_BRIDGE_DTMF_CHANNEL_1)) {
04421       ast_set_flag(p1, FLAG_P2P_NEED_DTMF);
04422       audio_p1_res = AST_RTP_TRY_PARTIAL;
04423    }
04424 
04425    /* If both sides are not using the same method of DTMF transmission 
04426     * (ie: one is RFC2833, other is INFO... then we can not do direct media. 
04427     * --------------------------------------------------
04428     * | DTMF Mode |  HAS_DTMF  |  Accepts Begin Frames |
04429     * |-----------|------------|-----------------------|
04430     * | Inband    | False      | True                  |
04431     * | RFC2833   | True       | True                  |
04432     * | SIP INFO  | False      | False                 |
04433     * --------------------------------------------------
04434     * However, if DTMF from both channels is being monitored by the core, then
04435     * we can still do packet-to-packet bridging, because passing through the 
04436     * core will handle DTMF mode translation.
04437     */
04438    if ((ast_test_flag(p0, FLAG_HAS_DTMF) != ast_test_flag(p1, FLAG_HAS_DTMF)) ||
04439       (!c0->tech->send_digit_begin != !c1->tech->send_digit_begin)) {
04440       if (!ast_test_flag(p0, FLAG_P2P_NEED_DTMF) || !ast_test_flag(p1, FLAG_P2P_NEED_DTMF)) {
04441          ast_channel_unlock(c0);
04442          ast_channel_unlock(c1);
04443          return AST_BRIDGE_FAILED_NOWARN;
04444       }
04445       audio_p0_res = AST_RTP_TRY_PARTIAL;
04446       audio_p1_res = AST_RTP_TRY_PARTIAL;
04447    }
04448 
04449    /* If we need to feed frames into the core don't do a P2P bridge */
04450    if ((audio_p0_res == AST_RTP_TRY_PARTIAL && ast_test_flag(p0, FLAG_P2P_NEED_DTMF)) ||
04451        (audio_p1_res == AST_RTP_TRY_PARTIAL && ast_test_flag(p1, FLAG_P2P_NEED_DTMF))) {
04452       ast_channel_unlock(c0);
04453       ast_channel_unlock(c1);
04454       return AST_BRIDGE_FAILED_NOWARN;
04455    }
04456 
04457    /* Get codecs from both sides */
04458    codec0 = pr0->get_codec ? pr0->get_codec(c0) : 0;
04459    codec1 = pr1->get_codec ? pr1->get_codec(c1) : 0;
04460    if (codec0 && codec1 && !(codec0 & codec1)) {
04461       /* Hey, we can't do native bridging if both parties speak different codecs */
04462       ast_debug(3, "Channel codec0 = %d is not codec1 = %d, cannot native bridge in RTP.\n", codec0, codec1);
04463       ast_channel_unlock(c0);
04464       ast_channel_unlock(c1);
04465       return AST_BRIDGE_FAILED_NOWARN;
04466    }
04467 
04468    /* If either side can only do a partial bridge, then don't try for a true native bridge */
04469    if (audio_p0_res == AST_RTP_TRY_PARTIAL || audio_p1_res == AST_RTP_TRY_PARTIAL) {
04470       struct ast_format_list fmt0, fmt1;
04471 
04472       /* In order to do Packet2Packet bridging both sides must be in the same rawread/rawwrite */
04473       if (c0->rawreadformat != c1->rawwriteformat || c1->rawreadformat != c0->rawwriteformat) {
04474          ast_debug(1, "Cannot packet2packet bridge - raw formats are incompatible\n");
04475          ast_channel_unlock(c0);
04476          ast_channel_unlock(c1);
04477          return AST_BRIDGE_FAILED_NOWARN;
04478       }
04479       /* They must also be using the same packetization */
04480       fmt0 = ast_codec_pref_getsize(&p0->pref, c0->rawreadformat);
04481       fmt1 = ast_codec_pref_getsize(&p1->pref, c1->rawreadformat);
04482       if (fmt0.cur_ms != fmt1.cur_ms) {
04483          ast_debug(1, "Cannot packet2packet bridge - packetization settings prevent it\n");
04484          ast_channel_unlock(c0);
04485          ast_channel_unlock(c1);
04486          return AST_BRIDGE_FAILED_NOWARN;
04487       }
04488 
04489       ast_verb(3, "Packet2Packet bridging %s and %s\n", c0->name, c1->name);
04490       res = bridge_p2p_loop(c0, c1, p0, p1, timeoutms, flags, fo, rc, pvt0, pvt1);
04491    } else {
04492       ast_verb(3, "Native bridging %s and %s\n", c0->name, c1->name);
04493       res = bridge_native_loop(c0, c1, p0, p1, vp0, vp1, tp0, tp1, pr0, pr1, codec0, codec1, timeoutms, flags, fo, rc, pvt0, pvt1);
04494    }
04495 
04496    return res;
04497 }

int ast_rtp_codec_getformat ( int  pt  ) 

get format from predefined dynamic payload format

Definition at line 3738 of file rtp.c.

References rtpPayloadType::code, and MAX_RTP_PT.

Referenced by process_sdp().

03739 {
03740    if (pt < 0 || pt > MAX_RTP_PT)
03741       return 0; /* bogus payload type */
03742 
03743    if (static_RTP_PT[pt].isAstFormat)
03744       return static_RTP_PT[pt].code;
03745    else
03746       return 0;
03747 }

struct ast_codec_pref* ast_rtp_codec_getpref ( struct ast_rtp rtp  )  [read]

Get codec preference.

Definition at line 3733 of file rtp.c.

References ast_rtp::pref.

Referenced by add_codec_to_sdp(), and process_sdp().

03734 {
03735    return &rtp->pref;
03736 }

void ast_rtp_codec_setpref ( struct ast_rtp rtp,
struct ast_codec_pref prefs 
)

Set codec preference.

Definition at line 3687 of file rtp.c.

References ast_codec_pref_getsize(), ast_log(), ast_smoother_new(), ast_smoother_reconfigure(), ast_smoother_set_flags(), ast_format_list::cur_ms, ast_format_list::flags, ast_format_list::fr_len, ast_format_list::inc_ms, ast_rtp::lasttxformat, LOG_DEBUG, LOG_WARNING, option_debug, ast_rtp::pref, and ast_rtp::smoother.

Referenced by __oh323_rtp_create(), check_peer_ok(), create_addr_from_peer(), gtalk_new(), jingle_new(), process_sdp(), register_verify(), set_peer_capabilities(), sip_alloc(), start_rtp(), and transmit_response_with_sdp().

03688 {
03689    struct ast_format_list current_format_old, current_format_new;
03690 
03691    /* if no packets have been sent through this session yet, then
03692     *  changing preferences does not require any extra work
03693     */
03694    if (rtp->lasttxformat == 0) {
03695       rtp->pref = *prefs;
03696       return;
03697    }
03698 
03699    current_format_old = ast_codec_pref_getsize(&rtp->pref, rtp->lasttxformat);
03700 
03701    rtp->pref = *prefs;
03702 
03703    current_format_new = ast_codec_pref_getsize(&rtp->pref, rtp->lasttxformat);
03704 
03705    /* if the framing desired for the current format has changed, we may have to create
03706     * or adjust the smoother for this session
03707     */
03708    if ((current_format_new.inc_ms != 0) &&
03709        (current_format_new.cur_ms != current_format_old.cur_ms)) {
03710       int new_size = (current_format_new.cur_ms * current_format_new.fr_len) / current_format_new.inc_ms;
03711 
03712       if (rtp->smoother) {
03713          ast_smoother_reconfigure(rtp->smoother, new_size);
03714          if (option_debug) {
03715             ast_log(LOG_DEBUG, "Adjusted smoother to %d ms and %d bytes\n", current_format_new.cur_ms, new_size);
03716          }
03717       } else {
03718          if (!(rtp->smoother = ast_smoother_new(new_size))) {
03719             ast_log(LOG_WARNING, "Unable to create smoother: format: %d ms: %d len: %d\n", rtp->lasttxformat, current_format_new.cur_ms, new_size);
03720             return;
03721          }
03722          if (current_format_new.flags) {
03723             ast_smoother_set_flags(rtp->smoother, current_format_new.flags);
03724          }
03725          if (option_debug) {
03726             ast_log(LOG_DEBUG, "Created smoother: format: %d ms: %d len: %d\n", rtp->lasttxformat, current_format_new.cur_ms, new_size);
03727          }
03728       }
03729    }
03730 
03731 }

void ast_rtp_destroy ( struct ast_rtp rtp  ) 

Destroy RTP session

Definition at line 3017 of file rtp.c.

References ast_free, ast_io_remove(), ast_mutex_destroy(), AST_SCHED_DEL, ast_smoother_free(), ast_verbose, EVENT_FLAG_REPORTING, ast_rtcp::expected_prior, ast_rtp::io, ast_rtp::ioid, manager_event, ast_rtcp::received_prior, ast_rtcp::reported_jitter, ast_rtcp::reported_lost, ast_rtcp::rr_count, ast_rtp::rtcp, rtcp_debug_test_addr(), ast_rtcp::rtt, ast_rtp::rxcount, ast_rtp::rxjitter, ast_rtp::rxtransit, ast_rtcp::s, ast_rtp::s, ast_rtp::sched, ast_rtcp::schedid, ast_rtp::smoother, ast_rtcp::sr_count, ast_rtp::ssrc, ast_rtp::them, ast_rtp::themssrc, and ast_rtp::txcount.

Referenced by __oh323_destroy(), __sip_destroy(), check_peer_ok(), cleanup_connection(), create_addr_from_peer(), destroy_endpoint(), gtalk_free_pvt(), jingle_free_pvt(), mgcp_hangup(), oh323_alloc(), skinny_hangup(), start_rtp(), unalloc_sub(), and unistim_hangup().

03018 {
03019    if (rtcp_debug_test_addr(&rtp->them) || rtcpstats) {
03020       /*Print some info on the call here */
03021       ast_verbose("  RTP-stats\n");
03022       ast_verbose("* Our Receiver:\n");
03023       ast_verbose("  SSRC:     %u\n", rtp->themssrc);
03024       ast_verbose("  Received packets: %u\n", rtp->rxcount);
03025       ast_verbose("  Lost packets:   %u\n", rtp->rtcp ? (rtp->rtcp->expected_prior - rtp->rtcp->received_prior) : 0);
03026       ast_verbose("  Jitter:      %.4f\n", rtp->rxjitter);
03027       ast_verbose("  Transit:     %.4f\n", rtp->rxtransit);
03028       ast_verbose("  RR-count:    %u\n", rtp->rtcp ? rtp->rtcp->rr_count : 0);
03029       ast_verbose("* Our Sender:\n");
03030       ast_verbose("  SSRC:     %u\n", rtp->ssrc);
03031       ast_verbose("  Sent packets:   %u\n", rtp->txcount);
03032       ast_verbose("  Lost packets:   %u\n", rtp->rtcp ? rtp->rtcp->reported_lost : 0);
03033       ast_verbose("  Jitter:      %u\n", rtp->rtcp ? (rtp->rtcp->reported_jitter / (unsigned int)65536.0) : 0);
03034       ast_verbose("  SR-count:    %u\n", rtp->rtcp ? rtp->rtcp->sr_count : 0);
03035       ast_verbose("  RTT:      %f\n", rtp->rtcp ? rtp->rtcp->rtt : 0);
03036    }
03037 
03038    manager_event(EVENT_FLAG_REPORTING, "RTPReceiverStat", "SSRC: %u\r\n"
03039                    "ReceivedPackets: %u\r\n"
03040                    "LostPackets: %u\r\n"
03041                    "Jitter: %.4f\r\n"
03042                    "Transit: %.4f\r\n"
03043                    "RRCount: %u\r\n",
03044                    rtp->themssrc,
03045                    rtp->rxcount,
03046                    rtp->rtcp ? (rtp->rtcp->expected_prior - rtp->rtcp->received_prior) : 0,
03047                    rtp->rxjitter,
03048                    rtp->rxtransit,
03049                    rtp->rtcp ? rtp->rtcp->rr_count : 0);
03050    manager_event(EVENT_FLAG_REPORTING, "RTPSenderStat", "SSRC: %u\r\n"
03051                    "SentPackets: %u\r\n"
03052                    "LostPackets: %u\r\n"
03053                    "Jitter: %u\r\n"
03054                    "SRCount: %u\r\n"
03055                    "RTT: %f\r\n",
03056                    rtp->ssrc,
03057                    rtp->txcount,
03058                    rtp->rtcp ? rtp->rtcp->reported_lost : 0,
03059                    rtp->rtcp ? rtp->rtcp->reported_jitter : 0,
03060                    rtp->rtcp ? rtp->rtcp->sr_count : 0,
03061                    rtp->rtcp ? rtp->rtcp->rtt : 0);
03062    if (rtp->smoother)
03063       ast_smoother_free(rtp->smoother);
03064    if (rtp->ioid)
03065       ast_io_remove(rtp->io, rtp->ioid);
03066    if (rtp->s > -1)
03067       close(rtp->s);
03068    if (rtp->rtcp) {
03069       AST_SCHED_DEL(rtp->sched, rtp->rtcp->schedid);
03070       close(rtp->rtcp->s);
03071       ast_free(rtp->rtcp);
03072       rtp->rtcp=NULL;
03073    }
03074 #ifdef P2P_INTENSE
03075    ast_mutex_destroy(&rtp->bridge_lock);
03076 #endif
03077    ast_free(rtp);
03078 }

int ast_rtp_early_bridge ( struct ast_channel c0,
struct ast_channel c1 
)

If possible, create an early bridge directly between the devices without having to send a re-invite later.

Definition at line 2076 of file rtp.c.

References ast_channel_lock, ast_channel_trylock, ast_channel_unlock, ast_debug, ast_log(), AST_RTP_GET_FAILED, AST_RTP_TRY_NATIVE, ast_test_flag, FLAG_NAT_ACTIVE, ast_rtp_protocol::get_codec, get_proto(), ast_rtp_protocol::get_rtp_info, ast_rtp_protocol::get_trtp_info, ast_rtp_protocol::get_vrtp_info, LOG_WARNING, and ast_rtp_protocol::set_rtp_peer.

02077 {
02078    struct ast_rtp *destp = NULL, *srcp = NULL;     /* Audio RTP Channels */
02079    struct ast_rtp *vdestp = NULL, *vsrcp = NULL;      /* Video RTP channels */
02080    struct ast_rtp *tdestp = NULL, *tsrcp = NULL;      /* Text RTP channels */
02081    struct ast_rtp_protocol *destpr = NULL, *srcpr = NULL;
02082    enum ast_rtp_get_result audio_dest_res = AST_RTP_GET_FAILED, video_dest_res = AST_RTP_GET_FAILED, text_dest_res = AST_RTP_GET_FAILED;
02083    enum ast_rtp_get_result audio_src_res = AST_RTP_GET_FAILED, video_src_res = AST_RTP_GET_FAILED, text_src_res = AST_RTP_GET_FAILED;
02084    int srccodec, destcodec, nat_active = 0;
02085 
02086    /* Lock channels */
02087    ast_channel_lock(c0);
02088    if (c1) {
02089       while (ast_channel_trylock(c1)) {
02090          ast_channel_unlock(c0);
02091          usleep(1);
02092          ast_channel_lock(c0);
02093       }
02094    }
02095 
02096    /* Find channel driver interfaces */
02097    destpr = get_proto(c0);
02098    if (c1)
02099       srcpr = get_proto(c1);
02100    if (!destpr) {
02101       ast_debug(1, "Channel '%s' has no RTP, not doing anything\n", c0->name);
02102       ast_channel_unlock(c0);
02103       if (c1)
02104          ast_channel_unlock(c1);
02105       return -1;
02106    }
02107    if (!srcpr) {
02108       ast_debug(1, "Channel '%s' has no RTP, not doing anything\n", c1 ? c1->name : "<unspecified>");
02109       ast_channel_unlock(c0);
02110       if (c1)
02111          ast_channel_unlock(c1);
02112       return -1;
02113    }
02114 
02115    /* Get audio, video  and text interface (if native bridge is possible) */
02116    audio_dest_res = destpr->get_rtp_info(c0, &destp);
02117    video_dest_res = destpr->get_vrtp_info ? destpr->get_vrtp_info(c0, &vdestp) : AST_RTP_GET_FAILED;
02118    text_dest_res = destpr->get_trtp_info ? destpr->get_trtp_info(c0, &tdestp) : AST_RTP_GET_FAILED;
02119    if (srcpr) {
02120       audio_src_res = srcpr->get_rtp_info(c1, &srcp);
02121       video_src_res = srcpr->get_vrtp_info ? srcpr->get_vrtp_info(c1, &vsrcp) : AST_RTP_GET_FAILED;
02122       text_src_res = srcpr->get_trtp_info ? srcpr->get_trtp_info(c1, &tsrcp) : AST_RTP_GET_FAILED;
02123    }
02124 
02125    /* Check if bridge is still possible (In SIP canreinvite=no stops this, like NAT) */
02126    if (audio_dest_res != AST_RTP_TRY_NATIVE || (video_dest_res != AST_RTP_GET_FAILED && video_dest_res != AST_RTP_TRY_NATIVE)) {
02127       /* Somebody doesn't want to play... */
02128       ast_channel_unlock(c0);
02129       if (c1)
02130          ast_channel_unlock(c1);
02131       return -1;
02132    }
02133    if (audio_src_res == AST_RTP_TRY_NATIVE && (video_src_res == AST_RTP_GET_FAILED || video_src_res == AST_RTP_TRY_NATIVE) && srcpr->get_codec)
02134       srccodec = srcpr->get_codec(c1);
02135    else
02136       srccodec = 0;
02137    if (audio_dest_res == AST_RTP_TRY_NATIVE && (video_dest_res == AST_RTP_GET_FAILED || video_dest_res == AST_RTP_TRY_NATIVE) && destpr->get_codec)
02138       destcodec = destpr->get_codec(c0);
02139    else
02140       destcodec = 0;
02141    /* Ensure we have at least one matching codec */
02142    if (srcp && !(srccodec & destcodec)) {
02143       ast_channel_unlock(c0);
02144       ast_channel_unlock(c1);
02145       return 0;
02146    }
02147    /* Consider empty media as non-existent */
02148    if (audio_src_res == AST_RTP_TRY_NATIVE && !srcp->them.sin_addr.s_addr)
02149       srcp = NULL;
02150    if (srcp && (srcp->nat || ast_test_flag(srcp, FLAG_NAT_ACTIVE)))
02151       nat_active = 1;
02152    /* Bridge media early */
02153    if (destpr->set_rtp_peer(c0, srcp, vsrcp, tsrcp, srccodec, nat_active))
02154       ast_log(LOG_WARNING, "Channel '%s' failed to setup early bridge to '%s'\n", c0->name, c1 ? c1->name : "<unspecified>");
02155    ast_channel_unlock(c0);
02156    if (c1)
02157       ast_channel_unlock(c1);
02158    ast_debug(1, "Setting early bridge SDP of '%s' with that of '%s'\n", c0->name, c1 ? c1->name : "<unspecified>");
02159    return 0;
02160 }

int ast_rtp_fd ( struct ast_rtp rtp  ) 

Definition at line 723 of file rtp.c.

References ast_rtp::s.

Referenced by __oh323_new(), __oh323_rtp_create(), __oh323_update_info(), gtalk_new(), jingle_new(), mgcp_new(), p2p_callback_disable(), sip_new(), skinny_new(), start_rtp(), and unistim_new().

00724 {
00725    return rtp->s;
00726 }

struct ast_rtp* ast_rtp_get_bridged ( struct ast_rtp rtp  )  [read]

Definition at line 2658 of file rtp.c.

References ast_rtp::bridged, rtp_bridge_lock(), and rtp_bridge_unlock().

Referenced by __sip_destroy(), ast_rtp_read(), and dialog_needdestroy().

02659 {
02660    struct ast_rtp *bridged = NULL;
02661 
02662    rtp_bridge_lock(rtp);
02663    bridged = rtp->bridged;
02664    rtp_bridge_unlock(rtp);
02665 
02666    return bridged;
02667 }

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

Return the union of all of the codecs that were set by rtp_set...() calls They're returned as two distinct sets: AST_FORMATs, and AST_RTPs.

Definition at line 2298 of file rtp.c.

References rtpPayloadType::code, ast_rtp::current_RTP_PT, rtpPayloadType::isAstFormat, MAX_RTP_PT, rtp_bridge_lock(), and rtp_bridge_unlock().

Referenced by gtalk_is_answered(), gtalk_newcall(), and process_sdp().

02300 {
02301    int pt;
02302    
02303    rtp_bridge_lock(rtp);
02304    
02305    *astFormats = *nonAstFormats = 0;
02306    for (pt = 0; pt < MAX_RTP_PT; ++pt) {
02307       if (rtp->current_RTP_PT[pt].isAstFormat) {
02308          *astFormats |= rtp->current_RTP_PT[pt].code;
02309       } else {
02310          *nonAstFormats |= rtp->current_RTP_PT[pt].code;
02311       }
02312    }
02313 
02314    rtp_bridge_unlock(rtp);
02315 }

int ast_rtp_get_peer ( struct ast_rtp rtp,
struct sockaddr_in *  them 
)

Definition at line 2640 of file rtp.c.

References ast_rtp::them.

Referenced by acf_channel_read(), add_sdp(), bridge_native_loop(), check_rtp_timeout(), gtalk_update_stun(), oh323_set_rtp_peer(), process_sdp(), sip_set_rtp_peer(), skinny_set_rtp_peer(), and transmit_modify_with_sdp().

02641 {
02642    if ((them->sin_family != AF_INET) ||
02643       (them->sin_port != rtp->them.sin_port) ||
02644       (them->sin_addr.s_addr != rtp->them.sin_addr.s_addr)) {
02645       them->sin_family = AF_INET;
02646       them->sin_port = rtp->them.sin_port;
02647       them->sin_addr = rtp->them.sin_addr;
02648       return 1;
02649    }
02650    return 0;
02651 }

int ast_rtp_get_qos ( struct ast_rtp rtp,
const char *  qos,
char *  buf,
unsigned int  buflen 
)

Get QOS stats on a RTP channel.

Since:
1.6.1

Definition at line 2779 of file rtp.c.

References __ast_rtp_get_qos().

Referenced by acf_channel_read().

02780 {
02781    double value;
02782    int found;
02783 
02784    value = __ast_rtp_get_qos(rtp, qos, &found);
02785 
02786    if (!found)
02787       return -1;
02788 
02789    snprintf(buf, buflen, "%.0lf", value);
02790 
02791    return 0;
02792 }

unsigned int ast_rtp_get_qosvalue ( struct ast_rtp rtp,
enum ast_rtp_qos_vars  value 
)

Return RTP and RTCP QoS values.

Since:
1.6.1

Get QoS values from RTP and RTCP data (used in "sip show channelstats")

Definition at line 2713 of file rtp.c.

References ast_log(), AST_RTP_RTT, AST_RTP_RXCOUNT, AST_RTP_RXJITTER, AST_RTP_RXPLOSS, AST_RTP_TXCOUNT, AST_RTP_TXJITTER, AST_RTP_TXPLOSS, ast_rtcp::expected_prior, LOG_DEBUG, option_debug, ast_rtcp::received_prior, ast_rtcp::reported_jitter, ast_rtcp::reported_lost, ast_rtp::rtcp, ast_rtcp::rtt, ast_rtp::rxcount, ast_rtp::rxjitter, and ast_rtp::txcount.

Referenced by show_chanstats_cb().

02714 {
02715    if (rtp == NULL) {
02716       if (option_debug > 1)
02717          ast_log(LOG_DEBUG, "NO RTP Structure? Kidding me? \n");
02718       return 0;
02719    }
02720    if (option_debug > 1 && rtp->rtcp == NULL) {
02721       ast_log(LOG_DEBUG, "NO RTCP structure. Maybe in RTP p2p bridging mode? \n");
02722    }
02723 
02724    switch (value) {
02725    case AST_RTP_TXCOUNT:
02726       return (unsigned int) rtp->txcount;
02727    case AST_RTP_RXCOUNT:
02728       return (unsigned int) rtp->rxcount;
02729    case AST_RTP_TXJITTER:
02730       return (unsigned int) (rtp->rxjitter * 100.0);
02731    case AST_RTP_RXJITTER:
02732       return (unsigned int) (rtp->rtcp ? (rtp->rtcp->reported_jitter / (unsigned int) 65536.0) : 0);
02733    case AST_RTP_RXPLOSS:
02734       return rtp->rtcp ? (rtp->rtcp->expected_prior - rtp->rtcp->received_prior) : 0;
02735    case AST_RTP_TXPLOSS:
02736       return rtp->rtcp ? rtp->rtcp->reported_lost : 0;
02737    case AST_RTP_RTT:
02738       return (unsigned int) (rtp->rtcp ? (rtp->rtcp->rtt * 100) : 0);
02739    }
02740    return 0;   /* To make the compiler happy */
02741 }

char* ast_rtp_get_quality ( struct ast_rtp rtp,
struct ast_rtp_quality qual,
enum ast_rtp_quality_type  qtype 
)

Return RTCP quality string.

Parameters:
rtp An rtp structure to get qos information about.
qual An (optional) rtp quality structure that will be filled with the quality information described in the ast_rtp_quality structure. This structure is not dependent on any qtype, so a call for any type of information would yield the same results because ast_rtp_quality is not a data type specific to any qos type.
qtype The quality type you'd like, default should be RTPQOS_SUMMARY which returns basic information about the call. The return from RTPQOS_SUMMARY is basically ast_rtp_quality in a string. The other types are RTPQOS_JITTER, RTPQOS_LOSS and RTPQOS_RTT which will return more specific statistics.
Version:
1.6.1 added qtype parameter

Definition at line 2986 of file rtp.c.

References __ast_rtp_get_quality(), __ast_rtp_get_quality_jitter(), __ast_rtp_get_quality_loss(), __ast_rtp_get_quality_rtt(), ast_rtcp::expected_prior, ast_rtp_quality::local_count, ast_rtp_quality::local_jitter, ast_rtp_quality::local_lostpackets, ast_rtp_quality::local_ssrc, ast_rtcp::received_prior, ast_rtp_quality::remote_count, ast_rtp_quality::remote_jitter, ast_rtp_quality::remote_lostpackets, ast_rtp_quality::remote_ssrc, ast_rtcp::reported_jitter, ast_rtcp::reported_lost, ast_rtp::rtcp, RTPQOS_JITTER, RTPQOS_LOSS, RTPQOS_RTT, RTPQOS_SUMMARY, ast_rtcp::rtt, ast_rtp_quality::rtt, ast_rtp::rxcount, ast_rtp::rxjitter, ast_rtp::ssrc, ast_rtp::themssrc, and ast_rtp::txcount.

Referenced by acf_channel_read(), ast_rtp_set_vars(), handle_request_bye(), and sip_hangup().

02987 {
02988    if (qual && rtp) {
02989       qual->local_ssrc   = rtp->ssrc;
02990       qual->local_jitter = rtp->rxjitter;
02991       qual->local_count  = rtp->rxcount;
02992       qual->remote_ssrc  = rtp->themssrc;
02993       qual->remote_count = rtp->txcount;
02994 
02995       if (rtp->rtcp) {
02996          qual->local_lostpackets  = rtp->rtcp->expected_prior - rtp->rtcp->received_prior;
02997          qual->remote_lostpackets = rtp->rtcp->reported_lost;
02998          qual->remote_jitter      = rtp->rtcp->reported_jitter / 65536.0;
02999          qual->rtt                = rtp->rtcp->rtt;
03000       }
03001    }
03002 
03003    switch (qtype) {
03004    case RTPQOS_SUMMARY:
03005       return __ast_rtp_get_quality(rtp);
03006    case RTPQOS_JITTER:
03007       return __ast_rtp_get_quality_jitter(rtp);
03008    case RTPQOS_LOSS:
03009       return __ast_rtp_get_quality_loss(rtp);
03010    case RTPQOS_RTT:
03011       return __ast_rtp_get_quality_rtt(rtp);
03012    }
03013 
03014    return NULL;
03015 }

int ast_rtp_get_rtpholdtimeout ( struct ast_rtp rtp  ) 

Get rtp hold timeout.

Definition at line 783 of file rtp.c.

References ast_rtp::rtpholdtimeout, and ast_rtp::rtptimeout.

Referenced by check_rtp_timeout().

00784 {
00785    if (rtp->rtptimeout < 0)   /* We're not checking, but remembering the setting (during T.38 transmission) */
00786       return 0;
00787    return rtp->rtpholdtimeout;
00788 }

int ast_rtp_get_rtpkeepalive ( struct ast_rtp rtp  ) 

Get RTP keepalive interval.

Definition at line 791 of file rtp.c.

References ast_rtp::rtpkeepalive.

Referenced by check_rtp_timeout().

00792 {
00793    return rtp->rtpkeepalive;
00794 }

int ast_rtp_get_rtptimeout ( struct ast_rtp rtp  ) 

Get rtp timeout.

Definition at line 775 of file rtp.c.

References ast_rtp::rtptimeout.

Referenced by check_rtp_timeout().

00776 {
00777    if (rtp->rtptimeout < 0)   /* We're not checking, but remembering the setting (during T.38 transmission) */
00778       return 0;
00779    return rtp->rtptimeout;
00780 }

void ast_rtp_get_us ( struct ast_rtp rtp,
struct sockaddr_in *  us 
)
int ast_rtp_getnat ( struct ast_rtp rtp  ) 

Definition at line 811 of file rtp.c.

References ast_test_flag, and FLAG_NAT_ACTIVE.

Referenced by sip_get_rtp_peer().

00812 {
00813    return ast_test_flag(rtp, FLAG_NAT_ACTIVE);
00814 }

void ast_rtp_init ( void   ) 

Initialize the RTP system in Asterisk.

Definition at line 4885 of file rtp.c.

References __ast_rtp_reload(), and ast_cli_register_multiple().

Referenced by main().

04886 {
04887    ast_cli_register_multiple(cli_rtp, sizeof(cli_rtp) / sizeof(struct ast_cli_entry));
04888    __ast_rtp_reload(0);
04889 }

int ast_rtp_lookup_code ( struct ast_rtp rtp,
int  isAstFormat,
int  code 
)

Looks up an RTP code out of our *static* outbound list.

Definition at line 2339 of file rtp.c.

References rtpPayloadType::code, ast_rtp::current_RTP_PT, rtpPayloadType::isAstFormat, MAX_RTP_PT, rtp_bridge_lock(), rtp_bridge_unlock(), 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_answer(), add_codec_to_sdp(), add_noncodec_to_sdp(), add_sdp(), add_tcodec_to_sdp(), add_vcodec_to_sdp(), ast_rtp_sendcng(), ast_rtp_senddigit_begin(), ast_rtp_write(), bridge_p2p_rtp_write(), and start_rtp().

02340 {
02341    int pt = 0;
02342 
02343    rtp_bridge_lock(rtp);
02344 
02345    if (isAstFormat == rtp->rtp_lookup_code_cache_isAstFormat &&
02346       code == rtp->rtp_lookup_code_cache_code) {
02347       /* Use our cached mapping, to avoid the overhead of the loop below */
02348       pt = rtp->rtp_lookup_code_cache_result;
02349       rtp_bridge_unlock(rtp);
02350       return pt;
02351    }
02352 
02353    /* Check the dynamic list first */
02354    for (pt = 0; pt < MAX_RTP_PT; ++pt) {
02355       if (rtp->current_RTP_PT[pt].code == code && rtp->current_RTP_PT[pt].isAstFormat == isAstFormat) {
02356          rtp->rtp_lookup_code_cache_isAstFormat = isAstFormat;
02357          rtp->rtp_lookup_code_cache_code = code;
02358          rtp->rtp_lookup_code_cache_result = pt;
02359          rtp_bridge_unlock(rtp);
02360          return pt;
02361       }
02362    }
02363 
02364    /* Then the static list */
02365    for (pt = 0; pt < MAX_RTP_PT; ++pt) {
02366       if (static_RTP_PT[pt].code == code && static_RTP_PT[pt].isAstFormat == isAstFormat) {
02367          rtp->rtp_lookup_code_cache_isAstFormat = isAstFormat;
02368          rtp->rtp_lookup_code_cache_code = code;
02369          rtp->rtp_lookup_code_cache_result = pt;
02370          rtp_bridge_unlock(rtp);
02371          return pt;
02372       }
02373    }
02374 
02375    rtp_bridge_unlock(rtp);
02376 
02377    return -1;
02378 }

char* ast_rtp_lookup_mime_multiple ( char *  buf,
size_t  size,
const int  capability,
const int  isAstFormat,
enum ast_rtp_options  options 
)

Build a string of MIME subtype names from a capability list.

Definition at line 2399 of file rtp.c.

References ast_copy_string(), ast_rtp_lookup_mime_subtype(), AST_RTP_MAX, format, len(), and name.

Referenced by process_sdp().

02401 {
02402    int format;
02403    unsigned len;
02404    char *end = buf;
02405    char *start = buf;
02406 
02407    if (!buf || !size)
02408       return NULL;
02409 
02410    snprintf(end, size, "0x%x (", capability);
02411 
02412    len = strlen(end);
02413    end += len;
02414    size -= len;
02415    start = end;
02416 
02417    for (format = 1; format < AST_RTP_MAX; format <<= 1) {
02418       if (capability & format) {
02419          const char *name = ast_rtp_lookup_mime_subtype(isAstFormat, format, options);
02420 
02421          snprintf(end, size, "%s|", name);
02422          len = strlen(end);
02423          end += len;
02424          size -= len;
02425       }
02426    }
02427 
02428    if (start == end)
02429       ast_copy_string(start, "nothing)", size); 
02430    else if (size > 1)
02431       *(end -1) = ')';
02432    
02433    return buf;
02434 }

const char* ast_rtp_lookup_mime_subtype ( int  isAstFormat,
int  code,
enum ast_rtp_options  options 
)

Mapping an Asterisk code into a MIME subtype (string):.

Definition at line 2380 of file rtp.c.

References ARRAY_LEN, AST_FORMAT_G726_AAL2, AST_RTP_OPT_G726_NONSTANDARD, rtpPayloadType::code, mimeTypes, and payloadType.

Referenced by add_codec_to_sdp(), add_noncodec_to_sdp(), add_sdp(), add_tcodec_to_sdp(), add_vcodec_to_sdp(), ast_rtp_lookup_mime_multiple(), transmit_connect_with_sdp(), and transmit_modify_with_sdp().

02382 {
02383    unsigned int i;
02384 
02385    for (i = 0; i < ARRAY_LEN(mimeTypes); ++i) {
02386       if ((mimeTypes[i].payloadType.code == code) && (mimeTypes[i].payloadType.isAstFormat == isAstFormat)) {
02387          if (isAstFormat &&
02388              (code == AST_FORMAT_G726_AAL2) &&
02389              (options & AST_RTP_OPT_G726_NONSTANDARD))
02390             return "G726-32";
02391          else
02392             return mimeTypes[i].subtype;
02393       }
02394    }
02395 
02396    return "";
02397 }

struct rtpPayloadType ast_rtp_lookup_pt ( struct ast_rtp rtp,
int  pt 
) [read]

Mapping between RTP payload format codes and Asterisk codes:.

Definition at line 2317 of file rtp.c.

References rtpPayloadType::code, rtpPayloadType::isAstFormat, MAX_RTP_PT, rtp_bridge_lock(), and rtp_bridge_unlock().

Referenced by ast_rtp_read(), bridge_p2p_rtp_write(), and setup_rtp_connection().

02318 {
02319    struct rtpPayloadType result;
02320 
02321    result.isAstFormat = result.code = 0;
02322 
02323    if (pt < 0 || pt > MAX_RTP_PT) 
02324       return result; /* bogus payload type */
02325 
02326    /* Start with negotiated codecs */
02327    rtp_bridge_lock(rtp);
02328    result = rtp->current_RTP_PT[pt];
02329    rtp_bridge_unlock(rtp);
02330 
02331    /* If it doesn't exist, check our static RTP type list, just in case */
02332    if (!result.code) 
02333       result = static_RTP_PT[pt];
02334 
02335    return result;
02336 }

int ast_rtp_make_compatible ( struct ast_channel dest,
struct ast_channel src,
int  media 
)

Definition at line 2162 of file rtp.c.

References ast_channel_lock, ast_channel_trylock, ast_channel_unlock, ast_debug, ast_log(), AST_RTP_GET_FAILED, ast_rtp_pt_copy(), AST_RTP_TRY_NATIVE, ast_test_flag, FLAG_NAT_ACTIVE, ast_rtp_protocol::get_codec, get_proto(), ast_rtp_protocol::get_rtp_info, ast_rtp_protocol::get_trtp_info, ast_rtp_protocol::get_vrtp_info, LOG_WARNING, and ast_rtp_protocol::set_rtp_peer.

Referenced by dial_exec_full(), and do_forward().

02163 {
02164    struct ast_rtp *destp = NULL, *srcp = NULL;     /* Audio RTP Channels */
02165    struct ast_rtp *vdestp = NULL, *vsrcp = NULL;      /* Video RTP channels */
02166    struct ast_rtp *tdestp = NULL, *tsrcp = NULL;      /* Text RTP channels */
02167    struct ast_rtp_protocol *destpr = NULL, *srcpr = NULL;
02168    enum ast_rtp_get_result audio_dest_res = AST_RTP_GET_FAILED, video_dest_res = AST_RTP_GET_FAILED, text_dest_res = AST_RTP_GET_FAILED;
02169    enum ast_rtp_get_result audio_src_res = AST_RTP_GET_FAILED, video_src_res = AST_RTP_GET_FAILED, text_src_res = AST_RTP_GET_FAILED; 
02170    int srccodec, destcodec;
02171 
02172    /* Lock channels */
02173    ast_channel_lock(dest);
02174    while (ast_channel_trylock(src)) {
02175       ast_channel_unlock(dest);
02176       usleep(1);
02177       ast_channel_lock(dest);
02178    }
02179 
02180    /* Find channel driver interfaces */
02181    if (!(destpr = get_proto(dest))) {
02182       ast_debug(1, "Channel '%s' has no RTP, not doing anything\n", dest->name);
02183       ast_channel_unlock(dest);
02184       ast_channel_unlock(src);
02185       return 0;
02186    }
02187    if (!(srcpr = get_proto(src))) {
02188       ast_debug(1, "Channel '%s' has no RTP, not doing anything\n", src->name);
02189       ast_channel_unlock(dest);
02190       ast_channel_unlock(src);
02191       return 0;
02192    }
02193 
02194    /* Get audio and video interface (if native bridge is possible) */
02195    audio_dest_res = destpr->get_rtp_info(dest, &destp);
02196    video_dest_res = destpr->get_vrtp_info ? destpr->get_vrtp_info(dest, &vdestp) : AST_RTP_GET_FAILED;
02197    text_dest_res = destpr->get_trtp_info ? destpr->get_trtp_info(dest, &tdestp) : AST_RTP_GET_FAILED;
02198    audio_src_res = srcpr->get_rtp_info(src, &srcp);
02199    video_src_res = srcpr->get_vrtp_info ? srcpr->get_vrtp_info(src, &vsrcp) : AST_RTP_GET_FAILED;
02200    text_src_res = srcpr->get_trtp_info ? srcpr->get_trtp_info(src, &tsrcp) : AST_RTP_GET_FAILED;
02201 
02202    /* Ensure we have at least one matching codec */
02203    if (srcpr->get_codec)
02204       srccodec = srcpr->get_codec(src);
02205    else
02206       srccodec = 0;
02207    if (destpr->get_codec)
02208       destcodec = destpr->get_codec(dest);
02209    else
02210       destcodec = 0;
02211 
02212    /* Check if bridge is still possible (In SIP canreinvite=no stops this, like NAT) */
02213    if (audio_dest_res != AST_RTP_TRY_NATIVE || (video_dest_res != AST_RTP_GET_FAILED && video_dest_res != AST_RTP_TRY_NATIVE) || audio_src_res != AST_RTP_TRY_NATIVE || (video_src_res != AST_RTP_GET_FAILED && video_src_res != AST_RTP_TRY_NATIVE) || !(srccodec & destcodec)) {
02214       /* Somebody doesn't want to play... */
02215       ast_channel_unlock(dest);
02216       ast_channel_unlock(src);
02217       return 0;
02218    }
02219    ast_rtp_pt_copy(destp, srcp);
02220    if (vdestp && vsrcp)
02221       ast_rtp_pt_copy(vdestp, vsrcp);
02222    if (tdestp && tsrcp)
02223       ast_rtp_pt_copy(tdestp, tsrcp);
02224    if (media) {
02225       /* Bridge early */
02226       if (destpr->set_rtp_peer(dest, srcp, vsrcp, tsrcp, srccodec, ast_test_flag(srcp, FLAG_NAT_ACTIVE)))
02227          ast_log(LOG_WARNING, "Channel '%s' failed to setup early bridge to '%s'\n", dest->name, src->name);
02228    }
02229    ast_channel_unlock(dest);
02230    ast_channel_unlock(src);
02231    ast_debug(1, "Seeded SDP of '%s' with that of '%s'\n", dest->name, src->name);
02232    return 1;
02233 }

struct ast_rtp* ast_rtp_new ( struct sched_context sched,
struct io_context io,
int  rtcpenable,
int  callbackmode 
) [read]

Initializate a RTP session.

Parameters:
sched 
io 
rtcpenable 
callbackmode 
Returns:
A representation (structure) of an RTP session.

Definition at line 2594 of file rtp.c.

References ast_rtp_new_with_bindaddr().

02595 {
02596    struct in_addr ia;
02597 
02598    memset(&ia, 0, sizeof(ia));
02599    return ast_rtp_new_with_bindaddr(sched, io, rtcpenable, callbackmode, ia);
02600 }

void ast_rtp_new_init ( struct ast_rtp rtp  ) 

Initialize a new RTP structure.

reload rtp configuration

Definition at line 2485 of file rtp.c.

References ast_mutex_init(), ast_random(), ast_set_flag, FLAG_HAS_DTMF, ast_rtp::seqno, ast_rtp::ssrc, STRICT_RTP_LEARN, STRICT_RTP_OPEN, ast_rtp::strict_rtp_state, ast_rtp::them, and ast_rtp::us.

Referenced by ast_rtp_new_with_bindaddr(), and process_sdp().

02486 {
02487 #ifdef P2P_INTENSE
02488    ast_mutex_init(&rtp->bridge_lock);
02489 #endif
02490 
02491    rtp->them.sin_family = AF_INET;
02492    rtp->us.sin_family = AF_INET;
02493    rtp->ssrc = ast_random();
02494    rtp->seqno = ast_random() & 0xffff;
02495    ast_set_flag(rtp, FLAG_HAS_DTMF);
02496    rtp->strict_rtp_state = (strictrtp ? STRICT_RTP_LEARN : STRICT_RTP_OPEN);
02497 }

void ast_rtp_new_source ( struct ast_rtp rtp  ) 

Definition at line 2607 of file rtp.c.

References ast_rtp::set_marker_bit.

Referenced by mgcp_indicate(), oh323_indicate(), sip_answer(), sip_indicate(), sip_write(), and skinny_indicate().

02608 {
02609    if (rtp) {
02610       rtp->set_marker_bit = 1;
02611    }
02612    return;
02613 }

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().

Parameters:
sched 
io 
rtcpenable 
callbackmode 
in 
Returns:
A representation (structure) of an RTP session.

Definition at line 2499 of file rtp.c.

References ast_calloc, ast_free, ast_io_add(), AST_IO_IN, ast_log(), ast_random(), ast_rtcp_new(), ast_rtp_new_init(), ast_rtp_pt_default(), ast_set_flag, errno, FLAG_CALLBACK_MODE, ast_rtp::io, ast_rtp::ioid, LOG_ERROR, ast_rtp::rtcp, rtp_socket(), rtpread(), ast_rtcp::s, ast_rtp::s, ast_rtp::sched, ast_rtcp::us, and ast_rtp::us.

Referenced by __oh323_rtp_create(), ast_rtp_new(), gtalk_alloc(), jingle_alloc(), sip_alloc(), and start_rtp().

02500 {
02501    struct ast_rtp *rtp;
02502    int x;
02503    int startplace;
02504    
02505    if (!(rtp = ast_calloc(1, sizeof(*rtp))))
02506       return NULL;
02507 
02508    ast_rtp_new_init(rtp);
02509 
02510    rtp->s = rtp_socket("RTP");
02511    if (rtp->s < 0)
02512       goto fail;
02513    if (sched && rtcpenable) {
02514       rtp->sched = sched;
02515       rtp->rtcp = ast_rtcp_new();
02516    }
02517    
02518    /*
02519     * Try to bind the RTP port, x, and possibly the RTCP port, x+1 as well.
02520     * Start from a random (even, by RTP spec) port number, and
02521     * iterate until success or no ports are available.
02522     * Note that the requirement of RTP port being even, or RTCP being the
02523     * next one, cannot be enforced in presence of a NAT box because the
02524     * mapping is not under our control.
02525     */
02526    x = (rtpend == rtpstart) ? rtpstart : (ast_random() % (rtpend - rtpstart)) + rtpstart;
02527    x = x & ~1;    /* make it an even number */
02528    startplace = x;      /* remember the starting point */
02529    /* this is constant across the loop */
02530    rtp->us.sin_addr = addr;
02531    if (rtp->rtcp)
02532       rtp->rtcp->us.sin_addr = addr;
02533    for (;;) {
02534       rtp->us.sin_port = htons(x);
02535       if (!bind(rtp->s, (struct sockaddr *)&rtp->us, sizeof(rtp->us))) {
02536          /* bind succeeded, if no rtcp then we are done */
02537          if (!rtp->rtcp)
02538             break;
02539          /* have rtcp, try to bind it */
02540          rtp->rtcp->us.sin_port = htons(x + 1);
02541          if (!bind(rtp->rtcp->s, (struct sockaddr *)&rtp->rtcp->us, sizeof(rtp->rtcp->us)))
02542             break;   /* success again, we are really done */
02543          /*
02544           * RTCP bind failed, so close and recreate the
02545           * already bound RTP socket for the next round.
02546           */
02547          close(rtp->s);
02548          rtp->s = rtp_socket("RTP");
02549          if (rtp->s < 0)
02550             goto fail;
02551       }
02552       /*
02553        * If we get here, there was an error in one of the bind()
02554        * calls, so make sure it is nothing unexpected.
02555        */
02556       if (errno != EADDRINUSE) {
02557          /* We got an error that wasn't expected, abort! */
02558          ast_log(LOG_ERROR, "Unexpected bind error: %s\n", strerror(errno));
02559          goto fail;
02560       }
02561       /*
02562        * One of the ports is in use. For the next iteration,
02563        * increment by two and handle wraparound.
02564        * If we reach the starting point, then declare failure.
02565        */
02566       x += 2;
02567       if (x > rtpend)
02568          x = (rtpstart + 1) & ~1;
02569       if (x == startplace) {
02570          ast_log(LOG_ERROR, "No RTP ports remaining. Can't setup media stream for this call.\n");
02571          goto fail;
02572       }
02573    }
02574    rtp->sched = sched;
02575    rtp->io = io;
02576    if (callbackmode) {
02577       rtp->ioid = ast_io_add(rtp->io, rtp->s, rtpread, AST_IO_IN, rtp);
02578       ast_set_flag(rtp, FLAG_CALLBACK_MODE);
02579    }
02580    ast_rtp_pt_default(rtp);
02581    return rtp;
02582 
02583 fail:
02584    if (rtp->s >= 0)
02585       close(rtp->s);
02586    if (rtp->rtcp) {
02587       close(rtp->rtcp->s);
02588       ast_free(rtp->rtcp);
02589    }
02590    ast_free(rtp);
02591    return NULL;
02592 }

int ast_rtp_proto_register ( struct ast_rtp_protocol proto  ) 

Register an RTP channel client.

Definition at line 3844 of file rtp.c.

References ast_log(), AST_RWLIST_INSERT_HEAD, AST_RWLIST_TRAVERSE, AST_RWLIST_UNLOCK, AST_RWLIST_WRLOCK, ast_rtp_protocol::list, LOG_WARNING, and ast_rtp_protocol::type.

Referenced by load_module().

03845 {
03846    struct ast_rtp_protocol *cur;
03847 
03848    AST_RWLIST_WRLOCK(&protos);
03849    AST_RWLIST_TRAVERSE(&protos, cur, list) { 
03850       if (!strcmp(cur->type, proto->type)) {
03851          ast_log(LOG_WARNING, "Tried to register same protocol '%s' twice\n", cur->type);
03852          AST_RWLIST_UNLOCK(&protos);
03853          return -1;
03854       }
03855    }
03856    AST_RWLIST_INSERT_HEAD(&protos, proto, list);
03857    AST_RWLIST_UNLOCK(&protos);
03858    
03859    return 0;
03860 }

void ast_rtp_proto_unregister ( struct ast_rtp_protocol proto  ) 

Unregister an RTP channel client.

Definition at line 3836 of file rtp.c.

References AST_RWLIST_REMOVE, AST_RWLIST_UNLOCK, and AST_RWLIST_WRLOCK.

Referenced by load_module(), and unload_module().

03837 {
03838    AST_RWLIST_WRLOCK(&protos);
03839    AST_RWLIST_REMOVE(&protos, proto, list);
03840    AST_RWLIST_UNLOCK(&protos);
03841 }

void ast_rtp_pt_clear ( struct ast_rtp rtp  ) 

Setting RTP payload types from lines in a SDP description:.

Definition at line 2000 of file rtp.c.

References rtpPayloadType::code, ast_rtp::current_RTP_PT, rtpPayloadType::isAstFormat, MAX_RTP_PT, rtp_bridge_lock(), rtp_bridge_unlock(), ast_rtp::rtp_lookup_code_cache_code, ast_rtp::rtp_lookup_code_cache_isAstFormat, and ast_rtp::rtp_lookup_code_cache_result.

Referenced by gtalk_alloc(), and process_sdp().

02001 {
02002    int i;
02003 
02004    if (!rtp)
02005       return;
02006 
02007    rtp_bridge_lock(rtp);
02008 
02009    for (i = 0; i < MAX_RTP_PT; ++i) {
02010       rtp->current_RTP_PT[i].isAstFormat = 0;
02011       rtp->current_RTP_PT[i].code = 0;
02012    }
02013 
02014    rtp->rtp_lookup_code_cache_isAstFormat = 0;
02015    rtp->rtp_lookup_code_cache_code = 0;
02016    rtp->rtp_lookup_code_cache_result = 0;
02017 
02018    rtp_bridge_unlock(rtp);
02019 }

void ast_rtp_pt_copy ( struct ast_rtp dest,
struct ast_rtp src 
)

Copy payload types between RTP structures.

Definition at line 2040 of file rtp.c.

References rtpPayloadType::code, ast_rtp::current_RTP_PT, rtpPayloadType::isAstFormat, MAX_RTP_PT, rtp_bridge_lock(), rtp_bridge_unlock(), 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_make_compatible(), and process_sdp().

02041 {
02042    unsigned int i;
02043 
02044    rtp_bridge_lock(dest);
02045    rtp_bridge_lock(src);
02046 
02047    for (i = 0; i < MAX_RTP_PT; ++i) {
02048       dest->current_RTP_PT[i].isAstFormat = 
02049          src->current_RTP_PT[i].isAstFormat;
02050       dest->current_RTP_PT[i].code = 
02051          src->current_RTP_PT[i].code; 
02052    }
02053    dest->rtp_lookup_code_cache_isAstFormat = 0;
02054    dest->rtp_lookup_code_cache_code = 0;
02055    dest->rtp_lookup_code_cache_result = 0;
02056 
02057    rtp_bridge_unlock(src);
02058    rtp_bridge_unlock(dest);
02059 }

void ast_rtp_pt_default ( struct ast_rtp rtp  ) 

Set payload types to defaults.

Definition at line 2021 of file rtp.c.

References rtpPayloadType::code, ast_rtp::current_RTP_PT, rtpPayloadType::isAstFormat, MAX_RTP_PT, rtp_bridge_lock(), rtp_bridge_unlock(), 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().

02022 {
02023    int i;
02024 
02025    rtp_bridge_lock(rtp);
02026 
02027    /* Initialize to default payload types */
02028    for (i = 0; i < MAX_RTP_PT; ++i) {
02029       rtp->current_RTP_PT[i].isAstFormat = static_RTP_PT[i].isAstFormat;
02030       rtp->current_RTP_PT[i].code = static_RTP_PT[i].code;
02031    }
02032 
02033    rtp->rtp_lookup_code_cache_isAstFormat = 0;
02034    rtp->rtp_lookup_code_cache_code = 0;
02035    rtp->rtp_lookup_code_cache_result = 0;
02036 
02037    rtp_bridge_unlock(rtp);
02038 }

struct ast_frame* ast_rtp_read ( struct ast_rtp rtp  )  [read]

Definition at line 1575 of file rtp.c.

References ast_rtp::altthem, ast_assert, ast_codec_get_samples(), ast_debug, AST_FORMAT_AUDIO_MASK, ast_format_rate(), AST_FORMAT_SLINEAR, AST_FORMAT_T140, AST_FORMAT_T140RED, AST_FORMAT_VIDEO_MASK, ast_frame_byteswap_be, AST_FRAME_DTMF_END, AST_FRAME_TEXT, AST_FRAME_VIDEO, AST_FRAME_VOICE, AST_FRFLAG_HAS_TIMING_INFO, AST_FRIENDLY_OFFSET, ast_inet_ntoa(), ast_log(), ast_null_frame, ast_rtcp_calc_interval(), ast_rtcp_write(), AST_RTP_CISCO_DTMF, AST_RTP_CN, AST_RTP_DTMF, ast_rtp_get_bridged(), ast_rtp_lookup_pt(), ast_rtp_senddigit_continuation(), ast_samp2tv(), ast_sched_add(), ast_set_flag, ast_tv(), ast_tvdiff_ms(), ast_verbose, bridge_p2p_rtp_write(), ast_rtp::bridged, calc_rxstamp(), rtpPayloadType::code, ast_rtp::cycles, ast_frame::data, ast_frame::datalen, ast_frame::delivery, ast_rtp::dtmf_duration, ast_rtp::dtmf_timeout, errno, ext, ast_rtp::f, f, FLAG_NAT_ACTIVE, ast_frame::frametype, rtpPayloadType::isAstFormat, ast_rtp::lastevent, ast_rtp::lastitexttimestamp, ast_rtp::lastividtimestamp, ast_rtp::lastrxformat, ast_rtp::lastrxseqno, ast_rtp::lastrxts, ast_frame::len, len(), LOG_NOTICE, LOG_WARNING, ast_frame::mallocd, ast_rtp::nat, ast_frame::offset, option_debug, process_cisco_dtmf(), process_rfc2833(), process_rfc3389(), ast_frame::ptr, ast_rtp::rawdata, ast_rtp::resp, ast_rtp::rtcp, rtp_debug_test_addr(), rtp_get_rate(), RTP_SEQ_MOD, ast_rtp::rxcount, ast_rtp::rxseqno, ast_rtp::rxssrc, ast_rtp::s, ast_frame::samples, ast_rtp::sched, ast_rtcp::schedid, ast_rtp::seedrxseqno, send_dtmf(), ast_rtp::sending_digit, ast_frame::seqno, ast_frame::src, ast_rtp::strict_rtp_address, STRICT_RTP_CLOSED, STRICT_RTP_LEARN, ast_rtp::strict_rtp_state, STUN_ACCEPT, stun_handle_packet(), ast_frame::subclass, ast_rtcp::them, ast_rtp::them, ast_rtp::themssrc, ast_frame::ts, and version.

Referenced by gtalk_rtp_read(), jingle_rtp_read(), mgcp_rtp_read(), oh323_rtp_read(), rtpread(), sip_rtp_read(), skinny_rtp_read(), and unistim_rtp_read().

01576 {
01577    int res;
01578    struct sockaddr_in sock_in;
01579    socklen_t len;
01580    unsigned int seqno;
01581    int version;
01582    int payloadtype;
01583    int hdrlen = 12;
01584    int padding;
01585    int mark;
01586    int ext;
01587    int cc;
01588    unsigned int ssrc;
01589    unsigned int timestamp;
01590    unsigned int *rtpheader;
01591    struct rtpPayloadType rtpPT;
01592    struct ast_rtp *bridged = NULL;
01593    int prev_seqno;
01594    
01595    /* If time is up, kill it */
01596    if (rtp->sending_digit)
01597       ast_rtp_senddigit_continuation(rtp);
01598 
01599    len = sizeof(sock_in);
01600    
01601    /* Cache where the header will go */
01602    res = recvfrom(rtp->s, rtp->rawdata + AST_FRIENDLY_OFFSET, sizeof(rtp->rawdata) - AST_FRIENDLY_OFFSET,
01603                0, (struct sockaddr *)&sock_in, &len);
01604 
01605    /* If strict RTP protection is enabled see if we need to learn this address or if the packet should be dropped */
01606    if (rtp->strict_rtp_state == STRICT_RTP_LEARN) {
01607       /* Copy over address that this packet was received on */
01608       memcpy(&rtp->strict_rtp_address, &sock_in, sizeof(rtp->strict_rtp_address));
01609       /* Now move over to actually protecting the RTP port */
01610       rtp->strict_rtp_state = STRICT_RTP_CLOSED;
01611       ast_debug(1, "Learned remote address is %s:%d for strict RTP purposes, now protecting the port.\n", ast_inet_ntoa(rtp->strict_rtp_address.sin_addr), ntohs(rtp->strict_rtp_address.sin_port));
01612    } else if (rtp->strict_rtp_state == STRICT_RTP_CLOSED) {
01613       /* If the address we previously learned doesn't match the address this packet came in on simply drop it */
01614       if ((rtp->strict_rtp_address.sin_addr.s_addr != sock_in.sin_addr.s_addr) || (rtp->strict_rtp_address.sin_port != sock_in.sin_port)) {
01615          ast_debug(1, "Received RTP packet from %s:%d, dropping due to strict RTP protection. Expected it to be from %s:%d\n", ast_inet_ntoa(sock_in.sin_addr), ntohs(sock_in.sin_port), ast_inet_ntoa(rtp->strict_rtp_address.sin_addr), ntohs(rtp->strict_rtp_address.sin_port));
01616          return &ast_null_frame;
01617       }
01618    }
01619 
01620    rtpheader = (unsigned int *)(rtp->rawdata + AST_FRIENDLY_OFFSET);
01621    if (res < 0) {
01622       ast_assert(errno != EBADF);
01623       if (errno != EAGAIN) {
01624          ast_log(LOG_WARNING, "RTP Read error: %s.  Hanging up.\n", strerror(errno));
01625          return NULL;
01626       }
01627       return &ast_null_frame;
01628    }
01629    
01630    if (res < hdrlen) {
01631       ast_log(LOG_WARNING, "RTP Read too short\n");
01632       return &ast_null_frame;
01633    }
01634 
01635    /* Get fields */
01636    seqno = ntohl(rtpheader[0]);
01637 
01638    /* Check RTP version */
01639    version = (seqno & 0xC0000000) >> 30;
01640    if (!version) {
01641       /* If the two high bits are 0, this might be a
01642        * STUN message, so process it. stun_handle_packet()
01643        * answers to requests, and it returns STUN_ACCEPT
01644        * if the request is valid.
01645        */
01646       if ((stun_handle_packet(rtp->s, &sock_in, rtp->rawdata + AST_FRIENDLY_OFFSET, res, NULL, NULL) == STUN_ACCEPT) &&
01647          (!rtp->them.sin_port && !rtp->them.sin_addr.s_addr)) {
01648          memcpy(&rtp->them, &sock_in, sizeof(rtp->them));
01649       }
01650       return &ast_null_frame;
01651    }
01652 
01653 #if 0 /* Allow to receive RTP stream with closed transmission path */
01654    /* If we don't have the other side's address, then ignore this */
01655    if (!rtp->them.sin_addr.s_addr || !rtp->them.sin_port)
01656       return &ast_null_frame;
01657 #endif
01658 
01659    /* Send to whoever send to us if NAT is turned on */
01660    if (rtp->nat) {
01661       if (((rtp->them.sin_addr.s_addr != sock_in.sin_addr.s_addr) ||
01662           (rtp->them.sin_port != sock_in.sin_port)) && 
01663           ((rtp->altthem.sin_addr.s_addr != sock_in.sin_addr.s_addr) ||
01664           (rtp->altthem.sin_port != sock_in.sin_port))) {
01665          rtp->them = sock_in;
01666          if (rtp->rtcp) {
01667             int h = 0;
01668             memcpy(&rtp->rtcp->them, &sock_in, sizeof(rtp->rtcp->them));
01669             h = ntohs(rtp->them.sin_port);
01670             rtp->rtcp->them.sin_port = htons(h + 1);
01671          }
01672          rtp->rxseqno = 0;
01673          ast_set_flag(rtp, FLAG_NAT_ACTIVE);
01674          if (option_debug || rtpdebug)
01675             ast_debug(0, "RTP NAT: Got audio from other end. Now sending to address %s:%d\n", ast_inet_ntoa(rtp->them.sin_addr), ntohs(rtp->them.sin_port));
01676       }
01677    }
01678 
01679    /* If we are bridged to another RTP stream, send direct */
01680    if ((bridged = ast_rtp_get_bridged(rtp)) && !bridge_p2p_rtp_write(rtp, bridged, rtpheader, res, hdrlen))
01681       return &ast_null_frame;
01682 
01683    if (version != 2)
01684       return &ast_null_frame;
01685 
01686    payloadtype = (seqno & 0x7f0000) >> 16;
01687    padding = seqno & (1 << 29);
01688    mark = seqno & (1 << 23);
01689    ext = seqno & (1 << 28);
01690    cc = (seqno & 0xF000000) >> 24;
01691    seqno &= 0xffff;
01692    timestamp = ntohl(rtpheader[1]);
01693    ssrc = ntohl(rtpheader[2]);
01694    
01695    if (!mark && rtp->rxssrc && rtp->rxssrc != ssrc) {
01696       if (option_debug || rtpdebug)
01697          ast_debug(0, "Forcing Marker bit, because SSRC has changed\n");
01698       mark = 1;
01699    }
01700 
01701    rtp->rxssrc = ssrc;
01702    
01703    if (padding) {
01704       /* Remove padding bytes */
01705       res -= rtp->rawdata[AST_FRIENDLY_OFFSET + res - 1];
01706    }
01707    
01708    if (cc) {
01709       /* CSRC fields present */
01710       hdrlen += cc*4;
01711    }
01712 
01713    if (ext) {
01714       /* RTP Extension present */
01715       hdrlen += (ntohl(rtpheader[hdrlen/4]) & 0xffff) << 2;
01716       hdrlen += 4;
01717       if (option_debug) {
01718          int profile;
01719          profile = (ntohl(rtpheader[3]) & 0xffff0000) >> 16;
01720          if (profile == 0x505a)
01721             ast_debug(1, "Found Zfone extension in RTP stream - zrtp - not supported.\n");
01722          else
01723             ast_debug(1, "Found unknown RTP Extensions %x\n", profile);
01724       }
01725    }
01726 
01727    if (res < hdrlen) {
01728       ast_log(LOG_WARNING, "RTP Read too short (%d, expecting %d)\n", res, hdrlen);
01729       return &ast_null_frame;
01730    }
01731 
01732    rtp->rxcount++; /* Only count reasonably valid packets, this'll make the rtcp stats more accurate */
01733 
01734    if (rtp->rxcount==1) {
01735       /* This is the first RTP packet successfully received from source */
01736       rtp->seedrxseqno = seqno;
01737    }
01738 
01739    /* Do not schedule RR if RTCP isn't run */
01740    if (rtp->rtcp && rtp->rtcp->them.sin_addr.s_addr && rtp->rtcp->schedid < 1) {
01741       /* Schedule transmission of Receiver Report */
01742       rtp->rtcp->schedid = ast_sched_add(rtp->sched, ast_rtcp_calc_interval(rtp), ast_rtcp_write, rtp);
01743    }
01744    if ((int)rtp->lastrxseqno - (int)seqno  > 100) /* if so it would indicate that the sender cycled; allow for misordering */
01745       rtp->cycles += RTP_SEQ_MOD;
01746    
01747    prev_seqno = rtp->lastrxseqno;
01748 
01749    rtp->lastrxseqno = seqno;
01750    
01751    if (!rtp->themssrc)
01752       rtp->themssrc = ntohl(rtpheader[2]); /* Record their SSRC to put in future RR */
01753    
01754    if (rtp_debug_test_addr(&sock_in))
01755       ast_verbose("Got  RTP packet from    %s:%u (type %-2.2d, seq %-6.6u, ts %-6.6u, len %-6.6u)\n",
01756          ast_inet_ntoa(sock_in.sin_addr), ntohs(sock_in.sin_port), payloadtype, seqno, timestamp,res - hdrlen);
01757 
01758    rtpPT = ast_rtp_lookup_pt(rtp, payloadtype);
01759    if (!rtpPT.isAstFormat) {
01760       struct ast_frame *f = NULL;
01761 
01762       /* This is special in-band data that's not one of our codecs */
01763       if (rtpPT.code == AST_RTP_DTMF) {
01764          /* It's special -- rfc2833 process it */
01765          if (rtp_debug_test_addr(&sock_in)) {
01766             unsigned char *data;
01767             unsigned int event;
01768             unsigned int event_end;
01769             unsigned int duration;
01770             data = rtp->rawdata + AST_FRIENDLY_OFFSET + hdrlen;
01771             event = ntohl(*((unsigned int *)(data)));
01772             event >>= 24;
01773             event_end = ntohl(*((unsigned int *)(data)));
01774             event_end <<= 8;
01775             event_end >>= 24;
01776             duration = ntohl(*((unsigned int *)(data)));
01777             duration &= 0xFFFF;
01778             ast_verbose("Got  RTP RFC2833 from   %s:%u (type %-2.2d, seq %-6.6u, ts %-6.6u, len %-6.6u, mark %d, event %08x, end %d, duration %-5.5d) \n", ast_inet_ntoa(sock_in.sin_addr), ntohs(sock_in.sin_port), payloadtype, seqno, timestamp, res - hdrlen, (mark?1:0), event, ((event_end & 0x80)?1:0), duration);
01779          }
01780          f = process_rfc2833(rtp, rtp->rawdata + AST_FRIENDLY_OFFSET + hdrlen, res - hdrlen, seqno, timestamp);
01781       } else if (rtpPT.code == AST_RTP_CISCO_DTMF) {
01782          /* It's really special -- process it the Cisco way */
01783          if (rtp->lastevent <= seqno || (rtp->lastevent >= 65530 && seqno <= 6)) {
01784             f = process_cisco_dtmf(rtp, rtp->rawdata + AST_FRIENDLY_OFFSET + hdrlen, res - hdrlen);
01785             rtp->lastevent = seqno;
01786          }
01787       } else if (rtpPT.code == AST_RTP_CN) {
01788          /* Comfort Noise */
01789          f = process_rfc3389(rtp, rtp->rawdata + AST_FRIENDLY_OFFSET + hdrlen, res - hdrlen);
01790       } else {
01791          ast_log(LOG_NOTICE, "Unknown RTP codec %d received from '%s'\n", payloadtype, ast_inet_ntoa(rtp->them.sin_addr));
01792       }
01793       return f ? f : &ast_null_frame;
01794    }
01795    rtp->lastrxformat = rtp->f.subclass = rtpPT.code;
01796    rtp->f.frametype = (rtp->f.subclass & AST_FORMAT_AUDIO_MASK) ? AST_FRAME_VOICE : (rtp->f.subclass & AST_FORMAT_VIDEO_MASK) ? AST_FRAME_VIDEO : AST_FRAME_TEXT;
01797 
01798    rtp->rxseqno = seqno;
01799 
01800    if (rtp->dtmf_timeout && rtp->dtmf_timeout < timestamp) {
01801       rtp->dtmf_timeout = 0;
01802 
01803       if (rtp->resp) {
01804          struct ast_frame *f;
01805          f = send_dtmf(rtp, AST_FRAME_DTMF_END);
01806          f->len = ast_tvdiff_ms(ast_samp2tv(rtp->dtmf_duration, rtp_get_rate(f->subclass)), ast_tv(0, 0));
01807          rtp->resp = 0;
01808          rtp->dtmf_timeout = rtp->dtmf_duration = 0;
01809          return f;
01810       }
01811    }
01812 
01813    /* Record received timestamp as last received now */
01814    rtp->lastrxts = timestamp;
01815 
01816    rtp->f.mallocd = 0;
01817    rtp->f.datalen = res - hdrlen;
01818    rtp->f.data.ptr = rtp->rawdata + hdrlen + AST_FRIENDLY_OFFSET;
01819    rtp->f.offset = hdrlen + AST_FRIENDLY_OFFSET;
01820    rtp->f.seqno = seqno;
01821 
01822    if (rtp->f.subclass == AST_FORMAT_T140 && (int)seqno - (prev_seqno+1) > 0 && (int)seqno - (prev_seqno+1) < 10) {
01823         unsigned char *data = rtp->f.data.ptr;
01824         
01825         memmove(rtp->f.data.ptr+3, rtp->f.data.ptr, rtp->f.datalen);
01826         rtp->f.datalen +=3;
01827         *data++ = 0xEF;
01828         *data++ = 0xBF;
01829         *data = 0xBD;
01830    }
01831  
01832    if (rtp->f.subclass == AST_FORMAT_T140RED) {
01833       unsigned char *data = rtp->f.data.ptr;
01834       unsigned char *header_end;
01835       int num_generations;
01836       int header_length;
01837       int length;
01838       int diff =(int)seqno - (prev_seqno+1); /* if diff = 0, no drop*/
01839       int x;
01840 
01841       rtp->f.subclass = AST_FORMAT_T140;
01842       header_end = memchr(data, ((*data) & 0x7f), rtp->f.datalen);
01843       if (header_end == NULL) {
01844          return &ast_null_frame;
01845       }
01846       header_end++;
01847       
01848       header_length = header_end - data;
01849       num_generations = header_length / 4;
01850       length = header_length;
01851 
01852       if (!diff) {
01853          for (x = 0; x < num_generations; x++)
01854             length += data[x * 4 + 3];
01855          
01856          if (!(rtp->f.datalen - length))
01857             return &ast_null_frame;
01858          
01859          rtp->f.data.ptr += length;
01860          rtp->f.datalen -= length;
01861       } else if (diff > num_generations && diff < 10) {
01862          length -= 3;
01863          rtp->f.data.ptr += length;
01864          rtp->f.datalen -= length;
01865          
01866          data = rtp->f.data.ptr;
01867          *data++ = 0xEF;
01868          *data++ = 0xBF;
01869          *data = 0xBD;
01870       } else   {
01871          for ( x = 0; x < num_generations - diff; x++) 
01872             length += data[x * 4 + 3];
01873          
01874          rtp->f.data.ptr += length;
01875          rtp->f.datalen -= length;
01876       }
01877    }
01878 
01879    if (rtp->f.subclass & AST_FORMAT_AUDIO_MASK) {
01880       rtp->f.samples = ast_codec_get_samples(&rtp->f);
01881       if (rtp->f.subclass == AST_FORMAT_SLINEAR) 
01882          ast_frame_byteswap_be(&rtp->f);
01883       calc_rxstamp(&rtp->f.delivery, rtp, timestamp, mark);
01884       /* Add timing data to let ast_generic_bridge() put the frame into a jitterbuf */
01885       ast_set_flag(&rtp->f, AST_FRFLAG_HAS_TIMING_INFO);
01886       rtp->f.ts = timestamp / (rtp_get_rate(rtp->f.subclass) / 1000);
01887       rtp->f.len = rtp->f.samples / ( (ast_format_rate(rtp->f.subclass) == 16000) ? 16 : 8 );
01888    } else if (rtp->f.subclass & AST_FORMAT_VIDEO_MASK) {
01889       /* Video -- samples is # of samples vs. 90000 */
01890       if (!rtp->lastividtimestamp)
01891          rtp->lastividtimestamp = timestamp;
01892       rtp->f.samples = timestamp - rtp->lastividtimestamp;
01893       rtp->lastividtimestamp = timestamp;
01894       rtp->f.delivery.tv_sec = 0;
01895       rtp->f.delivery.tv_usec = 0;
01896       /* Pass the RTP marker bit as bit 0 in the subclass field.
01897        * This is ok because subclass is actually a bitmask, and
01898        * the low bits represent audio formats, that are not
01899        * involved here since we deal with video.
01900        */
01901       if (mark)
01902          rtp->f.subclass |= 0x1;
01903    } else {
01904       /* TEXT -- samples is # of samples vs. 1000 */
01905       if (!rtp->lastitexttimestamp)
01906          rtp->lastitexttimestamp = timestamp;
01907       rtp->f.samples = timestamp - rtp->lastitexttimestamp;
01908       rtp->lastitexttimestamp = timestamp;
01909       rtp->f.delivery.tv_sec = 0;
01910       rtp->f.delivery.tv_usec = 0;
01911    }
01912    rtp->f.src = "RTP";
01913    return &rtp->f;
01914 }

int ast_rtp_reload ( void   ) 

Initialize RTP subsystem

Definition at line 4879 of file rtp.c.

References __ast_rtp_reload().

04880 {
04881    return __ast_rtp_reload(1);
04882 }

void ast_rtp_reset ( struct ast_rtp rtp  ) 

Definition at line 2690 of file rtp.c.

References ast_rtp::dtmf_timeout, ast_rtp::dtmfmute, ast_rtp::dtmfsamples, ast_rtp::lastdigitts, ast_rtp::lastevent, ast_rtp::lasteventseqn, ast_rtp::lastitexttimestamp, ast_rtp::lastividtimestamp, ast_rtp::lastotexttimestamp, 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.

02691 {
02692    memset(&rtp->rxcore, 0, sizeof(rtp->rxcore));
02693    memset(&rtp->txcore, 0, sizeof(rtp->txcore));
02694    memset(&rtp->dtmfmute, 0, sizeof(rtp->dtmfmute));
02695    rtp->lastts = 0;
02696    rtp->lastdigitts = 0;
02697    rtp->lastrxts = 0;
02698    rtp->lastividtimestamp = 0;
02699    rtp->lastovidtimestamp = 0;
02700    rtp->lastitexttimestamp = 0;
02701    rtp->lastotexttimestamp = 0;
02702    rtp->lasteventseqn = 0;
02703    rtp->lastevent = 0;
02704    rtp->lasttxformat = 0;
02705    rtp->lastrxformat = 0;
02706    rtp->dtmf_timeout = 0;
02707    rtp->dtmfsamples = 0;
02708    rtp->seqno = 0;
02709    rtp->rxseqno = 0;
02710 }

int ast_rtp_sendcng ( struct ast_rtp rtp,
int  level 
)

generate comfort noice (CNG)

Definition at line 3533 of file rtp.c.

References ast_inet_ntoa(), ast_log(), AST_RTP_CN, ast_rtp_lookup_code(), ast_tv(), ast_tvadd(), ast_tvnow(), ast_verbose, ast_rtp::data, ast_rtp::dtmfmute, errno, ast_rtp::lastts, LOG_ERROR, rtp_debug_test_addr(), ast_rtp::s, ast_rtp::seqno, ast_rtp::ssrc, and ast_rtp::them.

Referenced by check_rtp_timeout().

03534 {
03535    unsigned int *rtpheader;
03536    int hdrlen = 12;
03537    int res;
03538    int payload;
03539    char data[256];
03540    level = 127 - (level & 0x7f);
03541    payload = ast_rtp_lookup_code(rtp, 0, AST_RTP_CN);
03542 
03543    /* If we have no peer, return immediately */ 
03544    if (!rtp->them.sin_addr.s_addr)
03545       return 0;
03546 
03547    rtp->dtmfmute = ast_tvadd(ast_tvnow(), ast_tv(0, 500000));
03548 
03549    /* Get a pointer to the header */
03550    rtpheader = (unsigned int *)data;
03551    rtpheader[0] = htonl((2 << 30) | (1 << 23) | (payload << 16) | (rtp->seqno++));
03552    rtpheader[1] = htonl(rtp->lastts);
03553    rtpheader[2] = htonl(rtp->ssrc); 
03554    data[12] = level;
03555    if (rtp->them.sin_port && rtp->them.sin_addr.s_addr) {
03556       res = sendto(rtp->s, (void *)rtpheader, hdrlen + 1, 0, (struct sockaddr *)&rtp->them, sizeof(rtp->them));
03557       if (res <0) 
03558          ast_log(LOG_ERROR, "RTP Comfort Noise Transmission error to %s:%d: %s\n", ast_inet_ntoa(rtp->them.sin_addr), ntohs(rtp->them.sin_port), strerror(errno));
03559       if (rtp_debug_test_addr(&rtp->them))
03560          ast_verbose("Sent Comfort Noise RTP packet to %s:%u (type %d, seq %u, ts %u, len %d)\n"
03561                , ast_inet_ntoa(rtp->them.sin_addr), ntohs(rtp->them.sin_port), payload, rtp->seqno, rtp->lastts,res - hdrlen);         
03562          
03563    }
03564    return 0;
03565 }

int ast_rtp_senddigit_begin ( struct ast_rtp rtp,
char  digit 
)

Send begin frames for DTMF.

Definition at line 3100 of file rtp.c.

References ast_inet_ntoa(), ast_log(), AST_RTP_DTMF, ast_rtp_lookup_code(), ast_tv(), ast_tvadd(), ast_tvnow(), ast_verbose, ast_rtp::dtmfmute, errno, ast_rtp::lastdigitts, ast_rtp::lastts, LOG_ERROR, LOG_WARNING, rtp_debug_test_addr(), ast_rtp::s, ast_rtp::send_digit, ast_rtp::send_duration, ast_rtp::send_payload, ast_rtp::sending_digit, ast_rtp::seqno, ast_rtp::ssrc, and ast_rtp::them.

Referenced by mgcp_senddigit_begin(), oh323_digit_begin(), and sip_senddigit_begin().

03101 {
03102    unsigned int *rtpheader;
03103    int hdrlen = 12, res = 0, i = 0, payload = 0;
03104    char data[256];
03105 
03106    if ((digit <= '9') && (digit >= '0'))
03107       digit -= '0';
03108    else if (digit == '*')
03109       digit = 10;
03110    else if (digit == '#')
03111       digit = 11;
03112    else if ((digit >= 'A') && (digit <= 'D'))
03113       digit = digit - 'A' + 12;
03114    else if ((digit >= 'a') && (digit <= 'd'))
03115       digit = digit - 'a' + 12;
03116    else {
03117       ast_log(LOG_WARNING, "Don't know how to represent '%c'\n", digit);
03118       return 0;
03119    }
03120 
03121    /* If we have no peer, return immediately */ 
03122    if (!rtp->them.sin_addr.s_addr || !rtp->them.sin_port)
03123       return 0;
03124 
03125    payload = ast_rtp_lookup_code(rtp, 0, AST_RTP_DTMF);
03126 
03127    rtp->dtmfmute = ast_tvadd(ast_tvnow(), ast_tv(0, 500000));
03128    rtp->send_duration = 160;
03129    rtp->lastdigitts = rtp->lastts + rtp->send_duration;
03130    
03131    /* Get a pointer to the header */
03132    rtpheader = (unsigned int *)data;
03133    rtpheader[0] = htonl((2 << 30) | (1 << 23) | (payload << 16) | (rtp->seqno));
03134    rtpheader[1] = htonl(rtp->lastdigitts);
03135    rtpheader[2] = htonl(rtp->ssrc); 
03136 
03137    for (i = 0; i < 2; i++) {
03138       rtpheader[3] = htonl((digit << 24) | (0xa << 16) | (rtp->send_duration));
03139       res = sendto(rtp->s, (void *) rtpheader, hdrlen + 4, 0, (struct sockaddr *) &rtp->them, sizeof(rtp->them));
03140       if (res < 0) 
03141          ast_log(LOG_ERROR, "RTP Transmission error to %s:%u: %s\n",
03142             ast_inet_ntoa(rtp->them.sin_addr),
03143             ntohs(rtp->them.sin_port), strerror(errno));
03144       if (rtp_debug_test_addr(&rtp->them))
03145          ast_verbose("Sent RTP DTMF packet to %s:%u (type %-2.2d, seq %-6.6u, ts %-6.6u, len %-6.6u)\n",
03146                 ast_inet_ntoa(rtp->them.sin_addr),
03147                 ntohs(rtp->them.sin_port), payload, rtp->seqno, rtp->lastdigitts, res - hdrlen);
03148       /* Increment sequence number */
03149       rtp->seqno++;
03150       /* Increment duration */
03151       rtp->send_duration += 160;
03152       /* Clear marker bit and set seqno */
03153       rtpheader[0] = htonl((2 << 30) | (payload << 16) | (rtp->seqno));
03154    }
03155 
03156    /* Since we received a begin, we can safely store the digit and disable any compensation */
03157    rtp->sending_digit = 1;
03158    rtp->send_digit = digit;
03159    rtp->send_payload = payload;
03160 
03161    return 0;
03162 }

int ast_rtp_senddigit_end ( struct ast_rtp rtp,
char  digit 
)

Send end packets for DTMF.

Definition at line 3202 of file rtp.c.

References ast_inet_ntoa(), ast_log(), ast_tv(), ast_tvadd(), ast_tvnow(), ast_verbose, ast_rtp::dtmfmute, errno, ast_rtp::lastdigitts, ast_rtp::lastts, LOG_ERROR, LOG_WARNING, rtp_debug_test_addr(), ast_rtp::s, ast_rtp::send_digit, ast_rtp::send_duration, ast_rtp::send_payload, ast_rtp::sending_digit, ast_rtp::seqno, ast_rtp::ssrc, and ast_rtp::them.

Referenced by mgcp_senddigit_end(), oh323_digit_end(), and sip_senddigit_end().

03203 {
03204    unsigned int *rtpheader;
03205    int hdrlen = 12, res = 0, i = 0;
03206    char data[256];
03207    
03208    /* If no address, then bail out */
03209    if (!rtp->them.sin_addr.s_addr || !rtp->them.sin_port)
03210       return 0;
03211    
03212    if ((digit <= '9') && (digit >= '0'))
03213       digit -= '0';
03214    else if (digit == '*')
03215       digit = 10;
03216    else if (digit == '#')
03217       digit = 11;
03218    else if ((digit >= 'A') && (digit <= 'D'))
03219       digit = digit - 'A' + 12;
03220    else if ((digit >= 'a') && (digit <= 'd'))
03221       digit = digit - 'a' + 12;
03222    else {
03223       ast_log(LOG_WARNING, "Don't know how to represent '%c'\n", digit);
03224       return 0;
03225    }
03226 
03227    rtp->dtmfmute = ast_tvadd(ast_tvnow(), ast_tv(0, 500000));
03228 
03229    rtpheader = (unsigned int *)data;
03230    rtpheader[1] = htonl(rtp->lastdigitts);
03231    rtpheader[2] = htonl(rtp->ssrc);
03232    rtpheader[3] = htonl((digit << 24) | (0xa << 16) | (rtp->send_duration));
03233    /* Set end bit */
03234    rtpheader[3] |= htonl((1 << 23));
03235 
03236    /* Send 3 termination packets */
03237    for (i = 0; i < 3; i++) {
03238       rtpheader[0] = htonl((2 << 30) | (rtp->send_payload << 16) | (rtp->seqno));
03239       res = sendto(rtp->s, (void *) rtpheader, hdrlen + 4, 0, (struct sockaddr *) &rtp->them, sizeof(rtp->them));
03240       rtp->seqno++;
03241       if (res < 0)
03242          ast_log(LOG_ERROR, "RTP Transmission error to %s:%d: %s\n",
03243             ast_inet_ntoa(rtp->them.sin_addr),
03244             ntohs(rtp->them.sin_port), strerror(errno));
03245       if (rtp_debug_test_addr(&rtp->them))
03246          ast_verbose("Sent RTP DTMF packet to %s:%u (type %-2.2d, seq %-6.6u, ts %-6.6u, len %-6.6u)\n",
03247                 ast_inet_ntoa(rtp->them.sin_addr),
03248                 ntohs(rtp->them.sin_port), rtp->send_payload, rtp->seqno, rtp->lastdigitts, res - hdrlen);
03249    }
03250    rtp->lastts += rtp->send_duration;
03251    rtp->sending_digit = 0;
03252    rtp->send_digit = 0;
03253 
03254    return res;
03255 }

void ast_rtp_set_alt_peer ( struct ast_rtp rtp,
struct sockaddr_in *  alt 
)

set potential alternate source for RTP media

Since:
1.4.26 This function may be used to give the RTP stack a hint that there is a potential second source of media. One case where this is used is when the SIP stack receives a REINVITE to which it will be replying with a 491. In such a scenario, the IP and port information in the SDP of that REINVITE lets us know that we may receive media from that source/those sources even though the SIP transaction was unable to be completed successfully
Parameters:
rtp The RTP structure we wish to set up an alternate host/port on
alt The address information for the alternate media source
Return values:
void 

Definition at line 2630 of file rtp.c.

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

Referenced by handle_request_invite().

02631 {
02632    rtp->altthem.sin_port = alt->sin_port;
02633    rtp->altthem.sin_addr = alt->sin_addr;
02634    if (rtp->rtcp) {
02635       rtp->rtcp->altthem.sin_port = htons(ntohs(alt->sin_port) + 1);
02636       rtp->rtcp->altthem.sin_addr = alt->sin_addr;
02637    }
02638 }

void ast_rtp_set_callback ( struct ast_rtp rtp,
ast_rtp_callback  callback 
)

Definition at line 801 of file rtp.c.

References ast_rtp::callback.

Referenced by start_rtp().

00802 {
00803    rtp->callback = callback;
00804 }

void ast_rtp_set_data ( struct ast_rtp rtp,
void *  data 
)

Definition at line 796 of file rtp.c.

References ast_rtp::data.

Referenced by start_rtp().

00797 {
00798    rtp->data = data;
00799 }

void ast_rtp_set_m_type ( struct ast_rtp rtp,
int  pt 
)

Activate payload type.

Definition at line 2239 of file rtp.c.

References ast_rtp::current_RTP_PT, MAX_RTP_PT, rtp_bridge_lock(), and rtp_bridge_unlock().

Referenced by gtalk_is_answered(), gtalk_newcall(), jingle_newcall(), and process_sdp().

02240 {
02241    if (pt < 0 || pt > MAX_RTP_PT || static_RTP_PT[pt].code == 0) 
02242       return; /* bogus payload type */
02243 
02244    rtp_bridge_lock(rtp);
02245    rtp->current_RTP_PT[pt] = static_RTP_PT[pt];
02246    rtp_bridge_unlock(rtp);
02247 } 

void ast_rtp_set_peer ( struct ast_rtp rtp,
struct sockaddr_in *  them 
)

Definition at line 2615 of file rtp.c.

References ast_rtp::rtcp, ast_rtp::rxseqno, STRICT_RTP_LEARN, ast_rtp::strict_rtp_state, ast_rtcp::them, and ast_rtp::them.

Referenced by handle_open_receive_channel_ack_message(), process_sdp(), setup_rtp_connection(), and start_rtp().

02616 {
02617    rtp->them.sin_port = them->sin_port;
02618    rtp->them.sin_addr = them->sin_addr;
02619    if (rtp->rtcp) {
02620       int h = ntohs(them->sin_port);
02621       rtp->rtcp->them.sin_port = htons(h + 1);
02622       rtp->rtcp->them.sin_addr = them->sin_addr;
02623    }
02624    rtp->rxseqno = 0;
02625    /* If strict RTP protection is enabled switch back to the learn state so we don't drop packets from above */
02626    if (strictrtp)
02627       rtp->strict_rtp_state = STRICT_RTP_LEARN;
02628 }

void ast_rtp_set_rtpholdtimeout ( struct ast_rtp rtp,
int  timeout 
)

Set rtp hold timeout.

Definition at line 763 of file rtp.c.

References ast_rtp::rtpholdtimeout.

Referenced by check_rtp_timeout(), create_addr_from_peer(), and sip_alloc().

00764 {
00765    rtp->rtpholdtimeout = timeout;
00766 }

void ast_rtp_set_rtpkeepalive ( struct ast_rtp rtp,
int  period 
)

set RTP keepalive interval

Definition at line 769 of file rtp.c.

References ast_rtp::rtpkeepalive.

Referenced by create_addr_from_peer(), and sip_alloc().

00770 {
00771    rtp->rtpkeepalive = period;
00772 }

int ast_rtp_set_rtpmap_type ( struct ast_rtp rtp,
int  pt,
char *  mimeType,
char *  mimeSubtype,
enum ast_rtp_options  options 
)

Initiate payload type to a known MIME media type for a codec.

Initiate payload type to a known MIME media type for a codec.

Returns:
0 if the MIME type was found and set, -1 if it wasn't found

Definition at line 2266 of file rtp.c.

References ARRAY_LEN, AST_FORMAT_G726, AST_FORMAT_G726_AAL2, AST_RTP_OPT_G726_NONSTANDARD, rtpPayloadType::code, ast_rtp::current_RTP_PT, MAX_RTP_PT, mimeTypes, payloadType, rtp_bridge_lock(), rtp_bridge_unlock(), subtype, and type.

Referenced by __oh323_rtp_create(), gtalk_is_answered(), gtalk_newcall(), jingle_newcall(), process_sdp(), set_dtmf_payload(), and setup_rtp_connection().

02269 {
02270    unsigned int i;
02271    int found = 0;
02272 
02273    if (pt < 0 || pt > MAX_RTP_PT) 
02274       return -1; /* bogus payload type */
02275    
02276    rtp_bridge_lock(rtp);
02277 
02278    for (i = 0; i < ARRAY_LEN(mimeTypes); ++i) {
02279       if (strcasecmp(mimeSubtype, mimeTypes[i].subtype) == 0 &&
02280           strcasecmp(mimeType, mimeTypes[i].type) == 0) {
02281          found = 1;
02282          rtp->current_RTP_PT[pt] = mimeTypes[i].payloadType;
02283          if ((mimeTypes[i].payloadType.code == AST_FORMAT_G726) &&
02284              mimeTypes[i].payloadType.isAstFormat &&
02285              (options & AST_RTP_OPT_G726_NONSTANDARD))
02286             rtp->current_RTP_PT[pt].code = AST_FORMAT_G726_AAL2;
02287          break;
02288       }
02289    }
02290 
02291    rtp_bridge_unlock(rtp);
02292 
02293    return (found ? 0 : -1);
02294 } 

void ast_rtp_set_rtptimeout ( struct ast_rtp rtp,
int  timeout 
)

Set rtp timeout.

Definition at line 757 of file rtp.c.

References ast_rtp::rtptimeout.

Referenced by check_rtp_timeout(), create_addr_from_peer(), and sip_alloc().

00758 {
00759    rtp->rtptimeout = timeout;
00760 }

void ast_rtp_set_rtptimers_onhold ( struct ast_rtp rtp  ) 

Definition at line 750 of file rtp.c.

References ast_rtp::rtpholdtimeout, and ast_rtp::rtptimeout.

Referenced by handle_response_invite().

00751 {
00752    rtp->rtptimeout = (-1) * rtp->rtptimeout;
00753    rtp->rtpholdtimeout = (-1) * rtp->rtpholdtimeout;
00754 }

void ast_rtp_set_vars ( struct ast_channel chan,
struct ast_rtp rtp 
)

Set RTPAUDIOQOS(...) variables on a channel when it is being hung up.

Since:
1.6.1

Definition at line 2794 of file rtp.c.

References ast_bridged_channel(), ast_rtp_get_quality(), pbx_builtin_setvar_helper(), RTPQOS_JITTER, RTPQOS_LOSS, RTPQOS_RTT, and RTPQOS_SUMMARY.

Referenced by handle_request_bye(), and sip_hangup().

02794                                                                      {
02795    char *audioqos;
02796    char *audioqos_jitter;
02797    char *audioqos_loss;
02798    char *audioqos_rtt;
02799    struct ast_channel *bridge;
02800 
02801    if (!rtp || !chan)
02802       return;
02803 
02804    bridge = ast_bridged_channel(chan);
02805 
02806    audioqos        = ast_rtp_get_quality(rtp, NULL, RTPQOS_SUMMARY);
02807    audioqos_jitter = ast_rtp_get_quality(rtp, NULL, RTPQOS_JITTER);
02808    audioqos_loss   = ast_rtp_get_quality(rtp, NULL, RTPQOS_LOSS);
02809    audioqos_rtt    = ast_rtp_get_quality(rtp, NULL, RTPQOS_RTT);
02810 
02811    pbx_builtin_setvar_helper(chan, "RTPAUDIOQOS", audioqos);
02812    pbx_builtin_setvar_helper(chan, "RTPAUDIOQOSJITTER", audioqos_jitter);
02813    pbx_builtin_setvar_helper(chan, "RTPAUDIOQOSLOSS", audioqos_loss);
02814    pbx_builtin_setvar_helper(chan, "RTPAUDIOQOSRTT", audioqos_rtt);
02815 
02816    if (!bridge)
02817       return;
02818 
02819    pbx_builtin_setvar_helper(bridge, "RTPAUDIOQOSBRIDGED", audioqos);
02820    pbx_builtin_setvar_helper(bridge, "RTPAUDIOQOSJITTERBRIDGED", audioqos_jitter);
02821    pbx_builtin_setvar_helper(bridge, "RTPAUDIOQOSLOSSBRIDGED", audioqos_loss);
02822    pbx_builtin_setvar_helper(bridge, "RTPAUDIOQOSRTTBRIDGED", audioqos_rtt);
02823 }

void ast_rtp_setdtmf ( struct ast_rtp rtp,
int  dtmf 
)

Indicate whether this RTP session is carrying DTMF or not.

Definition at line 816 of file rtp.c.

References ast_set2_flag, and FLAG_HAS_DTMF.

Referenced by create_addr_from_peer(), handle_request_invite(), process_sdp(), sip_alloc(), and sip_dtmfmode().

00817 {
00818    ast_set2_flag(rtp, dtmf ? 1 : 0, FLAG_HAS_DTMF);
00819 }

void ast_rtp_setdtmfcompensate ( struct ast_rtp rtp,
int  compensate 
)

Compensate for devices that send RFC2833 packets all at once.

Definition at line 821 of file rtp.c.

References ast_set2_flag, and FLAG_DTMF_COMPENSATE.

Referenced by create_addr_from_peer(), handle_request_invite(), process_sdp(), and sip_alloc().

00822 {
00823    ast_set2_flag(rtp, compensate ? 1 : 0, FLAG_DTMF_COMPENSATE);
00824 }

void ast_rtp_setnat ( struct ast_rtp rtp,
int  nat 
)

Definition at line 806 of file rtp.c.

References ast_rtp::nat.

Referenced by __oh323_rtp_create(), do_setnat(), oh323_rtp_read(), and start_rtp().

00807 {
00808    rtp->nat = nat;
00809 }

int ast_rtp_setqos ( struct ast_rtp rtp,
int  tos,
int  cos,
char *  desc 
)

Definition at line 2602 of file rtp.c.

References ast_netsock_set_qos(), and ast_rtp::s.

Referenced by __oh323_rtp_create(), sip_alloc(), and start_rtp().

02603 {
02604    return ast_netsock_set_qos(rtp->s, type_of_service, class_of_service, desc);
02605 }

void ast_rtp_setstun ( struct ast_rtp rtp,
int  stun_enable 
)

Enable STUN capability.

Definition at line 826 of file rtp.c.

References ast_set2_flag, and FLAG_HAS_STUN.

Referenced by gtalk_new().

00827 {
00828    ast_set2_flag(rtp, stun_enable ? 1 : 0, FLAG_HAS_STUN);
00829 }

void ast_rtp_stop ( struct ast_rtp rtp  ) 

Stop RTP session, do not destroy structure

Definition at line 2669 of file rtp.c.

References ast_clear_flag, AST_SCHED_DEL, FLAG_P2P_SENT_MARK, free, ast_rtp::red, ast_rtp::rtcp, ast_rtp::sched, rtp_red::schedid, ast_rtcp::schedid, ast_rtcp::them, and ast_rtp::them.

Referenced by process_sdp(), setup_rtp_connection(), and stop_media_flows().

02670 {
02671    if (rtp->rtcp) {
02672       AST_SCHED_DEL(rtp->sched, rtp->rtcp->schedid);
02673    }
02674    if (rtp->red) {
02675       AST_SCHED_DEL(rtp->sched, rtp->red->schedid);
02676       free(rtp->red);
02677       rtp->red = NULL;
02678    }
02679 
02680    memset(&rtp->them.sin_addr, 0, sizeof(rtp->them.sin_addr));
02681    memset(&rtp->them.sin_port, 0, sizeof(rtp->them.sin_port));
02682    if (rtp->rtcp) {
02683       memset(&rtp->rtcp->them.sin_addr, 0, sizeof(rtp->rtcp->them.sin_addr));
02684       memset(&rtp->rtcp->them.sin_port, 0, sizeof(rtp->rtcp->them.sin_port));
02685    }
02686    
02687    ast_clear_flag(rtp, FLAG_P2P_SENT_MARK);
02688 }

void ast_rtp_stun_request ( struct ast_rtp rtp,
struct sockaddr_in *  suggestion,
const char *  username 
)

Send STUN request for an RTP socket Deprecated, this is just a wrapper for ast_rtp_stun_request().

Definition at line 705 of file rtp.c.

References ast_stun_request(), and ast_rtp::s.

Referenced by gtalk_update_stun(), and jingle_update_stun().

00706 {
00707    ast_stun_request(rtp->s, suggestion, username, NULL);
00708 }

void ast_rtp_unset_m_type ( struct ast_rtp rtp,
int  pt 
)

clear payload type

Definition at line 2251 of file rtp.c.

References rtpPayloadType::code, ast_rtp::current_RTP_PT, rtpPayloadType::isAstFormat, MAX_RTP_PT, rtp_bridge_lock(), and rtp_bridge_unlock().

Referenced by process_sdp().

02252 {
02253    if (pt < 0 || pt > MAX_RTP_PT)
02254       return; /* bogus payload type */
02255 
02256    rtp_bridge_lock(rtp);
02257    rtp->current_RTP_PT[pt].isAstFormat = 0;
02258    rtp->current_RTP_PT[pt].code = 0;
02259    rtp_bridge_unlock(rtp);
02260 }

int ast_rtp_write ( struct ast_rtp rtp,
struct ast_frame f 
)

Bug:
XXX this might never be free'd. Why do we do this?

Definition at line 3749 of file rtp.c.

References ast_codec_pref_getsize(), ast_debug, AST_FORMAT_G723_1, AST_FORMAT_SPEEX, AST_FRAME_TEXT, 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_BE, ast_smoother_free(), ast_smoother_new(), ast_smoother_read(), ast_smoother_set_flags(), ast_smoother_test_flag(), ast_format_list::cur_ms, ast_frame::data, ast_frame::datalen, f, ast_format_list::flags, ast_format_list::fr_len, ast_frame::frametype, ast_format_list::inc_ms, ast_rtp::lasttxformat, LOG_WARNING, ast_frame::offset, ast_rtp::pref, ast_frame::ptr, ast_rtp::red, red_t140_to_red(), ast_rtp::smoother, ast_frame::subclass, and ast_rtp::them.

Referenced by gtalk_write(), jingle_write(), mgcp_write(), oh323_write(), red_write(), sip_write(), skinny_write(), and unistim_write().

03750 {
03751    struct ast_frame *f;
03752    int codec;
03753    int hdrlen = 12;
03754    int subclass;
03755    
03756 
03757    /* If we have no peer, return immediately */ 
03758    if (!rtp->them.sin_addr.s_addr)
03759       return 0;
03760 
03761    /* If there is no data length, return immediately */
03762    if (!_f->datalen && !rtp->red)
03763       return 0;
03764    
03765    /* Make sure we have enough space for RTP header */
03766    if ((_f->frametype != AST_FRAME_VOICE) && (_f->frametype != AST_FRAME_VIDEO) && (_f->frametype != AST_FRAME_TEXT)) {
03767       ast_log(LOG_WARNING, "RTP can only send voice, video and text\n");
03768       return -1;
03769    }
03770 
03771    if (rtp->red) {
03772       /* return 0; */
03773       /* no primary data or generations to send */
03774       if ((_f = red_t140_to_red(rtp->red)) == NULL) 
03775          return 0;
03776    }
03777 
03778    /* The bottom bit of a video subclass contains the marker bit */
03779    subclass = _f->subclass;
03780    if (_f->frametype == AST_FRAME_VIDEO)
03781       subclass &= ~0x1;
03782 
03783    codec = ast_rtp_lookup_code(rtp, 1, subclass);
03784    if (codec < 0) {
03785       ast_log(LOG_WARNING, "Don't know how to send format %s packets with RTP\n", ast_getformatname(_f->subclass));
03786       return -1;
03787    }
03788 
03789    if (rtp->lasttxformat != subclass) {
03790       /* New format, reset the smoother */
03791       ast_debug(1, "Ooh, format changed from %s to %s\n", ast_getformatname(rtp->lasttxformat), ast_getformatname(subclass));
03792       rtp->lasttxformat = subclass;
03793       if (rtp->smoother)
03794          ast_smoother_free(rtp->smoother);
03795       rtp->smoother = NULL;
03796    }
03797 
03798    if (!rtp->smoother && subclass != AST_FORMAT_SPEEX && subclass != AST_FORMAT_G723_1) {
03799       struct ast_format_list fmt = ast_codec_pref_getsize(&rtp->pref, subclass);
03800       if (fmt.inc_ms) { /* if codec parameters is set / avoid division by zero */
03801          if (!(rtp->smoother = ast_smoother_new((fmt.cur_ms * fmt.fr_len) / fmt.inc_ms))) {
03802             ast_log(LOG_WARNING, "Unable to create smoother: format: %d ms: %d len: %d\n", subclass, fmt.cur_ms, ((fmt.cur_ms * fmt.fr_len) / fmt.inc_ms));
03803             return -1;
03804          }
03805          if (fmt.flags)
03806             ast_smoother_set_flags(rtp->smoother, fmt.flags);
03807          ast_debug(1, "Created smoother: format: %d ms: %d len: %d\n", subclass, fmt.cur_ms, ((fmt.cur_ms * fmt.fr_len) / fmt.inc_ms));
03808       }
03809    }
03810    if (rtp->smoother) {
03811       if (ast_smoother_test_flag(rtp->smoother, AST_SMOOTHER_FLAG_BE)) {
03812          ast_smoother_feed_be(rtp->smoother, _f);
03813       } else {
03814          ast_smoother_feed(rtp->smoother, _f);
03815       }
03816 
03817       while ((f = ast_smoother_read(rtp->smoother)) && (f->data.ptr)) {
03818          ast_rtp_raw_write(rtp, f, codec);
03819       }
03820    } else {
03821       /* Don't buffer outgoing frames; send them one-per-packet: */
03822       if (_f->offset < hdrlen) 
03823          f = ast_frdup(_f);   /*! \bug XXX this might never be free'd. Why do we do this? */
03824       else
03825          f = _f;
03826       if (f->data.ptr)
03827          ast_rtp_raw_write(rtp, f, codec);
03828       if (f != _f)
03829          ast_frfree(f);
03830    }
03831       
03832    return 0;
03833 }

int ast_stun_request ( int  s,
struct sockaddr_in *  dst,
const char *  username,
struct sockaddr_in *  answer 
)

Generic STUN request send a generic stun request to the server specified.

Parameters:
s the socket used to send the request
dst the address of the STUN server
username if non null, add the username in the request
answer if non null, the function waits for a response and puts here the externally visible address.
Returns:
0 on success, other values on error. The interface it may change in the future.

Generic STUN request send a generic stun request to the server specified.

Parameters:
s the socket used to send the request
dst the address of the STUN server
username if non null, add the username in the request
answer if non null, the function waits for a response and puts here the externally visible address.
Returns:
0 on success, other values on error.

Definition at line 639 of file rtp.c.

References append_attr_string(), ast_log(), ast_select(), stun_header::ies, LOG_WARNING, stun_header::msglen, stun_header::msgtype, STUN_BINDREQ, stun_get_mapped(), stun_handle_packet(), stun_req_id(), stun_send(), and STUN_USERNAME.

Referenced by ast_rtp_stun_request(), ast_sip_ouraddrfor(), and reload_config().

00641 {
00642    struct stun_header *req;
00643    unsigned char reqdata[1024];
00644    int reqlen, reqleft;
00645    struct stun_attr *attr;
00646    int res = 0;
00647    int retry;
00648    
00649    req = (struct stun_header *)reqdata;
00650    stun_req_id(req);
00651    reqlen = 0;
00652    reqleft = sizeof(reqdata) - sizeof(struct stun_header);
00653    req->msgtype = 0;
00654    req->msglen = 0;
00655    attr = (struct stun_attr *)req->ies;
00656    if (username)
00657       append_attr_string(&attr, STUN_USERNAME, username, &reqlen, &reqleft);
00658    req->msglen = htons(reqlen);
00659    req->msgtype = htons(STUN_BINDREQ);
00660    for (retry = 0; retry < 3; retry++) {  /* XXX make retries configurable */
00661       /* send request, possibly wait for reply */
00662       unsigned char reply_buf[1024];
00663       fd_set rfds;
00664       struct timeval to = { 3, 0 }; /* timeout, make it configurable */
00665       struct sockaddr_in src;
00666       socklen_t srclen;
00667 
00668       res = stun_send(s, dst, req);
00669       if (res < 0) {
00670          ast_log(LOG_WARNING, "ast_stun_request send #%d failed error %d, retry\n",
00671             retry, res);
00672          continue;
00673       }
00674       if (answer == NULL)
00675          break;
00676       FD_ZERO(&rfds);
00677       FD_SET(s, &rfds);
00678       res = ast_select(s + 1, &rfds, NULL, NULL, &to);
00679       if (res <= 0)  /* timeout or error */
00680          continue;
00681       memset(&src, '\0', sizeof(src));
00682       srclen = sizeof(src);
00683       /* XXX pass -1 in the size, because stun_handle_packet might
00684        * write past the end of the buffer.
00685        */
00686       res = recvfrom(s, reply_buf, sizeof(reply_buf) - 1,
00687          0, (struct sockaddr *)&src, &srclen);
00688       if (res < 0) {
00689          ast_log(LOG_WARNING, "ast_stun_request recvfrom #%d failed error %d, retry\n",
00690             retry, res);
00691          continue;
00692       }
00693       memset(answer, '\0', sizeof(struct sockaddr_in));
00694       stun_handle_packet(s, &src, reply_buf, res,
00695          stun_get_mapped, answer);
00696       res = 0; /* signal regular exit */
00697       break;
00698    }
00699    return res;
00700 }

void red_buffer_t140 ( struct ast_rtp rtp,
struct ast_frame f 
)

Buffer t.140 data.

Buffer t.140 data.

Parameters:
rtp 
f frame

Definition at line 4989 of file rtp.c.

References rtp_red::buf_data, ast_frame::data, ast_frame::datalen, ast_frame::ptr, ast_rtp::red, rtp_red::t140, and ast_frame::ts.

Referenced by sip_write().

04990 {
04991    if (f->datalen > -1) {
04992       struct rtp_red *red = rtp->red;
04993       memcpy(&red->buf_data[red->t140.datalen], f->data.ptr, f->datalen); 
04994       red->t140.datalen += f->datalen;
04995       red->t140.ts = f->ts;
04996    }
04997 }

int rtp_red_init ( struct ast_rtp rtp,
int  ti,
int *  red_data_pt,
int  num_gen 
)

Initalize t.140 redudancy.

Parameters:
ti time between each t140red frame is sent
red_pt payloadtype for RTP packet
pt payloadtype numbers for each generation including primary data
num_gen number of redundant generations, primary data excluded
Since:
1.6.1

Initalize t.140 redudancy.

Parameters:
rtp 
ti buffer t140 for ti (msecs) before sending redundant frame
red_data_pt Payloadtypes for primary- and generation-data
num_gen numbers of generations (primary generation not encounted)

Definition at line 4950 of file rtp.c.

References ast_calloc, AST_FORMAT_T140RED, AST_FRAME_TEXT, ast_sched_add(), rtp_red::buf_data, ast_frame::data, ast_frame::datalen, ast_frame::frametype, rtp_red::hdrlen, rtp_red::num_gen, rtp_red::prev_ts, rtp_red::pt, ast_frame::ptr, ast_rtp::red, red_write(), ast_rtp::sched, rtp_red::schedid, ast_frame::subclass, rtp_red::t140, rtp_red::t140red, rtp_red::t140red_data, rtp_red::ti, and ast_frame::ts.

Referenced by process_sdp().

04951 {
04952    struct rtp_red *r;
04953    int x;
04954    
04955    if (!(r = ast_calloc(1, sizeof(struct rtp_red))))
04956       return -1;
04957 
04958    r->t140.frametype = AST_FRAME_TEXT;
04959    r->t140.subclass = AST_FORMAT_T140RED;
04960    r->t140.data.ptr = &r->buf_data; 
04961 
04962    r->t140.ts = 0;
04963    r->t140red = r->t140;
04964    r->t140red.data.ptr = &r->t140red_data;
04965    r->t140red.datalen = 0;
04966    r->ti = ti;
04967    r->num_gen = num_gen;
04968    r->hdrlen = num_gen * 4 + 1;
04969    r->prev_ts = 0;
04970 
04971    for (x = 0; x < num_gen; x++) {
04972       r->pt[x] = red_data_pt[x];
04973       r->pt[x] |= 1 << 7; /* mark redundant generations pt */ 
04974       r->t140red_data[x*4] = r->pt[x];
04975    }
04976    r->t140red_data[x*4] = r->pt[x] = red_data_pt[x]; /* primary pt */
04977    r->schedid = ast_sched_add(rtp->sched, ti, red_write, rtp);
04978    rtp->red = r;
04979 
04980    r->t140.datalen = 0;
04981    
04982    return 0;
04983 }


Generated on 3 Mar 2010 for Asterisk - the Open Source PBX by  doxygen 1.6.1