src/ortp.c

00001 /*
00002   The oRTP library is an RTP (Realtime Transport Protocol - rfc3550) stack.
00003   Copyright (C) 2001  Simon MORLAT simon.morlat@linphone.org
00004 
00005   This library is free software; you can redistribute it and/or
00006   modify it under the terms of the GNU Lesser General Public
00007   License as published by the Free Software Foundation; either
00008   version 2.1 of the License, or (at your option) any later version.
00009 
00010   This library is distributed in the hope that it will be useful,
00011   but WITHOUT ANY WARRANTY; without even the implied warranty of
00012   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00013   Lesser General Public License for more details.
00014 
00015   You should have received a copy of the GNU Lesser General Public
00016   License along with this library; if not, write to the Free Software
00017   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00018 */
00019 
00020 
00021 #if defined(WIN32) || defined(_WIN32_WCE)
00022 #include "ortp-config-win32.h"
00023 #else
00024 #include "ortp-config.h"
00025 #endif
00026 #include "ortp/ortp.h"
00027 #include "scheduler.h"
00028 
00029 rtp_stats_t ortp_global_stats;
00030 
00031 #ifdef ENABLE_MEMCHECK
00032 int ortp_allocations=0;
00033 #endif
00034 
00035 
00036 RtpScheduler *__ortp_scheduler;
00037 
00038 
00039 
00040 extern void av_profile_init(RtpProfile *profile);
00041 
00042 static void init_random_number_generator(){
00043         struct timeval t;
00044         gettimeofday(&t,NULL);
00045         srandom(t.tv_usec+t.tv_sec);
00046 }
00047 
00048 
00049 #ifdef WIN32
00050 static bool_t win32_init_sockets(void){
00051         WORD wVersionRequested;
00052         WSADATA wsaData;
00053         int i;
00054         
00055         wVersionRequested = MAKEWORD(1,1);
00056         if( (i = WSAStartup(wVersionRequested,  &wsaData))!=0)
00057         {
00058                 ortp_error("Unable to initialize windows socket api, reason: %d",i);
00059                 return FALSE;
00060         }
00061         return TRUE;
00062 }
00063 #endif
00064 
00069 void ortp_init()
00070 {
00071         static bool_t initialized=FALSE;
00072         if (initialized) return;
00073         initialized=TRUE;
00074 
00075 #ifdef WIN32
00076         win32_init_sockets();
00077 #endif
00078 
00079         av_profile_init(&av_profile);
00080         ortp_global_stats_reset();
00081         init_random_number_generator();
00082         ortp_message("oRTP-" ORTP_VERSION " initialized.");
00083 }
00084 
00085 
00091 void ortp_scheduler_init()
00092 {
00093         static bool_t initialized=FALSE;
00094         if (initialized) return;
00095         initialized=TRUE;
00096 #ifdef __hpux
00097         /* on hpux, we must block sigalrm on the main process, because signal delivery
00098         is ?random?, well, sometimes the SIGALRM goes to both the main thread and the 
00099         scheduler thread */
00100         sigset_t set;
00101         sigemptyset(&set);
00102         sigaddset(&set,SIGALRM);
00103         sigprocmask(SIG_BLOCK,&set,NULL);
00104 #endif /* __hpux */
00105 
00106         __ortp_scheduler=rtp_scheduler_new();
00107         rtp_scheduler_start(__ortp_scheduler);
00108         //sleep(1);
00109 }
00110 
00111 
00116 void ortp_exit()
00117 {
00118         if (__ortp_scheduler!=NULL)
00119         {
00120                 rtp_scheduler_destroy(__ortp_scheduler);
00121                 __ortp_scheduler=NULL;
00122         }
00123 }
00124 
00125 RtpScheduler * ortp_get_scheduler()
00126 {
00127         if (__ortp_scheduler==NULL) ortp_error("Cannot use the scheduled mode: the scheduler is not "
00128                                                                         "started. Call ortp_scheduler_init() at the begginning of the application.");
00129         return __ortp_scheduler;
00130 }
00131 
00132 
00133 static FILE *__log_file=0;
00134 
00139 void ortp_set_log_file(FILE *file)
00140 {
00141         __log_file=file;
00142 }
00143 
00144 static void __ortp_logv_out(OrtpLogLevel lev, const char *fmt, va_list args);
00145 
00146 OrtpLogFunc ortp_logv_out=__ortp_logv_out;
00147 
00152 void ortp_set_log_handler(OrtpLogFunc func){
00153         ortp_logv_out=func;
00154 }
00155 
00156 
00157 unsigned int __ortp_log_mask=ORTP_WARNING|ORTP_ERROR|ORTP_FATAL;
00158 
00163 void ortp_set_log_level_mask(int levelmask){
00164         __ortp_log_mask=levelmask;
00165 }
00166 
00167 static char * _strdup_vprintf(const char *fmt, va_list ap)
00168 {
00169         /* Guess we need no more than 100 bytes. */
00170         int n, size = 200;
00171         char *p,*np;
00172         //va_list ap;
00173         if ((p = (char *) ortp_malloc (size)) == NULL)
00174                 return NULL;
00175         while (1)
00176         {
00177                 /* Try to print in the allocated space. */
00178                 //va_start(ap, fmt);
00179                 n = vsnprintf (p, size, fmt, ap);
00180                 //va_end(ap);
00181                 /* If that worked, return the string. */
00182                 if (n > -1 && n < size)
00183                         return p;
00184                 //printf("Reallocing space.\n");
00185                 /* Else try again with more space. */
00186                 if (n > -1)     /* glibc 2.1 */
00187                         size = n + 1;   /* precisely what is needed */
00188                 else            /* glibc 2.0 */
00189                         size *= 2;      /* twice the old size */
00190                 if ((np = (char *) ortp_realloc (p, size)) == NULL)
00191                   {
00192                     free(p);
00193                     return NULL;
00194                   }
00195                 else
00196                   {
00197                     p = np;
00198                   }
00199         }
00200 }
00201 
00202 char *ortp_strdup_printf(const char *fmt,...){
00203         char *ret;
00204         va_list args;
00205         va_start (args, fmt);
00206         ret=_strdup_vprintf(fmt, args);
00207         va_end (args);
00208         return ret;
00209 }
00210 
00211 #if     defined(WIN32) || defined(_WIN32_WCE)
00212 #define ENDLINE "\r\n"
00213 #else
00214 #define ENDLINE "\n"
00215 #endif
00216 
00217 #if     defined(WIN32) || defined(_WIN32_WCE)
00218 void ortp_logv(int level, const char *fmt, va_list args)
00219 {
00220         if (ortp_logv_out!=NULL && ortp_log_level_enabled(level))
00221                 ortp_logv_out(level,fmt,args);
00222 #if !defined(_WIN32_WCE)
00223         if ((level)==ORTP_FATAL) abort();
00224 #endif
00225 }
00226 #endif
00227 
00228 static void __ortp_logv_out(OrtpLogLevel lev, const char *fmt, va_list args){
00229         const char *lname="undef";
00230         char *msg;
00231         if (__log_file==NULL) __log_file=stderr;
00232         switch(lev){
00233                 case ORTP_DEBUG:
00234                         lname="debug";
00235                         break;
00236                 case ORTP_MESSAGE:
00237                         lname="message";
00238                         break;
00239                 case ORTP_WARNING:
00240                         lname="warning";
00241                         break;
00242                 case ORTP_ERROR:
00243                         lname="error";
00244                         break;
00245                 case ORTP_FATAL:
00246                         lname="fatal";
00247                         break;
00248                 default:
00249                         ortp_fatal("Bad level !");
00250         }
00251         msg=_strdup_vprintf(fmt,args);
00252         fprintf(__log_file,"ortp-%s-%s" ENDLINE,lname,msg);
00253         ortp_free(msg);
00254 }
00255 
00259 void ortp_global_stats_display()
00260 {
00261         rtp_stats_display(&ortp_global_stats,"Global statistics");
00262 #ifdef ENABLE_MEMCHECK  
00263         printf("Unfreed allocations: %i\n",ortp_allocations);
00264 #endif
00265 }
00266 
00270 void rtp_stats_display(const rtp_stats_t *stats, const char *header)
00271 {
00272 #ifndef WIN32
00273   ortp_log(ORTP_MESSAGE,
00274            "oRTP-stats:\n   %s :\n",
00275            header);
00276   ortp_log(ORTP_MESSAGE,
00277            " number of rtp packet sent=%lld\n",
00278            (long long)stats->packet_sent);
00279   ortp_log(ORTP_MESSAGE,
00280            " number of rtp bytes sent=%lld bytes\n",
00281            (long long)stats->sent);
00282   ortp_log(ORTP_MESSAGE,
00283            " number of rtp packet received=%lld\n",
00284            (long long)stats->packet_recv);
00285   ortp_log(ORTP_MESSAGE,
00286            " number of rtp bytes received=%lld bytes\n",
00287            (long long)stats->hw_recv);
00288   ortp_log(ORTP_MESSAGE,
00289            " number of incoming rtp bytes successfully delivered to the application=%lld \n",
00290            (long long)stats->recv);
00291   ortp_log(ORTP_MESSAGE,
00292            " number of times the application queried a packet that didn't exist=%lld \n",
00293            (long long)stats->unavaillable);
00294   ortp_log(ORTP_MESSAGE,
00295            " number of rtp packet lost=%lld\n",
00296            (long long) stats->cum_packet_loss);
00297   ortp_log(ORTP_MESSAGE,
00298            " number of rtp packets received too late=%lld\n",
00299            (long long)stats->outoftime);
00300   ortp_log(ORTP_MESSAGE,
00301            " number of bad formatted rtp packets=%lld\n",
00302            (long long)stats->bad);
00303   ortp_log(ORTP_MESSAGE,
00304            " number of packet discarded because of queue overflow=%lld\n",
00305            (long long)stats->discarded);
00306 #else
00307   ortp_log(ORTP_MESSAGE,
00308            "oRTP-stats:\n   %s :\n",
00309            header);
00310   ortp_log(ORTP_MESSAGE,
00311            " number of rtp packet sent=%I64d\n",
00312            (uint64_t)stats->packet_sent);
00313   ortp_log(ORTP_MESSAGE,
00314            " number of rtp bytes sent=%I64d bytes\n",
00315            (uint64_t)stats->sent);
00316   ortp_log(ORTP_MESSAGE,
00317            " number of rtp packet received=%I64d\n",
00318            (uint64_t)stats->packet_recv);
00319   ortp_log(ORTP_MESSAGE,
00320            " number of rtp bytes received=%I64d bytes\n",
00321            (uint64_t)stats->hw_recv);
00322   ortp_log(ORTP_MESSAGE,
00323            " number of incoming rtp bytes successfully delivered to the application=%I64d \n",
00324            (uint64_t)stats->recv);
00325   ortp_log(ORTP_MESSAGE,
00326            " number of times the application queried a packet that didn't exist=%I64d \n",
00327            (uint64_t)stats->unavaillable);
00328   ortp_log(ORTP_MESSAGE,
00329            " number of rtp packet lost=%I64d\n",
00330            (uint64_t) stats->cum_packet_loss);
00331   ortp_log(ORTP_MESSAGE,
00332            " number of rtp packets received too late=%I64d\n",
00333            (uint64_t)stats->outoftime);
00334   ortp_log(ORTP_MESSAGE,
00335                  " number of bad formatted rtp packets=%I64d\n",
00336            (uint64_t)stats->bad);
00337   ortp_log(ORTP_MESSAGE,
00338            " number of packet discarded because of queue overflow=%I64d\n",
00339            (uint64_t)stats->discarded);
00340 #endif
00341 }
00342 
00343 void ortp_global_stats_reset(){
00344         memset(&ortp_global_stats,0,sizeof(rtp_stats_t));
00345 }
00346 
00347 rtp_stats_t *ortp_get_global_stats(){
00348         return &ortp_global_stats;
00349 }
00350 
00351 void rtp_stats_reset(rtp_stats_t *stats){
00352         memset((void*)stats,0,sizeof(rtp_stats_t));
00353 }
00354 
00355 
00362 bool_t ortp_min_version_required(int major, int minor, int micro){
00363         return ((major*1000000) + (minor*1000) + micro) <= 
00364                    ((ORTP_MAJOR_VERSION*1000000) + (ORTP_MINOR_VERSION*1000) + ORTP_MICRO_VERSION);
00365 }

Generated on Thu Feb 14 16:10:59 2008 for oRTP by  doxygen 1.5.4