Tue Mar 2 17:34:27 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_constantssrc (struct ast_rtp *rtp)
 When changing sources, don't generate a new SSRC.
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_a_text().


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

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

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 3270 of file rtp.c.

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

03271 {
03272    struct ast_rtp *rtp = data;
03273    int res;
03274 
03275    rtp->rtcp->sendfur = 1;
03276    res = ast_rtcp_write(data);
03277    
03278    return res;
03279 }

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 500 of file rtp.c.

Referenced by process_sdp().

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

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

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

int ast_rtp_codec_getformat ( int  pt  ) 

get format from predefined dynamic payload format

Definition at line 3750 of file rtp.c.

References rtpPayloadType::code, and MAX_RTP_PT.

Referenced by process_sdp_a_audio().

03751 {
03752    if (pt < 0 || pt >= MAX_RTP_PT)
03753       return 0; /* bogus payload type */
03754 
03755    if (static_RTP_PT[pt].isAstFormat)
03756       return static_RTP_PT[pt].code;
03757    else
03758       return 0;
03759 }

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

Get codec preference.

Definition at line 3745 of file rtp.c.

References ast_rtp::pref.

Referenced by add_codec_to_sdp(), and process_sdp_a_audio().

03746 {
03747    return &rtp->pref;
03748 }

void ast_rtp_codec_setpref ( struct ast_rtp rtp,
struct ast_codec_pref prefs 
)

Set codec preference.

Definition at line 3699 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_a_audio(), register_verify(), set_peer_capabilities(), sip_alloc(), start_rtp(), and transmit_response_with_sdp().

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

void ast_rtp_destroy ( struct ast_rtp rtp  ) 

Destroy RTP session

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

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

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

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

int ast_rtp_fd ( struct ast_rtp rtp  ) 

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

00725 {
00726    return rtp->s;
00727 }

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

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

02671 {
02672    struct ast_rtp *bridged = NULL;
02673 
02674    rtp_bridge_lock(rtp);
02675    bridged = rtp->bridged;
02676    rtp_bridge_unlock(rtp);
02677 
02678    return bridged;
02679 }

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

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

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

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

02653 {
02654    if ((them->sin_family != AF_INET) ||
02655       (them->sin_port != rtp->them.sin_port) ||
02656       (them->sin_addr.s_addr != rtp->them.sin_addr.s_addr)) {
02657       them->sin_family = AF_INET;
02658       them->sin_port = rtp->them.sin_port;
02659       them->sin_addr = rtp->them.sin_addr;
02660       return 1;
02661    }
02662    return 0;
02663 }

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 2791 of file rtp.c.

References __ast_rtp_get_qos().

Referenced by acf_channel_read().

02792 {
02793    double value;
02794    int found;
02795 
02796    value = __ast_rtp_get_qos(rtp, qos, &found);
02797 
02798    if (!found)
02799       return -1;
02800 
02801    snprintf(buf, buflen, "%.0lf", value);
02802 
02803    return 0;
02804 }

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

02726 {
02727    if (rtp == NULL) {
02728       if (option_debug > 1)
02729          ast_log(LOG_DEBUG, "NO RTP Structure? Kidding me? \n");
02730       return 0;
02731    }
02732    if (option_debug > 1 && rtp->rtcp == NULL) {
02733       ast_log(LOG_DEBUG, "NO RTCP structure. Maybe in RTP p2p bridging mode? \n");
02734    }
02735 
02736    switch (value) {
02737    case AST_RTP_TXCOUNT:
02738       return (unsigned int) rtp->txcount;
02739    case AST_RTP_RXCOUNT:
02740       return (unsigned int) rtp->rxcount;
02741    case AST_RTP_TXJITTER:
02742       return (unsigned int) (rtp->rxjitter * 100.0);
02743    case AST_RTP_RXJITTER:
02744       return (unsigned int) (rtp->rtcp ? (rtp->rtcp->reported_jitter / (unsigned int) 65536.0) : 0);
02745    case AST_RTP_RXPLOSS:
02746       return rtp->rtcp ? (rtp->rtcp->expected_prior - rtp->rtcp->received_prior) : 0;
02747    case AST_RTP_TXPLOSS:
02748       return rtp->rtcp ? rtp->rtcp->reported_lost : 0;
02749    case AST_RTP_RTT:
02750       return (unsigned int) (rtp->rtcp ? (rtp->rtcp->rtt * 100) : 0);
02751    }
02752    return 0;   /* To make the compiler happy */
02753 }

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

