LCOV - code coverage report
Current view: top level - utils - os_divers.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 468 594 78.8 %
Date: 2021-04-29 23:48:07 Functions: 64 71 90.1 %

          Line data    Source code
       1             : /*
       2             :  *                      GPAC - Multimedia Framework C SDK
       3             :  *
       4             :  *                      Authors: Jean Le Feuvre
       5             :  *                      Copyright (c) Telecom ParisTech 2000-2020
       6             :  *                                      All rights reserved
       7             :  *
       8             :  *  This file is part of GPAC / common tools sub-project
       9             :  *
      10             :  *  GPAC is free software; you can redistribute it and/or modify
      11             :  *  it under the terms of the GNU Lesser General Public License as published by
      12             :  *  the Free Software Foundation; either version 2, or (at your option)
      13             :  *  any later version.
      14             :  *
      15             :  *  GPAC is distributed in the hope that it will be useful,
      16             :  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
      17             :  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      18             :  *  GNU Lesser General Public License for more details.
      19             :  *
      20             :  *  You should have received a copy of the GNU Lesser General Public
      21             :  *  License along with this library; see the file COPYING.  If not, write to
      22             :  *  the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
      23             :  *
      24             :  */
      25             : 
      26             : #include <gpac/tools.h>
      27             : #include <gpac/network.h>
      28             : #include <gpac/config_file.h>
      29             : 
      30             : #if defined(_WIN32_WCE)
      31             : 
      32             : #include <winbase.h>
      33             : #include <winsock.h>
      34             : #include <tlhelp32.h>
      35             : //#include <direct.h>
      36             : 
      37             : #if !defined(__GNUC__)
      38             : #pragma comment(lib, "toolhelp")
      39             : #endif
      40             : 
      41             : #elif defined(WIN32)
      42             : 
      43             : #include <time.h>
      44             : #include <sys/timeb.h>
      45             : #include <io.h>
      46             : #include <windows.h>
      47             : #include <tlhelp32.h>
      48             : #include <direct.h>
      49             : 
      50             : #if !defined(__GNUC__)
      51             : #pragma comment(lib, "winmm")
      52             : #endif
      53             : 
      54             : #else
      55             : 
      56             : #include <time.h>
      57             : #include <sys/stat.h>
      58             : #include <sys/time.h>
      59             : #include <dirent.h>
      60             : #include <unistd.h>
      61             : #include <sys/times.h>
      62             : #include <sys/resource.h>
      63             : 
      64             : #ifndef __BEOS__
      65             : #include <errno.h>
      66             : #endif
      67             : 
      68             : #define SLEEP_ABS_SELECT                1
      69             : 
      70             : static u32 sys_start_time = 0;
      71             : static u64 sys_start_time_hr = 0;
      72             : #endif
      73             : 
      74             : 
      75             : #ifndef _WIN32_WCE
      76             : #include <locale.h>
      77             : #endif
      78             : 
      79             : 
      80             : #include <gpac/revision.h>
      81             : #define GPAC_FULL_VERSION       GPAC_VERSION "-rev" GPAC_GIT_REVISION
      82             : 
      83             : #define GPAC_COPYRIGHT "(c) 2000-2021 Telecom Paris distributed under LGPL v2.1+ - http://gpac.io"
      84             : 
      85             : GF_EXPORT
      86        6861 : const char *gf_gpac_version()
      87             : {
      88        6861 :         return GPAC_FULL_VERSION;
      89             : }
      90             : 
      91             : #ifdef GPAC_MP4BOX_MINI
      92             : #define MINI_BUILD_DISCLAIMER "\n\tMINI build (encoders, decoders, audio and video output disabled)"
      93             : #endif
      94             : 
      95             : GF_EXPORT
      96          10 : const char *gf_gpac_copyright()
      97             : {
      98          10 :         return GPAC_COPYRIGHT
      99             : #ifdef GPAC_MP4BOX_MINI
     100             :                 MINI_BUILD_DISCLAIMER
     101             : #endif
     102             :                 ;
     103             : }
     104             : GF_EXPORT
     105          13 : const char *gf_gpac_copyright_cite()
     106             : {
     107          13 :         return GPAC_COPYRIGHT
     108             : #ifdef GPAC_MP4BOX_MINI
     109             :                 MINI_BUILD_DISCLAIMER
     110             : #endif
     111             :                 "\n\n" \
     112             :                         "Please cite our work in your research:\n"\
     113             :                 "\tGPAC Filters: https://doi.org/10.1145/3339825.3394929\n"\
     114             :                 "\tGPAC: https://doi.org/10.1145/1291233.1291452\n"\
     115             :                 ;
     116             : 
     117             : }
     118             : 
     119             : GF_EXPORT
     120           5 : u32 gf_gpac_abi_major()
     121             : {
     122           5 :         return GPAC_VERSION_MAJOR;
     123             : }
     124             : GF_EXPORT
     125           5 : u32 gf_gpac_abi_minor()
     126             : {
     127           5 :         return GPAC_VERSION_MINOR;
     128             : }
     129             : GF_EXPORT
     130           1 : u32 gf_gpac_abi_micro()
     131             : {
     132           1 :         return GPAC_VERSION_MICRO;
     133             : }
     134             : 
     135             : 
     136             : #ifndef WIN32
     137             : 
     138             : GF_EXPORT
     139     1861891 : u32 gf_sys_clock()
     140             : {
     141             :         struct timeval now;
     142     1861891 :         gettimeofday(&now, NULL);
     143     1861891 :         return (u32) ( ( (now.tv_sec)*1000 + (now.tv_usec) / 1000) - sys_start_time );
     144             : }
     145             : 
     146             : GF_EXPORT
     147   240934575 : u64 gf_sys_clock_high_res()
     148             : {
     149             :         struct timeval now;
     150   240934575 :         gettimeofday(&now, NULL);
     151   240935413 :         return (now.tv_sec)*1000000 + (now.tv_usec) - sys_start_time_hr;
     152             : }
     153             : 
     154             : #endif
     155             : 
     156             : static Bool gf_sys_enable_remotery(Bool start, Bool is_shutdown);
     157             : 
     158             : 
     159             : GF_EXPORT
     160     1628696 : void gf_sleep(u32 ms)
     161             : {
     162     1628696 :         gf_rmt_begin(sleep, GF_RMT_AGGREGATE);
     163             : 
     164             : #ifdef WIN32
     165             :         Sleep(ms);
     166             : #else
     167             :         s32 sel_err;
     168             :         struct timeval tv;
     169             : 
     170             : #ifndef SLEEP_ABS_SELECT
     171             :         u32 prev, now, elapsed;
     172             : #endif
     173             : 
     174             : #ifdef SLEEP_ABS_SELECT
     175     1628785 :         tv.tv_sec = ms/1000;
     176     1628785 :         tv.tv_usec = (ms%1000)*1000;
     177             : #else
     178             :         prev = gf_sys_clock();
     179             : #endif
     180             : 
     181             :         do {
     182     1628785 :                 errno = 0;
     183             : 
     184             : #ifndef SLEEP_ABS_SELECT
     185             :                 now = gf_sys_clock();
     186             :                 elapsed = (now - prev);
     187             :                 if ( elapsed >= ms ) {
     188             :                         break;
     189             :                 }
     190             :                 prev = now;
     191             :                 ms -= elapsed;
     192             :                 tv.tv_sec = ms/1000;
     193             :                 tv.tv_usec = (ms%1000)*1000;
     194             : #endif
     195             : 
     196     1628785 :                 sel_err = select(0, NULL, NULL, NULL, &tv);
     197     1628755 :         } while ( sel_err && (errno == EINTR) );
     198             : #endif
     199             : 
     200     1628755 :         gf_rmt_end();
     201             : 
     202     1628762 : }
     203             : 
     204             : #ifndef gettimeofday
     205             : #ifdef _WIN32_WCE
     206             : 
     207             : #include <time.h>
     208             : //#include <wce_time.h>
     209             : 
     210             : /*
     211             :  * Author of first version (timeval.h): by Wu Yongwei
     212             :  * Author of Windows CE version: Mateusz Loskot (mateusz@loskot.net)
     213             :  *
     214             :  * All code here is considered in the public domain though we do wish our names
     215             :  * could be retained if anyone uses them.
     216             :  */
     217             : 
     218             : /*
     219             :  * Constants used internally by time functions.
     220             :  */
     221             : 
     222             : #ifndef _TM_DEFINED
     223             : struct tm
     224             : {
     225             :         int tm_sec;     /* seconds after the minute - [0,59] */
     226             :         int tm_min;     /* minutes after the hour - [0,59] */
     227             :         int tm_hour;    /* hours since midnight - [0,23] */
     228             :         int tm_mday;    /* day of the month - [1,31] */
     229             :         int tm_mon;     /* months since January - [0,11] */
     230             :         int tm_year;    /* years since 1900 */
     231             :         int tm_wday;    /* days since Sunday - [0,6] */
     232             :         int tm_yday;    /* days since January 1 - [0,365] */
     233             :         int tm_isdst;   /* daylight savings time flag */
     234             : };
     235             : #define _TM_DEFINED
     236             : #endif /* _TM_DEFINED */
     237             : 
     238             : #ifndef _TIMEZONE_DEFINED
     239             : struct timezone
     240             : {
     241             :         int tz_minuteswest; /* minutes W of Greenwich */
     242             :         int tz_dsttime;     /* type of dst correction */
     243             : };
     244             : #define _TIMEZONE_DEFINED
     245             : #endif /* _TIMEZONE_DEFINED */
     246             : 
     247             : 
     248             : #if defined(_MSC_VER) || defined(__BORLANDC__)
     249             : #define EPOCHFILETIME (116444736000000000i64)
     250             : #else
     251             : #define EPOCHFILETIME (116444736000000000LL)
     252             : #endif
     253             : 
     254             : int gettimeofday(struct timeval *tp, struct timezone *tzp)
     255             : {
     256             :         SYSTEMTIME      st;
     257             :         FILETIME        ft;
     258             :         LARGE_INTEGER   li;
     259             :         TIME_ZONE_INFORMATION tzi;
     260             :         __int64         t;
     261             : 
     262             :         if (NULL != tp)
     263             :         {
     264             :                 GetSystemTime(&st);
     265             :                 SystemTimeToFileTime(&st, &ft);
     266             :                 li.LowPart  = ft.dwLowDateTime;
     267             :                 li.HighPart = ft.dwHighDateTime;
     268             :                 t  = li.QuadPart;       /* In 100-nanosecond intervals */
     269             :                 t -= EPOCHFILETIME;     /* Offset to the Epoch time */
     270             :                 t /= 10;                /* In microseconds */
     271             :                 tp->tv_sec  = (long)(t / 1000000);
     272             :                 tp->tv_usec = (long)(t % 1000000);
     273             :         }
     274             : 
     275             :         if (NULL != tzp)
     276             :         {
     277             :                 GetTimeZoneInformation(&tzi);
     278             : 
     279             :                 tzp->tz_minuteswest = tzi.Bias;
     280             :                 if (tzi.StandardDate.wMonth != 0)
     281             :                 {
     282             :                         tzp->tz_minuteswest += tzi.StandardBias * 60;
     283             :                 }
     284             : 
     285             :                 if (tzi.DaylightDate.wMonth != 0)
     286             :                 {
     287             :                         tzp->tz_dsttime = 1;
     288             :                 }
     289             :                 else
     290             :                 {
     291             :                         tzp->tz_dsttime = 0;
     292             :                 }
     293             :         }
     294             : 
     295             :         return 0;
     296             : }
     297             : 
     298             : 
     299             : #if _GPAC_UNUSED
     300             : /*
     301             :         time between jan 1, 1601 and jan 1, 1970 in units of 100 nanoseconds
     302             :         FILETIME in Win32 is from jan 1, 1601
     303             : */
     304             : 
     305             : s32 __gettimeofday(struct timeval *tp, void *tz)
     306             : {
     307             :         FILETIME ft;
     308             :         SYSTEMTIME st;
     309             :         s32 val;
     310             : 
     311             :         GetSystemTime(&st);
     312             :         SystemTimeToFileTime(&st, &ft);
     313             : 
     314             :         val = (s32) ((*(LONGLONG *) &ft - TIMESPEC_TO_FILETIME_OFFSET) / 10000000);
     315             :         tp->tv_sec = (u32) val;
     316             :         val = (s32 ) ((*(LONGLONG *) &ft - TIMESPEC_TO_FILETIME_OFFSET - ((LONGLONG) val * (LONGLONG) 10000000)) * 100);
     317             :         tp->tv_usec = val;
     318             :         return 0;
     319             : }
     320             : #endif
     321             : 
     322             : 
     323             : #elif defined(WIN32)
     324             : 
     325             : static s32 gettimeofday(struct timeval *tp, void *tz)
     326             : {
     327             :         struct _timeb timebuffer;
     328             : 
     329             :         _ftime( &timebuffer );
     330             :         tp->tv_sec  = (long) (timebuffer.time);
     331             :         tp->tv_usec = timebuffer.millitm * 1000;
     332             :         return 0;
     333             : }
     334             : #endif
     335             : 
     336             : #endif
     337             : 
     338             : #ifdef _WIN32_WCE
     339             : 
     340             : void CE_Assert(u32 valid, char *file, u32 line)
     341             : {
     342             :         if (!valid) {
     343             :                 char szBuf[2048];
     344             :                 u16 wcBuf[2048];
     345             :                 sprintf(szBuf, "File %s : line %d", file, line);
     346             :                 CE_CharToWide(szBuf, wcBuf);
     347             :                 MessageBox(NULL, wcBuf, _T("GPAC Assertion Failure"), MB_OK);
     348             :                 exit(EXIT_FAILURE);
     349             :         }
     350             : }
     351             : 
     352             : void CE_WideToChar(unsigned short *w_str, char *str)
     353             : {
     354             :         WideCharToMultiByte(CP_ACP, 0, w_str, -1, str, GF_MAX_PATH, NULL, NULL);
     355             : }
     356             : 
     357             : void CE_CharToWide(char *str, unsigned short *w_str)
     358             : {
     359             :         MultiByteToWideChar(CP_ACP, 0, str, -1, w_str, GF_MAX_PATH);
     360             : }
     361             : 
     362             : 
     363             : #endif
     364             : 
     365             : GF_EXPORT
     366        6538 : void gf_rand_init(Bool Reset)
     367             : {
     368        6538 :         if (Reset) {
     369           1 :                 srand(1);
     370             :         } else {
     371             : #if defined(_WIN32_WCE)
     372             :                 srand( (u32) GetTickCount() );
     373             : #else
     374        6537 :                 srand( (u32) time(NULL) );
     375             : #endif
     376             :         }
     377        6538 : }
     378             : 
     379             : GF_EXPORT
     380         193 : u32 gf_rand()
     381             : {
     382         193 :         return rand();
     383             : }
     384             : 
     385             : #ifndef _WIN32_WCE
     386             : #include <sys/stat.h>
     387             : #endif
     388             : 
     389             : GF_EXPORT
     390      586534 : void gf_utc_time_since_1970(u32 *sec, u32 *msec)
     391             : {
     392             : #if defined (WIN32) && !defined(_WIN32_WCE)
     393             :         struct _timeb   tb;
     394             :         _ftime( &tb );
     395             :         *sec = (u32) tb.time;
     396             :         *msec = tb.millitm;
     397             : #else
     398             :         struct timeval tv;
     399      586534 :         gettimeofday(&tv, NULL);
     400      586534 :         *sec = (u32) tv.tv_sec;
     401      586534 :         *msec = tv.tv_usec/1000;
     402             : #endif
     403      586534 : }
     404             : 
     405             : GF_EXPORT
     406          56 : void gf_get_user_name(char buf[1024])
     407             : {
     408             :         strcpy(buf, "gpac-user");
     409             : 
     410             : #if 0
     411             :         s32 len;
     412             :         char *t;
     413             :         strcpy(buf, "");
     414             :         len = 1024;
     415             :         GetUserName(buf, &len);
     416             :         if (!len) {
     417             :                 t = getenv("USER");
     418             :                 if (t) strcpy(buf, t);
     419             :         }
     420             : #endif
     421             : #if 0
     422             :         struct passwd *pw;
     423             :         pw = getpwuid(getuid());
     424             :         strcpy(buf, "");
     425             :         if (pw && pw->pw_name) {
     426             :                 strncpy(name, pw->pw_name, 1023);
     427             :                 name[1023] = 0;
     428             :         }
     429             : #endif
     430          56 : }
     431             : 
     432             : 
     433             : #ifndef WIN32
     434             : GF_EXPORT
     435       23570 : char * my_str_upr(char *str)
     436             : {
     437             :         u32 i;
     438      215698 :         for (i=0; i<strlen(str); i++) {
     439      192128 :                 str[i] = toupper(str[i]);
     440             :         }
     441       23570 :         return str;
     442             : }
     443             : 
     444             : GF_EXPORT
     445       49490 : char * my_str_lwr(char *str)
     446             : {
     447             :         u32 i;
     448      287870 :         for (i=0; i<strlen(str); i++) {
     449      238380 :                 str[i] = tolower(str[i]);
     450             :         }
     451       49490 :         return str;
     452             : }
     453             : #endif
     454             : 
     455             : /*seems OK under mingw also*/
     456             : #ifdef WIN32
     457             : #ifdef _WIN32_WCE
     458             : 
     459             : Bool gf_prompt_has_input()
     460             : {
     461             :         return 0;
     462             : }
     463             : char gf_prompt_get_char() {
     464             :         return 0;
     465             : }
     466             : GF_EXPORT
     467             : void gf_prompt_set_echo_off(Bool echo_off) {
     468             :         return;
     469             : }
     470             : GF_Err gf_prompt_get_size(u32 *width, u32 *height)
     471             : {
     472             :         return GF_NOT_SUPPORTED;
     473             : }
     474             : 
     475             : #else
     476             : 
     477             : #include <conio.h>
     478             : #include <windows.h>
     479             : 
     480             : Bool gf_prompt_has_input()
     481             : {
     482             :         return kbhit();
     483             : }
     484             : 
     485             : char gf_prompt_get_char()
     486             : {
     487             :         return getchar();
     488             : }
     489             : 
     490             : GF_EXPORT
     491             : void gf_prompt_set_echo_off(Bool echo_off)
     492             : {
     493             :         DWORD flags;
     494             :         HANDLE hStdin = GetStdHandle(STD_INPUT_HANDLE);
     495             :         BOOL ret = GetConsoleMode(hStdin, &flags);
     496             :         if (!ret) {
     497             :                 DWORD err = GetLastError();
     498             :                 GF_LOG(GF_LOG_ERROR, GF_LOG_CONSOLE, ("[Console] GetConsoleMode() return with the following error code: %d\n", err));
     499             :                 return;
     500             :         }
     501             :         if (echo_off) flags &= ~ENABLE_ECHO_INPUT;
     502             :         else flags |= ENABLE_ECHO_INPUT;
     503             :         SetConsoleMode(hStdin, flags);
     504             : }
     505             : 
     506             : GF_EXPORT
     507             : GF_Err gf_prompt_get_size(u32 *width, u32 *height)
     508             : {
     509             :     CONSOLE_SCREEN_BUFFER_INFO info;
     510             :         HANDLE hStdin = GetStdHandle(STD_INPUT_HANDLE);
     511             :         BOOL ret = GetConsoleScreenBufferInfo(hStdin, &info);
     512             : 
     513             :         if (!ret) {
     514             :                 DWORD err = GetLastError();
     515             :                 GF_LOG(GF_LOG_ERROR, GF_LOG_CONSOLE, ("[Console] GetConsoleScreenBufferInfo() return with the following error code: %d\n", err));
     516             :                 return GF_IO_ERR;
     517             :         }
     518             :         if (width) *width = info.dwSize.X;
     519             :         if (height) *height = info.dwSize.Y;
     520             :         return GF_OK;
     521             : }
     522             : 
     523             : #endif
     524             : #else
     525             : /*linux kbhit/getchar- borrowed on debian mailing lists, (author Mike Brownlow)*/
     526             : #include <termios.h>
     527             : #include <sys/ioctl.h>
     528             : 
     529             : static struct termios t_orig, t_new;
     530             : static s32 ch_peek = -1;
     531             : 
     532           0 : static void init_keyboard()
     533             : {
     534           0 :         tcgetattr(0, &t_orig);
     535           0 :         t_new = t_orig;
     536           0 :         t_new.c_lflag &= ~ICANON;
     537           0 :         t_new.c_lflag &= ~ECHO;
     538           0 :         t_new.c_lflag &= ~ISIG;
     539           0 :         t_new.c_cc[VMIN] = 1;
     540           0 :         t_new.c_cc[VTIME] = 0;
     541           0 :         tcsetattr(0, TCSANOW, &t_new);
     542           0 : }
     543           0 : static void close_keyboard(Bool new_line)
     544             : {
     545           0 :         tcsetattr(0,TCSANOW, &t_orig);
     546           0 :         if (new_line) fprintf(stderr, "\n");
     547           0 : }
     548             : 
     549             : GF_EXPORT
     550           0 : void gf_prompt_set_echo_off(Bool echo_off)
     551             : {
     552           0 :         init_keyboard();
     553           0 :         if (echo_off) t_orig.c_lflag &= ~ECHO;
     554           0 :         else t_orig.c_lflag |= ECHO;
     555             :         close_keyboard(0);
     556           0 : }
     557             : 
     558             : GF_EXPORT
     559       70704 : Bool gf_prompt_has_input()
     560             : {
     561             :         u8 ch;
     562             :         s32 nread;
     563       70704 :         pid_t fg = tcgetpgrp(STDIN_FILENO);
     564             : 
     565             :         //we are not foreground nor piped (used for IDEs), can't read stdin
     566       70704 :         if ((fg!=-1) && (fg != getpgrp())) {
     567             :                 return 0;
     568             :         }
     569           0 :         init_keyboard();
     570           0 :         if (ch_peek != -1) return 1;
     571           0 :         t_new.c_cc[VMIN]=0;
     572           0 :         tcsetattr(0, TCSANOW, &t_new);
     573           0 :         nread = (s32) read(0, &ch, 1);
     574           0 :         t_new.c_cc[VMIN]=1;
     575           0 :         tcsetattr(0, TCSANOW, &t_new);
     576           0 :         if(nread == 1) {
     577           0 :                 ch_peek = ch;
     578           0 :                 return 1;
     579             :         }
     580             :         close_keyboard(0);
     581           0 :         return 0;
     582             : }
     583             : 
     584             : GF_EXPORT
     585           0 : char gf_prompt_get_char()
     586             : {
     587             :         char ch;
     588           0 :         if (ch_peek != -1) {
     589           0 :                 ch = ch_peek;
     590           0 :                 ch_peek = -1;
     591           0 :                 close_keyboard(1);
     592           0 :                 return ch;
     593             :         }
     594           0 :         if (0==read(0,&ch,1))
     595           0 :                 ch = 0;
     596           0 :         close_keyboard(1);
     597           0 :         return ch;
     598             : }
     599             : 
     600             : GF_EXPORT
     601           1 : GF_Err gf_prompt_get_size(u32 *width, u32 *height)
     602             : {
     603             : #if defined(TIOCGWINSZ)
     604             :     struct winsize ws;
     605           1 :     if (ioctl(STDIN_FILENO, TIOCGWINSZ, &ws) != 0) return GF_IO_ERR;
     606             : 
     607           1 :     if (width) *width = ws.ws_col;
     608           1 :     if (height) *height = ws.ws_row;
     609             :     return GF_OK;
     610             : #elif defined(WIOCGETD)
     611             :         struct uwdata w;
     612             :         if (ioctl(2, WIOCGETD, &w) != 0) return GF_IO_ERR;
     613             : 
     614             :         if (width && (w.uw_width > 0))
     615             :                 *width = w.uw_width / w.uw_hs;
     616             :         if (height && (w.uw_height > 0))
     617             :                 *height = w.uw_height / w.uw_vs;
     618             :     return GF_OK;
     619             : #else
     620             :     return GF_NOT_SUPPORTED;
     621             : #endif
     622             : }
     623             : 
     624             : #endif
     625             : 
     626             : 
     627             : static u32 sys_init = 0;
     628             : static u32 last_update_time = 0;
     629             : static u64 last_process_k_u_time = 0;
     630             : GF_SystemRTInfo the_rti;
     631             : 
     632             : 
     633             : #if defined(_WIN32_WCE)
     634             : static LARGE_INTEGER frequency , init_counter;
     635             : static u64 last_total_k_u_time = 0;
     636             : static u32 mem_usage_at_startup = 0;
     637             : 
     638             : 
     639             : #ifndef GetCurrentPermissions
     640             : DWORD GetCurrentPermissions();
     641             : #endif
     642             : #ifndef SetProcPermissions
     643             : void SetProcPermissions(DWORD );
     644             : #endif
     645             : 
     646             : #elif defined(WIN32)
     647             : static LARGE_INTEGER frequency , init_counter;
     648             : static u64 last_proc_idle_time = 0;
     649             : static u64 last_proc_k_u_time = 0;
     650             : 
     651             : static HINSTANCE psapi_hinst = NULL;
     652             : typedef BOOL(WINAPI* NTGetSystemTimes)(VOID *,VOID *,VOID *);
     653             : NTGetSystemTimes MyGetSystemTimes = NULL;
     654             : typedef BOOL(WINAPI* NTGetProcessMemoryInfo)(HANDLE,VOID *,DWORD);
     655             : NTGetProcessMemoryInfo MyGetProcessMemoryInfo = NULL;
     656             : typedef int(WINAPI* NTQuerySystemInfo)(ULONG,PVOID,ULONG,PULONG);
     657             : NTQuerySystemInfo MyQuerySystemInfo = NULL;
     658             : 
     659             : #ifndef PROCESS_MEMORY_COUNTERS
     660             : typedef struct _PROCESS_MEMORY_COUNTERS
     661             : {
     662             :         DWORD cb;
     663             :         DWORD PageFaultCount;
     664             :         SIZE_T PeakWorkingSetSize;
     665             :         SIZE_T WorkingSetSize;
     666             :         SIZE_T QuotaPeakPagedPoolUsage;
     667             :         SIZE_T QuotaPagedPoolUsage;
     668             :         SIZE_T QuotaPeakNonPagedPoolUsage;
     669             :         SIZE_T QuotaNonPagedPoolUsage;
     670             :         SIZE_T PagefileUsage;
     671             :         SIZE_T PeakPagefileUsage;
     672             : } PROCESS_MEMORY_COUNTERS;
     673             : #endif
     674             : 
     675             : #ifndef SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION
     676             : typedef struct _SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION
     677             : {
     678             :         LARGE_INTEGER IdleTime;
     679             :         LARGE_INTEGER KernelTime;
     680             :         LARGE_INTEGER UserTime;
     681             :         LARGE_INTEGER Reserved1[2];
     682             :         ULONG Reserved2;
     683             : } SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION;
     684             : #endif
     685             : 
     686             : 
     687             : #else
     688             : 
     689             : static u64 last_cpu_u_k_time = 0;
     690             : static u64 last_cpu_idle_time = 0;
     691             : static u64 mem_at_startup = 0;
     692             : 
     693             : #endif
     694             : 
     695             : #ifdef WIN32
     696             : static u32 (*OS_GetSysClock)();
     697             : 
     698             : u32 gf_sys_clock()
     699             : {
     700             :         return OS_GetSysClock();
     701             : }
     702             : 
     703             : 
     704             : static u64 (*OS_GetSysClockHR)();
     705             : u64 gf_sys_clock_high_res()
     706             : {
     707             :         return OS_GetSysClockHR();
     708             : }
     709             : #endif
     710             : 
     711             : 
     712             : #ifdef WIN32
     713             : 
     714             : static u32 OS_GetSysClockHIGHRES()
     715             : {
     716             :         LARGE_INTEGER now;
     717             :         QueryPerformanceCounter(&now);
     718             :         now.QuadPart -= init_counter.QuadPart;
     719             :         return (u32) ((now.QuadPart * 1000) / frequency.QuadPart);
     720             : }
     721             : 
     722             : static u64 OS_GetSysClockHIGHRES_FULL()
     723             : {
     724             :         LARGE_INTEGER now;
     725             :         QueryPerformanceCounter(&now);
     726             :         now.QuadPart -= init_counter.QuadPart;
     727             :         return (u64) ((now.QuadPart * 1000000) / frequency.QuadPart);
     728             : }
     729             : 
     730             : static u32 OS_GetSysClockNORMAL()
     731             : {
     732             : #ifdef _WIN32_WCE
     733             :         return GetTickCount();
     734             : #else
     735             :         return timeGetTime();
     736             : #endif
     737             : }
     738             : 
     739             : static u64 OS_GetSysClockNORMAL_FULL()
     740             : {
     741             :         u64 res = OS_GetSysClockNORMAL();
     742             :         return res*1000;
     743             : }
     744             : 
     745             : #endif /* WIN32 */
     746             : 
     747             : #if defined(__sh__)
     748             : /* Avoid exception for denormalized floating point values */
     749             : static int
     750             : sh4_get_fpscr()
     751             : {
     752             :         int ret;
     753             :         asm volatile ("sts fpscr,%0" : "=r" (ret));
     754             :         return ret;
     755             : }
     756             : 
     757             : static void
     758             : sh4_put_fpscr(int nv)
     759             : {
     760             :         asm volatile ("lds %0,fpscr" : : "r" (nv));
     761             : }
     762             : 
     763             : #define SH4_FPSCR_FR 0x00200000
     764             : #define SH4_FPSCR_SZ 0x00100000
     765             : #define SH4_FPSCR_PR 0x00080000
     766             : #define SH4_FPSCR_DN 0x00040000
     767             : #define SH4_FPSCR_RN 0x00000003
     768             : #define SH4_FPSCR_RN_N 0
     769             : #define SH4_FPSCR_RN_Z 1
     770             : 
     771             : extern int __fpscr_values[2];
     772             : 
     773             : void
     774             : sh4_change_fpscr(int off, int on)
     775             : {
     776             :         int b = sh4_get_fpscr();
     777             :         off = ~off;
     778             :         off |=   0x00180000;
     779             :         on  &= ~ 0x00180000;
     780             :         b &= off;
     781             :         b |= on;
     782             :         sh4_put_fpscr(b);
     783             :         __fpscr_values[0] &= off;
     784             :         __fpscr_values[0] |= on;
     785             :         __fpscr_values[1] &= off;
     786             :         __fpscr_values[1] |= on;
     787             : }
     788             : 
     789             : #endif
     790             : 
     791             : GF_EXPORT
     792       50016 : struct tm *gf_gmtime(const time_t *time)
     793             : {
     794             : #ifdef _WIN32_WCE
     795             :         FILETIME filet;
     796             :         LPSYSTEMTIME syst;
     797             :         *(LONGLONG *) &filet = (sec/* - GF_NTP_SEC_1900_TO_1970*/) * 10000000 + TIMESPEC_TO_FILETIME_OFFSET;
     798             :         FileTimeToSystemTime(&filet, &syst);
     799             :         if (syst.wSecond>60)
     800             :                 syst.wSecond=60;
     801             : #endif
     802             : 
     803       50016 :         struct tm *tm = gmtime(time);
     804             :         //see issue #859, no clue how this happened...
     805       50016 :         if (tm->tm_sec>60)
     806           0 :                 tm->tm_sec = 60;
     807       50016 :         return tm;
     808             : }
     809             : 
     810             : 
     811             : #ifdef GPAC_MEMORY_TRACKING
     812             : void gf_mem_enable_tracker(Bool enable_backtrace);
     813             : #endif
     814             : 
     815             : static u64 memory_at_gpac_startup = 0;
     816             : 
     817             : static u32 gpac_argc = 0;
     818             : const char **gpac_argv = NULL;
     819             : Bool *gpac_argv_state = NULL;
     820             : static Bool gpac_test_mode = GF_FALSE;
     821             : static Bool gpac_old_arch = GF_FALSE;
     822             : static Bool gpac_discard_config = GF_FALSE;
     823             : 
     824             : //in error.c
     825             : #ifndef GPAC_DISABLE_LOG
     826             : extern FILE *gpac_log_file;
     827             : extern Bool gpac_log_time_start;
     828             : extern Bool gpac_log_utc_time;
     829             : #endif
     830             : 
     831             : GF_EXPORT
     832           2 : Bool gf_log_use_file()
     833             : {
     834             : #ifndef GPAC_DISABLE_LOG
     835           2 :         return gpac_log_file ? GF_TRUE : GF_FALSE;
     836             : #else
     837             :         return GF_FALSE;
     838             : #endif
     839             : }
     840             : 
     841     1598335 : static void progress_quiet(const void *cbck, const char *title, u64 done, u64 total) { }
     842             : 
     843           3 : void gpac_disable_progress()
     844             : {
     845           3 :         gf_set_progress_callback(NULL, progress_quiet);
     846           3 : }
     847             : 
     848             : GF_EXPORT
     849     1101163 : Bool gf_sys_is_test_mode()
     850             : {
     851     1101163 :         return gpac_test_mode;
     852             : }
     853             : 
     854             : GF_EXPORT
     855     2239387 : Bool gf_sys_old_arch_compat()
     856             : {
     857     2239387 :         return gpac_old_arch;
     858             : }
     859             : 
     860             : #ifdef GPAC_ENABLE_COVERAGE
     861             : GF_EXPORT
     862       13751 : Bool gf_sys_is_cov_mode()
     863             : {
     864       13751 :         return gpac_test_mode;
     865             : }
     866             : #endif
     867             : 
     868             : const char *gpac_log_file_name=NULL;
     869             : 
     870             : GF_EXPORT
     871           2 : void gf_log_reset_file()
     872             : {
     873             : #ifndef GPAC_DISABLE_LOG
     874           2 :         if (gpac_log_file_name) {
     875           0 :                 if (gpac_log_file) gf_fclose(gpac_log_file);
     876           0 :                 gpac_log_file = gf_fopen(gpac_log_file_name, "wt");
     877             :         }
     878             : #endif
     879           2 : }
     880             : 
     881             : static Bool gpac_has_global_filter_args=GF_FALSE;
     882             : static Bool gpac_has_global_filter_meta_args=GF_FALSE;
     883             : #include <gpac/thread.h>
     884             : GF_Mutex *logs_mx = NULL;
     885             : 
     886      263019 : Bool gf_sys_has_filter_global_args()
     887             : {
     888      263019 :         return gpac_has_global_filter_args;
     889             : }
     890        3029 : Bool gf_sys_has_filter_global_meta_args()
     891             : {
     892        3029 :         return gpac_has_global_filter_meta_args;
     893             : }
     894             : 
     895             : static u32 gpac_quiet = 0;
     896             : char gf_prog_lf = '\r';
     897             : 
     898             : GF_EXPORT
     899        6219 : GF_Err gf_sys_set_args(s32 argc, const char **argv)
     900             : {
     901             :         s32 i;
     902        6219 :         if (!gpac_argc) {
     903             :                 Bool gf_opts_load_option(const char *arg_name, const char *val, Bool *consumed_next, GF_Err *e);
     904             :                 void gf_cfg_load_restrict();
     905             : 
     906       59559 :                 for (i=1; i<argc; i++) {
     907             :                         Bool consumed;
     908             :                         GF_Err e;
     909             :                         Bool use_sep=GF_FALSE;
     910             :                         Bool bool_value = GF_TRUE;
     911             :                         char *arg_val;
     912       59559 :                         const char *arg = argv[i];
     913       72181 :                         if (!arg) continue;
     914             : 
     915       59559 :                         arg_val = strchr(arg, '=');
     916       59559 :                         if (arg_val) {
     917        9832 :                                 arg_val[0]=0;
     918        9832 :                                 arg_val++;
     919             :                                 use_sep=GF_TRUE;
     920       49727 :                         } else if (i+1<argc) {
     921       44340 :                                 arg_val = (char *) argv[i+1];
     922             :                         }
     923       59559 :                         if ((arg[0] != '-') || ! arg[1]) {
     924       12622 :                                 if (use_sep) {
     925             :                                         arg_val--;
     926        2347 :                                         arg_val[0]='=';
     927             :                                 }
     928       12622 :                                 continue;
     929             :                         }
     930       46937 :                         if (arg_val && (!strcmp(arg_val, "no") || !strcmp(arg_val, "false") || !strcmp(arg_val, "°0") ) )
     931             :                                 bool_value = GF_FALSE;
     932             : 
     933             : 
     934       46937 :                         if (arg[1]=='-') {
     935          97 :                                 gpac_has_global_filter_args = GF_TRUE;
     936       46840 :                         } else if (arg[1]=='+') {
     937           0 :                                 gpac_has_global_filter_meta_args = GF_TRUE;
     938       46840 :                         } else if (!strcmp(arg, "-log-file") || !strcmp(arg, "-lf")) {
     939             : #ifndef GPAC_DISABLE_LOG
     940           0 :                                 gpac_log_file_name = arg_val;
     941             : #endif
     942           0 :                                 if (!use_sep) i += 1;
     943       46840 :                         } else if (!strcmp(arg, "-logs") ) {
     944         178 :                                 e = gf_log_set_tools_levels(arg_val, GF_FALSE);
     945         178 :                                 if (e) return e;
     946             :                                 
     947         178 :                                 if (!use_sep) i += 1;
     948       46662 :                         } else if (!strcmp(arg, "-log-clock") || !strcmp(arg, "-lc")) {
     949             : #ifndef GPAC_DISABLE_LOG
     950           1 :                                 gpac_log_time_start = GF_TRUE;
     951             : #endif
     952       46661 :                         } else if (!strcmp(arg, "-log-utc") || !strcmp(arg, "-lu")) {
     953             : #ifndef GPAC_DISABLE_LOG
     954           5 :                                 gpac_log_utc_time = GF_TRUE;
     955             : #endif
     956       46656 :                         } else if (!strcmp(arg, "-quiet")) {
     957           0 :                                 gpac_quiet = 2;
     958       46656 :                         } else if (!strcmp(arg, "-noprog")) {
     959        6187 :                                 if (!gpac_quiet) gpac_quiet = 1;
     960       40469 :                         } else if (!strcmp(arg, "-proglf")) {
     961           0 :                                 gf_prog_lf = '\n';
     962       40469 :                         } else if (!stricmp(arg, "-for-test")) {
     963        6201 :                                 gpac_test_mode = bool_value;
     964       34268 :                         } else if (!stricmp(arg, "-old-arch")) {
     965        6179 :                                 gpac_old_arch = bool_value;
     966       28089 :                         } else if (!stricmp(arg, "-no-save")) {
     967           1 :                                 gpac_discard_config = bool_value;
     968       28088 :                         } else if (!stricmp(arg, "-ntp-shift")) {
     969           0 :                                 s32 shift = arg_val ? atoi(arg_val) : 0;
     970           0 :                                 gf_net_set_ntp_shift(shift);
     971           0 :                                 if (!use_sep) i += 1;
     972       28088 :                         } else if (gf_opts_load_option(arg, arg_val, &consumed, &e)) {
     973        2800 :                                 if (e) return e;
     974             :                                 
     975        2800 :                                 if (consumed && !use_sep)
     976          11 :                                         i += 1;
     977             :                         }
     978       46937 :                         if (use_sep) {
     979             :                                 arg_val--;
     980        7485 :                                 arg_val[0]='=';
     981             :                         }
     982             :                 }
     983             : 
     984             : #ifdef GPAC_CONFIG_DARWIN
     985             :                 //if running in xcode disable color logs (not supported by output console)
     986             :                 if (getenv("__XCODE_BUILT_PRODUCTS_DIR_PATHS") != NULL) {
     987             :                         gf_log_set_tools_levels("ncl", GF_FALSE);
     988             :                 }
     989             : #endif
     990             : 
     991             : 
     992             : #ifndef GPAC_DISABLE_LOG
     993        6219 :                 if (gpac_log_file_name) {
     994           0 :                         gpac_log_file = gf_fopen(gpac_log_file_name, "wt");
     995             :                 }
     996             : #endif
     997        6219 :                 if (gf_opts_get_bool("core", "rmt"))
     998           2 :                         gf_sys_enable_remotery(GF_TRUE, GF_FALSE);
     999             : 
    1000        6219 :                 if (gpac_quiet) {
    1001        6187 :                         if (gpac_quiet==2) gf_log_set_tool_level(GF_LOG_ALL, GF_LOG_QUIET);
    1002        6187 :                         gf_set_progress_callback(NULL, progress_quiet);
    1003             :                 }
    1004             :                 //now that we have parsed all options, load restrict
    1005        6219 :                 gf_cfg_load_restrict();
    1006             : 
    1007             :         }
    1008             :         //for OSX we allow overwrite of argc/argv due to different behavior between console-mode apps and GUI
    1009             : #if !defined(__DARWIN__) && !defined(__APPLE__)
    1010        6219 :         if (!gpac_argc && (argc>=0) )
    1011             : #endif
    1012             :         {
    1013        6219 :                 gpac_argc = (u32) argc;
    1014        6219 :                 gpac_argv = argv;
    1015        6219 :                 gpac_argv_state = gf_realloc(gpac_argv_state, sizeof(Bool) * argc);
    1016       72009 :                 for (i=0; i<argc; i++)
    1017       65790 :                         gpac_argv_state[i] = GF_FALSE;
    1018             :         }
    1019             :         return GF_OK;
    1020             : }
    1021             : 
    1022             : GF_EXPORT
    1023       21395 : void gf_sys_mark_arg_used(s32 arg_idx, Bool used)
    1024             : {
    1025       21395 :         if (arg_idx < (s32) gpac_argc)
    1026       21395 :                 gpac_argv_state[arg_idx] = used;
    1027       21395 : }
    1028             : 
    1029             : GF_EXPORT
    1030       21359 : Bool gf_sys_is_arg_used(s32 arg_idx)
    1031             : {
    1032       21359 :         if (arg_idx < (s32) gpac_argc)
    1033       21359 :                 return  gpac_argv_state[arg_idx];
    1034             :         return GF_FALSE;
    1035             : }
    1036             : 
    1037             : GF_EXPORT
    1038         738 : u32 gf_sys_is_quiet()
    1039             : {
    1040         738 :         return gpac_quiet;
    1041             : }
    1042             : 
    1043             : 
    1044             : GF_EXPORT
    1045       31226 : u32 gf_sys_get_argc()
    1046             : {
    1047       31226 :         return gpac_argc;
    1048             : }
    1049             : GF_EXPORT
    1050           1 : const char **gf_sys_get_argv()
    1051             : {
    1052           1 :         return gpac_argv;
    1053             : }
    1054             : GF_EXPORT
    1055      107534 : const char *gf_sys_get_arg(u32 arg)
    1056             : {
    1057      107534 :         if (!gpac_argc || !gpac_argv) return NULL;
    1058      107534 :         if (arg>=gpac_argc) return NULL;
    1059      107534 :         return gpac_argv[arg];
    1060             : }
    1061             : GF_EXPORT
    1062           4 : const char *gf_sys_find_global_arg(const char *arg)
    1063             : {
    1064             :         u32 i;
    1065           4 :         if (!gpac_argc || !gpac_argv) return NULL;
    1066          36 :         for (i=0; i<gpac_argc; i++) {
    1067             :                 const char *sep;
    1068             :                 u32 len;
    1069          36 :                 const char *an_arg = gpac_argv[i];
    1070          36 :                 if (an_arg[0]!='-') continue;
    1071          24 :                 if ((an_arg[1]!='-') && (an_arg[1]!='+')) continue;
    1072           0 :                 an_arg += 2;
    1073           0 :                 sep = strchr(an_arg, '@');
    1074           0 :                 if (sep) an_arg = sep+1;
    1075           0 :                 sep = strchr(an_arg, '=');
    1076           0 :                 if (sep) len = (u32) (sep - an_arg);
    1077           0 :                 else len = (u32) strlen(an_arg);
    1078           0 :                 if (len != (u32) strlen(arg)) continue;
    1079             : 
    1080           0 :                 if (strncmp(an_arg, arg, len)) continue;
    1081             : 
    1082           0 :                 if (!sep) return "";
    1083           0 :                 return sep;
    1084             :         }
    1085             :         return NULL;
    1086             : }
    1087             : 
    1088             : 
    1089             : #ifndef GPAC_DISABLE_REMOTERY
    1090             : Remotery *remotery_handle=NULL;
    1091             : 
    1092             : //commented out as it put quite some load on the browser
    1093             : 
    1094             : gf_log_cbk gpac_prev_default_logs = NULL;
    1095             : 
    1096             : const char *gf_log_tool_name(GF_LOG_Tool log_tool);
    1097             : const char *gf_log_level_name(GF_LOG_Level log_level);
    1098             : 
    1099          87 : void gpac_rmt_log_callback(void *cbck, GF_LOG_Level level, GF_LOG_Tool tool, const char *fmt, va_list vlist)
    1100             : {
    1101             : #ifndef GPAC_DISABLE_LOG
    1102             : 
    1103             : #define RMT_LOG_SIZE    5000
    1104             :         char szMsg[RMT_LOG_SIZE];
    1105             :         u32 len;
    1106          87 :         sprintf(szMsg, "{ \"type\": \"logs\", \"level\": \"%s\" \"tool\": \"%s\", \"value\": \"", gf_log_level_name(level), gf_log_tool_name(tool));
    1107             : 
    1108          87 :         len = (u32) strlen(szMsg);
    1109          87 :         vsnprintf(szMsg, RMT_LOG_SIZE - len - 3, fmt, vlist);
    1110             :         strcat(szMsg, "\"}");
    1111             : 
    1112          87 :         rmt_LogText(szMsg);
    1113             : 
    1114             : #undef RMT_LOG_SIZE
    1115             : 
    1116             : #endif
    1117             : 
    1118          87 : }
    1119             : 
    1120             : static void *rmt_udta = NULL;
    1121             : gf_rmt_user_callback rmt_usr_cbk = NULL;
    1122             : 
    1123           0 : static void gpac_rmt_input_handler(const char* text, void* context)
    1124             : {
    1125           0 :         if (text && rmt_usr_cbk)
    1126           0 :                 rmt_usr_cbk(rmt_udta, text);
    1127           0 : }
    1128             : #endif
    1129             : 
    1130        6242 : static Bool gf_sys_enable_remotery(Bool start, Bool is_shutdown)
    1131             : {
    1132             : #ifndef GPAC_DISABLE_REMOTERY
    1133        6242 :         if (start && !remotery_handle) {
    1134           2 :                 rmtSettings *rmcfg = rmt_Settings();
    1135             : 
    1136           2 :                 rmcfg->port = gf_opts_get_int("core", "rmt-port");
    1137           2 :                 rmcfg->reuse_open_port = gf_opts_get_bool("core", "rmt-reuse");
    1138           2 :                 rmcfg->limit_connections_to_localhost = gf_opts_get_bool("core", "rmt-localhost");
    1139           2 :                 rmcfg->msSleepBetweenServerUpdates = gf_opts_get_int("core", "rmt-sleep");
    1140           2 :                 rmcfg->maxNbMessagesPerUpdate = gf_opts_get_int("core", "rmt-nmsg");
    1141           2 :                 rmcfg->messageQueueSizeInBytes = gf_opts_get_int("core", "rmt-qsize");
    1142           2 :                 rmcfg->input_handler = gpac_rmt_input_handler;
    1143             : 
    1144           2 :                 rmtError rme = rmt_CreateGlobalInstance(&remotery_handle);
    1145           2 :                 if (rme != RMT_ERROR_NONE) {
    1146           0 :                         GF_LOG(GF_LOG_ERROR, GF_LOG_CORE, ("[core] unable to initialize Remotery profiler: error %d\n", rme));
    1147             :                         return GF_FALSE;
    1148             :                 }
    1149             :                 //openGL binding is done upon loading of the driver, otherwise crashes on windows
    1150             : 
    1151           2 :                 if (gf_opts_get_bool("core", "rmt-log")) {
    1152           1 :                         gpac_prev_default_logs = gf_log_set_callback(NULL, gpac_rmt_log_callback);
    1153             :                 }
    1154             : #ifdef GPAC_ENABLE_COVERAGE
    1155           2 :                 if (gf_sys_is_cov_mode()) {
    1156             :                         gpac_rmt_input_handler(NULL, NULL);
    1157             :                 }
    1158             : #endif
    1159             : 
    1160        6240 :         } else if (!start && remotery_handle) {
    1161           2 :                 if (gf_opts_get_bool("core", "rmt-ogl"))
    1162           1 :                         rmt_UnbindOpenGL();
    1163             : 
    1164           2 :                 rmt_DestroyGlobalInstance(remotery_handle);
    1165             : 
    1166           2 :                 remotery_handle=NULL;
    1167           2 :                 if (gpac_prev_default_logs != NULL)
    1168           1 :                         gf_log_set_callback(NULL, gpac_prev_default_logs);
    1169             :         }
    1170             :         return GF_TRUE;
    1171             : #else
    1172             :         return GF_NOT_SUPPORTED;
    1173             : #endif
    1174             : }
    1175             : 
    1176             : GF_EXPORT
    1177           3 : GF_Err gf_sys_profiler_set_callback(void *udta, gf_rmt_user_callback usr_cbk)
    1178             : {
    1179             : #ifndef GPAC_DISABLE_REMOTERY
    1180           3 :         if (remotery_handle) {
    1181           0 :                 rmt_udta = udta;
    1182           0 :                 rmt_usr_cbk = usr_cbk;
    1183           0 :                 return GF_OK;
    1184             :         }
    1185             :         return GF_BAD_PARAM;
    1186             : #else
    1187             :         return GF_NOT_SUPPORTED;
    1188             : #endif
    1189             : }
    1190             : 
    1191             : GF_EXPORT
    1192           1 : GF_Err gf_sys_profiler_send(const char *msg)
    1193             : {
    1194             : #ifndef GPAC_DISABLE_REMOTERY
    1195           1 :         if (remotery_handle) {
    1196           0 :                 rmt_LogText(msg);
    1197           0 :                 return GF_OK;
    1198             :         }
    1199             :         return GF_BAD_PARAM;
    1200             : #else
    1201             :         return GF_NOT_SUPPORTED;
    1202             : #endif
    1203             : }
    1204             : 
    1205             : GF_EXPORT
    1206           1 : void gf_sys_profiler_enable_sampling(Bool enable)
    1207             : {
    1208             : #ifndef GPAC_DISABLE_REMOTERY
    1209           1 :         if (remotery_handle) {
    1210           0 :                 rmt_EnableSampling(enable);
    1211             :         }
    1212             : #endif
    1213           1 : }
    1214             : 
    1215             : GF_EXPORT
    1216           0 : Bool gf_sys_profiler_sampling_enabled()
    1217             : {
    1218             : #ifndef GPAC_DISABLE_REMOTERY
    1219           0 :         if (remotery_handle) {
    1220           0 :                 return rmt_SamplingEnabled();
    1221             :         }
    1222             : #endif
    1223             :         return GF_FALSE;
    1224             : }
    1225             : 
    1226             : void gf_init_global_config(const char *profile);
    1227             : void gf_uninit_global_config(Bool discard_config);
    1228             : 
    1229             : static GF_Config *gpac_lang_file = NULL;
    1230             : static const char *gpac_lang_code = NULL;
    1231             : 
    1232        2190 : GF_Config *gf_sys_get_lang_file()
    1233             : {
    1234        2190 :         const char *opt = gf_opts_get_key("core", "lang");
    1235             :         char szSharedPath[GF_MAX_PATH];
    1236        2190 :         if (!opt) return NULL;
    1237             : 
    1238           0 :         if (gpac_lang_code && strcmp(gpac_lang_code, opt)) {
    1239           0 :                 gf_cfg_del(gpac_lang_file);
    1240           0 :                 gpac_lang_file = NULL;
    1241             :         }
    1242           0 :         gpac_lang_code = opt;
    1243             : 
    1244           0 :         if (gpac_lang_file) return gpac_lang_file;
    1245             : 
    1246           0 :         if (! gf_opts_default_shared_directory(szSharedPath)) return NULL;
    1247             :         strcat(szSharedPath, "/lang/");
    1248             :         strcat(szSharedPath, opt);
    1249             :         strcat(szSharedPath, ".txt");
    1250           0 :         if (!gf_file_exists(szSharedPath)) return NULL;
    1251             : 
    1252           0 :         gpac_lang_file = gf_cfg_new(NULL, szSharedPath);
    1253             : 
    1254           0 :         return gpac_lang_file;
    1255             : }
    1256             : 
    1257             : 
    1258             : GF_EXPORT
    1259        2190 : const char *gf_sys_localized(const char *sec_name, const char *key_name, const char *def_val)
    1260             : {
    1261        2190 :         GF_Config *lcfg = gf_sys_get_lang_file();
    1262        2190 :         if (!lcfg) return def_val;
    1263             : 
    1264           0 :         const char *opt = gf_cfg_get_key(lcfg, sec_name, key_name);
    1265           0 :         if (opt) return opt;
    1266           0 :         return def_val;
    1267             : }
    1268             : 
    1269             : GF_EXPORT
    1270        6249 : GF_Err gf_sys_init(GF_MemTrackerType mem_tracker_type, const char *profile)
    1271             : {
    1272        6249 :         if (!sys_init) {
    1273             : #if defined (WIN32)
    1274             : #if defined(_WIN32_WCE)
    1275             :                 MEMORYSTATUS ms;
    1276             : #else
    1277             :                 SYSTEM_INFO sysinfo;
    1278             : #endif
    1279             : #endif
    1280             : 
    1281        6241 :                 if (mem_tracker_type!=GF_MemTrackerNone) {
    1282             : #ifdef GPAC_MEMORY_TRACKING
    1283        6212 :             gf_mem_enable_tracker( (mem_tracker_type==GF_MemTrackerBackTrace) ? GF_TRUE : GF_FALSE);
    1284             : #endif
    1285             :                 }
    1286             : #ifndef GPAC_DISABLE_LOG
    1287             :                 /*by default log subsystem is initialized to error on all tools, and info on console to debug scripts*/
    1288        6241 :                 gf_log_set_tool_level(GF_LOG_ALL, GF_LOG_WARNING);
    1289        6241 :                 gf_log_set_tool_level(GF_LOG_APP, GF_LOG_INFO);
    1290        6241 :                 gf_log_set_tool_level(GF_LOG_CONSOLE, GF_LOG_INFO);
    1291             : #endif
    1292             : 
    1293             : 
    1294             : #if defined(__sh__)
    1295             :                 /* Round all denormalized floatting point number to 0.0 */
    1296             :                 sh4_change_fpscr(0,SH4_FPSCR_DN) ;
    1297             : #endif
    1298             : 
    1299             : #if defined(WIN32)
    1300             :                 frequency.QuadPart = 0;
    1301             :                 /*clock setup*/
    1302             :                 if (QueryPerformanceFrequency(&frequency)) {
    1303             :                         QueryPerformanceCounter(&init_counter);
    1304             :                         OS_GetSysClock = OS_GetSysClockHIGHRES;
    1305             :                         OS_GetSysClockHR = OS_GetSysClockHIGHRES_FULL;
    1306             :                         GF_LOG(GF_LOG_INFO, GF_LOG_CORE, ("[core] using WIN32 performance timer\n"));
    1307             :                 } else {
    1308             :                         OS_GetSysClock = OS_GetSysClockNORMAL;
    1309             :                         OS_GetSysClockHR = OS_GetSysClockNORMAL_FULL;
    1310             :                         GF_LOG(GF_LOG_INFO, GF_LOG_CORE, ("[core] using WIN32 regular timer\n"));
    1311             :                 }
    1312             : 
    1313             : #ifndef _WIN32_WCE
    1314             :                 timeBeginPeriod(1);
    1315             : #endif
    1316             : 
    1317             :                 GF_LOG(GF_LOG_INFO, GF_LOG_CORE, ("[core] checking for run-time info tools"));
    1318             : #if defined(_WIN32_WCE)
    1319             :                 last_total_k_u_time = last_process_k_u_time = 0;
    1320             :                 last_update_time = 0;
    1321             :                 memset(&the_rti, 0, sizeof(GF_SystemRTInfo));
    1322             :                 the_rti.pid = GetCurrentProcessId();
    1323             :                 the_rti.nb_cores = 1;
    1324             :                 GlobalMemoryStatus(&ms);
    1325             :                 mem_usage_at_startup = ms.dwAvailPhys;
    1326             : #else
    1327             :                 /*cpu usage tools are buried in win32 dlls...*/
    1328             :                 MyGetSystemTimes = (NTGetSystemTimes) GetProcAddress(GetModuleHandle("kernel32.dll"), "GetSystemTimes");
    1329             :                 if (!MyGetSystemTimes) {
    1330             :                         MyQuerySystemInfo = (NTQuerySystemInfo) GetProcAddress(GetModuleHandle("ntdll.dll"), "NtQuerySystemInformation");
    1331             :                         if (MyQuerySystemInfo) {
    1332             :                                 GF_LOG(GF_LOG_INFO, GF_LOG_CORE, (" - CPU: QuerySystemInformation"));
    1333             :                         }
    1334             :                 } else {
    1335             :                         GF_LOG(GF_LOG_INFO, GF_LOG_CORE, (" - CPU: GetSystemsTimes"));
    1336             :                 }
    1337             :                 psapi_hinst = LoadLibrary("psapi.dll");
    1338             :                 MyGetProcessMemoryInfo = (NTGetProcessMemoryInfo) GetProcAddress(psapi_hinst, "GetProcessMemoryInfo");
    1339             :                 if (MyGetProcessMemoryInfo) {
    1340             :                         GF_LOG(GF_LOG_INFO, GF_LOG_CORE, (" - memory: GetProcessMemoryInfo"));
    1341             :                 }
    1342             :                 last_process_k_u_time = last_proc_idle_time = last_proc_k_u_time = 0;
    1343             :                 last_update_time = 0;
    1344             :                 memset(&the_rti, 0, sizeof(GF_SystemRTInfo));
    1345             :                 the_rti.pid = GetCurrentProcessId();
    1346             : 
    1347             :                 GetSystemInfo( &sysinfo );
    1348             :                 the_rti.nb_cores = sysinfo.dwNumberOfProcessors;
    1349             : #endif
    1350             :                 GF_LOG(GF_LOG_INFO, GF_LOG_CORE, ("\n"));
    1351             : 
    1352             : #else
    1353             :                 /*linux threads and OSX...*/
    1354        6241 :                 last_process_k_u_time = 0;
    1355        6241 :                 last_cpu_u_k_time = last_cpu_idle_time = 0;
    1356        6241 :                 last_update_time = 0;
    1357             :                 memset(&the_rti, 0, sizeof(GF_SystemRTInfo));
    1358        6241 :                 the_rti.pid = getpid();
    1359        6241 :                 the_rti.nb_cores = (u32) sysconf( _SC_NPROCESSORS_ONLN );
    1360        6241 :                 sys_start_time = gf_sys_clock();
    1361        6241 :                 sys_start_time_hr = gf_sys_clock_high_res();
    1362             : #endif
    1363        6241 :                 GF_LOG(GF_LOG_INFO, GF_LOG_CORE, ("[core] process id %d\n", the_rti.pid));
    1364             : 
    1365             : #ifndef _WIN32_WCE
    1366        6241 :                 setlocale( LC_NUMERIC, "C" );
    1367             : #endif
    1368             : 
    1369             : 
    1370        6241 :                 logs_mx = gf_mx_new("Logs");
    1371             : 
    1372        6241 :                 gf_rand_init(GF_FALSE);
    1373             :                 
    1374        6241 :                 gf_init_global_config(profile);
    1375             : 
    1376             : 
    1377             :         }
    1378        6249 :         sys_init += 1;
    1379             : 
    1380             : 
    1381             :         /*init RTI stats*/
    1382        6249 :         if (!memory_at_gpac_startup) {
    1383             :                 GF_SystemRTInfo rti;
    1384        6241 :                 if (gf_sys_get_rti(500, &rti, GF_RTI_SYSTEM_MEMORY_ONLY)) {
    1385        6241 :                         memory_at_gpac_startup = rti.physical_memory_avail;
    1386        6241 :                         GF_LOG(GF_LOG_INFO, GF_LOG_CORE, ("[core] System init OK - process id %d - %d MB physical RAM - %d cores\n", rti.pid, (u32) (rti.physical_memory/1024/1024), rti.nb_cores));
    1387             :                 } else {
    1388           0 :                         memory_at_gpac_startup = 0;
    1389             :                 }
    1390             :         }
    1391             : 
    1392        6249 :         return GF_OK;
    1393             : }
    1394             : 
    1395             : GF_EXPORT
    1396        6277 : void gf_sys_close()
    1397             : {
    1398        6277 :         if (sys_init > 0) {
    1399             :                 void gf_sys_cleanup_help();
    1400             : 
    1401             :                 GF_Mutex *old_log_mx;
    1402        6247 :                 sys_init --;
    1403        6247 :                 if (sys_init) return;
    1404             :                 /*prevent any call*/
    1405        6240 :                 last_update_time = 0xFFFFFFFF;
    1406             : 
    1407             : #if defined(WIN32) && !defined(_WIN32_WCE)
    1408             :                 timeEndPeriod(1);
    1409             : 
    1410             :                 MyGetSystemTimes = NULL;
    1411             :                 MyGetProcessMemoryInfo = NULL;
    1412             :                 MyQuerySystemInfo = NULL;
    1413             :                 if (psapi_hinst) FreeLibrary(psapi_hinst);
    1414             :                 psapi_hinst = NULL;
    1415             : #endif
    1416             : 
    1417        6240 :                 gf_sys_enable_remotery(GF_FALSE, GF_TRUE);
    1418             :                 
    1419        6240 :                 gf_uninit_global_config(gpac_discard_config);
    1420             : 
    1421             : #ifndef GPAC_DISABLE_LOG
    1422        6240 :                 if (gpac_log_file) {
    1423           0 :                         gf_fclose(gpac_log_file);
    1424           0 :                         gpac_log_file = NULL;
    1425             :                 }
    1426             : #endif
    1427        6240 :                 if (gpac_lang_file) gf_cfg_del(gpac_lang_file);
    1428        6240 :                 gpac_lang_file = NULL;
    1429             : 
    1430        6240 :                 gf_sys_cleanup_help();
    1431             : 
    1432        6240 :                 old_log_mx = logs_mx;
    1433        6240 :                 logs_mx = NULL;
    1434        6240 :                 gf_mx_del(old_log_mx);
    1435             : 
    1436        6240 :                 if (gpac_argv_state) {
    1437        6218 :                         gf_free(gpac_argv_state);
    1438        6218 :                         gpac_argv_state = NULL;
    1439             :                 }
    1440             :         }
    1441             : }
    1442             : 
    1443             : #ifdef GPAC_MEMORY_TRACKING
    1444             : extern size_t gpac_allocated_memory;
    1445             : extern size_t gpac_nb_alloc_blocs;
    1446             : #endif
    1447             : 
    1448             : /*CPU and Memory Usage*/
    1449             : #ifdef WIN32
    1450             : 
    1451             : Bool gf_sys_get_rti_os(u32 refresh_time_ms, GF_SystemRTInfo *rti, u32 flags)
    1452             : {
    1453             : #if defined(_WIN32_WCE)
    1454             :         THREADENTRY32 tentry;
    1455             :         u64 total_cpu_time, process_cpu_time;
    1456             :         DWORD orig_perm;
    1457             : #endif
    1458             :         MEMORYSTATUS ms;
    1459             :         u64 creation, exit, kernel, user, process_k_u_time, proc_idle_time, proc_k_u_time;
    1460             :         u32 entry_time;
    1461             :         HANDLE hSnapShot;
    1462             : 
    1463             :         assert(sys_init);
    1464             : 
    1465             :         if (!rti) return GF_FALSE;
    1466             : 
    1467             :         proc_idle_time = proc_k_u_time = process_k_u_time = 0;
    1468             : 
    1469             :         entry_time = gf_sys_clock();
    1470             :         if (last_update_time && (entry_time - last_update_time < refresh_time_ms)) {
    1471             :                 memcpy(rti, &the_rti, sizeof(GF_SystemRTInfo));
    1472             :                 return GF_FALSE;
    1473             :         }
    1474             : 
    1475             :         if (flags & GF_RTI_SYSTEM_MEMORY_ONLY) {
    1476             :                 memset(rti, 0, sizeof(GF_SystemRTInfo));
    1477             :                 rti->sampling_instant = last_update_time;
    1478             :                 GlobalMemoryStatus(&ms);
    1479             :                 rti->physical_memory = ms.dwTotalPhys;
    1480             :                 rti->physical_memory_avail = ms.dwAvailPhys;
    1481             : #ifdef GPAC_MEMORY_TRACKING
    1482             :                 rti->gpac_memory = (u64) gpac_allocated_memory;
    1483             : #endif
    1484             :                 return GF_TRUE;
    1485             :         }
    1486             : 
    1487             : #if defined (_WIN32_WCE)
    1488             : 
    1489             :         total_cpu_time = process_cpu_time = 0;
    1490             : 
    1491             :         /*get a snapshot of all running threads*/
    1492             :         orig_perm = GetCurrentPermissions();
    1493             :         SetProcPermissions(0xFFFFFFFF);
    1494             :         hSnapShot = CreateToolhelp32Snapshot(TH32CS_SNAPTHREAD, 0);
    1495             :         if (hSnapShot) {
    1496             :                 tentry.dwSize = sizeof(THREADENTRY32);
    1497             :                 the_rti.thread_count = 0;
    1498             :                 /*note we always act as if GF_RTI_ALL_PROCESSES_TIMES flag is set, since there is no other way
    1499             :                 to enumerate threads from a process, and GetProcessTimes doesn't exist on CE*/
    1500             :                 if (Thread32First(hSnapShot, &tentry)) {
    1501             :                         do {
    1502             :                                 /*get thread times*/
    1503             :                                 if (GetThreadTimes( (HANDLE) tentry.th32ThreadID, (FILETIME *) &creation, (FILETIME *) &exit, (FILETIME *) &kernel, (FILETIME *) &user)) {
    1504             :                                         total_cpu_time += user + kernel;
    1505             :                                         if (tentry.th32OwnerProcessID==the_rti.pid) {
    1506             :                                                 process_cpu_time += user + kernel;
    1507             :                                                 the_rti.thread_count ++;
    1508             :                                         }
    1509             :                                 }
    1510             :                         } while (Thread32Next(hSnapShot, &tentry));
    1511             :                 }
    1512             :                 CloseToolhelp32Snapshot(hSnapShot);
    1513             :         }
    1514             : 
    1515             :         if (flags & GF_RTI_PROCESS_MEMORY) {
    1516             :                 HEAPLIST32 hlentry;
    1517             :                 HEAPENTRY32 hentry;
    1518             :                 the_rti.process_memory = 0;
    1519             :                 hlentry.dwSize = sizeof(HEAPLIST32);
    1520             :                 hSnapShot = CreateToolhelp32Snapshot(TH32CS_SNAPHEAPLIST, the_rti.pid);
    1521             :                 if (hSnapShot && Heap32ListFirst(hSnapShot, &hlentry)) {
    1522             :                         do {
    1523             :                                 hentry.dwSize = sizeof(hentry);
    1524             :                                 if (Heap32First(hSnapShot, &hentry, hlentry.th32ProcessID, hlentry.th32HeapID)) {
    1525             :                                         do {
    1526             :                                                 the_rti.process_memory += hentry.dwBlockSize;
    1527             :                                         } while (Heap32Next(hSnapShot, &hentry));
    1528             :                                 }
    1529             :                         } while (Heap32ListNext(hSnapShot, &hlentry));
    1530             :                 }
    1531             :                 CloseToolhelp32Snapshot(hSnapShot);
    1532             :         }
    1533             :         SetProcPermissions(orig_perm);
    1534             :         total_cpu_time /= 10;
    1535             :         process_cpu_time /= 10;
    1536             : 
    1537             : #else
    1538             :         /*XP-SP1 and Win2003 servers only have GetSystemTimes support. This will give a better estimation
    1539             :         of CPU usage since we can take into account the idle time*/
    1540             :         if (MyGetSystemTimes) {
    1541             :                 u64 u_time;
    1542             :                 MyGetSystemTimes(&proc_idle_time, &proc_k_u_time, &u_time);
    1543             :                 proc_k_u_time += u_time;
    1544             :                 proc_idle_time /= 10;
    1545             :                 proc_k_u_time /= 10;
    1546             :         }
    1547             :         /*same rq for NtQuerySystemInformation*/
    1548             :         else if (MyQuerySystemInfo) {
    1549             :                 DWORD ret;
    1550             :                 SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION info;
    1551             :                 MyQuerySystemInfo(0x8 /*SystemProcessorPerformanceInformation*/, &info, sizeof(info), &ret);
    1552             :                 if (ret && (ret<=sizeof(info))) {
    1553             :                         proc_idle_time = info.IdleTime.QuadPart / 10;
    1554             :                         proc_k_u_time = (info.KernelTime.QuadPart + info.UserTime.QuadPart) / 10;
    1555             :                 }
    1556             :         }
    1557             :         /*no special API available, ONLY FETCH TIMES if requested (may eat up some time)*/
    1558             :         else if (flags & GF_RTI_ALL_PROCESSES_TIMES) {
    1559             :                 PROCESSENTRY32 pentry;
    1560             :                 /*get a snapshot of all running threads*/
    1561             :                 hSnapShot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
    1562             :                 if (!hSnapShot) return GF_FALSE;
    1563             :                 pentry.dwSize = sizeof(PROCESSENTRY32);
    1564             :                 if (Process32First(hSnapShot, &pentry)) {
    1565             :                         do {
    1566             :                                 HANDLE procH = NULL;
    1567             :                                 if (pentry.th32ProcessID) procH = OpenProcess(PROCESS_QUERY_INFORMATION, FALSE, pentry.th32ProcessID);
    1568             :                                 if (procH && GetProcessTimes(procH, (FILETIME *) &creation, (FILETIME *) &exit, (FILETIME *) &kernel, (FILETIME *) &user) ) {
    1569             :                                         user += kernel;
    1570             :                                         proc_k_u_time += user;
    1571             :                                         if (pentry.th32ProcessID==the_rti.pid) {
    1572             :                                                 process_k_u_time = user;
    1573             :                                                 //nb_threads = pentry.cntThreads;
    1574             :                                         }
    1575             :                                 }
    1576             :                                 if (procH) CloseHandle(procH);
    1577             :                         } while (Process32Next(hSnapShot, &pentry));
    1578             :                 }
    1579             :                 CloseHandle(hSnapShot);
    1580             :                 proc_k_u_time /= 10;
    1581             :         }
    1582             : 
    1583             : 
    1584             :         if (!process_k_u_time) {
    1585             :                 HANDLE procH = OpenProcess(PROCESS_QUERY_INFORMATION, FALSE, the_rti.pid);
    1586             :                 if (procH && GetProcessTimes(procH, (FILETIME *) &creation, (FILETIME *) &exit, (FILETIME *) &kernel, (FILETIME *) &user) ) {
    1587             :                         process_k_u_time = user + kernel;
    1588             :                 }
    1589             :                 if (procH) CloseHandle(procH);
    1590             :                 if (!process_k_u_time) return GF_FALSE;
    1591             :         }
    1592             :         process_k_u_time /= 10;
    1593             : 
    1594             :         /*this won't cost a lot*/
    1595             :         if (MyGetProcessMemoryInfo) {
    1596             :                 PROCESS_MEMORY_COUNTERS pmc;
    1597             :                 HANDLE procH = OpenProcess(PROCESS_QUERY_INFORMATION, FALSE, the_rti.pid);
    1598             :                 MyGetProcessMemoryInfo(procH, &pmc, sizeof (pmc));
    1599             :                 the_rti.process_memory = pmc.WorkingSetSize;
    1600             :                 if (procH) CloseHandle(procH);
    1601             :         }
    1602             :         /*THIS IS VERY HEAVY (eats up mem and time) - only perform if requested*/
    1603             :         else if (flags & GF_RTI_PROCESS_MEMORY) {
    1604             :                 HEAPLIST32 hlentry;
    1605             :                 HEAPENTRY32 hentry;
    1606             :                 the_rti.process_memory = 0;
    1607             :                 hlentry.dwSize = sizeof(HEAPLIST32);
    1608             :                 hSnapShot = CreateToolhelp32Snapshot(TH32CS_SNAPHEAPLIST, the_rti.pid);
    1609             :                 if (hSnapShot && Heap32ListFirst(hSnapShot, &hlentry)) {
    1610             :                         do {
    1611             :                                 hentry.dwSize = sizeof(hentry);
    1612             :                                 if (Heap32First(&hentry, hlentry.th32ProcessID, hlentry.th32HeapID)) {
    1613             :                                         do {
    1614             :                                                 the_rti.process_memory += hentry.dwBlockSize;
    1615             :                                         } while (Heap32Next(&hentry));
    1616             :                                 }
    1617             :                         } while (Heap32ListNext(hSnapShot, &hlentry));
    1618             :                 }
    1619             :                 CloseHandle(hSnapShot);
    1620             :         }
    1621             : #endif
    1622             : 
    1623             :         the_rti.sampling_instant = last_update_time;
    1624             : 
    1625             :         if (last_update_time) {
    1626             :                 the_rti.sampling_period_duration = entry_time - last_update_time;
    1627             :                 the_rti.process_cpu_time_diff = (u32) ((process_k_u_time - last_process_k_u_time)/1000);
    1628             : 
    1629             : #if defined(_WIN32_WCE)
    1630             :                 the_rti.total_cpu_time_diff = (u32) ((total_cpu_time - last_total_k_u_time)/1000);
    1631             :                 /*we're not that accurate....*/
    1632             :                 if (the_rti.total_cpu_time_diff > the_rti.sampling_period_duration)
    1633             :                         the_rti.sampling_period_duration = the_rti.total_cpu_time_diff;
    1634             : 
    1635             :                 /*rough values*/
    1636             :                 the_rti.cpu_idle_time = the_rti.sampling_period_duration - the_rti.total_cpu_time_diff;
    1637             :                 if (!the_rti.sampling_period_duration) the_rti.sampling_period_duration=1;
    1638             :                 the_rti.total_cpu_usage = (u32) (100 * the_rti.total_cpu_time_diff / the_rti.sampling_period_duration);
    1639             :                 if (the_rti.total_cpu_time_diff + the_rti.cpu_idle_time==0) the_rti.total_cpu_time_diff ++;
    1640             :                 the_rti.process_cpu_usage = (u32) (100*the_rti.process_cpu_time_diff / (the_rti.total_cpu_time_diff + the_rti.cpu_idle_time) );
    1641             : 
    1642             : #else
    1643             :                 /*oops, we have no choice but to assume 100% cpu usage during this period*/
    1644             :                 if (!proc_k_u_time) {
    1645             :                         the_rti.total_cpu_time_diff = the_rti.sampling_period_duration;
    1646             :                         proc_k_u_time = last_proc_k_u_time + the_rti.sampling_period_duration;
    1647             :                         the_rti.cpu_idle_time = 0;
    1648             :                         the_rti.total_cpu_usage = 100;
    1649             :                         if (the_rti.sampling_period_duration)
    1650             :                                 the_rti.process_cpu_usage = (u32) (100*the_rti.process_cpu_time_diff / the_rti.sampling_period_duration);
    1651             :                 } else {
    1652             :                         u64 samp_sys_time, idle;
    1653             :                         the_rti.total_cpu_time_diff = (u32) ((proc_k_u_time - last_proc_k_u_time)/1000);
    1654             : 
    1655             :                         /*we're not that accurate....*/
    1656             :                         if (the_rti.total_cpu_time_diff > the_rti.sampling_period_duration) {
    1657             :                                 the_rti.sampling_period_duration = the_rti.total_cpu_time_diff;
    1658             :                         }
    1659             : 
    1660             :                         if (!proc_idle_time)
    1661             :                                 proc_idle_time = last_proc_idle_time + (the_rti.sampling_period_duration - the_rti.total_cpu_time_diff);
    1662             : 
    1663             :                         samp_sys_time = proc_k_u_time - last_proc_k_u_time;
    1664             :                         idle = proc_idle_time - last_proc_idle_time;
    1665             :                         the_rti.cpu_idle_time = (u32) (idle/1000);
    1666             :                         if (samp_sys_time) {
    1667             :                                 the_rti.total_cpu_usage = (u32) ( (samp_sys_time - idle) / (samp_sys_time / 100) );
    1668             :                                 the_rti.process_cpu_usage = (u32) (100*the_rti.process_cpu_time_diff / (samp_sys_time/1000));
    1669             :                         }
    1670             :                 }
    1671             : #endif
    1672             :         }
    1673             :         last_update_time = entry_time;
    1674             :         last_process_k_u_time = process_k_u_time;
    1675             : 
    1676             :         GlobalMemoryStatus(&ms);
    1677             :         the_rti.physical_memory = ms.dwTotalPhys;
    1678             : #ifdef GPAC_MEMORY_TRACKING
    1679             :         the_rti.gpac_memory = (u64) gpac_allocated_memory;
    1680             : #endif
    1681             :         the_rti.physical_memory_avail = ms.dwAvailPhys;
    1682             : 
    1683             : #if defined(_WIN32_WCE)
    1684             :         last_total_k_u_time = total_cpu_time;
    1685             :         if (!the_rti.process_memory) the_rti.process_memory = mem_usage_at_startup - ms.dwAvailPhys;
    1686             : #else
    1687             :         last_proc_idle_time = proc_idle_time;
    1688             :         last_proc_k_u_time = proc_k_u_time;
    1689             : #endif
    1690             : 
    1691             :         if (!the_rti.gpac_memory) the_rti.gpac_memory = the_rti.process_memory;
    1692             : 
    1693             :         memcpy(rti, &the_rti, sizeof(GF_SystemRTInfo));
    1694             :         return GF_TRUE;
    1695             : }
    1696             : 
    1697             : 
    1698             : #elif defined(GPAC_CONFIG_DARWIN) && !defined(GPAC_CONFIG_IOS)
    1699             : 
    1700             : #include <sys/types.h>
    1701             : #include <sys/sysctl.h>
    1702             : #include <sys/vmmeter.h>
    1703             : #include <mach/mach_init.h>
    1704             : #include <mach/mach_host.h>
    1705             : #include <mach/mach_port.h>
    1706             : #include <mach/mach_traps.h>
    1707             : #include <mach/task_info.h>
    1708             : #include <mach/thread_info.h>
    1709             : #include <mach/thread_act.h>
    1710             : #include <mach/vm_region.h>
    1711             : #include <mach/vm_map.h>
    1712             : #include <mach/task.h>
    1713             : #if __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ >= 1060
    1714             : #include <mach/shared_region.h>
    1715             : #else
    1716             : #include <mach/shared_memory_server.h>
    1717             : #endif
    1718             : #include <mach/mach_error.h>
    1719             : 
    1720             : static u64 total_physical_memory = 0;
    1721             : 
    1722             : Bool gf_sys_get_rti_os(u32 refresh_time_ms, GF_SystemRTInfo *rti, u32 flags)
    1723             : {
    1724             :         size_t length;
    1725             :         u32 entry_time, i, percent;
    1726             :         int mib[6];
    1727             :         u64 result;
    1728             :         int pagesize;
    1729             :         u64 process_u_k_time;
    1730             :         double utime, stime;
    1731             :         vm_statistics_data_t vmstat;
    1732             :         task_t task;
    1733             :         kern_return_t error;
    1734             :         thread_array_t thread_table;
    1735             :         unsigned table_size;
    1736             :         thread_basic_info_t thi;
    1737             :         thread_basic_info_data_t thi_data;
    1738             :         struct task_basic_info ti;
    1739             :         mach_msg_type_number_t count = HOST_VM_INFO_COUNT, size = sizeof(ti);
    1740             : 
    1741             :         entry_time = gf_sys_clock();
    1742             :         if (last_update_time && (entry_time - last_update_time < refresh_time_ms)) {
    1743             :                 memcpy(rti, &the_rti, sizeof(GF_SystemRTInfo));
    1744             :                 return 0;
    1745             :         }
    1746             : 
    1747             :         mib[0] = CTL_HW;
    1748             :         mib[1] = HW_PAGESIZE;
    1749             :         length = sizeof(pagesize);
    1750             :         if (sysctl(mib, 2, &pagesize, &length, NULL, 0) < 0) {
    1751             :                 return 0;
    1752             :         }
    1753             : 
    1754             :         if (host_statistics(mach_host_self(), HOST_VM_INFO, (host_info_t)&vmstat, &count) != KERN_SUCCESS) {
    1755             :                 return 0;
    1756             :         }
    1757             : 
    1758             :         the_rti.physical_memory = (vmstat.wire_count + vmstat.active_count + vmstat.inactive_count + vmstat.free_count)* pagesize;
    1759             :         the_rti.physical_memory_avail = vmstat.free_count * pagesize;
    1760             : 
    1761             :         if (!total_physical_memory) {
    1762             :                 mib[0] = CTL_HW;
    1763             :                 mib[1] = HW_MEMSIZE;
    1764             :                 length = sizeof(u64);
    1765             :                 if (sysctl(mib, 2, &result, &length, NULL, 0) >= 0) {
    1766             :                         total_physical_memory = result;
    1767             :                 }
    1768             :         }
    1769             :         the_rti.physical_memory = total_physical_memory;
    1770             : 
    1771             :         error = task_for_pid(mach_task_self(), the_rti.pid, &task);
    1772             :         if (error) {
    1773             :                 GF_LOG(GF_LOG_ERROR, GF_LOG_CORE, ("[RTI] Cannot get process task for PID %d: error %d\n", the_rti.pid, error));
    1774             :                 return 0;
    1775             :         }
    1776             : 
    1777             :         error = task_info(mach_task_self(), TASK_BASIC_INFO, (task_info_t)&ti, &size);
    1778             :         if (error) {
    1779             :                 GF_LOG(GF_LOG_ERROR, GF_LOG_CORE, ("[RTI] Cannot get process task info (PID %d): error %d\n", the_rti.pid, error));
    1780             :                 return 0;
    1781             :         }
    1782             : 
    1783             :         percent = 0;
    1784             :         utime = ti.user_time.seconds + ti.user_time.microseconds * 1e-6;
    1785             :         stime = ti.system_time.seconds + ti.system_time.microseconds * 1e-6;
    1786             :         error = task_threads(task, &thread_table, &table_size);
    1787             :         if (error != KERN_SUCCESS) {
    1788             :                 GF_LOG(GF_LOG_ERROR, GF_LOG_CORE, ("[RTI] Cannot get threads task for PID %d: error %d\n", the_rti.pid, error));
    1789             :                 return 0;
    1790             :         }
    1791             :         thi = &thi_data;
    1792             :         for (i = 0; i != table_size; ++i) {
    1793             :                 count = THREAD_BASIC_INFO_COUNT;
    1794             :                 error = thread_info(thread_table[i], THREAD_BASIC_INFO, (thread_info_t)thi, &count);
    1795             :                 if (error != KERN_SUCCESS) {
    1796             :                         GF_LOG(GF_LOG_DEBUG, GF_LOG_CORE, ("[RTI] Unexpected thread_info error for process %d: %s\n", the_rti.pid, mach_error_string(error) ));
    1797             :                         break;
    1798             :                 }
    1799             :                 if ((thi->flags & TH_FLAGS_IDLE) == 0) {
    1800             :                         utime += thi->user_time.seconds + thi->user_time.microseconds * 1e-6;
    1801             :                         stime += thi->system_time.seconds + thi->system_time.microseconds * 1e-6;
    1802             :                         percent +=  (u32) (100 * (double)thi->cpu_usage / TH_USAGE_SCALE);
    1803             :                 }
    1804             :         }
    1805             :         vm_deallocate(mach_task_self(), (vm_offset_t)thread_table, table_size * sizeof(thread_array_t));
    1806             :         mach_port_deallocate(mach_task_self(), task);
    1807             : 
    1808             :         process_u_k_time = utime + stime;
    1809             : 
    1810             :         the_rti.sampling_instant = last_update_time;
    1811             : 
    1812             :         if (last_update_time) {
    1813             :                 the_rti.sampling_period_duration = (entry_time - last_update_time);
    1814             :                 the_rti.process_cpu_time_diff = (process_u_k_time - last_process_k_u_time) * 10;
    1815             : 
    1816             :                 the_rti.total_cpu_time_diff = the_rti.sampling_period_duration;
    1817             :                 /*TODO*/
    1818             :                 the_rti.cpu_idle_time = 0;
    1819             :                 the_rti.total_cpu_usage = 0;
    1820             :                 if (!the_rti.process_cpu_time_diff) the_rti.process_cpu_time_diff = the_rti.total_cpu_time_diff;
    1821             : 
    1822             :                 the_rti.process_cpu_usage = percent;
    1823             :         } else {
    1824             :                 mem_at_startup = the_rti.physical_memory_avail;
    1825             :         }
    1826             :         the_rti.process_memory = mem_at_startup - the_rti.physical_memory_avail;
    1827             : 
    1828             : #ifdef GPAC_MEMORY_TRACKING
    1829             :         the_rti.gpac_memory = gpac_allocated_memory;
    1830             : #endif
    1831             : 
    1832             :         last_process_k_u_time = process_u_k_time;
    1833             :         last_cpu_idle_time = 0;
    1834             :         last_update_time = entry_time;
    1835             :         memcpy(rti, &the_rti, sizeof(GF_SystemRTInfo));
    1836             :         return 1;
    1837             : }
    1838             : 
    1839             : //linux
    1840             : #else
    1841             : 
    1842        6678 : Bool gf_sys_get_rti_os(u32 refresh_time_ms, GF_SystemRTInfo *rti, u32 flags)
    1843             : {
    1844             :         u32 entry_time;
    1845             :         u64 process_u_k_time;
    1846             :         u32 u_k_time, idle_time;
    1847             : #if 0
    1848             :         char szProc[100];
    1849             : #endif
    1850             :         FILE *f;
    1851             : 
    1852             :         assert(sys_init);
    1853             : 
    1854        6678 :         entry_time = gf_sys_clock();
    1855        6678 :         if (last_update_time && (entry_time - last_update_time < refresh_time_ms)) {
    1856             :                 memcpy(rti, &the_rti, sizeof(GF_SystemRTInfo));
    1857          21 :                 return 0;
    1858             :         }
    1859        6657 :         u_k_time = idle_time = 0;
    1860        6657 :         f = gf_fopen("/proc/stat", "r");
    1861        6657 :         if (f) {
    1862             :                 char line[2048];
    1863             :                 u32 k_time, nice_time, u_time;
    1864        6657 :                 if (gf_fgets(line, 128, f) != NULL) {
    1865        6657 :                         if (sscanf(line, "cpu  %u %u %u %u\n", &u_time, &k_time, &nice_time, &idle_time) == 4) {
    1866        6657 :                                 u_k_time = u_time + k_time + nice_time;
    1867             :                         }
    1868             :                 }
    1869        6657 :                 gf_fclose(f);
    1870             :         }
    1871             :         process_u_k_time = 0;
    1872        6657 :         the_rti.process_memory = 0;
    1873             : 
    1874             :         /*FIXME? under LinuxThreads this will only fetch stats for the calling thread, we would have to enumerate /proc to get
    1875             :         the complete CPU usage of all therads of the process...*/
    1876             : #if 0
    1877             :         sprintf(szProc, "/proc/%d/stat", the_rti.pid);
    1878             :         f = gf_fopen(szProc, "r");
    1879             :         if (f) {
    1880             :                 gf_fflush(f);
    1881             :                 if (gf_fgets(line, 2048, f) != NULL) {
    1882             :                         char state;
    1883             :                         char *start;
    1884             :                         long cutime, cstime, priority, nice, itrealvalue, rss;
    1885             :                         int exit_signal, processor;
    1886             :                         unsigned long flags, minflt, cminflt, majflt, cmajflt, utime, stime,starttime, vsize, rlim, startcode, endcode, startstack, kstkesp, kstkeip, signal, blocked, sigignore, sigcatch, wchan, nswap, cnswap, rem;
    1887             :                         int ppid, pgrp ,session, tty_nr, tty_pgrp, res;
    1888             :                         start = strchr(line, ')');
    1889             :                         if (start) start += 2;
    1890             :                         else {
    1891             :                                 start = strchr(line, ' ');
    1892             :                                 start++;
    1893             :                         }
    1894             :                         res = sscanf(start,"%c %d %d %d %d %d %lu %lu %lu %lu \
    1895             : %lu %lu %lu %ld %ld %ld %ld %ld %ld %lu \
    1896             : %lu %ld %lu %lu %lu %lu %lu %lu %lu %lu \
    1897             : %lu %lu %lu %lu %lu %d %d",
    1898             :                                      &state, &ppid, &pgrp, &session, &tty_nr, &tty_pgrp, &flags, &minflt, &cminflt, &majflt,
    1899             :                                      &cmajflt, &utime, &stime, &cutime, &cstime, &priority, &nice, &itrealvalue, &rem, &starttime,
    1900             :                                      &vsize, &rss, &rlim, &startcode, &endcode, &startstack, &kstkesp, &kstkeip, &signal, &blocked,
    1901             :                                      &sigignore, &sigcatch, &wchan, &nswap, &cnswap, &exit_signal, &processor);
    1902             : 
    1903             :                         if (res) process_u_k_time = (u64) (cutime + cstime);
    1904             :                         else {
    1905             :                                 GF_LOG(GF_LOG_ERROR, GF_LOG_CORE, ("[RTI] PROC %s parse error\n", szProc));
    1906             :                         }
    1907             :                 } else {
    1908             :                         GF_LOG(GF_LOG_ERROR, GF_LOG_CORE, ("[RTI] error reading pid/stat\n\n", szProc));
    1909             :                 }
    1910             :                 gf_fclose(f);
    1911             :         } else {
    1912             :                 GF_LOG(GF_LOG_ERROR, GF_LOG_CORE, ("[RTI] cannot open %s\n", szProc));
    1913             :         }
    1914             :         sprintf(szProc, "/proc/%d/status", the_rti.pid);
    1915             :         f = gf_fopen(szProc, "r");
    1916             :         if (f) {
    1917             :                 while (gf_fgets(line, 1024, f) != NULL) {
    1918             :                         if (!strnicmp(line, "VmSize:", 7)) {
    1919             :                                 sscanf(line, "VmSize: %"LLD" kB",  &the_rti.process_memory);
    1920             :                                 the_rti.process_memory *= 1024;
    1921             :                         }
    1922             :                 }
    1923             :                 gf_fclose(f);
    1924             :         } else {
    1925             :                 GF_LOG(GF_LOG_ERROR, GF_LOG_CORE, ("[RTI] cannot open %s\n", szProc));
    1926             :         }
    1927             : #endif
    1928             : 
    1929             : 
    1930             : #ifndef GPAC_CONFIG_IOS
    1931        6657 :         the_rti.physical_memory = the_rti.physical_memory_avail = 0;
    1932        6657 :         f = gf_fopen("/proc/meminfo", "r");
    1933        6657 :         if (f) {
    1934             :                 char line[2048];
    1935       13314 :                 while (gf_fgets(line, 1024, f) != NULL) {
    1936       13314 :                         if (!strnicmp(line, "MemTotal:", 9)) {
    1937        6657 :                                 sscanf(line, "MemTotal: "LLU" kB",  &the_rti.physical_memory);
    1938        6657 :                                 the_rti.physical_memory *= 1024;
    1939        6657 :                         } else if (!strnicmp(line, "MemFree:", 8)) {
    1940        6657 :                                 sscanf(line, "MemFree: "LLU" kB",  &the_rti.physical_memory_avail);
    1941        6657 :                                 the_rti.physical_memory_avail *= 1024;
    1942        6657 :                                 break;
    1943             :                         }
    1944             :                 }
    1945        6657 :                 gf_fclose(f);
    1946             :         } else {
    1947           0 :                 GF_LOG(GF_LOG_ERROR, GF_LOG_CORE, ("[RTI] cannot open /proc/meminfo\n"));
    1948             :         }
    1949             : #endif
    1950             : 
    1951        6657 :         the_rti.sampling_instant = last_update_time;
    1952             : 
    1953        6657 :         if (last_update_time) {
    1954         209 :                 the_rti.sampling_period_duration = (entry_time - last_update_time);
    1955         209 :                 the_rti.process_cpu_time_diff = (u32) (process_u_k_time - last_process_k_u_time) * 10;
    1956             : 
    1957             :                 /*oops, we have no choice but to assume 100% cpu usage during this period*/
    1958         209 :                 if (!u_k_time) {
    1959           0 :                         the_rti.total_cpu_time_diff = the_rti.sampling_period_duration;
    1960           0 :                         u_k_time = (u32) (last_cpu_u_k_time + the_rti.sampling_period_duration);
    1961           0 :                         the_rti.cpu_idle_time = 0;
    1962           0 :                         the_rti.total_cpu_usage = 100;
    1963           0 :                         if (!the_rti.process_cpu_time_diff) the_rti.process_cpu_time_diff = the_rti.total_cpu_time_diff;
    1964           0 :                         the_rti.process_cpu_usage = (u32) ( 100 *  the_rti.process_cpu_time_diff / the_rti.sampling_period_duration);
    1965             :                 } else {
    1966             :                         u64 samp_sys_time;
    1967             :                         /*move to ms (/proc/stat gives times in 100 ms unit*/
    1968         209 :                         the_rti.total_cpu_time_diff = (u32) (u_k_time - last_cpu_u_k_time)*10;
    1969             : 
    1970             :                         /*we're not that accurate....*/
    1971         209 :                         if (the_rti.total_cpu_time_diff > the_rti.sampling_period_duration)
    1972           4 :                                 the_rti.sampling_period_duration = the_rti.total_cpu_time_diff;
    1973             : 
    1974         209 :                         if (!idle_time) idle_time = (the_rti.sampling_period_duration - the_rti.total_cpu_time_diff)/10;
    1975         209 :                         samp_sys_time = u_k_time - last_cpu_u_k_time;
    1976         209 :                         the_rti.cpu_idle_time = (u32) (idle_time - last_cpu_idle_time);
    1977         209 :                         if (the_rti.cpu_idle_time + samp_sys_time > 0)
    1978          16 :                                 the_rti.total_cpu_usage = (u32) ( 100 * samp_sys_time / (the_rti.cpu_idle_time + samp_sys_time ) );
    1979             :                         else
    1980         193 :                                 the_rti.total_cpu_usage = 0;
    1981             :                         /*move to ms (/proc/stat gives times in 100 ms unit*/
    1982         209 :                         the_rti.cpu_idle_time *= 10;
    1983         209 :                         if (!the_rti.process_cpu_time_diff) the_rti.process_cpu_time_diff = the_rti.total_cpu_time_diff;
    1984         209 :                         if (the_rti.cpu_idle_time + 10*samp_sys_time > 0)
    1985          16 :                                 the_rti.process_cpu_usage = (u32) ( 100 *  the_rti.process_cpu_time_diff / (the_rti.cpu_idle_time + 10*samp_sys_time ) );
    1986             :                         else
    1987         193 :                                 the_rti.process_cpu_usage = 0;
    1988             :                 }
    1989             :         } else {
    1990        6448 :                 mem_at_startup = the_rti.physical_memory_avail;
    1991             :         }
    1992        6657 :         the_rti.process_memory = mem_at_startup - the_rti.physical_memory_avail;
    1993             : #ifdef GPAC_MEMORY_TRACKING
    1994        6657 :         the_rti.gpac_memory = gpac_allocated_memory;
    1995             : #endif
    1996        6657 :         last_process_k_u_time = process_u_k_time;
    1997        6657 :         last_cpu_idle_time = idle_time;
    1998        6657 :         last_cpu_u_k_time = u_k_time;
    1999        6657 :         last_update_time = entry_time;
    2000             :         memcpy(rti, &the_rti, sizeof(GF_SystemRTInfo));
    2001        6657 :         return 1;
    2002             : }
    2003             : 
    2004             : #endif
    2005             : 
    2006             : GF_EXPORT
    2007        6678 : Bool gf_sys_get_rti(u32 refresh_time_ms, GF_SystemRTInfo *rti, u32 flags)
    2008             : {
    2009        6678 :         Bool res = gf_sys_get_rti_os(refresh_time_ms, rti, flags);
    2010        6678 :         if (res) {
    2011        6657 :                 if (!rti->process_memory) rti->process_memory = memory_at_gpac_startup - rti->physical_memory_avail;
    2012        6657 :                 if (!rti->gpac_memory) rti->gpac_memory = memory_at_gpac_startup - rti->physical_memory_avail;
    2013             :         }
    2014        6678 :         return res;
    2015             : }
    2016             : 
    2017             : static char szCacheDir[GF_MAX_PATH];
    2018             : 
    2019       12890 : const char * gf_get_default_cache_directory_ex(Bool do_create)
    2020             : {
    2021             :         const char *cache_dir;
    2022             :         char root_tmp[GF_MAX_PATH];
    2023             :         size_t len;
    2024             : 
    2025       12890 :         cache_dir = gf_opts_get_key("core", "cache");
    2026       12890 :         if (cache_dir) return cache_dir;
    2027             : 
    2028             : #ifdef _WIN32_WCE
    2029             :         strcpy(szCacheDir, "\\windows\\temp" );
    2030             : #elif defined(WIN32)
    2031             :         GetTempPath(GF_MAX_PATH, szCacheDir);
    2032             : #elif defined(GPAC_CONFIG_ANDROID)
    2033             :         strcpy(szCacheDir, "/data/data/com.gpac.Osmo4/cache");
    2034             : #else
    2035             :         strcpy(szCacheDir, "/tmp");
    2036             : #endif
    2037             : 
    2038             :         strcpy(root_tmp, szCacheDir);
    2039             : 
    2040       12420 :         len = strlen(szCacheDir);
    2041       12420 :         if (szCacheDir[len-1] != GF_PATH_SEPARATOR) {
    2042       12420 :                 szCacheDir[len] = GF_PATH_SEPARATOR;
    2043       12420 :                 szCacheDir[len+1] = 0;
    2044             :         }
    2045             : 
    2046             :         strcat(szCacheDir, "gpac_cache");
    2047             : 
    2048       12420 :         if (do_create && !gf_dir_exists(szCacheDir) && gf_mkdir(szCacheDir)!=GF_OK ) {
    2049             :                 strcpy(szCacheDir, root_tmp);
    2050           0 :                 return szCacheDir;
    2051             :         }
    2052             :         return szCacheDir;
    2053             : }
    2054             : 
    2055             : GF_EXPORT
    2056         470 : const char * gf_get_default_cache_directory()
    2057             : {
    2058         470 :         return gf_get_default_cache_directory_ex(GF_TRUE);
    2059             : }
    2060             : 
    2061             : 
    2062             : GF_EXPORT
    2063           6 : Bool gf_sys_get_battery_state(Bool *onBattery, u32 *onCharge, u32*level, u32 *batteryLifeTime, u32 *batteryFullLifeTime)
    2064             : {
    2065             : #if defined(_WIN32_WCE)
    2066             :         SYSTEM_POWER_STATUS_EX sps;
    2067             :         GetSystemPowerStatusEx(&sps, 0);
    2068             :         if (onBattery) *onBattery = sps.ACLineStatus ? 0 : 1;
    2069             :         if (onCharge) *onCharge = (sps.BatteryFlag & BATTERY_FLAG_CHARGING) ? 1 : 0;
    2070             :         if (level) *level = sps.BatteryLifePercent;
    2071             :         if (batteryLifeTime) *batteryLifeTime = sps.BatteryLifeTime;
    2072             :         if (batteryFullLifeTime) *batteryFullLifeTime = sps.BatteryFullLifeTime;
    2073             : #elif defined(WIN32)
    2074             :         SYSTEM_POWER_STATUS sps;
    2075             :         GetSystemPowerStatus(&sps);
    2076             :         if (onBattery) *onBattery = sps.ACLineStatus ? GF_FALSE : GF_TRUE;
    2077             :         if (onCharge) *onCharge = (sps.BatteryFlag & BATTERY_FLAG_CHARGING) ? 1 : 0;
    2078             :         if (level) *level = sps.BatteryLifePercent;
    2079             :         if (batteryLifeTime) *batteryLifeTime = sps.BatteryLifeTime;
    2080             :         if (batteryFullLifeTime) *batteryFullLifeTime = sps.BatteryFullLifeTime;
    2081             : #endif
    2082           6 :         return GF_TRUE;
    2083             : }
    2084             : 
    2085             : 
    2086             : #if 0 //global lock currently not used
    2087             : 
    2088             : struct GF_GlobalLock {
    2089             :         const char * resourceName;
    2090             : };
    2091             : 
    2092             : 
    2093             : #ifndef WIN32
    2094             : #define CPF_CLOEXEC 1
    2095             : 
    2096             : #include <sys/stat.h>
    2097             : #include <fcntl.h>
    2098             : #include <unistd.h>
    2099             : 
    2100             : struct _GF_GlobalLock_opaque {
    2101             :         char * resourceName;
    2102             :         char * pidFile;
    2103             :         int fd;
    2104             : };
    2105             : 
    2106             : GF_GlobalLock * gf_create_PID_file( const char * resourceName )
    2107             : {
    2108             :         const char * prefix = "/gpac_lock_";
    2109             :         const char * dir = gf_get_default_cache_directory();
    2110             :         char * pidfile;
    2111             :         int flags;
    2112             :         int status;
    2113             :         pidfile = gf_malloc(strlen(dir)+strlen(prefix)+strlen(resourceName)+1);
    2114             :         strcpy(pidfile, dir);
    2115             :         strcat(pidfile, prefix);
    2116             :         /* Use only valid names for file */
    2117             :         {
    2118             :                 const char *res;
    2119             :                 char * pid = &(pidfile[strlen(pidfile)]);
    2120             :                 for (res = resourceName; *res ; res++) {
    2121             :                         if (*res >= 'A' && *res <= 'z')
    2122             :                                 *pid = * res;
    2123             :                         else
    2124             :                                 *pid = '_';
    2125             :                         pid++;
    2126             :                 }
    2127             :                 *pid = '\0';
    2128             :         }
    2129             :         int fd = open(pidfile, O_RDWR | O_CREAT, S_IRUSR | S_IWUSR);
    2130             :         if (fd == -1)
    2131             :                 goto exit;
    2132             :         /* Get the flags */
    2133             :         flags = fcntl(fd, F_GETFD);
    2134             :         if (flags == -1) {
    2135             :                 goto exit;
    2136             :         }
    2137             :         /* Set FD_CLOEXEC, so exclusive lock will be removed on exit, so even if GPAC crashes,
    2138             :         * lock will be allowed for next instance */
    2139             :         flags |= FD_CLOEXEC;
    2140             :         /* Now, update the flags */
    2141             :         if (fcntl(fd, F_SETFD, flags) == -1) {
    2142             :                 goto exit;
    2143             :         }
    2144             : 
    2145             :         /* Now, we try to lock the file */
    2146             :         {
    2147             :                 struct flock fl;
    2148             :                 fl.l_type = F_WRLCK;
    2149             :                 fl.l_whence = SEEK_SET;
    2150             :                 fl.l_start = fl.l_len = 0;
    2151             :                 status = fcntl(fd, F_SETLK, &fl);
    2152             :         }
    2153             : 
    2154             :         if (status == -1) {
    2155             :                 goto exit;
    2156             :         }
    2157             : 
    2158             :         if (ftruncate(fd, 0) == -1) {
    2159             :                 goto exit;
    2160             :         }
    2161             :         /* Write the PID */
    2162             :         {
    2163             :                 int sz = 100;
    2164             :                 char * buf = gf_malloc( sz );
    2165             :                 sz = snprintf(buf, sz, "%ld\n", (long) getpid());
    2166             :                 if (write(fd, buf, sz) != sz) {
    2167             :                         gf_free(buf);
    2168             :                         goto exit;
    2169             :                 }
    2170             :         }
    2171             :         sync();
    2172             :         {
    2173             :                 GF_GlobalLock * lock = gf_malloc( sizeof(GF_GlobalLock));
    2174             :                 lock->resourceName = gf_strdup(resourceName);
    2175             :                 lock->pidFile = pidfile;
    2176             :                 lock->fd = fd;
    2177             :                 return lock;
    2178             :         }
    2179             : exit:
    2180             :         if (fd >= 0)
    2181             :                 close(fd);
    2182             :         return NULL;
    2183             : }
    2184             : #else /* WIN32 */
    2185             : struct _GF_GlobalLock_opaque {
    2186             :         char * resourceName;
    2187             :         HANDLE hMutex; /*a named mutex is a system-mode object on windows*/
    2188             : };
    2189             : #endif
    2190             : 
    2191             : GF_EXPORT
    2192             : GF_GlobalLock * gf_global_resource_lock(const char * resourceName) {
    2193             : #ifdef WIN32
    2194             : #ifdef _WIN32_WCE
    2195             :         unsigned short sWResourceName[MAX_PATH];
    2196             : #endif
    2197             :         DWORD lastErr;
    2198             :         GF_GlobalLock *lock = gf_malloc(sizeof(GF_GlobalLock));
    2199             :         lock->resourceName = gf_strdup(resourceName);
    2200             : 
    2201             :         /*first ensure mutex is created*/
    2202             : #ifdef _WIN32_WCE
    2203             :         CE_CharToWide((char *)resourceName, sWResourceName);
    2204             :         lock->hMutex = CreateMutex(NULL, TRUE, sWResourceName);
    2205             : #else
    2206             :         lock->hMutex = CreateMutex(NULL, TRUE, resourceName);
    2207             : #endif
    2208             :         lastErr = GetLastError();
    2209             :         if (lastErr && lastErr == ERROR_ALREADY_EXISTS)
    2210             :                 return NULL;
    2211             :         if (!lock->hMutex)
    2212             :         {
    2213             :                 GF_LOG(GF_LOG_ERROR, GF_LOG_MUTEX, ("[Mutex] Couldn't create mutex for global lock: %d\n", lastErr));
    2214             :                 return NULL;
    2215             :         }
    2216             : 
    2217             :         /*then lock it*/
    2218             :         switch (WaitForSingleObject(lock->hMutex, INFINITE)) {
    2219             :         case WAIT_ABANDONED:
    2220             :         case WAIT_TIMEOUT:
    2221             :                 assert(0); /*serious error: someone has modified the object elsewhere*/
    2222             :                 GF_LOG(GF_LOG_ERROR, GF_LOG_MUTEX, ("[Mutex] Couldn't get the global lock\n"));
    2223             :                 gf_global_resource_unlock(lock);
    2224             :                 return NULL;
    2225             :         }
    2226             : 
    2227             :         return lock;
    2228             : #else /* WIN32 */
    2229             :         return gf_create_PID_file(resourceName);
    2230             : #endif /* WIN32 */
    2231             : }
    2232             : 
    2233             : /*!
    2234             :  * Unlock a previouly locked resource
    2235             : \param lock The resource to unlock
    2236             : \param GF_OK if evertything went fine
    2237             :  */
    2238             : GF_EXPORT
    2239             : GF_Err gf_global_resource_unlock(GF_GlobalLock * lock) {
    2240             :         if (!lock)
    2241             :                 return GF_BAD_PARAM;
    2242             : #ifndef WIN32
    2243             :         assert( lock->pidFile);
    2244             :         close(lock->fd);
    2245             :         if (unlink(lock->pidFile))
    2246             :                 perror("Failed to unlink lock file");
    2247             :         gf_free(lock->pidFile);
    2248             :         lock->pidFile = NULL;
    2249             :         lock->fd = -1;
    2250             : #else /* WIN32 */
    2251             :         {
    2252             :                 /*MSDN: "The mutex object is destroyed when its last handle has been closed."*/
    2253             :                 BOOL ret = ReleaseMutex(lock->hMutex);
    2254             :                 if (!ret) {
    2255             :                         DWORD err = GetLastError();
    2256             :                         GF_LOG(GF_LOG_ERROR, GF_LOG_MUTEX, ("[Mutex] Couldn't release mutex for global lock: %d\n", err));
    2257             :                 }
    2258             :                 ret = CloseHandle(lock->hMutex);
    2259             :                 if (!ret) {
    2260             :                         DWORD err = GetLastError();
    2261             :                         GF_LOG(GF_LOG_ERROR, GF_LOG_MUTEX, ("[Mutex] Couldn't destroy mutex for global lock: %d\n", err));
    2262             :                 }
    2263             :         }
    2264             : #endif
    2265             :         if (lock->resourceName)
    2266             :                 gf_free(lock->resourceName);
    2267             :         lock->resourceName = NULL;
    2268             :         gf_free(lock);
    2269             :         return GF_OK;
    2270             : }
    2271             : 
    2272             : #endif //global lock uni-used
    2273             : 
    2274             : 
    2275             : #ifdef GPAC_CONFIG_ANDROID
    2276             : 
    2277             : fm_callback_func fm_cbk = NULL;
    2278             : static void *fm_cbk_obj = NULL;
    2279             : 
    2280             : void gf_fm_request_set_callback(void *cbk_obj, fm_callback_func cbk_func) {
    2281             :         fm_cbk = cbk_func;
    2282             :         fm_cbk_obj = cbk_obj;
    2283             : }
    2284             : 
    2285             : void gf_fm_request_call(u32 type, u32 param, int *value) {
    2286             :         if (fm_cbk)
    2287             :                 fm_cbk(fm_cbk_obj, type, param, value);
    2288             : }
    2289             : 
    2290             : #endif //GPAC_CONFIG_ANDROID
    2291             : 
    2292             : 
    2293             : static u32 ntp_shift = GF_NTP_SEC_1900_TO_1970;
    2294             : 
    2295             : GF_EXPORT
    2296           1 : void gf_net_set_ntp_shift(s32 shift)
    2297             : {
    2298           1 :         ntp_shift = GF_NTP_SEC_1900_TO_1970 + shift;
    2299           1 : }
    2300             : 
    2301             : /*
    2302             :                 NTP tools
    2303             : */
    2304             : GF_EXPORT
    2305      150167 : void gf_net_get_ntp(u32 *sec, u32 *frac)
    2306             : {
    2307             :         u64 frac_part;
    2308             :         struct timeval now;
    2309      150167 :         gettimeofday(&now, NULL);
    2310      150167 :         if (sec) {
    2311      150167 :                 *sec = (u32) (now.tv_sec) + ntp_shift;
    2312             :         }
    2313             : 
    2314      150167 :         if (frac) {
    2315      150167 :                 frac_part = now.tv_usec * 0xFFFFFFFFULL;
    2316      150167 :                 frac_part /= 1000000;
    2317      150167 :                 *frac = (u32) ( frac_part );
    2318             :         }
    2319      150167 : }
    2320             : 
    2321             : GF_EXPORT
    2322           7 : u64 gf_net_get_ntp_ts()
    2323             : {
    2324             :         u64 res;
    2325             :         u32 sec, frac;
    2326           7 :         gf_net_get_ntp(&sec, &frac);
    2327           7 :         res = sec;
    2328           7 :         res<<= 32;
    2329           7 :         res |= frac;
    2330           7 :         return res;
    2331             : }
    2332             : 
    2333             : GF_EXPORT
    2334           1 : s32 gf_net_ntp_diff_ms(u64 ntp_a, u64 ntp_b)
    2335             : {
    2336             :         u32 ntp_a_s, ntp_a_f, ntp_b_s, ntp_b_f;
    2337             :         s64 ntp_a_ms, ntp_b_ms;
    2338             : 
    2339           1 :         ntp_a_s = (ntp_a >> 32);
    2340             :         ntp_a_f = (u32) (ntp_a & 0xFFFFFFFFULL);
    2341           1 :         ntp_b_s = (ntp_b >> 32);
    2342             :         ntp_b_f = (u32) (ntp_b & 0xFFFFFFFFULL);
    2343             : 
    2344           1 :         ntp_a_ms = ntp_a_s;
    2345           1 :         ntp_a_ms *= 1000;
    2346           1 :         ntp_a_ms += ((u64) ntp_a_f)*1000 / 0xFFFFFFFFULL;
    2347             : 
    2348           1 :         ntp_b_ms = ntp_b_s;
    2349           1 :         ntp_b_ms *= 1000;
    2350           1 :         ntp_b_ms += ((u64) ntp_b_f)*1000 / 0xFFFFFFFFULL;
    2351             : 
    2352           1 :         return (s32) (ntp_a_ms - ntp_b_ms);
    2353             : }
    2354             : 
    2355             : GF_EXPORT
    2356           1 : s32 gf_net_get_ntp_diff_ms(u64 ntp)
    2357             : {
    2358             :         u32 remote_s, remote_f, local_s, local_f;
    2359             :         s64 local, remote;
    2360             : 
    2361           1 :         remote_s = (ntp >> 32);
    2362             :         remote_f = (u32) (ntp & 0xFFFFFFFFULL);
    2363           1 :         gf_net_get_ntp(&local_s, &local_f);
    2364             : 
    2365           1 :         local = local_s;
    2366           1 :         local *= 1000;
    2367           1 :         local += ((u64) local_f)*1000 / 0xFFFFFFFFULL;
    2368             : 
    2369           1 :         remote = remote_s;
    2370           1 :         remote *= 1000;
    2371           1 :         remote += ((u64) remote_f)*1000 / 0xFFFFFFFFULL;
    2372             : 
    2373           1 :         return (s32) (local - remote);
    2374             : }
    2375             : 
    2376             : #if 0
    2377             : /*!
    2378             : 
    2379             : Adds or remove a given amount of microseconds to an NTP timestamp
    2380             : \param ntp NTP timestamp
    2381             : \param usec microseconds to add/remove
    2382             : \return adjusted NTP timestamp
    2383             :  */
    2384             : GF_EXPORT
    2385             : u64 gf_net_add_usec(u64 ntp, s32 usec)
    2386             : {
    2387             :         u64 sec, frac;
    2388             :         s64 usec_ntp;
    2389             : 
    2390             :         sec = (ntp >> 32);
    2391             :         frac = (ntp & 0xFFFFFFFFULL);
    2392             :         usec_ntp = (s64) ( frac*1000000 / 0xFFFFFFFFULL );
    2393             :         usec_ntp += usec;
    2394             :         while (usec_ntp > 1000000) {
    2395             :                 usec_ntp -= 1000000;
    2396             :                 sec += 1;
    2397             :         }
    2398             :         while (usec_ntp < 0) {
    2399             :                 usec_ntp += 1000000;
    2400             :                 sec -= 1;
    2401             :         }
    2402             :         ntp = ( usec_ntp * 0xFFFFFFFFULL / 1000000 ) & 0xFFFFFFFFULL;
    2403             :         ntp |= (sec<<32);
    2404             :         return ntp;
    2405             : }
    2406             : #endif
    2407             : 
    2408             : 
    2409             : GF_EXPORT
    2410       70473 : u64 gf_net_get_ntp_ms()
    2411             : {
    2412             :         u32 sec, frac;
    2413             :         u64 time_ms;
    2414             :         Double msec;
    2415             : 
    2416       70473 :         gf_net_get_ntp(&sec, &frac);
    2417       70473 :         time_ms = sec;
    2418       70473 :         time_ms *= 1000;
    2419       70473 :         msec = frac*1000.0;
    2420       70473 :         msec /= 0xFFFFFFFF;
    2421             : 
    2422       70473 :         time_ms += (u32)msec;
    2423             : 
    2424       70473 :         return time_ms;
    2425             : }
    2426             : 
    2427             : 
    2428             : 
    2429             : GF_EXPORT
    2430           4 : s32 gf_net_get_timezone()
    2431             : {
    2432             : #if defined(_WIN32_WCE)
    2433             :         return 0;
    2434             : #else
    2435             :         //this has been commented due to some reports of broken implementation on some systems ...
    2436             :         //              s32 val = timezone;
    2437             :         //              return val;
    2438             : 
    2439             : 
    2440             :         /*FIXME - avoid errors at midnight when estimating timezone this does not work !!*/
    2441             :         s32 t_timezone;
    2442             :         struct tm t_gmt, t_local;
    2443             :         time_t t_time;
    2444           4 :         t_time = time(NULL);
    2445           4 :         t_gmt = *gf_gmtime(&t_time);
    2446           4 :         t_local = *localtime(&t_time);
    2447             : 
    2448           4 :         t_timezone = (t_gmt.tm_hour - t_local.tm_hour) * 3600 + (t_gmt.tm_min - t_local.tm_min) * 60;
    2449           4 :         return t_timezone;
    2450             : #endif
    2451             : }
    2452             : 
    2453             : GF_EXPORT
    2454           2 : Bool gf_net_time_is_dst()
    2455             : {
    2456             : #if defined(_WIN32_WCE)
    2457             :         return GF_FALSE;
    2458             : #else
    2459             :         struct tm t_local;
    2460             :         time_t t_time;
    2461           2 :         t_time = time(NULL);
    2462           2 :         t_local = *localtime(&t_time);
    2463           2 :         return t_local.tm_isdst ? GF_TRUE : GF_FALSE;
    2464             : #endif
    2465             : }
    2466             : //no mkgmtime on mingw..., use our own
    2467             : #if (defined(WIN32) && defined(__GNUC__))
    2468             : 
    2469             : static Bool leap_year(u32 year) {
    2470             :         year += 1900;
    2471             :         return (year % 4) == 0 && ((year % 100) != 0 || (year % 400) == 0) ? GF_TRUE : GF_FALSE;
    2472             : }
    2473             : static time_t gf_mktime_utc(struct tm *tm)
    2474             : {
    2475             :         static const u32 days_per_month[2][12] = {
    2476             :                 {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31},
    2477             :                 {31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}
    2478             :         };
    2479             :         time_t time=0;
    2480             :         int i;
    2481             : 
    2482             :         for (i=70; i<tm->tm_year; i++) {
    2483             :                 time += leap_year(i) ? 366 : 365;
    2484             :         }
    2485             : 
    2486             :         for (i=0; i<tm->tm_mon; ++i) {
    2487             :                 time += days_per_month[leap_year(tm->tm_year)][i];
    2488             :         }
    2489             :         time += tm->tm_mday - 1;
    2490             :         time *= 24;
    2491             :         time += tm->tm_hour;
    2492             :         time *= 60;
    2493             :         time += tm->tm_min;
    2494             :         time *= 60;
    2495             :         time += tm->tm_sec;
    2496             :         return time;
    2497             : }
    2498             : 
    2499             : #elif defined(WIN32)
    2500             : static time_t gf_mktime_utc(struct tm *tm)
    2501             : {
    2502             :         return  _mkgmtime(tm);
    2503             : }
    2504             : 
    2505             : #elif defined(GPAC_CONFIG_ANDROID)
    2506             : #include <time64.h>
    2507             : #if defined(__LP64__)
    2508             : static time_t gf_mktime_utc(struct tm *tm)
    2509             : {
    2510             :         return timegm64(tm);
    2511             : }
    2512             : #else
    2513             : static time_t gf_mktime_utc(struct tm *tm)
    2514             : {
    2515             :         static const time_t kTimeMax = ~(1L << (sizeof(time_t) * CHAR_BIT - 1));
    2516             :         static const time_t kTimeMin = (1L << (sizeof(time_t) * CHAR_BIT - 1));
    2517             :         time64_t result = timegm64(tm);
    2518             :         if (result < kTimeMin || result > kTimeMax)
    2519             :                 return -1;
    2520             :         return result;
    2521             : }
    2522             : #endif
    2523             : 
    2524             : #else
    2525             : 
    2526             : static time_t gf_mktime_utc(struct tm *tm)
    2527             : {
    2528          85 :         return timegm(tm);
    2529             : }
    2530             : 
    2531             : #endif
    2532             : 
    2533             : GF_EXPORT
    2534          83 : u64 gf_net_parse_date(const char *val)
    2535             : {
    2536             :         u64 current_time;
    2537             :         char szDay[50], szMonth[50];
    2538             :         u32 year, month, day, h, m, s, ms;
    2539             :         s32 oh, om;
    2540             :         Float secs;
    2541             :         Bool neg_time_zone = GF_FALSE;
    2542             : 
    2543             : #ifdef _WIN32_WCE
    2544             :         SYSTEMTIME syst;
    2545             :         FILETIME filet;
    2546             : #else
    2547             :         struct tm t;
    2548             :         memset(&t, 0, sizeof(struct tm));
    2549             : #endif
    2550             : 
    2551          83 :         szDay[0] = szMonth[0] = 0;
    2552          83 :         year = month = day = h = m = s = 0;
    2553          83 :         oh = om = 0;
    2554          83 :         secs = 0;
    2555             : 
    2556          83 :         if (sscanf(val, "%d-%d-%dT%d:%d:%gZ", &year, &month, &day, &h, &m, &secs) == 6) {
    2557             :         }
    2558           7 :         else if (sscanf(val, "%d-%d-%dT%d:%d:%g-%d:%d", &year, &month, &day, &h, &m, &secs, &oh, &om) == 8) {
    2559             :                 neg_time_zone = GF_TRUE;
    2560             :         }
    2561           7 :         else if (sscanf(val, "%d-%d-%dT%d:%d:%g+%d:%d", &year, &month, &day, &h, &m, &secs, &oh, &om) == 8) {
    2562             :         }
    2563           7 :         else if (sscanf(val, "%3s, %d %3s %d %d:%d:%d", szDay, &day, szMonth, &year, &h, &m, &s)==7) {
    2564           7 :                 secs  = (Float) s;
    2565             :         }
    2566           0 :         else if (sscanf(val, "%9s, %d-%3s-%d %02d:%02d:%02d GMT", szDay, &day, szMonth, &year, &h, &m, &s)==7) {
    2567           0 :                 secs  = (Float) s;
    2568             :         }
    2569           0 :         else if (sscanf(val, "%3s %3s %d %02d:%02d:%02d %d", szDay, szMonth, &day, &year, &h, &m, &s)==7) {
    2570           0 :                 secs  = (Float) s;
    2571             :         }
    2572             :         else {
    2573           0 :                 GF_LOG(GF_LOG_ERROR, GF_LOG_CORE, ("[Core] Cannot parse date string %s\n", val));
    2574             :                 return 0;
    2575             :         }
    2576             : 
    2577          83 :         if (month) {
    2578          76 :                 month -= 1;
    2579             :         } else {
    2580           7 :                 if (!strcmp(szMonth, "Jan")) month = 0;
    2581           7 :                 else if (!strcmp(szMonth, "Feb")) month = 1;
    2582           7 :                 else if (!strcmp(szMonth, "Mar")) month = 2;
    2583           7 :                 else if (!strcmp(szMonth, "Apr")) month = 3;
    2584           1 :                 else if (!strcmp(szMonth, "May")) month = 4;
    2585           1 :                 else if (!strcmp(szMonth, "Jun")) month = 5;
    2586           1 :                 else if (!strcmp(szMonth, "Jul")) month = 6;
    2587           1 :                 else if (!strcmp(szMonth, "Aug")) month = 7;
    2588           1 :                 else if (!strcmp(szMonth, "Sep")) month = 8;
    2589           1 :                 else if (!strcmp(szMonth, "Oct")) month = 9;
    2590           1 :                 else if (!strcmp(szMonth, "Nov")) month = 10;
    2591           0 :                 else if (!strcmp(szMonth, "Dec")) month = 11;
    2592             :         }
    2593             : 
    2594             : #ifdef _WIN32_WCE
    2595             :         memset(&syst, 0, sizeof(SYSTEMTIME));
    2596             :         syst.wYear = year;
    2597             :         syst.wMonth = month + 1;
    2598             :         syst.wDay = day;
    2599             :         syst.wHour = h;
    2600             :         syst.wMinute = m;
    2601             :         syst.wSecond = (u32) secs;
    2602             :         SystemTimeToFileTime(&syst, &filet);
    2603             :         current_time = (u64) ((*(LONGLONG *) &filet - TIMESPEC_TO_FILETIME_OFFSET) / 10000000);
    2604             : 
    2605             : #else
    2606             : 
    2607          83 :         t.tm_year = year>1000 ? year-1900 : year;
    2608          83 :         t.tm_mday = day;
    2609          83 :         t.tm_hour = h;
    2610          83 :         t.tm_min = m;
    2611          83 :         t.tm_sec = (u32) secs;
    2612          83 :         t.tm_mon = month;
    2613             : 
    2614          83 :         if (strlen(szDay) ) {
    2615           7 :                 if (!strcmp(szDay, "Mon") || !strcmp(szDay, "Monday")) t.tm_wday = 0;
    2616           7 :                 else if (!strcmp(szDay, "Tue") || !strcmp(szDay, "Tuesday")) t.tm_wday = 1;
    2617           7 :                 else if (!strcmp(szDay, "Wed") || !strcmp(szDay, "Wednesday")) t.tm_wday = 2;
    2618           7 :                 else if (!strcmp(szDay, "Thu") || !strcmp(szDay, "Thursday")) t.tm_wday = 3;
    2619           1 :                 else if (!strcmp(szDay, "Fri") || !strcmp(szDay, "Friday")) t.tm_wday = 4;
    2620           1 :                 else if (!strcmp(szDay, "Sat") || !strcmp(szDay, "Saturday")) t.tm_wday = 5;
    2621           1 :                 else if (!strcmp(szDay, "Sun") || !strcmp(szDay, "Sunday")) t.tm_wday = 6;
    2622             :         }
    2623             : 
    2624          83 :         current_time = gf_mktime_utc(&t);
    2625             : 
    2626          83 :         if ((s64) current_time == -1) {
    2627             :                 //use 1 ms
    2628             :                 return 1;
    2629             :         }
    2630          83 :         if (current_time == 0) {
    2631             :                 //use 1 ms
    2632             :                 return 1;
    2633             :         }
    2634             : 
    2635             : #endif
    2636             : 
    2637          78 :         if (om || oh) {
    2638           0 :                 s32 diff = (60*oh + om)*60;
    2639           0 :                 if (neg_time_zone) diff = -diff;
    2640           0 :                 current_time = current_time + diff;
    2641             :         }
    2642          78 :         current_time *= 1000;
    2643          78 :         ms = (u32) ( (secs - (u32) secs) * 1000);
    2644          78 :         return current_time + ms;
    2645             : }
    2646             : 
    2647             : GF_EXPORT
    2648           2 : u64 gf_net_get_utc_ts(u32 year, u32 month, u32 day, u32 hour, u32 min, u32 sec)
    2649             : {
    2650             :         u64 current_time;
    2651             : #ifdef _WIN32_WCE
    2652             :         SYSTEMTIME syst;
    2653             :         FILETIME filet;
    2654             : #else
    2655             :         struct tm t;
    2656             :         memset(&t, 0, sizeof(struct tm));
    2657             : #endif
    2658             : 
    2659             : #ifdef _WIN32_WCE
    2660             :         memset(&syst, 0, sizeof(SYSTEMTIME));
    2661             :         syst.wYear = year;
    2662             :         syst.wMonth = month + 1;
    2663             :         syst.wDay = day;
    2664             :         syst.wHour = hour;
    2665             :         syst.wMinute = min;
    2666             :         syst.wSecond = (u32) sec;
    2667             :         SystemTimeToFileTime(&syst, &filet);
    2668             :         current_time = (u64) ((*(LONGLONG *) &filet - TIMESPEC_TO_FILETIME_OFFSET) / 10000000);
    2669             : #else
    2670           2 :         t.tm_year = year>1000 ? year-1900 : year;
    2671           2 :         t.tm_mday = day;
    2672           2 :         t.tm_hour = hour;
    2673           2 :         t.tm_min = min;
    2674           2 :         t.tm_sec = (u32) sec;
    2675           2 :         t.tm_mon = month;
    2676             : 
    2677           2 :         current_time = gf_mktime_utc(&t);
    2678           2 :         if ((s64) current_time == -1) {
    2679             :                 //use 1 ms
    2680             :                 return 1;
    2681             :         }
    2682           2 :         if (current_time == 0) {
    2683             :                 //use 1 ms
    2684             :                 return 1;
    2685             :         }
    2686             : #endif
    2687             : 
    2688           2 :         current_time *= 1000;
    2689           2 :         return current_time;
    2690             : }
    2691             : 
    2692             : GF_EXPORT
    2693           0 : u64 gf_net_ntp_to_utc(u64 ntp)
    2694             : {
    2695             :         u64 current_time;
    2696             :         Double msec;
    2697           0 :         u32 sec = ntp>>32;
    2698           0 :         u32 frac = ntp & 0xFFFFFFFFUL;
    2699             : 
    2700           0 :         current_time = sec - GF_NTP_SEC_1900_TO_1970;
    2701           0 :         current_time *= 1000;
    2702           0 :         msec = frac*1000.0;
    2703           0 :         msec /= 0xFFFFFFFF;
    2704           0 :         current_time += (u64) msec;
    2705           0 :         return current_time;
    2706             : }
    2707             : 
    2708             : GF_EXPORT
    2709       76280 : u64 gf_net_get_utc()
    2710             : {
    2711             :         u64 current_time;
    2712             :         Double msec;
    2713             :         u32 sec, frac;
    2714             : 
    2715       76280 :         gf_net_get_ntp(&sec, &frac);
    2716       76280 :         current_time = sec - GF_NTP_SEC_1900_TO_1970;
    2717       76280 :         current_time *= 1000;
    2718       76280 :         msec = frac*1000.0;
    2719       76280 :         msec /= 0xFFFFFFFF;
    2720       76280 :         current_time += (u64) msec;
    2721       76280 :         return current_time;
    2722             : }
    2723             : 
    2724             : 
    2725             : 
    2726             : GF_EXPORT
    2727        1631 : GF_Err gf_bin128_parse(const char *string, bin128 value)
    2728             : {
    2729             :         u32 len;
    2730             :         u32     i=0;
    2731        1631 :         if (!strnicmp(string, "0x", 2)) string += 2;
    2732        1631 :         len = (u32) strlen(string);
    2733        1631 :         if (len >= 32) {
    2734             :                 u32 j;
    2735       26096 :                 for (j=0; j<len; j+=2) {
    2736             :                         u32 v;
    2737             :                         char szV[5];
    2738             : 
    2739       26096 :                         while (string[j] && !isalnum(string[j]))
    2740           0 :                                 j++;
    2741       26096 :                         if (!string[j])
    2742             :                                 break;
    2743       26096 :                         sprintf(szV, "%c%c", string[j], string[j+1]);
    2744       26096 :                         sscanf(szV, "%x", &v);
    2745       26096 :                         if (i > 15) {
    2746             :                                 // force error check below
    2747             :                                 i++;
    2748             :                                 break;
    2749             :                         }
    2750       26096 :                         value[i] = v;
    2751       26096 :                         i++;
    2752             : 
    2753             :                 }
    2754             :         }
    2755        1631 :         if (i != 16) {
    2756           0 :                 GF_LOG(GF_LOG_ERROR, GF_LOG_CORE, ("[CORE] 128bit blob is not 16-bytes long: %s\n", string));
    2757             :                 return GF_BAD_PARAM;
    2758             :         }
    2759             :         return GF_OK;
    2760             : }
    2761             : 
    2762             : 
    2763             : GF_EXPORT
    2764        2062 : GF_Err gf_file_load_data_filep(FILE *file, u8 **out_data, u32 *out_size)
    2765             : {
    2766             :         u64 fsize;
    2767        2062 :         *out_data = NULL;
    2768        2062 :         *out_size = 0;
    2769             : 
    2770        2062 :         fsize = gf_fsize(file);
    2771        2062 :         if (fsize>0xFFFFFFFFUL) {
    2772           0 :                 GF_LOG(GF_LOG_ERROR, GF_LOG_CORE, ("[Core] file %s is too big to load in memory ("LLU" bytes)\n", fsize));
    2773             :                 return GF_OUT_OF_MEM;
    2774             :         }
    2775             : 
    2776        2062 :         *out_size = (u32) fsize;
    2777        2062 :         if (fsize == 0) {
    2778           0 :                 GF_LOG(GF_LOG_ERROR, GF_LOG_CORE, ("[Core] file is empty\n"));
    2779             :                 return GF_OK;
    2780             :         }
    2781             : 
    2782             :         /* First, read the dump in a buffer */
    2783        2062 :         *out_data = gf_malloc((size_t)(fsize+1) * sizeof(char));
    2784        2062 :         if (! *out_data) {
    2785             :                 return GF_OUT_OF_MEM;
    2786             :         }
    2787        2062 :         fsize = gf_fread(*out_data, (size_t)fsize, file);
    2788             : 
    2789        2062 :         if ((u32) fsize != *out_size) {
    2790           0 :                 GF_LOG(GF_LOG_ERROR, GF_LOG_CORE, ("[Core] file read failed\n"));
    2791           0 :                 gf_free(*out_data);
    2792           0 :                 *out_data = NULL;
    2793           0 :                 *out_size = 0;
    2794           0 :                 return GF_IO_ERR;
    2795             :         }
    2796        2062 :         (*out_data)[fsize] = 0;
    2797        2062 :         return GF_OK;
    2798             : }
    2799             : 
    2800             : GF_EXPORT
    2801        2066 : GF_Err gf_file_load_data(const char *file_name, u8 **out_data, u32 *out_size)
    2802             : {
    2803             :         GF_Err e;
    2804        2066 :         FILE *file = gf_fopen(file_name, "rb");
    2805             : 
    2806        2066 :         if (!file) {
    2807           6 :                 GF_LOG(GF_LOG_ERROR, GF_LOG_CORE, ("[Core] Cannot open file %s\n", file_name));
    2808             :                 return GF_IO_ERR;
    2809             :         }
    2810        2060 :         e = gf_file_load_data_filep(file, out_data, out_size);
    2811        2060 :         gf_fclose(file);
    2812        2060 :         return e;
    2813             : }
    2814             : 
    2815             : #ifndef WIN32
    2816             : #include <unistd.h>
    2817             : GF_EXPORT
    2818           2 : u32 gf_sys_get_process_id()
    2819             : {
    2820           2 :         return getpid ();
    2821             : }
    2822             : #else
    2823             : #include <windows.h>
    2824             : GF_EXPORT
    2825             : u32 gf_sys_get_process_id()
    2826             : {
    2827             :         return GetCurrentProcessId();
    2828             : }
    2829             : #endif
    2830             : 

Generated by: LCOV version 1.13