1 /*
2 * GPAC - Multimedia Framework C SDK
3 *
4 * Authors: Jean Le Feuvre
5 * Copyright (c) Telecom ParisTech 2000-2012
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
29 #if defined(_WIN32_WCE)
30
31 #include <winbase.h>
32 #include <winsock.h>
33 #include <tlhelp32.h>
34 //#include <direct.h>
35
36 #if !defined(__GNUC__)
37 #pragma comment(lib, "toolhelp")
38 #endif
39
40 #elif defined(WIN32)
41
42 #include <time.h>
43 #include <sys/timeb.h>
44 #include <io.h>
45 #include <windows.h>
46 #include <tlhelp32.h>
47 #include <direct.h>
48
49 #if !defined(__GNUC__)
50 #pragma comment(lib, "winmm")
51 #endif
52
53 #else
54
55 #include <time.h>
56 #include <sys/stat.h>
57 #include <sys/time.h>
58 #include <dirent.h>
59 #include <unistd.h>
60 #include <sys/times.h>
61 #include <sys/resource.h>
62
63 #ifndef __BEOS__
64 #include <errno.h>
65 #endif
66
67 #define SLEEP_ABS_SELECT 1
68
69 static u32 sys_start_time = 0;
70 static u64 sys_start_time_hr = 0;
71 #endif
72
73
74 #ifndef _WIN32_WCE
75 #include <locale.h>
76 #endif
77
78
79 #ifndef WIN32
80
81 GF_EXPORT
gf_sys_clock()82 u32 gf_sys_clock()
83 {
84 struct timeval now;
85 gettimeofday(&now, NULL);
86 return (u32)(((now.tv_sec) * 1000 + (now.tv_usec) / 1000) - sys_start_time);
87 }
88
89 GF_EXPORT
gf_sys_clock_high_res()90 u64 gf_sys_clock_high_res()
91 {
92 struct timeval now;
93 gettimeofday(&now, NULL);
94 return (now.tv_sec) * 1000000 + (now.tv_usec) - sys_start_time_hr;
95 }
96
97 #endif
98
99
100
101 GF_EXPORT
gf_sleep(u32 ms)102 void gf_sleep(u32 ms)
103 {
104 #ifdef WIN32
105 Sleep(ms);
106 #else
107 s32 sel_err;
108 struct timeval tv;
109
110 #ifndef SLEEP_ABS_SELECT
111 u32 prev, now, elapsed;
112 #endif
113
114 #ifdef SLEEP_ABS_SELECT
115 tv.tv_sec = ms / 1000;
116 tv.tv_usec = (ms % 1000) * 1000;
117 #else
118 prev = gf_sys_clock();
119 #endif
120
121 do {
122 errno = 0;
123
124 #ifndef SLEEP_ABS_SELECT
125 now = gf_sys_clock();
126 elapsed = (now - prev);
127 if (elapsed >= ms) {
128 break;
129 }
130 prev = now;
131 ms -= elapsed;
132 tv.tv_sec = ms / 1000;
133 tv.tv_usec = (ms % 1000) * 1000;
134 #endif
135
136 sel_err = select(0, NULL, NULL, NULL, &tv);
137 } while (sel_err && (errno == EINTR));
138 #endif
139 }
140
141 #ifndef gettimeofday
142 #ifdef _WIN32_WCE
143
144 #include <time.h>
145 //#include <wce_time.h>
146
147 /*
148 * Author of first version (timeval.h): by Wu Yongwei
149 * Author of Windows CE version: Mateusz Loskot (mateusz@loskot.net)
150 *
151 * All code here is considered in the public domain though we do wish our names
152 * could be retained if anyone uses them.
153 */
154
155 /*
156 * Constants used internally by time functions.
157 */
158
159 #ifndef _TM_DEFINED
160 struct tm
161 {
162 int tm_sec; /* seconds after the minute - [0,59] */
163 int tm_min; /* minutes after the hour - [0,59] */
164 int tm_hour; /* hours since midnight - [0,23] */
165 int tm_mday; /* day of the month - [1,31] */
166 int tm_mon; /* months since January - [0,11] */
167 int tm_year; /* years since 1900 */
168 int tm_wday; /* days since Sunday - [0,6] */
169 int tm_yday; /* days since January 1 - [0,365] */
170 int tm_isdst; /* daylight savings time flag */
171 };
172 #define _TM_DEFINED
173 #endif /* _TM_DEFINED */
174
175 #ifndef _TIMEZONE_DEFINED
176 struct timezone
177 {
178 int tz_minuteswest; /* minutes W of Greenwich */
179 int tz_dsttime; /* type of dst correction */
180 };
181 #define _TIMEZONE_DEFINED
182 #endif /* _TIMEZONE_DEFINED */
183
184
185 #if defined(_MSC_VER) || defined(__BORLANDC__)
186 #define EPOCHFILETIME (116444736000000000i64)
187 #else
188 #define EPOCHFILETIME (116444736000000000LL)
189 #endif
190
gettimeofday(struct timeval * tp,struct timezone * tzp)191 int gettimeofday(struct timeval *tp, struct timezone *tzp)
192 {
193 SYSTEMTIME st;
194 FILETIME ft;
195 LARGE_INTEGER li;
196 TIME_ZONE_INFORMATION tzi;
197 __int64 t;
198 static int tzflag;
199
200 if (NULL != tp)
201 {
202 GetSystemTime(&st);
203 SystemTimeToFileTime(&st, &ft);
204 li.LowPart = ft.dwLowDateTime;
205 li.HighPart = ft.dwHighDateTime;
206 t = li.QuadPart; /* In 100-nanosecond intervals */
207 t -= EPOCHFILETIME; /* Offset to the Epoch time */
208 t /= 10; /* In microseconds */
209 tp->tv_sec = (long)(t / 1000000);
210 tp->tv_usec = (long)(t % 1000000);
211 }
212
213 if (NULL != tzp)
214 {
215 GetTimeZoneInformation(&tzi);
216
217 tzp->tz_minuteswest = tzi.Bias;
218 if (tzi.StandardDate.wMonth != 0)
219 {
220 tzp->tz_minuteswest += tzi.StandardBias * 60;
221 }
222
223 if (tzi.DaylightDate.wMonth != 0)
224 {
225 tzp->tz_dsttime = 1;
226 }
227 else
228 {
229 tzp->tz_dsttime = 0;
230 }
231 }
232
233 return 0;
234 }
235
236
237 #if _GPAC_UNUSED
238 /*
239 time between jan 1, 1601 and jan 1, 1970 in units of 100 nanoseconds
240 FILETIME in Win32 is from jan 1, 1601
241 */
242
__gettimeofday(struct timeval * tp,void * tz)243 s32 __gettimeofday(struct timeval *tp, void *tz)
244 {
245 FILETIME ft;
246 SYSTEMTIME st;
247 s32 val;
248
249 GetSystemTime(&st);
250 SystemTimeToFileTime(&st, &ft);
251
252 val = (s32)((*(LONGLONG *)&ft - TIMESPEC_TO_FILETIME_OFFSET) / 10000000);
253 tp->tv_sec = (u32)val;
254 val = (s32)((*(LONGLONG *)&ft - TIMESPEC_TO_FILETIME_OFFSET - ((LONGLONG)val * (LONGLONG)10000000)) * 100);
255 tp->tv_usec = val;
256 return 0;
257 }
258 #endif
259
260
261 #elif defined(WIN32)
262
gettimeofday(struct timeval * tp,void * tz)263 static s32 gettimeofday(struct timeval *tp, void *tz)
264 {
265 struct _timeb timebuffer;
266
267 _ftime(&timebuffer);
268 tp->tv_sec = (long)(timebuffer.time);
269 tp->tv_usec = timebuffer.millitm * 1000;
270 return 0;
271 }
272 #endif
273
274 #endif
275
276 #ifdef _WIN32_WCE
277
CE_Assert(u32 valid,char * file,u32 line)278 void CE_Assert(u32 valid, char *file, u32 line)
279 {
280 if (!valid) {
281 char szBuf[2048];
282 u16 wcBuf[2048];
283 sprintf(szBuf, "File %s : line %d", file, line);
284 CE_CharToWide(szBuf, wcBuf);
285 MessageBox(NULL, wcBuf, _T("GPAC Assertion Failure"), MB_OK);
286 exit(EXIT_FAILURE);
287 }
288 }
289
CE_WideToChar(unsigned short * w_str,char * str)290 void CE_WideToChar(unsigned short *w_str, char *str)
291 {
292 WideCharToMultiByte(CP_ACP, 0, w_str, -1, str, GF_MAX_PATH, NULL, NULL);
293 }
294
CE_CharToWide(char * str,unsigned short * w_str)295 void CE_CharToWide(char *str, unsigned short *w_str)
296 {
297 MultiByteToWideChar(CP_ACP, 0, str, -1, w_str, GF_MAX_PATH);
298 }
299
300
301 #endif
302
303 GF_EXPORT
gf_rand_init(Bool Reset)304 void gf_rand_init(Bool Reset)
305 {
306 if (Reset) {
307 srand(1);
308 }
309 else {
310 #if defined(_WIN32_WCE)
311 srand((u32)GetTickCount());
312 #else
313 srand((u32)time(NULL));
314 #endif
315 }
316 }
317
318 GF_EXPORT
gf_rand()319 u32 gf_rand()
320 {
321 return rand();
322 }
323
324 #ifndef _WIN32_WCE
325 #include <sys/stat.h>
326 #endif
327
328 GF_EXPORT
gf_utc_time_since_1970(u32 * sec,u32 * msec)329 void gf_utc_time_since_1970(u32 *sec, u32 *msec)
330 {
331 #if defined (WIN32) && !defined(_WIN32_WCE)
332 struct _timeb tb;
333 _ftime(&tb);
334 *sec = (u32)tb.time;
335 *msec = tb.millitm;
336 #else
337 struct timeval tv;
338 gettimeofday(&tv, NULL);
339 *sec = (u32)tv.tv_sec;
340 *msec = tv.tv_usec / 1000;
341 #endif
342 }
343
gf_get_user_name(char * buf,u32 buf_size)344 void gf_get_user_name(char *buf, u32 buf_size)
345 {
346 strcpy(buf, "mpeg4-user");
347
348 #if 0
349 s32 len;
350 char *t;
351 strcpy(buf, "");
352 len = 1024;
353 GetUserName(buf, &len);
354 if (!len) {
355 t = getenv("USER");
356 if (t) strcpy(buf, t);
357 }
358 #endif
359 #if 0
360 struct passwd *pw;
361 pw = getpwuid(getuid());
362 strcpy(buf, "");
363 if (pw && pw->pw_name) strcpy(name, pw->pw_name);
364 #endif
365 }
366
367
368 #ifndef WIN32
369 GF_EXPORT
my_str_upr(char * str)370 char * my_str_upr(char *str)
371 {
372 u32 i;
373 for (i = 0; i<strlen(str); i++) {
374 str[i] = toupper(str[i]);
375 }
376 return str;
377 }
378
379 GF_EXPORT
my_str_lwr(char * str)380 char * my_str_lwr(char *str)
381 {
382 u32 i;
383 for (i = 0; i<strlen(str); i++) {
384 str[i] = tolower(str[i]);
385 }
386 return str;
387 }
388 #endif
389
390 /*seems OK under mingw also*/
391 #ifdef WIN32
392 #ifdef _WIN32_WCE
393
gf_prompt_has_input()394 Bool gf_prompt_has_input()
395 {
396 return 0;
397 }
gf_prompt_get_char()398 char gf_prompt_get_char() {
399 return 0;
400 }
gf_prompt_set_echo_off(Bool echo_off)401 void gf_prompt_set_echo_off(Bool echo_off) {
402 return;
403 }
404
405 #else
406
407 #include <conio.h>
408 #include <windows.h>
409
gf_prompt_has_input()410 Bool gf_prompt_has_input()
411 {
412 return kbhit();
413 }
414
gf_prompt_get_char()415 char gf_prompt_get_char()
416 {
417 return getchar();
418 }
419
gf_prompt_set_echo_off(Bool echo_off)420 void gf_prompt_set_echo_off(Bool echo_off)
421 {
422 DWORD flags;
423 HANDLE hStdin = GetStdHandle(STD_INPUT_HANDLE);
424 BOOL ret = GetConsoleMode(hStdin, &flags);
425 if (!ret) {
426 DWORD err = GetLastError();
427 GF_LOG(GF_LOG_ERROR, GF_LOG_CONSOLE, ("[Console] GetConsoleMode() return with the following error code: %d\n", err));
428 }
429 if (echo_off) flags &= ~ENABLE_ECHO_INPUT;
430 else flags |= ENABLE_ECHO_INPUT;
431 SetConsoleMode(hStdin, flags);
432 }
433 #endif
434 #else
435 /*linux kbhit/getchar- borrowed on debian mailing lists, (author Mike Brownlow)*/
436 #include <termios.h>
437
438 static struct termios t_orig, t_new;
439 static s32 ch_peek = -1;
440
init_keyboard()441 static void init_keyboard()
442 {
443 tcgetattr(0, &t_orig);
444 t_new = t_orig;
445 t_new.c_lflag &= ~ICANON;
446 t_new.c_lflag &= ~ECHO;
447 t_new.c_lflag &= ~ISIG;
448 t_new.c_cc[VMIN] = 1;
449 t_new.c_cc[VTIME] = 0;
450 tcsetattr(0, TCSANOW, &t_new);
451 }
close_keyboard(Bool new_line)452 static void close_keyboard(Bool new_line)
453 {
454 tcsetattr(0, TCSANOW, &t_orig);
455 if (new_line) fprintf(stderr, "\n");
456 }
457
gf_prompt_set_echo_off(Bool echo_off)458 void gf_prompt_set_echo_off(Bool echo_off)
459 {
460 init_keyboard();
461 if (echo_off) t_orig.c_lflag &= ~ECHO;
462 else t_orig.c_lflag |= ECHO;
463 close_keyboard(0);
464 }
465
466 GF_EXPORT
gf_prompt_has_input()467 Bool gf_prompt_has_input()
468 {
469 u8 ch;
470 s32 nread;
471 pid_t fg = tcgetpgrp(STDIN_FILENO);
472
473 //we are not foreground nor piped (used for IDEs), can't read stdin
474 if ((fg != -1) && (fg != getpgrp())) {
475 return 0;
476 }
477 init_keyboard();
478 if (ch_peek != -1) return 1;
479 t_new.c_cc[VMIN] = 0;
480 tcsetattr(0, TCSANOW, &t_new);
481 nread = (s32)read(0, &ch, 1);
482 t_new.c_cc[VMIN] = 1;
483 tcsetattr(0, TCSANOW, &t_new);
484 if (nread == 1) {
485 ch_peek = ch;
486 return 1;
487 }
488 close_keyboard(0);
489 return 0;
490 }
491
492 GF_EXPORT
gf_prompt_get_char()493 char gf_prompt_get_char()
494 {
495 char ch;
496 if (ch_peek != -1) {
497 ch = ch_peek;
498 ch_peek = -1;
499 close_keyboard(1);
500 return ch;
501 }
502 if (0 == read(0, &ch, 1))
503 ch = 0;
504 close_keyboard(1);
505 return ch;
506 }
507
508 #endif
509
510
511 static u32 sys_init = 0;
512 static u32 last_update_time = 0;
513 static u64 last_process_k_u_time = 0;
514 GF_SystemRTInfo the_rti;
515
516
517 #if defined(_WIN32_WCE)
518 static LARGE_INTEGER frequency, init_counter;
519 static u64 last_total_k_u_time = 0;
520 static u32 mem_usage_at_startup = 0;
521
522
523 #ifndef GetCurrentPermissions
524 DWORD GetCurrentPermissions();
525 #endif
526 #ifndef SetProcPermissions
527 void SetProcPermissions(DWORD);
528 #endif
529
530 #elif defined(WIN32)
531 static LARGE_INTEGER frequency, init_counter;
532 static u64 last_proc_idle_time = 0;
533 static u64 last_proc_k_u_time = 0;
534
535 static HINSTANCE psapi_hinst = NULL;
536 typedef BOOL(WINAPI* NTGetSystemTimes)(VOID *, VOID *, VOID *);
537 NTGetSystemTimes MyGetSystemTimes = NULL;
538 typedef BOOL(WINAPI* NTGetProcessMemoryInfo)(HANDLE, VOID *, DWORD);
539 NTGetProcessMemoryInfo MyGetProcessMemoryInfo = NULL;
540 typedef int(WINAPI* NTQuerySystemInfo)(ULONG, PVOID, ULONG, PULONG);
541 NTQuerySystemInfo MyQuerySystemInfo = NULL;
542
543 #ifndef PROCESS_MEMORY_COUNTERS
544 typedef struct _PROCESS_MEMORY_COUNTERS
545 {
546 DWORD cb;
547 DWORD PageFaultCount;
548 SIZE_T PeakWorkingSetSize;
549 SIZE_T WorkingSetSize;
550 SIZE_T QuotaPeakPagedPoolUsage;
551 SIZE_T QuotaPagedPoolUsage;
552 SIZE_T QuotaPeakNonPagedPoolUsage;
553 SIZE_T QuotaNonPagedPoolUsage;
554 SIZE_T PagefileUsage;
555 SIZE_T PeakPagefileUsage;
556 } PROCESS_MEMORY_COUNTERS;
557 #endif
558
559 #ifndef SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION
560 typedef struct _SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION
561 {
562 LARGE_INTEGER IdleTime;
563 LARGE_INTEGER KernelTime;
564 LARGE_INTEGER UserTime;
565 LARGE_INTEGER Reserved1[2];
566 ULONG Reserved2;
567 } SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION;
568 #endif
569
570
571 #else
572
573 static u64 last_cpu_u_k_time = 0;
574 static u64 last_cpu_idle_time = 0;
575 static u64 mem_at_startup = 0;
576
577 #endif
578
579 #ifdef WIN32
580 static u32(*OS_GetSysClock)();
581
gf_sys_clock()582 u32 gf_sys_clock()
583 {
584 return OS_GetSysClock();
585 }
586
587
588 static u64(*OS_GetSysClockHR)();
gf_sys_clock_high_res()589 u64 gf_sys_clock_high_res()
590 {
591 return OS_GetSysClockHR();
592 }
593 #endif
594
595
596 #ifdef WIN32
597
OS_GetSysClockHIGHRES()598 static u32 OS_GetSysClockHIGHRES()
599 {
600 LARGE_INTEGER now;
601 QueryPerformanceCounter(&now);
602 now.QuadPart -= init_counter.QuadPart;
603 return (u32)((now.QuadPart * 1000) / frequency.QuadPart);
604 }
605
OS_GetSysClockHIGHRES_FULL()606 static u64 OS_GetSysClockHIGHRES_FULL()
607 {
608 LARGE_INTEGER now;
609 QueryPerformanceCounter(&now);
610 now.QuadPart -= init_counter.QuadPart;
611 return (u64)((now.QuadPart * 1000000) / frequency.QuadPart);
612 }
613
OS_GetSysClockNORMAL()614 static u32 OS_GetSysClockNORMAL()
615 {
616 #ifdef _WIN32_WCE
617 return GetTickCount();
618 #else
619 return timeGetTime();
620 #endif
621 }
622
OS_GetSysClockNORMAL_FULL()623 static u64 OS_GetSysClockNORMAL_FULL()
624 {
625 u64 res = OS_GetSysClockNORMAL();
626 return res * 1000;
627 }
628
629 #endif /* WIN32 */
630
631 #if defined(__sh__)
632 /* Avoid exception for denormalized floating point values */
633 static int
sh4_get_fpscr()634 sh4_get_fpscr()
635 {
636 int ret;
637 asm volatile ("sts fpscr,%0" : "=r" (ret));
638 return ret;
639 }
640
641 static void
sh4_put_fpscr(int nv)642 sh4_put_fpscr(int nv)
643 {
644 asm volatile ("lds %0,fpscr" : : "r" (nv));
645 }
646
647 #define SH4_FPSCR_FR 0x00200000
648 #define SH4_FPSCR_SZ 0x00100000
649 #define SH4_FPSCR_PR 0x00080000
650 #define SH4_FPSCR_DN 0x00040000
651 #define SH4_FPSCR_RN 0x00000003
652 #define SH4_FPSCR_RN_N 0
653 #define SH4_FPSCR_RN_Z 1
654
655 extern int __fpscr_values[2];
656
657 void
sh4_change_fpscr(int off,int on)658 sh4_change_fpscr(int off, int on)
659 {
660 int b = sh4_get_fpscr();
661 off = ~off;
662 off |= 0x00180000;
663 on &= ~0x00180000;
664 b &= off;
665 b |= on;
666 sh4_put_fpscr(b);
667 __fpscr_values[0] &= off;
668 __fpscr_values[0] |= on;
669 __fpscr_values[1] &= off;
670 __fpscr_values[1] |= on;
671 }
672
673 #endif
674
675 #ifdef GPAC_MEMORY_TRACKING
676 void gf_mem_enable_tracker(Bool enable_backtrace);
677 #endif
678
679 static u64 memory_at_gpac_startup = 0;
680
681 static u32 gpac_argc = 0;
682 const char **gpac_argv = NULL;
683
684 GF_EXPORT
gf_sys_set_args(s32 argc,const char ** argv)685 void gf_sys_set_args(s32 argc, const char **argv)
686 {
687 //for OSX we allow overwrite of argc/argv due to different behavior between console-mode apps and GUI
688 #if !defined(__DARWIN__) && !defined(__APPLE__)
689 if (!gpac_argc && (argc >= 0))
690 #endif
691 {
692 gpac_argc = (u32)argc;
693 gpac_argv = argv;
694 }
695 }
696 GF_EXPORT
gf_sys_get_argc()697 u32 gf_sys_get_argc()
698 {
699 return gpac_argc;
700 }
701
702 GF_EXPORT
gf_sys_get_arg(u32 arg)703 const char *gf_sys_get_arg(u32 arg)
704 {
705 if (!gpac_argc || !gpac_argv) return NULL;
706 if (arg >= gpac_argc) return NULL;
707 return gpac_argv[arg];
708 }
709
710
711 GF_EXPORT
gf_sys_init(GF_MemTrackerType mem_tracker_type)712 void gf_sys_init(GF_MemTrackerType mem_tracker_type)
713 {
714 if (!sys_init) {
715 #if defined (WIN32)
716 #if defined(_WIN32_WCE)
717 MEMORYSTATUS ms;
718 #else
719 SYSTEM_INFO sysinfo;
720 #endif
721 #endif
722
723 if (mem_tracker_type != GF_MemTrackerNone) {
724 #ifdef GPAC_MEMORY_TRACKING
725 gf_mem_enable_tracker((mem_tracker_type == GF_MemTrackerBackTrace) ? GF_TRUE : GF_FALSE);
726 #endif
727 }
728 #ifndef GPAC_DISABLE_LOG
729 /*by default log subsystem is initialized to error on all tools, and info on console to debug scripts*/
730 gf_log_set_tool_level(GF_LOG_ALL, GF_LOG_ERROR);
731 gf_log_set_tool_level(GF_LOG_CONSOLE, GF_LOG_INFO);
732 #endif
733
734
735 #if defined(__sh__)
736 /* Round all denormalized floatting point number to 0.0 */
737 sh4_change_fpscr(0, SH4_FPSCR_DN);
738 #endif
739
740 #if defined(WIN32)
741 frequency.QuadPart = 0;
742 /*clock setup*/
743 if (QueryPerformanceFrequency(&frequency)) {
744 QueryPerformanceCounter(&init_counter);
745 OS_GetSysClock = OS_GetSysClockHIGHRES;
746 OS_GetSysClockHR = OS_GetSysClockHIGHRES_FULL;
747 GF_LOG(GF_LOG_INFO, GF_LOG_CORE, ("[core] using WIN32 performance timer\n"));
748 }
749 else {
750 OS_GetSysClock = OS_GetSysClockNORMAL;
751 OS_GetSysClockHR = OS_GetSysClockNORMAL_FULL;
752 GF_LOG(GF_LOG_INFO, GF_LOG_CORE, ("[core] using WIN32 regular timer\n"));
753 }
754
755 #ifndef _WIN32_WCE
756 timeBeginPeriod(1);
757 #endif
758
759 GF_LOG(GF_LOG_INFO, GF_LOG_CORE, ("[core] checking for run-time info tools"));
760 #if defined(_WIN32_WCE)
761 last_total_k_u_time = last_process_k_u_time = 0;
762 last_update_time = 0;
763 memset(&the_rti, 0, sizeof(GF_SystemRTInfo));
764 the_rti.pid = GetCurrentProcessId();
765 the_rti.nb_cores = 1;
766 GlobalMemoryStatus(&ms);
767 mem_usage_at_startup = ms.dwAvailPhys;
768 #else
769 /*cpu usage tools are buried in win32 dlls...*/
770 MyGetSystemTimes = (NTGetSystemTimes)GetProcAddress(GetModuleHandle("kernel32.dll"), "GetSystemTimes");
771 if (!MyGetSystemTimes) {
772 MyQuerySystemInfo = (NTQuerySystemInfo)GetProcAddress(GetModuleHandle("ntdll.dll"), "NtQuerySystemInformation");
773 if (MyQuerySystemInfo) {
774 GF_LOG(GF_LOG_INFO, GF_LOG_CORE, (" - CPU: QuerySystemInformation"));
775 }
776 }
777 else {
778 GF_LOG(GF_LOG_INFO, GF_LOG_CORE, (" - CPU: GetSystemsTimes"));
779 }
780 psapi_hinst = LoadLibrary("psapi.dll");
781 MyGetProcessMemoryInfo = (NTGetProcessMemoryInfo)GetProcAddress(psapi_hinst, "GetProcessMemoryInfo");
782 if (MyGetProcessMemoryInfo) {
783 GF_LOG(GF_LOG_INFO, GF_LOG_CORE, (" - memory: GetProcessMemoryInfo"));
784 }
785 last_process_k_u_time = last_proc_idle_time = last_proc_k_u_time = 0;
786 last_update_time = 0;
787 memset(&the_rti, 0, sizeof(GF_SystemRTInfo));
788 the_rti.pid = GetCurrentProcessId();
789
790 GetSystemInfo(&sysinfo);
791 the_rti.nb_cores = sysinfo.dwNumberOfProcessors;
792 #endif
793 GF_LOG(GF_LOG_INFO, GF_LOG_CORE, ("\n"));
794
795 #else
796 /*linux threads and OSX...*/
797 last_process_k_u_time = 0;
798 last_cpu_u_k_time = last_cpu_idle_time = 0;
799 last_update_time = 0;
800 memset(&the_rti, 0, sizeof(GF_SystemRTInfo));
801 the_rti.pid = getpid();
802 the_rti.nb_cores = (u32)sysconf(_SC_NPROCESSORS_ONLN);
803 sys_start_time = gf_sys_clock();
804 sys_start_time_hr = gf_sys_clock_high_res();
805 #endif
806 GF_LOG(GF_LOG_INFO, GF_LOG_CORE, ("[core] process id %d\n", the_rti.pid));
807
808 #ifndef _WIN32_WCE
809 setlocale(LC_NUMERIC, "C");
810 #endif
811 }
812 sys_init += 1;
813
814
815 /*init RTI stats*/
816 if (!memory_at_gpac_startup) {
817 GF_SystemRTInfo rti;
818 if (gf_sys_get_rti(500, &rti, GF_RTI_SYSTEM_MEMORY_ONLY)) {
819 memory_at_gpac_startup = rti.physical_memory_avail;
820 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));
821 }
822 else {
823 memory_at_gpac_startup = 0;
824 }
825 }
826 }
827
828 GF_EXPORT
gf_sys_close()829 void gf_sys_close()
830 {
831 if (sys_init > 0) {
832 sys_init--;
833 if (sys_init) return;
834 /*prevent any call*/
835 last_update_time = 0xFFFFFFFF;
836
837 #if defined(WIN32) && !defined(_WIN32_WCE)
838 timeEndPeriod(1);
839
840 MyGetSystemTimes = NULL;
841 MyGetProcessMemoryInfo = NULL;
842 MyQuerySystemInfo = NULL;
843 if (psapi_hinst) FreeLibrary(psapi_hinst);
844 psapi_hinst = NULL;
845 #endif
846 }
847 }
848
849 #ifdef GPAC_MEMORY_TRACKING
850 extern size_t gpac_allocated_memory;
851 extern size_t gpac_nb_alloc_blocs;
852 #endif
853
854 /*CPU and Memory Usage*/
855 #ifdef WIN32
856
gf_sys_get_rti_os(u32 refresh_time_ms,GF_SystemRTInfo * rti,u32 flags)857 Bool gf_sys_get_rti_os(u32 refresh_time_ms, GF_SystemRTInfo *rti, u32 flags)
858 {
859 #if defined(_WIN32_WCE)
860 THREADENTRY32 tentry;
861 u64 total_cpu_time, process_cpu_time;
862 DWORD orig_perm;
863 #endif
864 MEMORYSTATUS ms;
865 u64 creation, exit, kernel, user, process_k_u_time, proc_idle_time, proc_k_u_time;
866 u32 entry_time;
867 HANDLE hSnapShot;
868
869 assert(sys_init);
870
871 if (!rti) return GF_FALSE;
872
873 proc_idle_time = proc_k_u_time = process_k_u_time = 0;
874
875 entry_time = gf_sys_clock();
876 if (last_update_time && (entry_time - last_update_time < refresh_time_ms)) {
877 memcpy(rti, &the_rti, sizeof(GF_SystemRTInfo));
878 return GF_FALSE;
879 }
880
881 if (flags & GF_RTI_SYSTEM_MEMORY_ONLY) {
882 memset(rti, 0, sizeof(GF_SystemRTInfo));
883 rti->sampling_instant = last_update_time;
884 GlobalMemoryStatus(&ms);
885 rti->physical_memory = ms.dwTotalPhys;
886 rti->physical_memory_avail = ms.dwAvailPhys;
887 #ifdef GPAC_MEMORY_TRACKING
888 rti->gpac_memory = (u64)gpac_allocated_memory;
889 #endif
890 return GF_TRUE;
891 }
892
893 #if defined (_WIN32_WCE)
894
895 total_cpu_time = process_cpu_time = 0;
896
897 /*get a snapshot of all running threads*/
898 orig_perm = GetCurrentPermissions();
899 SetProcPermissions(0xFFFFFFFF);
900 hSnapShot = CreateToolhelp32Snapshot(TH32CS_SNAPTHREAD, 0);
901 if (hSnapShot) {
902 tentry.dwSize = sizeof(THREADENTRY32);
903 the_rti.thread_count = 0;
904 /*note we always act as if GF_RTI_ALL_PROCESSES_TIMES flag is set, since there is no other way
905 to enumerate threads from a process, and GetProcessTimes doesn't exist on CE*/
906 if (Thread32First(hSnapShot, &tentry)) {
907 do {
908 /*get thread times*/
909 if (GetThreadTimes((HANDLE)tentry.th32ThreadID, (FILETIME *)&creation, (FILETIME *)&exit, (FILETIME *)&kernel, (FILETIME *)&user)) {
910 total_cpu_time += user + kernel;
911 if (tentry.th32OwnerProcessID == the_rti.pid) {
912 process_cpu_time += user + kernel;
913 the_rti.thread_count++;
914 }
915 }
916 } while (Thread32Next(hSnapShot, &tentry));
917 }
918 CloseToolhelp32Snapshot(hSnapShot);
919 }
920
921 if (flags & GF_RTI_PROCESS_MEMORY) {
922 HEAPLIST32 hlentry;
923 HEAPENTRY32 hentry;
924 the_rti.process_memory = 0;
925 hlentry.dwSize = sizeof(HEAPLIST32);
926 hSnapShot = CreateToolhelp32Snapshot(TH32CS_SNAPHEAPLIST, the_rti.pid);
927 if (hSnapShot && Heap32ListFirst(hSnapShot, &hlentry)) {
928 do {
929 hentry.dwSize = sizeof(hentry);
930 if (Heap32First(hSnapShot, &hentry, hlentry.th32ProcessID, hlentry.th32HeapID)) {
931 do {
932 the_rti.process_memory += hentry.dwBlockSize;
933 } while (Heap32Next(hSnapShot, &hentry));
934 }
935 } while (Heap32ListNext(hSnapShot, &hlentry));
936 }
937 CloseToolhelp32Snapshot(hSnapShot);
938 }
939 SetProcPermissions(orig_perm);
940 total_cpu_time /= 10;
941 process_cpu_time /= 10;
942
943 #else
944 /*XP-SP1 and Win2003 servers only have GetSystemTimes support. This will give a better estimation
945 of CPU usage since we can take into account the idle time*/
946 if (MyGetSystemTimes) {
947 u64 u_time;
948 MyGetSystemTimes(&proc_idle_time, &proc_k_u_time, &u_time);
949 proc_k_u_time += u_time;
950 proc_idle_time /= 10;
951 proc_k_u_time /= 10;
952 }
953 /*same rq for NtQuerySystemInformation*/
954 else if (MyQuerySystemInfo) {
955 DWORD ret;
956 SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION info;
957 MyQuerySystemInfo(0x8 /*SystemProcessorPerformanceInformation*/, &info, sizeof(info), &ret);
958 if (ret && (ret <= sizeof(info))) {
959 proc_idle_time = info.IdleTime.QuadPart / 10;
960 proc_k_u_time = (info.KernelTime.QuadPart + info.UserTime.QuadPart) / 10;
961 }
962 }
963 /*no special API available, ONLY FETCH TIMES if requested (may eat up some time)*/
964 else if (flags & GF_RTI_ALL_PROCESSES_TIMES) {
965 PROCESSENTRY32 pentry;
966 /*get a snapshot of all running threads*/
967 hSnapShot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
968 if (!hSnapShot) return GF_FALSE;
969 pentry.dwSize = sizeof(PROCESSENTRY32);
970 if (Process32First(hSnapShot, &pentry)) {
971 do {
972 HANDLE procH = NULL;
973 if (pentry.th32ProcessID) procH = OpenProcess(PROCESS_QUERY_INFORMATION, FALSE, pentry.th32ProcessID);
974 if (procH && GetProcessTimes(procH, (FILETIME *)&creation, (FILETIME *)&exit, (FILETIME *)&kernel, (FILETIME *)&user)) {
975 user += kernel;
976 proc_k_u_time += user;
977 if (pentry.th32ProcessID == the_rti.pid) {
978 process_k_u_time = user;
979 //nb_threads = pentry.cntThreads;
980 }
981 }
982 if (procH) CloseHandle(procH);
983 } while (Process32Next(hSnapShot, &pentry));
984 }
985 CloseHandle(hSnapShot);
986 proc_k_u_time /= 10;
987 }
988
989
990 if (!process_k_u_time) {
991 HANDLE procH = OpenProcess(PROCESS_QUERY_INFORMATION, FALSE, the_rti.pid);
992 if (procH && GetProcessTimes(procH, (FILETIME *)&creation, (FILETIME *)&exit, (FILETIME *)&kernel, (FILETIME *)&user)) {
993 process_k_u_time = user + kernel;
994 }
995 if (procH) CloseHandle(procH);
996 if (!process_k_u_time) return GF_FALSE;
997 }
998 process_k_u_time /= 10;
999
1000 /*this won't cost a lot*/
1001 if (MyGetProcessMemoryInfo) {
1002 PROCESS_MEMORY_COUNTERS pmc;
1003 HANDLE procH = OpenProcess(PROCESS_QUERY_INFORMATION, FALSE, the_rti.pid);
1004 MyGetProcessMemoryInfo(procH, &pmc, sizeof(pmc));
1005 the_rti.process_memory = pmc.WorkingSetSize;
1006 if (procH) CloseHandle(procH);
1007 }
1008 /*THIS IS VERY HEAVY (eats up mem and time) - only perform if requested*/
1009 else if (flags & GF_RTI_PROCESS_MEMORY) {
1010 HEAPLIST32 hlentry;
1011 HEAPENTRY32 hentry;
1012 the_rti.process_memory = 0;
1013 hlentry.dwSize = sizeof(HEAPLIST32);
1014 hSnapShot = CreateToolhelp32Snapshot(TH32CS_SNAPHEAPLIST, the_rti.pid);
1015 if (hSnapShot && Heap32ListFirst(hSnapShot, &hlentry)) {
1016 do {
1017 hentry.dwSize = sizeof(hentry);
1018 if (Heap32First(&hentry, hlentry.th32ProcessID, hlentry.th32HeapID)) {
1019 do {
1020 the_rti.process_memory += hentry.dwBlockSize;
1021 } while (Heap32Next(&hentry));
1022 }
1023 } while (Heap32ListNext(hSnapShot, &hlentry));
1024 }
1025 CloseHandle(hSnapShot);
1026 }
1027 #endif
1028
1029 the_rti.sampling_instant = last_update_time;
1030
1031 if (last_update_time) {
1032 the_rti.sampling_period_duration = entry_time - last_update_time;
1033 the_rti.process_cpu_time_diff = (u32)((process_k_u_time - last_process_k_u_time) / 1000);
1034
1035 #if defined(_WIN32_WCE)
1036 the_rti.total_cpu_time_diff = (u32)((total_cpu_time - last_total_k_u_time) / 1000);
1037 /*we're not that accurate....*/
1038 if (the_rti.total_cpu_time_diff > the_rti.sampling_period_duration)
1039 the_rti.sampling_period_duration = the_rti.total_cpu_time_diff;
1040
1041 /*rough values*/
1042 the_rti.cpu_idle_time = the_rti.sampling_period_duration - the_rti.total_cpu_time_diff;
1043 if (!the_rti.sampling_period_duration) the_rti.sampling_period_duration = 1;
1044 the_rti.total_cpu_usage = (u32)(100 * the_rti.total_cpu_time_diff / the_rti.sampling_period_duration);
1045 if (the_rti.total_cpu_time_diff + the_rti.cpu_idle_time == 0) the_rti.total_cpu_time_diff++;
1046 the_rti.process_cpu_usage = (u32)(100 * the_rti.process_cpu_time_diff / (the_rti.total_cpu_time_diff + the_rti.cpu_idle_time));
1047
1048 #else
1049 /*oops, we have no choice but to assume 100% cpu usage during this period*/
1050 if (!proc_k_u_time) {
1051 the_rti.total_cpu_time_diff = the_rti.sampling_period_duration;
1052 proc_k_u_time = last_proc_k_u_time + the_rti.sampling_period_duration;
1053 the_rti.cpu_idle_time = 0;
1054 the_rti.total_cpu_usage = 100;
1055 if (the_rti.sampling_period_duration)
1056 the_rti.process_cpu_usage = (u32)(100 * the_rti.process_cpu_time_diff / the_rti.sampling_period_duration);
1057 }
1058 else {
1059 u64 samp_sys_time, idle;
1060 the_rti.total_cpu_time_diff = (u32)((proc_k_u_time - last_proc_k_u_time) / 1000);
1061
1062 /*we're not that accurate....*/
1063 if (the_rti.total_cpu_time_diff > the_rti.sampling_period_duration) {
1064 the_rti.sampling_period_duration = the_rti.total_cpu_time_diff;
1065 }
1066
1067 if (!proc_idle_time)
1068 proc_idle_time = last_proc_idle_time + (the_rti.sampling_period_duration - the_rti.total_cpu_time_diff);
1069
1070 samp_sys_time = proc_k_u_time - last_proc_k_u_time;
1071 idle = proc_idle_time - last_proc_idle_time;
1072 the_rti.cpu_idle_time = (u32)(idle / 1000);
1073 if (samp_sys_time) {
1074 the_rti.total_cpu_usage = (u32)((samp_sys_time - idle) / (samp_sys_time / 100));
1075 the_rti.process_cpu_usage = (u32)(100 * the_rti.process_cpu_time_diff / (samp_sys_time / 1000));
1076 }
1077 }
1078 #endif
1079 }
1080 last_update_time = entry_time;
1081 last_process_k_u_time = process_k_u_time;
1082
1083 GlobalMemoryStatus(&ms);
1084 the_rti.physical_memory = ms.dwTotalPhys;
1085 #ifdef GPAC_MEMORY_TRACKING
1086 the_rti.gpac_memory = (u64)gpac_allocated_memory;
1087 #endif
1088 the_rti.physical_memory_avail = ms.dwAvailPhys;
1089
1090 #if defined(_WIN32_WCE)
1091 last_total_k_u_time = total_cpu_time;
1092 if (!the_rti.process_memory) the_rti.process_memory = mem_usage_at_startup - ms.dwAvailPhys;
1093 #else
1094 last_proc_idle_time = proc_idle_time;
1095 last_proc_k_u_time = proc_k_u_time;
1096 #endif
1097
1098 if (!the_rti.gpac_memory) the_rti.gpac_memory = the_rti.process_memory;
1099
1100 memcpy(rti, &the_rti, sizeof(GF_SystemRTInfo));
1101 return GF_TRUE;
1102 }
1103
1104
1105 #elif defined(GPAC_CONFIG_DARWIN) && !defined(GPAC_IPHONE)
1106
1107 #include <sys/types.h>
1108 #include <sys/sysctl.h>
1109 #include <sys/vmmeter.h>
1110 #include <mach/mach_init.h>
1111 #include <mach/mach_host.h>
1112 #include <mach/mach_port.h>
1113 #include <mach/mach_traps.h>
1114 #include <mach/task_info.h>
1115 #include <mach/thread_info.h>
1116 #include <mach/thread_act.h>
1117 #include <mach/vm_region.h>
1118 #include <mach/vm_map.h>
1119 #include <mach/task.h>
1120 #if __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ >= 1060
1121 #include <mach/shared_region.h>
1122 #else
1123 #include <mach/shared_memory_server.h>
1124 #endif
1125 #include <mach/mach_error.h>
1126
1127 static u64 total_physical_memory = 0;
1128
gf_sys_get_rti_os(u32 refresh_time_ms,GF_SystemRTInfo * rti,u32 flags)1129 Bool gf_sys_get_rti_os(u32 refresh_time_ms, GF_SystemRTInfo *rti, u32 flags)
1130 {
1131 size_t length;
1132 u32 entry_time, i, percent;
1133 int mib[6];
1134 u64 result;
1135 int pagesize;
1136 u64 process_u_k_time;
1137 double utime, stime;
1138 vm_statistics_data_t vmstat;
1139 task_t task;
1140 kern_return_t error;
1141 thread_array_t thread_table;
1142 unsigned table_size;
1143 thread_basic_info_t thi;
1144 thread_basic_info_data_t thi_data;
1145 struct task_basic_info ti;
1146 mach_msg_type_number_t count = HOST_VM_INFO_COUNT, size = sizeof(ti);
1147
1148 entry_time = gf_sys_clock();
1149 if (last_update_time && (entry_time - last_update_time < refresh_time_ms)) {
1150 memcpy(rti, &the_rti, sizeof(GF_SystemRTInfo));
1151 return 0;
1152 }
1153
1154 mib[0] = CTL_HW;
1155 mib[1] = HW_PAGESIZE;
1156 length = sizeof(pagesize);
1157 if (sysctl(mib, 2, &pagesize, &length, NULL, 0) < 0) {
1158 return 0;
1159 }
1160
1161 if (host_statistics(mach_host_self(), HOST_VM_INFO, (host_info_t)&vmstat, &count) != KERN_SUCCESS) {
1162 return 0;
1163 }
1164
1165 the_rti.physical_memory = (vmstat.wire_count + vmstat.active_count + vmstat.inactive_count + vmstat.free_count)* pagesize;
1166 the_rti.physical_memory_avail = vmstat.free_count * pagesize;
1167
1168 if (!total_physical_memory) {
1169 mib[0] = CTL_HW;
1170 mib[1] = HW_MEMSIZE;
1171 length = sizeof(u64);
1172 if (sysctl(mib, 2, &result, &length, NULL, 0) >= 0) {
1173 total_physical_memory = result;
1174 }
1175 }
1176 the_rti.physical_memory = total_physical_memory;
1177
1178 error = task_for_pid(mach_task_self(), the_rti.pid, &task);
1179 if (error) {
1180 GF_LOG(GF_LOG_ERROR, GF_LOG_CORE, ("[RTI] Cannot get process task for PID %d: error %d\n", the_rti.pid, error));
1181 return 0;
1182 }
1183
1184 error = task_info(mach_task_self(), TASK_BASIC_INFO, (task_info_t)&ti, &size);
1185 if (error) {
1186 GF_LOG(GF_LOG_ERROR, GF_LOG_CORE, ("[RTI] Cannot get process task info (PID %d): error %d\n", the_rti.pid, error));
1187 return 0;
1188 }
1189
1190 percent = 0;
1191 utime = ti.user_time.seconds + ti.user_time.microseconds * 1e-6;
1192 stime = ti.system_time.seconds + ti.system_time.microseconds * 1e-6;
1193 error = task_threads(task, &thread_table, &table_size);
1194 if (error != KERN_SUCCESS) {
1195 GF_LOG(GF_LOG_ERROR, GF_LOG_CORE, ("[RTI] Cannot get threads task for PID %d: error %d\n", the_rti.pid, error));
1196 return 0;
1197 }
1198 thi = &thi_data;
1199 for (i = 0; i != table_size; ++i) {
1200 count = THREAD_BASIC_INFO_COUNT;
1201 error = thread_info(thread_table[i], THREAD_BASIC_INFO, (thread_info_t)thi, &count);
1202 if (error != KERN_SUCCESS) {
1203 mach_error("[RTI] Unexpected thread_info() call return", error);
1204 GF_LOG(GF_LOG_WARNING, GF_LOG_CORE, ("[RTI] Unexpected thread info for PID %d\n", the_rti.pid));
1205 break;
1206 }
1207 if ((thi->flags & TH_FLAGS_IDLE) == 0) {
1208 utime += thi->user_time.seconds + thi->user_time.microseconds * 1e-6;
1209 stime += thi->system_time.seconds + thi->system_time.microseconds * 1e-6;
1210 percent += (u32)(100 * (double)thi->cpu_usage / TH_USAGE_SCALE);
1211 }
1212 }
1213 vm_deallocate(mach_task_self(), (vm_offset_t)thread_table, table_size * sizeof(thread_array_t));
1214 mach_port_deallocate(mach_task_self(), task);
1215
1216 process_u_k_time = utime + stime;
1217
1218 the_rti.sampling_instant = last_update_time;
1219
1220 if (last_update_time) {
1221 the_rti.sampling_period_duration = (entry_time - last_update_time);
1222 the_rti.process_cpu_time_diff = (process_u_k_time - last_process_k_u_time) * 10;
1223
1224 the_rti.total_cpu_time_diff = the_rti.sampling_period_duration;
1225 /*TODO*/
1226 the_rti.cpu_idle_time = 0;
1227 the_rti.total_cpu_usage = 0;
1228 if (!the_rti.process_cpu_time_diff) the_rti.process_cpu_time_diff = the_rti.total_cpu_time_diff;
1229
1230 the_rti.process_cpu_usage = percent;
1231 }
1232 else {
1233 mem_at_startup = the_rti.physical_memory_avail;
1234 }
1235 the_rti.process_memory = mem_at_startup - the_rti.physical_memory_avail;
1236
1237 #ifdef GPAC_MEMORY_TRACKING
1238 the_rti.gpac_memory = gpac_allocated_memory;
1239 #endif
1240
1241 last_process_k_u_time = process_u_k_time;
1242 last_cpu_idle_time = 0;
1243 last_update_time = entry_time;
1244 memcpy(rti, &the_rti, sizeof(GF_SystemRTInfo));
1245 return 1;
1246 }
1247
1248 //linux
1249 #else
1250
gf_sys_get_rti_os(u32 refresh_time_ms,GF_SystemRTInfo * rti,u32 flags)1251 Bool gf_sys_get_rti_os(u32 refresh_time_ms, GF_SystemRTInfo *rti, u32 flags)
1252 {
1253 u32 entry_time;
1254 u64 process_u_k_time;
1255 u32 u_k_time, idle_time;
1256 #if 0
1257 char szProc[100];
1258 #endif
1259 char line[2048];
1260 FILE *f;
1261
1262 assert(sys_init);
1263
1264 entry_time = gf_sys_clock();
1265 if (last_update_time && (entry_time - last_update_time < refresh_time_ms)) {
1266 memcpy(rti, &the_rti, sizeof(GF_SystemRTInfo));
1267 return 0;
1268 }
1269
1270 u_k_time = idle_time = 0;
1271 f = gf_fopen("/proc/stat", "r");
1272 if (f) {
1273 u32 k_time, nice_time, u_time;
1274 if (fgets(line, 128, f) != NULL) {
1275 if (sscanf(line, "cpu %u %u %u %u\n", &u_time, &k_time, &nice_time, &idle_time) == 4) {
1276 u_k_time = u_time + k_time + nice_time;
1277 }
1278 }
1279 gf_fclose(f);
1280 }
1281
1282 process_u_k_time = 0;
1283 the_rti.process_memory = 0;
1284
1285 /*FIXME? under LinuxThreads this will only fetch stats for the calling thread, we would have to enumerate /proc to get
1286 the complete CPU usage of all therads of the process...*/
1287 #if 0
1288 sprintf(szProc, "/proc/%d/stat", the_rti.pid);
1289 f = gf_fopen(szProc, "r");
1290 if (f) {
1291 fflush(f);
1292 if (fgets(line, 2048, f) != NULL) {
1293 char state;
1294 char *start;
1295 long cutime, cstime, priority, nice, itrealvalue, rss;
1296 int exit_signal, processor;
1297 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;
1298 int ppid, pgrp, session, tty_nr, tty_pgrp, res;
1299 start = strchr(line, ')');
1300 if (start) start += 2;
1301 else {
1302 start = strchr(line, ' ');
1303 start++;
1304 }
1305 res = sscanf(start, "%c %d %d %d %d %d %lu %lu %lu %lu \
1306 %lu %lu %lu %ld %ld %ld %ld %ld %ld %lu \
1307 %lu %ld %lu %lu %lu %lu %lu %lu %lu %lu \
1308 %lu %lu %lu %lu %lu %d %d",
1309 &state, &ppid, &pgrp, &session, &tty_nr, &tty_pgrp, &flags, &minflt, &cminflt, &majflt,
1310 &cmajflt, &utime, &stime, &cutime, &cstime, &priority, &nice, &itrealvalue, &rem, &starttime,
1311 &vsize, &rss, &rlim, &startcode, &endcode, &startstack, &kstkesp, &kstkeip, &signal, &blocked,
1312 &sigignore, &sigcatch, &wchan, &nswap, &cnswap, &exit_signal, &processor);
1313
1314 if (res) process_u_k_time = (u64)(cutime + cstime);
1315 else {
1316 GF_LOG(GF_LOG_ERROR, GF_LOG_CORE, ("[RTI] PROC %s parse error\n", szProc));
1317 }
1318 }
1319 else {
1320 GF_LOG(GF_LOG_ERROR, GF_LOG_CORE, ("[RTI] error reading pid/stat\n\n", szProc));
1321 }
1322 gf_fclose(f);
1323 }
1324 else {
1325 GF_LOG(GF_LOG_ERROR, GF_LOG_CORE, ("[RTI] cannot open %s\n", szProc));
1326 }
1327 sprintf(szProc, "/proc/%d/status", the_rti.pid);
1328 f = gf_fopen(szProc, "r");
1329 if (f) {
1330 while (fgets(line, 1024, f) != NULL) {
1331 if (!strnicmp(line, "VmSize:", 7)) {
1332 sscanf(line, "VmSize: %"LLD" kB", &the_rti.process_memory);
1333 the_rti.process_memory *= 1024;
1334 }
1335 }
1336 gf_fclose(f);
1337 }
1338 else {
1339 GF_LOG(GF_LOG_ERROR, GF_LOG_CORE, ("[RTI] cannot open %s\n", szProc));
1340 }
1341 #endif
1342
1343
1344 #ifndef GPAC_IPHONE
1345 the_rti.physical_memory = the_rti.physical_memory_avail = 0;
1346 f = gf_fopen("/proc/meminfo", "r");
1347 if (f) {
1348 while (fgets(line, 1024, f) != NULL) {
1349 if (!strnicmp(line, "MemTotal:", 9)) {
1350 sscanf(line, "MemTotal: "LLU" kB", &the_rti.physical_memory);
1351 the_rti.physical_memory *= 1024;
1352 }
1353 else if (!strnicmp(line, "MemFree:", 8)) {
1354 sscanf(line, "MemFree: "LLU" kB", &the_rti.physical_memory_avail);
1355 the_rti.physical_memory_avail *= 1024;
1356 break;
1357 }
1358 }
1359 gf_fclose(f);
1360 }
1361 else {
1362 GF_LOG(GF_LOG_ERROR, GF_LOG_CORE, ("[RTI] cannot open /proc/meminfo\n"));
1363 }
1364 #endif
1365
1366
1367 the_rti.sampling_instant = last_update_time;
1368
1369 if (last_update_time) {
1370 the_rti.sampling_period_duration = (entry_time - last_update_time);
1371 the_rti.process_cpu_time_diff = (u32)(process_u_k_time - last_process_k_u_time) * 10;
1372
1373 /*oops, we have no choice but to assume 100% cpu usage during this period*/
1374 if (!u_k_time) {
1375 the_rti.total_cpu_time_diff = the_rti.sampling_period_duration;
1376 u_k_time = (u32)(last_cpu_u_k_time + the_rti.sampling_period_duration);
1377 the_rti.cpu_idle_time = 0;
1378 the_rti.total_cpu_usage = 100;
1379 if (!the_rti.process_cpu_time_diff) the_rti.process_cpu_time_diff = the_rti.total_cpu_time_diff;
1380 the_rti.process_cpu_usage = (u32)(100 * the_rti.process_cpu_time_diff / the_rti.sampling_period_duration);
1381 }
1382 else {
1383 u64 samp_sys_time;
1384 /*move to ms (/proc/stat gives times in 100 ms unit*/
1385 the_rti.total_cpu_time_diff = (u32)(u_k_time - last_cpu_u_k_time) * 10;
1386
1387 /*we're not that accurate....*/
1388 if (the_rti.total_cpu_time_diff > the_rti.sampling_period_duration)
1389 the_rti.sampling_period_duration = the_rti.total_cpu_time_diff;
1390
1391
1392 if (!idle_time) idle_time = (the_rti.sampling_period_duration - the_rti.total_cpu_time_diff) / 10;
1393 samp_sys_time = u_k_time - last_cpu_u_k_time;
1394 the_rti.cpu_idle_time = (u32)(idle_time - last_cpu_idle_time);
1395 the_rti.total_cpu_usage = (u32)(100 * samp_sys_time / (the_rti.cpu_idle_time + samp_sys_time));
1396 /*move to ms (/proc/stat gives times in 100 ms unit*/
1397 the_rti.cpu_idle_time *= 10;
1398 if (!the_rti.process_cpu_time_diff) the_rti.process_cpu_time_diff = the_rti.total_cpu_time_diff;
1399 the_rti.process_cpu_usage = (u32)(100 * the_rti.process_cpu_time_diff / (the_rti.cpu_idle_time + 10 * samp_sys_time));
1400 }
1401 }
1402 else {
1403 mem_at_startup = the_rti.physical_memory_avail;
1404 }
1405 the_rti.process_memory = mem_at_startup - the_rti.physical_memory_avail;
1406 #ifdef GPAC_MEMORY_TRACKING
1407 the_rti.gpac_memory = gpac_allocated_memory;
1408 #endif
1409
1410 last_process_k_u_time = process_u_k_time;
1411 last_cpu_idle_time = idle_time;
1412 last_cpu_u_k_time = u_k_time;
1413 last_update_time = entry_time;
1414 memcpy(rti, &the_rti, sizeof(GF_SystemRTInfo));
1415 return 1;
1416 }
1417
1418 #endif
1419
1420 GF_EXPORT
gf_sys_get_rti(u32 refresh_time_ms,GF_SystemRTInfo * rti,u32 flags)1421 Bool gf_sys_get_rti(u32 refresh_time_ms, GF_SystemRTInfo *rti, u32 flags)
1422 {
1423 Bool res = gf_sys_get_rti_os(refresh_time_ms, rti, flags);
1424 if (res) {
1425 if (!rti->process_memory) rti->process_memory = memory_at_gpac_startup - rti->physical_memory_avail;
1426 if (!rti->gpac_memory) rti->gpac_memory = memory_at_gpac_startup - rti->physical_memory_avail;
1427 }
1428 return res;
1429 }
1430
1431
gf_get_default_cache_directory()1432 char * gf_get_default_cache_directory() {
1433 #ifdef _WIN32_WCE
1434 return gf_strdup("\\windows\\temp");
1435 #elif defined(WIN32)
1436 char szPath[MAX_PATH];
1437 /*ivica patch*/
1438 GetTempPath(MAX_PATH, szPath);
1439 return gf_strdup(szPath);
1440 #else
1441 return gf_strdup("/tmp");
1442 #endif
1443 }
1444
1445
1446 GF_EXPORT
gf_sys_get_battery_state(Bool * onBattery,u32 * onCharge,u32 * level,u32 * batteryLifeTime,u32 * batteryFullLifeTime)1447 Bool gf_sys_get_battery_state(Bool *onBattery, u32 *onCharge, u32*level, u32 *batteryLifeTime, u32 *batteryFullLifeTime)
1448 {
1449 #if defined(_WIN32_WCE)
1450 SYSTEM_POWER_STATUS_EX sps;
1451 GetSystemPowerStatusEx(&sps, 0);
1452 if (onBattery) *onBattery = sps.ACLineStatus ? 0 : 1;
1453 if (onCharge) *onCharge = (sps.BatteryFlag & BATTERY_FLAG_CHARGING) ? 1 : 0;
1454 if (level) *level = sps.BatteryLifePercent;
1455 if (batteryLifeTime) *batteryLifeTime = sps.BatteryLifeTime;
1456 if (batteryFullLifeTime) *batteryFullLifeTime = sps.BatteryFullLifeTime;
1457 #elif defined(WIN32)
1458 SYSTEM_POWER_STATUS sps;
1459 GetSystemPowerStatus(&sps);
1460 if (onBattery) *onBattery = sps.ACLineStatus ? GF_FALSE : GF_TRUE;
1461 if (onCharge) *onCharge = (sps.BatteryFlag & BATTERY_FLAG_CHARGING) ? 1 : 0;
1462 if (level) *level = sps.BatteryLifePercent;
1463 if (batteryLifeTime) *batteryLifeTime = sps.BatteryLifeTime;
1464 if (batteryFullLifeTime) *batteryFullLifeTime = sps.BatteryFullLifeTime;
1465 #endif
1466 return GF_TRUE;
1467 }
1468
1469
1470 struct GF_GlobalLock {
1471 const char * resourceName;
1472 };
1473
1474
1475 #ifndef WIN32
1476 #define CPF_CLOEXEC 1
1477
1478 #include <sys/stat.h>
1479 #include <fcntl.h>
1480 #include <unistd.h>
1481
1482 struct _GF_GlobalLock_opaque {
1483 char * resourceName;
1484 char * pidFile;
1485 int fd;
1486 };
1487
gf_create_PID_file(const char * resourceName)1488 GF_GlobalLock * gf_create_PID_file(const char * resourceName)
1489 {
1490 const char * prefix = "/gpac_lock_";
1491 const char * dir = gf_get_default_cache_directory();
1492 char * pidfile;
1493 int flags;
1494 int status;
1495 pidfile = gf_malloc(strlen(dir) + strlen(prefix) + strlen(resourceName) + 1);
1496 strcpy(pidfile, dir);
1497 strcat(pidfile, prefix);
1498 /* Use only valid names for file */
1499 {
1500 const char *res;
1501 char * pid = &(pidfile[strlen(pidfile)]);
1502 for (res = resourceName; *res; res++) {
1503 if (*res >= 'A' && *res <= 'z')
1504 *pid = *res;
1505 else
1506 *pid = '_';
1507 pid++;
1508 }
1509 *pid = '\0';
1510 }
1511 int fd = open(pidfile, O_RDWR | O_CREAT, S_IRUSR | S_IWUSR);
1512 if (fd == -1)
1513 goto exit;
1514 /* Get the flags */
1515 flags = fcntl(fd, F_GETFD);
1516 if (flags == -1) {
1517 goto exit;
1518 }
1519 /* Set FD_CLOEXEC, so exclusive lock will be removed on exit, so even if GPAC crashes,
1520 * lock will be allowed for next instance */
1521 flags |= FD_CLOEXEC;
1522 /* Now, update the flags */
1523 if (fcntl(fd, F_SETFD, flags) == -1) {
1524 goto exit;
1525 }
1526
1527 /* Now, we try to lock the file */
1528 {
1529 struct flock fl;
1530 fl.l_type = F_WRLCK;
1531 fl.l_whence = SEEK_SET;
1532 fl.l_start = fl.l_len = 0;
1533 status = fcntl(fd, F_SETLK, &fl);
1534 }
1535
1536 if (status == -1) {
1537 goto exit;
1538 }
1539
1540 if (ftruncate(fd, 0) == -1) {
1541 goto exit;
1542 }
1543 /* Write the PID */
1544 {
1545 int sz = 100;
1546 char * buf = gf_malloc(sz);
1547 sz = snprintf(buf, sz, "%ld\n", (long)getpid());
1548 if (write(fd, buf, sz) != sz) {
1549 gf_free(buf);
1550 goto exit;
1551 }
1552 }
1553 sync();
1554 {
1555 GF_GlobalLock * lock = gf_malloc(sizeof(GF_GlobalLock));
1556 lock->resourceName = gf_strdup(resourceName);
1557 lock->pidFile = pidfile;
1558 lock->fd = fd;
1559 return lock;
1560 }
1561 exit:
1562 if (fd >= 0)
1563 close(fd);
1564 return NULL;
1565 }
1566 #else /* WIN32 */
1567 struct _GF_GlobalLock_opaque {
1568 char * resourceName;
1569 HANDLE hMutex; /*a named mutex is a system-mode object on windows*/
1570 };
1571 #endif
1572
1573 GF_EXPORT
gf_global_resource_lock(const char * resourceName)1574 GF_GlobalLock * gf_global_resource_lock(const char * resourceName) {
1575 #ifdef WIN32
1576 #ifdef _WIN32_WCE
1577 unsigned short sWResourceName[MAX_PATH];
1578 #endif
1579 DWORD lastErr;
1580 GF_GlobalLock *lock = gf_malloc(sizeof(GF_GlobalLock));
1581 lock->resourceName = gf_strdup(resourceName);
1582
1583 /*first ensure mutex is created*/
1584 #ifdef _WIN32_WCE
1585 CE_CharToWide((char *)resourceName, sWResourceName);
1586 lock->hMutex = CreateMutex(NULL, TRUE, sWResourceName);
1587 #else
1588 lock->hMutex = CreateMutex(NULL, TRUE, resourceName);
1589 #endif
1590 lastErr = GetLastError();
1591 if (lastErr && lastErr == ERROR_ALREADY_EXISTS)
1592 return NULL;
1593 if (!lock->hMutex)
1594 {
1595 GF_LOG(GF_LOG_ERROR, GF_LOG_MUTEX, ("[Mutex] Couldn't create mutex for global lock: %d\n", lastErr));
1596 return NULL;
1597 }
1598
1599 /*then lock it*/
1600 switch (WaitForSingleObject(lock->hMutex, INFINITE)) {
1601 case WAIT_ABANDONED:
1602 case WAIT_TIMEOUT:
1603 assert(0); /*serious error: someone has modified the object elsewhere*/
1604 GF_LOG(GF_LOG_ERROR, GF_LOG_MUTEX, ("[Mutex] Couldn't get the global lock\n"));
1605 gf_global_resource_unlock(lock);
1606 return NULL;
1607 }
1608
1609 return lock;
1610 #else /* WIN32 */
1611 return gf_create_PID_file(resourceName);
1612 #endif /* WIN32 */
1613 }
1614
1615 /*!
1616 * Unlock a previouly locked resource
1617 * \param lock The resource to unlock
1618 * \return GF_OK if evertything went fine
1619 */
1620 GF_EXPORT
gf_global_resource_unlock(GF_GlobalLock * lock)1621 GF_Err gf_global_resource_unlock(GF_GlobalLock * lock) {
1622 if (!lock)
1623 return GF_BAD_PARAM;
1624 #ifndef WIN32
1625 assert(lock->pidFile);
1626 close(lock->fd);
1627 if (unlink(lock->pidFile))
1628 perror("Failed to unlink lock file");
1629 gf_free(lock->pidFile);
1630 lock->pidFile = NULL;
1631 lock->fd = -1;
1632 #else /* WIN32 */
1633 {
1634 /*MSDN: "The mutex object is destroyed when its last handle has been closed."*/
1635 BOOL ret = ReleaseMutex(lock->hMutex);
1636 if (!ret) {
1637 DWORD err = GetLastError();
1638 GF_LOG(GF_LOG_ERROR, GF_LOG_MUTEX, ("[Mutex] Couldn't release mutex for global lock: %d\n", err));
1639 }
1640 ret = CloseHandle(lock->hMutex);
1641 if (!ret) {
1642 DWORD err = GetLastError();
1643 GF_LOG(GF_LOG_ERROR, GF_LOG_MUTEX, ("[Mutex] Couldn't destroy mutex for global lock: %d\n", err));
1644 }
1645 }
1646 #endif
1647 if (lock->resourceName)
1648 gf_free(lock->resourceName);
1649 lock->resourceName = NULL;
1650 gf_free(lock);
1651 return GF_OK;
1652 }
1653
1654 #ifdef GPAC_ANDROID
1655
1656 fm_callback_func fm_cbk = NULL;
1657 static void *fm_cbk_obj = NULL;
1658
gf_fm_request_set_callback(void * cbk_obj,fm_callback_func cbk_func)1659 void gf_fm_request_set_callback(void *cbk_obj, fm_callback_func cbk_func) {
1660 fm_cbk = cbk_func;
1661 fm_cbk_obj = cbk_obj;
1662 }
1663
gf_fm_request_call(u32 type,u32 param,int * value)1664 void gf_fm_request_call(u32 type, u32 param, int *value) {
1665 if (fm_cbk)
1666 fm_cbk(fm_cbk_obj, type, param, value);
1667 }
1668
1669 #endif //GPAC_ANDROID
1670
1671 GF_EXPORT
gf_gettimeofday(struct timeval * tp,void * tz)1672 s32 gf_gettimeofday(struct timeval *tp, void *tz) {
1673 return gettimeofday(tp, tz);
1674 }
1675
1676
1677 static u32 ntp_shift = GF_NTP_SEC_1900_TO_1970;
1678
1679 GF_EXPORT
gf_net_set_ntp_shift(s32 shift)1680 void gf_net_set_ntp_shift(s32 shift)
1681 {
1682 ntp_shift = GF_NTP_SEC_1900_TO_1970 + shift;
1683 }
1684
1685 /*
1686 NTP tools
1687 */
1688 GF_EXPORT
gf_net_get_ntp(u32 * sec,u32 * frac)1689 void gf_net_get_ntp(u32 *sec, u32 *frac)
1690 {
1691 u64 frac_part;
1692 struct timeval now;
1693 gettimeofday(&now, NULL);
1694 if (sec) {
1695 *sec = (u32)(now.tv_sec) + ntp_shift;
1696 }
1697
1698 if (frac) {
1699 frac_part = now.tv_usec * 0xFFFFFFFFULL;
1700 frac_part /= 1000000;
1701 *frac = (u32)(frac_part);
1702 }
1703 }
1704
1705 GF_EXPORT
gf_net_get_ntp_ts()1706 u64 gf_net_get_ntp_ts()
1707 {
1708 u64 res;
1709 u32 sec, frac;
1710 gf_net_get_ntp(&sec, &frac);
1711 res = sec;
1712 res <<= 32;
1713 res |= frac;
1714 return res;
1715 }
1716
1717 GF_EXPORT
gf_net_get_ntp_diff_ms(u64 ntp)1718 s32 gf_net_get_ntp_diff_ms(u64 ntp)
1719 {
1720 u32 remote_s, remote_f, local_s, local_f;
1721 s64 local, remote;
1722
1723 remote_s = (ntp >> 32);
1724 remote_f = (u32)(ntp & 0xFFFFFFFFULL);
1725 gf_net_get_ntp(&local_s, &local_f);
1726
1727 local = local_s;
1728 local *= 1000;
1729 local += ((u64)local_f) * 1000 / 0xFFFFFFFFULL;
1730
1731 remote = remote_s;
1732 remote *= 1000;
1733 remote += ((u64)remote_f) * 1000 / 0xFFFFFFFFULL;
1734
1735 return (s32)(local - remote);
1736 }
1737
1738
1739
1740 GF_EXPORT
gf_net_get_timezone()1741 s32 gf_net_get_timezone()
1742 {
1743 #if defined(_WIN32_WCE)
1744 return 0;
1745 #else
1746 //this has been commented due to some reports of broken implementation on some systems ...
1747 // s32 val = timezone;
1748 // return val;
1749
1750
1751 /*FIXME - avoid errors at midnight when estimating timezone this does not work !!*/
1752 s32 t_timezone;
1753 struct tm t_gmt, t_local;
1754 time_t t_time;
1755 t_time = time(NULL);
1756 t_gmt = *gmtime(&t_time);
1757 t_local = *localtime(&t_time);
1758
1759 t_timezone = (t_gmt.tm_hour - t_local.tm_hour) * 3600 + (t_gmt.tm_min - t_local.tm_min) * 60;
1760 return t_timezone;
1761 #endif
1762
1763 }
1764
1765 //no mkgmtime on mingw..., use our own
1766 #if (defined(WIN32) && defined(__GNUC__))
1767
leap_year(u32 year)1768 static Bool leap_year(u32 year) {
1769 year += 1900;
1770 return (year % 4) == 0 && ((year % 100) != 0 || (year % 400) == 0) ? GF_TRUE : GF_FALSE;
1771 }
gf_mktime_utc(struct tm * tm)1772 static time_t gf_mktime_utc(struct tm *tm)
1773 {
1774 static const u32 days_per_month[2][12] = {
1775 { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 },
1776 { 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }
1777 };
1778 time_t time = 0;
1779 int i;
1780
1781 for (i = 70; i<tm->tm_year; i++) {
1782 time += leap_year(i) ? 366 : 365;
1783 }
1784
1785 for (i = 0; i<tm->tm_mon; ++i) {
1786 time += days_per_month[leap_year(tm->tm_year)][i];
1787 }
1788 time += tm->tm_mday - 1;
1789 time *= 24;
1790 time += tm->tm_hour;
1791 time *= 60;
1792 time += tm->tm_min;
1793 time *= 60;
1794 time += tm->tm_sec;
1795 return time;
1796 }
1797
1798 #elif defined(WIN32)
gf_mktime_utc(struct tm * tm)1799 static time_t gf_mktime_utc(struct tm *tm)
1800 {
1801 return _mkgmtime(tm);
1802 }
1803
1804 #elif defined(GPAC_ANDROID)
1805 #include <time64.h>
1806 #if defined(__LP64__)
gf_mktime_utc(struct tm * tm)1807 static time_t gf_mktime_utc(struct tm *tm)
1808 {
1809 return timegm64(tm);
1810 }
1811 #else
gf_mktime_utc(struct tm * tm)1812 static time_t gf_mktime_utc(struct tm *tm)
1813 {
1814 static const time_t kTimeMax = ~(1L << (sizeof(time_t) * CHAR_BIT - 1));
1815 static const time_t kTimeMin = (1L << (sizeof(time_t) * CHAR_BIT - 1));
1816 time64_t result = timegm64(tm);
1817 if (result < kTimeMin || result > kTimeMax)
1818 return -1;
1819 return result;
1820 }
1821 #endif
1822
1823 #else
1824
gf_mktime_utc(struct tm * tm)1825 static time_t gf_mktime_utc(struct tm *tm)
1826 {
1827 return timegm(tm);
1828 }
1829
1830 #endif
1831
1832 GF_EXPORT
gf_net_parse_date(const char * val)1833 u64 gf_net_parse_date(const char *val)
1834 {
1835 u64 current_time;
1836 char szDay[50], szMonth[50];
1837 u32 year, month, day, h, m, s, ms;
1838 s32 oh, om;
1839 Float secs;
1840 Bool neg_time_zone = GF_FALSE;
1841
1842 #ifdef _WIN32_WCE
1843 SYSTEMTIME syst;
1844 FILETIME filet;
1845 #else
1846 struct tm t;
1847 memset(&t, 0, sizeof(struct tm));
1848 #endif
1849
1850 szDay[0] = szMonth[0] = 0;
1851 year = month = day = h = m = s = 0;
1852 oh = om = 0;
1853 secs = 0;
1854
1855 if (sscanf(val, "%d-%d-%dT%d:%d:%gZ", &year, &month, &day, &h, &m, &secs) == 6) {
1856 }
1857 else if (sscanf(val, "%d-%d-%dT%d:%d:%g-%d:%d", &year, &month, &day, &h, &m, &secs, &oh, &om) == 8) {
1858 neg_time_zone = GF_TRUE;
1859 }
1860 else if (sscanf(val, "%d-%d-%dT%d:%d:%g+%d:%d", &year, &month, &day, &h, &m, &secs, &oh, &om) == 8) {
1861 }
1862 else if (sscanf(val, "%3s, %d %3s %d %d:%d:%d", szDay, &day, szMonth, &year, &h, &m, &s) == 7) {
1863 secs = (Float)s;
1864 }
1865 else if (sscanf(val, "%9s, %d-%3s-%d %02d:%02d:%02d GMT", szDay, &day, szMonth, &year, &h, &m, &s) == 7) {
1866 secs = (Float)s;
1867 }
1868 else if (sscanf(val, "%3s %3s %d %02d:%02d:%02d %d", szDay, szMonth, &day, &year, &h, &m, &s) == 7) {
1869 secs = (Float)s;
1870 }
1871 else {
1872 GF_LOG(GF_LOG_ERROR, GF_LOG_CORE, ("[Core] Cannot parse date string %s\n", val));
1873 return 0;
1874 }
1875
1876 if (month) {
1877 month -= 1;
1878 }
1879 else {
1880 if (!strcmp(szMonth, "Jan")) month = 0;
1881 else if (!strcmp(szMonth, "Feb")) month = 1;
1882 else if (!strcmp(szMonth, "Mar")) month = 2;
1883 else if (!strcmp(szMonth, "Apr")) month = 3;
1884 else if (!strcmp(szMonth, "May")) month = 4;
1885 else if (!strcmp(szMonth, "Jun")) month = 5;
1886 else if (!strcmp(szMonth, "Jul")) month = 6;
1887 else if (!strcmp(szMonth, "Aug")) month = 7;
1888 else if (!strcmp(szMonth, "Sep")) month = 8;
1889 else if (!strcmp(szMonth, "Oct")) month = 9;
1890 else if (!strcmp(szMonth, "Nov")) month = 10;
1891 else if (!strcmp(szMonth, "Dec")) month = 11;
1892 }
1893
1894 #ifdef _WIN32_WCE
1895 memset(&syst, 0, sizeof(SYSTEMTIME));
1896 syst.wYear = year;
1897 syst.wMonth = month + 1;
1898 syst.wDay = day;
1899 syst.wHour = h;
1900 syst.wMinute = m;
1901 syst.wSecond = (u32)secs;
1902 SystemTimeToFileTime(&syst, &filet);
1903 current_time = (u64)((*(LONGLONG *)&filet - TIMESPEC_TO_FILETIME_OFFSET) / 10000000);
1904
1905 #else
1906
1907 t.tm_year = year>1000 ? year - 1900 : year;
1908 t.tm_mday = day;
1909 t.tm_hour = h;
1910 t.tm_min = m;
1911 t.tm_sec = (u32)secs;
1912 t.tm_mon = month;
1913
1914 if (strlen(szDay)) {
1915 if (!strcmp(szDay, "Mon") || !strcmp(szDay, "Monday")) t.tm_wday = 0;
1916 else if (!strcmp(szDay, "Tue") || !strcmp(szDay, "Tuesday")) t.tm_wday = 1;
1917 else if (!strcmp(szDay, "Wed") || !strcmp(szDay, "Wednesday")) t.tm_wday = 2;
1918 else if (!strcmp(szDay, "Thu") || !strcmp(szDay, "Thursday")) t.tm_wday = 3;
1919 else if (!strcmp(szDay, "Fri") || !strcmp(szDay, "Friday")) t.tm_wday = 4;
1920 else if (!strcmp(szDay, "Sat") || !strcmp(szDay, "Saturday")) t.tm_wday = 5;
1921 else if (!strcmp(szDay, "Sun") || !strcmp(szDay, "Sunday")) t.tm_wday = 6;
1922 }
1923
1924 current_time = gf_mktime_utc(&t);
1925
1926 if ((s64)current_time == -1) {
1927 //use 1 ms
1928 return 1;
1929 }
1930 if (current_time == 0) {
1931 //use 1 ms
1932 return 1;
1933 }
1934
1935 #endif
1936
1937 if (om || oh) {
1938 s32 diff = (60 * oh + om) * 60;
1939 if (neg_time_zone) diff = -diff;
1940 current_time = current_time + diff;
1941 }
1942 current_time *= 1000;
1943 ms = (u32)((secs - (u32)secs) * 1000);
1944 return current_time + ms;
1945 }
1946
1947 GF_EXPORT
gf_net_get_utc()1948 u64 gf_net_get_utc()
1949 {
1950 u64 current_time;
1951 Double msec;
1952 u32 sec, frac;
1953
1954 gf_net_get_ntp(&sec, &frac);
1955 current_time = sec - GF_NTP_SEC_1900_TO_1970;
1956 current_time *= 1000;
1957 msec = frac*1000.0;
1958 msec /= 0xFFFFFFFF;
1959 current_time += (u64)msec;
1960 return current_time;
1961 }
1962
1963
1964
1965 GF_EXPORT
gf_bin128_parse(char * string,bin128 value)1966 GF_Err gf_bin128_parse(char *string, bin128 value)
1967 {
1968 u32 len;
1969 u32 i = 0;
1970 if (!strnicmp(string, "0x", 2)) string += 2;
1971 len = (u32)strlen(string);
1972 if (len >= 32) {
1973 u32 j;
1974 for (j = 0; j<len; j += 2) {
1975 u32 v;
1976 char szV[5];
1977
1978 while (string[j] && !isalnum(string[j]))
1979 j++;
1980 if (!string[j])
1981 break;
1982 sprintf(szV, "%c%c", string[j], string[j + 1]);
1983 sscanf(szV, "%x", &v);
1984 value[i] = v;
1985 i++;
1986 }
1987 }
1988 if (i != 16) {
1989 GF_LOG(GF_LOG_WARNING, GF_LOG_CORE, ("[CORE] 128bit blob is not 16-bytes long: %s\n", string));
1990 return GF_BAD_PARAM;
1991 }
1992 return GF_OK;
1993 }
1994