02999 {
03000    if (qual && rtp) {
03001       qual->local_ssrc   = rtp->ssrc;
03002       qual->local_jitter = rtp->rxjitter;
03003       qual->local_count  = rtp->rxcount;
03004       qual->remote_ssrc  = rtp->themssrc;
03005       qual->remote_count = rtp->txcount;
03006 
03007       if (rtp->rtcp) {
03008          qual->local_lostpackets  = rtp->rtcp->expected_prior - rtp->rtcp->received_prior;
03009          qual->remote_lostpackets = rtp->rtcp->reported_lost;
03010          qual->remote_jitter      = rtp->rtcp->reported_jitter / 65536.0;
03011          qual->rtt                = rtp->rtcp->rtt;
03012       }
03013    }
03014 
03015    switch (qtype) {
03016    case RTPQOS_SUMMARY:
03017       return __ast_rtp_get_quality(rtp);
03018    case RTPQOS_JITTER:
03019       return __ast_rtp_get_quality_jitter(rtp);
03020    case RTPQOS_LOSS:
03021       return __ast_rtp_get_quality_loss(rtp);
03022    case RTPQOS_RTT:
03023       return __ast_rtp_get_quality_rtt(rtp);
03024    }
03025 
03026    return NULL;
03027 }

int ast_rtp_get_rtpholdtimeout ( struct ast_rtp rtp  ) 

Get rtp hold timeout.

Definition at line 784 of file rtp.c.

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

Referenced by check_rtp_timeout().

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

int ast_rtp_get_rtpkeepalive ( struct ast_rtp rtp  ) 

Get RTP keepalive interval.

Definition at line 792 of file rtp.c.

References ast_rtp::rtpkeepalive.

Referenced by check_rtp_timeout().

00793 {
00794    return rtp->rtpkeepalive;
00795 }

int ast_rtp_get_rtptimeout ( struct ast_rtp rtp  ) 

Get rtp timeout.

Definition at line 776 of file rtp.c.

References ast_rtp::rtptimeout.

Referenced by check_rtp_timeout().

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

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

Definition at line 812 of file rtp.c.

References ast_test_flag, and FLAG_NAT_ACTIVE.

Referenced by sip_get_rtp_peer().

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

void ast_rtp_init ( void   ) 

Initialize the RTP system in Asterisk.

Definition at line 4901 of file rtp.c.

References __ast_rtp_reload(), and ast_cli_register_multiple().

Referenced by main().

04902 {
04903    ast_cli_register_multiple(cli_rtp, sizeof(cli_rtp) / sizeof(struct ast_cli_entry));
04904    __ast_rtp_reload(0);
04905 }

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

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

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 2404 of file rtp.c.

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

Referenced by process_sdp().

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

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

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

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

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

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

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

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

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 2599 of file rtp.c.

References ast_rtp_new_with_bindaddr().

02600 {
02601    struct in_addr ia;
02602 
02603    memset(&ia, 0, sizeof(ia));
02604    return ast_rtp_new_with_bindaddr(sched, io, rtcpenable, callbackmode, ia);
02605 }

void ast_rtp_new_init ( struct ast_rtp rtp  ) 

Initialize a new RTP structure.

reload rtp configuration

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

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

void ast_rtp_new_source ( struct ast_rtp rtp  ) 

Definition at line 2617 of file rtp.c.

References ast_random(), ast_rtp::constantssrc, ast_rtp::set_marker_bit, and ast_rtp::ssrc.

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

02618 {
02619    if (rtp) {
02620       rtp->set_marker_bit = 1;
02621       if (!rtp->constantssrc) {
02622          rtp->ssrc = ast_random();
02623       }
02624    }
02625 }

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

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

int ast_rtp_proto_register ( struct ast_rtp_protocol proto  ) 

Register an RTP channel client.

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

03857 {
03858    struct ast_rtp_protocol *cur;
03859 
03860    AST_RWLIST_WRLOCK(&protos);
03861    AST_RWLIST_TRAVERSE(&protos, cur, list) { 
03862       if (!strcmp(cur->type, proto->type)) {
03863          ast_log(LOG_WARNING, "Tried to register same protocol '%s' twice\n", cur->type);
03864          AST_RWLIST_UNLOCK(&protos);
03865          return -1;
03866       }
03867    }
03868    AST_RWLIST_INSERT_HEAD(&protos, proto, list);
03869    AST_RWLIST_UNLOCK(&protos);
03870    
03871    return 0;
03872 }

void ast_rtp_proto_unregister ( struct ast_rtp_protocol proto  ) 

Unregister an RTP channel client.

Definition at line 3848 of file rtp.c.

References AST_RWLIST_REMOVE, AST_RWLIST_UNLOCK, and AST_RWLIST_WRLOCK.

