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 
28 #if defined(WIN32) && !defined(GPAC_CONFIG_WIN32)
29 #include <windows.h>
30 #include <wincon.h>
31 static HANDLE console = NULL;
32 static WORD console_attr_ori = 0;
33 #endif
34 
35 
36 static char szTYPE[5];
37 
38 
39 GF_EXPORT
gf_4cc_to_str(u32 type)40 const char *gf_4cc_to_str(u32 type)
41 {
42 	u32 ch, i;
43 	char *ptr, *name = (char *)szTYPE;
44 	ptr = name;
45 	for (i = 0; i < 4; i++, name++) {
46 		ch = type >> (8 * (3 - i)) & 0xff;
47 		if (ch >= 0x20 && ch <= 0x7E) {
48 			*name = ch;
49 		}
50 		else {
51 			*name = '.';
52 		}
53 	}
54 	*name = 0;
55 	return (const char *)ptr;
56 }
57 
58 
59 static const char *szProg[] =
60 {
61 	"                    ",
62 	"=                   ",
63 	"==                  ",
64 	"===                 ",
65 	"====                ",
66 	"=====               ",
67 	"======              ",
68 	"=======             ",
69 	"========            ",
70 	"=========           ",
71 	"==========          ",
72 	"===========         ",
73 	"============        ",
74 	"=============       ",
75 	"==============      ",
76 	"===============     ",
77 	"================    ",
78 	"=================   ",
79 	"==================  ",
80 	"=================== ",
81 	"====================",
82 };
83 
84 static u64 prev_pos = 0;
85 static u64 prev_pc = 0;
gf_on_progress_std(const char * _title,u64 done,u64 total)86 static void gf_on_progress_std(const char *_title, u64 done, u64 total)
87 {
88 	Double prog;
89 	u32 pos, pc;
90 	const char *szT = _title ? (char *)_title : (char *) "";
91 	prog = (double)done;
92 	prog /= total;
93 	pos = MIN((u32)(20 * prog), 20);
94 
95 	if (pos>prev_pos) {
96 		prev_pos = 0;
97 		prev_pc = 0;
98 	}
99 	pc = (u32)(100 * prog);
100 	if ((pos != prev_pos) || (pc != prev_pc)) {
101 		prev_pos = pos;
102 		prev_pc = pc;
103 		fprintf(stderr, "%s: |%s| (%02d/100)\r", szT, szProg[pos], pc);
104 		fflush(stderr);
105 	}
106 	if (done == total) {
107 		u32 len = (u32)strlen(szT) + 40;
108 		while (len) {
109 			fprintf(stderr, " ");
110 			len--;
111 		};
112 		fprintf(stderr, "\r");
113 	}
114 }
115 
116 static gf_on_progress_cbk prog_cbk = NULL;
117 static void *user_cbk;
118 
119 GF_EXPORT
gf_set_progress(const char * title,u64 done,u64 total)120 void gf_set_progress(const char *title, u64 done, u64 total)
121 {
122 	if (prog_cbk) {
123 		prog_cbk(user_cbk, title, done, total);
124 	}
125 #ifndef _WIN32_WCE
126 	else {
127 		gf_on_progress_std(title, done, total);
128 	}
129 #endif
130 }
131 
132 GF_EXPORT
gf_set_progress_callback(void * _user_cbk,gf_on_progress_cbk _prog_cbk)133 void gf_set_progress_callback(void *_user_cbk, gf_on_progress_cbk _prog_cbk)
134 {
135 	prog_cbk = _prog_cbk;
136 	user_cbk = _user_cbk;
137 }
138 
139 /*ENTRIES MUST BE IN THE SAME ORDER AS LOG_TOOL DECLARATION IN <gpac/tools.h>*/
140 static struct log_tool_info {
141 	u32 type;
142 	const char *name;
143 	GF_LOG_Level level;
144 } global_log_tools[] =
145 {
146 	{ GF_LOG_CORE, "core", GF_LOG_WARNING },
147 	{ GF_LOG_CODING, "coding", GF_LOG_WARNING },
148 	{ GF_LOG_CONTAINER, "container", GF_LOG_WARNING },
149 	{ GF_LOG_NETWORK, "network", GF_LOG_WARNING },
150 	{ GF_LOG_RTP, "rtp", GF_LOG_WARNING },
151 	{ GF_LOG_AUTHOR, "author", GF_LOG_WARNING },
152 	{ GF_LOG_SYNC, "sync", GF_LOG_WARNING },
153 	{ GF_LOG_CODEC, "codec", GF_LOG_WARNING },
154 	{ GF_LOG_PARSER, "parser", GF_LOG_WARNING },
155 	{ GF_LOG_MEDIA, "media", GF_LOG_WARNING },
156 	{ GF_LOG_SCENE, "scene", GF_LOG_WARNING },
157 	{ GF_LOG_SCRIPT, "script", GF_LOG_WARNING },
158 	{ GF_LOG_INTERACT, "interact", GF_LOG_WARNING },
159 	{ GF_LOG_COMPOSE, "compose", GF_LOG_WARNING },
160 	{ GF_LOG_CACHE, "cache", GF_LOG_WARNING },
161 	{ GF_LOG_MMIO, "mmio", GF_LOG_WARNING },
162 	{ GF_LOG_RTI, "rti", GF_LOG_WARNING },
163 	{ GF_LOG_SMIL, "smil", GF_LOG_WARNING },
164 	{ GF_LOG_MEMORY, "mem", GF_LOG_WARNING },
165 	{ GF_LOG_AUDIO, "audio", GF_LOG_WARNING },
166 	{ GF_LOG_MODULE, "module", GF_LOG_WARNING },
167 	{ GF_LOG_MUTEX, "mutex", GF_LOG_WARNING },
168 	{ GF_LOG_CONDITION, "condition", GF_LOG_WARNING },
169 	{ GF_LOG_DASH, "dash", GF_LOG_WARNING },
170 	{ GF_LOG_CONSOLE, "console", GF_LOG_INFO },
171 	{ GF_LOG_APP, "app", GF_LOG_INFO },
172 	{ GF_LOG_SCHEDULER, "scheduler", GF_LOG_INFO },
173 };
174 
175 GF_EXPORT
gf_log_modify_tools_levels(const char * val)176 GF_Err gf_log_modify_tools_levels(const char *val)
177 {
178 #ifndef GPAC_DISABLE_LOG
179 	u32 level;
180 	char *sep, *sep_level;
181 	while (val && strlen(val)) {
182 		const char *next_val = NULL;
183 		const char *tools = NULL;
184 		/*look for log level*/
185 		sep_level = strchr(val, '@');
186 		if (!sep_level) {
187 			fprintf(stderr, "Unrecognized log format %s - expecting logTool@logLevel\n", val);
188 			return GF_BAD_PARAM;
189 		}
190 
191 		if (!strnicmp(sep_level + 1, "error", 5)) {
192 			level = GF_LOG_ERROR;
193 			next_val = sep_level + 1 + 5;
194 		}
195 		else if (!strnicmp(sep_level + 1, "warning", 7)) {
196 			level = GF_LOG_WARNING;
197 			next_val = sep_level + 1 + 7;
198 		}
199 		else if (!strnicmp(sep_level + 1, "info", 4)) {
200 			level = GF_LOG_INFO;
201 			next_val = sep_level + 1 + 4;
202 		}
203 		else if (!strnicmp(sep_level + 1, "debug", 5)) {
204 			level = GF_LOG_DEBUG;
205 			next_val = sep_level + 1 + 5;
206 		}
207 		else if (!strnicmp(sep_level + 1, "quiet", 5)) {
208 			level = GF_LOG_QUIET;
209 			next_val = sep_level + 1 + 5;
210 		}
211 		else {
212 			fprintf(stderr, "Unknown log level specified: %s\n", sep_level + 1);
213 			return GF_BAD_PARAM;
214 		}
215 
216 		sep_level[0] = 0;
217 		tools = val;
218 		while (tools) {
219 			u32 i;
220 
221 			sep = strchr(tools, ':');
222 			if (sep) sep[0] = 0;
223 
224 			if (!stricmp(tools, "all")) {
225 				for (i = 0; i<GF_LOG_TOOL_MAX; i++)
226 					global_log_tools[i].level = level;
227 			}
228 			else {
229 				Bool found = GF_FALSE;
230 				for (i = 0; i<GF_LOG_TOOL_MAX; i++) {
231 					if (!strcmp(global_log_tools[i].name, tools)) {
232 						global_log_tools[i].level = level;
233 						found = GF_TRUE;
234 					}
235 				}
236 				if (!found) {
237 					sep_level[0] = '@';
238 					if (sep) sep[0] = ':';
239 					fprintf(stderr, "Unknown log tool specified: %s\n", val);
240 					return GF_BAD_PARAM;
241 				}
242 			}
243 
244 			if (!sep) break;
245 			sep[0] = ':';
246 			tools = sep + 1;
247 		}
248 
249 		sep_level[0] = '@';
250 		if (!next_val[0]) break;
251 		val = next_val + 1;
252 	}
253 #endif
254 	return GF_OK;
255 }
256 
257 GF_EXPORT
gf_log_set_tools_levels(const char * val)258 GF_Err gf_log_set_tools_levels(const char *val)
259 {
260 #ifndef GPAC_DISABLE_LOG
261 	u32 i;
262 	for (i = 0; i<GF_LOG_TOOL_MAX; i++)
263 		global_log_tools[i].level = GF_LOG_WARNING;
264 
265 	return gf_log_modify_tools_levels(val);
266 #else
267 	return GF_OK;
268 #endif
269 }
270 
271 GF_EXPORT
gf_log_get_tools_levels()272 char *gf_log_get_tools_levels()
273 {
274 #ifndef GPAC_DISABLE_LOG
275 	u32 i, level, len;
276 	char szLogs[GF_MAX_PATH];
277 	char szLogTools[GF_MAX_PATH];
278 	strcpy(szLogTools, "");
279 
280 	level = GF_LOG_QUIET;
281 	while (level <= GF_LOG_DEBUG) {
282 		u32 nb_tools = 0;
283 		strcpy(szLogs, "");
284 		for (i = 0; i<GF_LOG_TOOL_MAX; i++) {
285 			if (global_log_tools[i].level == level) {
286 				strcat(szLogs, global_log_tools[i].name);
287 				strcat(szLogs, ":");
288 				nb_tools++;
289 			}
290 		}
291 		if (nb_tools) {
292 			char *levelstr = "@warning";
293 			if (level == GF_LOG_QUIET) levelstr = "@quiet";
294 			else if (level == GF_LOG_ERROR) levelstr = "@error";
295 			else if (level == GF_LOG_WARNING) levelstr = "@warning";
296 			else if (level == GF_LOG_INFO) levelstr = "@info";
297 			else if (level == GF_LOG_DEBUG) levelstr = "@debug";
298 
299 			if (nb_tools>GF_LOG_TOOL_MAX / 2) {
300 				strcpy(szLogs, szLogTools);
301 				strcpy(szLogTools, "all");
302 				strcat(szLogTools, levelstr);
303 				if (strlen(szLogs)) {
304 					strcat(szLogTools, ":");
305 					strcat(szLogTools, szLogs);
306 				}
307 			}
308 			else {
309 				if (strlen(szLogTools)) {
310 					strcat(szLogTools, ":");
311 				}
312 				/*remove last ':' from tool*/
313 				szLogs[strlen(szLogs) - 1] = 0;
314 				strcat(szLogTools, szLogs);
315 				strcat(szLogTools, levelstr);
316 			}
317 		}
318 		level++;
319 	}
320 	len = (u32)strlen(szLogTools);
321 	if (len) {
322 		/*remove last ':' from level*/
323 		if (szLogTools[len - 1] == ':') szLogTools[len - 1] = 0;
324 		return gf_strdup(szLogTools);
325 	}
326 #endif
327 	return gf_strdup("all@quiet");
328 }
329 
330 #ifndef GPAC_DISABLE_LOG
331 u32 call_lev = 0;
332 u32 call_tool = 0;
333 
334 GF_EXPORT
gf_log_tool_level_on(GF_LOG_Tool log_tool,GF_LOG_Level log_level)335 Bool gf_log_tool_level_on(GF_LOG_Tool log_tool, GF_LOG_Level log_level)
336 {
337 	assert(log_tool<GF_LOG_TOOL_MAX);
338 	if (global_log_tools[log_tool].level >= log_level) return GF_TRUE;
339 	return GF_FALSE;
340 }
341 
342 #define RED    "\x1b[31m"
343 #define YELLOW "\x1b[33m"
344 #define GREEN  "\x1b[32m"
345 #define CYAN   "\x1b[36m"
346 #define WHITE  "\x1b[37m"
347 #define RESET  "\x1b[0m"
348 
default_log_callback(void * cbck,GF_LOG_Level level,GF_LOG_Tool tool,const char * fmt,va_list vlist)349 void default_log_callback(void *cbck, GF_LOG_Level level, GF_LOG_Tool tool, const char *fmt, va_list vlist)
350 {
351 #if defined(WIN32) && !defined(GPAC_CONFIG_WIN32)
352 	if (console == NULL) {
353 		CONSOLE_SCREEN_BUFFER_INFO console_info;
354 		console = GetStdHandle(STD_ERROR_HANDLE);
355 		assert(console != INVALID_HANDLE_VALUE);
356 		if (console != INVALID_HANDLE_VALUE) {
357 			GetConsoleScreenBufferInfo(console, &console_info);
358 			console_attr_ori = console_info.wAttributes;
359 		}
360 	}
361 	switch (level) {
362 	case GF_LOG_ERROR:
363 		SetConsoleTextAttribute(console, FOREGROUND_RED | FOREGROUND_INTENSITY);
364 		break;
365 	case GF_LOG_WARNING:
366 		SetConsoleTextAttribute(console, FOREGROUND_INTENSITY | FOREGROUND_RED | FOREGROUND_GREEN);
367 		break;
368 	case GF_LOG_INFO:
369 		SetConsoleTextAttribute(console, FOREGROUND_INTENSITY | FOREGROUND_GREEN);
370 		break;
371 	case GF_LOG_DEBUG:
372 		SetConsoleTextAttribute(console, FOREGROUND_GREEN);
373 		break;
374 	default:
375 		SetConsoleTextAttribute(console, FOREGROUND_GREEN | FOREGROUND_RED | FOREGROUND_BLUE);
376 		break;
377 	}
378 
379 	vfprintf(stderr, fmt, vlist);
380 	SetConsoleTextAttribute(console, console_attr_ori);
381 #elif !defined(_WIN32_WCE)
382 	switch (level) {
383 	case GF_LOG_ERROR:
384 		fprintf(stderr, RED);
385 		break;
386 	case GF_LOG_WARNING:
387 		fprintf(stderr, YELLOW);
388 		break;
389 	case GF_LOG_INFO:
390 		fprintf(stderr, GREEN);
391 		break;
392 	case GF_LOG_DEBUG:
393 		fprintf(stderr, CYAN);
394 		break;
395 	default:
396 		fprintf(stderr, WHITE);
397 		break;
398 	}
399 
400 	vfprintf(stderr, fmt, vlist);
401 	fprintf(stderr, RESET);
402 #else /*_WIN32_WCE*/
403 	/*no log*/
404 #endif
405 }
406 
407 static void *user_log_cbk = NULL;
408 gf_log_cbk log_cbk = default_log_callback;
409 static Bool log_exit_on_error = GF_FALSE;
410 
411 GF_EXPORT
gf_log(const char * fmt,...)412 void gf_log(const char *fmt, ...)
413 {
414 	va_list vl;
415 	va_start(vl, fmt);
416 	log_cbk(user_log_cbk, call_lev, call_tool, fmt, vl);
417 	va_end(vl);
418 	if (log_exit_on_error && (call_lev == GF_LOG_ERROR) && (call_tool != GF_LOG_MEMORY)) {
419 		exit(1);
420 	}
421 }
422 
423 GF_EXPORT
gf_log_va_list(GF_LOG_Level level,GF_LOG_Tool tool,const char * fmt,va_list vl)424 void gf_log_va_list(GF_LOG_Level level, GF_LOG_Tool tool, const char *fmt, va_list vl)
425 {
426 	log_cbk(user_log_cbk, call_lev, call_tool, fmt, vl);
427 	if (log_exit_on_error && (call_lev == GF_LOG_ERROR) && (call_tool != GF_LOG_MEMORY)) {
428 		exit(1);
429 	}
430 }
431 
432 GF_EXPORT
gf_log_set_strict_error(Bool strict)433 void gf_log_set_strict_error(Bool strict)
434 {
435 	log_exit_on_error = strict;
436 }
437 
438 GF_EXPORT
gf_log_set_tool_level(GF_LOG_Tool tool,GF_LOG_Level level)439 void gf_log_set_tool_level(GF_LOG_Tool tool, GF_LOG_Level level)
440 {
441 	assert(tool <= GF_LOG_TOOL_MAX);
442 	if (tool == GF_LOG_ALL) {
443 		u32 i;
444 		for (i = 0; i<GF_LOG_TOOL_MAX; i++)
445 			global_log_tools[i].level = level;
446 	}
447 	else {
448 		global_log_tools[tool].level = level;
449 	}
450 }
451 
452 GF_EXPORT
gf_log_lt(GF_LOG_Level ll,GF_LOG_Tool lt)453 void gf_log_lt(GF_LOG_Level ll, GF_LOG_Tool lt)
454 {
455 	call_lev = ll;
456 	call_tool = lt;
457 }
458 
459 GF_EXPORT
gf_log_set_callback(void * usr_cbk,gf_log_cbk cbk)460 gf_log_cbk gf_log_set_callback(void *usr_cbk, gf_log_cbk cbk)
461 {
462 	gf_log_cbk prev_cbk = log_cbk;
463 	log_cbk = cbk;
464 	if (!log_cbk) log_cbk = default_log_callback;
465 	if (usr_cbk) user_log_cbk = usr_cbk;
466 	return prev_cbk;
467 }
468 
469 #else
470 GF_EXPORT
gf_log(const char * fmt,...)471 void gf_log(const char *fmt, ...)
472 {
473 }
474 GF_EXPORT
gf_log_lt(GF_LOG_Level ll,GF_LOG_Tool lt)475 void gf_log_lt(GF_LOG_Level ll, GF_LOG_Tool lt)
476 {
477 }
478 GF_EXPORT
gf_log_set_strict_error(Bool strict)479 void gf_log_set_strict_error(Bool strict)
480 {
481 }
482 
483 GF_EXPORT
gf_log_set_callback(void * usr_cbk,gf_log_cbk cbk)484 gf_log_cbk gf_log_set_callback(void *usr_cbk, gf_log_cbk cbk)
485 {
486 	return NULL;
487 }
488 #endif
489 
490 static char szErrMsg[20];
491 
492 GF_EXPORT
gf_error_to_string(GF_Err e)493 const char *gf_error_to_string(GF_Err e)
494 {
495 	switch (e) {
496 	case GF_EOS:
497 		return "End Of Stream / File";
498 	case GF_OK:
499 		return "No Error";
500 
501 		/*General errors */
502 	case GF_BAD_PARAM:
503 		return "Bad Parameter";
504 	case GF_OUT_OF_MEM:
505 		return "Out Of Memory";
506 	case GF_IO_ERR:
507 		return "I/O Error";
508 	case GF_NOT_SUPPORTED:
509 		return "Feature Not Supported";
510 	case GF_CORRUPTED_DATA:
511 		return "Corrupted Data in file/stream";
512 
513 		/*File Format Errors */
514 	case GF_ISOM_INVALID_FILE:
515 		return "Invalid IsoMedia File";
516 	case GF_ISOM_INCOMPLETE_FILE:
517 		return "IsoMedia File is truncated";
518 	case GF_ISOM_INVALID_MEDIA:
519 		return "Invalid IsoMedia Media";
520 	case GF_ISOM_INVALID_MODE:
521 		return "Invalid Mode while accessing the file";
522 	case GF_ISOM_UNKNOWN_DATA_REF:
523 		return "Media Data Reference not found";
524 
525 		/*Object Descriptor Errors */
526 	case GF_ODF_INVALID_DESCRIPTOR:
527 		return "Invalid MPEG-4 Descriptor";
528 	case GF_ODF_FORBIDDEN_DESCRIPTOR:
529 		return "MPEG-4 Descriptor Not Allowed";
530 	case GF_ODF_INVALID_COMMAND:
531 		return "Read OD Command Failed";
532 
533 		/*BIFS Errors */
534 	case GF_SG_UNKNOWN_NODE:
535 		return "Unknown BIFS Node";
536 	case GF_SG_INVALID_PROTO:
537 		return "Invalid Proto Interface";
538 	case GF_BIFS_UNKNOWN_VERSION:
539 		return "Invalid BIFS version";
540 	case GF_SCRIPT_ERROR:
541 		return "Invalid Script";
542 
543 		/*MPEG-4 Errors */
544 	case GF_BUFFER_TOO_SMALL:
545 		return "Bad Buffer size (too small)";
546 	case GF_NON_COMPLIANT_BITSTREAM:
547 		return "BitStream Not Compliant";
548 	case GF_CODEC_NOT_FOUND:
549 		return "Media Codec not found";
550 
551 		/*DMIF errors - local and control plane */
552 	case GF_URL_ERROR:
553 		return "Requested URL is not valid or cannot be found";
554 
555 	case GF_SERVICE_ERROR:
556 		return "Internal Service Error";
557 	case GF_REMOTE_SERVICE_ERROR:
558 		return "Dialog Failure with remote peer";
559 
560 	case GF_STREAM_NOT_FOUND:
561 		return "Media Channel couldn't be found";
562 
563 	case GF_IP_ADDRESS_NOT_FOUND:
564 		return "IP Address Not Found";
565 	case GF_IP_CONNECTION_FAILURE:
566 		return "IP Connection Failed";
567 	case GF_IP_NETWORK_FAILURE:
568 		return "Network Unreachable";
569 
570 	case GF_IP_NETWORK_EMPTY:
571 		return "Network Timeout";
572 	case GF_IP_SOCK_WOULD_BLOCK:
573 		return "Socket Would Block";
574 	case GF_IP_CONNECTION_CLOSED:
575 		return "Connection to server closed";
576 	case GF_IP_UDP_TIMEOUT:
577 		return "UDP traffic timeout";
578 	case GF_AUTHENTICATION_FAILURE:
579 		return "Authentication failure";
580 	case GF_SCRIPT_NOT_READY:
581 		return "Script not ready for playback";
582 	case GF_INVALID_CONFIGURATION:
583 		return "Bad configuration for the current context";
584 	case GF_NOT_FOUND:
585 		return "At least one required element has not been found";
586 	case GF_MISSING_REQUIREMENTS:
587 		return "The filter is missing at least one requirement";
588 	case GF_WRONG_DATAFORMAT:
589 		return "Unexpected data format";
590 	default:
591 		sprintf(szErrMsg, "Unknown Error (%d)", e);
592 		return szErrMsg;
593 	}
594 }
595 
596 static const u32 gf_crc_table[256] = {
597 	0x00000000, 0x04c11db7, 0x09823b6e, 0x0d4326d9, 0x130476dc, 0x17c56b6b,
598 	0x1a864db2, 0x1e475005, 0x2608edb8, 0x22c9f00f, 0x2f8ad6d6, 0x2b4bcb61,
599 	0x350c9b64, 0x31cd86d3, 0x3c8ea00a, 0x384fbdbd, 0x4c11db70, 0x48d0c6c7,
600 	0x4593e01e, 0x4152fda9, 0x5f15adac, 0x5bd4b01b, 0x569796c2, 0x52568b75,
601 	0x6a1936c8, 0x6ed82b7f, 0x639b0da6, 0x675a1011, 0x791d4014, 0x7ddc5da3,
602 	0x709f7b7a, 0x745e66cd, 0x9823b6e0, 0x9ce2ab57, 0x91a18d8e, 0x95609039,
603 	0x8b27c03c, 0x8fe6dd8b, 0x82a5fb52, 0x8664e6e5, 0xbe2b5b58, 0xbaea46ef,
604 	0xb7a96036, 0xb3687d81, 0xad2f2d84, 0xa9ee3033, 0xa4ad16ea, 0xa06c0b5d,
605 	0xd4326d90, 0xd0f37027, 0xddb056fe, 0xd9714b49, 0xc7361b4c, 0xc3f706fb,
606 	0xceb42022, 0xca753d95, 0xf23a8028, 0xf6fb9d9f, 0xfbb8bb46, 0xff79a6f1,
607 	0xe13ef6f4, 0xe5ffeb43, 0xe8bccd9a, 0xec7dd02d, 0x34867077, 0x30476dc0,
608 	0x3d044b19, 0x39c556ae, 0x278206ab, 0x23431b1c, 0x2e003dc5, 0x2ac12072,
609 	0x128e9dcf, 0x164f8078, 0x1b0ca6a1, 0x1fcdbb16, 0x018aeb13, 0x054bf6a4,
610 	0x0808d07d, 0x0cc9cdca, 0x7897ab07, 0x7c56b6b0, 0x71159069, 0x75d48dde,
611 	0x6b93dddb, 0x6f52c06c, 0x6211e6b5, 0x66d0fb02, 0x5e9f46bf, 0x5a5e5b08,
612 	0x571d7dd1, 0x53dc6066, 0x4d9b3063, 0x495a2dd4, 0x44190b0d, 0x40d816ba,
613 	0xaca5c697, 0xa864db20, 0xa527fdf9, 0xa1e6e04e, 0xbfa1b04b, 0xbb60adfc,
614 	0xb6238b25, 0xb2e29692, 0x8aad2b2f, 0x8e6c3698, 0x832f1041, 0x87ee0df6,
615 	0x99a95df3, 0x9d684044, 0x902b669d, 0x94ea7b2a, 0xe0b41de7, 0xe4750050,
616 	0xe9362689, 0xedf73b3e, 0xf3b06b3b, 0xf771768c, 0xfa325055, 0xfef34de2,
617 	0xc6bcf05f, 0xc27dede8, 0xcf3ecb31, 0xcbffd686, 0xd5b88683, 0xd1799b34,
618 	0xdc3abded, 0xd8fba05a, 0x690ce0ee, 0x6dcdfd59, 0x608edb80, 0x644fc637,
619 	0x7a089632, 0x7ec98b85, 0x738aad5c, 0x774bb0eb, 0x4f040d56, 0x4bc510e1,
620 	0x46863638, 0x42472b8f, 0x5c007b8a, 0x58c1663d, 0x558240e4, 0x51435d53,
621 	0x251d3b9e, 0x21dc2629, 0x2c9f00f0, 0x285e1d47, 0x36194d42, 0x32d850f5,
622 	0x3f9b762c, 0x3b5a6b9b, 0x0315d626, 0x07d4cb91, 0x0a97ed48, 0x0e56f0ff,
623 	0x1011a0fa, 0x14d0bd4d, 0x19939b94, 0x1d528623, 0xf12f560e, 0xf5ee4bb9,
624 	0xf8ad6d60, 0xfc6c70d7, 0xe22b20d2, 0xe6ea3d65, 0xeba91bbc, 0xef68060b,
625 	0xd727bbb6, 0xd3e6a601, 0xdea580d8, 0xda649d6f, 0xc423cd6a, 0xc0e2d0dd,
626 	0xcda1f604, 0xc960ebb3, 0xbd3e8d7e, 0xb9ff90c9, 0xb4bcb610, 0xb07daba7,
627 	0xae3afba2, 0xaafbe615, 0xa7b8c0cc, 0xa379dd7b, 0x9b3660c6, 0x9ff77d71,
628 	0x92b45ba8, 0x9675461f, 0x8832161a, 0x8cf30bad, 0x81b02d74, 0x857130c3,
629 	0x5d8a9099, 0x594b8d2e, 0x5408abf7, 0x50c9b640, 0x4e8ee645, 0x4a4ffbf2,
630 	0x470cdd2b, 0x43cdc09c, 0x7b827d21, 0x7f436096, 0x7200464f, 0x76c15bf8,
631 	0x68860bfd, 0x6c47164a, 0x61043093, 0x65c52d24, 0x119b4be9, 0x155a565e,
632 	0x18197087, 0x1cd86d30, 0x029f3d35, 0x065e2082, 0x0b1d065b, 0x0fdc1bec,
633 	0x3793a651, 0x3352bbe6, 0x3e119d3f, 0x3ad08088, 0x2497d08d, 0x2056cd3a,
634 	0x2d15ebe3, 0x29d4f654, 0xc5a92679, 0xc1683bce, 0xcc2b1d17, 0xc8ea00a0,
635 	0xd6ad50a5, 0xd26c4d12, 0xdf2f6bcb, 0xdbee767c, 0xe3a1cbc1, 0xe760d676,
636 	0xea23f0af, 0xeee2ed18, 0xf0a5bd1d, 0xf464a0aa, 0xf9278673, 0xfde69bc4,
637 	0x89b8fd09, 0x8d79e0be, 0x803ac667, 0x84fbdbd0, 0x9abc8bd5, 0x9e7d9662,
638 	0x933eb0bb, 0x97ffad0c, 0xafb010b1, 0xab710d06, 0xa6322bdf, 0xa2f33668,
639 	0xbcb4666d, 0xb8757bda, 0xb5365d03, 0xb1f740b4
640 };
641 
642 GF_EXPORT
gf_crc_32(const char * data,u32 len)643 u32 gf_crc_32(const char *data, u32 len)
644 {
645 	register u32 i;
646 	u32 crc = 0xffffffff;
647 	if (!data) return 0;
648 	for (i = 0; i<len; i++)
649 		crc = (crc << 8) ^ gf_crc_table[((crc >> 24) ^ *data++) & 0xff];
650 
651 	return crc;
652 }
653 
654 
655 #define CHECK_MAC(_a) "#_a :" ? (_a) ? "yes":"no"
656 
657 GF_EXPORT
gpac_features()658 const char *gpac_features()
659 {
660 	const char *features = ""
661 #ifdef GPAC_64_BITS
662 		"GPAC_64_BITS "
663 #endif
664 
665 #ifdef GPAC_FIXED_POINT
666 		"GPAC_FIXED_POINT "
667 #endif
668 #ifdef GPAC_MEMORY_TRACKING
669 		"GPAC_MEMORY_TRACKING "
670 #endif
671 #ifdef GPAC_BIG_ENDIAN
672 		"GPAC_BIG_ENDIAN "
673 #endif
674 #ifdef GPAC_HAS_SSL
675 		"GPAC_HAS_SSL "
676 #endif
677 #ifdef GPAC_HAS_SPIDERMONKEY
678 		"GPAC_HAS_SPIDERMONKEY "
679 #endif
680 #ifdef GPAC_HAS_JPEG
681 		"GPAC_HAS_JPEG "
682 #endif
683 #ifdef GPAC_HAS_PNG
684 		"GPAC_HAS_PNG "
685 #endif
686 #ifdef GPAC_DISABLE_3D
687 		"GPAC_DISABLE_3D "
688 #endif
689 #ifdef GPAC_USE_TINYGL
690 		"GPAC_USE_TINYGL "
691 #endif
692 #ifdef GPAC_USE_GLES1X
693 		"GPAC_USE_GLES1X "
694 #endif
695 #if defined(_WIN32_WCE)
696 #ifdef GPAC_USE_IGPP
697 		"GPAC_USE_IGPP "
698 #endif
699 #ifdef GPAC_USE_IGPP_HP
700 		"GPAC_USE_IGPP_HP "
701 #endif
702 #endif
703 #ifdef GPAC_DISABLE_SVG
704 		"GPAC_DISABLE_SVG "
705 #endif
706 #ifdef GPAC_DISABLE_VRML
707 		"GPAC_DISABLE_VRML "
708 #endif
709 #ifdef GPAC_MINIMAL_ODF
710 		"GPAC_MINIMAL_ODF "
711 #endif
712 #ifdef GPAC_DISABLE_BIFS
713 		"GPAC_DISABLE_BIFS "
714 #endif
715 #ifdef GPAC_DISABLE_QTVR
716 		"GPAC_DISABLE_QTVR "
717 #endif
718 #ifdef GPAC_DISABLE_AVILIB
719 		"GPAC_DISABLE_AVILIB "
720 #endif
721 #ifdef GPAC_DISABLE_OGG
722 		"GPAC_DISABLE_OGG "
723 #endif
724 #ifdef GPAC_DISABLE_MPEG2PS
725 		"GPAC_DISABLE_MPEG2PS "
726 #endif
727 #ifdef GPAC_DISABLE_MPEG2PS
728 		"GPAC_DISABLE_MPEG2TS "
729 #endif
730 #ifdef GPAC_DISABLE_SENG
731 		"GPAC_DISABLE_SENG "
732 #endif
733 #ifdef GPAC_DISABLE_MEDIA_IMPORT
734 		"GPAC_DISABLE_MEDIA_IMPORT "
735 #endif
736 #ifdef GPAC_DISABLE_AV_PARSERS
737 		"GPAC_DISABLE_AV_PARSERS "
738 #endif
739 #ifdef GPAC_DISABLE_MEDIA_EXPORT
740 		"GPAC_DISABLE_MEDIA_EXPORT "
741 #endif
742 #ifdef GPAC_DISABLE_SWF_IMPORT
743 		"GPAC_DISABLE_SWF_IMPORT "
744 #endif
745 #ifdef GPAC_DISABLE_SCENE_STATS
746 		"GPAC_DISABLE_SCENE_STATS "
747 #endif
748 #ifdef GPAC_DISABLE_SCENE_DUMP
749 		"GPAC_DISABLE_SCENE_DUMP "
750 #endif
751 #ifdef GPAC_DISABLE_SCENE_ENCODER
752 		"GPAC_DISABLE_SCENE_ENCODER "
753 #endif
754 #ifdef GPAC_DISABLE_LOADER_ISOM
755 		"GPAC_DISABLE_LOADER_ISOM "
756 #endif
757 #ifdef GPAC_DISABLE_OD_DUMP
758 		"GPAC_DISABLE_OD_DUMP "
759 #endif
760 #ifdef GPAC_DISABLE_MCRYPT
761 		"GPAC_DISABLE_MCRYPT "
762 #endif
763 #ifdef GPAC_DISABLE_ISOM
764 		"GPAC_DISABLE_MCRYPT "
765 #endif
766 #ifdef GPAC_DISABLE_ISOM_HINTING
767 		"GPAC_DISABLE_ISOM_HINTING "
768 #endif
769 #ifdef GPAC_DISABLE_ISOM_WRITE
770 		"GPAC_DISABLE_ISOM_WRITE "
771 #endif
772 #ifdef GPAC_DISABLE_ISOM_FRAGMENTS
773 		"GPAC_DISABLE_ISOM_FRAGMENTS "
774 #endif
775 #ifdef GPAC_DISABLE_LASER
776 		"GPAC_DISABLE_LASER "
777 #endif
778 #ifdef GPAC_DISABLE_STREAMING
779 		"GPAC_DISABLE_STREAMING "
780 #endif
781 
782 		;
783 	return features;
784 }
785 
786 
787 static const struct lang_def {
788 	const char *name;
789 	const char *three_char_code;
790 	const char *two_char_code;
791 } defined_languages[] =
792 {
793 	{ "Abkhazian","abk","ab" } ,
794 	{ "Achinese","ace","" } ,
795 	{ "Acoli","ach","" } ,
796 	{ "Adangme","ada","" } ,
797 	{ "Adyghe; Adygei","ady","" } ,
798 	{ "Afar","aar","aa" } ,
799 	{ "Afrihili","afh","" } ,
800 	{ "Afrikaans","afr","af" } ,
801 	{ "Afro-Asiatic languages","afa","" } ,
802 	{ "Ainu","ain","" } ,
803 	{ "Akan","aka","ak" } ,
804 	{ "Akkadian","akk","" } ,
805 	{ "Albanian","sqi","sq" } ,
806 	{ "Aleut","ale","" } ,
807 	{ "Algonquian languages","alg","" } ,
808 	{ "Altaic languages","tut","" } ,
809 	{ "Amharic","amh","am" } ,
810 	{ "Angika","anp","" } ,
811 	{ "Apache languages","apa","" } ,
812 	{ "Arabic","ara","ar" } ,
813 	{ "Aragonese","arg","an" } ,
814 	{ "Arapaho","arp","" } ,
815 	{ "Arawak","arw","" } ,
816 	{ "Armenian","hye","hy" } ,
817 	{ "Aromanian; Arumanian; Macedo-Romanian","rup","" } ,
818 	{ "Artificial languages","art","" } ,
819 	{ "Assamese","asm","as" } ,
820 	{ "Asturian; Bable; Leonese; Asturleonese","ast","" } ,
821 	{ "Athapascan languages","ath","" } ,
822 	{ "Australian languages","aus","" } ,
823 	{ "Austronesian languages","map","" } ,
824 	{ "Avaric","ava","av" } ,
825 	{ "Avestan","ave","ae" } ,
826 	{ "Awadhi","awa","" } ,
827 	{ "Aymara","aym","ay" } ,
828 	{ "Azerbaijani","aze","az" } ,
829 	{ "Balinese","ban","" } ,
830 	{ "Baltic languages","bat","" } ,
831 	{ "Baluchi","bal","" } ,
832 	{ "Bambara","bam","bm" } ,
833 	{ "Bamileke languages","bai","" } ,
834 	{ "Banda languages","bad","" } ,
835 	{ "Bantu languages","bnt","" } ,
836 	{ "Basa","bas","" } ,
837 	{ "Bashkir","bak","ba" } ,
838 	{ "Basque","eus","eu" } ,
839 	{ "Batak languages","btk","" } ,
840 	{ "Beja; Bedawiyet","bej","" } ,
841 	{ "Belarusian","bel","be" } ,
842 	{ "Bemba","bem","" } ,
843 	{ "Bengali","ben","bn" } ,
844 	{ "Berber languages","ber","" } ,
845 	{ "Bhojpuri","bho","" } ,
846 	{ "Bihari languages","bih","bh" } ,
847 	{ "Bikol","bik","" } ,
848 	{ "Bini; Edo","bin","" } ,
849 	{ "Bislama","bis","bi" } ,
850 	{ "Blin; Bilin","byn","" } ,
851 	{ "Blissymbols; Blissymbolics; Bliss","zbl","" } ,
852 	{ "Bokmal, Norwegian; Norwegian Bokmal","nob","nb" } ,
853 	{ "Bosnian","bos","bs" } ,
854 	{ "Braj","bra","" } ,
855 	{ "Breton","bre","br" } ,
856 	{ "Buginese","bug","" } ,
857 	{ "Bulgarian","bul","bg" } ,
858 	{ "Buriat","bua","" } ,
859 	{ "Burmese","mya","my" } ,
860 	{ "Caddo","cad","" } ,
861 	{ "Catalan; Valencian","cat","ca" } ,
862 	{ "Caucasian languages","cau","" } ,
863 	{ "Cebuano","ceb","" } ,
864 	{ "Celtic languages","cel","" } ,
865 	{ "Central American Indian languages","cai","" } ,
866 	{ "Central Khmer","khm","km" } ,
867 	{ "Chagatai","chg","" } ,
868 	{ "Chamic languages","cmc","" } ,
869 	{ "Chamorro","cha","ch" } ,
870 	{ "Chechen","che","ce" } ,
871 	{ "Cherokee","chr","" } ,
872 	{ "Cheyenne","chy","" } ,
873 	{ "Chibcha","chb","" } ,
874 	{ "Chichewa; Chewa; Nyanja","nya","ny" } ,
875 	{ "Chinese","zho","zh" } ,
876 	{ "Chinook jargon","chn","" } ,
877 	{ "Chipewyan; Dene Suline","chp","" } ,
878 	{ "Choctaw","cho","" } ,
879 	{ "Church Slavic; Old Slavonic; Church Slavonic; Old Bulgarian; Old Church}  S{ lavonic","chu","cu" } ,
880 	{ "Chuukese","chk","" } ,
881 	{ "Chuvash","chv","cv" } ,
882 	{ "Classical Newari; Old Newari; Classical Nepal Bhasa","nwc","" } ,
883 	{ "Classical Syriac","syc","" } ,
884 	{ "Coptic","cop","" } ,
885 	{ "Cornish","cor","kw" } ,
886 	{ "Corsican","cos","co" } ,
887 	{ "Cree","cre","cr" } ,
888 	{ "Creek","mus","" } ,
889 	{ "Creoles and pidgins","crp","" } ,
890 	{ "Creoles and pidgins, English based","cpe","" } ,
891 	{ "Creoles and pidgins, French-based","cpf","" } ,
892 	{ "Creoles and pidgins, Portuguese-based","cpp","" } ,
893 	{ "Crimean Tatar; Crimean Turkish","crh","" } ,
894 	{ "Croatian","hrv","hr" } ,
895 	{ "Cushitic languages","cus","" } ,
896 	{ "Czech","ces","cs" } ,
897 	{ "Dakota","dak","" } ,
898 	{ "Danish","dan","da" } ,
899 	{ "Dargwa","dar","" } ,
900 	{ "Delaware","del","" } ,
901 	{ "Dinka","din","" } ,
902 	{ "Divehi; Dhivehi; Maldivian","div","dv" } ,
903 	{ "Dogri","doi","" } ,
904 	{ "Dogrib","dgr","" } ,
905 	{ "Dravidian languages","dra","" } ,
906 	{ "Duala","dua","" } ,
907 	{ "Dutch, Middle (ca.1050-1350)","dum","" } ,
908 	{ "Dutch; Flemish","nld","nl" } ,
909 	{ "Dyula","dyu","" } ,
910 	{ "Dzongkha","dzo","dz" } ,
911 	{ "Eastern Frisian","frs","" } ,
912 	{ "Efik","efi","" } ,
913 	{ "Egyptian (Ancient)","egy","" } ,
914 	{ "Ekajuk","eka","" } ,
915 	{ "Elamite","elx","" } ,
916 	{ "English","eng","en" } ,
917 	{ "English, Middle (1100-1500)","enm","" } ,
918 	{ "English, Old (ca.450-1100)","ang","" } ,
919 	{ "Erzya","myv","" } ,
920 	{ "Esperanto","epo","eo" } ,
921 	{ "Estonian","est","et" } ,
922 	{ "Ewe","ewe","ee" } ,
923 	{ "Ewondo","ewo","" } ,
924 	{ "Fang","fan","" } ,
925 	{ "Fanti","fat","" } ,
926 	{ "Faroese","fao","fo" } ,
927 	{ "Fijian","fij","fj" } ,
928 	{ "Filipino; Pilipino","fil","" } ,
929 	{ "Finnish","fin","fi" } ,
930 	{ "Finno-Ugrian languages","fiu","" } ,
931 	{ "Fon","fon","" } ,
932 	{ "French","fra","fr" } ,
933 	{ "French, Middle (ca.1400-1600)","frm","" } ,
934 	{ "French, Old (842-ca.1400)","fro","" } ,
935 	{ "Friulian","fur","" } ,
936 	{ "Fulah","ful","ff" } ,
937 	{ "Ga","gaa","" } ,
938 	{ "Gaelic; Scottish Gaelic","gla","gd" } ,
939 	{ "Galibi Carib","car","" } ,
940 	{ "Galician","glg","gl" } ,
941 	{ "Ganda","lug","lg" } ,
942 	{ "Gayo","gay","" } ,
943 	{ "Gbaya","gba","" } ,
944 	{ "Geez","gez","" } ,
945 	{ "Georgian","kat","ka" } ,
946 	{ "German","deu","de" } ,
947 	{ "German, Middle High (ca.1050-1500)","gmh","" } ,
948 	{ "German, Old High (ca.750-1050)","goh","" } ,
949 	{ "Germanic languages","gem","" } ,
950 	{ "Gilbertese","gil","" } ,
951 	{ "Gondi","gon","" } ,
952 	{ "Gorontalo","gor","" } ,
953 	{ "Gothic","got","" } ,
954 	{ "Grebo","grb","" } ,
955 	{ "Greek, Ancient (to 1453)","grc","" } ,
956 	{ "Greek, Modern (1453-)","ell","el" } ,
957 	{ "Guarani","grn","gn" } ,
958 	{ "Gujarati","guj","gu" } ,
959 	{ "Gwich'in","gwi","" } ,
960 	{ "Haida","hai","" } ,
961 	{ "Haitian; Haitian Creole","hat","ht" } ,
962 	{ "Hausa","hau","ha" } ,
963 	{ "Hawaiian","haw","" } ,
964 	{ "Hebrew","heb","he" } ,
965 	{ "Herero","her","hz" } ,
966 	{ "Hiligaynon","hil","" } ,
967 	{ "Himachali languages; Western Pahari languages","him","" } ,
968 	{ "Hindi","hin","hi" } ,
969 	{ "Hiri Motu","hmo","ho" } ,
970 	{ "Hittite","hit","" } ,
971 	{ "Hmong; Mong","hmn","" } ,
972 	{ "Hungarian","hun","hu" } ,
973 	{ "Hupa","hup","" } ,
974 	{ "Iban","iba","" } ,
975 	{ "Icelandic","isl","is" } ,
976 	{ "Ido","ido","io" } ,
977 	{ "Igbo","ibo","ig" } ,
978 	{ "Ijo languages","ijo","" } ,
979 	{ "Iloko","ilo","" } ,
980 	{ "Inari Sami","smn","" } ,
981 	{ "Indic languages","inc","" } ,
982 	{ "Indo-European languages","ine","" } ,
983 	{ "Indonesian","ind","id" } ,
984 	{ "Ingush","inh","" } ,
985 	{ "Interlingua (International Auxiliary Language Association)","ina","ia" } ,
986 	{ "Interlingue; Occidental","ile","ie" } ,
987 	{ "Inuktitut","iku","iu" } ,
988 	{ "Inupiaq","ipk","ik" } ,
989 	{ "Iranian languages","ira","" } ,
990 	{ "Irish","gle","ga" } ,
991 	{ "Irish, Middle (900-1200)","mga","" } ,
992 	{ "Irish, Old (to 900)","sga","" } ,
993 	{ "Iroquoian languages","iro","" } ,
994 	{ "Italian","ita","it" } ,
995 	{ "Japanese","jpn","ja" } ,
996 	{ "Javanese","jav","jv" } ,
997 	{ "Judeo-Arabic","jrb","" } ,
998 	{ "Judeo-Persian","jpr","" } ,
999 	{ "Kabardian","kbd","" } ,
1000 	{ "Kabyle","kab","" } ,
1001 	{ "Kachin; Jingpho","kac","" } ,
1002 	{ "Kalaallisut; Greenlandic","kal","kl" } ,
1003 	{ "Kalmyk; Oirat","xal","" } ,
1004 	{ "Kamba","kam","" } ,
1005 	{ "Kannada","kan","kn" } ,
1006 	{ "Kanuri","kau","kr" } ,
1007 	{ "Kara-Kalpak","kaa","" } ,
1008 	{ "Karachay-Balkar","krc","" } ,
1009 	{ "Karelian","krl","" } ,
1010 	{ "Karen languages","kar","" } ,
1011 	{ "Kashmiri","kas","ks" } ,
1012 	{ "Kashubian","csb","" } ,
1013 	{ "Kawi","kaw","" } ,
1014 	{ "Kazakh","kaz","kk" } ,
1015 	{ "Khasi","kha","" } ,
1016 	{ "Khoisan languages","khi","" } ,
1017 	{ "Khotanese; Sakan","kho","" } ,
1018 	{ "Kikuyu; Gikuyu","kik","ki" } ,
1019 	{ "Kimbundu","kmb","" } ,
1020 	{ "Kinyarwanda","kin","rw" } ,
1021 	{ "Kirghiz; Kyrgyz","kir","ky" } ,
1022 	{ "Klingon; tlhIngan-Hol","tlh","" } ,
1023 	{ "Komi","kom","kv" } ,
1024 	{ "Kongo","kon","kg" } ,
1025 	{ "Konkani","kok","" } ,
1026 	{ "Korean","kor","ko" } ,
1027 	{ "Kosraean","kos","" } ,
1028 	{ "Kpelle","kpe","" } ,
1029 	{ "Kru languages","kro","" } ,
1030 	{ "Kuanyama; Kwanyama","kua","kj" } ,
1031 	{ "Kumyk","kum","" } ,
1032 	{ "Kurdish","kur","ku" } ,
1033 	{ "Kurukh","kru","" } ,
1034 	{ "Kutenai","kut","" } ,
1035 	{ "Ladino","lad","" } ,
1036 	{ "Lahnda","lah","" } ,
1037 	{ "Lamba","lam","" } ,
1038 	{ "Land Dayak languages","day","" } ,
1039 	{ "Lao","lao","lo" } ,
1040 	{ "Latin","lat","la" } ,
1041 	{ "Latvian","lav","lv" } ,
1042 	{ "Lezghian","lez","" } ,
1043 	{ "Limburgan; Limburger; Limburgish","lim","li" } ,
1044 	{ "Lingala","lin","ln" } ,
1045 	{ "Lithuanian","lit","lt" } ,
1046 	{ "Lojban","jbo","" } ,
1047 	{ "Low German; Low Saxon; German, Low; Saxon, Low","nds","" } ,
1048 	{ "Lower Sorbian","dsb","" } ,
1049 	{ "Lozi","loz","" } ,
1050 	{ "Luba-Katanga","lub","lu" } ,
1051 	{ "Luba-Lulua","lua","" } ,
1052 	{ "Luiseno","lui","" } ,
1053 	{ "Lule Sami","smj","" } ,
1054 	{ "Lunda","lun","" } ,
1055 	{ "Luo (Kenya and Tanzania)","luo","" } ,
1056 	{ "Lushai","lus","" } ,
1057 	{ "Luxembourgish; Letzeburgesch","ltz","lb" } ,
1058 	{ "Macedonian","mkd","mk" } ,
1059 	{ "Madurese","mad","" } ,
1060 	{ "Magahi","mag","" } ,
1061 	{ "Maithili","mai","" } ,
1062 	{ "Makasar","mak","" } ,
1063 	{ "Malagasy","mlg","mg" } ,
1064 	{ "Malay","msa","ms" } ,
1065 	{ "Malayalam","mal","ml" } ,
1066 	{ "Maltese","mlt","mt" } ,
1067 	{ "Manchu","mnc","" } ,
1068 	{ "Mandar","mdr","" } ,
1069 	{ "Mandingo","man","" } ,
1070 	{ "Manipuri","mni","" } ,
1071 	{ "Manobo languages","mno","" } ,
1072 	{ "Manx","glv","gv" } ,
1073 	{ "Maori","mri","mi" } ,
1074 	{ "Mapudungun; Mapuche","arn","" } ,
1075 	{ "Marathi","mar","mr" } ,
1076 	{ "Mari","chm","" } ,
1077 	{ "Marshallese","mah","mh" } ,
1078 	{ "Marwari","mwr","" } ,
1079 	{ "Masai","mas","" } ,
1080 	{ "Mayan languages","myn","" } ,
1081 	{ "Mende","men","" } ,
1082 	{ "Mi'kmaq; Micmac","mic","" } ,
1083 	{ "Minangkabau","min","" } ,
1084 	{ "Mirandese","mwl","" } ,
1085 	{ "Mohawk","moh","" } ,
1086 	{ "Moksha","mdf","" } ,
1087 	{ "Mon-Khmer languages","mkh","" } ,
1088 	{ "Mongo","lol","" } ,
1089 	{ "Mongolian","mon","mn" } ,
1090 	{ "Mossi","mos","" } ,
1091 	{ "Multiple languages","mul","" } ,
1092 	{ "Munda languages","mun","" } ,
1093 	{ "N'Ko","nqo","" } ,
1094 	{ "Nahuatl languages","nah","" } ,
1095 	{ "Nauru","nau","na" } ,
1096 	{ "Navajo; Navaho","nav","nv" } ,
1097 	{ "Ndebele, North; North Ndebele","nde","nd" } ,
1098 	{ "Ndebele, South; South Ndebele","nbl","nr" } ,
1099 	{ "Ndonga","ndo","ng" } ,
1100 	{ "Neapolitan","nap","" } ,
1101 	{ "Nepal Bhasa; Newari","new","" } ,
1102 	{ "Nepali","nep","ne" } ,
1103 	{ "Nias","nia","" } ,
1104 	{ "Niger-Kordofanian languages","nic","" } ,
1105 	{ "Nilo-Saharan languages","ssa","" } ,
1106 	{ "Niuean","niu","" } ,
1107 	{ "No linguistic content; Not applicable","zxx","" } ,
1108 	{ "Nogai","nog","" } ,
1109 	{ "Norse, Old","non","" } ,
1110 	{ "North American Indian languages","nai","" } ,
1111 	{ "Northern Frisian","frr","" } ,
1112 	{ "Northern Sami","sme","se" } ,
1113 	{ "Norwegian","nor","no" } ,
1114 	{ "Norwegian Nynorsk; Nynorsk, Norwegian","nno","nn" } ,
1115 	{ "Nubian languages","nub","" } ,
1116 	{ "Nyamwezi","nym","" } ,
1117 	{ "Nyankole","nyn","" } ,
1118 	{ "Nyoro","nyo","" } ,
1119 	{ "Nzima","nzi","" } ,
1120 	{ "Occitan (post 1500)","oci","oc" } ,
1121 	{ "Official Aramaic (700-300 BCE); Imperial Aramaic (700-300 BCE)","arc","" } ,
1122 	{ "Ojibwa","oji","oj" } ,
1123 	{ "Oriya","ori","or" } ,
1124 	{ "Oromo","orm","om" } ,
1125 	{ "Osage","osa","" } ,
1126 	{ "Ossetian; Ossetic","oss","os" } ,
1127 	{ "Otomian languages","oto","" } ,
1128 	{ "Pahlavi","pal","" } ,
1129 	{ "Palauan","pau","" } ,
1130 	{ "Pali","pli","pi" } ,
1131 	{ "Pampanga; Kapampangan","pam","" } ,
1132 	{ "Pangasinan","pag","" } ,
1133 	{ "Panjabi; Punjabi","pan","pa" } ,
1134 	{ "Papiamento","pap","" } ,
1135 	{ "Papuan languages","paa","" } ,
1136 	{ "Pedi; Sepedi; Northern Sotho","nso","" } ,
1137 	{ "Persian","fas","fa" } ,
1138 	{ "Persian, Old (ca.600-400 B.C.)","peo","" } ,
1139 	{ "Philippine languages","phi","" } ,
1140 	{ "Phoenician","phn","" } ,
1141 	{ "Pohnpeian","pon","" } ,
1142 	{ "Polish","pol","pl" } ,
1143 	{ "Portuguese","por","pt" } ,
1144 	{ "Prakrit languages","pra","" } ,
1145 	//{ "Proven�al, Old (to 1500);Occitan, Old (to 1500)","pro",""} ,
1146 	{ "Pushto; Pashto","pus","ps" } ,
1147 	{ "Quechua","que","qu" } ,
1148 	{ "Rajasthani","raj","" } ,
1149 	{ "Rapanui","rap","" } ,
1150 	{ "Rarotongan; Cook Islands Maori","rar","" } ,
1151 	{ "Reserved for local use","qaa-qtz","" } ,
1152 	{ "Romance languages","roa","" } ,
1153 	{ "Romanian; Moldavian; Moldovan","ron","ro" } ,
1154 	{ "Romansh","roh","rm" } ,
1155 	{ "Romany","rom","" } ,
1156 	{ "Rundi","run","rn" } ,
1157 	{ "Russian","rus","ru" } ,
1158 	{ "Salishan languages","sal","" } ,
1159 	{ "Samaritan Aramaic","sam","" } ,
1160 	{ "Sami languages","smi","" } ,
1161 	{ "Samoan","smo","sm" } ,
1162 	{ "Sandawe","sad","" } ,
1163 	{ "Sango","sag","sg" } ,
1164 	{ "Sanskrit","san","sa" } ,
1165 	{ "Santali","sat","" } ,
1166 	{ "Sardinian","srd","sc" } ,
1167 	{ "Sasak","sas","" } ,
1168 	{ "Scots","sco","" } ,
1169 	{ "Selkup","sel","" } ,
1170 	{ "Semitic languages","sem","" } ,
1171 	{ "Serbian","srp","sr" } ,
1172 	{ "Serer","srr","" } ,
1173 	{ "Shan","shn","" } ,
1174 	{ "Shona","sna","sn" } ,
1175 	{ "Sichuan Yi; Nuosu","iii","ii" } ,
1176 	{ "Sicilian","scn","" } ,
1177 	{ "Sidamo","sid","" } ,
1178 	{ "Sign Languages","sgn","" } ,
1179 	{ "Siksika","bla","" } ,
1180 	{ "Sindhi","snd","sd" } ,
1181 	{ "Sinhala; Sinhalese","sin","si" } ,
1182 	{ "Sino-Tibetan languages","sit","" } ,
1183 	{ "Siouan languages","sio","" } ,
1184 	{ "Skolt Sami","sms","" } ,
1185 	{ "Slave (Athapascan)","den","" } ,
1186 	{ "Slavic languages","sla","" } ,
1187 	{ "Slovak","slk","sk" } ,
1188 	{ "Slovenian","slv","sl" } ,
1189 	{ "Sogdian","sog","" } ,
1190 	{ "Somali","som","so" } ,
1191 	{ "Songhai languages","son","" } ,
1192 	{ "Soninke","snk","" } ,
1193 	{ "Sorbian languages","wen","" } ,
1194 	{ "Sotho, Southern","sot","st" } ,
1195 	{ "South American Indian languages","sai","" } ,
1196 	{ "Southern Altai","alt","" } ,
1197 	{ "Southern Sami","sma","" } ,
1198 	{ "Spanish; Castilian","spa","es" } ,
1199 	{ "Sranan Tongo","srn","" } ,
1200 	{ "Sukuma","suk","" } ,
1201 	{ "Sumerian","sux","" } ,
1202 	{ "Sundanese","sun","su" } ,
1203 	{ "Susu","sus","" } ,
1204 	{ "Swahili","swa","sw" } ,
1205 	{ "Swati","ssw","ss" } ,
1206 	{ "Swedish","swe","sv" } ,
1207 	{ "Swiss German; Alemannic; Alsatian","gsw","" } ,
1208 	{ "Syriac","syr","" } ,
1209 	{ "Tagalog","tgl","tl" } ,
1210 	{ "Tahitian","tah","ty" } ,
1211 	{ "Tai languages","tai","" } ,
1212 	{ "Tajik","tgk","tg" } ,
1213 	{ "Tamashek","tmh","" } ,
1214 	{ "Tamil","tam","ta" } ,
1215 	{ "Tatar","tat","tt" } ,
1216 	{ "Telugu","tel","te" } ,
1217 	{ "Tereno","ter","" } ,
1218 	{ "Tetum","tet","" } ,
1219 	{ "Thai","tha","th" } ,
1220 	{ "Tibetan","bod","bo" } ,
1221 	{ "Tigre","tig","" } ,
1222 	{ "Tigrinya","tir","ti" } ,
1223 	{ "Timne","tem","" } ,
1224 	{ "Tiv","tiv","" } ,
1225 	{ "Tlingit","tli","" } ,
1226 	{ "Tok Pisin","tpi","" } ,
1227 	{ "Tokelau","tkl","" } ,
1228 	{ "Tonga (Nyasa)","tog","" } ,
1229 	{ "Tonga (Tonga Islands)","ton","to" } ,
1230 	{ "Tsimshian","tsi","" } ,
1231 	{ "Tsonga","tso","ts" } ,
1232 	{ "Tswana","tsn","tn" } ,
1233 	{ "Tumbuka","tum","" } ,
1234 	{ "Tupi languages","tup","" } ,
1235 	{ "Turkish","tur","tr" } ,
1236 	{ "Turkish, Ottoman (1500-1928)","ota","" } ,
1237 	{ "Turkmen","tuk","tk" } ,
1238 	{ "Tuvalu","tvl","" } ,
1239 	{ "Tuvinian","tyv","" } ,
1240 	{ "Twi","twi","tw" } ,
1241 	{ "Udmurt","udm","" } ,
1242 	{ "Ugaritic","uga","" } ,
1243 	{ "Uighur; Uyghur","uig","ug" } ,
1244 	{ "Ukrainian","ukr","uk" } ,
1245 	{ "Umbundu","umb","" } ,
1246 	{ "Uncoded languages","mis","" } ,
1247 	{ "Undetermined","und","" } ,
1248 	{ "Upper Sorbian","hsb","" } ,
1249 	{ "Urdu","urd","ur" } ,
1250 	{ "Uzbek","uzb","uz" } ,
1251 	{ "Vai","vai","" } ,
1252 	{ "Venda","ven","ve" } ,
1253 	{ "Vietnamese","vie","vi" } ,
1254 	//{ "Volap�k","vol","vo"} ,
1255 	{ "Votic","vot","" } ,
1256 	{ "Wakashan languages","wak","" } ,
1257 	{ "Walloon","wln","wa" } ,
1258 	{ "Waray","war","" } ,
1259 	{ "Washo","was","" } ,
1260 	{ "Welsh","cym","cy" } ,
1261 	{ "Western Frisian","fry","fy" } ,
1262 	{ "Wolaitta; Wolaytta","wal","" } ,
1263 	{ "Wolof","wol","wo" } ,
1264 	{ "Xhosa","xho","xh" } ,
1265 	{ "Yakut","sah","" } ,
1266 	{ "Yao","yao","" } ,
1267 	{ "Yapese","yap","" } ,
1268 	{ "Yiddish","yid","yi" } ,
1269 	{ "Yoruba","yor","yo" } ,
1270 	{ "Yupik languages","ypk","" } ,
1271 	{ "Zande languages","znd","" } ,
1272 	{ "Zapotec","zap","" } ,
1273 	{ "Zaza; Dimili; Dimli; Kirdki; Kirmanjki; Zazaki","zza","" } ,
1274 	{ "Zenaga","zen","" } ,
1275 	{ "Zhuang; Chuang","zha","za" } ,
1276 	{ "Zulu","zul","zu" } ,
1277 	{ "Zuni","zun","" } ,
1278 };
1279 
1280 
1281 GF_EXPORT
gf_lang_get_count()1282 u32 gf_lang_get_count()
1283 {
1284 	return sizeof(defined_languages) / sizeof(struct lang_def);
1285 }
1286 
1287 GF_EXPORT
gf_lang_find(const char * lang_or_rfc_5646_code)1288 s32 gf_lang_find(const char *lang_or_rfc_5646_code)
1289 {
1290 	//find the language ISO639 entry for the given code
1291 	u32 i = 0;
1292 	u32 len = 0;
1293 	char *sep;
1294 	u32 count = sizeof(defined_languages) / sizeof(struct lang_def);
1295 
1296 	if (!lang_or_rfc_5646_code) return -1;
1297 
1298 	len = (u32)strlen(lang_or_rfc_5646_code);
1299 	sep = (char *)strchr(lang_or_rfc_5646_code, '-');
1300 	if (sep) {
1301 		sep[0] = 0;
1302 		len = (u32)strlen(lang_or_rfc_5646_code);
1303 		sep[0] = '-';
1304 	}
1305 
1306 	for (i = 0; i<count; i++) {
1307 		if (!strcmp(defined_languages[i].name, lang_or_rfc_5646_code)) {
1308 			return i;
1309 		}
1310 		if ((len == 3) && !strnicmp(defined_languages[i].three_char_code, lang_or_rfc_5646_code, 3)) {
1311 			return i;
1312 		}
1313 		if ((len == 2) && !strnicmp(defined_languages[i].two_char_code, lang_or_rfc_5646_code, 2)) {
1314 			return i;
1315 		}
1316 	}
1317 	return -1;
1318 }
1319 
1320 GF_EXPORT
gf_lang_get_name(u32 idx)1321 const char *gf_lang_get_name(u32 idx)
1322 {
1323 	if (idx >= sizeof(defined_languages) / sizeof(struct lang_def)) return NULL;
1324 	return defined_languages[idx].name;
1325 }
1326 
1327 GF_EXPORT
gf_lang_get_2cc(u32 idx)1328 const char *gf_lang_get_2cc(u32 idx)
1329 {
1330 	if (idx >= sizeof(defined_languages) / sizeof(struct lang_def)) return NULL;
1331 	return defined_languages[idx].two_char_code;
1332 }
1333 
1334 GF_EXPORT
gf_lang_get_3cc(u32 idx)1335 const char *gf_lang_get_3cc(u32 idx)
1336 {
1337 	if (idx >= sizeof(defined_languages) / sizeof(struct lang_def)) return NULL;
1338 	return defined_languages[idx].three_char_code;
1339 }
1340