LCOV - code coverage report
Current view: top level - utils - error.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 322 430 74.9 %
Date: 2021-04-29 23:48:07 Functions: 35 36 97.2 %

          Line data    Source code
       1             : /*
       2             :  *                      GPAC - Multimedia Framework C SDK
       3             :  *
       4             :  *                      Authors: Jean Le Feuvre
       5             :  *                      Copyright (c) Telecom ParisTech 2000-2021
       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/thread.h>
      28             : 
      29             : 
      30             : //ugly patch, we have a concurrence issue with gf_4cc_to_str, for now fixed by rolling buffers
      31             : #define NB_4CC_BUF      10
      32             : static char szTYPE_BUF[NB_4CC_BUF][GF_4CC_MSIZE];
      33             : static u32 buf_4cc_idx=0;
      34             : 
      35             : GF_EXPORT
      36      230404 : const char *gf_4cc_to_str(u32 type)
      37             : {
      38             :         u32 ch, i;
      39      230404 :         char *szTYPE = szTYPE_BUF[buf_4cc_idx];
      40             :         char *name = (char *)szTYPE;
      41      230404 :         if (!type) return "00000000";
      42      230312 :         buf_4cc_idx++;
      43      230312 :         if (buf_4cc_idx==NB_4CC_BUF)
      44       22155 :                 buf_4cc_idx=0;
      45             : 
      46      921248 :         for (i = 0; i < 4; i++) {
      47      921248 :                 ch = type >> (8 * (3-i) ) & 0xff;
      48      921248 :                 if ( ch >= 0x20 && ch <= 0x7E ) {
      49      917227 :                         *name = ch;
      50      917227 :                         name++;
      51             :                 } else {
      52             :                         sprintf(name, "%02X", ch);
      53        4021 :                         name += 2;
      54             :                 }
      55             :         }
      56      230312 :         *name = 0;
      57      230312 :         return (const char *) szTYPE;
      58             : }
      59             : 
      60             : GF_EXPORT
      61           1 : u32 gf_4cc_parse(const char *val)
      62             : {
      63           1 :         if (val && strlen(val)==4) return GF_4CC(val[0], val[1], val[2], val[3]);
      64           0 :         GF_LOG(GF_LOG_ERROR, GF_LOG_CORE, ("[Core] Value is not a properly defined 4CC", val));
      65             :         return 0;
      66             : }
      67             : 
      68             : static const char *szProg[] =
      69             : {
      70             :         "                    ",
      71             :         "=                   ",
      72             :         "==                  ",
      73             :         "===                 ",
      74             :         "====                ",
      75             :         "=====               ",
      76             :         "======              ",
      77             :         "=======             ",
      78             :         "========            ",
      79             :         "=========           ",
      80             :         "==========          ",
      81             :         "===========         ",
      82             :         "============        ",
      83             :         "=============       ",
      84             :         "==============      ",
      85             :         "===============     ",
      86             :         "================    ",
      87             :         "=================   ",
      88             :         "==================  ",
      89             :         "=================== ",
      90             :         "====================",
      91             : };
      92             : 
      93             : static u64 prev_pos = (u64) -1;
      94             : static u64 prev_pc = (u64) -1;
      95             : extern char gf_prog_lf;
      96             : 
      97         346 : static void gf_on_progress_std(const char *_title, u64 done, u64 total)
      98             : {
      99             :         Double prog;
     100             :         u32 pos, pc;
     101         346 :         const char *szT = _title ? (char *)_title : (char *) "";
     102         346 :         prog = (double) done;
     103         346 :         prog /= total;
     104         346 :         pos = MIN((u32) (20 * prog), 20);
     105             : 
     106         346 :         if (pos>prev_pos) {
     107          40 :                 prev_pos = 0;
     108          40 :                 prev_pc = 0;
     109             :         }
     110         346 :         pc = (u32) ( 100 * prog);
     111         346 :         if ((pos!=prev_pos) || (pc!=prev_pc)) {
     112         122 :                 prev_pos = pos;
     113         122 :                 prev_pc = pc;
     114         122 :                 fprintf(stderr, "%s: |%s| (%02d/100)%c", szT, szProg[pos], pc, gf_prog_lf);
     115         122 :                 fflush(stderr);
     116             :         }
     117         346 :         if (done==total) {
     118          14 :                 if (prev_pos) {
     119          14 :                         u32 len = (u32) strlen(szT) + 40;
     120         682 :                         while (len) {
     121         654 :                                 fprintf(stderr, " ");
     122         654 :                                 len--;
     123             :                         };
     124          14 :                         fprintf(stderr, "%c", gf_prog_lf);
     125             :                 }
     126          14 :                 prev_pos = 0;
     127             :         }
     128         346 : }
     129             : 
     130             : static gf_on_progress_cbk prog_cbk = NULL;
     131             : static void *user_cbk;
     132             : static Bool gpac_no_color_logs = GF_FALSE;
     133             : 
     134             : GF_EXPORT
     135     1598681 : void gf_set_progress(const char *title, u64 done, u64 total)
     136             : {
     137     1598681 :         if (done>=total)
     138             :                 done=total;
     139     1598681 :         if (prog_cbk) {
     140     1598335 :                 prog_cbk(user_cbk, title, done, total);
     141             :         }
     142             : #ifndef _WIN32_WCE
     143             :         else {
     144         346 :                 gf_on_progress_std(title, done, total);
     145             :         }
     146             : #endif
     147     1598681 : }
     148             : 
     149             : GF_EXPORT
     150        6190 : void gf_set_progress_callback(void *_user_cbk, gf_on_progress_cbk _prog_cbk)
     151             : {
     152        6190 :         prog_cbk = _prog_cbk;
     153        6190 :         user_cbk = _user_cbk;
     154        6190 : }
     155             : 
     156             : #ifndef GPAC_DISABLE_LOG
     157             : 
     158             : /*ENTRIES MUST BE IN THE SAME ORDER AS LOG_TOOL DECLARATION IN <gpac/tools.h>*/
     159             : static struct log_tool_info {
     160             :         u32 type;
     161             :         const char *name;
     162             :         GF_LOG_Level level;
     163             : } global_log_tools [] =
     164             : {
     165             :         { GF_LOG_CORE, "core", GF_LOG_WARNING },
     166             :         { GF_LOG_CODING, "coding", GF_LOG_WARNING },
     167             :         { GF_LOG_CONTAINER, "container", GF_LOG_WARNING },
     168             :         { GF_LOG_NETWORK, "network", GF_LOG_WARNING },
     169             :         { GF_LOG_HTTP, "http", GF_LOG_WARNING },
     170             :         { GF_LOG_RTP, "rtp", GF_LOG_WARNING },
     171             :         { GF_LOG_AUTHOR, "author", GF_LOG_WARNING },
     172             :         { GF_LOG_SYNC, "sync", GF_LOG_WARNING },
     173             :         { GF_LOG_CODEC, "codec", GF_LOG_WARNING },
     174             :         { GF_LOG_PARSER, "parser", GF_LOG_WARNING },
     175             :         { GF_LOG_MEDIA, "media", GF_LOG_WARNING },
     176             :         { GF_LOG_SCENE, "scene", GF_LOG_WARNING },
     177             :         { GF_LOG_SCRIPT, "script", GF_LOG_WARNING },
     178             :         { GF_LOG_INTERACT, "interact", GF_LOG_WARNING },
     179             :         { GF_LOG_COMPOSE, "compose", GF_LOG_WARNING },
     180             :         { GF_LOG_CACHE, "cache", GF_LOG_WARNING },
     181             :         { GF_LOG_MMIO, "mmio", GF_LOG_WARNING },
     182             :         { GF_LOG_RTI, "rti", GF_LOG_WARNING },
     183             :         { GF_LOG_SMIL, "smil", GF_LOG_WARNING },
     184             :         { GF_LOG_MEMORY, "mem", GF_LOG_WARNING },
     185             :         { GF_LOG_AUDIO, "audio", GF_LOG_WARNING },
     186             :         { GF_LOG_MODULE, "module", GF_LOG_WARNING },
     187             :         { GF_LOG_MUTEX, "mutex", GF_LOG_WARNING },
     188             :         { GF_LOG_CONDITION, "condition", GF_LOG_WARNING },
     189             :         { GF_LOG_DASH, "dash", GF_LOG_WARNING },
     190             :         { GF_LOG_FILTER, "filter", GF_LOG_WARNING },
     191             :         { GF_LOG_SCHEDULER, "sched", GF_LOG_WARNING },
     192             :         { GF_LOG_ROUTE, "route", GF_LOG_WARNING },
     193             :         { GF_LOG_CONSOLE, "console", GF_LOG_INFO },
     194             :         { GF_LOG_APP, "app", GF_LOG_INFO },
     195             : };
     196             : 
     197             : #define GF_LOG_TOOL_MAX_NAME_SIZE (GF_LOG_TOOL_MAX*10)
     198             : 
     199             : #endif
     200             : 
     201             : GF_EXPORT
     202         183 : GF_Err gf_log_modify_tools_levels(const char *val_)
     203             : {
     204             : #ifndef GPAC_DISABLE_LOG
     205             :         char tmp[GF_LOG_TOOL_MAX_NAME_SIZE];
     206             :         const char *val = tmp;
     207         183 :         if (!val_) val_ = "";
     208             :         assert(strlen(val_) < GF_LOG_TOOL_MAX_NAME_SIZE);
     209             :         strncpy(tmp, val_, GF_LOG_TOOL_MAX_NAME_SIZE - 1);
     210         183 :         tmp[GF_LOG_TOOL_MAX_NAME_SIZE - 1] = 0;
     211             : 
     212         368 :         while (val && strlen(val)) {
     213             :                 void default_log_callback(void *cbck, GF_LOG_Level level, GF_LOG_Tool tool, const char *fmt, va_list vlist);
     214             :                 u32 level;
     215             :                 const char *next_val = NULL;
     216             :                 const char *tools = NULL;
     217             :                 /*look for log level*/
     218         185 :                 char *sep_level = strchr(val, '@');
     219         185 :                 if (!sep_level) {
     220         136 :                         if (!strcmp(val, "ncl")) {
     221           1 :                                 gpac_no_color_logs = GF_TRUE;
     222           1 :                                 gf_log_set_callback(NULL, default_log_callback);
     223           1 :                                 if (!val[3]) break;
     224           0 :                                 val += 4;
     225           0 :                                 continue;
     226         135 :                         } else if (!strcmp(val, "strict")) {
     227         135 :                                 gf_log_set_strict_error(GF_TRUE);
     228         135 :                                 if (!val[6]) break;
     229           0 :                                 val += 7;
     230           0 :                                 continue;
     231           0 :                         } else if (!strcmp(val, "quiet")) {
     232             :                                 u32 i;
     233           0 :                                 for (i=0; i<GF_LOG_TOOL_MAX; i++)
     234           0 :                                         global_log_tools[i].level = GF_LOG_QUIET;
     235             : 
     236           0 :                                 if (!val[5]) break;
     237           0 :                                 val += 6;
     238           0 :                                 continue;
     239             :                         } else {
     240           0 :                                 GF_LOG(GF_LOG_ERROR, GF_LOG_CORE, ("Unrecognized log format %s - expecting logTool@logLevel\n", val));
     241             :                                 return GF_BAD_PARAM;
     242             :                         }
     243             :                 }
     244             : 
     245          49 :                 if (!strnicmp(sep_level+1, "error", 5)) {
     246             :                         level = GF_LOG_ERROR;
     247           5 :                         next_val = sep_level+1 + 5;
     248             :                 }
     249          44 :                 else if (!strnicmp(sep_level+1, "warning", 7)) {
     250             :                         level = GF_LOG_WARNING;
     251           0 :                         next_val = sep_level+1 + 7;
     252             :                 }
     253          44 :                 else if (!strnicmp(sep_level+1, "info", 4)) {
     254             :                         level = GF_LOG_INFO;
     255           6 :                         next_val = sep_level+1 + 4;
     256             :                 }
     257          38 :                 else if (!strnicmp(sep_level+1, "debug", 5)) {
     258             :                         level = GF_LOG_DEBUG;
     259          38 :                         next_val = sep_level+1 + 5;
     260             :                 }
     261           0 :                 else if (!strnicmp(sep_level+1, "quiet", 5)) {
     262             :                         level = GF_LOG_QUIET;
     263           0 :                         next_val = sep_level+1 + 5;
     264             :                 }
     265             :                 else {
     266           0 :                         GF_LOG(GF_LOG_ERROR, GF_LOG_CORE, ("Unknown log level specified: %s\n", sep_level+1));
     267             :                         return GF_BAD_PARAM;
     268             :                 }
     269             : 
     270          49 :                 sep_level[0] = 0;
     271             :                 tools = val;
     272         106 :                 while (tools) {
     273             :                         u32 i;
     274             : 
     275          57 :                         char *sep = strchr(tools, ':');
     276          57 :                         if (sep) sep[0] = 0;
     277             : 
     278          57 :                         if (!stricmp(tools, "all")) {
     279          30 :                                 for (i=0; i<GF_LOG_TOOL_MAX; i++)
     280          30 :                                         global_log_tools[i].level = level;
     281             :                         }
     282          56 :                         else if (!strcmp(val, "ncl")) {
     283           0 :                                 gpac_no_color_logs = GF_TRUE;
     284           0 :                                 gf_log_set_callback(NULL, default_log_callback);
     285             :                         }
     286             :                         else {
     287             :                                 Bool found = GF_FALSE;
     288         908 :                                 for (i=0; i<GF_LOG_TOOL_MAX; i++) {
     289         964 :                                         if (!strcmp(global_log_tools[i].name, tools)) {
     290          56 :                                                 global_log_tools[i].level = level;
     291             :                                                 found = GF_TRUE;
     292             :                                                 break;
     293             :                                         }
     294             :                                 }
     295             :                                 if (!found) {
     296           0 :                                         GF_LOG(GF_LOG_ERROR, GF_LOG_CORE, ("Unknown log tool specified: %s\n", tools));
     297             :                                         sep_level[0] = '@';
     298             :                                         if (sep) sep[0] = ':';
     299             :                                         return GF_BAD_PARAM;
     300             :                                 }
     301             :                         }
     302             : 
     303          57 :                         if (!sep) break;
     304           8 :                         sep[0] = ':';
     305           8 :                         tools = sep+1;
     306             :                 }
     307             : 
     308          49 :                 sep_level[0] = '@';
     309          49 :                 if (!next_val[0]) break;
     310           2 :                 val = next_val+1;
     311             :         }
     312             : #endif
     313             :         return GF_OK;
     314             : }
     315             : 
     316             : GF_EXPORT
     317         183 : GF_Err gf_log_set_tools_levels(const char *val, Bool reset_all)
     318             : {
     319             : #ifndef GPAC_DISABLE_LOG
     320             :         u32 i;
     321         183 :         if (reset_all) {
     322           0 :                 for (i=0; i<GF_LOG_TOOL_MAX; i++)
     323           0 :                         global_log_tools[i].level = GF_LOG_WARNING;
     324             :         }
     325         183 :         return gf_log_modify_tools_levels(val);
     326             : #else
     327             :         return GF_OK;
     328             : #endif
     329             : }
     330             : 
     331             : GF_EXPORT
     332           1 : char *gf_log_get_tools_levels()
     333             : {
     334             : #ifndef GPAC_DISABLE_LOG
     335             :         u32 i, level, len;
     336             :         char szLogs[GF_MAX_PATH];
     337             :         char szLogTools[GF_MAX_PATH];
     338             :         strcpy(szLogTools, "");
     339             : 
     340             :         level = GF_LOG_QUIET;
     341           7 :         while (level <= GF_LOG_DEBUG) {
     342             :                 u32 nb_tools = 0;
     343             :                 strcpy(szLogs, "");
     344         155 :                 for (i=0; i<GF_LOG_TOOL_MAX; i++) {
     345         150 :                         if (global_log_tools[i].level == level) {
     346          30 :                                 strcat(szLogs, global_log_tools[i].name);
     347             :                                 strcat(szLogs, ":");
     348          30 :                                 nb_tools++;
     349             :                         }
     350             :                 }
     351           5 :                 if (nb_tools) {
     352             :                         char *levelstr = "@warning";
     353           3 :                         if (level==GF_LOG_QUIET) levelstr = "@quiet";
     354           3 :                         else if (level==GF_LOG_ERROR) levelstr = "@error";
     355           3 :                         else if (level==GF_LOG_WARNING) levelstr = "@warning";
     356           2 :                         else if (level==GF_LOG_INFO) levelstr = "@info";
     357             :                         else if (level==GF_LOG_DEBUG) levelstr = "@debug";
     358             : 
     359           3 :                         if (nb_tools>GF_LOG_TOOL_MAX/2) {
     360             :                                 strcpy(szLogs, szLogTools);
     361             :                                 strcpy(szLogTools, "all");
     362             :                                 strcat(szLogTools, levelstr);
     363           1 :                                 if (strlen(szLogs)) {
     364             :                                         strcat(szLogTools, ":");
     365             :                                         strcat(szLogTools, szLogs);
     366             :                                 }
     367             :                         } else {
     368           2 :                                 if (strlen(szLogTools)) {
     369             :                                         strcat(szLogTools, ":");
     370             :                                 }
     371             :                                 /*remove last ':' from tool*/
     372           2 :                                 szLogs[ strlen(szLogs) - 1 ] = 0;
     373             :                                 strcat(szLogTools, szLogs);
     374             :                                 strcat(szLogTools, levelstr);
     375             :                         }
     376             :                 }
     377           5 :                 level++;
     378             :         }
     379           1 :         len = (u32) strlen(szLogTools);
     380           1 :         if (len) {
     381             :                 /*remove last ':' from level*/
     382           1 :                 if (szLogTools[ len-1 ] == ':') szLogTools[ len-1 ] = 0;
     383           1 :                 return gf_strdup(szLogTools);
     384             :         }
     385             : #endif
     386           0 :         return gf_strdup("all@quiet");
     387             : }
     388             : 
     389             : 
     390             : #if defined(GPAC_CONFIG_WIN32) || defined(WIN32)
     391             : #include <windows.h>
     392             : #include <wincon.h>
     393             : static HANDLE console = NULL;
     394             : static WORD console_attr_ori = 0;
     395             : static CONSOLE_SCREEN_BUFFER_INFO cbck_console;
     396             : static CONSOLE_CURSOR_INFO cbck_cursor;
     397             : static PCHAR_INFO cbck_buffer=NULL;
     398             : static Bool cbck_stored=GF_FALSE;
     399             : static Bool is_mintty = GF_FALSE;
     400             : #endif
     401             : 
     402             : 
     403             : 
     404             : 
     405             : GF_EXPORT
     406      443819 : void gf_sys_set_console_code(FILE *std, GF_ConsoleCodes code)
     407             : {
     408             :         u32 color_code;
     409             : 
     410      443819 :         if (gf_sys_is_test_mode() || gpac_no_color_logs)
     411             :                 return;
     412       38750 :         color_code = code & 0xFFFF;
     413             : #if defined(GPAC_CONFIG_WIN32) || defined(WIN32)
     414             :         WORD attribs=0;
     415             :         if (!is_mintty && (console == NULL)) {
     416             :                 CONSOLE_SCREEN_BUFFER_INFO console_info;
     417             :                 const char *shellv = getenv("SHELL");
     418             :                 if (shellv) {
     419             :                         is_mintty = GF_TRUE;
     420             :                         GF_LOG(GF_LOG_INFO, GF_LOG_CORE, ("[Console] Detected MSys/MinGW/Cygwin TTY, will use VT for coloring\n"))
     421             :                 } else {
     422             :                         console = GetStdHandle(STD_ERROR_HANDLE);
     423             :                         if (console != INVALID_HANDLE_VALUE) {
     424             :                                 GetConsoleScreenBufferInfo(console, &console_info);
     425             :                                 console_attr_ori = console_info.wAttributes;
     426             :                                 GF_LOG(GF_LOG_INFO, GF_LOG_CORE, ("[Console] Detected Windows shell, will use SetConsoleTextAttribute for coloring\n"))
     427             :                         }
     428             :                 }
     429             :         }
     430             : 
     431             :         if (is_mintty) goto win32_ismtty;
     432             : 
     433             :         switch(color_code) {
     434             :         case GF_CONSOLE_RED:
     435             :                 attribs = FOREGROUND_INTENSITY | FOREGROUND_RED;
     436             :                 break;
     437             :         case GF_CONSOLE_BLUE:
     438             :                 attribs = FOREGROUND_INTENSITY | FOREGROUND_BLUE;
     439             :                 break;
     440             :         case GF_CONSOLE_GREEN:
     441             :                 attribs = FOREGROUND_INTENSITY | FOREGROUND_GREEN;
     442             :                 break;
     443             :         case GF_CONSOLE_YELLOW:
     444             :                 attribs = FOREGROUND_INTENSITY | FOREGROUND_RED | FOREGROUND_GREEN;
     445             :                 break;
     446             :         case GF_CONSOLE_MAGENTA:
     447             :                 attribs = FOREGROUND_INTENSITY | FOREGROUND_RED | FOREGROUND_BLUE;
     448             :                 break;
     449             :         case GF_CONSOLE_CYAN:
     450             :                 attribs = FOREGROUND_INTENSITY | FOREGROUND_GREEN | FOREGROUND_BLUE;
     451             :                 break;
     452             :         case GF_CONSOLE_WHITE:
     453             :                 attribs = FOREGROUND_GREEN | FOREGROUND_RED | FOREGROUND_BLUE;
     454             :                 break;
     455             : 
     456             :         case GF_CONSOLE_SAVE:
     457             :                 if (!cbck_stored) {
     458             :                         u32 size, line, line_incr;
     459             :                         COORD pos;
     460             :                         BOOL res;
     461             :                         SMALL_RECT region;
     462             : 
     463             :                         res = GetConsoleScreenBufferInfo(console, &cbck_console);
     464             :                         if (res) res = GetConsoleCursorInfo(console, &cbck_cursor);
     465             : 
     466             :                         if (!res) {
     467             :                                 GF_LOG(GF_LOG_ERROR, GF_LOG_CORE, ("Failed to save win32 console info\n"));
     468             :                                 return;
     469             :                         }
     470             :                         size = cbck_console.dwSize.X * cbck_console.dwSize.Y;
     471             :                         cbck_buffer = (PCHAR_INFO) gf_malloc(size * sizeof(CHAR_INFO));
     472             :                         pos.X = 0;
     473             :                         region.Left = 0;
     474             :                         region.Right = cbck_console.dwSize.X - 1;
     475             :                         line_incr = 12000 / cbck_console.dwSize.X;
     476             :                         for (line=0; line < (u32) cbck_console.dwSize.Y; line += line_incr) {
     477             :                                 pos.Y = line;
     478             :                                 region.Top = line;
     479             :                                 region.Bottom = line + line_incr - 1;
     480             :                                 if (!ReadConsoleOutput(console, cbck_buffer, cbck_console.dwSize, pos, &region)) {
     481             :                                         gf_free(cbck_buffer);
     482             :                                         cbck_buffer = NULL;
     483             :                                         GF_LOG(GF_LOG_ERROR, GF_LOG_CORE, ("Failed to save win32 console info\n"));
     484             :                                         return;
     485             :                                 }
     486             :                         }
     487             :                         cbck_stored = GF_TRUE;
     488             :                 }
     489             :                 return;
     490             : 
     491             :         case GF_CONSOLE_RESTORE:
     492             :                 if (cbck_stored) {
     493             :                         COORD pos;
     494             :                         SMALL_RECT region;
     495             :                         BOOL res;
     496             :                         pos.X = pos.Y = 0;
     497             :                         region.Top = region.Left = 0;
     498             :                         region.Bottom = cbck_console.dwSize.Y - 1;
     499             :                         region.Right = cbck_console.dwSize.X - 1;
     500             :                         res = SetConsoleScreenBufferSize(console, cbck_console.dwSize);
     501             :                         if (res) res = SetConsoleWindowInfo(console, TRUE, &cbck_console.srWindow);
     502             :                         if (res) res = SetConsoleCursorPosition(console, cbck_console.dwCursorPosition);
     503             :                         if (res) res = SetConsoleTextAttribute(console, cbck_console.wAttributes);
     504             : 
     505             :                         if (!res) {
     506             :                                 GF_LOG(GF_LOG_ERROR, GF_LOG_CORE, ("Failed to restore win32 console info\n"));
     507             :                                 return;
     508             :                         }
     509             :                         WriteConsoleOutput(console, cbck_buffer, cbck_console.dwSize,
     510             :                                 pos, &region);
     511             :                         gf_free(cbck_buffer);
     512             :                         cbck_stored = GF_FALSE;
     513             :                 }
     514             :                 return;
     515             : 
     516             :         case GF_CONSOLE_CLEAR:
     517             :         {
     518             :                 COORD coords;
     519             :                 DWORD written;
     520             :                 DWORD consolesize;
     521             :                 CONSOLE_SCREEN_BUFFER_INFO console_info;
     522             : 
     523             :                 coords.X = coords.Y = 0;
     524             :                 GetConsoleScreenBufferInfo(console, &console_info);
     525             :                 consolesize = console_info.dwSize.X * console_info.dwSize.Y;
     526             : 
     527             :                 /* fill space & attribute */
     528             :                 FillConsoleOutputCharacter(console, ' ', consolesize, coords, &written);
     529             :                 FillConsoleOutputAttribute(console, console_info.wAttributes, consolesize, coords, &written);
     530             :                 SetConsoleCursorPosition(console, coords);
     531             :         }
     532             :                 return;
     533             :         case GF_CONSOLE_RESET:
     534             :         default:
     535             :                 attribs = console_attr_ori;
     536             :         }
     537             : 
     538             :         if ((code & 0xFFFF0000) && !color_code) {
     539             :                 attribs |= COMMON_LVB_UNDERSCORE;
     540             :         }
     541             : 
     542             :         SetConsoleTextAttribute(console, attribs);
     543             :         return;
     544             : 
     545             : win32_ismtty:
     546             : #endif
     547             : 
     548             : 
     549             : #if !defined(_WIN32_WCE)
     550             : 
     551       38750 :         switch(color_code) {
     552             :         case GF_CONSOLE_RED: fprintf(std, "\x1b[31m"); break;
     553             :         case GF_CONSOLE_BLUE:
     554             :                 fprintf(std, "\x1b[34m");
     555             :                 break;
     556             :         case GF_CONSOLE_GREEN:
     557             :                 fprintf(std, "\x1b[32m");
     558             :                 break;
     559             :         case GF_CONSOLE_YELLOW:
     560             :                 fprintf(std, "\x1b[33m");
     561             :                 break;
     562             :         case GF_CONSOLE_MAGENTA:
     563             :                 fprintf(std, "\x1b[35m");
     564             :                 break;
     565             :         case GF_CONSOLE_CYAN:
     566             :                 fprintf(std, "\x1b[36m");
     567             :                 break;
     568             :         case GF_CONSOLE_WHITE:
     569             :                 fprintf(std, "\x1b[37m");
     570             :                 break;
     571             : 
     572             :         case GF_CONSOLE_CLEAR:
     573             :                 fprintf(std, "\x1b[2J\x1b[0;0H");
     574             :                 return;
     575             : 
     576             :         case GF_CONSOLE_SAVE:
     577             :                 fprintf(std, "\033[?47h");
     578             :                 return;
     579             :         case GF_CONSOLE_RESTORE:
     580             :                 fprintf(std, "\033[?47l");
     581             :                 fprintf(std, "\x1b[J");
     582             :                 return;
     583             : 
     584       23876 :         case GF_CONSOLE_RESET:
     585             :         default:
     586       23876 :                 if (!code)
     587             :                         fprintf(std, "\x1b[0m");
     588             :         }
     589       38750 :         if (code) {
     590       19387 :                 if (code & GF_CONSOLE_BOLD) fprintf(std, "\x1b[1m");
     591       19387 :                 if (code & GF_CONSOLE_ITALIC) fprintf(std, "\x1b[3m");
     592       19387 :                 if (code & GF_CONSOLE_UNDERLINED) fprintf(std, "\x1b[4m");
     593       19387 :                 if (code & GF_CONSOLE_STRIKE) fprintf(std, "\x1b[9m");
     594             :         }
     595             : #endif
     596             : }
     597             : 
     598             : #ifndef GPAC_DISABLE_LOG
     599             : u32 call_lev = 0;
     600             : u32 call_tool = 0;
     601             : 
     602             : GF_EXPORT
     603   851335154 : Bool gf_log_tool_level_on(GF_LOG_Tool log_tool, GF_LOG_Level log_level)
     604             : {
     605   851335154 :         if (log_tool==GF_LOG_TOOL_MAX) return GF_TRUE;
     606   851387457 :         if (log_tool>GF_LOG_TOOL_MAX) return GF_FALSE;
     607   851454957 :         if (global_log_tools[log_tool].level >= log_level) return GF_TRUE;
     608   851242707 :         return GF_FALSE;
     609             : }
     610             : 
     611          87 : const char *gf_log_tool_name(GF_LOG_Tool log_tool)
     612             : {
     613          87 :         if (log_tool>=GF_LOG_TOOL_MAX) return "unknown";
     614          87 :         return global_log_tools[log_tool].name;
     615             : }
     616          87 : const char *gf_log_level_name(GF_LOG_Level log_level)
     617             : {
     618          87 :         switch (log_level) {
     619             :         case GF_LOG_DEBUG: return "debug";
     620          87 :         case GF_LOG_INFO: return "info";
     621           0 :         case GF_LOG_WARNING: return "warning";
     622           0 :         case GF_LOG_ERROR: return "error";
     623           0 :         default: return "unknown";
     624             :         }
     625             : }
     626             : 
     627             : GF_EXPORT
     628        6286 : u32 gf_log_get_tool_level(GF_LOG_Tool log_tool)
     629             : {
     630        6286 :         if (log_tool>=GF_LOG_TOOL_MAX) return GF_LOG_ERROR;
     631        6286 :         return global_log_tools[log_tool].level;
     632             : }
     633             : 
     634             : FILE *gpac_log_file = NULL;
     635             : Bool gpac_log_time_start = GF_FALSE;
     636             : Bool gpac_log_utc_time = GF_FALSE;
     637             : static u64 gpac_last_log_time=0;
     638             : 
     639      198287 : static void do_log_time(FILE *logs)
     640             : {
     641      198287 :         if (gpac_log_time_start) {
     642        7000 :                 u64 now = gf_sys_clock_high_res();
     643        7000 :                 gf_fprintf(logs, "At "LLD" (diff %d) - ", now, (u32) (now - gpac_last_log_time) );
     644        7000 :                 gpac_last_log_time = now;
     645             :         }
     646      198287 :         if (gpac_log_utc_time) {
     647         466 :                 u64 utc_clock = gf_net_get_utc() ;
     648         466 :                 time_t secs = utc_clock/1000;
     649             :                 struct tm t;
     650         466 :                 t = *gf_gmtime(&secs);
     651         466 :                 gf_fprintf(logs, "UTC %d-%02d-%02dT%02d:%02d:%02dZ (TS "LLU") - ", 1900+t.tm_year, t.tm_mon+1, t.tm_mday, t.tm_hour, t.tm_min, t.tm_sec, utc_clock);
     652             :         }
     653      198287 : }
     654             : 
     655             : int gf_fileio_printf(GF_FileIO *gfio, const char *format, va_list args);
     656             : 
     657         377 : void default_log_callback(void *cbck, GF_LOG_Level level, GF_LOG_Tool tool, const char *fmt, va_list vlist)
     658             : {
     659         377 :         FILE *logs = gpac_log_file ? gpac_log_file : stderr;
     660         377 :         do_log_time(logs);
     661             : 
     662         377 :         if (gf_fileio_check(logs)) {
     663           0 :                 gf_fileio_printf((GF_FileIO *)logs, fmt, vlist);
     664             :         } else {
     665             :                 vfprintf(logs, fmt, vlist);
     666             :         }
     667         377 :         gf_fflush(logs);
     668         377 : }
     669             : 
     670      197910 : void default_log_callback_color(void *cbck, GF_LOG_Level level, GF_LOG_Tool tool, const char *fmt, va_list vlist)
     671             : {
     672      197910 :         if (gpac_log_file) {
     673           0 :                 default_log_callback(cbck, level, tool, fmt, vlist);
     674           0 :                 return;
     675             :         }
     676      197910 :         switch(level) {
     677        2254 :         case GF_LOG_ERROR:
     678        2254 :                 gf_sys_set_console_code(stderr, GF_CONSOLE_RED);
     679        2254 :                 break;
     680        1753 :         case GF_LOG_WARNING:
     681        1753 :                 gf_sys_set_console_code(stderr, GF_CONSOLE_YELLOW);
     682        1753 :                 break;
     683       96369 :         case GF_LOG_INFO:
     684       96369 :                 gf_sys_set_console_code(stderr, (tool==GF_LOG_APP) ? GF_CONSOLE_WHITE : GF_CONSOLE_GREEN);
     685       96369 :                 break;
     686       97534 :         case GF_LOG_DEBUG:
     687       97534 :                 gf_sys_set_console_code(stderr, GF_CONSOLE_CYAN);
     688       97534 :                 break;
     689           0 :         default:
     690           0 :                 gf_sys_set_console_code(stderr, GF_CONSOLE_WHITE);
     691           0 :                 break;
     692             :         }
     693      197910 :         do_log_time(stderr);
     694             : 
     695      197910 :         vfprintf(stderr, fmt, vlist);
     696      197910 :         gf_sys_set_console_code(stderr, GF_CONSOLE_RESET);
     697      197910 :         gf_fflush(stderr);
     698             : }
     699             : 
     700             : 
     701             : 
     702             : static void *user_log_cbk = NULL;
     703             : gf_log_cbk log_cbk = default_log_callback_color;
     704             : static Bool log_exit_on_error = GF_FALSE;
     705             : extern GF_Mutex *logs_mx;
     706             : 
     707             : GF_EXPORT
     708           2 : Bool gf_log_use_color()
     709             : {
     710           2 :         return (log_cbk == default_log_callback_color) ? GF_TRUE : GF_FALSE;
     711             : }
     712             : 
     713             : GF_EXPORT
     714      214552 : void gf_log(const char *fmt, ...)
     715             : {
     716             :         va_list vl;
     717      214552 :         va_start(vl, fmt);
     718      214552 :         gf_mx_p(logs_mx);
     719      214552 :         log_cbk(user_log_cbk, call_lev, call_tool, fmt, vl);
     720      214552 :         gf_mx_v(logs_mx);
     721      214552 :         va_end(vl);
     722      214552 :         if (log_exit_on_error && (call_lev==GF_LOG_ERROR) && (call_tool != GF_LOG_MEMORY)) {
     723           0 :                 exit(1);
     724             :         }
     725      214552 : }
     726             : 
     727             : GF_EXPORT
     728           0 : void gf_log_va_list(GF_LOG_Level level, GF_LOG_Tool tool, const char *fmt, va_list vl)
     729             : {
     730           0 :         log_cbk(user_log_cbk, call_lev, call_tool, fmt, vl);
     731           0 :         if (log_exit_on_error && (call_lev==GF_LOG_ERROR) && (call_tool != GF_LOG_MEMORY)) {
     732           0 :                 exit(1);
     733             :         }
     734           0 : }
     735             : 
     736             : GF_EXPORT
     737         176 : Bool gf_log_set_strict_error(Bool strict)
     738             : {
     739         176 :         Bool old = log_exit_on_error;
     740         176 :         log_exit_on_error = strict;
     741         176 :         return old;
     742             : }
     743             : 
     744             : GF_EXPORT
     745       63731 : void gf_log_set_tool_level(GF_LOG_Tool tool, GF_LOG_Level level)
     746             : {
     747             :         assert(tool<=GF_LOG_TOOL_MAX);
     748       63731 :         if (tool==GF_LOG_ALL) {
     749             :                 u32 i;
     750      187530 :                 for (i=0; i<GF_LOG_TOOL_MAX; i++) {
     751      187530 :                         global_log_tools[i].level = level;
     752             :                 }
     753             :         } else {
     754       57480 :                 global_log_tools[tool].level = level;
     755             :         }
     756       63731 : }
     757             : 
     758             : GF_EXPORT
     759      214552 : void gf_log_lt(GF_LOG_Level ll, GF_LOG_Tool lt)
     760             : {
     761      214552 :         call_lev = ll;
     762      214552 :         call_tool = lt;
     763      214552 : }
     764             : 
     765             : GF_EXPORT
     766          15 : gf_log_cbk gf_log_set_callback(void *usr_cbk, gf_log_cbk cbk)
     767             : {
     768          15 :         gf_log_cbk prev_cbk = log_cbk;
     769          15 :         log_cbk = cbk;
     770          15 :         if (!log_cbk) log_cbk = default_log_callback;
     771          15 :         if (usr_cbk) user_log_cbk = usr_cbk;
     772          15 :         return prev_cbk;
     773             : }
     774             : 
     775             : #else
     776             : GF_EXPORT
     777             : void gf_log(const char *fmt, ...)
     778             : {
     779             : }
     780             : GF_EXPORT
     781             : void gf_log_lt(GF_LOG_Level ll, GF_LOG_Tool lt)
     782             : {
     783             : }
     784             : GF_EXPORT
     785             : Bool gf_log_set_strict_error(Bool strict)
     786             : {
     787             :         return GF_FALSE;
     788             : }
     789             : 
     790             : GF_EXPORT
     791             : gf_log_cbk gf_log_set_callback(void *usr_cbk, gf_log_cbk cbk)
     792             : {
     793             :         return NULL;
     794             : }
     795             : 
     796             : GF_EXPORT
     797             : void gf_log_set_tool_level(GF_LOG_Tool tool, GF_LOG_Level level)
     798             : {
     799             : }
     800             : 
     801             : GF_EXPORT
     802             : u32 gf_log_get_tool_level(GF_LOG_Tool log_tool)
     803             : {
     804             :         return 0;
     805             : }
     806             : 
     807             : GF_EXPORT
     808             : Bool gf_log_tool_level_on(GF_LOG_Tool log_tool, GF_LOG_Level log_level)
     809             : {
     810             :         return GF_FALSE;
     811             : }
     812             : 
     813             : #endif
     814             : 
     815             : static char szErrMsg[50];
     816             : 
     817             : GF_EXPORT
     818          65 : const char *gf_error_to_string(GF_Err e)
     819             : {
     820          65 :         switch (e) {
     821             :         case GF_EOS:
     822             :                 return "End Of Stream / File";
     823           0 :         case GF_OK:
     824           0 :                 return "No Error";
     825             : 
     826             :         /*General errors */
     827          14 :         case GF_BAD_PARAM:
     828          14 :                 return "Bad Parameter";
     829           0 :         case GF_OUT_OF_MEM:
     830           0 :                 return "Out Of Memory";
     831           5 :         case GF_IO_ERR:
     832           5 :                 return "I/O Error";
     833           2 :         case GF_NOT_SUPPORTED:
     834           2 :                 return "Feature Not Supported";
     835           2 :         case GF_CORRUPTED_DATA:
     836           2 :                 return "Corrupted Data in file/stream";
     837             : 
     838             :         /*File Format Errors */
     839           6 :         case GF_ISOM_INVALID_FILE:
     840           6 :                 return "Invalid IsoMedia File";
     841           0 :         case GF_ISOM_INCOMPLETE_FILE:
     842           0 :                 return "IsoMedia File is truncated";
     843           0 :         case GF_ISOM_INVALID_MEDIA:
     844           0 :                 return "Invalid IsoMedia Media";
     845           0 :         case GF_ISOM_INVALID_MODE:
     846           0 :                 return "Invalid Mode while accessing the file";
     847           0 :         case GF_ISOM_UNKNOWN_DATA_REF:
     848           0 :                 return "Media Data Reference not found";
     849             : 
     850             :         /*Object Descriptor Errors */
     851           0 :         case GF_ODF_INVALID_DESCRIPTOR:
     852           0 :                 return "Invalid MPEG-4 Descriptor";
     853           0 :         case GF_ODF_FORBIDDEN_DESCRIPTOR:
     854           0 :                 return "MPEG-4 Descriptor Not Allowed";
     855           0 :         case GF_ODF_INVALID_COMMAND:
     856           0 :                 return "Read OD Command Failed";
     857             : 
     858             :         /*BIFS Errors */
     859           0 :         case GF_SG_UNKNOWN_NODE:
     860           0 :                 return "Unknown BIFS Node";
     861           0 :         case GF_SG_INVALID_PROTO:
     862           0 :                 return "Invalid Proto Interface";
     863           0 :         case GF_BIFS_UNKNOWN_VERSION:
     864           0 :                 return "Invalid BIFS version";
     865           0 :         case GF_SCRIPT_ERROR:
     866           0 :                 return "Invalid Script";
     867             : 
     868           0 :         case GF_BUFFER_TOO_SMALL:
     869           0 :                 return "Bad Buffer size (too small)";
     870           0 :         case GF_NON_COMPLIANT_BITSTREAM:
     871           0 :                 return "BitStream Not Compliant";
     872           0 :         case GF_FILTER_NOT_FOUND:
     873           0 :                 return "Filter not found for the desired type";
     874             : 
     875          20 :         case GF_URL_ERROR:
     876          20 :                 return "Requested URL is not valid or cannot be found";
     877           0 :         case GF_URL_REMOVED:
     878           0 :                 return "Requested URL is no longer available";
     879             : 
     880           0 :         case GF_SERVICE_ERROR:
     881           0 :                 return "Internal Service Error";
     882           0 :         case GF_REMOTE_SERVICE_ERROR:
     883           0 :                 return "Dialog Failure with remote peer";
     884             : 
     885           0 :         case GF_STREAM_NOT_FOUND:
     886           0 :                 return "Media Channel couldn't be found";
     887             : 
     888           0 :         case GF_IP_ADDRESS_NOT_FOUND:
     889           0 :                 return "IP Address Not Found";
     890           0 :         case GF_IP_CONNECTION_FAILURE:
     891           0 :                 return "IP Connection Failed";
     892           0 :         case GF_IP_NETWORK_FAILURE:
     893           0 :                 return "Network Unreachable";
     894             : 
     895           3 :         case GF_IP_NETWORK_EMPTY:
     896           3 :                 return "Network Timeout";
     897           0 :         case GF_IP_SOCK_WOULD_BLOCK:
     898           0 :                 return "Socket Would Block";
     899           5 :         case GF_IP_CONNECTION_CLOSED:
     900           5 :                 return "Connection to server closed";
     901           0 :         case GF_IP_UDP_TIMEOUT:
     902           0 :                 return "UDP traffic timeout";
     903           0 :         case GF_AUTHENTICATION_FAILURE:
     904           0 :                 return "Authentication failure";
     905           0 :         case GF_SCRIPT_NOT_READY:
     906           0 :                 return "Script not ready for playback";
     907           0 :         case GF_INVALID_CONFIGURATION:
     908           0 :                 return "Bad configuration for the current context";
     909           8 :         case GF_NOT_FOUND:
     910           8 :                 return "At least one required element has not been found";
     911           0 :         case GF_PROFILE_NOT_SUPPORTED:
     912           0 :                 return "Unsupported codec profile";
     913           0 :         case GF_REQUIRES_NEW_INSTANCE:
     914           0 :                 return "Requires a new instance of the filter to be supported";
     915           0 :         case GF_FILTER_NOT_SUPPORTED:
     916           0 :                 return "Not supported by any filter chain";
     917             :         default:
     918             :                 sprintf(szErrMsg, "Unknown Error (%d)", e);
     919           0 :                 return szErrMsg;
     920             :         }
     921             : }
     922             : 
     923             : static const u32 gf_crc_table[256] = {
     924             :         0x00000000, 0x04c11db7, 0x09823b6e, 0x0d4326d9, 0x130476dc, 0x17c56b6b,
     925             :         0x1a864db2, 0x1e475005, 0x2608edb8, 0x22c9f00f, 0x2f8ad6d6, 0x2b4bcb61,
     926             :         0x350c9b64, 0x31cd86d3, 0x3c8ea00a, 0x384fbdbd, 0x4c11db70, 0x48d0c6c7,
     927             :         0x4593e01e, 0x4152fda9, 0x5f15adac, 0x5bd4b01b, 0x569796c2, 0x52568b75,
     928             :         0x6a1936c8, 0x6ed82b7f, 0x639b0da6, 0x675a1011, 0x791d4014, 0x7ddc5da3,
     929             :         0x709f7b7a, 0x745e66cd, 0x9823b6e0, 0x9ce2ab57, 0x91a18d8e, 0x95609039,
     930             :         0x8b27c03c, 0x8fe6dd8b, 0x82a5fb52, 0x8664e6e5, 0xbe2b5b58, 0xbaea46ef,
     931             :         0xb7a96036, 0xb3687d81, 0xad2f2d84, 0xa9ee3033, 0xa4ad16ea, 0xa06c0b5d,
     932             :         0xd4326d90, 0xd0f37027, 0xddb056fe, 0xd9714b49, 0xc7361b4c, 0xc3f706fb,
     933             :         0xceb42022, 0xca753d95, 0xf23a8028, 0xf6fb9d9f, 0xfbb8bb46, 0xff79a6f1,
     934             :         0xe13ef6f4, 0xe5ffeb43, 0xe8bccd9a, 0xec7dd02d, 0x34867077, 0x30476dc0,
     935             :         0x3d044b19, 0x39c556ae, 0x278206ab, 0x23431b1c, 0x2e003dc5, 0x2ac12072,
     936             :         0x128e9dcf, 0x164f8078, 0x1b0ca6a1, 0x1fcdbb16, 0x018aeb13, 0x054bf6a4,
     937             :         0x0808d07d, 0x0cc9cdca, 0x7897ab07, 0x7c56b6b0, 0x71159069, 0x75d48dde,
     938             :         0x6b93dddb, 0x6f52c06c, 0x6211e6b5, 0x66d0fb02, 0x5e9f46bf, 0x5a5e5b08,
     939             :         0x571d7dd1, 0x53dc6066, 0x4d9b3063, 0x495a2dd4, 0x44190b0d, 0x40d816ba,
     940             :         0xaca5c697, 0xa864db20, 0xa527fdf9, 0xa1e6e04e, 0xbfa1b04b, 0xbb60adfc,
     941             :         0xb6238b25, 0xb2e29692, 0x8aad2b2f, 0x8e6c3698, 0x832f1041, 0x87ee0df6,
     942             :         0x99a95df3, 0x9d684044, 0x902b669d, 0x94ea7b2a, 0xe0b41de7, 0xe4750050,
     943             :         0xe9362689, 0xedf73b3e, 0xf3b06b3b, 0xf771768c, 0xfa325055, 0xfef34de2,
     944             :         0xc6bcf05f, 0xc27dede8, 0xcf3ecb31, 0xcbffd686, 0xd5b88683, 0xd1799b34,
     945             :         0xdc3abded, 0xd8fba05a, 0x690ce0ee, 0x6dcdfd59, 0x608edb80, 0x644fc637,
     946             :         0x7a089632, 0x7ec98b85, 0x738aad5c, 0x774bb0eb, 0x4f040d56, 0x4bc510e1,
     947             :         0x46863638, 0x42472b8f, 0x5c007b8a, 0x58c1663d, 0x558240e4, 0x51435d53,
     948             :         0x251d3b9e, 0x21dc2629, 0x2c9f00f0, 0x285e1d47, 0x36194d42, 0x32d850f5,
     949             :         0x3f9b762c, 0x3b5a6b9b, 0x0315d626, 0x07d4cb91, 0x0a97ed48, 0x0e56f0ff,
     950             :         0x1011a0fa, 0x14d0bd4d, 0x19939b94, 0x1d528623, 0xf12f560e, 0xf5ee4bb9,
     951             :         0xf8ad6d60, 0xfc6c70d7, 0xe22b20d2, 0xe6ea3d65, 0xeba91bbc, 0xef68060b,
     952             :         0xd727bbb6, 0xd3e6a601, 0xdea580d8, 0xda649d6f, 0xc423cd6a, 0xc0e2d0dd,
     953             :         0xcda1f604, 0xc960ebb3, 0xbd3e8d7e, 0xb9ff90c9, 0xb4bcb610, 0xb07daba7,
     954             :         0xae3afba2, 0xaafbe615, 0xa7b8c0cc, 0xa379dd7b, 0x9b3660c6, 0x9ff77d71,
     955             :         0x92b45ba8, 0x9675461f, 0x8832161a, 0x8cf30bad, 0x81b02d74, 0x857130c3,
     956             :         0x5d8a9099, 0x594b8d2e, 0x5408abf7, 0x50c9b640, 0x4e8ee645, 0x4a4ffbf2,
     957             :         0x470cdd2b, 0x43cdc09c, 0x7b827d21, 0x7f436096, 0x7200464f, 0x76c15bf8,
     958             :         0x68860bfd, 0x6c47164a, 0x61043093, 0x65c52d24, 0x119b4be9, 0x155a565e,
     959             :         0x18197087, 0x1cd86d30, 0x029f3d35, 0x065e2082, 0x0b1d065b, 0x0fdc1bec,
     960             :         0x3793a651, 0x3352bbe6, 0x3e119d3f, 0x3ad08088, 0x2497d08d, 0x2056cd3a,
     961             :         0x2d15ebe3, 0x29d4f654, 0xc5a92679, 0xc1683bce, 0xcc2b1d17, 0xc8ea00a0,
     962             :         0xd6ad50a5, 0xd26c4d12, 0xdf2f6bcb, 0xdbee767c, 0xe3a1cbc1, 0xe760d676,
     963             :         0xea23f0af, 0xeee2ed18, 0xf0a5bd1d, 0xf464a0aa, 0xf9278673, 0xfde69bc4,
     964             :         0x89b8fd09, 0x8d79e0be, 0x803ac667, 0x84fbdbd0, 0x9abc8bd5, 0x9e7d9662,
     965             :         0x933eb0bb, 0x97ffad0c, 0xafb010b1, 0xab710d06, 0xa6322bdf, 0xa2f33668,
     966             :         0xbcb4666d, 0xb8757bda, 0xb5365d03, 0xb1f740b4
     967             : };
     968             : 
     969             : GF_EXPORT
     970      209657 : u32 gf_crc_32(const u8 *data, u32 len)
     971             : {
     972             :         register u32 i;
     973             :         u32 crc = 0xffffffff;
     974      209657 :         if (!data) return 0;
     975   646518064 :         for (i=0; i<len; i++)
     976   646518064 :                 crc = (crc << 8) ^ gf_crc_table[((crc >> 24) ^ *data++) & 0xff];
     977             : 
     978             :         return crc;
     979             : }
     980             : 
     981             : 
     982             : #define CHECK_MAC(_a) "#_a :" ? (_a) ? "yes":"no"
     983             : 
     984             : static const char *gf_enabled_features()
     985             : {
     986             :         const char *features = ""
     987             : #ifdef GPAC_CONFIG_WIN32
     988             :                                "GPAC_CONFIG_WIN32 "
     989             : #endif
     990             : #ifdef GPAC_CONFIG_DARWIN
     991             :                                "GPAC_CONFIG_DARWIN "
     992             : #endif
     993             : #ifdef GPAC_CONFIG_LINUX
     994             :                                "GPAC_CONFIG_LINUX "
     995             : #endif
     996             : #ifdef GPAC_CONFIG_ANDROID
     997             :                                "GPAC_CONFIG_ANDROID "
     998             : #endif
     999             : #ifdef GPAC_CONFIG_IOS
    1000             :                                "GPAC_CONFIG_IOS "
    1001             : #endif
    1002             : #ifdef GPAC_64_BITS
    1003             :                                "GPAC_64_BITS "
    1004             : #endif
    1005             : #ifdef GPAC_FIXED_POINT
    1006             :                                "GPAC_FIXED_POINT "
    1007             : #endif
    1008             : #ifdef GPAC_MEMORY_TRACKING
    1009             :                                "GPAC_MEMORY_TRACKING "
    1010             : #endif
    1011             : #ifdef GPAC_BIG_ENDIAN
    1012             :                                "GPAC_BIG_ENDIAN "
    1013             : #endif
    1014             : #ifdef GPAC_HAS_IPV6
    1015             :                                "GPAC_HAS_IPV6 "
    1016             : #endif
    1017             : #ifdef GPAC_HAS_SSL
    1018             :                                "GPAC_HAS_SSL "
    1019             : #endif
    1020             : #ifdef GPAC_HAS_SOCK_UN
    1021             :                                "GPAC_HAS_SOCK_UN "
    1022             : #endif
    1023             : #ifdef GPAC_ENABLE_COVERAGE
    1024             :                                "GPAC_ENABLE_COVERAGE "
    1025             : #endif
    1026             : #ifdef GPAC_MINIMAL_ODF
    1027             :                                "GPAC_MINIMAL_ODF "
    1028             : #endif
    1029             : #ifdef GPAC_HAS_QJS
    1030             :                                "GPAC_HAS_QJS "
    1031             : #endif
    1032             : #ifdef GPAC_HAS_FREETYPE
    1033             :                                "GPAC_HAS_FREETYPE "
    1034             : #endif
    1035             : #ifdef GPAC_HAS_FAAD
    1036             :                                "GPAC_HAS_FAAD "
    1037             : #endif
    1038             : #ifdef GPAC_HAS_MAD
    1039             :                                "GPAC_HAS_MAD "
    1040             : #endif
    1041             : #ifdef GPAC_HAS_LIBA52
    1042             :                                "GPAC_HAS_LIBA52 "
    1043             : #endif
    1044             : #ifdef GPAC_HAS_JPEG
    1045             :                                "GPAC_HAS_JPEG "
    1046             : #endif
    1047             : #ifdef GPAC_HAS_PNG
    1048             :                                "GPAC_HAS_PNG "
    1049             : #endif
    1050             : #ifdef GPAC_HAS_FFMPEG
    1051             :                                "GPAC_HAS_FFMPEG "
    1052             : #endif
    1053             : #ifdef GPAC_HAS_OPENSVC
    1054             :                                "GPAC_HAS_OPENSVC "
    1055             : #endif
    1056             : #ifdef GPAC_HAS_JP2
    1057             :                                "GPAC_HAS_JP2 "
    1058             : #endif
    1059             : #ifdef GPAC_HAS_OPENHEVC
    1060             :                                "GPAC_HAS_OPENHEVC "
    1061             : #endif
    1062             : #ifdef GPAC_HAS_THEORA
    1063             :                                "GPAC_HAS_THEORA "
    1064             : #endif
    1065             : #ifdef GPAC_HAS_VORBIS
    1066             :                                "GPAC_HAS_VORBIS "
    1067             : #endif
    1068             : #ifdef GPAC_HAS_XVID
    1069             :                                "GPAC_HAS_XVID "
    1070             : #endif
    1071             : #ifdef GPAC_HAS_LINUX_DVB
    1072             :                                "GPAC_HAS_LINUX_DVB "
    1073             : #endif
    1074             : #ifdef GPAC_HAS_GLU
    1075             :                                "GPAC_HAS_GLU "
    1076             : #endif
    1077             : 
    1078             : #if defined(_WIN32_WCE)
    1079             : #ifdef GPAC_USE_IGPP
    1080             :                                "GPAC_USE_IGPP "
    1081             : #endif
    1082             : #ifdef GPAC_USE_IGPP_HP
    1083             :                                "GPAC_USE_IGPP_HP "
    1084             : #endif
    1085             : #endif
    1086             :                                ;
    1087             :         return features;
    1088             : }
    1089             : 
    1090             : static const char *gf_disabled_features()
    1091             : {
    1092             :         const char *features = ""
    1093             : #ifdef GPAC_DISABLE_3D
    1094             :                                "GPAC_DISABLE_3D "
    1095             : #endif
    1096             : #ifdef GPAC_USE_TINYGL
    1097             :                                "GPAC_USE_TINYGL "
    1098             : #endif
    1099             : #ifdef GPAC_USE_GLES1X
    1100             :                                "GPAC_USE_GLES1X "
    1101             : #endif
    1102             : #ifdef GPAC_USE_GLES2
    1103             :                                "GPAC_USE_GLES2 "
    1104             : #endif
    1105             : #ifdef GPAC_DISABLE_ZLIB
    1106             :                                "GPAC_DISABLE_ZLIB "
    1107             : #endif
    1108             : #ifdef GPAC_DISABLE_SVG
    1109             :                                "GPAC_DISABLE_SVG "
    1110             : #endif
    1111             : #ifdef GPAC_DISABLE_VRML
    1112             :                                "GPAC_DISABLE_VRML "
    1113             : #endif
    1114             : #ifdef GPAC_DISABLE_BIFS
    1115             :                                "GPAC_DISABLE_BIFS "
    1116             : #endif
    1117             : #ifdef GPAC_DISABLE_QTVR
    1118             :                                "GPAC_DISABLE_QTVR "
    1119             : #endif
    1120             : #ifdef GPAC_DISABLE_AVILIB
    1121             :                                "GPAC_DISABLE_AVILIB "
    1122             : #endif
    1123             : #ifdef GPAC_DISABLE_OGG
    1124             :                                "GPAC_DISABLE_OGG "
    1125             : #endif
    1126             : #ifdef GPAC_DISABLE_MPEG2PS
    1127             :                                "GPAC_DISABLE_MPEG2PS "
    1128             : #endif
    1129             : #ifdef GPAC_DISABLE_MPEG2PS
    1130             :                                "GPAC_DISABLE_MPEG2TS "
    1131             : #endif
    1132             : #ifdef GPAC_DISABLE_SENG
    1133             :                                "GPAC_DISABLE_SENG "
    1134             : #endif
    1135             : #ifdef GPAC_DISABLE_MEDIA_IMPORT
    1136             :                                "GPAC_DISABLE_MEDIA_IMPORT "
    1137             : #endif
    1138             : #ifdef GPAC_DISABLE_AV_PARSERS
    1139             :                                "GPAC_DISABLE_AV_PARSERS "
    1140             : #endif
    1141             : #ifdef GPAC_DISABLE_MEDIA_EXPORT
    1142             :                                "GPAC_DISABLE_MEDIA_EXPORT "
    1143             : #endif
    1144             : #ifdef GPAC_DISABLE_SWF_IMPORT
    1145             :                                "GPAC_DISABLE_SWF_IMPORT "
    1146             : #endif
    1147             : #ifdef GPAC_DISABLE_SCENE_STATS
    1148             :                                "GPAC_DISABLE_SCENE_STATS "
    1149             : #endif
    1150             : #ifdef GPAC_DISABLE_SCENE_DUMP
    1151             :                                "GPAC_DISABLE_SCENE_DUMP "
    1152             : #endif
    1153             : #ifdef GPAC_DISABLE_SCENE_ENCODER
    1154             :                                "GPAC_DISABLE_SCENE_ENCODER "
    1155             : #endif
    1156             : #ifdef GPAC_DISABLE_LOADER_ISOM
    1157             :                                "GPAC_DISABLE_LOADER_ISOM "
    1158             : #endif
    1159             : #ifdef GPAC_DISABLE_OD_DUMP
    1160             :                                "GPAC_DISABLE_OD_DUMP "
    1161             : #endif
    1162             : #ifdef GPAC_DISABLE_CRYPTO
    1163             :                                "GPAC_DISABLE_CRYPTO "
    1164             : #endif
    1165             : #ifdef GPAC_DISABLE_ISOM
    1166             :                                "GPAC_DISABLE_CRYPTO "
    1167             : #endif
    1168             : #ifdef GPAC_DISABLE_ISOM_HINTING
    1169             :                                "GPAC_DISABLE_ISOM_HINTING "
    1170             : #endif
    1171             : #ifdef GPAC_DISABLE_ISOM_WRITE
    1172             :                                "GPAC_DISABLE_ISOM_WRITE "
    1173             : #endif
    1174             : #ifdef GPAC_DISABLE_ISOM_FRAGMENTS
    1175             :                                "GPAC_DISABLE_ISOM_FRAGMENTS "
    1176             : #endif
    1177             : #ifdef GPAC_DISABLE_LASER
    1178             :                                "GPAC_DISABLE_LASER "
    1179             : #endif
    1180             : #ifdef GPAC_DISABLE_STREAMING
    1181             :                                "GPAC_DISABLE_STREAMING "
    1182             : #endif
    1183             : #ifdef GPAC_DISABLE_ROUTE
    1184             :                                "GPAC_DISABLE_ROUTE "
    1185             : #endif
    1186             : 
    1187             :                                ;
    1188             :         return features;
    1189             : }
    1190             : 
    1191             : GF_EXPORT
    1192          26 : const char *gf_sys_features(Bool disabled)
    1193             : {
    1194          26 :         if (disabled)
    1195             :                 return gf_disabled_features();
    1196             :         else
    1197          13 :                 return gf_enabled_features();
    1198             : }
    1199             : 
    1200             : static const struct lang_def {
    1201             :         const char *name;
    1202             :         const char *three_char_code;
    1203             :         const char *two_char_code;
    1204             : } defined_languages [] =
    1205             : {
    1206             :         { "Abkhazian","abk","ab"} ,
    1207             :         { "Achinese","ace",""} ,
    1208             :         { "Acoli","ach",""} ,
    1209             :         { "Adangme","ada",""} ,
    1210             :         { "Adyghe; Adygei","ady",""} ,
    1211             :         { "Afar","aar","aa"} ,
    1212             :         { "Afrihili","afh",""} ,
    1213             :         { "Afrikaans","afr","af"} ,
    1214             :         { "Afro-Asiatic languages","afa",""} ,
    1215             :         { "Ainu","ain",""} ,
    1216             :         { "Akan","aka","ak"} ,
    1217             :         { "Akkadian","akk",""} ,
    1218             :         { "Albanian","sqi","sq"} ,
    1219             :         { "Aleut","ale",""} ,
    1220             :         { "Algonquian languages","alg",""} ,
    1221             :         { "Altaic languages","tut",""} ,
    1222             :         { "Amharic","amh","am"} ,
    1223             :         { "Angika","anp",""} ,
    1224             :         { "Apache languages","apa",""} ,
    1225             :         { "Arabic","ara","ar"} ,
    1226             :         { "Aragonese","arg","an"} ,
    1227             :         { "Arapaho","arp",""} ,
    1228             :         { "Arawak","arw",""} ,
    1229             :         { "Armenian","hye","hy"} ,
    1230             :         { "Aromanian; Arumanian; Macedo-Romanian","rup",""} ,
    1231             :         { "Artificial languages","art",""} ,
    1232             :         { "Assamese","asm","as"} ,
    1233             :         { "Asturian; Bable; Leonese; Asturleonese","ast",""} ,
    1234             :         { "Athapascan languages","ath",""} ,
    1235             :         { "Australian languages","aus",""} ,
    1236             :         { "Austronesian languages","map",""} ,
    1237             :         { "Avaric","ava","av"} ,
    1238             :         { "Avestan","ave","ae"} ,
    1239             :         { "Awadhi","awa",""} ,
    1240             :         { "Aymara","aym","ay"} ,
    1241             :         { "Azerbaijani","aze","az"} ,
    1242             :         { "Balinese","ban",""} ,
    1243             :         { "Baltic languages","bat",""} ,
    1244             :         { "Baluchi","bal",""} ,
    1245             :         { "Bambara","bam","bm"} ,
    1246             :         { "Bamileke languages","bai",""} ,
    1247             :         { "Banda languages","bad",""} ,
    1248             :         { "Bantu languages","bnt",""} ,
    1249             :         { "Basa","bas",""} ,
    1250             :         { "Bashkir","bak","ba"} ,
    1251             :         { "Basque","eus","eu"} ,
    1252             :         { "Batak languages","btk",""} ,
    1253             :         { "Beja; Bedawiyet","bej",""} ,
    1254             :         { "Belarusian","bel","be"} ,
    1255             :         { "Bemba","bem",""} ,
    1256             :         { "Bengali","ben","bn"} ,
    1257             :         { "Berber languages","ber",""} ,
    1258             :         { "Bhojpuri","bho",""} ,
    1259             :         { "Bihari languages","bih","bh"} ,
    1260             :         { "Bikol","bik",""} ,
    1261             :         { "Bini; Edo","bin",""} ,
    1262             :         { "Bislama","bis","bi"} ,
    1263             :         { "Blin; Bilin","byn",""} ,
    1264             :         { "Blissymbols; Blissymbolics; Bliss","zbl",""} ,
    1265             :         { "Bokmal, Norwegian; Norwegian Bokmal","nob","nb"} ,
    1266             :         { "Bosnian","bos","bs"} ,
    1267             :         { "Braj","bra",""} ,
    1268             :         { "Breton","bre","br"} ,
    1269             :         { "Buginese","bug",""} ,
    1270             :         { "Bulgarian","bul","bg"} ,
    1271             :         { "Buriat","bua",""} ,
    1272             :         { "Burmese","mya","my"} ,
    1273             :         { "Caddo","cad",""} ,
    1274             :         { "Catalan; Valencian","cat","ca"} ,
    1275             :         { "Caucasian languages","cau",""} ,
    1276             :         { "Cebuano","ceb",""} ,
    1277             :         { "Celtic languages","cel",""} ,
    1278             :         { "Central American Indian languages","cai",""} ,
    1279             :         { "Central Khmer","khm","km"} ,
    1280             :         { "Chagatai","chg",""} ,
    1281             :         { "Chamic languages","cmc",""} ,
    1282             :         { "Chamorro","cha","ch"} ,
    1283             :         { "Chechen","che","ce"} ,
    1284             :         { "Cherokee","chr",""} ,
    1285             :         { "Cheyenne","chy",""} ,
    1286             :         { "Chibcha","chb",""} ,
    1287             :         { "Chichewa; Chewa; Nyanja","nya","ny"} ,
    1288             :         { "Chinese","zho","zh"} ,
    1289             :         { "Chinook jargon","chn",""} ,
    1290             :         { "Chipewyan; Dene Suline","chp",""} ,
    1291             :         { "Choctaw","cho",""} ,
    1292             :         { "Church Slavic; Old Slavonic; Church Slavonic; Old Bulgarian; Old Church}  S{ lavonic","chu","cu"} ,
    1293             :         { "Chuukese","chk",""} ,
    1294             :         { "Chuvash","chv","cv"} ,
    1295             :         { "Classical Newari; Old Newari; Classical Nepal Bhasa","nwc",""} ,
    1296             :         { "Classical Syriac","syc",""} ,
    1297             :         { "Coptic","cop",""} ,
    1298             :         { "Cornish","cor","kw"} ,
    1299             :         { "Corsican","cos","co"} ,
    1300             :         { "Cree","cre","cr"} ,
    1301             :         { "Creek","mus",""} ,
    1302             :         { "Creoles and pidgins","crp",""} ,
    1303             :         { "Creoles and pidgins, English based","cpe",""} ,
    1304             :         { "Creoles and pidgins, French-based","cpf",""} ,
    1305             :         { "Creoles and pidgins, Portuguese-based","cpp",""} ,
    1306             :         { "Crimean Tatar; Crimean Turkish","crh",""} ,
    1307             :         { "Croatian","hrv","hr"} ,
    1308             :         { "Cushitic languages","cus",""} ,
    1309             :         { "Czech","ces","cs"} ,
    1310             :         { "Dakota","dak",""} ,
    1311             :         { "Danish","dan","da"} ,
    1312             :         { "Dargwa","dar",""} ,
    1313             :         { "Delaware","del",""} ,
    1314             :         { "Dinka","din",""} ,
    1315             :         { "Divehi; Dhivehi; Maldivian","div","dv"} ,
    1316             :         { "Dogri","doi",""} ,
    1317             :         { "Dogrib","dgr",""} ,
    1318             :         { "Dravidian languages","dra",""} ,
    1319             :         { "Duala","dua",""} ,
    1320             :         { "Dutch, Middle (ca.1050-1350)","dum",""} ,
    1321             :         { "Dutch; Flemish","nld","nl"} ,
    1322             :         { "Dyula","dyu",""} ,
    1323             :         { "Dzongkha","dzo","dz"} ,
    1324             :         { "Eastern Frisian","frs",""} ,
    1325             :         { "Efik","efi",""} ,
    1326             :         { "Egyptian (Ancient)","egy",""} ,
    1327             :         { "Ekajuk","eka",""} ,
    1328             :         { "Elamite","elx",""} ,
    1329             :         { "English","eng","en"} ,
    1330             :         { "English, Middle (1100-1500)","enm",""} ,
    1331             :         { "English, Old (ca.450-1100)","ang",""} ,
    1332             :         { "Erzya","myv",""} ,
    1333             :         { "Esperanto","epo","eo"} ,
    1334             :         { "Estonian","est","et"} ,
    1335             :         { "Ewe","ewe","ee"} ,
    1336             :         { "Ewondo","ewo",""} ,
    1337             :         { "Fang","fan",""} ,
    1338             :         { "Fanti","fat",""} ,
    1339             :         { "Faroese","fao","fo"} ,
    1340             :         { "Fijian","fij","fj"} ,
    1341             :         { "Filipino; Pilipino","fil",""} ,
    1342             :         { "Finnish","fin","fi"} ,
    1343             :         { "Finno-Ugrian languages","fiu",""} ,
    1344             :         { "Fon","fon",""} ,
    1345             :         { "French","fra","fr"} ,
    1346             :         { "French, Middle (ca.1400-1600)","frm",""} ,
    1347             :         { "French, Old (842-ca.1400)","fro",""} ,
    1348             :         { "Friulian","fur",""} ,
    1349             :         { "Fulah","ful","ff"} ,
    1350             :         { "Ga","gaa",""} ,
    1351             :         { "Gaelic; Scottish Gaelic","gla","gd"} ,
    1352             :         { "Galibi Carib","car",""} ,
    1353             :         { "Galician","glg","gl"} ,
    1354             :         { "Ganda","lug","lg"} ,
    1355             :         { "Gayo","gay",""} ,
    1356             :         { "Gbaya","gba",""} ,
    1357             :         { "Geez","gez",""} ,
    1358             :         { "Georgian","kat","ka"} ,
    1359             :         { "German","deu","de"} ,
    1360             :         { "German, Middle High (ca.1050-1500)","gmh",""} ,
    1361             :         { "German, Old High (ca.750-1050)","goh",""} ,
    1362             :         { "Germanic languages","gem",""} ,
    1363             :         { "Gilbertese","gil",""} ,
    1364             :         { "Gondi","gon",""} ,
    1365             :         { "Gorontalo","gor",""} ,
    1366             :         { "Gothic","got",""} ,
    1367             :         { "Grebo","grb",""} ,
    1368             :         { "Greek, Ancient (to 1453)","grc",""} ,
    1369             :         { "Greek, Modern (1453-)","ell","el"} ,
    1370             :         { "Guarani","grn","gn"} ,
    1371             :         { "Gujarati","guj","gu"} ,
    1372             :         { "Gwich'in","gwi",""} ,
    1373             :         { "Haida","hai",""} ,
    1374             :         { "Haitian; Haitian Creole","hat","ht"} ,
    1375             :         { "Hausa","hau","ha"} ,
    1376             :         { "Hawaiian","haw",""} ,
    1377             :         { "Hebrew","heb","he"} ,
    1378             :         { "Herero","her","hz"} ,
    1379             :         { "Hiligaynon","hil",""} ,
    1380             :         { "Himachali languages; Western Pahari languages","him",""} ,
    1381             :         { "Hindi","hin","hi"} ,
    1382             :         { "Hiri Motu","hmo","ho"} ,
    1383             :         { "Hittite","hit",""} ,
    1384             :         { "Hmong; Mong","hmn",""} ,
    1385             :         { "Hungarian","hun","hu"} ,
    1386             :         { "Hupa","hup",""} ,
    1387             :         { "Iban","iba",""} ,
    1388             :         { "Icelandic","isl","is"} ,
    1389             :         { "Ido","ido","io"} ,
    1390             :         { "Igbo","ibo","ig"} ,
    1391             :         { "Ijo languages","ijo",""} ,
    1392             :         { "Iloko","ilo",""} ,
    1393             :         { "Inari Sami","smn",""} ,
    1394             :         { "Indic languages","inc",""} ,
    1395             :         { "Indo-European languages","ine",""} ,
    1396             :         { "Indonesian","ind","id"} ,
    1397             :         { "Ingush","inh",""} ,
    1398             :         { "Interlingua (International Auxiliary Language Association)","ina","ia"} ,
    1399             :         { "Interlingue; Occidental","ile","ie"} ,
    1400             :         { "Inuktitut","iku","iu"} ,
    1401             :         { "Inupiaq","ipk","ik"} ,
    1402             :         { "Iranian languages","ira",""} ,
    1403             :         { "Irish","gle","ga"} ,
    1404             :         { "Irish, Middle (900-1200)","mga",""} ,
    1405             :         { "Irish, Old (to 900)","sga",""} ,
    1406             :         { "Iroquoian languages","iro",""} ,
    1407             :         { "Italian","ita","it"} ,
    1408             :         { "Japanese","jpn","ja"} ,
    1409             :         { "Javanese","jav","jv"} ,
    1410             :         { "Judeo-Arabic","jrb",""} ,
    1411             :         { "Judeo-Persian","jpr",""} ,
    1412             :         { "Kabardian","kbd",""} ,
    1413             :         { "Kabyle","kab",""} ,
    1414             :         { "Kachin; Jingpho","kac",""} ,
    1415             :         { "Kalaallisut; Greenlandic","kal","kl"} ,
    1416             :         { "Kalmyk; Oirat","xal",""} ,
    1417             :         { "Kamba","kam",""} ,
    1418             :         { "Kannada","kan","kn"} ,
    1419             :         { "Kanuri","kau","kr"} ,
    1420             :         { "Kara-Kalpak","kaa",""} ,
    1421             :         { "Karachay-Balkar","krc",""} ,
    1422             :         { "Karelian","krl",""} ,
    1423             :         { "Karen languages","kar",""} ,
    1424             :         { "Kashmiri","kas","ks"} ,
    1425             :         { "Kashubian","csb",""} ,
    1426             :         { "Kawi","kaw",""} ,
    1427             :         { "Kazakh","kaz","kk"} ,
    1428             :         { "Khasi","kha",""} ,
    1429             :         { "Khoisan languages","khi",""} ,
    1430             :         { "Khotanese; Sakan","kho",""} ,
    1431             :         { "Kikuyu; Gikuyu","kik","ki"} ,
    1432             :         { "Kimbundu","kmb",""} ,
    1433             :         { "Kinyarwanda","kin","rw"} ,
    1434             :         { "Kirghiz; Kyrgyz","kir","ky"} ,
    1435             :         { "Klingon; tlhIngan-Hol","tlh",""} ,
    1436             :         { "Komi","kom","kv"} ,
    1437             :         { "Kongo","kon","kg"} ,
    1438             :         { "Konkani","kok",""} ,
    1439             :         { "Korean","kor","ko"} ,
    1440             :         { "Kosraean","kos",""} ,
    1441             :         { "Kpelle","kpe",""} ,
    1442             :         { "Kru languages","kro",""} ,
    1443             :         { "Kuanyama; Kwanyama","kua","kj"} ,
    1444             :         { "Kumyk","kum",""} ,
    1445             :         { "Kurdish","kur","ku"} ,
    1446             :         { "Kurukh","kru",""} ,
    1447             :         { "Kutenai","kut",""} ,
    1448             :         { "Ladino","lad",""} ,
    1449             :         { "Lahnda","lah",""} ,
    1450             :         { "Lamba","lam",""} ,
    1451             :         { "Land Dayak languages","day",""} ,
    1452             :         { "Lao","lao","lo"} ,
    1453             :         { "Latin","lat","la"} ,
    1454             :         { "Latvian","lav","lv"} ,
    1455             :         { "Lezghian","lez",""} ,
    1456             :         { "Limburgan; Limburger; Limburgish","lim","li"} ,
    1457             :         { "Lingala","lin","ln"} ,
    1458             :         { "Lithuanian","lit","lt"} ,
    1459             :         { "Lojban","jbo",""} ,
    1460             :         { "Low German; Low Saxon; German, Low; Saxon, Low","nds",""} ,
    1461             :         { "Lower Sorbian","dsb",""} ,
    1462             :         { "Lozi","loz",""} ,
    1463             :         { "Luba-Katanga","lub","lu"} ,
    1464             :         { "Luba-Lulua","lua",""} ,
    1465             :         { "Luiseno","lui",""} ,
    1466             :         { "Lule Sami","smj",""} ,
    1467             :         { "Lunda","lun",""} ,
    1468             :         { "Luo (Kenya and Tanzania)","luo",""} ,
    1469             :         { "Lushai","lus",""} ,
    1470             :         { "Luxembourgish; Letzeburgesch","ltz","lb"} ,
    1471             :         { "Macedonian","mkd","mk"} ,
    1472             :         { "Madurese","mad",""} ,
    1473             :         { "Magahi","mag",""} ,
    1474             :         { "Maithili","mai",""} ,
    1475             :         { "Makasar","mak",""} ,
    1476             :         { "Malagasy","mlg","mg"} ,
    1477             :         { "Malay","msa","ms"} ,
    1478             :         { "Malayalam","mal","ml"} ,
    1479             :         { "Maltese","mlt","mt"} ,
    1480             :         { "Manchu","mnc",""} ,
    1481             :         { "Mandar","mdr",""} ,
    1482             :         { "Mandingo","man",""} ,
    1483             :         { "Manipuri","mni",""} ,
    1484             :         { "Manobo languages","mno",""} ,
    1485             :         { "Manx","glv","gv"} ,
    1486             :         { "Maori","mri","mi"} ,
    1487             :         { "Mapudungun; Mapuche","arn",""} ,
    1488             :         { "Marathi","mar","mr"} ,
    1489             :         { "Mari","chm",""} ,
    1490             :         { "Marshallese","mah","mh"} ,
    1491             :         { "Marwari","mwr",""} ,
    1492             :         { "Masai","mas",""} ,
    1493             :         { "Mayan languages","myn",""} ,
    1494             :         { "Mende","men",""} ,
    1495             :         { "Mi'kmaq; Micmac","mic",""} ,
    1496             :         { "Minangkabau","min",""} ,
    1497             :         { "Mirandese","mwl",""} ,
    1498             :         { "Mohawk","moh",""} ,
    1499             :         { "Moksha","mdf",""} ,
    1500             :         { "Mon-Khmer languages","mkh",""} ,
    1501             :         { "Mongo","lol",""} ,
    1502             :         { "Mongolian","mon","mn"} ,
    1503             :         { "Mossi","mos",""} ,
    1504             :         { "Multiple languages","mul",""} ,
    1505             :         { "Munda languages","mun",""} ,
    1506             :         { "N'Ko","nqo",""} ,
    1507             :         { "Nahuatl languages","nah",""} ,
    1508             :         { "Nauru","nau","na"} ,
    1509             :         { "Navajo; Navaho","nav","nv"} ,
    1510             :         { "Ndebele, North; North Ndebele","nde","nd"} ,
    1511             :         { "Ndebele, South; South Ndebele","nbl","nr"} ,
    1512             :         { "Ndonga","ndo","ng"} ,
    1513             :         { "Neapolitan","nap",""} ,
    1514             :         { "Nepal Bhasa; Newari","new",""} ,
    1515             :         { "Nepali","nep","ne"} ,
    1516             :         { "Nias","nia",""} ,
    1517             :         { "Niger-Kordofanian languages","nic",""} ,
    1518             :         { "Nilo-Saharan languages","ssa",""} ,
    1519             :         { "Niuean","niu",""} ,
    1520             :         { "No linguistic content; Not applicable","zxx",""} ,
    1521             :         { "Nogai","nog",""} ,
    1522             :         { "Norse, Old","non",""} ,
    1523             :         { "North American Indian languages","nai",""} ,
    1524             :         { "Northern Frisian","frr",""} ,
    1525             :         { "Northern Sami","sme","se"} ,
    1526             :         { "Norwegian","nor","no"} ,
    1527             :         { "Norwegian Nynorsk; Nynorsk, Norwegian","nno","nn"} ,
    1528             :         { "Nubian languages","nub",""} ,
    1529             :         { "Nyamwezi","nym",""} ,
    1530             :         { "Nyankole","nyn",""} ,
    1531             :         { "Nyoro","nyo",""} ,
    1532             :         { "Nzima","nzi",""} ,
    1533             :         { "Occitan (post 1500)","oci","oc"} ,
    1534             :         { "Official Aramaic (700-300 BCE); Imperial Aramaic (700-300 BCE)","arc",""} ,
    1535             :         { "Ojibwa","oji","oj"} ,
    1536             :         { "Oriya","ori","or"} ,
    1537             :         { "Oromo","orm","om"} ,
    1538             :         { "Osage","osa",""} ,
    1539             :         { "Ossetian; Ossetic","oss","os"} ,
    1540             :         { "Otomian languages","oto",""} ,
    1541             :         { "Pahlavi","pal",""} ,
    1542             :         { "Palauan","pau",""} ,
    1543             :         { "Pali","pli","pi"} ,
    1544             :         { "Pampanga; Kapampangan","pam",""} ,
    1545             :         { "Pangasinan","pag",""} ,
    1546             :         { "Panjabi; Punjabi","pan","pa"} ,
    1547             :         { "Papiamento","pap",""} ,
    1548             :         { "Papuan languages","paa",""} ,
    1549             :         { "Pedi; Sepedi; Northern Sotho","nso",""} ,
    1550             :         { "Persian","fas","fa"} ,
    1551             :         { "Persian, Old (ca.600-400 B.C.)","peo",""} ,
    1552             :         { "Philippine languages","phi",""} ,
    1553             :         { "Phoenician","phn",""} ,
    1554             :         { "Pohnpeian","pon",""} ,
    1555             :         { "Polish","pol","pl"} ,
    1556             :         { "Portuguese","por","pt"} ,
    1557             :         { "Prakrit languages","pra",""} ,
    1558             :         { "Provencal, Old (to 1500);Occitan, Old (to 1500)","pro",""} ,
    1559             :         { "Pushto; Pashto","pus","ps"} ,
    1560             :         { "Quechua","que","qu"} ,
    1561             :         { "Rajasthani","raj",""} ,
    1562             :         { "Rapanui","rap",""} ,
    1563             :         { "Rarotongan; Cook Islands Maori","rar",""} ,
    1564             :         { "Reserved for local use","qaa-qtz",""} ,
    1565             :         { "Romance languages","roa",""} ,
    1566             :         { "Romanian; Moldavian; Moldovan","ron","ro"} ,
    1567             :         { "Romansh","roh","rm"} ,
    1568             :         { "Romany","rom",""} ,
    1569             :         { "Rundi","run","rn"} ,
    1570             :         { "Russian","rus","ru"} ,
    1571             :         { "Salishan languages","sal",""} ,
    1572             :         { "Samaritan Aramaic","sam",""} ,
    1573             :         { "Sami languages","smi",""} ,
    1574             :         { "Samoan","smo","sm"} ,
    1575             :         { "Sandawe","sad",""} ,
    1576             :         { "Sango","sag","sg"} ,
    1577             :         { "Sanskrit","san","sa"} ,
    1578             :         { "Santali","sat",""} ,
    1579             :         { "Sardinian","srd","sc"} ,
    1580             :         { "Sasak","sas",""} ,
    1581             :         { "Scots","sco",""} ,
    1582             :         { "Selkup","sel",""} ,
    1583             :         { "Semitic languages","sem",""} ,
    1584             :         { "Serbian","srp","sr"} ,
    1585             :         { "Serer","srr",""} ,
    1586             :         { "Shan","shn",""} ,
    1587             :         { "Shona","sna","sn"} ,
    1588             :         { "Sichuan Yi; Nuosu","iii","ii"} ,
    1589             :         { "Sicilian","scn",""} ,
    1590             :         { "Sidamo","sid",""} ,
    1591             :         { "Sign Languages","sgn",""} ,
    1592             :         { "Siksika","bla",""} ,
    1593             :         { "Sindhi","snd","sd"} ,
    1594             :         { "Sinhala; Sinhalese","sin","si"} ,
    1595             :         { "Sino-Tibetan languages","sit",""} ,
    1596             :         { "Siouan languages","sio",""} ,
    1597             :         { "Skolt Sami","sms",""} ,
    1598             :         { "Slave (Athapascan)","den",""} ,
    1599             :         { "Slavic languages","sla",""} ,
    1600             :         { "Slovak","slk","sk"} ,
    1601             :         { "Slovenian","slv","sl"} ,
    1602             :         { "Sogdian","sog",""} ,
    1603             :         { "Somali","som","so"} ,
    1604             :         { "Songhai languages","son",""} ,
    1605             :         { "Soninke","snk",""} ,
    1606             :         { "Sorbian languages","wen",""} ,
    1607             :         { "Sotho, Southern","sot","st"} ,
    1608             :         { "South American Indian languages","sai",""} ,
    1609             :         { "Southern Altai","alt",""} ,
    1610             :         { "Southern Sami","sma",""} ,
    1611             :         { "Spanish; Castilian","spa","es"} ,
    1612             :         { "Sranan Tongo","srn",""} ,
    1613             :         { "Sukuma","suk",""} ,
    1614             :         { "Sumerian","sux",""} ,
    1615             :         { "Sundanese","sun","su"} ,
    1616             :         { "Susu","sus",""} ,
    1617             :         { "Swahili","swa","sw"} ,
    1618             :         { "Swati","ssw","ss"} ,
    1619             :         { "Swedish","swe","sv"} ,
    1620             :         { "Swiss German; Alemannic; Alsatian","gsw",""} ,
    1621             :         { "Syriac","syr",""} ,
    1622             :         { "Tagalog","tgl","tl"} ,
    1623             :         { "Tahitian","tah","ty"} ,
    1624             :         { "Tai languages","tai",""} ,
    1625             :         { "Tajik","tgk","tg"} ,
    1626             :         { "Tamashek","tmh",""} ,
    1627             :         { "Tamil","tam","ta"} ,
    1628             :         { "Tatar","tat","tt"} ,
    1629             :         { "Telugu","tel","te"} ,
    1630             :         { "Tereno","ter",""} ,
    1631             :         { "Tetum","tet",""} ,
    1632             :         { "Thai","tha","th"} ,
    1633             :         { "Tibetan","bod","bo"} ,
    1634             :         { "Tigre","tig",""} ,
    1635             :         { "Tigrinya","tir","ti"} ,
    1636             :         { "Timne","tem",""} ,
    1637             :         { "Tiv","tiv",""} ,
    1638             :         { "Tlingit","tli",""} ,
    1639             :         { "Tok Pisin","tpi",""} ,
    1640             :         { "Tokelau","tkl",""} ,
    1641             :         { "Tonga (Nyasa)","tog",""} ,
    1642             :         { "Tonga (Tonga Islands)","ton","to"} ,
    1643             :         { "Tsimshian","tsi",""} ,
    1644             :         { "Tsonga","tso","ts"} ,
    1645             :         { "Tswana","tsn","tn"} ,
    1646             :         { "Tumbuka","tum",""} ,
    1647             :         { "Tupi languages","tup",""} ,
    1648             :         { "Turkish","tur","tr"} ,
    1649             :         { "Turkish, Ottoman (1500-1928)","ota",""} ,
    1650             :         { "Turkmen","tuk","tk"} ,
    1651             :         { "Tuvalu","tvl",""} ,
    1652             :         { "Tuvinian","tyv",""} ,
    1653             :         { "Twi","twi","tw"} ,
    1654             :         { "Udmurt","udm",""} ,
    1655             :         { "Ugaritic","uga",""} ,
    1656             :         { "Uighur; Uyghur","uig","ug"} ,
    1657             :         { "Ukrainian","ukr","uk"} ,
    1658             :         { "Umbundu","umb",""} ,
    1659             :         { "Uncoded languages","mis",""} ,
    1660             :         { "Undetermined","und",""} ,
    1661             :         { "Upper Sorbian","hsb",""} ,
    1662             :         { "Urdu","urd","ur"} ,
    1663             :         { "Uzbek","uzb","uz"} ,
    1664             :         { "Vai","vai",""} ,
    1665             :         { "Venda","ven","ve"} ,
    1666             :         { "Vietnamese","vie","vi"} ,
    1667             :         { "Volapuk","vol","vo"} ,
    1668             :         { "Votic","vot",""} ,
    1669             :         { "Wakashan languages","wak",""} ,
    1670             :         { "Walloon","wln","wa"} ,
    1671             :         { "Waray","war",""} ,
    1672             :         { "Washo","was",""} ,
    1673             :         { "Welsh","cym","cy"} ,
    1674             :         { "Western Frisian","fry","fy"} ,
    1675             :         { "Wolaitta; Wolaytta","wal",""} ,
    1676             :         { "Wolof","wol","wo"} ,
    1677             :         { "Xhosa","xho","xh"} ,
    1678             :         { "Yakut","sah",""} ,
    1679             :         { "Yao","yao",""} ,
    1680             :         { "Yapese","yap",""} ,
    1681             :         { "Yiddish","yid","yi"} ,
    1682             :         { "Yoruba","yor","yo"} ,
    1683             :         { "Yupik languages","ypk",""} ,
    1684             :         { "Zande languages","znd",""} ,
    1685             :         { "Zapotec","zap",""} ,
    1686             :         { "Zaza; Dimili; Dimli; Kirdki; Kirmanjki; Zazaki","zza",""} ,
    1687             :         { "Zenaga","zen",""} ,
    1688             :         { "Zhuang; Chuang","zha","za"} ,
    1689             :         { "Zulu","zul","zu"} ,
    1690             :         { "Zuni","zun",""} ,
    1691             : };
    1692             : 
    1693             : 
    1694             : GF_EXPORT
    1695           2 : u32 gf_lang_get_count()
    1696             : {
    1697           2 :         return sizeof(defined_languages) / sizeof(struct lang_def);
    1698             : }
    1699             : 
    1700             : GF_EXPORT
    1701         672 : s32 gf_lang_find(const char *lang_or_rfc_5646_code)
    1702             : {
    1703             :         //find the language ISO639 entry for the given code
    1704             :         u32 i=0;
    1705             :         u32 len=0;
    1706             :         char *sep;
    1707             :         u32 count = sizeof(defined_languages) / sizeof(struct lang_def);
    1708             : 
    1709         672 :         if (!lang_or_rfc_5646_code) return -1;
    1710             : 
    1711         672 :         len = (u32)strlen(lang_or_rfc_5646_code);
    1712         672 :         sep = (char *) strchr(lang_or_rfc_5646_code, '-');
    1713         672 :         if (sep) {
    1714          23 :                 sep[0] = 0;
    1715          23 :                 len = (u32) strlen(lang_or_rfc_5646_code);
    1716          23 :                 sep[0] = '-';
    1717             :         }
    1718             : 
    1719      187384 :         for (i=0; i<count; i++) {
    1720      187384 :                 if (!strcmp(defined_languages[i].name, lang_or_rfc_5646_code)) {
    1721           0 :                         return i;
    1722             :                 }
    1723      187384 :                 if ((len==3) && !strnicmp(defined_languages[i].three_char_code, lang_or_rfc_5646_code, 3)) {
    1724         478 :                         return i;
    1725             :                 }
    1726      186906 :                 if ((len==2) && !strnicmp(defined_languages[i].two_char_code, lang_or_rfc_5646_code, 2)) {
    1727         194 :                         return i;
    1728             :                 }
    1729             :         }
    1730             :         return -1;
    1731             : }
    1732             : 
    1733             : GF_EXPORT
    1734         704 : const char *gf_lang_get_name(u32 idx)
    1735             : {
    1736         704 :         if (idx>=sizeof(defined_languages) / sizeof(struct lang_def)) return NULL;
    1737         704 :         return defined_languages[idx].name;
    1738             : }
    1739             : 
    1740             : GF_EXPORT
    1741        1090 : const char *gf_lang_get_2cc(u32 idx)
    1742             : {
    1743        1090 :         if (idx>=sizeof(defined_languages) / sizeof(struct lang_def)) return NULL;
    1744        1090 :         return defined_languages[idx].two_char_code;
    1745             : }
    1746             : 
    1747             : GF_EXPORT
    1748         637 : const char *gf_lang_get_3cc(u32 idx)
    1749             : {
    1750         637 :         if (idx>=sizeof(defined_languages) / sizeof(struct lang_def)) return NULL;
    1751         637 :         return defined_languages[idx].three_char_code;
    1752             : }
    1753             : 
    1754             : GF_EXPORT
    1755       21929 : GF_Err gf_blob_get(const char *blob_url, u8 **out_data, u32 *out_size, u32 *out_flags)
    1756             : {
    1757       21929 :         GF_Blob *blob = NULL;
    1758       21929 :         if (strncmp(blob_url, "gmem://", 7)) return GF_BAD_PARAM;
    1759       21929 :         if (sscanf(blob_url, "gmem://%p", &blob) != 1) return GF_BAD_PARAM;
    1760       21929 :         if (!blob) return GF_BAD_PARAM;
    1761       21929 :         if (out_data) *out_data = blob->data;
    1762       21929 :         if (out_size) *out_size = blob->size;
    1763       21929 :         if (out_flags) *out_flags = blob->flags;
    1764       21929 :         if (blob->data && blob->mx)
    1765       21918 :                 gf_mx_p(blob->mx);
    1766             :         return GF_OK;
    1767             : }
    1768             : 
    1769             : GF_EXPORT
    1770       21928 : GF_Err gf_blob_release(const char *blob_url)
    1771             : {
    1772       21928 :     GF_Blob *blob = NULL;
    1773       21928 :     if (strncmp(blob_url, "gmem://", 7)) return GF_BAD_PARAM;
    1774       21928 :     if (sscanf(blob_url, "gmem://%p", &blob) != 1) return GF_BAD_PARAM;
    1775       21928 :     if (!blob) return GF_BAD_PARAM;
    1776       21928 :     if (blob->data && blob->mx)
    1777       21918 :         gf_mx_v(blob->mx);
    1778             :     return GF_OK;
    1779             : }
    1780             : 
    1781             : GF_EXPORT
    1782      199243 : GF_Err gf_dynstrcat(char **str, const char *to_append, const char *sep)
    1783             : {
    1784             :         u32     l1, l2, lsep;
    1785      199243 :         if (!to_append) return GF_OK;
    1786             : 
    1787      190749 :         lsep = sep ? (u32) strlen(sep) : 0;
    1788      190749 :         l1 = *str ? (u32) strlen(*str) : 0;
    1789      190749 :         l2 = (u32) strlen(to_append);
    1790      190749 :         if (l1) (*str) = gf_realloc((*str), sizeof(char)*(l1+l2+lsep+1));
    1791       16354 :         else (*str) = gf_realloc((*str), sizeof(char)*(l2+lsep+1));
    1792             : 
    1793      190749 :         if (! (*str) )
    1794             :                 return GF_OUT_OF_MEM;
    1795             : 
    1796      190749 :         (*str)[l1]=0;
    1797      190749 :         if (l1 && sep) strcat((*str), sep);
    1798      190749 :         strcat((*str), to_append);
    1799      190749 :         return GF_OK;
    1800             : }
    1801             : 
    1802             : GF_EXPORT
    1803       13196 : Bool gf_parse_lfrac(const char *value, GF_Fraction64 *frac)
    1804             : {
    1805             :         Float v;
    1806             :         u32 len, i;
    1807             :         Bool all_num=GF_TRUE;
    1808             :         char *sep;
    1809       13196 :         if (!frac) return GF_FALSE;
    1810       13196 :         frac->num = 0;
    1811       13196 :         frac->den = 0;
    1812       13196 :         if (!value) return GF_FALSE;
    1813             : 
    1814       13190 :         if (sscanf(value, LLD"/"LLU, &frac->num, &frac->den) == 2) {
    1815             :                 return GF_TRUE;
    1816             :         }
    1817        8710 :         if (sscanf(value, LLD"-"LLU, &frac->num, &frac->den) == 2) {
    1818             :                 return GF_TRUE;
    1819             :         }
    1820        5780 :         if (sscanf(value, "%g", &v) != 1) {
    1821           6 :                 frac->num = 0;
    1822           6 :                 frac->den = 0;
    1823           6 :                 return GF_FALSE;
    1824             :         }
    1825        5774 :         sep = strchr(value, '.');
    1826        5774 :         if (!sep) sep = strchr(value, ',');
    1827        5774 :         if (!sep) {
    1828        5446 :                 frac->num = atoi(value);
    1829        5446 :                 frac->den = 1;
    1830        5446 :                 return GF_TRUE;
    1831             :         }
    1832             : 
    1833         328 :         len = (u32) strlen(sep+1);
    1834         695 :         for (i=1; i<=len; i++) {
    1835         367 :                 if ((sep[i]<'0') || (sep[i]>'9')) {
    1836             :                         all_num = GF_FALSE;
    1837             :                         break;
    1838             :                 }
    1839             :         }
    1840         328 :         if (all_num) {
    1841             :                 u32 div_trail_zero = 1;
    1842         328 :                 sscanf(value, LLD"."LLU, &frac->num, &frac->den);
    1843             : 
    1844             :                 i=0;
    1845         328 :                 frac->den = 1;
    1846        1023 :                 while (i<len) {
    1847         367 :                         i++;
    1848         367 :                         frac->den *= 10;
    1849             :                 }
    1850             :                 //trash trailing zero
    1851             :                 i=len;
    1852         331 :                 while (i>0) {
    1853         328 :                         if (sep[i] != '0') {
    1854             :                                 break;
    1855             :                         }
    1856           3 :                         div_trail_zero *= 10;
    1857           3 :                         i--;
    1858             :                 }
    1859             : 
    1860             : 
    1861         328 :                 frac->num *= frac->den / div_trail_zero;
    1862         328 :                 frac->num += atoi(sep+1) / div_trail_zero;
    1863         328 :                 frac->den /= div_trail_zero;
    1864             : 
    1865         328 :                 return GF_TRUE;
    1866             :         }
    1867             : 
    1868             :         sep += 1;
    1869           0 :         if (len <= 3) frac->den = 1000;
    1870           0 :         else if (len <= 6) frac->den = 1000000;
    1871           0 :         else frac->den = 1000000000;
    1872             : 
    1873           0 :         frac->num = (u64)( (atof(value) * frac->den) + 0.5 );
    1874           0 :         return GF_TRUE;
    1875             : }
    1876             : 
    1877             : GF_EXPORT
    1878        8331 : Bool gf_parse_frac(const char *value, GF_Fraction *frac)
    1879             : {
    1880             :         GF_Fraction64 r;
    1881             :         Bool res;
    1882        8331 :         if (!frac) return GF_FALSE;
    1883        8331 :         res = gf_parse_lfrac(value, &r);
    1884       16662 :         while ((r.num >= 0x80000000) && (r.den > 1000)) {
    1885           0 :                 r.num /= 1000;
    1886           0 :                 r.den /= 1000;
    1887             :         }
    1888        8331 :         frac->num = (s32) r.num;
    1889        8331 :         frac->den = (u32) r.den;
    1890        8331 :         return res;
    1891             : }

Generated by: LCOV version 1.13