Referenced by load_module(), and unload_module().

03849 {
03850    AST_RWLIST_WRLOCK(&protos);
03851    AST_RWLIST_REMOVE(&protos, proto, list);
03852    AST_RWLIST_UNLOCK(&protos);
03853 }

void ast_rtp_pt_clear ( struct ast_rtp rtp  ) 

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

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

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

void ast_rtp_pt_copy ( struct ast_rtp dest,
struct ast_rtp src 
)

Copy payload types between RTP structures.

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

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

void ast_rtp_pt_default ( struct ast_rtp rtp  ) 

Set payload types to defaults.

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

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

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

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

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

int ast_rtp_reload ( void   ) 

Initialize RTP subsystem

Definition at line 4895 of file rtp.c.

References __ast_rtp_reload().

04896 {
04897    return __ast_rtp_reload(1);
04898 }

void ast_rtp_reset ( struct ast_rtp rtp  ) 

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

02703 {
02704    memset(&rtp->rxcore, 0, sizeof(rtp->rxcore));
02705    memset(&rtp->txcore, 0, sizeof(rtp->txcore));
02706    memset(&rtp->dtmfmute, 0, sizeof(rtp->dtmfmute));
02707    rtp->lastts = 0;
02708    rtp->lastdigitts = 0;
02709    rtp->lastrxts = 0;
02710    rtp->lastividtimestamp = 0;
02711    rtp->lastovidtimestamp = 0;
02712    rtp->lastitexttimestamp = 0;
02713    rtp->lastotexttimestamp = 0;
02714    rtp->lasteventseqn = 0;
02715    rtp->lastevent = 0;
02716    rtp->lasttxformat = 0;
02717    rtp->lastrxformat = 0;
02718    rtp->dtmf_timeout = 0;
02719    rtp->dtmfsamples = 0;
02720    rtp->seqno = 0;
02721    rtp->rxseqno = 0;
02722 }

int ast_rtp_sendcng ( struct ast_rtp rtp,
int  level 
)

generate comfort noice (CNG)

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

03546 {
03547    unsigned int *rtpheader;
03548    int hdrlen = 12;
03549    int res;
03550    int payload;
03551    char data[256];
03552    level = 127 - (level & 0x7f);
03553    payload = ast_rtp_lookup_code(rtp, 0, AST_RTP_CN);
03554 
03555    /* If we have no peer, return immediately */ 
03556    if (!rtp->them.sin_addr.s_addr)
03557       return 0;
03558 
03559    rtp->dtmfmute = ast_tvadd(ast_tvnow(), ast_tv(0, 500000));
03560 
03561    /* Get a pointer to the header */
03562    rtpheader = (unsigned int *)data;
03563    rtpheader[0] = htonl((2 << 30) | (1 << 23) | (payload << 16) | (rtp->seqno++));
03564    rtpheader[1] = htonl(rtp->lastts);
03565    rtpheader[2] = htonl(rtp->ssrc); 
03566    data[12] = level;
03567    if (rtp->them.sin_port && rtp->them.sin_addr.s_addr) {
03568       res = sendto(rtp->s, (void *)rtpheader, hdrlen + 1, 0, (struct sockaddr *)&rtp->them, sizeof(rtp->them));
03569       if (res <0) 
03570          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));
03571       if (rtp_debug_test_addr(&rtp->them))
03572          ast_verbose("Sent Comfort Noise RTP packet to %s:%u (type %d, seq %u, ts %u, len %d)\n"
03573                , ast_inet_ntoa(rtp->them.sin_addr), ntohs(rtp->them.sin_port), payload, rtp->seqno, rtp->lastts,res - hdrlen);         
03574          
03575    }
03576    return 0;
03577 }

int ast_rtp_senddigit_begin ( struct ast_rtp rtp,
char  digit 
)

Send begin frames for DTMF.

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

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

int ast_rtp_senddigit_end ( struct ast_rtp rtp,
char  digit 
)

Send end packets for DTMF.

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

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

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 2642 of file rtp.c.

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

Referenced by handle_request_invite().

02643 {
02644    rtp->altthem.sin_port = alt->sin_port;
02645    rtp->altthem.sin_addr = alt->sin_addr;
02646    if (rtp->rtcp) {
02647       rtp->rtcp->altthem.sin_port = htons(ntohs(alt->sin_port) + 1);
02648       rtp->rtcp->altthem.sin_addr = alt->sin_addr;
02649    }
02650 }

void ast_rtp_set_callback ( struct ast_rtp rtp,
ast_rtp_callback  callback 
)

