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