Definition at line 802 of file rtp.c.

References ast_rtp::callback.

Referenced by start_rtp().

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

void ast_rtp_set_constantssrc ( struct ast_rtp rtp  ) 

When changing sources, don't generate a new SSRC.

Definition at line 2612 of file rtp.c.

References ast_rtp::constantssrc.

Referenced by create_addr_from_peer(), and handle_request_invite().

02613 {
02614    rtp->constantssrc = 1;
02615 }

void ast_rtp_set_data ( struct ast_rtp rtp,
void *  data 
)

Definition at line 797 of file rtp.c.

References ast_rtp::data.

Referenced by start_rtp().

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

void ast_rtp_set_m_type ( struct ast_rtp rtp,
int  pt 
)

Activate payload type.

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

02245 {
02246    if (pt < 0 || pt >= MAX_RTP_PT || static_RTP_PT[pt].code == 0) 
02247       return; /* bogus payload type */
02248 
02249    rtp_bridge_lock(rtp);
02250    rtp->current_RTP_PT[pt] = static_RTP_PT[pt];
02251    rtp_bridge_unlock(rtp);
02252 } 

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

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

02628 {
02629    rtp->them.sin_port = them->sin_port;
02630    rtp->them.sin_addr = them->sin_addr;
02631    if (rtp->rtcp) {
02632       int h = ntohs(them->sin_port);
02633       rtp->rtcp->them.sin_port = htons(h + 1);
02634       rtp->rtcp->them.sin_addr = them->sin_addr;
02635    }
02636    rtp->rxseqno = 0;
02637    /* If strict RTP protection is enabled switch back to the learn state so we don't drop packets from above */
02638    if (strictrtp)
02639       rtp->strict_rtp_state = STRICT_RTP_LEARN;
02640 }

void ast_rtp_set_rtpholdtimeout ( struct ast_rtp rtp,
int  timeout 
)

Set rtp hold timeout.

Definition at line 764 of file rtp.c.

References ast_rtp::rtpholdtimeout.

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

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

void ast_rtp_set_rtpkeepalive ( struct ast_rtp rtp,
int  period 
)

set RTP keepalive interval

Definition at line 770 of file rtp.c.

References ast_rtp::rtpkeepalive.

Referenced by create_addr_from_peer(), and sip_alloc().

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

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 2271 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(), process_sdp_a_audio(), process_sdp_a_text(), process_sdp_a_video(), set_dtmf_payload(), and setup_rtp_connection().

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

void ast_rtp_set_rtptimeout ( struct ast_rtp rtp,
int  timeout 
)

Set rtp timeout.

Definition at line 758 of file rtp.c.

References ast_rtp::rtptimeout.

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

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

void ast_rtp_set_rtptimers_onhold ( struct ast_rtp rtp  ) 

Definition at line 751 of file rtp.c.

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

Referenced by handle_response_invite().

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

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

02806                                                                      {
02807    char *audioqos;
02808    char *audioqos_jitter;
02809    char *audioqos_loss;
02810    char *audioqos_rtt;
02811    struct ast_channel *bridge;
02812 
02813    if (!rtp || !chan)
02814       return;
02815 
02816    bridge = ast_bridged_channel(chan);
02817 
02818    audioqos        = ast_rtp_get_quality(rtp, NULL, RTPQOS_SUMMARY);
02819    audioqos_jitter = ast_rtp_get_quality(rtp, NULL, RTPQOS_JITTER);
02820    audioqos_loss   = ast_rtp_get_quality(rtp, NULL, RTPQOS_LOSS);
02821    audioqos_rtt    = ast_rtp_get_quality(rtp, NULL, RTPQOS_RTT);
02822 
02823    pbx_builtin_setvar_helper(chan, "RTPAUDIOQOS", audioqos);
02824    pbx_builtin_setvar_helper(chan, "RTPAUDIOQOSJITTER", audioqos_jitter);
02825    pbx_builtin_setvar_helper(chan, "RTPAUDIOQOSLOSS", audioqos_loss);
02826    pbx_builtin_setvar_helper(chan, "RTPAUDIOQOSRTT", audioqos_rtt);
02827 
02828    if (!bridge)
02829       return;
02830 
02831    pbx_builtin_setvar_helper(bridge, "RTPAUDIOQOSBRIDGED", audioqos);
02832    pbx_builtin_setvar_helper(bridge, "RTPAUDIOQOSJITTERBRIDGED", audioqos_jitter);
02833    pbx_builtin_setvar_helper(bridge, "RTPAUDIOQOSLOSSBRIDGED", audioqos_loss);
02834    pbx_builtin_setvar_helper(bridge, "RTPAUDIOQOSRTTBRIDGED", audioqos_rtt);
02835 }

void ast_rtp_setdtmf ( struct ast_rtp rtp,
int  dtmf 
)

Indicate whether this RTP session is carrying DTMF or not.

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

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

void ast_rtp_setdtmfcompensate ( struct ast_rtp rtp,
int  compensate 
)

Compensate for devices that send RFC2833 packets all at once.

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

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

void ast_rtp_setnat ( struct ast_rtp rtp,
int  nat 
)

Definition at line 807 of file rtp.c.

References ast_rtp::nat.

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

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

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

Definition at line 2607 of file rtp.c.

References ast_netsock_set_qos(), and ast_rtp::s.

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

02608 {
02609    return ast_netsock_set_qos(rtp->s, type_of_service, class_of_service, desc);
02610 }

void ast_rtp_setstun ( struct ast_rtp rtp,
int  stun_enable 
)

Enable STUN capability.

Definition at line 827 of file rtp.c.

References ast_set2_flag, and FLAG_HAS_STUN.

Referenced by gtalk_new().

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

void ast_rtp_stop ( struct ast_rtp rtp  ) 

Stop RTP session, do not destroy structure

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

02682 {
02683    if (rtp->rtcp) {
02684       AST_SCHED_DEL(rtp->sched, rtp->rtcp->schedid);
02685    }
02686    if (rtp->red) {
02687       AST_SCHED_DEL(rtp->sched, rtp->red->schedid);
02688       free(rtp->red);
02689       rtp->red = NULL;
02690    }
02691 
02692    memset(&rtp->them.sin_addr, 0, sizeof(rtp->them.sin_addr));
02693    memset(&rtp->them.sin_port, 0, sizeof(rtp->them.sin_port));
02694    if (rtp->rtcp) {
02695       memset(&rtp->rtcp->them.sin_addr, 0, sizeof(rtp->rtcp->them.sin_addr));
02696       memset(&rtp->rtcp->them.sin_port, 0, sizeof(rtp->rtcp->them.sin_port));
02697    }
02698    
02699    ast_clear_flag(rtp, FLAG_P2P_SENT_MARK);
02700 }

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 706 of file rtp.c.

References ast_stun_request(), and ast_rtp::s.

Referenced by gtalk_update_stun(), and jingle_update_stun().

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

void ast_rtp_unset_m_type ( struct ast_rtp rtp,
int  pt 
)

clear payload type

Definition at line 2256 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_a_audio(), and process_sdp_a_video().

02257 {
02258    if (pt < 0 || pt >= MAX_RTP_PT)
02259       return; /* bogus payload type */
02260 
02261    rtp_bridge_lock(rtp);
02262    rtp->current_RTP_PT[pt].isAstFormat = 0;
02263    rtp->current_RTP_PT[pt].code = 0;
02264    rtp_bridge_unlock(rtp);
02265 }

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

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

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

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

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

05006 {
05007    if (f->datalen > -1) {
05008       struct rtp_red *red = rtp->red;
05009       memcpy(&red->buf_data[red->t140.datalen], f->data.ptr, f->datalen); 
05010       red->t140.datalen += f->datalen;
05011       red->t140.ts = f->ts;
05012    }
05013 }

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

04967 {
04968    struct rtp_red *r;
04969    int x;
04970    
04971    if (!(r = ast_calloc(1, sizeof(struct rtp_red))))
04972       return -1;
04973 
04974    r->t140.frametype = AST_FRAME_TEXT;
04975    r->t140.subclass = AST_FORMAT_T140RED;
04976    r->t140.data.ptr = &r->buf_data; 
04977 
04978    r->t140.ts = 0;
04979    r->t140red = r->t140;
04980    r->t140red.data.ptr = &r->t140red_data;
04981    r->t140red.datalen = 0;
04982    r->ti = ti;
04983    r->num_gen = num_gen;
04984    r->hdrlen = num_gen * 4 + 1;
04985    r->prev_ts = 0;
04986 
04987    for (x = 0; x < num_gen; x++) {
04988       r->pt[x] = red_data_pt[x];
04989       r->pt[x] |= 1 << 7; /* mark redundant generations pt */ 
04990       r->t140red_data[x*4] = r->pt[x];
04991    }
04992    r->t140red_data[x*4] = r->pt[x] = red_data_pt[x]; /* primary pt */
04993    r->schedid = ast_sched_add(rtp->sched, ti, red_write, rtp);
04994    rtp->red = r;
04995 
04996    r->t140.datalen = 0;
04997    
04998    return 0;
04999 }


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