diff --git a/CMakeLists.txt b/CMakeLists.txt index ec540aa280c7776002921f2c5d945ecae88a71a6..964f1091afb51e8138c5286ed30515186ebeab87 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -34,6 +34,7 @@ option(ENABLE_MATHEX "Enable MathEx expression parser" ON) option(ENABLE_MED "Enable MED mesh and post-processing file formats" ON) option(ENABLE_MESH "Build the mesh module" ON) option(ENABLE_METIS "Enable Metis mesh partitioner" ON) +option(ENABLE_MPEG_ENCODE "Enable built-in MPEG encoder" ON) option(ENABLE_MPI "Enable MPI parallelization" OFF) option(ENABLE_MSVC_STATIC_RUNTIME "Use static Visual C++ runtime" OFF) option(ENABLE_NATIVE_FILE_CHOOSER "Enable native file chooser in GUI" ON) @@ -488,6 +489,13 @@ if(ENABLE_MPI) endif(MPI_FOUND) endif(ENABLE_MPI) +if(ENABLE_MPEG_ENCODE) + add_subdirectory(contrib/mpeg_encode) + include_directories(contrib/mpeg_encode/headers) + set(HAVE_MPEG_ENCODE TRUE) + list(APPEND CONFIG_OPTIONS "Mpeg") +endif(ENABLE_MPEG_ENCODE) + if(ENABLE_METIS) add_subdirectory(contrib/Metis) include_directories(contrib/Metis) diff --git a/Common/Context.cpp b/Common/Context.cpp index 0906ce556cca1c7183dbf088e8e15fcec1a5cdc1..bc79e31fa5a87b4eeac97d04d2cb514a13c223c0 100644 --- a/Common/Context.cpp +++ b/Common/Context.cpp @@ -7,26 +7,12 @@ #include <string.h> #include "GmshConfig.h" #include "Context.h" +#include "OS.h" #if defined(HAVE_FLTK) #include <FL/Fl.H> #endif -static const char *getEnvironmentVariable(const char *var) -{ -#if !defined(WIN32) - return getenv(var); -#else - const char *tmp = getenv(var); - // Don't accept top dir or anything partially expanded like - // c:\Documents and Settings\%USERPROFILE%, etc. - if(!tmp || !strcmp(tmp, "/") || strstr(tmp, "%") || strstr(tmp, "$")) - return 0; - else - return tmp; -#endif -} - CTX::CTX() { // Initialize everything that has no default value in @@ -37,13 +23,13 @@ CTX::CTX() bigEndian = (byte[0] ? 0 : 1); const char *tmp; - if((tmp = getEnvironmentVariable("GMSH_HOME"))) + if((tmp = GetEnvironmentVariable("GMSH_HOME"))) homeDir = tmp; - else if((tmp = getEnvironmentVariable("HOME"))) + else if((tmp = GetEnvironmentVariable("HOME"))) homeDir = tmp; - else if((tmp = getEnvironmentVariable("TMP"))) + else if((tmp = GetEnvironmentVariable("TMP"))) homeDir = tmp; - else if((tmp = getEnvironmentVariable("TEMP"))) + else if((tmp = GetEnvironmentVariable("TEMP"))) homeDir = tmp; else homeDir = ""; diff --git a/Common/CreateFile.cpp b/Common/CreateFile.cpp index 3f69d2e2d7db6c45c6df70700946da37993c712e..06a513d875cb761379c77efb9f63bce5049b3f51 100644 --- a/Common/CreateFile.cpp +++ b/Common/CreateFile.cpp @@ -26,6 +26,8 @@ #include "gl2yuv.h" #endif +extern int mpeg_encode_main(int, char**); + int GuessFileFormatFromFileName(std::string fileName) { std::string ext = SplitFileName(fileName)[2]; @@ -49,6 +51,8 @@ int GuessFileFormatFromFileName(std::string fileName) else if(ext == ".gif") return FORMAT_GIF; else if(ext == ".jpg") return FORMAT_JPEG; else if(ext == ".jpeg") return FORMAT_JPEG; + else if(ext == ".mpg") return FORMAT_MPEG; + else if(ext == ".mpeg") return FORMAT_MPEG; else if(ext == ".png") return FORMAT_PNG; else if(ext == ".ps") return FORMAT_PS; else if(ext == ".eps") return FORMAT_EPS; @@ -87,6 +91,7 @@ std::string GetDefaultFileName(int format) case FORMAT_VRML: name += ".wrl"; break; case FORMAT_GIF: name += ".gif"; break; case FORMAT_JPEG: name += ".jpg"; break; + case FORMAT_MPEG: name += ".mpg"; break; case FORMAT_PNG: name += ".png"; break; case FORMAT_PS: name += ".ps"; break; case FORMAT_EPS: name += ".eps"; break; @@ -397,7 +402,6 @@ void CreateOutputFile(std::string fileName, int format) case FORMAT_TEX: { - printf("couc tex format \n"); if(!FlGui::available()) break; FILE *fp = fopen(fileName.c_str(), "w"); @@ -426,6 +430,51 @@ void CreateOutputFile(std::string fileName, int format) fclose(fp); } break; + +#if defined(HAVE_MPEG_ENCODE) + case FORMAT_MPEG: + { + std::string parFileName = CTX::instance()->homeDir + ".gmsh-mpeg_encode.par"; + FILE *fp = fopen(parFileName.c_str(), "w"); + if(!fp){ + Msg::Error("Unable to open file '%s'", parFileName.c_str()); + break; + } + int numViews = (int)opt_post_nb_views(0, GMSH_GET, 0), numSteps = 0; + for(unsigned int i = 0; i < numViews; i++){ + if(opt_view_visible(i, GMSH_GET, 0)) + numSteps = std::max(numSteps, (int)opt_view_nb_timestep(i, GMSH_GET, 0)); + } + int numFrames = CTX::instance()->post.animCycle ? numViews : numSteps; + status_play_manual(!CTX::instance()->post.animCycle, 0); + for(int i = 0; i < numFrames; i++){ + char tmp[256]; + sprintf(tmp, "%s.gmsh-%03d.ppm", CTX::instance()->homeDir.c_str(), i + 1); + CreateOutputFile(tmp, FORMAT_PPM); + status_play_manual(!CTX::instance()->post.animCycle, 1); + } + fprintf(fp, "PATTERN I\n" "BASE_FILE_FORMAT PPM\n" + "GOP_SIZE 30\n" "SLICES_PER_FRAME 1\n" + "PIXEL HALF\n" "RANGE 10\n" + "PSEARCH_ALG TWOLEVEL\n" "BSEARCH_ALG CROSS2\n" + "IQSCALE 1\n" "PQSCALE 10\n" + "BQSCALE 25\n" "REFERENCE_FRAME DECODED\n" + "OUTPUT %s\n" "INPUT_CONVERT *\n" + "INPUT_DIR %s\n" + "INPUT\n" ".gmsh-*.ppm [001-%03d]\n" "END_INPUT\n", + fileName.c_str(), CTX::instance()->homeDir.c_str(), numFrames); + fclose(fp); + char *args[] = {(char*)"gmsh", (char*)parFileName.c_str()}; + try{ + mpeg_encode_main(2, args); + } + catch (const char *error){ + Msg::Error("mpeg_encode: %s", error); + } + } + break; +#endif + #endif default: diff --git a/Common/DefaultOptions.h b/Common/DefaultOptions.h index 8da8dd5c7531ff71b1dce2181c40e1c32a26894b..15f9bf8f19b7ea967b6b971ac3f468a6588d9132 100644 --- a/Common/DefaultOptions.h +++ b/Common/DefaultOptions.h @@ -1308,7 +1308,7 @@ StringXNumber PostProcessingOptions_Number[] = { { F|O, "AnimationDelay" , opt_post_anim_delay , 0.25 , "Delay (in seconds) between frames in automatic animation mode" }, { F|O, "AnimationCycle" , opt_post_anim_cycle , 0. , - "Cycle through views instead of time steps in automatic animation mode" }, + "Cycle through time steps (0) or views (1) for animations" }, { F|O, "CombineRemoveOriginal" , opt_post_combine_remove_orig , 1. , "Remove original views after a Combine operation" }, diff --git a/Common/GmshConfig.h.in b/Common/GmshConfig.h.in index 5f0ff0fcc29b7deb925aa1be1f5d97ce8c165b0a..ef67a45ae1bae295987620ed2f4bb0dc097ce57c 100644 --- a/Common/GmshConfig.h.in +++ b/Common/GmshConfig.h.in @@ -29,6 +29,7 @@ #cmakedefine HAVE_MED #cmakedefine HAVE_MESH #cmakedefine HAVE_METIS +#cmakedefine HAVE_MPEG_ENCODE #cmakedefine HAVE_MPI #cmakedefine HAVE_NATIVE_FILE_CHOOSER #cmakedefine HAVE_NETGEN diff --git a/Common/GmshDefines.h b/Common/GmshDefines.h index b9d91aa18cd1d1a92936c7fb6215700c63eb931a..6b0e1e201aedf3828db09a3de913c98e230ff953 100644 --- a/Common/GmshDefines.h +++ b/Common/GmshDefines.h @@ -23,6 +23,7 @@ #define FORMAT_SMS 14 #define FORMAT_OPT 15 #define FORMAT_VTK 16 +#define FORMAT_MPEG 17 #define FORMAT_TEX 18 #define FORMAT_VRML 19 #define FORMAT_EPS 20 diff --git a/Common/GmshMessage.cpp b/Common/GmshMessage.cpp index 26a052d022272840f8f88c4b12431dcd7e7cda3e..a7c6357060fc7cc4dff2fec3eb4b1339ac13f4fa 100644 --- a/Common/GmshMessage.cpp +++ b/Common/GmshMessage.cpp @@ -509,6 +509,31 @@ double Msg::GetValue(const char *text, double defaultval) return atof(str); } +std::string Msg::GetString(const char *text, std::string defaultval) +{ + // if a callback is given let's assume we don't want to be bothered + // with interactive stuff + if(CTX::instance()->noPopup || _callback) return defaultval; + +#if defined(HAVE_FLTK) + if(FlGui::available()){ + const char *ret = fl_input(text, defaultval.c_str(), ""); + if(!ret) + return defaultval; + else + return std::string(ret); + } +#endif + + printf("%s (default=%s): ", text, defaultval.c_str()); + char str[256]; + char *ret = fgets(str, sizeof(str), stdin); + if(!ret || !strlen(str) || !strcmp(str, "\n")) + return defaultval; + else + return std::string(str); +} + int Msg::GetAnswer(const char *question, int defaultval, const char *zero, const char *one, const char *two) { diff --git a/Common/GmshMessage.h b/Common/GmshMessage.h index e1a95138163240c6a5b6adfe86eddeff5dd7b676..6a9d8d60b8ef35dda91aa4f6e4273ccbf35cbf58 100644 --- a/Common/GmshMessage.h +++ b/Common/GmshMessage.h @@ -75,6 +75,7 @@ class Msg { static void ResetErrorCounter(){ _warningCount = 0; _errorCount = 0; } static void PrintErrorCounter(const char *title); static double GetValue(const char *text, double defaultval); + static std::string GetString(const char *text, std::string defaultval); static int GetAnswer(const char *question, int defaultval, const char *zero, const char *one, const char *two=0); static void InitClient(std::string sockname); diff --git a/Common/OS.cpp b/Common/OS.cpp index e46b56f93158bbde3ed154209ac471d55d8c9665..0c163ec6e683cf6f39c628ef952063a5d750e86d 100644 --- a/Common/OS.cpp +++ b/Common/OS.cpp @@ -34,6 +34,21 @@ #include "GmshMessage.h" +const char *GetEnvironmentVariable(const char *var) +{ +#if !defined(WIN32) + return getenv(var); +#else + const char *tmp = getenv(var); + // Don't accept top dir or anything partially expanded like + // c:\Documents and Settings\%USERPROFILE%, etc. + if(!tmp || !strcmp(tmp, "/") || strstr(tmp, "%") || strstr(tmp, "$")) + return 0; + else + return tmp; +#endif +} + double GetTimeInSeconds() { #if !defined(WIN32) || defined(__CYGWIN__) diff --git a/Common/OS.h b/Common/OS.h index 578f1f44c59b59335cbefa4856a65652547d16fa..4ec46810125dc98550a18f4c3db43fc9f748f159 100644 --- a/Common/OS.h +++ b/Common/OS.h @@ -8,6 +8,7 @@ #include <string> +const char *GetEnvironmentVariable(const char *var); double GetTimeInSeconds(); void SleepInSeconds(double s); void CheckResources(); diff --git a/Fltk/graphicWindow.cpp b/Fltk/graphicWindow.cpp index 31e4572cffcffb27124dcd7988592acb24f9428a..fc10b346d3b9161f9c5d5d50f1dd519ad0e4e0d2 100644 --- a/Fltk/graphicWindow.cpp +++ b/Fltk/graphicWindow.cpp @@ -296,7 +296,12 @@ void status_play_manual(int time, int incr) } } else { // hide all views except view_in_cycle - if(incr > 0) { + if(incr == 0) { + view_in_cycle = 0; + for(int i = 0; i < (int)PView::list.size(); i++) + opt_view_visible(i, GMSH_SET | GMSH_GUI, (i == view_in_cycle)); + } + else if(incr > 0) { if((view_in_cycle += incr) >= (int)PView::list.size()) view_in_cycle = 0; for(int i = 0; i < (int)PView::list.size(); i += incr) diff --git a/Fltk/menuWindow.cpp b/Fltk/menuWindow.cpp index 8027900133363e67017218eb57866306cf611d7c..392828b8c9472d0b5af70f2c94cd8ab2988e3c90 100644 --- a/Fltk/menuWindow.cpp +++ b/Fltk/menuWindow.cpp @@ -332,6 +332,9 @@ static void file_save_as_cb(Fl_Widget *w, void *data) {"GIF" TT "*.gif", _save_gif}, #if defined(HAVE_LIBJPEG) {"JPEG" TT "*.jpg", _save_jpeg}, +#endif +#if defined(HAVE_MPEG_ENCODE) + {"MPEG" TT "*.mpg", 0}, #endif {"LaTeX" TT "*.tex", _save_tex}, {"PDF" TT "*.pdf", _save_pdf}, diff --git a/Parser/Gmsh.l b/Parser/Gmsh.l index dd9d02ddc512710187849be1a840137373dd8049..a3bbc2c81aaee17b00d39f610be7775ed7c74c77 100644 --- a/Parser/Gmsh.l +++ b/Parser/Gmsh.l @@ -132,6 +132,8 @@ Fmod return tFmod; For return tFor; Function return tFunction; +GetEnv return tGetEnv; +GetString return tGetString; GetValue return tGetValue; GMSH_MAJOR_VERSION return tGMSH_MAJOR_VERSION; GMSH_MINOR_VERSION return tGMSH_MINOR_VERSION; diff --git a/Parser/Gmsh.tab.cpp b/Parser/Gmsh.tab.cpp index 962b44b2b58aabccece10d59d56e30938f210e5b..0eee92b74abb7dbc3afb9f8847035718a3c7aa55 100644 --- a/Parser/Gmsh.tab.cpp +++ b/Parser/Gmsh.tab.cpp @@ -182,26 +182,28 @@ tShow = 363, tHide = 364, tGetValue = 365, - tGMSH_MAJOR_VERSION = 366, - tGMSH_MINOR_VERSION = 367, - tGMSH_PATCH_VERSION = 368, - tHomRank = 369, - tHomGen = 370, - tHomCut = 371, - tHomSeq = 372, - tAFFECTDIVIDE = 373, - tAFFECTTIMES = 374, - tAFFECTMINUS = 375, - tAFFECTPLUS = 376, - tOR = 377, - tAND = 378, - tNOTEQUAL = 379, - tEQUAL = 380, - tGREATEROREQUAL = 381, - tLESSOREQUAL = 382, - UNARYPREC = 383, - tMINUSMINUS = 384, - tPLUSPLUS = 385 + tGetEnv = 366, + tGetString = 367, + tGMSH_MAJOR_VERSION = 368, + tGMSH_MINOR_VERSION = 369, + tGMSH_PATCH_VERSION = 370, + tHomRank = 371, + tHomGen = 372, + tHomCut = 373, + tHomSeq = 374, + tAFFECTDIVIDE = 375, + tAFFECTTIMES = 376, + tAFFECTMINUS = 377, + tAFFECTPLUS = 378, + tOR = 379, + tAND = 380, + tNOTEQUAL = 381, + tEQUAL = 382, + tGREATEROREQUAL = 383, + tLESSOREQUAL = 384, + UNARYPREC = 385, + tMINUSMINUS = 386, + tPLUSPLUS = 387 }; #endif /* Tokens. */ @@ -313,26 +315,28 @@ #define tShow 363 #define tHide 364 #define tGetValue 365 -#define tGMSH_MAJOR_VERSION 366 -#define tGMSH_MINOR_VERSION 367 -#define tGMSH_PATCH_VERSION 368 -#define tHomRank 369 -#define tHomGen 370 -#define tHomCut 371 -#define tHomSeq 372 -#define tAFFECTDIVIDE 373 -#define tAFFECTTIMES 374 -#define tAFFECTMINUS 375 -#define tAFFECTPLUS 376 -#define tOR 377 -#define tAND 378 -#define tNOTEQUAL 379 -#define tEQUAL 380 -#define tGREATEROREQUAL 381 -#define tLESSOREQUAL 382 -#define UNARYPREC 383 -#define tMINUSMINUS 384 -#define tPLUSPLUS 385 +#define tGetEnv 366 +#define tGetString 367 +#define tGMSH_MAJOR_VERSION 368 +#define tGMSH_MINOR_VERSION 369 +#define tGMSH_PATCH_VERSION 370 +#define tHomRank 371 +#define tHomGen 372 +#define tHomCut 373 +#define tHomSeq 374 +#define tAFFECTDIVIDE 375 +#define tAFFECTTIMES 376 +#define tAFFECTMINUS 377 +#define tAFFECTPLUS 378 +#define tOR 379 +#define tAND 380 +#define tNOTEQUAL 381 +#define tEQUAL 382 +#define tGREATEROREQUAL 383 +#define tLESSOREQUAL 384 +#define UNARYPREC 385 +#define tMINUSMINUS 386 +#define tPLUSPLUS 387 @@ -457,7 +461,7 @@ typedef union YYSTYPE List_T *l; } /* Line 193 of yacc.c. */ -#line 461 "Gmsh.tab.cpp" +#line 465 "Gmsh.tab.cpp" YYSTYPE; # define yystype YYSTYPE /* obsolescent; will be withdrawn */ # define YYSTYPE_IS_DECLARED 1 @@ -470,7 +474,7 @@ typedef union YYSTYPE /* Line 216 of yacc.c. */ -#line 474 "Gmsh.tab.cpp" +#line 478 "Gmsh.tab.cpp" #ifdef short # undef short @@ -685,20 +689,20 @@ union yyalloc /* YYFINAL -- State number of the termination state. */ #define YYFINAL 5 /* YYLAST -- Last index in YYTABLE. */ -#define YYLAST 6738 +#define YYLAST 6711 /* YYNTOKENS -- Number of terminals. */ -#define YYNTOKENS 151 +#define YYNTOKENS 153 /* YYNNTS -- Number of nonterminals. */ #define YYNNTS 82 /* YYNRULES -- Number of rules. */ -#define YYNRULES 386 +#define YYNRULES 388 /* YYNRULES -- Number of states. */ -#define YYNSTATES 1376 +#define YYNSTATES 1386 /* YYTRANSLATE(YYLEX) -- Bison symbol number corresponding to YYLEX. */ #define YYUNDEFTOK 2 -#define YYMAXUTOK 385 +#define YYMAXUTOK 387 #define YYTRANSLATE(YYX) \ ((unsigned int) (YYX) <= YYMAXUTOK ? yytranslate[YYX] : YYUNDEFTOK) @@ -709,16 +713,16 @@ static const yytype_uint8 yytranslate[] = 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 136, 2, 146, 2, 135, 2, 2, - 141, 142, 133, 131, 147, 132, 145, 134, 2, 2, + 2, 2, 2, 138, 2, 148, 2, 137, 2, 2, + 143, 144, 135, 133, 149, 134, 147, 136, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 127, 2, 128, 122, 2, 2, 2, 2, 2, 2, + 129, 2, 130, 124, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 143, 2, 144, 140, 2, 2, 2, 2, 2, + 2, 145, 2, 146, 142, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 148, 2, 149, 150, 2, 2, 2, + 2, 2, 2, 150, 2, 151, 152, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, @@ -743,8 +747,8 @@ static const yytype_uint8 yytranslate[] = 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, - 115, 116, 117, 118, 119, 120, 121, 123, 124, 125, - 126, 129, 130, 137, 138, 139 + 115, 116, 117, 118, 119, 120, 121, 122, 123, 125, + 126, 127, 128, 131, 132, 139, 140, 141 }; #if YYDEBUG @@ -790,237 +794,238 @@ static const yytype_uint16 yyprhs[] = 2083, 2087, 2092, 2098, 2100, 2102, 2105, 2109, 2113, 2119, 2124, 2126, 2128, 2132, 2139, 2141, 2143, 2147, 2151, 2161, 2169, 2171, 2177, 2181, 2188, 2190, 2194, 2196, 2198, 2202, - 2209, 2211, 2213, 2220, 2225, 2230, 2235 + 2209, 2211, 2213, 2218, 2225, 2232, 2237, 2242, 2247 }; /* YYRHS -- A `-1'-separated list of the rules' RHS. */ static const yytype_int16 yyrhs[] = { - 152, 0, -1, 153, -1, 1, 6, -1, -1, 153, - 154, -1, 157, -1, 156, -1, 175, -1, 179, -1, - 184, -1, 188, -1, 189, -1, 190, -1, 193, -1, - 214, -1, 215, -1, 216, -1, 217, -1, 192, -1, - 191, -1, 187, -1, 218, -1, 128, -1, 128, 128, - -1, 35, 141, 5, 142, 6, -1, 35, 141, 5, - 142, 155, 231, 6, -1, 35, 141, 5, 147, 227, - 142, 6, -1, 35, 141, 5, 147, 227, 142, 155, - 231, 6, -1, 4, 5, 148, 158, 149, 6, -1, - 84, 4, 143, 219, 144, 6, -1, 85, 4, 143, - 219, 144, 6, -1, -1, 158, 161, -1, 158, 165, - -1, 158, 168, -1, 158, 170, -1, 158, 171, -1, - 219, -1, 159, 147, 219, -1, 219, -1, 160, 147, - 219, -1, -1, -1, 4, 162, 141, 159, 142, 163, - 148, 160, 149, 6, -1, 231, -1, 164, 147, 231, - -1, -1, 86, 141, 219, 147, 219, 147, 219, 142, - 166, 148, 164, 149, 6, -1, 231, -1, 167, 147, - 231, -1, -1, 87, 141, 219, 147, 219, 147, 219, - 147, 219, 142, 169, 148, 167, 149, 6, -1, 88, - 148, 223, 149, 148, 223, 149, 6, -1, 88, 148, - 223, 149, 148, 223, 149, 148, 223, 149, 148, 223, - 149, 6, -1, -1, 89, 172, 148, 160, 149, 6, - -1, 7, -1, 121, -1, 120, -1, 119, -1, 118, - -1, 139, -1, 138, -1, 4, 173, 219, 6, -1, - 4, 143, 219, 144, 173, 219, 6, -1, 4, 143, - 148, 227, 149, 144, 173, 224, 6, -1, 4, 143, - 144, 7, 224, 6, -1, 4, 143, 144, 121, 224, - 6, -1, 4, 174, 6, -1, 4, 143, 219, 144, - 174, 6, -1, 4, 7, 232, 6, -1, 4, 145, - 4, 7, 232, 6, -1, 4, 143, 219, 144, 145, - 4, 7, 232, 6, -1, 4, 145, 4, 173, 219, - 6, -1, 4, 143, 219, 144, 145, 4, 173, 219, - 6, -1, 4, 145, 4, 174, 6, -1, 4, 143, - 219, 144, 145, 4, 174, 6, -1, 4, 145, 96, - 145, 4, 7, 228, 6, -1, 4, 143, 219, 144, - 145, 96, 145, 4, 7, 228, 6, -1, 4, 145, - 97, 7, 229, 6, -1, 4, 143, 219, 144, 145, - 97, 7, 229, 6, -1, 4, 104, 7, 219, 6, - -1, 104, 143, 219, 144, 7, 4, 6, -1, 104, - 143, 219, 144, 145, 4, 7, 219, 6, -1, 104, - 143, 219, 144, 145, 4, 7, 232, 6, -1, 104, - 143, 219, 144, 145, 4, 7, 148, 227, 149, 6, - -1, 67, 141, 4, 142, 145, 4, 7, 219, 6, - -1, 67, 141, 4, 142, 145, 4, 7, 232, 6, - -1, 219, -1, 232, -1, -1, 99, 50, 148, 219, - 149, -1, -1, 59, 221, -1, 46, 141, 219, 142, - 7, 221, 6, -1, -1, 63, 46, 180, 141, 176, - 142, 7, 224, 6, -1, 55, 56, 224, 7, 219, - 6, -1, 49, 141, 219, 142, 7, 224, 6, -1, - 68, 49, 224, 6, -1, 53, 141, 219, 142, 7, - 224, 6, -1, 47, 141, 219, 142, 7, 224, 178, - 6, -1, 48, 141, 219, 142, 7, 224, 178, 6, - -1, 91, 141, 219, 142, 7, 224, 6, -1, 92, - 141, 219, 142, 7, 224, 6, -1, 93, 141, 219, - 142, 7, 224, 95, 224, 94, 219, 6, -1, 49, - 75, 141, 219, 142, 7, 224, 6, -1, 64, 49, - 141, 219, 142, 7, 224, 6, -1, -1, 63, 49, - 181, 141, 176, 142, 7, 224, 6, -1, 59, 52, - 141, 219, 142, 7, 224, 6, -1, 60, 52, 141, - 219, 142, 7, 224, 177, 6, -1, 12, 13, 6, - -1, 13, 52, 219, 6, -1, 57, 52, 141, 219, - 142, 7, 5, 5, 5, 6, -1, 50, 141, 219, - 142, 7, 224, 6, -1, 51, 141, 219, 142, 7, - 224, 6, -1, 52, 75, 141, 219, 142, 7, 224, - 6, -1, 64, 52, 141, 219, 142, 7, 224, 209, - 6, -1, 64, 52, 141, 219, 142, 7, 224, 4, - 148, 223, 149, 209, 6, -1, -1, 63, 52, 182, - 141, 176, 142, 7, 224, 6, -1, 62, 54, 141, - 219, 142, 7, 224, 6, -1, 54, 141, 219, 142, - 7, 224, 6, -1, 64, 54, 141, 219, 142, 7, - 224, 6, -1, -1, 63, 54, 183, 141, 176, 142, - 7, 224, 6, -1, 70, 221, 148, 185, 149, -1, - 69, 148, 221, 147, 221, 147, 219, 149, 148, 185, - 149, -1, 71, 221, 148, 185, 149, -1, 72, 148, - 221, 147, 219, 149, 148, 185, 149, -1, 4, 148, - 185, 149, -1, 81, 49, 148, 227, 149, 52, 148, - 219, 149, -1, 78, 49, 141, 219, 142, 148, 227, - 149, 6, -1, 186, -1, 184, -1, -1, 186, 179, - -1, 186, 46, 148, 227, 149, 6, -1, 186, 49, - 148, 227, 149, 6, -1, 186, 52, 148, 227, 149, - 6, -1, 186, 54, 148, 227, 149, 6, -1, 74, - 59, 141, 219, 142, 7, 224, 6, -1, 74, 59, - 141, 219, 142, 7, 148, 221, 147, 221, 147, 227, - 149, 6, -1, 74, 59, 141, 219, 142, 7, 148, - 221, 147, 221, 147, 221, 147, 227, 149, 6, -1, - 74, 50, 141, 219, 142, 7, 148, 221, 147, 227, - 149, 6, -1, 74, 4, 141, 219, 142, 7, 224, - 6, -1, 74, 4, 141, 219, 142, 7, 5, 6, - -1, 74, 4, 148, 219, 149, 6, -1, 74, 4, - 141, 219, 142, 7, 148, 221, 147, 221, 147, 227, - 149, 6, -1, 79, 148, 186, 149, -1, 79, 104, - 143, 219, 144, 6, -1, 79, 4, 143, 219, 144, + 154, 0, -1, 155, -1, 1, 6, -1, -1, 155, + 156, -1, 159, -1, 158, -1, 177, -1, 181, -1, + 186, -1, 190, -1, 191, -1, 192, -1, 195, -1, + 216, -1, 217, -1, 218, -1, 219, -1, 194, -1, + 193, -1, 189, -1, 220, -1, 130, -1, 130, 130, + -1, 35, 143, 5, 144, 6, -1, 35, 143, 5, + 144, 157, 233, 6, -1, 35, 143, 5, 149, 229, + 144, 6, -1, 35, 143, 5, 149, 229, 144, 157, + 233, 6, -1, 4, 5, 150, 160, 151, 6, -1, + 84, 4, 145, 221, 146, 6, -1, 85, 4, 145, + 221, 146, 6, -1, -1, 160, 163, -1, 160, 167, + -1, 160, 170, -1, 160, 172, -1, 160, 173, -1, + 221, -1, 161, 149, 221, -1, 221, -1, 162, 149, + 221, -1, -1, -1, 4, 164, 143, 161, 144, 165, + 150, 162, 151, 6, -1, 233, -1, 166, 149, 233, + -1, -1, 86, 143, 221, 149, 221, 149, 221, 144, + 168, 150, 166, 151, 6, -1, 233, -1, 169, 149, + 233, -1, -1, 87, 143, 221, 149, 221, 149, 221, + 149, 221, 144, 171, 150, 169, 151, 6, -1, 88, + 150, 225, 151, 150, 225, 151, 6, -1, 88, 150, + 225, 151, 150, 225, 151, 150, 225, 151, 150, 225, + 151, 6, -1, -1, 89, 174, 150, 162, 151, 6, + -1, 7, -1, 123, -1, 122, -1, 121, -1, 120, + -1, 141, -1, 140, -1, 4, 175, 221, 6, -1, + 4, 145, 221, 146, 175, 221, 6, -1, 4, 145, + 150, 229, 151, 146, 175, 226, 6, -1, 4, 145, + 146, 7, 226, 6, -1, 4, 145, 146, 123, 226, + 6, -1, 4, 176, 6, -1, 4, 145, 221, 146, + 176, 6, -1, 4, 7, 234, 6, -1, 4, 147, + 4, 7, 234, 6, -1, 4, 145, 221, 146, 147, + 4, 7, 234, 6, -1, 4, 147, 4, 175, 221, + 6, -1, 4, 145, 221, 146, 147, 4, 175, 221, + 6, -1, 4, 147, 4, 176, 6, -1, 4, 145, + 221, 146, 147, 4, 176, 6, -1, 4, 147, 96, + 147, 4, 7, 230, 6, -1, 4, 145, 221, 146, + 147, 96, 147, 4, 7, 230, 6, -1, 4, 147, + 97, 7, 231, 6, -1, 4, 145, 221, 146, 147, + 97, 7, 231, 6, -1, 4, 104, 7, 221, 6, + -1, 104, 145, 221, 146, 7, 4, 6, -1, 104, + 145, 221, 146, 147, 4, 7, 221, 6, -1, 104, + 145, 221, 146, 147, 4, 7, 234, 6, -1, 104, + 145, 221, 146, 147, 4, 7, 150, 229, 151, 6, + -1, 67, 143, 4, 144, 147, 4, 7, 221, 6, + -1, 67, 143, 4, 144, 147, 4, 7, 234, 6, + -1, 221, -1, 234, -1, -1, 99, 50, 150, 221, + 151, -1, -1, 59, 223, -1, 46, 143, 221, 144, + 7, 223, 6, -1, -1, 63, 46, 182, 143, 178, + 144, 7, 226, 6, -1, 55, 56, 226, 7, 221, + 6, -1, 49, 143, 221, 144, 7, 226, 6, -1, + 68, 49, 226, 6, -1, 53, 143, 221, 144, 7, + 226, 6, -1, 47, 143, 221, 144, 7, 226, 180, + 6, -1, 48, 143, 221, 144, 7, 226, 180, 6, + -1, 91, 143, 221, 144, 7, 226, 6, -1, 92, + 143, 221, 144, 7, 226, 6, -1, 93, 143, 221, + 144, 7, 226, 95, 226, 94, 221, 6, -1, 49, + 75, 143, 221, 144, 7, 226, 6, -1, 64, 49, + 143, 221, 144, 7, 226, 6, -1, -1, 63, 49, + 183, 143, 178, 144, 7, 226, 6, -1, 59, 52, + 143, 221, 144, 7, 226, 6, -1, 60, 52, 143, + 221, 144, 7, 226, 179, 6, -1, 12, 13, 6, + -1, 13, 52, 221, 6, -1, 57, 52, 143, 221, + 144, 7, 5, 5, 5, 6, -1, 50, 143, 221, + 144, 7, 226, 6, -1, 51, 143, 221, 144, 7, + 226, 6, -1, 52, 75, 143, 221, 144, 7, 226, + 6, -1, 64, 52, 143, 221, 144, 7, 226, 211, + 6, -1, 64, 52, 143, 221, 144, 7, 226, 4, + 150, 225, 151, 211, 6, -1, -1, 63, 52, 184, + 143, 178, 144, 7, 226, 6, -1, 62, 54, 143, + 221, 144, 7, 226, 6, -1, 54, 143, 221, 144, + 7, 226, 6, -1, 64, 54, 143, 221, 144, 7, + 226, 6, -1, -1, 63, 54, 185, 143, 178, 144, + 7, 226, 6, -1, 70, 223, 150, 187, 151, -1, + 69, 150, 223, 149, 223, 149, 221, 151, 150, 187, + 151, -1, 71, 223, 150, 187, 151, -1, 72, 150, + 223, 149, 221, 151, 150, 187, 151, -1, 4, 150, + 187, 151, -1, 81, 49, 150, 229, 151, 52, 150, + 221, 151, -1, 78, 49, 143, 221, 144, 150, 229, + 151, 6, -1, 188, -1, 186, -1, -1, 188, 181, + -1, 188, 46, 150, 229, 151, 6, -1, 188, 49, + 150, 229, 151, 6, -1, 188, 52, 150, 229, 151, + 6, -1, 188, 54, 150, 229, 151, 6, -1, 74, + 59, 143, 221, 144, 7, 226, 6, -1, 74, 59, + 143, 221, 144, 7, 150, 223, 149, 223, 149, 229, + 151, 6, -1, 74, 59, 143, 221, 144, 7, 150, + 223, 149, 223, 149, 223, 149, 229, 151, 6, -1, + 74, 50, 143, 221, 144, 7, 150, 223, 149, 229, + 151, 6, -1, 74, 4, 143, 221, 144, 7, 226, + 6, -1, 74, 4, 143, 221, 144, 7, 5, 6, + -1, 74, 4, 150, 221, 151, 6, -1, 74, 4, + 143, 221, 144, 7, 150, 223, 149, 223, 149, 229, + 151, 6, -1, 79, 150, 188, 151, -1, 79, 104, + 145, 221, 146, 6, -1, 79, 4, 145, 221, 146, 6, -1, 79, 4, 6, -1, 79, 4, 4, 6, - -1, 96, 228, 148, 186, 149, -1, 108, 5, 6, - -1, 109, 5, 6, -1, 108, 148, 186, 149, -1, - 109, 148, 186, 149, -1, 4, 232, 6, -1, 4, - 4, 143, 219, 144, 231, 6, -1, 4, 4, 4, - 143, 219, 144, 6, -1, 4, 219, 6, -1, 67, - 141, 4, 142, 145, 4, 6, -1, 90, 4, 6, + -1, 96, 230, 150, 188, 151, -1, 108, 5, 6, + -1, 109, 5, 6, -1, 108, 150, 188, 151, -1, + 109, 150, 188, 151, -1, 4, 234, 6, -1, 4, + 4, 145, 221, 146, 233, 6, -1, 4, 4, 4, + 145, 221, 146, 6, -1, 4, 221, 6, -1, 67, + 143, 4, 144, 147, 4, 6, -1, 90, 4, 6, -1, 103, 6, -1, 43, 6, -1, 40, 6, -1, - 40, 148, 219, 147, 219, 147, 219, 147, 219, 147, - 219, 147, 219, 149, 6, -1, 41, 6, -1, 44, - 6, -1, 98, 141, 219, 8, 219, 142, -1, 98, - 141, 219, 8, 219, 8, 219, 142, -1, 98, 4, - 99, 148, 219, 8, 219, 149, -1, 98, 4, 99, - 148, 219, 8, 219, 8, 219, 149, -1, 100, -1, + 40, 150, 221, 149, 221, 149, 221, 149, 221, 149, + 221, 149, 221, 151, 6, -1, 41, 6, -1, 44, + 6, -1, 98, 143, 221, 8, 221, 144, -1, 98, + 143, 221, 8, 221, 8, 221, 144, -1, 98, 4, + 99, 150, 221, 8, 221, 151, -1, 98, 4, 99, + 150, 221, 8, 221, 8, 221, 151, -1, 100, -1, 107, 4, -1, 105, -1, 106, 4, 6, -1, 101, - 141, 219, 142, -1, 102, -1, 73, 221, 148, 186, - 149, -1, 73, 148, 221, 147, 221, 147, 219, 149, - 148, 186, 149, -1, 73, 148, 221, 147, 221, 147, - 221, 147, 219, 149, 148, 186, 149, -1, -1, 73, - 221, 148, 186, 194, 207, 149, -1, -1, 73, 148, - 221, 147, 221, 147, 219, 149, 148, 186, 195, 207, - 149, -1, -1, 73, 148, 221, 147, 221, 147, 221, - 147, 219, 149, 148, 186, 196, 207, 149, -1, -1, - 73, 148, 186, 197, 207, 149, -1, 73, 46, 148, - 219, 147, 221, 149, 6, -1, 73, 49, 148, 219, - 147, 221, 149, 6, -1, 73, 52, 148, 219, 147, - 221, 149, 6, -1, 73, 46, 148, 219, 147, 221, - 147, 221, 147, 219, 149, 6, -1, 73, 49, 148, - 219, 147, 221, 147, 221, 147, 219, 149, 6, -1, - 73, 52, 148, 219, 147, 221, 147, 221, 147, 219, - 149, 6, -1, 73, 46, 148, 219, 147, 221, 147, - 221, 147, 221, 147, 219, 149, 6, -1, 73, 49, - 148, 219, 147, 221, 147, 221, 147, 221, 147, 219, - 149, 6, -1, 73, 52, 148, 219, 147, 221, 147, - 221, 147, 221, 147, 219, 149, 6, -1, -1, 73, - 46, 148, 219, 147, 221, 149, 198, 148, 207, 149, - 6, -1, -1, 73, 49, 148, 219, 147, 221, 149, - 199, 148, 207, 149, 6, -1, -1, 73, 52, 148, - 219, 147, 221, 149, 200, 148, 207, 149, 6, -1, - -1, 73, 46, 148, 219, 147, 221, 147, 221, 147, - 219, 149, 201, 148, 207, 149, 6, -1, -1, 73, - 49, 148, 219, 147, 221, 147, 221, 147, 219, 149, - 202, 148, 207, 149, 6, -1, -1, 73, 52, 148, - 219, 147, 221, 147, 221, 147, 219, 149, 203, 148, - 207, 149, 6, -1, -1, 73, 46, 148, 219, 147, - 221, 147, 221, 147, 221, 147, 219, 149, 204, 148, - 207, 149, 6, -1, -1, 73, 49, 148, 219, 147, - 221, 147, 221, 147, 221, 147, 219, 149, 205, 148, - 207, 149, 6, -1, -1, 73, 52, 148, 219, 147, - 221, 147, 221, 147, 221, 147, 219, 149, 206, 148, - 207, 149, 6, -1, 208, -1, 207, 208, -1, 82, - 148, 219, 149, 6, -1, 82, 148, 224, 147, 224, - 149, 6, -1, 82, 148, 224, 147, 224, 147, 224, - 149, 6, -1, 76, 6, -1, 83, 141, 219, 142, - 7, 224, 66, 219, 6, -1, -1, 4, -1, -1, - 66, 4, 219, -1, -1, 4, -1, -1, 7, 224, - -1, -1, 7, 219, -1, 61, 49, 225, 7, 219, - 210, 6, -1, 61, 52, 225, 212, 211, 6, -1, - 58, 52, 148, 219, 149, 7, 224, 6, -1, 61, - 54, 225, 212, 6, -1, 76, 52, 225, 213, 6, - -1, 77, 52, 224, 7, 219, 6, -1, 65, 49, - 224, 7, 224, 6, -1, 65, 52, 224, 7, 224, - 6, -1, 46, 148, 227, 149, 99, 52, 148, 219, - 149, 6, -1, 49, 148, 227, 149, 99, 52, 148, - 219, 149, 6, -1, 49, 148, 227, 149, 99, 54, - 148, 219, 149, 6, -1, 52, 148, 227, 149, 99, - 54, 148, 219, 149, 6, -1, 80, 6, -1, 80, - 4, 6, -1, 114, 141, 231, 142, 7, 148, 224, - 147, 224, 149, 6, -1, 115, 141, 231, 142, 7, - 148, 224, 147, 224, 149, 6, -1, 116, 141, 231, - 142, 7, 148, 224, 147, 224, 149, 6, -1, 117, - 141, 231, 142, 7, 148, 224, 147, 224, 149, 6, - -1, 220, -1, 141, 219, 142, -1, 132, 219, -1, - 131, 219, -1, 136, 219, -1, 219, 132, 219, -1, - 219, 131, 219, -1, 219, 133, 219, -1, 219, 134, - 219, -1, 219, 135, 219, -1, 219, 140, 219, -1, - 219, 127, 219, -1, 219, 128, 219, -1, 219, 130, - 219, -1, 219, 129, 219, -1, 219, 126, 219, -1, - 219, 125, 219, -1, 219, 124, 219, -1, 219, 123, - 219, -1, 219, 122, 219, 8, 219, -1, 14, 141, - 219, 142, -1, 15, 141, 219, 142, -1, 16, 141, - 219, 142, -1, 17, 141, 219, 142, -1, 18, 141, - 219, 142, -1, 19, 141, 219, 142, -1, 20, 141, - 219, 142, -1, 21, 141, 219, 142, -1, 22, 141, - 219, 142, -1, 24, 141, 219, 142, -1, 25, 141, - 219, 147, 219, 142, -1, 26, 141, 219, 142, -1, - 27, 141, 219, 142, -1, 28, 141, 219, 142, -1, - 29, 141, 219, 142, -1, 30, 141, 219, 142, -1, - 31, 141, 219, 142, -1, 32, 141, 219, 147, 219, - 142, -1, 33, 141, 219, 147, 219, 142, -1, 34, - 141, 219, 147, 219, 142, -1, 23, 141, 219, 142, - -1, 14, 143, 219, 144, -1, 15, 143, 219, 144, - -1, 16, 143, 219, 144, -1, 17, 143, 219, 144, - -1, 18, 143, 219, 144, -1, 19, 143, 219, 144, - -1, 20, 143, 219, 144, -1, 21, 143, 219, 144, - -1, 22, 143, 219, 144, -1, 24, 143, 219, 144, - -1, 25, 143, 219, 147, 219, 144, -1, 26, 143, - 219, 144, -1, 27, 143, 219, 144, -1, 28, 143, - 219, 144, -1, 29, 143, 219, 144, -1, 30, 143, - 219, 144, -1, 31, 143, 219, 144, -1, 32, 143, - 219, 147, 219, 144, -1, 33, 143, 219, 147, 219, - 144, -1, 34, 143, 219, 147, 219, 144, -1, 23, - 143, 219, 144, -1, 3, -1, 9, -1, 10, -1, - 11, -1, 111, -1, 112, -1, 113, -1, 4, -1, - 4, 150, 148, 219, 149, -1, 4, 143, 219, 144, - -1, 146, 4, 143, 144, -1, 4, 174, -1, 4, - 143, 219, 144, 174, -1, 4, 145, 4, -1, 4, - 143, 219, 144, 145, 4, -1, 4, 145, 4, 174, - -1, 4, 143, 219, 144, 145, 4, 174, -1, 110, - 141, 5, 147, 219, 142, -1, 222, -1, 132, 221, - -1, 131, 221, -1, 221, 132, 221, -1, 221, 131, - 221, -1, 148, 219, 147, 219, 147, 219, 147, 219, - 147, 219, 149, -1, 148, 219, 147, 219, 147, 219, - 147, 219, 149, -1, 148, 219, 147, 219, 147, 219, - 149, -1, 141, 219, 147, 219, 147, 219, 142, -1, - 224, -1, 223, 147, 224, -1, 219, -1, 226, -1, - 148, 149, -1, 148, 227, 149, -1, 132, 148, 227, - 149, -1, 219, 133, 148, 227, 149, -1, 224, -1, - 5, -1, 132, 226, -1, 219, 133, 226, -1, 219, - 8, 219, -1, 219, 8, 219, 8, 219, -1, 46, - 148, 219, 149, -1, 184, -1, 193, -1, 4, 143, - 144, -1, 4, 143, 148, 227, 149, 144, -1, 219, - -1, 226, -1, 227, 147, 219, -1, 227, 147, 226, - -1, 148, 219, 147, 219, 147, 219, 147, 219, 149, - -1, 148, 219, 147, 219, 147, 219, 149, -1, 4, - -1, 4, 145, 96, 145, 4, -1, 148, 230, 149, - -1, 4, 143, 219, 144, 145, 97, -1, 228, -1, - 230, 147, 228, -1, 232, -1, 4, -1, 4, 145, - 4, -1, 4, 143, 219, 144, 145, 4, -1, 5, - -1, 42, -1, 37, 141, 231, 147, 231, 142, -1, - 38, 141, 231, 142, -1, 39, 141, 231, 142, -1, - 36, 141, 231, 142, -1, 36, 141, 231, 147, 227, - 142, -1 + 143, 221, 144, -1, 102, -1, 73, 223, 150, 188, + 151, -1, 73, 150, 223, 149, 223, 149, 221, 151, + 150, 188, 151, -1, 73, 150, 223, 149, 223, 149, + 223, 149, 221, 151, 150, 188, 151, -1, -1, 73, + 223, 150, 188, 196, 209, 151, -1, -1, 73, 150, + 223, 149, 223, 149, 221, 151, 150, 188, 197, 209, + 151, -1, -1, 73, 150, 223, 149, 223, 149, 223, + 149, 221, 151, 150, 188, 198, 209, 151, -1, -1, + 73, 150, 188, 199, 209, 151, -1, 73, 46, 150, + 221, 149, 223, 151, 6, -1, 73, 49, 150, 221, + 149, 223, 151, 6, -1, 73, 52, 150, 221, 149, + 223, 151, 6, -1, 73, 46, 150, 221, 149, 223, + 149, 223, 149, 221, 151, 6, -1, 73, 49, 150, + 221, 149, 223, 149, 223, 149, 221, 151, 6, -1, + 73, 52, 150, 221, 149, 223, 149, 223, 149, 221, + 151, 6, -1, 73, 46, 150, 221, 149, 223, 149, + 223, 149, 223, 149, 221, 151, 6, -1, 73, 49, + 150, 221, 149, 223, 149, 223, 149, 223, 149, 221, + 151, 6, -1, 73, 52, 150, 221, 149, 223, 149, + 223, 149, 223, 149, 221, 151, 6, -1, -1, 73, + 46, 150, 221, 149, 223, 151, 200, 150, 209, 151, + 6, -1, -1, 73, 49, 150, 221, 149, 223, 151, + 201, 150, 209, 151, 6, -1, -1, 73, 52, 150, + 221, 149, 223, 151, 202, 150, 209, 151, 6, -1, + -1, 73, 46, 150, 221, 149, 223, 149, 223, 149, + 221, 151, 203, 150, 209, 151, 6, -1, -1, 73, + 49, 150, 221, 149, 223, 149, 223, 149, 221, 151, + 204, 150, 209, 151, 6, -1, -1, 73, 52, 150, + 221, 149, 223, 149, 223, 149, 221, 151, 205, 150, + 209, 151, 6, -1, -1, 73, 46, 150, 221, 149, + 223, 149, 223, 149, 223, 149, 221, 151, 206, 150, + 209, 151, 6, -1, -1, 73, 49, 150, 221, 149, + 223, 149, 223, 149, 223, 149, 221, 151, 207, 150, + 209, 151, 6, -1, -1, 73, 52, 150, 221, 149, + 223, 149, 223, 149, 223, 149, 221, 151, 208, 150, + 209, 151, 6, -1, 210, -1, 209, 210, -1, 82, + 150, 221, 151, 6, -1, 82, 150, 226, 149, 226, + 151, 6, -1, 82, 150, 226, 149, 226, 149, 226, + 151, 6, -1, 76, 6, -1, 83, 143, 221, 144, + 7, 226, 66, 221, 6, -1, -1, 4, -1, -1, + 66, 4, 221, -1, -1, 4, -1, -1, 7, 226, + -1, -1, 7, 221, -1, 61, 49, 227, 7, 221, + 212, 6, -1, 61, 52, 227, 214, 213, 6, -1, + 58, 52, 150, 221, 151, 7, 226, 6, -1, 61, + 54, 227, 214, 6, -1, 76, 52, 227, 215, 6, + -1, 77, 52, 226, 7, 221, 6, -1, 65, 49, + 226, 7, 226, 6, -1, 65, 52, 226, 7, 226, + 6, -1, 46, 150, 229, 151, 99, 52, 150, 221, + 151, 6, -1, 49, 150, 229, 151, 99, 52, 150, + 221, 151, 6, -1, 49, 150, 229, 151, 99, 54, + 150, 221, 151, 6, -1, 52, 150, 229, 151, 99, + 54, 150, 221, 151, 6, -1, 80, 6, -1, 80, + 4, 6, -1, 116, 143, 233, 144, 7, 150, 226, + 149, 226, 151, 6, -1, 117, 143, 233, 144, 7, + 150, 226, 149, 226, 151, 6, -1, 118, 143, 233, + 144, 7, 150, 226, 149, 226, 151, 6, -1, 119, + 143, 233, 144, 7, 150, 226, 149, 226, 151, 6, + -1, 222, -1, 143, 221, 144, -1, 134, 221, -1, + 133, 221, -1, 138, 221, -1, 221, 134, 221, -1, + 221, 133, 221, -1, 221, 135, 221, -1, 221, 136, + 221, -1, 221, 137, 221, -1, 221, 142, 221, -1, + 221, 129, 221, -1, 221, 130, 221, -1, 221, 132, + 221, -1, 221, 131, 221, -1, 221, 128, 221, -1, + 221, 127, 221, -1, 221, 126, 221, -1, 221, 125, + 221, -1, 221, 124, 221, 8, 221, -1, 14, 143, + 221, 144, -1, 15, 143, 221, 144, -1, 16, 143, + 221, 144, -1, 17, 143, 221, 144, -1, 18, 143, + 221, 144, -1, 19, 143, 221, 144, -1, 20, 143, + 221, 144, -1, 21, 143, 221, 144, -1, 22, 143, + 221, 144, -1, 24, 143, 221, 144, -1, 25, 143, + 221, 149, 221, 144, -1, 26, 143, 221, 144, -1, + 27, 143, 221, 144, -1, 28, 143, 221, 144, -1, + 29, 143, 221, 144, -1, 30, 143, 221, 144, -1, + 31, 143, 221, 144, -1, 32, 143, 221, 149, 221, + 144, -1, 33, 143, 221, 149, 221, 144, -1, 34, + 143, 221, 149, 221, 144, -1, 23, 143, 221, 144, + -1, 14, 145, 221, 146, -1, 15, 145, 221, 146, + -1, 16, 145, 221, 146, -1, 17, 145, 221, 146, + -1, 18, 145, 221, 146, -1, 19, 145, 221, 146, + -1, 20, 145, 221, 146, -1, 21, 145, 221, 146, + -1, 22, 145, 221, 146, -1, 24, 145, 221, 146, + -1, 25, 145, 221, 149, 221, 146, -1, 26, 145, + 221, 146, -1, 27, 145, 221, 146, -1, 28, 145, + 221, 146, -1, 29, 145, 221, 146, -1, 30, 145, + 221, 146, -1, 31, 145, 221, 146, -1, 32, 145, + 221, 149, 221, 146, -1, 33, 145, 221, 149, 221, + 146, -1, 34, 145, 221, 149, 221, 146, -1, 23, + 145, 221, 146, -1, 3, -1, 9, -1, 10, -1, + 11, -1, 113, -1, 114, -1, 115, -1, 4, -1, + 4, 152, 150, 221, 151, -1, 4, 145, 221, 146, + -1, 148, 4, 145, 146, -1, 4, 176, -1, 4, + 145, 221, 146, 176, -1, 4, 147, 4, -1, 4, + 145, 221, 146, 147, 4, -1, 4, 147, 4, 176, + -1, 4, 145, 221, 146, 147, 4, 176, -1, 110, + 143, 233, 149, 221, 144, -1, 224, -1, 134, 223, + -1, 133, 223, -1, 223, 134, 223, -1, 223, 133, + 223, -1, 150, 221, 149, 221, 149, 221, 149, 221, + 149, 221, 151, -1, 150, 221, 149, 221, 149, 221, + 149, 221, 151, -1, 150, 221, 149, 221, 149, 221, + 151, -1, 143, 221, 149, 221, 149, 221, 144, -1, + 226, -1, 225, 149, 226, -1, 221, -1, 228, -1, + 150, 151, -1, 150, 229, 151, -1, 134, 150, 229, + 151, -1, 221, 135, 150, 229, 151, -1, 226, -1, + 5, -1, 134, 228, -1, 221, 135, 228, -1, 221, + 8, 221, -1, 221, 8, 221, 8, 221, -1, 46, + 150, 221, 151, -1, 186, -1, 195, -1, 4, 145, + 146, -1, 4, 145, 150, 229, 151, 146, -1, 221, + -1, 228, -1, 229, 149, 221, -1, 229, 149, 228, + -1, 150, 221, 149, 221, 149, 221, 149, 221, 151, + -1, 150, 221, 149, 221, 149, 221, 151, -1, 4, + -1, 4, 147, 96, 147, 4, -1, 150, 232, 151, + -1, 4, 145, 221, 146, 147, 97, -1, 230, -1, + 232, 149, 230, -1, 234, -1, 4, -1, 4, 147, + 4, -1, 4, 145, 221, 146, 147, 4, -1, 5, + -1, 42, -1, 111, 143, 233, 144, -1, 112, 143, + 233, 149, 233, 144, -1, 37, 143, 233, 149, 233, + 144, -1, 38, 143, 233, 144, -1, 39, 143, 233, + 144, -1, 36, 143, 233, 144, -1, 36, 143, 233, + 149, 229, 144, -1 }; /* YYRLINE[YYN] -- source line where rule number YYN was defined. */ @@ -1064,7 +1069,7 @@ static const yytype_uint16 yyrline[] = 3799, 3803, 3811, 3822, 3826, 3838, 3846, 3854, 3861, 3872, 3892, 3902, 3912, 3922, 3942, 3947, 3951, 3955, 3967, 3971, 3983, 3990, 4000, 4004, 4019, 4024, 4031, 4035, 4048, 4056, - 4067, 4071, 4079, 4087, 4101, 4115, 4119 + 4067, 4071, 4079, 4087, 4095, 4103, 4117, 4131, 4135 }; #endif @@ -1091,23 +1096,23 @@ static const char *const yytname[] = "tInterpolationScheme", "tTime", "tCombine", "tBSpline", "tBezier", "tNurbs", "tNurbsOrder", "tNurbsKnots", "tColor", "tColorTable", "tFor", "tIn", "tEndFor", "tIf", "tEndIf", "tExit", "tField", "tReturn", "tCall", - "tFunction", "tShow", "tHide", "tGetValue", "tGMSH_MAJOR_VERSION", - "tGMSH_MINOR_VERSION", "tGMSH_PATCH_VERSION", "tHomRank", "tHomGen", - "tHomCut", "tHomSeq", "tAFFECTDIVIDE", "tAFFECTTIMES", "tAFFECTMINUS", - "tAFFECTPLUS", "'?'", "tOR", "tAND", "tNOTEQUAL", "tEQUAL", "'<'", "'>'", - "tGREATEROREQUAL", "tLESSOREQUAL", "'+'", "'-'", "'*'", "'/'", "'%'", - "'!'", "UNARYPREC", "tMINUSMINUS", "tPLUSPLUS", "'^'", "'('", "')'", - "'['", "']'", "'.'", "'#'", "','", "'{'", "'}'", "'~'", "$accept", "All", - "GeoFormatItems", "GeoFormatItem", "SendToFile", "Printf", "View", - "Views", "ElementCoords", "ElementValues", "Element", "@1", "@2", - "Text2DValues", "Text2D", "@3", "Text3DValues", "Text3D", "@4", - "InterpolationMatrix", "Time", "@5", "NumericAffectation", - "NumericIncrement", "Affectation", "PhysicalId", "InSphereCenter", - "CircleOptions", "Shape", "@6", "@7", "@8", "@9", "Transform", - "MultipleShape", "ListOfShapes", "LevelSet", "Delete", "Colorify", - "Visibility", "Command", "Loop", "Extrude", "@10", "@11", "@12", "@13", - "@14", "@15", "@16", "@17", "@18", "@19", "@20", "@21", "@22", - "ExtrudeParameters", "ExtrudeParameter", "CompoundMap", + "tFunction", "tShow", "tHide", "tGetValue", "tGetEnv", "tGetString", + "tGMSH_MAJOR_VERSION", "tGMSH_MINOR_VERSION", "tGMSH_PATCH_VERSION", + "tHomRank", "tHomGen", "tHomCut", "tHomSeq", "tAFFECTDIVIDE", + "tAFFECTTIMES", "tAFFECTMINUS", "tAFFECTPLUS", "'?'", "tOR", "tAND", + "tNOTEQUAL", "tEQUAL", "'<'", "'>'", "tGREATEROREQUAL", "tLESSOREQUAL", + "'+'", "'-'", "'*'", "'/'", "'%'", "'!'", "UNARYPREC", "tMINUSMINUS", + "tPLUSPLUS", "'^'", "'('", "')'", "'['", "']'", "'.'", "'#'", "','", + "'{'", "'}'", "'~'", "$accept", "All", "GeoFormatItems", "GeoFormatItem", + "SendToFile", "Printf", "View", "Views", "ElementCoords", + "ElementValues", "Element", "@1", "@2", "Text2DValues", "Text2D", "@3", + "Text3DValues", "Text3D", "@4", "InterpolationMatrix", "Time", "@5", + "NumericAffectation", "NumericIncrement", "Affectation", "PhysicalId", + "InSphereCenter", "CircleOptions", "Shape", "@6", "@7", "@8", "@9", + "Transform", "MultipleShape", "ListOfShapes", "LevelSet", "Delete", + "Colorify", "Visibility", "Command", "Loop", "Extrude", "@10", "@11", + "@12", "@13", "@14", "@15", "@16", "@17", "@18", "@19", "@20", "@21", + "@22", "ExtrudeParameters", "ExtrudeParameter", "CompoundMap", "TransfiniteType", "TransfiniteArrangement", "TransfiniteCorners", "RecombineAngle", "Transfinite", "Periodic", "Embedding", "Coherence", "Homology", "FExpr", "FExpr_Single", "VExpr", "VExpr_Single", @@ -1134,55 +1139,55 @@ static const yytype_uint16 yytoknum[] = 345, 346, 347, 348, 349, 350, 351, 352, 353, 354, 355, 356, 357, 358, 359, 360, 361, 362, 363, 364, 365, 366, 367, 368, 369, 370, 371, 372, 373, 374, - 375, 376, 63, 377, 378, 379, 380, 60, 62, 381, - 382, 43, 45, 42, 47, 37, 33, 383, 384, 385, - 94, 40, 41, 91, 93, 46, 35, 44, 123, 125, - 126 + 375, 376, 377, 378, 63, 379, 380, 381, 382, 60, + 62, 383, 384, 43, 45, 42, 47, 37, 33, 385, + 386, 387, 94, 40, 41, 91, 93, 46, 35, 44, + 123, 125, 126 }; # endif /* YYR1[YYN] -- Symbol number of symbol that rule YYN derives. */ static const yytype_uint8 yyr1[] = { - 0, 151, 152, 152, 153, 153, 154, 154, 154, 154, - 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, - 154, 154, 154, 155, 155, 156, 156, 156, 156, 157, - 157, 157, 158, 158, 158, 158, 158, 158, 159, 159, - 160, 160, 162, 163, 161, 164, 164, 166, 165, 167, - 167, 169, 168, 170, 170, 172, 171, 173, 173, 173, - 173, 173, 174, 174, 175, 175, 175, 175, 175, 175, - 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, - 175, 175, 175, 175, 175, 175, 175, 175, 175, 176, - 176, 177, 177, 178, 178, 179, 180, 179, 179, 179, - 179, 179, 179, 179, 179, 179, 179, 179, 179, 181, - 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, - 179, 182, 179, 179, 179, 179, 183, 179, 184, 184, - 184, 184, 184, 184, 184, 185, 185, 186, 186, 186, - 186, 186, 186, 187, 187, 187, 187, 187, 187, 187, - 187, 188, 188, 188, 188, 188, 189, 190, 190, 190, - 190, 191, 191, 191, 191, 191, 191, 191, 191, 191, - 191, 191, 191, 192, 192, 192, 192, 192, 192, 192, - 192, 192, 192, 193, 193, 193, 194, 193, 195, 193, - 196, 193, 197, 193, 193, 193, 193, 193, 193, 193, - 193, 193, 193, 198, 193, 199, 193, 200, 193, 201, - 193, 202, 193, 203, 193, 204, 193, 205, 193, 206, - 193, 207, 207, 208, 208, 208, 208, 208, 209, 209, - 210, 210, 211, 211, 212, 212, 213, 213, 214, 214, - 214, 214, 214, 214, 215, 215, 216, 216, 216, 216, - 217, 217, 218, 218, 218, 218, 219, 219, 219, 219, - 219, 219, 219, 219, 219, 219, 219, 219, 219, 219, - 219, 219, 219, 219, 219, 219, 219, 219, 219, 219, - 219, 219, 219, 219, 219, 219, 219, 219, 219, 219, - 219, 219, 219, 219, 219, 219, 219, 219, 219, 219, - 219, 219, 219, 219, 219, 219, 219, 219, 219, 219, - 219, 219, 219, 219, 219, 219, 219, 219, 220, 220, - 220, 220, 220, 220, 220, 220, 220, 220, 220, 220, - 220, 220, 220, 220, 220, 220, 221, 221, 221, 221, - 221, 222, 222, 222, 222, 223, 223, 224, 224, 224, - 224, 224, 224, 225, 225, 226, 226, 226, 226, 226, - 226, 226, 226, 226, 227, 227, 227, 227, 228, 228, - 228, 228, 229, 229, 230, 230, 231, 231, 231, 231, - 232, 232, 232, 232, 232, 232, 232 + 0, 153, 154, 154, 155, 155, 156, 156, 156, 156, + 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, + 156, 156, 156, 157, 157, 158, 158, 158, 158, 159, + 159, 159, 160, 160, 160, 160, 160, 160, 161, 161, + 162, 162, 164, 165, 163, 166, 166, 168, 167, 169, + 169, 171, 170, 172, 172, 174, 173, 175, 175, 175, + 175, 175, 176, 176, 177, 177, 177, 177, 177, 177, + 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, + 177, 177, 177, 177, 177, 177, 177, 177, 177, 178, + 178, 179, 179, 180, 180, 181, 182, 181, 181, 181, + 181, 181, 181, 181, 181, 181, 181, 181, 181, 183, + 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, + 181, 184, 181, 181, 181, 181, 185, 181, 186, 186, + 186, 186, 186, 186, 186, 187, 187, 188, 188, 188, + 188, 188, 188, 189, 189, 189, 189, 189, 189, 189, + 189, 190, 190, 190, 190, 190, 191, 192, 192, 192, + 192, 193, 193, 193, 193, 193, 193, 193, 193, 193, + 193, 193, 193, 194, 194, 194, 194, 194, 194, 194, + 194, 194, 194, 195, 195, 195, 196, 195, 197, 195, + 198, 195, 199, 195, 195, 195, 195, 195, 195, 195, + 195, 195, 195, 200, 195, 201, 195, 202, 195, 203, + 195, 204, 195, 205, 195, 206, 195, 207, 195, 208, + 195, 209, 209, 210, 210, 210, 210, 210, 211, 211, + 212, 212, 213, 213, 214, 214, 215, 215, 216, 216, + 216, 216, 216, 216, 217, 217, 218, 218, 218, 218, + 219, 219, 220, 220, 220, 220, 221, 221, 221, 221, + 221, 221, 221, 221, 221, 221, 221, 221, 221, 221, + 221, 221, 221, 221, 221, 221, 221, 221, 221, 221, + 221, 221, 221, 221, 221, 221, 221, 221, 221, 221, + 221, 221, 221, 221, 221, 221, 221, 221, 221, 221, + 221, 221, 221, 221, 221, 221, 221, 221, 221, 221, + 221, 221, 221, 221, 221, 221, 221, 221, 222, 222, + 222, 222, 222, 222, 222, 222, 222, 222, 222, 222, + 222, 222, 222, 222, 222, 222, 223, 223, 223, 223, + 223, 224, 224, 224, 224, 225, 225, 226, 226, 226, + 226, 226, 226, 227, 227, 228, 228, 228, 228, 228, + 228, 228, 228, 228, 229, 229, 229, 229, 230, 230, + 230, 230, 231, 231, 232, 232, 233, 233, 233, 233, + 234, 234, 234, 234, 234, 234, 234, 234, 234 }; /* YYR2[YYN] -- Number of symbols composing right hand side of rule YYN. */ @@ -1226,7 +1231,7 @@ static const yytype_uint8 yyr2[] = 3, 4, 5, 1, 1, 2, 3, 3, 5, 4, 1, 1, 3, 6, 1, 1, 3, 3, 9, 7, 1, 5, 3, 6, 1, 3, 1, 1, 3, 6, - 1, 1, 6, 4, 4, 4, 6 + 1, 1, 4, 6, 6, 4, 4, 4, 6 }; /* YYDEFACT[STATE-NAME] -- Default rule to reduce with in state @@ -1246,89 +1251,90 @@ static const yytype_uint16 yydefact[] = 57, 319, 320, 321, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 381, - 0, 0, 322, 323, 324, 61, 60, 59, 58, 0, - 0, 0, 63, 62, 0, 0, 0, 0, 137, 0, - 0, 0, 256, 0, 0, 0, 0, 169, 0, 171, - 168, 172, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 322, 323, 324, 61, 60, 59, + 58, 0, 0, 0, 63, 62, 0, 0, 0, 0, + 137, 0, 0, 0, 256, 0, 0, 0, 0, 169, + 0, 171, 168, 172, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 96, 109, 121, 126, 0, 0, + 0, 0, 0, 0, 0, 0, 96, 109, 121, 126, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 336, 0, 0, 0, 0, 0, 137, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 137, 0, 250, - 0, 0, 0, 0, 0, 0, 0, 370, 0, 0, - 0, 0, 0, 167, 0, 0, 178, 0, 137, 0, - 137, 0, 0, 0, 0, 0, 0, 0, 0, 329, - 32, 380, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 336, 0, 0, 0, 0, 0, 137, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 137, + 0, 250, 0, 0, 0, 0, 0, 0, 0, 370, + 0, 0, 0, 0, 0, 167, 0, 0, 178, 0, + 137, 0, 137, 0, 0, 0, 0, 0, 0, 0, + 0, 329, 32, 380, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 325, 259, 258, 260, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 136, 0, 135, 0, 69, 164, + 0, 0, 0, 0, 0, 325, 259, 258, 260, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 136, 0, + 135, 0, 69, 164, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 161, + 113, 0, 0, 0, 0, 325, 0, 0, 360, 361, + 364, 365, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 347, 0, 348, 0, + 0, 0, 0, 354, 353, 0, 234, 234, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 161, 113, 0, 0, 0, - 0, 325, 0, 0, 360, 361, 364, 365, 0, 0, + 0, 338, 337, 0, 0, 0, 0, 137, 137, 0, + 0, 0, 0, 0, 0, 0, 192, 0, 137, 0, + 0, 0, 0, 236, 0, 0, 0, 154, 0, 0, + 0, 251, 0, 0, 0, 166, 0, 0, 0, 0, + 0, 137, 0, 0, 0, 0, 180, 157, 0, 158, + 0, 377, 0, 376, 0, 0, 0, 0, 0, 331, + 0, 0, 71, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 347, 0, 348, 0, 0, 0, 0, 354, - 353, 0, 234, 234, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 338, 337, 0, - 0, 0, 0, 137, 137, 0, 0, 0, 0, 0, - 0, 0, 192, 0, 137, 0, 0, 0, 0, 236, - 0, 0, 0, 154, 0, 0, 0, 251, 0, 0, - 0, 166, 0, 0, 0, 0, 0, 137, 0, 0, - 0, 0, 180, 157, 0, 158, 0, 377, 0, 376, - 0, 0, 0, 0, 0, 331, 0, 0, 71, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 257, 0, 0, 0, 0, 57, + 0, 0, 0, 0, 0, 132, 0, 0, 0, 0, + 138, 64, 0, 274, 273, 272, 271, 267, 268, 270, + 269, 262, 261, 263, 264, 265, 266, 114, 0, 0, + 0, 0, 0, 0, 258, 355, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 257, 0, - 0, 0, 0, 57, 0, 0, 0, 0, 0, 132, - 0, 0, 0, 0, 138, 64, 0, 274, 273, 272, - 271, 267, 268, 270, 269, 262, 261, 263, 264, 265, - 266, 114, 0, 0, 0, 0, 0, 0, 258, 355, + 0, 0, 349, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 232, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 100, 0, 0, 0, 340, + 339, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 186, 0, 0, 0, 0, 0, 0, 0, 0, 155, + 0, 0, 151, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 181, 0, 159, 160, 0, 0, + 0, 0, 0, 0, 0, 327, 333, 0, 42, 0, + 0, 0, 55, 0, 33, 34, 35, 36, 37, 276, + 297, 277, 298, 278, 299, 279, 300, 280, 301, 281, + 302, 282, 303, 283, 304, 284, 305, 296, 317, 285, + 306, 0, 0, 287, 308, 288, 309, 289, 310, 290, + 311, 291, 312, 292, 313, 0, 0, 0, 0, 0, + 0, 387, 0, 0, 385, 386, 82, 0, 382, 0, + 0, 0, 0, 0, 57, 0, 0, 0, 0, 0, + 76, 0, 0, 0, 0, 328, 0, 0, 0, 0, + 0, 25, 23, 0, 0, 0, 0, 362, 0, 0, + 357, 263, 356, 366, 367, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 350, 0, + 0, 0, 0, 0, 0, 230, 235, 233, 0, 241, + 0, 0, 89, 90, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 128, 130, 0, 0, + 0, 0, 0, 0, 0, 0, 221, 0, 183, 0, + 0, 0, 0, 0, 237, 242, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 156, 0, + 0, 0, 0, 0, 378, 0, 0, 0, 0, 0, + 0, 330, 0, 326, 0, 0, 0, 0, 0, 29, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 349, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 232, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 100, - 0, 0, 0, 340, 339, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 186, 0, 0, 0, 0, 0, - 0, 0, 0, 155, 0, 0, 151, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 181, 0, - 159, 160, 0, 0, 0, 0, 0, 0, 0, 327, - 333, 0, 42, 0, 0, 0, 55, 0, 33, 34, - 35, 36, 37, 276, 297, 277, 298, 278, 299, 279, - 300, 280, 301, 281, 302, 282, 303, 283, 304, 284, - 305, 296, 317, 285, 306, 0, 0, 287, 308, 288, - 309, 289, 310, 290, 311, 291, 312, 292, 313, 0, - 0, 0, 0, 0, 0, 385, 0, 0, 383, 384, - 82, 0, 0, 0, 0, 0, 57, 0, 0, 0, - 0, 0, 76, 0, 0, 0, 0, 328, 0, 0, - 0, 0, 0, 25, 23, 0, 0, 0, 0, 362, - 0, 0, 357, 263, 356, 366, 367, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 350, 0, 0, 0, 0, 0, 0, 230, 235, 233, - 0, 241, 0, 0, 89, 90, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 128, 130, - 0, 0, 0, 0, 0, 0, 0, 0, 221, 0, - 183, 0, 0, 0, 0, 0, 237, 242, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 156, 0, 0, 0, 0, 0, 378, 0, 0, 0, - 0, 0, 0, 330, 0, 326, 0, 0, 0, 0, - 0, 29, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 327, 67, 68, 0, 0, 0, 0, - 0, 70, 72, 74, 0, 0, 374, 0, 80, 0, - 0, 0, 0, 275, 24, 0, 0, 0, 0, 0, - 359, 0, 0, 93, 93, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 351, 0, 98, 0, 0, - 0, 0, 0, 0, 239, 0, 0, 0, 0, 0, - 0, 0, 0, 244, 245, 0, 0, 0, 0, 0, - 0, 0, 0, 226, 0, 0, 193, 222, 0, 0, - 0, 149, 0, 0, 243, 0, 153, 152, 0, 30, - 31, 0, 0, 0, 371, 0, 0, 0, 173, 0, - 0, 0, 0, 0, 0, 0, 163, 332, 162, 0, - 0, 0, 0, 345, 0, 286, 307, 293, 314, 294, - 315, 295, 316, 386, 382, 335, 0, 57, 0, 0, + 0, 0, 327, 67, 68, 0, 0, 0, 0, 0, + 70, 72, 74, 0, 0, 374, 0, 80, 0, 0, + 0, 0, 275, 24, 0, 0, 0, 0, 0, 359, + 0, 0, 93, 93, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 351, 0, 98, 0, 0, 0, + 0, 0, 0, 239, 0, 0, 0, 0, 0, 0, + 0, 0, 244, 245, 0, 0, 0, 0, 0, 0, + 0, 0, 226, 0, 0, 193, 222, 0, 0, 0, + 149, 0, 0, 243, 0, 153, 152, 0, 30, 31, + 0, 0, 0, 371, 0, 0, 0, 173, 0, 0, + 0, 0, 0, 0, 0, 163, 332, 162, 0, 0, + 0, 0, 345, 0, 286, 307, 293, 314, 294, 315, + 295, 316, 388, 384, 335, 383, 0, 57, 0, 0, 0, 0, 65, 0, 0, 0, 372, 0, 0, 0, 0, 26, 27, 0, 0, 95, 0, 358, 0, 0, 0, 0, 0, 99, 0, 0, 116, 117, 0, 0, @@ -1377,174 +1383,175 @@ static const yytype_uint16 yydefact[] = /* YYDEFGOTO[NTERM-NUM]. */ static const yytype_int16 yydefgoto[] = { - -1, 2, 3, 69, 705, 70, 71, 437, 1037, 1043, - 628, 806, 1189, 1336, 629, 1299, 1362, 630, 1338, 631, - 632, 810, 139, 239, 72, 743, 1074, 970, 504, 365, - 366, 367, 368, 334, 305, 306, 75, 76, 77, 78, - 79, 80, 335, 771, 1257, 1314, 582, 1094, 1097, 1100, - 1279, 1283, 1287, 1325, 1328, 1331, 767, 768, 1083, 873, - 740, 556, 590, 82, 83, 84, 85, 86, 352, 142, - 378, 191, 932, 933, 361, 354, 547, 219, 696, 837, - 428, 429 + -1, 2, 3, 69, 713, 70, 71, 441, 1047, 1053, + 634, 814, 1199, 1346, 635, 1309, 1372, 636, 1348, 637, + 638, 818, 141, 241, 72, 751, 1084, 980, 510, 369, + 370, 371, 372, 338, 309, 310, 75, 76, 77, 78, + 79, 80, 339, 779, 1267, 1324, 588, 1104, 1107, 1110, + 1289, 1293, 1297, 1335, 1338, 1341, 775, 776, 1093, 882, + 748, 562, 596, 82, 83, 84, 85, 86, 356, 144, + 382, 193, 941, 942, 365, 358, 553, 221, 704, 846, + 432, 433 }; /* YYPACT[STATE-NUM] -- Index in YYTABLE of the portion describing STATE-NUM. */ -#define YYPACT_NINF -1118 +#define YYPACT_NINF -1126 static const yytype_int16 yypact[] = { - 3266, 62, 9, 3372, -1118, -1118, 1673, 45, 29, 2, - 27, 113, 154, 196, -41, 73, 82, -33, 138, 139, - -31, 149, 159, 147, 165, 242, 281, 282, 382, 305, - 438, 462, 85, 235, 344, 218, 188, 188, 246, 325, - 278, 345, 348, 357, 22, 58, 363, 422, 428, 433, - 309, 313, 319, 19, 39, -1118, 341, -1118, 440, 310, - -1118, 468, 481, 26, 30, 353, 354, 378, 390, -1118, - -1118, -1118, -1118, -1118, -1118, -1118, -1118, -1118, -1118, -1118, - -1118, -1118, -1118, -1118, -1118, -1118, -1118, -1118, 23, 384, - 383, -1118, -1118, -1118, 212, 226, 272, 333, 386, 387, - 420, 477, 511, 515, 519, 528, 533, 536, 537, 557, - 570, 573, 580, 593, 602, 399, 400, 410, 431, -1118, - 482, 435, -1118, -1118, -1118, -1118, -1118, -1118, -1118, 839, - 839, 839, -1118, -1118, 839, 2642, 15, 578, 32, 839, - 581, 1528, -1118, 596, 632, 839, 600, -1118, 839, -1118, - -1118, -1118, 839, 3028, 839, 839, 506, 839, 3028, 839, - 839, 507, 3028, 839, 839, 2009, 510, 543, 540, 561, - 1729, 1729, 1729, 562, -1118, -1118, -1118, -1118, 569, 574, - 579, 2009, 2009, 722, 2009, 188, 188, 188, 839, 839, - 53, -1118, 225, 188, 582, 587, 590, 2888, 292, -32, - 586, 606, 1729, 2009, 612, 34, 631, -1118, 774, -1118, - 648, 657, 671, 811, 839, 839, 839, 681, 839, 684, - 740, 839, 839, -1118, 839, 834, -1118, 841, -1118, 845, - -1118, 508, 508, 508, 508, 709, 839, 871, 730, -1118, - -1118, -1118, 873, 839, 839, 839, 839, 839, 839, 839, - 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, - 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, - 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, - 839, 839, 839, 839, 839, 508, 508, 508, 508, 839, - 882, 594, 750, 750, 750, 5504, 60, 3028, 4768, 204, - 776, 919, 791, 781, -1118, 787, 3190, 1722, -1118, -1118, - 839, 839, 839, 839, 839, 839, 839, 839, 839, 839, - 839, 839, 839, 839, 839, -1118, -1118, 1797, -53, 4066, - 5525, 680, 789, 3028, -1118, -1118, 2703, -1118, 599, 5546, - 5567, 839, 5588, 605, 5609, 5630, 839, 622, 5651, 5672, - 2149, 1496, 2801, 931, -1118, 839, 839, 839, 839, -1118, - -1118, 932, 933, 933, 839, 800, 802, 803, 805, 839, - 839, 839, 940, 946, 812, 950, -52, -1118, -1118, 4092, - 4118, 188, 188, 32, 32, 199, 839, 839, 839, 2888, - 2888, 839, 3190, 317, -1118, 839, 839, 839, 839, 951, - 952, 839, 954, -1118, 839, 839, 1167, -1118, 3028, 839, - 839, -1118, 5693, 5714, 5735, 861, 4144, -1118, 813, 2843, - 5756, 4791, -1118, -1118, 1231, -1118, 1532, 627, 821, -1118, - 822, 824, 825, 839, 4814, -109, 839, 10, -1118, 5777, - 4837, 5798, 4860, 5819, 4883, 5840, 4906, 5861, 4929, 5882, - 4952, 5903, 4975, 5924, 4998, 5945, 5021, 5966, 5044, 5987, - 5067, 4170, 4196, 6008, 5090, 6029, 5113, 6050, 5136, 6071, - 5159, 6092, 5182, 6113, 5205, 4222, 4248, 4274, 4300, 4326, - 4352, 151, 827, 830, 835, 1937, 831, 839, -1118, 2009, - 2009, 628, 86, 383, 839, 973, 979, 21, 847, -1118, - 51, -3, -30, 144, -1118, -1118, 2881, 502, 659, 676, - 676, 476, 476, 476, 476, 444, 444, 750, 750, 750, - 750, -1118, 7, 3028, 839, 986, 2849, 839, 750, -1118, - 839, 3028, 3028, 895, 993, 994, 6134, 995, 904, 997, - 999, 6155, 908, 1001, 1002, 3028, -1118, 629, 2289, 839, - 6176, 3265, 6197, 6218, 839, 2009, 1007, 1006, 6239, 3162, - 3162, 3162, 3162, 6260, 6281, 6302, 2009, 2009, 870, -1118, - 188, 839, 839, -1118, -1118, 868, 869, 839, 4378, 4404, - 4430, 4040, -26, 188, 1905, 6323, 3396, 6344, 6365, 839, - 1013, 839, 6386, -1118, 5228, 5251, -1118, 634, 5274, 5297, - 1014, 1015, 1016, 880, 839, 2045, 839, 839, -1118, 5, - -1118, -1118, 839, 1022, 1020, 1023, 1024, 1025, 5320, 48, - -1118, 3424, -1118, 888, 894, 906, -1118, 1046, -1118, -1118, - -1118, -1118, -1118, -1118, -1118, -1118, -1118, -1118, -1118, -1118, - -1118, -1118, -1118, -1118, -1118, -1118, -1118, -1118, -1118, -1118, - -1118, -1118, -1118, -1118, -1118, 839, 839, -1118, -1118, -1118, - -1118, -1118, -1118, -1118, -1118, -1118, -1118, -1118, -1118, 839, - 839, 839, 839, 839, 839, -1118, 3028, 508, -1118, -1118, - -1118, 839, 5343, 1049, 1051, 914, -1118, 24, 839, 1053, - 1054, 2077, -1118, 1056, 918, 19, 1058, -1118, 3028, 3028, - 3028, 3028, 839, -1118, 938, 508, 179, 4456, 188, -1118, - 3028, 3452, 2955, 750, -1118, 2703, -1118, 1032, 2009, 2009, - 1060, 2009, 743, 2009, 2009, 1078, 1034, 2009, 2009, 666, - -1118, 3028, 2217, 1079, 1083, 1084, 1085, 375, -1118, -1118, - 1087, -1118, 1088, 955, 1703, -1118, 956, 958, 961, 1089, - 1097, 1098, 1100, 1102, 1090, 336, 4482, 4508, -1118, -1118, - 3480, 188, 188, 188, 1103, 963, 975, -35, -1118, 339, - -1118, -26, 1110, 1112, 1113, 1114, 1703, -1118, 2357, 971, - 1116, 1117, 1073, 1120, 1121, 2009, 2009, 2009, 1124, 4534, - -1118, 2988, 947, 1126, 1127, 5366, -1118, 984, 985, 987, - 988, 1128, 1134, -1118, 1135, -1118, 1004, 839, 839, 2009, - 992, -1118, 6407, 5389, 6428, 5412, 6449, 5435, 6470, 5458, - 228, 1005, 6491, 89, -1118, -1118, 76, 290, 998, 1141, - 2389, -1118, -1118, -1118, 19, 839, -1118, 675, -1118, 686, - 689, 697, 727, 1703, -1118, 1143, 43, 839, -1, 736, - -1118, 839, 1003, 1091, 1091, 2009, 1152, 1012, 1017, 1156, - 1158, 2009, 1018, 1161, 1162, -1118, 737, -1118, 1165, 2009, - 2009, 2009, 1168, 1169, -1118, 2009, 1164, 1170, 1171, 1174, - 2009, 2009, 2009, -1118, -1118, 99, 839, 839, 839, 1026, - 286, 312, 331, -1118, 2009, 839, -1118, -1118, 2888, -22, - 1869, -1118, 1028, 2429, -1118, 3028, -1118, -1118, 1035, -1118, - -1118, 1176, 1178, 1092, -1118, 839, 839, 839, -1118, 1182, - 1183, 1044, 2009, 2009, 2009, 2009, -1118, -109, -1118, 839, - 4560, 4586, 744, -1118, 839, -1118, -1118, -1118, -1118, -1118, - -1118, -1118, -1118, -1118, -1118, -1118, 2009, 383, 839, 1185, - 1189, 21, -1118, 1190, 5481, 19, -1118, 1191, 1193, 1194, - 1196, -1118, -1118, 508, 4612, -1118, 1059, 1703, 839, 188, - 1198, 1199, 1200, -1118, 839, 839, -1118, -1118, 1201, 839, - -1118, -1118, -1118, 1203, 1204, 1205, 1096, 839, -1118, 1206, - 2009, 2009, 2009, 2009, 1217, 1221, 1226, -1118, 3162, 3508, - 6512, 3021, 32, 188, 1227, 188, 1228, 188, 1230, 633, - 1094, 6533, 3536, 391, -1118, 1232, 1342, 1240, 188, 1342, - 1241, 747, 839, -1118, -1118, 2009, 3083, 916, 6554, -1118, - 2709, 1233, 1101, 1104, 1105, 1107, -1118, 254, 1703, 839, - 839, 2009, 1108, 748, 1703, 1244, 1251, 2422, -1118, 1254, - 1256, -1118, 1118, -1118, -1118, -1118, -1118, -1118, 1263, 839, - -1118, 3564, 57, -1118, -1118, -1118, 3592, 3620, -1118, 3648, - 1267, -1118, -1118, 1223, 1270, 1703, -1118, 1281, 1283, 1286, - 1290, -1118, 1149, 1292, -1118, 2497, 1294, 1153, -1118, 839, - -1118, 1154, 405, -1118, 1159, 443, -1118, 1163, 449, -1118, - 1166, 1296, 2009, 1297, 1172, 839, -1118, 2569, 457, -1118, - 512, 514, -1118, 1300, 3676, 1215, 839, -1118, 839, -1118, - -1118, 3028, 2562, 1306, -1118, 2009, 2009, 2009, 2009, -1118, - 839, 4638, 4664, -1118, 2009, 839, 1307, -1118, -1118, -1118, - 19, -1118, 1218, -1118, 4690, 1311, 1312, 1313, 1315, 1319, - 1179, -1118, -1118, -1118, -1118, -1118, 2009, -1118, -1118, -1118, - 32, 3368, -1118, 2888, -26, 2888, -26, 2888, -26, -1118, - 751, 2009, -1118, 3704, 188, 3028, 188, -1118, -1118, 839, - 3732, 3760, 754, -1118, -1118, 1177, 1180, 1181, 1186, 1188, - 1703, 839, 839, 755, 1703, -1118, 1322, -1118, 839, -1118, - -1118, -1118, -1118, -1118, 839, 758, 1192, 839, -1118, 3788, - 541, -17, 3816, 552, -13, 3844, 554, -5, 2009, 1325, - 1271, 2185, 1195, 558, 759, 575, 2637, -1118, -1118, 1332, - 1333, 1334, 1336, 1338, 839, 6575, 4716, 31, -1118, 4742, - 3872, 1343, -1118, 3900, 1344, 839, 1348, 1349, 839, 1371, - 1372, 839, 1373, 1234, -1118, 839, -1118, -26, -1118, 3028, - 1375, 2569, -1118, -1118, -1118, -1118, -1118, -1118, 765, -1118, - 839, -1118, 2009, 839, -1118, -1118, 1376, -1118, -1118, 1236, - 3928, -1118, -1118, 1237, 3956, -1118, -1118, 1238, 3984, -1118, - 1381, 2671, 137, 2325, 766, -1118, 577, 769, 1383, 1242, - 6596, 770, 4012, -1118, -26, 1385, -26, 1386, -26, 1387, - -1118, -1118, -1118, -1118, -26, 1388, 3028, 1389, -1118, 508, - -1118, 1249, 1392, 150, -1118, 1252, 153, -1118, 1253, 205, - -1118, 1255, 213, -1118, 773, -1118, 778, -1118, 1257, 2009, - -1118, 1393, -26, 1398, -26, 1400, -26, -1118, 1401, 508, - 1403, 508, 783, -1118, 256, -1118, 265, -1118, 296, -1118, - -1118, -1118, 786, -1118, 1413, 1415, 1418, 1419, 508, 1420, - -1118, -1118, -1118, -1118, -1118, -1118 + 3354, 52, 47, 3462, -1126, -1126, 1642, 51, 43, -70, + 36, 70, 106, 122, -81, -1, 80, -66, 149, 150, + -12, 160, 181, 136, 281, 286, 295, 305, 410, 297, + 861, 536, 152, 223, 314, 226, 514, 514, 247, 148, + 24, 318, 377, 362, 29, 280, 388, 436, 440, 447, + 312, 350, 358, 21, 19, -1126, 365, -1126, 461, 339, + -1126, 509, 517, 15, 31, 382, 398, 403, 404, -1126, + -1126, -1126, -1126, -1126, -1126, -1126, -1126, -1126, -1126, -1126, + -1126, -1126, -1126, -1126, -1126, -1126, -1126, -1126, 28, 370, + 887, -1126, -1126, -1126, 159, 180, 228, 293, 347, 369, + 451, 475, 523, 543, 554, 568, 571, 589, 642, 647, + 684, 700, 716, 722, 723, 420, 427, 437, 444, -1126, + 546, 455, 462, 470, -1126, -1126, -1126, -1126, -1126, -1126, + -1126, 3238, 3238, 3238, -1126, -1126, 3238, 2831, 23, 548, + 405, 3238, 550, 671, -1126, 586, 611, 3238, 590, -1126, + 3238, -1126, -1126, -1126, 3238, 3065, 3238, 3238, 487, 3238, + 3065, 3238, 3238, 495, 3065, 3238, 3238, 2074, 496, 459, + 499, 500, 1790, 1790, 1790, 503, -1126, -1126, -1126, -1126, + 519, 532, 537, 2074, 2074, 683, 2074, 514, 514, 514, + 3238, 3238, 225, -1126, 248, 514, 556, 560, 581, 3018, + 299, -57, 598, 599, 1790, 2074, 610, 18, 601, -1126, + 809, -1126, 625, 666, 687, 838, 3238, 3238, 3238, 690, + 3238, 698, 750, 3238, 3238, -1126, 3238, 846, -1126, 849, + -1126, 854, -1126, 467, 467, 467, 467, 739, 3238, 884, + 759, -1126, -1126, -1126, 893, 3238, 3238, 3238, 3238, 3238, + 3238, 3238, 3238, 3238, 3238, 3238, 3238, 3238, 3238, 3238, + 3238, 3238, 3238, 3238, 3238, 3238, 3238, 3238, 3238, 3238, + 3238, 3238, 3238, 3238, 3238, 3238, 3238, 3238, 3238, 3238, + 3238, 3238, 3238, 3238, 3238, 3238, 3238, 467, 467, 467, + 467, 3238, 467, 467, 467, 544, 758, 758, 758, 5456, + 41, 3065, 4720, 220, 770, 909, 776, 777, -1126, 784, + 2859, 745, -1126, -1126, 3238, 3238, 3238, 3238, 3238, 3238, + 3238, 3238, 3238, 3238, 3238, 3238, 3238, 3238, 3238, -1126, + -1126, 953, -115, 4018, 5477, 706, 788, 3065, -1126, -1126, + 2282, -1126, 665, 5498, 5519, 3238, 5540, 734, 5561, 5582, + 3238, 744, 5603, 5624, 2216, 1493, 2316, 935, -1126, 3238, + 3238, 3238, 3238, -1126, -1126, 936, 943, 943, 3238, 842, + 845, 857, 870, 3238, 3238, 3238, 974, 982, 853, 998, + 49, -1126, -1126, 4044, 4070, 514, 514, 405, 405, 324, + 3238, 3238, 3238, 3018, 3018, 3238, 2859, 366, -1126, 3238, + 3238, 3238, 3238, 1011, 1017, 3238, 1026, -1126, 3238, 3238, + 54, -1126, 3065, 3238, 3238, -1126, 5645, 5666, 5687, 937, + 4096, -1126, 885, 2352, 5708, 4743, -1126, -1126, 771, -1126, + 1675, 749, 892, -1126, 894, 895, 896, 3238, 4766, 260, + 3238, 1, -1126, 5729, 4789, 5750, 4812, 5771, 4835, 5792, + 4858, 5813, 4881, 5834, 4904, 5855, 4927, 5876, 4950, 5897, + 4973, 5918, 4996, 5939, 5019, 4122, 4148, 5960, 5042, 5981, + 5065, 6002, 5088, 6023, 5111, 6044, 5134, 6065, 5157, 4174, + 4200, 4226, 4252, 4278, 4304, -34, 888, 897, 898, 1088, + 912, 901, 913, 3238, -1126, 2074, 2074, 763, 68, 887, + 3238, 1040, 1043, 22, 919, -1126, -14, 147, 155, 88, + -1126, -1126, 2424, 1346, 922, 1446, 1446, 769, 769, 769, + 769, 164, 164, 758, 758, 758, 758, -1126, 2, 3065, + 3238, 1059, 2870, 3238, 758, -1126, 3238, 3065, 3065, 968, + 1061, 1062, 6086, 1063, 972, 1065, 1066, 6107, 975, 1068, + 1084, 3065, -1126, 779, 2358, 3238, 6128, 2988, 6149, 6170, + 3238, 2074, 1093, 1086, 6191, 3201, 3201, 3201, 3201, 6212, + 6233, 6254, 2074, 2074, 951, -1126, 514, 3238, 3238, -1126, + -1126, 949, 950, 3238, 4330, 4356, 4382, 2929, 9, 514, + 1826, 6275, 3149, 6296, 6317, 3238, 1097, 3238, 6338, -1126, + 5180, 5203, -1126, 782, 5226, 5249, 1098, 1099, 1100, 957, + 3238, 1968, 3238, 3238, -1126, 30, -1126, -1126, 3238, 1104, + 1103, 1105, 1106, 1107, 5272, 341, -1126, 3194, -1126, 973, + 976, 965, -1126, 1111, -1126, -1126, -1126, -1126, -1126, -1126, + -1126, -1126, -1126, -1126, -1126, -1126, -1126, -1126, -1126, -1126, + -1126, -1126, -1126, -1126, -1126, -1126, -1126, -1126, -1126, -1126, + -1126, 3238, 3238, -1126, -1126, -1126, -1126, -1126, -1126, -1126, + -1126, -1126, -1126, -1126, -1126, 3238, 3238, 3238, 3238, 3238, + 3238, -1126, 3065, 467, -1126, -1126, -1126, 3238, -1126, 467, + 5295, 1112, 1115, 977, -1126, 27, 3238, 1118, 1121, 1242, + -1126, 1122, 985, 21, 1125, -1126, 3065, 3065, 3065, 3065, + 3238, -1126, 1002, 467, -10, 4408, 514, -1126, 3065, 3353, + 2458, 758, -1126, 2282, -1126, 1081, 2074, 2074, 1128, 2074, + 882, 2074, 2074, 1129, 1083, 2074, 2074, 790, -1126, 3065, + 1305, 1131, 1133, 1134, 1135, 2682, -1126, -1126, 1137, -1126, + 1140, 1004, 6569, -1126, 1005, 1006, 1007, 1146, 1148, 1150, + 1152, 1153, 1156, 409, 4434, 4460, -1126, -1126, 3458, 514, + 514, 514, 1155, 1012, 1021, -30, -1126, 466, -1126, 9, + 1159, 1162, 1163, 1165, 6569, -1126, 1329, 1024, 1171, 1176, + 1136, 1180, 1181, 2074, 2074, 2074, 1185, 4486, -1126, 2494, + 632, 1187, 1188, 5318, -1126, 1044, 1047, 1048, 1049, 1194, + 1189, -1126, 1197, -1126, 1064, 3238, 3238, 2074, 1055, -1126, + 6359, 5341, 6380, 5364, 6401, 5387, 6422, 5410, 58, 1082, + 6443, 1085, -96, -1126, -1126, 206, 325, 1080, 1199, 1416, + -1126, -1126, -1126, 21, 3238, -1126, 797, -1126, 798, 802, + 805, 806, 6569, -1126, 1203, 7, 3238, 62, 811, -1126, + 3238, 1060, 1169, 1169, 2074, 1225, 1087, 1089, 1226, 1227, + 2074, 1090, 1228, 1229, -1126, 812, -1126, 1231, 2074, 2074, + 2074, 1237, 1239, -1126, 2074, 1240, 1244, 1246, 1247, 2074, + 2074, 2074, -1126, -1126, 282, 3238, 3238, 3238, 1096, -55, + -52, 201, -1126, 2074, 3238, -1126, -1126, 3018, -11, 1932, + -1126, 1110, 2500, -1126, 3065, -1126, -1126, 1114, -1126, -1126, + 1250, 1251, 1166, -1126, 3238, 3238, 3238, -1126, 1256, 1259, + 1120, 2074, 2074, 2074, 2074, -1126, 260, -1126, 3238, 4512, + 4538, 815, -1126, 3238, -1126, -1126, -1126, -1126, -1126, -1126, + -1126, -1126, -1126, -1126, -1126, -1126, 2074, 887, 3238, 1262, + 1265, 22, -1126, 1264, 5433, 21, -1126, 1266, 1267, 1269, + 1270, -1126, -1126, 467, 4564, -1126, 1132, 6569, 3238, 514, + 1275, 1277, 1278, -1126, 3238, 3238, -1126, -1126, 1282, 3238, + -1126, -1126, -1126, 1284, 1306, 1308, 1172, 3238, -1126, 1309, + 2074, 2074, 2074, 2074, 1310, 1313, 1312, -1126, 3201, 3486, + 6464, 1716, 405, 514, 1315, 514, 1317, 514, 1318, 288, + 1177, 6485, 3514, 492, -1126, 1319, 1276, 1324, 514, 1276, + 1325, 818, 3238, -1126, -1126, 2074, 2863, 593, 6506, -1126, + 2642, 1328, 1192, 1201, 1202, 1204, -1126, 72, 6569, 3238, + 3238, 2074, 1184, 819, 6569, 1330, 1331, 1486, -1126, 1336, + 1349, -1126, 1209, -1126, -1126, -1126, -1126, -1126, 1353, 3238, + -1126, 3542, 345, -1126, -1126, -1126, 3570, 3598, -1126, 3626, + 1355, -1126, -1126, 1232, 1356, 6569, -1126, 1357, 1358, 1359, + 1379, -1126, 1238, 1381, -1126, 1566, 1386, 1243, -1126, 3238, + -1126, 1245, 511, -1126, 1248, 516, -1126, 1252, 518, -1126, + 1253, 1388, 2074, 1390, 1254, 3238, -1126, 2689, 545, -1126, + 549, 559, -1126, 1389, 3654, 1307, 3238, -1126, 3238, -1126, + -1126, 3065, 1858, 1394, -1126, 2074, 2074, 2074, 2074, -1126, + 3238, 4590, 4616, -1126, 2074, 3238, 1400, -1126, -1126, -1126, + 21, -1126, 1311, -1126, 4642, 1401, 1405, 1406, 1407, 1409, + 1268, -1126, -1126, -1126, -1126, -1126, 2074, -1126, -1126, -1126, + 405, 3058, -1126, 3018, 9, 3018, 9, 3018, 9, -1126, + 822, 2074, -1126, 3682, 514, 3065, 514, -1126, -1126, 3238, + 3710, 3738, 825, -1126, -1126, 1272, 1274, 1292, 1293, 1271, + 6569, 3238, 3238, 826, 6569, -1126, 1410, -1126, 3238, -1126, + -1126, -1126, -1126, -1126, 3238, 831, 1294, 3238, -1126, 3766, + 603, 143, 3794, 605, 254, 3822, 637, 359, 2074, 1411, + 1354, 2110, 1296, 639, 835, 644, 2000, -1126, -1126, 1422, + 1442, 1461, 1462, 1463, 3238, 6527, 4668, 37, -1126, 4694, + 3850, 1466, -1126, 3878, 1479, 3238, 1480, 1481, 3238, 1483, + 1484, 3238, 1485, 1342, -1126, 3238, -1126, 9, -1126, 3065, + 1488, 2689, -1126, -1126, -1126, -1126, -1126, -1126, 844, -1126, + 3238, -1126, 2074, 3238, -1126, -1126, 1489, -1126, -1126, 1348, + 3906, -1126, -1126, 1351, 3934, -1126, -1126, 1378, 3962, -1126, + 1499, 2142, 378, 2252, 852, -1126, 708, 860, 1500, 1380, + 6548, 863, 3990, -1126, 9, 1523, 9, 1525, 9, 1526, + -1126, -1126, -1126, -1126, 9, 1527, 3065, 1528, -1126, 467, + -1126, 1385, 1530, 387, -1126, 1387, 413, -1126, 1404, 415, + -1126, 1417, 435, -1126, 868, -1126, 876, -1126, 1418, 2074, + -1126, 1532, 9, 1549, 9, 1550, 9, -1126, 1551, 467, + 1553, 467, 879, -1126, 452, -1126, 457, -1126, 468, -1126, + -1126, -1126, 880, -1126, 1554, 1563, 1564, 1567, 467, 1583, + -1126, -1126, -1126, -1126, -1126, -1126 }; /* YYPGOTO[NTERM-NUM]. */ static const yytype_int16 yypgoto[] = { - -1118, -1118, -1118, -1118, 503, -1118, -1118, -1118, -1118, 114, - -1118, -1118, -1118, -1118, -1118, -1118, -1118, -1118, -1118, -1118, - -1118, -1118, -292, 4, -1118, 52, -1118, 576, 1428, -1118, - -1118, -1118, -1118, 3, -381, -196, -1118, -1118, -1118, -1118, - -1118, -1118, 1429, -1118, -1118, -1118, -1118, -1118, -1118, -1118, - -1118, -1118, -1118, -1118, -1118, -1118, -689, -759, 192, -1118, - -1118, 1071, -1118, -1118, -1118, -1118, -1118, -1118, -6, -1118, - -21, -1118, -1117, 547, -80, 289, -107, -671, 484, -1118, - -212, -2 + -1126, -1126, -1126, -1126, 735, -1126, -1126, -1126, -1126, 255, + -1126, -1126, -1126, -1126, -1126, -1126, -1126, -1126, -1126, -1126, + -1126, -1126, -299, 4, -1126, -332, -1126, 728, 1589, -1126, + -1126, -1126, -1126, 3, -376, -192, -1126, -1126, -1126, -1126, + -1126, -1126, 1590, -1126, -1126, -1126, -1126, -1126, -1126, -1126, + -1126, -1126, -1126, -1126, -1126, -1126, -609, -705, 343, -1126, + -1126, 1230, -1126, -1126, -1126, -1126, -1126, -1126, -6, -1126, + -21, -1126, -1125, 449, -124, 73, -125, -682, 634, -1126, + -233, 8 }; /* YYTABLE[YYPACT[STATE-NUM]]. What to do in state STATE-NUM. If @@ -1554,1502 +1561,1499 @@ static const yytype_int16 yypgoto[] = #define YYTABLE_NINF -5 static const yytype_int16 yytable[] = { - 141, 392, 575, 576, 143, 965, 74, 494, 897, 5, - 140, 406, 793, 703, 622, 190, 192, 1193, 198, 299, - 430, 431, 432, 217, 836, 694, 205, 235, 827, 132, - 133, 227, 424, 147, 426, 229, 303, 1271, 402, 1205, - 403, 764, 156, 220, 161, 161, 338, 765, 766, 962, - 764, 343, 427, 241, 764, 347, 765, 766, 144, 764, - 765, 766, 208, 764, 209, 765, 766, 489, 4, 765, - 766, 764, 156, 481, 482, 483, 484, 765, 766, 381, - 382, 145, 899, 686, 115, 116, 117, 118, 242, 522, - 119, 362, 363, 686, 523, 570, 623, 624, 625, 626, - 152, 35, 36, 37, 38, 997, 998, 153, 157, 395, - 43, 300, 301, 46, 896, 158, 396, 162, 700, 149, - 828, 829, 399, 292, 293, 294, 206, 1014, 295, 298, - 381, 382, 1246, 307, 181, 704, 1249, 182, 157, 327, - 897, 304, 329, 146, 1252, 699, 330, 336, 339, 340, - 794, 342, 336, 344, 345, 1301, 336, 348, 349, 627, - 150, 132, 133, 953, 376, 377, 236, 218, 237, 695, - 207, 704, 385, 238, 228, 148, 393, 404, 230, 1272, - 221, 490, 379, 380, 381, 382, 132, 133, 381, 382, - 491, 380, 152, 802, 125, 126, 127, 128, 584, 698, - 688, 383, 151, 165, 125, 126, 127, 128, 412, 413, - 414, 493, 416, 764, 154, 419, 420, 166, 421, 765, - 766, 605, 1352, 155, 132, 133, 764, 132, 133, 764, - 434, 687, 765, 766, 802, 765, 766, 439, 440, 441, - 442, 443, 444, 445, 446, 447, 448, 449, 450, 451, - 452, 453, 454, 455, 456, 457, 458, 459, 460, 461, - 462, 463, 464, 465, 466, 467, 468, 469, 470, 471, - 472, 473, 474, 475, 476, 477, 478, 479, 480, 159, - 160, 764, 199, 485, 1053, 164, 1312, 765, 766, 764, - 163, 336, 701, 675, 167, 765, 766, 947, 676, 1341, - 164, 597, 1343, 495, 506, 507, 508, 509, 510, 511, - 512, 513, 514, 515, 516, 517, 518, 519, 520, 186, - 187, 846, 125, 126, 127, 128, 532, 528, 200, 188, - 381, 382, 764, 168, 169, 536, 189, 201, 765, 766, - 541, 764, 132, 133, 528, 336, 577, 765, 766, 550, - 551, 552, 553, 243, 1345, 244, 381, 382, 558, 173, - 573, 574, 1347, 563, 564, 565, 185, 245, 377, 246, - 943, 194, 764, 384, 195, 532, 183, 196, 765, 766, - 578, 579, 580, 292, 293, 581, 304, 304, 241, 585, - 586, 587, 588, 184, 193, 592, 1129, 202, 594, 595, - 203, 1130, 336, 598, 599, 1365, 204, 804, 125, 126, - 127, 128, 210, 247, 1366, 248, 706, 381, 382, 115, - 116, 117, 118, 381, 382, 119, 211, 618, 132, 133, - 621, 170, 212, 1003, 171, 1004, 172, 213, 729, 620, - 394, 872, 337, 381, 382, 1367, 223, 337, 381, 382, - 214, 337, 897, 224, 215, 897, 186, 187, 897, 1005, - 216, 1006, 381, 382, 583, 821, 188, 381, 382, 1196, - 381, 382, 225, 197, 249, 1211, 250, 1214, 1007, 1217, - 1008, 682, 222, 886, 174, 226, 898, 175, 691, 289, - 176, 690, 177, 845, 231, 232, 689, 310, 311, 312, - 313, 314, 315, 316, 317, 318, 319, 320, 321, 322, - 323, 178, 427, 241, 179, 324, 180, 336, 707, 233, - 682, 711, 381, 382, 712, 713, 715, 251, 253, 252, - 254, 234, 240, 897, 946, 948, 381, 382, 1105, 336, - 285, 286, 713, 732, 115, 116, 117, 118, 737, 755, - 119, 287, 1163, 744, 744, 744, 744, 745, 745, 745, - 745, 255, 769, 256, 897, 756, 757, 897, 1292, 820, - 897, 760, 288, 897, 381, 382, 290, 321, 322, 323, - 381, 382, 302, 776, 324, 778, 337, 308, 381, 382, - 1165, 839, 840, 841, 842, 897, 1167, 897, 789, 897, - 791, 792, 325, 849, 1174, 328, 795, 319, 320, 321, - 322, 323, 746, 747, 748, 1323, 324, 1326, 257, 1329, - 258, 1091, 529, 803, 866, 1332, 312, 313, 314, 315, - 316, 317, 318, 319, 320, 321, 322, 323, 326, 529, - 337, 530, 324, 381, 382, 381, 382, 341, 346, 812, - 813, 355, 259, 1354, 260, 1356, 261, 1358, 262, 1175, - 263, 1176, 264, 814, 815, 816, 817, 818, 819, 265, - 336, 266, 381, 382, 267, 822, 268, 269, 271, 270, - 272, 357, 830, 381, 382, 381, 382, 848, 1245, 381, - 382, 356, 336, 336, 336, 336, 843, 337, 273, 1248, - 274, 1251, 358, 364, 336, 1259, 381, 382, 381, 382, - 369, 275, 353, 276, 277, 370, 278, 360, 360, 360, - 371, 279, 1261, 280, 1316, 336, 374, 397, 372, 373, - 386, 375, 132, 133, 281, 387, 282, 487, 388, 237, - 890, 891, 892, 283, 238, 284, 532, 398, 533, 360, - 400, 1058, 532, 401, 538, 310, 311, 312, 313, 314, - 315, 316, 317, 318, 319, 320, 548, 322, 323, 532, - 612, 542, 613, 324, 405, 532, 532, 685, 730, 1206, - 407, 532, 1101, 782, 313, 314, 315, 316, 317, 318, - 319, 320, 321, 322, 323, 857, 408, 858, 1021, 324, - 409, 930, 931, 315, 316, 317, 318, 319, 320, 321, - 322, 323, 337, 532, 410, 865, 324, 411, 132, 133, - 714, 716, 955, 526, 956, 237, 415, 803, 138, 954, - 238, 949, 417, 532, 337, 957, 532, 714, 958, 418, - 422, 964, 87, 291, 532, 967, 959, 423, 91, 92, - 93, 425, 433, 94, 95, 96, 97, 98, 99, 100, - 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, - 111, 112, 113, 114, 532, 435, 960, 1013, 436, 438, - 999, 1000, 1001, 532, 532, 966, 982, 486, 1009, 1011, - 324, 1041, 1012, 1042, 532, 1135, 1113, 1136, 1218, 336, - 1219, 532, 1041, 1229, 1237, 1041, 532, 1241, 1260, 1026, - 1027, 1028, 1135, 532, 1298, 1315, 532, 1041, 1317, 1321, - 532, 496, 1348, 1038, 1118, 1349, 497, 1350, 1044, 138, - 1041, 1036, 1364, 1368, 498, 1369, 499, 527, 549, 554, - 555, 559, 1047, 560, 561, 1046, 562, 566, 1062, 121, - 122, 123, 124, 567, 568, 917, 569, 603, 589, 591, - 593, 606, 1061, 614, 615, 337, 616, 617, 1066, 1067, - 129, 130, 678, 1069, 677, 131, 1221, 679, 681, 692, - 134, 1075, 1092, 693, 1095, 137, 1098, 337, 337, 337, - 337, 697, 1085, 708, 717, 1108, 1086, 1110, 1111, 337, - 718, 719, 721, 722, 723, 304, 724, 726, 727, 728, - 336, 739, 741, 336, 1182, 754, 1114, 758, 759, 777, - 337, 785, 786, 787, 1122, 788, 796, 797, 1123, 807, - 798, 799, 800, 1131, 1132, 808, 683, 684, 310, 311, - 312, 313, 314, 315, 316, 317, 318, 319, 320, 321, - 322, 323, 811, 1144, 809, 824, 324, 825, 826, 831, - 832, 835, 1293, 834, 838, 1119, 844, 855, 1224, 310, - 311, 312, 313, 314, 315, 316, 317, 318, 319, 320, - 321, 322, 323, 1161, 852, 861, 868, 324, 862, 918, - 869, 870, 871, 874, 885, 875, 880, 876, 877, 1173, - 878, 528, 738, 879, 881, 882, 883, 1337, 884, 893, - 1180, 894, 1181, 752, 753, 336, 895, 900, 901, 905, - 902, 903, 906, 907, 1190, 908, 909, 910, 914, 1194, - 919, 920, 922, 923, 926, 924, 925, 1360, 927, 1363, - 934, 928, 1210, 950, 1213, 929, 1216, 944, 951, 961, - 969, 968, 1294, 1223, 1297, 1225, 1374, 1209, 973, 1212, - 974, 1215, 976, 304, 977, 975, 979, 980, 981, 336, - 983, 990, 987, 1226, 1002, 988, 1018, 991, 992, 7, - 8, 993, 1023, 1022, 1024, 1235, 1236, 1025, 1029, 1031, - 1030, 1048, 1239, 1049, 337, 1073, 1051, 1054, 1240, 1055, - 1056, 1243, 1057, 1060, 1063, 1064, 1065, 1068, 1070, 1334, - 1071, 1072, 1076, 500, 15, 16, 501, 18, 19, 502, - 21, 503, 23, 1081, 24, 1082, 26, 27, 1044, 29, - 30, 31, 1084, 1093, 1096, 34, 1099, 1124, 1106, 1280, - 1296, 1102, 1284, 7, 8, 1288, 1109, 1112, 1125, 1291, - 1137, 1126, 1127, 336, 1128, 336, 1134, 1138, 50, 51, - 52, 1140, 1141, 1142, 1300, 853, 854, 1302, 856, 1143, - 859, 860, 1149, 1150, 863, 864, 1151, 500, 15, 16, - 501, 18, 19, 502, 21, 503, 23, 1152, 24, 1153, - 26, 27, 1154, 29, 30, 31, 1155, 1156, 1157, 34, - 1159, 1160, 1169, 1162, 1171, 337, 1177, 1164, 337, 1179, - 336, 1166, 1184, 1195, 1168, 1197, 596, 1199, 1200, 1201, - 1172, 1202, 50, 51, 52, 1203, 1230, 1204, 1238, 1231, - 1232, 1254, 911, 912, 913, 1233, 1234, 1255, 1263, 1264, - 1265, 1242, 1266, 1258, 1267, 87, 331, 1275, 1268, 963, - 1278, 91, 92, 93, 1281, 1282, 94, 95, 96, 97, - 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, - 108, 109, 110, 111, 112, 113, 114, 1285, 1286, 1289, - 610, 1295, 1303, 1290, 1304, 1306, 1308, 1310, 332, 1318, - 1319, 1324, 1327, 1330, 1333, 1335, 529, 1339, 1340, 1353, - 1342, 1344, 972, 1346, 1355, 1351, 1357, 1359, 978, 1361, - 337, 35, 36, 37, 38, 39, 984, 985, 986, 1370, - 43, 1371, 989, 46, 1372, 1373, 1375, 994, 995, 996, - 971, 73, 81, 1276, 557, 1050, 0, 0, 0, 0, - 0, 1010, 0, 0, 0, 0, 0, 1017, 0, 0, - 1020, 0, 121, 122, 123, 124, 0, 0, 0, 0, - 0, 0, 0, 0, 337, 0, 0, 0, 0, 1032, - 1033, 1034, 1035, 389, 1107, 0, 0, 0, 131, 0, - 0, 0, 0, 391, 0, 0, 0, 0, 137, 0, - 189, 546, 0, 1045, 0, 0, 0, 0, 0, 87, - 331, 0, 0, 0, 0, 91, 92, 93, 0, 0, + 143, 434, 435, 436, 500, 628, 74, 396, 711, 158, + 142, 581, 582, 972, 145, 192, 194, 410, 200, 1203, + 229, 845, 406, 222, 407, 219, 702, 303, 201, 528, + 342, 836, 237, 207, 529, 347, 231, 801, 428, 351, + 430, 1215, 149, 1281, 134, 135, 772, 5, 495, 366, + 367, 810, 773, 774, 485, 486, 487, 488, 4, 490, + 491, 492, 154, 163, 146, 772, 7, 8, 975, 155, + 906, 773, 774, 148, 202, 694, 151, 159, 385, 386, + 403, 385, 386, 203, 160, 772, 399, 629, 630, 631, + 632, 773, 774, 400, 1013, 147, 1014, 1015, 244, 1016, + 506, 15, 16, 507, 18, 19, 508, 21, 509, 23, + 681, 24, 152, 26, 27, 682, 29, 30, 31, 304, + 305, 905, 34, 837, 838, 296, 297, 298, 153, 154, + 299, 302, 712, 208, 855, 311, 706, 712, 164, 538, + 1024, 331, 156, 308, 333, 50, 51, 52, 334, 340, + 343, 344, 633, 346, 340, 348, 349, 1311, 340, 352, + 353, 963, 223, 408, 496, 230, 380, 381, 134, 135, + 908, 220, 703, 238, 389, 239, 497, 802, 397, 209, + 240, 232, 385, 386, 383, 384, 150, 1282, 127, 128, + 129, 130, 167, 384, 196, 385, 386, 197, 576, 696, + 198, 183, 952, 906, 184, 602, 590, 538, 134, 135, + 416, 417, 418, 694, 420, 695, 1139, 423, 424, 772, + 425, 1140, 158, 157, 1362, 773, 774, 499, 341, 611, + 163, 166, 438, 341, 754, 755, 756, 341, 709, 443, + 444, 445, 446, 447, 448, 449, 450, 451, 452, 453, + 454, 455, 456, 457, 458, 459, 460, 461, 462, 463, + 464, 465, 466, 467, 468, 469, 470, 471, 472, 473, + 474, 475, 476, 477, 478, 479, 480, 481, 482, 483, + 484, 188, 189, 1063, 210, 489, 211, 603, 1007, 1008, + 159, 190, 161, 162, 1256, 340, 536, 707, 199, 325, + 326, 327, 245, 165, 246, 708, 328, 501, 512, 513, + 514, 515, 516, 517, 518, 519, 520, 521, 522, 523, + 524, 525, 526, 247, 166, 248, 127, 128, 129, 130, + 772, 534, 957, 168, 385, 386, 773, 774, 169, 542, + 127, 128, 129, 130, 547, 431, 243, 170, 534, 340, + 1017, 175, 1018, 556, 557, 558, 559, 171, 385, 386, + 134, 135, 564, 186, 579, 580, 185, 569, 570, 571, + 204, 249, 381, 250, 341, 387, 187, 115, 116, 117, + 118, 385, 386, 119, 584, 585, 586, 296, 297, 587, + 308, 308, 812, 591, 592, 593, 594, 195, 388, 598, + 134, 135, 600, 601, 714, 1259, 340, 604, 605, 307, + 535, 206, 314, 315, 316, 317, 318, 319, 320, 321, + 322, 323, 324, 554, 326, 327, 737, 535, 341, 205, + 328, 624, 385, 386, 627, 772, 251, 212, 252, 1111, + 213, 773, 774, 626, 214, 127, 128, 129, 130, 398, + 829, 215, 122, 123, 772, 216, 831, 385, 386, 172, + 773, 774, 173, 772, 174, 134, 135, 225, 1206, 773, + 774, 431, 243, 583, 35, 36, 37, 38, 385, 386, + 854, 134, 135, 43, 226, 341, 46, 690, 810, 772, + 253, 772, 254, 217, 699, 773, 774, 773, 774, 385, + 386, 218, 697, 115, 116, 117, 118, 698, 224, 119, + 1262, 772, 255, 227, 256, 589, 906, 773, 774, 906, + 242, 228, 906, 340, 715, 233, 690, 719, 772, 1322, + 720, 721, 723, 772, 773, 774, 956, 958, 1351, 773, + 774, 234, 385, 386, 772, 340, 235, 236, 721, 740, + 773, 774, 306, 291, 745, 763, 312, 828, 895, 752, + 752, 752, 752, 287, 1353, 1221, 1355, 1224, 777, 1227, + 288, 764, 765, 753, 753, 753, 753, 768, 122, 123, + 289, 848, 849, 850, 851, 180, 1357, 290, 181, 784, + 182, 786, 329, 858, 257, 332, 258, 906, 292, 385, + 386, 1128, 341, 1375, 797, 293, 799, 800, 1376, 360, + 722, 724, 803, 294, 875, 907, 357, 330, 259, 1377, + 260, 364, 364, 364, 341, 385, 386, 722, 906, 811, + 345, 906, 376, 377, 906, 379, 1101, 906, 350, 359, + 926, 1115, 361, 362, 385, 386, 368, 188, 189, 385, + 386, 385, 386, 364, 404, 820, 821, 190, 1302, 906, + 1173, 906, 373, 906, 191, 1175, 261, 1177, 262, 822, + 823, 824, 825, 826, 827, 374, 340, 313, 385, 386, + 375, 830, 385, 386, 134, 135, 263, 378, 264, 493, + 839, 239, 385, 386, 1184, 857, 240, 265, 1185, 266, + 340, 340, 340, 340, 852, 1333, 390, 1336, 1186, 1339, + 391, 267, 340, 268, 269, 1342, 270, 314, 315, 316, + 317, 318, 319, 320, 321, 322, 323, 324, 325, 326, + 327, 392, 271, 340, 272, 328, 385, 386, 385, 386, + 1068, 401, 402, 1364, 1129, 1366, 409, 1368, 899, 900, + 901, 511, 1255, 405, 1258, 341, 314, 315, 316, 317, + 318, 319, 320, 321, 322, 323, 324, 325, 326, 327, + 385, 386, 385, 386, 328, 412, 927, 385, 386, 341, + 341, 341, 341, 7, 8, 273, 1261, 274, 1269, 1031, + 275, 341, 276, 1271, 1216, 314, 315, 316, 317, 318, + 319, 320, 321, 322, 323, 324, 325, 326, 327, 939, + 940, 413, 341, 328, 538, 411, 539, 506, 15, 16, + 507, 18, 19, 508, 21, 509, 23, 277, 24, 278, + 26, 27, 414, 29, 30, 31, 811, 419, 964, 34, + 959, 385, 386, 279, 415, 280, 134, 135, 421, 422, + 974, 532, 426, 239, 977, 427, 140, 1326, 240, 281, + 429, 282, 50, 51, 52, 283, 285, 284, 286, 314, + 315, 316, 317, 318, 319, 320, 321, 322, 323, 324, + 325, 326, 327, 538, 437, 544, 1023, 328, 439, 1009, + 1010, 1011, 243, 538, 618, 548, 619, 1019, 1021, 442, + 328, 1022, 323, 324, 325, 326, 327, 176, 340, 440, + 177, 328, 538, 178, 693, 179, 503, 502, 1036, 1037, + 1038, 504, 616, 115, 116, 117, 118, 140, 538, 119, + 738, 538, 1048, 790, 866, 505, 867, 1054, 533, 538, + 1046, 874, 555, 560, 691, 692, 965, 538, 966, 967, + 561, 538, 1057, 968, 538, 538, 969, 970, 1072, 527, + 538, 538, 976, 992, 1051, 1056, 1052, 538, 1145, 1123, + 1146, 1228, 1071, 1229, 538, 1051, 1239, 1247, 1076, 1077, + 1051, 572, 1251, 1079, 538, 565, 1270, 341, 566, 573, + 1231, 1085, 1102, 1145, 1105, 1308, 1108, 574, 122, 123, + 567, 538, 1095, 1325, 575, 1118, 1192, 1120, 1121, 538, + 746, 1327, 1051, 568, 1331, 308, 1096, 538, 595, 1358, + 340, 760, 761, 340, 597, 1359, 1124, 1360, 1051, 1378, + 1374, 1379, 599, 609, 1132, 612, 620, 683, 621, 622, + 623, 684, 685, 1141, 1142, 688, 700, 701, 1133, 317, + 318, 319, 320, 321, 322, 323, 324, 325, 326, 327, + 1234, 687, 689, 1154, 328, 705, 716, 725, 726, 727, + 729, 730, 731, 732, 734, 735, 1303, 314, 315, 316, + 317, 318, 319, 320, 321, 322, 323, 324, 325, 326, + 327, 736, 749, 1171, 686, 328, 1347, 747, 762, 341, + 766, 767, 341, 785, 796, 793, 794, 795, 804, 1183, + 805, 534, 806, 807, 808, 817, 815, 819, 833, 816, + 1190, 834, 1191, 835, 840, 340, 1370, 841, 1373, 843, + 844, 847, 853, 861, 1200, 864, 870, 871, 877, 1204, + 878, 879, 880, 883, 1304, 1384, 1307, 884, 885, 886, + 887, 888, 1220, 889, 1223, 890, 1226, 891, 892, 893, + 894, 902, 903, 1233, 904, 1235, 909, 1219, 910, 1222, + 911, 1225, 912, 308, 914, 862, 863, 915, 865, 340, + 868, 869, 916, 1236, 872, 873, 918, 919, 917, 923, + 535, 928, 929, 936, 931, 1245, 1246, 932, 933, 934, + 935, 1344, 1249, 937, 341, 943, 961, 938, 1250, 971, + 978, 1253, 314, 315, 316, 317, 318, 319, 320, 321, + 322, 323, 324, 325, 326, 327, 953, 960, 979, 955, + 328, 983, 986, 987, 990, 991, 993, 984, 1054, 985, + 989, 997, 920, 921, 922, 998, 1012, 1000, 842, 1290, + 1306, 1001, 1294, 1002, 1003, 1298, 1033, 1034, 341, 1301, + 1028, 1035, 1039, 340, 1032, 340, 1040, 1041, 1058, 1059, + 1061, 1083, 1064, 1065, 1310, 1066, 1067, 1312, 1070, 87, + 335, 1073, 1160, 1074, 1075, 91, 92, 93, 1078, 1080, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, - 114, 0, 0, 0, 309, 0, 0, 1077, 1078, 1079, - 1080, 0, 332, 0, 7, 8, 0, 0, 337, 0, - 337, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 35, 36, 37, 38, 39, - 0, 0, 1115, 0, 43, 0, 0, 46, 500, 15, - 16, 501, 18, 19, 502, 21, 503, 23, 1133, 24, - 0, 26, 27, 0, 29, 30, 31, 0, 0, 0, - 34, 0, 0, 0, 0, 337, 121, 122, 123, 124, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 50, 51, 52, 0, 129, 333, 0, - 0, 0, 131, 0, 0, 0, 0, 134, 0, 0, - 0, 0, 137, 0, 0, 546, 0, 0, 0, 1170, - 310, 311, 312, 313, 314, 315, 316, 317, 318, 319, - 320, 321, 322, 323, 0, 0, 0, 0, 324, 0, - 0, 0, 1185, 1186, 1187, 1188, 87, 88, 89, 0, - 90, 611, 91, 92, 93, 0, 0, 94, 95, 96, + 114, 876, 1081, 982, 1082, 1086, 1091, 1092, 1094, 988, + 340, 1103, 336, 1106, 1109, 1116, 1112, 994, 995, 996, + 1119, 1122, 1134, 999, 1144, 913, 1147, 1148, 1004, 1005, + 1006, 1135, 341, 1150, 341, 35, 36, 37, 38, 39, + 1136, 1137, 1020, 1138, 43, 1151, 1152, 46, 1027, 1153, + 1159, 1030, 1161, 1162, 1163, 1164, 314, 315, 316, 317, + 318, 319, 320, 321, 322, 323, 324, 325, 326, 327, + 1042, 1043, 1044, 1045, 328, 1165, 121, 1167, 1166, 124, + 125, 126, 1169, 1170, 1179, 1187, 1172, 1181, 1174, 341, + 1194, 1189, 1176, 1178, 1182, 1055, 1205, 1209, 1207, 393, + 1117, 1210, 1211, 1212, 133, 1213, 1248, 1264, 1214, 395, + 1265, 1244, 962, 1240, 139, 1241, 191, 552, 1273, 314, + 315, 316, 317, 318, 319, 320, 321, 322, 323, 324, + 325, 326, 327, 1242, 1243, 1252, 1268, 328, 1274, 1087, + 1088, 1089, 1090, 314, 315, 316, 317, 318, 319, 320, + 321, 322, 323, 324, 325, 326, 327, 1275, 1276, 1277, + 1285, 328, 316, 317, 318, 319, 320, 321, 322, 323, + 324, 325, 326, 327, 1125, 1288, 1291, 1292, 328, 1295, + 1296, 1299, 1149, 1300, 1305, 1313, 87, 335, 1314, 1278, + 1143, 1316, 91, 92, 93, 1320, 1328, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, - 107, 108, 109, 110, 111, 112, 113, 114, 0, 115, - 116, 117, 118, 0, 0, 119, 0, 0, 1220, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 505, 0, - 0, 0, 87, 331, 359, 0, 0, 0, 91, 92, - 93, 0, 0, 94, 95, 96, 97, 98, 99, 100, - 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, - 111, 112, 113, 114, 0, 1253, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 332, 0, 120, 0, 0, - 0, 0, 0, 121, 122, 123, 124, 0, 0, 0, - 0, 125, 126, 127, 128, 0, 0, 0, 35, 36, - 37, 38, 39, 521, 129, 130, 0, 43, 0, 131, - 46, 132, 133, 0, 134, 0, 135, 0, 136, 137, - 0, 138, 0, 0, 0, 310, 311, 312, 313, 314, - 315, 316, 317, 318, 319, 320, 321, 322, 323, 121, - 122, 123, 124, 324, 310, 311, 312, 313, 314, 315, - 316, 317, 318, 319, 320, 321, 322, 323, 0, 0, - 129, 350, 324, 0, 0, 131, 0, 0, 0, 0, - 134, 0, 87, 331, 1015, 137, 0, 351, 91, 92, - 93, 0, 0, 94, 95, 96, 97, 98, 99, 100, - 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, - 111, 112, 113, 114, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 332, 0, 7, 8, 310, - 311, 312, 313, 314, 315, 316, 317, 318, 319, 320, - 321, 322, 323, 0, 0, 0, 0, 324, 35, 36, - 37, 38, 39, 680, 0, 0, 0, 43, 0, 0, - 46, 500, 15, 16, 501, 18, 19, 502, 21, 503, - 23, 0, 24, 0, 26, 27, 0, 29, 30, 31, - 0, 0, 0, 34, 0, 0, 0, 0, 0, 121, - 122, 123, 124, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 50, 51, 52, 0, - 129, 350, 0, 0, 0, 131, 0, 0, 0, 0, - 134, 0, 87, 331, 0, 137, 0, 1016, 91, 92, - 93, 0, 0, 94, 95, 96, 97, 98, 99, 100, - 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, - 111, 112, 113, 114, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 770, 332, 0, 7, 8, 310, - 311, 312, 313, 314, 315, 316, 317, 318, 319, 320, - 321, 322, 323, 0, 0, 0, 0, 324, 35, 36, - 37, 38, 39, 833, 0, 0, 0, 43, 0, 0, - 46, 500, 15, 16, 501, 18, 19, 502, 21, 503, - 23, 0, 24, 0, 26, 27, 0, 29, 30, 31, - 0, 0, 0, 34, 0, 0, 0, 0, 0, 121, - 122, 123, 124, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 50, 51, 52, 0, - 129, 350, 0, 0, 0, 131, 0, 0, 0, 0, - 134, 0, 87, 331, 0, 137, 0, 351, 91, 92, - 93, 0, 0, 94, 95, 96, 97, 98, 99, 100, - 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, - 111, 112, 113, 114, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 790, 332, 0, 7, 8, 310, - 311, 312, 313, 314, 315, 316, 317, 318, 319, 320, - 321, 322, 323, 0, 0, 0, 0, 324, 35, 36, - 37, 38, 39, 867, 0, 0, 0, 43, 0, 0, - 46, 500, 15, 16, 501, 18, 19, 502, 21, 503, - 23, 0, 24, 0, 26, 27, 0, 29, 30, 31, - 0, 0, 0, 34, 0, 0, 0, 0, 0, 121, - 122, 123, 124, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 50, 51, 52, 0, - 129, 333, 0, 0, 0, 131, 0, 0, 0, 0, - 134, 0, 87, 331, 0, 137, 0, 545, 91, 92, - 93, 0, 0, 94, 95, 96, 97, 98, 99, 100, - 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, - 111, 112, 113, 114, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 1256, 332, 0, 7, 8, 310, - 311, 312, 313, 314, 315, 316, 317, 318, 319, 320, - 321, 322, 323, 0, 0, 0, 0, 324, 35, 36, - 37, 38, 39, 904, 0, 0, 0, 43, 0, 0, - 46, 500, 15, 16, 501, 18, 19, 502, 21, 503, + 107, 108, 109, 110, 111, 112, 113, 114, 1318, 1334, + 1329, 1337, 1340, 1343, 1345, 1349, 1350, 1352, 1363, 336, + 314, 315, 316, 317, 318, 319, 320, 321, 322, 323, + 324, 325, 326, 327, 1354, 1365, 1367, 1369, 328, 1371, + 1380, 1180, 35, 36, 37, 38, 39, 1356, 1361, 1381, + 1382, 43, 1168, 1383, 46, 319, 320, 321, 322, 323, + 324, 325, 326, 327, 1195, 1196, 1197, 1198, 328, 1385, + 973, 981, 73, 81, 1286, 1060, 0, 563, 0, 0, + 0, 0, 0, 121, 0, 0, 124, 125, 126, 0, + 314, 315, 316, 317, 318, 319, 320, 321, 322, 323, + 324, 325, 326, 327, 0, 0, 131, 337, 328, 0, + 1230, 133, 0, 0, 0, 0, 136, 0, 0, 0, + 0, 139, 0, 0, 552, 87, 88, 89, 0, 90, + 0, 91, 92, 93, 0, 0, 94, 95, 96, 97, + 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, + 108, 109, 110, 111, 112, 113, 114, 1263, 115, 116, + 117, 118, 0, 0, 119, 0, 0, 7, 8, 0, + 314, 315, 316, 317, 318, 319, 320, 321, 322, 323, + 324, 325, 326, 327, 0, 0, 0, 0, 328, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 506, 15, 16, 507, 18, 19, 508, 21, 509, 23, 0, 24, 0, 26, 27, 0, 29, 30, 31, - 0, 0, 0, 34, 0, 952, 0, 0, 0, 121, - 122, 123, 124, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 50, 51, 52, 0, - 129, 333, 0, 0, 0, 131, 0, 0, 1139, 0, - 134, 0, 87, 331, 0, 137, 0, 731, 91, 92, - 93, 0, 0, 94, 95, 96, 97, 98, 99, 100, - 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, - 111, 112, 113, 114, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 1313, 332, 0, 0, 0, 310, - 311, 312, 313, 314, 315, 316, 317, 318, 319, 320, - 321, 322, 323, 0, 0, 0, 0, 324, 35, 36, - 37, 38, 39, 1158, 0, 0, 0, 43, 0, 0, - 46, 310, 311, 312, 313, 314, 315, 316, 317, 318, - 319, 320, 321, 322, 323, 0, 0, 0, 0, 324, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 121, - 122, 123, 124, 0, 310, 311, 312, 313, 314, 315, - 316, 317, 318, 319, 320, 321, 322, 323, 0, 0, - 129, 350, 324, 0, 0, 131, 0, 0, 1183, 0, - 134, 0, 87, 331, 0, 137, 0, 1019, 91, 92, - 93, 0, 0, 94, 95, 96, 97, 98, 99, 100, - 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, - 111, 112, 113, 114, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 332, 0, 0, 0, 310, - 311, 312, 313, 314, 315, 316, 317, 318, 319, 320, - 321, 322, 323, 0, 0, 0, 0, 324, 35, 36, - 37, 38, 39, 1262, 0, 87, 291, 43, 0, 0, - 46, 91, 92, 93, 0, 0, 94, 95, 96, 97, + 0, 0, 0, 34, 0, 0, 120, 0, 0, 0, + 0, 0, 121, 122, 123, 124, 125, 126, 0, 0, + 0, 0, 127, 128, 129, 130, 50, 51, 52, 0, + 0, 0, 0, 0, 0, 131, 132, 0, 0, 0, + 133, 0, 134, 135, 0, 136, 0, 137, 0, 138, + 139, 0, 140, 87, 335, 363, 0, 0, 0, 91, + 92, 93, 0, 0, 94, 95, 96, 97, 98, 99, + 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, + 110, 111, 112, 113, 114, 0, 617, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 336, 0, 7, 8, + 314, 315, 316, 317, 318, 319, 320, 321, 322, 323, + 324, 325, 326, 327, 0, 0, 0, 0, 328, 35, + 36, 37, 38, 39, 1193, 1099, 0, 1100, 43, 0, + 0, 46, 506, 15, 16, 507, 18, 19, 508, 21, + 509, 23, 0, 24, 0, 26, 27, 0, 29, 30, + 31, 0, 0, 0, 34, 0, 0, 0, 0, 0, + 121, 0, 0, 124, 125, 126, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 50, 51, 52, + 0, 0, 0, 131, 354, 0, 0, 0, 133, 0, + 0, 0, 0, 136, 0, 87, 335, 1025, 139, 0, + 355, 91, 92, 93, 0, 0, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, - 108, 109, 110, 111, 112, 113, 114, 1311, 0, 121, - 122, 123, 124, 0, 310, 311, 312, 313, 314, 315, - 316, 317, 318, 319, 320, 321, 322, 323, 0, 0, - 389, 1107, 324, 0, 0, 131, 0, 0, 0, 0, - 391, 530, 87, 291, 241, 137, 0, 189, 91, 92, - 93, 0, 0, 94, 95, 96, 97, 98, 99, 100, - 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, - 111, 112, 113, 114, 0, 115, 116, 117, 118, 0, - 0, 119, 121, 122, 123, 124, 0, 0, 0, 310, - 311, 312, 313, 314, 315, 316, 317, 318, 319, 320, - 321, 322, 323, 129, 130, 0, 0, 324, 131, 0, - 0, 0, 0, 134, 0, 0, 296, 0, 137, 0, - 297, 0, 0, 310, 311, 312, 313, 314, 315, 316, - 317, 318, 319, 320, 321, 322, 323, 0, 0, 530, - 0, 324, 0, 0, 0, 0, 0, 0, 0, 121, - 122, 123, 124, 0, 0, 310, 311, 312, 313, 314, - 315, 316, 317, 318, 319, 320, 531, 322, 323, 0, - 129, 130, 0, 324, 0, 131, 0, 0, 0, 0, - 134, 607, 87, 291, 0, 137, 0, 1121, 91, 92, + 108, 109, 110, 111, 112, 113, 114, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 778, 336, 0, + 7, 8, 314, 315, 316, 317, 318, 319, 320, 321, + 322, 323, 324, 325, 326, 327, 0, 0, 0, 0, + 328, 35, 36, 37, 38, 39, 1272, 0, 0, 0, + 43, 0, 0, 46, 506, 15, 16, 507, 18, 19, + 508, 21, 509, 23, 0, 24, 0, 26, 27, 0, + 29, 30, 31, 0, 0, 0, 34, 0, 0, 0, + 0, 0, 121, 0, 0, 124, 125, 126, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 50, + 51, 52, 0, 0, 0, 131, 354, 0, 0, 0, + 133, 0, 0, 0, 0, 136, 0, 87, 335, 0, + 139, 0, 1026, 91, 92, 93, 0, 0, 94, 95, + 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, + 106, 107, 108, 109, 110, 111, 112, 113, 114, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 798, + 336, 0, 7, 8, 314, 315, 316, 317, 318, 319, + 320, 321, 322, 323, 324, 325, 326, 327, 0, 0, + 0, 0, 328, 35, 36, 37, 38, 39, 1321, 0, + 0, 0, 43, 0, 0, 46, 506, 15, 16, 507, + 18, 19, 508, 21, 509, 23, 0, 24, 0, 26, + 27, 0, 29, 30, 31, 0, 0, 0, 34, 0, + 0, 0, 0, 0, 121, 0, 0, 124, 125, 126, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 50, 51, 52, 0, 0, 0, 131, 354, 0, + 0, 0, 133, 0, 0, 0, 0, 136, 0, 87, + 335, 0, 139, 0, 355, 91, 92, 93, 0, 0, + 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, + 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, + 114, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 1266, 336, 0, 7, 8, 314, 315, 316, 317, + 318, 319, 320, 321, 322, 323, 324, 325, 326, 327, + 0, 0, 0, 0, 328, 35, 36, 37, 38, 39, + 536, 0, 0, 0, 43, 0, 0, 46, 506, 15, + 16, 507, 18, 19, 508, 21, 509, 23, 0, 24, + 0, 26, 27, 0, 29, 30, 31, 0, 0, 0, + 34, 0, 0, 0, 536, 0, 121, 0, 0, 124, + 125, 126, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 50, 51, 52, 0, 0, 0, 131, + 337, 0, 0, 0, 133, 0, 0, 0, 0, 136, + 613, 87, 335, 0, 139, 0, 551, 91, 92, 93, + 0, 0, 94, 95, 96, 97, 98, 99, 100, 101, + 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, + 112, 113, 114, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 1323, 336, 0, 314, 315, 316, 317, + 318, 319, 320, 321, 322, 323, 324, 537, 326, 327, + 0, 0, 0, 0, 328, 0, 0, 35, 36, 37, + 38, 39, 710, 0, 0, 0, 43, 0, 0, 46, + 314, 315, 316, 317, 318, 319, 320, 321, 322, 323, + 324, 554, 326, 327, 0, 0, 0, 0, 328, 0, + 0, 0, 0, 0, 0, 0, 860, 0, 121, 0, + 0, 124, 125, 126, 0, 0, 314, 315, 316, 317, + 318, 319, 320, 321, 322, 323, 324, 325, 326, 327, + 0, 131, 337, 0, 328, 0, 133, 0, 0, 0, + 0, 136, 925, 87, 335, 0, 139, 0, 739, 91, + 92, 93, 0, 0, 94, 95, 96, 97, 98, 99, + 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, + 110, 111, 112, 113, 114, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 336, 0, 314, 315, + 316, 317, 318, 319, 320, 321, 322, 323, 324, 325, + 326, 327, 0, 0, 0, 0, 328, 0, 0, 35, + 36, 37, 38, 39, 0, 0, 0, 0, 43, 0, + 0, 46, 314, 315, 316, 317, 318, 319, 320, 321, + 322, 323, 324, 325, 326, 327, 0, 0, 0, 0, + 328, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 121, 0, 0, 124, 125, 126, 0, 0, 314, 315, + 316, 317, 318, 319, 320, 321, 322, 323, 324, 325, + 326, 327, 0, 131, 354, 0, 328, 0, 133, 0, + 0, 0, 0, 136, 0, 87, 295, 243, 139, 0, + 1029, 91, 92, 93, 0, 0, 94, 95, 96, 97, + 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, + 108, 109, 110, 111, 112, 113, 114, 0, 115, 116, + 117, 118, 0, 0, 119, 0, 0, 0, 0, 0, + 0, 0, 87, 335, 0, 0, 0, 0, 91, 92, 93, 0, 0, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, - 111, 112, 113, 114, 0, 0, 0, 0, 0, 702, - 0, 87, 291, 0, 0, 0, 0, 91, 92, 93, + 111, 112, 113, 114, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 336, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 881, 0, + 0, 0, 121, 122, 123, 124, 125, 126, 35, 36, + 37, 38, 39, 0, 0, 0, 0, 43, 0, 0, + 46, 0, 0, 0, 0, 131, 132, 0, 0, 0, + 133, 0, 0, 0, 0, 136, 0, 0, 0, 0, + 139, 0, 1131, 0, 0, 0, 0, 0, 0, 121, + 0, 0, 124, 125, 126, 0, 314, 315, 316, 317, + 318, 319, 320, 321, 322, 323, 324, 325, 326, 327, + 0, 0, 393, 1117, 328, 0, 0, 133, 0, 0, + 0, 0, 395, 0, 87, 295, 0, 139, 0, 191, + 91, 92, 93, 0, 0, 94, 95, 96, 97, 98, + 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, + 109, 110, 111, 112, 113, 114, 0, 0, 0, 0, + 0, 7, 8, 87, 295, 0, 0, 0, 0, 91, + 92, 93, 0, 0, 94, 95, 96, 97, 98, 99, + 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, + 110, 111, 112, 113, 114, 506, 15, 16, 507, 18, + 19, 508, 21, 509, 23, 0, 24, 0, 26, 27, + 0, 29, 30, 31, 0, 0, 0, 34, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 121, 0, 0, 124, 125, 126, 0, 0, 0, + 50, 51, 52, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 131, 132, 0, 0, 0, 133, + 0, 0, 0, 0, 136, 0, 0, 300, 0, 139, + 121, 301, 0, 124, 125, 126, 0, 314, 315, 316, + 317, 318, 319, 320, 321, 322, 323, 324, 325, 326, + 327, 0, 0, 131, 132, 328, 0, 0, 133, 0, + 0, 0, 1126, 136, 1127, 0, 717, 0, 139, 0, + 718, 87, 295, 0, 0, 0, 0, 91, 92, 93, 0, 0, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, - 112, 113, 114, 310, 311, 312, 313, 314, 315, 316, - 317, 318, 319, 320, 548, 322, 323, 0, 0, 0, - 0, 324, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 121, - 122, 123, 124, 851, 0, 310, 311, 312, 313, 314, - 315, 316, 317, 318, 319, 320, 321, 322, 323, 0, - 129, 130, 0, 324, 0, 131, 0, 0, 0, 0, - 134, 0, 0, 709, 0, 137, 916, 710, 121, 122, - 123, 124, 0, 310, 311, 312, 313, 314, 315, 316, - 317, 318, 319, 320, 321, 322, 323, 0, 0, 389, - 390, 324, 0, 0, 131, 0, 0, 0, 0, 391, - 0, 87, 331, 0, 137, 0, 189, 91, 92, 93, + 112, 113, 114, 314, 315, 316, 317, 318, 319, 320, + 321, 322, 323, 324, 325, 326, 327, 0, 87, 335, + 0, 328, 0, 494, 91, 92, 93, 0, 577, 94, + 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, + 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 336, 314, 315, 316, 317, 318, 319, 320, 321, + 322, 323, 324, 325, 326, 327, 0, 0, 121, 0, + 328, 124, 125, 126, 35, 36, 37, 38, 39, 742, + 0, 0, 0, 43, 0, 0, 46, 0, 0, 0, + 0, 393, 394, 0, 0, 0, 133, 0, 0, 0, + 0, 395, 0, 0, 0, 0, 139, 0, 191, 0, + 0, 0, 0, 0, 0, 121, 0, 0, 124, 125, + 126, 0, 314, 315, 316, 317, 318, 319, 320, 321, + 322, 323, 324, 325, 326, 327, 0, 0, 131, 337, + 328, 0, 0, 133, 87, 295, 243, 1217, 136, 1218, + 91, 92, 93, 139, 0, 94, 95, 96, 97, 98, + 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, + 109, 110, 111, 112, 113, 114, 0, 115, 116, 117, + 118, 87, 295, 119, 0, 0, 0, 91, 92, 93, 0, 0, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, - 112, 113, 114, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 332, 0, 0, 310, 311, 312, - 313, 314, 315, 316, 317, 318, 319, 320, 321, 322, - 323, 0, 0, 0, 0, 324, 0, 35, 36, 37, - 38, 39, 0, 0, 0, 0, 43, 0, 0, 46, - 310, 311, 312, 313, 314, 315, 316, 317, 318, 319, - 320, 321, 322, 323, 0, 0, 0, 0, 324, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 121, 122, - 123, 124, 0, 310, 311, 312, 313, 314, 315, 316, - 317, 318, 319, 320, 321, 322, 323, 0, 0, 129, - 333, 324, 0, 0, 131, 87, 291, 241, 1089, 134, - 1090, 91, 92, 93, 137, 0, 94, 95, 96, 97, - 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, - 108, 109, 110, 111, 112, 113, 114, 0, 115, 116, - 117, 118, 7, 8, 119, 310, 311, 312, 313, 314, - 315, 316, 317, 318, 319, 320, 321, 322, 323, 0, - 0, 0, 0, 324, 0, 0, 0, 0, 0, 0, - 1116, 0, 1117, 0, 0, 0, 500, 15, 16, 501, - 18, 19, 502, 21, 503, 23, 0, 24, 0, 26, - 27, 0, 29, 30, 31, 0, 0, 0, 34, 0, - 0, 0, 0, 0, 0, 0, -4, 1, 0, 0, - -4, 0, 121, 122, 123, 124, 0, 0, -4, -4, - 0, 50, 51, 52, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 129, 130, 0, 0, 0, 131, 0, - 0, -4, 0, 134, 0, 0, -4, -4, 137, -4, - -4, 0, -4, -4, -4, -4, -4, -4, -4, -4, - -4, -4, 0, -4, -4, -4, -4, -4, -4, -4, - -4, -4, 0, -4, -4, -4, -4, -4, -4, -4, - -4, 0, -4, -4, -4, -4, -4, -4, 0, 0, - -4, -4, 0, 0, 0, 0, -4, -4, -4, -4, - 0, 0, -4, 0, -4, 0, -4, -4, -4, -4, - -4, -4, -4, -4, -4, -4, 6, 0, 0, 0, - -4, -4, -4, -4, 7, 8, 0, 310, 311, 312, - 313, 314, 315, 316, 317, 318, 319, 320, 321, 322, - 323, 0, 0, 0, 0, 324, 0, 9, 0, 0, - 0, 0, 10, 11, 734, 12, 13, 0, 14, 15, + 112, 113, 114, 314, 315, 316, 317, 318, 319, 320, + 321, 322, 323, 324, 325, 326, 327, 0, 0, 0, + 0, 328, 0, 0, 0, 0, 0, 0, 0, 0, + 781, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 121, 122, 123, 124, 125, 126, 0, 314, 315, + 316, 317, 318, 319, 320, 321, 322, 323, 324, 325, + 326, 327, 0, 0, 131, 132, 328, 0, 0, 133, + 0, 0, 0, 0, 136, 813, 0, 0, 121, 139, + 0, 124, 125, 126, -4, 1, 0, 0, -4, 0, + 0, 0, 0, 0, 0, 0, -4, -4, 0, 0, + 0, 131, 132, 0, 0, 0, 133, 0, 0, 0, + 0, 136, 0, 0, 0, 0, 139, 0, 0, -4, + 0, 0, 0, 0, -4, -4, 0, -4, -4, 0, + -4, -4, -4, -4, -4, -4, -4, -4, -4, -4, + 0, -4, -4, -4, -4, -4, -4, -4, -4, -4, + 0, -4, -4, -4, -4, -4, -4, -4, -4, 0, + -4, -4, -4, -4, -4, -4, 0, 0, -4, -4, + 0, 0, 0, 0, -4, -4, -4, -4, 0, 0, + -4, 0, -4, 0, -4, -4, -4, -4, -4, -4, + -4, -4, -4, -4, 0, 0, 6, 0, 0, 0, + -4, -4, -4, -4, 7, 8, 0, 314, 315, 316, + 317, 318, 319, 320, 321, 322, 323, 324, 325, 326, + 327, 0, 0, 0, 0, 328, 0, 9, 0, 0, + 0, 0, 10, 11, 859, 12, 13, 0, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 0, 24, 25, 26, 27, 28, 29, 30, 31, 32, 0, 33, 34, 35, 36, 37, 38, 39, 40, 0, 41, 42, 43, 44, 45, 46, 0, 0, 47, 48, 0, 0, 0, 0, 49, 50, 51, 52, 0, 0, 53, 0, 54, 0, 55, 56, 57, 58, 59, 60, 61, 62, - 63, 64, 0, 0, 0, 0, 65, 66, 67, 68, - 310, 311, 312, 313, 314, 315, 316, 317, 318, 319, - 320, 321, 322, 323, 0, 0, 0, 0, 324, 0, - 0, 0, 0, 0, 0, 1207, 0, 1208, 310, 311, - 312, 313, 314, 315, 316, 317, 318, 319, 320, 321, - 322, 323, 0, 0, 0, 0, 324, 0, 0, 0, - 0, 0, 0, 0, 0, 773, 310, 311, 312, 313, - 314, 315, 316, 317, 318, 319, 320, 321, 322, 323, - 0, 0, 0, 0, 324, 0, 0, 0, 0, 0, - 0, 0, 0, 805, 310, 311, 312, 313, 314, 315, - 316, 317, 318, 319, 320, 321, 322, 323, 0, 0, - 0, 0, 324, 0, 0, 0, 0, 0, 0, 0, - 0, 850, 310, 311, 312, 313, 314, 315, 316, 317, - 318, 319, 320, 321, 322, 323, 0, 0, 0, 0, - 324, 0, 0, 0, 0, 0, 0, 0, 0, 889, - 310, 311, 312, 313, 314, 315, 316, 317, 318, 319, - 320, 321, 322, 323, 0, 0, 0, 0, 324, 0, - 0, 0, 0, 0, 0, 0, 0, 1087, 310, 311, - 312, 313, 314, 315, 316, 317, 318, 319, 320, 321, - 322, 323, 0, 0, 0, 0, 324, 0, 0, 0, - 0, 0, 0, 0, 0, 1104, 310, 311, 312, 313, + 63, 64, 0, 0, 0, 0, 0, 0, 65, 66, + 67, 68, 314, 315, 316, 317, 318, 319, 320, 321, + 322, 323, 324, 325, 326, 327, 0, 0, 0, 0, + 328, 0, 0, 0, 0, 0, 0, 0, 0, 898, 314, 315, 316, 317, 318, 319, 320, 321, 322, 323, - 0, 0, 0, 0, 324, 0, 0, 0, 0, 0, - 0, 0, 0, 1145, 310, 311, 312, 313, 314, 315, - 316, 317, 318, 319, 320, 321, 322, 323, 0, 0, - 0, 0, 324, 0, 0, 0, 0, 0, 0, 0, - 0, 1146, 310, 311, 312, 313, 314, 315, 316, 317, - 318, 319, 320, 321, 322, 323, 0, 0, 0, 0, - 324, 0, 0, 0, 0, 0, 0, 0, 0, 1147, - 310, 311, 312, 313, 314, 315, 316, 317, 318, 319, - 320, 321, 322, 323, 0, 0, 0, 0, 324, 0, - 0, 0, 0, 0, 0, 0, 0, 1148, 310, 311, - 312, 313, 314, 315, 316, 317, 318, 319, 320, 321, - 322, 323, 0, 0, 0, 0, 324, 0, 0, 0, - 0, 0, 0, 0, 0, 1178, 310, 311, 312, 313, + 324, 325, 326, 327, 0, 0, 0, 0, 328, 0, + 0, 0, 0, 0, 0, 0, 0, 1097, 314, 315, + 316, 317, 318, 319, 320, 321, 322, 323, 324, 325, + 326, 327, 0, 0, 0, 0, 328, 0, 0, 0, + 0, 0, 0, 0, 0, 1114, 314, 315, 316, 317, + 318, 319, 320, 321, 322, 323, 324, 325, 326, 327, + 0, 0, 0, 0, 328, 0, 0, 0, 0, 0, + 0, 0, 0, 1155, 314, 315, 316, 317, 318, 319, + 320, 321, 322, 323, 324, 325, 326, 327, 0, 0, + 0, 0, 328, 0, 0, 0, 0, 0, 0, 0, + 0, 1156, 314, 315, 316, 317, 318, 319, 320, 321, + 322, 323, 324, 325, 326, 327, 0, 0, 0, 0, + 328, 0, 0, 0, 0, 0, 0, 0, 0, 1157, 314, 315, 316, 317, 318, 319, 320, 321, 322, 323, - 0, 0, 0, 0, 324, 0, 0, 0, 0, 0, - 0, 0, 0, 1222, 310, 311, 312, 313, 314, 315, - 316, 317, 318, 319, 320, 321, 322, 323, 0, 0, - 0, 0, 324, 0, 0, 0, 0, 0, 0, 0, - 0, 1227, 310, 311, 312, 313, 314, 315, 316, 317, - 318, 319, 320, 321, 322, 323, 0, 0, 0, 0, - 324, 0, 0, 0, 0, 0, 0, 0, 0, 1228, - 310, 311, 312, 313, 314, 315, 316, 317, 318, 319, - 320, 321, 322, 323, 0, 0, 0, 0, 324, 0, - 0, 0, 0, 0, 0, 0, 0, 1244, 310, 311, - 312, 313, 314, 315, 316, 317, 318, 319, 320, 321, - 322, 323, 0, 0, 0, 0, 324, 0, 0, 0, - 0, 0, 0, 0, 0, 1247, 310, 311, 312, 313, + 324, 325, 326, 327, 0, 0, 0, 0, 328, 0, + 0, 0, 0, 0, 0, 0, 0, 1158, 314, 315, + 316, 317, 318, 319, 320, 321, 322, 323, 324, 325, + 326, 327, 0, 0, 0, 0, 328, 0, 0, 0, + 0, 0, 0, 0, 0, 1188, 314, 315, 316, 317, + 318, 319, 320, 321, 322, 323, 324, 325, 326, 327, + 0, 0, 0, 0, 328, 0, 0, 0, 0, 0, + 0, 0, 0, 1232, 314, 315, 316, 317, 318, 319, + 320, 321, 322, 323, 324, 325, 326, 327, 0, 0, + 0, 0, 328, 0, 0, 0, 0, 0, 0, 0, + 0, 1237, 314, 315, 316, 317, 318, 319, 320, 321, + 322, 323, 324, 325, 326, 327, 0, 0, 0, 0, + 328, 0, 0, 0, 0, 0, 0, 0, 0, 1238, 314, 315, 316, 317, 318, 319, 320, 321, 322, 323, - 0, 0, 0, 0, 324, 0, 0, 0, 0, 0, - 0, 0, 0, 1250, 310, 311, 312, 313, 314, 315, - 316, 317, 318, 319, 320, 321, 322, 323, 0, 0, - 0, 0, 324, 0, 0, 0, 0, 0, 0, 0, - 0, 1274, 310, 311, 312, 313, 314, 315, 316, 317, - 318, 319, 320, 321, 322, 323, 0, 0, 0, 0, - 324, 0, 0, 0, 0, 0, 0, 0, 0, 1277, - 310, 311, 312, 313, 314, 315, 316, 317, 318, 319, - 320, 321, 322, 323, 0, 0, 0, 0, 324, 0, - 0, 0, 0, 0, 0, 0, 0, 1305, 310, 311, - 312, 313, 314, 315, 316, 317, 318, 319, 320, 321, - 322, 323, 0, 0, 0, 0, 324, 0, 0, 0, - 0, 0, 0, 0, 0, 1307, 310, 311, 312, 313, + 324, 325, 326, 327, 0, 0, 0, 0, 328, 0, + 0, 0, 0, 0, 0, 0, 0, 1254, 314, 315, + 316, 317, 318, 319, 320, 321, 322, 323, 324, 325, + 326, 327, 0, 0, 0, 0, 328, 0, 0, 0, + 0, 0, 0, 0, 0, 1257, 314, 315, 316, 317, + 318, 319, 320, 321, 322, 323, 324, 325, 326, 327, + 0, 0, 0, 0, 328, 0, 0, 0, 0, 0, + 0, 0, 0, 1260, 314, 315, 316, 317, 318, 319, + 320, 321, 322, 323, 324, 325, 326, 327, 0, 0, + 0, 0, 328, 0, 0, 0, 0, 0, 0, 0, + 0, 1284, 314, 315, 316, 317, 318, 319, 320, 321, + 322, 323, 324, 325, 326, 327, 0, 0, 0, 0, + 328, 0, 0, 0, 0, 0, 0, 0, 0, 1287, 314, 315, 316, 317, 318, 319, 320, 321, 322, 323, - 0, 0, 0, 0, 324, 0, 0, 0, 0, 0, - 0, 0, 0, 1309, 310, 311, 312, 313, 314, 315, - 316, 317, 318, 319, 320, 321, 322, 323, 0, 0, - 0, 0, 324, 0, 0, 0, 0, 0, 0, 0, - 0, 1322, 310, 311, 312, 313, 314, 315, 316, 317, - 318, 319, 320, 321, 322, 323, 0, 0, 0, 0, - 324, 0, 488, 0, 0, 0, 0, 571, 310, 311, - 312, 313, 314, 315, 316, 317, 318, 319, 320, 321, - 322, 323, 0, 0, 0, 0, 324, 0, 0, 0, - 0, 0, 0, 524, 310, 311, 312, 313, 314, 315, - 316, 317, 318, 319, 320, 321, 322, 323, 0, 0, - 0, 0, 324, 0, 0, 0, 0, 0, 0, 571, - 310, 311, 312, 313, 314, 315, 316, 317, 318, 319, - 320, 321, 322, 323, 0, 0, 0, 0, 324, 0, - 0, 0, 0, 0, 0, 572, 310, 311, 312, 313, + 324, 325, 326, 327, 0, 0, 0, 0, 328, 0, + 0, 0, 0, 0, 0, 0, 0, 1315, 314, 315, + 316, 317, 318, 319, 320, 321, 322, 323, 324, 325, + 326, 327, 0, 0, 0, 0, 328, 0, 0, 0, + 0, 0, 0, 0, 0, 1317, 314, 315, 316, 317, + 318, 319, 320, 321, 322, 323, 324, 325, 326, 327, + 0, 0, 0, 0, 328, 0, 0, 0, 0, 0, + 0, 0, 0, 1319, 314, 315, 316, 317, 318, 319, + 320, 321, 322, 323, 324, 325, 326, 327, 0, 0, + 0, 0, 328, 0, 0, 0, 0, 0, 0, 0, + 0, 1332, 314, 315, 316, 317, 318, 319, 320, 321, + 322, 323, 324, 325, 326, 327, 0, 0, 0, 0, + 328, 0, 0, 0, 0, 0, 0, 530, 314, 315, + 316, 317, 318, 319, 320, 321, 322, 323, 324, 325, + 326, 327, 0, 0, 0, 0, 328, 0, 0, 0, + 0, 0, 0, 577, 314, 315, 316, 317, 318, 319, + 320, 321, 322, 323, 324, 325, 326, 327, 0, 0, + 0, 0, 328, 0, 0, 0, 0, 0, 0, 578, 314, 315, 316, 317, 318, 319, 320, 321, 322, 323, - 0, 0, 0, 0, 324, 0, 0, 0, 0, 0, - 0, 604, 310, 311, 312, 313, 314, 315, 316, 317, - 318, 319, 320, 321, 322, 323, 0, 0, 0, 0, - 324, 0, 0, 0, 0, 0, 0, 655, 310, 311, - 312, 313, 314, 315, 316, 317, 318, 319, 320, 321, - 322, 323, 0, 0, 0, 0, 324, 0, 0, 0, - 0, 0, 0, 656, 310, 311, 312, 313, 314, 315, - 316, 317, 318, 319, 320, 321, 322, 323, 0, 0, - 0, 0, 324, 0, 0, 0, 0, 0, 0, 669, - 310, 311, 312, 313, 314, 315, 316, 317, 318, 319, - 320, 321, 322, 323, 0, 0, 0, 0, 324, 0, - 0, 0, 0, 0, 0, 670, 310, 311, 312, 313, + 324, 325, 326, 327, 0, 0, 0, 0, 328, 0, + 0, 0, 0, 0, 0, 610, 314, 315, 316, 317, + 318, 319, 320, 321, 322, 323, 324, 325, 326, 327, + 0, 0, 0, 0, 328, 0, 0, 0, 0, 0, + 0, 661, 314, 315, 316, 317, 318, 319, 320, 321, + 322, 323, 324, 325, 326, 327, 0, 0, 0, 0, + 328, 0, 0, 0, 0, 0, 0, 662, 314, 315, + 316, 317, 318, 319, 320, 321, 322, 323, 324, 325, + 326, 327, 0, 0, 0, 0, 328, 0, 0, 0, + 0, 0, 0, 675, 314, 315, 316, 317, 318, 319, + 320, 321, 322, 323, 324, 325, 326, 327, 0, 0, + 0, 0, 328, 0, 0, 0, 0, 0, 0, 676, 314, 315, 316, 317, 318, 319, 320, 321, 322, 323, - 0, 0, 0, 0, 324, 0, 0, 0, 0, 0, - 0, 671, 310, 311, 312, 313, 314, 315, 316, 317, - 318, 319, 320, 321, 322, 323, 0, 0, 0, 0, - 324, 0, 0, 0, 0, 0, 0, 672, 310, 311, - 312, 313, 314, 315, 316, 317, 318, 319, 320, 321, - 322, 323, 0, 0, 0, 0, 324, 0, 0, 0, - 0, 0, 0, 673, 310, 311, 312, 313, 314, 315, - 316, 317, 318, 319, 320, 321, 322, 323, 0, 0, - 0, 0, 324, 0, 0, 0, 0, 0, 0, 674, - 310, 311, 312, 313, 314, 315, 316, 317, 318, 319, - 320, 321, 322, 323, 0, 0, 0, 0, 324, 0, - 0, 0, 0, 0, 0, 761, 310, 311, 312, 313, + 324, 325, 326, 327, 0, 0, 0, 0, 328, 0, + 0, 0, 0, 0, 0, 677, 314, 315, 316, 317, + 318, 319, 320, 321, 322, 323, 324, 325, 326, 327, + 0, 0, 0, 0, 328, 0, 0, 0, 0, 0, + 0, 678, 314, 315, 316, 317, 318, 319, 320, 321, + 322, 323, 324, 325, 326, 327, 0, 0, 0, 0, + 328, 0, 0, 0, 0, 0, 0, 679, 314, 315, + 316, 317, 318, 319, 320, 321, 322, 323, 324, 325, + 326, 327, 0, 0, 0, 0, 328, 0, 0, 0, + 0, 0, 0, 680, 314, 315, 316, 317, 318, 319, + 320, 321, 322, 323, 324, 325, 326, 327, 0, 0, + 0, 0, 328, 0, 0, 0, 0, 0, 0, 769, 314, 315, 316, 317, 318, 319, 320, 321, 322, 323, - 0, 0, 0, 0, 324, 0, 0, 0, 0, 0, - 0, 762, 310, 311, 312, 313, 314, 315, 316, 317, - 318, 319, 320, 321, 322, 323, 0, 0, 0, 0, - 324, 0, 0, 0, 0, 0, 0, 763, 310, 311, - 312, 313, 314, 315, 316, 317, 318, 319, 320, 321, - 322, 323, 0, 0, 0, 0, 324, 0, 0, 0, - 0, 0, 0, 847, 310, 311, 312, 313, 314, 315, - 316, 317, 318, 319, 320, 321, 322, 323, 0, 0, - 0, 0, 324, 0, 0, 0, 0, 0, 0, 887, - 310, 311, 312, 313, 314, 315, 316, 317, 318, 319, - 320, 321, 322, 323, 0, 0, 0, 0, 324, 0, - 0, 0, 0, 0, 0, 888, 310, 311, 312, 313, + 324, 325, 326, 327, 0, 0, 0, 0, 328, 0, + 0, 0, 0, 0, 0, 770, 314, 315, 316, 317, + 318, 319, 320, 321, 322, 323, 324, 325, 326, 327, + 0, 0, 0, 0, 328, 0, 0, 0, 0, 0, + 0, 771, 314, 315, 316, 317, 318, 319, 320, 321, + 322, 323, 324, 325, 326, 327, 0, 0, 0, 0, + 328, 0, 0, 0, 0, 0, 0, 856, 314, 315, + 316, 317, 318, 319, 320, 321, 322, 323, 324, 325, + 326, 327, 0, 0, 0, 0, 328, 0, 0, 0, + 0, 0, 0, 896, 314, 315, 316, 317, 318, 319, + 320, 321, 322, 323, 324, 325, 326, 327, 0, 0, + 0, 0, 328, 0, 0, 0, 0, 0, 0, 897, 314, 315, 316, 317, 318, 319, 320, 321, 322, 323, - 0, 0, 0, 0, 324, 0, 0, 0, 0, 0, - 0, 915, 310, 311, 312, 313, 314, 315, 316, 317, - 318, 319, 320, 321, 322, 323, 0, 0, 0, 0, - 324, 0, 0, 0, 0, 0, 0, 1039, 310, 311, - 312, 313, 314, 315, 316, 317, 318, 319, 320, 321, - 322, 323, 0, 0, 0, 0, 324, 0, 0, 0, - 0, 0, 0, 1040, 310, 311, 312, 313, 314, 315, - 316, 317, 318, 319, 320, 321, 322, 323, 0, 0, - 0, 0, 324, 0, 0, 0, 0, 0, 0, 1059, - 310, 311, 312, 313, 314, 315, 316, 317, 318, 319, - 320, 321, 322, 323, 0, 0, 0, 0, 324, 0, - 0, 0, 0, 0, 0, 1191, 310, 311, 312, 313, + 324, 325, 326, 327, 0, 0, 0, 0, 328, 0, + 0, 0, 0, 0, 0, 924, 314, 315, 316, 317, + 318, 319, 320, 321, 322, 323, 324, 325, 326, 327, + 0, 0, 0, 0, 328, 0, 0, 0, 0, 0, + 0, 1049, 314, 315, 316, 317, 318, 319, 320, 321, + 322, 323, 324, 325, 326, 327, 0, 0, 0, 0, + 328, 0, 0, 0, 0, 0, 0, 1050, 314, 315, + 316, 317, 318, 319, 320, 321, 322, 323, 324, 325, + 326, 327, 0, 0, 0, 0, 328, 0, 0, 0, + 0, 0, 0, 1069, 314, 315, 316, 317, 318, 319, + 320, 321, 322, 323, 324, 325, 326, 327, 0, 0, + 0, 0, 328, 0, 0, 0, 0, 0, 0, 1201, 314, 315, 316, 317, 318, 319, 320, 321, 322, 323, - 0, 0, 0, 0, 324, 0, 0, 0, 0, 0, - 0, 1192, 310, 311, 312, 313, 314, 315, 316, 317, - 318, 319, 320, 321, 322, 323, 0, 0, 0, 0, - 324, 0, 0, 0, 0, 0, 0, 1198, 310, 311, - 312, 313, 314, 315, 316, 317, 318, 319, 320, 321, - 322, 323, 0, 0, 0, 0, 324, 0, 0, 0, - 0, 0, 0, 1270, 310, 311, 312, 313, 314, 315, - 316, 317, 318, 319, 320, 321, 322, 323, 0, 0, - 0, 0, 324, 0, 0, 0, 0, 0, 0, 1273, - 310, 311, 312, 313, 314, 315, 316, 317, 318, 319, - 320, 321, 322, 323, 0, 0, 0, 0, 324, 0, - 0, 0, 492, 310, 311, 312, 313, 314, 315, 316, - 317, 318, 319, 320, 321, 322, 323, 0, 0, 0, - 0, 324, 0, 0, 0, 609, 310, 311, 312, 313, + 324, 325, 326, 327, 0, 0, 0, 0, 328, 0, + 0, 0, 0, 0, 0, 1202, 314, 315, 316, 317, + 318, 319, 320, 321, 322, 323, 324, 325, 326, 327, + 0, 0, 0, 0, 328, 0, 0, 0, 0, 0, + 0, 1208, 314, 315, 316, 317, 318, 319, 320, 321, + 322, 323, 324, 325, 326, 327, 0, 0, 0, 0, + 328, 0, 0, 0, 0, 0, 0, 1280, 314, 315, + 316, 317, 318, 319, 320, 321, 322, 323, 324, 325, + 326, 327, 0, 0, 0, 0, 328, 0, 0, 0, + 0, 0, 0, 1283, 314, 315, 316, 317, 318, 319, + 320, 321, 322, 323, 324, 325, 326, 327, 0, 0, + 0, 0, 328, 0, 0, 0, 498, 314, 315, 316, + 317, 318, 319, 320, 321, 322, 323, 324, 325, 326, + 327, 0, 0, 0, 0, 328, 0, 0, 0, 615, 314, 315, 316, 317, 318, 319, 320, 321, 322, 323, - 0, 0, 0, 0, 324, 0, 0, 0, 619, 310, - 311, 312, 313, 314, 315, 316, 317, 318, 319, 320, - 321, 322, 323, 0, 0, 0, 0, 324, 0, 0, - 0, 634, 310, 311, 312, 313, 314, 315, 316, 317, - 318, 319, 320, 321, 322, 323, 0, 0, 0, 0, - 324, 0, 0, 0, 636, 310, 311, 312, 313, 314, - 315, 316, 317, 318, 319, 320, 321, 322, 323, 0, - 0, 0, 0, 324, 0, 0, 0, 638, 310, 311, - 312, 313, 314, 315, 316, 317, 318, 319, 320, 321, - 322, 323, 0, 0, 0, 0, 324, 0, 0, 0, - 640, 310, 311, 312, 313, 314, 315, 316, 317, 318, - 319, 320, 321, 322, 323, 0, 0, 0, 0, 324, - 0, 0, 0, 642, 310, 311, 312, 313, 314, 315, - 316, 317, 318, 319, 320, 321, 322, 323, 0, 0, - 0, 0, 324, 0, 0, 0, 644, 310, 311, 312, - 313, 314, 315, 316, 317, 318, 319, 320, 321, 322, - 323, 0, 0, 0, 0, 324, 0, 0, 0, 646, - 310, 311, 312, 313, 314, 315, 316, 317, 318, 319, - 320, 321, 322, 323, 0, 0, 0, 0, 324, 0, - 0, 0, 648, 310, 311, 312, 313, 314, 315, 316, - 317, 318, 319, 320, 321, 322, 323, 0, 0, 0, - 0, 324, 0, 0, 0, 650, 310, 311, 312, 313, + 324, 325, 326, 327, 0, 0, 0, 0, 328, 0, + 0, 0, 625, 314, 315, 316, 317, 318, 319, 320, + 321, 322, 323, 324, 325, 326, 327, 0, 0, 0, + 0, 328, 0, 0, 0, 640, 314, 315, 316, 317, + 318, 319, 320, 321, 322, 323, 324, 325, 326, 327, + 0, 0, 0, 0, 328, 0, 0, 0, 642, 314, + 315, 316, 317, 318, 319, 320, 321, 322, 323, 324, + 325, 326, 327, 0, 0, 0, 0, 328, 0, 0, + 0, 644, 314, 315, 316, 317, 318, 319, 320, 321, + 322, 323, 324, 325, 326, 327, 0, 0, 0, 0, + 328, 0, 0, 0, 646, 314, 315, 316, 317, 318, + 319, 320, 321, 322, 323, 324, 325, 326, 327, 0, + 0, 0, 0, 328, 0, 0, 0, 648, 314, 315, + 316, 317, 318, 319, 320, 321, 322, 323, 324, 325, + 326, 327, 0, 0, 0, 0, 328, 0, 0, 0, + 650, 314, 315, 316, 317, 318, 319, 320, 321, 322, + 323, 324, 325, 326, 327, 0, 0, 0, 0, 328, + 0, 0, 0, 652, 314, 315, 316, 317, 318, 319, + 320, 321, 322, 323, 324, 325, 326, 327, 0, 0, + 0, 0, 328, 0, 0, 0, 654, 314, 315, 316, + 317, 318, 319, 320, 321, 322, 323, 324, 325, 326, + 327, 0, 0, 0, 0, 328, 0, 0, 0, 656, 314, 315, 316, 317, 318, 319, 320, 321, 322, 323, - 0, 0, 0, 0, 324, 0, 0, 0, 652, 310, - 311, 312, 313, 314, 315, 316, 317, 318, 319, 320, - 321, 322, 323, 0, 0, 0, 0, 324, 0, 0, - 0, 654, 310, 311, 312, 313, 314, 315, 316, 317, - 318, 319, 320, 321, 322, 323, 0, 0, 0, 0, - 324, 0, 0, 0, 658, 310, 311, 312, 313, 314, - 315, 316, 317, 318, 319, 320, 321, 322, 323, 0, - 0, 0, 0, 324, 0, 0, 0, 660, 310, 311, - 312, 313, 314, 315, 316, 317, 318, 319, 320, 321, - 322, 323, 0, 0, 0, 0, 324, 0, 0, 0, - 662, 310, 311, 312, 313, 314, 315, 316, 317, 318, - 319, 320, 321, 322, 323, 0, 0, 0, 0, 324, - 0, 0, 0, 664, 310, 311, 312, 313, 314, 315, - 316, 317, 318, 319, 320, 321, 322, 323, 0, 0, - 0, 0, 324, 0, 0, 0, 666, 310, 311, 312, - 313, 314, 315, 316, 317, 318, 319, 320, 321, 322, - 323, 0, 0, 0, 0, 324, 0, 0, 0, 668, - 310, 311, 312, 313, 314, 315, 316, 317, 318, 319, - 320, 321, 322, 323, 0, 0, 0, 0, 324, 0, - 0, 0, 780, 310, 311, 312, 313, 314, 315, 316, - 317, 318, 319, 320, 321, 322, 323, 0, 0, 0, - 0, 324, 0, 0, 0, 781, 310, 311, 312, 313, + 324, 325, 326, 327, 0, 0, 0, 0, 328, 0, + 0, 0, 658, 314, 315, 316, 317, 318, 319, 320, + 321, 322, 323, 324, 325, 326, 327, 0, 0, 0, + 0, 328, 0, 0, 0, 660, 314, 315, 316, 317, + 318, 319, 320, 321, 322, 323, 324, 325, 326, 327, + 0, 0, 0, 0, 328, 0, 0, 0, 664, 314, + 315, 316, 317, 318, 319, 320, 321, 322, 323, 324, + 325, 326, 327, 0, 0, 0, 0, 328, 0, 0, + 0, 666, 314, 315, 316, 317, 318, 319, 320, 321, + 322, 323, 324, 325, 326, 327, 0, 0, 0, 0, + 328, 0, 0, 0, 668, 314, 315, 316, 317, 318, + 319, 320, 321, 322, 323, 324, 325, 326, 327, 0, + 0, 0, 0, 328, 0, 0, 0, 670, 314, 315, + 316, 317, 318, 319, 320, 321, 322, 323, 324, 325, + 326, 327, 0, 0, 0, 0, 328, 0, 0, 0, + 672, 314, 315, 316, 317, 318, 319, 320, 321, 322, + 323, 324, 325, 326, 327, 0, 0, 0, 0, 328, + 0, 0, 0, 674, 314, 315, 316, 317, 318, 319, + 320, 321, 322, 323, 324, 325, 326, 327, 0, 0, + 0, 0, 328, 0, 0, 0, 788, 314, 315, 316, + 317, 318, 319, 320, 321, 322, 323, 324, 325, 326, + 327, 0, 0, 0, 0, 328, 0, 0, 0, 789, 314, 315, 316, 317, 318, 319, 320, 321, 322, 323, - 0, 0, 0, 0, 324, 0, 0, 0, 783, 310, - 311, 312, 313, 314, 315, 316, 317, 318, 319, 320, - 321, 322, 323, 0, 0, 0, 0, 324, 0, 0, - 0, 784, 310, 311, 312, 313, 314, 315, 316, 317, - 318, 319, 320, 321, 322, 323, 0, 0, 0, 0, - 324, 0, 0, 0, 801, 310, 311, 312, 313, 314, - 315, 316, 317, 318, 319, 320, 321, 322, 323, 0, - 0, 0, 0, 324, 0, 0, 0, 823, 310, 311, - 312, 313, 314, 315, 316, 317, 318, 319, 320, 321, - 322, 323, 0, 0, 0, 0, 324, 0, 0, 0, - 921, 310, 311, 312, 313, 314, 315, 316, 317, 318, - 319, 320, 321, 322, 323, 0, 0, 0, 0, 324, - 0, 0, 0, 936, 310, 311, 312, 313, 314, 315, - 316, 317, 318, 319, 320, 321, 322, 323, 0, 0, - 0, 0, 324, 0, 0, 0, 938, 310, 311, 312, - 313, 314, 315, 316, 317, 318, 319, 320, 321, 322, - 323, 0, 0, 0, 0, 324, 0, 0, 0, 940, - 310, 311, 312, 313, 314, 315, 316, 317, 318, 319, - 320, 321, 322, 323, 0, 0, 0, 0, 324, 0, - 0, 0, 942, 310, 311, 312, 313, 314, 315, 316, - 317, 318, 319, 320, 321, 322, 323, 0, 0, 0, - 0, 324, 0, 0, 0, 1052, 310, 311, 312, 313, + 324, 325, 326, 327, 0, 0, 0, 0, 328, 0, + 0, 0, 791, 314, 315, 316, 317, 318, 319, 320, + 321, 322, 323, 324, 325, 326, 327, 0, 0, 0, + 0, 328, 0, 0, 0, 792, 314, 315, 316, 317, + 318, 319, 320, 321, 322, 323, 324, 325, 326, 327, + 0, 0, 0, 0, 328, 0, 0, 0, 809, 314, + 315, 316, 317, 318, 319, 320, 321, 322, 323, 324, + 325, 326, 327, 0, 0, 0, 0, 328, 0, 0, + 0, 832, 314, 315, 316, 317, 318, 319, 320, 321, + 322, 323, 324, 325, 326, 327, 0, 0, 0, 0, + 328, 0, 0, 0, 930, 314, 315, 316, 317, 318, + 319, 320, 321, 322, 323, 324, 325, 326, 327, 0, + 0, 0, 0, 328, 0, 0, 0, 945, 314, 315, + 316, 317, 318, 319, 320, 321, 322, 323, 324, 325, + 326, 327, 0, 0, 0, 0, 328, 0, 0, 0, + 947, 314, 315, 316, 317, 318, 319, 320, 321, 322, + 323, 324, 325, 326, 327, 0, 0, 0, 0, 328, + 0, 0, 0, 949, 314, 315, 316, 317, 318, 319, + 320, 321, 322, 323, 324, 325, 326, 327, 0, 0, + 0, 0, 328, 0, 0, 0, 951, 314, 315, 316, + 317, 318, 319, 320, 321, 322, 323, 324, 325, 326, + 327, 0, 0, 0, 0, 328, 0, 0, 0, 1062, 314, 315, 316, 317, 318, 319, 320, 321, 322, 323, - 0, 0, 0, 0, 324, 0, 488, 310, 311, 312, - 313, 314, 315, 316, 317, 318, 319, 320, 321, 322, - 323, 0, 0, 0, 0, 324, 0, 525, 310, 311, - 312, 313, 314, 315, 316, 317, 318, 319, 320, 321, - 322, 323, 0, 0, 0, 0, 324, 0, 534, 310, - 311, 312, 313, 314, 315, 316, 317, 318, 319, 320, - 321, 322, 323, 0, 0, 0, 0, 324, 0, 535, - 310, 311, 312, 313, 314, 315, 316, 317, 318, 319, - 320, 321, 322, 323, 0, 0, 0, 0, 324, 0, - 537, 310, 311, 312, 313, 314, 315, 316, 317, 318, - 319, 320, 321, 322, 323, 0, 0, 0, 0, 324, - 0, 539, 310, 311, 312, 313, 314, 315, 316, 317, - 318, 319, 320, 321, 322, 323, 0, 0, 0, 0, - 324, 0, 540, 310, 311, 312, 313, 314, 315, 316, - 317, 318, 319, 320, 321, 322, 323, 0, 0, 0, - 0, 324, 0, 543, 310, 311, 312, 313, 314, 315, - 316, 317, 318, 319, 320, 321, 322, 323, 0, 0, - 0, 0, 324, 0, 544, 310, 311, 312, 313, 314, - 315, 316, 317, 318, 319, 320, 321, 322, 323, 0, - 0, 0, 0, 324, 0, 600, 310, 311, 312, 313, + 324, 325, 326, 327, 0, 0, 0, 0, 328, 0, + 494, 314, 315, 316, 317, 318, 319, 320, 321, 322, + 323, 324, 325, 326, 327, 0, 0, 0, 0, 328, + 0, 531, 314, 315, 316, 317, 318, 319, 320, 321, + 322, 323, 324, 325, 326, 327, 0, 0, 0, 0, + 328, 0, 540, 314, 315, 316, 317, 318, 319, 320, + 321, 322, 323, 324, 325, 326, 327, 0, 0, 0, + 0, 328, 0, 541, 314, 315, 316, 317, 318, 319, + 320, 321, 322, 323, 324, 325, 326, 327, 0, 0, + 0, 0, 328, 0, 543, 314, 315, 316, 317, 318, + 319, 320, 321, 322, 323, 324, 325, 326, 327, 0, + 0, 0, 0, 328, 0, 545, 314, 315, 316, 317, + 318, 319, 320, 321, 322, 323, 324, 325, 326, 327, + 0, 0, 0, 0, 328, 0, 546, 314, 315, 316, + 317, 318, 319, 320, 321, 322, 323, 324, 325, 326, + 327, 0, 0, 0, 0, 328, 0, 549, 314, 315, + 316, 317, 318, 319, 320, 321, 322, 323, 324, 325, + 326, 327, 0, 0, 0, 0, 328, 0, 550, 314, + 315, 316, 317, 318, 319, 320, 321, 322, 323, 324, + 325, 326, 327, 0, 0, 0, 0, 328, 0, 606, 314, 315, 316, 317, 318, 319, 320, 321, 322, 323, - 0, 0, 0, 0, 324, 0, 601, 310, 311, 312, - 313, 314, 315, 316, 317, 318, 319, 320, 321, 322, - 323, 0, 0, 0, 0, 324, 0, 602, 310, 311, - 312, 313, 314, 315, 316, 317, 318, 319, 320, 321, - 322, 323, 0, 0, 0, 0, 324, 0, 608, 310, - 311, 312, 313, 314, 315, 316, 317, 318, 319, 320, - 321, 322, 323, 0, 0, 0, 0, 324, 0, 633, - 310, 311, 312, 313, 314, 315, 316, 317, 318, 319, - 320, 321, 322, 323, 0, 0, 0, 0, 324, 0, - 635, 310, 311, 312, 313, 314, 315, 316, 317, 318, - 319, 320, 321, 322, 323, 0, 0, 0, 0, 324, - 0, 637, 310, 311, 312, 313, 314, 315, 316, 317, - 318, 319, 320, 321, 322, 323, 0, 0, 0, 0, - 324, 0, 639, 310, 311, 312, 313, 314, 315, 316, - 317, 318, 319, 320, 321, 322, 323, 0, 0, 0, - 0, 324, 0, 641, 310, 311, 312, 313, 314, 315, - 316, 317, 318, 319, 320, 321, 322, 323, 0, 0, - 0, 0, 324, 0, 643, 310, 311, 312, 313, 314, - 315, 316, 317, 318, 319, 320, 321, 322, 323, 0, - 0, 0, 0, 324, 0, 645, 310, 311, 312, 313, + 324, 325, 326, 327, 0, 0, 0, 0, 328, 0, + 607, 314, 315, 316, 317, 318, 319, 320, 321, 322, + 323, 324, 325, 326, 327, 0, 0, 0, 0, 328, + 0, 608, 314, 315, 316, 317, 318, 319, 320, 321, + 322, 323, 324, 325, 326, 327, 0, 0, 0, 0, + 328, 0, 614, 314, 315, 316, 317, 318, 319, 320, + 321, 322, 323, 324, 325, 326, 327, 0, 0, 0, + 0, 328, 0, 639, 314, 315, 316, 317, 318, 319, + 320, 321, 322, 323, 324, 325, 326, 327, 0, 0, + 0, 0, 328, 0, 641, 314, 315, 316, 317, 318, + 319, 320, 321, 322, 323, 324, 325, 326, 327, 0, + 0, 0, 0, 328, 0, 643, 314, 315, 316, 317, + 318, 319, 320, 321, 322, 323, 324, 325, 326, 327, + 0, 0, 0, 0, 328, 0, 645, 314, 315, 316, + 317, 318, 319, 320, 321, 322, 323, 324, 325, 326, + 327, 0, 0, 0, 0, 328, 0, 647, 314, 315, + 316, 317, 318, 319, 320, 321, 322, 323, 324, 325, + 326, 327, 0, 0, 0, 0, 328, 0, 649, 314, + 315, 316, 317, 318, 319, 320, 321, 322, 323, 324, + 325, 326, 327, 0, 0, 0, 0, 328, 0, 651, 314, 315, 316, 317, 318, 319, 320, 321, 322, 323, - 0, 0, 0, 0, 324, 0, 647, 310, 311, 312, - 313, 314, 315, 316, 317, 318, 319, 320, 321, 322, - 323, 0, 0, 0, 0, 324, 0, 649, 310, 311, - 312, 313, 314, 315, 316, 317, 318, 319, 320, 321, - 322, 323, 0, 0, 0, 0, 324, 0, 651, 310, - 311, 312, 313, 314, 315, 316, 317, 318, 319, 320, - 321, 322, 323, 0, 0, 0, 0, 324, 0, 653, - 310, 311, 312, 313, 314, 315, 316, 317, 318, 319, - 320, 321, 322, 323, 0, 0, 0, 0, 324, 0, - 657, 310, 311, 312, 313, 314, 315, 316, 317, 318, - 319, 320, 321, 322, 323, 0, 0, 0, 0, 324, - 0, 659, 310, 311, 312, 313, 314, 315, 316, 317, - 318, 319, 320, 321, 322, 323, 0, 0, 0, 0, - 324, 0, 661, 310, 311, 312, 313, 314, 315, 316, - 317, 318, 319, 320, 321, 322, 323, 0, 0, 0, - 0, 324, 0, 663, 310, 311, 312, 313, 314, 315, - 316, 317, 318, 319, 320, 321, 322, 323, 0, 0, - 0, 0, 324, 0, 665, 310, 311, 312, 313, 314, - 315, 316, 317, 318, 319, 320, 321, 322, 323, 0, - 0, 0, 0, 324, 0, 667, 310, 311, 312, 313, + 324, 325, 326, 327, 0, 0, 0, 0, 328, 0, + 653, 314, 315, 316, 317, 318, 319, 320, 321, 322, + 323, 324, 325, 326, 327, 0, 0, 0, 0, 328, + 0, 655, 314, 315, 316, 317, 318, 319, 320, 321, + 322, 323, 324, 325, 326, 327, 0, 0, 0, 0, + 328, 0, 657, 314, 315, 316, 317, 318, 319, 320, + 321, 322, 323, 324, 325, 326, 327, 0, 0, 0, + 0, 328, 0, 659, 314, 315, 316, 317, 318, 319, + 320, 321, 322, 323, 324, 325, 326, 327, 0, 0, + 0, 0, 328, 0, 663, 314, 315, 316, 317, 318, + 319, 320, 321, 322, 323, 324, 325, 326, 327, 0, + 0, 0, 0, 328, 0, 665, 314, 315, 316, 317, + 318, 319, 320, 321, 322, 323, 324, 325, 326, 327, + 0, 0, 0, 0, 328, 0, 667, 314, 315, 316, + 317, 318, 319, 320, 321, 322, 323, 324, 325, 326, + 327, 0, 0, 0, 0, 328, 0, 669, 314, 315, + 316, 317, 318, 319, 320, 321, 322, 323, 324, 325, + 326, 327, 0, 0, 0, 0, 328, 0, 671, 314, + 315, 316, 317, 318, 319, 320, 321, 322, 323, 324, + 325, 326, 327, 0, 0, 0, 0, 328, 0, 673, 314, 315, 316, 317, 318, 319, 320, 321, 322, 323, - 0, 0, 0, 0, 324, 0, 720, 310, 311, 312, - 313, 314, 315, 316, 317, 318, 319, 320, 321, 322, - 323, 0, 0, 0, 0, 324, 0, 725, 310, 311, - 312, 313, 314, 315, 316, 317, 318, 319, 320, 321, - 322, 323, 0, 0, 0, 0, 324, 0, 733, 310, - 311, 312, 313, 314, 315, 316, 317, 318, 319, 320, - 321, 322, 323, 0, 0, 0, 0, 324, 0, 735, - 310, 311, 312, 313, 314, 315, 316, 317, 318, 319, - 320, 321, 322, 323, 0, 0, 0, 0, 324, 0, - 736, 310, 311, 312, 313, 314, 315, 316, 317, 318, - 319, 320, 321, 322, 323, 0, 0, 0, 0, 324, - 0, 742, 310, 311, 312, 313, 314, 315, 316, 317, - 318, 319, 320, 321, 322, 323, 0, 0, 0, 0, - 324, 0, 749, 310, 311, 312, 313, 314, 315, 316, - 317, 318, 319, 320, 321, 322, 323, 0, 0, 0, - 0, 324, 0, 750, 310, 311, 312, 313, 314, 315, - 316, 317, 318, 319, 320, 321, 322, 323, 0, 0, - 0, 0, 324, 0, 751, 310, 311, 312, 313, 314, - 315, 316, 317, 318, 319, 320, 321, 322, 323, 0, - 0, 0, 0, 324, 0, 772, 310, 311, 312, 313, + 324, 325, 326, 327, 0, 0, 0, 0, 328, 0, + 728, 314, 315, 316, 317, 318, 319, 320, 321, 322, + 323, 324, 325, 326, 327, 0, 0, 0, 0, 328, + 0, 733, 314, 315, 316, 317, 318, 319, 320, 321, + 322, 323, 324, 325, 326, 327, 0, 0, 0, 0, + 328, 0, 741, 314, 315, 316, 317, 318, 319, 320, + 321, 322, 323, 324, 325, 326, 327, 0, 0, 0, + 0, 328, 0, 743, 314, 315, 316, 317, 318, 319, + 320, 321, 322, 323, 324, 325, 326, 327, 0, 0, + 0, 0, 328, 0, 744, 314, 315, 316, 317, 318, + 319, 320, 321, 322, 323, 324, 325, 326, 327, 0, + 0, 0, 0, 328, 0, 750, 314, 315, 316, 317, + 318, 319, 320, 321, 322, 323, 324, 325, 326, 327, + 0, 0, 0, 0, 328, 0, 757, 314, 315, 316, + 317, 318, 319, 320, 321, 322, 323, 324, 325, 326, + 327, 0, 0, 0, 0, 328, 0, 758, 314, 315, + 316, 317, 318, 319, 320, 321, 322, 323, 324, 325, + 326, 327, 0, 0, 0, 0, 328, 0, 759, 314, + 315, 316, 317, 318, 319, 320, 321, 322, 323, 324, + 325, 326, 327, 0, 0, 0, 0, 328, 0, 780, 314, 315, 316, 317, 318, 319, 320, 321, 322, 323, - 0, 0, 0, 0, 324, 0, 774, 310, 311, 312, - 313, 314, 315, 316, 317, 318, 319, 320, 321, 322, - 323, 0, 0, 0, 0, 324, 0, 775, 310, 311, - 312, 313, 314, 315, 316, 317, 318, 319, 320, 321, - 322, 323, 0, 0, 0, 0, 324, 0, 779, 310, - 311, 312, 313, 314, 315, 316, 317, 318, 319, 320, - 321, 322, 323, 0, 0, 0, 0, 324, 0, 935, - 310, 311, 312, 313, 314, 315, 316, 317, 318, 319, - 320, 321, 322, 323, 0, 0, 0, 0, 324, 0, - 937, 310, 311, 312, 313, 314, 315, 316, 317, 318, - 319, 320, 321, 322, 323, 0, 0, 0, 0, 324, - 0, 939, 310, 311, 312, 313, 314, 315, 316, 317, - 318, 319, 320, 321, 322, 323, 0, 0, 0, 0, - 324, 0, 941, 310, 311, 312, 313, 314, 315, 316, - 317, 318, 319, 320, 321, 322, 323, 0, 0, 0, - 0, 324, 0, 945, 310, 311, 312, 313, 314, 315, - 316, 317, 318, 319, 320, 321, 322, 323, 0, 0, - 0, 0, 324, 0, 1088, 310, 311, 312, 313, 314, - 315, 316, 317, 318, 319, 320, 321, 322, 323, 0, - 0, 0, 0, 324, 0, 1103, 310, 311, 312, 313, + 324, 325, 326, 327, 0, 0, 0, 0, 328, 0, + 782, 314, 315, 316, 317, 318, 319, 320, 321, 322, + 323, 324, 325, 326, 327, 0, 0, 0, 0, 328, + 0, 783, 314, 315, 316, 317, 318, 319, 320, 321, + 322, 323, 324, 325, 326, 327, 0, 0, 0, 0, + 328, 0, 787, 314, 315, 316, 317, 318, 319, 320, + 321, 322, 323, 324, 325, 326, 327, 0, 0, 0, + 0, 328, 0, 944, 314, 315, 316, 317, 318, 319, + 320, 321, 322, 323, 324, 325, 326, 327, 0, 0, + 0, 0, 328, 0, 946, 314, 315, 316, 317, 318, + 319, 320, 321, 322, 323, 324, 325, 326, 327, 0, + 0, 0, 0, 328, 0, 948, 314, 315, 316, 317, + 318, 319, 320, 321, 322, 323, 324, 325, 326, 327, + 0, 0, 0, 0, 328, 0, 950, 314, 315, 316, + 317, 318, 319, 320, 321, 322, 323, 324, 325, 326, + 327, 0, 0, 0, 0, 328, 0, 954, 314, 315, + 316, 317, 318, 319, 320, 321, 322, 323, 324, 325, + 326, 327, 0, 0, 0, 0, 328, 0, 1098, 314, + 315, 316, 317, 318, 319, 320, 321, 322, 323, 324, + 325, 326, 327, 0, 0, 0, 0, 328, 0, 1113, 314, 315, 316, 317, 318, 319, 320, 321, 322, 323, - 0, 0, 0, 0, 324, 0, 1120, 310, 311, 312, - 313, 314, 315, 316, 317, 318, 319, 320, 321, 322, - 323, 0, 0, 0, 0, 324, 0, 1269, 310, 311, - 312, 313, 314, 315, 316, 317, 318, 319, 320, 321, - 322, 323, 0, 0, 0, 0, 324, 0, 1320 + 324, 325, 326, 327, 0, 0, 0, 0, 328, 0, + 1130, 314, 315, 316, 317, 318, 319, 320, 321, 322, + 323, 324, 325, 326, 327, 0, 0, 0, 0, 328, + 0, 1279, 314, 315, 316, 317, 318, 319, 320, 321, + 322, 323, 324, 325, 326, 327, 0, 0, 0, 0, + 328, 0, 1330, 314, 315, 316, 317, 318, 319, 320, + 321, 322, 323, 324, 325, 326, 327, 0, 0, 0, + 0, 328 }; static const yytype_int16 yycheck[] = { - 6, 197, 383, 384, 6, 6, 3, 299, 767, 0, - 6, 207, 7, 6, 4, 36, 37, 1134, 39, 4, - 232, 233, 234, 4, 695, 4, 4, 4, 4, 138, - 139, 5, 228, 6, 230, 5, 4, 6, 4, 1156, - 6, 76, 75, 4, 75, 75, 153, 82, 83, 6, - 76, 158, 4, 5, 76, 162, 82, 83, 13, 76, - 82, 83, 4, 76, 6, 82, 83, 7, 6, 82, - 83, 76, 75, 285, 286, 287, 288, 82, 83, 131, - 132, 52, 771, 7, 36, 37, 38, 39, 90, 142, - 42, 171, 172, 7, 147, 147, 86, 87, 88, 89, - 141, 69, 70, 71, 72, 6, 7, 148, 141, 141, - 78, 96, 97, 81, 149, 148, 148, 148, 148, 6, - 96, 97, 202, 129, 130, 131, 104, 149, 134, 135, - 131, 132, 149, 139, 49, 128, 149, 52, 141, 145, - 899, 138, 148, 141, 149, 148, 152, 153, 154, 155, - 145, 157, 158, 159, 160, 1272, 162, 163, 164, 149, - 6, 138, 139, 834, 185, 186, 143, 148, 145, 148, - 148, 128, 193, 150, 148, 148, 197, 143, 148, 148, - 141, 121, 188, 189, 131, 132, 138, 139, 131, 132, - 297, 197, 141, 145, 118, 119, 120, 121, 394, 148, - 492, 148, 6, 56, 118, 119, 120, 121, 214, 215, - 216, 7, 218, 76, 141, 221, 222, 52, 224, 82, - 83, 417, 1339, 141, 138, 139, 76, 138, 139, 76, - 236, 145, 82, 83, 145, 82, 83, 243, 244, 245, + 6, 234, 235, 236, 303, 4, 3, 199, 6, 75, + 6, 387, 388, 6, 6, 36, 37, 209, 39, 1144, + 5, 703, 4, 4, 6, 4, 4, 4, 4, 144, + 155, 4, 4, 4, 149, 160, 5, 7, 230, 164, + 232, 1166, 6, 6, 140, 141, 76, 0, 7, 173, + 174, 147, 82, 83, 287, 288, 289, 290, 6, 292, + 293, 294, 143, 75, 13, 76, 12, 13, 6, 150, + 775, 82, 83, 143, 50, 7, 6, 143, 133, 134, + 204, 133, 134, 59, 150, 76, 143, 86, 87, 88, + 89, 82, 83, 150, 149, 52, 151, 149, 90, 151, + 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, + 144, 57, 6, 59, 60, 149, 62, 63, 64, 96, + 97, 151, 68, 96, 97, 131, 132, 133, 6, 143, + 136, 137, 130, 104, 144, 141, 150, 130, 150, 149, + 151, 147, 143, 140, 150, 91, 92, 93, 154, 155, + 156, 157, 151, 159, 160, 161, 162, 1282, 164, 165, + 166, 843, 143, 145, 123, 150, 187, 188, 140, 141, + 779, 150, 150, 145, 195, 147, 301, 147, 199, 150, + 152, 150, 133, 134, 190, 191, 150, 150, 120, 121, + 122, 123, 56, 199, 46, 133, 134, 49, 149, 498, + 52, 49, 144, 908, 52, 151, 398, 149, 140, 141, + 216, 217, 218, 7, 220, 147, 144, 223, 224, 76, + 226, 149, 75, 143, 1349, 82, 83, 7, 155, 421, + 75, 143, 238, 160, 566, 567, 568, 164, 150, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 255, 256, 257, 258, 259, 260, 261, 262, 263, 264, 265, 266, 267, 268, 269, 270, 271, 272, 273, 274, 275, - 276, 277, 278, 279, 280, 281, 282, 283, 284, 141, - 141, 76, 4, 289, 955, 141, 149, 82, 83, 76, - 141, 297, 148, 142, 52, 82, 83, 7, 147, 149, - 141, 408, 149, 299, 310, 311, 312, 313, 314, 315, - 316, 317, 318, 319, 320, 321, 322, 323, 324, 131, - 132, 142, 118, 119, 120, 121, 147, 333, 50, 141, - 131, 132, 76, 52, 52, 341, 148, 59, 82, 83, - 346, 76, 138, 139, 350, 351, 147, 82, 83, 355, - 356, 357, 358, 141, 149, 143, 131, 132, 364, 54, - 381, 382, 149, 369, 370, 371, 148, 141, 389, 143, - 142, 46, 76, 148, 49, 147, 141, 52, 82, 83, - 386, 387, 388, 389, 390, 391, 383, 384, 5, 395, - 396, 397, 398, 49, 148, 401, 142, 52, 404, 405, - 52, 147, 408, 409, 410, 149, 49, 619, 118, 119, - 120, 121, 49, 141, 149, 143, 523, 131, 132, 36, - 37, 38, 39, 131, 132, 42, 4, 433, 138, 139, - 436, 49, 4, 147, 52, 149, 54, 4, 545, 435, - 148, 66, 153, 131, 132, 149, 6, 158, 131, 132, - 141, 162, 1211, 143, 141, 1214, 131, 132, 1217, 147, - 141, 149, 131, 132, 147, 677, 141, 131, 132, 1140, - 131, 132, 4, 148, 141, 1164, 143, 1166, 147, 1168, - 149, 487, 141, 147, 46, 4, 147, 49, 494, 7, - 52, 493, 54, 705, 141, 141, 492, 122, 123, 124, + 276, 277, 278, 279, 280, 281, 282, 283, 284, 285, + 286, 133, 134, 965, 4, 291, 6, 412, 6, 7, + 143, 143, 143, 143, 151, 301, 8, 150, 150, 135, + 136, 137, 143, 143, 145, 150, 142, 303, 314, 315, + 316, 317, 318, 319, 320, 321, 322, 323, 324, 325, + 326, 327, 328, 143, 143, 145, 120, 121, 122, 123, + 76, 337, 7, 52, 133, 134, 82, 83, 52, 345, + 120, 121, 122, 123, 350, 4, 5, 52, 354, 355, + 149, 54, 151, 359, 360, 361, 362, 52, 133, 134, + 140, 141, 368, 49, 385, 386, 143, 373, 374, 375, + 52, 143, 393, 145, 301, 150, 150, 36, 37, 38, + 39, 133, 134, 42, 390, 391, 392, 393, 394, 395, + 387, 388, 625, 399, 400, 401, 402, 150, 150, 405, + 140, 141, 408, 409, 529, 151, 412, 413, 414, 4, + 337, 49, 124, 125, 126, 127, 128, 129, 130, 131, + 132, 133, 134, 135, 136, 137, 551, 354, 355, 52, + 142, 437, 133, 134, 440, 76, 143, 49, 145, 151, + 4, 82, 83, 439, 4, 120, 121, 122, 123, 150, + 683, 4, 111, 112, 76, 143, 689, 133, 134, 49, + 82, 83, 52, 76, 54, 140, 141, 6, 1150, 82, + 83, 4, 5, 149, 69, 70, 71, 72, 133, 134, + 713, 140, 141, 78, 145, 412, 81, 493, 147, 76, + 143, 76, 145, 143, 500, 82, 83, 82, 83, 133, + 134, 143, 498, 36, 37, 38, 39, 499, 143, 42, + 151, 76, 143, 4, 145, 149, 1221, 82, 83, 1224, + 150, 4, 1227, 529, 530, 143, 532, 533, 76, 151, + 536, 537, 538, 76, 82, 83, 835, 836, 151, 82, + 83, 143, 133, 134, 76, 551, 143, 143, 554, 555, + 82, 83, 4, 7, 560, 576, 6, 682, 149, 565, + 566, 567, 568, 143, 151, 1174, 151, 1176, 589, 1178, + 143, 577, 578, 565, 566, 567, 568, 583, 111, 112, + 143, 706, 707, 708, 709, 49, 151, 143, 52, 595, + 54, 597, 6, 718, 143, 5, 145, 1302, 143, 133, + 134, 8, 529, 151, 610, 143, 612, 613, 151, 150, + 537, 538, 618, 143, 739, 149, 167, 6, 143, 151, + 145, 172, 173, 174, 551, 133, 134, 554, 1333, 625, + 143, 1336, 183, 184, 1339, 186, 1012, 1342, 143, 143, + 8, 149, 143, 143, 133, 134, 143, 133, 134, 133, + 134, 133, 134, 204, 205, 661, 662, 143, 1267, 1364, + 149, 1366, 143, 1368, 150, 149, 143, 149, 145, 675, + 676, 677, 678, 679, 680, 143, 682, 6, 133, 134, + 143, 687, 133, 134, 140, 141, 143, 4, 145, 145, + 696, 147, 133, 134, 149, 716, 152, 143, 149, 145, + 706, 707, 708, 709, 710, 1314, 150, 1316, 149, 1318, + 150, 143, 718, 145, 143, 1324, 145, 124, 125, 126, + 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, + 137, 150, 143, 739, 145, 142, 133, 134, 133, 134, + 973, 143, 143, 1352, 151, 1354, 145, 1356, 769, 770, + 771, 6, 149, 143, 149, 682, 124, 125, 126, 127, + 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, + 133, 134, 133, 134, 142, 150, 144, 133, 134, 706, + 707, 708, 709, 12, 13, 143, 149, 145, 149, 914, + 143, 718, 145, 149, 1170, 124, 125, 126, 127, 128, + 129, 130, 131, 132, 133, 134, 135, 136, 137, 815, + 816, 145, 739, 142, 149, 6, 151, 46, 47, 48, + 49, 50, 51, 52, 53, 54, 55, 143, 57, 145, + 59, 60, 145, 62, 63, 64, 832, 147, 844, 68, + 836, 133, 134, 143, 6, 145, 140, 141, 150, 99, + 856, 145, 6, 147, 860, 6, 150, 149, 152, 143, + 6, 145, 91, 92, 93, 143, 143, 145, 145, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, - 135, 49, 4, 5, 52, 140, 54, 523, 524, 141, - 526, 527, 131, 132, 530, 531, 532, 141, 141, 143, - 143, 141, 148, 1292, 826, 827, 131, 132, 147, 545, - 141, 141, 548, 549, 36, 37, 38, 39, 554, 570, - 42, 141, 147, 559, 560, 561, 562, 559, 560, 561, - 562, 141, 583, 143, 1323, 571, 572, 1326, 1257, 676, - 1329, 577, 141, 1332, 131, 132, 141, 133, 134, 135, - 131, 132, 4, 589, 140, 591, 297, 6, 131, 132, - 147, 698, 699, 700, 701, 1354, 147, 1356, 604, 1358, - 606, 607, 6, 710, 147, 5, 612, 131, 132, 133, - 134, 135, 560, 561, 562, 1304, 140, 1306, 141, 1308, - 143, 1002, 333, 619, 731, 1314, 124, 125, 126, 127, - 128, 129, 130, 131, 132, 133, 134, 135, 6, 350, - 351, 8, 140, 131, 132, 131, 132, 141, 141, 655, - 656, 141, 141, 1342, 143, 1344, 141, 1346, 143, 147, - 141, 147, 143, 669, 670, 671, 672, 673, 674, 141, - 676, 143, 131, 132, 141, 681, 143, 141, 141, 143, - 143, 141, 688, 131, 132, 131, 132, 708, 147, 131, - 132, 148, 698, 699, 700, 701, 702, 408, 141, 147, - 143, 147, 141, 141, 710, 147, 131, 132, 131, 132, - 141, 141, 165, 143, 141, 141, 143, 170, 171, 172, - 141, 141, 147, 143, 147, 731, 4, 141, 181, 182, - 148, 184, 138, 139, 141, 148, 143, 143, 148, 145, - 761, 762, 763, 141, 150, 143, 147, 141, 149, 202, - 203, 963, 147, 141, 149, 122, 123, 124, 125, 126, - 127, 128, 129, 130, 131, 132, 133, 134, 135, 147, - 143, 149, 145, 140, 143, 147, 147, 149, 149, 1160, - 6, 147, 149, 149, 125, 126, 127, 128, 129, 130, - 131, 132, 133, 134, 135, 52, 148, 54, 905, 140, - 143, 807, 808, 127, 128, 129, 130, 131, 132, 133, - 134, 135, 523, 147, 143, 149, 140, 6, 138, 139, - 531, 532, 147, 143, 149, 145, 145, 823, 148, 835, - 150, 827, 148, 147, 545, 149, 147, 548, 149, 99, - 6, 847, 3, 4, 147, 851, 149, 6, 9, 10, - 11, 6, 143, 14, 15, 16, 17, 18, 19, 20, - 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, - 31, 32, 33, 34, 147, 4, 149, 898, 148, 6, - 886, 887, 888, 147, 147, 149, 149, 5, 894, 895, - 140, 147, 898, 149, 147, 147, 149, 149, 147, 905, - 149, 147, 147, 149, 149, 147, 147, 149, 149, 915, - 916, 917, 147, 147, 149, 149, 147, 147, 149, 149, - 147, 145, 149, 929, 8, 147, 7, 149, 934, 148, - 147, 927, 149, 147, 143, 149, 149, 148, 7, 7, - 7, 141, 948, 141, 141, 947, 141, 7, 969, 110, - 111, 112, 113, 7, 142, 8, 6, 96, 7, 7, - 6, 148, 968, 142, 142, 676, 142, 142, 974, 975, - 131, 132, 142, 979, 147, 136, 1172, 142, 147, 6, - 141, 987, 1003, 4, 1005, 146, 1007, 698, 699, 700, - 701, 144, 998, 7, 99, 1016, 998, 1018, 1019, 710, - 7, 7, 7, 99, 7, 1002, 7, 99, 7, 7, - 1016, 4, 6, 1019, 1121, 145, 1022, 149, 149, 6, - 731, 7, 7, 7, 1030, 145, 4, 7, 1030, 141, - 7, 7, 7, 1039, 1040, 141, 489, 490, 122, 123, + 135, 136, 137, 149, 145, 151, 907, 142, 4, 895, + 896, 897, 5, 149, 145, 151, 147, 903, 904, 6, + 142, 907, 133, 134, 135, 136, 137, 46, 914, 150, + 49, 142, 149, 52, 151, 54, 7, 147, 924, 925, + 926, 145, 151, 36, 37, 38, 39, 150, 149, 42, + 151, 149, 938, 151, 52, 151, 54, 943, 150, 149, + 936, 151, 7, 7, 495, 496, 149, 149, 151, 151, + 7, 149, 958, 151, 149, 149, 151, 151, 979, 6, + 149, 149, 151, 151, 149, 957, 151, 149, 149, 151, + 151, 149, 978, 151, 149, 149, 151, 151, 984, 985, + 149, 7, 151, 989, 149, 143, 151, 914, 143, 7, + 1182, 997, 1013, 149, 1015, 151, 1017, 144, 111, 112, + 143, 149, 1008, 151, 6, 1026, 1131, 1028, 1029, 149, + 561, 151, 149, 143, 151, 1012, 1008, 149, 7, 151, + 1026, 572, 573, 1029, 7, 149, 1032, 151, 149, 149, + 151, 151, 6, 96, 1040, 150, 144, 149, 144, 144, + 144, 144, 144, 1049, 1050, 144, 6, 4, 1040, 127, + 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, + 1185, 149, 149, 1069, 142, 146, 7, 99, 7, 7, + 7, 99, 7, 7, 99, 7, 1268, 124, 125, 126, + 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, + 137, 7, 6, 1099, 6, 142, 1329, 4, 147, 1026, + 151, 151, 1029, 6, 147, 7, 7, 7, 4, 1115, + 7, 1117, 7, 7, 7, 150, 143, 6, 6, 143, + 1126, 6, 1128, 146, 6, 1131, 1359, 6, 1361, 7, + 145, 6, 130, 52, 1140, 7, 7, 54, 7, 1145, + 7, 7, 7, 6, 1269, 1378, 1271, 7, 144, 144, + 144, 144, 1173, 7, 1175, 7, 1177, 7, 6, 6, + 4, 6, 150, 1184, 143, 1186, 7, 1173, 6, 1175, + 7, 1177, 7, 1170, 150, 726, 727, 6, 729, 1185, + 731, 732, 6, 1189, 735, 736, 6, 6, 52, 4, + 1117, 4, 4, 4, 150, 1201, 1202, 150, 150, 150, + 6, 1326, 1208, 6, 1131, 150, 7, 143, 1214, 6, + 150, 1217, 124, 125, 126, 127, 128, 129, 130, 131, + 132, 133, 134, 135, 136, 137, 144, 147, 59, 144, + 142, 6, 6, 6, 6, 6, 5, 150, 1244, 150, + 150, 4, 793, 794, 795, 6, 150, 7, 6, 1255, + 1271, 7, 1258, 7, 7, 1261, 6, 6, 1185, 1265, + 150, 95, 6, 1269, 150, 1271, 7, 147, 6, 4, + 6, 99, 6, 6, 1280, 6, 6, 1283, 146, 3, + 4, 6, 50, 6, 6, 9, 10, 11, 6, 5, + 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, + 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, + 34, 6, 6, 864, 6, 6, 6, 4, 6, 870, + 1326, 6, 46, 6, 6, 6, 149, 878, 879, 880, + 6, 6, 4, 884, 150, 6, 6, 6, 889, 890, + 891, 149, 1269, 7, 1271, 69, 70, 71, 72, 73, + 149, 149, 903, 149, 78, 6, 147, 81, 909, 6, + 5, 912, 6, 6, 6, 6, 124, 125, 126, 127, + 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, + 931, 932, 933, 934, 142, 6, 110, 6, 150, 113, + 114, 115, 6, 150, 6, 6, 151, 7, 150, 1326, + 6, 94, 150, 150, 150, 956, 6, 6, 97, 133, + 134, 6, 6, 6, 138, 6, 6, 6, 150, 143, + 66, 150, 6, 151, 148, 151, 150, 151, 6, 124, + 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, + 135, 136, 137, 151, 151, 151, 150, 142, 6, 1000, + 1001, 1002, 1003, 124, 125, 126, 127, 128, 129, 130, + 131, 132, 133, 134, 135, 136, 137, 6, 6, 6, + 4, 142, 126, 127, 128, 129, 130, 131, 132, 133, + 134, 135, 136, 137, 1035, 6, 6, 6, 142, 6, + 6, 6, 6, 151, 6, 6, 3, 4, 150, 1244, + 1051, 150, 9, 10, 11, 6, 6, 14, 15, 16, + 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, + 27, 28, 29, 30, 31, 32, 33, 34, 150, 6, + 150, 6, 6, 6, 6, 150, 6, 150, 6, 46, + 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, + 134, 135, 136, 137, 150, 6, 6, 6, 142, 6, + 6, 1112, 69, 70, 71, 72, 73, 150, 150, 6, + 6, 78, 6, 6, 81, 129, 130, 131, 132, 133, + 134, 135, 136, 137, 1135, 1136, 1137, 1138, 142, 6, + 855, 863, 3, 3, 1251, 961, -1, 367, -1, -1, + -1, -1, -1, 110, -1, -1, 113, 114, 115, -1, + 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, + 134, 135, 136, 137, -1, -1, 133, 134, 142, -1, + 1181, 138, -1, -1, -1, -1, 143, -1, -1, -1, + -1, 148, -1, -1, 151, 3, 4, 5, -1, 7, + -1, 9, 10, 11, -1, -1, 14, 15, 16, 17, + 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, + 28, 29, 30, 31, 32, 33, 34, 1228, 36, 37, + 38, 39, -1, -1, 42, -1, -1, 12, 13, -1, + 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, + 134, 135, 136, 137, -1, -1, -1, -1, 142, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, 46, 47, 48, 49, 50, 51, 52, 53, 54, + 55, -1, 57, -1, 59, 60, -1, 62, 63, 64, + -1, -1, -1, 68, -1, -1, 104, -1, -1, -1, + -1, -1, 110, 111, 112, 113, 114, 115, -1, -1, + -1, -1, 120, 121, 122, 123, 91, 92, 93, -1, + -1, -1, -1, -1, -1, 133, 134, -1, -1, -1, + 138, -1, 140, 141, -1, 143, -1, 145, -1, 147, + 148, -1, 150, 3, 4, 5, -1, -1, -1, 9, + 10, 11, -1, -1, 14, 15, 16, 17, 18, 19, + 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, + 30, 31, 32, 33, 34, -1, 151, -1, -1, -1, + -1, -1, -1, -1, -1, -1, 46, -1, 12, 13, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, - 134, 135, 6, 1059, 148, 6, 140, 6, 144, 6, - 6, 143, 1258, 7, 6, 149, 128, 7, 1175, 122, - 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, - 133, 134, 135, 1089, 52, 7, 7, 140, 54, 142, - 7, 7, 7, 6, 4, 7, 7, 142, 142, 1105, - 142, 1107, 555, 142, 7, 7, 6, 1319, 6, 6, - 1116, 148, 1118, 566, 567, 1121, 141, 7, 6, 148, - 7, 7, 6, 6, 1130, 52, 6, 6, 4, 1135, - 4, 4, 148, 148, 6, 148, 148, 1349, 4, 1351, - 148, 6, 1163, 145, 1165, 141, 1167, 142, 7, 6, - 59, 148, 1259, 1174, 1261, 1176, 1368, 1163, 6, 1165, - 148, 1167, 6, 1160, 6, 148, 148, 6, 6, 1175, - 5, 7, 4, 1179, 148, 6, 148, 7, 7, 12, - 13, 7, 6, 148, 6, 1191, 1192, 95, 6, 145, - 7, 6, 1198, 4, 905, 99, 6, 6, 1204, 6, - 6, 1207, 6, 144, 6, 6, 6, 6, 5, 1316, - 6, 6, 6, 46, 47, 48, 49, 50, 51, 52, - 53, 54, 55, 6, 57, 4, 59, 60, 1234, 62, - 63, 64, 6, 6, 6, 68, 6, 4, 6, 1245, - 1261, 147, 1248, 12, 13, 1251, 6, 6, 147, 1255, - 6, 147, 147, 1259, 147, 1261, 148, 6, 91, 92, - 93, 7, 6, 145, 1270, 718, 719, 1273, 721, 6, - 723, 724, 5, 50, 727, 728, 6, 46, 47, 48, - 49, 50, 51, 52, 53, 54, 55, 6, 57, 6, - 59, 60, 6, 62, 63, 64, 6, 148, 6, 68, - 6, 148, 6, 149, 7, 1016, 6, 148, 1019, 94, - 1316, 148, 6, 6, 148, 97, 149, 6, 6, 6, - 148, 6, 91, 92, 93, 6, 149, 148, 6, 149, - 149, 6, 785, 786, 787, 149, 148, 66, 6, 6, - 6, 149, 6, 148, 6, 3, 4, 4, 1234, 846, - 6, 9, 10, 11, 6, 6, 14, 15, 16, 17, + 134, 135, 136, 137, -1, -1, -1, -1, 142, 69, + 70, 71, 72, 73, 6, 149, -1, 151, 78, -1, + -1, 81, 46, 47, 48, 49, 50, 51, 52, 53, + 54, 55, -1, 57, -1, 59, 60, -1, 62, 63, + 64, -1, -1, -1, 68, -1, -1, -1, -1, -1, + 110, -1, -1, 113, 114, 115, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, 91, 92, 93, + -1, -1, -1, 133, 134, -1, -1, -1, 138, -1, + -1, -1, -1, 143, -1, 3, 4, 5, 148, -1, + 150, 9, 10, 11, -1, -1, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, - 28, 29, 30, 31, 32, 33, 34, 6, 6, 6, - 149, 6, 6, 149, 148, 148, 148, 6, 46, 6, - 148, 6, 6, 6, 6, 6, 1107, 148, 6, 6, - 148, 148, 855, 148, 6, 148, 6, 6, 861, 6, - 1121, 69, 70, 71, 72, 73, 869, 870, 871, 6, - 78, 6, 875, 81, 6, 6, 6, 880, 881, 882, - 854, 3, 3, 1241, 363, 951, -1, -1, -1, -1, - -1, 894, -1, -1, -1, -1, -1, 900, -1, -1, - 903, -1, 110, 111, 112, 113, -1, -1, -1, -1, - -1, -1, -1, -1, 1175, -1, -1, -1, -1, 922, - 923, 924, 925, 131, 132, -1, -1, -1, 136, -1, - -1, -1, -1, 141, -1, -1, -1, -1, 146, -1, - 148, 149, -1, 946, -1, -1, -1, -1, -1, 3, - 4, -1, -1, -1, -1, 9, 10, 11, -1, -1, + 28, 29, 30, 31, 32, 33, 34, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, 151, 46, -1, + 12, 13, 124, 125, 126, 127, 128, 129, 130, 131, + 132, 133, 134, 135, 136, 137, -1, -1, -1, -1, + 142, 69, 70, 71, 72, 73, 6, -1, -1, -1, + 78, -1, -1, 81, 46, 47, 48, 49, 50, 51, + 52, 53, 54, 55, -1, 57, -1, 59, 60, -1, + 62, 63, 64, -1, -1, -1, 68, -1, -1, -1, + -1, -1, 110, -1, -1, 113, 114, 115, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, 91, + 92, 93, -1, -1, -1, 133, 134, -1, -1, -1, + 138, -1, -1, -1, -1, 143, -1, 3, 4, -1, + 148, -1, 150, 9, 10, 11, -1, -1, 14, 15, + 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, + 26, 27, 28, 29, 30, 31, 32, 33, 34, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, 151, + 46, -1, 12, 13, 124, 125, 126, 127, 128, 129, + 130, 131, 132, 133, 134, 135, 136, 137, -1, -1, + -1, -1, 142, 69, 70, 71, 72, 73, 6, -1, + -1, -1, 78, -1, -1, 81, 46, 47, 48, 49, + 50, 51, 52, 53, 54, 55, -1, 57, -1, 59, + 60, -1, 62, 63, 64, -1, -1, -1, 68, -1, + -1, -1, -1, -1, 110, -1, -1, 113, 114, 115, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, 91, 92, 93, -1, -1, -1, 133, 134, -1, + -1, -1, 138, -1, -1, -1, -1, 143, -1, 3, + 4, -1, 148, -1, 150, 9, 10, 11, -1, -1, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, - 34, -1, -1, -1, 6, -1, -1, 990, 991, 992, - 993, -1, 46, -1, 12, 13, -1, -1, 1259, -1, - 1261, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, 69, 70, 71, 72, 73, - -1, -1, 1025, -1, 78, -1, -1, 81, 46, 47, - 48, 49, 50, 51, 52, 53, 54, 55, 1041, 57, + 34, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, 151, 46, -1, 12, 13, 124, 125, 126, 127, + 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, + -1, -1, -1, -1, 142, 69, 70, 71, 72, 73, + 8, -1, -1, -1, 78, -1, -1, 81, 46, 47, + 48, 49, 50, 51, 52, 53, 54, 55, -1, 57, -1, 59, 60, -1, 62, 63, 64, -1, -1, -1, - 68, -1, -1, -1, -1, 1316, 110, 111, 112, 113, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, 91, 92, 93, -1, 131, 132, -1, - -1, -1, 136, -1, -1, -1, -1, 141, -1, -1, - -1, -1, 146, -1, -1, 149, -1, -1, -1, 1102, - 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, - 132, 133, 134, 135, -1, -1, -1, -1, 140, -1, - -1, -1, 1125, 1126, 1127, 1128, 3, 4, 5, -1, - 7, 149, 9, 10, 11, -1, -1, 14, 15, 16, - 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, - 27, 28, 29, 30, 31, 32, 33, 34, -1, 36, - 37, 38, 39, -1, -1, 42, -1, -1, 1171, -1, - -1, -1, -1, -1, -1, -1, -1, -1, 6, -1, - -1, -1, 3, 4, 5, -1, -1, -1, 9, 10, - 11, -1, -1, 14, 15, 16, 17, 18, 19, 20, - 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, - 31, 32, 33, 34, -1, 1218, -1, -1, -1, -1, - -1, -1, -1, -1, -1, 46, -1, 104, -1, -1, - -1, -1, -1, 110, 111, 112, 113, -1, -1, -1, - -1, 118, 119, 120, 121, -1, -1, -1, 69, 70, - 71, 72, 73, 6, 131, 132, -1, 78, -1, 136, - 81, 138, 139, -1, 141, -1, 143, -1, 145, 146, - -1, 148, -1, -1, -1, 122, 123, 124, 125, 126, - 127, 128, 129, 130, 131, 132, 133, 134, 135, 110, - 111, 112, 113, 140, 122, 123, 124, 125, 126, 127, - 128, 129, 130, 131, 132, 133, 134, 135, -1, -1, - 131, 132, 140, -1, -1, 136, -1, -1, -1, -1, - 141, -1, 3, 4, 5, 146, -1, 148, 9, 10, - 11, -1, -1, 14, 15, 16, 17, 18, 19, 20, - 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, - 31, 32, 33, 34, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, 46, -1, 12, 13, 122, - 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, - 133, 134, 135, -1, -1, -1, -1, 140, 69, 70, - 71, 72, 73, 6, -1, -1, -1, 78, -1, -1, - 81, 46, 47, 48, 49, 50, 51, 52, 53, 54, - 55, -1, 57, -1, 59, 60, -1, 62, 63, 64, - -1, -1, -1, 68, -1, -1, -1, -1, -1, 110, - 111, 112, 113, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, 91, 92, 93, -1, - 131, 132, -1, -1, -1, 136, -1, -1, -1, -1, - 141, -1, 3, 4, -1, 146, -1, 148, 9, 10, - 11, -1, -1, 14, 15, 16, 17, 18, 19, 20, - 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, - 31, 32, 33, 34, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, 149, 46, -1, 12, 13, 122, - 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, - 133, 134, 135, -1, -1, -1, -1, 140, 69, 70, - 71, 72, 73, 6, -1, -1, -1, 78, -1, -1, - 81, 46, 47, 48, 49, 50, 51, 52, 53, 54, - 55, -1, 57, -1, 59, 60, -1, 62, 63, 64, - -1, -1, -1, 68, -1, -1, -1, -1, -1, 110, - 111, 112, 113, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, 91, 92, 93, -1, - 131, 132, -1, -1, -1, 136, -1, -1, -1, -1, - 141, -1, 3, 4, -1, 146, -1, 148, 9, 10, - 11, -1, -1, 14, 15, 16, 17, 18, 19, 20, - 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, - 31, 32, 33, 34, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, 149, 46, -1, 12, 13, 122, - 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, - 133, 134, 135, -1, -1, -1, -1, 140, 69, 70, - 71, 72, 73, 6, -1, -1, -1, 78, -1, -1, - 81, 46, 47, 48, 49, 50, 51, 52, 53, 54, - 55, -1, 57, -1, 59, 60, -1, 62, 63, 64, - -1, -1, -1, 68, -1, -1, -1, -1, -1, 110, - 111, 112, 113, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, 91, 92, 93, -1, - 131, 132, -1, -1, -1, 136, -1, -1, -1, -1, - 141, -1, 3, 4, -1, 146, -1, 148, 9, 10, - 11, -1, -1, 14, 15, 16, 17, 18, 19, 20, - 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, - 31, 32, 33, 34, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, 149, 46, -1, 12, 13, 122, - 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, - 133, 134, 135, -1, -1, -1, -1, 140, 69, 70, - 71, 72, 73, 6, -1, -1, -1, 78, -1, -1, - 81, 46, 47, 48, 49, 50, 51, 52, 53, 54, - 55, -1, 57, -1, 59, 60, -1, 62, 63, 64, - -1, -1, -1, 68, -1, 6, -1, -1, -1, 110, - 111, 112, 113, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, 91, 92, 93, -1, - 131, 132, -1, -1, -1, 136, -1, -1, 6, -1, - 141, -1, 3, 4, -1, 146, -1, 148, 9, 10, - 11, -1, -1, 14, 15, 16, 17, 18, 19, 20, - 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, - 31, 32, 33, 34, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, 149, 46, -1, -1, -1, 122, - 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, - 133, 134, 135, -1, -1, -1, -1, 140, 69, 70, - 71, 72, 73, 6, -1, -1, -1, 78, -1, -1, - 81, 122, 123, 124, 125, 126, 127, 128, 129, 130, - 131, 132, 133, 134, 135, -1, -1, -1, -1, 140, - -1, -1, -1, -1, -1, -1, -1, -1, -1, 110, - 111, 112, 113, -1, 122, 123, 124, 125, 126, 127, - 128, 129, 130, 131, 132, 133, 134, 135, -1, -1, - 131, 132, 140, -1, -1, 136, -1, -1, 6, -1, - 141, -1, 3, 4, -1, 146, -1, 148, 9, 10, - 11, -1, -1, 14, 15, 16, 17, 18, 19, 20, - 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, - 31, 32, 33, 34, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, 46, -1, -1, -1, 122, - 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, - 133, 134, 135, -1, -1, -1, -1, 140, 69, 70, - 71, 72, 73, 6, -1, 3, 4, 78, -1, -1, - 81, 9, 10, 11, -1, -1, 14, 15, 16, 17, + 68, -1, -1, -1, 8, -1, 110, -1, -1, 113, + 114, 115, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, 91, 92, 93, -1, -1, -1, 133, + 134, -1, -1, -1, 138, -1, -1, -1, -1, 143, + 8, 3, 4, -1, 148, -1, 150, 9, 10, 11, + -1, -1, 14, 15, 16, 17, 18, 19, 20, 21, + 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, + 32, 33, 34, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, 151, 46, -1, 124, 125, 126, 127, + 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, + -1, -1, -1, -1, 142, -1, -1, 69, 70, 71, + 72, 73, 8, -1, -1, -1, 78, -1, -1, 81, + 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, + 134, 135, 136, 137, -1, -1, -1, -1, 142, -1, + -1, -1, -1, -1, -1, -1, 8, -1, 110, -1, + -1, 113, 114, 115, -1, -1, 124, 125, 126, 127, + 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, + -1, 133, 134, -1, 142, -1, 138, -1, -1, -1, + -1, 143, 8, 3, 4, -1, 148, -1, 150, 9, + 10, 11, -1, -1, 14, 15, 16, 17, 18, 19, + 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, + 30, 31, 32, 33, 34, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, 46, -1, 124, 125, + 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, + 136, 137, -1, -1, -1, -1, 142, -1, -1, 69, + 70, 71, 72, 73, -1, -1, -1, -1, 78, -1, + -1, 81, 124, 125, 126, 127, 128, 129, 130, 131, + 132, 133, 134, 135, 136, 137, -1, -1, -1, -1, + 142, -1, -1, -1, -1, -1, -1, -1, -1, -1, + 110, -1, -1, 113, 114, 115, -1, -1, 124, 125, + 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, + 136, 137, -1, 133, 134, -1, 142, -1, 138, -1, + -1, -1, -1, 143, -1, 3, 4, 5, 148, -1, + 150, 9, 10, 11, -1, -1, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, - 28, 29, 30, 31, 32, 33, 34, 6, -1, 110, - 111, 112, 113, -1, 122, 123, 124, 125, 126, 127, - 128, 129, 130, 131, 132, 133, 134, 135, -1, -1, - 131, 132, 140, -1, -1, 136, -1, -1, -1, -1, - 141, 8, 3, 4, 5, 146, -1, 148, 9, 10, - 11, -1, -1, 14, 15, 16, 17, 18, 19, 20, - 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, - 31, 32, 33, 34, -1, 36, 37, 38, 39, -1, - -1, 42, 110, 111, 112, 113, -1, -1, -1, 122, - 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, - 133, 134, 135, 131, 132, -1, -1, 140, 136, -1, - -1, -1, -1, 141, -1, -1, 144, -1, 146, -1, - 148, -1, -1, 122, 123, 124, 125, 126, 127, 128, - 129, 130, 131, 132, 133, 134, 135, -1, -1, 8, - -1, 140, -1, -1, -1, -1, -1, -1, -1, 110, - 111, 112, 113, -1, -1, 122, 123, 124, 125, 126, - 127, 128, 129, 130, 131, 132, 133, 134, 135, -1, - 131, 132, -1, 140, -1, 136, -1, -1, -1, -1, - 141, 8, 3, 4, -1, 146, -1, 148, 9, 10, + 28, 29, 30, 31, 32, 33, 34, -1, 36, 37, + 38, 39, -1, -1, 42, -1, -1, -1, -1, -1, + -1, -1, 3, 4, -1, -1, -1, -1, 9, 10, 11, -1, -1, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, - 31, 32, 33, 34, -1, -1, -1, -1, -1, 8, - -1, 3, 4, -1, -1, -1, -1, 9, 10, 11, + 31, 32, 33, 34, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, 46, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, 66, -1, + -1, -1, 110, 111, 112, 113, 114, 115, 69, 70, + 71, 72, 73, -1, -1, -1, -1, 78, -1, -1, + 81, -1, -1, -1, -1, 133, 134, -1, -1, -1, + 138, -1, -1, -1, -1, 143, -1, -1, -1, -1, + 148, -1, 150, -1, -1, -1, -1, -1, -1, 110, + -1, -1, 113, 114, 115, -1, 124, 125, 126, 127, + 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, + -1, -1, 133, 134, 142, -1, -1, 138, -1, -1, + -1, -1, 143, -1, 3, 4, -1, 148, -1, 150, + 9, 10, 11, -1, -1, 14, 15, 16, 17, 18, + 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, + 29, 30, 31, 32, 33, 34, -1, -1, -1, -1, + -1, 12, 13, 3, 4, -1, -1, -1, -1, 9, + 10, 11, -1, -1, 14, 15, 16, 17, 18, 19, + 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, + 30, 31, 32, 33, 34, 46, 47, 48, 49, 50, + 51, 52, 53, 54, 55, -1, 57, -1, 59, 60, + -1, 62, 63, 64, -1, -1, -1, 68, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, 110, -1, -1, 113, 114, 115, -1, -1, -1, + 91, 92, 93, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, 133, 134, -1, -1, -1, 138, + -1, -1, -1, -1, 143, -1, -1, 146, -1, 148, + 110, 150, -1, 113, 114, 115, -1, 124, 125, 126, + 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, + 137, -1, -1, 133, 134, 142, -1, -1, 138, -1, + -1, -1, 149, 143, 151, -1, 146, -1, 148, -1, + 150, 3, 4, -1, -1, -1, -1, 9, 10, 11, -1, -1, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, - 32, 33, 34, 122, 123, 124, 125, 126, 127, 128, - 129, 130, 131, 132, 133, 134, 135, -1, -1, -1, - -1, 140, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, 110, - 111, 112, 113, 8, -1, 122, 123, 124, 125, 126, - 127, 128, 129, 130, 131, 132, 133, 134, 135, -1, - 131, 132, -1, 140, -1, 136, -1, -1, -1, -1, - 141, -1, -1, 144, -1, 146, 8, 148, 110, 111, - 112, 113, -1, 122, 123, 124, 125, 126, 127, 128, - 129, 130, 131, 132, 133, 134, 135, -1, -1, 131, - 132, 140, -1, -1, 136, -1, -1, -1, -1, 141, - -1, 3, 4, -1, 146, -1, 148, 9, 10, 11, + 32, 33, 34, 124, 125, 126, 127, 128, 129, 130, + 131, 132, 133, 134, 135, 136, 137, -1, 3, 4, + -1, 142, -1, 144, 9, 10, 11, -1, 149, 14, + 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, + 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, 46, 124, 125, 126, 127, 128, 129, 130, 131, + 132, 133, 134, 135, 136, 137, -1, -1, 110, -1, + 142, 113, 114, 115, 69, 70, 71, 72, 73, 151, + -1, -1, -1, 78, -1, -1, 81, -1, -1, -1, + -1, 133, 134, -1, -1, -1, 138, -1, -1, -1, + -1, 143, -1, -1, -1, -1, 148, -1, 150, -1, + -1, -1, -1, -1, -1, 110, -1, -1, 113, 114, + 115, -1, 124, 125, 126, 127, 128, 129, 130, 131, + 132, 133, 134, 135, 136, 137, -1, -1, 133, 134, + 142, -1, -1, 138, 3, 4, 5, 149, 143, 151, + 9, 10, 11, 148, -1, 14, 15, 16, 17, 18, + 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, + 29, 30, 31, 32, 33, 34, -1, 36, 37, 38, + 39, 3, 4, 42, -1, -1, -1, 9, 10, 11, -1, -1, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, - 32, 33, 34, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, 46, -1, -1, 122, 123, 124, - 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, - 135, -1, -1, -1, -1, 140, -1, 69, 70, 71, - 72, 73, -1, -1, -1, -1, 78, -1, -1, 81, - 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, - 132, 133, 134, 135, -1, -1, -1, -1, 140, -1, - -1, -1, -1, -1, -1, -1, -1, -1, 110, 111, - 112, 113, -1, 122, 123, 124, 125, 126, 127, 128, - 129, 130, 131, 132, 133, 134, 135, -1, -1, 131, - 132, 140, -1, -1, 136, 3, 4, 5, 147, 141, - 149, 9, 10, 11, 146, -1, 14, 15, 16, 17, - 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, - 28, 29, 30, 31, 32, 33, 34, -1, 36, 37, - 38, 39, 12, 13, 42, 122, 123, 124, 125, 126, - 127, 128, 129, 130, 131, 132, 133, 134, 135, -1, - -1, -1, -1, 140, -1, -1, -1, -1, -1, -1, - 147, -1, 149, -1, -1, -1, 46, 47, 48, 49, - 50, 51, 52, 53, 54, 55, -1, 57, -1, 59, - 60, -1, 62, 63, 64, -1, -1, -1, 68, -1, - -1, -1, -1, -1, -1, -1, 0, 1, -1, -1, - 4, -1, 110, 111, 112, 113, -1, -1, 12, 13, - -1, 91, 92, 93, -1, -1, -1, -1, -1, -1, - -1, -1, -1, 131, 132, -1, -1, -1, 136, -1, - -1, 35, -1, 141, -1, -1, 40, 41, 146, 43, - 44, -1, 46, 47, 48, 49, 50, 51, 52, 53, - 54, 55, -1, 57, 58, 59, 60, 61, 62, 63, - 64, 65, -1, 67, 68, 69, 70, 71, 72, 73, - 74, -1, 76, 77, 78, 79, 80, 81, -1, -1, - 84, 85, -1, -1, -1, -1, 90, 91, 92, 93, - -1, -1, 96, -1, 98, -1, 100, 101, 102, 103, - 104, 105, 106, 107, 108, 109, 4, -1, -1, -1, - 114, 115, 116, 117, 12, 13, -1, 122, 123, 124, - 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, - 135, -1, -1, -1, -1, 140, -1, 35, -1, -1, - -1, -1, 40, 41, 149, 43, 44, -1, 46, 47, + 32, 33, 34, 124, 125, 126, 127, 128, 129, 130, + 131, 132, 133, 134, 135, 136, 137, -1, -1, -1, + -1, 142, -1, -1, -1, -1, -1, -1, -1, -1, + 151, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, 110, 111, 112, 113, 114, 115, -1, 124, 125, + 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, + 136, 137, -1, -1, 133, 134, 142, -1, -1, 138, + -1, -1, -1, -1, 143, 151, -1, -1, 110, 148, + -1, 113, 114, 115, 0, 1, -1, -1, 4, -1, + -1, -1, -1, -1, -1, -1, 12, 13, -1, -1, + -1, 133, 134, -1, -1, -1, 138, -1, -1, -1, + -1, 143, -1, -1, -1, -1, 148, -1, -1, 35, + -1, -1, -1, -1, 40, 41, -1, 43, 44, -1, + 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, + -1, 57, 58, 59, 60, 61, 62, 63, 64, 65, + -1, 67, 68, 69, 70, 71, 72, 73, 74, -1, + 76, 77, 78, 79, 80, 81, -1, -1, 84, 85, + -1, -1, -1, -1, 90, 91, 92, 93, -1, -1, + 96, -1, 98, -1, 100, 101, 102, 103, 104, 105, + 106, 107, 108, 109, -1, -1, 4, -1, -1, -1, + 116, 117, 118, 119, 12, 13, -1, 124, 125, 126, + 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, + 137, -1, -1, -1, -1, 142, -1, 35, -1, -1, + -1, -1, 40, 41, 151, 43, 44, -1, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, -1, 57, 58, 59, 60, 61, 62, 63, 64, 65, -1, 67, 68, 69, 70, 71, 72, 73, 74, -1, 76, 77, 78, 79, 80, 81, -1, -1, 84, 85, -1, -1, -1, -1, 90, 91, 92, 93, -1, -1, 96, -1, 98, -1, 100, 101, 102, 103, 104, 105, 106, 107, - 108, 109, -1, -1, -1, -1, 114, 115, 116, 117, - 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, - 132, 133, 134, 135, -1, -1, -1, -1, 140, -1, - -1, -1, -1, -1, -1, 147, -1, 149, 122, 123, - 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, - 134, 135, -1, -1, -1, -1, 140, -1, -1, -1, - -1, -1, -1, -1, -1, 149, 122, 123, 124, 125, - 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, - -1, -1, -1, -1, 140, -1, -1, -1, -1, -1, - -1, -1, -1, 149, 122, 123, 124, 125, 126, 127, - 128, 129, 130, 131, 132, 133, 134, 135, -1, -1, - -1, -1, 140, -1, -1, -1, -1, -1, -1, -1, - -1, 149, 122, 123, 124, 125, 126, 127, 128, 129, - 130, 131, 132, 133, 134, 135, -1, -1, -1, -1, - 140, -1, -1, -1, -1, -1, -1, -1, -1, 149, - 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, - 132, 133, 134, 135, -1, -1, -1, -1, 140, -1, - -1, -1, -1, -1, -1, -1, -1, 149, 122, 123, + 108, 109, -1, -1, -1, -1, -1, -1, 116, 117, + 118, 119, 124, 125, 126, 127, 128, 129, 130, 131, + 132, 133, 134, 135, 136, 137, -1, -1, -1, -1, + 142, -1, -1, -1, -1, -1, -1, -1, -1, 151, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, - 134, 135, -1, -1, -1, -1, 140, -1, -1, -1, - -1, -1, -1, -1, -1, 149, 122, 123, 124, 125, + 134, 135, 136, 137, -1, -1, -1, -1, 142, -1, + -1, -1, -1, -1, -1, -1, -1, 151, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, - -1, -1, -1, -1, 140, -1, -1, -1, -1, -1, - -1, -1, -1, 149, 122, 123, 124, 125, 126, 127, - 128, 129, 130, 131, 132, 133, 134, 135, -1, -1, - -1, -1, 140, -1, -1, -1, -1, -1, -1, -1, - -1, 149, 122, 123, 124, 125, 126, 127, 128, 129, - 130, 131, 132, 133, 134, 135, -1, -1, -1, -1, - 140, -1, -1, -1, -1, -1, -1, -1, -1, 149, - 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, - 132, 133, 134, 135, -1, -1, -1, -1, 140, -1, - -1, -1, -1, -1, -1, -1, -1, 149, 122, 123, + 136, 137, -1, -1, -1, -1, 142, -1, -1, -1, + -1, -1, -1, -1, -1, 151, 124, 125, 126, 127, + 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, + -1, -1, -1, -1, 142, -1, -1, -1, -1, -1, + -1, -1, -1, 151, 124, 125, 126, 127, 128, 129, + 130, 131, 132, 133, 134, 135, 136, 137, -1, -1, + -1, -1, 142, -1, -1, -1, -1, -1, -1, -1, + -1, 151, 124, 125, 126, 127, 128, 129, 130, 131, + 132, 133, 134, 135, 136, 137, -1, -1, -1, -1, + 142, -1, -1, -1, -1, -1, -1, -1, -1, 151, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, - 134, 135, -1, -1, -1, -1, 140, -1, -1, -1, - -1, -1, -1, -1, -1, 149, 122, 123, 124, 125, + 134, 135, 136, 137, -1, -1, -1, -1, 142, -1, + -1, -1, -1, -1, -1, -1, -1, 151, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, - -1, -1, -1, -1, 140, -1, -1, -1, -1, -1, - -1, -1, -1, 149, 122, 123, 124, 125, 126, 127, - 128, 129, 130, 131, 132, 133, 134, 135, -1, -1, - -1, -1, 140, -1, -1, -1, -1, -1, -1, -1, - -1, 149, 122, 123, 124, 125, 126, 127, 128, 129, - 130, 131, 132, 133, 134, 135, -1, -1, -1, -1, - 140, -1, -1, -1, -1, -1, -1, -1, -1, 149, - 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, - 132, 133, 134, 135, -1, -1, -1, -1, 140, -1, - -1, -1, -1, -1, -1, -1, -1, 149, 122, 123, + 136, 137, -1, -1, -1, -1, 142, -1, -1, -1, + -1, -1, -1, -1, -1, 151, 124, 125, 126, 127, + 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, + -1, -1, -1, -1, 142, -1, -1, -1, -1, -1, + -1, -1, -1, 151, 124, 125, 126, 127, 128, 129, + 130, 131, 132, 133, 134, 135, 136, 137, -1, -1, + -1, -1, 142, -1, -1, -1, -1, -1, -1, -1, + -1, 151, 124, 125, 126, 127, 128, 129, 130, 131, + 132, 133, 134, 135, 136, 137, -1, -1, -1, -1, + 142, -1, -1, -1, -1, -1, -1, -1, -1, 151, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, - 134, 135, -1, -1, -1, -1, 140, -1, -1, -1, - -1, -1, -1, -1, -1, 149, 122, 123, 124, 125, + 134, 135, 136, 137, -1, -1, -1, -1, 142, -1, + -1, -1, -1, -1, -1, -1, -1, 151, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, - -1, -1, -1, -1, 140, -1, -1, -1, -1, -1, - -1, -1, -1, 149, 122, 123, 124, 125, 126, 127, - 128, 129, 130, 131, 132, 133, 134, 135, -1, -1, - -1, -1, 140, -1, -1, -1, -1, -1, -1, -1, - -1, 149, 122, 123, 124, 125, 126, 127, 128, 129, - 130, 131, 132, 133, 134, 135, -1, -1, -1, -1, - 140, -1, -1, -1, -1, -1, -1, -1, -1, 149, - 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, - 132, 133, 134, 135, -1, -1, -1, -1, 140, -1, - -1, -1, -1, -1, -1, -1, -1, 149, 122, 123, + 136, 137, -1, -1, -1, -1, 142, -1, -1, -1, + -1, -1, -1, -1, -1, 151, 124, 125, 126, 127, + 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, + -1, -1, -1, -1, 142, -1, -1, -1, -1, -1, + -1, -1, -1, 151, 124, 125, 126, 127, 128, 129, + 130, 131, 132, 133, 134, 135, 136, 137, -1, -1, + -1, -1, 142, -1, -1, -1, -1, -1, -1, -1, + -1, 151, 124, 125, 126, 127, 128, 129, 130, 131, + 132, 133, 134, 135, 136, 137, -1, -1, -1, -1, + 142, -1, -1, -1, -1, -1, -1, -1, -1, 151, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, - 134, 135, -1, -1, -1, -1, 140, -1, -1, -1, - -1, -1, -1, -1, -1, 149, 122, 123, 124, 125, + 134, 135, 136, 137, -1, -1, -1, -1, 142, -1, + -1, -1, -1, -1, -1, -1, -1, 151, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, - -1, -1, -1, -1, 140, -1, -1, -1, -1, -1, - -1, -1, -1, 149, 122, 123, 124, 125, 126, 127, - 128, 129, 130, 131, 132, 133, 134, 135, -1, -1, - -1, -1, 140, -1, -1, -1, -1, -1, -1, -1, - -1, 149, 122, 123, 124, 125, 126, 127, 128, 129, - 130, 131, 132, 133, 134, 135, -1, -1, -1, -1, - 140, -1, 142, -1, -1, -1, -1, 147, 122, 123, - 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, - 134, 135, -1, -1, -1, -1, 140, -1, -1, -1, - -1, -1, -1, 147, 122, 123, 124, 125, 126, 127, - 128, 129, 130, 131, 132, 133, 134, 135, -1, -1, - -1, -1, 140, -1, -1, -1, -1, -1, -1, 147, - 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, - 132, 133, 134, 135, -1, -1, -1, -1, 140, -1, - -1, -1, -1, -1, -1, 147, 122, 123, 124, 125, + 136, 137, -1, -1, -1, -1, 142, -1, -1, -1, + -1, -1, -1, -1, -1, 151, 124, 125, 126, 127, + 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, + -1, -1, -1, -1, 142, -1, -1, -1, -1, -1, + -1, -1, -1, 151, 124, 125, 126, 127, 128, 129, + 130, 131, 132, 133, 134, 135, 136, 137, -1, -1, + -1, -1, 142, -1, -1, -1, -1, -1, -1, -1, + -1, 151, 124, 125, 126, 127, 128, 129, 130, 131, + 132, 133, 134, 135, 136, 137, -1, -1, -1, -1, + 142, -1, -1, -1, -1, -1, -1, 149, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, - -1, -1, -1, -1, 140, -1, -1, -1, -1, -1, - -1, 147, 122, 123, 124, 125, 126, 127, 128, 129, - 130, 131, 132, 133, 134, 135, -1, -1, -1, -1, - 140, -1, -1, -1, -1, -1, -1, 147, 122, 123, + 136, 137, -1, -1, -1, -1, 142, -1, -1, -1, + -1, -1, -1, 149, 124, 125, 126, 127, 128, 129, + 130, 131, 132, 133, 134, 135, 136, 137, -1, -1, + -1, -1, 142, -1, -1, -1, -1, -1, -1, 149, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, - 134, 135, -1, -1, -1, -1, 140, -1, -1, -1, - -1, -1, -1, 147, 122, 123, 124, 125, 126, 127, - 128, 129, 130, 131, 132, 133, 134, 135, -1, -1, - -1, -1, 140, -1, -1, -1, -1, -1, -1, 147, - 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, - 132, 133, 134, 135, -1, -1, -1, -1, 140, -1, - -1, -1, -1, -1, -1, 147, 122, 123, 124, 125, + 134, 135, 136, 137, -1, -1, -1, -1, 142, -1, + -1, -1, -1, -1, -1, 149, 124, 125, 126, 127, + 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, + -1, -1, -1, -1, 142, -1, -1, -1, -1, -1, + -1, 149, 124, 125, 126, 127, 128, 129, 130, 131, + 132, 133, 134, 135, 136, 137, -1, -1, -1, -1, + 142, -1, -1, -1, -1, -1, -1, 149, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, - -1, -1, -1, -1, 140, -1, -1, -1, -1, -1, - -1, 147, 122, 123, 124, 125, 126, 127, 128, 129, - 130, 131, 132, 133, 134, 135, -1, -1, -1, -1, - 140, -1, -1, -1, -1, -1, -1, 147, 122, 123, + 136, 137, -1, -1, -1, -1, 142, -1, -1, -1, + -1, -1, -1, 149, 124, 125, 126, 127, 128, 129, + 130, 131, 132, 133, 134, 135, 136, 137, -1, -1, + -1, -1, 142, -1, -1, -1, -1, -1, -1, 149, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, - 134, 135, -1, -1, -1, -1, 140, -1, -1, -1, - -1, -1, -1, 147, 122, 123, 124, 125, 126, 127, - 128, 129, 130, 131, 132, 133, 134, 135, -1, -1, - -1, -1, 140, -1, -1, -1, -1, -1, -1, 147, - 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, - 132, 133, 134, 135, -1, -1, -1, -1, 140, -1, - -1, -1, -1, -1, -1, 147, 122, 123, 124, 125, + 134, 135, 136, 137, -1, -1, -1, -1, 142, -1, + -1, -1, -1, -1, -1, 149, 124, 125, 126, 127, + 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, + -1, -1, -1, -1, 142, -1, -1, -1, -1, -1, + -1, 149, 124, 125, 126, 127, 128, 129, 130, 131, + 132, 133, 134, 135, 136, 137, -1, -1, -1, -1, + 142, -1, -1, -1, -1, -1, -1, 149, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, - -1, -1, -1, -1, 140, -1, -1, -1, -1, -1, - -1, 147, 122, 123, 124, 125, 126, 127, 128, 129, - 130, 131, 132, 133, 134, 135, -1, -1, -1, -1, - 140, -1, -1, -1, -1, -1, -1, 147, 122, 123, + 136, 137, -1, -1, -1, -1, 142, -1, -1, -1, + -1, -1, -1, 149, 124, 125, 126, 127, 128, 129, + 130, 131, 132, 133, 134, 135, 136, 137, -1, -1, + -1, -1, 142, -1, -1, -1, -1, -1, -1, 149, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, - 134, 135, -1, -1, -1, -1, 140, -1, -1, -1, - -1, -1, -1, 147, 122, 123, 124, 125, 126, 127, - 128, 129, 130, 131, 132, 133, 134, 135, -1, -1, - -1, -1, 140, -1, -1, -1, -1, -1, -1, 147, - 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, - 132, 133, 134, 135, -1, -1, -1, -1, 140, -1, - -1, -1, -1, -1, -1, 147, 122, 123, 124, 125, + 134, 135, 136, 137, -1, -1, -1, -1, 142, -1, + -1, -1, -1, -1, -1, 149, 124, 125, 126, 127, + 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, + -1, -1, -1, -1, 142, -1, -1, -1, -1, -1, + -1, 149, 124, 125, 126, 127, 128, 129, 130, 131, + 132, 133, 134, 135, 136, 137, -1, -1, -1, -1, + 142, -1, -1, -1, -1, -1, -1, 149, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, - -1, -1, -1, -1, 140, -1, -1, -1, -1, -1, - -1, 147, 122, 123, 124, 125, 126, 127, 128, 129, - 130, 131, 132, 133, 134, 135, -1, -1, -1, -1, - 140, -1, -1, -1, -1, -1, -1, 147, 122, 123, + 136, 137, -1, -1, -1, -1, 142, -1, -1, -1, + -1, -1, -1, 149, 124, 125, 126, 127, 128, 129, + 130, 131, 132, 133, 134, 135, 136, 137, -1, -1, + -1, -1, 142, -1, -1, -1, -1, -1, -1, 149, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, - 134, 135, -1, -1, -1, -1, 140, -1, -1, -1, - -1, -1, -1, 147, 122, 123, 124, 125, 126, 127, - 128, 129, 130, 131, 132, 133, 134, 135, -1, -1, - -1, -1, 140, -1, -1, -1, -1, -1, -1, 147, - 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, - 132, 133, 134, 135, -1, -1, -1, -1, 140, -1, - -1, -1, -1, -1, -1, 147, 122, 123, 124, 125, + 134, 135, 136, 137, -1, -1, -1, -1, 142, -1, + -1, -1, -1, -1, -1, 149, 124, 125, 126, 127, + 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, + -1, -1, -1, -1, 142, -1, -1, -1, -1, -1, + -1, 149, 124, 125, 126, 127, 128, 129, 130, 131, + 132, 133, 134, 135, 136, 137, -1, -1, -1, -1, + 142, -1, -1, -1, -1, -1, -1, 149, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, - -1, -1, -1, -1, 140, -1, -1, -1, -1, -1, - -1, 147, 122, 123, 124, 125, 126, 127, 128, 129, - 130, 131, 132, 133, 134, 135, -1, -1, -1, -1, - 140, -1, -1, -1, -1, -1, -1, 147, 122, 123, + 136, 137, -1, -1, -1, -1, 142, -1, -1, -1, + -1, -1, -1, 149, 124, 125, 126, 127, 128, 129, + 130, 131, 132, 133, 134, 135, 136, 137, -1, -1, + -1, -1, 142, -1, -1, -1, -1, -1, -1, 149, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, - 134, 135, -1, -1, -1, -1, 140, -1, -1, -1, - -1, -1, -1, 147, 122, 123, 124, 125, 126, 127, - 128, 129, 130, 131, 132, 133, 134, 135, -1, -1, - -1, -1, 140, -1, -1, -1, -1, -1, -1, 147, - 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, - 132, 133, 134, 135, -1, -1, -1, -1, 140, -1, - -1, -1, 144, 122, 123, 124, 125, 126, 127, 128, - 129, 130, 131, 132, 133, 134, 135, -1, -1, -1, - -1, 140, -1, -1, -1, 144, 122, 123, 124, 125, + 134, 135, 136, 137, -1, -1, -1, -1, 142, -1, + -1, -1, -1, -1, -1, 149, 124, 125, 126, 127, + 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, + -1, -1, -1, -1, 142, -1, -1, -1, -1, -1, + -1, 149, 124, 125, 126, 127, 128, 129, 130, 131, + 132, 133, 134, 135, 136, 137, -1, -1, -1, -1, + 142, -1, -1, -1, -1, -1, -1, 149, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, - -1, -1, -1, -1, 140, -1, -1, -1, 144, 122, - 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, - 133, 134, 135, -1, -1, -1, -1, 140, -1, -1, - -1, 144, 122, 123, 124, 125, 126, 127, 128, 129, - 130, 131, 132, 133, 134, 135, -1, -1, -1, -1, - 140, -1, -1, -1, 144, 122, 123, 124, 125, 126, - 127, 128, 129, 130, 131, 132, 133, 134, 135, -1, - -1, -1, -1, 140, -1, -1, -1, 144, 122, 123, + 136, 137, -1, -1, -1, -1, 142, -1, -1, -1, + -1, -1, -1, 149, 124, 125, 126, 127, 128, 129, + 130, 131, 132, 133, 134, 135, 136, 137, -1, -1, + -1, -1, 142, -1, -1, -1, 146, 124, 125, 126, + 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, + 137, -1, -1, -1, -1, 142, -1, -1, -1, 146, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, - 134, 135, -1, -1, -1, -1, 140, -1, -1, -1, - 144, 122, 123, 124, 125, 126, 127, 128, 129, 130, - 131, 132, 133, 134, 135, -1, -1, -1, -1, 140, - -1, -1, -1, 144, 122, 123, 124, 125, 126, 127, - 128, 129, 130, 131, 132, 133, 134, 135, -1, -1, - -1, -1, 140, -1, -1, -1, 144, 122, 123, 124, + 134, 135, 136, 137, -1, -1, -1, -1, 142, -1, + -1, -1, 146, 124, 125, 126, 127, 128, 129, 130, + 131, 132, 133, 134, 135, 136, 137, -1, -1, -1, + -1, 142, -1, -1, -1, 146, 124, 125, 126, 127, + 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, + -1, -1, -1, -1, 142, -1, -1, -1, 146, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, - 135, -1, -1, -1, -1, 140, -1, -1, -1, 144, - 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, - 132, 133, 134, 135, -1, -1, -1, -1, 140, -1, - -1, -1, 144, 122, 123, 124, 125, 126, 127, 128, - 129, 130, 131, 132, 133, 134, 135, -1, -1, -1, - -1, 140, -1, -1, -1, 144, 122, 123, 124, 125, + 135, 136, 137, -1, -1, -1, -1, 142, -1, -1, + -1, 146, 124, 125, 126, 127, 128, 129, 130, 131, + 132, 133, 134, 135, 136, 137, -1, -1, -1, -1, + 142, -1, -1, -1, 146, 124, 125, 126, 127, 128, + 129, 130, 131, 132, 133, 134, 135, 136, 137, -1, + -1, -1, -1, 142, -1, -1, -1, 146, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, - -1, -1, -1, -1, 140, -1, -1, -1, 144, 122, - 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, - 133, 134, 135, -1, -1, -1, -1, 140, -1, -1, - -1, 144, 122, 123, 124, 125, 126, 127, 128, 129, - 130, 131, 132, 133, 134, 135, -1, -1, -1, -1, - 140, -1, -1, -1, 144, 122, 123, 124, 125, 126, - 127, 128, 129, 130, 131, 132, 133, 134, 135, -1, - -1, -1, -1, 140, -1, -1, -1, 144, 122, 123, + 136, 137, -1, -1, -1, -1, 142, -1, -1, -1, + 146, 124, 125, 126, 127, 128, 129, 130, 131, 132, + 133, 134, 135, 136, 137, -1, -1, -1, -1, 142, + -1, -1, -1, 146, 124, 125, 126, 127, 128, 129, + 130, 131, 132, 133, 134, 135, 136, 137, -1, -1, + -1, -1, 142, -1, -1, -1, 146, 124, 125, 126, + 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, + 137, -1, -1, -1, -1, 142, -1, -1, -1, 146, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, - 134, 135, -1, -1, -1, -1, 140, -1, -1, -1, - 144, 122, 123, 124, 125, 126, 127, 128, 129, 130, - 131, 132, 133, 134, 135, -1, -1, -1, -1, 140, - -1, -1, -1, 144, 122, 123, 124, 125, 126, 127, - 128, 129, 130, 131, 132, 133, 134, 135, -1, -1, - -1, -1, 140, -1, -1, -1, 144, 122, 123, 124, + 134, 135, 136, 137, -1, -1, -1, -1, 142, -1, + -1, -1, 146, 124, 125, 126, 127, 128, 129, 130, + 131, 132, 133, 134, 135, 136, 137, -1, -1, -1, + -1, 142, -1, -1, -1, 146, 124, 125, 126, 127, + 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, + -1, -1, -1, -1, 142, -1, -1, -1, 146, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, - 135, -1, -1, -1, -1, 140, -1, -1, -1, 144, - 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, - 132, 133, 134, 135, -1, -1, -1, -1, 140, -1, - -1, -1, 144, 122, 123, 124, 125, 126, 127, 128, - 129, 130, 131, 132, 133, 134, 135, -1, -1, -1, - -1, 140, -1, -1, -1, 144, 122, 123, 124, 125, + 135, 136, 137, -1, -1, -1, -1, 142, -1, -1, + -1, 146, 124, 125, 126, 127, 128, 129, 130, 131, + 132, 133, 134, 135, 136, 137, -1, -1, -1, -1, + 142, -1, -1, -1, 146, 124, 125, 126, 127, 128, + 129, 130, 131, 132, 133, 134, 135, 136, 137, -1, + -1, -1, -1, 142, -1, -1, -1, 146, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, - -1, -1, -1, -1, 140, -1, -1, -1, 144, 122, - 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, - 133, 134, 135, -1, -1, -1, -1, 140, -1, -1, - -1, 144, 122, 123, 124, 125, 126, 127, 128, 129, - 130, 131, 132, 133, 134, 135, -1, -1, -1, -1, - 140, -1, -1, -1, 144, 122, 123, 124, 125, 126, - 127, 128, 129, 130, 131, 132, 133, 134, 135, -1, - -1, -1, -1, 140, -1, -1, -1, 144, 122, 123, + 136, 137, -1, -1, -1, -1, 142, -1, -1, -1, + 146, 124, 125, 126, 127, 128, 129, 130, 131, 132, + 133, 134, 135, 136, 137, -1, -1, -1, -1, 142, + -1, -1, -1, 146, 124, 125, 126, 127, 128, 129, + 130, 131, 132, 133, 134, 135, 136, 137, -1, -1, + -1, -1, 142, -1, -1, -1, 146, 124, 125, 126, + 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, + 137, -1, -1, -1, -1, 142, -1, -1, -1, 146, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, - 134, 135, -1, -1, -1, -1, 140, -1, -1, -1, - 144, 122, 123, 124, 125, 126, 127, 128, 129, 130, - 131, 132, 133, 134, 135, -1, -1, -1, -1, 140, - -1, -1, -1, 144, 122, 123, 124, 125, 126, 127, - 128, 129, 130, 131, 132, 133, 134, 135, -1, -1, - -1, -1, 140, -1, -1, -1, 144, 122, 123, 124, + 134, 135, 136, 137, -1, -1, -1, -1, 142, -1, + -1, -1, 146, 124, 125, 126, 127, 128, 129, 130, + 131, 132, 133, 134, 135, 136, 137, -1, -1, -1, + -1, 142, -1, -1, -1, 146, 124, 125, 126, 127, + 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, + -1, -1, -1, -1, 142, -1, -1, -1, 146, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, - 135, -1, -1, -1, -1, 140, -1, -1, -1, 144, - 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, - 132, 133, 134, 135, -1, -1, -1, -1, 140, -1, - -1, -1, 144, 122, 123, 124, 125, 126, 127, 128, - 129, 130, 131, 132, 133, 134, 135, -1, -1, -1, - -1, 140, -1, -1, -1, 144, 122, 123, 124, 125, + 135, 136, 137, -1, -1, -1, -1, 142, -1, -1, + -1, 146, 124, 125, 126, 127, 128, 129, 130, 131, + 132, 133, 134, 135, 136, 137, -1, -1, -1, -1, + 142, -1, -1, -1, 146, 124, 125, 126, 127, 128, + 129, 130, 131, 132, 133, 134, 135, 136, 137, -1, + -1, -1, -1, 142, -1, -1, -1, 146, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, - -1, -1, -1, -1, 140, -1, 142, 122, 123, 124, - 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, - 135, -1, -1, -1, -1, 140, -1, 142, 122, 123, + 136, 137, -1, -1, -1, -1, 142, -1, -1, -1, + 146, 124, 125, 126, 127, 128, 129, 130, 131, 132, + 133, 134, 135, 136, 137, -1, -1, -1, -1, 142, + -1, -1, -1, 146, 124, 125, 126, 127, 128, 129, + 130, 131, 132, 133, 134, 135, 136, 137, -1, -1, + -1, -1, 142, -1, -1, -1, 146, 124, 125, 126, + 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, + 137, -1, -1, -1, -1, 142, -1, -1, -1, 146, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, - 134, 135, -1, -1, -1, -1, 140, -1, 142, 122, - 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, - 133, 134, 135, -1, -1, -1, -1, 140, -1, 142, - 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, - 132, 133, 134, 135, -1, -1, -1, -1, 140, -1, - 142, 122, 123, 124, 125, 126, 127, 128, 129, 130, - 131, 132, 133, 134, 135, -1, -1, -1, -1, 140, - -1, 142, 122, 123, 124, 125, 126, 127, 128, 129, - 130, 131, 132, 133, 134, 135, -1, -1, -1, -1, - 140, -1, 142, 122, 123, 124, 125, 126, 127, 128, - 129, 130, 131, 132, 133, 134, 135, -1, -1, -1, - -1, 140, -1, 142, 122, 123, 124, 125, 126, 127, - 128, 129, 130, 131, 132, 133, 134, 135, -1, -1, - -1, -1, 140, -1, 142, 122, 123, 124, 125, 126, - 127, 128, 129, 130, 131, 132, 133, 134, 135, -1, - -1, -1, -1, 140, -1, 142, 122, 123, 124, 125, + 134, 135, 136, 137, -1, -1, -1, -1, 142, -1, + 144, 124, 125, 126, 127, 128, 129, 130, 131, 132, + 133, 134, 135, 136, 137, -1, -1, -1, -1, 142, + -1, 144, 124, 125, 126, 127, 128, 129, 130, 131, + 132, 133, 134, 135, 136, 137, -1, -1, -1, -1, + 142, -1, 144, 124, 125, 126, 127, 128, 129, 130, + 131, 132, 133, 134, 135, 136, 137, -1, -1, -1, + -1, 142, -1, 144, 124, 125, 126, 127, 128, 129, + 130, 131, 132, 133, 134, 135, 136, 137, -1, -1, + -1, -1, 142, -1, 144, 124, 125, 126, 127, 128, + 129, 130, 131, 132, 133, 134, 135, 136, 137, -1, + -1, -1, -1, 142, -1, 144, 124, 125, 126, 127, + 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, + -1, -1, -1, -1, 142, -1, 144, 124, 125, 126, + 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, + 137, -1, -1, -1, -1, 142, -1, 144, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, - -1, -1, -1, -1, 140, -1, 142, 122, 123, 124, + 136, 137, -1, -1, -1, -1, 142, -1, 144, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, - 135, -1, -1, -1, -1, 140, -1, 142, 122, 123, + 135, 136, 137, -1, -1, -1, -1, 142, -1, 144, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, - 134, 135, -1, -1, -1, -1, 140, -1, 142, 122, - 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, - 133, 134, 135, -1, -1, -1, -1, 140, -1, 142, - 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, - 132, 133, 134, 135, -1, -1, -1, -1, 140, -1, - 142, 122, 123, 124, 125, 126, 127, 128, 129, 130, - 131, 132, 133, 134, 135, -1, -1, -1, -1, 140, - -1, 142, 122, 123, 124, 125, 126, 127, 128, 129, - 130, 131, 132, 133, 134, 135, -1, -1, -1, -1, - 140, -1, 142, 122, 123, 124, 125, 126, 127, 128, - 129, 130, 131, 132, 133, 134, 135, -1, -1, -1, - -1, 140, -1, 142, 122, 123, 124, 125, 126, 127, - 128, 129, 130, 131, 132, 133, 134, 135, -1, -1, - -1, -1, 140, -1, 142, 122, 123, 124, 125, 126, - 127, 128, 129, 130, 131, 132, 133, 134, 135, -1, - -1, -1, -1, 140, -1, 142, 122, 123, 124, 125, + 134, 135, 136, 137, -1, -1, -1, -1, 142, -1, + 144, 124, 125, 126, 127, 128, 129, 130, 131, 132, + 133, 134, 135, 136, 137, -1, -1, -1, -1, 142, + -1, 144, 124, 125, 126, 127, 128, 129, 130, 131, + 132, 133, 134, 135, 136, 137, -1, -1, -1, -1, + 142, -1, 144, 124, 125, 126, 127, 128, 129, 130, + 131, 132, 133, 134, 135, 136, 137, -1, -1, -1, + -1, 142, -1, 144, 124, 125, 126, 127, 128, 129, + 130, 131, 132, 133, 134, 135, 136, 137, -1, -1, + -1, -1, 142, -1, 144, 124, 125, 126, 127, 128, + 129, 130, 131, 132, 133, 134, 135, 136, 137, -1, + -1, -1, -1, 142, -1, 144, 124, 125, 126, 127, + 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, + -1, -1, -1, -1, 142, -1, 144, 124, 125, 126, + 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, + 137, -1, -1, -1, -1, 142, -1, 144, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, - -1, -1, -1, -1, 140, -1, 142, 122, 123, 124, + 136, 137, -1, -1, -1, -1, 142, -1, 144, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, - 135, -1, -1, -1, -1, 140, -1, 142, 122, 123, + 135, 136, 137, -1, -1, -1, -1, 142, -1, 144, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, - 134, 135, -1, -1, -1, -1, 140, -1, 142, 122, - 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, - 133, 134, 135, -1, -1, -1, -1, 140, -1, 142, - 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, - 132, 133, 134, 135, -1, -1, -1, -1, 140, -1, - 142, 122, 123, 124, 125, 126, 127, 128, 129, 130, - 131, 132, 133, 134, 135, -1, -1, -1, -1, 140, - -1, 142, 122, 123, 124, 125, 126, 127, 128, 129, - 130, 131, 132, 133, 134, 135, -1, -1, -1, -1, - 140, -1, 142, 122, 123, 124, 125, 126, 127, 128, - 129, 130, 131, 132, 133, 134, 135, -1, -1, -1, - -1, 140, -1, 142, 122, 123, 124, 125, 126, 127, - 128, 129, 130, 131, 132, 133, 134, 135, -1, -1, - -1, -1, 140, -1, 142, 122, 123, 124, 125, 126, - 127, 128, 129, 130, 131, 132, 133, 134, 135, -1, - -1, -1, -1, 140, -1, 142, 122, 123, 124, 125, + 134, 135, 136, 137, -1, -1, -1, -1, 142, -1, + 144, 124, 125, 126, 127, 128, 129, 130, 131, 132, + 133, 134, 135, 136, 137, -1, -1, -1, -1, 142, + -1, 144, 124, 125, 126, 127, 128, 129, 130, 131, + 132, 133, 134, 135, 136, 137, -1, -1, -1, -1, + 142, -1, 144, 124, 125, 126, 127, 128, 129, 130, + 131, 132, 133, 134, 135, 136, 137, -1, -1, -1, + -1, 142, -1, 144, 124, 125, 126, 127, 128, 129, + 130, 131, 132, 133, 134, 135, 136, 137, -1, -1, + -1, -1, 142, -1, 144, 124, 125, 126, 127, 128, + 129, 130, 131, 132, 133, 134, 135, 136, 137, -1, + -1, -1, -1, 142, -1, 144, 124, 125, 126, 127, + 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, + -1, -1, -1, -1, 142, -1, 144, 124, 125, 126, + 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, + 137, -1, -1, -1, -1, 142, -1, 144, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, - -1, -1, -1, -1, 140, -1, 142, 122, 123, 124, + 136, 137, -1, -1, -1, -1, 142, -1, 144, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, - 135, -1, -1, -1, -1, 140, -1, 142, 122, 123, + 135, 136, 137, -1, -1, -1, -1, 142, -1, 144, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, - 134, 135, -1, -1, -1, -1, 140, -1, 142, 122, - 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, - 133, 134, 135, -1, -1, -1, -1, 140, -1, 142, - 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, - 132, 133, 134, 135, -1, -1, -1, -1, 140, -1, - 142, 122, 123, 124, 125, 126, 127, 128, 129, 130, - 131, 132, 133, 134, 135, -1, -1, -1, -1, 140, - -1, 142, 122, 123, 124, 125, 126, 127, 128, 129, - 130, 131, 132, 133, 134, 135, -1, -1, -1, -1, - 140, -1, 142, 122, 123, 124, 125, 126, 127, 128, - 129, 130, 131, 132, 133, 134, 135, -1, -1, -1, - -1, 140, -1, 142, 122, 123, 124, 125, 126, 127, - 128, 129, 130, 131, 132, 133, 134, 135, -1, -1, - -1, -1, 140, -1, 142, 122, 123, 124, 125, 126, - 127, 128, 129, 130, 131, 132, 133, 134, 135, -1, - -1, -1, -1, 140, -1, 142, 122, 123, 124, 125, + 134, 135, 136, 137, -1, -1, -1, -1, 142, -1, + 144, 124, 125, 126, 127, 128, 129, 130, 131, 132, + 133, 134, 135, 136, 137, -1, -1, -1, -1, 142, + -1, 144, 124, 125, 126, 127, 128, 129, 130, 131, + 132, 133, 134, 135, 136, 137, -1, -1, -1, -1, + 142, -1, 144, 124, 125, 126, 127, 128, 129, 130, + 131, 132, 133, 134, 135, 136, 137, -1, -1, -1, + -1, 142, -1, 144, 124, 125, 126, 127, 128, 129, + 130, 131, 132, 133, 134, 135, 136, 137, -1, -1, + -1, -1, 142, -1, 144, 124, 125, 126, 127, 128, + 129, 130, 131, 132, 133, 134, 135, 136, 137, -1, + -1, -1, -1, 142, -1, 144, 124, 125, 126, 127, + 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, + -1, -1, -1, -1, 142, -1, 144, 124, 125, 126, + 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, + 137, -1, -1, -1, -1, 142, -1, 144, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, - -1, -1, -1, -1, 140, -1, 142, 122, 123, 124, + 136, 137, -1, -1, -1, -1, 142, -1, 144, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, - 135, -1, -1, -1, -1, 140, -1, 142, 122, 123, + 135, 136, 137, -1, -1, -1, -1, 142, -1, 144, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, - 134, 135, -1, -1, -1, -1, 140, -1, 142, 122, - 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, - 133, 134, 135, -1, -1, -1, -1, 140, -1, 142, - 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, - 132, 133, 134, 135, -1, -1, -1, -1, 140, -1, - 142, 122, 123, 124, 125, 126, 127, 128, 129, 130, - 131, 132, 133, 134, 135, -1, -1, -1, -1, 140, - -1, 142, 122, 123, 124, 125, 126, 127, 128, 129, - 130, 131, 132, 133, 134, 135, -1, -1, -1, -1, - 140, -1, 142, 122, 123, 124, 125, 126, 127, 128, - 129, 130, 131, 132, 133, 134, 135, -1, -1, -1, - -1, 140, -1, 142, 122, 123, 124, 125, 126, 127, - 128, 129, 130, 131, 132, 133, 134, 135, -1, -1, - -1, -1, 140, -1, 142, 122, 123, 124, 125, 126, - 127, 128, 129, 130, 131, 132, 133, 134, 135, -1, - -1, -1, -1, 140, -1, 142, 122, 123, 124, 125, + 134, 135, 136, 137, -1, -1, -1, -1, 142, -1, + 144, 124, 125, 126, 127, 128, 129, 130, 131, 132, + 133, 134, 135, 136, 137, -1, -1, -1, -1, 142, + -1, 144, 124, 125, 126, 127, 128, 129, 130, 131, + 132, 133, 134, 135, 136, 137, -1, -1, -1, -1, + 142, -1, 144, 124, 125, 126, 127, 128, 129, 130, + 131, 132, 133, 134, 135, 136, 137, -1, -1, -1, + -1, 142, -1, 144, 124, 125, 126, 127, 128, 129, + 130, 131, 132, 133, 134, 135, 136, 137, -1, -1, + -1, -1, 142, -1, 144, 124, 125, 126, 127, 128, + 129, 130, 131, 132, 133, 134, 135, 136, 137, -1, + -1, -1, -1, 142, -1, 144, 124, 125, 126, 127, + 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, + -1, -1, -1, -1, 142, -1, 144, 124, 125, 126, + 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, + 137, -1, -1, -1, -1, 142, -1, 144, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, - -1, -1, -1, -1, 140, -1, 142, 122, 123, 124, + 136, 137, -1, -1, -1, -1, 142, -1, 144, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, - 135, -1, -1, -1, -1, 140, -1, 142, 122, 123, + 135, 136, 137, -1, -1, -1, -1, 142, -1, 144, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, - 134, 135, -1, -1, -1, -1, 140, -1, 142 + 134, 135, 136, 137, -1, -1, -1, -1, 142, -1, + 144, 124, 125, 126, 127, 128, 129, 130, 131, 132, + 133, 134, 135, 136, 137, -1, -1, -1, -1, 142, + -1, 144, 124, 125, 126, 127, 128, 129, 130, 131, + 132, 133, 134, 135, 136, 137, -1, -1, -1, -1, + 142, -1, 144, 124, 125, 126, 127, 128, 129, 130, + 131, 132, 133, 134, 135, 136, 137, -1, -1, -1, + -1, 142 }; /* YYSTOS[STATE-NUM] -- The (internal number of the) accessing symbol of state STATE-NUM. */ static const yytype_uint8 yystos[] = { - 0, 1, 152, 153, 6, 0, 4, 12, 13, 35, + 0, 1, 154, 155, 6, 0, 4, 12, 13, 35, 40, 41, 43, 44, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 57, 58, 59, 60, 61, 62, 63, 64, 65, 67, 68, 69, 70, 71, 72, 73, 74, 76, 77, 78, 79, 80, 81, 84, 85, 90, 91, 92, 93, 96, 98, 100, 101, 102, 103, 104, - 105, 106, 107, 108, 109, 114, 115, 116, 117, 154, - 156, 157, 175, 179, 184, 187, 188, 189, 190, 191, - 192, 193, 214, 215, 216, 217, 218, 3, 4, 5, + 105, 106, 107, 108, 109, 116, 117, 118, 119, 156, + 158, 159, 177, 181, 186, 189, 190, 191, 192, 193, + 194, 195, 216, 217, 218, 219, 220, 3, 4, 5, 7, 9, 10, 11, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 36, 37, 38, 39, 42, - 104, 110, 111, 112, 113, 118, 119, 120, 121, 131, - 132, 136, 138, 139, 141, 143, 145, 146, 148, 173, - 174, 219, 220, 232, 13, 52, 141, 6, 148, 6, - 6, 6, 141, 148, 141, 141, 75, 141, 148, 141, - 141, 75, 148, 141, 141, 56, 52, 52, 52, 52, - 49, 52, 54, 54, 46, 49, 52, 54, 49, 52, - 54, 49, 52, 141, 49, 148, 131, 132, 141, 148, - 221, 222, 221, 148, 46, 49, 52, 148, 221, 4, - 50, 59, 52, 52, 49, 4, 104, 148, 4, 6, - 49, 4, 4, 4, 141, 141, 141, 4, 148, 228, - 4, 141, 141, 6, 143, 4, 4, 5, 148, 5, - 148, 141, 141, 141, 141, 4, 143, 145, 150, 174, - 148, 5, 232, 141, 143, 141, 143, 141, 143, 141, - 143, 141, 143, 141, 143, 141, 143, 141, 143, 141, - 143, 141, 143, 141, 143, 141, 143, 141, 143, 141, - 143, 141, 143, 141, 143, 141, 143, 141, 143, 141, - 143, 141, 143, 141, 143, 141, 141, 141, 141, 7, - 141, 4, 219, 219, 219, 219, 144, 148, 219, 4, - 96, 97, 4, 4, 184, 185, 186, 219, 6, 6, - 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, - 132, 133, 134, 135, 140, 6, 6, 219, 5, 219, - 219, 4, 46, 132, 184, 193, 219, 226, 227, 219, - 219, 141, 219, 227, 219, 219, 141, 227, 219, 219, - 132, 148, 219, 224, 226, 141, 148, 141, 141, 5, - 224, 225, 225, 225, 141, 180, 181, 182, 183, 141, - 141, 141, 224, 224, 4, 224, 221, 221, 221, 219, - 219, 131, 132, 148, 148, 221, 148, 148, 148, 131, - 132, 141, 186, 221, 148, 141, 148, 141, 141, 225, - 224, 141, 4, 6, 143, 143, 186, 6, 148, 143, - 143, 6, 219, 219, 219, 145, 219, 148, 99, 219, - 219, 219, 6, 6, 186, 6, 186, 4, 231, 232, - 231, 231, 231, 143, 219, 4, 148, 158, 6, 219, - 219, 219, 219, 219, 219, 219, 219, 219, 219, 219, - 219, 219, 219, 219, 219, 219, 219, 219, 219, 219, - 219, 219, 219, 219, 219, 219, 219, 219, 219, 219, - 219, 219, 219, 219, 219, 219, 219, 219, 219, 219, - 219, 231, 231, 231, 231, 219, 5, 143, 142, 7, - 121, 227, 144, 7, 173, 174, 145, 7, 143, 149, - 46, 49, 52, 54, 179, 6, 219, 219, 219, 219, - 219, 219, 219, 219, 219, 219, 219, 219, 219, 219, - 219, 6, 142, 147, 147, 142, 143, 148, 219, 226, - 8, 133, 147, 149, 142, 142, 219, 142, 149, 142, - 142, 219, 149, 142, 142, 148, 149, 227, 133, 7, - 219, 219, 219, 219, 7, 7, 212, 212, 219, 141, - 141, 141, 141, 219, 219, 219, 7, 7, 142, 6, - 147, 147, 147, 221, 221, 185, 185, 147, 219, 219, - 219, 219, 197, 147, 186, 219, 219, 219, 219, 7, - 213, 7, 219, 6, 219, 219, 149, 227, 219, 219, - 142, 142, 142, 96, 147, 186, 148, 8, 142, 144, - 149, 149, 143, 145, 142, 142, 142, 142, 219, 144, - 174, 219, 4, 86, 87, 88, 89, 149, 161, 165, - 168, 170, 171, 142, 144, 142, 144, 142, 144, 142, - 144, 142, 144, 142, 144, 142, 144, 142, 144, 142, - 144, 142, 144, 142, 144, 147, 147, 142, 144, 142, - 144, 142, 144, 142, 144, 142, 144, 142, 144, 147, - 147, 147, 147, 147, 147, 142, 147, 147, 142, 142, - 6, 147, 219, 224, 224, 149, 7, 145, 173, 174, - 232, 219, 6, 4, 4, 148, 229, 144, 148, 148, - 148, 148, 8, 6, 128, 155, 227, 219, 7, 144, - 148, 219, 219, 219, 226, 219, 226, 99, 7, 7, - 142, 7, 99, 7, 7, 142, 99, 7, 7, 227, - 149, 148, 219, 142, 149, 142, 142, 219, 224, 4, - 211, 6, 142, 176, 219, 232, 176, 176, 176, 142, - 142, 142, 224, 224, 145, 221, 219, 219, 149, 149, - 219, 147, 147, 147, 76, 82, 83, 207, 208, 221, - 149, 194, 142, 149, 142, 142, 219, 6, 219, 142, - 144, 144, 149, 144, 144, 7, 7, 7, 145, 219, - 149, 219, 219, 7, 145, 219, 4, 7, 7, 7, - 7, 144, 145, 174, 231, 149, 162, 141, 141, 148, - 172, 6, 219, 219, 219, 219, 219, 219, 219, 219, - 227, 231, 219, 144, 6, 6, 144, 4, 96, 97, - 219, 6, 6, 6, 7, 143, 228, 230, 6, 227, - 227, 227, 227, 219, 128, 231, 142, 147, 221, 227, - 149, 8, 52, 224, 224, 7, 224, 52, 54, 224, - 224, 7, 54, 224, 224, 149, 227, 6, 7, 7, - 7, 7, 66, 210, 6, 7, 142, 142, 142, 142, - 7, 7, 7, 6, 6, 4, 147, 147, 147, 149, - 221, 221, 221, 6, 148, 141, 149, 208, 147, 207, - 7, 6, 7, 7, 6, 148, 6, 6, 52, 6, - 6, 224, 224, 224, 4, 147, 8, 8, 142, 4, - 4, 144, 148, 148, 148, 148, 6, 4, 6, 141, - 219, 219, 223, 224, 148, 142, 144, 142, 144, 142, - 144, 142, 144, 142, 142, 142, 173, 7, 173, 174, - 145, 7, 6, 228, 219, 147, 149, 149, 149, 149, - 149, 6, 6, 155, 219, 6, 149, 219, 148, 59, - 178, 178, 224, 6, 148, 148, 6, 6, 224, 148, - 6, 6, 149, 5, 224, 224, 224, 4, 6, 224, - 7, 7, 7, 7, 224, 224, 224, 6, 7, 219, - 219, 219, 148, 147, 149, 147, 149, 147, 149, 219, - 224, 219, 219, 221, 149, 5, 148, 224, 148, 148, - 224, 227, 148, 6, 6, 95, 219, 219, 219, 6, - 7, 145, 224, 224, 224, 224, 174, 159, 219, 147, - 147, 147, 149, 160, 219, 224, 232, 219, 6, 4, - 229, 6, 144, 228, 6, 6, 6, 6, 231, 147, - 144, 219, 221, 6, 6, 6, 219, 219, 6, 219, - 5, 6, 6, 99, 177, 219, 6, 224, 224, 224, - 224, 6, 4, 209, 6, 219, 232, 149, 142, 147, - 149, 185, 221, 6, 198, 221, 6, 199, 221, 6, - 200, 149, 147, 142, 149, 147, 6, 132, 221, 6, - 221, 221, 6, 149, 219, 224, 147, 149, 8, 149, - 142, 148, 219, 232, 4, 147, 147, 147, 147, 142, - 147, 219, 219, 224, 148, 147, 149, 6, 6, 6, - 7, 6, 145, 6, 219, 149, 149, 149, 149, 5, - 50, 6, 6, 6, 6, 6, 148, 6, 6, 6, - 148, 219, 149, 147, 148, 147, 148, 147, 148, 6, - 224, 7, 148, 219, 147, 147, 147, 6, 149, 94, - 219, 219, 227, 6, 6, 224, 224, 224, 224, 163, - 219, 147, 147, 223, 219, 6, 228, 97, 147, 6, - 6, 6, 6, 6, 148, 223, 185, 147, 149, 219, - 221, 207, 219, 221, 207, 219, 221, 207, 147, 149, - 224, 186, 149, 221, 227, 221, 219, 149, 149, 149, - 149, 149, 149, 149, 148, 219, 219, 149, 6, 219, - 219, 149, 149, 219, 149, 147, 149, 149, 147, 149, - 149, 147, 149, 224, 6, 66, 149, 195, 148, 147, - 149, 147, 6, 6, 6, 6, 6, 6, 160, 142, - 147, 6, 148, 147, 149, 4, 209, 149, 6, 201, - 219, 6, 6, 202, 219, 6, 6, 203, 219, 6, - 149, 219, 207, 186, 227, 6, 221, 227, 149, 166, - 219, 223, 219, 6, 148, 149, 148, 149, 148, 149, - 6, 6, 149, 149, 196, 149, 147, 149, 6, 148, - 142, 149, 149, 207, 6, 204, 207, 6, 205, 207, - 6, 206, 207, 6, 227, 6, 164, 231, 169, 148, - 6, 149, 148, 149, 148, 149, 148, 149, 149, 147, - 149, 148, 223, 6, 207, 6, 207, 6, 207, 6, - 231, 6, 167, 231, 149, 149, 149, 149, 147, 149, - 6, 6, 6, 6, 231, 6 + 104, 110, 111, 112, 113, 114, 115, 120, 121, 122, + 123, 133, 134, 138, 140, 141, 143, 145, 147, 148, + 150, 175, 176, 221, 222, 234, 13, 52, 143, 6, + 150, 6, 6, 6, 143, 150, 143, 143, 75, 143, + 150, 143, 143, 75, 150, 143, 143, 56, 52, 52, + 52, 52, 49, 52, 54, 54, 46, 49, 52, 54, + 49, 52, 54, 49, 52, 143, 49, 150, 133, 134, + 143, 150, 223, 224, 223, 150, 46, 49, 52, 150, + 223, 4, 50, 59, 52, 52, 49, 4, 104, 150, + 4, 6, 49, 4, 4, 4, 143, 143, 143, 4, + 150, 230, 4, 143, 143, 6, 145, 4, 4, 5, + 150, 5, 150, 143, 143, 143, 143, 4, 145, 147, + 152, 176, 150, 5, 234, 143, 145, 143, 145, 143, + 145, 143, 145, 143, 145, 143, 145, 143, 145, 143, + 145, 143, 145, 143, 145, 143, 145, 143, 145, 143, + 145, 143, 145, 143, 145, 143, 145, 143, 145, 143, + 145, 143, 145, 143, 145, 143, 145, 143, 143, 143, + 143, 7, 143, 143, 143, 4, 221, 221, 221, 221, + 146, 150, 221, 4, 96, 97, 4, 4, 186, 187, + 188, 221, 6, 6, 124, 125, 126, 127, 128, 129, + 130, 131, 132, 133, 134, 135, 136, 137, 142, 6, + 6, 221, 5, 221, 221, 4, 46, 134, 186, 195, + 221, 228, 229, 221, 221, 143, 221, 229, 221, 221, + 143, 229, 221, 221, 134, 150, 221, 226, 228, 143, + 150, 143, 143, 5, 226, 227, 227, 227, 143, 182, + 183, 184, 185, 143, 143, 143, 226, 226, 4, 226, + 223, 223, 223, 221, 221, 133, 134, 150, 150, 223, + 150, 150, 150, 133, 134, 143, 188, 223, 150, 143, + 150, 143, 143, 227, 226, 143, 4, 6, 145, 145, + 188, 6, 150, 145, 145, 6, 221, 221, 221, 147, + 221, 150, 99, 221, 221, 221, 6, 6, 188, 6, + 188, 4, 233, 234, 233, 233, 233, 145, 221, 4, + 150, 160, 6, 221, 221, 221, 221, 221, 221, 221, + 221, 221, 221, 221, 221, 221, 221, 221, 221, 221, + 221, 221, 221, 221, 221, 221, 221, 221, 221, 221, + 221, 221, 221, 221, 221, 221, 221, 221, 221, 221, + 221, 221, 221, 221, 221, 233, 233, 233, 233, 221, + 233, 233, 233, 145, 144, 7, 123, 229, 146, 7, + 175, 176, 147, 7, 145, 151, 46, 49, 52, 54, + 181, 6, 221, 221, 221, 221, 221, 221, 221, 221, + 221, 221, 221, 221, 221, 221, 221, 6, 144, 149, + 149, 144, 145, 150, 221, 228, 8, 135, 149, 151, + 144, 144, 221, 144, 151, 144, 144, 221, 151, 144, + 144, 150, 151, 229, 135, 7, 221, 221, 221, 221, + 7, 7, 214, 214, 221, 143, 143, 143, 143, 221, + 221, 221, 7, 7, 144, 6, 149, 149, 149, 223, + 223, 187, 187, 149, 221, 221, 221, 221, 199, 149, + 188, 221, 221, 221, 221, 7, 215, 7, 221, 6, + 221, 221, 151, 229, 221, 221, 144, 144, 144, 96, + 149, 188, 150, 8, 144, 146, 151, 151, 145, 147, + 144, 144, 144, 144, 221, 146, 176, 221, 4, 86, + 87, 88, 89, 151, 163, 167, 170, 172, 173, 144, + 146, 144, 146, 144, 146, 144, 146, 144, 146, 144, + 146, 144, 146, 144, 146, 144, 146, 144, 146, 144, + 146, 149, 149, 144, 146, 144, 146, 144, 146, 144, + 146, 144, 146, 144, 146, 149, 149, 149, 149, 149, + 149, 144, 149, 149, 144, 144, 6, 149, 144, 149, + 221, 226, 226, 151, 7, 147, 175, 176, 234, 221, + 6, 4, 4, 150, 231, 146, 150, 150, 150, 150, + 8, 6, 130, 157, 229, 221, 7, 146, 150, 221, + 221, 221, 228, 221, 228, 99, 7, 7, 144, 7, + 99, 7, 7, 144, 99, 7, 7, 229, 151, 150, + 221, 144, 151, 144, 144, 221, 226, 4, 213, 6, + 144, 178, 221, 234, 178, 178, 178, 144, 144, 144, + 226, 226, 147, 223, 221, 221, 151, 151, 221, 149, + 149, 149, 76, 82, 83, 209, 210, 223, 151, 196, + 144, 151, 144, 144, 221, 6, 221, 144, 146, 146, + 151, 146, 146, 7, 7, 7, 147, 221, 151, 221, + 221, 7, 147, 221, 4, 7, 7, 7, 7, 146, + 147, 176, 233, 151, 164, 143, 143, 150, 174, 6, + 221, 221, 221, 221, 221, 221, 221, 221, 229, 233, + 221, 233, 146, 6, 6, 146, 4, 96, 97, 221, + 6, 6, 6, 7, 145, 230, 232, 6, 229, 229, + 229, 229, 221, 130, 233, 144, 149, 223, 229, 151, + 8, 52, 226, 226, 7, 226, 52, 54, 226, 226, + 7, 54, 226, 226, 151, 229, 6, 7, 7, 7, + 7, 66, 212, 6, 7, 144, 144, 144, 144, 7, + 7, 7, 6, 6, 4, 149, 149, 149, 151, 223, + 223, 223, 6, 150, 143, 151, 210, 149, 209, 7, + 6, 7, 7, 6, 150, 6, 6, 52, 6, 6, + 226, 226, 226, 4, 149, 8, 8, 144, 4, 4, + 146, 150, 150, 150, 150, 6, 4, 6, 143, 221, + 221, 225, 226, 150, 144, 146, 144, 146, 144, 146, + 144, 146, 144, 144, 144, 144, 175, 7, 175, 176, + 147, 7, 6, 230, 221, 149, 151, 151, 151, 151, + 151, 6, 6, 157, 221, 6, 151, 221, 150, 59, + 180, 180, 226, 6, 150, 150, 6, 6, 226, 150, + 6, 6, 151, 5, 226, 226, 226, 4, 6, 226, + 7, 7, 7, 7, 226, 226, 226, 6, 7, 221, + 221, 221, 150, 149, 151, 149, 151, 149, 151, 221, + 226, 221, 221, 223, 151, 5, 150, 226, 150, 150, + 226, 229, 150, 6, 6, 95, 221, 221, 221, 6, + 7, 147, 226, 226, 226, 226, 176, 161, 221, 149, + 149, 149, 151, 162, 221, 226, 234, 221, 6, 4, + 231, 6, 146, 230, 6, 6, 6, 6, 233, 149, + 146, 221, 223, 6, 6, 6, 221, 221, 6, 221, + 5, 6, 6, 99, 179, 221, 6, 226, 226, 226, + 226, 6, 4, 211, 6, 221, 234, 151, 144, 149, + 151, 187, 223, 6, 200, 223, 6, 201, 223, 6, + 202, 151, 149, 144, 151, 149, 6, 134, 223, 6, + 223, 223, 6, 151, 221, 226, 149, 151, 8, 151, + 144, 150, 221, 234, 4, 149, 149, 149, 149, 144, + 149, 221, 221, 226, 150, 149, 151, 6, 6, 6, + 7, 6, 147, 6, 221, 151, 151, 151, 151, 5, + 50, 6, 6, 6, 6, 6, 150, 6, 6, 6, + 150, 221, 151, 149, 150, 149, 150, 149, 150, 6, + 226, 7, 150, 221, 149, 149, 149, 6, 151, 94, + 221, 221, 229, 6, 6, 226, 226, 226, 226, 165, + 221, 149, 149, 225, 221, 6, 230, 97, 149, 6, + 6, 6, 6, 6, 150, 225, 187, 149, 151, 221, + 223, 209, 221, 223, 209, 221, 223, 209, 149, 151, + 226, 188, 151, 223, 229, 223, 221, 151, 151, 151, + 151, 151, 151, 151, 150, 221, 221, 151, 6, 221, + 221, 151, 151, 221, 151, 149, 151, 151, 149, 151, + 151, 149, 151, 226, 6, 66, 151, 197, 150, 149, + 151, 149, 6, 6, 6, 6, 6, 6, 162, 144, + 149, 6, 150, 149, 151, 4, 211, 151, 6, 203, + 221, 6, 6, 204, 221, 6, 6, 205, 221, 6, + 151, 221, 209, 188, 229, 6, 223, 229, 151, 168, + 221, 225, 221, 6, 150, 151, 150, 151, 150, 151, + 6, 6, 151, 151, 198, 151, 149, 151, 6, 150, + 144, 151, 151, 209, 6, 206, 209, 6, 207, 209, + 6, 208, 209, 6, 229, 6, 166, 233, 171, 150, + 6, 151, 150, 151, 150, 151, 150, 151, 151, 149, + 151, 150, 225, 6, 209, 6, 209, 6, 209, 6, + 233, 6, 169, 233, 151, 151, 151, 151, 149, 151, + 6, 6, 6, 6, 233, 6 }; #define yyerrok (yyerrstatus = 0) @@ -8706,6 +8710,28 @@ yyreduce: case 382: #line 4080 "Gmsh.y" + { + const char *env = GetEnvironmentVariable((yyvsp[(3) - (4)].c)); + if(!env) env = ""; + (yyval.c) = (char *)Malloc((sizeof(env) + 1) * sizeof(char)); + strcpy((yyval.c), env); + Free((yyvsp[(3) - (4)].c)); + ;} + break; + + case 383: +#line 4088 "Gmsh.y" + { + std::string s = Msg::GetString((yyvsp[(3) - (6)].c), (yyvsp[(5) - (6)].c)); + (yyval.c) = (char *)Malloc((s.size() + 1) * sizeof(char)); + strcpy((yyval.c), s.c_str()); + Free((yyvsp[(3) - (6)].c)); + Free((yyvsp[(5) - (6)].c)); + ;} + break; + + case 384: +#line 4096 "Gmsh.y" { (yyval.c) = (char *)Malloc((strlen((yyvsp[(3) - (6)].c)) + strlen((yyvsp[(5) - (6)].c)) + 1) * sizeof(char)); strcpy((yyval.c), (yyvsp[(3) - (6)].c)); @@ -8715,8 +8741,8 @@ yyreduce: ;} break; - case 383: -#line 4088 "Gmsh.y" + case 385: +#line 4104 "Gmsh.y" { (yyval.c) = (char *)Malloc((strlen((yyvsp[(3) - (4)].c)) + 1) * sizeof(char)); int i; @@ -8732,8 +8758,8 @@ yyreduce: ;} break; - case 384: -#line 4102 "Gmsh.y" + case 386: +#line 4118 "Gmsh.y" { (yyval.c) = (char *)Malloc((strlen((yyvsp[(3) - (4)].c)) + 1) * sizeof(char)); int i; @@ -8749,15 +8775,15 @@ yyreduce: ;} break; - case 385: -#line 4116 "Gmsh.y" + case 387: +#line 4132 "Gmsh.y" { (yyval.c) = (yyvsp[(3) - (4)].c); ;} break; - case 386: -#line 4120 "Gmsh.y" + case 388: +#line 4136 "Gmsh.y" { char tmpstring[1024]; int i = PrintListOfDouble((yyvsp[(3) - (6)].c), (yyvsp[(5) - (6)].l), tmpstring); @@ -8780,7 +8806,7 @@ yyreduce: /* Line 1267 of yacc.c. */ -#line 8784 "Gmsh.tab.cpp" +#line 8810 "Gmsh.tab.cpp" default: break; } YY_SYMBOL_PRINT ("-> $$ =", yyr1[yyn], &yyval, &yyloc); @@ -8994,7 +9020,7 @@ yyreturn: } -#line 4140 "Gmsh.y" +#line 4156 "Gmsh.y" int PrintListOfDouble(char *format, List_T *list, char *buffer) diff --git a/Parser/Gmsh.tab.hpp b/Parser/Gmsh.tab.hpp index 437d7b5c5710023f48f8f52cceefab0bb6208998..7399324920f64431094453520982636e155b9891 100644 --- a/Parser/Gmsh.tab.hpp +++ b/Parser/Gmsh.tab.hpp @@ -147,26 +147,28 @@ tShow = 363, tHide = 364, tGetValue = 365, - tGMSH_MAJOR_VERSION = 366, - tGMSH_MINOR_VERSION = 367, - tGMSH_PATCH_VERSION = 368, - tHomRank = 369, - tHomGen = 370, - tHomCut = 371, - tHomSeq = 372, - tAFFECTDIVIDE = 373, - tAFFECTTIMES = 374, - tAFFECTMINUS = 375, - tAFFECTPLUS = 376, - tOR = 377, - tAND = 378, - tNOTEQUAL = 379, - tEQUAL = 380, - tGREATEROREQUAL = 381, - tLESSOREQUAL = 382, - UNARYPREC = 383, - tMINUSMINUS = 384, - tPLUSPLUS = 385 + tGetEnv = 366, + tGetString = 367, + tGMSH_MAJOR_VERSION = 368, + tGMSH_MINOR_VERSION = 369, + tGMSH_PATCH_VERSION = 370, + tHomRank = 371, + tHomGen = 372, + tHomCut = 373, + tHomSeq = 374, + tAFFECTDIVIDE = 375, + tAFFECTTIMES = 376, + tAFFECTMINUS = 377, + tAFFECTPLUS = 378, + tOR = 379, + tAND = 380, + tNOTEQUAL = 381, + tEQUAL = 382, + tGREATEROREQUAL = 383, + tLESSOREQUAL = 384, + UNARYPREC = 385, + tMINUSMINUS = 386, + tPLUSPLUS = 387 }; #endif /* Tokens. */ @@ -278,26 +280,28 @@ #define tShow 363 #define tHide 364 #define tGetValue 365 -#define tGMSH_MAJOR_VERSION 366 -#define tGMSH_MINOR_VERSION 367 -#define tGMSH_PATCH_VERSION 368 -#define tHomRank 369 -#define tHomGen 370 -#define tHomCut 371 -#define tHomSeq 372 -#define tAFFECTDIVIDE 373 -#define tAFFECTTIMES 374 -#define tAFFECTMINUS 375 -#define tAFFECTPLUS 376 -#define tOR 377 -#define tAND 378 -#define tNOTEQUAL 379 -#define tEQUAL 380 -#define tGREATEROREQUAL 381 -#define tLESSOREQUAL 382 -#define UNARYPREC 383 -#define tMINUSMINUS 384 -#define tPLUSPLUS 385 +#define tGetEnv 366 +#define tGetString 367 +#define tGMSH_MAJOR_VERSION 368 +#define tGMSH_MINOR_VERSION 369 +#define tGMSH_PATCH_VERSION 370 +#define tHomRank 371 +#define tHomGen 372 +#define tHomCut 373 +#define tHomSeq 374 +#define tAFFECTDIVIDE 375 +#define tAFFECTTIMES 376 +#define tAFFECTMINUS 377 +#define tAFFECTPLUS 378 +#define tOR 379 +#define tAND 380 +#define tNOTEQUAL 381 +#define tEQUAL 382 +#define tGREATEROREQUAL 383 +#define tLESSOREQUAL 384 +#define UNARYPREC 385 +#define tMINUSMINUS 386 +#define tPLUSPLUS 387 @@ -315,7 +319,7 @@ typedef union YYSTYPE List_T *l; } /* Line 1529 of yacc.c. */ -#line 319 "Gmsh.tab.hpp" +#line 323 "Gmsh.tab.hpp" YYSTYPE; # define yystype YYSTYPE /* obsolescent; will be withdrawn */ # define YYSTYPE_IS_DECLARED 1 diff --git a/Parser/Gmsh.y b/Parser/Gmsh.y index 56b65f8c794e23010948ee3270f74979ce6df2e4..f1a7d6e5a60cb01a6b3503c93c363702c122321e 100644 --- a/Parser/Gmsh.y +++ b/Parser/Gmsh.y @@ -114,7 +114,7 @@ fullMatrix<double> ListOfListOfDouble2Matrix(List_T *list); %token tText2D tText3D tInterpolationScheme tTime tCombine %token tBSpline tBezier tNurbs tNurbsOrder tNurbsKnots %token tColor tColorTable tFor tIn tEndFor tIf tEndIf tExit -%token tField tReturn tCall tFunction tShow tHide tGetValue +%token tField tReturn tCall tFunction tShow tHide tGetValue tGetEnv tGetString %token tGMSH_MAJOR_VERSION tGMSH_MINOR_VERSION tGMSH_PATCH_VERSION %token tHomRank tHomGen tHomCut tHomSeq @@ -3720,7 +3720,7 @@ FExpr_Single : } Free($1); Free($6); } - | tGetValue '(' tBIGSTR ',' FExpr ')' + | tGetValue '(' StringExprVar ',' FExpr ')' { $$ = Msg::GetValue($3, $5); Free($3); @@ -4076,6 +4076,22 @@ StringExpr : strcpy($$, ctime(&now)); $$[strlen($$) - 1] = '\0'; } + | tGetEnv '(' StringExprVar ')' + { + const char *env = GetEnvironmentVariable($3); + if(!env) env = ""; + $$ = (char *)Malloc((sizeof(env) + 1) * sizeof(char)); + strcpy($$, env); + Free($3); + } + | tGetString '(' StringExprVar ',' StringExprVar ')' + { + std::string s = Msg::GetString($3, $5); + $$ = (char *)Malloc((s.size() + 1) * sizeof(char)); + strcpy($$, s.c_str()); + Free($3); + Free($5); + } | tStrCat '(' StringExprVar ',' StringExprVar ')' { $$ = (char *)Malloc((strlen($3) + strlen($5) + 1) * sizeof(char)); diff --git a/Parser/Gmsh.yy.cpp b/Parser/Gmsh.yy.cpp index 2481e80059eddcd6bd9a2b9feeb92de374bd1d14..c3a05213f45e925a001e0cd1e266f16167f20dc3 100644 --- a/Parser/Gmsh.yy.cpp +++ b/Parser/Gmsh.yy.cpp @@ -379,8 +379,8 @@ static void yy_fatal_error (yyconst char msg[] ); *yy_cp = '\0'; \ (yy_c_buf_p) = yy_cp; -#define YY_NUM_RULES 151 -#define YY_END_OF_BUFFER 152 +#define YY_NUM_RULES 153 +#define YY_END_OF_BUFFER 154 /* This struct is not used in this scanner, but its presence is necessary. */ struct yy_trans_info @@ -388,79 +388,80 @@ struct yy_trans_info flex_int32_t yy_verify; flex_int32_t yy_nxt; }; -static yyconst flex_int16_t yy_accept[648] = +static yyconst flex_int16_t yy_accept[657] = { 0, - 0, 0, 152, 150, 1, 1, 150, 5, 150, 6, - 150, 150, 150, 150, 150, 145, 21, 2, 150, 16, - 150, 149, 149, 149, 149, 149, 149, 149, 149, 149, - 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, - 149, 149, 149, 150, 28, 24, 19, 25, 17, 26, - 18, 0, 147, 3, 4, 20, 146, 145, 0, 29, - 27, 30, 149, 149, 149, 149, 149, 149, 149, 149, - 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, - 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, - 149, 149, 149, 149, 149, 149, 90, 89, 149, 149, - - 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, - 108, 149, 149, 149, 149, 149, 149, 149, 149, 149, - 149, 149, 149, 149, 149, 149, 135, 136, 149, 149, - 149, 149, 149, 149, 149, 23, 22, 0, 146, 0, - 0, 148, 149, 149, 149, 149, 149, 149, 149, 149, - 149, 149, 149, 149, 149, 149, 149, 149, 149, 49, - 149, 149, 149, 149, 149, 149, 149, 149, 149, 63, - 149, 149, 149, 149, 149, 76, 149, 149, 149, 149, - 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, - 97, 149, 149, 149, 149, 149, 149, 149, 149, 149, - - 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, - 122, 149, 149, 149, 149, 149, 149, 149, 149, 149, - 149, 141, 149, 149, 149, 149, 149, 0, 147, 0, - 0, 146, 31, 149, 149, 149, 149, 35, 37, 149, - 149, 149, 57, 149, 44, 149, 149, 149, 149, 149, - 149, 149, 48, 149, 149, 149, 149, 62, 149, 149, - 149, 149, 71, 149, 72, 149, 149, 75, 149, 149, - 149, 82, 83, 149, 149, 149, 149, 149, 149, 149, - 149, 149, 149, 149, 95, 149, 96, 149, 149, 149, - 149, 149, 149, 149, 149, 149, 149, 149, 149, 118, - - 149, 149, 149, 149, 132, 123, 149, 149, 149, 149, - 121, 149, 149, 149, 149, 149, 149, 137, 140, 149, - 149, 149, 149, 10, 15, 9, 8, 149, 12, 14, - 0, 146, 33, 149, 149, 149, 39, 149, 149, 149, - 149, 149, 149, 149, 52, 149, 149, 149, 149, 149, - 149, 149, 149, 149, 149, 69, 149, 149, 73, 74, - 149, 149, 149, 149, 149, 149, 149, 88, 149, 149, - 93, 149, 149, 149, 98, 149, 149, 149, 104, 105, - 149, 149, 149, 109, 149, 110, 149, 149, 149, 149, - 149, 117, 149, 149, 149, 126, 149, 149, 149, 149, - - 149, 149, 149, 142, 149, 143, 149, 11, 149, 13, - 149, 32, 36, 38, 149, 41, 149, 149, 149, 45, - 149, 149, 149, 149, 149, 149, 149, 149, 59, 61, - 149, 149, 68, 149, 149, 149, 149, 149, 149, 86, - 85, 149, 87, 149, 149, 99, 94, 149, 149, 149, - 101, 149, 149, 149, 114, 149, 113, 149, 119, 116, - 149, 124, 125, 149, 129, 149, 149, 149, 149, 149, - 149, 149, 144, 7, 149, 40, 42, 149, 149, 149, - 149, 149, 47, 51, 149, 149, 149, 149, 65, 149, - 149, 149, 66, 149, 149, 149, 149, 149, 84, 149, - - 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, - 128, 149, 149, 127, 149, 149, 149, 149, 149, 149, - 149, 149, 149, 149, 54, 149, 149, 149, 64, 67, - 149, 77, 149, 149, 149, 78, 149, 149, 100, 102, - 103, 149, 106, 107, 149, 149, 120, 149, 149, 133, - 149, 149, 149, 149, 149, 149, 149, 46, 149, 149, - 149, 149, 70, 149, 149, 149, 149, 91, 149, 149, - 115, 130, 149, 134, 149, 139, 149, 149, 56, 149, - 53, 149, 149, 149, 149, 149, 149, 149, 111, 149, - 149, 149, 149, 43, 149, 55, 149, 60, 149, 149, - - 149, 149, 112, 131, 138, 149, 149, 149, 149, 149, - 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, - 50, 58, 149, 149, 149, 149, 149, 149, 149, 149, - 149, 34, 149, 149, 149, 149, 149, 149, 149, 149, - 79, 80, 81, 149, 149, 92, 0 + 0, 0, 154, 152, 1, 1, 152, 5, 152, 6, + 152, 152, 152, 152, 152, 147, 21, 2, 152, 16, + 152, 151, 151, 151, 151, 151, 151, 151, 151, 151, + 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, + 151, 151, 151, 152, 28, 24, 19, 25, 17, 26, + 18, 0, 149, 3, 4, 20, 148, 147, 0, 29, + 27, 30, 151, 151, 151, 151, 151, 151, 151, 151, + 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, + 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, + 151, 151, 151, 151, 151, 151, 92, 91, 151, 151, + + 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, + 110, 151, 151, 151, 151, 151, 151, 151, 151, 151, + 151, 151, 151, 151, 151, 151, 137, 138, 151, 151, + 151, 151, 151, 151, 151, 23, 22, 0, 148, 0, + 0, 150, 151, 151, 151, 151, 151, 151, 151, 151, + 151, 151, 151, 151, 151, 151, 151, 151, 151, 49, + 151, 151, 151, 151, 151, 151, 151, 151, 151, 63, + 151, 151, 151, 151, 151, 76, 151, 151, 151, 151, + 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, + 99, 151, 151, 151, 151, 151, 151, 151, 151, 151, + + 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, + 124, 151, 151, 151, 151, 151, 151, 151, 151, 151, + 151, 143, 151, 151, 151, 151, 151, 0, 149, 0, + 0, 148, 31, 151, 151, 151, 151, 35, 37, 151, + 151, 151, 57, 151, 44, 151, 151, 151, 151, 151, + 151, 151, 48, 151, 151, 151, 151, 62, 151, 151, + 151, 151, 71, 151, 72, 151, 151, 75, 151, 151, + 151, 151, 151, 84, 85, 151, 151, 151, 151, 151, + 151, 151, 151, 151, 151, 151, 97, 151, 98, 151, + 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, + + 151, 120, 151, 151, 151, 151, 134, 125, 151, 151, + 151, 151, 123, 151, 151, 151, 151, 151, 151, 139, + 142, 151, 151, 151, 151, 10, 15, 9, 8, 151, + 12, 14, 0, 148, 33, 151, 151, 151, 39, 151, + 151, 151, 151, 151, 151, 151, 52, 151, 151, 151, + 151, 151, 151, 151, 151, 151, 151, 69, 151, 151, + 73, 74, 151, 151, 151, 151, 151, 151, 151, 151, + 151, 90, 151, 151, 95, 151, 151, 151, 100, 151, + 151, 151, 106, 107, 151, 151, 151, 111, 151, 112, + 151, 151, 151, 151, 151, 119, 151, 151, 151, 128, + + 151, 151, 151, 151, 151, 151, 151, 144, 151, 145, + 151, 11, 151, 13, 151, 32, 36, 38, 151, 41, + 151, 151, 151, 45, 151, 151, 151, 151, 151, 151, + 151, 151, 59, 61, 151, 151, 68, 151, 151, 151, + 151, 151, 78, 151, 151, 88, 87, 151, 89, 151, + 151, 101, 96, 151, 151, 151, 103, 151, 151, 151, + 116, 151, 115, 151, 121, 118, 151, 126, 127, 151, + 131, 151, 151, 151, 151, 151, 151, 151, 146, 7, + 151, 40, 42, 151, 151, 151, 151, 151, 47, 51, + 151, 151, 151, 151, 65, 151, 151, 151, 66, 151, + + 151, 151, 151, 151, 151, 86, 151, 151, 151, 151, + 151, 151, 151, 151, 151, 151, 151, 130, 151, 151, + 129, 151, 151, 151, 151, 151, 151, 151, 151, 151, + 151, 54, 151, 151, 151, 64, 67, 151, 77, 151, + 151, 151, 151, 80, 151, 151, 102, 104, 105, 151, + 108, 109, 151, 151, 122, 151, 151, 135, 151, 151, + 151, 151, 151, 151, 151, 46, 151, 151, 151, 151, + 70, 151, 151, 151, 79, 151, 93, 151, 151, 117, + 132, 151, 136, 151, 141, 151, 151, 56, 151, 53, + 151, 151, 151, 151, 151, 151, 151, 113, 151, 151, + + 151, 151, 43, 151, 55, 151, 60, 151, 151, 151, + 151, 114, 133, 140, 151, 151, 151, 151, 151, 151, + 151, 151, 151, 151, 151, 151, 151, 151, 151, 50, + 58, 151, 151, 151, 151, 151, 151, 151, 151, 151, + 34, 151, 151, 151, 151, 151, 151, 151, 151, 81, + 82, 83, 151, 151, 94, 0 } ; static yyconst flex_int32_t yy_ec[256] = @@ -507,157 +508,159 @@ static yyconst flex_int32_t yy_meta[73] = 2, 1 } ; -static yyconst flex_int16_t yy_base[649] = +static yyconst flex_int16_t yy_base[658] = { 0, - 0, 0, 769, 770, 770, 770, 747, 770, 761, 770, - 745, 64, 65, 63, 75, 77, 770, 770, 744, 743, - 742, 46, 48, 66, 51, 65, 78, 46, 45, 71, - 0, 703, 90, 80, 695, 697, 92, 106, 109, 145, - 695, 698, 706, 684, 770, 770, 770, 770, 770, 770, - 770, 744, 167, 770, 770, 770, 172, 187, 211, 770, - 770, 770, 0, 694, 698, 703, 696, 703, 688, 677, - 681, 62, 691, 698, 681, 152, 692, 59, 685, 694, - 683, 689, 689, 93, 689, 685, 675, 674, 670, 673, - 690, 665, 679, 111, 667, 685, 0, 661, 665, 654, - - 92, 664, 137, 691, 671, 657, 669, 655, 654, 646, - 0, 35, 136, 660, 655, 113, 648, 655, 651, 651, - 649, 176, 645, 644, 643, 137, 0, 0, 670, 645, - 653, 655, 646, 643, 631, 770, 770, 227, 232, 241, - 247, 252, 634, 650, 190, 637, 636, 637, 638, 633, - 634, 632, 632, 625, 638, 635, 625, 174, 621, 629, - 635, 630, 629, 632, 610, 622, 242, 619, 610, 0, - 611, 609, 615, 611, 620, 0, 620, 638, 623, 615, - 614, 246, 604, 636, 611, 596, 609, 606, 607, 606, - 642, 594, 608, 587, 604, 600, 603, 594, 584, 588, - - 593, 586, 597, 584, 592, 581, 574, 592, 587, 569, - 582, 575, 583, 578, 577, 566, 251, 578, 571, 579, - 600, 572, 578, 565, 564, 556, 233, 264, 288, 297, - 302, 307, 0, 557, 560, 564, 571, 0, 602, 561, - 564, 564, 0, 547, 0, 565, 554, 547, 546, 553, - 235, 557, 0, 541, 546, 539, 538, 0, 541, 541, - 548, 544, 0, 532, 0, 547, 533, 0, 530, 548, - 546, 0, 0, 526, 540, 543, 538, 523, 547, 523, - 521, 521, 518, 525, 0, 568, 0, 212, 523, 515, - 515, 519, 516, 520, 523, 518, 507, 508, 505, 0, - - 511, 505, 502, 516, 0, 0, 500, 501, 148, 504, - 0, 515, 498, 509, 512, 507, 522, 0, 0, 486, - 491, 501, 495, 0, 0, 495, 0, 500, 493, 0, - 312, 317, 504, 484, 488, 487, 0, 486, 481, 488, - 485, 492, 489, 488, 496, 478, 485, 469, 479, 482, - 481, 480, 479, 234, 466, 0, 478, 477, 0, 0, - 471, 300, 468, 459, 464, 463, 459, 0, 482, 455, - 0, 454, 463, 452, 0, 468, 459, 453, 0, 0, - 461, 461, 461, 0, 450, 0, 467, 455, 458, 446, - 453, 0, 449, 451, 450, 0, 435, 434, 447, 440, - - 447, 430, 434, 0, 177, 0, 442, 0, 439, 0, - 436, 0, 0, 475, 438, 0, 429, 430, 421, 0, - 426, 437, 432, 413, 422, 421, 437, 415, 0, 0, - 122, 422, 0, 421, 424, 414, 188, 450, 406, 0, - 0, 415, 0, 433, 418, 0, 0, 417, 408, 395, - 0, 400, 409, 416, 0, 401, 0, 406, 0, 0, - 409, 0, 0, 407, 0, 406, 410, 405, 392, 404, - 398, 405, 0, 0, 386, 0, 0, 397, 409, 397, - 398, 398, 0, 0, 395, 397, 383, 395, 0, 377, - 391, 392, 0, 379, 405, 400, 393, 383, 0, 399, - - 383, 366, 374, 378, 365, 378, 369, 371, 365, 360, - 0, 367, 356, 0, 350, 368, 359, 352, 362, 391, - 354, 350, 361, 354, 0, 345, 348, 343, 0, 0, - 348, 0, 369, 368, 379, 0, 380, 337, 0, 0, - 0, 346, 0, 0, 349, 348, 0, 329, 342, 0, - 339, 340, 343, 356, 332, 333, 335, 0, 338, 337, - 327, 335, 0, 345, 344, 353, 340, 0, 332, 317, - 0, 0, 312, 0, 313, 0, 316, 307, 0, 311, - 0, 310, 316, 322, 325, 324, 323, 337, 0, 316, - 315, 314, 299, 0, 298, 0, 302, 0, 317, 316, - - 315, 321, 0, 0, 0, 302, 301, 302, 327, 326, - 325, 315, 290, 300, 278, 307, 306, 305, 298, 284, - 0, 0, 301, 300, 299, 298, 273, 305, 278, 277, - 268, 0, 251, 247, 237, 242, 181, 129, 120, 115, - 0, 0, 0, 97, 71, 0, 770, 82 + 0, 0, 778, 779, 779, 779, 756, 779, 770, 779, + 754, 64, 65, 63, 75, 77, 779, 779, 753, 752, + 751, 46, 48, 66, 51, 65, 78, 46, 45, 71, + 0, 712, 90, 80, 704, 706, 92, 106, 109, 145, + 704, 707, 715, 693, 779, 779, 779, 779, 779, 779, + 779, 753, 167, 779, 779, 779, 172, 187, 211, 779, + 779, 779, 0, 703, 707, 712, 705, 712, 697, 686, + 690, 62, 700, 707, 690, 152, 701, 59, 694, 703, + 692, 698, 698, 93, 698, 694, 684, 683, 679, 682, + 699, 674, 688, 111, 676, 694, 0, 670, 674, 663, + + 92, 673, 137, 700, 680, 666, 678, 664, 663, 655, + 0, 35, 136, 669, 664, 113, 657, 664, 660, 660, + 658, 176, 654, 653, 652, 137, 0, 0, 679, 654, + 662, 664, 655, 652, 640, 779, 779, 227, 232, 241, + 247, 252, 643, 659, 190, 646, 645, 646, 647, 642, + 643, 641, 641, 634, 647, 644, 634, 174, 630, 638, + 644, 639, 638, 641, 619, 631, 242, 628, 619, 0, + 620, 618, 624, 620, 629, 0, 629, 647, 244, 625, + 624, 249, 614, 646, 621, 606, 619, 616, 617, 616, + 652, 604, 618, 597, 614, 610, 613, 604, 594, 598, + + 603, 596, 607, 594, 602, 591, 584, 602, 597, 579, + 592, 585, 593, 588, 587, 576, 254, 588, 581, 589, + 610, 582, 588, 575, 574, 566, 244, 299, 304, 313, + 318, 323, 0, 567, 570, 574, 581, 0, 612, 571, + 574, 574, 0, 557, 0, 575, 564, 557, 556, 563, + 215, 567, 0, 551, 556, 549, 548, 0, 551, 551, + 558, 554, 0, 542, 0, 557, 543, 0, 540, 558, + 544, 537, 554, 0, 0, 534, 548, 551, 546, 531, + 555, 531, 529, 529, 526, 533, 0, 576, 0, 212, + 531, 523, 523, 527, 524, 528, 531, 526, 515, 516, + + 513, 0, 519, 513, 510, 524, 0, 0, 508, 509, + 148, 512, 0, 523, 506, 517, 520, 515, 530, 0, + 0, 494, 499, 509, 503, 0, 0, 503, 0, 508, + 501, 0, 328, 333, 512, 492, 496, 495, 0, 494, + 489, 496, 493, 500, 497, 496, 504, 486, 493, 477, + 487, 490, 489, 488, 487, 212, 474, 0, 486, 485, + 0, 0, 479, 246, 466, 469, 474, 465, 470, 469, + 465, 0, 488, 461, 0, 460, 469, 458, 0, 474, + 465, 459, 0, 0, 467, 467, 467, 0, 456, 0, + 473, 461, 464, 452, 459, 0, 455, 457, 456, 0, + + 441, 440, 453, 446, 453, 436, 440, 0, 177, 0, + 448, 0, 445, 0, 442, 0, 0, 481, 444, 0, + 435, 436, 427, 0, 432, 443, 438, 419, 428, 427, + 443, 421, 0, 0, 122, 428, 0, 427, 430, 420, + 188, 456, 0, 423, 411, 0, 0, 420, 0, 438, + 423, 0, 0, 422, 413, 400, 0, 405, 414, 421, + 0, 406, 0, 411, 0, 0, 414, 0, 0, 412, + 0, 411, 415, 410, 397, 409, 403, 410, 0, 0, + 391, 0, 0, 402, 414, 402, 403, 403, 0, 0, + 400, 402, 388, 400, 0, 382, 396, 397, 0, 384, + + 410, 405, 398, 380, 387, 0, 403, 387, 370, 378, + 382, 369, 382, 373, 375, 369, 364, 0, 371, 360, + 0, 354, 372, 363, 356, 366, 395, 358, 354, 365, + 358, 0, 349, 352, 347, 0, 0, 352, 0, 373, + 372, 383, 354, 0, 383, 340, 0, 0, 0, 349, + 0, 0, 352, 351, 0, 332, 345, 0, 342, 343, + 346, 359, 335, 336, 338, 0, 341, 340, 330, 338, + 0, 348, 347, 356, 0, 343, 0, 335, 320, 0, + 0, 315, 0, 316, 0, 319, 310, 0, 314, 0, + 313, 319, 325, 328, 327, 326, 340, 0, 319, 318, + + 317, 302, 0, 301, 0, 305, 0, 320, 319, 318, + 324, 0, 0, 0, 305, 304, 305, 330, 329, 328, + 318, 293, 303, 281, 285, 284, 270, 263, 247, 0, + 0, 263, 262, 261, 259, 235, 267, 266, 264, 266, + 0, 250, 249, 245, 250, 181, 129, 120, 115, 0, + 0, 0, 97, 71, 0, 779, 82 } ; -static yyconst flex_int16_t yy_def[649] = +static yyconst flex_int16_t yy_def[658] = { 0, - 647, 1, 647, 647, 647, 647, 647, 647, 647, 647, - 647, 647, 647, 647, 647, 647, 647, 647, 647, 647, - 647, 648, 648, 648, 648, 648, 648, 648, 648, 648, - 648, 648, 648, 648, 648, 648, 648, 648, 648, 648, - 648, 648, 648, 647, 647, 647, 647, 647, 647, 647, - 647, 647, 647, 647, 647, 647, 647, 647, 647, 647, - 647, 647, 648, 648, 648, 648, 648, 648, 648, 648, - 648, 648, 648, 648, 648, 648, 648, 648, 648, 648, - 648, 648, 648, 648, 648, 648, 648, 648, 648, 648, - 648, 648, 648, 648, 648, 648, 648, 648, 648, 648, - - 648, 648, 648, 648, 648, 648, 648, 648, 648, 648, - 648, 648, 648, 648, 648, 648, 648, 648, 648, 648, - 648, 648, 648, 648, 648, 648, 648, 648, 648, 648, - 648, 648, 648, 648, 648, 647, 647, 647, 647, 647, - 647, 647, 648, 648, 648, 648, 648, 648, 648, 648, - 648, 648, 648, 648, 648, 648, 648, 648, 648, 648, - 648, 648, 648, 648, 648, 648, 648, 648, 648, 648, - 648, 648, 648, 648, 648, 648, 648, 648, 648, 648, - 648, 648, 648, 648, 648, 648, 648, 648, 648, 648, - 648, 648, 648, 648, 648, 648, 648, 648, 648, 648, - - 648, 648, 648, 648, 648, 648, 648, 648, 648, 648, - 648, 648, 648, 648, 648, 648, 648, 648, 648, 648, - 648, 648, 648, 648, 648, 648, 648, 647, 647, 647, - 647, 647, 648, 648, 648, 648, 648, 648, 648, 648, - 648, 648, 648, 648, 648, 648, 648, 648, 648, 648, - 648, 648, 648, 648, 648, 648, 648, 648, 648, 648, - 648, 648, 648, 648, 648, 648, 648, 648, 648, 648, - 648, 648, 648, 648, 648, 648, 648, 648, 648, 648, - 648, 648, 648, 648, 648, 648, 648, 648, 648, 648, - 648, 648, 648, 648, 648, 648, 648, 648, 648, 648, - - 648, 648, 648, 648, 648, 648, 648, 648, 648, 648, - 648, 648, 648, 648, 648, 648, 648, 648, 648, 648, - 648, 648, 648, 648, 648, 648, 648, 648, 648, 648, - 647, 647, 648, 648, 648, 648, 648, 648, 648, 648, - 648, 648, 648, 648, 648, 648, 648, 648, 648, 648, - 648, 648, 648, 648, 648, 648, 648, 648, 648, 648, - 648, 648, 648, 648, 648, 648, 648, 648, 648, 648, - 648, 648, 648, 648, 648, 648, 648, 648, 648, 648, - 648, 648, 648, 648, 648, 648, 648, 648, 648, 648, - 648, 648, 648, 648, 648, 648, 648, 648, 648, 648, - - 648, 648, 648, 648, 648, 648, 648, 648, 648, 648, - 648, 648, 648, 648, 648, 648, 648, 648, 648, 648, - 648, 648, 648, 648, 648, 648, 648, 648, 648, 648, - 648, 648, 648, 648, 648, 648, 648, 648, 648, 648, - 648, 648, 648, 648, 648, 648, 648, 648, 648, 648, - 648, 648, 648, 648, 648, 648, 648, 648, 648, 648, - 648, 648, 648, 648, 648, 648, 648, 648, 648, 648, - 648, 648, 648, 648, 648, 648, 648, 648, 648, 648, - 648, 648, 648, 648, 648, 648, 648, 648, 648, 648, - 648, 648, 648, 648, 648, 648, 648, 648, 648, 648, - - 648, 648, 648, 648, 648, 648, 648, 648, 648, 648, - 648, 648, 648, 648, 648, 648, 648, 648, 648, 648, - 648, 648, 648, 648, 648, 648, 648, 648, 648, 648, - 648, 648, 648, 648, 648, 648, 648, 648, 648, 648, - 648, 648, 648, 648, 648, 648, 648, 648, 648, 648, - 648, 648, 648, 648, 648, 648, 648, 648, 648, 648, - 648, 648, 648, 648, 648, 648, 648, 648, 648, 648, - 648, 648, 648, 648, 648, 648, 648, 648, 648, 648, - 648, 648, 648, 648, 648, 648, 648, 648, 648, 648, - 648, 648, 648, 648, 648, 648, 648, 648, 648, 648, - - 648, 648, 648, 648, 648, 648, 648, 648, 648, 648, - 648, 648, 648, 648, 648, 648, 648, 648, 648, 648, - 648, 648, 648, 648, 648, 648, 648, 648, 648, 648, - 648, 648, 648, 648, 648, 648, 648, 648, 648, 648, - 648, 648, 648, 648, 648, 648, 0, 647 + 656, 1, 656, 656, 656, 656, 656, 656, 656, 656, + 656, 656, 656, 656, 656, 656, 656, 656, 656, 656, + 656, 657, 657, 657, 657, 657, 657, 657, 657, 657, + 657, 657, 657, 657, 657, 657, 657, 657, 657, 657, + 657, 657, 657, 656, 656, 656, 656, 656, 656, 656, + 656, 656, 656, 656, 656, 656, 656, 656, 656, 656, + 656, 656, 657, 657, 657, 657, 657, 657, 657, 657, + 657, 657, 657, 657, 657, 657, 657, 657, 657, 657, + 657, 657, 657, 657, 657, 657, 657, 657, 657, 657, + 657, 657, 657, 657, 657, 657, 657, 657, 657, 657, + + 657, 657, 657, 657, 657, 657, 657, 657, 657, 657, + 657, 657, 657, 657, 657, 657, 657, 657, 657, 657, + 657, 657, 657, 657, 657, 657, 657, 657, 657, 657, + 657, 657, 657, 657, 657, 656, 656, 656, 656, 656, + 656, 656, 657, 657, 657, 657, 657, 657, 657, 657, + 657, 657, 657, 657, 657, 657, 657, 657, 657, 657, + 657, 657, 657, 657, 657, 657, 657, 657, 657, 657, + 657, 657, 657, 657, 657, 657, 657, 657, 657, 657, + 657, 657, 657, 657, 657, 657, 657, 657, 657, 657, + 657, 657, 657, 657, 657, 657, 657, 657, 657, 657, + + 657, 657, 657, 657, 657, 657, 657, 657, 657, 657, + 657, 657, 657, 657, 657, 657, 657, 657, 657, 657, + 657, 657, 657, 657, 657, 657, 657, 656, 656, 656, + 656, 656, 657, 657, 657, 657, 657, 657, 657, 657, + 657, 657, 657, 657, 657, 657, 657, 657, 657, 657, + 657, 657, 657, 657, 657, 657, 657, 657, 657, 657, + 657, 657, 657, 657, 657, 657, 657, 657, 657, 657, + 657, 657, 657, 657, 657, 657, 657, 657, 657, 657, + 657, 657, 657, 657, 657, 657, 657, 657, 657, 657, + 657, 657, 657, 657, 657, 657, 657, 657, 657, 657, + + 657, 657, 657, 657, 657, 657, 657, 657, 657, 657, + 657, 657, 657, 657, 657, 657, 657, 657, 657, 657, + 657, 657, 657, 657, 657, 657, 657, 657, 657, 657, + 657, 657, 656, 656, 657, 657, 657, 657, 657, 657, + 657, 657, 657, 657, 657, 657, 657, 657, 657, 657, + 657, 657, 657, 657, 657, 657, 657, 657, 657, 657, + 657, 657, 657, 657, 657, 657, 657, 657, 657, 657, + 657, 657, 657, 657, 657, 657, 657, 657, 657, 657, + 657, 657, 657, 657, 657, 657, 657, 657, 657, 657, + 657, 657, 657, 657, 657, 657, 657, 657, 657, 657, + + 657, 657, 657, 657, 657, 657, 657, 657, 657, 657, + 657, 657, 657, 657, 657, 657, 657, 657, 657, 657, + 657, 657, 657, 657, 657, 657, 657, 657, 657, 657, + 657, 657, 657, 657, 657, 657, 657, 657, 657, 657, + 657, 657, 657, 657, 657, 657, 657, 657, 657, 657, + 657, 657, 657, 657, 657, 657, 657, 657, 657, 657, + 657, 657, 657, 657, 657, 657, 657, 657, 657, 657, + 657, 657, 657, 657, 657, 657, 657, 657, 657, 657, + 657, 657, 657, 657, 657, 657, 657, 657, 657, 657, + 657, 657, 657, 657, 657, 657, 657, 657, 657, 657, + + 657, 657, 657, 657, 657, 657, 657, 657, 657, 657, + 657, 657, 657, 657, 657, 657, 657, 657, 657, 657, + 657, 657, 657, 657, 657, 657, 657, 657, 657, 657, + 657, 657, 657, 657, 657, 657, 657, 657, 657, 657, + 657, 657, 657, 657, 657, 657, 657, 657, 657, 657, + 657, 657, 657, 657, 657, 657, 657, 657, 657, 657, + 657, 657, 657, 657, 657, 657, 657, 657, 657, 657, + 657, 657, 657, 657, 657, 657, 657, 657, 657, 657, + 657, 657, 657, 657, 657, 657, 657, 657, 657, 657, + 657, 657, 657, 657, 657, 657, 657, 657, 657, 657, + + 657, 657, 657, 657, 657, 657, 657, 657, 657, 657, + 657, 657, 657, 657, 657, 657, 657, 657, 657, 657, + 657, 657, 657, 657, 657, 657, 657, 657, 657, 657, + 657, 657, 657, 657, 657, 657, 657, 657, 657, 657, + 657, 657, 657, 657, 657, 657, 657, 657, 657, 657, + 657, 657, 657, 657, 657, 0, 656 } ; -static yyconst flex_int16_t yy_nxt[843] = +static yyconst flex_int16_t yy_nxt[852] = { 0, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 16, 16, 16, 16, 17, 18, 19, @@ -668,93 +671,94 @@ static yyconst flex_int16_t yy_nxt[843] = 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 44, 48, 52, 50, 53, 53, 53, 53, 53, 91, 200, 54, 63, 49, 51, 55, 57, 69, 58, - 58, 58, 58, 58, 64, 56, 92, 646, 70, 93, + 58, 58, 58, 58, 64, 56, 92, 655, 70, 93, 201, 78, 65, 59, 94, 79, 96, 71, 66, 67, 68, 162, 72, 80, 95, 163, 73, 104, 151, 74, 75, 81, 97, 82, 85, 76, 152, 59, 77, 98, - 83, 645, 86, 84, 87, 88, 100, 89, 108, 105, - 101, 644, 109, 90, 102, 110, 111, 169, 112, 103, - 188, 113, 115, 170, 114, 643, 116, 171, 189, 127, - 128, 206, 119, 120, 642, 117, 121, 181, 182, 122, - 123, 118, 489, 124, 125, 129, 490, 207, 126, 53, + 83, 654, 86, 84, 87, 88, 100, 89, 108, 105, + 101, 653, 109, 90, 102, 110, 111, 169, 112, 103, + 188, 113, 115, 170, 114, 652, 116, 171, 189, 127, + 128, 206, 119, 120, 651, 117, 121, 181, 182, 122, + 123, 118, 495, 124, 125, 129, 496, 207, 126, 53, 53, 53, 53, 53, 139, 139, 139, 139, 139, 191, 202, 130, 203, 138, 219, 220, 192, 57, 140, 58, - 58, 58, 58, 58, 131, 156, 395, 132, 157, 158, - 495, 159, 396, 59, 235, 160, 641, 138, 496, 141, - 141, 250, 140, 142, 142, 142, 142, 142, 471, 213, - 236, 237, 214, 472, 251, 228, 228, 59, 215, 229, + 58, 58, 58, 58, 131, 156, 399, 132, 157, 158, + 501, 159, 400, 59, 235, 160, 650, 138, 502, 141, + 141, 250, 140, 142, 142, 142, 142, 142, 477, 213, + 236, 237, 214, 478, 251, 228, 228, 59, 215, 229, 229, 229, 229, 229, 139, 139, 139, 139, 139, 231, - 231, 376, 377, 232, 232, 232, 232, 232, 230, 142, + 231, 380, 381, 232, 232, 232, 232, 232, 230, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 260, - 274, 640, 261, 639, 275, 312, 229, 229, 229, 229, - 229, 324, 230, 638, 325, 276, 277, 637, 313, 326, - 314, 347, 636, 327, 348, 328, 329, 431, 432, 330, - - 229, 229, 229, 229, 229, 331, 331, 635, 634, 332, - 332, 332, 332, 332, 232, 232, 232, 232, 232, 232, - 232, 232, 232, 232, 332, 332, 332, 332, 332, 332, - 332, 332, 332, 332, 437, 633, 632, 438, 631, 630, - 629, 628, 627, 626, 625, 624, 623, 622, 621, 620, - 619, 618, 617, 616, 615, 614, 613, 612, 611, 610, - 609, 608, 607, 606, 605, 604, 603, 602, 601, 600, - 599, 598, 597, 596, 595, 594, 593, 592, 591, 590, - 589, 588, 587, 586, 585, 584, 583, 582, 581, 580, - 579, 578, 577, 576, 575, 574, 573, 572, 571, 570, - - 569, 568, 567, 566, 565, 564, 563, 562, 561, 560, - 559, 558, 557, 556, 555, 554, 553, 552, 551, 550, - 549, 548, 547, 546, 545, 544, 543, 542, 541, 540, - 539, 538, 537, 536, 535, 534, 533, 532, 531, 530, - 529, 528, 527, 526, 525, 524, 523, 522, 521, 520, - 519, 518, 517, 516, 515, 514, 513, 512, 511, 510, - 509, 508, 507, 506, 505, 504, 503, 502, 501, 500, - 499, 498, 497, 494, 493, 492, 491, 488, 487, 486, - 485, 484, 483, 482, 481, 480, 479, 478, 477, 476, - 475, 474, 473, 470, 469, 468, 467, 466, 465, 464, - - 463, 462, 461, 460, 459, 458, 457, 456, 455, 454, - 453, 452, 451, 450, 449, 448, 447, 446, 445, 444, - 443, 442, 441, 440, 439, 436, 435, 434, 433, 430, - 429, 428, 427, 426, 425, 424, 423, 422, 421, 420, - 419, 418, 417, 416, 415, 414, 413, 412, 411, 410, - 409, 408, 407, 406, 405, 404, 403, 402, 401, 400, - 399, 398, 397, 394, 393, 392, 391, 390, 389, 388, - 387, 386, 385, 384, 383, 382, 381, 380, 379, 378, - 375, 374, 373, 372, 371, 370, 369, 368, 367, 366, - 365, 364, 363, 362, 361, 360, 359, 358, 357, 356, - - 355, 354, 353, 352, 351, 350, 349, 346, 345, 344, - 343, 342, 341, 340, 339, 338, 337, 336, 335, 334, - 333, 323, 322, 321, 320, 319, 318, 317, 316, 315, - 311, 310, 309, 308, 307, 306, 305, 304, 303, 302, - 301, 300, 299, 298, 297, 296, 295, 294, 293, 292, - 291, 290, 289, 288, 287, 286, 285, 284, 283, 282, - 281, 280, 279, 278, 273, 272, 271, 270, 269, 268, - 267, 266, 265, 264, 263, 262, 259, 258, 257, 256, - 255, 254, 253, 252, 249, 248, 247, 246, 245, 244, - 243, 242, 241, 240, 239, 238, 234, 233, 227, 226, - - 225, 224, 223, 222, 221, 218, 217, 216, 212, 211, - 210, 209, 208, 205, 204, 199, 198, 197, 196, 195, - 194, 193, 190, 187, 186, 185, 184, 183, 180, 179, - 178, 177, 176, 175, 174, 173, 172, 168, 167, 166, - 165, 164, 161, 155, 154, 153, 150, 149, 148, 147, - 146, 145, 144, 143, 137, 136, 135, 134, 133, 107, - 106, 99, 62, 61, 60, 47, 46, 45, 647, 3, - 647, 647, 647, 647, 647, 647, 647, 647, 647, 647, - 647, 647, 647, 647, 647, 647, 647, 647, 647, 647, - 647, 647, 647, 647, 647, 647, 647, 647, 647, 647, - - 647, 647, 647, 647, 647, 647, 647, 647, 647, 647, - 647, 647, 647, 647, 647, 647, 647, 647, 647, 647, - 647, 647, 647, 647, 647, 647, 647, 647, 647, 647, - 647, 647, 647, 647, 647, 647, 647, 647, 647, 647, - 647, 647 + 271, 349, 261, 276, 350, 435, 436, 277, 314, 649, + 441, 648, 230, 442, 272, 647, 646, 273, 278, 279, + 645, 315, 326, 316, 644, 327, 643, 642, 641, 640, + + 328, 639, 638, 637, 329, 636, 330, 331, 635, 634, + 332, 229, 229, 229, 229, 229, 229, 229, 229, 229, + 229, 333, 333, 633, 632, 334, 334, 334, 334, 334, + 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, + 334, 334, 334, 334, 334, 334, 334, 334, 334, 334, + 631, 630, 629, 628, 627, 626, 625, 624, 623, 622, + 621, 620, 619, 618, 617, 616, 615, 614, 613, 612, + 611, 610, 609, 608, 607, 606, 605, 604, 603, 602, + 601, 600, 599, 598, 597, 596, 595, 594, 593, 592, + 591, 590, 589, 588, 587, 586, 585, 584, 583, 582, + + 581, 580, 579, 578, 577, 576, 575, 574, 573, 572, + 571, 570, 569, 568, 567, 566, 565, 564, 563, 562, + 561, 560, 559, 558, 557, 556, 555, 554, 553, 552, + 551, 550, 549, 548, 547, 546, 545, 544, 543, 542, + 541, 540, 539, 538, 537, 536, 535, 534, 533, 532, + 531, 530, 529, 528, 527, 526, 525, 524, 523, 522, + 521, 520, 519, 518, 517, 516, 515, 514, 513, 512, + 511, 510, 509, 508, 507, 506, 505, 504, 503, 500, + 499, 498, 497, 494, 493, 492, 491, 490, 489, 488, + 487, 486, 485, 484, 483, 482, 481, 480, 479, 476, + + 475, 474, 473, 472, 471, 470, 469, 468, 467, 466, + 465, 464, 463, 462, 461, 460, 459, 458, 457, 456, + 455, 454, 453, 452, 451, 450, 449, 448, 447, 446, + 445, 444, 443, 440, 439, 438, 437, 434, 433, 432, + 431, 430, 429, 428, 427, 426, 425, 424, 423, 422, + 421, 420, 419, 418, 417, 416, 415, 414, 413, 412, + 411, 410, 409, 408, 407, 406, 405, 404, 403, 402, + 401, 398, 397, 396, 395, 394, 393, 392, 391, 390, + 389, 388, 387, 386, 385, 384, 383, 382, 379, 378, + 377, 376, 375, 374, 373, 372, 371, 370, 369, 368, + + 367, 366, 365, 364, 363, 362, 361, 360, 359, 358, + 357, 356, 355, 354, 353, 352, 351, 348, 347, 346, + 345, 344, 343, 342, 341, 340, 339, 338, 337, 336, + 335, 325, 324, 323, 322, 321, 320, 319, 318, 317, + 313, 312, 311, 310, 309, 308, 307, 306, 305, 304, + 303, 302, 301, 300, 299, 298, 297, 296, 295, 294, + 293, 292, 291, 290, 289, 288, 287, 286, 285, 284, + 283, 282, 281, 280, 275, 274, 270, 269, 268, 267, + 266, 265, 264, 263, 262, 259, 258, 257, 256, 255, + 254, 253, 252, 249, 248, 247, 246, 245, 244, 243, + + 242, 241, 240, 239, 238, 234, 233, 227, 226, 225, + 224, 223, 222, 221, 218, 217, 216, 212, 211, 210, + 209, 208, 205, 204, 199, 198, 197, 196, 195, 194, + 193, 190, 187, 186, 185, 184, 183, 180, 179, 178, + 177, 176, 175, 174, 173, 172, 168, 167, 166, 165, + 164, 161, 155, 154, 153, 150, 149, 148, 147, 146, + 145, 144, 143, 137, 136, 135, 134, 133, 107, 106, + 99, 62, 61, 60, 47, 46, 45, 656, 3, 656, + 656, 656, 656, 656, 656, 656, 656, 656, 656, 656, + 656, 656, 656, 656, 656, 656, 656, 656, 656, 656, + + 656, 656, 656, 656, 656, 656, 656, 656, 656, 656, + 656, 656, 656, 656, 656, 656, 656, 656, 656, 656, + 656, 656, 656, 656, 656, 656, 656, 656, 656, 656, + 656, 656, 656, 656, 656, 656, 656, 656, 656, 656, + 656, 656, 656, 656, 656, 656, 656, 656, 656, 656, + 656 } ; -static yyconst flex_int16_t yy_chk[843] = +static yyconst flex_int16_t yy_chk[852] = { 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, @@ -764,91 +768,92 @@ static yyconst flex_int16_t yy_chk[843] = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 12, 14, 13, 14, 14, 14, 14, 14, - 28, 112, 15, 648, 12, 13, 15, 16, 23, 16, - 16, 16, 16, 16, 22, 15, 28, 645, 23, 29, + 28, 112, 15, 657, 12, 13, 15, 16, 23, 16, + 16, 16, 16, 16, 22, 15, 28, 654, 23, 29, 112, 25, 22, 16, 29, 25, 30, 23, 22, 22, 22, 78, 24, 25, 29, 78, 24, 34, 72, 24, 24, 26, 30, 26, 27, 24, 72, 16, 24, 30, - 26, 644, 27, 26, 27, 27, 33, 27, 37, 34, - 33, 640, 37, 27, 33, 37, 37, 84, 37, 33, - 101, 37, 38, 84, 37, 639, 38, 84, 101, 40, - 40, 116, 39, 39, 638, 38, 39, 94, 94, 39, - 39, 38, 431, 39, 39, 40, 431, 116, 39, 53, + 26, 653, 27, 26, 27, 27, 33, 27, 37, 34, + 33, 649, 37, 27, 33, 37, 37, 84, 37, 33, + 101, 37, 38, 84, 37, 648, 38, 84, 101, 40, + 40, 116, 39, 39, 647, 38, 39, 94, 94, 39, + 39, 38, 435, 39, 39, 40, 435, 116, 39, 53, 53, 53, 53, 53, 57, 57, 57, 57, 57, 103, 113, 40, 113, 53, 126, 126, 103, 58, 57, 58, - 58, 58, 58, 58, 40, 76, 309, 40, 76, 76, - 437, 76, 309, 58, 145, 76, 637, 53, 437, 59, - 59, 158, 57, 59, 59, 59, 59, 59, 405, 122, - 145, 145, 122, 405, 158, 138, 138, 58, 122, 138, + 58, 58, 58, 58, 40, 76, 311, 40, 76, 76, + 441, 76, 311, 58, 145, 76, 646, 53, 441, 59, + 59, 158, 57, 59, 59, 59, 59, 59, 409, 122, + 145, 145, 122, 409, 158, 138, 138, 58, 122, 138, 138, 138, 138, 138, 139, 139, 139, 139, 139, 140, - 140, 288, 288, 140, 140, 140, 140, 140, 139, 141, + 140, 290, 290, 140, 140, 140, 140, 140, 139, 141, 141, 141, 141, 141, 142, 142, 142, 142, 142, 167, - 182, 636, 167, 635, 182, 217, 228, 228, 228, 228, - 228, 227, 139, 634, 227, 182, 182, 633, 217, 227, - 217, 251, 631, 227, 251, 227, 227, 354, 354, 227, - - 229, 229, 229, 229, 229, 230, 230, 630, 629, 230, - 230, 230, 230, 230, 231, 231, 231, 231, 231, 232, - 232, 232, 232, 232, 331, 331, 331, 331, 331, 332, - 332, 332, 332, 332, 362, 628, 627, 362, 626, 625, - 624, 623, 620, 619, 618, 617, 616, 615, 614, 613, - 612, 611, 610, 609, 608, 607, 606, 602, 601, 600, - 599, 597, 595, 593, 592, 591, 590, 588, 587, 586, - 585, 584, 583, 582, 580, 578, 577, 575, 573, 570, - 569, 567, 566, 565, 564, 562, 561, 560, 559, 557, - 556, 555, 554, 553, 552, 551, 549, 548, 546, 545, - - 542, 538, 537, 535, 534, 533, 531, 528, 527, 526, - 524, 523, 522, 521, 520, 519, 518, 517, 516, 515, - 513, 512, 510, 509, 508, 507, 506, 505, 504, 503, - 502, 501, 500, 498, 497, 496, 495, 494, 492, 491, - 490, 488, 487, 486, 485, 482, 481, 480, 479, 478, - 475, 472, 471, 470, 469, 468, 467, 466, 464, 461, - 458, 456, 454, 453, 452, 450, 449, 448, 445, 444, - 442, 439, 438, 436, 435, 434, 432, 428, 427, 426, - 425, 424, 423, 422, 421, 419, 418, 417, 415, 414, - 411, 409, 407, 403, 402, 401, 400, 399, 398, 397, - - 395, 394, 393, 391, 390, 389, 388, 387, 385, 383, - 382, 381, 378, 377, 376, 374, 373, 372, 370, 369, - 367, 366, 365, 364, 363, 361, 358, 357, 355, 353, + 179, 251, 167, 182, 251, 356, 356, 182, 217, 645, + 364, 644, 139, 364, 179, 643, 642, 179, 182, 182, + 640, 217, 227, 217, 639, 227, 638, 637, 636, 635, + + 227, 634, 633, 632, 227, 629, 227, 227, 628, 627, + 227, 228, 228, 228, 228, 228, 229, 229, 229, 229, + 229, 230, 230, 626, 625, 230, 230, 230, 230, 230, + 231, 231, 231, 231, 231, 232, 232, 232, 232, 232, + 333, 333, 333, 333, 333, 334, 334, 334, 334, 334, + 624, 623, 622, 621, 620, 619, 618, 617, 616, 615, + 611, 610, 609, 608, 606, 604, 602, 601, 600, 599, + 597, 596, 595, 594, 593, 592, 591, 589, 587, 586, + 584, 582, 579, 578, 576, 574, 573, 572, 570, 569, + 568, 567, 565, 564, 563, 562, 561, 560, 559, 557, + + 556, 554, 553, 550, 546, 545, 543, 542, 541, 540, + 538, 535, 534, 533, 531, 530, 529, 528, 527, 526, + 525, 524, 523, 522, 520, 519, 517, 516, 515, 514, + 513, 512, 511, 510, 509, 508, 507, 505, 504, 503, + 502, 501, 500, 498, 497, 496, 494, 493, 492, 491, + 488, 487, 486, 485, 484, 481, 478, 477, 476, 475, + 474, 473, 472, 470, 467, 464, 462, 460, 459, 458, + 456, 455, 454, 451, 450, 448, 445, 444, 442, 440, + 439, 438, 436, 432, 431, 430, 429, 428, 427, 426, + 425, 423, 422, 421, 419, 418, 415, 413, 411, 407, + + 406, 405, 404, 403, 402, 401, 399, 398, 397, 395, + 394, 393, 392, 391, 389, 387, 386, 385, 382, 381, + 380, 378, 377, 376, 374, 373, 371, 370, 369, 368, + 367, 366, 365, 363, 360, 359, 357, 355, 354, 353, 352, 351, 350, 349, 348, 347, 346, 345, 344, 343, - 342, 341, 340, 339, 338, 336, 335, 334, 333, 329, - 328, 326, 323, 322, 321, 320, 317, 316, 315, 314, - 313, 312, 310, 308, 307, 304, 303, 302, 301, 299, - 298, 297, 296, 295, 294, 293, 292, 291, 290, 289, - 286, 284, 283, 282, 281, 280, 279, 278, 277, 276, - 275, 274, 271, 270, 269, 267, 266, 264, 262, 261, + 342, 341, 340, 338, 337, 336, 335, 331, 330, 328, + 325, 324, 323, 322, 319, 318, 317, 316, 315, 314, + 312, 310, 309, 306, 305, 304, 303, 301, 300, 299, + 298, 297, 296, 295, 294, 293, 292, 291, 288, 286, + 285, 284, 283, 282, 281, 280, 279, 278, 277, 276, + 273, 272, 271, 270, 269, 267, 266, 264, 262, 261, 260, 259, 257, 256, 255, 254, 252, 250, 249, 248, 247, 246, 244, 242, 241, 240, 239, 237, 236, 235, 234, 226, 225, 224, 223, 222, 221, 220, 219, 218, 216, 215, 214, 213, 212, 211, 210, 209, 208, 207, 206, 205, 204, 203, 202, 201, 200, 199, 198, 197, 196, 195, 194, 193, 192, 191, 190, 189, 188, 187, - 186, 185, 184, 183, 181, 180, 179, 178, 177, 175, - 174, 173, 172, 171, 169, 168, 166, 165, 164, 163, - 162, 161, 160, 159, 157, 156, 155, 154, 153, 152, - 151, 150, 149, 148, 147, 146, 144, 143, 135, 134, - - 133, 132, 131, 130, 129, 125, 124, 123, 121, 120, - 119, 118, 117, 115, 114, 110, 109, 108, 107, 106, - 105, 104, 102, 100, 99, 98, 96, 95, 93, 92, - 91, 90, 89, 88, 87, 86, 85, 83, 82, 81, - 80, 79, 77, 75, 74, 73, 71, 70, 69, 68, - 67, 66, 65, 64, 52, 44, 43, 42, 41, 36, - 35, 32, 21, 20, 19, 11, 9, 7, 3, 647, - 647, 647, 647, 647, 647, 647, 647, 647, 647, 647, - 647, 647, 647, 647, 647, 647, 647, 647, 647, 647, - 647, 647, 647, 647, 647, 647, 647, 647, 647, 647, - - 647, 647, 647, 647, 647, 647, 647, 647, 647, 647, - 647, 647, 647, 647, 647, 647, 647, 647, 647, 647, - 647, 647, 647, 647, 647, 647, 647, 647, 647, 647, - 647, 647, 647, 647, 647, 647, 647, 647, 647, 647, - 647, 647 + 186, 185, 184, 183, 181, 180, 178, 177, 175, 174, + 173, 172, 171, 169, 168, 166, 165, 164, 163, 162, + 161, 160, 159, 157, 156, 155, 154, 153, 152, 151, + + 150, 149, 148, 147, 146, 144, 143, 135, 134, 133, + 132, 131, 130, 129, 125, 124, 123, 121, 120, 119, + 118, 117, 115, 114, 110, 109, 108, 107, 106, 105, + 104, 102, 100, 99, 98, 96, 95, 93, 92, 91, + 90, 89, 88, 87, 86, 85, 83, 82, 81, 80, + 79, 77, 75, 74, 73, 71, 70, 69, 68, 67, + 66, 65, 64, 52, 44, 43, 42, 41, 36, 35, + 32, 21, 20, 19, 11, 9, 7, 3, 656, 656, + 656, 656, 656, 656, 656, 656, 656, 656, 656, 656, + 656, 656, 656, 656, 656, 656, 656, 656, 656, 656, + + 656, 656, 656, 656, 656, 656, 656, 656, 656, 656, + 656, 656, 656, 656, 656, 656, 656, 656, 656, 656, + 656, 656, 656, 656, 656, 656, 656, 656, 656, 656, + 656, 656, 656, 656, 656, 656, 656, 656, 656, 656, + 656, 656, 656, 656, 656, 656, 656, 656, 656, 656, + 656 } ; static yy_state_type yy_last_accepting_state; @@ -905,7 +910,7 @@ void skipline(void); #define YY_NO_UNISTD_H #endif -#line 909 "Gmsh.yy.cpp" +#line 914 "Gmsh.yy.cpp" #define INITIAL 0 @@ -1090,7 +1095,7 @@ YY_DECL #line 49 "Gmsh.l" -#line 1094 "Gmsh.yy.cpp" +#line 1099 "Gmsh.yy.cpp" if ( !(yy_init) ) { @@ -1143,13 +1148,13 @@ yy_match: while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state ) { yy_current_state = (int) yy_def[yy_current_state]; - if ( yy_current_state >= 648 ) + if ( yy_current_state >= 657 ) yy_c = yy_meta[(unsigned int) yy_c]; } yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c]; ++yy_cp; } - while ( yy_base[yy_current_state] != 770 ); + while ( yy_base[yy_current_state] != 779 ); yy_find_action: yy_act = yy_accept[yy_current_state]; @@ -1562,365 +1567,375 @@ return tFunction; case 78: YY_RULE_SETUP #line 135 "Gmsh.l" -return tGetValue; +return tGetEnv; YY_BREAK case 79: YY_RULE_SETUP #line 136 "Gmsh.l" -return tGMSH_MAJOR_VERSION; +return tGetString; YY_BREAK case 80: YY_RULE_SETUP #line 137 "Gmsh.l" -return tGMSH_MINOR_VERSION; +return tGetValue; YY_BREAK case 81: YY_RULE_SETUP #line 138 "Gmsh.l" -return tGMSH_PATCH_VERSION; +return tGMSH_MAJOR_VERSION; YY_BREAK case 82: YY_RULE_SETUP -#line 140 "Gmsh.l" -return tHide; +#line 139 "Gmsh.l" +return tGMSH_MINOR_VERSION; YY_BREAK case 83: YY_RULE_SETUP -#line 141 "Gmsh.l" -return tHole; +#line 140 "Gmsh.l" +return tGMSH_PATCH_VERSION; YY_BREAK case 84: YY_RULE_SETUP #line 142 "Gmsh.l" -return tHomRank; +return tHide; YY_BREAK case 85: YY_RULE_SETUP #line 143 "Gmsh.l" -return tHomGen; +return tHole; YY_BREAK case 86: YY_RULE_SETUP #line 144 "Gmsh.l" -return tHomCut; +return tHomRank; YY_BREAK case 87: YY_RULE_SETUP #line 145 "Gmsh.l" -return tHomSeq; +return tHomGen; YY_BREAK case 88: YY_RULE_SETUP #line 146 "Gmsh.l" -return tHypot; +return tHomCut; YY_BREAK case 89: YY_RULE_SETUP -#line 148 "Gmsh.l" -return tIn; +#line 147 "Gmsh.l" +return tHomSeq; YY_BREAK case 90: YY_RULE_SETUP -#line 149 "Gmsh.l" -return tIf; +#line 148 "Gmsh.l" +return tHypot; YY_BREAK case 91: YY_RULE_SETUP #line 150 "Gmsh.l" -return tIntersect; +return tIn; YY_BREAK case 92: YY_RULE_SETUP #line 151 "Gmsh.l" -return tInterpolationScheme; +return tIf; YY_BREAK case 93: YY_RULE_SETUP -#line 153 "Gmsh.l" -return tNurbsKnots; +#line 152 "Gmsh.l" +return tIntersect; YY_BREAK case 94: YY_RULE_SETUP -#line 155 "Gmsh.l" -return tLength; +#line 153 "Gmsh.l" +return tInterpolationScheme; YY_BREAK case 95: YY_RULE_SETUP -#line 156 "Gmsh.l" -return tLine; +#line 155 "Gmsh.l" +return tNurbsKnots; YY_BREAK case 96: YY_RULE_SETUP #line 157 "Gmsh.l" -return tLoop; +return tLength; YY_BREAK case 97: YY_RULE_SETUP #line 158 "Gmsh.l" -return tLog; +return tLine; YY_BREAK case 98: YY_RULE_SETUP #line 159 "Gmsh.l" -return tLog10; +return tLoop; YY_BREAK case 99: YY_RULE_SETUP #line 160 "Gmsh.l" -return tLayers; +return tLog; YY_BREAK case 100: YY_RULE_SETUP #line 161 "Gmsh.l" -return tLevelset; +return tLog10; YY_BREAK case 101: YY_RULE_SETUP -#line 163 "Gmsh.l" -return tModulo; +#line 162 "Gmsh.l" +return tLayers; YY_BREAK case 102: YY_RULE_SETUP -#line 164 "Gmsh.l" -return tMPI_Rank; +#line 163 "Gmsh.l" +return tLevelset; YY_BREAK case 103: YY_RULE_SETUP #line 165 "Gmsh.l" -return tMPI_Size; +return tModulo; YY_BREAK case 104: YY_RULE_SETUP -#line 167 "Gmsh.l" -return tNurbs; +#line 166 "Gmsh.l" +return tMPI_Rank; YY_BREAK case 105: YY_RULE_SETUP -#line 169 "Gmsh.l" -return tNurbsOrder; +#line 167 "Gmsh.l" +return tMPI_Size; YY_BREAK case 106: YY_RULE_SETUP -#line 171 "Gmsh.l" -return tPeriodic; +#line 169 "Gmsh.l" +return tNurbs; YY_BREAK case 107: YY_RULE_SETUP -#line 172 "Gmsh.l" -return tPhysical; +#line 171 "Gmsh.l" +return tNurbsOrder; YY_BREAK case 108: YY_RULE_SETUP #line 173 "Gmsh.l" -return tPi; +return tPeriodic; YY_BREAK case 109: YY_RULE_SETUP #line 174 "Gmsh.l" -return tPlane; +return tPhysical; YY_BREAK case 110: YY_RULE_SETUP #line 175 "Gmsh.l" -return tPoint; +return tPi; YY_BREAK case 111: YY_RULE_SETUP #line 176 "Gmsh.l" -return tParametric; +return tPlane; YY_BREAK case 112: YY_RULE_SETUP #line 177 "Gmsh.l" -return tPolarSphere; +return tPoint; YY_BREAK case 113: YY_RULE_SETUP #line 178 "Gmsh.l" -return tPrintf; +return tParametric; YY_BREAK case 114: YY_RULE_SETUP #line 179 "Gmsh.l" -return tPlugin; +return tPolarSphere; YY_BREAK case 115: YY_RULE_SETUP -#line 181 "Gmsh.l" -return tRecombine; +#line 180 "Gmsh.l" +return tPrintf; YY_BREAK case 116: YY_RULE_SETUP -#line 182 "Gmsh.l" -return tRotate; +#line 181 "Gmsh.l" +return tPlugin; YY_BREAK case 117: YY_RULE_SETUP #line 183 "Gmsh.l" -return tRuled; +return tRecombine; YY_BREAK case 118: YY_RULE_SETUP #line 184 "Gmsh.l" -return tRand; +return tRotate; YY_BREAK case 119: YY_RULE_SETUP #line 185 "Gmsh.l" -return tReturn; +return tRuled; YY_BREAK case 120: YY_RULE_SETUP -#line 187 "Gmsh.l" -return tSmoother; +#line 186 "Gmsh.l" +return tRand; YY_BREAK case 121: YY_RULE_SETUP -#line 188 "Gmsh.l" -return tSqrt; +#line 187 "Gmsh.l" +return tReturn; YY_BREAK case 122: YY_RULE_SETUP #line 189 "Gmsh.l" -return tSin; +return tSmoother; YY_BREAK case 123: YY_RULE_SETUP #line 190 "Gmsh.l" -return tSinh; +return tSqrt; YY_BREAK case 124: YY_RULE_SETUP #line 191 "Gmsh.l" -return tSphere; +return tSin; YY_BREAK case 125: YY_RULE_SETUP #line 192 "Gmsh.l" -return tSpline; +return tSinh; YY_BREAK case 126: YY_RULE_SETUP #line 193 "Gmsh.l" -return tSplit; +return tSphere; YY_BREAK case 127: YY_RULE_SETUP #line 194 "Gmsh.l" -return tSurface; +return tSpline; YY_BREAK case 128: YY_RULE_SETUP #line 195 "Gmsh.l" -return tSprintf; +return tSplit; YY_BREAK case 129: YY_RULE_SETUP #line 196 "Gmsh.l" -return tStrCat; +return tSurface; YY_BREAK case 130: YY_RULE_SETUP #line 197 "Gmsh.l" -return tStrPrefix; +return tSprintf; YY_BREAK case 131: YY_RULE_SETUP #line 198 "Gmsh.l" -return tStrRelative; +return tStrCat; YY_BREAK case 132: YY_RULE_SETUP #line 199 "Gmsh.l" -return tShow; +return tStrPrefix; YY_BREAK case 133: YY_RULE_SETUP #line 200 "Gmsh.l" -return tSymmetry; +return tStrRelative; YY_BREAK case 134: YY_RULE_SETUP #line 201 "Gmsh.l" -return tSyncModel; +return tShow; YY_BREAK case 135: YY_RULE_SETUP -#line 203 "Gmsh.l" -return tText2D; +#line 202 "Gmsh.l" +return tSymmetry; YY_BREAK case 136: YY_RULE_SETUP -#line 204 "Gmsh.l" -return tText3D; +#line 203 "Gmsh.l" +return tSyncModel; YY_BREAK case 137: YY_RULE_SETUP #line 205 "Gmsh.l" -return tTime; +return tText2D; YY_BREAK case 138: YY_RULE_SETUP #line 206 "Gmsh.l" -return tTransfinite; +return tText3D; YY_BREAK case 139: YY_RULE_SETUP #line 207 "Gmsh.l" -return tTranslate; +return tTime; YY_BREAK case 140: YY_RULE_SETUP #line 208 "Gmsh.l" -return tTanh; +return tTransfinite; YY_BREAK case 141: YY_RULE_SETUP #line 209 "Gmsh.l" -return tTan; +return tTranslate; YY_BREAK case 142: YY_RULE_SETUP #line 210 "Gmsh.l" -return tToday; +return tTanh; YY_BREAK case 143: YY_RULE_SETUP -#line 212 "Gmsh.l" -return tUsing; +#line 211 "Gmsh.l" +return tTan; YY_BREAK case 144: YY_RULE_SETUP -#line 214 "Gmsh.l" -return tVolume; +#line 212 "Gmsh.l" +return tToday; YY_BREAK case 145: -#line 217 "Gmsh.l" +YY_RULE_SETUP +#line 214 "Gmsh.l" +return tUsing; + YY_BREAK case 146: -#line 218 "Gmsh.l" +YY_RULE_SETUP +#line 216 "Gmsh.l" +return tVolume; + YY_BREAK case 147: #line 219 "Gmsh.l" case 148: +#line 220 "Gmsh.l" +case 149: +#line 221 "Gmsh.l" +case 150: YY_RULE_SETUP -#line 219 "Gmsh.l" +#line 221 "Gmsh.l" { gmsh_yylval.d = atof((char *)gmsh_yytext); return tDOUBLE; } YY_BREAK -case 149: +case 151: YY_RULE_SETUP -#line 221 "Gmsh.l" +#line 223 "Gmsh.l" { gmsh_yylval.c = strsave((char*)gmsh_yytext); return tSTRING; } YY_BREAK -case 150: +case 152: YY_RULE_SETUP -#line 223 "Gmsh.l" +#line 225 "Gmsh.l" return gmsh_yytext[0]; YY_BREAK -case 151: +case 153: YY_RULE_SETUP -#line 225 "Gmsh.l" +#line 227 "Gmsh.l" ECHO; YY_BREAK -#line 1924 "Gmsh.yy.cpp" +#line 1939 "Gmsh.yy.cpp" case YY_STATE_EOF(INITIAL): yyterminate(); @@ -2212,7 +2227,7 @@ static int yy_get_next_buffer (void) while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state ) { yy_current_state = (int) yy_def[yy_current_state]; - if ( yy_current_state >= 648 ) + if ( yy_current_state >= 657 ) yy_c = yy_meta[(unsigned int) yy_c]; } yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c]; @@ -2240,11 +2255,11 @@ static int yy_get_next_buffer (void) while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state ) { yy_current_state = (int) yy_def[yy_current_state]; - if ( yy_current_state >= 648 ) + if ( yy_current_state >= 657 ) yy_c = yy_meta[(unsigned int) yy_c]; } yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c]; - yy_is_jam = (yy_current_state == 647); + yy_is_jam = (yy_current_state == 656); return yy_is_jam ? 0 : yy_current_state; } @@ -2917,7 +2932,7 @@ void gmsh_yyfree (void * ptr ) #define YYTABLES_NAME "yytables" -#line 225 "Gmsh.l" +#line 227 "Gmsh.l" diff --git a/Plugin/Curl.cpp b/Plugin/Curl.cpp index 9959d725c1f9ea63bdf430e5dbf9f7a20b52b72a..307ac6cb83481d97cd4ee589d07ca8f21cc121e4 100644 --- a/Plugin/Curl.cpp +++ b/Plugin/Curl.cpp @@ -44,7 +44,7 @@ PView *GMSH_CurlPlugin::execute(PView *v) PView *v1 = getView(iView, v); if(!v1) return v; - PViewData *data1 = v1->getData(true); // get adaptive data is available + PViewData *data1 = v1->getData(true); // get adaptive data if available if(data1->hasMultipleMeshes()){ Msg::Error("Curl plugin cannot be run on multi-mesh views"); return v; diff --git a/Plugin/Divergence.cpp b/Plugin/Divergence.cpp index d71fa716c5ac3e9f6080b548a40fb99d119805d4..6b02c42d2c34811df71d88017fae2b4fa87a0e44 100644 --- a/Plugin/Divergence.cpp +++ b/Plugin/Divergence.cpp @@ -44,7 +44,7 @@ PView *GMSH_DivergencePlugin::execute(PView *v) PView *v1 = getView(iView, v); if(!v1) return v; - PViewData *data1 = v1->getData(true); // get adaptive data is available + PViewData *data1 = v1->getData(true); // get adaptive data if available if(data1->hasMultipleMeshes()){ Msg::Error("Divergence plugin cannot be run on multi-mesh views"); return v; diff --git a/Plugin/Gradient.cpp b/Plugin/Gradient.cpp index 3801292a78181f2cb46eb3c879014c9433713325..f299217a04dcd93da42931c957e0bd5e6cd5e516 100644 --- a/Plugin/Gradient.cpp +++ b/Plugin/Gradient.cpp @@ -44,7 +44,7 @@ PView *GMSH_GradientPlugin::execute(PView *v) PView *v1 = getView(iView, v); if(!v1) return v; - PViewData *data1 = v1->getData(true); // get adaptive data is available + PViewData *data1 = v1->getData(true); // get adaptive data if available if(data1->hasMultipleMeshes()){ Msg::Error("Gradient plugin cannot be run on multi-mesh views"); return v; diff --git a/Plugin/Integrate.cpp b/Plugin/Integrate.cpp index 2f25f270bfc5164366a74e9598683f5a345c6566..31870fae86fc0bf48b309c67d6dabc4330bed2c3 100644 --- a/Plugin/Integrate.cpp +++ b/Plugin/Integrate.cpp @@ -46,7 +46,7 @@ PView *GMSH_IntegratePlugin::execute(PView * v) PView *v1 = getView(iView, v); if(!v1) return v; - PViewData *data1 = v1->getData(true); // get adaptive data is available + PViewData *data1 = v1->getData(true); // get adaptive data if available PView *v2 = new PView(); PViewDataList *data2 = getDataList(v2); diff --git a/Plugin/Levelset.cpp b/Plugin/Levelset.cpp index 688947617f56be21237c07f0dc5ba9225739f4fc..d06bacec4e2c94acc447689d395ad05c1042b239 100644 --- a/Plugin/Levelset.cpp +++ b/Plugin/Levelset.cpp @@ -402,7 +402,7 @@ PView *GMSH_LevelsetPlugin::execute(PView *v) v->setChanged(true); } - // get adaptive data is available + // get adaptive data if available PViewData *vdata = v->getData(true), *wdata; if(_valueView < 0) { wdata = vdata; diff --git a/Post/PViewOptions.cpp b/Post/PViewOptions.cpp index 48318ac2ed9c917291c59dc715396f9fbdc445d3..3f7c440bfc62f229a8b9dd7f7ff26c5cc1279e0f 100644 --- a/Post/PViewOptions.cpp +++ b/Post/PViewOptions.cpp @@ -128,6 +128,7 @@ bool PViewOptions::skipElement(int type) case TYPE_HEX: return !drawHexahedra; case TYPE_PRI: return !drawPrisms; case TYPE_PYR: return !drawPyramids; + case TYPE_POLYG: case TYPE_POLYH: return false; default: return true; } } diff --git a/contrib/mpeg_encode/CMakeLists.txt b/contrib/mpeg_encode/CMakeLists.txt new file mode 100644 index 0000000000000000000000000000000000000000..608772a679a13e7fe238a3637f2df15ae2032ed4 --- /dev/null +++ b/contrib/mpeg_encode/CMakeLists.txt @@ -0,0 +1,38 @@ +# Gmsh - Copyright (C) 1997-2010 C. Geuzaine, J.-F. Remacle +# +# See the LICENSE.txt file for license information. Please report all +# bugs and problems to <gmsh@geuz.org>. + +set(SRC + bframe.cpp + bsearch.cpp + frame.cpp + huff.cpp + jrevdct.cpp + param.cpp + postdct.cpp + rate.cpp + specifics.cpp + bitio.cpp + combine.cpp + frametype.cpp + iframe.cpp + libpnmrw.cpp + mfwddct.cpp + mpeg.cpp + psearch.cpp + readframe.cpp + subsample.cpp + block.cpp + fsize.cpp + nojpeg.cpp + noparallel.cpp + main.cpp + mheaders.cpp + opts.cpp + pframe.cpp + rgbtoycc.cpp +) + +file(GLOB_RECURSE HDR RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} headers/*.h) +append_gmsh_src(contrib/mpeg_encode "${SRC};${HDR}") diff --git a/contrib/mpeg_encode/COPYRIGHT.txt b/contrib/mpeg_encode/COPYRIGHT.txt new file mode 100644 index 0000000000000000000000000000000000000000..08216f34c1c663643c50b3a9fd253624d01341ae --- /dev/null +++ b/contrib/mpeg_encode/COPYRIGHT.txt @@ -0,0 +1,20 @@ +/* + * Copyright (c) 1995 The Regents of the University of California. + * All rights reserved. + * + * Permission to use, copy, modify, and distribute this software and its + * documentation for any purpose, without fee, and without written agreement is + * hereby granted, provided that the above copyright notice and the following + * two paragraphs appear in all copies of this software. + * + * IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR + * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT + * OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF + * CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS + * ON AN "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO + * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. + */ diff --git a/contrib/mpeg_encode/README.txt b/contrib/mpeg_encode/README.txt new file mode 100644 index 0000000000000000000000000000000000000000..199dd797d0332abb10f37fc32c6809990114deaa --- /dev/null +++ b/contrib/mpeg_encode/README.txt @@ -0,0 +1,137 @@ +************************************************************************* +This is a heavily modified version of mpeg_encode, version 1.5b, for +inclusion in gmsh. The code was made to compile in C++ and modified so +that all errors throw exceptions. + +FIXME: When used as a subroutine the code clearly leaks memory (see +e.g. frametype.cpp and param.cpp). This should be fixed... +************************************************************************* + + MPEG-1 Video Software Encoder + (Version 1.5; February 1, 1995) + + Lawrence A. Rowe, Kevin Gong, Eugene Hung, Ketan Patel, Steve Smoot + and Dan Wallach + Computer Science Division-EECS, Univ. of Calif. at Berkeley + +This directory contains the freely distributed Berkeley MPEG-1 Video +Encoder. The encoder implements the standard described in the ISO/IEC +International Standard 11172-2. The code has been compiled and tested +on the following platforms: + + DECstation 5000 and Alpha + HP PA-RISC (HP/UX 9.X) (i.e., HP 9000/7XX and 9000/3XX) + SGI Indigo running IRIX 5.0.1 + Sun Sparc (SunOS 4.X) + +In addition, Rainer Menes from the Technical University of Munich has +ported the encoder and decoder to the Macintosh. You can get that code +directly from him (menes@statistik.tu-muenchen.de), or from the +Berkeley FTP archive (mm-ftp.CS.Berkeley.EDU). If you decide to port +the code to a new architecture, please let us know so that we can +incorporate the changes into our sources. + +This directory contains everything required to build the encoder +and run it. We have included source code, makefiles, binaries +for selected platforms, documentation, and test data. Installation +instructions are given in the file named src/mpeg_encode/INSTALL. A man +page is given in the file doc/mpeg_encode.1. A detailed user +manual is provided in postscript format in the file doc/user-manual.ps. + +The encoder will accept any input file format as long as you provide +a script to convert the images to PPM, YUV, JPEG, or JMOVIE format. Input +file processing is described in the file doc/INPUT.FORMAT. Options to +control input file processing and compression parameters are specified in +a parameter file. Very little error processing is done when reading +this file. We suggest you start with the sample parameter file +examples/template.param and modify it. See also examples/default.param. + +The convert directory of Mpeg-Tools contains utilities you might find +useful including: + +programs to do PPM/YUV conversion and programs to convert Parallax +XVideo JPEG files into PPM, YUV, or JPEG frames. + +The motion vector search window can be specified, including half-pixel +block matching, in the parameter file. We have implemented several +search algorithms for P-frames including: 1) exhaustive search, +2) subsampled search, and 3) logarithmic search. We have also implemented +several alternatives for B-frame block matching including: 1) interpolate +best forward and best backward block, 2) find backward block for best +forward or vice-versa (called CROSS2), and 3) exhaustive cross product +(i.e., go out for coffee and a donut!). The search algorithms are controlled +by options in the parameters file. For tips on choosing the right search +technique, see the user manual. + +The encoder can be run on one computer (i.e., sequential) or on several +computers (i.e., parallel). Our goal is to produce a portable, easy-to-use +encoder that we can use to encode large volumes of video material for +the Berkeley VOD system (see paper VodsProp93.ps.Z on the FTP archive). +The parallelism is done on a sequence of pictures. In other words, you +can spawn one or more children to encode continuous runs pictures. The +uncompressed data can be accessed either through NFS or TCP sockets. +The goal is to allow you to encode using multiple processors, think +spare cycles on workstations, to speed up the encoding time. Although +performance depends on the speed of individual processors, the file system +and network, and the P/B frame search methods, we have encoded 3.75 +frames/second on 8 HP Snakes running in parallel as compared with 0.6 +frames/second on 1 Snake. These are preliminary results. We are continuing +to experiment with and tune the code. Instructions to run the parallel system +are given in the man page and the parallel.param example parameter file. + +We have done some tuning to produce a reasonable encoder, but there are +many more optimizations that we would like to incorporate. These +extensions are listed in the file doc/EXTENSIONS. If you succeed in +implementing any of them, please let us know! + +Send bug reports to: + +mpeg-bugs@CS.Berkeley.EDU + Problems, questions, or patches should be sent to this address. + +Anyone interested in providing financial support for this research or +discussing other aspects of this project should contact Larry Rowe at +Rowe@CS.Berkeley.EDU (+1 510-642-5117). + +This software is freely distributed. That means, you may use it for +any non-commercial purpose. However, patents are held by several companies +on various aspects of the MPEG video standard. Companies or individuals +who want to develop commercial products that include this code must +acquire licenses from these companies. For information on licensing, see +Appendix F in the standard. + +ACKNOWLEDGEMENTS: + +We gratefully thank Hewlett-Packard and Fujitsu who provided financial +support for this work. We also want to thank the following people and +organizations for their help: + + Jef Poskanzer who developed the pbmplus package. + --------- + Copyright (C) 1989, 1991 by Jef Poskanzer. + + Permission to use, copy, modify, and distribute this software and its + documentation for any purpose and without fee is hereby granted, provided + that the above copyright notice appear in all copies and that both that + copyright notice and this permission notice appear in supporting + documentation. This software is provided "as is" without express or + implied warranty. + --------- + + Eiichi Kowashi of Intel and Avideh Zakhor of U.C. Berkeley who + provided valuable suggestions on motion vector searching. + + Chad Fogg of the University of Washington who has helped us + understand many issues in MPEG coding and decoding. + + Rainer Menes of the Technical University of Munich who has ported the + the Berkeley MPEG encoder and decoder to the Macintosh, and he has + provided us with many suggestions to improve the code. + + Robert Safranek of ATT for comments, suggestions, and most of the + code for custom quantization tables. + + Jim Boucher of Boston University for jmovie2jpeg. + + The San Diego SuperComputing Center for providing facilities to + develop some of the code contained within. diff --git a/contrib/mpeg_encode/bframe.cpp b/contrib/mpeg_encode/bframe.cpp new file mode 100644 index 0000000000000000000000000000000000000000..7513f0b59ac2e4b37fb39c752cff5595da62145b --- /dev/null +++ b/contrib/mpeg_encode/bframe.cpp @@ -0,0 +1,1318 @@ +/*===========================================================================* + * bframe.c * + * * + * Procedures concerned with the B-frame encoding * + * * + * EXPORTED PROCEDURES: * + * GenBFrame * + * ResetBFrameStats * + * ShowBFrameSummary * + * EstimateSecondsPerBFrame * + * ComputeBMotionLumBlock * + * SetBQScale * + * GetBQScale * + * * + *===========================================================================*/ + +/* + * Copyright (c) 1995 The Regents of the University of California. + * All rights reserved. + * + * Permission to use, copy, modify, and distribute this software and its + * documentation for any purpose, without fee, and without written agreement is + * hereby granted, provided that the above copyright notice and the following + * two paragraphs appear in all copies of this software. + * + * IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR + * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT + * OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF + * CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS + * ON AN "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO + * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. + */ + +/* + * $Header: /n/picasso/project/mpeg/mpeg_dist/mpeg_encode/RCS/bframe.c,v 1.20 1995/08/14 22:28:11 smoot Exp $ + * $Log: bframe.c,v $ + * Revision 1.20 1995/08/14 22:28:11 smoot + * renamed index to idx + * added option to not skip in B frames + * + * Revision 1.19 1995/08/07 21:52:11 smoot + * added Color to skip routine + * fixed full/half bug in intial loop + * added comments + * removed buggy "extra skips" code + * + * Revision 1.18 1995/06/21 22:22:24 smoot + * generalized time checking, fixed bug in specifics filesm + * and added TUNEing stuff + * + * Revision 1.17 1995/04/14 23:08:02 smoot + * reorganized to ease rate control experimentation + * + * Revision 1.16 1995/02/24 23:49:10 smoot + * added Spec version 2 + * + * Revision 1.15 1995/01/30 19:45:45 smoot + * Fixed a cr/cb screwup + * + * Revision 1.14 1995/01/23 02:46:43 darryl + * initialized variable + * + * Revision 1.13 1995/01/19 23:07:12 eyhung + * Changed copyrights + * + * Revision 1.12 1995/01/16 07:44:11 eyhung + * Added realQuiet + * + * Revision 1.11 1994/12/07 00:40:36 smoot + * Added seperate P and B search ranges + * + * Revision 1.10 1994/11/24 00:35:47 smoot + * fixed bug (divide by 0) in B fram statsitics + * + * Revision 1.9 1994/11/14 22:26:48 smoot + * Merged specifics and rate control. + * + * Revision 1.8 1994/11/01 05:01:16 darryl + * with rate control changes added + * + * Revision 2.0 1994/10/24 02:38:51 darryl + * will be adding the experiment code + * + * Revision 1.1 1994/09/27 00:16:04 darryl + * Initial revision + * + * Revision 1.7 1994/03/15 00:27:11 keving + * nothing + * + * Revision 1.6 1993/12/22 19:19:01 keving + * nothing + * + * Revision 1.5 1993/07/30 19:24:04 keving + * nothing + * + * Revision 1.4 1993/07/22 22:23:43 keving + * nothing + * + * Revision 1.3 1993/06/30 20:06:09 keving + * nothing + * + * Revision 1.2 1993/06/03 21:08:08 keving + * nothing + * + * Revision 1.1 1993/02/19 19:14:28 keving + * nothing + * + */ + + +/*==============* + * HEADER FILES * + *==============*/ + +#include "all.h" +#include <sys/param.h> +#include <assert.h> +#include "mtypes.h" +#include "bitio.h" +#include "frames.h" +#include "prototypes.h" +#include "fsize.h" +#include "param.h" +#include "mheaders.h" +#include "postdct.h" +#include "rate.h" +#include "opts.h" + +/*==================* + * STATIC VARIABLES * + *==================*/ + +static int numBIBlocks = 0; +static int numBBBlocks = 0; +static int numBSkipped = 0; +static int numBIBits = 0; +static int numBBBits = 0; +static int numFrames = 0; +static int numFrameBits = 0; +static int32 totalTime = 0; +static int qscaleB; +static float totalSNR = 0.0; +static float totalPSNR = 0.0; + +static int numBFOBlocks = 0; /* forward only */ +static int numBBABlocks = 0; /* backward only */ +static int numBINBlocks = 0; /* interpolate */ +static int numBFOBits = 0; +static int numBBABits = 0; +static int numBINBits = 0; + +/*====================* + * EXTERNAL VARIABLES * + *====================*/ + +extern Block **dct, **dctr, **dctb; +extern dct_data_type **dct_data; +#define NO_MOTION 0 +#define MOTION 1 +#define SKIP 2 /* used in useMotion in dct_data */ + +/*===============================* + * INTERNAL PROCEDURE prototypes * + *===============================*/ + +static boolean MotionSufficient _ANSI_ARGS_((MpegFrame *curr, LumBlock currBlock, MpegFrame *prev, MpegFrame *next, + int by, int bx, int mode, int fmy, int fmx, + int bmy, int bmx)); +static void ComputeBMotionBlock _ANSI_ARGS_((MpegFrame *prev, MpegFrame *next, + int by, int bx, int mode, int fmy, int fmx, + int bmy, int bmx, Block motionBlock, int type)); +static void ComputeBDiffDCTs _ANSI_ARGS_((MpegFrame *current, MpegFrame *prev, MpegFrame *next, + int by, int bx, int mode, int fmy, int fmx, + int bmy, int bmx, int *pattern)); +static boolean DoBIntraCode _ANSI_ARGS_((MpegFrame *current, MpegFrame *prev, MpegFrame *next, + int by, int bx, int mode, int fmy, int fmx, int bmy, + int bmx)); + +static int ComputeBlockColorDiff _ANSI_ARGS_((Block current, Block motionBlock)); + +/*=====================* + * EXPORTED PROCEDURES * + *=====================*/ + +/*===========================================================================* + * + * GenBFrame + * + * generate a B-frame from previous and next frames, adding the result + * to the given bit bucket + * + * RETURNS: frame appended to bb + * + * SIDE EFFECTS: none + * + *===========================================================================*/ +void +GenBFrame(BitBucket *bb, + MpegFrame *curr, + MpegFrame *prev, + MpegFrame *next) +{ + extern int **bfmvHistogram; + extern int **bbmvHistogram; + FlatBlock fba[6], fb[6]; + Block dec[6]; + int32 y_dc_pred, cr_dc_pred, cb_dc_pred; + int x, y; + int fMotionX = 0, fMotionY = 0; + int bMotionX = 0, bMotionY = 0; + int oldFMotionX = 0, oldFMotionY = 0; + int oldBMotionX = 0, oldBMotionY = 0; + int oldMode = MOTION_FORWARD; + int mode = MOTION_FORWARD; + int offsetX, offsetY; + int tempX, tempY; + int fMotionXrem = 0, fMotionXquot = 0; + int fMotionYrem = 0, fMotionYquot = 0; + int bMotionXrem = 0, bMotionXquot = 0; + int bMotionYrem = 0, bMotionYquot = 0; + int pattern; + int numIBlocks = 0, numBBlocks = 0; + int numSkipped = 0, totalBits; + int numIBits = 0, numBBits = 0; + boolean lastIntra = TRUE; + boolean motionForward, motionBackward; + int totalFrameBits; + int32 startTime, endTime; + int lastX, lastY; + int lastBlockX, lastBlockY; + register int ix, iy; + LumBlock currentBlock; + int fy, fx; + boolean make_skip_block; + int mbAddrInc = 1; + int mbAddress; + int slicePos; + float snr[3], psnr[3]; + int idx; + int QScale; + BlockMV *info; + int bitstreamMode, newQScale; + int rc_blockStart=0; + boolean overflowChange=FALSE; + int overflowValue = 0; + + if (collect_quant) {fprintf(collect_quant_fp, "# B\n");} + if (dct == NULL) AllocDctBlocks(); + numFrames++; + totalFrameBits = bb->cumulativeBits; + startTime = time_elapsed(); + + /* Rate Control */ + bitstreamMode = getRateMode(); + if (bitstreamMode == FIXED_RATE) { + targetRateControl(curr); + } + + QScale = GetBQScale(); + Mhead_GenPictureHeader(bb, B_FRAME, curr->id, fCodeB); + /* Check for Qscale change */ + if (specificsOn) { + newQScale = SpecLookup(curr->id, 0, 0 /* junk */, &info, QScale); + if (newQScale != -1) { + QScale = newQScale; + } + /* check for slice */ + newQScale = SpecLookup(curr->id, 1, 1, &info, QScale); + if (newQScale != -1) { + QScale = newQScale; + } + } + + Mhead_GenSliceHeader(bb, 1, QScale, NULL, 0); + + Frame_AllocBlocks(curr); + BlockifyFrame(curr); + + if ( printSNR ) { + Frame_AllocDecoded(curr, FALSE); + } + + /* for I-blocks */ + y_dc_pred = cr_dc_pred = cb_dc_pred = 128; + + totalBits = bb->cumulativeBits; + + if ( ! pixelFullSearch ) { + if ( ! prev->halfComputed && (prev != NULL)) { + ComputeHalfPixelData(prev); + } + + if ( ! next->halfComputed ) { + ComputeHalfPixelData(next); + } + } + + lastBlockX = Fsize_x>>3; + lastBlockY = Fsize_y>>3; + lastX = lastBlockX-2; + lastY = lastBlockY-2; + mbAddress = 0; + + /* find motion vectors and do dcts */ + /* In this first loop, all MVs are in half-pixel scope, (if FULL is set + then they will be multiples of 2). This is not true in the second loop. */ + for (y = 0; y < lastBlockY; y += 2) { + for (x = 0; x < lastBlockX; x += 2) { + slicePos = (mbAddress % blocksPerSlice); + + /* compute currentBlock */ + BLOCK_TO_FRAME_COORD(y, x, fy, fx); + for ( iy = 0; iy < 16; iy++ ) { + for ( ix = 0; ix < 16; ix++ ) { + currentBlock[iy][ix] = (int16)curr->orig_y[fy+iy][fx+ix]; + } + } + + if (slicePos == 0) { + oldFMotionX = 0; oldFMotionY = 0; + oldBMotionX = 0; oldBMotionY = 0; + oldMode = MOTION_FORWARD; + lastIntra = TRUE; + } + + /* STEP 1: Select Forward, Backward, or Interpolated motion vectors */ + /* see if old motion is good enough */ + /* but force last block to be non-skipped */ + /* can only skip if: + * 1) not the last block in frame + * 2) not the last block in slice + * 3) not the first block in slice + * 4) previous block was not intra-coded + */ + if ( ((y < lastY) || (x < lastX)) && + (slicePos+1 != blocksPerSlice) && + (slicePos != 0) && + (! lastIntra) && + (BSkipBlocks) ) { + make_skip_block = MotionSufficient(curr, currentBlock, prev, next, y, x, oldMode, + oldFMotionY, oldFMotionX, + oldBMotionY, oldBMotionX); + } else { + make_skip_block = FALSE; + } + + if ( make_skip_block ) { + skip_it: + /* skipped macro block */ + dct_data[y][x].useMotion = SKIP; + } else { + if (specificsOn) { + (void) SpecLookup(curr->id, 2, mbAddress, &info, QScale); + if (info == (BlockMV*)NULL) goto gosearch; + else { + switch (info->typ) { + case TYP_SKIP: + goto skip_it; + case TYP_FORW: + fMotionX = info->fx; + fMotionY = info->fy; + mode = MOTION_FORWARD; + break; + case TYP_BACK: + bMotionX = info->bx; + bMotionY = info->by; + mode = MOTION_BACKWARD; + break; + case TYP_BOTH: + fMotionX = info->fx; + fMotionY = info->fy; + bMotionX = info->bx; + bMotionY = info->by; + mode = MOTION_INTERPOLATE; + break; + default: + fprintf(stderr,"Unreachable code in GenBFrame!\n"); + goto gosearch; + } + goto skipsearch; + }} + gosearch: /* do bsearch */ + mode = BMotionSearch(currentBlock, prev, next, y, x, &fMotionY, + &fMotionX, &bMotionY, &bMotionX, mode); + skipsearch: + + /* STEP 2: INTRA OR NON-INTRA CODING */ + if ( IntraPBAllowed && DoBIntraCode(curr, prev, next, y, x, mode, fMotionY, + fMotionX, bMotionY, bMotionX) ) { + /* output I-block inside a B-frame */ + numIBlocks++; + oldFMotionX = 0; oldFMotionY = 0; + oldBMotionX = 0; oldBMotionY = 0; + lastIntra = TRUE; + dct_data[y][x].useMotion = NO_MOTION; + oldMode = MOTION_FORWARD; + /* calculate forward dct's */ + if (collect_quant && (collect_quant_detailed & 1)) fprintf(collect_quant_fp, "l\n"); + mp_fwd_dct_block2(curr->y_blocks[y][x], dct[y][x]); + mp_fwd_dct_block2(curr->y_blocks[y][x+1], dct[y][x+1]); + mp_fwd_dct_block2(curr->y_blocks[y+1][x], dct[y+1][x]); + mp_fwd_dct_block2(curr->y_blocks[y+1][x+1], dct[y+1][x+1]); + if (collect_quant && (collect_quant_detailed & 1)) {fprintf(collect_quant_fp, "c\n");} + mp_fwd_dct_block2(curr->cb_blocks[y>>1][x>>1], dctb[y>>1][x>>1]); + mp_fwd_dct_block2(curr->cr_blocks[y>>1][x>>1], dctr[y>>1][x>>1]); + + } else { /* dct P/Bi/B block */ + + pattern = 63; + lastIntra = FALSE; + numBBlocks++; + dct_data[y][x].mode = mode; + oldMode = mode; + dct_data[y][x].fmotionX = fMotionX; + dct_data[y][x].fmotionY = fMotionY; + dct_data[y][x].bmotionX = bMotionX; + dct_data[y][x].bmotionY = bMotionY; + switch (mode) { + case MOTION_FORWARD: + numBFOBlocks++; + oldFMotionX = fMotionX; oldFMotionY = fMotionY; + break; + case MOTION_BACKWARD: + numBBABlocks++; + oldBMotionX = bMotionX; oldBMotionY = bMotionY; + break; + case MOTION_INTERPOLATE: + numBINBlocks++; + oldFMotionX = fMotionX; oldFMotionY = fMotionY; + oldBMotionX = bMotionX; oldBMotionY = bMotionY; + break; + default: + throw "PROGRAMMER ERROR: Illegal mode"; + } + + ComputeBDiffDCTs(curr, prev, next, y, x, mode, fMotionY, + fMotionX, bMotionY, bMotionX, &pattern); + + dct_data[y][x].pattern = pattern; + dct_data[y][x].useMotion = MOTION; + if ( computeMVHist ) { + assert(fMotionX+searchRangeB+1 >= 0); + assert(fMotionY+searchRangeB+1 >= 0); + assert(fMotionX+searchRangeB+1 <= 2*searchRangeB+2); + assert(fMotionY+searchRangeB+1 <= 2*searchRangeB+2); + assert(bMotionX+searchRangeB+1 >= 0); + assert(bMotionY+searchRangeB+1 >= 0); + assert(bMotionX+searchRangeB+1 <= 2*searchRangeB+2); + assert(bMotionY+searchRangeB+1 <= 2*searchRangeB+2); + + bfmvHistogram[fMotionX+searchRangeB+1][fMotionY+searchRangeB+1]++; + bbmvHistogram[bMotionX+searchRangeB+1][bMotionY+searchRangeB+1]++; + } + } /* motion-block */ + } /* not skipped */ + mbAddress++; + }} + + /* reset everything */ + oldFMotionX = 0; oldFMotionY = 0; + oldBMotionX = 0; oldBMotionY = 0; + oldMode = MOTION_FORWARD; + lastIntra = TRUE; + y_dc_pred = cr_dc_pred = cb_dc_pred = 128; + mbAddress = 0; + + /* Now generate the frame */ + for (y = 0; y < lastBlockY; y += 2) { + for (x = 0; x < lastBlockX; x += 2) { + slicePos = (mbAddress % blocksPerSlice); + + if ( (slicePos == 0) && (mbAddress != 0) ) { + if (specificsOn) { + /* Make sure no slice Qscale change */ + newQScale = SpecLookup(curr->id,1,mbAddress/blocksPerSlice, &info, QScale); + if (newQScale != -1) QScale = newQScale; + } + Mhead_GenSliceEnder(bb); + Mhead_GenSliceHeader(bb, 1+(y>>1), QScale, NULL, 0); + + /* reset everything */ + oldFMotionX = 0; oldFMotionY = 0; + oldBMotionX = 0; oldBMotionY = 0; + oldMode = MOTION_FORWARD; + lastIntra = TRUE; + y_dc_pred = cr_dc_pred = cb_dc_pred = 128; + + mbAddrInc = 1+(x>>1); + } + + /* Determine if new Qscale needed for Rate Control purposes */ + if (bitstreamMode == FIXED_RATE) { + rc_blockStart = bb->cumulativeBits; + newQScale = needQScaleChange(QScale, + curr->y_blocks[y][x], + curr->y_blocks[y][x+1], + curr->y_blocks[y+1][x], + curr->y_blocks[y+1][x+1]); + if (newQScale > 0) { + QScale = newQScale; + } + } + + if (specificsOn) { + newQScale = SpecLookup(curr->id, 2, mbAddress, &info, QScale); + if (newQScale != -1) { + QScale = newQScale; + }} + + if (dct_data[y][x].useMotion == NO_MOTION) { + + GEN_I_BLOCK(B_FRAME, curr, bb, mbAddrInc, QScale); + mbAddrInc = 1; + numIBits += (bb->cumulativeBits-totalBits); + totalBits = bb->cumulativeBits; + + /* reset because intra-coded */ + oldFMotionX = 0; oldFMotionY = 0; + oldBMotionX = 0; oldBMotionY = 0; + oldMode = MOTION_FORWARD; + lastIntra = TRUE; + + if ( printSNR ) { + /* need to decode block we just encoded */ + /* and reverse the DCT transform */ + for ( idx = 0; idx < 6; idx++ ) { + Mpost_UnQuantZigBlock(fb[idx], dec[idx], QScale, TRUE); + mpeg_jrevdct((int16 *)dec[idx]); + } + + /* now, unblockify */ + BlockToData(curr->decoded_y, dec[0], y, x); + BlockToData(curr->decoded_y, dec[1], y, x+1); + BlockToData(curr->decoded_y, dec[2], y+1, x); + BlockToData(curr->decoded_y, dec[3], y+1, x+1); + BlockToData(curr->decoded_cb, dec[4], y>>1, x>>1); + BlockToData(curr->decoded_cr, dec[5], y>>1, x>>1); + } + } else if (dct_data[y][x].useMotion == SKIP) { + skip_block: + numSkipped++; + mbAddrInc++; + + /* decode skipped block */ + if ( printSNR ) { + int fmy, fmx, bmy, bmx; + + for ( idx = 0; idx < 6; idx++ ) { + memset((char *)dec[idx], 0, sizeof(Block)); + } + + if ( pixelFullSearch ) { + fmy = 2*oldFMotionY; + fmx = 2*oldFMotionX; + bmy = 2*oldBMotionY; + bmx = 2*oldBMotionX; + } else { + fmy = oldFMotionY; + fmx = oldFMotionX; + bmy = oldBMotionY; + bmx = oldBMotionX; + } + + /* now add the motion block */ + AddBMotionBlock(dec[0], prev->decoded_y, + next->decoded_y, y, x, mode, + fmy, fmx, bmy, bmx); + AddBMotionBlock(dec[1], prev->decoded_y, + next->decoded_y, y, x+1, mode, + fmy, fmx, bmy, bmx); + AddBMotionBlock(dec[2], prev->decoded_y, + next->decoded_y, y+1, x, mode, + fmy, fmx, bmy, bmx); + AddBMotionBlock(dec[3], prev->decoded_y, + next->decoded_y, y+1, x+1, mode, + fmy, fmx, bmy, bmx); + AddBMotionBlock(dec[4], prev->decoded_cb, + next->decoded_cb, y>>1, x>>1, mode, + fmy/2, fmx/2, + bmy/2, bmx/2); + AddBMotionBlock(dec[5], prev->decoded_cr, + next->decoded_cr, y>>1, x>>1, mode, + fmy/2, fmx/2, + bmy/2, bmx/2); + + /* now, unblockify */ + BlockToData(curr->decoded_y, dec[0], y, x); + BlockToData(curr->decoded_y, dec[1], y, x+1); + BlockToData(curr->decoded_y, dec[2], y+1, x); + BlockToData(curr->decoded_y, dec[3], y+1, x+1); + BlockToData(curr->decoded_cb, dec[4], y>>1, x>>1); + BlockToData(curr->decoded_cr, dec[5], y>>1, x>>1); + } + } else /* B block */ { + int fCode = fCodeB; + + pattern = dct_data[y][x].pattern; + fMotionX = dct_data[y][x].fmotionX; + fMotionY = dct_data[y][x].fmotionY; + bMotionX = dct_data[y][x].bmotionX; + bMotionY = dct_data[y][x].bmotionY; + + if ( pixelFullSearch ) { + fMotionX /= 2; fMotionY /= 2; + bMotionX /= 2; bMotionY /= 2; + } + + /* create flat blocks and update pattern if necessary */ + calc_blocks: + /* Note DoQuant references QScale, overflowChange, overflowValue, + pattern, and the calc_blocks label */ + DoQuant(0x20, dct[y][x], fba[0]); + DoQuant(0x10, dct[y][x+1], fba[1]); + DoQuant(0x08, dct[y+1][x], fba[2]); + DoQuant(0x04, dct[y+1][x+1], fba[3]); + DoQuant(0x02, dctb[y>>1][x>>1], fba[4]); + DoQuant(0x01, dctr[y>>1][x>>1], fba[5]); + + motionForward = (dct_data[y][x].mode != MOTION_BACKWARD); + motionBackward = (dct_data[y][x].mode != MOTION_FORWARD); + +#ifdef BUGGY_CODE + /* + send us mail if you can tell me why this code + doesnt work. Generates some bad vectors. + I suspect 'cuz oldMode/motions aren't being set right, + but am unsure. + */ + /* Check to see if we should have skipped */ + if ((pattern == 0) && + ((y < lastY) || (x < lastX)) && + (slicePos+1 != blocksPerSlice) && + (slicePos != 0) && + (!lastIntra) && + ( (!motionForward) || + (motionForward && + fMotionX == oldFMotionX && fMotionY == oldFMotionY)) && + ( (!motionBackward) || + (motionBackward && + bMotionX == oldBMotionX && bMotionY == oldBMotionY)) + ) { + /* Now *thats* an if statement! */ + goto skip_block; + } +#endif + /* Encode Vectors */ + if ( motionForward ) { + /* transform the fMotion vector into the appropriate values */ + offsetX = fMotionX - oldFMotionX; + offsetY = fMotionY - oldFMotionY; + + ENCODE_MOTION_VECTOR(offsetX, offsetY, fMotionXquot, + fMotionYquot, fMotionXrem, fMotionYrem, + FORW_F); + oldFMotionX = fMotionX; oldFMotionY = fMotionY; + } + + if ( motionBackward ) { + /* transform the bMotion vector into the appropriate values */ + offsetX = bMotionX - oldBMotionX; + offsetY = bMotionY - oldBMotionY; + ENCODE_MOTION_VECTOR(offsetX, offsetY, bMotionXquot, + bMotionYquot, bMotionXrem, bMotionYrem, + BACK_F); + oldBMotionX = bMotionX; oldBMotionY = bMotionY; + } + + oldMode = dct_data[y][x].mode; + + if ( printSNR ) { /* Need to decode */ + if ( pixelFullSearch ) { + fMotionX *= 2; fMotionY *= 2; + bMotionX *= 2; bMotionY *= 2; + } + for ( idx = 0; idx < 6; idx++ ) { + if ( pattern & (1 << (5-idx)) ) { + Mpost_UnQuantZigBlock(fba[idx], dec[idx], QScale, FALSE); + mpeg_jrevdct((int16 *)dec[idx]); + } else { + memset((char *)dec[idx], 0, sizeof(Block)); + } + } + + /* now add the motion block */ + AddBMotionBlock(dec[0], prev->decoded_y, + next->decoded_y, y, x, mode, + fMotionY, fMotionX, bMotionY, bMotionX); + AddBMotionBlock(dec[1], prev->decoded_y, + next->decoded_y, y, x+1, mode, + fMotionY, fMotionX, bMotionY, bMotionX); + AddBMotionBlock(dec[2], prev->decoded_y, + next->decoded_y, y+1, x, mode, + fMotionY, fMotionX, bMotionY, bMotionX); + AddBMotionBlock(dec[3], prev->decoded_y, + next->decoded_y, y+1, x+1, mode, + fMotionY, fMotionX, bMotionY, bMotionX); + AddBMotionBlock(dec[4], prev->decoded_cb, + next->decoded_cb, y>>1, x>>1, mode, + fMotionY/2, fMotionX/2, + bMotionY/2, bMotionX/2); + AddBMotionBlock(dec[5], prev->decoded_cr, + next->decoded_cr, y>>1, x>>1, mode, + fMotionY/2, fMotionX/2, + bMotionY/2, bMotionX/2); + + /* now, unblockify */ + BlockToData(curr->decoded_y, dec[0], y, x); + BlockToData(curr->decoded_y, dec[1], y, x+1); + BlockToData(curr->decoded_y, dec[2], y+1, x); + BlockToData(curr->decoded_y, dec[3], y+1, x+1); + BlockToData(curr->decoded_cb, dec[4], y>>1, x>>1); + BlockToData(curr->decoded_cr, dec[5], y>>1, x>>1); + } + + /* reset because non-intra-coded */ + y_dc_pred = cr_dc_pred = cb_dc_pred = 128; + lastIntra = FALSE; + mode = dct_data[y][x].mode; + + /* DBG_PRINT(("MB Header(%d,%d)\n", x, y)); */ + Mhead_GenMBHeader(bb, 3 /* pict_code_type */, mbAddrInc /* addr_incr */, + QScale /* q_scale */, + fCodeB /* forw_f_code */, fCodeB /* back_f_code */, + fMotionXrem /* horiz_forw_r */, fMotionYrem /* vert_forw_r */, + bMotionXrem /* horiz_back_r */, bMotionYrem /* vert_back_r */, + motionForward /* motion_forw */, fMotionXquot /* m_horiz_forw */, + fMotionYquot /* m_vert_forw */, motionBackward /* motion_back */, + bMotionXquot /* m_horiz_back */, bMotionYquot /* m_vert_back */, + pattern /* mb_pattern */, FALSE /* mb_intra */); + mbAddrInc = 1; + + /* now output the difference */ + for ( tempX = 0; tempX < 6; tempX++ ) { + if ( GET_ITH_BIT(pattern, 5-tempX) ) { + Mpost_RLEHuffPBlock(fba[tempX], bb); + } + } + + + switch (mode) { + case MOTION_FORWARD: + numBFOBits += (bb->cumulativeBits-totalBits); + break; + case MOTION_BACKWARD: + numBBABits += (bb->cumulativeBits-totalBits); + break; + case MOTION_INTERPOLATE: + numBINBits += (bb->cumulativeBits-totalBits); + break; + default: + throw "PROGRAMMER ERROR: Illegal mode"; + } + + numBBits += (bb->cumulativeBits-totalBits); + totalBits = bb->cumulativeBits; + + if (overflowChange) { + /* undo an overflow-caused Qscale change */ + overflowChange = FALSE; + QScale -= overflowValue; + overflowValue = 0; + } + } /* if I-block, skip, or B */ + + mbAddress++; + /* Rate Control */ + if (bitstreamMode == FIXED_RATE) { + incMacroBlockBits( bb->cumulativeBits - rc_blockStart); + rc_blockStart = bb->cumulativeBits; + MB_RateOut(TYPE_BFRAME); + } + + } + } + + if ( printSNR ) { + BlockComputeSNR(curr,snr,psnr); + totalSNR += snr[0]; + totalPSNR += psnr[0]; + } + + Mhead_GenSliceEnder(bb); + /* Rate Control */ + if (bitstreamMode == FIXED_RATE) { + updateRateControl(TYPE_BFRAME); + } + + endTime = time_elapsed(); + totalTime += (endTime-startTime); + + if ( ( ! childProcess) && showBitRatePerFrame ) { + /* ASSUMES 30 FRAMES PER SECOND */ + fprintf(bitRateFile, "%5d\t%8d\n", curr->id, + 30*(bb->cumulativeBits-totalFrameBits)); + } + + if ( (! childProcess) && frameSummary && !realQuiet) { + fprintf(stdout, "FRAME %d (B): I BLOCKS: %d; B BLOCKS: %d SKIPPED: %d (%ld seconds)\n", + curr->id, numIBlocks, numBBlocks, numSkipped, (long)((endTime-startTime)/TIME_RATE)); + if ( printSNR ) + fprintf(stdout, "FRAME %d: SNR: %.1f\t%.1f\t%.1f\tPSNR: %.1f\t%.1f\t%.1f\n", + curr->id, snr[0], snr[1], snr[2], + psnr[0], psnr[1], psnr[2]); + } + + numFrameBits += (bb->cumulativeBits-totalFrameBits); + numBIBlocks += numIBlocks; + numBBBlocks += numBBlocks; + numBSkipped += numSkipped; + numBIBits += numIBits; + numBBBits += numBBits; + } + + +/*===========================================================================* + * + * SetBQScale + * + * set the B-frame Q-scale + * + * RETURNS: nothing + * + * SIDE EFFECTS: qscaleB + * + *===========================================================================*/ +void +SetBQScale(int qB) +{ + qscaleB = qB; +} + + +/*===========================================================================* + * + * GetBQScale + * + * get the B-frame Q-scale + * + * RETURNS: the Q-scale + * + * SIDE EFFECTS: none + * + *===========================================================================*/ +int +GetBQScale() +{ + return qscaleB; +} + + +/*===========================================================================* + * + * ResetBFrameStats + * + * reset the B-frame stats + * + * RETURNS: nothing + * + * SIDE EFFECTS: none + * + *===========================================================================*/ +void +ResetBFrameStats() +{ + numBIBlocks = 0; + numBBBlocks = 0; + numBSkipped = 0; + numBIBits = 0; + numBBBits = 0; + numFrames = 0; + numFrameBits = 0; + totalTime = 0; +} + + +/*===========================================================================* + * + * ShowBFrameSummary + * + * print out statistics on all B-frames + * + * RETURNS: time taken for B-frames (in seconds) + * + * SIDE EFFECTS: none + * + *===========================================================================*/ +float +ShowBFrameSummary(int inputFrameBits, + int32 totalBits, + FILE *fpointer) +{ + if ( numFrames == 0 ) { + return 0.0; + } + + fprintf(fpointer, "-------------------------\n"); + fprintf(fpointer, "*****B FRAME SUMMARY*****\n"); + fprintf(fpointer, "-------------------------\n"); + + if ( numBIBlocks != 0 ) { + fprintf(fpointer, " I Blocks: %5d (%6d bits) (%5d bpb)\n", + numBIBlocks, numBIBits, numBIBits/numBIBlocks); + } else { + fprintf(fpointer, " I Blocks: %5d\n", 0); + } + + if ( numBBBlocks != 0 ) { + fprintf(fpointer, " B Blocks: %5d (%6d bits) (%5d bpb)\n", + numBBBlocks, numBBBits, numBBBits/numBBBlocks); + fprintf(fpointer, " B types: %5d (%4d bpb) forw %5d (%4d bpb) back %5d (%4d bpb) bi\n", + numBFOBlocks, (numBFOBlocks==0)?0:numBFOBits/numBFOBlocks, + numBBABlocks, (numBBABlocks==0)?0:numBBABits/numBBABlocks, + numBINBlocks, (numBINBlocks==0)?0:numBINBits/numBINBlocks); + } else { + fprintf(fpointer, " B Blocks: %5d\n", 0); + } + + fprintf(fpointer, " Skipped: %5d\n", numBSkipped); + + fprintf(fpointer, " Frames: %5d (%6d bits) (%5d bpf) (%2.1f%% of total)\n", + numFrames, numFrameBits, numFrameBits/numFrames, + 100.0*(float)numFrameBits/(float)totalBits); + fprintf(fpointer, " Compression: %3d:1 (%9.4f bpp)\n", + numFrames*inputFrameBits/numFrameBits, + 24.0*(float)numFrameBits/(float)(numFrames*inputFrameBits)); + if ( printSNR ) + fprintf(fpointer, " Avg Y SNR/PSNR: %.1f %.1f\n", + totalSNR/(float)numFrames, totalPSNR/(float)numFrames); + if ( totalTime == 0 ) { + fprintf(fpointer, " Seconds: NONE\n"); + } else { + fprintf(fpointer, " Seconds: %9ld (%9.4f fps) (%9ld pps) (%9ld mps)\n", + (long)(totalTime/TIME_RATE), + (float)((float)(TIME_RATE*numFrames)/(float)totalTime), + (long)((float)TIME_RATE*(float)numFrames*(float)inputFrameBits/(24.0*(float)totalTime)), + (long)((float)TIME_RATE*(float)numFrames*(float)inputFrameBits/(256.0*24.0*(float)totalTime))); + } + + return (float)totalTime/TIME_RATE; +} + + +/*===========================================================================* + * + * ComputeBMotionLumBlock + * + * compute the luminance block resulting from motion compensation + * + * RETURNS: motionBlock modified + * + * SIDE EFFECTS: none + * + * PRECONDITION: the motion vectors must be valid! + * + *===========================================================================*/ +void +ComputeBMotionLumBlock(MpegFrame *prev, + MpegFrame *next, + int by, + int bx, + int mode, + int fmy, + int fmx, + int bmy, + int bmx, + LumBlock motionBlock) +{ + LumBlock prevBlock, nextBlock; + register int y, x; + + switch(mode) { + case MOTION_FORWARD: + ComputeMotionLumBlock(prev, by, bx, fmy, fmx, motionBlock); + break; + case MOTION_BACKWARD: + ComputeMotionLumBlock(next, by, bx, bmy, bmx, motionBlock); + break; + case MOTION_INTERPOLATE: + ComputeMotionLumBlock(prev, by, bx, fmy, fmx, prevBlock); + ComputeMotionLumBlock(next, by, bx, bmy, bmx, nextBlock); + + for ( y = 0; y < 16; y++ ) { + for ( x = 0; x < 16; x++ ) { + motionBlock[y][x] = (prevBlock[y][x]+nextBlock[y][x]+1)/2; + } + } + break; + default: + fprintf(stderr, "Bad mode!\nProgrammer error!\n"); + break; + + } +} + + +/*===========================================================================* + * + * EstimateSecondsPerBFrame + * + * estimate the seconds to compute a B-frame + * + * RETURNS: the time, in seconds + * + * SIDE EFFECTS: none + * + *===========================================================================*/ +float +EstimateSecondsPerBFrame() +{ + if ( numFrames == 0 ) { + return 20.0; + } else { + return (float)totalTime/((float)TIME_RATE*(float)numFrames); + } +} + + +/*=====================* + * INTERNAL PROCEDURES * + *=====================*/ + +/*===========================================================================* + * + * ComputeBMotionBlock + * + * compute the block resulting from motion compensation + * + * RETURNS: motionBlock is modified + * + * SIDE EFFECTS: none + * + * PRECONDITION: the motion vectors must be valid! + * + *===========================================================================*/ +static void +ComputeBMotionBlock(MpegFrame *prev, + MpegFrame *next, + int by, + int bx, + int mode, + int fmy, + int fmx, + int bmy, + int bmx, + Block motionBlock, + int type) +{ + Block prevBlock, nextBlock; + register int y, x; + + switch(mode) { + case MOTION_FORWARD: + if ( type == LUM_BLOCK ) { + ComputeMotionBlock(prev->ref_y, by, bx, fmy, fmx, motionBlock); + } else if ( type == CB_BLOCK ) { + ComputeMotionBlock(prev->ref_cb, by, bx, fmy, fmx, motionBlock); + } else if ( type == CR_BLOCK ) { + ComputeMotionBlock(prev->ref_cr, by, bx, fmy, fmx, motionBlock); + } + break; + case MOTION_BACKWARD: + if ( type == LUM_BLOCK ) { + ComputeMotionBlock(next->ref_y, by, bx, bmy, bmx, motionBlock); + } else if ( type == CB_BLOCK ) { + ComputeMotionBlock(next->ref_cb, by, bx, bmy, bmx, motionBlock); + } else if ( type == CR_BLOCK ) { + ComputeMotionBlock(next->ref_cr, by, bx, bmy, bmx, motionBlock); + } + break; + case MOTION_INTERPOLATE: + if ( type == LUM_BLOCK ) { + ComputeMotionBlock(prev->ref_y, by, bx, fmy, fmx, prevBlock); + ComputeMotionBlock(next->ref_y, by, bx, bmy, bmx, nextBlock); + } else if ( type == CB_BLOCK ) { + ComputeMotionBlock(prev->ref_cb, by, bx, fmy, fmx, prevBlock); + ComputeMotionBlock(next->ref_cb, by, bx, bmy, bmx, nextBlock); + } else if ( type == CR_BLOCK ) { + ComputeMotionBlock(prev->ref_cr, by, bx, fmy, fmx, prevBlock); + ComputeMotionBlock(next->ref_cr, by, bx, bmy, bmx, nextBlock); + } + + for ( y = 0; y < 8; y++ ) { + for ( x = 0; x < 8; x++ ) { + motionBlock[y][x] = (prevBlock[y][x]+nextBlock[y][x]+1)/2; + } + } + break; + } +} + + +/*===========================================================================* + * + * ComputeBDiffDCTs + * + * compute the DCT of the error term + * + * RETURNS: appropriate blocks of current will contain the DCTs + * + * SIDE EFFECTS: none + * + * PRECONDITION: the motion vectors must be valid! + * + *===========================================================================*/ +static void +ComputeBDiffDCTs(MpegFrame *current, + MpegFrame *prev, + MpegFrame *next, + int by, + int bx, + int mode, + int fmy, + int fmx, + int bmy, + int bmx, + int *pattern) +{ + Block motionBlock; + + if ( *pattern & 0x20 ) { + ComputeBMotionBlock(prev, next, by, bx, mode, fmy, fmx, + bmy, bmx, motionBlock, LUM_BLOCK); + if (! ComputeDiffDCTBlock(current->y_blocks[by][bx], dct[by][bx], motionBlock)) { + *pattern ^= 0x20; + } + } + + if ( *pattern & 0x10 ) { + ComputeBMotionBlock(prev, next, by, bx+1, mode, fmy, fmx, + bmy, bmx, motionBlock, LUM_BLOCK); + if (! ComputeDiffDCTBlock(current->y_blocks[by][bx+1], dct[by][bx+1], motionBlock)) { + *pattern ^= 0x10; + } + } + + if ( *pattern & 0x8 ) { + ComputeBMotionBlock(prev, next, by+1, bx, mode, fmy, fmx, + bmy, bmx, motionBlock, LUM_BLOCK); + if (! ComputeDiffDCTBlock(current->y_blocks[by+1][bx], dct[by+1][bx], motionBlock)) { + *pattern ^= 0x8; + } + } + + if ( *pattern & 0x4 ) { + ComputeBMotionBlock(prev, next, by+1, bx+1, mode, fmy, fmx, + bmy, bmx, motionBlock, LUM_BLOCK); + if (! ComputeDiffDCTBlock(current->y_blocks[by+1][bx+1], dct[by+1][bx+1], motionBlock)) { + *pattern ^= 0x4; + } + } + + if ( *pattern & 0x2 ) { + ComputeBMotionBlock(prev, next, by>>1, bx>>1, mode, fmy/2, fmx/2, + bmy/2, bmx/2, motionBlock, CB_BLOCK); + if (! ComputeDiffDCTBlock(current->cb_blocks[by >> 1][bx >> 1], dctb[by >> 1][bx >> 1], motionBlock)) { + *pattern ^= 0x2; + } + } + + if ( *pattern & 0x1 ) { + ComputeBMotionBlock(prev, next, by>>1, bx>>1, mode, fmy/2, fmx/2, + bmy/2, bmx/2, motionBlock, CR_BLOCK); + if (! ComputeDiffDCTBlock(current->cr_blocks[by >> 1][bx >> 1], dctr[by >> 1][bx >> 1], motionBlock)) { + *pattern ^= 0x1; + } + } +} + + +/*===========================================================================* + * + * USER-MODIFIABLE + * + * DoBIntraCode + * + * decides if this block should be coded as intra-block + * + * RETURNS: TRUE if intra-coding should be used; FALSE otherwise + * + * SIDE EFFECTS: none + * + * PRECONDITION: the motion vectors must be valid! + * + *===========================================================================*/ +static boolean +DoBIntraCode(MpegFrame *current, + MpegFrame *prev, + MpegFrame *next, + int by, + int bx, + int mode, + int fmy, + int fmx, + int bmy, + int bmx) +{ + int x, y; + int32 sum = 0, vard = 0, varc = 0, dif; + int32 currPixel, prevPixel; + LumBlock motionBlock; + int fy, fx; + + ComputeBMotionLumBlock(prev, next, by, bx, mode, fmy, fmx, + bmy, bmx, motionBlock); + + MOTION_TO_FRAME_COORD(by, bx, 0, 0, fy, fx); + + for ( y = 0; y < 16; y++ ) { + for ( x = 0; x < 16; x++ ) { + currPixel = current->orig_y[fy+y][fx+x]; + prevPixel = motionBlock[y][x]; + + sum += currPixel; + varc += currPixel*currPixel; + + dif = currPixel - prevPixel; + vard += dif*dif; + } + } + + vard >>= 8; /* divide by 256; assumes mean is close to zero */ + varc = (varc>>8) - (sum>>8)*(sum>>8); + + if ( vard <= 64 ) { + return FALSE; + } else if ( vard < varc ) { + return FALSE; + } else { + return TRUE; + } +} + +static int +ComputeBlockColorDiff(Block current, Block motionBlock) +{ + register int x, y, diff_total = 0, diff_tmp; + + for ( y = 0; y < 8; y++ ) { + for ( x = 0; x < 8; x++ ) { + diff_tmp = current[y][x] - motionBlock[y][x]; + diff_total += ABS(diff_tmp); + } + } + return diff_total; +} + +/*===========================================================================* + * + * USER-MODIFIABLE + * + * MotionSufficient + * + * decides if this motion vector is sufficient without DCT coding + * + * RETURNS: TRUE if no DCT is needed; FALSE otherwise + * + * SIDE EFFECTS: none + * + * PRECONDITION: the motion vectors must be valid! + * + *===========================================================================*/ +static boolean +MotionSufficient(MpegFrame *curr, + LumBlock currBlock, + MpegFrame *prev, + MpegFrame *next, + int by, int bx, + int mode, + int fmy, int fmx, + int bmy, int bmx) +{ + LumBlock mLumBlock; + Block mColorBlock; + int lumErr, colorErr; + + /* check bounds */ + if ( mode != MOTION_BACKWARD ) { + if ( (by*DCTSIZE+(fmy-1)/2 < 0) || ((by+2)*DCTSIZE+(fmy+1)/2-1 >= Fsize_y) ) { + return FALSE; + } + if ( (bx*DCTSIZE+(fmx-1)/2 < 0) || ((bx+2)*DCTSIZE+(fmx+1)/2-1 >= Fsize_x) ) { + return FALSE; + } + } + + if ( mode != MOTION_FORWARD ) { + if ( (by*DCTSIZE+(bmy-1)/2 < 0) || ((by+2)*DCTSIZE+(bmy+1)/2-1 >= Fsize_y) ) { + return FALSE; + } + if ( (bx*DCTSIZE+(bmx-1)/2 < 0) || ((bx+2)*DCTSIZE+(bmx+1)/2-1 >= Fsize_x) ) { + return FALSE; + } + } + + /* check Lum */ + ComputeBMotionLumBlock(prev, next, by, bx, mode, fmy, fmx, + bmy, bmx, mLumBlock); + lumErr = LumBlockMAD(currBlock, mLumBlock, 0x7fffffff); + if (lumErr > 512) { + return FALSE; + } + + /* check color */ + ComputeBMotionBlock(prev, next, by>>1, bx>>1, mode, fmy/2, fmx/2, + bmy/2, bmx/2, mColorBlock, CR_BLOCK); + colorErr = ComputeBlockColorDiff(curr->cr_blocks[by >> 1][bx >> 1], mColorBlock); + ComputeBMotionBlock(prev, next, by>>1, bx>>1, mode, fmy/2, fmx/2, + bmy/2, bmx/2, mColorBlock, CB_BLOCK); + colorErr += ComputeBlockColorDiff(curr->cr_blocks[by >> 1][bx >> 1], mColorBlock); + + return (colorErr < 256); /* lumErr checked above */ +} + + diff --git a/contrib/mpeg_encode/bitio.cpp b/contrib/mpeg_encode/bitio.cpp new file mode 100644 index 0000000000000000000000000000000000000000..8e33c7d35237edb63f5c4f6b4c9fac31f1937633 --- /dev/null +++ b/contrib/mpeg_encode/bitio.cpp @@ -0,0 +1,471 @@ +/*===========================================================================* + * bitio.c * + * * + * Procedures concerned with the bit-wise I/O * + * * + * EXPORTED PROCEDURES: * + * Bitio_New * + * Bitio_Free * + * Bitio_Write * + * Bitio_Flush * + * Bitio_WriteToSocket * + * Bitio_BytePad * + * * + *===========================================================================*/ + +/* + * Copyright (c) 1995 The Regents of the University of California. + * All rights reserved. + * + * Permission to use, copy, modify, and distribute this software and its + * documentation for any purpose, without fee, and without written agreement is + * hereby granted, provided that the above copyright notice and the following + * two paragraphs appear in all copies of this software. + * + * IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR + * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT + * OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF + * CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS + * ON AN "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO + * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. + */ + +/* + * $Header: /n/picasso/project/mm/mpeg/mpeg_dist/mpeg_encode/RCS/bitio.c,v 1.13 1995/06/21 18:36:06 smoot Exp $ + * $Log: bitio.c,v $ + * Revision 1.13 1995/06/21 18:36:06 smoot + * added a flush when done with file + * + * Revision 1.12 1995/01/19 23:07:15 eyhung + * Changed copyrights + * + * Revision 1.11 1994/11/12 02:11:43 keving + * nothing + * + * Revision 1.10 1993/12/22 19:19:01 keving + * nothing + * + * Revision 1.10 1993/12/22 19:19:01 keving + * nothing + * + * Revision 1.9 1993/07/22 22:23:43 keving + * nothing + * + * Revision 1.8 1993/06/30 20:06:09 keving + * nothing + * + * Revision 1.7 1993/06/03 21:08:08 keving + * nothing + * + * Revision 1.6 1993/02/17 23:21:41 dwallach + * checkin prior to keving's joining the project + * + * Revision 1.5 1993/01/18 10:20:02 dwallach + * *** empty log message *** + * + * Revision 1.4 1993/01/18 10:17:29 dwallach + * RCS headers installed, code indented uniformly + * + * Revision 1.4 1993/01/18 10:17:29 dwallach + * RCS headers installed, code indented uniformly + * + */ + +/*==============* + * HEADER FILES * + *==============*/ + +#include <assert.h> +#include <time.h> +#include <stdio.h> +#include "all.h" +#include "byteorder.h" +#include "bitio.h" +#include "mtypes.h" + + +/*===============================* + * INTERNAL PROCEDURE prototypes * + *===============================*/ + +static void Dump _ANSI_ARGS_((BitBucket *bbPtr)); + + +/*==================* + * STATIC VARIABLES * + *==================*/ + +static uint32 lower_mask[33] = { + 0, + 0x1, 0x3, 0x7, 0xf, + 0x1f, 0x3f, 0x7f, 0xff, + 0x1ff, 0x3ff, 0x7ff, 0xfff, + 0x1fff, 0x3fff, 0x7fff, 0xffff, + 0x1ffff, 0x3ffff, 0x7ffff, 0xfffff, + 0x1fffff, 0x3fffff, 0x7fffff, 0xffffff, + 0x1ffffff, 0x3ffffff, 0x7ffffff, 0xfffffff, + 0x1fffffff, 0x3fffffff, 0x7fffffff, 0xffffffff +}; + + +extern time_t IOtime; + + +/*=====================* + * EXPORTED PROCEDURES * + *=====================*/ + + +/*===========================================================================* + * + * Bitio_New + * + * Create a new bit bucket; filePtr is a pointer to the open file the + * bits should ultimately be written to. + * + * RETURNS: pointer to the resulting bit bucket + * + * SIDE EFFECTS: none + * + *===========================================================================*/ +BitBucket * +Bitio_New(FILE *filePtr) +{ + BitBucket *bbPtr; + + bbPtr = (BitBucket *) malloc(sizeof(BitBucket)); + ERRCHK(bbPtr, "malloc"); + + bbPtr->firstPtr = bbPtr->lastPtr = (struct bitBucket *) malloc(sizeof(struct bitBucket)); + ERRCHK(bbPtr->firstPtr, "malloc"); + + bbPtr->totalbits = 0; + bbPtr->cumulativeBits = 0; + bbPtr->bitsWritten = 0; + bbPtr->filePtr = filePtr; + + bbPtr->firstPtr->nextPtr = NULL; + bbPtr->firstPtr->bitsleft = MAXBITS_PER_BUCKET; + bbPtr->firstPtr->bitsleftcur = 32; + bbPtr->firstPtr->currword = 0; + memset((char *)bbPtr->firstPtr->bits, 0, sizeof(uint32) * WORDS_PER_BUCKET); + + return bbPtr; +} + + +/*===========================================================================* + * + * Bitio_Free + * + * Frees the memory associated with the given bit bucket + * + * RETURNS: nothing + * + * SIDE EFFECTS: none + * + *===========================================================================*/ +void +Bitio_Free(BitBucket *bbPtr) +{ + struct bitBucket *tmpPtr, *nextPtr; + + for (tmpPtr = bbPtr->firstPtr; tmpPtr != NULL; tmpPtr = nextPtr) { + nextPtr = tmpPtr->nextPtr; + free(tmpPtr); + } + free(bbPtr); +} + + +/*===========================================================================* + * + * Bitio_Write + * + * Writes 'nbits' bits from 'bits' into the given bit bucket + * 'nbits' must be between 0 and 32 + * + * RETURNS: nothing + * + * SIDE EFFECTS: if the number of bits in the bit bucket surpasses + * MAX_BITS, then that many bits are flushed to the + * appropriate output file + * + *===========================================================================*/ +void +Bitio_Write(BitBucket *bbPtr, + uint32 bits, + int nbits) +{ + register struct bitBucket *lastPtr, *newPtr; + register int delta; + + assert(nbits <= 32 && nbits >= 0); + + /* + * Clear top bits if not part of data, necessary due to down and + * dirty calls of Bitio_Write with unecessary top bits set. + */ + + bits = bits & lower_mask[nbits]; + + bbPtr->totalbits += nbits; + bbPtr->cumulativeBits += nbits; + lastPtr = bbPtr->lastPtr; + + delta = nbits - lastPtr->bitsleft; + if (delta >= 0) { + /* + * there's not enough room in the current bucket, so we're + * going to have to allocate another bucket + */ + newPtr = lastPtr->nextPtr = (struct bitBucket *) malloc(sizeof(struct bitBucket)); + ERRCHK(newPtr, "malloc"); + newPtr->nextPtr = NULL; + newPtr->bitsleft = MAXBITS_PER_BUCKET; + newPtr->bitsleftcur = 32; + newPtr->currword = 0; + memset((char *)newPtr->bits, 0, sizeof(uint32) * WORDS_PER_BUCKET); + bbPtr->lastPtr = newPtr; + + assert(lastPtr->currword == WORDS_PER_BUCKET - 1); + lastPtr->bits[WORDS_PER_BUCKET - 1] |= (bits >> delta); + lastPtr->bitsleft = 0; + lastPtr->bitsleftcur = 0; + /* lastPtr->currword++; */ + + if (!delta) { + if ( bbPtr->totalbits > MAX_BITS ) { + Dump(bbPtr); + } + } + + assert(delta <= 32); + newPtr->bits[0] = (bits & lower_mask[delta]) << (32 - delta); + newPtr->bitsleft -= delta; + newPtr->bitsleftcur -= delta; + } else { + /* + * the current bucket will be sufficient + */ + delta = nbits - lastPtr->bitsleftcur; + lastPtr->bitsleftcur -= nbits; + lastPtr->bitsleft -= nbits; + + if (delta >= 0) + { + /* + * these bits will span more than one word + */ + lastPtr->bits[lastPtr->currword] |= (bits >> delta); + lastPtr->currword++; + lastPtr->bits[lastPtr->currword] = (bits & lower_mask[delta]) << (32 - delta); + lastPtr->bitsleftcur = 32 - delta; + } else { + /* + * these bits will fit, whole + */ + lastPtr->bits[lastPtr->currword] |= (bits << (-delta)); + } + } + + if ( bbPtr->totalbits > MAX_BITS ) /* flush bits */ + Dump(bbPtr); +} + + +/*===========================================================================* + * + * Bitio_Flush + * + * Flushes all of the remaining bits in the given bit bucket to the + * appropriate output file. It will generate up to the nearest 8-bit + * unit of bits, which means that up to 7 extra 0 bits will be appended + * to the end of the file. + * + * RETURNS: nothing + * + * SIDE EFFECTS: frees the bit bucket + * + *===========================================================================*/ +void +Bitio_Flush(BitBucket *bbPtr) +{ + struct bitBucket *ptr, *tempPtr; + uint32 buffer[WORDS_PER_BUCKET]; + uint32 lastWord; + int i, nitems; + int bitsWritten = 0; + int bitsLeft; + int numWords; + uint8 charBuf[4]; + boolean flushHere = FALSE; + time_t tempTimeStart, tempTimeEnd; + + time(&tempTimeStart); + + bitsLeft = bbPtr->totalbits; + + for (ptr = bbPtr->firstPtr; ptr; ptr = ptr->nextPtr) { + if (ptr->bitsleftcur == 32 && ptr->currword == 0) { + continue; /* empty */ + } + + if ( bitsLeft >= 32 ) { + if ( ((ptr->currword + 1) * 32) > bitsLeft ) { + numWords = ptr->currword; + flushHere = TRUE; + } else { + numWords = ptr->currword+1; + } + + for (i = 0; i < numWords; i++) { + buffer[i] = htonl(ptr->bits[i]); + } + + nitems = fwrite(buffer, sizeof(uint32), numWords, bbPtr->filePtr); + if (nitems != numWords) { + throw "Whoa! Trouble writing bytes"; + } + + bitsWritten += (numWords * 32); + bitsLeft -= (numWords * 32); + } else { + flushHere = TRUE; + } + + if ( (bitsLeft < 32) && flushHere ) { + lastWord = ptr->bits[ptr->currword]; + + /* output the lastPtr word in big-endian order (network) */ + + /* now write out lastPtr bits */ + while ( bitsLeft > 0 ) { + charBuf[0] = (lastWord >> 24); + charBuf[0] &= lower_mask[8]; + fwrite(charBuf, 1, sizeof(uint8), bbPtr->filePtr); + lastWord = (lastWord << 8); + bitsLeft -= 8; + bitsWritten += 8; + } + } + } + fflush(bbPtr->filePtr); + while ( bbPtr->firstPtr != ptr ) { + tempPtr = bbPtr->firstPtr; + bbPtr->firstPtr = tempPtr->nextPtr; + free(tempPtr); + } + + free(bbPtr); + + time(&tempTimeEnd); + IOtime += (tempTimeEnd-tempTimeStart); +} + + +/*===========================================================================* + * + * Bitio_WriteToSocket + * + * Writes all of the remaining bits in the given bit bucket to the + * given socket. May pad the end of the socket stream with extra 0 + * bits as does Bitio_Flush. + * + * RETURNS: nothing + * + * SIDE EFFECTS: frees the bit bucket + * + *===========================================================================*/ +void +Bitio_WriteToSocket(BitBucket *bbPtr, + int socket) +{ + throw "WriteToSocket not implemented"; +} + + +/*===========================================================================* + * + * Bitio_BytePad + * + * Pads the end of the bit bucket to the nearest byte with 0 bits + * + * RETURNS: nothing + * + *===========================================================================*/ +void +Bitio_BytePad(BitBucket *bbPtr) +{ + struct bitBucket *lastPtrPtr = bbPtr->lastPtr; + + if (lastPtrPtr->bitsleftcur % 8) { + Bitio_Write(bbPtr, 0, lastPtrPtr->bitsleftcur % 8); + } +} + + +/*=====================* + * INTERNAL PROCEDURES * + *=====================*/ + + +/*===========================================================================* + * + * Dump + * + * Writes out the first MAX_BITS bits of the bit bucket to the + * appropriate output file + * + * RETURNS: nothing + * + * SIDE EFFECTS: none + * + *===========================================================================*/ +static void +Dump(BitBucket *bbPtr) +{ + struct bitBucket *ptr, *tempPtr; + uint32 buffer[WORDS_PER_BUCKET]; + int i, nitems; + int bitsWritten = 0; + time_t tempTimeStart, tempTimeEnd; + + time(&tempTimeStart); + + for (ptr = bbPtr->firstPtr; ptr && (bitsWritten < MAX_BITS); + ptr = ptr->nextPtr) { + if (ptr->bitsleftcur == 32 && ptr->currword == 0) { + continue; /* empty */ + } + + for (i = 0; i <= ptr->currword; i++) { + buffer[i] = htonl(ptr->bits[i]); + } + + nitems = fwrite((uint8 *)buffer, sizeof(uint32), (ptr->currword + 1), bbPtr->filePtr); + if (nitems != (ptr->currword+1)) { + throw "Whoa! Trouble writing bytes"; + } + + bitsWritten += ((ptr->currword + 1) * 32); + } + + while ( bbPtr->firstPtr != ptr ) { + tempPtr = bbPtr->firstPtr; + bbPtr->firstPtr = tempPtr->nextPtr; + free(tempPtr); + } + + bbPtr->totalbits -= bitsWritten; + bbPtr->bitsWritten += bitsWritten; + + time(&tempTimeEnd); + IOtime += (tempTimeEnd-tempTimeStart); +} + + diff --git a/contrib/mpeg_encode/block.cpp b/contrib/mpeg_encode/block.cpp new file mode 100644 index 0000000000000000000000000000000000000000..2997e54322dfa7a51b9897f2780b89f0c1cf4275 --- /dev/null +++ b/contrib/mpeg_encode/block.cpp @@ -0,0 +1,1224 @@ +/*===========================================================================* + * block.c * + * * + * Block routines * + * * + * EXPORTED PROCEDURES: * + * ComputeDiffDCTBlock * + * ComputeDiffDCTs * + * ComputeMotionBlock * + * ComputeMotionLumBlock * + * LumBlockMAD * + * LumMotionError * + * LumMotionErrorSubSampled * + * LumAddMotionError * + * AddMotionBlock * + * BlockToData * + * BlockifyFrame * + * * + * NOTES: MAD = Mean Absolute Difference * + * * + *===========================================================================*/ + +/* + * Copyright (c) 1995 The Regents of the University of California. + * All rights reserved. + * + * Permission to use, copy, modify, and distribute this software and its + * documentation for any purpose, without fee, and without written agreement is + * hereby granted, provided that the above copyright notice and the following + * two paragraphs appear in all copies of this software. + * + * IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR + * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT + * OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF + * CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS + * ON AN "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO + * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. + */ + +/* + * $Header: /n/picasso/project/mpeg/mpeg_dist/mpeg_encode/RCS/block.c,v 1.16 1995/08/07 21:43:29 smoot Exp $ + * $Log: block.c,v $ + * Revision 1.16 1995/08/07 21:43:29 smoot + * restructured lumdiff so it read better and used a switch instead of ifs + * + * Revision 1.15 1995/06/21 22:21:16 smoot + * added TUNEing options + * + * Revision 1.14 1995/05/08 22:47:45 smoot + * typechecking better + * + * Revision 1.13 1995/05/08 22:44:14 smoot + * added prototypes (postdct.h) + * + * Revision 1.12 1995/05/02 21:44:07 smoot + * added tuneing parameters + * + * Revision 1.11 1995/03/31 23:50:45 smoot + * removed block bound (moved to opts.c) + * + * Revision 1.10 1995/03/29 20:12:39 smoot + * added block_bound for TUNEing + * + * Revision 1.9 1995/02/01 21:43:55 smoot + * cleanup + * + * Revision 1.8 1995/01/19 23:52:43 smoot + * Made computeDiffDCTs able to rule out changes to the pattern (diff too small) + * + * Revision 1.7 1995/01/19 23:07:17 eyhung + * Changed copyrights + * + * Revision 1.6 1994/11/12 02:11:44 keving + * nothing + * + * Revision 1.5 1993/12/22 19:19:01 keving + * nothing + * + * Revision 1.5 1993/12/22 19:19:01 keving + * nothing + * + * Revision 1.4 1993/07/22 22:23:43 keving + * nothing + * + * Revision 1.3 1993/06/30 20:06:09 keving + * nothing + * + * Revision 1.2 1993/06/03 21:08:08 keving + * nothing + * + * Revision 1.1 1993/04/08 21:31:59 keving + * nothing + * + */ + + +/*==============* + * HEADER FILES * + *==============*/ + +#include "all.h" +#include "mtypes.h" +#include "frames.h" +#include "bitio.h" +#include "prototypes.h" +#include "fsize.h" +#include "opts.h" +#include "postdct.h" + +#undef ABS +#define ABS(x) ((x < 0) ? (-x) : x) + +#define TRUNCATE_UINT8(x) ((x < 0) ? 0 : ((x > 255) ? 255 : x)) + +/*==================* + * GLOBAL VARIABLES * + *==================*/ + + +extern Block **dct, **dctb, **dctr; + +/*===========================* + * COMPUTE DCT OF DIFFERENCE * + *===========================*/ + +/*===========================================================================* + * + * ComputeDiffDCTBlock + * + * compute current-motionBlock, take the DCT, and put the difference + * back into current + * + * RETURNS: current block modified + * + * SIDE EFFECTS: none + * + *===========================================================================*/ +boolean +ComputeDiffDCTBlock(Block current, Block dest, Block motionBlock) +{ + register int x, y, diff = 0; + + for ( y = 0; y < 8; y++ ) { + for ( x = 0; x < 8; x++ ) { + current[y][x] -= motionBlock[y][x]; + diff += ABS(current[y][x]); + } + } + /* Kill the block if change is too small */ + /* (block_bound defaults to 128, see opts.c) */ + if (diff < block_bound) return FALSE; + + mp_fwd_dct_block2(current, dest); + + return TRUE; +} + +/*===========================================================================* + * + * ComputeDiffDCTs + * + * appropriate (according to pattern, the coded block pattern) blocks + * of 'current' are diff'ed and DCT'd. + * + * RETURNS: current blocks modified + * + * SIDE EFFECTS: Can remove too-small difference blocks from pattern + * + * PRECONDITIONS: appropriate blocks of 'current' have not yet been + * modified + * + *===========================================================================*/ +void +ComputeDiffDCTs(MpegFrame *current, + MpegFrame *prev, + int by, + int bx, + int my, + int mx, + int *pattern) +{ + Block motionBlock; + + if (collect_quant && (collect_quant_detailed & 1)) fprintf(collect_quant_fp, "l\n"); + if ( *pattern & 0x20 ) { + ComputeMotionBlock(prev->ref_y, by, bx, my, mx, motionBlock); + if (!ComputeDiffDCTBlock(current->y_blocks[by][bx], dct[by][bx], motionBlock)) + *pattern^=0x20; + } + + if ( *pattern & 0x10 ) { + ComputeMotionBlock(prev->ref_y, by, bx+1, my, mx, motionBlock); + if (!ComputeDiffDCTBlock(current->y_blocks[by][bx+1], dct[by][bx+1], motionBlock)) + *pattern^=0x10; + } + + if ( *pattern & 0x8 ) { + ComputeMotionBlock(prev->ref_y, by+1, bx, my, mx, motionBlock); + if (!ComputeDiffDCTBlock(current->y_blocks[by+1][bx], dct[by+1][bx], motionBlock)) + *pattern^=0x8; + } + + if ( *pattern & 0x4 ) { + ComputeMotionBlock(prev->ref_y, by+1, bx+1, my, mx, motionBlock); + if (!ComputeDiffDCTBlock(current->y_blocks[by+1][bx+1], dct[by+1][bx+1], motionBlock)) + *pattern^=0x4; + } + + if (collect_quant && (collect_quant_detailed & 1)) fprintf(collect_quant_fp, "c\n"); + if ( *pattern & 0x2 ) { + ComputeMotionBlock(prev->ref_cb, by >> 1, bx >> 1, my/2, mx/2, motionBlock); + if (!ComputeDiffDCTBlock(current->cb_blocks[by >> 1][bx >> 1], dctb[by >> 1][bx >> 1], motionBlock)) + *pattern^=0x2; + } + + if ( *pattern & 0x1 ) { + ComputeMotionBlock(prev->ref_cr, by >> 1, bx >> 1, my/2, mx/2, motionBlock); + if (!ComputeDiffDCTBlock(current->cr_blocks[by >> 1][bx >> 1], dctr[by >> 1][bx >> 1], motionBlock)) + *pattern^=0x1; + } +} + + + /*======================* + * COMPUTE MOTION BLOCK * + *======================*/ + +/*===========================================================================* + * + * ComputeMotionBlock + * + * compute the motion-compensated block + * + * RETURNS: motionBlock + * + * SIDE EFFECTS: none + * + * PRECONDITIONS: motion vector MUST be valid + * + * NOTE: could try to speed this up using halfX, halfY, halfBoth, + * but then would have to compute for chrominance, and it's just + * not worth the trouble (this procedure is not called relatively + * often -- a constant number of times per macroblock) + * + *===========================================================================*/ +void +ComputeMotionBlock(uint8 **prev, + int by, + int bx, + int my, + int mx, + Block motionBlock) +{ + register int fy, fx; + register int y; + register int16 *destPtr; + register uint8 *srcPtr; + register uint8 *srcPtr2; + boolean xHalf, yHalf; + + xHalf = (ABS(mx) % 2 == 1); + yHalf = (ABS(my) % 2 == 1); + + MOTION_TO_FRAME_COORD(by, bx, (my/2), (mx/2), fy, fx); + + if ( xHalf && yHalf ) { + /* really should be fy+y-1 and fy+y so do (fy-1)+y = fy+y-1 and + (fy-1)+y+1 = fy+y + */ + if ( my < 0 ) { + fy--; + } + if ( mx < 0 ) { + fx--; + } + + for ( y = 0; y < 8; y++ ) { + destPtr = motionBlock[y]; + srcPtr = &(prev[fy+y][fx]); + srcPtr2 = &(prev[fy+y+1][fx]); + + destPtr[0] = (srcPtr[0]+srcPtr[1]+srcPtr2[0]+srcPtr2[1]+2)>>2; + destPtr[1] = (srcPtr[1]+srcPtr[2]+srcPtr2[1]+srcPtr2[2]+2)>>2; + destPtr[2] = (srcPtr[2]+srcPtr[3]+srcPtr2[2]+srcPtr2[3]+2)>>2; + destPtr[3] = (srcPtr[3]+srcPtr[4]+srcPtr2[3]+srcPtr2[4]+2)>>2; + destPtr[4] = (srcPtr[4]+srcPtr[5]+srcPtr2[4]+srcPtr2[5]+2)>>2; + destPtr[5] = (srcPtr[5]+srcPtr[6]+srcPtr2[5]+srcPtr2[6]+2)>>2; + destPtr[6] = (srcPtr[6]+srcPtr[7]+srcPtr2[6]+srcPtr2[7]+2)>>2; + destPtr[7] = (srcPtr[7]+srcPtr[8]+srcPtr2[7]+srcPtr2[8]+2)>>2; + } + } else if ( xHalf ) { + if ( mx < 0 ) { + fx--; + } + + for ( y = 0; y < 8; y++ ) { + destPtr = motionBlock[y]; + srcPtr = &(prev[fy+y][fx]); + + destPtr[0] = (srcPtr[0]+srcPtr[1]+1)>>1; + destPtr[1] = (srcPtr[1]+srcPtr[2]+1)>>1; + destPtr[2] = (srcPtr[2]+srcPtr[3]+1)>>1; + destPtr[3] = (srcPtr[3]+srcPtr[4]+1)>>1; + destPtr[4] = (srcPtr[4]+srcPtr[5]+1)>>1; + destPtr[5] = (srcPtr[5]+srcPtr[6]+1)>>1; + destPtr[6] = (srcPtr[6]+srcPtr[7]+1)>>1; + destPtr[7] = (srcPtr[7]+srcPtr[8]+1)>>1; + } + } else if ( yHalf ) { + if ( my < 0 ) { + fy--; + } + + for ( y = 0; y < 8; y++ ) { + destPtr = motionBlock[y]; + srcPtr = &(prev[fy+y][fx]); + srcPtr2 = &(prev[fy+y+1][fx]); + + destPtr[0] = (srcPtr[0]+srcPtr2[0]+1)>>1; + destPtr[1] = (srcPtr[1]+srcPtr2[1]+1)>>1; + destPtr[2] = (srcPtr[2]+srcPtr2[2]+1)>>1; + destPtr[3] = (srcPtr[3]+srcPtr2[3]+1)>>1; + destPtr[4] = (srcPtr[4]+srcPtr2[4]+1)>>1; + destPtr[5] = (srcPtr[5]+srcPtr2[5]+1)>>1; + destPtr[6] = (srcPtr[6]+srcPtr2[6]+1)>>1; + destPtr[7] = (srcPtr[7]+srcPtr2[7]+1)>>1; + } + } else { + for ( y = 0; y < 8; y++ ) { + destPtr = motionBlock[y]; + srcPtr = &(prev[fy+y][fx]); + + destPtr[0] = (uint8) srcPtr[0]; + destPtr[1] = (uint8) srcPtr[1]; + destPtr[2] = (uint8) srcPtr[2]; + destPtr[3] = (uint8) srcPtr[3]; + destPtr[4] = (uint8) srcPtr[4]; + destPtr[5] = (uint8) srcPtr[5]; + destPtr[6] = (uint8) srcPtr[6]; + destPtr[7] = (uint8) srcPtr[7]; + } + } +} + + +/*===========================================================================* + * + * ComputeMotionLumBlock + * + * compute the motion-compensated luminance block + * + * RETURNS: motionBlock + * + * SIDE EFFECTS: none + * + * PRECONDITIONS: motion vector MUST be valid + * + * NOTE: see ComputeMotionBlock + * + *===========================================================================*/ +void +ComputeMotionLumBlock(MpegFrame *prevFrame, + int by, + int bx, + int my, + int mx, + LumBlock motionBlock) +{ + register uint8 *across; + register int32 *macross; + register int y; + uint8 **prev; + int fy, fx; + boolean xHalf, yHalf; + + xHalf = (ABS(mx) % 2 == 1); + yHalf = (ABS(my) % 2 == 1); + + MOTION_TO_FRAME_COORD(by, bx, my/2, mx/2, fy, fx); + + if ( xHalf ) { + if ( mx < 0 ) { + fx--; + } + + if ( yHalf ) { + if ( my < 0 ) { + fy--; + } + + prev = prevFrame->halfBoth; + } else { + prev = prevFrame->halfX; + } + } else if ( yHalf ) { + if ( my < 0 ) { + fy--; + } + + prev = prevFrame->halfY; + } else { + prev = prevFrame->ref_y; + } + + for ( y = 0; y < 16; y++ ) { + across = &(prev[fy+y][fx]); + macross = motionBlock[y]; + + macross[0] = across[0]; + macross[1] = across[1]; + macross[2] = across[2]; + macross[3] = across[3]; + macross[4] = across[4]; + macross[5] = across[5]; + macross[6] = across[6]; + macross[7] = across[7]; + macross[8] = across[8]; + macross[9] = across[9]; + macross[10] = across[10]; + macross[11] = across[11]; + macross[12] = across[12]; + macross[13]= across[13]; + macross[14] = across[14]; + macross[15] = across[15]; + } + + /* this is what's really happening, in slow motion: + * + * for ( y = 0; y < 16; y++, py++ ) + * for ( x = 0; x < 16; x++, px++ ) + * motionBlock[y][x] = prev[fy+y][fx+x]; + * + */ +} + + +/*=======================* + * BASIC ERROR FUNCTIONS * + *=======================*/ + + +/*===========================================================================* + * + * LumBlockMAD + * + * return the MAD of two luminance blocks + * + * RETURNS: the MAD, if less than bestSoFar, or + * some number bigger if not + * + * SIDE EFFECTS: none + * + *===========================================================================*/ +int32 +LumBlockMAD(LumBlock currentBlock, + LumBlock motionBlock, + int32 bestSoFar) +{ + register int32 diff = 0; /* max value of diff is 255*256 = 65280 */ + register int32 localDiff; + register int y, x; + + for ( y = 0; y < 16; y++ ) { + for ( x = 0; x < 16; x++ ) { + localDiff = currentBlock[y][x] - motionBlock[y][x]; + diff += ABS(localDiff); + } + + if ( diff > bestSoFar ) { + return diff; + } + } + + return (int32)diff; +} + + +/*===========================================================================* + * + * LumMotionError + * + * return the MAD of the currentBlock and the motion-compensated block + * (without TUNEing) + * + * RETURNS: the MAD, if less than bestSoFar, or + * some number bigger if not + * + * SIDE EFFECTS: none + * + * PRECONDITIONS: motion vector MUST be valid + * + * NOTES: this is the procedure that is called the most, and should therefore + * be the most optimized!!! + * + *===========================================================================*/ +int32 +LumMotionError(LumBlock currentBlock, + MpegFrame *prevFrame, + int by, + int bx, + int my, + int mx, + int32 bestSoFar) +{ + register int32 adiff = 0, diff = 0; /* max value of diff is 255*256 = 65280 */ + register int32 localDiff; + register uint8 *across; + register int32 *cacross; + register int y; + uint8 **prev; + int fy, fx; + boolean xHalf, yHalf; + + xHalf = (ABS(mx) % 2 == 1); + yHalf = (ABS(my) % 2 == 1); + + MOTION_TO_FRAME_COORD(by, bx, my/2, mx/2, fy, fx); + + if ( xHalf ) { + if ( mx < 0 ) { + fx--; + } + + if ( yHalf ) { + if ( my < 0 ) { + fy--; + } + + prev = prevFrame->halfBoth; + } else { + prev = prevFrame->halfX; + } + } else if ( yHalf ) { + if ( my < 0 ) { + fy--; + } + + prev = prevFrame->halfY; + } else { + prev = prevFrame->ref_y; + } + + switch (SearchCompareMode) { + case DEFAULT_SEARCH: /* Default. */ + /* this is what's happening: + * ComputeMotionLumBlock(prevFrame, by, bx, my, mx, lumMotionBlock); + * for ( y = 0; y < 16; y++ ) + * for ( x = 0; x < 16; x++ ) + * { + * localDiff = currentBlock[y][x] - lumMotionBlock[y][x]; + * diff += ABS(localDiff); + * } + */ + for ( y = 0; y < 16; y++ ) { + across = &(prev[fy+y][fx]); + cacross = currentBlock[y]; + + localDiff = across[0]-cacross[0]; diff += ABS(localDiff); + localDiff = across[1]-cacross[1]; diff += ABS(localDiff); + localDiff = across[2]-cacross[2]; diff += ABS(localDiff); + localDiff = across[3]-cacross[3]; diff += ABS(localDiff); + localDiff = across[4]-cacross[4]; diff += ABS(localDiff); + localDiff = across[5]-cacross[5]; diff += ABS(localDiff); + localDiff = across[6]-cacross[6]; diff += ABS(localDiff); + localDiff = across[7]-cacross[7]; diff += ABS(localDiff); + localDiff = across[8]-cacross[8]; diff += ABS(localDiff); + localDiff = across[9]-cacross[9]; diff += ABS(localDiff); + localDiff = across[10]-cacross[10]; diff += ABS(localDiff); + localDiff = across[11]-cacross[11]; diff += ABS(localDiff); + localDiff = across[12]-cacross[12]; diff += ABS(localDiff); + localDiff = across[13]-cacross[13]; diff += ABS(localDiff); + localDiff = across[14]-cacross[14]; diff += ABS(localDiff); + localDiff = across[15]-cacross[15]; diff += ABS(localDiff); + + if ( diff > bestSoFar ) { + return diff; + } + } + break; + + case LOCAL_DCT: { + Block dctdiff[4], dctquant[4]; + FlatBlock quant; + int x, i, tmp; + int distortion=0, datarate=0; + int pq = GetPQScale(); + + for (y = 0; y < 16; y++) { + across = &(prev[fy+y][fx]); + cacross = currentBlock[y]; + for (x = 0; x < 16; x++) { + dctdiff[(x>7)+2*(y>7)][y%8][x%8] = cacross[x]-across[x]; + }} + + /* Calculate rate */ + for (i = 0; i < 4; i++) { + mp_fwd_dct_block2(dctdiff[i], dctdiff[i]); + if (Mpost_QuantZigBlock(dctdiff[i], quant, pq, FALSE) == MPOST_ZERO) { + /* no sense in continuing */ + memset((char *)dctquant[i], 0, sizeof(Block)); + } else { + Mpost_UnQuantZigBlock(quant, dctquant[i], pq, FALSE); + mpeg_jrevdct((int16 *)dctquant[i]); + datarate += CalcRLEHuffLength(quant); + } + } + + /* Calculate distortion */ + for (y = 0; y < 16; y++) { + across = &(prev[fy+y][fx]); + cacross = currentBlock[y]; + for (x = 0; x < 16; x++) { + tmp = across[x] - cacross[x] + dctquant[(x>7)+2*(y>7)][y%8][x%8]; + distortion += tmp*tmp; + }} + distortion /= 256; + distortion *= LocalDCTDistortScale; + datarate *= LocalDCTRateScale; + diff = (int) sqrt(distortion*distortion + datarate*datarate); + break; + } + + case NO_DC_SEARCH: { + extern int32 niqtable[]; + int pq = niqtable[0]*GetPQScale(); + + for ( y = 0; y < 16; y++ ) { + across = &(prev[fy+y][fx]); + cacross = currentBlock[y]; + + localDiff = across[0]-cacross[0]; diff += localDiff; adiff += ABS(localDiff); + localDiff = across[1]-cacross[1]; diff += localDiff; adiff += ABS(localDiff); + localDiff = across[2]-cacross[2]; diff += localDiff; adiff += ABS(localDiff); + localDiff = across[3]-cacross[3]; diff += localDiff; adiff += ABS(localDiff); + localDiff = across[4]-cacross[4]; diff += localDiff; adiff += ABS(localDiff); + localDiff = across[5]-cacross[5]; diff += localDiff; adiff += ABS(localDiff); + localDiff = across[6]-cacross[6]; diff += localDiff; adiff += ABS(localDiff); + localDiff = across[7]-cacross[7]; diff += localDiff; adiff += ABS(localDiff); + localDiff = across[8]-cacross[8]; diff += localDiff; adiff += ABS(localDiff); + localDiff = across[9]-cacross[9]; diff += localDiff; adiff += ABS(localDiff); + localDiff = across[10]-cacross[10]; diff += localDiff; adiff += ABS(localDiff); + localDiff = across[11]-cacross[11]; diff += localDiff; adiff += ABS(localDiff); + localDiff = across[12]-cacross[12]; diff += localDiff; adiff += ABS(localDiff); + localDiff = across[13]-cacross[13]; diff += localDiff; adiff += ABS(localDiff); + localDiff = across[14]-cacross[14]; diff += localDiff; adiff += ABS(localDiff); + localDiff = across[15]-cacross[15]; diff += localDiff; adiff += ABS(localDiff); + + } + + diff /= 64*pq; /* diff is now the DC difference (with QSCALE 1) */ + adiff -= 64*pq*ABS(diff); + diff = adiff; + } + break; + + case DO_Mean_Squared_Distortion: + for ( y = 0; y < 16; y++ ) { + across = &(prev[fy+y][fx]); + cacross = currentBlock[y]; + + localDiff = across[0]-cacross[0]; diff += localDiff*localDiff; + localDiff = across[1]-cacross[1]; diff += localDiff*localDiff; + localDiff = across[2]-cacross[2]; diff += localDiff*localDiff; + localDiff = across[3]-cacross[3]; diff += localDiff*localDiff; + localDiff = across[4]-cacross[4]; diff += localDiff*localDiff; + localDiff = across[5]-cacross[5]; diff += localDiff*localDiff; + localDiff = across[6]-cacross[6]; diff += localDiff*localDiff; + localDiff = across[7]-cacross[7]; diff += localDiff*localDiff; + localDiff = across[8]-cacross[8]; diff += localDiff*localDiff; + localDiff = across[9]-cacross[9]; diff += localDiff*localDiff; + localDiff = across[10]-cacross[10]; diff += localDiff*localDiff; + localDiff = across[11]-cacross[11]; diff += localDiff*localDiff; + localDiff = across[12]-cacross[12]; diff += localDiff*localDiff; + localDiff = across[13]-cacross[13]; diff += localDiff*localDiff; + localDiff = across[14]-cacross[14]; diff += localDiff*localDiff; + localDiff = across[15]-cacross[15]; diff += localDiff*localDiff; + + if ( diff > bestSoFar ) { + return diff; + } + } + break; + } /* End of Switch */ + + return diff; +} + + +/*===========================================================================* + * + * LumAddMotionError + * + * return the MAD of the currentBlock and the average of the blockSoFar + * and the motion-compensated block (this is used for B-frame searches) + * + * RETURNS: the MAD, if less than bestSoFar, or + * some number bigger if not + * + * SIDE EFFECTS: none + * + * PRECONDITIONS: motion vector MUST be valid + * + *===========================================================================*/ +int32 +LumAddMotionError(LumBlock currentBlock, + LumBlock blockSoFar, + MpegFrame *prevFrame, + int by, + int bx, + int my, + int mx, + int32 bestSoFar) +{ + register int32 diff = 0; /* max value of diff is 255*256 = 65280 */ + register int32 localDiff; + register uint8 *across; + register int32 *bacross; + register int32 *cacross; + register int y; + uint8 **prev; + int fy, fx; + boolean xHalf, yHalf; + + xHalf = (ABS(mx) % 2 == 1); + yHalf = (ABS(my) % 2 == 1); + + MOTION_TO_FRAME_COORD(by, bx, my/2, mx/2, fy, fx); + + if ( xHalf ) { + if ( mx < 0 ) { + fx--; + } + + if ( yHalf ) { + if ( my < 0 ) { + fy--; + } + + prev = prevFrame->halfBoth; + } else { + prev = prevFrame->halfX; + } + } else if ( yHalf ) { + if ( my < 0 ) { + fy--; + } + + prev = prevFrame->halfY; + } else { + prev = prevFrame->ref_y; + } + +/* do we add 1 before dividing by two? Yes -- see MPEG-1 doc page 46 */ + +#define ADD_ADD_DIFF(d,l,a,b,c,i) \ + l = ((a[i]+b[i]+1)>>1)-c[i]; \ + d += ABS(l) + + for ( y = 0; y < 16; y++ ) { + across = &(prev[fy+y][fx]); + bacross = blockSoFar[y]; + cacross = currentBlock[y]; + + ADD_ADD_DIFF(diff,localDiff,across,bacross,cacross,0); + ADD_ADD_DIFF(diff,localDiff,across,bacross,cacross,1); + ADD_ADD_DIFF(diff,localDiff,across,bacross,cacross,2); + ADD_ADD_DIFF(diff,localDiff,across,bacross,cacross,3); + ADD_ADD_DIFF(diff,localDiff,across,bacross,cacross,4); + ADD_ADD_DIFF(diff,localDiff,across,bacross,cacross,5); + ADD_ADD_DIFF(diff,localDiff,across,bacross,cacross,6); + ADD_ADD_DIFF(diff,localDiff,across,bacross,cacross,7); + ADD_ADD_DIFF(diff,localDiff,across,bacross,cacross,8); + ADD_ADD_DIFF(diff,localDiff,across,bacross,cacross,9); + ADD_ADD_DIFF(diff,localDiff,across,bacross,cacross,10); + ADD_ADD_DIFF(diff,localDiff,across,bacross,cacross,11); + ADD_ADD_DIFF(diff,localDiff,across,bacross,cacross,12); + ADD_ADD_DIFF(diff,localDiff,across,bacross,cacross,13); + ADD_ADD_DIFF(diff,localDiff,across,bacross,cacross,14); + ADD_ADD_DIFF(diff,localDiff,across,bacross,cacross,15); + + if ( diff > bestSoFar ) { + return diff; + } + } + + /* this is what's happening: + * + * ComputeMotionLumBlock(prevFrame, by, bx, my, mx, lumMotionBlock); + * + * for ( y = 0; y < 16; y++ ) + * for ( x = 0; x < 16; x++ ) + * { + * localDiff = currentBlock[y][x] - lumMotionBlock[y][x]; + * diff += ABS(localDiff); + * } + * + */ + + return diff; +} + + +/*===========================================================================* + * + * AddMotionBlock + * + * adds the motion-compensated block to the given block + * + * RETURNS: block modified + * + * SIDE EFFECTS: none + * + * PRECONDITIONS: motion vector MUST be valid + * + *===========================================================================*/ +void +AddMotionBlock(Block block, + uint8 **prev, + int by, + int bx, + int my, + int mx) +{ + int fy, fx; + int x, y; + boolean xHalf, yHalf; + + xHalf = (ABS(mx) % 2 == 1); + yHalf = (ABS(my) % 2 == 1); + + MOTION_TO_FRAME_COORD(by, bx, (my/2), (mx/2), fy, fx); + + if ( xHalf && yHalf ) { + /* really should be fy+y-1 and fy+y so do (fy-1)+y = fy+y-1 and + (fy-1)+y+1 = fy+y + */ + if ( my < 0 ) { + fy--; + } + if ( mx < 0 ) { + fx--; + } + + for ( y = 0; y < 8; y++ ) { + for ( x = 0; x < 8; x++ ) { + block[y][x] += (prev[fy+y][fx+x]+prev[fy+y][fx+x+1]+ + prev[fy+y+1][fx+x]+prev[fy+y+1][fx+x+1]+2)>>2; + } + } + } else if ( xHalf ) { + if ( mx < 0 ) { + fx--; + } + + for ( y = 0; y < 8; y++ ) { + for ( x = 0; x < 8; x++ ) { + block[y][x] += (prev[fy+y][fx+x]+prev[fy+y][fx+x+1]+1)>>1; + } + } + } else if ( yHalf ) { + if ( my < 0 ) { + fy--; + } + + for ( y = 0; y < 8; y++ ) { + for ( x = 0; x < 8; x++ ) { + block[y][x] += (prev[fy+y][fx+x]+prev[fy+y+1][fx+x]+1)>>1; + } + } + } else { + for ( y = 0; y < 8; y++ ) { + for ( x = 0; x < 8; x++ ) { + block[y][x] += (int16)prev[fy+y][fx+x]; + } + } + } +} + + +/*===========================================================================* + * + * AddBMotionBlock + * + * adds the motion-compensated B-frame block to the given block + * + * RETURNS: block modified + * + * SIDE EFFECTS: none + * + * PRECONDITIONS: motion vectors MUST be valid + * + *===========================================================================*/ +void +AddBMotionBlock(Block block, + uint8 **prev, + uint8 **next, + int by, + int bx, + int mode, + int fmy, + int fmx, + int bmy, + int bmx) +{ + int x, y; + Block prevBlock, nextBlock; + + if ( mode == MOTION_FORWARD ) { + AddMotionBlock(block, prev, by, bx, fmy, fmx); + } else if ( mode == MOTION_BACKWARD ) { + AddMotionBlock(block, next, by, bx, bmy, bmx); + } else { + ComputeMotionBlock(prev, by, bx, fmy, fmx, prevBlock); + ComputeMotionBlock(next, by, bx, bmy, bmx, nextBlock); + + for ( y = 0; y < 8; y++ ) { + for ( x = 0; x < 8; x++ ) { + block[y][x] += (prevBlock[y][x]+nextBlock[y][x]+1)/2; + } + } + } +} + + +/*===========================================================================* + * + * BlockToData + * + * copies the given block into the appropriate data area + * + * RETURNS: data modified + * + * SIDE EFFECTS: none + * + *===========================================================================*/ +void +BlockToData(uint8 **data, + Block block, + int by, + int bx) +{ + register int x, y; + register int fy, fx; + register int16 blockItem; + + BLOCK_TO_FRAME_COORD(by, bx, fy, fx); + + for ( y = 0; y < 8; y++ ) { + for ( x = 0; x < 8; x++ ) { + blockItem = block[y][x]; + data[fy+y][fx+x] = TRUNCATE_UINT8(blockItem); + } + } +} + + +/*===========================================================================* + * + * BlockifyFrame + * + * copies data into appropriate blocks + * + * RETURNS: mf modified + * + * SIDE EFFECTS: none + * + * NOTES: probably shouldn't be in this file + * + *===========================================================================*/ +void +BlockifyFrame(MpegFrame *framePtr) +{ + register int dctx, dcty; + register int x, y; + register int bx, by; + register int fy, fx; + register int16 *destPtr; + register uint8 *srcPtr; + register int16 *destPtr2; + register uint8 *srcPtr2; + Block *blockPtr; + Block *blockPtr2; + + dctx = Fsize_x / DCTSIZE; + dcty = Fsize_y / DCTSIZE; + + /* + * copy y data into y_blocks + */ + for (by = 0; by < dcty; by++) { + fy = by*DCTSIZE; + for (bx = 0; bx < dctx; bx++) { + fx = bx*DCTSIZE; + blockPtr = (Block *) &(framePtr->y_blocks[by][bx][0][0]); + for (y = 0; y < DCTSIZE; y++) { + destPtr = &((*blockPtr)[y][0]); + srcPtr = &(framePtr->orig_y[fy+y][fx]); + for (x = 0; x < DCTSIZE; x++) { + destPtr[x] = srcPtr[x]; + } + } + } + } + + /* + * copy cr/cb data into cr/cb_blocks + */ + for (by = 0; by < (dcty >> 1); by++) { + fy = by*DCTSIZE; + for (bx = 0; bx < (dctx >> 1); bx++) { + fx = bx*DCTSIZE; + blockPtr = (Block *) &(framePtr->cr_blocks[by][bx][0][0]); + blockPtr2 = (Block *) &(framePtr->cb_blocks[by][bx][0][0]); + for (y = 0; y < DCTSIZE; y++) { + destPtr = &((*blockPtr)[y][0]); + srcPtr = &(framePtr->orig_cr[fy+y][fx]); + destPtr2 = &((*blockPtr2)[y][0]); + srcPtr2 = &(framePtr->orig_cb[fy+y][fx]); + for (x = 0; x < DCTSIZE; x++) { + destPtr[x] = srcPtr[x]; + destPtr2[x] = srcPtr2[x]; + } + } + } + } +} + + +/*===========================================================================* + * * + * UNUSED PROCEDURES * + * * + * The following procedures are all unused by the encoder * + * * + * They are listed here for your convenience. You might want to use * + * them if you experiment with different search techniques * + * * + *===========================================================================*/ + +#ifdef UNUSED_PROCEDURES + +/* this procedure calculates the subsampled motion block (obviously) + * + * for speed, this procedure is probably not called anywhere (it is + * incorporated directly into LumDiffA, LumDiffB, etc. + * + * but leave it here anyway for clarity + * + * (startY, startX) = (0,0) for A....(0,1) for B...(1,0) for C...(1,1) for D + * + */ +void +ComputeSubSampledMotionLumBlock(prevFrame, by, bx, my, mx, motionBlock, + startY, startX) + MpegFrame *prevFrame; + int by; + int bx; + int my; + int mx; + LumBlock motionBlock; + int startY; + int startX; +{ + register uint8 *across; + register int32 *macross; + register int32 *lastx; + register int y; + uint8 **prev; + int fy, fx; + boolean xHalf, yHalf; + + xHalf = (ABS(mx) % 2 == 1); + yHalf = (ABS(my) % 2 == 1); + + MOTION_TO_FRAME_COORD(by, bx, my/2, mx/2, fy, fx); + + if ( xHalf ) { + if ( mx < 0 ) { + fx--; + } + + if ( yHalf ) { + if ( my < 0 ) { + fy--; + } + + prev = prevFrame->halfBoth; + } else { + prev = prevFrame->halfX; + } + } else if ( yHalf ) { + if ( my < 0 ) { + fy--; + } + + prev = prevFrame->halfY; + } else { + prev = prevFrame->ref_y; + } + + for ( y = startY; y < 16; y += 2 ) { + across = &(prev[fy+y][fx+startX]); + macross = &(motionBlock[y][startX]); + lastx = &(motionBlock[y][16]); + while ( macross < lastx ) { + (*macross) = (*across); + across += 2; + macross += 2; + } + } + + /* this is what's really going on in slow motion: + * + * for ( y = startY; y < 16; y += 2 ) + * for ( x = startX; x < 16; x += 2 ) + * motionBlock[y][x] = prev[fy+y][fx+x]; + * + */ +} + + +/*===========================================================================* + * + * LumMotionErrorSubSampled + * + * return the MAD of the currentBlock and the motion-compensated block, + * subsampled 4:1 with given starting coordinates (startY, startX) + * + * RETURNS: the MAD + * + * SIDE EFFECTS: none + * + * PRECONDITIONS: motion vector MUST be valid + * + * NOTES: this procedure is never called. Instead, see subsample.c. This + * procedure is provided only for possible use in extensions + * + *===========================================================================*/ +int32 +LumMotionErrorSubSampled(currentBlock, prevFrame, by, bx, my, mx, startY, + startX) + LumBlock currentBlock; + MpegFrame *prevFrame; + int by; + int bx; + int my; + int mx; + int startY; + int startX; +{ + register int32 diff = 0; /* max value of diff is 255*256 = 65280 */ + register int32 localDiff; + register int32 *cacross; + register uint8 *macross; + register int32 *lastx; + register int y; + uint8 **prev; + int fy, fx; + boolean xHalf, yHalf; + + xHalf = (ABS(mx) % 2 == 1); + yHalf = (ABS(my) % 2 == 1); + + MOTION_TO_FRAME_COORD(by, bx, my/2, mx/2, fy, fx); + + if ( xHalf ) { + if ( mx < 0 ) { + fx--; + } + + if ( yHalf ) { + if ( my < 0 ) { + fy--; + } + + prev = prevFrame->halfBoth; + } else { + prev = prevFrame->halfX; + } + } else if ( yHalf ) { + if ( my < 0 ) { + fy--; + } + + prev = prevFrame->halfY; + } else { + prev = prevFrame->ref_y; + } + + for ( y = startY; y < 16; y += 2 ) { + macross = &(prev[fy+y][fx+startX]); + cacross = &(currentBlock[y][startX]); + lastx = &(currentBlock[y][16]); + while ( cacross < lastx ) { + localDiff = (*cacross)-(*macross); + diff += ABS(localDiff); + macross += 2; + cacross += 2; + } + } + + /* this is what's really happening: + * + * ComputeSubSampledMotionLumBlock(prevFrame, by, bx, my, mx, + * lumMotionBlock, startY, startX); + * + * for ( y = startY; y < 16; y += 2 ) + * for ( x = startX; x < 16; x += 2 ) + * { + * localDiff = currentBlock[y][x] - lumMotionBlock[y][x]; + * diff += ABS(localDiff); + * } + * + */ + + return (int32)diff; +} + + +#endif /* UNUSED_PROCEDURES */ diff --git a/contrib/mpeg_encode/bsearch.cpp b/contrib/mpeg_encode/bsearch.cpp new file mode 100644 index 0000000000000000000000000000000000000000..416e36e778e442bc42b80955926f17789bd7417c --- /dev/null +++ b/contrib/mpeg_encode/bsearch.cpp @@ -0,0 +1,1126 @@ +/*===========================================================================* + * bsearch.c * + * * + * Procedures concerned with the B-frame motion search * + * * + * EXPORTED PROCEDURES: * + * SetBSearchAlg * + * BMotionSearch * + * BSearchName * + * * + *===========================================================================*/ + +/* + * Copyright (c) 1995 The Regents of the University of California. + * All rights reserved. + * + * Permission to use, copy, modify, and distribute this software and its + * documentation for any purpose, without fee, and without written agreement is + * hereby granted, provided that the above copyright notice and the following + * two paragraphs appear in all copies of this software. + * + * IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR + * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT + * OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF + * CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS + * ON AN "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO + * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. + */ + +/* + * $Header: /n/picasso/project/mpeg/mpeg_dist/mpeg_encode/RCS/bsearch.c,v 1.10 1995/08/07 21:49:01 smoot Exp $ + * $Log: bsearch.c,v $ + * Revision 1.10 1995/08/07 21:49:01 smoot + * fixed bug in initial-B-frame searches + * + * Revision 1.9 1995/06/26 21:36:07 smoot + * added new ordering constraints + * (B frames which are backward P's at the start of a sequence) + * + * Revision 1.8 1995/03/27 19:17:43 smoot + * killed useless type error messge (int32 defiend as int) + * + * Revision 1.7 1995/01/19 23:07:20 eyhung + * Changed copyrights + * + * Revision 1.6 1994/12/07 00:40:36 smoot + * Added seperate P and B search ranges + * + * Revision 1.5 1994/03/15 00:27:11 keving + * nothing + * + * Revision 1.4 1993/12/22 19:19:01 keving + * nothing + * + * Revision 1.3 1993/07/22 22:23:43 keving + * nothing + * + * Revision 1.2 1993/06/30 20:06:09 keving + * nothing + * + * Revision 1.1 1993/06/03 21:08:08 keving + * nothing + * + * Revision 1.1 1993/03/02 18:27:05 keving + * nothing + * + */ + + +/*==============* + * HEADER FILES * + *==============*/ + +#include "all.h" +#include "mtypes.h" +#include "frames.h" +#include "search.h" +#include "fsize.h" + + +/*==================* + * STATIC VARIABLES * + *==================*/ + +static int bsearchAlg; + + +/*===============================* + * INTERNAL PROCEDURE prototypes * + *===============================*/ + +static int32 FindBestMatch _ANSI_ARGS_((LumBlock block, LumBlock currentBlock, MpegFrame *prev, + int by, int bx, int *motionY, int *motionX, int32 bestSoFar, int searchRange)); +static int BMotionSearchSimple _ANSI_ARGS_((LumBlock currentBlock, MpegFrame *prev, + MpegFrame *next, int by, int bx, int *fmy, int *fmx, + int *bmy, int *bmx, int oldMode)); +static int BMotionSearchCross2 _ANSI_ARGS_((LumBlock currentBlock, MpegFrame *prev, + MpegFrame *next, int by, int bx, int *fmy, int *fmx, + int *bmy, int *bmx, int oldMode)); +static int BMotionSearchExhaust _ANSI_ARGS_((LumBlock currentBlock, MpegFrame *prev, + MpegFrame *next, int by, int bx, int *fmy, int *fmx, + int *bmy, int *bmx, int oldMode)); +static void BMotionSearchNoInterp _ANSI_ARGS_((LumBlock currentBlock, MpegFrame *prev, + MpegFrame *next, int by, int bx, + int *fmy, int *fmx, int32 *forwardErr, + int *bmy, int *bmx, int32 *backErr, + boolean backNeeded)); +static int32 FindBestMatchExhaust _ANSI_ARGS_((LumBlock block, LumBlock currentBlock, MpegFrame *prev, + int by, int bx, int *motionY, int *motionX, + int32 bestSoFar, int searchRange)); +static int32 FindBestMatchTwoLevel _ANSI_ARGS_((LumBlock block, LumBlock currentBlock, MpegFrame *prev, + int by, int bx, int *motionY, int *motionX, + int32 bestSoFar, int searchRange)); +static int32 FindBestMatchLogarithmic _ANSI_ARGS_((LumBlock block, LumBlock currentBlock, MpegFrame *prev, + int by, int bx, int *motionY, int *motionX, + int32 bestSoFar, int searchRange)); +static int32 FindBestMatchSubSample _ANSI_ARGS_((LumBlock block, LumBlock currentBlock, MpegFrame *prev, + int by, int bx, int *motionY, int *motionX, + int32 bestSoFar, int searchRange)); + + +/*=====================* + * EXPORTED PROCEDURES * + *=====================*/ + +/*===========================* + * INITIALIZATION PROCEDURES * + *===========================*/ + + +/*===========================================================================* + * + * SetBSearchAlg + * + * set the B-search algorithm + * + * RETURNS: nothing + * + * SIDE EFFECTS: bsearchAlg modified + * + *===========================================================================*/ +void +SetBSearchAlg(char *alg) +{ + if ( strcmp(alg, "SIMPLE") == 0 ) { + bsearchAlg = BSEARCH_SIMPLE; + } else if ( strcmp(alg, "CROSS2") == 0 ) { + bsearchAlg = BSEARCH_CROSS2; + } else if ( strcmp(alg, "EXHAUSTIVE") == 0 ) { + bsearchAlg = BSEARCH_EXHAUSTIVE; + } else { + throw "Illegal bsearch algoritm"; + } +} + + +/*===========================================================================* + * + * BSearchName + * + * return the text of the B-search algorithm + * + * RETURNS: a pointer to the string + * + * SIDE EFFECTS: none + * + *===========================================================================*/ +char * +BSearchName() +{ + switch(bsearchAlg) { + case BSEARCH_SIMPLE: + return (char*)"SIMPLE"; + case BSEARCH_CROSS2: + return (char*)"CROSS2"; + case BSEARCH_EXHAUSTIVE: + return (char*)"EXHAUSTIVE"; + default: + throw "Error in BSearchName"; + break; + } +} + + +/*===========================================================================* + * + * BMotionSearch + * + * search for the best B-frame motion vectors + * + * RETURNS: MOTION_FORWARD forward motion should be used + * MOTION_BACKWARD backward motion should be used + * MOTION_INTERPOLATE both should be used and interpolated + * + * OUTPUTS: *fmx, *fmy = TWICE the forward motion vector + * *bmx, *bmy = TWICE the backward motion vector + * + * SIDE EFFECTS: none + * + * PRECONDITIONS: The relevant block in 'current' is valid (it has not + * been dct'd). Thus, the data in 'current' can be + * accesed through y_blocks, cr_blocks, and cb_blocks. + * This is not the case for the blocks in 'prev' and + * 'next.' Therefore, references into 'prev' and 'next' + * should be done + * through the struct items ref_y, ref_cr, ref_cb + * + * POSTCONDITIONS: current, prev, next should be unchanged. + * Some computation could be saved by requiring + * the dct'd difference to be put into current's block + * elements here, depending on the search technique. + * However, it was decided that it mucks up the code + * organization a little, and the saving in computation + * would be relatively little (if any). + * + * NOTES: the search procedure MAY return (0,0) motion vectors + * + *===========================================================================*/ +int +BMotionSearch(LumBlock currentBlock, + MpegFrame *prev, + MpegFrame *next, + int by, + int bx, + int *fmy, + int *fmx, + int *bmy, + int *bmx, + int oldMode) +{ + /* If we are an initial B frame, no possibility of forward motion */ + if (prev == (MpegFrame *) NULL) { + PMotionSearch(currentBlock, next, by, bx, bmy, bmx); + return MOTION_BACKWARD; + } + + /* otherwise simply call the appropriate algorithm, based on user preference */ + + switch(bsearchAlg) { + case BSEARCH_SIMPLE: + return BMotionSearchSimple(currentBlock, prev, next, by, bx, fmy, + fmx, bmy, bmx, oldMode); + break; + case BSEARCH_CROSS2: + return BMotionSearchCross2(currentBlock, prev, next, by, bx, fmy, + fmx, bmy, bmx, oldMode); + break; + case BSEARCH_EXHAUSTIVE: + return BMotionSearchExhaust(currentBlock, prev, next, by, bx, fmy, + fmx, bmy, bmx, oldMode); + break; + default: + throw "Illegal B-frame motion search algorithm"; + } +} + + +/*===========================================================================* + * + * BMotionSearchSimple + * + * does a simple search for B-frame motion vectors + * see BMotionSearch for generic description + * + * DESCRIPTION: + * 1) find best backward and forward vectors + * 2) compute interpolated error using those two vectors + * 3) return the best of the three choices + * + *===========================================================================*/ +static int +BMotionSearchSimple(LumBlock currentBlock, + MpegFrame *prev, + MpegFrame *next, + int by, + int bx, + int *fmy, + int *fmx, + int *bmy, + int *bmx, + int oldMode) +{ + int32 forwardErr, backErr, interpErr; + LumBlock interpBlock; + int32 bestSoFar; + + /* STEP 1 */ + BMotionSearchNoInterp(currentBlock, prev, next, by, bx, fmy, fmx, + &forwardErr, bmy, bmx, &backErr, TRUE); + + /* STEP 2 */ + + ComputeBMotionLumBlock(prev, next, by, bx, MOTION_INTERPOLATE, + *fmy, *fmx, *bmy, *bmx, interpBlock); + bestSoFar = min(backErr, forwardErr); + interpErr = LumBlockMAD(currentBlock, interpBlock, bestSoFar); + + /* STEP 3 */ + + if ( interpErr <= forwardErr ) { + if ( interpErr <= backErr ) { + return MOTION_INTERPOLATE; + } + else + return MOTION_BACKWARD; + } else if ( forwardErr <= backErr ) { + return MOTION_FORWARD; + } else { + return MOTION_BACKWARD; + } +} + + +/*===========================================================================* + * + * BMotionSearchCross2 + * + * does a cross-2 search for B-frame motion vectors + * see BMotionSearch for generic description + * + * DESCRIPTION: + * 1) find best backward and forward vectors + * 2) find best matching interpolating vectors + * 3) return the best of the 4 choices + * + *===========================================================================*/ +static int +BMotionSearchCross2(LumBlock currentBlock, + MpegFrame *prev, + MpegFrame *next, + int by, + int bx, + int *fmy, + int *fmx, + int *bmy, + int *bmx, + int oldMode) +{ + LumBlock forwardBlock, backBlock; + int32 forwardErr, backErr, interpErr; + int newfmy, newfmx, newbmy, newbmx; + int32 interpErr2; + int32 bestErr; + + /* STEP 1 */ + + BMotionSearchNoInterp(currentBlock, prev, next, by, bx, fmy, fmx, + &forwardErr, bmy, bmx, &backErr, TRUE); + + bestErr = min(forwardErr, backErr); + + /* STEP 2 */ + ComputeBMotionLumBlock(prev, next, by, bx, MOTION_FORWARD, + *fmy, *fmx, 0, 0, forwardBlock); + ComputeBMotionLumBlock(prev, next, by, bx, MOTION_BACKWARD, + 0, 0, *bmy, *bmx, backBlock); + + /* try a cross-search; total of 4 local searches */ + newbmy = *bmy; newbmx = *bmx; + newfmy = *fmy; newfmx = *fmx; + + interpErr = FindBestMatch(forwardBlock, currentBlock, next, by, bx, + &newbmy, &newbmx, bestErr, searchRangeB); + bestErr = min(bestErr, interpErr); + interpErr2 = FindBestMatch(backBlock, currentBlock, prev, by, bx, + &newfmy, &newfmx, bestErr, searchRangeB); + + /* STEP 3 */ + + if ( interpErr <= interpErr2 ) { + newfmy = *fmy; + newfmx = *fmx; + } + else + { + newbmy = *bmy; + newbmx = *bmx; + interpErr = interpErr2; + } + + if ( interpErr <= forwardErr ) { + if ( interpErr <= backErr ) { + *fmy = newfmy; + *fmx = newfmx; + *bmy = newbmy; + *bmx = newbmx; + + return MOTION_INTERPOLATE; + } + else + return MOTION_BACKWARD; + } else if ( forwardErr <= backErr ) { + return MOTION_FORWARD; + } else { + return MOTION_BACKWARD; + } +} + + +/*===========================================================================* + * + * BMotionSearchExhaust + * + * does an exhaustive search for B-frame motion vectors + * see BMotionSearch for generic description + * + * DESCRIPTION: + * 1) find best backward and forward vectors + * 2) use exhaustive search to find best interpolating vectors + * 3) return the best of the 3 choices + * + *===========================================================================*/ +static int +BMotionSearchExhaust(LumBlock currentBlock, + MpegFrame *prev, + MpegFrame *next, + int by, + int bx, + int *fmy, + int *fmx, + int *bmy, + int *bmx, + int oldMode) +{ + register int mx, my; + int32 diff, bestDiff; + int stepSize; + LumBlock forwardBlock; + int32 forwardErr, backErr; + int newbmy, newbmx; + int leftMY, leftMX; + int rightMY, rightMX; + boolean result; + + /* STEP 1 */ + + BMotionSearchNoInterp(currentBlock, prev, next, by, bx, fmy, fmx, + &forwardErr, bmy, bmx, &backErr, FALSE); + + if ( forwardErr <= backErr ) { + bestDiff = forwardErr; + result = MOTION_FORWARD; + } + else + { + bestDiff = backErr; + result = MOTION_BACKWARD; + } + + /* STEP 2 */ + + stepSize = (pixelFullSearch ? 2 : 1); + + COMPUTE_MOTION_BOUNDARY(by,bx,stepSize,leftMY,leftMX,rightMY,rightMX); + + if ( searchRangeB < rightMY ) { + rightMY = searchRangeB; + } + if ( searchRangeB < rightMX ) { + rightMX = searchRangeB; + } + + for ( my = -searchRangeB; my < rightMY; my += stepSize ) { + if ( my < leftMY ) { + continue; + } + + for ( mx = -searchRangeB; mx < rightMX; mx += stepSize ) { + if ( mx < leftMX ) { + continue; + } + + ComputeBMotionLumBlock(prev, next, by, bx, MOTION_FORWARD, + my, mx, 0, 0, forwardBlock); + + newbmy = my; newbmx = mx; + + diff = FindBestMatch(forwardBlock, currentBlock, next, by, bx, + &newbmy, &newbmx, bestDiff, searchRangeB); + + if ( diff < bestDiff ) { + *fmy = my; + *fmx = mx; + *bmy = newbmy; + *bmx = newbmx; + bestDiff = diff; + result = MOTION_INTERPOLATE; + } + } + } + + return result; +} + + +/*===========================================================================* + * + * FindBestMatch + * + * given a motion-compensated block in one direction, tries to find + * the best motion vector in the opposite direction to match it + * + * RETURNS: the best vector (*motionY, *motionX), and the corresponding + * error is returned if it is better than bestSoFar. If not, + * then a number greater than bestSoFar is returned and + * (*motionY, *motionX) has no meaning. + * + * SIDE EFFECTS: none + * + *===========================================================================*/ +static int32 +FindBestMatch(LumBlock block, + LumBlock currentBlock, + MpegFrame *prev, + int by, + int bx, + int *motionY, + int *motionX, + int32 bestSoFar, + int searchRange) +{ + int32 result; + + switch(psearchAlg) { + case PSEARCH_SUBSAMPLE: + result = FindBestMatchSubSample(block, currentBlock, prev, by, bx, + motionY, motionX, bestSoFar, searchRange); + break; + case PSEARCH_EXHAUSTIVE: + result = FindBestMatchExhaust(block, currentBlock, prev, by, bx, + motionY, motionX, bestSoFar, searchRange); + break; + case PSEARCH_LOGARITHMIC: + result = FindBestMatchLogarithmic(block, currentBlock, prev, by, bx, + motionY, motionX, bestSoFar, searchRange); + break; + case PSEARCH_TWOLEVEL: + result = FindBestMatchTwoLevel(block, currentBlock, prev, by, bx, + motionY, motionX, bestSoFar, searchRange); + break; + default: + throw "Illegal P-search alg"; + } + + return result; +} + + +/*===========================================================================* + * + * FindBestMatchExhaust + * + * tries to find matching motion vector + * see FindBestMatch for generic description + * + * DESCRIPTION: uses an exhaustive search + * + *===========================================================================*/ +static int32 +FindBestMatchExhaust(LumBlock block, + LumBlock currentBlock, + MpegFrame *prev, + int by, + int bx, + int *motionY, + int *motionX, + int32 bestSoFar, + int searchRange) +{ + register int mx, my; + int32 diff, bestDiff; + int stepSize; + int leftMY, leftMX; + int rightMY, rightMX; + int distance; + int tempRightMY, tempRightMX; + boolean changed = FALSE; + + stepSize = (pixelFullSearch ? 2 : 1); + + COMPUTE_MOTION_BOUNDARY(by,bx,stepSize,leftMY,leftMX,rightMY,rightMX); + + /* try old motion vector first */ + if ( VALID_MOTION(*motionY, *motionX) ) { + bestDiff = LumAddMotionError(currentBlock, block, prev, by, bx, + *motionY, *motionX, bestSoFar); + + if ( bestSoFar < bestDiff ) { + bestDiff = bestSoFar; + } + } + else + { + *motionY = 0; + *motionX = 0; + + bestDiff = bestSoFar; + } + +/* maybe should try spiral pattern centered around prev motion vector? */ + + + /* try a spiral pattern */ + for ( distance = stepSize; distance <= searchRange; distance += stepSize ) { + tempRightMY = rightMY; + if ( distance < tempRightMY ) { + tempRightMY = distance; + } + tempRightMX = rightMX; + if ( distance < tempRightMX ) { + tempRightMX = distance; + } + + /* do top, bottom */ + for ( my = -distance; my < tempRightMY; + my += max(tempRightMY+distance-stepSize, stepSize) ) { + if ( my < leftMY ) { + continue; + } + + for ( mx = -distance; mx < tempRightMX; mx += stepSize ) { + if ( mx < leftMX ) { + continue; + } + + diff = LumAddMotionError(currentBlock, block, prev, by, bx, + my, mx, bestDiff); + + if ( diff < bestDiff ) { + *motionY = my; + *motionX = mx; + bestDiff = diff; + } + } + } + + /* do left, right */ + for ( mx = -distance; mx < tempRightMX; mx += max(tempRightMX+distance-stepSize, stepSize) ) { + if ( mx < leftMX ) { + continue; + } + + for ( my = -distance+stepSize; my < tempRightMY-stepSize; my += stepSize ) { + if ( my < leftMY ) { + continue; + } + + diff = LumAddMotionError(currentBlock, block, prev, by, bx, + my, mx, bestDiff); + + if ( diff < bestDiff ) { + *motionY = my; + *motionX = mx; + bestDiff = diff; + changed = TRUE; + } + } + } + } + + if ( ! changed ) { + bestDiff++; + } + + return bestDiff; +} + + +/*===========================================================================* + * + * FindBestMatchTwoLevel + * + * tries to find matching motion vector + * see FindBestMatch for generic description + * + * DESCRIPTION: uses an exhaustive full-pixel search, then looks at + * neighboring half-pixels + * + *===========================================================================*/ +static int32 +FindBestMatchTwoLevel(LumBlock block, + LumBlock currentBlock, + MpegFrame *prev, + int by, + int bx, + int *motionY, + int *motionX, + int32 bestSoFar, + int searchRange) +{ + register int mx, my; + int32 diff, bestDiff; + int leftMY, leftMX; + int rightMY, rightMX; + int distance; + int tempRightMY, tempRightMX; + boolean changed = FALSE; + int yOffset, xOffset; + + /* exhaustive full-pixel search first */ + + COMPUTE_MOTION_BOUNDARY(by,bx,2,leftMY,leftMX,rightMY,rightMX); + + rightMY--; + rightMX--; + + /* convert vector into full-pixel vector */ + if ( *motionY > 0 ) { + if ( ((*motionY) % 2) == 1 ) { + (*motionY)--; + } + } else if ( ((-(*motionY)) % 2) == 1 ) { + (*motionY)++; + } + + if ( *motionX > 0 ) { + if ( ((*motionX) % 2) == 1 ) { + (*motionX)--; + } + } else if ( ((-(*motionX)) % 2) == 1 ) { + (*motionX)++; + } + + /* try old motion vector first */ + if ( VALID_MOTION(*motionY, *motionX) ) { + bestDiff = LumAddMotionError(currentBlock, block, prev, by, bx, + *motionY, *motionX, bestSoFar); + + if ( bestSoFar < bestDiff ) { + bestDiff = bestSoFar; + } + } + else + { + *motionY = 0; + *motionX = 0; + + bestDiff = bestSoFar; + } + + rightMY++; + rightMX++; + +/* maybe should try spiral pattern centered around prev motion vector? */ + + + /* try a spiral pattern */ + for ( distance = 2; distance <= searchRange; distance += 2 ) { + tempRightMY = rightMY; + if ( distance < tempRightMY ) { + tempRightMY = distance; + } + tempRightMX = rightMX; + if ( distance < tempRightMX ) { + tempRightMX = distance; + } + + /* do top, bottom */ + for ( my = -distance; my < tempRightMY; + my += max(tempRightMY+distance-2, 2) ) { + if ( my < leftMY ) { + continue; + } + + for ( mx = -distance; mx < tempRightMX; mx += 2 ) { + if ( mx < leftMX ) { + continue; + } + + diff = LumAddMotionError(currentBlock, block, prev, by, bx, + my, mx, bestDiff); + + if ( diff < bestDiff ) { + *motionY = my; + *motionX = mx; + bestDiff = diff; + } + } + } + + /* do left, right */ + for ( mx = -distance; mx < tempRightMX; mx += max(tempRightMX+distance-2, 2) ) { + if ( mx < leftMX ) { + continue; + } + + for ( my = -distance+2; my < tempRightMY-2; my += 2 ) { + if ( my < leftMY ) { + continue; + } + + diff = LumAddMotionError(currentBlock, block, prev, by, bx, + my, mx, bestDiff); + + if ( diff < bestDiff ) { + *motionY = my; + *motionX = mx; + bestDiff = diff; + changed = TRUE; + } + } + } + } + + /* now look at neighboring half-pixels */ + my = *motionY; + mx = *motionX; + + rightMY--; + rightMX--; + + for ( yOffset = -1; yOffset <= 1; yOffset++ ) { + for ( xOffset = -1; xOffset <= 1; xOffset++ ) { + if ( (yOffset == 0) && (xOffset == 0) ) + continue; + + if ( VALID_MOTION(my+yOffset, mx+xOffset) && + ((diff = LumAddMotionError(currentBlock, block, prev, by, bx, + my+yOffset, mx+xOffset, bestDiff)) < bestDiff) ) { + *motionY = my+yOffset; + *motionX = mx+xOffset; + bestDiff = diff; + changed = TRUE; + } + } + } + + if ( ! changed ) { + bestDiff++; + } + + return bestDiff; +} + + +/*===========================================================================* + * + * FindBestMatchLogarithmic + * + * tries to find matching motion vector + * see FindBestMatch for generic description + * + * DESCRIPTION: uses a logarithmic search + * + *===========================================================================*/ +static int32 +FindBestMatchLogarithmic(LumBlock block, + LumBlock currentBlock, + MpegFrame *prev, + int by, + int bx, + int *motionY, + int *motionX, + int32 bestSoFar, + int searchRange) +{ + register int mx, my; + int32 diff, bestDiff; + int stepSize; + int leftMY, leftMX; + int rightMY, rightMX; + int tempRightMY, tempRightMX; + int spacing; + int centerX, centerY; + int newCenterX, newCenterY; + + stepSize = (pixelFullSearch ? 2 : 1); + + COMPUTE_MOTION_BOUNDARY(by,bx,stepSize,leftMY,leftMX,rightMY,rightMX); + + bestDiff = 0x7fffffff; + + /* grid spacing */ + if ( stepSize == 2 ) { /* make sure spacing is even */ + spacing = (searchRange+1)/2; + if ( (spacing % 2) != 0 ) { + spacing++; + } + } + else + spacing = (searchRange+1)/2; + centerX = 0; + centerY = 0; + + while ( spacing >= stepSize ) { + newCenterY = centerY; + newCenterX = centerX; + + tempRightMY = rightMY; + if ( centerY+spacing+1 < tempRightMY ) { + tempRightMY = centerY+spacing+1; + } + tempRightMX = rightMX; + if ( centerX+spacing+1 < tempRightMX ) { + tempRightMX = centerX+spacing+1; + } + + for ( my = centerY-spacing; my < tempRightMY; my += spacing ) { + if ( my < leftMY ) { + continue; + } + + for ( mx = centerX-spacing; mx < tempRightMX; mx += spacing ) { + if ( mx < leftMX ) { + continue; + } + + diff = LumAddMotionError(currentBlock, block, prev, by, bx, + my, mx, bestDiff); + + if ( diff < bestDiff ) { + newCenterY = my; + newCenterX = mx; + + bestDiff = diff; + } + } + } + + centerY = newCenterY; + centerX = newCenterX; + + if ( stepSize == 2 ) { /* make sure spacing is even */ + if ( spacing == 2 ) { + spacing = 0; + } + else + { + spacing = (spacing+1)/2; + if ( (spacing % 2) != 0 ) { + spacing++; + } + } + } + else + { + if ( spacing == 1 ) { + spacing = 0; + } + else + spacing = (spacing+1)/2; + } + } + + /* check old motion -- see if it's better */ + if ( (*motionY >= leftMY) && (*motionY < rightMY) && + (*motionX >= leftMX) && (*motionX < rightMX) ) { + diff = LumAddMotionError(currentBlock, block, prev, by, bx, *motionY, *motionX, bestDiff); + } else { + diff = 0x7fffffff; + } + + if ( bestDiff < diff ) { + *motionY = centerY; + *motionX = centerX; + } + else + bestDiff = diff; + + return bestDiff; +} + + +/*===========================================================================* + * + * FindBestMatchSubSample + * + * tries to find matching motion vector + * see FindBestMatch for generic description + * + * DESCRIPTION: should use subsampling method, but too lazy to write all + * the code for it (so instead just calls FindBestMatchExhaust) + * + *===========================================================================*/ +static int32 +FindBestMatchSubSample(LumBlock block, + LumBlock currentBlock, + MpegFrame *prev, + int by, + int bx, + int *motionY, + int *motionX, + int32 bestSoFar, + int searchRange) +{ + /* too lazy to write the code for this... */ + + return FindBestMatchExhaust(block, currentBlock, prev, + by, bx, motionY, motionX, bestSoFar, searchRange); +} + + +/*===========================================================================* + * + * BMotionSearchNoInterp + * + * finds the best backward and forward motion vectors + * if backNeeded == FALSE, then won't find best backward vector if it + * is worse than the best forward vector + * + * RETURNS: (*fmy,*fmx) and associated error *forwardErr + * (*bmy,*bmx) and associated error *backErr + * + * SIDE EFFECTS: none + * + *===========================================================================*/ +static void +BMotionSearchNoInterp(LumBlock currentBlock, + MpegFrame *prev, + MpegFrame *next, + int by, + int bx, + int *fmy, + int *fmx, + int32 *forwardErr, + int *bmy, + int *bmx, + int32 *backErr, + boolean backNeeded) +{ + /* CALL SEARCH PROCEDURE */ + switch(psearchAlg) { + case PSEARCH_SUBSAMPLE: + *forwardErr = PSubSampleSearch(currentBlock, prev, by, bx, + fmy, fmx, searchRangeB); + *backErr = PSubSampleSearch(currentBlock, next, by, bx, + bmy, bmx, searchRangeB); + break; + case PSEARCH_EXHAUSTIVE: + *forwardErr = PLocalSearch(currentBlock, prev, by, bx, fmy, fmx, + 0x7fffffff, searchRangeB); + if ( backNeeded ) { + *backErr = PLocalSearch(currentBlock, next, by, bx, bmy, bmx, + 0x7fffffff, searchRangeB); + } else { + *backErr = PLocalSearch(currentBlock, next, by, bx, bmy, bmx, + *forwardErr, searchRangeB); + } + break; + case PSEARCH_LOGARITHMIC: + *forwardErr = PLogarithmicSearch(currentBlock, prev, by, bx, + fmy, fmx, searchRangeB); + *backErr = PLogarithmicSearch(currentBlock, next, by, bx, + bmy, bmx, searchRangeB); + break; + case PSEARCH_TWOLEVEL: + *forwardErr = PTwoLevelSearch(currentBlock, prev, by, bx, fmy, fmx, + 0x7fffffff, searchRangeB); + if ( backNeeded ) { + *backErr = PTwoLevelSearch(currentBlock, next, by, bx, bmy, bmx, + 0x7fffffff, searchRangeB); + } else { + *backErr = PTwoLevelSearch(currentBlock, next, by, bx, bmy, bmx, + *forwardErr, searchRangeB); + } + break; + default: + throw "Illegal PSEARCH ALG"; + break; + } +} + + + +/*===========================================================================* + * * + * UNUSED PROCEDURES * + * * + * The following procedures are all unused by the encoder * + * * + * They are listed here for your convenience. You might want to use * + * them if you experiment with different search techniques * + * * + *===========================================================================*/ + +#ifdef UNUSED_PROCEDURES + +/*===========================================================================* + * + * ValidBMotion + * + * decides if the given B-frame motion is valid + * + * RETURNS: TRUE if the motion is valid, FALSE otherwise + * + * SIDE EFFECTS: none + * + *===========================================================================*/ +boolean +ValidBMotion(int by, + int bx, + int mode, + int fmy, + int fmx, + int bmy, + int bmx) +{ + if ( mode != MOTION_BACKWARD ) { + /* check forward motion for bounds */ + if ( (by*DCTSIZE+(fmy-1)/2 < 0) || ((by+2)*DCTSIZE+(fmy+1)/2-1 >= Fsize_y) ) { + return FALSE; + } + if ( (bx*DCTSIZE+(fmx-1)/2 < 0) || ((bx+2)*DCTSIZE+(fmx+1)/2-1 >= Fsize_x) ) { + return FALSE; + } + } + + if ( mode != MOTION_FORWARD ) { + /* check backward motion for bounds */ + if ( (by*DCTSIZE+(bmy-1)/2 < 0) || ((by+2)*DCTSIZE+(bmy+1)/2-1 >= Fsize_y) ) { + return FALSE; + } + if ( (bx*DCTSIZE+(bmx-1)/2 < 0) || ((bx+2)*DCTSIZE+(bmx+1)/2-1 >= Fsize_x) ) { + return FALSE; + } + } + + return TRUE; +} + + +#endif /* UNUSED_PROCEDURES */ diff --git a/contrib/mpeg_encode/combine.cpp b/contrib/mpeg_encode/combine.cpp new file mode 100644 index 0000000000000000000000000000000000000000..3ce6bda17b0ceb2c99370400de736457a24e2bce --- /dev/null +++ b/contrib/mpeg_encode/combine.cpp @@ -0,0 +1,501 @@ +/*===========================================================================* + * combine.c * + * * + * Procedures to combine frames or GOPS into an MPEG sequence * + * * + * EXPORTED PROCEDURES: * + * GOPStoMPEG * + * FramesToMPEG * + * * + *===========================================================================*/ + +/* + * Copyright (c) 1995 The Regents of the University of California. + * All rights reserved. + * + * Permission to use, copy, modify, and distribute this software and its + * documentation for any purpose, without fee, and without written agreement is + * hereby granted, provided that the above copyright notice and the following + * two paragraphs appear in all copies of this software. + * + * IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR + * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT + * OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF + * CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS + * ON AN "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO + * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. + */ + +/* + * $Header: /n/picasso/project/mpeg/mpeg_dist/mpeg_encode/RCS/combine.c,v 1.9 1995/08/07 21:42:38 smoot Exp $ + * $Log: combine.c,v $ + * Revision 1.9 1995/08/07 21:42:38 smoot + * Sleeps when files do not exist. + * renamed index to idx + * + * Revision 1.8 1995/06/21 22:20:45 smoot + * added a sleep for NFS to complete file writes + * + * Revision 1.7 1995/06/08 20:23:19 smoot + * added "b"'s to fopen so PCs are happy + * + * Revision 1.6 1995/01/19 23:07:22 eyhung + * Changed copyrights + * + * Revision 1.5 1995/01/16 07:53:55 eyhung + * Added realQuiet + * + * Revision 1.4 1994/11/12 02:11:46 keving + * nothing + * + * Revision 1.3 1994/03/15 00:27:11 keving + * nothing + * + * Revision 1.2 1993/12/22 19:19:01 keving + * nothing + * + * Revision 1.1 1993/07/22 22:23:43 keving + * nothing + * + */ + + +/*==============* + * HEADER FILES * + *==============*/ + +#include "all.h" +#include <time.h> +#include <errno.h> +#include "mtypes.h" +#include "frames.h" +#include "search.h" +#include "mpeg.h" +#include "prototypes.h" +#include "parallel.h" +#include "param.h" +#include "readframe.h" +#include "mheaders.h" +#include "fsize.h" +#include "combine.h" +#include <unistd.h> + +/* note, remove() might not have a prototype in the standard header files, + * but it really should -- it's not my fault! + */ + + +static int currentGOP; + +#define READ_ATTEMPTS 5 /* number of times (seconds) to retry an input file */ + +/*==================* + * GLOBAL VARIABLES * + *==================*/ +extern int yuvWidth, yuvHeight; +char currentGOPPath[MAXPATHLEN]; +char currentFramePath[MAXPATHLEN]; + + +/*===============================* + * INTERNAL PROCEDURE prototypes * + *===============================*/ + +static void AppendFile _ANSI_ARGS_((FILE *outputFile, FILE *inputFile)); + + +/*=====================* + * EXPORTED PROCEDURES * + *=====================*/ + +/*===========================================================================* + * + * GOPStoMPEG + * + * convert some number of GOP files into a single MPEG sequence file + * + * RETURNS: nothing + * + * SIDE EFFECTS: none + * + *===========================================================================*/ +void +GOPStoMPEG(int numGOPS, + char *outputFileName, + FILE *outputFilePtr) +{ + register int ind; + BitBucket *bb; + char fileName[1024]; + char inputFileName[1024]; + FILE *inputFile; + int q; + + { + /* Why is this reset called? */ + int x=Fsize_x, y=Fsize_y; + Fsize_Reset(); + Fsize_Note(0, yuvWidth, yuvHeight); + if (Fsize_x == 0 || Fsize_y == 0) { + Fsize_Note(0, x, y); + }} + + bb = Bitio_New(outputFilePtr); + + Mhead_GenSequenceHeader(bb, Fsize_x, Fsize_y, /* pratio */ aspectRatio, + /* pict_rate */ frameRate, /* bit_rate */ -1, + /* buf_size */ -1, /*c_param_flag */ 1, + /* iq_matrix */ customQtable, /* niq_matrix */ customNIQtable, + /* ext_data */ NULL, /* ext_data_size */ 0, + /* user_data */ NULL, /* user_data_size */ 0); + + /* it's byte-padded, so we can dump it now */ + Bitio_Flush(bb); + + if ( numGOPS > 0 ) { + for ( ind = 0; ind < numGOPS; ind++ ) { + GetNthInputFileName(inputFileName, ind); + sprintf(fileName, "%s/%s", currentGOPPath, inputFileName); + + for (q = 0; q < READ_ATTEMPTS; ++q ) { + if ( (inputFile = fopen(fileName, "rb")) != NULL ) break; + fprintf(stderr, "ERROR: Couldn't read (GOPStoMPEG): %s retry %d\n", + fileName, q); + fflush(stderr); + sleep(1); + } + if (q == READ_ATTEMPTS) { + throw "Giving up"; + } + + if (! realQuiet) { + fprintf(stdout, "appending file: %s\n", fileName); + } + + AppendFile(outputFilePtr, inputFile); + } + } else { + ind = 0; + while ( TRUE ) { + sprintf(fileName, "%s.gop.%d", outputFileName, ind); + + if ( (inputFile = fopen(fileName, "rb")) == NULL ) { + break; + } + + if (! realQuiet) { + fprintf(stdout, "appending file: %s\n", fileName); + } + + AppendFile(outputFilePtr, inputFile); + + ind++; + } + } + + bb = Bitio_New(outputFilePtr); + + /* SEQUENCE END CODE */ + Mhead_GenSequenceEnder(bb); + + Bitio_Flush(bb); + + fclose(outputFilePtr); +} + + +/*===========================================================================* + * + * FramestoMPEG + * + * convert some number of frame files into a single MPEG sequence file + * + * if parallel == TRUE, then when appending a file, blocks until that + * file is actually ready + * + * RETURNS: nothing + * + * SIDE EFFECTS: none + * + *===========================================================================*/ +void +FramesToMPEG(int numFrames, + char *outputFileName, + FILE *outputFile, + boolean parallel) +{ + register int ind; + BitBucket *bb; + char fileName[1024]; + char inputFileName[1024]; + FILE *inputFile; + int pastRefNum = -1; + int futureRefNum = -1; + int q; + + tc_hrs = 0; tc_min = 0; tc_sec = 0; tc_pict = 0; tc_extra = 0; + + { + /* Why is this reset called? */ + int x=Fsize_x, y=Fsize_y; + Fsize_Reset(); + Fsize_Note(0, yuvWidth, yuvHeight); + if (Fsize_x == 0 || Fsize_y == 0) { + Fsize_Note(0, x, y); + }} + SetBlocksPerSlice(); + + bb = Bitio_New(outputFile); + Mhead_GenSequenceHeader(bb, Fsize_x, Fsize_y, /* pratio */ aspectRatio, + /* pict_rate */ frameRate, /* bit_rate */ -1, + /* buf_size */ -1, /*c_param_flag */ 1, + /* iq_matrix */ qtable, /* niq_matrix */ niqtable, + /* ext_data */ NULL, /* ext_data_size */ 0, + /* user_data */ NULL, /* user_data_size */ 0); + /* it's byte-padded, so we can dump it now */ + Bitio_Flush(bb); + + /* need to do these in the right order!!! */ + /* also need to add GOP headers */ + + currentGOP = gopSize; + totalFramesSent = 0; + + if ( numFrames > 0 ) { + for ( ind = 0; ind < numFrames; ind++ ) { + if ( FRAME_TYPE(ind) == 'b' ) { + continue; + } + + pastRefNum = futureRefNum; + futureRefNum = ind; + + if ( (FRAME_TYPE(ind) == 'i') && (currentGOP >= gopSize) ) { + int closed; + + /* first, check to see if closed GOP */ + if ( totalFramesSent == ind ) { + closed = 1; + } else { + closed = 0; + } + + if (! realQuiet) { + fprintf(stdout, "Creating new GOP (closed = %d) after %d frames\n", + closed, currentGOP); + } + + /* new GOP */ + bb = Bitio_New(outputFile); + Mhead_GenGOPHeader(bb, /* drop_frame_flag */ 0, + tc_hrs, tc_min, tc_sec, tc_pict, + closed, /* broken_link */ 0, + /* ext_data */ NULL, /* ext_data_size */ 0, + /* user_data */ NULL, /* user_data_size */ 0); + Bitio_Flush(bb); + SetGOPStartTime(ind); + + currentGOP -= gopSize; + } + + if ( parallel ) { + WaitForOutputFile(ind); + sprintf(fileName, "%s.frame.%d", outputFileName, ind); + } else { + GetNthInputFileName(inputFileName, ind); + sprintf(fileName, "%s/%s", currentFramePath, inputFileName); + } + + for (q = 0; q < READ_ATTEMPTS; ++q ) { + if ( (inputFile = fopen(fileName, "rb")) != NULL ) break; + fprintf(stderr, "ERROR: Couldn't read 2: %s retry %d\n", fileName, q); + fflush(stderr); + sleep(1); + } + if (q == READ_ATTEMPTS) { + throw "Giving up"; + } + + AppendFile(outputFile, inputFile); + if ( parallel ) { + remove(fileName); + } + + currentGOP++; + IncrementTCTime(); + + /* now, output the B-frames */ + if ( pastRefNum != -1 ) { + register int bNum; + + for ( bNum = pastRefNum+1; bNum < futureRefNum; bNum++ ) { + if ( parallel ) { + WaitForOutputFile(bNum); + sprintf(fileName, "%s.frame.%d", outputFileName, bNum); + } else { + GetNthInputFileName(inputFileName, bNum); + sprintf(fileName, "%s/%s", currentFramePath, inputFileName); + } + + + for (q = 0; q < READ_ATTEMPTS; ++q ) { + if ( (inputFile = fopen(fileName, "rb")) != NULL ) break; + fprintf(stderr, "ERROR: Couldn't read (bNum=%d): %s retry %d\n", + bNum, fileName, q); + fflush(stderr); + sleep(1); + } + if (q == READ_ATTEMPTS) { + throw "Giving up"; + } + + AppendFile(outputFile, inputFile); + if ( parallel ) { + remove(fileName); + } + + currentGOP++; + IncrementTCTime(); + } + } + } + } else { + if ( parallel ) { + throw "PARALLEL COMBINE WITH 0 FRAMES"; + } + + ind = 0; + while ( TRUE ) { + if ( FRAME_TYPE(ind) == 'b' ) { + ind++; + continue; + } + + if ( (FRAME_TYPE(ind) == 'i') && (currentGOP >= gopSize) ) { + int closed; + + /* first, check to see if closed GOP */ + if ( totalFramesSent == ind ) { + closed = 1; + } else { + closed = 0; + } + + if (! realQuiet) { + fprintf(stdout, "Creating new GOP (closed = %d) before frame %d\n", + closed, ind); + } + + /* new GOP */ + bb = Bitio_New(outputFile); + Mhead_GenGOPHeader(bb, /* drop_frame_flag */ 0, + tc_hrs, tc_min, tc_sec, tc_pict, + closed, /* broken_link */ 0, + /* ext_data */ NULL, /* ext_data_size */ 0, + /* user_data */ NULL, /* user_data_size */ 0); + Bitio_Flush(bb); + SetGOPStartTime(ind); + + currentGOP -= gopSize; + } + + sprintf(fileName, "%s.frame.%d", outputFileName, ind); + + if ( (inputFile = fopen(fileName, "rb")) == NULL ) { + break; + } + + AppendFile(outputFile, inputFile); + if ( parallel ) { + remove(fileName); + } + + currentGOP++; + IncrementTCTime(); + + /* now, output the B-frames */ + if ( pastRefNum != -1 ) { + register int bNum; + + for ( bNum = pastRefNum+1; bNum < futureRefNum; bNum++ ) { + sprintf(fileName, "%s.frame.%d", outputFileName, bNum); + + for (q = 0; q < READ_ATTEMPTS; ++q ) { + if ( (inputFile = fopen(fileName, "rb")) != NULL ) break; + fprintf(stderr, "ERROR: Couldn't read (FramestoMPEG): %s retry %d\n", + fileName, q); + fflush(stderr); + sleep(1); + } + if (q == READ_ATTEMPTS) { + throw "Giving up"; + } + + AppendFile(outputFile, inputFile); + if ( parallel ) { + remove(fileName); + } + + currentGOP++; + IncrementTCTime(); + } + } + + ind++; + } + } + + if (! realQuiet) { + fprintf(stdout, "Wrote %d frames\n", totalFramesSent); + fflush(stdout); + } + + bb = Bitio_New(outputFile); + + /* SEQUENCE END CODE */ + Mhead_GenSequenceEnder(bb); + + Bitio_Flush(bb); + + fclose(outputFile); +} + + +/*=====================* + * INTERNAL PROCEDURES * + *=====================*/ + +/*===========================================================================* + * + * AppendFile + * + * appends the output file with the contents of the given input file + * + * RETURNS: nothing + * + * SIDE EFFECTS: none + * + *===========================================================================*/ +static void +AppendFile(FILE *outputFile, + FILE *inputFile) +{ + uint8 data[9999]; + int readItems; + + readItems = 9999; + while ( readItems == 9999 ) { + readItems = fread(data, sizeof(uint8), 9999, inputFile); + if ( readItems > 0 ) { + fwrite(data, sizeof(uint8), readItems, outputFile); + } + } + + fclose(inputFile); +} + + diff --git a/contrib/mpeg_encode/frame.cpp b/contrib/mpeg_encode/frame.cpp new file mode 100644 index 0000000000000000000000000000000000000000..8698b439e87123ca5d33e1ad4562bb8c656a93d9 --- /dev/null +++ b/contrib/mpeg_encode/frame.cpp @@ -0,0 +1,952 @@ +/*===========================================================================* + * frame.c * + * * + * basic frame procedures * + * * + * EXPORTED PROCEDURES: * + * Frame_Init * + * Frame_Exit * + * Frame_New * + * Frame_Free * + * Frame_AllocPPM * + * Frame_AllocBlocks * + * Frame_AllocYCC * + * Frame_AllocDecoded * + * Frame_AllocHalf * + * Frame_Resize * + * * + *===========================================================================*/ + +/* + * Copyright (c) 1995 The Regents of the University of California. + * All rights reserved. + * + * Permission to use, copy, modify, and distribute this software and its + * documentation for any purpose, without fee, and without written agreement is + * hereby granted, provided that the above copyright notice and the following + * two paragraphs appear in all copies of this software. + * + * IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR + * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT + * OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF + * CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS + * ON AN "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO + * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. + */ + + +/*==============* + * HEADER FILES * + *==============*/ + +#include "all.h" +#include "mtypes.h" +#include "frames.h" +#include "frame.h" +#include "fsize.h" +#include "dct.h" + +/*===========* + * CONSTANTS * + *===========*/ + +/* The maximum number of B-Frames allowed between reference frames. */ +#define B_FRAME_RUN 16 + +/*==================* + * GLOBAL VARIABLES * + *==================*/ + +MpegFrame *frameMemory[B_FRAME_RUN+2]; +extern boolean stdinUsed; +extern char *framePattern; + + +/*===============================* + * INTERNAL PROCEDURE prototypes * + *===============================*/ + +static void FreeFrame _ANSI_ARGS_((MpegFrame * mf)); +static MpegFrame *GetUnusedFrame _ANSI_ARGS_((void)); +static void GetNumOfFrames _ANSI_ARGS_((int *numOfFrames)); +static void ResetFrame _ANSI_ARGS_((int fnumber, int type, MpegFrame *frame)); +static void Resize_Width _ANSI_ARGS_((MpegFrame *omfrw,MpegFrame *mfrw, int in_x, + int in_y, int out_x)); +static void Resize_Height _ANSI_ARGS_((MpegFrame *omfrh,MpegFrame *mfrh, + int in_x, + int in_y, int out_y)); +static void Resize_Array_Width _ANSI_ARGS_((uint8 **inarray,int in_x, + int in_y,uint8 **outarray, int out_x)); +static void Resize_Array_Height _ANSI_ARGS_((uint8 **inarray,int in_x, + int in_y,uint8 **outarray, int out_y)); + + +/*=====================* + * EXPORTED PROCEDURES * + *=====================*/ + +/*=============================================================== + * + * Frame_Resize by James Boucher + * Boston University Multimedia Communications Lab + * + * This function takes the mf input frame, read in READFrame(), + * and resizes all the input component arrays to the output + * dimensions specified in the parameter file as OUT_SIZE. + * The new frame is returned with the omf pointer. As well, + * the values of Fsize_x and Fsize_y are adjusted. + ***************************************************************/ +void +Frame_Resize(MpegFrame *omf, MpegFrame *mf, + int insize_x, int insize_y, int outsize_x, int outsize_y) +{ +MpegFrame *frameA; /* intermediate frame */ + +frameA = (MpegFrame *)malloc(sizeof(MpegFrame)); + +if((insize_x != outsize_x)&&(insize_y != outsize_y)){ +Resize_Width(frameA,mf,insize_x,insize_y,outsize_x); +Resize_Height(omf,frameA,outsize_x,insize_y,outsize_y); +}else +if((insize_x ==outsize_x)&&(insize_y != outsize_y)){ +Resize_Height(omf,mf,insize_x,insize_y,outsize_y); +} else +if((insize_x !=outsize_x)&&(insize_y == outsize_y)){ +Resize_Width(omf,mf,insize_x,insize_y,outsize_x); +} +else{ + throw "Problem in Frame_Resize"; + } +/* Free memory */ +free(frameA); +free(mf); +} +/*======================================================== +* Resize_Width +*======================================================*/ +static void +Resize_Width(MpegFrame *omfrw, MpegFrame *mfrw, + int in_x, int in_y, int out_x) +{ +register int y; +int i; + +omfrw->orig_y = NULL; +Fsize_x = out_x; +/* Allocate new frame memory */ + omfrw->orig_y = (uint8 **) malloc(sizeof(uint8 *) * Fsize_y); + ERRCHK(omfrw->orig_y, "malloc"); + for (y = 0; y < Fsize_y; y++) { + omfrw->orig_y[y] = (uint8 *) malloc(sizeof(uint8) * out_x); + ERRCHK(omfrw->orig_y[y], "malloc"); + } + + omfrw->orig_cr = (uint8 **) malloc(sizeof(int8 *) * Fsize_y / 2); + ERRCHK(omfrw->orig_cr, "malloc"); + for (y = 0; y < Fsize_y / 2; y++) { + omfrw->orig_cr[y] = (uint8 *) malloc(sizeof(int8) * out_x / 2); + ERRCHK(omfrw->orig_cr[y], "malloc"); + } + + omfrw->orig_cb = (uint8 **) malloc(sizeof(int8 *) * Fsize_y / 2); + ERRCHK(omfrw->orig_cb, "malloc"); + for (y = 0; y < Fsize_y / 2; y++) { + omfrw->orig_cb[y] = (uint8 *) malloc(sizeof(int8) * out_x / 2); + ERRCHK(omfrw->orig_cb[y], "malloc"); + } + + if ( referenceFrame == ORIGINAL_FRAME ) { + omfrw->ref_y = omfrw->orig_y; + omfrw->ref_cr = omfrw->orig_cr; + omfrw->ref_cb = omfrw->orig_cb; + } + +/* resize each component array separately */ +Resize_Array_Width(mfrw->orig_y,in_x,in_y,omfrw->orig_y,out_x); +Resize_Array_Width(mfrw->orig_cr,(in_x/2),(in_y/2),omfrw->orig_cr,(out_x/2)); +Resize_Array_Width(mfrw->orig_cb,(in_x/2),(in_y/2),omfrw->orig_cb,(out_x/2)); + +/* Free old frame memory */ + if (mfrw->orig_y) { + for (i = 0; i < in_y; i++) { + free(mfrw->orig_y[i]); + } + free(mfrw->orig_y); + + for (i = 0; i < in_y / 2; i++) { + free(mfrw->orig_cr[i]); + } + free(mfrw->orig_cr); + + for (i = 0; i < in_y / 2; i++) { + free(mfrw->orig_cb[i]); + } + free(mfrw->orig_cb); + } + +} + +/*======================================================= +* Resize_Height +* +* Resize Frame height up or down +*=======================================================*/ +static void +Resize_Height(MpegFrame *omfrh, MpegFrame *mfrh, + int in_x, int in_y, int out_y) +{ +register int y; +int i; + +Fsize_y = out_y; + +/* Allocate new frame memory */ + omfrh->orig_y = (uint8 **) malloc(sizeof(uint8 *) * out_y); + ERRCHK(omfrh->orig_y, "malloc"); + for (y = 0; y < out_y; y++) { + omfrh->orig_y[y] = (uint8 *) malloc(sizeof(uint8) * Fsize_x); + ERRCHK(omfrh->orig_y[y], "malloc"); + } + + omfrh->orig_cr = (uint8 **) malloc(sizeof(int8 *) * out_y / 2); + ERRCHK(omfrh->orig_cr, "malloc"); + for (y = 0; y < out_y / 2; y++) { + omfrh->orig_cr[y] = (uint8 *) malloc(sizeof(int8) * Fsize_x / 2); + ERRCHK(omfrh->orig_cr[y], "malloc"); + } + + omfrh->orig_cb = (uint8 **) malloc(sizeof(int8 *) * out_y / 2); + ERRCHK(omfrh->orig_cb, "malloc"); + for (y = 0; y < out_y / 2; y++) { + omfrh->orig_cb[y] = (uint8 *) malloc(sizeof(int8) * Fsize_x / 2); + ERRCHK(omfrh->orig_cb[y], "malloc"); + } + + if ( referenceFrame == ORIGINAL_FRAME ) { + omfrh->ref_y = omfrh->orig_y; + omfrh->ref_cr = omfrh->orig_cr; + omfrh->ref_cb = omfrh->orig_cb; + } + +/* resize component arrays separately */ +Resize_Array_Height(mfrh->orig_y,in_x,in_y,omfrh->orig_y,out_y); +Resize_Array_Height(mfrh->orig_cr,(in_x/2),(in_y/2),omfrh->orig_cr,(out_y/2)); +Resize_Array_Height(mfrh->orig_cb,(in_x/2),(in_y/2),omfrh->orig_cb,(out_y/2)); + +/* Free old frame memory */ + if (mfrh->orig_y) { + for (i = 0; i < in_y; i++) { + free(mfrh->orig_y[i]); + } + free(mfrh->orig_y); + + for (i = 0; i < in_y / 2; i++) { + free(mfrh->orig_cr[i]); + } + free(mfrh->orig_cr); + + for (i = 0; i < in_y / 2; i++) { + free(mfrh->orig_cb[i]); + } + free(mfrh->orig_cb); + } + +} +/*==================================================== +* Resize_Array_Width +* +* This function will resize any array width up +* or down in size. The algorithm is based on the +* least common multiple approach more commonly +* used in audio frequency adjustments. +*=====================================================*/ +static void +Resize_Array_Width(uint8 **inarray, + int in_x, + int in_y, + uint8 **outarray, + int out_x) +{ +int i,j; +int in_total; +int out_total; +uint8 *inptr; +uint8 *outptr; +uint8 pointA,pointB; +/* double slope,diff; */ + + for(i=0;i<in_y;i++){ /* For every row */ + inptr = &inarray[i][0]; + outptr = &outarray[i][0]; + in_total = 0; + out_total = 0; + for(j=0;j<out_x;j++){ /* For every output value */ + if(in_total == out_total){ + *outptr = *inptr; + outptr++; + out_total=out_total+in_x; + while(in_total < out_total){ + in_total = in_total + out_x; + inptr++; + } + if(in_total > out_total){ + in_total = in_total - out_x; + inptr--; + } + } else { + pointA = *inptr; + inptr++; + pointB = *inptr; + inptr--; +/*Interpolative solution */ +/* slope = ((double)(pointB -pointA))/((double)(out_x)); + diff = (((double)(out_total - in_total))); + if(diff < (out_x/2)){ + *outptr = (pointA + (uint8)(slope*diff)); + } else { + *outptr = (pointB - (uint8)(slope*(((float)(out_x)) - diff))); + } */ +/* Non-Interpolative solution */ + *outptr = *inptr; + + outptr++; + out_total=out_total+in_x; + while(in_total < out_total){ + in_total = in_total + out_x; + inptr++; + } + if(in_total > out_total){ + in_total = in_total - out_x; + inptr--; + } + } /* end if */ + } /* end for each output value */ + + } /* end for each row */ +} /* end main */ +/*============================== +* Resize_Array_Height +* +* Resize any array height larger or smaller. +* Same as Resize_array_Width except pointer +* manipulation must change. +*===============================*/ +static void +Resize_Array_Height(uint8 **inarray, + int in_x, + int in_y, + uint8 **outarray, + int out_y) +{ +int i,j,k; +int in_total; +int out_total; +uint8 pointA,pointB; +double slope,diff; + + for(i=0;i<in_x;i++){ /* for each column */ + in_total = 0; + out_total = 0; + k = 0; + for(j=0;j<out_y;j++){ /* for each output value */ + if(in_total == out_total){ + outarray[j][i] = inarray[k][i]; + out_total=out_total+in_y; + while(in_total < out_total){ + in_total = in_total + out_y; + k++; + } + if(in_total > out_total){ + in_total = in_total - out_y; + k--; + } + } else { + + pointA = inarray[k][i]; + if(k != (in_y -1)){ + pointB = inarray[k+1][i]; + } else { + pointB = pointA; + } +/* Interpolative case */ + slope = ((double)(pointB -pointA))/(double)(out_y); + diff = (double)(out_total - in_total); +/* outarray[j][i] = (inarray[k][i] + (uint8)(slope*diff)); +*/ +/* Non-Interpolative case */ + outarray[j][i] = inarray[k][i]; + out_total=out_total+in_y; + while(in_total < out_total){ + in_total = in_total + out_y; + k++; + } + if(in_total > out_total){ + in_total = in_total - out_y; + k--; + } + } + } + } + +} + + + +/*===========================================================================* + * + * Frame_Init + * + * initializes the memory associated with all frames ever + * If the input is not coming in from stdin, only 3 frames are needed ; + * else, the program must create frames equal to the greatest distance + * between two reference frames to hold the B frames while it is parsing + * the input from stdin. + * + * RETURNS: nothing + * + * SIDE EFFECTS: frameMemory + * + *===========================================================================*/ +void +Frame_Init() +{ + register int idx; + int numOfFrames = 0; + + GetNumOfFrames(&numOfFrames); + + for ( idx = 0; idx < numOfFrames; idx++ ) { + frameMemory[idx] = (MpegFrame *) malloc(sizeof(MpegFrame)); + frameMemory[idx]->inUse = FALSE; + frameMemory[idx]->ppm_data = NULL; + frameMemory[idx]->rgb_data = NULL; + frameMemory[idx]->orig_y = NULL; /* if NULL, then orig_cr, orig_cb invalid */ + frameMemory[idx]->y_blocks = NULL; /* if NULL, then cr_blocks, cb_blocks invalid */ + frameMemory[idx]->decoded_y = NULL; /* if NULL, then blah blah */ + frameMemory[idx]->halfX = NULL; + frameMemory[idx]->next = NULL; + } + +#ifdef BLEAH +fprintf (stderr, "%d frames allocated.\n", numOfFrames); +#endif +} + + +/*===========================================================================* + * + * Frame_Exit + * + * frees the memory associated with frames + * + * RETURNS: nothing + * + * SIDE EFFECTS: frameMemory + * + *===========================================================================*/ +void +Frame_Exit() +{ + register int idx; + int numOfFrames = 0; + + GetNumOfFrames(&numOfFrames); + + for ( idx = 0; idx < numOfFrames; idx++ ) { + FreeFrame(frameMemory[idx]); + } +} + + +/*===========================================================================* + * + * Frame_Free + * + * frees the given frame -- allows it to be re-used + * + * RETURNS: nothing + * + * SIDE EFFECTS: none + * + *===========================================================================*/ +void +Frame_Free(MpegFrame *frame) +{ + frame->inUse = FALSE; +} + + +/*===========================================================================* + * + * Frame_New + * + * finds a frame that isn't currently being used and resets it + * + * RETURNS: the frame + * + * SIDE EFFECTS: none + * + *===========================================================================*/ +MpegFrame * +Frame_New(int id, int type) +{ + MpegFrame *frame; + + frame = GetUnusedFrame(); + ResetFrame(id, type, frame); + + return frame; +} + + +/*===========================================================================* + * + * Frame_AllocPPM + * + * allocate memory for ppm data for the given frame, if required + * + * RETURNS: nothing + * + * SIDE EFFECTS: none + * + *===========================================================================*/ +void +Frame_AllocPPM(MpegFrame *frame) +{ + register int y; + + if ( frame->ppm_data != NULL ) { /* already allocated */ + return; + } + + frame->ppm_data = (uint8 **) malloc(sizeof(uint8 *) * Fsize_y); + ERRCHK(frame->ppm_data, "malloc"); + + for ( y = 0; y < Fsize_y; y++ ) { + frame->ppm_data[y] = (uint8 *) malloc(3*sizeof(uint8) * Fsize_x); + ERRCHK(frame->ppm_data[y], "malloc"); + } +} + + +/*===========================================================================* + * + * Frame_AllocBlocks + * + * allocate memory for blocks for the given frame, if required + * + * RETURNS: nothing + * + * SIDE EFFECTS: none + * + *===========================================================================*/ +void +Frame_AllocBlocks(MpegFrame *frame) +{ + int dctx, dcty; + int i; + + if ( frame->y_blocks != NULL ) { /* already allocated */ + return; + } + + dctx = Fsize_x / DCTSIZE; + dcty = Fsize_y / DCTSIZE; + + frame->y_blocks = (Block **) malloc(sizeof(Block *) * dcty); + ERRCHK(frame->y_blocks, "malloc"); + for (i = 0; i < dcty; i++) { + frame->y_blocks[i] = (Block *) malloc(sizeof(Block) * dctx); + ERRCHK(frame->y_blocks[i], "malloc"); + } + + frame->cr_blocks = (Block **) malloc(sizeof(Block *) * (dcty >> 1)); + frame->cb_blocks = (Block **) malloc(sizeof(Block *) * (dcty >> 1)); + ERRCHK(frame->cr_blocks, "malloc"); + ERRCHK(frame->cb_blocks, "malloc"); + for (i = 0; i < (dcty >> 1); i++) { + frame->cr_blocks[i] = (Block *) malloc(sizeof(Block) * (dctx >> 1)); + frame->cb_blocks[i] = (Block *) malloc(sizeof(Block) * (dctx >> 1)); + ERRCHK(frame->cr_blocks[i], "malloc"); + ERRCHK(frame->cb_blocks[i], "malloc"); + } +} + + +/*===========================================================================* + * + * Frame_AllocYCC + * + * allocate memory for YCC info for the given frame, if required + * + * RETURNS: nothing + * + * SIDE EFFECTS: none + * + *===========================================================================*/ +void +Frame_AllocYCC(MpegFrame *frame) +{ + register int y; + + if ( frame->orig_y != NULL ) { /* already allocated */ + return /* nothing */ ; + } + + DBG_PRINT(("ycc_calc:\n")); + /* + * first, allocate tons of memory + */ + frame->orig_y = (uint8 **) malloc(sizeof(uint8 *) * Fsize_y); + ERRCHK(frame->orig_y, "malloc"); + for (y = 0; y < Fsize_y; y++) { + frame->orig_y[y] = (uint8 *) malloc(sizeof(uint8) * Fsize_x); + ERRCHK(frame->orig_y[y], "malloc"); + } + + frame->orig_cr = (uint8 **) malloc(sizeof(int8 *) * (Fsize_y >> 1)); + ERRCHK(frame->orig_cr, "malloc"); + for (y = 0; y < (Fsize_y >> 1); y++) { + frame->orig_cr[y] = (uint8 *) malloc(sizeof(int8) * (Fsize_x >> 1)); + ERRCHK(frame->orig_cr[y], "malloc"); + } + + frame->orig_cb = (uint8 **) malloc(sizeof(int8 *) * (Fsize_y >> 1)); + ERRCHK(frame->orig_cb, "malloc"); + for (y = 0; y < (Fsize_y >> 1); y++) { + frame->orig_cb[y] = (uint8 *) malloc(sizeof(int8) * (Fsize_x >> 1)); + ERRCHK(frame->orig_cb[y], "malloc"); + } + + if ( referenceFrame == ORIGINAL_FRAME ) { + frame->ref_y = frame->orig_y; + frame->ref_cr = frame->orig_cr; + frame->ref_cb = frame->orig_cb; + } +} + + + +/*===========================================================================* + * + * Frame_AllocHalf + * + * allocate memory for half-pixel values for the given frame, if required + * + * RETURNS: nothing + * + * SIDE EFFECTS: none + * + *===========================================================================*/ +void +Frame_AllocHalf(MpegFrame *frame) +{ + register int y; + + if ( frame->halfX != NULL ) { + return; + } + + frame->halfX = (uint8 **) malloc(Fsize_y*sizeof(uint8 *)); + ERRCHK(frame->halfX, "malloc"); + frame->halfY = (uint8 **) malloc((Fsize_y-1)*sizeof(uint8 *)); + ERRCHK(frame->halfY, "malloc"); + frame->halfBoth = (uint8 **) malloc((Fsize_y-1)*sizeof(uint8 *)); + ERRCHK(frame->halfBoth, "malloc"); + for ( y = 0; y < Fsize_y; y++ ) { + frame->halfX[y] = (uint8 *) malloc((Fsize_x-1)*sizeof(uint8)); + ERRCHK(frame->halfX[y], "malloc"); + } + for ( y = 0; y < Fsize_y-1; y++ ) { + frame->halfY[y] = (uint8 *) malloc(Fsize_x*sizeof(uint8)); + ERRCHK(frame->halfY[y], "malloc"); + } + for ( y = 0; y < Fsize_y-1; y++ ) { + frame->halfBoth[y] = (uint8 *) malloc((Fsize_x-1)*sizeof(uint8)); + ERRCHK(frame->halfBoth[y], "malloc"); + } +} + + +/*===========================================================================* + * + * Frame_AllocDecoded + * + * allocate memory for decoded frame for the given frame, if required + * if makeReference == TRUE, then makes it reference frame + * + * RETURNS: nothing + * + * SIDE EFFECTS: none + * + *===========================================================================*/ +void +Frame_AllocDecoded(MpegFrame *frame, boolean makeReference) +{ + register int y; + + if ( frame->decoded_y != NULL) { /* already allocated */ + return; + } + + /* allocate memory for decoded image */ + /* can probably reuse original image memory, but may decide to use + it for some reason, so do it this way at least for now -- more + flexible + */ + frame->decoded_y = (uint8 **) malloc(sizeof(uint8 *) * Fsize_y); + ERRCHK(frame->decoded_y, "malloc"); + for (y = 0; y < Fsize_y; y++) { + frame->decoded_y[y] = (uint8 *) malloc(sizeof(uint8) * Fsize_x); + ERRCHK(frame->decoded_y[y], "malloc"); + } + + frame->decoded_cr = (uint8 **) malloc(sizeof(int8 *) * (Fsize_y >> 1)); + ERRCHK(frame->decoded_cr, "malloc"); + for (y = 0; y < (Fsize_y >> 1); y++) { + frame->decoded_cr[y] = (uint8 *) malloc(sizeof(uint8) * (Fsize_x >> 1)); + ERRCHK(frame->decoded_cr[y], "malloc"); + } + + frame->decoded_cb = (uint8 **) malloc(sizeof(int8 *) * (Fsize_y >> 1)); + ERRCHK(frame->decoded_cb, "malloc"); + for (y = 0; y < (Fsize_y >> 1); y++) { + frame->decoded_cb[y] = (uint8 *) malloc(sizeof(uint8) * (Fsize_x >> 1)); + ERRCHK(frame->decoded_cb[y], "malloc"); + } + + if ( makeReference ) { + frame->ref_y = frame->decoded_y; + frame->ref_cr = frame->decoded_cr; + frame->ref_cb = frame->decoded_cb; + } +} + + +/*=====================* + * INTERNAL PROCEDURES * + *=====================*/ + + +/*===========================================================================* + * + * GetUnusedFrame + * + * return an unused frame + * + * RETURNS: the frame + * + * SIDE EFFECTS: none + * + *===========================================================================*/ +static MpegFrame * +GetUnusedFrame() +{ + register int idx; + int numOfFrames; + + GetNumOfFrames(&numOfFrames); + + for ( idx = 0; idx < numOfFrames; idx++ ) { + if ( ! frameMemory[idx]->inUse ) { + frameMemory[idx]->inUse = TRUE; + return frameMemory[idx]; + } + } + + throw "No unused frames: " + "If you are using stdin for input, it is likely that you have too many " + "B-frames between two reference frames. See the man page for help."; +} + + +/*===========================================================================* + * + * GetNumOfFrames + * + * return the number of frames to allocate + * + * RETURNS: nothing + * + * SIDE EFFECTS: numOfFrames contains the number to allocate + * + *===========================================================================*/ +static void +GetNumOfFrames(int *numOfFrames) +{ + int idx, bcount; + + if (stdinUsed) { + for ( idx = 0, bcount = 0; idx < strlen(framePattern); idx++) { + + /* counts the maximum number of B frames between two reference + * frames. + */ + + switch( framePattern[idx] ) { + case 'b': + bcount++; + break; + case 'i': + case 'p': + if (bcount > *numOfFrames) { + *numOfFrames = bcount; + } + bcount = 0; + break; + } + + /* add 2 to hold the forward and past reference frames in addition + * to the maximum number of B's + */ + } + + *numOfFrames += 2; + + } else { + /* non-interactive, only 3 frames needed */ + *numOfFrames = 3; + } +} + +/*===========================================================================* + * + * ResetFrame + * + * reset a frame to the given id and type + * + * RETURNS: nothing + * + * SIDE EFFECTS: none + * + *===========================================================================*/ +static void +ResetFrame(int id, int type, MpegFrame *frame) +{ + switch (type) { + case 'i': + frame->type = TYPE_IFRAME; + break; + case 'p': + frame->type = TYPE_PFRAME; + break; + case 'b': + frame->type = TYPE_BFRAME; + break; + default: + throw "frame type: not supported"; + } + + frame->id = id; + frame->halfComputed = FALSE; + frame->next = NULL; +} + + +/*===========================================================================* + * + * FreeFrame + * + * frees the memory associated with the given frame + * + * RETURNS: nothing + * + * SIDE EFFECTS: none + * + *===========================================================================*/ +static void +FreeFrame(MpegFrame *frame) +{ + int i; + + if (!frame) { + return; + } + + if ( frame->ppm_data ) { + /* it may be a little bigger than Fsize_y, but that's fine for + our purposes, since we aren't going to free until we exit anyway, + so by the time we call this we won't care + */ + pnm_freearray(frame->ppm_data, Fsize_y); + frame->ppm_data = NULL; + } + + if (frame->rgb_data) { + pnm_freearray(frame->rgb_data, Fsize_y); + } + if (frame->orig_y) { + for (i = 0; i < Fsize_y; i++) { + free(frame->orig_y[i]); + } + free(frame->orig_y); + + for (i = 0; i < (Fsize_y >> 1); i++) { + free(frame->orig_cr[i]); + } + free(frame->orig_cr); + + for (i = 0; i < (Fsize_y >> 1); i++) { + free(frame->orig_cb[i]); + } + free(frame->orig_cb); + } + if ( frame->decoded_y ) { + for (i = 0; i < Fsize_y; i++) { + free(frame->decoded_y[i]); + } + free(frame->decoded_y); + + for (i = 0; i < (Fsize_y >> 1); i++) { + free(frame->decoded_cr[i]); + } + free(frame->decoded_cr); + + for (i = 0; i < (Fsize_y >> 1); i++) { + free(frame->decoded_cb[i]); + } + free(frame->decoded_cb); + } + + if (frame->y_blocks) { + for (i = 0; i < Fsize_y / DCTSIZE; i++) { + free(frame->y_blocks[i]); + } + free(frame->y_blocks); + + for (i = 0; i < Fsize_y / (2 * DCTSIZE); i++) { + free(frame->cr_blocks[i]); + } + free(frame->cr_blocks); + + for (i = 0; i < Fsize_y / (2 * DCTSIZE); i++) { + free(frame->cb_blocks[i]); + } + free(frame->cb_blocks); + } + if ( frame->halfX ) { + for ( i = 0; i < Fsize_y; i++ ) { + free(frame->halfX[i]); + } + free(frame->halfX); + + for ( i = 0; i < Fsize_y-1; i++ ) { + free(frame->halfY[i]); + } + free(frame->halfY); + + for ( i = 0; i < Fsize_y-1; i++ ) { + free(frame->halfBoth[i]); + } + free(frame->halfBoth); + } + + + free(frame); +} + + diff --git a/contrib/mpeg_encode/frametype.cpp b/contrib/mpeg_encode/frametype.cpp new file mode 100644 index 0000000000000000000000000000000000000000..16020db01531976657a46d6c95f16d3266176074 --- /dev/null +++ b/contrib/mpeg_encode/frametype.cpp @@ -0,0 +1,367 @@ +/*===========================================================================* + * frametype.c * + * * + * procedures to keep track of frame types (I, P, B) * + * * + * EXPORTED PROCEDURES: * + * FType_Type * + * FType_FutureRef * + * FType_PastRef * + * * + * SYNOPSIS * + * FType_Type returns the type of the given numbered frame * + * FType_FutureRef returns the number of the future reference frame * + * FType_PastRef returns the number of the past reference frame * + * * + *===========================================================================*/ + +/* + * Copyright (c) 1995 The Regents of the University of California. + * All rights reserved. + * + * Permission to use, copy, modify, and distribute this software and its + * documentation for any purpose, without fee, and without written agreement is + * hereby granted, provided that the above copyright notice and the following + * two paragraphs appear in all copies of this software. + * + * IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR + * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT + * OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF + * CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS + * ON AN "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO + * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. + */ + + +/*==============* + * HEADER FILES * + *==============*/ + +#include "all.h" +#include "prototypes.h" +#include "frames.h" +#include "frame.h" +#include "param.h" + + +static FrameTable *frameTable=NULL; +static boolean use_cache = FALSE; +static int firstI = 0; + +/*==================* + * GLOBAL VARIABLES * + *==================*/ + +boolean forceEncodeLast = FALSE; +extern int framePatternLen; +extern char *framePattern; + + +/*=====================* + * EXPORTED PROCEDURES * + *=====================*/ + +/*===========================================================================* + * + * FType_Type + * + * returns the type of the given numbered frame + * + * RETURNS: the type + * + * SIDE EFFECTS: none + * + *===========================================================================*/ +int +FType_Type(int frameNum) +{ + if (use_cache) return (int)frameTable[frameNum].typ; + + if ( forceEncodeLast && (frameNum+1 == numInputFiles) ) { + int result; + + result = framePattern[frameNum % framePatternLen]; + if ( result == 'b' ) return 'i'; + else return result; + } else { + if (specificsOn) { + static int lastI = -1; + int newtype; + + if (lastI > frameNum) lastI = -1; + newtype = SpecTypeLookup(frameNum); + switch (newtype) { + case 1: + lastI = frameNum; + return 'i'; + case 2: + return 'p'; + case 3: + return 'b'; + default: + if (lastI != -1) return framePattern[(frameNum-lastI+firstI) % framePatternLen]; + else return framePattern[frameNum % framePatternLen]; + } + } else return framePattern[frameNum % framePatternLen]; + } +} + + +/*===========================================================================* + * + * FType_FutureRef + * + * returns the number of the future reference frame + * + * RETURNS: the number; -1 if none + * + * SIDE EFFECTS: none + * + *===========================================================================*/ +int +FType_FutureRef(int currFrameNum) +{ + int index; + int futureIndex; + int result; + + if (use_cache) { + return frameTable[currFrameNum].next->number; + } else { + index = currFrameNum % framePatternLen; + futureIndex = frameTable[index].next->number; + + result = currFrameNum + + (((futureIndex-index)+framePatternLen) % framePatternLen); + + if ( (result >= numInputFiles) && forceEncodeLast ) { + return numInputFiles-1; + } else { + return result; + } + } +} + + +/*===========================================================================* + * + * FType_PastRef + * + * returns the number of the past reference frame + * + * RETURNS: the number + * + * SIDE EFFECTS: none + * + *===========================================================================*/ +int +FType_PastRef(int currFrameNum) +{ + int index; + int pastIndex; + + if (use_cache) { + return frameTable[currFrameNum].prev->number; + } else { + index = currFrameNum % framePatternLen; + pastIndex = frameTable[index].prev->number; + + return currFrameNum - + (((index-pastIndex)+framePatternLen) % framePatternLen); + } +} + + +/*===========================================================================* + * + * SetFramePattern + * + * set the IPB pattern; calls ComputeFrameTable to set up table + * + * RETURNS: nothing + * + * SIDE EFFECTS: framePattern, framePatternLen, frameTable + * + *===========================================================================*/ +#define SIMPLE_ASCII_UPPER(x) (((x)>='a') ? ((x)-'a'+'A') : (x)) +void +SetFramePattern(char *pattern) +{ + int len = strlen(pattern); + char *buf; + int index; + + if ( ! pattern ) { + throw "pattern cannot be NULL"; + } + + if ( SIMPLE_ASCII_UPPER(pattern[0]) != 'I' ) { + for (index=0; index < len; index++) { + + if (SIMPLE_ASCII_UPPER(pattern[index]) == 'I') { + break; + } else if (SIMPLE_ASCII_UPPER(pattern[index]) == 'P') { + throw "first reference frame must be 'i'"; + } + } + } + + buf = (char *)malloc(sizeof(char)*(len+1)); + ERRCHK(buf, "malloc"); + + firstI = -1; + for ( index = 0; index < len; index++ ) { + switch( SIMPLE_ASCII_UPPER(pattern[index]) ) { + case 'I': + buf[index] = 'i'; + if (firstI == -1) firstI = index; + break; + case 'P': + buf[index] = 'p'; + break; + case 'B': + buf[index] = 'b'; + break; + default: + throw "Frame type not supported"; + } + } + buf[len] = 0; + + if (firstI == -1) { + throw "Must have an I-frame in PATTERN"; + } + + framePattern = buf; + framePatternLen = len; + + /* Used to ComputeFrameTable(), but now must wait until param parsed. (STDIN or not)*/ +} + + +/*===========================================================================* + * + * ComputeFrameTable + * + * compute a table of I, P, B frames to help in determining dependencies + * + * RETURNS: nothing + * + * SIDE EFFECTS: frameTable + * + *===========================================================================*/ +void +ComputeFrameTable() +{ + register int index; + FrameTable *lastI, *lastIP, *firstB, *secondIP; + FrameTable *ptr; + char typ; + int table_size; + + if (!stdinUsed) { + table_size = numInputFiles; + } else { + table_size = framePatternLen; + } + + frameTable = (FrameTable *) malloc((1+table_size)*sizeof(FrameTable)); + ERRCHK(frameTable, "malloc"); + + lastI = NULL; + lastIP = NULL; + firstB = NULL; + secondIP = NULL; + for ( index = 0; index < table_size; index++ ) { + frameTable[index].number = index; + typ = FType_Type(index); + frameTable[index].typ = typ; + switch( typ ) { + case 'i': + ptr = firstB; + while ( ptr != NULL ) { + ptr->next = &(frameTable[index]); + ptr = ptr->nextOutput; + } + frameTable[index].nextOutput = firstB; + frameTable[index].prev = lastIP; /* for freeing */ + if ( lastIP != NULL ) { + lastIP->next = &(frameTable[index]); + if ( secondIP == NULL ) { + secondIP = &(frameTable[index]); + } + } + lastIP = &(frameTable[index]); + firstB = NULL; + break; + case 'p': + ptr = firstB; + while ( ptr != NULL ) { + ptr->next = &(frameTable[index]); + ptr = ptr->nextOutput; + } + frameTable[index].nextOutput = firstB; + frameTable[index].prev = lastIP; + if ( lastIP != NULL ) { + lastIP->next = &(frameTable[index]); + if ( secondIP == NULL ) { + secondIP = &(frameTable[index]); + } + } + lastIP = &(frameTable[index]); + firstB = NULL; + break; + case 'b': + if ( (index+1 == framePatternLen) || + (FType_Type(index+1) != 'b') ) { + frameTable[index].nextOutput = NULL; + } else { + frameTable[index].nextOutput = &(frameTable[index+1]); + } + frameTable[index].prev = lastIP; + if ( firstB == NULL ) { + firstB = &(frameTable[index]); + } + break; + default: + throw "Programmer Error in ComputeFrameTable"; + break; + } + } + + /* why? SRS */ + frameTable[table_size].number = framePatternLen; + ptr = firstB; + while ( ptr != NULL ) { + ptr->next = &(frameTable[table_size]); + ptr = ptr->nextOutput; + } + frameTable[table_size].nextOutput = firstB; + frameTable[table_size].prev = lastIP; + if ( secondIP == NULL ) + frameTable[table_size].next = &(frameTable[0]); + else + frameTable[table_size].next = secondIP; + + frameTable[0].prev = lastIP; + if ( lastIP != NULL ) { + lastIP->next = &(frameTable[table_size]); + } + + if (!stdinUsed) { + use_cache = TRUE; + } +} + +// for gmsh +void +FrameType_Exit() +{ + free(frameTable); + use_cache = FALSE; + int firstI = 0; +} diff --git a/contrib/mpeg_encode/fsize.cpp b/contrib/mpeg_encode/fsize.cpp new file mode 100644 index 0000000000000000000000000000000000000000..09bc17497abfe7976750de816922b70887df722e --- /dev/null +++ b/contrib/mpeg_encode/fsize.cpp @@ -0,0 +1,133 @@ +/*===========================================================================* + * fsize.c * + * * + * procedures to keep track of frame size * + * * + * EXPORTED PROCEDURES: * + * Fsize_Reset * + * Fsize_Note * + * Fsize_Validate * + * * + * EXPORTED VARIABLES: * + * Fsize_x * + * Fsize_y * + * * + *===========================================================================*/ + +/* + * Copyright (c) 1995 The Regents of the University of California. + * All rights reserved. + * + * Permission to use, copy, modify, and distribute this software and its + * documentation for any purpose, without fee, and without written agreement is + * hereby granted, provided that the above copyright notice and the following + * two paragraphs appear in all copies of this software. + * + * IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR + * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT + * OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF + * CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS + * ON AN "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO + * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. + */ + + +/*==============* + * HEADER FILES * + *==============*/ + +#include "all.h" +#include "fsize.h" +#include "dct.h" + + +/*==================* + * GLOBAL VARIABLES * + *==================*/ +int Fsize_x = 0; +int Fsize_y = 0; + + +/*=====================* + * EXPORTED PROCEDURES * + *=====================*/ + +/*===========================================================================* + * + * Fsize_Reset + * + * reset the frame size to 0 + * + * RETURNS: nothing + * + * SIDE EFFECTS: Fsize_x, Fsize_y + * + *===========================================================================*/ +void +Fsize_Reset() +{ + Fsize_x = Fsize_y = 0; +} + + +/*===========================================================================* + * + * Fsize_Validate + * + * make sure that the x, y values are 16-pixel aligned + * + * RETURNS: modifies the x, y values to 16-pixel alignment + * + * SIDE EFFECTS: none + * + *===========================================================================*/ +void +Fsize_Validate(int *x, + int *y) +{ + *x &= ~(DCTSIZE * 2 - 1); + *y &= ~(DCTSIZE * 2 - 1); +} + + +/*===========================================================================* + * + * Fsize_Note + * + * note the given frame size and modify the global values as appropriate + * + * RETURNS: nothing + * + * SIDE EFFECTS: Fsize_x, Fsize_y + * + *===========================================================================*/ +void +Fsize_Note(int id, + int width, + int height) +{ + Fsize_x = width; + Fsize_y = height; + Fsize_Validate(&Fsize_x, &Fsize_y); + + if ((Fsize_x==0) || (Fsize_y==0)) { + fprintf(stderr,"Frame %d: size is zero!\n",id); +/* exit(1); */ + } + +#ifdef BLEAH + if (Fsize_x == 0) { + Fsize_x = width; + Fsize_y = height; + Fsize_Validate(&Fsize_x, &Fsize_y); + } else if (width < Fsize_x || height < Fsize_y) { + fprintf(stderr, "Frame %d: wrong size: (%d,%d). Should be greater or equal to: (%d,%d)\n", + id, width, height, Fsize_x, Fsize_y); + exit(1); + } +#endif +} diff --git a/contrib/mpeg_encode/headers/all.h b/contrib/mpeg_encode/headers/all.h new file mode 100644 index 0000000000000000000000000000000000000000..f7d46bf04feefd7b9f6248b5127a7c1fdb0c06e8 --- /dev/null +++ b/contrib/mpeg_encode/headers/all.h @@ -0,0 +1,96 @@ +/*===========================================================================* + * all.h * + * * + * stuff included from ALL source files * + * * + *===========================================================================*/ + +/* + * Copyright (c) 1995 The Regents of the University of California. + * All rights reserved. + * + * Permission to use, copy, modify, and distribute this software and its + * documentation for any purpose, without fee, and without written agreement is + * hereby granted, provided that the above copyright notice and the following + * two paragraphs appear in all copies of this software. + * + * IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR + * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT + * OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF + * CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS + * ON AN "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO + * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. + */ + +/* + * $Header: /u/smoot/md/mpeg_encode/headers/RCS/all.h,v 1.9 1995/06/05 21:11:06 smoot Exp $ + * $Log: all.h,v $ + * Revision 1.9 1995/06/05 21:11:06 smoot + * added little_endian force for irizx + * + * Revision 1.8 1995/02/02 22:02:18 smoot + * added ifdefs for compatability on stranger and stranger architectures... + * + * Revision 1.7 1995/02/02 07:26:45 eyhung + * added parens to all.h to remove compiler warning + * + * Revision 1.6 1995/02/02 01:47:11 eyhung + * added MAXINT + * + * Revision 1.5 1995/01/19 23:54:33 eyhung + * Changed copyrights + * + * Revision 1.4 1994/11/14 22:52:04 smoot + * Added linux #include for time.h + * + * Revision 1.3 1994/11/12 02:12:13 keving + * nothing + * + * Revision 1.2 1993/07/22 22:24:23 keving + * nothing + * + * Revision 1.1 1993/07/09 00:17:23 keving + * nothing + * + */ + + +#ifndef ENCODE_ALL_INCLUDED +#define ENCODE_ALL_INCLUDED + +#include <stdio.h> +#include <stdlib.h> +#include <math.h> +#include <memory.h> +#include <limits.h> + +/* There's got to be a better way.... */ +#ifdef LINUX +#include <time.h> +#endif +#ifdef MIPS +#include <time.h> +#endif +#ifdef IRIX +#define FORCE_LITTLE_ENDIAN +#include <time.h> +#endif + +#include "libpnmrw.h" +#include "ansi.h" +#include "general.h" + +/* some machines have #define index strchr; get rid of this nonsense */ +#ifdef index +#undef index +#endif /* index */ + +#ifndef MAXINT +#define MAXINT 0x7fffffff +#endif + +#endif /* ENCODE_ALL_INCLUDED */ diff --git a/contrib/mpeg_encode/headers/ansi.h b/contrib/mpeg_encode/headers/ansi.h new file mode 100644 index 0000000000000000000000000000000000000000..6a24f9362b0439e01fd3a67581211c2766325a16 --- /dev/null +++ b/contrib/mpeg_encode/headers/ansi.h @@ -0,0 +1,76 @@ +/*===========================================================================* + * ansi.h * + * * + * macro for non-ansi compilers * + * * + *===========================================================================*/ + +/* + * Copyright (c) 1995 The Regents of the University of California. + * All rights reserved. + * + * Permission to use, copy, modify, and distribute this software and its + * documentation for any purpose, without fee, and without written agreement is + * hereby granted, provided that the above copyright notice and the following + * two paragraphs appear in all copies of this software. + * + * IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR + * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT + * OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF + * CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS + * ON AN "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO + * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. + */ + +/* + * $Header: /n/picasso/project/mpeg/mpeg_dist/mpeg_encode/headers/RCS/ansi.h,v 1.6 1995/08/15 23:43:13 smoot Exp $ + * $Log: ansi.h,v $ + * Revision 1.6 1995/08/15 23:43:13 smoot + * *** empty log message *** + * + * Revision 1.5 1995/01/19 23:54:35 eyhung + * Changed copyrights + * + * Revision 1.4 1994/11/12 02:12:13 keving + * nothing + * + * Revision 1.3 1993/07/22 22:24:23 keving + * nothing + * + * Revision 1.2 1993/07/09 00:17:23 keving + * nothing + * + * Revision 1.1 1993/06/14 22:50:22 keving + * nothing + * + */ + + +#ifndef ANSI_INCLUDED +#define ANSI_INCLUDED + + +/* + * _ANSI_ARGS_ macro stolen from Tcl6.5 by John Ousterhout + */ +#undef _ANSI_ARGS_ +#undef const +#ifdef NON_ANSI_COMPILER +#define _ANSI_ARGS_(x) () +#define CONST +#else +#define _ANSI_ARGS_(x) x +#define CONST const +#ifdef __cplusplus +#define VARARGS (...) +#else +#define VARARGS () +#endif +#endif + + +#endif /* ANSI_INCLUDED */ diff --git a/contrib/mpeg_encode/headers/bitio.h b/contrib/mpeg_encode/headers/bitio.h new file mode 100644 index 0000000000000000000000000000000000000000..327ef330f38733db214943c3b4503e7aec89cd59 --- /dev/null +++ b/contrib/mpeg_encode/headers/bitio.h @@ -0,0 +1,122 @@ +/*===========================================================================* + * bitio.h * + * * + * bitwise input/output * + * * + *===========================================================================*/ + +/* + * Copyright (c) 1995 The Regents of the University of California. + * All rights reserved. + * + * Permission to use, copy, modify, and distribute this software and its + * documentation for any purpose, without fee, and without written agreement is + * hereby granted, provided that the above copyright notice and the following + * two paragraphs appear in all copies of this software. + * + * IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR + * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT + * OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF + * CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS + * ON AN "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO + * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. + */ + +/* + * $Header: /n/charlie-brown/project/mm/mpeg/mpeg_dist/mpeg_encode/headers/RCS/bitio.h,v 1.8 1995/01/19 23:54:37 eyhung Exp $ + * $Log: bitio.h,v $ + * Revision 1.8 1995/01/19 23:54:37 eyhung + * Changed copyrights + * + * Revision 1.7 1994/11/12 02:12:14 keving + * nothing + * + * Revision 1.6 1993/07/22 22:24:23 keving + * nothing + * + * Revision 1.5 1993/07/09 00:17:23 keving + * nothing + * + * Revision 1.4 1993/06/03 21:08:53 keving + * nothing + * + * Revision 1.3 1993/01/18 10:20:02 dwallach + * *** empty log message *** + * + * Revision 1.2 1993/01/18 10:17:29 dwallach + * RCS headers installed, code indented uniformly + * + * Revision 1.2 1993/01/18 10:17:29 dwallach + * RCS headers installed, code indented uniformly + * + */ + + +#ifndef BIT_IO_INCLUDED +#define BIT_IO_INCLUDED + + +/*==============* + * HEADER FILES * + *==============*/ + +#include <stdio.h> // gmsh +#include "general.h" +#include "ansi.h" + + +/*===========* + * CONSTANTS * + *===========*/ + +#define WORDS_PER_BUCKET 128 +#define MAXBITS_PER_BUCKET (WORDS_PER_BUCKET * 32) +#define MAX_BUCKETS 128 +#define MAX_BITS MAX_BUCKETS*MAXBITS_PER_BUCKET + + +/*=======================* + * STRUCTURE DEFINITIONS * + *=======================*/ + +typedef struct bitBucket { + struct bitBucket *nextPtr; + uint32 bits[WORDS_PER_BUCKET]; + int bitsleft, bitsleftcur, currword; +} ActualBucket; + +typedef struct _BitBucket { + int totalbits; + int cumulativeBits; + int bitsWritten; + FILE *filePtr; + ActualBucket *firstPtr; + ActualBucket *lastPtr; +} BitBucket; + + +/*========* + * MACROS * + *========*/ + +#define SET_ITH_BIT(bits, i) (bits |= (1 << (i))) +#define GET_ITH_BIT(bits, i) (bits & (1 << (i))) + + +/*===============================* + * EXTERNAL PROCEDURE prototypes * + *===============================*/ + +void Bitio_Free _ANSI_ARGS_((BitBucket *bbPtr)); +void Bitio_Write _ANSI_ARGS_((BitBucket *bbPtr, uint32 bits, int nbits)); +void Bitio_BytePad _ANSI_ARGS_((BitBucket *bbPtr)); +BitBucket *Bitio_New _ANSI_ARGS_((FILE *filePtr)); +void Bitio_Flush _ANSI_ARGS_((BitBucket *bbPtr)); +void Bitio_WriteToSocket _ANSI_ARGS_((BitBucket *bbPtr, int socket)); + + +#endif /* BIT_IO_INCLUDED */ diff --git a/contrib/mpeg_encode/headers/byteorder.h b/contrib/mpeg_encode/headers/byteorder.h new file mode 100644 index 0000000000000000000000000000000000000000..e3f2047403bf613ebe2417af04974e293cd5608e --- /dev/null +++ b/contrib/mpeg_encode/headers/byteorder.h @@ -0,0 +1,77 @@ +/*===========================================================================* + * byteorder.h * + * * + * stuff to handle different byte order * + * * + *===========================================================================*/ + +/* + * Copyright (c) 1995 The Regents of the University of California. + * All rights reserved. + * + * Permission to use, copy, modify, and distribute this software and its + * documentation for any purpose, without fee, and without written agreement is + * hereby granted, provided that the above copyright notice and the following + * two paragraphs appear in all copies of this software. + * + * IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR + * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT + * OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF + * CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS + * ON AN "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO + * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. + */ + +/* + * $Header: /u/smoot/md/mpeg_encode/headers/RCS/byteorder.h,v 1.3 1995/01/19 23:54:39 eyhung Exp $ + * $Log: byteorder.h,v $ + * Revision 1.3 1995/01/19 23:54:39 eyhung + * Changed copyrights + * + * Revision 1.3 1995/01/19 23:54:39 eyhung + * Changed copyrights + * + * Revision 1.2 1994/11/12 02:12:15 keving + * nothing + * + * Revision 1.1 1993/07/22 22:24:23 keving + * nothing + * + */ + + +#include "general.h" + + +#ifdef FORCE_BIG_ENDIAN + /* leave byte order as it is */ +#define htonl(x) (x) +#define ntohl(x) (x) +#define htons(x) (x) +#define ntohs(x) (x) +#else +#ifdef FORCE_LITTLE_ENDIAN + /* need to reverse byte order */ + /* note -- we assume here that htonl is called on a variable, not a + * constant; thus, this is not for general use, but works with bitio.c + */ +#define htonl(x) \ + ((((unsigned char *)(&x))[0] << 24) | \ + (((unsigned char *)(&x))[1] << 16) | \ + (((unsigned char *)(&x))[2] << 8) | \ + (((unsigned char *)(&x))[3])) +#define ntohl(x) htonl(x) +#define htons(x) \ + ((((unsigned char *)(&x))[0] << 8) | \ + ((unsigned char *)(&x))[1]) +#define ntohs(x) htons(x) +#else + /* let in.h handle it, if possible */ +#include <sys/types.h> +#include <netinet/in.h> +#endif /* FORCE_LITTLE_ENDIAN */ +#endif /* FORCE_BIG_ENDIAN */ diff --git a/contrib/mpeg_encode/headers/combine.h b/contrib/mpeg_encode/headers/combine.h new file mode 100644 index 0000000000000000000000000000000000000000..e8413e871b44d831636dd087bf29ddfe16e0bcd2 --- /dev/null +++ b/contrib/mpeg_encode/headers/combine.h @@ -0,0 +1,34 @@ +/*===========================================================================* + * combine.h * + * * + * procedures to combine frames or GOPs * + * * + *===========================================================================*/ + +/* + * Copyright (c) 1995 The Regents of the University of California. + * All rights reserved. + * + * Permission to use, copy, modify, and distribute this software and its + * documentation for any purpose, without fee, and without written agreement is + * hereby granted, provided that the above copyright notice and the following + * two paragraphs appear in all copies of this software. + * + * IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR + * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT + * OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF + * CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS + * ON AN "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO + * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. + */ + + +void GOPStoMPEG _ANSI_ARGS_((int numGOPS, char *outputFileName, + FILE *fpointer)); +void FramesToMPEG _ANSI_ARGS_((int numFrames, + char *outputFileName, FILE *fpointer, + boolean parallel)); diff --git a/contrib/mpeg_encode/headers/dct.h b/contrib/mpeg_encode/headers/dct.h new file mode 100644 index 0000000000000000000000000000000000000000..0dfb5f4e87aaa3d4a255d1d6df7fcc01487d1cdd --- /dev/null +++ b/contrib/mpeg_encode/headers/dct.h @@ -0,0 +1,79 @@ +/*===========================================================================* + * dct.h * + * * + * DCT procedures * + * * + *===========================================================================*/ + +/* + * Copyright (c) 1995 The Regents of the University of California. + * All rights reserved. + * + * Permission to use, copy, modify, and distribute this software and its + * documentation for any purpose, without fee, and without written agreement is + * hereby granted, provided that the above copyright notice and the following + * two paragraphs appear in all copies of this software. + * + * IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR + * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT + * OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF + * CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS + * ON AN "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO + * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. + */ + + +#ifndef DCT_INCLUDED +#define DCT_INCLUDED + + +#include "ansi.h" + + + +#define DCTSIZE 8 /* you really don't want to change this */ +#define DCTSIZE_SQ 64 /* you really don't want to change this */ + +#define DCTSIZE2 DCTSIZE*DCTSIZE +typedef short DCTELEM; +typedef DCTELEM DCTBLOCK[DCTSIZE2]; +typedef DCTELEM DCTBLOCK_2D[DCTSIZE][DCTSIZE]; + + +/* + * from mfwddct.c: + */ +extern void mp_fwd_dct_block2 _ANSI_ARGS_((DCTBLOCK_2D src, DCTBLOCK_2D dest)); + +/* jrevdct.c */ +extern void init_pre_idct _ANSI_ARGS_((void )); +extern void mpeg_jrevdct _ANSI_ARGS_((DCTBLOCK data )); + + +/* We assume that right shift corresponds to signed division by 2 with + * rounding towards minus infinity. This is correct for typical "arithmetic + * shift" instructions that shift in copies of the sign bit. But some + * C compilers implement >> with an unsigned shift. For these machines you + * must define RIGHT_SHIFT_IS_UNSIGNED. + * RIGHT_SHIFT provides a proper signed right shift of an int32 quantity. + * It is only applied with constant shift counts. SHIFT_TEMPS must be + * included in the variables of any routine using RIGHT_SHIFT. + */ + +#ifdef RIGHT_SHIFT_IS_UNSIGNED +#define SHIFT_TEMPS int32 shift_temp; +#define RIGHT_SHIFT(x,shft) \ + ((shift_temp = (x)) < 0 ? \ + (shift_temp >> (shft)) | ((~((int32) 0)) << (32-(shft))) : \ + (shift_temp >> (shft))) +#else +#define SHIFT_TEMPS +#define RIGHT_SHIFT(x,shft) ((x) >> (shft)) +#endif + + +#endif /* DCT_INCLUDED */ diff --git a/contrib/mpeg_encode/headers/frame.h b/contrib/mpeg_encode/headers/frame.h new file mode 100644 index 0000000000000000000000000000000000000000..6f2eae76aec62196fc51697873bac21fdedf0c33 --- /dev/null +++ b/contrib/mpeg_encode/headers/frame.h @@ -0,0 +1,118 @@ +/*===========================================================================* + * frame.h * + * * + * basic frames procedures * + * * + *===========================================================================*/ + +/* + * Copyright (c) 1995 The Regents of the University of California. + * All rights reserved. + * + * Permission to use, copy, modify, and distribute this software and its + * documentation for any purpose, without fee, and without written agreement is + * hereby granted, provided that the above copyright notice and the following + * two paragraphs appear in all copies of this software. + * + * IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR + * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT + * OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF + * CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS + * ON AN "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO + * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. + */ + + +#ifndef FRAME_INCLUDED +#define FRAME_INCLUDED + +/*==============* + * HEADER FILES * + *==============*/ + +#include "general.h" +#include "ansi.h" +#include "mtypes.h" +#include "libpnmrw.h" //gmsh + +/*===========* + * CONSTANTS * + *===========*/ +#define TYPE_IFRAME 2 +#define TYPE_PFRAME 3 +#define TYPE_BFRAME 4 + + +/*=======================* + * STRUCTURE DEFINITIONS * + *=======================*/ + +typedef struct mpegFrame { + int type; + char inputFileName[256]; + int id; /* the frame number -- starts at 0 */ + boolean inUse; /* TRUE iff this frame is currently being used */ + /* FALSE means any data here can be thrashed */ + + uint8 **ppm_data; + xel **rgb_data; /* pnm format -- see pbmplus docs */ + xelval rgb_maxval; /* largest value of any pixel index */ + int rgb_format; /* more info from pnm */ + + /* + * now, the YCrCb data. All pixel information is stored in unsigned + * 8-bit pieces. We separate y, cr, and cb because cr and cb are + * subsampled by a factor of 2. + */ + uint8 **orig_y, **orig_cr, **orig_cb; + + /* now, the decoded data -- relevant only if + * referenceFrame == DECODED_FRAME + * + */ + uint8 **decoded_y, **decoded_cr, **decoded_cb; + + /* reference data */ + uint8 **ref_y, **ref_cr, **ref_cb; + + /* + * these are the Blocks which will ultimately compose MacroBlocks. + * A Block is in a format that mp_fwddct() can crunch. + */ + Block **y_blocks, **cr_blocks, **cb_blocks; + + /* + * this is the half-pixel luminance data (for reference frames) + */ + uint8 **halfX, **halfY, **halfBoth; + + boolean halfComputed; /* TRUE iff half-pixels already computed */ + + struct mpegFrame *next; /* points to the next B-frame to be encoded, if + * stdin is used as the input. + */ +} MpegFrame; + + +extern MpegFrame *Frame_New _ANSI_ARGS_((int id, int type)); +extern void Frame_Init _ANSI_ARGS_((void)); +extern void Frame_Free _ANSI_ARGS_((MpegFrame *frame)); +extern void Frame_Exit _ANSI_ARGS_((void)); +extern void Frame_AllocPPM _ANSI_ARGS_((MpegFrame * frame)); +extern void Frame_AllocYCC _ANSI_ARGS_((MpegFrame * mf)); +extern void Frame_AllocDecoded _ANSI_ARGS_((MpegFrame *frame, + boolean makeReference)); +extern void Frame_AllocHalf _ANSI_ARGS_((MpegFrame *frame)); +extern void Frame_AllocBlocks _ANSI_ARGS_((MpegFrame *mf)); +extern void Frame_Resize _ANSI_ARGS_((MpegFrame *omf, MpegFrame *mf, + int insize_x, int insize_y, + int outsize_x, int outsize_y)); + +extern void FrameType_Exit(); // for gmsh + + +#endif /* FRAME_INCLUDED */ diff --git a/contrib/mpeg_encode/headers/frames.h b/contrib/mpeg_encode/headers/frames.h new file mode 100644 index 0000000000000000000000000000000000000000..e602cde84d790656b2dcdc3f0073df5391c4c2f3 --- /dev/null +++ b/contrib/mpeg_encode/headers/frames.h @@ -0,0 +1,379 @@ +/*===========================================================================* + * frames.h * + * * + * stuff dealing with frames * + * * + *===========================================================================*/ + +/* + * Copyright (c) 1995 The Regents of the University of California. + * All rights reserved. + * + * Permission to use, copy, modify, and distribute this software and its + * documentation for any purpose, without fee, and without written agreement is + * hereby granted, provided that the above copyright notice and the following + * two paragraphs appear in all copies of this software. + * + * IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR + * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT + * OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF + * CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS + * ON AN "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO + * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. + */ + +/* + * $Header: /n/picasso/project/mpeg/mpeg_dist/mpeg_encode/headers/RCS/frames.h,v 1.13 1995/08/15 23:43:04 smoot Exp $ + * $Log: frames.h,v $ + * Revision 1.13 1995/08/15 23:43:04 smoot + * *** empty log message *** + * + * Revision 1.12 1995/04/14 23:13:18 smoot + * Reorganized for better rate control. Added overflow in DCT values + * handling. + * + * Revision 1.11 1995/01/19 23:54:46 smoot + * allow computediffdcts to un-assert parts of the pattern + * + * Revision 1.10 1995/01/16 07:43:10 eyhung + * Added realQuiet + * + * Revision 1.9 1995/01/10 23:15:28 smoot + * Fixed searchRange lack of def + * + * Revision 1.8 1994/11/15 00:55:36 smoot + * added printMSE + * + * Revision 1.7 1994/11/14 22:51:02 smoot + * added specifics flag. Added BlockComputeSNR parameters + * + * Revision 1.6 1994/11/01 05:07:23 darryl + * with rate control changes added + * + * Revision 1.1 1994/09/27 01:02:55 darryl + * Initial revision + * + * Revision 1.5 1993/07/22 22:24:23 keving + * nothing + * + * Revision 1.4 1993/07/09 00:17:23 keving + * nothing + * + * Revision 1.3 1993/06/03 21:08:53 keving + * nothing + * + * Revision 1.2 1993/03/02 19:00:27 keving + * nothing + * + * Revision 1.1 1993/02/19 20:15:51 keving + * nothing + * + */ + + +#ifndef FRAMES_INCLUDED +#define FRAMES_INCLUDED + +/*==============* + * HEADER FILES * + *==============*/ + +#include "ansi.h" +#include "mtypes.h" +#include "mheaders.h" +#include "frame.h" + + +/*===========* + * CONSTANTS * + *===========*/ + +#define I_FRAME 1 +#define P_FRAME 2 +#define B_FRAME 3 + +#define LUM_BLOCK 0 +#define CHROM_BLOCK 1 +#define CR_BLOCK 2 +#define CB_BLOCK 3 + +#define MOTION_FORWARD 0 +#define MOTION_BACKWARD 1 +#define MOTION_INTERPOLATE 2 + + +#define USE_HALF 0 +#define USE_FULL 1 + + /* motion vector stuff */ +#define FORW_F_CODE fCode /* from picture header */ +#define BACK_F_CODE fCode +#define FORW_F (1 << (FORW_F_CODE - 1)) +#define BACK_F (1 << (BACK_F_CODE - 1)) +#define RANGE_NEG (-(1 << (3 + FORW_F_CODE))) +#define RANGE_POS ((1 << (3 + FORW_F_CODE))-1) +#define MODULUS (1 << (4 + FORW_F_CODE)) + +#define ORIGINAL_FRAME 0 +#define DECODED_FRAME 1 + + +/*=======================* + * STRUCTURE DEFINITIONS * + *=======================*/ + +typedef struct FrameTableStruct { + /* the following are all initted once and never changed */ + /* (they depend only on the pattern */ + char typ; + struct FrameTableStruct *next; + struct FrameTableStruct *prev; + + /* nextOutput is a pointer to next frame table entry to output */ + struct FrameTableStruct *nextOutput; + + boolean freeNow; /* TRUE iff no frames point back to this */ + + int number; + + int bFrameNumber; /* actual frame number, if a b-frame */ + +} FrameTable; + + +/*==================* + * TYPE DEFINITIONS * + *==================*/ + +typedef struct dct_data_tye_struct { + char useMotion; + char pattern, mode; + int fmotionX, fmotionY, bmotionX, bmotionY; +} dct_data_type; + +void EncodeYDC _ANSI_ARGS_((int32 dc_term, int32 *pred_term, BitBucket *bb)); +void EncodeCDC _ANSI_ARGS_((int32 dc_term, int32 *pred_term, BitBucket *bb)); + + +/*========* + * MACROS * + *========*/ + +#define FRAME_TYPE(num) framePattern[num % framePatternLen] + +/* return ceiling(a/b) where a, b are ints, using temp value c */ +#define int_ceil_div(a,b,c) ((b*(c = a/b) < a) ? (c+1) : c) +#define int_floor_div(a,b,c) ((b*(c = a/b) > a) ? (c-1) : c) + +/* assumes many things: + * block indices are (y,x) + * variables y_dc_pred, cr_dc_pred, and cb_dc_pred + * flat block fb exists + */ +#define GEN_I_BLOCK(frameType, frame, bb, mbAI, qscale) { \ + boolean overflow, overflowChange=FALSE; \ + int overflowValue = 0; \ + do { \ + overflow = Mpost_QuantZigBlock(dct[y][x], fb[0], \ + qscale, TRUE)==MPOST_OVERFLOW; \ + overflow |= Mpost_QuantZigBlock(dct[y][x+1], fb[1], \ + qscale, TRUE)==MPOST_OVERFLOW; \ + overflow |= Mpost_QuantZigBlock(dct[y+1][x], fb[2], \ + qscale, TRUE)==MPOST_OVERFLOW; \ + overflow |= Mpost_QuantZigBlock(dct[y+1][x+1], fb[3], \ + qscale, TRUE)==MPOST_OVERFLOW; \ + overflow |= Mpost_QuantZigBlock(dctb[y >> 1][x >> 1], \ + fb[4], qscale, TRUE)==MPOST_OVERFLOW; \ + overflow |= Mpost_QuantZigBlock(dctr[y >> 1][x >> 1], \ + fb[5], qscale, TRUE)==MPOST_OVERFLOW; \ + if ((overflow) && (qscale!=31)) { \ + overflowChange = TRUE; overflowValue++; \ + qscale++; \ + } else overflow = FALSE; \ + } while (overflow); \ + Mhead_GenMBHeader(bb, \ + frameType /* pict_code_type */, mbAI /* addr_incr */, \ + qscale /* q_scale */, \ + 0 /* forw_f_code */, 0 /* back_f_code */, \ + 0 /* horiz_forw_r */, 0 /* vert_forw_r */, \ + 0 /* horiz_back_r */, 0 /* vert_back_r */, \ + 0 /* motion_forw */, 0 /* m_horiz_forw */, \ + 0 /* m_vert_forw */, 0 /* motion_back */, \ + 0 /* m_horiz_back */, 0 /* m_vert_back */, \ + 0 /* mb_pattern */, TRUE /* mb_intra */); \ + \ + /* Y blocks */ \ + EncodeYDC(fb[0][0], &y_dc_pred, bb); \ + Mpost_RLEHuffIBlock(fb[0], bb); \ + EncodeYDC(fb[1][0], &y_dc_pred, bb); \ + Mpost_RLEHuffIBlock(fb[1], bb); \ + EncodeYDC(fb[2][0], &y_dc_pred, bb); \ + Mpost_RLEHuffIBlock(fb[2], bb); \ + EncodeYDC(fb[3][0], &y_dc_pred, bb); \ + Mpost_RLEHuffIBlock(fb[3], bb); \ + \ + /* CB block */ \ + EncodeCDC(fb[4][0], &cb_dc_pred, bb); \ + Mpost_RLEHuffIBlock(fb[4], bb); \ + \ + /* CR block */ \ + EncodeCDC(fb[5][0], &cr_dc_pred, bb); \ + Mpost_RLEHuffIBlock(fb[5], bb); \ + if (overflowChange) qscale -= overflowValue; \ + } + +#define BLOCK_TO_FRAME_COORD(bx1, bx2, x1, x2) { \ + x1 = (bx1)*DCTSIZE; \ + x2 = (bx2)*DCTSIZE; \ + } + +#define MOTION_TO_FRAME_COORD(bx1, bx2, mx1, mx2, x1, x2) { \ + x1 = (bx1)*DCTSIZE+(mx1); \ + x2 = (bx2)*DCTSIZE+(mx2); \ + } + +#define COORD_IN_FRAME(fy,fx, type) \ + ((type == LUM_BLOCK) ? \ + ((fy >= 0) && (fx >= 0) && (fy < Fsize_y) && (fx < Fsize_x)) : \ + ((fy >= 0) && (fx >= 0) && (fy < (Fsize_y>>1)) && (fx < (Fsize_x>>1)))) + +#define ENCODE_MOTION_VECTOR(x,y,xq, yq, xr, yr, f) { \ + int tempC; \ + \ + if ( x < RANGE_NEG ) tempX = x + MODULUS; \ + else if ( x > RANGE_POS ) tempX = x - MODULUS; \ + else tempX = x; \ + \ + if ( y < RANGE_NEG ) tempY = y + MODULUS; \ + else if ( y > RANGE_POS ) tempY = y - MODULUS; \ + else tempY = y; \ + \ + if ( tempX >= 0 ) { \ + xq = int_ceil_div(tempX, f, tempC); \ + xr = f - 1 + tempX - xq*f; \ + } else { \ + xq = int_floor_div(tempX, f, tempC); \ + xr = f - 1 - tempX + xq*f; \ + } \ + \ + if ( tempY >= 0 ) { \ + yq = int_ceil_div(tempY, f, tempC); \ + yr = f - 1 + tempY - yq*f; \ + } else { \ + yq = int_floor_div(tempY, f, tempC); \ + yr = f - 1 - tempY + yq*f; \ + } \ + } + + +#define DoQuant(bit, src, dest) \ + if (pattern & bit) { \ + switch (Mpost_QuantZigBlock(src, dest, QScale, FALSE)) { \ + case MPOST_NON_ZERO: \ + break; \ + case MPOST_ZERO: \ + pattern ^= bit; \ + break; \ + case MPOST_OVERFLOW: \ + if (QScale != 31) { \ + QScale++; \ + overflowChange = TRUE; \ + overflowValue++; \ + goto calc_blocks; \ + } \ + break; \ + } \ + } + +/*===============================* + * EXTERNAL PROCEDURE prototypes * + *===============================*/ + +void ComputeBMotionLumBlock _ANSI_ARGS_((MpegFrame *prev, MpegFrame *next, + int by, int bx, int mode, int fmy, int fmx, + int bmy, int bmx, LumBlock motionBlock)); +int BMotionSearch _ANSI_ARGS_((LumBlock currentBlock, MpegFrame *prev, MpegFrame *next, + int by, int bx, int *fmy, int *fmx, int *bmy, int *bmx, int oldMode)); + + +void ComputeDiffDCTs _ANSI_ARGS_((MpegFrame *current, MpegFrame *prev, int by, int bx, + int my, int mx, int *pattern)); +int ComputeDiffDCTBlock _ANSI_ARGS_((Block current, Block dest, Block motionBlock)); +void ComputeMotionBlock _ANSI_ARGS_((uint8 **prev, int by, int bx, int my, int mx, + Block motionBlock)); +void ComputeMotionLumBlock _ANSI_ARGS_((MpegFrame *prevFrame, int by, + int bx, int my, int mx, + LumBlock motionBlock)); +int32 ComputeBlockMAD _ANSI_ARGS_((Block current, Block prev)); + +void GenIFrame _ANSI_ARGS_((BitBucket *bb, MpegFrame *mf)); +void GenPFrame _ANSI_ARGS_((BitBucket *bb, MpegFrame *current, MpegFrame *prev)); +void GenBFrame _ANSI_ARGS_((BitBucket *bb, MpegFrame *curr, MpegFrame *prev, MpegFrame *next)); +void AllocDctBlocks _ANSI_ARGS_((void )); + +float ShowIFrameSummary _ANSI_ARGS_((int inputFrameBits, int32 totalBits, FILE *fpointer)); +float ShowPFrameSummary _ANSI_ARGS_((int inputFrameBits, int32 totalBits, FILE *fpointer)); +float ShowBFrameSummary _ANSI_ARGS_((int inputFrameBits, int32 totalBits, FILE *fpointer)); + + +/* DIFFERENCE FUNCTIONS */ + +int32 LumBlockMAD _ANSI_ARGS_((LumBlock currentBlock, LumBlock motionBlock, int32 bestSoFar)); +int32 LumBlockMSE _ANSI_ARGS_((LumBlock currentBlock, LumBlock motionBlock, int32 bestSoFar)); +int32 LumMotionError _ANSI_ARGS_((LumBlock currentBlock, MpegFrame *prev, + int by, int bx, int my, int mx, + int32 bestSoFar)); +int32 LumAddMotionError _ANSI_ARGS_((LumBlock currentBlock, + LumBlock blockSoFar, MpegFrame *prev, + int by, int bx, int my, int mx, + int32 bestSoFar)); +int32 LumMotionErrorA _ANSI_ARGS_((LumBlock current, MpegFrame *prevFrame, + int by, int bx, int my, int mx, + int32 bestSoFar)); +int32 LumMotionErrorB _ANSI_ARGS_((LumBlock current, MpegFrame *prevFrame, + int by, int bx, int my, int mx, + int32 bestSoFar)); +int32 LumMotionErrorC _ANSI_ARGS_((LumBlock current, MpegFrame *prevFrame, + int by, int bx, int my, int mx, + int32 bestSoFar)); +int32 LumMotionErrorD _ANSI_ARGS_((LumBlock current, MpegFrame *prevFrame, + int by, int bx, int my, int mx, + int32 bestSoFar)); +int32 LumMotionErrorSubSampled _ANSI_ARGS_((LumBlock currentBlock, MpegFrame *prevFrame, + int by, int bx, int my, int mx, + int startY, int startX)); +void BlockComputeSNR _ANSI_ARGS_((MpegFrame *current, + float *snr, float *psnr)); +int32 time_elapsed _ANSI_ARGS_((void)); +void AllocDctBlocks _ANSI_ARGS_((void)); + +/*==================* + * GLOBAL VARIABLES * + *==================*/ + +extern int pixelFullSearch; +extern int searchRangeP,searchRangeB; +extern int qscaleI; +extern int gopSize; +extern int slicesPerFrame; +extern int blocksPerSlice; +extern int referenceFrame; +extern int specificsOn; +extern int quietTime; /* shut up for at least quietTime seconds; + * negative means shut up forever + */ +extern boolean realQuiet; /* TRUE = no messages to stdout */ + +extern boolean frameSummary; /* TRUE = frame summaries should be printed */ +extern boolean printSNR; +extern boolean printMSE; +extern boolean decodeRefFrames; /* TRUE = should decode I and P frames */ +extern int fCodeI,fCodeP,fCodeB; +extern boolean forceEncodeLast; +extern int TIME_RATE; + +#endif /* FRAMES_INCLUDED */ diff --git a/contrib/mpeg_encode/headers/fsize.h b/contrib/mpeg_encode/headers/fsize.h new file mode 100644 index 0000000000000000000000000000000000000000..8b680e0399ed7965437c102015e949e556c8b2f3 --- /dev/null +++ b/contrib/mpeg_encode/headers/fsize.h @@ -0,0 +1,49 @@ +/*===========================================================================* + * fsize.h * + * * + * procedures to deal with frame size * + * * + *===========================================================================*/ + +/* + * Copyright (c) 1995 The Regents of the University of California. + * All rights reserved. + * + * Permission to use, copy, modify, and distribute this software and its + * documentation for any purpose, without fee, and without written agreement is + * hereby granted, provided that the above copyright notice and the following + * two paragraphs appear in all copies of this software. + * + * IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR + * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT + * OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF + * CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS + * ON AN "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO + * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. + */ + + +#ifndef FSIZE_INCLUDED +#define FSIZE_INCLUDED + +/*==================* + * GLOBAL VARIABLES * + *==================*/ +extern int Fsize_x; +extern int Fsize_y; + + +/*===============================* + * EXTERNAL PROCEDURE prototypes * + *===============================*/ + +extern void Fsize_Reset _ANSI_ARGS_((void)); +extern void Fsize_Validate _ANSI_ARGS_((int *x, int *y)); +extern void Fsize_Note _ANSI_ARGS_((int id, int width, int height)); + + +#endif /* FSIZE_INCLUDED */ diff --git a/contrib/mpeg_encode/headers/general.h b/contrib/mpeg_encode/headers/general.h new file mode 100644 index 0000000000000000000000000000000000000000..5c1dc02c9ce01cf34aa807916d1aec41929996cc --- /dev/null +++ b/contrib/mpeg_encode/headers/general.h @@ -0,0 +1,153 @@ +/*===========================================================================* + * general.h * + * * + * very general stuff * + * * + *===========================================================================*/ + +/* + * Copyright (c) 1995 The Regents of the University of California. + * All rights reserved. + * + * Permission to use, copy, modify, and distribute this software and its + * documentation for any purpose, without fee, and without written agreement is + * hereby granted, provided that the above copyright notice and the following + * two paragraphs appear in all copies of this software. + * + * IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR + * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT + * OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF + * CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS + * ON AN "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO + * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. + */ + +/* + * $Header: /n/picasso/project/mpeg/mpeg_dist/mpeg_encode/headers/RCS/general.h,v 1.7 1995/08/04 23:34:13 smoot Exp $ + * $Log: general.h,v $ + * Revision 1.7 1995/08/04 23:34:13 smoot + * jpeg5 changed the silly HAVE_BOOLEAN define.... + * + * Revision 1.6 1995/01/19 23:54:49 eyhung + * Changed copyrights + * + * Revision 1.5 1994/11/12 02:12:48 keving + * nothing + * + * Revision 1.4 1993/07/22 22:24:23 keving + * nothing + * + * Revision 1.3 1993/07/09 00:17:23 keving + * nothing + * + * Revision 1.2 1993/06/03 21:08:53 keving + * nothing + * + * Revision 1.1 1993/02/22 22:39:19 keving + * nothing + * + */ + + +#ifndef GENERAL_INCLUDED +#define GENERAL_INCLUDED + + +/* prototypes for library procedures + * + * if your /usr/include headers do not have these, then pass -DMISSING_PROTOS + * to your compiler + * + */ +#ifdef MISSING_PROTOS +int fprintf(); +int fwrite(); +int fread(); +int fflush(); +int fclose(); + +int sscanf(); +int bzero(); +int bcopy(); +int system(); +int time(); +int perror(); + +int socket(); +int bind(); +int listen(); +int accept(); +int connect(); +int close(); +int read(); +int write(); + +int pclose(); + +#endif + + +/*===========* + * CONSTANTS * + *===========*/ + +#ifndef NULL +#define NULL 0 +#endif + +#ifndef TRUE +#define TRUE 1 +#define FALSE 0 +#endif + +#define SPACE ' ' +#define TAB '\t' +#define SEMICOLON ';' +#define NULL_CHAR '\0' +#define NEWLINE '\n' + + +/*==================* + * TYPE DEFINITIONS * + *==================*/ + +typedef int boolean; +/* this is for JPEG stuff */ +#define BOOLEAN_DEFINED +#define HAVE_BOOLEAN + +typedef unsigned char uint8; +typedef char int8; +typedef unsigned short uint16; +typedef short int16; + + /* LONG_32 should only be defined iff + * 1) long's are 32 bits and + * 2) int's are not + */ +#ifdef LONG_32 +typedef unsigned long uint32; +typedef long int32; +#else +typedef unsigned int uint32; +typedef int int32; +#endif + + +/*========* + * MACROS * + *========*/ + +#undef max +#define max(a,b) ((a) > (b) ? (a) : (b)) +#undef min +#define min(a,b) ((a) < (b) ? (a) : (b)) +#undef abs +#define abs(a) ((a) >= 0 ? (a) : -(a)) + + +#endif diff --git a/contrib/mpeg_encode/headers/huff.h b/contrib/mpeg_encode/headers/huff.h new file mode 100644 index 0000000000000000000000000000000000000000..a858082b7ee2a0468dd55c67a1ca311554351cbf --- /dev/null +++ b/contrib/mpeg_encode/headers/huff.h @@ -0,0 +1,34 @@ +/* + * Copyright (c) 1995 The Regents of the University of California. + * All rights reserved. + * + * Permission to use, copy, modify, and distribute this software and its + * documentation for any purpose, without fee, and without written agreement is + * hereby granted, provided that the above copyright notice and the following + * two paragraphs appear in all copies of this software. + * + * IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR + * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT + * OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF + * CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS + * ON AN "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO + * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. + */ + +/* + * $Header: /n/charlie-brown/project/mm/mpeg/mpeg_dist/mpeg_encode/headers/RCS/huff.h,v 1.3 1995/01/19 23:54:51 eyhung Exp $ + */ + +/* + * THIS FILE IS MACHINE GENERATED! DO NOT EDIT! + */ +#define HUFF_MAXRUN 32 +#define HUFF_MAXLEVEL 41 + +extern int huff_maxlevel[]; +extern uint32 *huff_table[]; +extern int *huff_bits[]; diff --git a/contrib/mpeg_encode/headers/jpeg.h b/contrib/mpeg_encode/headers/jpeg.h new file mode 100644 index 0000000000000000000000000000000000000000..d001b6568ca04a61edc27b77280cecdf32401bb4 --- /dev/null +++ b/contrib/mpeg_encode/headers/jpeg.h @@ -0,0 +1,49 @@ +/*===========================================================================* + * jpeg.h * + * * + *===========================================================================*/ + +/* + * Copyright (c) 1995 The Regents of the University of California. + * All rights reserved. + * + * Permission to use, copy, modify, and distribute this software and its + * documentation for any purpose, without fee, and without written agreement is + * hereby granted, provided that the above copyright notice and the following + * two paragraphs appear in all copies of this software. + * + * IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR + * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT + * OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF + * CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS + * ON AN "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO + * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. + */ + +/* + * $Header: /n/charlie-brown/project/mm/mpeg/mpeg_dist/mpeg_encode/headers/RCS/jpeg.h,v 1.2 1995/01/19 23:54:53 eyhung Exp $ + * $Log: jpeg.h,v $ + * Revision 1.2 1995/01/19 23:54:53 eyhung + * Changed copyrights + * + * Revision 1.1 1994/11/12 02:12:49 keving + * nothing + * + * Revision 1.2 1993/07/22 22:24:23 keving + * nothing + * + * Revision 1.1 1993/07/09 00:17:23 keving + * nothing + * + */ + +#include "ansi.h" + + +extern void JMovie2JPEG _ANSI_ARGS_((char *infilename, char *obase, + int start, int end)); +extern void ReadJPEG _ANSI_ARGS_((MpegFrame * mf, FILE *fp)); diff --git a/contrib/mpeg_encode/headers/libpnmrw.h b/contrib/mpeg_encode/headers/libpnmrw.h new file mode 100644 index 0000000000000000000000000000000000000000..18a729949ede0e09c11a14c192125e916dd600cf --- /dev/null +++ b/contrib/mpeg_encode/headers/libpnmrw.h @@ -0,0 +1,195 @@ +/* pnmrw.h - header file for PBM/PGM/PPM read/write library +** +** Copyright (C) 1988, 1989, 1991 by Jef Poskanzer. +** +** Permission to use, copy, modify, and distribute this software and its +** documentation for any purpose and without fee is hereby granted, provided +** that the above copyright notice appear in all copies and that both that +** copyright notice and this permission notice appear in supporting +** documentation. This software is provided "as is" without express or +** implied warranty. +*/ + +#ifndef _PNMRW_H_ +#define _PNMRW_H_ + +/* CONFIGURE: On some systems, malloc.h doesn't declare these, so we have +** to do it. On other systems, for example HP/UX, it declares them +** incompatibly. And some systems, for example Dynix, don't have a +** malloc.h at all. A sad situation. If you have compilation problems +** that point here, feel free to tweak or remove these declarations. +*/ +//#include <malloc.h> + +/* End of configurable definitions. */ + + +/* Definitions to make PBMPLUS work with either ANSI C or C Classic. */ + +#if __STDC__ +#define ARGS(alist) alist +#else /*__STDC__*/ +#define ARGS(alist) () +#define const +#endif /*__STDC__*/ + + +/* Types. */ + +typedef unsigned char bit; +#define PBM_WHITE 0 +#define PBM_BLACK 1 +#define PBM_FORMAT_TYPE(f) ((f) == PBM_FORMAT || (f) == RPBM_FORMAT ? PBM_TYPE : -1) + +typedef unsigned char gray; +#define PGM_MAXMAXVAL 255 +#define PGM_FORMAT_TYPE(f) ((f) == PGM_FORMAT || (f) == RPGM_FORMAT ? PGM_TYPE : PBM_FORMAT_TYPE(f)) + +typedef gray pixval; +#define PPM_MAXMAXVAL PGM_MAXMAXVAL +typedef struct + { + pixval r, g, b; + } pixel; +#define PPM_GETR(p) ((p).r) +#define PPM_GETG(p) ((p).g) +#define PPM_GETB(p) ((p).b) +#define PPM_ASSIGN(p,red,grn,blu) do { (p).r = (red); (p).g = (grn); (p).b = (blu); } while ( 0 ) +#define PPM_EQUAL(p,q) ( (p).r == (q).r && (p).g == (q).g && (p).b == (q).b ) +#define PPM_FORMAT_TYPE(f) ((f) == PPM_FORMAT || (f) == RPPM_FORMAT ? PPM_TYPE : PGM_FORMAT_TYPE(f)) + +typedef pixel xel; +typedef pixval xelval; +#define PNM_MAXMAXVAL PPM_MAXMAXVAL +#define PNM_GET1(x) PPM_GETB(x) +#define PNM_ASSIGN1(x,v) PPM_ASSIGN(x,0,0,v) +#define PNM_EQUAL(x,y) PPM_EQUAL(x,y) +#define PNM_FORMAT_TYPE(f) PPM_FORMAT_TYPE(f) + + +/* Magic constants. */ + +#define PBM_MAGIC1 'P' +#define PBM_MAGIC2 '1' +#define RPBM_MAGIC2 '4' +#define PBM_FORMAT (PBM_MAGIC1 * 256 + PBM_MAGIC2) +#define RPBM_FORMAT (PBM_MAGIC1 * 256 + RPBM_MAGIC2) +#define PBM_TYPE PBM_FORMAT + +#define PGM_MAGIC1 'P' +#define PGM_MAGIC2 '2' +#define RPGM_MAGIC2 '5' +#define PGM_FORMAT (PGM_MAGIC1 * 256 + PGM_MAGIC2) +#define RPGM_FORMAT (PGM_MAGIC1 * 256 + RPGM_MAGIC2) +#define PGM_TYPE PGM_FORMAT + +#define PPM_MAGIC1 'P' +#define PPM_MAGIC2 '3' +#define RPPM_MAGIC2 '6' +#define PPM_FORMAT (PPM_MAGIC1 * 256 + PPM_MAGIC2) +#define RPPM_FORMAT (PPM_MAGIC1 * 256 + RPPM_MAGIC2) +#define PPM_TYPE PPM_FORMAT + + +/* Color scaling macro -- to make writing ppmtowhatever easier. */ + +#define PPM_DEPTH(newp,p,oldmaxval,newmaxval) \ + PPM_ASSIGN( (newp), \ + ( (int) PPM_GETR(p) * (newmaxval) + (oldmaxval) / 2 ) / (oldmaxval), \ + ( (int) PPM_GETG(p) * (newmaxval) + (oldmaxval) / 2 ) / (oldmaxval), \ + ( (int) PPM_GETB(p) * (newmaxval) + (oldmaxval) / 2 ) / (oldmaxval) ) + + +/* Luminance macro. */ + +#define PPM_LUMIN(p) ( 0.299 * PPM_GETR(p) + 0.587 * PPM_GETG(p) + 0.114 * PPM_GETB(p) ) + + +/* Declarations of pnmrw routines. */ + +void pnm_init2 ARGS(( char* pn )); + +char** pm_allocarray ARGS(( int cols, int rows, int size )); +#define pnm_allocarray( cols, rows ) ((xel**) pm_allocarray( cols, rows, sizeof(xel) )) +char* pm_allocrow ARGS(( int cols, int size )); +#define pnm_allocrow( cols ) ((xel*) pm_allocrow( cols, sizeof(xel) )) +void pm_freearray ARGS(( char** its, int rows )); +#define pnm_freearray( xels, rows ) pm_freearray( (char**) xels, rows ) +void pm_freerow ARGS(( char* itrow )); +#define pnm_freerow( xelrow ) pm_freerow( (char*) xelrow ) + +xel** pnm_readpnm ARGS(( FILE* file, int* colsP, int* rowsP, xelval* maxvalP, int* formatP )); +int pnm_readpnminit ARGS(( FILE* file, int* colsP, int* rowsP, xelval* maxvalP, int* formatP )); +int pnm_readpnmrow ARGS(( FILE* file, xel* xelrow, int cols, xelval maxval, int format )); + +int pnm_writepnm ARGS(( FILE* file, xel** xels, int cols, int rows, xelval maxval, int format, int forceplain )); +int pnm_writepnminit ARGS(( FILE* file, int cols, int rows, xelval maxval, int format, int forceplain )); +int pnm_writepnmrow ARGS(( FILE* file, xel* xelrow, int cols, xelval maxval, int format, int forceplain )); + +extern xelval pnm_pbmmaxval; +/* This is the maxval used when a PNM program reads a PBM file. Normally +** it is 1; however, for some programs, a larger value gives better results +*/ + + +/* File open/close that handles "-" as stdin and checks errors. */ + +FILE* pm_openr ARGS(( char* name )); +FILE* pm_openw ARGS(( char* name )); +int pm_closer ARGS(( FILE* f )); +int pm_closew ARGS(( FILE* f )); + + +/* Colormap stuff. */ + +typedef struct colorhist_item* colorhist_vector; +struct colorhist_item + { + pixel color; + int value; + }; + +typedef struct colorhist_list_item* colorhist_list; +struct colorhist_list_item + { + struct colorhist_item ch; + colorhist_list next; + }; + +typedef colorhist_list* colorhash_table; + +colorhist_vector ppm_computecolorhist ARGS(( pixel** pixels, int cols, int rows, int maxcolors, int* colorsP )); +/* Returns a colorhist *colorsP long (with space allocated for maxcolors. */ + +void ppm_addtocolorhist ARGS(( colorhist_vector chv, int* colorsP, int maxcolors, pixel* colorP, int value, int position )); + +void ppm_freecolorhist ARGS(( colorhist_vector chv )); + +colorhash_table ppm_computecolorhash ARGS(( pixel** pixels, int cols, int rows, int maxcolors, int* colorsP )); + +int +ppm_lookupcolor ARGS(( colorhash_table cht, pixel* colorP )); + +colorhist_vector ppm_colorhashtocolorhist ARGS(( colorhash_table cht, int maxcolors )); +colorhash_table ppm_colorhisttocolorhash ARGS(( colorhist_vector chv, int colors )); + +int ppm_addtocolorhash ARGS(( colorhash_table cht, pixel* colorP, int value )); +/* Returns -1 on failure. */ + +colorhash_table ppm_alloccolorhash ARGS(( void )); + +void ppm_freecolorhash ARGS(( colorhash_table cht )); + +/* Other function declarations */ +void pnm_promoteformat ARGS(( xel** xels, int cols, int rows, xelval maxval, +int format, xelval newmaxval, int newformat )); +void pnm_promoteformatrow ARGS(( xel* xelrow, int cols, xelval maxval, +int format, xelval newmaxval, int newformat )); + +xel pnm_backgroundxel ARGS(( xel** xels, int cols, int rows, xelval maxval, int format )); +xel pnm_backgroundxelrow ARGS(( xel* xelrow, int cols, xelval maxval, int format )); +xel pnm_whitexel ARGS(( xelval maxval, int format )); +xel pnm_blackxel ARGS(( xelval maxval, int format )); +void pnm_invertxel ARGS(( xel* xP, xelval maxval, int format )); + +#endif /*_PNMRW_H_*/ diff --git a/contrib/mpeg_encode/headers/mheaders.h b/contrib/mpeg_encode/headers/mheaders.h new file mode 100644 index 0000000000000000000000000000000000000000..4f2598aa482964f6ab6c7de831df8fa359181190 --- /dev/null +++ b/contrib/mpeg_encode/headers/mheaders.h @@ -0,0 +1,99 @@ +/*===========================================================================* + * mheaders.h * + * * + * MPEG headers * + * * + *===========================================================================*/ + +/* + * Copyright (c) 1995 The Regents of the University of California. + * All rights reserved. + * + * Permission to use, copy, modify, and distribute this software and its + * documentation for any purpose, without fee, and without written agreement is + * hereby granted, provided that the above copyright notice and the following + * two paragraphs appear in all copies of this software. + * + * IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR + * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT + * OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF + * CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS + * ON AN "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO + * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. + */ + +/* + * $Header: /n/picasso/project/mm/mpeg/mpeg_dist/mpeg_encode/headers/RCS/mheaders.h,v 1.4 1995/03/27 19:29:24 smoot Exp $ + * $Log: mheaders.h,v $ + * Revision 1.4 1995/03/27 19:29:24 smoot + * changed to remove mb_quant + * + * Revision 1.3 1995/01/19 23:54:56 eyhung + * Changed copyrights + * + * Revision 1.2 1994/11/12 02:12:51 keving + * nothing + * + * Revision 1.1 1993/07/22 22:24:23 keving + * nothing + * + * + */ + + +#ifndef MHEADERS_INCLUDED +#define MHEADERS_INCLUDED + + +/*==============* + * HEADER FILES * + *==============*/ + +#include "general.h" +#include "ansi.h" +#include "bitio.h" + + +/*===============================* + * EXTERNAL PROCEDURE prototypes * + *===============================*/ + +void SetGOPStartTime _ANSI_ARGS_((int index)); +void Mhead_GenSequenceHeader _ANSI_ARGS_((BitBucket *bbPtr, + uint32 hsize, uint32 vsize, + int32 pratio, int32 pict_rate, + int32 bit_rate, int32 buf_size, + int32 c_param_flag, int32 *iq_matrix, + int32 *niq_matrix, uint8 *ext_data, + int32 ext_data_size, uint8 *user_data, int32 user_data_size)); +void Mhead_GenSequenceEnder _ANSI_ARGS_((BitBucket *bbPtr)); +void Mhead_GenGOPHeader _ANSI_ARGS_((BitBucket *bbPtr, + int32 drop_frame_flag, + int32 tc_hrs, int32 tc_min, + int32 tc_sec, int32 tc_pict, + int32 closed_gop, int32 broken_link, + uint8 *ext_data, int32 ext_data_size, + uint8 *user_data, int32 user_data_size)); +void Mhead_GenPictureHeader _ANSI_ARGS_((BitBucket *bbPtr, int frameType, + int pictCount, int f_code)); +void Mhead_GenSliceHeader _ANSI_ARGS_((BitBucket *bbPtr, uint32 slicenum, + uint32 qscale, uint8 *extra_info, + uint32 extra_info_size)); +void Mhead_GenSliceEnder _ANSI_ARGS_((BitBucket *bbPtr)); +void Mhead_GenMBHeader _ANSI_ARGS_((BitBucket *bbPtr, + uint32 pict_code_type, uint32 addr_incr, + uint32 q_scale, + uint32 forw_f_code, uint32 back_f_code, + uint32 horiz_forw_r, uint32 vert_forw_r, + uint32 horiz_back_r, uint32 vert_back_r, + int32 motion_forw, int32 m_horiz_forw, + int32 m_vert_forw, int32 motion_back, + int32 m_horiz_back, int32 m_vert_back, + uint32 mb_pattern, uint32 mb_intra)); + + +#endif /* MHEADERS_INCLUDED */ diff --git a/contrib/mpeg_encode/headers/mpeg.h b/contrib/mpeg_encode/headers/mpeg.h new file mode 100644 index 0000000000000000000000000000000000000000..aa7b7b460048589f0210acff44fbeade72e886ca --- /dev/null +++ b/contrib/mpeg_encode/headers/mpeg.h @@ -0,0 +1,102 @@ +/*===========================================================================* + * mpeg.h * + * * + * no comment * + * * + *===========================================================================*/ + +/* + * Copyright (c) 1995 The Regents of the University of California. + * All rights reserved. + * + * Permission to use, copy, modify, and distribute this software and its + * documentation for any purpose, without fee, and without written agreement is + * hereby granted, provided that the above copyright notice and the following + * two paragraphs appear in all copies of this software. + * + * IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR + * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT + * OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF + * CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS + * ON AN "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO + * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. + */ + +/* + * $Header: /n/charlie-brown/project/mm/mpeg/mpeg_dist/mpeg_encode/headers/RCS/mpeg.h,v 1.2 1995/01/19 23:54:58 eyhung Exp $ + * $Log: mpeg.h,v $ + * Revision 1.2 1995/01/19 23:54:58 eyhung + * Changed copyrights + * + * Revision 1.1 1994/11/12 02:12:51 keving + * nothing + * + * Revision 1.1 1994/10/07 04:24:40 darryl + * Initial revision + * + * Revision 1.4 1993/07/22 22:24:23 keving + * nothing + * + * Revision 1.3 1993/07/09 00:17:23 keving + * nothing + * + * Revision 1.2 1993/06/03 21:08:53 keving + * nothing + * + * Revision 1.1 1993/02/17 23:18:20 dwallach + * Initial revision + * + */ + + +/*==============* + * HEADER FILES * + *==============*/ + +#include "ansi.h" +#include "mtypes.h" +#include "frame.h" + + +/*===============================* + * EXTERNAL PROCEDURE prototypes * + *===============================*/ + +int32 GenMPEGStream _ANSI_ARGS_((int whichGOP, int frameStart, int frameEnd, + int32 qtable[], int32 niqtable[], + int numFrames, FILE *ofp, + char *outputFileName)); +extern void PrintStartStats _ANSI_ARGS_((int firstFrame, int lastFrame)); +extern void IncrementTCTime _ANSI_ARGS_((void)); +void SetReferenceFrameType _ANSI_ARGS_((char *type)); +boolean NonLocalRefFrame _ANSI_ARGS_((int id)); +extern void ReadDecodedRefFrame _ANSI_ARGS_((MpegFrame *frame, + int frameNumber)); +extern void WriteDecodedFrame _ANSI_ARGS_((MpegFrame *frame)); +extern void SetBitRateFileName _ANSI_ARGS_((char *fileName)); +extern void SetFrameRate _ANSI_ARGS_((void)); + + +/*==================* + * GLOBAL VARIABLES * + *==================*/ + +extern MpegFrame *frameMemory[3]; +extern int32 tc_hrs, tc_min, tc_sec, tc_pict, tc_extra; +extern int totalFramesSent; +extern int gopSize; +extern char *framePattern; +extern int framePatternLen; +extern int32 qtable[]; +extern int32 niqtable[]; +extern int32 *customQtable; +extern int32 *customNIQtable; +extern int aspectRatio; +extern int frameRate; +extern int frameRateRounded; +extern boolean frameRateInteger; + diff --git a/contrib/mpeg_encode/headers/mproto.h b/contrib/mpeg_encode/headers/mproto.h new file mode 100644 index 0000000000000000000000000000000000000000..83b222883f21ba75d5a24a2d9c46bd23004f5e17 --- /dev/null +++ b/contrib/mpeg_encode/headers/mproto.h @@ -0,0 +1,134 @@ +/*===========================================================================* + * mproto.h * + * * + * basically a lot of miscellaneous prototypes * + * * + *===========================================================================*/ + +/* + * Copyright (c) 1995 The Regents of the University of California. + * All rights reserved. + * + * Permission to use, copy, modify, and distribute this software and its + * documentation for any purpose, without fee, and without written agreement is + * hereby granted, provided that the above copyright notice and the following + * two paragraphs appear in all copies of this software. + * + * IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR + * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT + * OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF + * CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS + * ON AN "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO + * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. + */ + +/* + * $Header: /n/picasso/project/mm/mpeg/mpeg_dist/mpeg_encode/headers/RCS/mproto.h,v 1.12 1995/03/29 20:14:29 smoot Exp $ + * $Log: mproto.h,v $ + * Revision 1.12 1995/03/29 20:14:29 smoot + * deleted unneeded dct prototype + * + * Revision 1.11 1995/01/19 23:55:02 eyhung + * Changed copyrights + * + * Revision 1.10 1995/01/16 06:20:10 eyhung + * Changed ReadYUV to ReadEYUV + * + * Revision 1.9 1993/07/22 22:24:23 keving + * nothing + * + * Revision 1.8 1993/07/09 00:17:23 keving + * nothing + * + * Revision 1.7 1993/06/03 21:08:53 keving + * nothing + * + * Revision 1.6 1993/02/24 19:13:33 keving + * nothing + * + * Revision 1.5 1993/02/17 23:18:20 dwallach + * checkin prior to keving's joining the project + * + * Revision 1.4 1993/01/18 10:20:02 dwallach + * *** empty log message *** + * + * Revision 1.3 1993/01/18 10:17:29 dwallach + * RCS headers installed, code indented uniformly + * + * Revision 1.3 1993/01/18 10:17:29 dwallach + * RCS headers installed, code indented uniformly + * + */ + + +/*==============* + * HEADER FILES * + *==============*/ + +#include "general.h" +#include "ansi.h" +#include "bitio.h" +#include "dct.h" // gmsh +#include "frame.h" //gmsh + +// gmsh: +//#define DCTSIZE2 DCTSIZE*DCTSIZE +//typedef short DCTELEM; +//typedef DCTELEM DCTBLOCK[DCTSIZE2]; + + + +/*===============================* + * EXTERNAL PROCEDURE prototypes * + *===============================*/ + +/* + * from mbasic.c: + */ +void mp_reset _ANSI_ARGS_((void)); +void mp_free _ANSI_ARGS_((MpegFrame *mf)); +MpegFrame *mp_new _ANSI_ARGS_((int fnumber, char type, MpegFrame *oldFrame)); +void mp_ycc_calc _ANSI_ARGS_((MpegFrame *mf)); +void mp_dct_blocks _ANSI_ARGS_((MpegFrame *mf)); +void AllocDecoded _ANSI_ARGS_((MpegFrame *frame)); + +/* + * from moutput.c: + */ +boolean mp_quant_zig_block _ANSI_ARGS_((Block in, FlatBlock out, int qscale, int iblock)); +void UnQuantZig _ANSI_ARGS_((FlatBlock in, Block out, int qscale, boolean iblock)); +void mp_rle_huff_block _ANSI_ARGS_((FlatBlock in, BitBucket *out)); +void mp_rle_huff_pblock _ANSI_ARGS_((FlatBlock in, BitBucket *out)); +void mp_create_blocks _ANSI_ARGS_((MpegFrame *mf)); + + + + +void ReadEYUV _ANSI_ARGS_((MpegFrame * mf, FILE *fpointer, int width, + int height)); +boolean ReadPPM _ANSI_ARGS_((MpegFrame *mf, FILE *fpointer)); +void PPMtoYCC _ANSI_ARGS_((MpegFrame * mf)); + +void MotionSearchPreComputation _ANSI_ARGS_((MpegFrame *frame)); +boolean PMotionSearch _ANSI_ARGS_((LumBlock currentBlock, MpegFrame *prev, + int by, int bx, int *motionY, int *motionX)); +void ComputeHalfPixelData _ANSI_ARGS_((MpegFrame *frame)); +void mp_validate_size _ANSI_ARGS_((int *x, int *y)); +void AllocYCC _ANSI_ARGS_((MpegFrame * mf)); + + +/* jrevdct.c */ +void init_pre_idct _ANSI_ARGS_((void )); +void j_rev_dct_sparse _ANSI_ARGS_((DCTBLOCK data , int pos )); +void j_rev_dct _ANSI_ARGS_((DCTBLOCK data )); +void j_rev_dct_sparse _ANSI_ARGS_((DCTBLOCK data , int pos )); +void j_rev_dct _ANSI_ARGS_((DCTBLOCK data )); + +/* block.c */ +void BlockToData _ANSI_ARGS_((uint8 **data, Block block, int by, int bx)); +void AddMotionBlock _ANSI_ARGS_((Block block, uint8 **prev, int by, int bx, + int my, int mx)); diff --git a/contrib/mpeg_encode/headers/mtypes.h b/contrib/mpeg_encode/headers/mtypes.h new file mode 100644 index 0000000000000000000000000000000000000000..dcd7545c27c31fcea585cb8ab6f38df5b6e86235 --- /dev/null +++ b/contrib/mpeg_encode/headers/mtypes.h @@ -0,0 +1,134 @@ +/*===========================================================================* + * mtypes.h * + * * + * MPEG data types * + * * + *===========================================================================*/ + +/* + * Copyright (c) 1995 The Regents of the University of California. + * All rights reserved. + * + * Permission to use, copy, modify, and distribute this software and its + * documentation for any purpose, without fee, and without written agreement is + * hereby granted, provided that the above copyright notice and the following + * two paragraphs appear in all copies of this software. + * + * IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR + * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT + * OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF + * CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS + * ON AN "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO + * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. + */ + +/* + * $Header: /u/smoot/md/mpeg_encode/headers/RCS/mtypes.h,v 1.12 1995/04/14 23:12:11 smoot Exp $ + * $Log: mtypes.h,v $ + * Revision 1.12 1995/04/14 23:12:11 smoot + * added ChromBlock for future color MV searches + * + * Revision 1.11 1995/01/19 23:55:05 eyhung + * Changed copyrights + * + * Revision 1.10 1994/11/14 22:48:57 smoot + * added defines for Specifics operation + * + * Revision 1.9 1994/11/12 02:12:52 keving + * nothing + * + * Revision 1.8 1993/07/22 22:24:23 keving + * nothing + * + * Revision 1.7 1993/07/09 00:17:23 keving + * nothing + * + * Revision 1.6 1993/06/03 21:08:53 keving + * nothing + * + * Revision 1.5 1993/02/17 23:18:20 dwallach + * checkin prior to keving's joining the project + * + * Revision 1.4 1993/01/18 10:20:02 dwallach + * *** empty log message *** + * + * Revision 1.3 1993/01/18 10:17:29 dwallach + * RCS headers installed, code indented uniformly + * + * Revision 1.3 1993/01/18 10:17:29 dwallach + * RCS headers installed, code indented uniformly + * + */ + + +#ifndef MTYPES_INCLUDED +#define MTYPES_INCLUDED + + +/*==============* + * HEADER FILES * + *==============*/ + +#include "general.h" +#include "dct.h" + + +/*===========* + * CONSTANTS * + *===========*/ + +#define TYPE_BOGUS 0 /* for the header of the circular list */ +#define TYPE_VIRGIN 1 + +#define STATUS_EMPTY 0 +#define STATUS_LOADED 1 +#define STATUS_WRITTEN 2 + + +/*==================* + * TYPE DEFINITIONS * + *==================*/ + +/* + * your basic Block type + */ +typedef int16 Block[DCTSIZE][DCTSIZE]; +typedef int16 FlatBlock[DCTSIZE_SQ]; +typedef int32 LumBlock[2*DCTSIZE][2*DCTSIZE]; +typedef int32 ChromBlock[DCTSIZE][DCTSIZE]; + +/*========* + * MACROS * + *========*/ + +#ifdef ABS +#undef ABS +#endif + +#define ABS(x) (((x)<0)?-(x):(x)) + +#ifdef HEINOUS_DEBUG_MODE +#define DBG_PRINT(x) {printf x; fflush(stdout);} +#else +#define DBG_PRINT(x) +#endif + +#define ERRCHK(bool, str) {if(!(bool)) {perror(str); exit(1);}} + +/* For Specifics */ +typedef struct detalmv_def { + int typ,fx,fy,bx,by; +} BlockMV; +#define TYP_SKIP 0 +#define TYP_FORW 1 +#define TYP_BACK 2 +#define TYP_BOTH 3 + + +#endif /* MTYPES_INCLUDED */ + + diff --git a/contrib/mpeg_encode/headers/opts.h b/contrib/mpeg_encode/headers/opts.h new file mode 100644 index 0000000000000000000000000000000000000000..4052dbc508e98d1d8e847fcfd52cb1c95c575311 --- /dev/null +++ b/contrib/mpeg_encode/headers/opts.h @@ -0,0 +1,124 @@ +/* + * opts.h - set optional parameters + */ + +/* + * Copyright (c) 1995 The Regents of the University of California. + * All rights reserved. + * + * Permission to use, copy, modify, and distribute this software and its + * documentation for any purpose, without fee, and without written agreement is + * hereby granted, provided that the above copyright notice and the following + * two paragraphs appear in all copies of this software. + * + * IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR + * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT + * OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF + * CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS + * ON AN "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO + * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. + */ + +/* + * $Header: /n/picasso/project/mpeg/mpeg_dist/mpeg_encode/headers/RCS/opts.h,v 1.3 1995/08/15 23:43:43 smoot Exp $ + * $Log: opts.h,v $ + * Revision 1.3 1995/08/15 23:43:43 smoot + * *** empty log message *** + * + * Revision 1.2 1995/05/02 22:00:51 smoot + * added TUNEing stuff + * + * Revision 1.1 1995/04/14 23:12:53 smoot + * Initial revision + * + */ + +#include "general.h" +#include "ansi.h" +#include "mtypes.h" + +/* + TUNE b [limit] lower limit on how different a block must be to be DCT coded + TUNE c [file [color-diff]] Collect statistics on Quantization + TUNE d [RateScale DistortionScale] Do a DCT in the P search, not just DIFF + TUNE k [breakpt end [slope]] Squash small lum values + TUNE l Figure out Laplacian distrib and use them to dequantize and do snr calc + TUNE n Dont consider DC differenece in DCT searches + TUNE q Do MSE for distortion measure, not MAD + TUNE s [Max] | [LumMax ChromMax] Squash small differences in successive frames + TUNE u disallow skip blocks in B frames + TUNE w filename [c] Write I block distortion numbers to file [with bit-rates] + TUNE z Zaps Intra blocks in P/B frames. + + [ Note k and s make -snr numbers a lie, by playing with input ] + [ Note d n and q are contradictory (can only use one) ] + [ Note c will not work on parallel encodings ] +*/ + +extern boolean tuneingOn; + +/* Smash to no-change a motion block DCT with MAD less than: */ +/* DETAL b value */ +extern int block_bound; + +/* Collect info on quantization */ +extern boolean collect_quant; +extern int collect_quant_detailed; +extern FILE *collect_quant_fp; + +/* Nuke dim areas */ +extern int kill_dim, kill_dim_break, kill_dim_end; +extern float kill_dim_slope; + + +/* Stuff to control MV search comparisons */ +#define DEFAULT_SEARCH 0 +#define LOCAL_DCT 1 /* Do DCT in search (SLOW!!!!) */ +#define NO_DC_SEARCH 2 /* Dont consider DC component in motion searches */ +#define DO_Mean_Squared_Distortion 3 /* Do Squared distortion, not ABS */ + +/* Parameters for special searches */ +/* LOCAL_DCT */ +extern float LocalDCTRateScale, LocalDCTDistortScale; + +/* Search Type Variable */ +extern int SearchCompareMode; + +/* squash small differences */ +extern boolean squash_small_differences; +extern int SquashMaxLum, SquashMaxChr; + +/* Disallows Intra blocks in P/B code */ +extern boolean IntraPBAllowed; + +/* Write out distortion numbers */ +extern boolean WriteDistortionNumbers; +extern int collect_distortion_detailed; +extern FILE *distortion_fp; +extern FILE *fp_table_rate[31], *fp_table_dist[31]; + +/* Laplacian Distrib */ +extern boolean DoLaplace; +extern double **L1, **L2, **Lambdas; +extern int LaplaceNum, LaplaceCnum; + +/* Turn on/off skipping in B frames */ +extern boolean BSkipBlocks; + +/* Procedures Prototypes */ +int GetIQScale _ANSI_ARGS_((void)); +int GetPQScale _ANSI_ARGS_((void)); +int GetBQScale _ANSI_ARGS_((void)); +void Tune_Init _ANSI_ARGS_((void)); +char *SkipSpacesTabs _ANSI_ARGS_((char *start)); +int CalcRLEHuffLength _ANSI_ARGS_((FlatBlock in)); +void ParseTuneParam _ANSI_ARGS_((char *charPtr)); +int mse _ANSI_ARGS_((Block blk1, Block blk2)); + + + + diff --git a/contrib/mpeg_encode/headers/parallel.h b/contrib/mpeg_encode/headers/parallel.h new file mode 100644 index 0000000000000000000000000000000000000000..031e6fefaa492c4d602945b7b5509cf06668c698 --- /dev/null +++ b/contrib/mpeg_encode/headers/parallel.h @@ -0,0 +1,109 @@ +/*===========================================================================* + * parallel.h * + * * + * parallel encoding * + * * + *===========================================================================*/ + +/* + * Copyright (c) 1995 The Regents of the University of California. + * All rights reserved. + * + * Permission to use, copy, modify, and distribute this software and its + * documentation for any purpose, without fee, and without written agreement is + * hereby granted, provided that the above copyright notice and the following + * two paragraphs appear in all copies of this software. + * + * IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR + * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT + * OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF + * CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS + * ON AN "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO + * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. + */ + +/* + * $Header: /n/picasso/project/mpeg/mpeg_dist/mpeg_encode/headers/RCS/parallel.h,v 1.5 1995/08/15 23:43:26 smoot Exp $ + * $Log: parallel.h,v $ + * Revision 1.5 1995/08/15 23:43:26 smoot + * *** empty log message *** + * + * Revision 1.4 1995/01/19 23:55:08 eyhung + * Changed copyrights + * + * Revision 1.3 1994/11/12 02:12:53 keving + * nothing + * + * Revision 1.2 1993/07/22 22:24:23 keving + * nothing + * + * Revision 1.1 1993/07/09 00:17:23 keving + * nothing + * + */ + + +/*==============* + * HEADER FILES * + *==============*/ + +#include "ansi.h" +#include "bitio.h" +#include "frame.h" + + +/*===============================* + * EXTERNAL PROCEDURE prototypes * + *===============================*/ + +extern void StartMasterServer _ANSI_ARGS_((int numInputFiles, + char *paramFile, + char *outputFileName)); +extern boolean NotifyMasterDone _ANSI_ARGS_((char *hostName, int portNum, + int machineNumber, + int seconds, + int *frameStart, int *frameEnd)); +extern void StartIOServer _ANSI_ARGS_((int numInputFiles, + char *hostName, int portNum)); +extern void StartCombineServer _ANSI_ARGS_((int numInputFiles, + char *outputFileName, + char *hostName, int portNum)); +extern void StartDecodeServer _ANSI_ARGS_((int numInputFiles, + char *outputFileName, + char *hostName, int portNum)); +extern void WaitForOutputFile _ANSI_ARGS_((int number)); +extern void GetRemoteFrame _ANSI_ARGS_((MpegFrame *frame, int frameNumber)); +extern void SendRemoteFrame _ANSI_ARGS_((int frameNumber, BitBucket *bb)); +extern void NoteFrameDone _ANSI_ARGS_((int frameStart, int frameEnd)); +extern void SetIOConvert _ANSI_ARGS_((boolean separate)); +void SetRemoteShell _ANSI_ARGS_((char *shell)); +extern void NotifyDecodeServerReady _ANSI_ARGS_((int id)); +extern void WaitForDecodedFrame _ANSI_ARGS_((int id)); +extern void SendDecodedFrame _ANSI_ARGS_((MpegFrame *frame)); +extern void GetRemoteDecodedRefFrame _ANSI_ARGS_((MpegFrame *frame, + int frameNumber)); +extern void SetParallelPerfect _ANSI_ARGS_((boolean val)); + + +/*==================* + * GLOBAL VARIABLES * + *==================*/ + +extern int parallelTestFrames; +extern int parallelTimeChunks; + +extern char *IOhostName; +extern int ioPortNumber; +extern int combinePortNumber; +extern int decodePortNumber; + +extern boolean ioServer; +extern boolean niceProcesses; +extern boolean forceIalign; +extern int machineNumber; +extern boolean remoteIO; +extern boolean separateConversion; diff --git a/contrib/mpeg_encode/headers/param.h b/contrib/mpeg_encode/headers/param.h new file mode 100644 index 0000000000000000000000000000000000000000..24c46e0701dee39d7210a3b0d889ade8641c118c --- /dev/null +++ b/contrib/mpeg_encode/headers/param.h @@ -0,0 +1,114 @@ +/*===========================================================================* + * param.h * + * * + * reading the parameter file * + * * + *===========================================================================*/ + +/* + * Copyright (c) 1995 The Regents of the University of California. + * All rights reserved. + * + * Permission to use, copy, modify, and distribute this software and its + * documentation for any purpose, without fee, and without written agreement is + * hereby granted, provided that the above copyright notice and the following + * two paragraphs appear in all copies of this software. + * + * IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR + * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT + * OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF + * CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS + * ON AN "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO + * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. + */ + +/* + * $Header: /n/video/199/eyhung/encode/headers/RCS/param.h,v 1.8 1995/05/02 01:51:08 eyhung Exp $ + * $Log: param.h,v $ + * Revision 1.8 1995/05/02 01:51:08 eyhung + * added VidRateNum for determining frame rate + * + * Revision 1.7 1995/01/19 23:55:10 eyhung + * Changed copyrights + * + * Revision 1.6 1995/01/17 04:47:26 eyhung + * added coding-on-the-fly variable + * + * Revision 1.5 1995/01/16 06:06:58 eyhung + * added yuvConversion global variable + * + * Revision 1.4 1994/12/08 20:13:28 smoot + * Killed linux MAXPATHLEN warning + * + * Revision 1.3 1994/11/12 02:12:54 keving + * nothing + * + * Revision 1.2 1993/07/22 22:24:23 keving + * nothing + * + * Revision 1.1 1993/07/09 00:17:23 keving + * nothing + * + */ + + +/*==============* + * HEADER FILES * + *==============*/ + +#include "ansi.h" + + +/*===========* + * CONSTANTS * + *===========*/ + +#define MAX_MACHINES 256 +#ifndef MAXPATHLEN +#define MAXPATHLEN 1024 +#endif + +#define ENCODE_FRAMES 0 +#define COMBINE_GOPS 1 +#define COMBINE_FRAMES 2 + + +/*===============================* + * EXTERNAL PROCEDURE prototypes * + *===============================*/ + +boolean ReadParamFile _ANSI_ARGS_((char *fileName, int function)); +void GetNthInputFileName _ANSI_ARGS_((char *fileName, int n)); +extern void JM2JPEG _ANSI_ARGS_((void)); + + +/*==================* + * GLOBAL VARIABLES * + *==================*/ + +extern int numInputFiles; +extern char outputFileName[256]; +extern int whichGOP; +extern int numMachines; +extern char machineName[MAX_MACHINES][256]; +extern char userName[MAX_MACHINES][256]; +extern char executable[MAX_MACHINES][1024]; +extern char remoteParamFile[MAX_MACHINES][1024]; +extern boolean remote[MAX_MACHINES]; +extern boolean childProcess; +extern char currentPath[MAXPATHLEN]; +extern char inputConversion[1024]; +extern char yuvConversion[256]; +extern int yuvWidth, yuvHeight; +extern int realWidth, realHeight; +extern char ioConversion[1024]; +extern char slaveConversion[1024]; +extern FILE *bitRateFile; +extern boolean showBitRatePerFrame; +extern boolean computeMVHist; +extern boolean stdinUsed; +extern double VidRateNum[9]; diff --git a/contrib/mpeg_encode/headers/postdct.h b/contrib/mpeg_encode/headers/postdct.h new file mode 100644 index 0000000000000000000000000000000000000000..f4e549dd75ab79a81c62f82aa5967e7a63225c87 --- /dev/null +++ b/contrib/mpeg_encode/headers/postdct.h @@ -0,0 +1,40 @@ +/*===========================================================================* + * postdct.h * + * * + * MPEG post-DCT processing * + * * + *===========================================================================*/ + +/* + * Copyright (c) 1995 The Regents of the University of California. + * All rights reserved. + * + * Permission to use, copy, modify, and distribute this software and its + * documentation for any purpose, without fee, and without written agreement is + * hereby granted, provided that the above copyright notice and the following + * two paragraphs appear in all copies of this software. + * + * IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR + * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT + * OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF + * CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS + * ON AN "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO + * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. + */ + + + +int Mpost_QuantZigBlock _ANSI_ARGS_((Block in, FlatBlock out, int qscale, + int iblock)); +void Mpost_UnQuantZigBlock _ANSI_ARGS_((FlatBlock in, Block out, + int qscale, boolean iblock)); +void Mpost_RLEHuffIBlock _ANSI_ARGS_((FlatBlock in, BitBucket *out)); +void Mpost_RLEHuffPBlock _ANSI_ARGS_((FlatBlock in, BitBucket *out)); + +#define MPOST_ZERO 0 +#define MPOST_NON_ZERO 1 +#define MPOST_OVERFLOW (-1) diff --git a/contrib/mpeg_encode/headers/prototypes.h b/contrib/mpeg_encode/headers/prototypes.h new file mode 100644 index 0000000000000000000000000000000000000000..0a3e603fdfae0a07fdbab2422a27949bc7b843c1 --- /dev/null +++ b/contrib/mpeg_encode/headers/prototypes.h @@ -0,0 +1,143 @@ +/*===========================================================================* + * prototypes.h * + * * + * miscellaneous prototypes * + * * + *===========================================================================*/ + +/* + * Copyright (c) 1995 The Regents of the University of California. + * All rights reserved. + * + * Permission to use, copy, modify, and distribute this software and its + * documentation for any purpose, without fee, and without written agreement is + * hereby granted, provided that the above copyright notice and the following + * two paragraphs appear in all copies of this software. + * + * IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR + * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT + * OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF + * CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS + * ON AN "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO + * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. + */ + +/* + * $Header: /n/picasso/project/mm/mpeg/mpeg_dist/mpeg_encode/headers/RCS/prototypes.h,v 1.9 1995/03/30 01:46:58 smoot Exp smoot $ + * $Log: prototypes.h,v $ + * Revision 1.9 1995/03/30 01:46:58 smoot + * added SpecType + * + * Revision 1.8 1995/03/21 00:27:10 smoot + * added pnm stuff + * + * Revision 1.7 1995/02/18 01:48:27 smoot + * changed SpecLookup for version 2 specfiles + * + * Revision 1.6 1995/01/19 23:55:14 eyhung + * Changed copyrights + * + * Revision 1.5 1995/01/17 21:53:10 smoot + * Added Specs like + * Make that: Added specifics prototypes + * + * Revision 1.4 1994/12/07 00:42:01 smoot + * Added seperate P and B search ranges + * + * Revision 1.3 1994/11/12 02:12:56 keving + * nothing + * + * Revision 1.2 1993/07/22 22:24:23 keving + * nothing + * + * Revision 1.1 1993/07/09 00:17:23 keving + * nothing + * + */ + + +/*==============* + * HEADER FILES * + *==============*/ + +#include "general.h" +#include "ansi.h" +#include "frame.h" + + +/*===============================* + * EXTERNAL PROCEDURE prototypes * + *===============================*/ + +int GetBQScale _ANSI_ARGS_((void)); +int GetPQScale _ANSI_ARGS_((void)); +void ResetBFrameStats _ANSI_ARGS_((void)); +void ResetPFrameStats _ANSI_ARGS_((void)); +void SetSearchRange _ANSI_ARGS_((int pixelsP, int pixelsB)); +void ResetIFrameStats _ANSI_ARGS_((void)); +void SetPixelSearch _ANSI_ARGS_((char *searchType)); +void SetIQScale _ANSI_ARGS_((int qI)); +void SetPQScale _ANSI_ARGS_((int qP)); +void SetBQScale _ANSI_ARGS_((int qB)); +float EstimateSecondsPerIFrame _ANSI_ARGS_((void)); +float EstimateSecondsPerPFrame _ANSI_ARGS_((void)); +float EstimateSecondsPerBFrame _ANSI_ARGS_((void)); +void SetGOPSize _ANSI_ARGS_((int size)); +void SetStatFileName _ANSI_ARGS_((char *fileName)); +void SetSlicesPerFrame _ANSI_ARGS_((int number)); +void SetBlocksPerSlice _ANSI_ARGS_((void)); + + +void DCTFrame _ANSI_ARGS_((MpegFrame * mf)); + +void PPMtoYCC _ANSI_ARGS_((MpegFrame * mf)); + +void MotionSearchPreComputation _ANSI_ARGS_((MpegFrame *frame)); +boolean PMotionSearch _ANSI_ARGS_((LumBlock currentBlock, MpegFrame *prev, + int by, int bx, int *motionY, int *motionX)); +void ComputeHalfPixelData _ANSI_ARGS_((MpegFrame *frame)); +void mp_validate_size _ANSI_ARGS_((int *x, int *y)); + +/* block.c */ +void BlockToData _ANSI_ARGS_((uint8 **data, Block block, int by, int bx)); +void AddMotionBlock _ANSI_ARGS_((Block block, uint8 **prev, int by, int bx, + int my, int mx)); +void AddBMotionBlock _ANSI_ARGS_((Block block, uint8 **prev, uint8 **next, + int by, int bx, int mode, + int fmy, int fmx, int bmy, int bmx)); + +void BlockifyFrame _ANSI_ARGS_((MpegFrame *frame)); + + + +extern void SetFCode _ANSI_ARGS_((void)); + + +/* frametype.c */ +int FType_Type _ANSI_ARGS_((int frameNum)); +int FType_FutureRef _ANSI_ARGS_((int currFrameNum)); +int FType_PastRef _ANSI_ARGS_((int currFrameNum)); +void SetFramePattern _ANSI_ARGS_((char *pattern)); +void ComputeFrameTable _ANSI_ARGS_((void)); + +/* psearch.c */ +void ShowPMVHistogram _ANSI_ARGS_((FILE *fpointer)); +void ShowBBMVHistogram _ANSI_ARGS_((FILE *fpointer)); +void ShowBFMVHistogram _ANSI_ARGS_((FILE *fpointer)); + +/* specifics.c */ +void Specifics_Init _ANSI_ARGS_((void)); +int SpecLookup _ANSI_ARGS_((int fn, int typ, int num, + BlockMV **info, int start_qs)); +int SpecTypeLookup _ANSI_ARGS_((int fn)); + +/* libpnm.c */ + +void pnm_promoteformat _ANSI_ARGS_(( xel** xels, int cols, int rows, xelval maxval, +int format, xelval newmaxval, int newformat )); +void pnm_promoteformatrow _ANSI_ARGS_(( xel* xelrow, int cols, xelval maxval, +int format, xelval newmaxval, int newformat )); diff --git a/contrib/mpeg_encode/headers/rate.h b/contrib/mpeg_encode/headers/rate.h new file mode 100644 index 0000000000000000000000000000000000000000..89e8d04c188ca6ab2099c770ca97cbfc4a2448b5 --- /dev/null +++ b/contrib/mpeg_encode/headers/rate.h @@ -0,0 +1,199 @@ +/*===========================================================================* + * rate.h * + * * + * Procedures concerned with rate control + * * + * EXPORTED PROCEDURES: * + * getRateMode() + * setBitRate() + * getBitRate() + * setBufferSize() + * getBufferSize() + * initRateControl() + * targetRateControl() + * updateRateControl() + * MB_RateOut() + * * + *===========================================================================*/ + +/* COPYRIGHT INFO HERE */ + +#define VARIABLE_RATE 0 +#define FIXED_RATE 1 + + +/*==================* + * Exported VARIABLES * + *==================*/ + + +extern int rc_bitsThisMB; +extern int rc_numBlocks; +extern int rc_totalQuant; +extern int rc_quantOverride; + + +/*=====================* + * EXPORTED PROCEDURES * + *=====================*/ + +/*===========================================================================* + * + * initRateControl + * + * initialize the allocation parameters. + *===========================================================================*/ +extern int initRateControl _ANSI_ARGS_((void)); + + +/*===========================================================================* + * + * targetRateControl + * + * Determine the target allocation for given picture type. + * + * RETURNS: target size in bits + *===========================================================================*/ +extern void targetRateControl _ANSI_ARGS_((MpegFrame *frame)); + + +/*===========================================================================* + * + * MB_RateOut + * + * Prints out sampling of MB rate control data. Every "nth" block + * stats are printed, with "n" controled by global RC_MB_SAMPLE_RATE + * + * RETURNS: nothing + *===========================================================================*/ +extern void MB_RateOut _ANSI_ARGS_((int type)); + + +/*===========================================================================* + * + * updateRateControl + * + * Update the statistics kept, after end of frame + * + * RETURNS: nothing + * + * SIDE EFFECTS: many global variables + *===========================================================================*/ +extern void updateRateControl _ANSI_ARGS_((int type)); + + +/*===========================================================================* + * + * needQScaleChange(current Q scale, 4 luminance blocks) + * + * + * RETURNS: new Qscale + *===========================================================================*/ +extern int needQScaleChange _ANSI_ARGS_((int oldQScale, Block blk0, Block blk1, Block blk2, Block blk3)); + +/*===========================================================================* + * + * incNumBlocks() + * + * + * RETURNS: nothing + *===========================================================================*/ +extern void incNumBlocks _ANSI_ARGS_((int num)); + + +/*===========================================================================* + * + * incMacroBlockBits() + * + * Increments the number of Macro Block bits and the total of Frame + * bits by the number passed. + * + * RETURNS: nothing + *===========================================================================*/ +extern void incMacroBlockBits _ANSI_ARGS_((int num)); + + +/*===========================================================================* + * + * SetRateControl () + * + * Checks the string parsed from the parameter file. Verifies + * number and sets global values. + * + * RETURNS: nothing + *===========================================================================*/ +extern void SetRateControl _ANSI_ARGS_((char *charPtr)); + + +/*===========================================================================* + * + * setBufferSize () + * + * Checks the string parsed from the parameter file. Verifies + * number and sets global values. + * + * RETURNS: nothing + *===========================================================================*/ +extern void setBufferSize _ANSI_ARGS_((char *charPtr)); + + +/*===========================================================================* + * + * getBufferSize () + * + * returns the buffer size read from the parameter file. Size is + * in bits- not in units of 16k as written to the sequence header. + * + * RETURNS: int (or -1 if invalid) + *===========================================================================*/ +extern int getBufferSize _ANSI_ARGS_((void)); + + +/*===========================================================================* + * + * setBitRate () + * + * Checks the string parsed from the parameter file. Verifies + * number and sets global values. + * + * RETURNS: nothing + * + * SIDE EFFECTS: global variables + *===========================================================================*/ +extern void setBitRate _ANSI_ARGS_((char *charPtr)); + + +/*===========================================================================* + * + * getBitRate () + * + * Returns the bit rate read from the parameter file. This is the + * real rate in bits per second, not in 400 bit units as is written to + * the sequence header. + * + * RETURNS: int (-1 if Variable mode operation) + *===========================================================================*/ +extern int getBitRate _ANSI_ARGS_((void)); + + +/*===========================================================================* + * + * getRateMode () + * + * Returns the rate mode- interpreted waa either Fixed or Variable + * + * RETURNS: integer + *===========================================================================*/ +extern int getRateMode _ANSI_ARGS_((void)); + + +/*===========================================================================* + * + * incQuantOverride() + * + * counter of override of quantization + * + * RETURNS: nothing + *===========================================================================*/ +extern void incQuantOverride _ANSI_ARGS_((int num)); + diff --git a/contrib/mpeg_encode/headers/readframe.h b/contrib/mpeg_encode/headers/readframe.h new file mode 100644 index 0000000000000000000000000000000000000000..bbb4d2e2f6076b13d0299407529edc0b66f3fd75 --- /dev/null +++ b/contrib/mpeg_encode/headers/readframe.h @@ -0,0 +1,79 @@ +/*===========================================================================* + * readframe.h * + * * + * stuff dealing with reading frames * + * * + *===========================================================================*/ + +/* + * Copyright (c) 1995 The Regents of the University of California. + * All rights reserved. + * + * Permission to use, copy, modify, and distribute this software and its + * documentation for any purpose, without fee, and without written agreement is + * hereby granted, provided that the above copyright notice and the following + * two paragraphs appear in all copies of this software. + * + * IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR + * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT + * OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF + * CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS + * ON AN "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO + * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. + */ + +/* + * $Header: /n/charlie-brown/project/mm/mpeg/mpeg_dist/mpeg_encode/headers/RCS/readframe.h,v 1.6 1995/01/19 23:55:17 eyhung Exp $ + * $Log: readframe.h,v $ + * Revision 1.6 1995/01/19 23:55:17 eyhung + * Changed copyrights + * + * Revision 1.5 1995/01/14 00:05:54 smoot + * *** empty log message *** + * + * Revision 1.4 1995/01/13 23:44:54 smoot + * added B&W (Y files) + * + * Revision 1.3 1994/11/12 02:12:57 keving + * nothing + * + * Revision 1.2 1993/07/22 22:24:23 keving + * nothing + * + * Revision 1.1 1993/07/09 00:17:23 keving + * nothing + * + */ + + +/*===========* + * CONSTANTS * + *===========*/ + +#define PPM_FILE_TYPE 0 +#define YUV_FILE_TYPE 2 +#define ANY_FILE_TYPE 3 +#define BASE_FILE_TYPE 4 +#define PNM_FILE_TYPE 5 +#define SUB4_FILE_TYPE 6 +#define JPEG_FILE_TYPE 7 +#define JMOVIE_FILE_TYPE 8 +#define Y_FILE_TYPE 9 + +/*===============================* + * EXTERNAL PROCEDURE prototypes * + *===============================*/ + +extern void ReadFrame _ANSI_ARGS_((MpegFrame *frame, char *fileName, + char *conversion, boolean addPath)); +extern void SetFileType _ANSI_ARGS_((char *conversion)); +extern void SetFileFormat _ANSI_ARGS_((char *format)); +extern FILE *ReadIOConvert _ANSI_ARGS_((char *fileName)); +extern void SetResize _ANSI_ARGS_((boolean set)); + + +extern int baseFormat; diff --git a/contrib/mpeg_encode/headers/rgbtoycc.h b/contrib/mpeg_encode/headers/rgbtoycc.h new file mode 100644 index 0000000000000000000000000000000000000000..7df1b32c4f42c1ed8973cc2c62a4de6e1281a1b1 --- /dev/null +++ b/contrib/mpeg_encode/headers/rgbtoycc.h @@ -0,0 +1,35 @@ +/*===========================================================================* + * rgbtoycc.h * + * * + * Procedures to convert from RGB space to YUV space * + * * + *===========================================================================*/ + +/* + * Copyright (c) 1995 The Regents of the University of California. + * All rights reserved. + * + * Permission to use, copy, modify, and distribute this software and its + * documentation for any purpose, without fee, and without written agreement is + * hereby granted, provided that the above copyright notice and the following + * two paragraphs appear in all copies of this software. + * + * IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR + * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT + * OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF + * CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS + * ON AN "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO + * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. + */ + + + +#include "frame.h" + + +extern void PNMtoYUV _ANSI_ARGS_((MpegFrame * frame)); +extern void PPMtoYUV _ANSI_ARGS_((MpegFrame * frame)); diff --git a/contrib/mpeg_encode/headers/search.h b/contrib/mpeg_encode/headers/search.h new file mode 100644 index 0000000000000000000000000000000000000000..4210948a957bd8df5b2e8abc7c4150d2600a0e01 --- /dev/null +++ b/contrib/mpeg_encode/headers/search.h @@ -0,0 +1,129 @@ +/*===========================================================================* + * search.h * + * * + * stuff dealing with the motion search * + * * + *===========================================================================*/ + +/* + * Copyright (c) 1995 The Regents of the University of California. + * All rights reserved. + * + * Permission to use, copy, modify, and distribute this software and its + * documentation for any purpose, without fee, and without written agreement is + * hereby granted, provided that the above copyright notice and the following + * two paragraphs appear in all copies of this software. + * + * IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR + * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT + * OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF + * CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS + * ON AN "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO + * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. + */ + +/* + * $Header: /n/picasso/project/mpeg/mpeg_dist/mpeg_encode/headers/RCS/search.h,v 1.6 1995/08/15 23:43:36 smoot Exp $ + * $Log: search.h,v $ + * Revision 1.6 1995/08/15 23:43:36 smoot + * *** empty log message *** + * + * Revision 1.5 1995/01/19 23:55:20 eyhung + * Changed copyrights + * + * Revision 1.4 1994/12/07 00:42:01 smoot + * Added seperate P and B search ranges + * + * Revision 1.3 1994/11/12 02:12:58 keving + * nothing + * + * Revision 1.2 1993/07/22 22:24:23 keving + * nothing + * + * Revision 1.1 1993/07/09 00:17:23 keving + * nothing + * + */ + + +/*==============* + * HEADER FILES * + *==============*/ + +#include "ansi.h" + + +/*===========* + * CONSTANTS * + *===========*/ + +#define PSEARCH_SUBSAMPLE 0 +#define PSEARCH_EXHAUSTIVE 1 +#define PSEARCH_LOGARITHMIC 2 +#define PSEARCH_TWOLEVEL 3 + +#define BSEARCH_EXHAUSTIVE 0 +#define BSEARCH_CROSS2 1 +#define BSEARCH_SIMPLE 2 + + +/*========* + * MACROS * + *========*/ + +#define COMPUTE_MOTION_BOUNDARY(by,bx,stepSize,leftMY,leftMX,rightMY,rightMX)\ + leftMY = -2*DCTSIZE*by; /* these are valid motion vectors */ \ + leftMX = -2*DCTSIZE*bx; \ + /* these are invalid motion vectors */ \ + rightMY = 2*(Fsize_y - (by+2)*DCTSIZE + 1) - 1; \ + rightMX = 2*(Fsize_x - (bx+2)*DCTSIZE + 1) - 1; \ + \ + if ( stepSize == 2 ) { \ + rightMY++; \ + rightMX++; \ + } + +#define VALID_MOTION(y,x) \ + (((y) >= leftMY) && ((y) < rightMY) && \ + ((x) >= leftMX) && ((x) < rightMX) ) + + +/*===============================* + * EXTERNAL PROCEDURE prototypes * + *===============================*/ + +void SetPSearchAlg _ANSI_ARGS_((char *alg)); +void SetBSearchAlg _ANSI_ARGS_((char *alg)); +char *BSearchName _ANSI_ARGS_((void)); +char *PSearchName _ANSI_ARGS_((void)); +int32 PLogarithmicSearch _ANSI_ARGS_((LumBlock currentBlock, + MpegFrame *prev, + int by, int bx, + int *motionY, int *motionX, int searchRange)); +int32 PSubSampleSearch _ANSI_ARGS_((LumBlock currentBlock, + MpegFrame *prev, int by, int bx, + int *motionY, int *motionX, int searchRange)); +int32 PLocalSearch _ANSI_ARGS_((LumBlock currentBlock, + MpegFrame *prev, int by, int bx, + int *motionY, int *motionX, + int32 bestSoFar, int searchRange)); +int32 PTwoLevelSearch _ANSI_ARGS_((LumBlock currentBlock, + MpegFrame *prev, int by, int bx, + int *motionY, int *motionX, + int32 bestSoFar, int searchRange)); +boolean PMotionSearch _ANSI_ARGS_((LumBlock currentBlock, + MpegFrame *prev, + int by, int bx, + int *motionY, int *motionX)); + + +/*==================* + * GLOBAL VARIABLES * + *==================*/ + +extern int psearchAlg; + diff --git a/contrib/mpeg_encode/headers/specifics.h b/contrib/mpeg_encode/headers/specifics.h new file mode 100644 index 0000000000000000000000000000000000000000..77d01c3a2695066b2f54a5948ffd899f847f8556 --- /dev/null +++ b/contrib/mpeg_encode/headers/specifics.h @@ -0,0 +1,90 @@ +/*===========================================================================* + * specifics.h * + * * + * reading the specifics file * + * * + *===========================================================================*/ + +/* + * Copyright (c) 1995 The Regents of the University of California. + * All rights reserved. + * + * Permission to use, copy, modify, and distribute this software and its + * documentation for any purpose, without fee, and without written agreement is + * hereby granted, provided that the above copyright notice and the following + * two paragraphs appear in all copies of this software. + * + * IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR + * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT + * OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF + * CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS + * ON AN "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO + * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. + */ + +/* + * $Header: /u/smoot/md/mpeg_encode/headers/RCS/specifics.h,v 1.4 1995/04/14 23:11:39 smoot Exp $ + * $Log: specifics.h,v $ + * Revision 1.4 1995/04/14 23:11:39 smoot + * made types smalled + * + * Revision 1.3 1995/01/19 23:55:23 eyhung + * Changed copyrights + * + * Revision 1.2 1995/01/17 21:53:32 smoot + * killed prototypes + * + * Revision 1.1 1994/11/15 00:40:35 smoot + * Initial revision + * + * + */ + + +/*==============* + * HEADER FILES * + *==============*/ + +#include "ansi.h" + + +/*===========* + * TYPES * + *===========*/ + +typedef struct bs_def { + int num; + boolean relative; + char qscale; + BlockMV *mv; /* defined in mtypes.h */ + struct bs_def *next; +} Block_Specifics; + +typedef struct detail_def { + int num; + char qscale; + struct detail_def *next; +} Slice_Specifics; + +typedef struct fsl_def { + int framenum; + int frametype; + char qscale; + Slice_Specifics *slc; + Block_Specifics *bs; + struct fsl_def *next; +} FrameSpecList; + +/*===========* + * CONSTANTS * + *===========*/ + + +/*==================* + * GLOBAL VARIABLES * + *==================*/ + diff --git a/contrib/mpeg_encode/huff.cpp b/contrib/mpeg_encode/huff.cpp new file mode 100644 index 0000000000000000000000000000000000000000..821daca1f668a30417bab3835389200fc50a06ef --- /dev/null +++ b/contrib/mpeg_encode/huff.cpp @@ -0,0 +1,131 @@ +/* + * Copyright (c) 1995 The Regents of the University of California. + * All rights reserved. + * + * Permission to use, copy, modify, and distribute this software and its + * documentation for any purpose, without fee, and without written agreement is + * hereby granted, provided that the above copyright notice and the following + * two paragraphs appear in all copies of this software. + * + * IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR + * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT + * OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF + * CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS + * ON AN "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO + * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. + */ + +/* + * $Header: /n/charlie-brown/project/mm/mpeg/mpeg_dist/mpeg_encode/RCS/huff.c,v 1.6 1995/01/19 23:07:39 eyhung Exp $ + */ + +/* + * THIS FILE IS MACHINE GENERATED! DO NOT EDIT! + */ +#include "mtypes.h" +#include "huff.h" + +int huff_maxlevel[32] = { 41, 19, 6, 5, 4, 4, 4, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2 }; + +uint32 huff_table0[41] = { 0x0, 0x6, 0x8, 0xa, 0xc, 0x4c, 0x42, 0x14, 0x3a, 0x30, 0x26, 0x20, 0x34, 0x32, 0x30, 0x2e, 0x3e, 0x3c, 0x3a, 0x38, 0x36, 0x34, 0x32, 0x30, 0x2e, 0x2c, 0x2a, 0x28, 0x26, 0x24, 0x22, 0x20, 0x30, 0x2e, 0x2c, 0x2a, 0x28, 0x26, 0x24, 0x22, 0x20 }; +int huff_bits0[41] = { 0, 3, 5, 6, 8, 9, 9, 11, 13, 13, 13, 13, 14, 14, 14, 14, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 16, 16, 16, 16, 16, 16, 16, 16, 16 }; + +uint32 huff_table1[19] = { 0x0, 0x6, 0xc, 0x4a, 0x18, 0x36, 0x2c, 0x2a, 0x3e, 0x3c, 0x3a, 0x38, 0x36, 0x34, 0x32, 0x26, 0x24, 0x22, 0x20 }; +int huff_bits1[19] = { 0, 4, 7, 9, 11, 13, 14, 14, 16, 16, 16, 16, 16, 16, 16, 17, 17, 17, 17 }; + +uint32 huff_table2[6] = { 0x0, 0xa, 0x8, 0x16, 0x28, 0x28 }; +int huff_bits2[6] = { 0, 5, 8, 11, 13, 14 }; + +uint32 huff_table3[5] = { 0x0, 0xe, 0x48, 0x38, 0x26 }; +int huff_bits3[5] = { 0, 6, 9, 13, 14 }; + +uint32 huff_table4[4] = { 0x0, 0xc, 0x1e, 0x24 }; +int huff_bits4[4] = { 0, 6, 11, 13 }; + +uint32 huff_table5[4] = { 0x0, 0xe, 0x12, 0x24 }; +int huff_bits5[4] = { 0, 7, 11, 14 }; + +uint32 huff_table6[4] = { 0x0, 0xa, 0x3c, 0x28 }; +int huff_bits6[4] = { 0, 7, 13, 17 }; + +uint32 huff_table7[3] = { 0x0, 0x8, 0x2a }; +int huff_bits7[3] = { 0, 7, 13 }; + +uint32 huff_table8[3] = { 0x0, 0xe, 0x22 }; +int huff_bits8[3] = { 0, 8, 13 }; + +uint32 huff_table9[3] = { 0x0, 0xa, 0x22 }; +int huff_bits9[3] = { 0, 8, 14 }; + +uint32 huff_table10[3] = { 0x0, 0x4e, 0x20 }; +int huff_bits10[3] = { 0, 9, 14 }; + +uint32 huff_table11[3] = { 0x0, 0x46, 0x34 }; +int huff_bits11[3] = { 0, 9, 17 }; + +uint32 huff_table12[3] = { 0x0, 0x44, 0x32 }; +int huff_bits12[3] = { 0, 9, 17 }; + +uint32 huff_table13[3] = { 0x0, 0x40, 0x30 }; +int huff_bits13[3] = { 0, 9, 17 }; + +uint32 huff_table14[3] = { 0x0, 0x1c, 0x2e }; +int huff_bits14[3] = { 0, 11, 17 }; + +uint32 huff_table15[3] = { 0x0, 0x1a, 0x2c }; +int huff_bits15[3] = { 0, 11, 17 }; + +uint32 huff_table16[3] = { 0x0, 0x10, 0x2a }; +int huff_bits16[3] = { 0, 11, 17 }; + +uint32 huff_table17[2] = { 0x0, 0x3e }; +int huff_bits17[2] = { 0, 13 }; + +uint32 huff_table18[2] = { 0x0, 0x34 }; +int huff_bits18[2] = { 0, 13 }; + +uint32 huff_table19[2] = { 0x0, 0x32 }; +int huff_bits19[2] = { 0, 13 }; + +uint32 huff_table20[2] = { 0x0, 0x2e }; +int huff_bits20[2] = { 0, 13 }; + +uint32 huff_table21[2] = { 0x0, 0x2c }; +int huff_bits21[2] = { 0, 13 }; + +uint32 huff_table22[2] = { 0x0, 0x3e }; +int huff_bits22[2] = { 0, 14 }; + +uint32 huff_table23[2] = { 0x0, 0x3c }; +int huff_bits23[2] = { 0, 14 }; + +uint32 huff_table24[2] = { 0x0, 0x3a }; +int huff_bits24[2] = { 0, 14 }; + +uint32 huff_table25[2] = { 0x0, 0x38 }; +int huff_bits25[2] = { 0, 14 }; + +uint32 huff_table26[2] = { 0x0, 0x36 }; +int huff_bits26[2] = { 0, 14 }; + +uint32 huff_table27[2] = { 0x0, 0x3e }; +int huff_bits27[2] = { 0, 17 }; + +uint32 huff_table28[2] = { 0x0, 0x3c }; +int huff_bits28[2] = { 0, 17 }; + +uint32 huff_table29[2] = { 0x0, 0x3a }; +int huff_bits29[2] = { 0, 17 }; + +uint32 huff_table30[2] = { 0x0, 0x38 }; +int huff_bits30[2] = { 0, 17 }; + +uint32 huff_table31[2] = { 0x0, 0x36 }; +int huff_bits31[2] = { 0, 17 }; + +uint32 *huff_table[32] = { huff_table0, huff_table1, huff_table2, huff_table3, huff_table4, huff_table5, huff_table6, huff_table7, huff_table8, huff_table9, huff_table10, huff_table11, huff_table12, huff_table13, huff_table14, huff_table15, huff_table16, huff_table17, huff_table18, huff_table19, huff_table20, huff_table21, huff_table22, huff_table23, huff_table24, huff_table25, huff_table26, huff_table27, huff_table28, huff_table29, huff_table30, huff_table31 }; +int *huff_bits[32] = { huff_bits0, huff_bits1, huff_bits2, huff_bits3, huff_bits4, huff_bits5, huff_bits6, huff_bits7, huff_bits8, huff_bits9, huff_bits10, huff_bits11, huff_bits12, huff_bits13, huff_bits14, huff_bits15, huff_bits16, huff_bits17, huff_bits18, huff_bits19, huff_bits20, huff_bits21, huff_bits22, huff_bits23, huff_bits24, huff_bits25, huff_bits26, huff_bits27, huff_bits28, huff_bits29, huff_bits30, huff_bits31 }; diff --git a/contrib/mpeg_encode/huff.h b/contrib/mpeg_encode/huff.h new file mode 100644 index 0000000000000000000000000000000000000000..9d35659a26161dcad31b99f611c66a6badeeb484 --- /dev/null +++ b/contrib/mpeg_encode/huff.h @@ -0,0 +1,34 @@ +/* + * Copyright (c) 1995 The Regents of the University of California. + * All rights reserved. + * + * Permission to use, copy, modify, and distribute this software and its + * documentation for any purpose, without fee, and without written agreement is + * hereby granted, provided that the above copyright notice and the following + * two paragraphs appear in all copies of this software. + * + * IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR + * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT + * OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF + * CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS + * ON AN "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO + * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. + */ + +/* + * $Header: /n/charlie-brown/project/mm/mpeg/mpeg_dist/mpeg_encode/RCS/huff.h,v 1.2 1995/01/19 23:08:28 eyhung Exp $ + */ + +/* + * THIS FILE IS MACHINE GENERATED! DO NOT EDIT! + */ +#define HUFF_MAXRUN 32 +#define HUFF_MAXLEVEL 41 + +extern int huff_maxlevel[]; +extern uint32 *huff_table[]; +extern int *huff_bits[]; diff --git a/contrib/mpeg_encode/huff.table b/contrib/mpeg_encode/huff.table new file mode 100644 index 0000000000000000000000000000000000000000..4f01d32552f58c35a857d3268cca18af074dfbdc --- /dev/null +++ b/contrib/mpeg_encode/huff.table @@ -0,0 +1,172 @@ +# +# Copyright (c) 1993 The Regents of the University of California. +# All rights reserved. +# +# Permission to use, copy, modify, and distribute this software and its +# documentation for any purpose, without fee, and without written agreement is +# hereby granted, provided that the above copyright notice and the following +# two paragraphs appear in all copies of this software. +# +# IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR +# DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT +# OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF +# CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES, +# INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY +# AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS +# ON AN "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO +# PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. +# + +# +# $Header: /n/picasso/users/dwallach/vid2/mpeg_encode/RCS/huff.table,v 1.3 1993/02/17 23:21:58 dwallach Exp $ +# $Log: huff.table,v $ +# Revision 1.3 1993/02/17 23:21:58 dwallach +# checkin prior to keving's joining the project +# +# Revision 1.2 1993/01/18 10:20:02 dwallach +# *** empty log message *** +# +# + +# this files is the raw Huffman encoding tables, from +# the MPEG draft standard, P. D-41 - D-43 (Table D-2.15) + +# Format: +# Run Level VLC Code + +# Run 0, Level 1 is special -- this table has the "NOT FIRST COEFF" entry +# The "IF FIRST COEFF" would be: 0 1 1s + +0 1 11s + +0 2 0100 s +0 3 0010 1s +0 4 0000 110s +0 5 0010 0110 s +0 6 0010 0001 s +0 7 0000 0010 10s +0 8 0000 0001 1101 s +0 9 0000 0001 1000 s +0 10 0000 0001 0011 s +0 11 0000 0001 0000 s +0 12 0000 0000 1101 0s +0 13 0000 0000 1100 1s +0 14 0000 0000 1100 0s +0 15 0000 0000 1011 1s +0 16 0000 0000 0111 11s +0 17 0000 0000 0111 10s +0 18 0000 0000 0111 01s +0 19 0000 0000 0111 00s +0 20 0000 0000 0110 11s +0 21 0000 0000 0110 10s +0 22 0000 0000 0110 01s +0 23 0000 0000 0110 00s +0 24 0000 0000 0101 11s +0 25 0000 0000 0101 10s +0 26 0000 0000 0101 01s +0 27 0000 0000 0101 00s +0 28 0000 0000 0100 11s +0 29 0000 0000 0100 10s +0 30 0000 0000 0100 01s +0 31 0000 0000 0100 00s +0 32 0000 0000 0011 000s +0 33 0000 0000 0010 111s +0 34 0000 0000 0010 110s +0 35 0000 0000 0010 101s +0 36 0000 0000 0010 100s +0 37 0000 0000 0010 011s +0 38 0000 0000 0010 010s +0 39 0000 0000 0010 001s +0 40 0000 0000 0010 000s + +1 1 011s +1 2 0001 10s +1 3 0010 0101 s +1 4 0000 0011 00s +1 5 0000 0001 1011 s +1 6 0000 0000 1011 0s +1 7 0000 0000 1010 1s +1 8 0000 0000 0011 111s +1 9 0000 0000 0011 110s +1 10 0000 0000 0011 101s +1 11 0000 0000 0011 100s +1 12 0000 0000 0011 011s +1 13 0000 0000 0011 010s +1 14 0000 0000 0011 001s +1 15 0000 0000 0001 0011 s +1 16 0000 0000 0001 0010 s +1 17 0000 0000 0001 0001 s +1 18 0000 0000 0001 0000 s + +2 1 0101 s +2 2 0000 100s +2 3 0000 0010 11s +2 4 0000 0001 0100 s +2 5 0000 0000 1010 0s + +3 1 0011 1s +3 2 0010 0100 s +3 3 0000 0001 1100 s +3 4 0000 0000 1001 1s + +4 1 0011 0s +4 2 0000 0011 11s +4 3 0000 0001 0010 s + +5 1 0001 11s +5 2 0000 0010 01s +5 3 0000 0000 1001 0s + +6 1 0001 01s +6 2 0000 0001 1110 s +6 3 0000 0000 0001 0100 s + +7 1 0001 00s +7 2 0000 0001 0101 s + +8 1 0000 111s +8 2 0000 0001 0001 s + +9 1 0000 101s +9 2 0000 0000 1000 1s + +10 1 0010 0111 s +10 2 0000 0000 1000 0s + +11 1 0010 0011 s +11 2 0000 0000 0001 1010 s + +12 1 0010 0010 s +12 2 0000 0000 0001 1001 s + +13 1 0010 0000 s +13 2 0000 0000 0001 1000 s + +14 1 0000 0011 10s +14 2 0000 0000 0001 0111 s + +15 1 0000 0011 01s +15 2 0000 0000 0001 0110 s + +16 1 0000 0010 00s +16 2 0000 0000 0001 0101 s + +17 1 0000 0001 1111 s +18 1 0000 0001 1010 s +19 1 0000 0001 1001 s +20 1 0000 0001 0111 s +21 1 0000 0001 0110 s + +22 1 0000 0000 1111 1s +23 1 0000 0000 1111 0s +24 1 0000 0000 1110 1s +25 1 0000 0000 1110 0s +26 1 0000 0000 1101 1s + +27 1 0000 0000 0001 1111 s +28 1 0000 0000 0001 1110 s +29 1 0000 0000 0001 1101 s +30 1 0000 0000 0001 1100 s +31 1 0000 0000 0001 1011 s diff --git a/contrib/mpeg_encode/iframe.cpp b/contrib/mpeg_encode/iframe.cpp new file mode 100644 index 0000000000000000000000000000000000000000..9dea8da4631babad264a491489a219ebbdd0c27f --- /dev/null +++ b/contrib/mpeg_encode/iframe.cpp @@ -0,0 +1,1135 @@ +/*===========================================================================* + * iframe.c * + * * + * Procedures concerned with the I-frame encoding * + * * + * EXPORTED PROCEDURES: * + * GenIFrame * + * SetSlicesPerFrame * + * SetBlocksPerSlice * + * SetIQScale * + * GetIQScale * + * ResetIFrameStats * + * ShowIFrameSummary * + * EstimateSecondsPerIFrame * + * EncodeYDC * + * EncodeCDC * + * time_elapsed * + * * + *===========================================================================*/ + +/* + * Copyright (c) 1995 The Regents of the University of California. + * All rights reserved. + * + * Permission to use, copy, modify, and distribute this software and its + * documentation for any purpose, without fee, and without written agreement is + * hereby granted, provided that the above copyright notice and the following + * two paragraphs appear in all copies of this software. + * + * IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR + * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT + * OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF + * CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS + * ON AN "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO + * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. + */ + +/* + * $Header: /n/picasso/project/mpeg/mpeg_dist/mpeg_encode/RCS/iframe.c,v 1.23 1995/08/14 22:29:49 smoot Exp $ + * $Log: iframe.c,v $ + * Revision 1.23 1995/08/14 22:29:49 smoot + * changed inits in BlockComputeSNR so sgi compiler would be happy + * + * Revision 1.22 1995/08/07 21:50:51 smoot + * spacing + * simplified some code + * added Laplace stuff + * minor error check bug in alloc + * + * Revision 1.21 1995/06/21 22:24:25 smoot + * added CalcDistortion (TUNEing) + * fixed timeing stuff for ANSI + * fixed specifics bug + * + * Revision 1.20 1995/05/02 21:59:43 smoot + * fixed BlockComputeSNR bugs + * + * Revision 1.19 1995/04/24 23:02:50 smoot + * Fixed BlockComputeSNR for Linux and others + * + * Revision 1.18 1995/04/14 23:08:02 smoot + * reorganized to ease rate control experimentation + * + * Revision 1.17 1995/02/24 23:49:38 smoot + * added support for Specifics file version 2 + * + * Revision 1.16 1995/01/30 20:02:34 smoot + * cleanup, killed a couple warnings + * + * Revision 1.15 1995/01/30 19:49:17 smoot + * cosmetic + * + * Revision 1.14 1995/01/23 02:49:34 darryl + * initialized variable + * + * Revision 1.13 1995/01/19 23:08:30 eyhung + * Changed copyrights + * + * Revision 1.12 1995/01/16 08:01:34 eyhung + * Added realQuiet + * + * Revision 1.11 1994/12/07 00:40:36 smoot + * Added seperate P and B search ranges + * + * Revision 1.10 1994/11/14 22:30:30 smoot + * Merged specifics and rate control + * + * Revision 1.9 1994/11/01 05:00:48 darryl + * with rate control changes added + * + * Revision 2.2 1994/10/31 00:06:07 darryl + * version before, hopefully, final changes + * + * Revision 2.1 1994/10/24 22:03:01 darryl + * put in preliminary experiments code + * + * Revision 2.0 1994/10/24 02:38:04 darryl + * will be adding the experiment stuff. + * + * Revision 1.1 1994/09/27 00:15:24 darryl + * Initial revision + * + * Revision 1.8 1994/03/15 00:27:11 keving + * nothing + * + * Revision 1.7 1993/12/22 19:19:01 keving + * nothing + * + * Revision 1.6 1993/07/22 22:23:43 keving + * nothing + * + * Revision 1.5 1993/06/30 20:06:09 keving + * nothing + * + * Revision 1.4 1993/06/03 21:08:08 keving + * nothing + * + * Revision 1.3 1993/03/04 22:24:06 keving + * nothing + * + * Revision 1.2 1993/02/19 18:10:02 keving + * nothing + * + * Revision 1.1 1993/02/18 22:56:39 keving + * nothing + * + * + */ + + +/*==============* + * HEADER FILES * + *==============*/ + + +#ifdef CLOCKS_PER_SEC +#include <times.h> +#else +#include <sys/times.h> +#endif + +#include <sys/param.h> +#include "all.h" +#include "mtypes.h" +#include "frames.h" +#include "prototypes.h" +#include "mpeg.h" +#include "param.h" +#include "mheaders.h" +#include "fsize.h" +#include "parallel.h" +#include "postdct.h" +#include "rate.h" +#include "opts.h" + +void Mpost_UnQuantZigBlockLaplace _ANSI_ARGS_((FlatBlock in, Block out, int qscale, boolean iblock)); + +/*==================* + * STATIC VARIABLES * + *==================*/ + +static int lastNumBits = 0; +static int lastIFrame = 0; +static int numBlocks = 0; +static int numBits; +static int numFrames = 0; +static int numFrameBits = 0; +static int32 totalTime = 0; +static float totalSNR = 0.0; +static float totalPSNR = 0.0; + +static int lengths[256] = { + 0, 1, 2, 2, 3, 3, 3, 3, /* 0 - 7 */ + 4, 4, 4, 4, 4, 4, 4, 4, /* 8 - 15 */ + 5, 5, 5, 5, 5, 5, 5, 5, /* 16 - 31 */ + 5, 5, 5, 5, 5, 5, 5, 5, + 6, 6, 6, 6, 6, 6, 6, 6, /* 32 - 63 */ + 6, 6, 6, 6, 6, 6, 6, 6, + 6, 6, 6, 6, 6, 6, 6, 6, + 6, 6, 6, 6, 6, 6, 6, 6, + 7, 7, 7, 7, 7, 7, 7, 7, /* 64 - 127 */ + 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 7, + 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8 +}; + + +/*==================* + * GLOBAL VARIABLES * + *==================*/ + +int qscaleI; +int slicesPerFrame; +int blocksPerSlice; +int fCodeI, fCodeP, fCodeB; +boolean printSNR = FALSE; +boolean printMSE = FALSE; +boolean decodeRefFrames = FALSE; +Block **dct=NULL, **dctr=NULL, **dctb=NULL; +dct_data_type **dct_data; /* used in p/bframe.c */ +int TIME_RATE; + + +/*=====================* + * EXPORTED PROCEDURES * + *=====================*/ +extern void PrintItoIBitRate _ANSI_ARGS_((int numBits, int frameNum)); + +/*===============================* + * INTERNAL PROCEDURE prototypes * + *===============================*/ +void AllocDctBlocks _ANSI_ARGS_((void )); +int SetFCodeHelper _ANSI_ARGS_((int sr)); +void CalcDistortion _ANSI_ARGS_((MpegFrame *current, int y, int x)); + +int +SetFCodeHelper(int SR) +{ + int range,fCode; + + if ( pixelFullSearch ) { + range = SR; + } else { + range = SR*2; + } + + if ( range < 256 ) { + if ( range < 64 ) { + if ( range < 32 ) { + fCode = 1; + } else { + fCode = 2; + } + } else { + if ( range < 128 ) { + fCode = 3; + } else { + fCode = 4; + } + } + } else { + if ( range < 1024 ) { + if ( range < 512 ) { + fCode = 5; + } else { + fCode = 6; + } + } else { + if ( range < 2048 ) { + fCode = 7; + } else { + throw "INVALID SEARCH RANGE!!!"; + } + } + } + return fCode; +} + +/*===========================================================================* + * + * SetFCode + * + * set the forward_f_code and backward_f_code according to the search + * range. Must be called AFTER pixelFullSearch and searchRange have + * been initialized. Irrelevant for I-frames, but computation is + * negligible (done only once, as well) + * + * RETURNS: nothing + * + * SIDE EFFECTS: fCodeI,fCodeP,fCodeB + * + *===========================================================================*/ +void +SetFCode() +{ + fCodeI = SetFCodeHelper(1); /* GenIFrame ignores value */ + fCodeP = SetFCodeHelper(searchRangeP); + fCodeB = SetFCodeHelper(searchRangeB); +} + +/*===========================================================================* + * + * SetSlicesPerFrame + * + * set the number of slices per frame + * + * RETURNS: nothing + * + * SIDE EFFECTS: slicesPerFrame + * + *===========================================================================*/ +void +SetSlicesPerFrame(int number) +{ + slicesPerFrame = number; +} + + +/*===========================================================================* + * + * SetBlocksPerSlice + * + * set the number of blocks per slice, based on slicesPerFrame + * + * RETURNS: nothing + * + * SIDE EFFECTS: blocksPerSlice + * + *===========================================================================*/ +void +SetBlocksPerSlice() +{ + int totalBlocks; + + totalBlocks = (Fsize_y>>4)*(Fsize_x>>4); + + if ( slicesPerFrame > totalBlocks ) { + blocksPerSlice = 1; + } else { + blocksPerSlice = totalBlocks/slicesPerFrame; + } +} + + +/*===========================================================================* + * + * SetIQScale + * + * set the I-frame Q-scale + * + * RETURNS: nothing + * + * SIDE EFFECTS: qscaleI + * + *===========================================================================*/ +void +SetIQScale(int qI) +{ + qscaleI = qI; +} + +/*===========================================================================* + * + * GetIQScale + * + * Get the I-frame Q-scale + * + * RETURNS: the Iframe Qscale + * + * SIDE EFFECTS: none + * + *===========================================================================*/ +int +GetIQScale() +{ + return qscaleI; +} + +/*===========================================================================* + * + * GenIFrame + * + * generate an I-frame; appends result to bb + * + * RETURNS: I-frame appended to bb + * + * SIDE EFFECTS: none + * + *===========================================================================*/ +void +GenIFrame(BitBucket *bb, MpegFrame *current) +{ + register int x, y; + register int index; + FlatBlock fb[6]; + Block dec[6]; + int32 y_dc_pred, cr_dc_pred, cb_dc_pred; + int totalBits; + int totalFrameBits; + int32 startTime, endTime; + float snr[3], psnr[3]; + int mbAddress; + int QScale; + BlockMV *info; /* Not used in Iframes, but nice to pass in anyway */ + int bitstreamMode, newQScale; + int rc_blockStart=0; + + if (dct==NULL) AllocDctBlocks(); + if (collect_quant) {fprintf(collect_quant_fp, "# I\n");} + + /* set-up for statistics */ + numFrames++; + totalFrameBits = bb->cumulativeBits; + if ( ( ! childProcess) && showBitRatePerFrame ) { + if ( lastNumBits == 0 ) { + lastNumBits = bb->cumulativeBits; + lastIFrame = current->id; + } else { + /* ASSUMES 30 FRAMES PER SECOND */ + + if (! realQuiet) { + fprintf(stdout, "I-to-I (frames %5d to %5d) bitrate: %8d\n", + lastIFrame, current->id-1, + ((bb->cumulativeBits-lastNumBits)*30)/ + (current->id-lastIFrame)); + } + + fprintf(bitRateFile, "I-to-I (frames %5d to %5d) bitrate: %8d\n", + lastIFrame, current->id-1, + ((bb->cumulativeBits-lastNumBits)*30)/ + (current->id-lastIFrame)); + lastNumBits = bb->cumulativeBits; + lastIFrame = current->id; + } + } + + startTime = time_elapsed(); + + Frame_AllocBlocks(current); + BlockifyFrame(current); + + DBG_PRINT(("Generating iframe\n")); + QScale = GetIQScale(); + /* Allocate bits for this frame for rate control purposes */ + bitstreamMode = getRateMode(); + if (bitstreamMode == FIXED_RATE) { + targetRateControl(current); + } + + Mhead_GenPictureHeader(bb, I_FRAME, current->id, fCodeI); + /* Check for Qscale change */ + if (specificsOn) { + newQScale = SpecLookup(current->id, 0, 0 /* junk */, &info, QScale); + if (newQScale != -1) { + QScale = newQScale; + } + /* check for slice */ + newQScale = SpecLookup(current->id, 1, 1, &info, QScale); + if (newQScale != -1) { + QScale = newQScale; + } + } + Mhead_GenSliceHeader(bb, 1, QScale, NULL, 0); + + if ( referenceFrame == DECODED_FRAME ) { + Frame_AllocDecoded(current, TRUE); + } else if ( printSNR ) { + Frame_AllocDecoded(current, FALSE); + } + + y_dc_pred = cr_dc_pred = cb_dc_pred = 128; + totalBits = bb->cumulativeBits; + mbAddress = 0; + + /* DCT the macroblocks */ + for (y = 0; y < (Fsize_y >> 3); y += 2) { + for (x = 0; x < (Fsize_x >> 3); x += 2) { + if (collect_quant && (collect_quant_detailed & 1)) fprintf(collect_quant_fp, "l\n"); + if (DoLaplace) {LaplaceCnum = 0;} + mp_fwd_dct_block2(current->y_blocks[y][x], dct[y][x]); + mp_fwd_dct_block2(current->y_blocks[y][x+1], dct[y][x+1]); + mp_fwd_dct_block2(current->y_blocks[y+1][x], dct[y+1][x]); + mp_fwd_dct_block2(current->y_blocks[y+1][x+1], dct[y+1][x+1]); + if (collect_quant && (collect_quant_detailed & 1)) fprintf(collect_quant_fp, "c\n"); + if (DoLaplace) {LaplaceCnum = 1;} + mp_fwd_dct_block2(current->cb_blocks[y>>1][x>>1], dctb[y>>1][x>>1]); + if (DoLaplace) {LaplaceCnum = 2;} + mp_fwd_dct_block2(current->cr_blocks[y>>1][x>>1], dctr[y>>1][x>>1]); + }} + + if (DoLaplace) { + extern void CalcLambdas(); + CalcLambdas(); + } + + for (y = 0; y < (Fsize_y >> 3); y += 2) { + for (x = 0; x < (Fsize_x >> 3); x += 2) { + /* Check for Qscale change */ + if (specificsOn) { + newQScale = SpecLookup(current->id, 2, mbAddress, &info, QScale); + if (newQScale != -1) { + QScale = newQScale; + } + } + + /* Determine if new Qscale needed for Rate Control purposes */ + if (bitstreamMode == FIXED_RATE) { + rc_blockStart = bb->cumulativeBits; + newQScale = needQScaleChange(qscaleI, + current->y_blocks[y][x], + current->y_blocks[y][x+1], + current->y_blocks[y+1][x], + current->y_blocks[y+1][x+1]); + if (newQScale > 0) { + QScale = newQScale; + } + } + + if ( (mbAddress % blocksPerSlice == 0) && (mbAddress != 0) ) { + /* create a new slice */ + if (specificsOn) { + /* Make sure no slice Qscale change */ + newQScale = SpecLookup(current->id,1,mbAddress/blocksPerSlice, &info, QScale); + if (newQScale != -1) QScale = newQScale; + } + Mhead_GenSliceEnder(bb); + Mhead_GenSliceHeader(bb, 1+(y>>1), QScale, NULL, 0); + y_dc_pred = cr_dc_pred = cb_dc_pred = 128; + + GEN_I_BLOCK(I_FRAME, current, bb, 1+(x>>1), QScale); + } else { + GEN_I_BLOCK(I_FRAME, current, bb, 1, QScale); + } + + if (WriteDistortionNumbers) { + CalcDistortion(current, y, x); + } + + if ( decodeRefFrames ) { + /* now, reverse the DCT transform */ + LaplaceCnum = 0; + for ( index = 0; index < 6; index++ ) { + if (!DoLaplace) { + Mpost_UnQuantZigBlock(fb[index], dec[index], QScale, TRUE); + } else { + if (index == 4) {LaplaceCnum = 1;} + if (index == 5) {LaplaceCnum = 2;} + Mpost_UnQuantZigBlockLaplace(fb[index], dec[index], QScale, TRUE); + } + mpeg_jrevdct((int16 *)dec[index]); + } + + /* now, unblockify */ + BlockToData(current->decoded_y, dec[0], y, x); + BlockToData(current->decoded_y, dec[1], y, x+1); + BlockToData(current->decoded_y, dec[2], y+1, x); + BlockToData(current->decoded_y, dec[3], y+1, x+1); + BlockToData(current->decoded_cb, dec[4], y>>1, x>>1); + BlockToData(current->decoded_cr, dec[5], y>>1, x>>1); + } + + numBlocks++; + mbAddress++; + /* Rate Control */ + if (bitstreamMode == FIXED_RATE) { + incMacroBlockBits(bb->cumulativeBits - rc_blockStart); + rc_blockStart = bb->cumulativeBits; + MB_RateOut(TYPE_IFRAME); + } + } + } + + if ( printSNR ) { + BlockComputeSNR(current,snr,psnr); + totalSNR += snr[0]; + totalPSNR += psnr[0]; + } + + if ( (referenceFrame == DECODED_FRAME) && NonLocalRefFrame(current->id) ) { + if ( remoteIO ) { + SendDecodedFrame(current); + } else { + WriteDecodedFrame(current); + } + + /* now, tell decode server it is ready */ + NotifyDecodeServerReady(current->id); + } + + numBits += (bb->cumulativeBits-totalBits); + + DBG_PRINT(("End of frame\n")); + + Mhead_GenSliceEnder(bb); + /* Rate Control */ + if (bitstreamMode == FIXED_RATE) { + updateRateControl(TYPE_IFRAME); + } + + endTime = time_elapsed(); + totalTime += (endTime-startTime); + + numFrameBits += (bb->cumulativeBits-totalFrameBits); + + if ( ( ! childProcess) && showBitRatePerFrame ) { + /* ASSUMES 30 FRAMES PER SECOND */ + fprintf(bitRateFile, "%5d\t%8d\n", current->id, + 30*(bb->cumulativeBits-totalFrameBits)); + } + + if ( (! childProcess) && frameSummary && (! realQuiet) ) { + + /* ASSUMES 30 FRAMES PER SECOND */ + fprintf(stdout, "FRAME %d (I): %ld seconds (%d bits/s output)\n", + current->id, (long)((endTime-startTime)/TIME_RATE), + 30*(bb->cumulativeBits-totalFrameBits)); + if ( printSNR ) { + fprintf(stdout, "FRAME %d: SNR: %.1f\t%.1f\t%.1f\tPSNR: %.1f\t%.1f\t%.1f\n", + current->id, snr[0], snr[1], snr[2], + psnr[0], psnr[1], psnr[2]); + } + } +} + + +/*===========================================================================* + * + * ResetIFrameStats + * + * reset the I-frame statistics + * + * RETURNS: nothing + * + * SIDE EFFECTS: none + * + *===========================================================================*/ +void +ResetIFrameStats() +{ + numBlocks = 0; + numBits = 0; + numFrames = 0; + numFrameBits = 0; + totalTime = 0; +} + + +/*===========================================================================* + * + * ShowIFrameSummary + * + * prints out statistics on all I-frames + * + * RETURNS: time taken for I-frames (in seconds) + * + * SIDE EFFECTS: none + * + *===========================================================================*/ +float +ShowIFrameSummary(int inputFrameBits, + int32 totalBits, + FILE *fpointer) +{ + if ( numFrames == 0 ) { + return 0.0; + } + + fprintf(fpointer, "-------------------------\n"); + fprintf(fpointer, "*****I FRAME SUMMARY*****\n"); + fprintf(fpointer, "-------------------------\n"); + + fprintf(fpointer, " Blocks: %5d (%6d bits) (%5d bpb)\n", + numBlocks, numBits, numBits/numBlocks); + fprintf(fpointer, " Frames: %5d (%6d bits) (%5d bpf) (%2.1f%% of total)\n", + numFrames, numFrameBits, numFrameBits/numFrames, + 100.0*(float)numFrameBits/(float)totalBits); + fprintf(fpointer, " Compression: %3d:1 (%9.4f bpp)\n", + numFrames*inputFrameBits/numFrameBits, + 24.0*(float)numFrameBits/(float)(numFrames*inputFrameBits)); + if ( printSNR ) + fprintf(fpointer, " Avg Y SNR/PSNR: %.1f %.1f\n", + totalSNR/(float)numFrames, totalPSNR/(float)numFrames); + if ( totalTime == 0 ) { + fprintf(fpointer, " Seconds: NONE\n"); + } else { + fprintf(fpointer, " Seconds: %9ld (%9.4f fps) (%9ld pps) (%9ld mps)\n", + (long)(totalTime/TIME_RATE), + (float)((float)(TIME_RATE*numFrames)/(float)totalTime), + (long)((float)TIME_RATE*(float)numFrames*(float)inputFrameBits/(24.0*(float)totalTime)), + (long)((float)TIME_RATE*(float)numFrames*(float)inputFrameBits/(256.0*24.0*(float)totalTime))); + } + + return (float)totalTime/(float)TIME_RATE; +} + + +/*===========================================================================* + * + * EstimateSecondsPerIFrame + * + * estimates the number of seconds required per I-frame + * + * RETURNS: seconds (floating point value) + * + * SIDE EFFECTS: none + * + *===========================================================================*/ +float +EstimateSecondsPerIFrame() +{ + return (float)totalTime/((float)TIME_RATE*(float)numFrames); +} + + +/*===========================================================================* + * + * EncodeYDC + * + * Encode the DC portion of a DCT of a luminance block + * + * RETURNS: result appended to bb + * + * SIDE EFFECTS: updates pred_term + * + *===========================================================================*/ +void +EncodeYDC(int32 dc_term, + int32 *pred_term, + BitBucket *bb) +{ + /* see Table B.5a -- MPEG-I doc */ + static int codes[9] = { + 0x4, 0x0, 0x1, 0x5, 0x6, 0xe, 0x1e, 0x3e, 0x7e + }; + static int codeLengths[9] = { + 3, 2, 2, 3, 3, 4, 5, 6, 7 + }; + int ydiff, ydiff_abs; + int length; + + ydiff = (dc_term - (*pred_term)); + if (ydiff > 255) { +#ifdef BLEAH + fprintf(stdout, "TRUNCATED\n"); +#endif + ydiff = 255; + } else if (ydiff < -255) { +#ifdef BLEAH + fprintf(stdout, "TRUNCATED\n"); +#endif + ydiff = -255; + } + + ydiff_abs = ABS(ydiff); + length = lengths[ydiff_abs]; + Bitio_Write(bb, codes[length], codeLengths[length]); + if ( length != 0 ) { + if ( ydiff > 0 ) { + Bitio_Write(bb, ydiff_abs, length); + } else { + Bitio_Write(bb, ~ydiff_abs, length); + } + } + + (*pred_term) += ydiff; +} + + +/*===========================================================================* + * + * EncodeCDC + * + * Encode the DC portion of a DCT of a chrominance block + * + * RETURNS: result appended to bb + * + * SIDE EFFECTS: updates pred_term + * + *===========================================================================*/ +void +EncodeCDC(int32 dc_term, + int32 *pred_term, + BitBucket *bb) +{ + /* see Table B.5b -- MPEG-I doc */ + static int codes[9] = { + 0x0, 0x1, 0x2, 0x6, 0xe, 0x1e, 0x3e, 0x7e, 0xfe + }; + static int codeLengths[9] = { + 2, 2, 2, 3, 4, 5, 6, 7, 8 + }; + int cdiff, cdiff_abs; + int length; + + cdiff = (dc_term - (*pred_term)); + if (cdiff > 255) { +#ifdef BLEAH +fprintf(stdout, "TRUNCATED\n"); +#endif + cdiff = 255; + } else if (cdiff < -255) { +#ifdef BLEAH +fprintf(stdout, "TRUNCATED\n"); +#endif + cdiff = -255; + } + + cdiff_abs = ABS(cdiff); + length = lengths[cdiff_abs]; + Bitio_Write(bb, codes[length], codeLengths[length]); + if ( length != 0 ) { + if ( cdiff > 0 ) { + Bitio_Write(bb, cdiff_abs, length); + } else { + Bitio_Write(bb, ~cdiff_abs, length); + } + } + + (*pred_term) += cdiff; +} + + +void +BlockComputeSNR(MpegFrame *current, + float snr[], + float psnr[]) +{ + register int32 tempInt; + register int y, x; + int32 varDiff[3]; + double ratio[3]; + double total[3]; + register uint8 **origY=current->orig_y, **origCr=current->orig_cr, + **origCb=current->orig_cb; + register uint8 **newY=current->decoded_y, **newCr=current->decoded_cr, + **newCb=current->decoded_cb; + static int32 **SignalY, **NoiseY; + static int32 **SignalCb, **NoiseCb; + static int32 **SignalCr, **NoiseCr; + static short ySize[3], xSize[3]; + static boolean needs_init=TRUE; + + /* Init */ + if (needs_init) { + int ysz = (Fsize_y>>3) * sizeof(int32 *); + int xsz = (Fsize_x>>3); + + needs_init = FALSE; + for (y=0; y<3; y++) { + varDiff[y] = ratio[y] = total[y] = 0.0; + } + ySize[0]=Fsize_y; xSize[0]=Fsize_x; + ySize[1]=Fsize_y>>1; xSize[1]=Fsize_x>>1; + ySize[2]=Fsize_y>>1; xSize[2]=Fsize_x>>1; + SignalY = (int32 **) malloc(ysz); + NoiseY = (int32 **) malloc(ysz); + SignalCb = (int32 **) malloc(ysz); + NoiseCb = (int32 **) malloc(ysz); + SignalCr = (int32 **) malloc(ysz); + NoiseCr = (int32 **) malloc(ysz); + if (SignalY == NULL || NoiseY == NULL || SignalCr == NULL || + NoiseCb == NULL || SignalCb == NULL || NoiseCr == NULL) { + throw "Out of memory in BlockComputeSNR"; + } + for (y = 0; y < ySize[0]>>3; y++) { + SignalY[y] = (int32 *) calloc(xsz,4); + SignalCr[y] = (int32 *) calloc(xsz,4); + SignalCb[y] = (int32 *) calloc(xsz,4); + NoiseY[y] = (int32 *) calloc(xsz,4); + NoiseCr[y] = (int32 *) calloc(xsz,4); + NoiseCb[y] = (int32 *) calloc(xsz,4); + } + } else { + for (y = 0; y < ySize[0]>>3; y++) { + memset((char *) &NoiseY[y][0], 0, (xSize[0]>>3) * 4); + memset((char *) &SignalY[y][0], 0, (xSize[0]>>3) * 4); + memset((char *) &NoiseCb[y][0], 0, (xSize[0]>>3) * 4); + memset((char *) &NoiseCr[y][0], 0, (xSize[0]>>3) * 4); + memset((char *) &SignalCb[y][0], 0, (xSize[0]>>3) * 4); + memset((char *) &SignalCr[y][0], 0, (xSize[0]>>3) * 4); + } + } + + /* find all the signal and noise */ + for (y = 0; y < ySize[0]; y++) { + for (x = 0; x < xSize[0]; x++) { + tempInt = (origY[y][x] - newY[y][x]); + NoiseY[y>>4][x>>4] += tempInt*tempInt; + total[0] += (double)abs(tempInt); + tempInt = origY[y][x]; + SignalY[y>>4][x>>4] += tempInt*tempInt; + }} + for (y = 0; y < ySize[1]; y++) { + for (x = 0; x < xSize[1]; x ++) { + tempInt = (origCb[y][x] - newCb[y][x]); + NoiseCb[y>>3][x>>3] += tempInt*tempInt; + total[1] += (double)abs(tempInt); + tempInt = origCb[y][x]; + SignalCb[y>>3][x>>3] += tempInt*tempInt; + tempInt = (origCr[y][x]-newCr[y][x]); + NoiseCr[y>>3][x>>3] += tempInt*tempInt; + total[2] += (double)abs(tempInt); + tempInt = origCr[y][x]; + SignalCr[y>>3][x>>3] += tempInt*tempInt; + }} + + /* Now sum up that noise */ + for(y=0; y<Fsize_y>>4; y++){ + for(x=0; x<Fsize_x>>4; x++){ + varDiff[0] += NoiseY[y][x]; + varDiff[1] += NoiseCb[y][x]; + varDiff[2] += NoiseCr[y][x]; + if (printMSE) printf("%4d ",(int)(NoiseY[y][x]/256.0)); + } + if (printMSE) puts(""); + } + + /* Now look at those ratios! */ + for(y=0; y<Fsize_y>>4; y++){ + for(x=0; x<Fsize_x>>4; x++){ + ratio[0] += (double)SignalY[y][x]/(double)varDiff[0]; + ratio[1] += (double)SignalCb[y][x]/(double)varDiff[1]; + ratio[2] += (double)SignalCr[y][x]/(double)varDiff[2]; + }} + + for (x=0; x<3; x++) { + snr[x] = 10.0*log10(ratio[x]); + psnr[x] = 20.0*log10(255.0/sqrt((double)varDiff[x]/(double)(ySize[x]*xSize[x]))); + + if (! realQuiet) { + fprintf(stdout, "Mean error[%1d]: %f\n", x, total[x]/(double)(xSize[x]*ySize[x])); + } + + } +} + +void +WriteDecodedFrame(MpegFrame *frame) +{ + FILE *fpointer; + char fileName[256]; + int width, height; + register int y; + + /* need to save decoded frame to disk because it might be accessed + by another process */ + + width = Fsize_x; + height = Fsize_y; + + sprintf(fileName, "%s.decoded.%d", outputFileName, frame->id); + + if (!realQuiet) { + fprintf(stdout, "Outputting to %s\n", fileName); + fflush(stdout); + } + + fpointer = fopen(fileName, "wb"); + + for ( y = 0; y < height; y++ ) { + fwrite(frame->decoded_y[y], 1, width, fpointer); + } + + for (y = 0; y < (height >> 1); y++) { /* U */ + fwrite(frame->decoded_cb[y], 1, width >> 1, fpointer); + } + + for (y = 0; y < (height >> 1); y++) { /* V */ + fwrite(frame->decoded_cr[y], 1, width >> 1, fpointer); + } + fflush(fpointer); + fclose(fpointer); +} + + +void +PrintItoIBitRate(int numBits, + int frameNum) +{ + if ( ( ! childProcess) && showBitRatePerFrame ) { + /* ASSUMES 30 FRAMES PER SECOND */ + + if (! realQuiet) { + fprintf(stdout, "I-to-I (frames %5d to %5d) bitrate: %8d\n", + lastIFrame, frameNum-1, + ((numBits-lastNumBits)*30)/ + (frameNum-lastIFrame)); + } + + fprintf(bitRateFile, "I-to-I (frames %5d to %5d) bitrate: %8d\n", + lastIFrame, frameNum-1, + ((numBits-lastNumBits)*30)/ + (frameNum-lastIFrame)); + } +} + + +/*===========================================================================* + * + * AllocDctBlocks + * + * allocate memory for dct blocks + * + * RETURNS: nothing + * + * SIDE EFFECTS: creates dct, dctr, dctb + * + *===========================================================================*/ +void +AllocDctBlocks() +{ + int dctx, dcty; + int i; + + dctx = Fsize_x / DCTSIZE; + dcty = Fsize_y / DCTSIZE; + + dct = (Block **) malloc(sizeof(Block *) * dcty); + ERRCHK(dct, "malloc"); + for (i = 0; i < dcty; i++) { + dct[i] = (Block *) malloc(sizeof(Block) * dctx); + ERRCHK(dct[i], "malloc"); + } + + dct_data = (dct_data_type **) malloc(sizeof(dct_data_type *) * dcty); + ERRCHK(dct_data, "malloc"); + for (i = 0; i < dcty; i++) { + dct_data[i] = (dct_data_type *) malloc(sizeof(dct_data_type) * dctx); + ERRCHK(dct[i], "malloc"); + } + + dctr = (Block **) malloc(sizeof(Block *) * (dcty >> 1)); + dctb = (Block **) malloc(sizeof(Block *) * (dcty >> 1)); + ERRCHK(dctr, "malloc"); + ERRCHK(dctb, "malloc"); + for (i = 0; i < (dcty >> 1); i++) { + dctr[i] = (Block *) malloc(sizeof(Block) * (dctx >> 1)); + dctb[i] = (Block *) malloc(sizeof(Block) * (dctx >> 1)); + ERRCHK(dctr[i], "malloc"); + ERRCHK(dctb[i], "malloc"); + } +} + + +/*======================================================================* + * + * time_elapsed + * + * Handle different time systems on different machines + * + * RETURNS number of seconds process time used + * + *======================================================================*/ +int32 time_elapsed() +{ +#ifdef CLOCKS_PER_SEC + /* ANSI C */ + TIME_RATE = CLOCKS_PER_SEC; + return (int32) clock(); +#else + struct tms timeBuffer; + TIME_RATE = 60; + times(&timeBuffer); + return timeBuffer.tms_utime + timeBuffer.tms_stime; +#endif +} + + +void +CalcDistortion(MpegFrame *current, + int y, int x) +{ + + int qscale, distort=0; + Block decblk; + FlatBlock fblk; + int datarate = 0; + + for (qscale = 1; qscale < 32; qscale ++) { + distort = 0; + datarate = 0; + Mpost_QuantZigBlock(dct[y][x], fblk, qscale, TRUE); + Mpost_UnQuantZigBlock(fblk, decblk, qscale, TRUE); + if (collect_distortion_detailed) datarate += CalcRLEHuffLength(fblk); + mpeg_jrevdct((int16 *)decblk); + distort += mse(current->y_blocks[y][x], decblk); + + Mpost_QuantZigBlock(dct[y][x+1], fblk, qscale, TRUE); + Mpost_UnQuantZigBlock(fblk, decblk, qscale, TRUE); + if (collect_distortion_detailed) datarate += CalcRLEHuffLength(fblk); + mpeg_jrevdct((int16 *)decblk); + distort += mse(current->y_blocks[y][x+1], decblk); + + Mpost_QuantZigBlock(dct[y+1][x], fblk, qscale, TRUE); + Mpost_UnQuantZigBlock(fblk, decblk, qscale, TRUE); + if (collect_distortion_detailed) datarate += CalcRLEHuffLength(fblk); + mpeg_jrevdct((int16 *)decblk); + distort += mse(current->y_blocks[y+1][x], decblk); + + Mpost_QuantZigBlock(dct[y+1][x+1], fblk, qscale, TRUE); + Mpost_UnQuantZigBlock(fblk, decblk, qscale, TRUE); + if (collect_distortion_detailed) datarate += CalcRLEHuffLength(fblk); + mpeg_jrevdct((int16 *)decblk); + distort += mse(current->y_blocks[y+1][x+1], decblk); + + Mpost_QuantZigBlock(dctb[y >> 1][x >> 1], fblk, qscale, TRUE); + Mpost_UnQuantZigBlock(fblk, decblk, qscale, TRUE); + if (collect_distortion_detailed) datarate += CalcRLEHuffLength(fblk); + mpeg_jrevdct((int16 *)decblk); + distort += mse(current->cb_blocks[y>>1][x>>1], decblk); + + Mpost_QuantZigBlock(dctr[y >> 1][x >> 1], fblk, qscale, TRUE); + Mpost_UnQuantZigBlock(fblk, decblk, qscale, TRUE); + if (collect_distortion_detailed) datarate += CalcRLEHuffLength(fblk); + mpeg_jrevdct((int16 *)decblk); + distort += mse(current->cr_blocks[y >> 1][x >> 1], decblk); + + if (!collect_distortion_detailed) { + fprintf(distortion_fp, "\t%d\n", distort); + } else if (collect_distortion_detailed == 1) { + fprintf(distortion_fp, "\t%d\t%d\n", distort, datarate); + } else { + fprintf(fp_table_rate[qscale-1], "%d\n", datarate); + fprintf(fp_table_dist[qscale-1], "%d\n", distort); + } + } +} + + + + diff --git a/contrib/mpeg_encode/jpeg.cpp b/contrib/mpeg_encode/jpeg.cpp new file mode 100644 index 0000000000000000000000000000000000000000..2bec8146d2ba6bb9679e5f26afd321a6a31308f1 --- /dev/null +++ b/contrib/mpeg_encode/jpeg.cpp @@ -0,0 +1,661 @@ +/*===========================================================================* + * jpeg.c * + * * + * procedures to deal with JPEG files * + * * + * EXPORTED PROCEDURES: * + * JMovie2JPEG * + * ReadJPEG * + * * + *===========================================================================*/ + +/* + * Copyright (c) 1995 The Regents of the University of California. + * All rights reserved. + * + * Permission to use, copy, modify, and distribute this software and its + * documentation for any purpose, without fee, and without written agreement is + * hereby granted, provided that the above copyright notice and the following + * two paragraphs appear in all copies of this software. + * + * IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR + * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT + * OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF + * CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS + * ON AN "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO + * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. + */ + +/* + * $Header: /u/smoot/md/mpeg_encode/RCS/jpeg.c,v 1.6 1995/06/08 20:36:00 smoot Exp $ + * $Log: jpeg.c,v $ + * Revision 1.6 1995/06/08 20:36:00 smoot + * added "b"'s to fopen()s for MSDOS + * + * Revision 1.5 1995/02/02 21:24:02 eyhung + * slight cleanup of unused variables + * + * Revision 1.4 1995/01/19 23:08:33 eyhung + * Changed copyrights + * + * Revision 1.3 1995/01/19 22:58:34 smoot + * fixes (I dont know what) + * + * Revision 1.2 1994/11/12 02:11:50 keving + * nothing + * + * Revision 1.1 1994/03/15 00:27:11 keving + * nothing + * + * Revision 1.2 1993/12/22 19:19:01 keving + * nothing + * + * Revision 1.1 1993/07/22 22:23:43 keving + * nothing + * + */ + + +/*==============* + * HEADER FILES * + *==============*/ + +#include <stdio.h> +#include "all.h" +#include "mtypes.h" +#include "frames.h" +#include "prototypes.h" +#include "param.h" +#include "readframe.h" +#include "fsize.h" +#include "rgbtoycc.h" +#include <jpeglib.h> + +/* make it happier.... */ +//#undef DCTSIZE2 +//#include "jpeg/jpeglib.h" + + +#define HEADER_SIZE 607 /*JFIF header size used on output images*/ + + + +/*=======================================================================* + * * + * JMovie2JPEG * + * * + * Splits up a Parallax J_Movie into a set of JFIF image files * + * * + * RETURNS: nothing * + * * + * SIDE EFFECTS: none * + * * + * Contributed By James Boucher(jboucher@flash.bu.edu) * + * Boston University Multimedia Communications Lab * + * This code was adapted from the Berkeley Playone.c and Brian Smith's * + * JGetFrame code after being modified on 10-7-93 by Dinesh Venkatesh * + * of BU. * + * This code converts a version 2 Parallax J_Movie into a * + * set of JFIF compatible JPEG images. It works for all image * + * sizes and qualities. * + ************************************************************************/ +void + JMovie2JPEG(infilename,obase,start,end) +char *infilename; /* input filename string */ +char *obase; /* output filename base string=>obase##.jpg */ +int start; /* first frame to be extracted */ +int end; /* last frame to be extracted */ +{ + FILE *inFile; /* Jmovie file pointer */ + FILE *outFile; /* JPEG file pointer for output file */ + int fd, i; /* input file descriptor and a counting variable*/ + char ofname[256]; /* output filename string */ + int Temp = 0, temp = 0; /* dummy variables */ + int image_offset = 0; /* counting variable */ + /* J_Movie header infomation */ + int ver_no; /* version number - expected to be 2 */ + int fps; /* frame rate - frames per second */ + int no_frames; /* total number of frames in jmovie */ + int bandwidth; /* bandwidth required for normal playback*/ + int qfactor; /* quality factor used to scale Q matrix */ + int mapsize; /* number of color map entries - 2^24 */ + int audio_tracks; /* number of audio tracks ==1 */ + int audiosize; /*number of bytes in audio tracks */ + int *inoffsets; /* input frame offsets from start of jmovie*/ + int width; /* image width */ + int height; /* image height */ + int size; /* total image size in bytes */ + char op_code; /* jmovie op_code */ + char jpeg_size[4]; /* jpeg data size */ + static char junk[1000]; /* data sink for audio data */ + + /* The next array represents the default JFIF header for + quality = 100 and size = 320x240. The values are + adjusted as the J_Movie header is read. The default + size of this array is set large so as to make room + for the appending of the jpeg bitstream. It can be + made smaller if you have a better idea of its expected size*/ + static char inbuffer[300000] = { + 0xFF, 0xD8, 0xFF, 0xE0, 0x00, 0x10, 0x4A, 0x46, + 0x49, 0x46, 0x00, 0x01, 0x01, 0x00, 0x00, 0x01, + 0x00, 0x01, 0x00, 0x00, 0xFF, 0xC0, 0x00, 0x11, + 0x08, 0x00, 0xF0, 0x01, 0x40, 0x03, 0x01, 0x21, + 0x00, 0x02, 0x11, 0x01, 0x03, 0x11, 0x01, 0xFF, + 0xDB, 0x00, 0x84, 0x00, 0x10, 0x0B, 0x0C, 0x0E, + 0x0C, 0x0A, 0x10, 0x0E, 0x0D, 0x0E, 0x12, + 0x11, 0x10, 0x13, 0x18, 0x28, 0x1A, 0x18, 0x16, + 0x16, 0x18, 0x31, 0x23, 0x25, 0x1D, 0x28, 0x3A, + 0x33, 0x3D, 0x3C, 0x39, 0x33, 0x38, 0x37, 0x40, + 0x48, 0x5C, 0x4E, 0x40, 0x44, 0x57, 0x45, 0x37, + 0x38, 0x50, 0x6D, 0x51, 0x57, 0x5F, 0x62, 0x67, + 0x68, 0x67, 0x3E, 0x4D, 0x71, 0x79, 0x70, 0x64, + 0x78, 0x5C, 0x65, 0x67, 0x63, 0x01, 0x11, 0x12, + 0x12, 0x18, 0x15, 0x18, 0x2F, 0x1A, 0x1A, 0x2F, + 0x63, 0x42, 0x38, 0x42, 0x63, 0x63, 0x63, 0x63, + 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, + 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, + 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, + 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, + 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, + 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0xFF, 0xC4, + 0x01, 0xA2, 0x00, 0x00, 0x01, 0x05, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x03, 0x04, + 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, + 0x10, 0x00, 0x02, 0x01, 0x03, 0x03, 0x02, 0x04, + 0x03, 0x05, 0x05, 0x04, 0x04, 0x00, 0x00, 0x01, + 0x7D, 0x01, 0x02, 0x03, 0x00, 0x04, 0x11, 0x05, + 0x12, 0x21, 0x31, 0x41, 0x06, 0x13, 0x51, 0x61, + 0x07, 0x22, 0x71, 0x14, 0x32, 0x81, 0x91, 0xA1, + 0x08, 0x23, 0x42, 0xB1, 0xC1, 0x15, 0x52, 0xD1, + 0xF0, 0x24, 0x33, 0x62, 0x72, 0x82, 0x09, + 0x0A, 0x16, 0x17, 0x18, 0x19, 0x1A, 0x25, 0x26, + 0x27, 0x28, 0x29, 0x2A, 0x34, 0x35, 0x36, 0x37, + 0x38, 0x39, 0x3A, 0x43, 0x44, 0x45, 0x46, 0x47, + 0x48, 0x49, 0x4A, 0x53, 0x54, 0x55, 0x56, 0x57, + 0x58, 0x59, 0x5A, 0x63, 0x64, 0x65, 0x66, 0x67, + 0x68, 0x69, 0x6A, 0x73, 0x74, 0x75, 0x76, 0x77, + 0x78, 0x79, 0x7A, 0x83, 0x84, 0x85, 0x86, 0x87, + 0x88, 0x89, 0x8A, 0x92, 0x93, 0x94, 0x95, 0x96, + 0x97, 0x98, 0x99, 0x9A, 0xA2, 0xA3, 0xA4, 0xA5, + 0xA6, 0xA7, 0xA8, 0xA9, 0xAA, 0xB2, 0xB3, 0xB4, + 0xB5, 0xB6, 0xB7, 0xB8, 0xB9, 0xBA, 0xC2, 0xC3, + 0xC4, 0xC5, 0xC6, 0xC7, 0xC8, 0xC9, 0xCA, 0xD2, + 0xD3, 0xD4, 0xD5, 0xD6, 0xD7, 0xD8, 0xD9, 0xDA, + 0xE1, 0xE2, 0xE3, 0xE4, 0xE5, 0xE6, 0xE7, 0xE8, + 0xE9, 0xEA, 0xF1, 0xF2, 0xF3, 0xF4, 0xF5, 0xF6, + 0xF7, 0xF8, 0xF9, 0xFA, 0x01, 0x00, 0x03, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02, + 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, + 0x0A, 0x0B, 0x11, 0x00, 0x02, 0x01, 0x02, 0x04, + 0x04, 0x03, 0x04, 0x07, 0x05, 0x04, 0x04, 0x00, + 0x01, 0x02, 0x77, 0x00, 0x01, 0x02, 0x03, 0x11, + 0x04, 0x05, 0x21, 0x31, 0x06, 0x12, 0x41, 0x51, + 0x07, 0x61, 0x71, 0x13, 0x22, 0x32, 0x81, 0x08, + 0x14, 0x42, 0x91, 0xA1, 0xB1, 0xC1, 0x09, 0x23, + 0x33, 0x52, 0xF0, 0x15, 0x62, 0x72, 0xD1, + 0x0A, 0x16, 0x24, 0x34, 0xE1, 0x25, 0xF1, 0x17, + 0x18, 0x19, 0x1A, 0x26, 0x27, 0x28, 0x29, 0x2A, + 0x35, 0x36, 0x37, 0x38, 0x39, 0x3A, 0x43, 0x44, + 0x45, 0x46, 0x47, 0x48, 0x49, 0x4A, 0x53, 0x54, + 0x55, 0x56, 0x57, 0x58, 0x59, 0x5A, 0x63, 0x64, + 0x65, 0x66, 0x67, 0x68, 0x69, 0x6A, 0x73, 0x74, + 0x75, 0x76, 0x77, 0x78, 0x79, 0x7A, 0x82, 0x83, + 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8A, 0x92, + 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9A, + 0xA2, 0xA3, 0xA4, 0xA5, 0xA6, 0xA7, 0xA8, 0xA9, + 0xAA, 0xB2, 0xB3, 0xB4, 0xB5, 0xB6, 0xB7, 0xB8, + 0xB9, 0xBA, 0xC2, 0xC3, 0xC4, 0xC5, 0xC6, 0xC7, + 0xC8, 0xC9, 0xCA, 0xD2, 0xD3, 0xD4, 0xD5, 0xD6, + 0xD7, 0xD8, 0xD9, 0xDA, 0xE2, 0xE3, 0xE4, 0xE5, + 0xE6, 0xE7, 0xE8, 0xE9, 0xEA, 0xF2, 0xF3, 0xF4, + 0xF5, 0xF6, 0xF7, 0xF8, 0xF9, 0xFA, 0xFF, 0xDA, + 0x00, 0x0C, 0x03, 0x01, 0x00, 0x02, 0x11, 0x03, + 0x11, 0x00, 0x3F, 0x00 + + }; + + if(start > end) + { + fprintf(stderr,"bad frame numbers\n"); + exit(1); + } + + /* open J_Movie */ + inFile = fopen(infilename, "rb"); + if (inFile == NULL) + { + perror (infilename); + exit (1); + } + + /* get file descriptor */ + fd = fileno(inFile); + + /* The following lines parse the jpeg_movie header and recover the */ + /* relavant information */ + + fseek (inFile, (8*sizeof(char)),0); + + if (fread (&ver_no,sizeof(int),1,inFile) != 1) + { + perror("Error in reading version"); + exit(1); + } + if(ver_no != 2){ + perror("Unrecognized version - Quantization tables may be wrong\n"); + } + if (fread (&(fps),sizeof(int),1,inFile) != 1) + { + perror("Error in reading fps"); + exit(1); + } + if (fread (&(no_frames),sizeof(int),1,inFile) != 1) + { + perror("Error in reading no_frames"); + exit(1); + } + + inoffsets = (int *)malloc(no_frames*sizeof(int)); + + if (fread (&(width),sizeof(int),1,inFile) != 1) + { + perror("Error in reading width"); + exit(1); + } + /* set image width in JFIF header */ + inbuffer[27] = (char)(0xFF & (width >> 8)); + inbuffer[28] = (char)(0xFF & width); + + if (fread (&(height),sizeof(int), 1,inFile) != 1) + { + perror("Error in reading height"); + exit(1); + } + /* set image height in JFIF header */ + inbuffer[25] = (char)(0xFF & (height >> 8)); + inbuffer[26] = (char)(0xFF & height); + + if (fread (&(bandwidth),sizeof(int),1,inFile) != 1) + { + perror("Error in reading bandwidth"); + exit(1); + } + + if (fread (&(qfactor),sizeof(int),1,inFile) != 1) + { + perror("Error in reading qfactor"); + exit(1); + } + /* The default quality factor = 100, therefore, if + our quality factor does not equal 100 we must + scale the quantization matrices in the JFIF header*/ + /* Note values are clipped to a max of 255 */ + if(qfactor != 100){ + for(Temp=44;Temp<108;Temp++){ + temp= (inbuffer[Temp]*qfactor)/100; + inbuffer[Temp] = (char)((temp<255) ? temp : 255); + } + for(Temp=109;Temp<173;Temp++){ + temp = (inbuffer[Temp]*qfactor)/100; + inbuffer[Temp] = (char)((temp<255) ? temp : 255); + } + } + + if (fread (&(mapsize),sizeof(int),1,inFile) != 1) + { + perror("Error in reading mapsize"); + exit(1); + } + if (fread (&(image_offset),sizeof(int),1,inFile) != 1) + { + perror("Error in reading image offset"); + exit(1); + } + if (fread (&(audio_tracks),sizeof(int),1,inFile) != 1) + { + perror("Error in reading audio tracks"); + exit(1); + } + + fread(junk,sizeof(int),1,inFile); + + if (fread (&(audiosize),sizeof(int),1,inFile) != 1) + { + perror("Error in reading audiosize"); + exit(1); + } + + fseek (inFile,(image_offset),0); + + + if(no_frames <= end) + { + end = no_frames - 1; + } + + + for(i=0;i<no_frames;i++) + { + fread(&(inoffsets[i]),sizeof(int),1,inFile); + } /* Reads in the frame sizes into the array */ + + rewind(inFile); + + /* Extract JFIF files from J_Movie */ + for (i=start; i<=end ; i++) + { + size = inoffsets[i]- inoffsets[i-1]- 5; + lseek(fd, inoffsets[i-1],0); + read(fd, &(op_code), 1); + while( op_code != 0xffffffec) + { + read(fd,junk,audiosize); + read(fd, &(op_code), 1); + size = size - audiosize ; + } /* To skip the audio bytes in each frame */ + read(fd,jpeg_size,4); + read(fd,&(inbuffer[607]),(size)); + sprintf(ofname,"%s%d.jpg",obase,i); + outFile = fopen(ofname, "wb"); + fwrite(inbuffer,(size+607),sizeof(char),outFile); + fclose(outFile); + } + free(inoffsets); + fclose(inFile); +} + + + + +/*===========================================================================* + * + * ReadJPEG contributed by James Arthur Boucher of Boston University's + * Multimedia Communications Lab + * + * read a JPEG file and copy data into frame original data arrays + * + * RETURNS: mf modified + * + * SIDE EFFECTS: none + * + *===========================================================================*/ +/*************************JPEG LIBRARY INTERFACE*********************/ +/* + * THE BIG PICTURE: + * + * The rough outline this JPEG decompression operation is: + * + * allocate and initialize JPEG decompression object + * specify data source (eg, a file) + * jpeg_read_header(); // obtain image dimensions and other parameters + * set parameters for decompression + * jpeg_start_decompress(); + * while (scan lines remain to be read) + * jpeg_read_scanlines(...); + * jpeg_finish_decompress(); + * release JPEG decompression object + * + */ +void +ReadJPEG(mf, fp) + MpegFrame *mf; + FILE *fp; +{ + + /* This struct contains the JPEG decompression parameters and pointers to + * working data (which is allocated as needed by the JPEG library). + */ + static struct jpeg_decompress_struct cinfo; + struct jpeg_error_mgr jerr; + /* More stuff */ + JSAMPARRAY scanarray[3]; + int ci,cd,cp; + JDIMENSION ncols[3]; + JDIMENSION nrows[3]; + jpeg_component_info *compptr; + int buffer_height; + int current_row[3]; + uint8 **orig[3]; + int h_samp[3],v_samp[3]; + int max_h_samp,max_v_samp; + int temp_h, temp_v; + int temp; + + /* Allocate and initialize JPEG decompression object */ + cinfo.err = jpeg_std_error(&jerr); + + /* + ** If we're reading from stdin we want to create the cinfo struct + ** ONCE (during the first read). This is because when reading jpeg + ** from stdin we will not release the cinfo struct, because doing + ** so would totally screw up the read buffer and make it impossible + ** to read jpegs from stdin. + ** Dave Scott (dhs), UofO, 7/19/95 + */ + { + static int first_stdin = 1; + if( (fp != stdin) || first_stdin) + { + first_stdin = 0; + /* Now we can initialize the JPEG decompression object. */ + jpeg_create_decompress(&cinfo); + /* specify data source (eg, a file) */ + jpeg_stdio_src(&cinfo, fp); + } + } + + /* specify data source (eg, a file) */ + + jpeg_stdio_src(&cinfo, fp); + + /* read file parameters with jpeg_read_header() */ + + + (void) jpeg_read_header(&cinfo, TRUE); + /* We can ignore the return value from jpeg_read_header since + * (a) suspension is not possible with the stdio data source, and + * (b) we passed TRUE to reject a tables-only JPEG file as an error. + */ + + /* set parameters for decompression */ +#ifdef JPEG4 + cinfo.want_raw_output = TRUE; +#else + cinfo.raw_data_out = TRUE; +#endif + cinfo.out_color_space = JCS_YCbCr; + + /* calculate image output dimensions */ + jpeg_calc_output_dimensions(&cinfo); + /* the above calculation will set these soon */ + /* for now we'll set them ourselves */ + + + /* tell mpeg_encode the size of the JPEG Image*/ + Fsize_Note(mf->id,(int)(cinfo.image_width),(int)(cinfo.image_height)); + + /* Allocate memory for the raw YCbCr data to occupy*/ + Frame_AllocYCC(mf); /*allocate space for mpeg frame*/ + + /* copy pointers to array structure- this make the following + code more compact */ + orig[0] = mf->orig_y; + orig[1] = mf->orig_cb; + orig[2] = mf->orig_cr; + + /* Note that we can use the info obtained from jpeg_read_header. + */ + + /* Start decompressor */ + + jpeg_start_decompress(&cinfo); + + + /* JSAMPLEs per row in output buffer */ + /* collect component subsample values*/ + for(cp=0,compptr = cinfo.comp_info;cp<cinfo.num_components; + cp++,compptr++) { + h_samp[cp] = compptr->h_samp_factor; + v_samp[cp] = compptr->v_samp_factor; + } + /* calculate max subsample values*/ + temp_h = (h_samp[0]<h_samp[1]) ? h_samp[1] : h_samp[0]; + max_h_samp = (temp_h<h_samp[2]) ? h_samp[2]:temp_h; + temp_v = (v_samp[0]<v_samp[1]) ? v_samp[1] : v_samp[0]; + max_v_samp = (temp_v<v_samp[2]) ? v_samp[2]:temp_v; + + /* Make an 8-row-high sample array that will go away when done with image */ +#ifdef JPEG4 + buffer_height = 8; /* could be 2, 4,8 rows high */ +#else + buffer_height = cinfo.max_v_samp_factor * cinfo.min_DCT_scaled_size; +#endif + + for(cp=0,compptr = cinfo.comp_info;cp<cinfo.num_components; + cp++,compptr++) { + ncols[cp] = (JDIMENSION)((cinfo.image_width*compptr->h_samp_factor)/ + max_h_samp); + + nrows[cp] = (JDIMENSION)((buffer_height*compptr->v_samp_factor)/ + max_v_samp); + + scanarray[cp] = (*cinfo.mem->alloc_sarray) + ((j_common_ptr) &cinfo, JPOOL_IMAGE, ncols[cp], nrows[cp]); + + } + + + /* while (scan lines remain to be read) */ + /* jpeg_read_scanlines(...); */ + + /* Here we use the library's state variable cinfo.output_scanline as the + * loop counter, so that we don't have to keep track ourselves. + */ + + while (cinfo.output_scanline < cinfo.output_height) { + +#ifdef JPEG4 + (void) jpeg_read_raw_scanlines(&cinfo, scanarray, buffer_height); +#else + (void) jpeg_read_raw_data(&cinfo, scanarray, buffer_height); +#endif + +/* alter subsample ratio's if neccessary */ + if((h_samp[0]==2)&&(h_samp[1]==1)&&(h_samp[2]==1)&& + (v_samp[0]==2)&&(v_samp[1]==1)&&(v_samp[2]==1)){ + /* we are 4:1:1 as expected by the encoder*/ + }else if((h_samp[0]==2)&&(h_samp[1]==1)&&(h_samp[2]==1)&& + (v_samp[0]==1)&&(v_samp[1]==1)&&(v_samp[2]==1)){ + /* must subsample 2:1 vertically and adjust params*/ + for(ci=1; ci<3; ci++){ + for(cp=0; cp<(buffer_height/2);cp=cp+1){ + for(cd=0;cd<ncols[ci];cd++){ + temp =((scanarray[ci][cp*2][cd]+scanarray[ci][(cp*2)+1][cd])/2); + scanarray[ci][cp][cd] = (JSAMPLE)(temp); + } + } + } + /* only reset values the first time through*/ + if(cinfo.output_scanline==buffer_height){ + nrows[1] = nrows[1]/2; + nrows[2] = nrows[2]/2; + max_v_samp = 2; + v_samp[0] = 2; + } + }else{ + fprintf(stderr, "Not a supported subsampling ratio\n"); + exit(1); + } + + /* transfer data from jpeg buffer to MPEG frame */ + /* calculate the row we wish to output into */ + for(ci=0,compptr=cinfo.comp_info;ci<cinfo.num_components; + ci++,compptr++){ + current_row[ci] =((cinfo.output_scanline - buffer_height)* + (v_samp[ci])/max_v_samp); + + jcopy_sample_rows(scanarray[ci],0,(JSAMPARRAY)(orig[ci]), + current_row[ci],nrows[ci],ncols[ci]); + } + + } + + /* Step 7: Finish decompression */ + + (void) jpeg_finish_decompress(&cinfo); + /* We can ignore the return value since suspension is not possible + * with the stdio data source. + */ + + /* Step 8: Release JPEG decompression object */ + + /* + ** DO NOT release the cinfo struct if we are reading from stdin, this + ** is because the cinfo struct contains the read buffer, and the read + ** buffer may (and almost always does) contain the end of one image and + ** the beginning of another. If we throw away the read buffer then + ** we loose the beginning of the next image, and we're screwed. + ** Dave Scott (dhs), UofO, 7/19/95 + */ + if( fp == stdin) { + static int no_from_stdin = 0; + no_from_stdin++; + /* fprintf( stderr, "%d jpeg images read from stdin\n", no_from_stdin); */ + } + else { + /* This is an important step since it will release a good deal of memory. */ + jpeg_destroy_decompress(&cinfo); + } + + /* After finish_decompress, we can close the input file. + * Here we postpone it until after no more JPEG errors are possible, + * so as to simplify the setjmp error logic above. (Actually, I don't + * think that jpeg_destroy can do an error exit, but why assume anything...) + */ + + + /* At this point you may want to check to see whether any corrupt-data + * warnings occurred (test whether jerr.pub.num_warnings is nonzero). + * If you prefer to treat corrupt data as a fatal error, override the + * error handler's emit_message method to call error_exit on a warning. + */ + + /* And we're done! */ + +} + + +/* + * SOME FINE POINTS: + * + * In the above loop, we ignored the return value of jpeg_read_scanlines, + * which is the number of scanlines actually read. We could get away with + * this for the same reasons discussed in the compression example. Actually + * there is one perfectly normal situation in which jpeg_read_scanlines may + * return fewer lines than you asked for: at the bottom of the image. But the + * loop above can't ask for more lines than there are in the image since it + * reads only one line at a time. + * + * In some high-speed operating modes, some data copying can be saved by + * making the buffer passed to jpeg_read_scanlines be cinfo.rec_outbuf_height + * lines high (or a multiple thereof). This will usually be 1, 2, or 4 lines. + * + * To decompress multiple images, you can repeat the whole sequence, or you + * can keep the JPEG object around and just repeat steps 2-7. This will + * save a little bit of startup/shutdown time. + * + * As with compression, some operating modes may require temporary files. + * On some systems you may need to set up a signal handler to ensure that + * temporary files are deleted if the program is interrupted. + * + * Scanlines are returned in the same order as they appear in the JPEG file, + * which is standardly top-to-bottom. If you must have data supplied + * bottom-to-top, you can use one of the virtual arrays provided by the + * JPEG memory manager to invert the data. See wrrle.c for an example. + */ diff --git a/contrib/mpeg_encode/jrevdct.cpp b/contrib/mpeg_encode/jrevdct.cpp new file mode 100644 index 0000000000000000000000000000000000000000..8f9564d15da8254648d2217f54c44a684dfe3e68 --- /dev/null +++ b/contrib/mpeg_encode/jrevdct.cpp @@ -0,0 +1,1275 @@ +/* + * jrevdct.c + * + * Copyright (C) 1991, 1992, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file contains the basic inverse-DCT transformation subroutine. + * + * This implementation is based on an algorithm described in + * C. Loeffler, A. Ligtenberg and G. Moschytz, "Practical Fast 1-D DCT + * Algorithms with 11 Multiplications", Proc. Int'l. Conf. on Acoustics, + * Speech, and Signal Processing 1989 (ICASSP '89), pp. 988-991. + * The primary algorithm described there uses 11 multiplies and 29 adds. + * We use their alternate method with 12 multiplies and 32 adds. + * The advantage of this method is that no data path contains more than one + * multiplication; this allows a very simple and accurate implementation in + * scaled fixed-point arithmetic, with a minimal number of shifts. + * + * I've made lots of modifications to attempt to take advantage of the + * sparse nature of the DCT matrices we're getting. Although the logic + * is cumbersome, it's straightforward and the resulting code is much + * faster. + * + * A better way to do this would be to pass in the DCT block as a sparse + * matrix, perhaps with the difference cases encoded. + */ + +#include <memory.h> +#include "all.h" +#include "ansi.h" +#include "dct.h" + + +#define CONST_BITS 13 + +/* + * This routine is specialized to the case DCTSIZE = 8. + */ + +#if DCTSIZE != 8 + Sorry, this code only copes with 8x8 DCTs. /* deliberate syntax err */ +#endif + + +/* + * A 2-D IDCT can be done by 1-D IDCT on each row followed by 1-D IDCT + * on each column. Direct algorithms are also available, but they are + * much more complex and seem not to be any faster when reduced to code. + * + * The poop on this scaling stuff is as follows: + * + * Each 1-D IDCT step produces outputs which are a factor of sqrt(N) + * larger than the true IDCT outputs. The final outputs are therefore + * a factor of N larger than desired; since N=8 this can be cured by + * a simple right shift at the end of the algorithm. The advantage of + * this arrangement is that we save two multiplications per 1-D IDCT, + * because the y0 and y4 inputs need not be divided by sqrt(N). + * + * We have to do addition and subtraction of the integer inputs, which + * is no problem, and multiplication by fractional constants, which is + * a problem to do in integer arithmetic. We multiply all the constants + * by CONST_SCALE and convert them to integer constants (thus retaining + * CONST_BITS bits of precision in the constants). After doing a + * multiplication we have to divide the product by CONST_SCALE, with proper + * rounding, to produce the correct output. This division can be done + * cheaply as a right shift of CONST_BITS bits. We postpone shifting + * as long as possible so that partial sums can be added together with + * full fractional precision. + * + * The outputs of the first pass are scaled up by PASS1_BITS bits so that + * they are represented to better-than-integral precision. These outputs + * require BITS_IN_JSAMPLE + PASS1_BITS + 3 bits; this fits in a 16-bit word + * with the recommended scaling. (To scale up 12-bit sample data further, an + * intermediate int32 array would be needed.) + * + * To avoid overflow of the 32-bit intermediate results in pass 2, we must + * have BITS_IN_JSAMPLE + CONST_BITS + PASS1_BITS <= 26. Error analysis + * shows that the values given below are the most effective. + */ + +#ifdef EIGHT_BIT_SAMPLES +#define PASS1_BITS 2 +#else +#define PASS1_BITS 1 /* lose a little precision to avoid overflow */ +#endif + +#define ONE ((int32) 1) + +#define CONST_SCALE (ONE << CONST_BITS) + +/* Convert a positive real constant to an integer scaled by CONST_SCALE. + * IMPORTANT: if your compiler doesn't do this arithmetic at compile time, + * you will pay a significant penalty in run time. In that case, figure + * the correct integer constant values and insert them by hand. + */ + +/* Actually FIX is no longer used, we precomputed them all */ +#define FIX(x) ((int32) ((x) * CONST_SCALE + 0.5)) + +/* Descale and correctly round an int32 value that's scaled by N bits. + * We assume RIGHT_SHIFT rounds towards minus infinity, so adding + * the fudge factor is correct for either sign of X. + */ + +#define DESCALE(x,n) RIGHT_SHIFT((x) + (ONE << ((n)-1)), n) + +/* Multiply an int32 variable by an int32 constant to yield an int32 result. + * For 8-bit samples with the recommended scaling, all the variable + * and constant values involved are no more than 16 bits wide, so a + * 16x16->32 bit multiply can be used instead of a full 32x32 multiply; + * this provides a useful speedup on many machines. + * There is no way to specify a 16x16->32 multiply in portable C, but + * some C compilers will do the right thing if you provide the correct + * combination of casts. + * NB: for 12-bit samples, a full 32-bit multiplication will be needed. + */ + +#ifdef EIGHT_BIT_SAMPLES +#ifdef SHORTxSHORT_32 /* may work if 'int' is 32 bits */ +#define MULTIPLY(var,const) (((INT16) (var)) * ((INT16) (const))) +#endif +#ifdef SHORTxLCONST_32 /* known to work with Microsoft C 6.0 */ +#define MULTIPLY(var,const) (((INT16) (var)) * ((int32) (const))) +#endif +#endif + +#ifndef MULTIPLY /* default definition */ +#define MULTIPLY(var,const) ((var) * (const)) +#endif + + +/* + Unlike our decoder where we approximate the FIXes, we need to use exact +ones here or successive P-frames will drift too much with Reference frame coding +*/ +#define FIX_0_211164243 1730 +#define FIX_0_275899380 2260 +#define FIX_0_298631336 2446 +#define FIX_0_390180644 3196 +#define FIX_0_509795579 4176 +#define FIX_0_541196100 4433 +#define FIX_0_601344887 4926 +#define FIX_0_765366865 6270 +#define FIX_0_785694958 6436 +#define FIX_0_899976223 7373 +#define FIX_1_061594337 8697 +#define FIX_1_111140466 9102 +#define FIX_1_175875602 9633 +#define FIX_1_306562965 10703 +#define FIX_1_387039845 11363 +#define FIX_1_451774981 11893 +#define FIX_1_501321110 12299 +#define FIX_1_662939225 13623 +#define FIX_1_847759065 15137 +#define FIX_1_961570560 16069 +#define FIX_2_053119869 16819 +#define FIX_2_172734803 17799 +#define FIX_2_562915447 20995 +#define FIX_3_072711026 25172 + +/* + Switch on reverse_dct choices +*/ +void reference_rev_dct _ANSI_ARGS_((int16 *block)); +void mpeg_jrevdct_quick _ANSI_ARGS_((int16 *block)); +void init_idctref _ANSI_ARGS_((void)); + +extern boolean pureDCT; + +void +mpeg_jrevdct(DCTBLOCK data) +{ + if (pureDCT) reference_rev_dct(data); + else mpeg_jrevdct_quick(data); +} + +/* + * Perform the inverse DCT on one block of coefficients. + */ + +void +mpeg_jrevdct_quick(DCTBLOCK data) +{ + int32 tmp0, tmp1, tmp2, tmp3; + int32 tmp10, tmp11, tmp12, tmp13; + int32 z1, z2, z3, z4, z5; + int32 d0, d1, d2, d3, d4, d5, d6, d7; + register DCTELEM *dataptr; + int rowctr; + SHIFT_TEMPS + + /* Pass 1: process rows. */ + /* Note results are scaled up by sqrt(8) compared to a true IDCT; */ + /* furthermore, we scale the results by 2**PASS1_BITS. */ + + dataptr = data; + + for (rowctr = DCTSIZE-1; rowctr >= 0; rowctr--) { + /* Due to quantization, we will usually find that many of the input + * coefficients are zero, especially the AC terms. We can exploit this + * by short-circuiting the IDCT calculation for any row in which all + * the AC terms are zero. In that case each output is equal to the + * DC coefficient (with scale factor as needed). + * With typical images and quantization tables, half or more of the + * row DCT calculations can be simplified this way. + */ + + register int *idataptr = (int*)dataptr; + d0 = dataptr[0]; + d1 = dataptr[1]; + if ((d1 == 0) && (idataptr[1] | idataptr[2] | idataptr[3]) == 0) { + /* AC terms all zero */ + if (d0) { + /* Compute a 32 bit value to assign. */ + DCTELEM dcval = (DCTELEM) (d0 << PASS1_BITS); + register int v = (dcval & 0xffff) | ((dcval << 16) & 0xffff0000); + + idataptr[0] = v; + idataptr[1] = v; + idataptr[2] = v; + idataptr[3] = v; + } + + dataptr += DCTSIZE; /* advance pointer to next row */ + continue; + } + d2 = dataptr[2]; + d3 = dataptr[3]; + d4 = dataptr[4]; + d5 = dataptr[5]; + d6 = dataptr[6]; + d7 = dataptr[7]; + + /* Even part: reverse the even part of the forward DCT. */ + /* The rotator is sqrt(2)*c(-6). */ +{ + if (d6) { + if (d4) { + if (d2) { + if (d0) { + /* d0 != 0, d2 != 0, d4 != 0, d6 != 0 */ + z1 = MULTIPLY(d2 + d6, FIX_0_541196100); + tmp2 = z1 + MULTIPLY(-d6, FIX_1_847759065); + tmp3 = z1 + MULTIPLY(d2, FIX_0_765366865); + + tmp0 = (d0 + d4) << CONST_BITS; + tmp1 = (d0 - d4) << CONST_BITS; + + tmp10 = tmp0 + tmp3; + tmp13 = tmp0 - tmp3; + tmp11 = tmp1 + tmp2; + tmp12 = tmp1 - tmp2; + } else { + /* d0 == 0, d2 != 0, d4 != 0, d6 != 0 */ + z1 = MULTIPLY(d2 + d6, FIX_0_541196100); + tmp2 = z1 + MULTIPLY(-d6, FIX_1_847759065); + tmp3 = z1 + MULTIPLY(d2, FIX_0_765366865); + + tmp0 = d4 << CONST_BITS; + + tmp10 = tmp0 + tmp3; + tmp13 = tmp0 - tmp3; + tmp11 = tmp2 - tmp0; + tmp12 = -(tmp0 + tmp2); + } + } else { + if (d0) { + /* d0 != 0, d2 == 0, d4 != 0, d6 != 0 */ + tmp2 = MULTIPLY(-d6, FIX_1_306562965); + tmp3 = MULTIPLY(d6, FIX_0_541196100); + + tmp0 = (d0 + d4) << CONST_BITS; + tmp1 = (d0 - d4) << CONST_BITS; + + tmp10 = tmp0 + tmp3; + tmp13 = tmp0 - tmp3; + tmp11 = tmp1 + tmp2; + tmp12 = tmp1 - tmp2; + } else { + /* d0 == 0, d2 == 0, d4 != 0, d6 != 0 */ + tmp2 = MULTIPLY(-d6, FIX_1_306562965); + tmp3 = MULTIPLY(d6, FIX_0_541196100); + + tmp0 = d4 << CONST_BITS; + + tmp10 = tmp0 + tmp3; + tmp13 = tmp0 - tmp3; + tmp11 = tmp2 - tmp0; + tmp12 = -(tmp0 + tmp2); + } + } + } else { + if (d2) { + if (d0) { + /* d0 != 0, d2 != 0, d4 == 0, d6 != 0 */ + z1 = MULTIPLY(d2 + d6, FIX_0_541196100); + tmp2 = z1 + MULTIPLY(-d6, FIX_1_847759065); + tmp3 = z1 + MULTIPLY(d2, FIX_0_765366865); + + tmp0 = d0 << CONST_BITS; + + tmp10 = tmp0 + tmp3; + tmp13 = tmp0 - tmp3; + tmp11 = tmp0 + tmp2; + tmp12 = tmp0 - tmp2; + } else { + /* d0 == 0, d2 != 0, d4 == 0, d6 != 0 */ + z1 = MULTIPLY(d2 + d6, FIX_0_541196100); + tmp2 = z1 + MULTIPLY(-d6, FIX_1_847759065); + tmp3 = z1 + MULTIPLY(d2, FIX_0_765366865); + + tmp10 = tmp3; + tmp13 = -tmp3; + tmp11 = tmp2; + tmp12 = -tmp2; + } + } else { + if (d0) { + /* d0 != 0, d2 == 0, d4 == 0, d6 != 0 */ + tmp2 = MULTIPLY(-d6, FIX_1_306562965); + tmp3 = MULTIPLY(d6, FIX_0_541196100); + + tmp0 = d0 << CONST_BITS; + + tmp10 = tmp0 + tmp3; + tmp13 = tmp0 - tmp3; + tmp11 = tmp0 + tmp2; + tmp12 = tmp0 - tmp2; + } else { + /* d0 == 0, d2 == 0, d4 == 0, d6 != 0 */ + tmp2 = MULTIPLY(-d6, FIX_1_306562965); + tmp3 = MULTIPLY(d6, FIX_0_541196100); + + tmp10 = tmp3; + tmp13 = -tmp3; + tmp11 = tmp2; + tmp12 = -tmp2; + } + } + } + } else { + if (d4) { + if (d2) { + if (d0) { + /* d0 != 0, d2 != 0, d4 != 0, d6 == 0 */ + tmp2 = MULTIPLY(d2, FIX_0_541196100); + tmp3 = MULTIPLY(d2, FIX_1_306562965); + + tmp0 = (d0 + d4) << CONST_BITS; + tmp1 = (d0 - d4) << CONST_BITS; + + tmp10 = tmp0 + tmp3; + tmp13 = tmp0 - tmp3; + tmp11 = tmp1 + tmp2; + tmp12 = tmp1 - tmp2; + } else { + /* d0 == 0, d2 != 0, d4 != 0, d6 == 0 */ + tmp2 = MULTIPLY(d2, FIX_0_541196100); + tmp3 = MULTIPLY(d2, FIX_1_306562965); + + tmp0 = d4 << CONST_BITS; + + tmp10 = tmp0 + tmp3; + tmp13 = tmp0 - tmp3; + tmp11 = tmp2 - tmp0; + tmp12 = -(tmp0 + tmp2); + } + } else { + if (d0) { + /* d0 != 0, d2 == 0, d4 != 0, d6 == 0 */ + tmp10 = tmp13 = (d0 + d4) << CONST_BITS; + tmp11 = tmp12 = (d0 - d4) << CONST_BITS; + } else { + /* d0 == 0, d2 == 0, d4 != 0, d6 == 0 */ + tmp10 = tmp13 = d4 << CONST_BITS; + tmp11 = tmp12 = -tmp10; + } + } + } else { + if (d2) { + if (d0) { + /* d0 != 0, d2 != 0, d4 == 0, d6 == 0 */ + tmp2 = MULTIPLY(d2, FIX_0_541196100); + tmp3 = MULTIPLY(d2, FIX_1_306562965); + + tmp0 = d0 << CONST_BITS; + + tmp10 = tmp0 + tmp3; + tmp13 = tmp0 - tmp3; + tmp11 = tmp0 + tmp2; + tmp12 = tmp0 - tmp2; + } else { + /* d0 == 0, d2 != 0, d4 == 0, d6 == 0 */ + tmp2 = MULTIPLY(d2, FIX_0_541196100); + tmp3 = MULTIPLY(d2, FIX_1_306562965); + + tmp10 = tmp3; + tmp13 = -tmp3; + tmp11 = tmp2; + tmp12 = -tmp2; + } + } else { + if (d0) { + /* d0 != 0, d2 == 0, d4 == 0, d6 == 0 */ + tmp10 = tmp13 = tmp11 = tmp12 = d0 << CONST_BITS; + } else { + /* d0 == 0, d2 == 0, d4 == 0, d6 == 0 */ + tmp10 = tmp13 = tmp11 = tmp12 = 0; + } + } + } + } + + /* Odd part per figure 8; the matrix is unitary and hence its + * transpose is its inverse. i0..i3 are y7,y5,y3,y1 respectively. + */ + + if (d7) { + if (d5) { + if (d3) { + if (d1) { + /* d1 != 0, d3 != 0, d5 != 0, d7 != 0 */ + z1 = d7 + d1; + z2 = d5 + d3; + z3 = d7 + d3; + z4 = d5 + d1; + z5 = MULTIPLY(z3 + z4, FIX_1_175875602); + + tmp0 = MULTIPLY(d7, FIX_0_298631336); + tmp1 = MULTIPLY(d5, FIX_2_053119869); + tmp2 = MULTIPLY(d3, FIX_3_072711026); + tmp3 = MULTIPLY(d1, FIX_1_501321110); + z1 = MULTIPLY(-z1, FIX_0_899976223); + z2 = MULTIPLY(-z2, FIX_2_562915447); + z3 = MULTIPLY(-z3, FIX_1_961570560); + z4 = MULTIPLY(-z4, FIX_0_390180644); + + z3 += z5; + z4 += z5; + + tmp0 += z1 + z3; + tmp1 += z2 + z4; + tmp2 += z2 + z3; + tmp3 += z1 + z4; + } else { + /* d1 == 0, d3 != 0, d5 != 0, d7 != 0 */ + z2 = d5 + d3; + z3 = d7 + d3; + z5 = MULTIPLY(z3 + d5, FIX_1_175875602); + + tmp0 = MULTIPLY(d7, FIX_0_298631336); + tmp1 = MULTIPLY(d5, FIX_2_053119869); + tmp2 = MULTIPLY(d3, FIX_3_072711026); + z1 = MULTIPLY(-d7, FIX_0_899976223); + z2 = MULTIPLY(-z2, FIX_2_562915447); + z3 = MULTIPLY(-z3, FIX_1_961570560); + z4 = MULTIPLY(-d5, FIX_0_390180644); + + z3 += z5; + z4 += z5; + + tmp0 += z1 + z3; + tmp1 += z2 + z4; + tmp2 += z2 + z3; + tmp3 = z1 + z4; + } + } else { + if (d1) { + /* d1 != 0, d3 == 0, d5 != 0, d7 != 0 */ + z1 = d7 + d1; + z4 = d5 + d1; + z5 = MULTIPLY(d7 + z4, FIX_1_175875602); + + tmp0 = MULTIPLY(d7, FIX_0_298631336); + tmp1 = MULTIPLY(d5, FIX_2_053119869); + tmp3 = MULTIPLY(d1, FIX_1_501321110); + z1 = MULTIPLY(-z1, FIX_0_899976223); + z2 = MULTIPLY(-d5, FIX_2_562915447); + z3 = MULTIPLY(-d7, FIX_1_961570560); + z4 = MULTIPLY(-z4, FIX_0_390180644); + + z3 += z5; + z4 += z5; + + tmp0 += z1 + z3; + tmp1 += z2 + z4; + tmp2 = z2 + z3; + tmp3 += z1 + z4; + } else { + /* d1 == 0, d3 == 0, d5 != 0, d7 != 0 */ + tmp0 = MULTIPLY(-d7, FIX_0_601344887); + z1 = MULTIPLY(-d7, FIX_0_899976223); + z3 = MULTIPLY(-d7, FIX_1_961570560); + tmp1 = MULTIPLY(-d5, FIX_0_509795579); + z2 = MULTIPLY(-d5, FIX_2_562915447); + z4 = MULTIPLY(-d5, FIX_0_390180644); + z5 = MULTIPLY(d5 + d7, FIX_1_175875602); + + z3 += z5; + z4 += z5; + + tmp0 += z3; + tmp1 += z4; + tmp2 = z2 + z3; + tmp3 = z1 + z4; + } + } + } else { + if (d3) { + if (d1) { + /* d1 != 0, d3 != 0, d5 == 0, d7 != 0 */ + z1 = d7 + d1; + z3 = d7 + d3; + z5 = MULTIPLY(z3 + d1, FIX_1_175875602); + + tmp0 = MULTIPLY(d7, FIX_0_298631336); + tmp2 = MULTIPLY(d3, FIX_3_072711026); + tmp3 = MULTIPLY(d1, FIX_1_501321110); + z1 = MULTIPLY(-z1, FIX_0_899976223); + z2 = MULTIPLY(-d3, FIX_2_562915447); + z3 = MULTIPLY(-z3, FIX_1_961570560); + z4 = MULTIPLY(-d1, FIX_0_390180644); + + z3 += z5; + z4 += z5; + + tmp0 += z1 + z3; + tmp1 = z2 + z4; + tmp2 += z2 + z3; + tmp3 += z1 + z4; + } else { + /* d1 == 0, d3 != 0, d5 == 0, d7 != 0 */ + z3 = d7 + d3; + + tmp0 = MULTIPLY(-d7, FIX_0_601344887); + z1 = MULTIPLY(-d7, FIX_0_899976223); + tmp2 = MULTIPLY(d3, FIX_0_509795579); + z2 = MULTIPLY(-d3, FIX_2_562915447); + z5 = MULTIPLY(z3, FIX_1_175875602); + z3 = MULTIPLY(-z3, FIX_0_785694958); + + tmp0 += z3; + tmp1 = z2 + z5; + tmp2 += z3; + tmp3 = z1 + z5; + } + } else { + if (d1) { + /* d1 != 0, d3 == 0, d5 == 0, d7 != 0 */ + z1 = d7 + d1; + z5 = MULTIPLY(z1, FIX_1_175875602); + + z1 = MULTIPLY(z1, FIX_0_275899380); + z3 = MULTIPLY(-d7, FIX_1_961570560); + tmp0 = MULTIPLY(-d7, FIX_1_662939225); + z4 = MULTIPLY(-d1, FIX_0_390180644); + tmp3 = MULTIPLY(d1, FIX_1_111140466); + + tmp0 += z1; + tmp1 = z4 + z5; + tmp2 = z3 + z5; + tmp3 += z1; + } else { + /* d1 == 0, d3 == 0, d5 == 0, d7 != 0 */ + tmp0 = MULTIPLY(-d7, FIX_1_387039845); + tmp1 = MULTIPLY(d7, FIX_1_175875602); + tmp2 = MULTIPLY(-d7, FIX_0_785694958); + tmp3 = MULTIPLY(d7, FIX_0_275899380); + } + } + } + } else { + if (d5) { + if (d3) { + if (d1) { + /* d1 != 0, d3 != 0, d5 != 0, d7 == 0 */ + z2 = d5 + d3; + z4 = d5 + d1; + z5 = MULTIPLY(d3 + z4, FIX_1_175875602); + + tmp1 = MULTIPLY(d5, FIX_2_053119869); + tmp2 = MULTIPLY(d3, FIX_3_072711026); + tmp3 = MULTIPLY(d1, FIX_1_501321110); + z1 = MULTIPLY(-d1, FIX_0_899976223); + z2 = MULTIPLY(-z2, FIX_2_562915447); + z3 = MULTIPLY(-d3, FIX_1_961570560); + z4 = MULTIPLY(-z4, FIX_0_390180644); + + z3 += z5; + z4 += z5; + + tmp0 = z1 + z3; + tmp1 += z2 + z4; + tmp2 += z2 + z3; + tmp3 += z1 + z4; + } else { + /* d1 == 0, d3 != 0, d5 != 0, d7 == 0 */ + z2 = d5 + d3; + + z5 = MULTIPLY(z2, FIX_1_175875602); + tmp1 = MULTIPLY(d5, FIX_1_662939225); + z4 = MULTIPLY(-d5, FIX_0_390180644); + z2 = MULTIPLY(-z2, FIX_1_387039845); + tmp2 = MULTIPLY(d3, FIX_1_111140466); + z3 = MULTIPLY(-d3, FIX_1_961570560); + + tmp0 = z3 + z5; + tmp1 += z2; + tmp2 += z2; + tmp3 = z4 + z5; + } + } else { + if (d1) { + /* d1 != 0, d3 == 0, d5 != 0, d7 == 0 */ + z4 = d5 + d1; + + z5 = MULTIPLY(z4, FIX_1_175875602); + z1 = MULTIPLY(-d1, FIX_0_899976223); + tmp3 = MULTIPLY(d1, FIX_0_601344887); + tmp1 = MULTIPLY(-d5, FIX_0_509795579); + z2 = MULTIPLY(-d5, FIX_2_562915447); + z4 = MULTIPLY(z4, FIX_0_785694958); + + tmp0 = z1 + z5; + tmp1 += z4; + tmp2 = z2 + z5; + tmp3 += z4; + } else { + /* d1 == 0, d3 == 0, d5 != 0, d7 == 0 */ + tmp0 = MULTIPLY(d5, FIX_1_175875602); + tmp1 = MULTIPLY(d5, FIX_0_275899380); + tmp2 = MULTIPLY(-d5, FIX_1_387039845); + tmp3 = MULTIPLY(d5, FIX_0_785694958); + } + } + } else { + if (d3) { + if (d1) { + /* d1 != 0, d3 != 0, d5 == 0, d7 == 0 */ + z5 = d1 + d3; + tmp3 = MULTIPLY(d1, FIX_0_211164243); + tmp2 = MULTIPLY(-d3, FIX_1_451774981); + z1 = MULTIPLY(d1, FIX_1_061594337); + z2 = MULTIPLY(-d3, FIX_2_172734803); + z4 = MULTIPLY(z5, FIX_0_785694958); + z5 = MULTIPLY(z5, FIX_1_175875602); + + tmp0 = z1 - z4; + tmp1 = z2 + z4; + tmp2 += z5; + tmp3 += z5; + } else { + /* d1 == 0, d3 != 0, d5 == 0, d7 == 0 */ + tmp0 = MULTIPLY(-d3, FIX_0_785694958); + tmp1 = MULTIPLY(-d3, FIX_1_387039845); + tmp2 = MULTIPLY(-d3, FIX_0_275899380); + tmp3 = MULTIPLY(d3, FIX_1_175875602); + } + } else { + if (d1) { + /* d1 != 0, d3 == 0, d5 == 0, d7 == 0 */ + tmp0 = MULTIPLY(d1, FIX_0_275899380); + tmp1 = MULTIPLY(d1, FIX_0_785694958); + tmp2 = MULTIPLY(d1, FIX_1_175875602); + tmp3 = MULTIPLY(d1, FIX_1_387039845); + } else { + /* d1 == 0, d3 == 0, d5 == 0, d7 == 0 */ + tmp0 = tmp1 = tmp2 = tmp3 = 0; + } + } + } + } +} + /* Final output stage: inputs are tmp10..tmp13, tmp0..tmp3 */ + + dataptr[0] = (DCTELEM) DESCALE(tmp10 + tmp3, CONST_BITS-PASS1_BITS); + dataptr[7] = (DCTELEM) DESCALE(tmp10 - tmp3, CONST_BITS-PASS1_BITS); + dataptr[1] = (DCTELEM) DESCALE(tmp11 + tmp2, CONST_BITS-PASS1_BITS); + dataptr[6] = (DCTELEM) DESCALE(tmp11 - tmp2, CONST_BITS-PASS1_BITS); + dataptr[2] = (DCTELEM) DESCALE(tmp12 + tmp1, CONST_BITS-PASS1_BITS); + dataptr[5] = (DCTELEM) DESCALE(tmp12 - tmp1, CONST_BITS-PASS1_BITS); + dataptr[3] = (DCTELEM) DESCALE(tmp13 + tmp0, CONST_BITS-PASS1_BITS); + dataptr[4] = (DCTELEM) DESCALE(tmp13 - tmp0, CONST_BITS-PASS1_BITS); + + dataptr += DCTSIZE; /* advance pointer to next row */ + } + + /* Pass 2: process columns. */ + /* Note that we must descale the results by a factor of 8 == 2**3, */ + /* and also undo the PASS1_BITS scaling. */ + + dataptr = data; + for (rowctr = DCTSIZE-1; rowctr >= 0; rowctr--) { + /* Columns of zeroes can be exploited in the same way as we did with rows. + * However, the row calculation has created many nonzero AC terms, so the + * simplification applies less often (typically 5% to 10% of the time). + * On machines with very fast multiplication, it's possible that the + * test takes more time than it's worth. In that case this section + * may be commented out. + */ + + d0 = dataptr[DCTSIZE*0]; + d1 = dataptr[DCTSIZE*1]; + d2 = dataptr[DCTSIZE*2]; + d3 = dataptr[DCTSIZE*3]; + d4 = dataptr[DCTSIZE*4]; + d5 = dataptr[DCTSIZE*5]; + d6 = dataptr[DCTSIZE*6]; + d7 = dataptr[DCTSIZE*7]; + + /* Even part: reverse the even part of the forward DCT. */ + /* The rotator is sqrt(2)*c(-6). */ + if (d6) { + if (d4) { + if (d2) { + if (d0) { + /* d0 != 0, d2 != 0, d4 != 0, d6 != 0 */ + z1 = MULTIPLY(d2 + d6, FIX_0_541196100); + tmp2 = z1 + MULTIPLY(-d6, FIX_1_847759065); + tmp3 = z1 + MULTIPLY(d2, FIX_0_765366865); + + tmp0 = (d0 + d4) << CONST_BITS; + tmp1 = (d0 - d4) << CONST_BITS; + + tmp10 = tmp0 + tmp3; + tmp13 = tmp0 - tmp3; + tmp11 = tmp1 + tmp2; + tmp12 = tmp1 - tmp2; + } else { + /* d0 == 0, d2 != 0, d4 != 0, d6 != 0 */ + z1 = MULTIPLY(d2 + d6, FIX_0_541196100); + tmp2 = z1 + MULTIPLY(-d6, FIX_1_847759065); + tmp3 = z1 + MULTIPLY(d2, FIX_0_765366865); + + tmp0 = d4 << CONST_BITS; + + tmp10 = tmp0 + tmp3; + tmp13 = tmp0 - tmp3; + tmp11 = tmp2 - tmp0; + tmp12 = -(tmp0 + tmp2); + } + } else { + if (d0) { + /* d0 != 0, d2 == 0, d4 != 0, d6 != 0 */ + tmp2 = MULTIPLY(-d6, FIX_1_306562965); + tmp3 = MULTIPLY(d6, FIX_0_541196100); + + tmp0 = (d0 + d4) << CONST_BITS; + tmp1 = (d0 - d4) << CONST_BITS; + + tmp10 = tmp0 + tmp3; + tmp13 = tmp0 - tmp3; + tmp11 = tmp1 + tmp2; + tmp12 = tmp1 - tmp2; + } else { + /* d0 == 0, d2 == 0, d4 != 0, d6 != 0 */ + tmp2 = MULTIPLY(-d6, FIX_1_306562965); + tmp3 = MULTIPLY(d6, FIX_0_541196100); + + tmp0 = d4 << CONST_BITS; + + tmp10 = tmp0 + tmp3; + tmp13 = tmp0 - tmp3; + tmp11 = tmp2 - tmp0; + tmp12 = -(tmp0 + tmp2); + } + } + } else { + if (d2) { + if (d0) { + /* d0 != 0, d2 != 0, d4 == 0, d6 != 0 */ + z1 = MULTIPLY(d2 + d6, FIX_0_541196100); + tmp2 = z1 + MULTIPLY(-d6, FIX_1_847759065); + tmp3 = z1 + MULTIPLY(d2, FIX_0_765366865); + + tmp0 = d0 << CONST_BITS; + + tmp10 = tmp0 + tmp3; + tmp13 = tmp0 - tmp3; + tmp11 = tmp0 + tmp2; + tmp12 = tmp0 - tmp2; + } else { + /* d0 == 0, d2 != 0, d4 == 0, d6 != 0 */ + z1 = MULTIPLY(d2 + d6, FIX_0_541196100); + tmp2 = z1 + MULTIPLY(-d6, FIX_1_847759065); + tmp3 = z1 + MULTIPLY(d2, FIX_0_765366865); + + tmp10 = tmp3; + tmp13 = -tmp3; + tmp11 = tmp2; + tmp12 = -tmp2; + } + } else { + if (d0) { + /* d0 != 0, d2 == 0, d4 == 0, d6 != 0 */ + tmp2 = MULTIPLY(-d6, FIX_1_306562965); + tmp3 = MULTIPLY(d6, FIX_0_541196100); + + tmp0 = d0 << CONST_BITS; + + tmp10 = tmp0 + tmp3; + tmp13 = tmp0 - tmp3; + tmp11 = tmp0 + tmp2; + tmp12 = tmp0 - tmp2; + } else { + /* d0 == 0, d2 == 0, d4 == 0, d6 != 0 */ + tmp2 = MULTIPLY(-d6, FIX_1_306562965); + tmp3 = MULTIPLY(d6, FIX_0_541196100); + + tmp10 = tmp3; + tmp13 = -tmp3; + tmp11 = tmp2; + tmp12 = -tmp2; + } + } + } + } else { + if (d4) { + if (d2) { + if (d0) { + /* d0 != 0, d2 != 0, d4 != 0, d6 == 0 */ + tmp2 = MULTIPLY(d2, FIX_0_541196100); + tmp3 = MULTIPLY(d2, FIX_1_306562965); + + tmp0 = (d0 + d4) << CONST_BITS; + tmp1 = (d0 - d4) << CONST_BITS; + + tmp10 = tmp0 + tmp3; + tmp13 = tmp0 - tmp3; + tmp11 = tmp1 + tmp2; + tmp12 = tmp1 - tmp2; + } else { + /* d0 == 0, d2 != 0, d4 != 0, d6 == 0 */ + tmp2 = MULTIPLY(d2, FIX_0_541196100); + tmp3 = MULTIPLY(d2, FIX_1_306562965); + + tmp0 = d4 << CONST_BITS; + + tmp10 = tmp0 + tmp3; + tmp13 = tmp0 - tmp3; + tmp11 = tmp2 - tmp0; + tmp12 = -(tmp0 + tmp2); + } + } else { + if (d0) { + /* d0 != 0, d2 == 0, d4 != 0, d6 == 0 */ + tmp10 = tmp13 = (d0 + d4) << CONST_BITS; + tmp11 = tmp12 = (d0 - d4) << CONST_BITS; + } else { + /* d0 == 0, d2 == 0, d4 != 0, d6 == 0 */ + tmp10 = tmp13 = d4 << CONST_BITS; + tmp11 = tmp12 = -tmp10; + } + } + } else { + if (d2) { + if (d0) { + /* d0 != 0, d2 != 0, d4 == 0, d6 == 0 */ + tmp2 = MULTIPLY(d2, FIX_0_541196100); + tmp3 = MULTIPLY(d2, FIX_1_306562965); + + tmp0 = d0 << CONST_BITS; + + tmp10 = tmp0 + tmp3; + tmp13 = tmp0 - tmp3; + tmp11 = tmp0 + tmp2; + tmp12 = tmp0 - tmp2; + } else { + /* d0 == 0, d2 != 0, d4 == 0, d6 == 0 */ + tmp2 = MULTIPLY(d2, FIX_0_541196100); + tmp3 = MULTIPLY(d2, FIX_1_306562965); + + tmp10 = tmp3; + tmp13 = -tmp3; + tmp11 = tmp2; + tmp12 = -tmp2; + } + } else { + if (d0) { + /* d0 != 0, d2 == 0, d4 == 0, d6 == 0 */ + tmp10 = tmp13 = tmp11 = tmp12 = d0 << CONST_BITS; + } else { + /* d0 == 0, d2 == 0, d4 == 0, d6 == 0 */ + tmp10 = tmp13 = tmp11 = tmp12 = 0; + } + } + } + } + + /* Odd part per figure 8; the matrix is unitary and hence its + * transpose is its inverse. i0..i3 are y7,y5,y3,y1 respectively. + */ + if (d7) { + if (d5) { + if (d3) { + if (d1) { + /* d1 != 0, d3 != 0, d5 != 0, d7 != 0 */ + z1 = d7 + d1; + z2 = d5 + d3; + z3 = d7 + d3; + z4 = d5 + d1; + z5 = MULTIPLY(z3 + z4, FIX_1_175875602); + + tmp0 = MULTIPLY(d7, FIX_0_298631336); + tmp1 = MULTIPLY(d5, FIX_2_053119869); + tmp2 = MULTIPLY(d3, FIX_3_072711026); + tmp3 = MULTIPLY(d1, FIX_1_501321110); + z1 = MULTIPLY(-z1, FIX_0_899976223); + z2 = MULTIPLY(-z2, FIX_2_562915447); + z3 = MULTIPLY(-z3, FIX_1_961570560); + z4 = MULTIPLY(-z4, FIX_0_390180644); + + z3 += z5; + z4 += z5; + + tmp0 += z1 + z3; + tmp1 += z2 + z4; + tmp2 += z2 + z3; + tmp3 += z1 + z4; + } else { + /* d1 == 0, d3 != 0, d5 != 0, d7 != 0 */ + z1 = d7; + z2 = d5 + d3; + z3 = d7 + d3; + z5 = MULTIPLY(z3 + d5, FIX_1_175875602); + + tmp0 = MULTIPLY(d7, FIX_0_298631336); + tmp1 = MULTIPLY(d5, FIX_2_053119869); + tmp2 = MULTIPLY(d3, FIX_3_072711026); + z1 = MULTIPLY(-d7, FIX_0_899976223); + z2 = MULTIPLY(-z2, FIX_2_562915447); + z3 = MULTIPLY(-z3, FIX_1_961570560); + z4 = MULTIPLY(-d5, FIX_0_390180644); + + z3 += z5; + z4 += z5; + + tmp0 += z1 + z3; + tmp1 += z2 + z4; + tmp2 += z2 + z3; + tmp3 = z1 + z4; + } + } else { + if (d1) { + /* d1 != 0, d3 == 0, d5 != 0, d7 != 0 */ + z1 = d7 + d1; + z2 = d5; + z3 = d7; + z4 = d5 + d1; + z5 = MULTIPLY(z3 + z4, FIX_1_175875602); + + tmp0 = MULTIPLY(d7, FIX_0_298631336); + tmp1 = MULTIPLY(d5, FIX_2_053119869); + tmp3 = MULTIPLY(d1, FIX_1_501321110); + z1 = MULTIPLY(-z1, FIX_0_899976223); + z2 = MULTIPLY(-d5, FIX_2_562915447); + z3 = MULTIPLY(-d7, FIX_1_961570560); + z4 = MULTIPLY(-z4, FIX_0_390180644); + + z3 += z5; + z4 += z5; + + tmp0 += z1 + z3; + tmp1 += z2 + z4; + tmp2 = z2 + z3; + tmp3 += z1 + z4; + } else { + /* d1 == 0, d3 == 0, d5 != 0, d7 != 0 */ + tmp0 = MULTIPLY(-d7, FIX_0_601344887); + z1 = MULTIPLY(-d7, FIX_0_899976223); + z3 = MULTIPLY(-d7, FIX_1_961570560); + tmp1 = MULTIPLY(-d5, FIX_0_509795579); + z2 = MULTIPLY(-d5, FIX_2_562915447); + z4 = MULTIPLY(-d5, FIX_0_390180644); + z5 = MULTIPLY(d5 + d7, FIX_1_175875602); + + z3 += z5; + z4 += z5; + + tmp0 += z3; + tmp1 += z4; + tmp2 = z2 + z3; + tmp3 = z1 + z4; + } + } + } else { + if (d3) { + if (d1) { + /* d1 != 0, d3 != 0, d5 == 0, d7 != 0 */ + z1 = d7 + d1; + z3 = d7 + d3; + z5 = MULTIPLY(z3 + d1, FIX_1_175875602); + + tmp0 = MULTIPLY(d7, FIX_0_298631336); + tmp2 = MULTIPLY(d3, FIX_3_072711026); + tmp3 = MULTIPLY(d1, FIX_1_501321110); + z1 = MULTIPLY(-z1, FIX_0_899976223); + z2 = MULTIPLY(-d3, FIX_2_562915447); + z3 = MULTIPLY(-z3, FIX_1_961570560); + z4 = MULTIPLY(-d1, FIX_0_390180644); + + z3 += z5; + z4 += z5; + + tmp0 += z1 + z3; + tmp1 = z2 + z4; + tmp2 += z2 + z3; + tmp3 += z1 + z4; + } else { + /* d1 == 0, d3 != 0, d5 == 0, d7 != 0 */ + z3 = d7 + d3; + + tmp0 = MULTIPLY(-d7, FIX_0_601344887); + z1 = MULTIPLY(-d7, FIX_0_899976223); + tmp2 = MULTIPLY(d3, FIX_0_509795579); + z2 = MULTIPLY(-d3, FIX_2_562915447); + z5 = MULTIPLY(z3, FIX_1_175875602); + z3 = MULTIPLY(-z3, FIX_0_785694958); + + tmp0 += z3; + tmp1 = z2 + z5; + tmp2 += z3; + tmp3 = z1 + z5; + } + } else { + if (d1) { + /* d1 != 0, d3 == 0, d5 == 0, d7 != 0 */ + z1 = d7 + d1; + z5 = MULTIPLY(z1, FIX_1_175875602); + + z1 = MULTIPLY(z1, FIX_0_275899380); + z3 = MULTIPLY(-d7, FIX_1_961570560); + tmp0 = MULTIPLY(-d7, FIX_1_662939225); + z4 = MULTIPLY(-d1, FIX_0_390180644); + tmp3 = MULTIPLY(d1, FIX_1_111140466); + + tmp0 += z1; + tmp1 = z4 + z5; + tmp2 = z3 + z5; + tmp3 += z1; + } else { + /* d1 == 0, d3 == 0, d5 == 0, d7 != 0 */ + tmp0 = MULTIPLY(-d7, FIX_1_387039845); + tmp1 = MULTIPLY(d7, FIX_1_175875602); + tmp2 = MULTIPLY(-d7, FIX_0_785694958); + tmp3 = MULTIPLY(d7, FIX_0_275899380); + } + } + } + } else { + if (d5) { + if (d3) { + if (d1) { + /* d1 != 0, d3 != 0, d5 != 0, d7 == 0 */ + z2 = d5 + d3; + z4 = d5 + d1; + z5 = MULTIPLY(d3 + z4, FIX_1_175875602); + + tmp1 = MULTIPLY(d5, FIX_2_053119869); + tmp2 = MULTIPLY(d3, FIX_3_072711026); + tmp3 = MULTIPLY(d1, FIX_1_501321110); + z1 = MULTIPLY(-d1, FIX_0_899976223); + z2 = MULTIPLY(-z2, FIX_2_562915447); + z3 = MULTIPLY(-d3, FIX_1_961570560); + z4 = MULTIPLY(-z4, FIX_0_390180644); + + z3 += z5; + z4 += z5; + + tmp0 = z1 + z3; + tmp1 += z2 + z4; + tmp2 += z2 + z3; + tmp3 += z1 + z4; + } else { + /* d1 == 0, d3 != 0, d5 != 0, d7 == 0 */ + z2 = d5 + d3; + + z5 = MULTIPLY(z2, FIX_1_175875602); + tmp1 = MULTIPLY(d5, FIX_1_662939225); + z4 = MULTIPLY(-d5, FIX_0_390180644); + z2 = MULTIPLY(-z2, FIX_1_387039845); + tmp2 = MULTIPLY(d3, FIX_1_111140466); + z3 = MULTIPLY(-d3, FIX_1_961570560); + + tmp0 = z3 + z5; + tmp1 += z2; + tmp2 += z2; + tmp3 = z4 + z5; + } + } else { + if (d1) { + /* d1 != 0, d3 == 0, d5 != 0, d7 == 0 */ + z4 = d5 + d1; + + z5 = MULTIPLY(z4, FIX_1_175875602); + z1 = MULTIPLY(-d1, FIX_0_899976223); + tmp3 = MULTIPLY(d1, FIX_0_601344887); + tmp1 = MULTIPLY(-d5, FIX_0_509795579); + z2 = MULTIPLY(-d5, FIX_2_562915447); + z4 = MULTIPLY(z4, FIX_0_785694958); + + tmp0 = z1 + z5; + tmp1 += z4; + tmp2 = z2 + z5; + tmp3 += z4; + } else { + /* d1 == 0, d3 == 0, d5 != 0, d7 == 0 */ + tmp0 = MULTIPLY(d5, FIX_1_175875602); + tmp1 = MULTIPLY(d5, FIX_0_275899380); + tmp2 = MULTIPLY(-d5, FIX_1_387039845); + tmp3 = MULTIPLY(d5, FIX_0_785694958); + } + } + } else { + if (d3) { + if (d1) { + /* d1 != 0, d3 != 0, d5 == 0, d7 == 0 */ + z5 = d1 + d3; + tmp3 = MULTIPLY(d1, FIX_0_211164243); + tmp2 = MULTIPLY(-d3, FIX_1_451774981); + z1 = MULTIPLY(d1, FIX_1_061594337); + z2 = MULTIPLY(-d3, FIX_2_172734803); + z4 = MULTIPLY(z5, FIX_0_785694958); + z5 = MULTIPLY(z5, FIX_1_175875602); + + tmp0 = z1 - z4; + tmp1 = z2 + z4; + tmp2 += z5; + tmp3 += z5; + } else { + /* d1 == 0, d3 != 0, d5 == 0, d7 == 0 */ + tmp0 = MULTIPLY(-d3, FIX_0_785694958); + tmp1 = MULTIPLY(-d3, FIX_1_387039845); + tmp2 = MULTIPLY(-d3, FIX_0_275899380); + tmp3 = MULTIPLY(d3, FIX_1_175875602); + } + } else { + if (d1) { + /* d1 != 0, d3 == 0, d5 == 0, d7 == 0 */ + tmp0 = MULTIPLY(d1, FIX_0_275899380); + tmp1 = MULTIPLY(d1, FIX_0_785694958); + tmp2 = MULTIPLY(d1, FIX_1_175875602); + tmp3 = MULTIPLY(d1, FIX_1_387039845); + } else { + /* d1 == 0, d3 == 0, d5 == 0, d7 == 0 */ + tmp0 = tmp1 = tmp2 = tmp3 = 0; + } + } + } + } + + /* Final output stage: inputs are tmp10..tmp13, tmp0..tmp3 */ + + dataptr[DCTSIZE*0] = (DCTELEM) DESCALE(tmp10 + tmp3, + CONST_BITS+PASS1_BITS+3); + dataptr[DCTSIZE*7] = (DCTELEM) DESCALE(tmp10 - tmp3, + CONST_BITS+PASS1_BITS+3); + dataptr[DCTSIZE*1] = (DCTELEM) DESCALE(tmp11 + tmp2, + CONST_BITS+PASS1_BITS+3); + dataptr[DCTSIZE*6] = (DCTELEM) DESCALE(tmp11 - tmp2, + CONST_BITS+PASS1_BITS+3); + dataptr[DCTSIZE*2] = (DCTELEM) DESCALE(tmp12 + tmp1, + CONST_BITS+PASS1_BITS+3); + dataptr[DCTSIZE*5] = (DCTELEM) DESCALE(tmp12 - tmp1, + CONST_BITS+PASS1_BITS+3); + dataptr[DCTSIZE*3] = (DCTELEM) DESCALE(tmp13 + tmp0, + CONST_BITS+PASS1_BITS+3); + dataptr[DCTSIZE*4] = (DCTELEM) DESCALE(tmp13 - tmp0, + CONST_BITS+PASS1_BITS+3); + + dataptr++; /* advance pointer to next column */ + } +} + + +/* here is the reference one, in case of problems with the normal one */ + +/* idctref.c, Inverse Discrete Fourier Transform, double precision */ + +/* Copyright (C) 1994, MPEG Software Simulation Group. All Rights Reserved. */ + +/* + * Disclaimer of Warranty + * + * These software programs are available to the user without any license fee or + * royalty on an "as is" basis. The MPEG Software Simulation Group disclaims + * any and all warranties, whether express, implied, or statuary, including any + * implied warranties or merchantability or of fitness for a particular + * purpose. In no event shall the copyright-holder be liable for any + * incidental, punitive, or consequential damages of any kind whatsoever + * arising from the use of these programs. + * + * This disclaimer of warranty extends to the user of these programs and user's + * customers, employees, agents, transferees, successors, and assigns. + * + * The MPEG Software Simulation Group does not represent or warrant that the + * programs furnished hereunder are free of infringement of any third-party + * patents. + * + * Commercial implementations of MPEG-1 and MPEG-2 video, including shareware, + * are subject to royalty fees to patent holders. Many of these patents are + * general enough such that they are unavoidable regardless of implementation + * design. + * + */ + +/* Perform IEEE 1180 reference (64-bit floating point, separable 8x1 + * direct matrix multiply) Inverse Discrete Cosine Transform +*/ + + +/* Here we use math.h to generate constants. Compiler results may + vary a little */ + +#ifndef PI +#ifdef M_PI +#define PI M_PI +#else +#define PI 3.14159265358979323846 +#endif +#endif + +/* cosine transform matrix for 8x1 IDCT */ +static double itrans_coef[8][8]; + +/* initialize DCT coefficient matrix */ + +void init_idctref() +{ + int freq, time; + double scale; + + for (freq=0; freq < 8; freq++) + { + scale = (freq == 0) ? sqrt(0.125) : 0.5; + for (time=0; time<8; time++) + itrans_coef[freq][time] = scale*cos((PI/8.0)*freq*(time + 0.5)); + } +} + +/* perform IDCT matrix multiply for 8x8 coefficient block */ + +void reference_rev_dct(int16 *block) +{ + int i, j, k, v; + double partial_product; + double tmp[64]; + + for (i=0; i<8; i++) + for (j=0; j<8; j++) + { + partial_product = 0.0; + + for (k=0; k<8; k++) + partial_product+= itrans_coef[k][j]*block[8*i+k]; + + tmp[8*i+j] = partial_product; + } + + /* Transpose operation is integrated into address mapping by switching + loop order of i and j */ + + for (j=0; j<8; j++) + for (i=0; i<8; i++) + { + partial_product = 0.0; + + for (k=0; k<8; k++) + partial_product+= itrans_coef[k][i]*tmp[8*k+j]; + + v = floor(partial_product+0.5); + block[8*i+j] = (v<-256) ? -256 : ((v>255) ? 255 : v); + } +} diff --git a/contrib/mpeg_encode/libpnmrw.cpp b/contrib/mpeg_encode/libpnmrw.cpp new file mode 100644 index 0000000000000000000000000000000000000000..e8de080b4b6fcffddf0fc0435b13d6d923171b5f --- /dev/null +++ b/contrib/mpeg_encode/libpnmrw.cpp @@ -0,0 +1,1568 @@ +/* libpnmrw.c - PBM/PGM/PPM read/write library + ** + ** Copyright (C) 1988, 1989, 1991, 1992 by Jef Poskanzer. + ** + ** Permission to use, copy, modify, and distribute this software and its + ** documentation for any purpose and without fee is hereby granted, provided + ** that the above copyright notice appear in all copies and that both that + ** copyright notice and this permission notice appear in supporting + ** documentation. This software is provided "as is" without express or + ** implied warranty. + */ + +#define pm_error(x) throw x + + +#if defined(SVR2) || defined(SVR3) || defined(SVR4) +#define SYSV +#endif +#if ! ( defined(BSD) || defined(SYSV) || defined(MSDOS) ) +/* CONFIGURE: If your system is >= 4.2BSD, set the BSD option; if you're a + ** System V site, set the SYSV option; and if you're IBM-compatible, set +** MSDOS. If your compiler is ANSI C, you're probably better off setting +** SYSV - all it affects is string handling. +*/ +#define BSD +/* #define SYSV */ +/* #define MSDOS */ +#endif + +#include <stdio.h> +#include <stdlib.h> // gmsh +#include "libpnmrw.h" + +/* if don't have string.h, try strings.h */ +#include <string.h> +#define rindex(s,c) strrchr(s,c) + + +/* Definitions. */ + +#define pbm_allocarray( cols, rows ) ((bit**) pm_allocarray( cols, rows, sizeof(bit) )) +#define pbm_allocrow( cols ) ((bit*) pm_allocrow( cols, sizeof(bit) )) +#define pbm_freearray( bits, rows ) pm_freearray( (char**) bits, rows ) +#define pbm_freerow( bitrow ) pm_freerow( (char*) bitrow ) +#define pgm_allocarray( cols, rows ) ((gray**) pm_allocarray( cols, rows, sizeof(gray) )) +#define pgm_allocrow( cols ) ((gray*) pm_allocrow( cols, sizeof(gray) )) +#define pgm_freearray( grays, rows ) pm_freearray( (char**) grays, rows ) +#define pgm_freerow( grayrow ) pm_freerow( (char*) grayrow ) +#define ppm_allocarray( cols, rows ) ((pixel**) pm_allocarray( cols, rows, sizeof(pixel) )) +#define ppm_allocrow( cols ) ((pixel*) pm_allocrow( cols, sizeof(pixel) )) +#define ppm_freearray( pixels, rows ) pm_freearray( (char**) pixels, rows ) +#define ppm_freerow( pixelrow ) pm_freerow( (char*) pixelrow ) + + +/* Variables. */ + +static char* progname; + + +/* Variable-sized arrays. */ + +char* +pm_allocrow(int cols, + int size) +{ + register char* itrow; + + itrow = (char*) malloc( cols * size ); + if ( itrow == (char*) 0 ) + { + (void) fprintf( + stderr, "%s: out of memory allocating a row\n", progname ); + return (char*) 0; + } + return itrow; +} + +void +pm_freerow(char* itrow) +{ + free( itrow ); +} + +char** +pm_allocarray(int cols, int rows, + int size) +{ + char** its; + int i; + + its = (char**) malloc( rows * sizeof(char*) ); + if ( its == (char**) 0 ) + { + (void) fprintf( + stderr, "%s: out of memory allocating an array\n", progname ); + return (char**) 0; + } + its[0] = (char*) malloc( rows * cols * size ); + if ( its[0] == (char*) 0 ) + { + (void) fprintf( + stderr, "%s: out of memory allocating an array\n", progname ); + free( (char*) its ); + return (char**) 0; + } + for ( i = 1; i < rows; ++i ) + its[i] = &(its[0][i * cols * size]); + return its; +} + +void +pm_freearray(char** its, int rows) +{ + free( its[0] ); + free( its ); +} + + +/* File open/close that handles "-" as stdin and checks errors. */ + +static void +pm_perror(const char* reason) +{ + extern int errno; + const char* e; + + e = ""; + + if ( reason != 0 && reason[0] != '\0' ) + (void) fprintf( stderr, "%s: %s - %s\n", progname, reason, e ); + else + (void) fprintf( stderr, "%s: %s\n", progname, e ); +} + +FILE* +pm_openr(char* name) +{ + FILE* f; + + if ( strcmp( name, "-" ) == 0 ) + f = stdin; + else + { + f = fopen( name, "rb" ); + if ( f == NULL ) + { + pm_perror( name ); + return (FILE*) 0; + } + } + return f; +} + +FILE* +pm_openw(char* name) +{ + FILE* f; + + f = fopen( name, "wb" ); + if ( f == NULL ) { + pm_perror( name ); + return (FILE*) 0; + } + return f; +} + +int +pm_closer(FILE* f) +{ + if ( ferror( f ) ) + { + (void) fprintf( + stderr, "%s: a file read error occurred at some point\n", + progname ); + return -1; + } + if ( f != stdin ) + if ( fclose( f ) != 0 ) + { + pm_perror( (char*)"fclose" ); + return -1; + } + return 0; +} + +int +pm_closew(FILE* f) +{ + fflush( f ); + if ( ferror( f ) ) + { + (void) fprintf( + stderr, "%s: a file write error occurred at some point\n", + progname ); + return -1; + } + if ( f != stdout ) + if ( fclose( f ) != 0 ) + { + pm_perror( "fclose" ); + return -1; + } + return 0; +} + +static int +pbm_getc(FILE* file) +{ + register int ich; + + ich = getc( file ); + if ( ich == EOF ) + { + (void) fprintf( stderr, "%s: EOF / read error\n", progname ); + return EOF; + } + + if ( ich == '#' ) + { + do + { + ich = getc( file ); + if ( ich == EOF ) + { + (void) fprintf( stderr, "%s: EOF / read error\n", progname ); + return EOF; + } + } + while ( ich != '\n' && ich != '\r' ); + } + + return ich; +} + +static bit +pbm_getbit(FILE* file) +{ + register int ich; + + do + { + ich = pbm_getc( file ); + if ( ich == EOF ) + return -1; + } + while ( ich == ' ' || ich == '\t' || ich == '\n' || ich == '\r' ); + + if ( ich != '0' && ich != '1' ) + { + (void) fprintf( + stderr, "%s: junk in file where bits should be\n", progname ); + return -1; + } + + return ( ich == '1' ) ? 1 : 0; +} + +static int +pbm_readmagicnumber(FILE* file) +{ + int ich1, ich2; + + ich1 = getc( file ); + if ( ich1 == EOF ) + { + (void) fprintf( + stderr, "%s: EOF / read error reading magic number\n", progname ); + return -1; + } + ich2 = getc( file ); + if ( ich2 == EOF ) + { + (void) fprintf( + stderr, "%s: EOF / read error reading magic number\n", progname ); + return -1; + } + return ich1 * 256 + ich2; +} + +static int +pbm_getint(FILE* file) +{ + register int ich; + register int i; + + do + { + ich = pbm_getc( file ); + if ( ich == EOF ) + return -1; + } + while ( ich == ' ' || ich == '\t' || ich == '\n' || ich == '\r' ); + + if ( ich < '0' || ich > '9' ) + { + (void) fprintf( + stderr, "%s: junk in file where an integer should be\n", progname ); + return -1; + } + + i = 0; + do + { + i = i * 10 + ich - '0'; + ich = pbm_getc( file ); + if ( ich == EOF ) + return -1; + } + while ( ich >= '0' && ich <= '9' ); + + return i; +} + +static int +pbm_readpbminitrest(FILE* file, + int* colsP, + int* rowsP) +{ + /* Read size. */ + *colsP = pbm_getint( file ); + *rowsP = pbm_getint( file ); + if ( *colsP == -1 || *rowsP == -1 ) + return -1; + return 0; +} + +static int +pbm_getrawbyte(FILE* file) +{ + register int iby; + + iby = getc( file ); + if ( iby == EOF ) + { + (void) fprintf( stderr, "%s: EOF / read error\n", progname ); + return -1; + } + return iby; +} + +static int +pbm_readpbmrow(FILE* file, + bit* bitrow, + int cols, int format) +{ + register int col, bitshift, b; + register int item; + register bit* bP; + + switch ( format ) + { + case PBM_FORMAT: + for ( col = 0, bP = bitrow; col < cols; ++col, ++bP ) + { + b = pbm_getbit( file ); + if ( b == -1 ) + return -1; + *bP = b; + } + break; + + case RPBM_FORMAT: + bitshift = -1; + for ( col = 0, bP = bitrow; col < cols; ++col, ++bP ) + { + if ( bitshift == -1 ) + { + item = pbm_getrawbyte( file ); + if ( item == -1 ) + return -1; + bitshift = 7; + } + *bP = ( item >> bitshift ) & 1; + --bitshift; + } + break; + + default: + (void) fprintf( stderr, "%s: can't happen\n", progname ); + return -1; + } + return 0; +} + +static void +pbm_writepbminit(FILE* file, + int cols, int rows, + int forceplain) +{ + if ( ! forceplain ) + (void) fprintf( + file, "%c%c\n%d %d\n", PBM_MAGIC1, RPBM_MAGIC2, cols, rows ); + else + (void) fprintf( + file, "%c%c\n%d %d\n", PBM_MAGIC1, PBM_MAGIC2, cols, rows ); +} + +static void +pbm_writepbmrowraw(FILE* file, + bit* bitrow, + int cols) +{ + register int col, bitshift; + register unsigned char item; + register bit* bP; + + bitshift = 7; + item = 0; + for ( col = 0, bP = bitrow; col < cols; ++col, ++bP ) + { + if ( *bP ) + item += 1 << bitshift; + --bitshift; + if ( bitshift == -1 ) + { + (void) putc( item, file ); + bitshift = 7; + item = 0; + } + } + if ( bitshift != 7 ) + (void) putc( item, file ); +} + +static void +pbm_writepbmrowplain(FILE* file, + bit* bitrow, + int cols) +{ + register int col, charcount; + register bit* bP; + + charcount = 0; + for ( col = 0, bP = bitrow; col < cols; ++col, ++bP ) + { + if ( charcount >= 70 ) + { + (void) putc( '\n', file ); + charcount = 0; + } + putc( *bP ? '1' : '0', file ); + ++charcount; + } + (void) putc( '\n', file ); +} + +static void +pbm_writepbmrow(FILE* file, + bit* bitrow, + int cols, + int forceplain) +{ + if ( ! forceplain ) + pbm_writepbmrowraw( file, bitrow, cols ); + else + pbm_writepbmrowplain( file, bitrow, cols ); +} + +static int +pgm_readpgminitrest(FILE* file, + int* colsP, + int* rowsP, + gray* maxvalP) +{ + int maxval; + + /* Read size. */ + *colsP = pbm_getint( file ); + *rowsP = pbm_getint( file ); + if ( *colsP == -1 || *rowsP == -1 ) + return -1; + + /* Read maxval. */ + maxval = pbm_getint( file ); + if ( maxval == -1 ) + return -1; + if ( maxval > PGM_MAXMAXVAL ) + { + (void) fprintf( stderr, "%s: maxval is too large\n", progname ); + return -1; + } + *maxvalP = maxval; + return 0; +} + +static int +pgm_readpgmrow( FILE* file, gray* grayrow, int cols, gray maxval, int format ) +{ + register int col, val; + register gray* gP; + /* + bit* bitrow; + register bit* bP; + */ + + switch ( format ) + { + case PGM_FORMAT: + for ( col = 0, gP = grayrow; col < cols; ++col, ++gP ) + { + val = pbm_getint( file ); + if ( val == -1 ) + return -1; + *gP = val; + } + break; + + case RPGM_FORMAT: + if ( fread( grayrow, 1, cols, file ) != cols ) + { + (void) fprintf( stderr, "%s: EOF / read error\n", progname ); + return -1; + } + break; + + default: + (void) fprintf( stderr, "%s: can't happen\n", progname ); + return -1; + } + return 0; +} + +static void + pgm_writepgminit( FILE* file, int cols, int rows, gray maxval, int forceplain ) +{ + if ( maxval <= 255 && ! forceplain ) + fprintf( + file, "%c%c\n%d %d\n%d\n", PGM_MAGIC1, RPGM_MAGIC2, + cols, rows, maxval ); + else + fprintf( + file, "%c%c\n%d %d\n%d\n", PGM_MAGIC1, PGM_MAGIC2, + cols, rows, maxval ); +} + +static void +putus(unsigned short n, + FILE* file) +{ + if ( n >= 10 ) + putus( n / 10, file ); + putc( n % 10 + '0', file ); +} + +static int +pgm_writepgmrowraw(FILE* file, + gray* grayrow, + int cols, + gray maxval) +{ + if ( fwrite( grayrow, 1, cols, file ) != cols ) + { + (void) fprintf( stderr, "%s: write error\n", progname ); + return -1; + } + return 0; +} + +static int +pgm_writepgmrowplain(FILE* file, + gray* grayrow, + int cols, + gray maxval) +{ + register int col, charcount; + register gray* gP; + + charcount = 0; + for ( col = 0, gP = grayrow; col < cols; ++col, ++gP ) + { + if ( charcount >= 65 ) + { + (void) putc( '\n', file ); + charcount = 0; + } + else if ( charcount > 0 ) + { + (void) putc( ' ', file ); + ++charcount; + } + putus( (unsigned short) *gP, file ); + charcount += 3; + } + if ( charcount > 0 ) + (void) putc( '\n', file ); + return 0; +} + +static int + pgm_writepgmrow( FILE* file, gray* grayrow, int cols, gray maxval, int forceplain ) +{ + if ( maxval <= 255 && ! forceplain ) + return pgm_writepgmrowraw( file, grayrow, cols, maxval ); + else + return pgm_writepgmrowplain( file, grayrow, cols, maxval ); +} + +static int +ppm_readppminitrest(FILE* file, + int* colsP, + int* rowsP, + pixval* maxvalP) +{ + int maxval; + + /* Read size. */ + *colsP = pbm_getint( file ); + *rowsP = pbm_getint( file ); + if ( *colsP == -1 || *rowsP == -1 ) + return -1; + + /* Read maxval. */ + maxval = pbm_getint( file ); + if ( maxval == -1 ) + return -1; + if ( maxval > PPM_MAXMAXVAL ) + { + (void) fprintf( stderr, "%s: maxval is too large\n", progname ); + return -1; + } + *maxvalP = maxval; + return 0; +} + +static int + ppm_readppmrow( FILE* file, pixel* pixelrow, int cols, pixval maxval, int format ) +{ + register int col; + register pixel* pP; + register int r, g, b; + gray* grayrow; + register gray* gP; + /* + bit* bitrow; + register bit* bP; + */ + + switch ( format ) + { + case PPM_FORMAT: + for ( col = 0, pP = pixelrow; col < cols; ++col, ++pP ) + { + r = pbm_getint( file ); + g = pbm_getint( file ); + b = pbm_getint( file ); + if ( r == -1 || g == -1 || b == -1 ) + return -1; + PPM_ASSIGN( *pP, r, g, b ); + } + break; + + case RPPM_FORMAT: + grayrow = pgm_allocrow( 3 * cols ); + if ( grayrow == (gray*) 0 ) + return -1; + if ( fread( grayrow, 1, 3 * cols, file ) != 3 * cols ) + { + (void) fprintf( stderr, "%s: EOF / read error\n", progname ); + return -1; + } + for ( col = 0, gP = grayrow, pP = pixelrow; col < cols; ++col, ++pP ) + { + r = *gP++; + g = *gP++; + b = *gP++; + PPM_ASSIGN( *pP, r, g, b ); + } + pgm_freerow( grayrow ); + break; + + default: + (void) fprintf( stderr, "%s: can't happen\n", progname ); + return -1; + } + return 0; +} + +static void + ppm_writeppminit( FILE* file, int cols, int rows, pixval maxval, int forceplain ) +{ + if ( maxval <= 255 && ! forceplain ) + fprintf( + file, "%c%c\n%d %d\n%d\n", PPM_MAGIC1, RPPM_MAGIC2, + cols, rows, maxval ); + else + fprintf( + file, "%c%c\n%d %d\n%d\n", PPM_MAGIC1, PPM_MAGIC2, + cols, rows, maxval ); +} + +static int +ppm_writeppmrowraw(FILE* file, + pixel* pixelrow, + int cols, + pixval maxval) +{ + register int col; + register pixel* pP; + gray* grayrow; + register gray* gP; + + grayrow = pgm_allocrow( 3 * cols ); + if ( grayrow == (gray*) 0 ) + return -1; + for ( col = 0, pP = pixelrow, gP = grayrow; col < cols; ++col, ++pP ) + { + *gP++ = PPM_GETR( *pP ); + *gP++ = PPM_GETG( *pP ); + *gP++ = PPM_GETB( *pP ); + } + if ( fwrite( grayrow, 1, 3 * cols, file ) != 3 * cols ) + { + (void) fprintf( stderr, "%s: write error\n", progname ); + return -1; + } + pgm_freerow( grayrow ); + return 0; +} + +static int +ppm_writeppmrowplain(FILE* file, + pixel* pixelrow, + int cols, + pixval maxval) +{ + register int col, charcount; + register pixel* pP; + register pixval val; + + charcount = 0; + for ( col = 0, pP = pixelrow; col < cols; ++col, ++pP ) + { + if ( charcount >= 65 ) + { + (void) putc( '\n', file ); + charcount = 0; + } + else if ( charcount > 0 ) + { + (void) putc( ' ', file ); + (void) putc( ' ', file ); + charcount += 2; + } + val = PPM_GETR( *pP ); + putus( val, file ); + (void) putc( ' ', file ); + val = PPM_GETG( *pP ); + putus( val, file ); + (void) putc( ' ', file ); + val = PPM_GETB( *pP ); + putus( val, file ); + charcount += 11; + } + if ( charcount > 0 ) + (void) putc( '\n', file ); + return 0; +} + +static int + ppm_writeppmrow( FILE* file, pixel* pixelrow, int cols, pixval maxval, int forceplain ) +{ + if ( maxval <= 255 && ! forceplain ) + return ppm_writeppmrowraw( file, pixelrow, cols, maxval ); + else + return ppm_writeppmrowplain( file, pixelrow, cols, maxval ); +} + +void +pnm_init2(char* pn) +{ + /* Save program name. */ + progname = pn; +} + +xelval pnm_pbmmaxval = 1; + +int +pnm_readpnminit(FILE* file, + int* colsP, + int* rowsP, + xelval* maxvalP, + int* formatP) +{ + gray gmaxval; + + /* Check magic number. */ + *formatP = pbm_readmagicnumber( file ); + if ( *formatP == -1 ) + return -1; + switch ( PNM_FORMAT_TYPE(*formatP) ) + { + case PPM_TYPE: + if ( ppm_readppminitrest( file, colsP, rowsP, (pixval*) maxvalP ) < 0 ) + return -1; + break; + + case PGM_TYPE: + if ( pgm_readpgminitrest( file, colsP, rowsP, &gmaxval ) < 0 ) + return -1; + *maxvalP = (xelval) gmaxval; + break; + + case PBM_TYPE: + if ( pbm_readpbminitrest( file, colsP, rowsP ) < 0 ) + return -1; + *maxvalP = pnm_pbmmaxval; + break; + + default: + (void) fprintf( + stderr, "%s: bad magic number - not a ppm, pgm, or pbm file\n", + progname ); + return -1; + } + return 0; +} + +int + pnm_readpnmrow( FILE* file, xel* xelrow, int cols, xelval maxval, int format ) +{ + register int col; + register xel* xP; + gray* grayrow; + register gray* gP; + bit* bitrow; + register bit* bP; + + switch ( PNM_FORMAT_TYPE(format) ) + { + case PPM_TYPE: + if ( ppm_readppmrow( file, (pixel*) xelrow, cols, (pixval) maxval, format ) < 0 ) + return -1; + break; + + case PGM_TYPE: + grayrow = pgm_allocrow( cols ); + if ( grayrow == (gray*) 0 ) + return -1; + if ( pgm_readpgmrow( file, grayrow, cols, (gray) maxval, format ) < 0 ) + return -1; + for ( col = 0, xP = xelrow, gP = grayrow; col < cols; ++col, ++xP, ++gP ) + PNM_ASSIGN1( *xP, *gP ); + pgm_freerow( grayrow ); + break; + + case PBM_TYPE: + bitrow = pbm_allocrow( cols ); + if ( bitrow == (bit*) 0 ) + return -1; + if ( pbm_readpbmrow( file, bitrow, cols, format ) < 0 ) + { + pbm_freerow( bitrow ); + return -1; + } + for ( col = 0, xP = xelrow, bP = bitrow; col < cols; ++col, ++xP, ++bP ) + PNM_ASSIGN1( *xP, *bP == PBM_BLACK ? 0: pnm_pbmmaxval ); + pbm_freerow( bitrow ); + break; + + default: + (void) fprintf( stderr, "%s: can't happen\n", progname ); + return -1; + } + return 0; +} + +xel** +pnm_readpnm(FILE* file, + int* colsP, + int* rowsP, + xelval* maxvalP, + int* formatP) +{ + xel** xels; + int row; + + if ( pnm_readpnminit( file, colsP, rowsP, maxvalP, formatP ) < 0 ) + return (xel**) 0; + + xels = pnm_allocarray( *colsP, *rowsP ); + if ( xels == (xel**) 0 ) + return (xel**) 0; + + for ( row = 0; row < *rowsP; ++row ) + if ( pnm_readpnmrow( file, xels[row], *colsP, *maxvalP, *formatP ) < 0 ) + { + pnm_freearray( xels, *rowsP ); + return (xel**) 0; + } + + return xels; +} + +int + pnm_writepnminit( FILE* file, int cols, int rows, xelval maxval, int format, int forceplain ) +{ + switch ( PNM_FORMAT_TYPE(format) ) + { + case PPM_TYPE: + ppm_writeppminit( file, cols, rows, (pixval) maxval, forceplain ); + break; + + case PGM_TYPE: + pgm_writepgminit( file, cols, rows, (gray) maxval, forceplain ); + break; + + case PBM_TYPE: + pbm_writepbminit( file, cols, rows, forceplain ); + break; + + default: + (void) fprintf( stderr, "%s: can't happen\n", progname ); + return -1; + } + return 0; +} + +int + pnm_writepnmrow( FILE* file, xel* xelrow, int cols, xelval maxval, int format, int forceplain ) +{ + register int col; + register xel* xP; + gray* grayrow; + register gray* gP; + bit* bitrow; + register bit* bP; + + switch ( PNM_FORMAT_TYPE(format) ) + { + case PPM_TYPE: + if ( ppm_writeppmrow( file, (pixel*) xelrow, cols, (pixval) maxval, forceplain ) < 0 ) + return -1; + break; + + case PGM_TYPE: + grayrow = pgm_allocrow( cols ); + if ( grayrow == (gray*) 0 ) + return -1; + for ( col = 0, gP = grayrow, xP = xelrow; col < cols; ++col, ++gP, ++xP ) + *gP = PNM_GET1( *xP ); + if ( pgm_writepgmrow( file, grayrow, cols, (gray) maxval, forceplain ) < 0 ) + { + pgm_freerow( grayrow ); + return -1; + } + pgm_freerow( grayrow ); + break; + + case PBM_TYPE: + bitrow = pbm_allocrow( cols ); + if ( bitrow == (bit*) 0 ) + return -1; + for ( col = 0, bP = bitrow, xP = xelrow; col < cols; ++col, ++bP, ++xP ) + *bP = PNM_GET1( *xP ) == 0 ? PBM_BLACK : PBM_WHITE; + pbm_writepbmrow( file, bitrow, cols, forceplain ); + pbm_freerow( bitrow ); + break; + + default: + (void) fprintf( stderr, "%s: can't happen\n", progname ); + return -1; + } + return 0; +} + +int + pnm_writepnm( FILE* file, xel** xels, int cols, int rows, xelval maxval, int format, int forceplain ) +{ + int row; + + if ( pnm_writepnminit( file, cols, rows, maxval, format, forceplain ) < 0 ) + return -1; + + for ( row = 0; row < rows; ++row ) + if ( pnm_writepnmrow( file, xels[row], cols, maxval, format, forceplain ) < 0 ) + return -1; + return 0; +} + + +/* Colormap stuff. */ + +#define HASH_SIZE 20023 + +#define ppm_hashpixel(p) ( ( ( (long) PPM_GETR(p) * 33023 + (long) PPM_GETG(p) * 30013 + (long) PPM_GETB(p) * 27011 ) & 0x7fffffff ) % HASH_SIZE ) + +colorhist_vector +ppm_computecolorhist(pixel** pixels, + int cols, int rows, int maxcolors, + int* colorsP) +{ + colorhash_table cht; + colorhist_vector chv; + + cht = ppm_computecolorhash( pixels, cols, rows, maxcolors, colorsP ); + if ( cht == (colorhash_table) 0 ) + return (colorhist_vector) 0; + chv = ppm_colorhashtocolorhist( cht, maxcolors ); + ppm_freecolorhash( cht ); + return chv; +} + +void +ppm_addtocolorhist(colorhist_vector chv, + pixel* colorP, + int* colorsP, + int maxcolors, int value, int position) +{ + int i, j; + + /* Search colorhist for the color. */ + for ( i = 0; i < *colorsP; ++i ) + if ( PPM_EQUAL( chv[i].color, *colorP ) ) + { + /* Found it - move to new slot. */ + if ( position > i ) + { + for ( j = i; j < position; ++j ) + chv[j] = chv[j + 1]; + } + else if ( position < i ) + { + for ( j = i; j > position; --j ) + chv[j] = chv[j - 1]; + } + chv[position].color = *colorP; + chv[position].value = value; + return; + } + if ( *colorsP < maxcolors ) + { + /* Didn't find it, but there's room to add it; so do so. */ + for ( i = *colorsP; i > position; --i ) + chv[i] = chv[i - 1]; + chv[position].color = *colorP; + chv[position].value = value; + ++(*colorsP); + } +} + +colorhash_table +ppm_computecolorhash(pixel** pixels, + int cols, int rows, int maxcolors, + int* colorsP) +{ + colorhash_table cht; + register pixel* pP; + colorhist_list chl; + int col, row, hash; + + cht = ppm_alloccolorhash( ); + if ( cht == (colorhash_table) 0 ) + return (colorhash_table) 0; + *colorsP = 0; + + /* Go through the entire image, building a hash table of colors. */ + for ( row = 0; row < rows; ++row ) + for ( col = 0, pP = pixels[row]; col < cols; ++col, ++pP ) + { + hash = ppm_hashpixel( *pP ); + for ( chl = cht[hash]; chl != (colorhist_list) 0; chl = chl->next ) + if ( PPM_EQUAL( chl->ch.color, *pP ) ) + break; + if ( chl != (colorhist_list) 0 ) + ++(chl->ch.value); + else + { + if ( ++(*colorsP) > maxcolors ) + { + ppm_freecolorhash( cht ); + return (colorhash_table) 0; + } + chl = (colorhist_list) malloc( sizeof(struct colorhist_list_item) ); + if ( chl == 0 ) + { + (void) fprintf( + stderr, "%s: out of memory computing hash table\n", + progname ); + ppm_freecolorhash( cht ); + return (colorhash_table) 0; + } + chl->ch.color = *pP; + chl->ch.value = 1; + chl->next = cht[hash]; + cht[hash] = chl; + } + } + + return cht; +} + +colorhash_table + ppm_alloccolorhash( ) +{ + colorhash_table cht; + int i; + + cht = (colorhash_table) malloc( HASH_SIZE * sizeof(colorhist_list) ); + if ( cht == 0 ) + { + (void) fprintf( + stderr, "%s: out of memory allocating hash table\n", progname ); + return (colorhash_table) 0; + } + + for ( i = 0; i < HASH_SIZE; ++i ) + cht[i] = (colorhist_list) 0; + + return cht; +} + +int +ppm_addtocolorhash(colorhash_table cht, + pixel* colorP, + int value) +{ + register int hash; + register colorhist_list chl; + + chl = (colorhist_list) malloc( sizeof(struct colorhist_list_item) ); + if ( chl == 0 ) + return -1; + hash = ppm_hashpixel( *colorP ); + chl->ch.color = *colorP; + chl->ch.value = value; + chl->next = cht[hash]; + cht[hash] = chl; + return 0; +} + +colorhist_vector +ppm_colorhashtocolorhist(colorhash_table cht, + int maxcolors) +{ + colorhist_vector chv; + colorhist_list chl; + int i, j; + + /* Now collate the hash table into a simple colorhist array. */ + chv = (colorhist_vector) malloc( maxcolors * sizeof(struct colorhist_item) ); + /* (Leave room for expansion by caller.) */ + if ( chv == (colorhist_vector) 0 ) + { + (void) fprintf( + stderr, "%s: out of memory generating histogram\n", progname ); + return (colorhist_vector) 0; + } + + /* Loop through the hash table. */ + j = 0; + for ( i = 0; i < HASH_SIZE; ++i ) + for ( chl = cht[i]; chl != (colorhist_list) 0; chl = chl->next ) + { + /* Add the new entry. */ + chv[j] = chl->ch; + ++j; + } + + /* All done. */ + return chv; +} + +colorhash_table +ppm_colorhisttocolorhash(colorhist_vector chv, + int colors) +{ + colorhash_table cht; + int i, hash; + pixel color; + colorhist_list chl; + + cht = ppm_alloccolorhash( ); + if ( cht == (colorhash_table) 0 ) + return (colorhash_table) 0; + + for ( i = 0; i < colors; ++i ) + { + color = chv[i].color; + hash = ppm_hashpixel( color ); + for ( chl = cht[hash]; chl != (colorhist_list) 0; chl = chl->next ) + if ( PPM_EQUAL( chl->ch.color, color ) ) + { + (void) fprintf( + stderr, "%s: same color found twice - %d %d %d\n", progname, + PPM_GETR(color), PPM_GETG(color), PPM_GETB(color) ); + ppm_freecolorhash( cht ); + return (colorhash_table) 0; + } + chl = (colorhist_list) malloc( sizeof(struct colorhist_list_item) ); + if ( chl == (colorhist_list) 0 ) + { + (void) fprintf( stderr, "%s: out of memory\n", progname ); + ppm_freecolorhash( cht ); + return (colorhash_table) 0; + } + chl->ch.color = color; + chl->ch.value = i; + chl->next = cht[hash]; + cht[hash] = chl; + } + + return cht; +} + +int +ppm_lookupcolor(colorhash_table cht, + pixel* colorP) +{ + int hash; + colorhist_list chl; + + hash = ppm_hashpixel( *colorP ); + for ( chl = cht[hash]; chl != (colorhist_list) 0; chl = chl->next ) + if ( PPM_EQUAL( chl->ch.color, *colorP ) ) + return chl->ch.value; + + return -1; +} + +void +ppm_freecolorhist(colorhist_vector chv) +{ + free( (char*) chv ); +} + +void +ppm_freecolorhash(colorhash_table cht) +{ + int i; + colorhist_list chl, chlnext; + + for ( i = 0; i < HASH_SIZE; ++i ) + for ( chl = cht[i]; chl != (colorhist_list) 0; chl = chlnext ) + { + chlnext = chl->next; + free( (char*) chl ); + } + free( (char*) cht ); +} + + + + +/* added from libpnm3.c: */ + +/* libpnm3.c - pnm utility library part 3 + ** + ** Copyright (C) 1989, 1991 by Jef Poskanzer. + ** + ** Permission to use, copy, modify, and distribute this software and its + ** documentation for any purpose and without fee is hereby granted, provided + ** that the above copyright notice appear in all copies and that both that + ** copyright notice and this permission notice appear in supporting + ** documentation. This software is provided "as is" without express or + ** implied warranty. + */ + +xel + pnm_backgroundxel( xel** xels, int cols, int rows, xelval maxval, int format ) +{ + xel bgxel, ul, ur, ll, lr; + + /* Guess a good background value. */ + ul = xels[0][0]; + ur = xels[0][cols-1]; + ll = xels[rows-1][0]; + lr = xels[rows-1][cols-1]; + + /* First check for three corners equal. */ + if ( PNM_EQUAL( ul, ur ) && PNM_EQUAL( ur, ll ) ) + bgxel = ul; + else if ( PNM_EQUAL( ul, ur ) && PNM_EQUAL( ur, lr ) ) + bgxel = ul; + else if ( PNM_EQUAL( ul, ll ) && PNM_EQUAL( ll, lr ) ) + bgxel = ul; + else if ( PNM_EQUAL( ur, ll ) && PNM_EQUAL( ll, lr ) ) + bgxel = ur; + /* Nope, check for two corners equal. */ + else if ( PNM_EQUAL( ul, ur ) || PNM_EQUAL( ul, ll ) || + PNM_EQUAL( ul, lr ) ) + bgxel = ul; + else if ( PNM_EQUAL( ur, ll ) || PNM_EQUAL( ur, lr ) ) + bgxel = ur; + else if ( PNM_EQUAL( ll, lr ) ) + bgxel = ll; + else + { + /* Nope, we have to average the four corners. This breaks the + ** rules of pnm, but oh well. Let's try to do it portably. */ + switch ( PNM_FORMAT_TYPE(format) ) + { + case PPM_TYPE: + PPM_ASSIGN( bgxel, + PPM_GETR(ul) + PPM_GETR(ur) + PPM_GETR(ll) + PPM_GETR(lr) / 4, + PPM_GETG(ul) + PPM_GETG(ur) + PPM_GETG(ll) + PPM_GETG(lr) / 4, + PPM_GETB(ul) + PPM_GETB(ur) + PPM_GETB(ll) + PPM_GETB(lr) / 4 ); + break; + + case PGM_TYPE: + { + gray gul, gur, gll, glr; + gul = (gray) PNM_GET1( ul ); + gur = (gray) PNM_GET1( ur ); + gll = (gray) PNM_GET1( ll ); + glr = (gray) PNM_GET1( lr ); + PNM_ASSIGN1( bgxel, ( ( gul + gur + gll + glr ) / 4 ) ); + break; + } + + case PBM_TYPE: + pm_error( + "pnm_backgroundxel: four bits no two of which equal each other??" ); + + default: + pm_error( "can't happen" ); + } + } + + return bgxel; +} + +xel + pnm_backgroundxelrow( xel* xelrow, int cols, xelval maxval, int format ) +{ + xel bgxel, l, r; + + /* Guess a good background value. */ + l = xelrow[0]; + r = xelrow[cols-1]; + + /* First check for both corners equal. */ + if ( PNM_EQUAL( l, r ) ) + bgxel = l; + else + { + /* Nope, we have to average the two corners. This breaks the + ** rules of pnm, but oh well. Let's try to do it portably. */ + switch ( PNM_FORMAT_TYPE(format) ) + { + case PPM_TYPE: + PPM_ASSIGN( bgxel, PPM_GETR(l) + PPM_GETR(r) / 2, + PPM_GETG(l) + PPM_GETG(r) / 2, PPM_GETB(l) + PPM_GETB(r) / 2 ); + break; + + case PGM_TYPE: + { + gray gl, gr; + gl = (gray) PNM_GET1( l ); + gr = (gray) PNM_GET1( r ); + PNM_ASSIGN1( bgxel, ( ( gl + gr ) / 2 ) ); + break; + } + + case PBM_TYPE: + { + int col, blacks; + + /* One black, one white. Gotta count. */ + for ( col = 0, blacks = 0; col < cols; ++col ) + { + if ( PNM_GET1( xelrow[col] ) == 0 ) + ++blacks; + } + if ( blacks >= cols / 2 ) + PNM_ASSIGN1( bgxel, 0 ); + else + PNM_ASSIGN1( bgxel, pnm_pbmmaxval ); + break; + } + + default: + pm_error( "can't happen" ); + } + } + + return bgxel; +} + +xel + pnm_whitexel( xelval maxval, int format ) +{ + xel x; + + switch ( PNM_FORMAT_TYPE(format) ) + { + case PPM_TYPE: + PPM_ASSIGN( x, maxval, maxval, maxval ); + break; + + case PGM_TYPE: + PNM_ASSIGN1( x, maxval ); + break; + + case PBM_TYPE: + PNM_ASSIGN1( x, pnm_pbmmaxval ); + break; + + default: + pm_error( "can't happen" ); + } + + return x; +} + +xel + pnm_blackxel( xelval maxval, int format ) +{ + xel x; + + switch ( PNM_FORMAT_TYPE(format) ) + { + case PPM_TYPE: + PPM_ASSIGN( x, 0, 0, 0 ); + break; + + case PGM_TYPE: + PNM_ASSIGN1( x, (xelval) 0 ); + break; + + case PBM_TYPE: + PNM_ASSIGN1( x, (xelval) 0 ); + break; + + default: + pm_error( "can't happen" ); + } + + return x; +} + +void + pnm_invertxel( xel* xP, xelval maxval, int format ) +{ + switch ( PNM_FORMAT_TYPE(format) ) + { + case PPM_TYPE: + PPM_ASSIGN( + *xP, maxval - PPM_GETR( *xP ), + maxval - PPM_GETG( *xP ), maxval - PPM_GETB( *xP ) ); + break; + + case PGM_TYPE: + PNM_ASSIGN1( *xP, (gray) maxval - (gray) PNM_GET1( *xP ) ); + break; + + case PBM_TYPE: + PNM_ASSIGN1( *xP, ( PNM_GET1( *xP ) == 0 ) ? pnm_pbmmaxval : 0 ); + break; + + default: + pm_error( "can't happen" ); + } +} + +void + pnm_promoteformat( xel** xels, int cols, int rows, xelval maxval, int format, xelval newmaxval, int newformat ) +{ + int row; + + for ( row = 0; row < rows; ++row ) + pnm_promoteformatrow( + xels[row], cols, maxval, format, newmaxval, newformat ); +} + +void + pnm_promoteformatrow( xel* xelrow, int cols, xelval maxval, int format, xelval newmaxval, int newformat ) +{ + register int col; + register xel* xP; + + if ( ( PNM_FORMAT_TYPE(format) == PPM_TYPE && + ( PNM_FORMAT_TYPE(newformat) == PGM_TYPE || + PNM_FORMAT_TYPE(newformat) == PBM_TYPE ) ) || + ( PNM_FORMAT_TYPE(format) == PGM_TYPE && + PNM_FORMAT_TYPE(newformat) == PBM_TYPE ) ) + pm_error( "pnm_promoteformatrow: can't promote downwards!" ); + + /* Are we promoting to the same type? */ + if ( PNM_FORMAT_TYPE(format) == PNM_FORMAT_TYPE(newformat) ) + { + if ( PNM_FORMAT_TYPE(format) == PBM_TYPE ) + return; + if ( newmaxval < maxval ) + pm_error( + "pnm_promoteformatrow: can't decrease maxval - try using pnmdepth" ); + if ( newmaxval == maxval ) + return; + /* Increase maxval. */ + switch ( PNM_FORMAT_TYPE(format) ) + { + case PGM_TYPE: + for ( col = 0, xP = xelrow; col < cols; ++col, ++xP ) + PNM_ASSIGN1( + *xP, (int) PNM_GET1(*xP) * newmaxval / maxval ); + break; + + case PPM_TYPE: + for ( col = 0, xP = xelrow; col < cols; ++col, ++xP ) + PPM_DEPTH( *xP, *xP, maxval, newmaxval ); + break; + + default: + pm_error( "shouldn't happen" ); + } + return; + } + + /* We must be promoting to a higher type. */ + switch ( PNM_FORMAT_TYPE(format) ) + { + case PBM_TYPE: + switch ( PNM_FORMAT_TYPE(newformat) ) + { + case PGM_TYPE: + for ( col = 0, xP = xelrow; col < cols; ++col, ++xP ) + if ( PNM_GET1(*xP) == 0 ) + PNM_ASSIGN1( *xP, 0 ); + else + PNM_ASSIGN1( *xP, newmaxval ); + break; + + case PPM_TYPE: + for ( col = 0, xP = xelrow; col < cols; ++col, ++xP ) + if ( PNM_GET1(*xP) == 0 ) + PPM_ASSIGN( *xP, 0, 0, 0 ); + else + PPM_ASSIGN( *xP, newmaxval, newmaxval, newmaxval ); + break; + + default: + pm_error( "can't happen" ); + } + break; + + case PGM_TYPE: + switch ( PNM_FORMAT_TYPE(newformat) ) + { + case PPM_TYPE: + if ( newmaxval < maxval ) + pm_error( + "pnm_promoteformatrow: can't decrease maxval - try using pnmdepth" ); + if ( newmaxval == maxval ) + { + for ( col = 0, xP = xelrow; col < cols; ++col, ++xP ) + PPM_ASSIGN( + *xP, PNM_GET1(*xP), PNM_GET1(*xP), PNM_GET1(*xP) ); + } + else + { /* Increase maxval. */ + for ( col = 0, xP = xelrow; col < cols; ++col, ++xP ) + PPM_ASSIGN( + *xP, (int) PNM_GET1(*xP) * newmaxval / maxval, + (int) PNM_GET1(*xP) * newmaxval / maxval, + (int) PNM_GET1(*xP) * newmaxval / maxval ); + } + break; + + default: + pm_error( "can't happen" ); + } + break; + + default: + pm_error( "can't happen" ); + } +} + + diff --git a/contrib/mpeg_encode/main.cpp b/contrib/mpeg_encode/main.cpp new file mode 100644 index 0000000000000000000000000000000000000000..3bfe275192ad7a942fed89c28f75ac1f77d94404 --- /dev/null +++ b/contrib/mpeg_encode/main.cpp @@ -0,0 +1,579 @@ +/*===========================================================================* + * main.c * + * * + * Main procedure * + * * + * EXPORTED PROCEDURES: * + * main * + * * + *===========================================================================*/ + +/* + * Copyright (c) 1995 The Regents of the University of California. + * All rights reserved. + * + * Permission to use, copy, modify, and distribute this software and its + * documentation for any purpose, without fee, and without written agreement is + * hereby granted, provided that the above copyright notice and the following + * two paragraphs appear in all copies of this software. + * + * IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR + * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT + * OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF + * CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS + * ON AN "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO + * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. + */ + +/* + * $Header: /n/picasso/project/mpeg/mpeg_dist/mpeg_encode/RCS/main.c,v 1.25 1995/08/07 21:44:21 smoot Exp $ + * $Log: main.c,v $ + * Revision 1.25 1995/08/07 21:44:21 smoot + * renamed index -> idx; save the encoder's name; compute frame types ahead of time + * + * Revision 1.24 1995/06/21 18:25:57 smoot + * added binary write flag (DOS!) + * + * Revision 1.23 1995/05/16 06:25:28 smoot + * added TUNEing init and float-dct == float_dct + * + * Revision 1.22 1995/05/16 00:15:05 smoot + * fixed usage print + * + * Revision 1.21 1995/05/11 23:59:56 smoot + * *** empty log message *** + * + * Revision 1.20 1995/02/02 20:05:37 eyhung + * fixed smoot typo in 1.19 + * + * Revision 1.19 1995/02/02 18:56:11 smoot + * ANSI-ified some prototypes + * + * Revision 1.18 1995/02/01 21:47:37 smoot + * cleanup + * + * Revision 1.17 1995/01/31 22:22:49 eyhung + * Fixed steve's typo and added float_dct to Usage() + * + * Revision 1.16 1995/01/31 21:44:08 smoot + * Added -float_dct option + * + * Revision 1.15 1995/01/31 01:19:39 eyhung + * removed -interactive + * + * Revision 1.14 1995/01/27 21:56:57 eyhung + * Deleted setting JMOVIE_TYPE to JPEG_TYPE since we need to know + * if we started with a JMOVIE for getting input files + * + * Revision 1.13 1995/01/19 23:50:06 eyhung + * Removed printing of output file to screen - done at end of encoding now. + * + * Revision 1.12 1995/01/19 23:08:41 eyhung + * Changed copyrights + * + * Revision 1.11 1995/01/17 08:25:44 eyhung + * added -interactive to Usage + * + * Revision 1.10 1995/01/17 08:24:53 eyhung + * Added -interactive option + * + * Revision 1.9 1995/01/16 08:04:10 eyhung + * More realQuiet stuff. + * + * Revision 1.8 1995/01/16 07:38:49 eyhung + * Added realquiet option + * + * Revision 1.7 1994/11/14 22:32:01 smoot + * Merged specifics and rate control + * + * Revision 1.6 1994/11/12 02:11:52 keving + * nothing + * + * Revision 1.5 1994/03/15 00:27:11 keving + * nothing + * + * Revision 1.4 1993/12/22 19:19:01 keving + * nothing + * + * Revision 1.3 1993/07/22 22:23:43 keving + * nothing + * + * Revision 1.2 1993/06/30 20:06:09 keving + * nothing + * + * Revision 1.1 1993/02/17 23:18:20 dwallach + * Initial revision + * + */ + + +/*==============* + * HEADER FILES * + *==============*/ + +#include <assert.h> +#include "all.h" +#include "mtypes.h" +#include "mpeg.h" +#include "search.h" +#include "prototypes.h" +#include "param.h" +#include "parallel.h" +#include "readframe.h" +#include "combine.h" +#include "frames.h" +#include "jpeg.h" +#include "specifics.h" +#include "opts.h" +#include <time.h> + +int main _ANSI_ARGS_((int argc, char **argv)); + +/*==================* + * STATIC VARIABLES * + *==================*/ + +static int frameStart = -1; +static int frameEnd; + + +/*==================* + * GLOBAL VARIABLES * + *==================*/ + +extern time_t IOtime; +int whichGOP = -1; +boolean childProcess = FALSE; +boolean ioServer = FALSE; +boolean outputServer = FALSE; +boolean decodeServer = FALSE; +int quietTime = 0; +boolean realQuiet = FALSE; +boolean frameSummary = TRUE; +boolean debugSockets = FALSE; +boolean debugMachines = FALSE; +boolean showBitRatePerFrame = FALSE; +boolean computeMVHist = FALSE; +int baseFormat; +extern boolean specificsOn; +extern FrameSpecList *fsl; +boolean pureDCT=FALSE; +char encoder_name[1024]; + +/*===============================* + * INTERNAL PROCEDURE prototypes * + *===============================*/ + +static void Usage _ANSI_ARGS_((void)); +static void CompileTests _ANSI_ARGS_((void)); + + +/*================================* + * External PROCEDURE prototypes * + *================================*/ + +void init_idctref _ANSI_ARGS_((void)); +void init_fdct _ANSI_ARGS_((void)); + +/*=====================* + * EXPORTED PROCEDURES * + *=====================*/ + + +/*===========================================================================* + * + * main + * + * see man page. run without arguments to see usage + * + * RETURNS: 0 if all is well; 1 on most if not all errors + * + *===========================================================================*/ +int +mpeg_encode_main(int argc, char **argv) +{ + FILE *ofp = NULL; + register int idx; + int function = ENCODE_FRAMES; + int portNumber = 0; + char *hostName = NULL; + int32 totalTime = -1; + int maxMachines = 0x7fffffff; + int outputFrames = 0; + time_t initTimeStart; + time_t framesTimeStart, framesTimeEnd; + + frameStart = -1; + + strcpy(encoder_name, argv[0]); + + CompileTests(); + + time(&initTimeStart); + + if ( argc == 1 ) { + Usage(); + } + + SetStatFileName((char*)""); + + /* parse the arguments */ + idx = 1; + while ( idx < argc-1 ) { + if ( argv[idx][0] != '-' ) { + Usage(); + } + + if ( strcmp(argv[idx], "-stat") == 0 ) { + if ( idx+1 < argc-1 ) { + SetStatFileName(argv[idx+1]); + idx += 2; + } else { + Usage(); + } + } else if ( strcmp(argv[idx], "-gop") == 0 ) { + if ( (function != ENCODE_FRAMES) || (frameStart != -1) ) { + Usage(); + } + + if ( idx+1 < argc-1 ) { + whichGOP = atoi(argv[idx+1]); + idx += 2; + } else { + Usage(); + } + } else if ( strcmp(argv[idx], "-frames") == 0 ) { + if ( (function != ENCODE_FRAMES) || (whichGOP != -1) ) { + Usage(); + } + + if ( idx+2 < argc-1 ) { + frameStart = atoi(argv[idx+1]); + frameEnd = atoi(argv[idx+2]); + + if ( (frameStart > frameEnd) || (frameStart < 0) ) { + fprintf(stderr, "ERROR: bad frame numbers!\n"); + Usage(); + } + + idx += 3; + } else { + Usage(); + } + } else if ( strcmp(argv[idx], "-combine_gops") == 0 ) { + if ( (function != ENCODE_FRAMES) || (whichGOP != -1) || + (frameStart != -1) ) { + Usage(); + } + + function = COMBINE_GOPS; + idx++; + } else if ( strcmp(argv[idx], "-combine_frames") == 0 ) { + if ( (function != ENCODE_FRAMES) || (whichGOP != -1) || + (frameStart != -1) ) { + Usage(); + } + + function = COMBINE_FRAMES; + idx++; + } else if ( strcmp(argv[idx], "-child") == 0 ) { + if ( idx+7 < argc-1 ) { + hostName = argv[idx+1]; + portNumber = atoi(argv[idx+2]); + ioPortNumber = atoi(argv[idx+3]); + combinePortNumber = atoi(argv[idx+4]); + decodePortNumber = atoi(argv[idx+5]); + machineNumber = atoi(argv[idx+6]); + remoteIO = atoi(argv[idx+7]); + + IOhostName = hostName; + } else { + Usage(); + } + + childProcess = TRUE; + idx += 8; + } else if ( strcmp(argv[idx], "-io_server") == 0 ) { + if ( idx+2 < argc-1 ) { + hostName = argv[idx+1]; + portNumber = atoi(argv[idx+2]); + } else { + Usage(); + } + + ioServer = TRUE; + idx += 3; + } else if ( strcmp(argv[idx], "-output_server") == 0 ) { + if ( idx+3 < argc-1 ) { + hostName = argv[idx+1]; + portNumber = atoi(argv[idx+2]); + outputFrames = atoi(argv[idx+3]); + } else { + Usage(); + } + + function = COMBINE_FRAMES; + outputServer = TRUE; + idx += 4; + } else if ( strcmp(argv[idx], "-decode_server") == 0 ) { + if ( idx+3 < argc-1 ) { + hostName = argv[idx+1]; + portNumber = atoi(argv[idx+2]); + outputFrames = atoi(argv[idx+3]); + } else { + Usage(); + } + + function = COMBINE_FRAMES; + decodeServer = TRUE; + idx += 4; + } else if ( strcmp(argv[idx], "-nice") == 0 ) { + niceProcesses = TRUE; + idx++; + } else if ( strcmp(argv[idx], "-max_machines") == 0 ) { + if ( idx+1 < argc-1 ) { + maxMachines = atoi(argv[idx+1]); + } else { + Usage(); + } + + idx += 2; + } else if ( strcmp(argv[idx], "-quiet") == 0 ) { + if ( idx+1 < argc-1 ) { + quietTime = atoi(argv[idx+1]); + } else { + Usage(); + } + + idx += 2; + } else if ( strcmp(argv[idx], "-realquiet") == 0 ) { + realQuiet = TRUE; + idx++; + } else if (( strcmp(argv[idx], "-float_dct") == 0 ) || + ( strcmp(argv[idx], "-float-dct") == 0 )) { + pureDCT = TRUE; + init_idctref(); + init_fdct(); + idx++; + } else if ( strcmp(argv[idx], "-no_frame_summary") == 0 ) { + if ( idx < argc-1 ) { + frameSummary = FALSE; + } else { + Usage(); + } + + idx++; + } else if ( strcmp(argv[idx], "-snr") == 0 ) { + printSNR = TRUE; + idx++; + } else if ( strcmp(argv[idx], "-mse") == 0 ) { + printSNR = printMSE = TRUE; + idx++; + } else if ( strcmp(argv[idx], "-debug_sockets") == 0 ) { + debugSockets = TRUE; + idx++; + } else if ( strcmp(argv[idx], "-debug_machines") == 0 ) { + debugMachines = TRUE; + idx++; + } else if ( strcmp(argv[idx], "-bit_rate_info") == 0 ) { + if ( idx+1 < argc-1 ) { + showBitRatePerFrame = TRUE; + SetBitRateFileName(argv[idx+1]); + idx += 2; + } else { + Usage(); + } + } else if ( strcmp(argv[idx], "-mv_histogram") == 0 ) { + computeMVHist = TRUE; + idx++; + } else { + Usage(); + } + } + + if ( ! ReadParamFile(argv[argc-1], function) ) { + Usage(); + } + + /* Jim Boucher's stuff: + if we are using a movie format then break up into frames*/ + if ( (!childProcess) && (baseFormat == JMOVIE_FILE_TYPE) ) { + JM2JPEG(); + } + + if ( printSNR || (referenceFrame == DECODED_FRAME) ) { + decodeRefFrames = TRUE; + } + + numMachines = min(numMachines, maxMachines); + + Tune_Init(); + Frame_Init(); + +#ifdef BLEAH + time_t initTimeEnd; + + time(&initTimeEnd); + fprintf(stdout, "INIT TIME: %d seconds\n", + initTimeEnd-initTimeStart); + fflush(stdout); +#endif + + if (specificsOn) Specifics_Init(); + + ComputeFrameTable(); + + if ( ioServer ) { + StartIOServer(numInputFiles, hostName, portNumber); + return 0; + } else if ( outputServer ) { + StartCombineServer(outputFrames, outputFileName, hostName, portNumber); + return 0; + } else if ( decodeServer ) { + StartDecodeServer(outputFrames, outputFileName, hostName, portNumber); + return 0; + } + + if ( (frameStart == -1) && + ((numMachines == 0) || (function != ENCODE_FRAMES)) ) { + if ( (ofp = fopen(outputFileName, "wb")) == NULL ) { + throw "Could not open output file"; + } + } + + if ( function == ENCODE_FRAMES ) { + if ( (numMachines == 0) || (frameStart != -1) ) { + time(&framesTimeStart); + totalTime = GenMPEGStream(whichGOP, frameStart, frameEnd, + customQtable, customNIQtable, + numInputFiles, ofp, + outputFileName); + time(&framesTimeEnd); + if ( childProcess && (! realQuiet) ) { +#ifdef BLEAH + fprintf(stdout, "SCHEDULE: MACHINE %d FRAMES %d-%d TIME %d-%d IOTIME %d\n", + machineNumber, frameStart, frameEnd, + framesTimeStart, framesTimeEnd, + IOtime); +#endif + fprintf(stdout, "%s: FRAMES %d-%d (%d seconds)\n", + getenv("HOST"), frameStart, frameEnd, + (int) (framesTimeEnd-framesTimeStart)); + fflush(stdout); + } + } else { + /* check if parameter file has absolute path */ + if ( (argv[argc-1][0] != '/') && (argv[argc-1][0] != '~') ) { + char *buf; + buf = (char*)malloc(MAXPATHLEN+1); + ERRCHK(buf, "main"); + //getcwd(buf, MAXPATHLEN); + strcat(buf, argv[argc-1]); + StartMasterServer(numInputFiles, buf, outputFileName); + } else { + StartMasterServer(numInputFiles, argv[argc-1], outputFileName); + } + } + } else if ( function == COMBINE_GOPS ) { + GOPStoMPEG(numInputFiles, outputFileName, ofp); + } else if ( function == COMBINE_FRAMES ) { + FramesToMPEG(numInputFiles, outputFileName, ofp, FALSE); + } + + if ( childProcess ) { + while ( NotifyMasterDone(hostName, portNumber, machineNumber, + totalTime, + &frameStart, &frameEnd) ) { + /* do more frames */ + time(&framesTimeStart); + totalTime = GenMPEGStream(-1, frameStart, frameEnd, + customQtable, customNIQtable, + numInputFiles, NULL, + outputFileName); + time(&framesTimeEnd); + + if (! realQuiet) { +#ifdef BLEAH + fprintf(stdout, "SCHEDULE: MACHINE %d FRAMES %d-%d TIME %d-%d IOTIME %d\n", + machineNumber, frameStart, frameEnd, + framesTimeStart, framesTimeEnd, + IOtime); +#endif + fprintf(stdout, "%s: FRAMES %d-%d (%d seconds)\n", + getenv("HOST"), frameStart, frameEnd, + (int) (framesTimeEnd-framesTimeStart)); + fflush(stdout); + } + + } + } + + Frame_Exit(); + FrameType_Exit(); // for gmsh + + return 0; /* all is well */ +} + +/*=====================* + * INTERNAL PROCEDURES * + *=====================*/ + +/*===========================================================================* + * + * Usage + * + * prints out usage for the program + * + * RETURNS: nothing + * + * SIDE EFFECTS: none + * + *===========================================================================*/ +static void +Usage() +{ + fprintf(stderr, "Usage: mpeg_encode [options] param_file\n"); + fprintf(stderr, "Options:\n"); + fprintf(stderr, "\t-stat stat_file: append stats to stat_file\n"); + fprintf(stderr, "\t-quiet n: don't report remaining time for at least n seconds\n"); + fprintf(stderr, "\t-realquiet: output nothing at all if successful\n"); + fprintf(stderr, "\t-no_frame_summary: suppress frame summary lines\n"); + fprintf(stderr, "\t-float_dct: use more accurate floating point DCT\n"); + fprintf(stderr, "\t-gop gop_num: encode only the numbered GOP\n"); + fprintf(stderr, "\t-combine_gops: combine GOP files instead of encode\n"); + fprintf(stderr, "\t-frames first_frame last_frame: encode only the specified frames\n"); + fprintf(stderr, "\t-combine_frames: combine frame files instead of encode\n"); + fprintf(stderr, "\t-nice: run slave processes nicely\n"); + fprintf(stderr, "\t-max_machines num_machines: use at most num_machines machines\n"); + fprintf(stderr, "\t-snr: print signal-to-noise ratio\n"); + fprintf(stderr, "\t-bit_rate_info rate_file: put bit rate in specified file\n"); + fprintf(stderr, "\t-mv_histogram: show histograms of motion vectors\n"); + +/* extended usage (used by parallel code; shouldn't be called by user): + -child parallelHostName portNumber ioPortNumber combinePortNumber machineNumber remote + -io_server parallelHostName portNumber + + (remote = 1 if need to use ioPortNumber) + */ +} + + +static void +CompileTests() +{ + assert(sizeof(uint8) == 1); + assert(sizeof(uint16) == 2); + assert(sizeof(uint32) == 4); + assert(sizeof(int8) == 1); + assert(sizeof(int16) == 2); + assert(sizeof(int32) == 4); + + if ( (-8 >> 3) != -1 ) { + throw "Right shifts are NOT arithmetic! " + "Change >> to multiplies by powers of 2"; + } +} diff --git a/contrib/mpeg_encode/mfwddct.cpp b/contrib/mpeg_encode/mfwddct.cpp new file mode 100644 index 0000000000000000000000000000000000000000..cd78dd05cb6be84fe04b054f84cd1f6cb6399740 --- /dev/null +++ b/contrib/mpeg_encode/mfwddct.cpp @@ -0,0 +1,390 @@ + +/* + * mfwddct.c (derived from jfwddct.c, which carries the following info) + * + * Copyright (C) 1991, 1992, Thomas G. Lane. This file is part of the + * Independent JPEG Group's software. For conditions of distribution and use, + * see the accompanying README file. + * + * This file contains the basic DCT (Discrete Cosine Transform) transformation + * subroutine. + * + * This implementation is based on Appendix A.2 of the book "Discrete Cosine + * Transform---Algorithms, Advantages, Applications" by K.R. Rao and P. Yip + * (Academic Press, Inc, London, 1990). It uses scaled fixed-point arithmetic + * instead of floating point. + */ + +#include "all.h" + +#include "dct.h" +#include "mtypes.h" +#include "opts.h" + +/* + * The poop on this scaling stuff is as follows: + * + * We have to do addition and subtraction of the integer inputs, which is no + * problem, and multiplication by fractional constants, which is a problem to + * do in integer arithmetic. We multiply all the constants by DCT_SCALE and + * convert them to integer constants (thus retaining LG2_DCT_SCALE bits of + * precision in the constants). After doing a multiplication we have to + * divide the product by DCT_SCALE, with proper rounding, to produce the + * correct output. The division can be implemented cheaply as a right shift + * of LG2_DCT_SCALE bits. The DCT equations also specify an additional + * division by 2 on the final outputs; this can be folded into the + * right-shift by shifting one more bit (see UNFIXH). + * + * If you are planning to recode this in assembler, you might want to set + * LG2_DCT_SCALE to 15. This loses a bit of precision, but then all the + * multiplications are between 16-bit quantities (given 8-bit JSAMPLEs!) so + * you could use a signed 16x16=>32 bit multiply instruction instead of full + * 32x32 multiply. Unfortunately there's no way to describe such a multiply + * portably in C, so we've gone for the extra bit of accuracy here. + */ + +#define EIGHT_BIT_SAMPLES +#ifdef EIGHT_BIT_SAMPLES +#define LG2_DCT_SCALE 16 +#else +#define LG2_DCT_SCALE 15 /* lose a little precision to avoid overflow */ +#endif + +#define ONE ((int32) 1) + +#define DCT_SCALE (ONE << LG2_DCT_SCALE) + +/* In some places we shift the inputs left by a couple more bits, */ +/* so that they can be added to fractional results without too much */ +/* loss of precision. */ +#define LG2_OVERSCALE 2 +#define OVERSCALE (ONE << LG2_OVERSCALE) +#define OVERSHIFT(x) ((x) <<= LG2_OVERSCALE) + +/* Scale a fractional constant by DCT_SCALE */ +#define FIX(x) ((int32) ((x) * DCT_SCALE + 0.5)) + +/* Scale a fractional constant by DCT_SCALE/OVERSCALE */ +/* Such a constant can be multiplied with an overscaled input */ +/* to produce something that's scaled by DCT_SCALE */ +#define FIXO(x) ((int32) ((x) * DCT_SCALE / OVERSCALE + 0.5)) + +/* Descale and correctly round a value that's scaled by DCT_SCALE */ +#define UNFIX(x) RIGHT_SHIFT((x) + (ONE << (LG2_DCT_SCALE-1)), LG2_DCT_SCALE) + +/* Same with an additional division by 2, ie, correctly rounded UNFIX(x/2) */ +#define UNFIXH(x) RIGHT_SHIFT((x) + (ONE << LG2_DCT_SCALE), LG2_DCT_SCALE+1) + +/* Take a value scaled by DCT_SCALE and round to integer scaled by OVERSCALE */ +#define UNFIXO(x) RIGHT_SHIFT((x) + (ONE << (LG2_DCT_SCALE-1-LG2_OVERSCALE)),\ + LG2_DCT_SCALE-LG2_OVERSCALE) + +/* Here are the constants we need */ +/* SIN_i_j is sine of i*pi/j, scaled by DCT_SCALE */ +/* COS_i_j is cosine of i*pi/j, scaled by DCT_SCALE */ + +#define SIN_1_4 FIX(0.707106781) +#define COS_1_4 SIN_1_4 + +#define SIN_1_8 FIX(0.382683432) +#define COS_1_8 FIX(0.923879533) +#define SIN_3_8 COS_1_8 +#define COS_3_8 SIN_1_8 + +#define SIN_1_16 FIX(0.195090322) +#define COS_1_16 FIX(0.980785280) +#define SIN_7_16 COS_1_16 +#define COS_7_16 SIN_1_16 + +#define SIN_3_16 FIX(0.555570233) +#define COS_3_16 FIX(0.831469612) +#define SIN_5_16 COS_3_16 +#define COS_5_16 SIN_3_16 + +/* OSIN_i_j is sine of i*pi/j, scaled by DCT_SCALE/OVERSCALE */ +/* OCOS_i_j is cosine of i*pi/j, scaled by DCT_SCALE/OVERSCALE */ + +#define OSIN_1_4 FIXO(0.707106781) +#define OCOS_1_4 OSIN_1_4 + +#define OSIN_1_8 FIXO(0.382683432) +#define OCOS_1_8 FIXO(0.923879533) +#define OSIN_3_8 OCOS_1_8 +#define OCOS_3_8 OSIN_1_8 + +#define OSIN_1_16 FIXO(0.195090322) +#define OCOS_1_16 FIXO(0.980785280) +#define OSIN_7_16 OCOS_1_16 +#define OCOS_7_16 OSIN_1_16 + +#define OSIN_3_16 FIXO(0.555570233) +#define OCOS_3_16 FIXO(0.831469612) +#define OSIN_5_16 OCOS_3_16 +#define OCOS_5_16 OSIN_3_16 + +/* Prototypes */ +void reference_fwd_dct _ANSI_ARGS_((Block block, Block dest)); +void mp_fwd_dct_fast _ANSI_ARGS_((Block data2d, Block dest2d)); +void init_fdct _ANSI_ARGS_((void)); + +/* + * -------------------------------------------------------------- + * + * mp_fwd_dct_block2 -- + * + * Select the appropriate mp_fwd_dct routine + * + * Results: None + * + * Side effects: None + * + * -------------------------------------------------------------- + */ +extern boolean pureDCT; +void +mp_fwd_dct_block2(Block data, Block dest) +{ + if (pureDCT) reference_fwd_dct(data, dest); + else mp_fwd_dct_fast(data, dest); +} + +/* + * -------------------------------------------------------------- + * + * mp_fwd_dct_fast -- + * + * Perform the forward DCT on one block of samples. + * + * A 2-D DCT can be done by 1-D DCT on each row followed by 1-D DCT on each + * column. + * + * Results: None + * + * Side effects: Overwrites the input data + * + * -------------------------------------------------------------- + */ + +void +mp_fwd_dct_fast(Block data2d, Block dest2d) +{ + int16 *data = (int16 *) data2d; /* this algorithm wants + * a 1-d array */ + int16 *dest = (int16 *) dest2d; + int pass, rowctr; + register int16 *inptr, *outptr; + int16 workspace[DCTSIZE_SQ]; + SHIFT_TEMPS + +#ifdef ndef + { + int y; + + printf("fwd_dct (beforehand):\n"); + for (y = 0; y < 8; y++) + printf("%4d %4d %4d %4d %4d %4d %4d %4d\n", + data2d[y][0], data2d[y][1], + data2d[y][2], data2d[y][3], + data2d[y][4], data2d[y][5], + data2d[y][6], data2d[y][7]); + } +#endif + + /* + * Each iteration of the inner loop performs one 8-point 1-D DCT. It + * reads from a *row* of the input matrix and stores into a *column* + * of the output matrix. In the first pass, we read from the data[] + * array and store into the local workspace[]. In the second pass, + * we read from the workspace[] array and store into data[], thus + * performing the equivalent of a columnar DCT pass with no variable + * array indexing. + */ + + inptr = data; /* initialize pointers for first pass */ + outptr = workspace; + for (pass = 1; pass >= 0; pass--) { + for (rowctr = DCTSIZE - 1; rowctr >= 0; rowctr--) { + /* + * many tmps have nonoverlapping lifetime -- flashy + * register colourers should be able to do this lot + * very well + */ + int32 tmp0, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7; + int32 tmp10, tmp11, tmp12, tmp13; + int32 tmp14, tmp15, tmp16, tmp17; + int32 tmp25, tmp26; + /* SHIFT_TEMPS */ + + /* temp0 through tmp7: -512 to +512 */ + /* if I-block, then -256 to +256 */ + tmp0 = inptr[7] + inptr[0]; + tmp1 = inptr[6] + inptr[1]; + tmp2 = inptr[5] + inptr[2]; + tmp3 = inptr[4] + inptr[3]; + tmp4 = inptr[3] - inptr[4]; + tmp5 = inptr[2] - inptr[5]; + tmp6 = inptr[1] - inptr[6]; + tmp7 = inptr[0] - inptr[7]; + + /* tmp10 through tmp13: -1024 to +1024 */ + /* if I-block, then -512 to +512 */ + tmp10 = tmp3 + tmp0; + tmp11 = tmp2 + tmp1; + tmp12 = tmp1 - tmp2; + tmp13 = tmp0 - tmp3; + + outptr[0] = (int16) UNFIXH((tmp10 + tmp11) * SIN_1_4); + outptr[DCTSIZE * 4] = (int16) UNFIXH((tmp10 - tmp11) * COS_1_4); + + outptr[DCTSIZE * 2] = (int16) UNFIXH(tmp13 * COS_1_8 + tmp12 * SIN_1_8); + outptr[DCTSIZE * 6] = (int16) UNFIXH(tmp13 * SIN_1_8 - tmp12 * COS_1_8); + + tmp16 = UNFIXO((tmp6 + tmp5) * SIN_1_4); + tmp15 = UNFIXO((tmp6 - tmp5) * COS_1_4); + + OVERSHIFT(tmp4); + OVERSHIFT(tmp7); + + /* + * tmp4, tmp7, tmp15, tmp16 are overscaled by + * OVERSCALE + */ + + tmp14 = tmp4 + tmp15; + tmp25 = tmp4 - tmp15; + tmp26 = tmp7 - tmp16; + tmp17 = tmp7 + tmp16; + + outptr[DCTSIZE] = (int16) UNFIXH(tmp17 * OCOS_1_16 + tmp14 * OSIN_1_16); + outptr[DCTSIZE * 7] = (int16) UNFIXH(tmp17 * OCOS_7_16 - tmp14 * OSIN_7_16); + outptr[DCTSIZE * 5] = (int16) UNFIXH(tmp26 * OCOS_5_16 + tmp25 * OSIN_5_16); + outptr[DCTSIZE * 3] = (int16) UNFIXH(tmp26 * OCOS_3_16 - tmp25 * OSIN_3_16); + + inptr += DCTSIZE; /* advance inptr to next row */ + outptr++; /* advance outptr to next column */ + } + /* end of pass; in case it was pass 1, set up for pass 2 */ + inptr = workspace; + outptr = dest; + } +#ifdef ndef + { + int y; + + printf("fwd_dct (afterward):\n"); + for (y = 0; y < 8; y++) + printf("%4d %4d %4d %4d %4d %4d %4d %4d\n", + dest2d[y][0], dest2d[y][1], + dest2d[y][2], dest2d[y][3], + dest2d[y][4], dest2d[y][5], + dest2d[y][6], dest2d[y][7]); + } +#endif +} + + +/* Modifies from the MPEG2 verification coder */ +/* fdctref.c, forward discrete cosine transform, double precision */ + +/* Copyright (C) 1994, MPEG Software Simulation Group. All Rights Reserved. */ + +/* + * Disclaimer of Warranty + * + * These software programs are available to the user without any license fee or + * royalty on an "as is" basis. The MPEG Software Simulation Group disclaims + * any and all warranties, whether express, implied, or statuary, including any + * implied warranties or merchantability or of fitness for a particular + * purpose. In no event shall the copyright-holder be liable for any + * incidental, punitive, or consequential damages of any kind whatsoever + * arising from the use of these programs. + * + * This disclaimer of warranty extends to the user of these programs and user's + * customers, employees, agents, transferees, successors, and assigns. + * + * The MPEG Software Simulation Group does not represent or warrant that the + * programs furnished hereunder are free of infringement of any third-party + * patents. + * + * Commercial implementations of MPEG-1 and MPEG-2 video, including shareware, + * are subject to royalty fees to patent holders. Many of these patents are + * general enough such that they are unavoidable regardless of implementation + * design. + * + */ + +#ifndef PI +#ifdef M_PI +#define PI M_PI +#else +#define PI 3.14159265358979323846 +#endif +#endif + +/* private data */ +static double trans_coef[8][8]; /* transform coefficients */ + +void init_fdct() +{ + int i, j; + double s; + + for (i=0; i<8; i++) + { + s = (i==0) ? sqrt(0.125) : 0.5; + + for (j=0; j<8; j++) + trans_coef[i][j] = s * cos((PI/8.0)*i*(j+0.5)); + } +} + +void reference_fwd_dct(Block block, Block dest) +{ + int i, j, k; + double s; + double tmp[64]; + + if (DoLaplace) { + LaplaceNum++; + } + + for (i=0; i<8; i++) + for (j=0; j<8; j++) + { + s = 0.0; + + for (k=0; k<8; k++) + s += trans_coef[j][k] * block[i][k]; + + tmp[8*i+j] = s; + } + + for (i=0; i<8; i++) + for (j=0; j<8; j++) + { + s = 0.0; + + for (k=0; k<8; k++) + s += trans_coef[i][k] * tmp[8*k+j]; + + if (collect_quant) { + fprintf(collect_quant_fp, "%d %lf\n", 8*i+j, s); + } + if (DoLaplace) { + L1[LaplaceCnum][i*8+j] += s*s; + L2[LaplaceCnum][i*8+j] += s; + } + + + dest[i][j] = (int)floor(s+0.499999); + /* + * reason for adding 0.499999 instead of 0.5: + * s is quite often x.5 (at least for i and/or j = 0 or 4) + * and setting the rounding threshold exactly to 0.5 leads to an + * extremely high arithmetic implementation dependency of the result; + * s being between x.5 and x.500001 (which is now incorrectly rounded + * downwards instead of upwards) is assumed to occur less often + * (if at all) + */ + } +} diff --git a/contrib/mpeg_encode/mheaders.cpp b/contrib/mpeg_encode/mheaders.cpp new file mode 100644 index 0000000000000000000000000000000000000000..eec9e1e4d8dd83d0dc5e3d9fff1fc72d980c6fa1 --- /dev/null +++ b/contrib/mpeg_encode/mheaders.cpp @@ -0,0 +1,1158 @@ +/*===========================================================================* + * mheaders.c * + * * + * Procedures to generate MPEG headers * + * * + * EXPORTED PROCEDURES: * + * Mhead_GenPictureHeader * + * Mhead_GenSequenceHeader * + * Mhead_GenSequenceEnder * + * Mhead_GenGOPHeader * + * Mhead_GenSliceHeader * + * Mhead_GenSliceEnder * + * Mhead_GenMBHeader * + * * + *===========================================================================*/ + +/* + * Copyright (c) 1995 The Regents of the University of California. + * All rights reserved. + * + * Permission to use, copy, modify, and distribute this software and its + * documentation for any purpose, without fee, and without written agreement is + * hereby granted, provided that the above copyright notice and the following + * two paragraphs appear in all copies of this software. + * + * IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR + * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT + * OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF + * CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS + * ON AN "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO + * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. + */ + +/* + * $Header: /n/picasso/project/mpeg/mpeg_dist/mpeg_encode/RCS/mheaders.c,v 1.15 1995/08/07 21:45:19 smoot Exp $ + * $Log: mheaders.c,v $ + * Revision 1.15 1995/08/07 21:45:19 smoot + * check for illegal MVs (shouldnt ever be called, but....) + * fix bug which made us not weite Iframe Qscale changes + * warns if writing a size=0 mpeg + * + * Revision 1.14 1995/05/22 20:53:35 smoot + * corrected bit_rate value in constrained params flag + * + * Revision 1.13 1995/05/02 01:50:38 eyhung + * made VidRateNum un-static + * + * Revision 1.12 1995/03/27 19:28:23 smoot + * auto-determines Qscale changes (was mb_quant) + * + * Revision 1.11 1995/02/16 09:12:39 eyhung + * fixed compile bug with HP7xx + * + * Revision 1.10 1995/01/25 22:53:50 smoot + * Better buf_size checking, and actually check constrained params + * + * Revision 1.9 1995/01/19 23:08:47 eyhung + * Changed copyrights + * + * Revision 1.8 1995/01/16 08:45:10 eyhung + * BLEAH'ed hsize and vsize + * + * Revision 1.7 1994/12/09 22:27:17 smoot + * Fixed buffer size in stream + * + * Revision 1.6 1994/11/12 02:11:54 keving + * nothing + * + * Revision 1.5 1994/03/15 00:27:11 keving + * nothing + * + * Revision 1.4 1993/12/22 19:19:01 keving + * nothing + * + * Revision 1.3 1993/07/22 22:23:43 keving + * nothing + * + * Revision 1.2 1993/06/30 20:06:09 keving + * nothing + * + * Revision 1.1 1993/06/03 21:08:08 keving + * nothing + * + * Revision 1.6 1993/03/01 23:03:40 keving + * nothing + * + * Revision 1.5 1993/02/17 23:18:20 dwallach + * checkin prior to keving's joining the project + * + * Revision 1.4 1993/01/18 10:20:02 dwallach + * *** empty log message *** + * + * Revision 1.3 1993/01/18 10:17:29 dwallach + * RCS headers installed, code indented uniformly + * + * Revision 1.3 1993/01/18 10:17:29 dwallach + * RCS headers installed, code indented uniformly + * + */ + + +/*==============* + * HEADER FILES * + *==============*/ + +#include "all.h" +#include "bitio.h" +#include "frames.h" +#include "mheaders.h" + + +/*==================* + * STATIC VARIABLES * + *==================*/ + +static int gopStartFrame = 0; +static int lastGOPStart = 0; +static int lastQSSet; + +static uint32 mbAddrIncrTable[][2] = { + {0x0, 0}, + {0x1, 1}, + {0x3, 3}, + {0x2, 3}, + {0x3, 4}, + {0x2, 4}, + {0x3, 5}, + {0x2, 5}, + {0x7, 7}, + {0x6, 7}, + {0xb, 8}, + {0xa, 8}, + {0x9, 8}, + {0x8, 8}, + {0x7, 8}, + {0x6, 8}, + {0x17, 10}, + {0x16, 10}, + {0x15, 10}, + {0x14, 10}, + {0x13, 10}, + {0x12, 10}, + {0x23, 11}, + {0x22, 11}, + {0x21, 11}, + {0x20, 11}, + {0x1f, 11}, + {0x1e, 11}, + {0x1d, 11}, + {0x1c, 11}, + {0x1b, 11}, + {0x1a, 11}, + {0x19, 11}, + {0x18, 11}}; + +static uint32 mbMotionVectorTable[][2] = { + {0x19, 11}, + {0x1b, 11}, + {0x1d, 11}, + {0x1f, 11}, + {0x21, 11}, + {0x23, 11}, + {0x13, 10}, + {0x15, 10}, + {0x17, 10}, + {0x7, 8}, + {0x9, 8}, + {0xb, 8}, + {0x7, 7}, + {0x3, 5}, + {0x3, 4}, + {0x3, 3}, + {0x1, 1}, + {0x2, 3}, + {0x2, 4}, + {0x2, 5}, + {0x6, 7}, + {0xa, 8}, + {0x8, 8}, + {0x6, 8}, + {0x16, 10}, + {0x14, 10}, + {0x12, 10}, + {0x22, 11}, + {0x20, 11}, + {0x1e, 11}, + {0x1c, 11}, + {0x1a, 11}, + {0x18, 11}}; + +static uint32 mbPatTable[][2] = { + {0x0, 0}, + {0xb, 5}, + {0x9, 5}, + {0xd, 6}, + {0xd, 4}, + {0x17, 7}, + {0x13, 7}, + {0x1f, 8}, + {0xc, 4}, + {0x16, 7}, + {0x12, 7}, + {0x1e, 8}, + {0x13, 5}, + {0x1b, 8}, + {0x17, 8}, + {0x13, 8}, + {0xb, 4}, + {0x15, 7}, + {0x11, 7}, + {0x1d, 8}, + {0x11, 5}, + {0x19, 8}, + {0x15, 8}, + {0x11, 8}, + {0xf, 6}, + {0xf, 8}, + {0xd, 8}, + {0x3, 9}, + {0xf, 5}, + {0xb, 8}, + {0x7, 8}, + {0x7, 9}, + {0xa, 4}, + {0x14, 7}, + {0x10, 7}, + {0x1c, 8}, + {0xe, 6}, + {0xe, 8}, + {0xc, 8}, + {0x2, 9}, + {0x10, 5}, + {0x18, 8}, + {0x14, 8}, + {0x10, 8}, + {0xe, 5}, + {0xa, 8}, + {0x6, 8}, + {0x6, 9}, + {0x12, 5}, + {0x1a, 8}, + {0x16, 8}, + {0x12, 8}, + {0xd, 5}, + {0x9, 8}, + {0x5, 8}, + {0x5, 9}, + {0xc, 5}, + {0x8, 8}, + {0x4, 8}, + {0x4, 9}, + {0x7, 3}, + {0xa, 5}, /* grrr... 61, 62, 63 added - Kevin */ + {0x8, 5}, + {0xc, 6} +}; + +/*===========* + * CONSTANTS * + *===========*/ + +#define SEQ_HEAD_CODE 0x000001b3 +#define EXT_START_CODE 0x000001b5 +#define USER_START_CODE 0x000001b2 +#define GOP_START_CODE 0x000001b8 +#define PICT_START_CODE 0x00000100 +#define SLICE_BASE_CODE 0x00000100 + +#define SEQ_END_CODE 0x000001b7 + +/* not static anymore because information is used for computing frame rate + * and for statistics */ +double VidRateNum[9]={1.0, 23.976, 24.0, 25.0, 29.97, 30.0, + 50.0 ,59.94, 60.0}; + + +/*===============================* + * INTERNAL PROCEDURE prototypes * + *===============================*/ + +static void GenMBAddrIncr _ANSI_ARGS_((BitBucket *bb, uint32 addr_incr)); +static void GenPictHead _ANSI_ARGS_((BitBucket *bb, uint32 temp_ref, + uint32 code_type, uint32 vbv_delay, + int32 full_pel_forw_flag, uint32 forw_f_code, + int32 full_pel_back_flag, uint32 back_f_code, + uint8 *extra_info, uint32 extra_info_size, + uint8 *ext_data, uint32 ext_data_size, + uint8 *user_data, uint32 user_data_size)); +static void GenMBType _ANSI_ARGS_((BitBucket *bb, uint32 pict_code_type, + uint32 mb_quant, uint32 motion_forw, uint32 motion_back, + uint32 mb_pattern, uint32 mb_intra)); +static void GenMotionCode _ANSI_ARGS_((BitBucket *bb, int32 vector)); +static void GenBlockPattern _ANSI_ARGS_((BitBucket *bb, + uint32 mb_pattern)); + + +/*=====================* + * EXPORTED PROCEDURES * + *=====================*/ + + +/*===========================================================================* + * + * SetGOPStartTime + * + * sets the start frame of the GOP; to be used with GenPictureHeader + * + * RETURNS: nothing + * + * SIDE EFFECTS: none + * + *===========================================================================*/ +void +SetGOPStartTime(int index) +{ + lastGOPStart = gopStartFrame; + gopStartFrame = index; +} + + +/*===========================================================================* + * + * Mhead_GenPictureHeader + * + * generate picture header with given frame type and picture count + * append result to the specified bitstream + * + * RETURNS: nothing + * + * SIDE EFFECTS: none + * + *===========================================================================*/ +void +Mhead_GenPictureHeader(BitBucket *bbPtr, + int frameType, + int pictCount, + int f_code) +{ + int temporalRef; + + if ( pictCount >= gopStartFrame ) { + temporalRef = (pictCount-gopStartFrame); + } else { + temporalRef = (pictCount-lastGOPStart); + } + temporalRef = (temporalRef % 1024); + + DBG_PRINT(("Picture Header\n")); + GenPictHead(bbPtr, temporalRef, frameType, + 0 /* vbv_delay */, + pixelFullSearch /* full_pel_forw_flag */, + f_code /* forw_f_code */, + pixelFullSearch /* full_pel_back_flag */, + f_code /* back_f_code */, + NULL, 0, NULL, 0, NULL, 0); +} + + +/*===========================================================================* + * + * Mhead_GenSequenceHeader + * + * generate sequence header with given attributes + * append result to the specified bitstream + * + * RETURNS: nothing + * + * SIDE EFFECTS: none + * + *===========================================================================*/ +void +Mhead_GenSequenceHeader(BitBucket *bbPtr, + uint32 hsize, + uint32 vsize, + int32 pratio, + int32 pict_rate, + int32 bit_rate, + int32 buf_size, + int32 c_param_flag, + int32 *iq_matrix, + int32 *niq_matrix, + uint8 *ext_data, + int32 ext_data_size, + uint8 *user_data, + int32 user_data_size) +{ + extern int ZAG[]; + int i; + + /* Write seq start code. */ + + Bitio_Write(bbPtr, SEQ_HEAD_CODE, 32); + + /* Write horiz. and vert. sizes. */ + +#ifdef BLEAH +fprintf(stdout, "hsize, vsize = %d, %d\n", hsize, vsize); +#endif + + if (hsize==0 || vsize==0) { + fprintf(stderr, "Writing zero size to stream!\n"); + } + Bitio_Write(bbPtr, hsize, 12); + Bitio_Write(bbPtr, vsize, 12); + + /* Write pixel aspect ratio, negative values default to 1. */ + + if (pratio < 0) { + throw "PROGRAMMER ERROR: pratio < 0"; + } + Bitio_Write(bbPtr, pratio, 4); + + /* Wrtie picture rate, negative values default to 30 fps. */ + + if (pict_rate < 0) { + throw "PROGRAMMER ERROR: pict_rate < 0"; + } + Bitio_Write(bbPtr, pict_rate, 4); + + /* Write bit rate, negative values default to variable. */ + + if (bit_rate < 0) { + bit_rate = -1; + } else { + bit_rate = bit_rate / 400; + } + + Bitio_Write(bbPtr, bit_rate, 18); + + /* Marker bit. */ + Bitio_Write(bbPtr, 0x1, 1); + + /* Write VBV buffer size. Negative values default to zero. */ + if (buf_size < 0) { + buf_size = 0; + } + + buf_size = (buf_size + (16*1024 - 1)) / (16*1024); + if (buf_size>=0x400) buf_size=0x3ff; + Bitio_Write(bbPtr, buf_size, 10); + + /* Write constrained parameter flag. */ + { + int num_mb = ((hsize+15)/16) * ((vsize+15)/16); + /* At present we cheat on buffer size */ + c_param_flag = ((bit_rate <= 4640) && + (bit_rate >0) && + (buf_size <= 20) && + (pict_rate >= 1) && + (pict_rate <= 5) && + (hsize <= 768) && + (vsize <= 576) && + (num_mb <= 396) && + (num_mb*VidRateNum[pict_rate] <= 9900) && + (fCodeP<=4) && + (fCodeB<=4)); + } + + if (c_param_flag) { + Bitio_Write(bbPtr, 0x01, 1); + } else { + Bitio_Write(bbPtr, 0x00, 1); + } + + /* Write intra quant matrix if present. */ + + if (iq_matrix != NULL) { + Bitio_Write(bbPtr, 0x01, 1); + for (i = 0; i < 64; i++) { + Bitio_Write(bbPtr, iq_matrix[ZAG[i]], 8); + } + } else { + Bitio_Write(bbPtr, 0x00, 1); + } + + /* Write non intra quant matrix if present. */ + + if (niq_matrix != NULL) { + Bitio_Write(bbPtr, 0x01, 1); + for (i = 0; i < 64; i++) { + Bitio_Write(bbPtr, niq_matrix[ZAG[i]], 8); + } + } else { + Bitio_Write(bbPtr, 0x00, 1); + } + + /* next start code */ + Bitio_BytePad(bbPtr); + + + /* Write ext data if present. */ + + if (ext_data != NULL) { + Bitio_Write(bbPtr, EXT_START_CODE, 32); + + for (i = 0; i < ext_data_size; i++) { + Bitio_Write(bbPtr, ext_data[i], 8); + } + Bitio_BytePad(bbPtr); + } + /* Write user data if present. */ + if ((user_data != NULL) && (user_data_size != 0)) { + Bitio_Write(bbPtr, USER_START_CODE, 32); + + for (i = 0; i < user_data_size; i++) { + Bitio_Write(bbPtr, user_data[i], 8); + } + Bitio_BytePad(bbPtr); + } +} + + +/*===========================================================================* + * + * Mhead_GenSequenceEnder + * + * generate sequence ender + * append result to the specified bitstream + * + * RETURNS: nothing + * + * SIDE EFFECTS: none + * + *===========================================================================*/ +void +Mhead_GenSequenceEnder(BitBucket *bbPtr) +{ + Bitio_Write(bbPtr, SEQ_END_CODE, 32); +} + + +/*===========================================================================* + * + * Mhead_GenGOPHeader + * + * generate GOP header with specified attributes + * append result to the specified bitstream + * + * RETURNS: nothing + * + * SIDE EFFECTS: none + * + *===========================================================================*/ +void +Mhead_GenGOPHeader(BitBucket *bbPtr, + int32 drop_frame_flag, + int32 tc_hrs, + int32 tc_min, + int32 tc_sec, + int32 tc_pict, + int32 closed_gop, + int32 broken_link, + uint8 *ext_data, + int32 ext_data_size, + uint8 *user_data, + int32 user_data_size) +{ + int i; + + /* Write gop start code. */ + Bitio_Write(bbPtr, GOP_START_CODE, 32); + + /* Construct and write timecode. */ + + /* Drop frame flag. */ + if (drop_frame_flag) { + Bitio_Write(bbPtr, 0x01, 1); + } else { + Bitio_Write(bbPtr, 0x00, 1); + } + + /* Time code hours. */ + Bitio_Write(bbPtr, tc_hrs, 5); + + /* Time code minutes. */ + Bitio_Write(bbPtr, tc_min, 6); + + /* Marker bit. */ + Bitio_Write(bbPtr, 0x01, 1); + + /* Time code seconds. */ + Bitio_Write(bbPtr, tc_sec, 6); + + /* Time code pictures. */ + Bitio_Write(bbPtr, tc_pict, 6); + + + /* Closed gop flag. */ + if (closed_gop) { + Bitio_Write(bbPtr, 0x01, 1); + } else { + Bitio_Write(bbPtr, 0x00, 1); + } + + /* Broken link flag. */ + if (broken_link) { + Bitio_Write(bbPtr, 0x01, 1); + } else { + Bitio_Write(bbPtr, 0x00, 1); + } + + /* next start code */ + Bitio_BytePad(bbPtr); + + /* Write ext data if present. */ + + if (ext_data != NULL) { + Bitio_Write(bbPtr, EXT_START_CODE, 32); + + for (i = 0; i < ext_data_size; i++) { + Bitio_Write(bbPtr, ext_data[i], 8); + } + Bitio_BytePad(bbPtr); + } + /* Write user data if present. */ + if (user_data != NULL) { + Bitio_Write(bbPtr, USER_START_CODE, 32); + + for (i = 0; i < user_data_size; i++) { + Bitio_Write(bbPtr, user_data[i], 8); + } + Bitio_BytePad(bbPtr); + } +} + + +/*===========================================================================* + * + * Mhead_GenSliceHeader + * + * generate slice header with specified attributes + * append result to the specified bitstream + * + * RETURNS: nothing + * + * SIDE EFFECTS: none + * + *===========================================================================*/ +void +Mhead_GenSliceHeader(BitBucket *bbPtr, + uint32 verticalPos, + uint32 qscale, + uint8 *extra_info, + uint32 extra_info_size) +{ + int i; + + /* Write slice start code. */ + Bitio_Write(bbPtr, (SLICE_BASE_CODE + verticalPos), 32); + + /* Quant. scale. */ + Bitio_Write(bbPtr, qscale, 5); + lastQSSet = qscale; + + /* Extra bit slice info. */ + + if (extra_info != NULL) { + for (i = 0; i < extra_info_size; i++) { + Bitio_Write(bbPtr, 0x01, 1); + Bitio_Write(bbPtr, extra_info[i], 8); + } + } + + /* extra_bit_slice */ + Bitio_Write(bbPtr, 0x00, 1); +} + + +/*===========================================================================* + * + * Mhead_GenSliceEnder + * + * generate slice ender + * append result to the specified bitstream + * + * RETURNS: nothing + * + * SIDE EFFECTS: none + * + *===========================================================================*/ +void +Mhead_GenSliceEnder(BitBucket *bbPtr) +{ + Bitio_BytePad(bbPtr); +} + + +/*===========================================================================* + * + * Mhead_GenMBHeader + * + * generate macroblock header with given attributes + * append result to the specified bitstream + * + * RETURNS: nothing + * + * SIDE EFFECTS: none + * + *===========================================================================*/ +void +Mhead_GenMBHeader(BitBucket *bbPtr, + uint32 pict_code_type, + uint32 addr_incr, + uint32 q_scale, + uint32 forw_f_code, + uint32 back_f_code, + uint32 horiz_forw_r, + uint32 vert_forw_r, + uint32 horiz_back_r, + uint32 vert_back_r, + int32 motion_forw, + int32 m_horiz_forw, + int32 m_vert_forw, + int32 motion_back, + int32 m_horiz_back, + int32 m_vert_back, + uint32 mb_pattern, + uint32 mb_intra) +{ + uint32 mb_quant; + + /* MB escape sequences if necessary. */ + +#ifdef BLEAH +if ( addr_incr != 1 ) + fprintf(stdout, "Creating MB_INCR: %d\n", addr_incr); +#endif + + while (addr_incr > 33) { + Bitio_Write(bbPtr, 0x008, 11); + addr_incr -= 33; + } + + /* Generate addr incr code. */ + GenMBAddrIncr(bbPtr, addr_incr); + + /* Determine mb_quant (true if change in q scale) */ + if ((q_scale != lastQSSet) && ((mb_pattern != 0) || (mb_intra == TRUE))) { + mb_quant = TRUE; + lastQSSet = q_scale; + } else { + mb_quant = FALSE; + } + + /* Generate mb type code. */ + GenMBType(bbPtr, pict_code_type, mb_quant, motion_forw, motion_back, mb_pattern, mb_intra); + + /* MB quant. */ + if (mb_quant) { + Bitio_Write(bbPtr, q_scale, 5); + } + /* Forward predictive vector stuff. */ + + if (motion_forw) { + int forw_f, forw_r_size; + + forw_r_size = forw_f_code - 1; + forw_f = 1 << forw_r_size; /* 1 > 0 */ + if ((m_horiz_forw > 16*forw_f-1) || (m_horiz_forw < -16*forw_f)) { + fprintf(stderr, "Illegal motion? %d %d\n", m_horiz_forw, 16*forw_f); + } + if ((m_vert_forw > 16*forw_f-1) || (m_vert_forw < -16*forw_f)) { + fprintf(stderr, "Illegal motion? %d %d\n", m_vert_forw, 16*forw_f); + } + GenMotionCode(bbPtr, m_horiz_forw); + + if ((forw_f != 1) && (m_horiz_forw != 0)) { + Bitio_Write(bbPtr, horiz_forw_r, forw_r_size); + } + GenMotionCode(bbPtr, m_vert_forw); + + if ((forw_f != 1) && (m_vert_forw != 0)) { + Bitio_Write(bbPtr, vert_forw_r, forw_r_size); + } + } + /* Back predicted vector stuff. */ + + if (motion_back) { + int back_f, back_r_size; + + back_r_size = back_f_code - 1; + back_f = 1 << back_r_size; /* 1 > 0 */ + + if ((m_horiz_back > 16*back_f-1) || (m_horiz_back < -16*back_f)) { + fprintf(stderr, "Illegal motion? %d %d\n", m_horiz_back, 16*back_f); + } + if ((m_vert_back > 16*back_f-1) || (m_vert_back < -16*back_f)) { + fprintf(stderr, "Illegal motion? %d %d\n", m_vert_back, 16*back_f); + } + + GenMotionCode(bbPtr, m_horiz_back); + + if ((back_f != 1) && (m_horiz_back != 0)) { + Bitio_Write(bbPtr, horiz_back_r, back_r_size); + } + GenMotionCode(bbPtr, m_vert_back); + + if ((back_f != 1) && (m_vert_back != 0)) { + Bitio_Write(bbPtr, vert_back_r, back_r_size); + } + } + /* MB pattern. */ + + if (mb_pattern) { + GenBlockPattern(bbPtr, mb_pattern); + } +} + + +/*=====================* + * INTERNAL PROCEDURES * + *=====================*/ + +/*===========================================================================* + * + * GenMBType + * + * generate macroblock type with given attributes + * append result to the specified bitstream + * + * RETURNS: nothing + * + * SIDE EFFECTS: none + * + *===========================================================================*/ +static void +GenMBType(BitBucket *bbPtr, + uint32 pict_code_type, + uint32 mb_quant, + uint32 motion_forw, + uint32 motion_back, + uint32 mb_pattern, + uint32 mb_intra) +{ + int code; + + switch (pict_code_type) { + case 1: + if ((motion_forw != 0) || (motion_back != 0) || (mb_pattern != 0) || (mb_intra != 1)) { + throw "Illegal parameters for macroblock type"; + } + if (mb_quant) { + Bitio_Write(bbPtr, 0x1, 2); + } else { + Bitio_Write(bbPtr, 0x1, 1); + } + break; + + case 2: + code = 0; + if (mb_quant) { + code += 16; + } + if (motion_forw) { + code += 8; + } + if (motion_back) { + code += 4; + } + if (mb_pattern) { + code += 2; + } + if (mb_intra) { + code += 1; + } + + switch (code) { + case 1: + Bitio_Write(bbPtr, 0x3, 5); + break; + case 2: + Bitio_Write(bbPtr, 0x1, 2); + break; + case 8: + Bitio_Write(bbPtr, 0x1, 3); + break; + case 10: + Bitio_Write(bbPtr, 0x1, 1); + break; + case 17: + Bitio_Write(bbPtr, 0x1, 6); + break; + case 18: + Bitio_Write(bbPtr, 0x1, 5); + break; + case 26: + Bitio_Write(bbPtr, 0x2, 5); + break; + default: + throw "Illegal parameters for macroblock type"; + break; + } + break; + + case 3: + code = 0; + if (mb_quant) { + code += 16; + } + if (motion_forw) { + code += 8; + } + if (motion_back) { + code += 4; + } + if (mb_pattern) { + code += 2; + } + if (mb_intra) { + code += 1; + } + + switch (code) { + case 12: + Bitio_Write(bbPtr, 0x2, 2); + break; + case 14: + Bitio_Write(bbPtr, 0x3, 2); + break; + case 4: + Bitio_Write(bbPtr, 0x2, 3); + break; + case 6: + Bitio_Write(bbPtr, 0x3, 3); + break; + case 8: + Bitio_Write(bbPtr, 0x2, 4); + break; + case 10: + Bitio_Write(bbPtr, 0x3, 4); + break; + case 1: + Bitio_Write(bbPtr, 0x3, 5); + break; + case 30: + Bitio_Write(bbPtr, 0x2, 5); + break; + case 26: + Bitio_Write(bbPtr, 0x3, 6); + break; + case 22: + Bitio_Write(bbPtr, 0x2, 6); + break; + case 17: + Bitio_Write(bbPtr, 0x1, 6); + break; + default: + throw "Illegal parameters for macroblock type"; + break; + } + break; + } +} + + +/*===========================================================================* + * + * GenMotionCode + * + * generate motion vector output with given value + * append result to the specified bitstream + * + * RETURNS: nothing + * + * SIDE EFFECTS: none + * + *===========================================================================*/ +static void +GenMotionCode(BitBucket *bbPtr, + int32 vector) +{ + uint32 code, num; + + if ((vector < -16) || (vector > 16)) { + throw "Motion vector out of range"; + } + code = mbMotionVectorTable[vector + 16][0]; + num = mbMotionVectorTable[vector + 16][1]; + + Bitio_Write(bbPtr, code, num); +} + + +/*===========================================================================* + * + * GenBlockPattern + * + * generate macroblock pattern output + * append result to the specified bitstream + * + * RETURNS: nothing + * + * SIDE EFFECTS: none + * + *===========================================================================*/ +static void +GenBlockPattern(BitBucket *bbPtr, + uint32 mb_pattern) +{ + uint32 code, num; + + code = mbPatTable[mb_pattern][0]; + num = mbPatTable[mb_pattern][1]; + + Bitio_Write(bbPtr, code, num); +} + + +/*===========================================================================* + * + * GenMBAddrIncr + * + * generate macroblock address increment output + * append result to the specified bitstream + * + * RETURNS: nothing + * + * SIDE EFFECTS: none + * + *===========================================================================*/ +static void +GenMBAddrIncr(BitBucket *bbPtr, + uint32 addr_incr) +{ + uint32 code; + uint32 num; + + code = mbAddrIncrTable[addr_incr][0]; + num = mbAddrIncrTable[addr_incr][1]; + + Bitio_Write(bbPtr, code, num); +} + + +/*===========================================================================* + * + * GenPictHead + * + * generate picture header with given attributes + * append result to the specified bitstream + * + * RETURNS: nothing + * + * SIDE EFFECTS: none + * + *===========================================================================*/ +static void +GenPictHead(BitBucket *bbPtr, + uint32 temp_ref, + uint32 code_type, + uint32 vbv_delay, + int32 full_pel_forw_flag, + uint32 forw_f_code, + int32 full_pel_back_flag, + uint32 back_f_code, + uint8 *extra_info, + uint32 extra_info_size, + uint8 *ext_data, + uint32 ext_data_size, + uint8 *user_data, + uint32 user_data_size) +{ + int i; + + /* Write picture start code. */ + Bitio_Write(bbPtr, PICT_START_CODE, 32); + + /* Temp reference. */ + Bitio_Write(bbPtr, temp_ref, 10); + + /* Code_type. */ + if (code_type == 0) { + code_type = 1; + } + Bitio_Write(bbPtr, code_type, 3); + + /* vbv_delay. */ + vbv_delay = 0xffff; /* see page 36 (section 2.4.3.4) */ + Bitio_Write(bbPtr, vbv_delay, 16); + + if ((code_type == 2) || (code_type == 3)) { + + /* Full pel forw flag. */ + + if (full_pel_forw_flag) { + Bitio_Write(bbPtr, 0x01, 1); + } else { + Bitio_Write(bbPtr, 0x00, 1); + } + + /* Forw f code. */ + + Bitio_Write(bbPtr, forw_f_code, 3); + } + if (code_type == 3) { + + /* Full pel back flag. */ + + if (full_pel_back_flag) { + Bitio_Write(bbPtr, 0x01, 1); + } else { + Bitio_Write(bbPtr, 0x00, 1); + } + + /* Back f code. */ + + Bitio_Write(bbPtr, back_f_code, 3); + } + /* Extra bit picture info. */ + + if (extra_info != NULL) { + for (i = 0; i < extra_info_size; i++) { + Bitio_Write(bbPtr, 0x01, 1); + Bitio_Write(bbPtr, extra_info[i], 8); + } + } + Bitio_Write(bbPtr, 0x00, 1); + + /* next start code */ + Bitio_BytePad(bbPtr); + + /* Write ext data if present. */ + + if (ext_data != NULL) { + Bitio_Write(bbPtr, EXT_START_CODE, 32); + + for (i = 0; i < ext_data_size; i++) { + Bitio_Write(bbPtr, ext_data[i], 8); + } + Bitio_BytePad(bbPtr); + } + /* Write user data if present. */ + if (user_data != NULL) { + Bitio_Write(bbPtr, USER_START_CODE, 32); + + for (i = 0; i < user_data_size; i++) { + Bitio_Write(bbPtr, user_data[i], 8); + } + Bitio_BytePad(bbPtr); + } +} + + +#ifdef UNUSED_PROCEDURES + +/* GenMBEnd only used for `D` pictures. Shouldn't really ever be called. */ +/* - dwallach */ +void +GenMBEnd(BitBucket *bbPtr) +{ + Bitio_Write(bbPtr, 0x01, 1); +} + +#endif /* UNUSED_PROCEDURES */ diff --git a/contrib/mpeg_encode/mpeg.cpp b/contrib/mpeg_encode/mpeg.cpp new file mode 100644 index 0000000000000000000000000000000000000000..cb548e6cb3965dd45301ae456ffee6d3a3eeb0eb --- /dev/null +++ b/contrib/mpeg_encode/mpeg.cpp @@ -0,0 +1,1635 @@ +/*===========================================================================* + * mpeg.c * + * * + * Procedures to generate the MPEG sequence * + * * + * EXPORTED PROCEDURES: * + * GetMPEGStream * + * IncrementTCTime * + * SetStatFileName * + * SetGOPSize * + * PrintStartStats * + * * + *===========================================================================*/ + +/* + * Copyright (c) 1995 The Regents of the University of California. + * All rights reserved. + * + * Permission to use, copy, modify, and distribute this software and its + * documentation for any purpose, without fee, and without written agreement is + * hereby granted, provided that the above copyright notice and the following + * two paragraphs appear in all copies of this software. + * + * IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR + * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT + * OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF + * CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS + * ON AN "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO + * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. + */ + +/* + * $Header: /n/picasso/project/mpeg/mpeg_dist/mpeg_encode/RCS/mpeg.c,v 1.24 1995/08/16 18:10:48 smoot Exp $ + * $Log: mpeg.c,v $ + * Revision 1.24 1995/08/16 18:10:48 smoot + * *** empty log message *** + * + * Revision 1.23 1995/08/07 21:48:08 smoot + * stdin bugs fixed + * + * Revision 1.22 1995/06/26 21:49:19 smoot + * added new frame ordering (hacks)^H^H^H^H^H code ;-) + * + * Revision 1.21 1995/06/21 18:30:41 smoot + * changed time structure to be ANSI + * changed file access to be binary (DOS!) + * added time to userdata + * Added a sleep to remote reads (NFS delay) + * + * Revision 1.20 1995/05/02 01:49:21 eyhung + * prints out true output bit rate and slightly untabified + * + * Revision 1.19 1995/05/02 00:45:35 eyhung + * endstats now contain correct output fbit rate at the specified frame rate + * + * Revision 1.18 1995/03/27 23:43:20 smoot + * killed printing long as int (compiler warning) + * + * Revision 1.17 1995/03/27 19:18:54 smoot + * fixed divide by zero for very quick encodings + * + * Revision 1.16 1995/02/02 22:03:37 smoot + * added types for MIPS + * + * Revision 1.15 1995/02/02 07:26:58 eyhung + * removed unused tempframe + * + * Revision 1.14 1995/02/01 05:01:35 eyhung + * Completed infinite coding-on-the-fly + * + * Revision 1.13 1995/02/01 02:34:02 eyhung + * Added full coding-on-the-fly + * + * Revision 1.12 1995/01/31 23:05:14 eyhung + * Added some stdin stuff + * + * Revision 1.11 1995/01/20 00:01:16 eyhung + * Added output file to PrintEndStats + * + * Revision 1.10 1995/01/19 23:08:51 eyhung + * Changed copyrights + * + * Revision 1.9 1995/01/17 18:55:54 smoot + * added right version number, and error if no frames selected + * + * Revision 1.8 1995/01/16 08:12:54 eyhung + * added realQuiet + * + * Revision 1.7 1994/12/07 00:40:36 smoot + * Added seperate P and B search ranges + * + * Revision 1.6 1994/11/28 21:46:45 smoot + * Added version printing + * + * Revision 1.5 1994/11/19 01:33:05 smoot + * put in userdata + * + * Revision 1.4 1994/11/14 22:36:22 smoot + * Merged specifics and rate control + * + * Revision 1.2 1994/03/15 00:27:11 keving + * nothing + * + * Revision 1.1 1993/12/22 19:19:01 keving + * nothing + * + * Revision 1.6 1993/07/22 22:23:43 keving + * nothing + * + * Revision 1.5 1993/06/30 20:06:09 keving + * nothing + * + * Revision 1.4 1993/06/03 21:08:08 keving + * nothing + * + * Revision 1.3 1993/02/19 18:10:12 keving + * nothing + * + * Revision 1.2 1993/02/17 23:18:20 dwallach + * checkin prior to keving's joining the project + * + */ + + +/*==============* + * HEADER FILES * + *==============*/ + +#include "all.h" +#include <time.h> +#include <errno.h> +#include <unistd.h> +#include "mtypes.h" +#include "frames.h" +#include "search.h" +#include "mpeg.h" +#include "prototypes.h" +#include "parallel.h" +#include "param.h" +#include "readframe.h" +#include "fsize.h" +#include "mheaders.h" +#include "rate.h" +#ifdef MIPS +#include <sys/types.h> +#endif +#include <sys/stat.h> + +/*===========* + * VERSION * + *===========*/ + +#define VERSION "1.5b" + + +/*===========* + * CONSTANTS * + *===========*/ + +#define FPS_30 0x5 /* from MPEG standard sect. 2.4.3.2 */ +#define ASPECT_1 0x1 /* aspect ratio, from MPEG standard sect. 2.4.3.2 */ + + +/*==================* + * STATIC VARIABLES * + *==================*/ + +static int32 diffTime; +static int framesOutput; +static int realStart, realEnd; +static int currentGOP; +static int timeMask; +static int numI, numP, numB; + + +/*==================* + * GLOBAL VARIABLES * + *==================*/ + +/* important -- don't initialize anything here */ +/* must be re-initted anyway in GenMPEGStream */ + +extern int IOtime; +extern boolean resizeFrame; +extern int outputWidth, outputHeight; +int gopSize = 100; /* default */ +int32 tc_hrs, tc_min, tc_sec, tc_pict, tc_extra; +int totalFramesSent; +int yuvWidth, yuvHeight; +int realWidth, realHeight; +char currentPath[MAXPATHLEN]; +char statFileName[256]; +char bitRateFileName[256]; +time_t timeStart, timeEnd; +FILE *statFile; +FILE *bitRateFile = NULL; +char *framePattern; +int framePatternLen; +int referenceFrame; +static int framesRead; +MpegFrame *pastRefFrame; +MpegFrame *futureRefFrame; +int frameRate = FPS_30; +int frameRateRounded = 30; +boolean frameRateInteger = TRUE; +int aspectRatio = ASPECT_1; +extern unsigned char userDataFileName[]; +extern int mult_seq_headers; + +int32 bit_rate, buf_size; + +/*===============================* + * INTERNAL PROCEDURE prototypes * + *===============================*/ + +static void ShowRemainingTime _ANSI_ARGS_((void)); +static void ComputeDHMSTime _ANSI_ARGS_((int32 someTime, char *timeText)); +static void ComputeGOPFrames _ANSI_ARGS_((int whichGOP, int *firstFrame, + int *lastFrame, int numFrames)); +static void PrintEndStats _ANSI_ARGS_((int inputFrameBits, int32 totalBits)); +static void ProcessRefFrame _ANSI_ARGS_((MpegFrame *frame, + BitBucket *bb, int lastFrame, + char *outputFileName)); +static void OpenBitRateFile _ANSI_ARGS_((void)); +static void CloseBitRateFile _ANSI_ARGS_((void)); + + +/*=====================* + * EXPORTED PROCEDURES * + *=====================*/ + +/*===========================================================================* + * + * SetReferenceFrameType + * + * set the reference frame type to be original or decoded + * + * RETURNS: nothing + * + * SIDE EFFECTS: referenceFrame + * + *===========================================================================*/ +void +SetReferenceFrameType(char *type) +{ + if ( strcmp(type, "ORIGINAL") == 0 ) { + referenceFrame = ORIGINAL_FRAME; + } else if ( strcmp(type, "DECODED") == 0 ) { + referenceFrame = DECODED_FRAME; + } else { + throw "Illegal reference frame type"; + } +} + +void +SetBitRateFileName(char *fileName) +{ + strcpy(bitRateFileName, fileName); +} + + +/*===========================================================================* + * + * GenMPEGStream + * + * generate an MPEG sequence stream (generally) + * if whichGOP == frameStart == -1 then does complete MPEG sequence + * if whichGOP != -1 then does numbered GOP only (without sequence + * header) + * if frameStart != -1 then does numbered frames only (without any + * sequence or GOP headers) + * + * RETURNS: amount of time it took + * + * SIDE EFFECTS: too numerous to mention + * + *===========================================================================*/ +int32 +GenMPEGStream(int whichGOP, + int frameStart, + int frameEnd, + int32 qtable[], + int32 niqtable[], + int numFrames, + FILE *ofp, + char *outputFileName) +{ + extern void PrintItoIBitRate _ANSI_ARGS_((int numBits, int frameNum)); + BitBucket *bb; + int i; + char frameType; + MpegFrame *frame = NULL; + MpegFrame *tempFrame; + int firstFrame, lastFrame; + int inputFrameBits = 0; + char inputFileName[1024]; + time_t tempTimeStart, tempTimeEnd; + boolean firstFrameDone = FALSE; + int numBits; + int32 bitstreamMode, res; + + if ( (whichGOP == -1) && (frameStart == -1) && + (! stdinUsed) && (FType_Type(numFrames-1) == 'b') ) { + fprintf(stderr, "\n"); + fprintf(stderr, "WARNING: One or more B-frames at end will not be encoded.\n"); + fprintf(stderr, " See FORCE_ENCODE_LAST_FRAME option in man page.\n"); + fprintf(stderr, "\n"); + } + + time(&timeStart); + + framesRead = 0; + + ResetIFrameStats(); + ResetPFrameStats(); + ResetBFrameStats(); + + Fsize_Reset(); + + framesOutput = 0; + + if ( childProcess && separateConversion ) { + SetFileType(slaveConversion); + } else { + SetFileType(inputConversion); + } + + if ( whichGOP != -1 ) { + ComputeGOPFrames(whichGOP, &firstFrame, &lastFrame, numFrames); + + realStart = firstFrame; + realEnd = lastFrame; + + if ( FType_Type(firstFrame) == 'b' ) { + + /* can't find the previous frame interactively */ + if ( stdinUsed ) { + throw "Cannot encode GOP from stdin when first frame is a B-frame"; + } + + /* need to load in previous frame; call it an I frame */ + frame = Frame_New(firstFrame-1, 'i'); + + time(&tempTimeStart); + + if ( (referenceFrame == DECODED_FRAME) && + childProcess ) { + WaitForDecodedFrame(firstFrame); + + if ( remoteIO ) { + GetRemoteDecodedRefFrame(frame, firstFrame-1); + } else { + ReadDecodedRefFrame(frame, firstFrame-1); + } + } else { + if ( remoteIO ) { + GetRemoteFrame(frame, firstFrame-1); + } else { + GetNthInputFileName(inputFileName, firstFrame-1); + + if ( childProcess && separateConversion ) { + ReadFrame(frame, inputFileName, slaveConversion, TRUE); + } else { + ReadFrame(frame, inputFileName, inputConversion, TRUE); + } + } + } + + framesRead++; + + time(&tempTimeEnd); + IOtime += (tempTimeEnd-tempTimeStart); + } + } else if ( frameStart != -1 ) { + if ( frameEnd > numFrames-1 ) { + throw "Specified last frame is out of bounds"; + } + + realStart = frameStart; + realEnd = frameEnd; + + firstFrame = frameStart; + lastFrame = frameEnd; + + /* if first frame is P or B, need to read in P or I frame before it */ + if ( FType_Type(firstFrame) != 'i' ) { + + /* can't find the previous frame interactively */ + if ( stdinUsed ) { + throw "Cannot encode frames from stdin when first frame is not an I-frame"; + } + + firstFrame = FType_PastRef(firstFrame); + } + + /* if last frame is B, need to read in P or I frame after it */ + if ( (FType_Type(lastFrame) == 'b') && (lastFrame != numFrames-1) ) { + + /* can't find the next reference frame interactively */ + if ( stdinUsed ) { + throw "Cannot encode frames from stdin when last frame is a B-frame"; + } + + lastFrame = FType_FutureRef(lastFrame); + } + + if ( lastFrame > numFrames-1 ) { /* can't go last frame! */ + lastFrame = numFrames-1; + } + + } else { + firstFrame = 0; + lastFrame = numFrames-1; + + realStart = 0; + realEnd = numFrames-1; + if ( numFrames == 0 ) { + throw "No frames selected!"; + } + } + + /* count number of I, P, and B frames */ + numI = 0; numP = 0; numB = 0; + timeMask = 0; + if (stdinUsed) { + numI = numP = numB = MAXINT/4; + } else { + for ( i = firstFrame; i <= lastFrame; i++ ) { + frameType = FType_Type(i); + switch(frameType) { + case 'i': numI++; timeMask |= 0x1; break; + case 'p': numP++; timeMask |= 0x2; break; + case 'b': numB++; timeMask |= 0x4; break; + } + } + } + + if ( ! childProcess ) { + if ( showBitRatePerFrame ) + OpenBitRateFile(); + PrintStartStats(realStart, realEnd); + } + + if ( frameStart == -1 ) { + bb = Bitio_New(ofp); + } else { + bb = NULL; + } + + tc_hrs = 0; tc_min = 0; tc_sec = 0; tc_pict = 0; tc_extra = 0; + for ( i = 0; i < firstFrame; i++ ) { + IncrementTCTime(); + } + + totalFramesSent = firstFrame; + currentGOP = gopSize; /* so first I-frame generates GOP Header */ + + /* Rate Control Initialization */ + bitstreamMode = getRateMode(); + if (bitstreamMode == FIXED_RATE) { + res = initRateControl(); + /* + SetFrameRate(); + */ + } + +#ifdef BLEAH +fprintf(stdout, "firstFrame, lastFrame = %d, %d; real = %d, %d\n", + firstFrame, lastFrame, realStart, realEnd); +fflush(stdout); +#endif + + pastRefFrame = NULL; + futureRefFrame = NULL; + for ( i = firstFrame; i <= lastFrame; i++) { + + /* break out of the near-infinite loop if input from stdin is done */ +#if 0 + char eofcheck[1]; + if ( stdinUsed ) { + if (scanf("%c", eofcheck) != EOF) { + ungetc(eofcheck[0], stdin); + } else { + break; + } + } +#else + /* + ** For some reason the above version of this stdin EOF check does not + ** work right with jpeg files, the ungetc() is not padding anything to + ** stdin, I have no idea why (perhaps because a char is passed instead + ** of an int?), and it drove me nuts, so I wrote my own, slightly + ** cleaner version, and this one seems to work. + ** Dave Scott (dhs), UofO, 7/19/95. + */ + if ( stdinUsed) { + int eofcheck_; + eofcheck_ = fgetc(stdin); + if ( eofcheck_ == EOF) + break; + else + ungetc(eofcheck_, stdin); + } +#endif + frameType = FType_Type(i); + + time(&tempTimeStart); + + /* skip non-reference frames if non-interactive + * read in non-reference frames if interactive */ + if ( frameType == 'b' ) { + if ( stdinUsed ) { + frame = Frame_New(i, frameType); + ReadFrame(frame, (char*)"stdin", inputConversion, TRUE); + + framesRead++; + + time(&tempTimeEnd); + IOtime += (tempTimeEnd-tempTimeStart); + + /* Add the B frame to the end of the queue of B-frames + * for later encoding + */ + + if (futureRefFrame != NULL) { + tempFrame = futureRefFrame; + while (tempFrame->next != NULL) { + tempFrame = tempFrame->next; + } + tempFrame->next = frame; + } else { + fprintf(stderr, "Yow, something wrong in neverland! (hit bad code in mpeg.c\n"); + } + } + continue; + } + + frame = Frame_New(i, frameType); + + pastRefFrame = futureRefFrame; + futureRefFrame = frame; + + if ( (referenceFrame == DECODED_FRAME) && + ((i < realStart) || (i > realEnd)) ) { + WaitForDecodedFrame(i); + + if ( remoteIO ) { + GetRemoteDecodedRefFrame(frame, i); + } else { + ReadDecodedRefFrame(frame, i); + } + } else { + if ( remoteIO ) { + GetRemoteFrame(frame, i); + } else { + GetNthInputFileName(inputFileName, i); + if ( childProcess && separateConversion ) { + ReadFrame(frame, inputFileName, slaveConversion, TRUE); + } else { + ReadFrame(frame, inputFileName, inputConversion, TRUE); + } + } + } + + framesRead++; + + time(&tempTimeEnd); + IOtime += (tempTimeEnd-tempTimeStart); + + if ( ! firstFrameDone ) { + char *userData = (char *)NULL; + int userDataSize = 0; + + inputFrameBits = 24*Fsize_x*Fsize_y; + SetBlocksPerSlice(); + + if ( (whichGOP == -1) && (frameStart == -1) ) { + DBG_PRINT(("Generating sequence header\n")); + bitstreamMode = getRateMode(); + if (bitstreamMode == FIXED_RATE) { + bit_rate = getBitRate(); + buf_size = getBufferSize(); + } + else { + bit_rate = -1; + buf_size = -1; + } + + if (strlen((char*)userDataFileName) != 0) { + struct stat statbuf; + FILE *fp; + + stat((char*)userDataFileName,&statbuf); + userDataSize = statbuf.st_size; + userData = (char*)malloc(userDataSize); + if ((fp = fopen((char*)userDataFileName,"rb")) == NULL) { + fprintf(stderr,"Could not open userdata file-%s.\n", + userDataFileName); + userData = NULL; + userDataSize = 0; + goto write; + } + if (fread(userData,1,userDataSize,fp) != userDataSize) { + fprintf(stderr,"Could not read %d bytes from userdata file-%s.\n", + userDataSize,userDataFileName); + userData = NULL; + userDataSize = 0; + goto write; + } + } else { /* Put in our UserData Header */ + time_t now; + + time(&now); + userData = (char*)malloc(100); + sprintf(userData,"MPEG stream encoded by UCB Encoder (mpeg_encode) v%s on %s.", + VERSION, ctime(&now)); + userDataSize = strlen(userData); + } + write: + Mhead_GenSequenceHeader(bb, Fsize_x, Fsize_y, + /* pratio */ aspectRatio, + /* pict_rate */ frameRate, /* bit_rate */ bit_rate, + /* buf_size */ buf_size, /*c_param_flag */ 1, + /* iq_matrix */ qtable, /* niq_matrix */ niqtable, + /* ext_data */ NULL, /* ext_data_size */ 0, + /* user_data */ (uint8*)userData, /* user_data_size */ userDataSize); + } + + firstFrameDone = TRUE; + } + + ProcessRefFrame(frame, bb, lastFrame, outputFileName); + + } + + if ( frame != NULL ) { + Frame_Free(frame); + } + + /* SEQUENCE END CODE */ + if ( (whichGOP == -1) && (frameStart == -1) ) { + Mhead_GenSequenceEnder(bb); + } + + if ( frameStart == -1 ) { + /* I think this is right, since (bb == NULL) if (frameStart != -1). + See above where "bb" is initialized */ + numBits = bb->cumulativeBits; + } else { + /* What should the correct value be? Most likely 1. "numBits" is + used below, so we need to make sure it's properly initialized + to somthing (anything). */ + numBits = 1; + } + + if ( frameStart == -1 ) { + Bitio_Flush(bb); + bb = NULL; + fclose(ofp); + + time(&timeEnd); + diffTime = (int32)(timeEnd-timeStart); + + if ( ! childProcess ) { + PrintEndStats(inputFrameBits, numBits); + } + } else { + time(&timeEnd); + diffTime = (int32)(timeEnd-timeStart); + + if ( ! childProcess ) { + PrintEndStats(inputFrameBits, 1); + } + } + + if ( FType_Type(realEnd) != 'i' ) { + PrintItoIBitRate(numBits, realEnd+1); + } + + if ( (! childProcess) && showBitRatePerFrame ) + CloseBitRateFile(); + +#ifdef BLEAH + if ( childProcess ) { + NoteFrameDone(frameStart, frameEnd); + } +#endif + + if (! realQuiet) { + fprintf(stdout, "======FRAMES READ: %d\n", framesRead); + fflush(stdout); + } + + return diffTime; +} + + +/*===========================================================================* + * + * IncrementTCTime + * + * increment the tc time by one second (and update min, hrs if necessary) + * also increments totalFramesSent + * + * RETURNS: nothing + * + * SIDE EFFECTS: totalFramesSent, tc_pict, tc_sec, tc_min, tc_hrs, tc_extra + * + *===========================================================================*/ +void +IncrementTCTime() +{ + /* if fps = an integer, then tc_extra = 0 and is ignored + + otherwise, it is the number of extra 1/1001 frames we've passed by + + so far; for example, if fps = 24000/1001, then 24 frames = 24024/24000 + seconds = 1 second + 24/24000 seconds = 1 + 1/1000 seconds; similary, + if fps = 30000/1001, then 30 frames = 30030/30000 = 1 + 1/1000 seconds + and if fps = 60000/1001, then 60 frames = 1 + 1/1000 seconds + + if fps = 24000/1001, then 1/1000 seconds = 24/1001 frames + if fps = 30000/1001, then 1/1000 seconds = 30/1001 frames + if fps = 60000/1001, then 1/1000 seconds = 60/1001 frames + */ + + totalFramesSent++; + tc_pict++; + if ( tc_pict >= frameRateRounded ) { + tc_pict = 0; + tc_sec++; + if ( tc_sec == 60 ) { + tc_sec = 0; + tc_min++; + if ( tc_min == 60 ) { + tc_min = 0; + tc_hrs++; + } + } + if ( ! frameRateInteger ) { + tc_extra += frameRateRounded; + if ( tc_extra >= 1001 ) { /* a frame's worth */ + tc_pict++; + tc_extra -= 1001; + } + } + } +} + + +/*===========================================================================* + * + * SetStatFileName + * + * set the statistics file name + * + * RETURNS: nothing + * + * SIDE EFFECTS: statFileName + * + *===========================================================================*/ +void +SetStatFileName(char *fileName) +{ + strcpy(statFileName, fileName); +} + + +/*===========================================================================* + * + * SetGOPSize + * + * set the GOP size (frames per GOP) + * + * RETURNS: nothing + * + * SIDE EFFECTS: gopSize + * + *===========================================================================*/ +void +SetGOPSize(int size) +{ + gopSize = size; +} + + +/*===========================================================================* + * + * PrintStartStats + * + * print out the starting statistics (stuff from the param file) + * firstFrame, lastFrame represent the first, last frames to be + * encoded + * + * RETURNS: nothing + * + * SIDE EFFECTS: none + * + *===========================================================================*/ +void +PrintStartStats(int firstFrame, + int lastFrame) +{ + FILE *fpointer; + register int i; + char inputFileName[1024]; + + if ( statFileName[0] == '\0' ) { + statFile = NULL; + } else { + statFile = fopen(statFileName, "a"); /* open for appending */ + if ( statFile == NULL ) { + fprintf(stderr, "ERROR: Could not open stat file: %s\n", statFileName); + fprintf(stderr, " Sending statistics to stdout only.\n"); + fprintf(stderr, "\n\n"); + } else if (! realQuiet) { + fprintf(stdout, "Appending statistics to file: %s\n", statFileName); + fprintf(stdout, "\n\n"); + } + } + + for ( i = 0; i < 2; i++ ) { + if ( ( i == 0 ) && (! realQuiet) ) { + fpointer = stdout; + } else if ( statFile != NULL ) { + fpointer = statFile; + } else { + continue; + } + + fprintf(fpointer, "MPEG ENCODER STATS (%s)\n",VERSION); + fprintf(fpointer, "------------------------\n"); + fprintf(fpointer, "TIME STARTED: %s", ctime(&timeStart)); + if ( getenv("HOST") != NULL ) { + fprintf(fpointer, "MACHINE: %s\n", getenv("HOST")); + } else { + fprintf(fpointer, "MACHINE: unknown\n"); + } + + if ( stdinUsed ) { + fprintf(fpointer, "INPUT: stdin\n"); + } + + + if ( firstFrame == -1 ) { + fprintf(fpointer, "OUTPUT: %s\n", outputFileName); + } else if ( ! stdinUsed ) { + GetNthInputFileName(inputFileName, firstFrame); + fprintf(fpointer, "FIRST FILE: %s/%s\n", currentPath, inputFileName); + GetNthInputFileName(inputFileName, lastFrame); + fprintf(fpointer, "LAST FILE: %s/%s\n", currentPath, + inputFileName); + } + if ( resizeFrame ) + fprintf(fpointer, "RESIZED TO: %dx%d\n", + outputWidth, outputHeight); + fprintf(fpointer, "PATTERN: %s\n", framePattern); + fprintf(fpointer, "GOP_SIZE: %d\n", gopSize); + fprintf(fpointer, "SLICES PER FRAME: %d\n", slicesPerFrame); + if (searchRangeP==searchRangeB) + fprintf(fpointer, "RANGE: +/-%d\n", searchRangeP/2); + else fprintf(fpointer, "RANGES: +/-%d %d\n", + searchRangeP/2,searchRangeB/2); + fprintf(fpointer, "PIXEL SEARCH: %s\n", pixelFullSearch ? "FULL" : "HALF"); + fprintf(fpointer, "PSEARCH: %s\n", PSearchName()); + fprintf(fpointer, "BSEARCH: %s\n", BSearchName()); + fprintf(fpointer, "QSCALE: %d %d %d\n", qscaleI, + GetPQScale(), GetBQScale()); + if (specificsOn) + fprintf(fpointer, "(Except as modified by Specifics file)\n"); + if ( referenceFrame == DECODED_FRAME ) { + fprintf(fpointer, "REFERENCE FRAME: DECODED\n"); + } else if ( referenceFrame == ORIGINAL_FRAME ) { + fprintf(fpointer, "REFERENCE FRAME: ORIGINAL\n"); + } else { + throw "Illegal referenceFrame!!!"; + } + /* For new Rate control parameters */ + if (getRateMode() == FIXED_RATE) { + fprintf(fpointer, "PICTURE RATE: %d\n", frameRateRounded); + if (getBitRate() != -1) { + fprintf(fpointer, "\nBIT RATE: %d\n", getBitRate()); + } + if (getBufferSize() != -1) { + fprintf(fpointer, "BUFFER SIZE: %d\n", getBufferSize()); + } + } + } + if (! realQuiet) { + fprintf(stdout, "\n\n"); + } +} + + +/*===========================================================================* + * + * NonLocalRefFrame + * + * decides if this frame can be referenced from a non-local process + * + * RETURNS: TRUE or FALSE + * + * SIDE EFFECTS: none + * + *===========================================================================*/ +boolean +NonLocalRefFrame(int id) +{ + int lastIPid; + int nextIPid; + + if ( ! childProcess ) { + return FALSE; + } + + lastIPid = FType_PastRef(id); + + /* might be accessed by B-frame */ + if ( lastIPid+1 < realStart ) { + return TRUE; + } + + /* if B-frame is out of range, then current frame can be ref'd by it */ + nextIPid = FType_FutureRef(id); + + /* might be accessed by B-frame */ + if ( nextIPid-1 > realEnd ) { + return TRUE; + } + + /* might be accessed by P-frame */ + if ( (nextIPid > realEnd) && (FType_Type(nextIPid) == 'p') ) { + return TRUE; + } + + return FALSE; +} + + + +/*===========================================================================* + * + * SetFrameRate + * + * sets global frame rate variables. value passed is MPEG frame rate code. + * + * RETURNS: TRUE or FALSE + * + * SIDE EFFECTS: frameRateRounded, frameRateInteger + * + *===========================================================================*/ +void +SetFrameRate() +{ + switch(frameRate) { + case 1: + frameRateRounded = 24; + frameRateInteger = FALSE; + break; + case 2: + frameRateRounded = 24; + frameRateInteger = TRUE; + break; + case 3: + frameRateRounded = 25; + frameRateInteger = TRUE; + break; + case 4: + frameRateRounded = 30; + frameRateInteger = FALSE; + break; + case 5: + frameRateRounded = 30; + frameRateInteger = TRUE; + break; + case 6: + frameRateRounded = 50; + frameRateInteger = TRUE; + break; + case 7: + frameRateRounded = 60; + frameRateInteger = FALSE; + break; + case 8: + frameRateRounded = 60; + frameRateInteger = TRUE; + break; + } + printf("frame rate(%d) set to %d\n", frameRate, frameRateRounded); +} + + +/*=====================* + * INTERNAL PROCEDURES * + *=====================*/ + +/*===========================================================================* + * + * ComputeDHMSTime + * + * turn some number of seconds (someTime) into a string which + * summarizes that time according to scale (days, hours, minutes, or + * seconds) + * + * RETURNS: nothing + * + * SIDE EFFECTS: none + * + *===========================================================================*/ +static void +ComputeDHMSTime(int32 someTime, + char *timeText) +{ + int days, hours, mins, secs; + + days = someTime / (24*60*60); + someTime -= days*24*60*60; + hours = someTime / (60*60); + someTime -= hours*60*60; + mins = someTime / 60; + secs = someTime - mins*60; + + if ( days > 0 ) { + sprintf(timeText, "Total time: %d days and %d hours", days, hours); + } else if ( hours > 0 ) { + sprintf(timeText, "Total time: %d hours and %d minutes", hours, mins); + } else if ( mins > 0 ) { + sprintf(timeText, "Total time: %d minutes and %d seconds", mins, secs); + } else { + sprintf(timeText, "Total time: %d seconds", secs); + } +} + + +/*===========================================================================* + * + * ComputeGOPFrames + * + * calculate the first, last frames of the numbered GOP + * + * RETURNS: lastFrame, firstFrame changed + * + * SIDE EFFECTS: none + * + *===========================================================================*/ +static void +ComputeGOPFrames(int whichGOP, + int *firstFrame, + int *lastFrame, + int numFrames) +{ + int passedB; + int currGOP; + int gopNum, frameNum; + + /* calculate first, last frames of whichGOP GOP */ + + *firstFrame = -1; + *lastFrame = -1; + gopNum = 0; + frameNum = 0; + passedB = 0; + currGOP = 0; + while ( *lastFrame == -1 ) { + if ( frameNum >= numFrames ) { + throw "There aren't that many GOPs!"; + } + +#ifdef BLEAH +if (! realQuiet) { +fprintf(stdout, "GOP STARTS AT %d\n", frameNum-passedB); +} +#endif + + if ( gopNum == whichGOP ) { + *firstFrame = frameNum; + } + + /* go past one gop */ + /* must go past at least one frame */ + do { + currGOP += (1 + passedB); + + frameNum++; + + passedB = 0; + while ( (frameNum < numFrames) && (FType_Type(frameNum) == 'b') ) { + frameNum++; + passedB++; + } + } while ( (frameNum < numFrames) && + ((FType_Type(frameNum) != 'i') || (currGOP < gopSize)) ); + + currGOP -= gopSize; + + if ( gopNum == whichGOP ) { + *lastFrame = (frameNum-passedB-1); + } + +#ifdef BLEAH +if (! realQuiet) { +fprintf(stdout, "GOP ENDS at %d\n", frameNum-passedB-1); +} +#endif + + gopNum++; + } +} + + +/*===========================================================================* + * + * PrintEndStats + * + * print end statistics (summary, time information) + * + * RETURNS: nothing + * + * SIDE EFFECTS: none + * + *===========================================================================*/ +static void +PrintEndStats(int inputFrameBits, + int32 totalBits) +{ + FILE *fpointer; + register int i; + char timeText[256]; + float totalCPU; + + if (! realQuiet) { + fprintf(stdout, "\n\n"); + } + + ComputeDHMSTime(diffTime, timeText); + + for ( i = 0; i < 2; i++ ) { + if ( ( i == 0 ) && (! realQuiet) ) { + fpointer = stdout; + } else if ( statFile != NULL ) { + fpointer = statFile; + } else { + continue; + } + + fprintf(fpointer, "TIME COMPLETED: %s", ctime(&timeEnd)); + fprintf(fpointer, "%s\n\n", timeText); + + totalCPU = 0.0; + totalCPU += ShowIFrameSummary(inputFrameBits, totalBits, fpointer); + totalCPU += ShowPFrameSummary(inputFrameBits, totalBits, fpointer); + totalCPU += ShowBFrameSummary(inputFrameBits, totalBits, fpointer); + fprintf(fpointer, "---------------------------------------------\n"); + fprintf(fpointer, "Total Compression: %3d:1 (%9.4f bpp)\n", + framesOutput*inputFrameBits/totalBits, + 24.0*(float)(totalBits)/(float)(framesOutput*inputFrameBits)); + if (diffTime > 0) { + fprintf(fpointer, "Total Frames Per Second: %f (%ld mps)\n", + (float)framesOutput/(float)diffTime, + (long)((float)framesOutput*(float)inputFrameBits/(256.0*24.0*(float)diffTime))); + } else { + fprintf(fpointer, "Total Frames Per Second: Infinite!\n"); + } + if ( totalCPU == 0.0 ) { + fprintf(fpointer, "CPU Time: NONE!\n"); + } else { + fprintf(fpointer, "CPU Time: %f fps (%ld mps)\n", + (float)framesOutput/totalCPU, + (long)((float)framesOutput*(float)inputFrameBits/(256.0*24.0*totalCPU))); + } + fprintf(fpointer, "Total Output Bit Rate (%d fps): %d bits/sec\n", + frameRateRounded, frameRateRounded*totalBits/framesOutput); + fprintf(fpointer, "MPEG file created in : %s\n", outputFileName); + fprintf(fpointer, "\n\n"); + + if ( computeMVHist ) { + ShowPMVHistogram(fpointer); + ShowBBMVHistogram(fpointer); + ShowBFMVHistogram(fpointer); + } + } + + if ( statFile != NULL ) { + fclose(statFile); + } +} + + +/*===========================================================================* + * + * ProcessRefFrame + * + * process an I or P frame -- encode it, and process any B frames that + * we can now + * + * RETURNS: nothing + * + * SIDE EFFECTS: stuff appended to bb + * + *===========================================================================*/ +static void +ProcessRefFrame(MpegFrame *frame, + BitBucket *bb, + int lastFrame, + char *outputFileName) +{ + MpegFrame *bFrame = NULL; + char fileName[1024]; + char inputFileName[1024]; + FILE *fpointer = NULL; + boolean separateFiles; + int id; + time_t tempTimeStart, tempTimeEnd; + + separateFiles = (bb == NULL); + + if ( separateFiles && (frame->id >= realStart) && + (frame->id <= realEnd) ) { + if ( remoteIO ) { + bb = Bitio_New(NULL); + } else { + sprintf(fileName, "%s.frame.%d", outputFileName, frame->id); + if ( (fpointer = fopen(fileName, "wb")) == NULL ) { + throw "Could not open output file"; + } + + bb = Bitio_New(fpointer); + } + } + + /* nothing to do */ + if ( frame->id < realStart ) { + return; + } + + /* first, output this frame */ + if ( frame->type == TYPE_IFRAME ) { + +#ifdef BLEAH + fprintf(stdout, "I-frame %d, currentGOP = %d\n", + frame->id, currentGOP); + fflush(stdout); +#endif + + /* only start a new GOP with I */ + /* don't start GOP if only doing frames */ + if ( (! separateFiles) && (currentGOP >= gopSize) ) { + int closed; + static int num_gop = 0; + + /* first, check to see if closed GOP */ + if ( totalFramesSent == frame->id || pastRefFrame == NULL) { + closed = 1; + } else { + closed = 0; + } + + /* new GOP */ + if (num_gop != 0 && mult_seq_headers && num_gop % mult_seq_headers == 0) { + if (! realQuiet) { + fprintf(stdout, "Creating new Sequence before GOP %d\n", num_gop); + fflush(stdout); + } + + Mhead_GenSequenceHeader(bb, Fsize_x, Fsize_y, + /* pratio */ aspectRatio, + /* pict_rate */ frameRate, /* bit_rate */ bit_rate, + /* buf_size */ buf_size, /* c_param_flag */ 1, + /* iq_matrix */ customQtable, /* niq_matrix */ customNIQtable, + /* ext_data */ NULL, /* ext_data_size */ 0, + /* user_data */ NULL, /* user_data_size */ 0); + } + + if (! realQuiet) { + fprintf(stdout, "Creating new GOP (closed = %c) before frame %d\n", + "FT"[closed], frame->id); + fflush(stdout); + } + + num_gop++; + Mhead_GenGOPHeader(bb, /* drop_frame_flag */ 0, + tc_hrs, tc_min, tc_sec, tc_pict, + closed, /* broken_link */ 0, + /* ext_data */ NULL, /* ext_data_size */ 0, + /* user_data */ NULL, /* user_data_size */ 0); + currentGOP -= gopSize; + if (pastRefFrame == NULL) { + SetGOPStartTime(0); + } else { + SetGOPStartTime(pastRefFrame->id+1); + } + } + + if ( (frame->id >= realStart) && (frame->id <= realEnd) ) { + GenIFrame(bb, frame); + + framesOutput++; + + if ( separateFiles ) { + if ( remoteIO ) { + SendRemoteFrame(frame->id, bb); + } else { + Bitio_Flush(bb); + fclose(fpointer); + } + } + } + + numI--; + timeMask &= 0x6; + + currentGOP++; + IncrementTCTime(); + } else { + if ( (frame->id >= realStart) && (frame->id <= realEnd) ) { + GenPFrame(bb, frame, pastRefFrame); + + framesOutput++; + + if ( separateFiles ) { + if ( remoteIO ) { + SendRemoteFrame(frame->id, bb); + } else { + Bitio_Flush(bb); + fclose(fpointer); + } + } + } + + numP--; + timeMask &= 0x5; + ShowRemainingTime(); + + currentGOP++; + IncrementTCTime(); + } + + /* now, output B-frames */ + if ( pastRefFrame != NULL ) { + for ( id = pastRefFrame->id+1; id < futureRefFrame->id; id++ ) { + if ( ! ((id >= realStart) && (id <= realEnd)) ) + continue; + + if ( ! stdinUsed ) { + bFrame = Frame_New(id, 'b'); + + time(&tempTimeStart); + + /* read B frame, output it */ + if ( remoteIO ) { + GetRemoteFrame(bFrame, bFrame->id); + } else { + GetNthInputFileName(inputFileName, id); + if ( childProcess && separateConversion ) { + ReadFrame(bFrame, inputFileName, slaveConversion, TRUE); + } else { + ReadFrame(bFrame, inputFileName, inputConversion, TRUE); + } + } + + time(&tempTimeEnd); + IOtime += (tempTimeEnd-tempTimeStart); + + framesRead++; + } else { + + /* retrieve and remove B-frame from queue set up in + * GenMPEGStream + */ + bFrame = pastRefFrame->next; + pastRefFrame->next = bFrame->next; + } + + + if ( separateFiles ) { + if ( remoteIO ) { + bb = Bitio_New(NULL); + } else { + sprintf(fileName, "%s.frame.%d", outputFileName, + bFrame->id); + if ( (fpointer = fopen(fileName, "wb")) == NULL ) { + throw "Could not open output file"; + } + bb = Bitio_New(fpointer); + } + } + + GenBFrame(bb, bFrame, pastRefFrame, futureRefFrame); + framesOutput++; + + if ( separateFiles ) { + if ( remoteIO ) { + SendRemoteFrame(bFrame->id, bb); + } else { + Bitio_Flush(bb); + fclose(fpointer); + } + } + + /* free this B frame right away */ + Frame_Free(bFrame); + + numB--; + timeMask &= 0x3; + ShowRemainingTime(); + + currentGOP++; + IncrementTCTime(); + } + } else { + /* SRS replicated code */ + for ( id = 0; id < futureRefFrame->id; id++ ) { + if ( ! ((id >= realStart) && (id <= realEnd)) ) + continue; + + if ( ! stdinUsed ) { + bFrame = Frame_New(id, 'b'); + + time(&tempTimeStart); + + /* read B frame, output it */ + if ( remoteIO ) { + GetRemoteFrame(bFrame, bFrame->id); + } else { + GetNthInputFileName(inputFileName, id); + if ( childProcess && separateConversion ) { + ReadFrame(bFrame, inputFileName, slaveConversion, TRUE); + } else { + ReadFrame(bFrame, inputFileName, inputConversion, TRUE); + } + } + + time(&tempTimeEnd); + IOtime += (tempTimeEnd-tempTimeStart); + + framesRead++; + } else { + + /* retrieve and remove B-frame from queue set up in + * GenMPEGStream + */ + printf("Yow, I doubt this works!\n"); + bFrame = pastRefFrame->next; + pastRefFrame->next = bFrame->next; + } + + + if ( separateFiles ) { + if ( remoteIO ) { + bb = Bitio_New(NULL); + } else { + sprintf(fileName, "%s.frame.%d", outputFileName, + bFrame->id); + if ( (fpointer = fopen(fileName, "wb")) == NULL ) { + throw "Could not open output file"; + } + bb = Bitio_New(fpointer); + } + } + + GenBFrame(bb, bFrame, (MpegFrame *)NULL, futureRefFrame); + framesOutput++; + + if ( separateFiles ) { + if ( remoteIO ) { + SendRemoteFrame(bFrame->id, bb); + } else { + Bitio_Flush(bb); + fclose(fpointer); + } + } + + /* free this B frame right away */ + Frame_Free(bFrame); + + numB--; + timeMask &= 0x3; + ShowRemainingTime(); + + currentGOP++; + IncrementTCTime(); + } + + } + + /* now free previous frame, if there was one */ + if ( pastRefFrame != NULL ) { + Frame_Free(pastRefFrame); + } + + /* note, we may still not free last frame if lastFrame is incorrect + * (if the last frames are B frames, they aren't output!) + */ +} + + +/*===========================================================================* + * + * ShowRemainingTime + * + * print out an estimate of the time left to encode + * + * RETURNS: nothing + * + * SIDE EFFECTS: none + * + *===========================================================================*/ +static void +ShowRemainingTime() +{ + static int lastTime = 0; + float total; + time_t nowTime; + float secondsPerFrame; + + if ( childProcess ) { + return /* nothing */; + } + + if ( numI + numP + numB == 0 ) { /* no time left */ + return /* nothing */ ; + } + + if ( timeMask != 0 ) { /* haven't encoded all types yet */ + return /* nothing */ ; + } + + time(&nowTime); + secondsPerFrame = (nowTime-timeStart)/(float)framesOutput; + total = secondsPerFrame*(float)(numI+numP+numB); + +#ifdef BLEAH + float timeI, timeP, timeB; + + timeI = EstimateSecondsPerIFrame(); + timeP = EstimateSecondsPerPFrame(); + timeB = EstimateSecondsPerBFrame(); + total = (float)numI*timeI + (float)numP*timeP + (float)numB*timeB; +#endif + + if ( (quietTime >= 0) && (! realQuiet) && (! stdinUsed) && + ((lastTime < (int)total) || ((lastTime-(int)total) >= quietTime) || + (lastTime == 0) || (quietTime == 0)) ) { + if ( total > 270.0 ) { + fprintf(stdout, "ESTIMATED TIME OF COMPLETION: %d minutes\n", + ((int)total+30)/60); + } else { + fprintf(stdout, "ESTIMATED TIME OF COMPLETION: %d seconds\n", + (int)total); + } + + lastTime = (int)total; + } +} + + +void +ReadDecodedRefFrame(MpegFrame *frame, + int frameNumber) +{ + FILE *fpointer; + char fileName[256]; + int width, height; + register int y; + + width = Fsize_x; + height = Fsize_y; + + sprintf(fileName, "%s.decoded.%d", outputFileName, frameNumber); + if (! realQuiet) { + fprintf(stdout, "reading %s\n", fileName); + fflush(stdout); + } + + if ((fpointer = fopen(fileName, "rb")) == NULL) { + sleep(1); + if ((fpointer = fopen(fileName, "rb")) == NULL) { + throw "Cannot open file"; + }} + + Frame_AllocDecoded(frame, TRUE); + + for ( y = 0; y < height; y++ ) { + if (fread(frame->decoded_y[y], 1, width, fpointer) != width) { + fprintf(stderr, "Could not read enough bytes from %s\n", fileName); + } + } + + for (y = 0; y < (height >> 1); y++) { /* U */ + if (fread(frame->decoded_cb[y], 1, width >> 1, fpointer) != (width>>1)) { + fprintf(stderr, "Could not read enough bytes from %s\n", fileName); + } + } + + for (y = 0; y < (height >> 1); y++) { /* V */ + if (fread(frame->decoded_cr[y], 1, width >> 1, fpointer) != (width>>1)) { + fprintf(stderr, "Could not read enough bytes from %s\n", fileName); + } + } + + fclose(fpointer); +} + + +static void +OpenBitRateFile() +{ + bitRateFile = fopen(bitRateFileName, "w"); + if ( bitRateFile == NULL ) { + fprintf(stderr, "ERROR: Could not open bit rate file: %s\n", bitRateFileName); + fprintf(stderr, "\n\n"); + showBitRatePerFrame = FALSE; + } +} + + +static void +CloseBitRateFile() +{ +#ifdef BLEAH + char command[256]; +#endif + + fclose(bitRateFile); +#ifdef BLEAH + sprintf(command, "sort -n %s > /tmp/fubahr", bitRateFileName); + system(command); + sprintf(command, "mv /tmp/fubahr %s", bitRateFileName); + system(command); +#endif +} diff --git a/contrib/mpeg_encode/nojpeg.cpp b/contrib/mpeg_encode/nojpeg.cpp new file mode 100644 index 0000000000000000000000000000000000000000..e8a5c0d6c8671e3c5a3265b1bc98942c3ecf70a0 --- /dev/null +++ b/contrib/mpeg_encode/nojpeg.cpp @@ -0,0 +1,131 @@ +/*===========================================================================* + * nojpeg.c * + * * + * procedures to deal with JPEG files * + * * + * EXPORTED PROCEDURES: * + * JMovie2JPEG * + * ReadJPEG * + * * + *===========================================================================*/ + +/* + * Copyright (c) 1995 The Regents of the University of California. + * All rights reserved. + * + * Permission to use, copy, modify, and distribute this software and its + * documentation for any purpose, without fee, and without written agreement is + * hereby granted, provided that the above copyright notice and the following + * two paragraphs appear in all copies of this software. + * + * IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR + * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT + * OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF + * CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS + * ON AN "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO + * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. + */ + +/* + * $Header: /n/charlie-brown/project/mm/mpeg/mpeg_dist/mpeg_encode/RCS/nojpeg.c,v 1.2 1995/01/19 23:08:55 eyhung Exp $ + * $Log: nojpeg.c,v $ + * Revision 1.2 1995/01/19 23:08:55 eyhung + * Changed copyrights + * + * Revision 1.1 1994/03/15 00:27:11 keving + * nothing + * + * Revision 1.2 1993/12/22 19:19:01 keving + * nothing + * + * Revision 1.1 1993/07/22 22:23:43 keving + * nothing + * + */ + +/*==============* + * HEADER FILES * + *==============*/ + +#include "all.h" +#include "mtypes.h" +#include "frames.h" +#include "prototypes.h" +#include "param.h" +#include "readframe.h" +#include "fsize.h" +#include "rgbtoycc.h" +#include "jpeg.h" + + + +/*=======================================================================* + * * + * JMovie2JPEG * + * * + * Splits up a Parallax J_Movie into a set of JFIF image files * + * * + * RETURNS: nothing * + * * + * SIDE EFFECTS: none * + * * + * Contributed By James Boucher(jboucher@flash.bu.edu) * + * Boston University Multimedia Communications Lab * + * This code was adapted from the Berkeley Playone.c and Brian Smith's * + * JGetFrame code after being modified on 10-7-93 by Dinesh Venkatesh * + * of BU. * + * This code converts a version 2 Parallax J_Movie into a * + * set of JFIF compatible JPEG images. It works for all image * + * sizes and qualities. * + ************************************************************************/ +void +JMovie2JPEG(char *infilename, /* input filename string */ + char *obase, /* output filename base string=>obase##.jpg */ + int start, /* first frame to be extracted */ + int end) /* last frame to be extracted */ +{ + throw "This has not been compiled with JPEG support"; +} + + + + +/*===========================================================================* + * + * ReadJPEG contributed by James Arthur Boucher of Boston University's + * Multimedia Communications Lab + * + * read a JPEG file and copy data into frame original data arrays + * + * RETURNS: mf modified + * + * SIDE EFFECTS: none + * + *===========================================================================*/ +/*************************JPEG LIBRARY INTERFACE*********************/ +/* + * THE BIG PICTURE: + * + * The rough outline this JPEG decompression operation is: + * + * allocate and initialize JPEG decompression object + * specify data source (eg, a file) + * jpeg_read_header(); // obtain image dimensions and other parameters + * set parameters for decompression + * jpeg_start_decompress(); + * while (scan lines remain to be read) + * jpeg_read_scanlines(...); + * jpeg_finish_decompress(); + * release JPEG decompression object + * + */ +void +ReadJPEG(MpegFrame *mf, + FILE *fp) +{ + throw "This has not been compiled with JPEG support"; +} diff --git a/contrib/mpeg_encode/noparallel.cpp b/contrib/mpeg_encode/noparallel.cpp new file mode 100644 index 0000000000000000000000000000000000000000..a5a2d2b802b1d454239ef9234b2c7bddfc38a683 --- /dev/null +++ b/contrib/mpeg_encode/noparallel.cpp @@ -0,0 +1,246 @@ +/*===========================================================================* + * noparallel.c * + * * + * would be procedures to make encoder to run in parallel -- except * + * this machine doesn't have sockets, so we can only run sequentially * + * so this file has dummy procedures which lets it compile * + * * + * EXPORTED PROCEDURES: * + * StartIOServer * + * StartCombineServer * + * SendRemoteFrame * + * GetRemoteFrame * + * StartMasterServer * + * NotifyMasterDone * + * * + *===========================================================================*/ + +/* + * Copyright (c) 1995 The Regents of the University of California. + * All rights reserved. + * + * Permission to use, copy, modify, and distribute this software and its + * documentation for any purpose, without fee, and without written agreement is + * hereby granted, provided that the above copyright notice and the following + * two paragraphs appear in all copies of this software. + * + * IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR + * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT + * OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF + * CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS + * ON AN "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO + * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. + */ + +/* + * $Header: /n/picasso/project/mm/mpeg/mpeg_dist/mpeg_encode/RCS/noparallel.c,v 1.6 1995/05/12 00:00:06 smoot Exp $ + * $Log: noparallel.c,v $ + * Revision 1.6 1995/05/12 00:00:06 smoot + * sco defined check + * + * Revision 1.5 1995/01/19 23:08:58 eyhung + * Changed copyrights + * + * Revision 1.4 1994/11/14 22:33:31 smoot + * added ifdef for Linux + * + * Revision 1.3 1994/11/12 02:11:55 keving + * nothing + * + * Revision 1.2 1993/12/22 19:19:01 keving + * nothing + * + * Revision 1.2 1993/12/22 19:19:01 keving + * nothing + * + * Revision 1.1 1993/07/22 22:23:43 keving + * nothing + * + * Revision 1.1 1993/06/30 20:06:09 keving + * nothing + * + */ + + +/*==============* + * HEADER FILES * + *==============*/ + +#include "all.h" +#include "mtypes.h" +#include "parallel.h" +#include "frame.h" +#include <time.h> + +/*==================* + * GLOBAL VARIABLES * + *==================*/ + +int parallelTestFrames = 10; +int parallelTimeChunks = 60; +char *IOhostName; +int ioPortNumber; +int combinePortNumber; +int decodePortNumber; +boolean niceProcesses = FALSE; +boolean forceIalign = FALSE; +int machineNumber = -1; +boolean remoteIO = FALSE; +boolean separateConversion; +time_t IOtime = 0; + + +/*=====================* + * EXPORTED PROCEDURES * + *=====================*/ + + /*=================* + * IO SERVER STUFF * + *=================*/ + + +void +SetIOConvert(boolean separate) +{ + /* do nothing -- this may be called during non-parallel execution */ +} + + +void +SetParallelPerfect(boolean val) +{ + /* do nothing -- this may be called during non-parallel execution */ +} + + +void +SetRemoteShell(char *shell) +{ + /* do nothing -- this may be called during non-parallel execution */ +} + + +/* StartIOServer + */ +void +StartIOServer(int numInputFiles, + char *parallelHostName, + int portNum) +{ + throw "(StartIOServer) This machine can NOT run parallel version"; +} + + +void +StartCombineServer(int numInputFiles, + char *outputFileName, + char *parallelHostName, + int portNum) +{ + throw "(StartCombineServer) This machine can NOT run parallel version"; +} + + +void +NoteFrameDone(int frameStart, + int frameEnd) +{ + throw "(NoteFrameDone) This machine can NOT run parallel version"; +} + +/* SendRemoteFrame + */ +void +SendRemoteFrame(int frameNumber, + BitBucket *bb) +{ + throw "(SendRemoteFrame) This machine can NOT run parallel version"; +} + + +/* GetRemoteFrame + */ +void +GetRemoteFrame(MpegFrame *frame, + int frameNumber) +{ + throw "(GetRemoteFrame) This machine can NOT run parallel version"; +} + + +void +WaitForOutputFile(int number) +{ + throw "(WaitForOutputFile) This machine can NOT run parallel version"; +} + + + /*=======================* + * PARALLEL SERVER STUFF * + *=======================*/ + + +/* StartMasterServer + */ +void +StartMasterServer(int numInputFiles, + char *paramFile, + char *outputFileName) +{ + throw "(StartMasterServer) This machine can NOT run parallel version"; +} + + +/* NotifyMasterDone + */ +boolean +NotifyMasterDone(char *hostName, + int portNum, + int machineNumber, + int seconds, + int *frameStart, + int *frameEnd) +{ + throw "(NotifyMasterDone) This machine can NOT run parallel version"; +} + + +void +StartDecodeServer(int numInputFiles, + char *decodeFileName, + char *parallelHostName, + int portNum) +{ + throw "(StartDecodeServer) This machine can NOT run parallel version"; +} + + +void +NotifyDecodeServerReady(int id) +{ + throw "(NotifyDecodeServerReady) This machine can NOT run parallel version"; +} + + +void +WaitForDecodedFrame(int id) +{ + throw "(WaitForDecodedFrame) This machine can NOT run parallel version"; +} + +void +SendDecodedFrame(MpegFrame *frame) +{ + throw "(SendDecodedFrame) This machine can NOT run parallel version"; +} + +void +GetRemoteDecodedRefFrame(MpegFrame *frame, + int frameNumber) +{ + throw "(GetRemoteDecodedRefFrame) This machine can NOT run parallel version"; +} diff --git a/contrib/mpeg_encode/opts.cpp b/contrib/mpeg_encode/opts.cpp new file mode 100644 index 0000000000000000000000000000000000000000..11567289cbf32bab9ba9ee66a91d58143e5b5c41 --- /dev/null +++ b/contrib/mpeg_encode/opts.cpp @@ -0,0 +1,509 @@ +/*===========================================================================* + * opts.c * + * * + * Special C code to handle TUNEing options * + * * + * EXPORTED PROCEDURES: * + * Tune_Init * + * CollectQuantStats * + * * + *===========================================================================*/ + + +/* + * Copyright (c) 1995 The Regents of the University of California. + * All rights reserved. + * + * Permission to use, copy, modify, and distribute this software and its + * documentation for any purpose, without fee, and without written agreement is + * hereby granted, provided that the above copyright notice and the following + * two paragraphs appear in all copies of this software. + * + * IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR + * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT + * OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF + * CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS + * ON AN "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO + * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. + */ + +/*==============* + * HEADER FILES * + *==============*/ + +#include <stdio.h> +#include <stdlib.h> // gmsh +#include <string.h> +#include "opts.h" +//#include <malloc.h> +#include <math.h> + +/*==============* + * EXTERNALS * + *==============*/ + +extern char outputFileName[]; +extern boolean pureDCT; +extern int32 qtable[], niqtable[]; +extern int ZAG[]; +extern boolean printSNR, decodeRefFrames; + +void init_idctref _ANSI_ARGS_((void)); +void init_fdct _ANSI_ARGS_((void)); + + +/*===================* + * GLOBALS MADE HERE * + *===================*/ + +boolean tuneingOn = FALSE; +int block_bound = 128; +boolean collect_quant = FALSE; +int collect_quant_detailed = 0; +FILE *collect_quant_fp; +int kill_dim = FALSE; +int kill_dim_break, kill_dim_end; +float kill_dim_slope; +int SearchCompareMode = DEFAULT_SEARCH; +boolean squash_small_differences = FALSE; +int SquashMaxLum, SquashMaxChr; +float LocalDCTRateScale = 1.0, LocalDCTDistortScale = 1.0; +boolean IntraPBAllowed = TRUE; +boolean WriteDistortionNumbers = FALSE; +int collect_distortion_detailed = 0; +FILE *distortion_fp; +FILE *fp_table_rate[31], *fp_table_dist[31]; +boolean DoLaplace = FALSE; +double **L1, **L2, **Lambdas; +int LaplaceNum, LaplaceCnum; +boolean BSkipBlocks = TRUE; + +/*====================* + * Internal Prototypes* + *====================*/ +void SetupCollectQuantStats _ANSI_ARGS_((char *charPtr)); +void SetupSquashSmall _ANSI_ARGS_ ((char *charPtr)); +void SetupKillDimAreas _ANSI_ARGS_((char *charPtr)); +void SetupLocalDCT _ANSI_ARGS_((char *charPtr)); +void SetupWriteDistortions _ANSI_ARGS_((char *charPtr)); +void SetupLaplace _ANSI_ARGS_((void)); +void CalcLambdas _ANSI_ARGS_((void)); +void Mpost_UnQuantZigBlockLaplace _ANSI_ARGS_((FlatBlock in, Block out, int qscale, boolean iblock)); + +/* define this as it too much of a pain to find toupper on different arch'es */ +#define ASCII_TOUPPER(c) ((c>='a') && (c<='z')) ? c-'a'+'A' : c + +/*=====================* + * EXPORTED PROCEDURES * + *=====================*/ + +/*===========================================================================* + * + * Tune_Init + * + * Do any setup needed before coding stream + * + * RETURNS: nothing + * + * SIDE EFFECTS: varies + * + *===========================================================================*/ +void Tune_Init() +{ + int i; + + /* Just check for each, and do whats needed */ + if (collect_quant) { + if (!pureDCT) { + pureDCT = TRUE; + init_idctref(); + init_fdct(); + } + fprintf(collect_quant_fp, "# %s\n", outputFileName); + fprintf(collect_quant_fp, "#"); + for (i=0; i<64; i++) + fprintf(collect_quant_fp, " %d", qtable[i]); + fprintf(collect_quant_fp, "\n#"); + for (i=0; i<64; i++) + fprintf(collect_quant_fp, " %d", niqtable[i]); + fprintf(collect_quant_fp, "\n# %d %d %d\n\n", + GetIQScale(), GetPQScale(), GetBQScale()); + + } + + if (DoLaplace) { + if (!pureDCT) { + pureDCT = TRUE; + init_idctref(); + init_fdct(); + } + decodeRefFrames = TRUE; + printSNR = TRUE; + } + +} + +/*===========================================================================* + * + * ParseTuneParam + * + * Handle the strings following TUNE + * + * RETURNS: nothing + * + * SIDE EFFECTS: varies + * + *===========================================================================*/ +void ParseTuneParam(char *charPtr) +{ + switch (ASCII_TOUPPER(*charPtr)) { + case 'B': + if (1 != sscanf(charPtr+2, "%d", &block_bound)) { + fprintf(stderr, "Invalid tuning parameter (b) in parameter file.\n"); + } + break; + case 'C': + SetupCollectQuantStats(charPtr+2); + break; + case 'D': + SetupLocalDCT(SkipSpacesTabs(charPtr+1)); + break; + case 'K': + SetupKillDimAreas(SkipSpacesTabs(charPtr+1)); + break; + case 'L': + SetupLaplace(); + break; + case 'N': + SearchCompareMode = NO_DC_SEARCH; + break; + case 'Q': + SearchCompareMode = DO_Mean_Squared_Distortion; + break; + case 'S': + SetupSquashSmall(SkipSpacesTabs(charPtr+1)); + break; + case 'W': + SetupWriteDistortions(SkipSpacesTabs(charPtr+1)); + break; + case 'U': + BSkipBlocks = FALSE; + break; + case 'Z': + IntraPBAllowed = FALSE; + break; + default: + fprintf(stderr, "Unknown tuning (%s) in parameter file.\n",charPtr); + break; + } +} + + +/*===============* + * Internals * + *===============*/ + +/*===========================================================================* + * + * SetupCollectQuantStats + * + * Setup variables to collect statistics on quantization values + * + * RETURNS: nothing + * + * SIDE EFFECTS: sets collect_quant and collect_quant_fp + * + *===========================================================================*/ +void SetupCollectQuantStats(char *charPtr) +{ + char fname[256], *cp; + + cp = charPtr; + while ( (*cp != ' ') && (*cp != '\t') && (*cp != '\n')) { + cp++; + } + + strncpy(fname, charPtr, cp-charPtr); + fname[cp-charPtr] = '\0'; + collect_quant = TRUE; + if ((collect_quant_fp = fopen(fname,"w")) == NULL) { + fprintf(stderr, "Error opening %s for quant statistics\n", fname); + fprintf(stderr, "Using stdout (ick!)\n"); + collect_quant_fp = stdout; + } + + cp = SkipSpacesTabs(cp); + if (*cp != '\n') { + switch (*cp) { + case 'c': + collect_quant_detailed = 1; + break; + default: + fprintf(stderr, "Unknown TUNE parameter setting format %s\n", cp); + }} +} + + + + +/*===========================================================================* + * + * SetupKillDimAreas + * + * Do a transform on small lum values + * + * RETURNS: nothing + * + * SIDE EFFECTS: sets kill_dim, kill_dim_break, kill_dim_end + * + *===========================================================================*/ +void SetupKillDimAreas(char *charPtr) +{ + int items_scanned; + + kill_dim = TRUE; + items_scanned = sscanf(charPtr, "%d %d %f", + &kill_dim_break, &kill_dim_end, &kill_dim_slope); + if (items_scanned != 3) { + kill_dim_slope = 0.25; + items_scanned = sscanf(charPtr, "%d %d", + &kill_dim_break, &kill_dim_end); + if (items_scanned != 2) { + /* Use defaults */ + kill_dim_break = 20; + kill_dim_end = 25; + } + } + /* check values */ + if (kill_dim_break > kill_dim_end) { + throw "TUNE parameter k: break > end is illegal"; + } + if (kill_dim_slope < 0) { + throw "TUNE parameter k: slope < 0 is illegal"; + } +} + + + +/*===========================================================================* + * + * SetupSquashSmall + * + * Setup encoder to squash small changes in Y or Cr/Cb values + * + * RETURNS: nothing + * + * SIDE EFFECTS: sets squash_max_differences SquashMaxLum SquashMaxChr + * + *===========================================================================*/ +void SetupSquashSmall(char *charPtr) +{ + squash_small_differences = TRUE; + + if (sscanf(charPtr, "%d %d", &SquashMaxLum, &SquashMaxChr) == 1) { + /* Only set one, do both */ + SquashMaxChr = SquashMaxLum; + } +} + + +/*===========================================================================* + * + * SetupLocalDCT + * + * Setup encoder to use DCT for rate-distortion estimat ein Psearches + * + * RETURNS: nothing + * + * SIDE EFFECTS: sets SearchCompareMode and + * can change LocalDCTRateScale, LocalDCTDistortScale + * + *===========================================================================*/ +void SetupLocalDCT(char *charPtr) +{ + int num_scales=0; + + SearchCompareMode = LOCAL_DCT; + + /* Set scaling factors if present */ + num_scales = sscanf(charPtr, "%f %f", &LocalDCTRateScale, &LocalDCTDistortScale); + if (num_scales == 1) { + fprintf(stderr, "Invalid number of scaling factors for local DCT\n"); + fprintf(stderr, "Must specify Rate Scale and Distorion scale (both floats)\n"); + fprintf(stderr, "Continuing with 1.0 1.0\n"); + LocalDCTRateScale = 1.0; + LocalDCTDistortScale = 1.0; + } +} + + +/*===========================================================================* + * + * SetupLaplace + * + * Setup encoder to find distrubution for I-frames, and use for -snr + * + * RETURNS: nothing + * + * SIDE EFFECTS: sets DoLaplace, L1, L2, and Lambdas + * + *===========================================================================*/ +void SetupLaplace() +{ + int i; + + DoLaplace = TRUE; + LaplaceNum = 0; + L1 = (double **)malloc(sizeof(double *)*3); + L2 = (double **)malloc(sizeof(double *)*3); + Lambdas = (double **)malloc(sizeof(double *)*3); + if (L1 == NULL || L2 == NULL || Lambdas == NULL) { + throw "Out of memory!"; + } + for (i = 0; i < 3; i++) { + L1[i] = (double *)calloc(64, sizeof(double)); + L2[i] = (double *)calloc(64, sizeof(double)); + Lambdas[i] = (double *)malloc(sizeof(double) * 64); + if (L1[i] == NULL || L2[i] == NULL || Lambdas[i] == NULL) { + throw "Out of memory!"; + } + } +} + +void CalcLambdas() +{ + int i,j,n; + double var; + + n = LaplaceNum; + for (i = 0; i < 3; i++) { + for (j = 0; j < 64; j++) { + var = (n*L1[i][j] + L2[i][j]*L2[i][j]) / (n*(n-1)); + Lambdas[i][j] = sqrt(2.0) / sqrt(var); + } + } +} + + +/*===========================================================================* + * + * Mpost_UnQuantZigBlockLaplace + * + * unquantize and zig-zag (decode) a single block, using the distrib to get vals + * Iblocks only now + * + * RETURNS: nothing + * + * SIDE EFFECTS: none + * + *===========================================================================*/ +void +Mpost_UnQuantZigBlockLaplace(FlatBlock in, + Block out, + int qscale, + boolean iblock) +{ + register int index; + int position; + register int qentry; + int level, coeff; + double low, high; + double mid,lam; + + /* qtable[0] must be 8 */ + out[0][0] = (int16)(in[0] * 8); + + for ( index = 1; index < DCTSIZE_SQ; index++ ) { + position = ZAG[index]; + level = in[index]; + + if (level == 0) { + ((int16 *)out)[position] = 0; + continue; + } + qentry = qtable[position] * qscale; + coeff = (level*qentry)/8; + low = ((ABS(level)-.5)*qentry)/8; + high = ((ABS(level)+.5)*qentry)/8; + lam = Lambdas[LaplaceCnum][position]; + mid = (1.0/lam) * log(0.5*(exp(-lam*low)+exp(-lam*high))); + mid = ABS(mid); + if (mid - floor(mid) > .4999) { + mid = ceil(mid); + } else { + mid = floor(mid); + } + if (level<0) {mid = -mid;} +/*printf("(%2.1lf-%2.1lf): old: %d vs %d\n",low,high,coeff,(int) mid);*/ + coeff = mid; + if ( (coeff & 1) == 0 ) { + if ( coeff < 0 ) { + coeff++; + } else if ( coeff > 0 ) { + coeff--; + } + } + ((int16 *)out)[position] = coeff; + } +} + +void +SetupWriteDistortions(char *charPtr) +{ + char fname[256], *cp; + int i; + + WriteDistortionNumbers = TRUE; + cp = charPtr; + while ( (*cp != ' ') && (*cp != '\t') && (*cp != '\n')) { + cp++; + } + + strncpy(fname, charPtr, cp-charPtr); + fname[cp-charPtr] = '\0'; + collect_quant = TRUE; + if ((distortion_fp = fopen(fname,"w")) == NULL) { + fprintf(stderr, "Error opening %s for quant statistics\n", fname); + fprintf(stderr, "Using stdout (ick!)\n"); + distortion_fp = stdout; + } + + cp = SkipSpacesTabs(cp); + if (*cp != '\n') { + switch (*cp) { + case 'c': + collect_distortion_detailed = TRUE; + break; + case 't': { + char scratch[256]; + collect_distortion_detailed = 2; + for (i = 1; i < 32; i++) { + sprintf(scratch, "%srate%d", fname, i); + fp_table_rate[i-1] = fopen(scratch, "w"); + sprintf(scratch, "%sdist%d", fname, i); + fp_table_dist[i-1] = fopen(scratch, "w"); + }} + break; + default: + fprintf(stderr, "Unknown TUNE parameter setting format %s\n", cp); + }} +} + +int mse(Block blk1, Block blk2) +{ + register int index, error, tmp; + int16 *bp1, *bp2; + + bp1 = (int16 *)blk1; + bp2 = (int16 *)blk2; + error = 0; + for ( index = 0; index < DCTSIZE_SQ; index++ ) { + tmp = *bp1++ - *bp2++; + error += tmp*tmp; + } + return error; +} diff --git a/contrib/mpeg_encode/param.cpp b/contrib/mpeg_encode/param.cpp new file mode 100644 index 0000000000000000000000000000000000000000..5dc505a6a3f7eee88d9b144d4fdd201bf96f5b9f --- /dev/null +++ b/contrib/mpeg_encode/param.cpp @@ -0,0 +1,1339 @@ +/*===========================================================================* + * param.c * + * * + * Procedures to read in parameter file * + * * + * EXPORTED PROCEDURES: * + * ReadParamFile * + * GetNthInputFileName * + * * + *===========================================================================*/ + +/* + * Copyright (c) 1995 The Regents of the University of California. + * All rights reserved. + * + * Permission to use, copy, modify, and distribute this software and its + * documentation for any purpose, without fee, and without written agreement is + * hereby granted, provided that the above copyright notice and the following + * two paragraphs appear in all copies of this software. + * + * IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR + * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT + * OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF + * CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS + * ON AN "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO + * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. + */ + +/* + * $Header: /n/picasso/project/mpeg/mpeg_dist/mpeg_encode/RCS/param.c,v 1.38 1995/08/14 22:29:13 smoot Exp smoot $ + * $Log: param.c,v $ + * Revision 1.38 1995/08/14 22:29:13 smoot + * cleaned up subcommand for file name generation + * fixed bug where foo* didnt work as input string + * + * Revision 1.37 1995/08/07 21:47:01 smoot + * allows spaces after lines in param files + * added SIZE == YUV_SIZE for parallel encoding (otherwise you'd have + * to parse PPM files in the master server... Ick. + * So we have it specified) + * + * Revision 1.36 1995/06/26 21:52:52 smoot + * allow uppercase stdin + * + * Revision 1.35 1995/06/21 18:35:01 smoot + * moved TUNE stuff to opts.c + * Added ability to do: + * INPUT + * file.ppm [1-10] + * to do 10 copies + * added CDL = SPECIFICS + * + * Revision 1.34 1995/05/02 01:48:25 eyhung + * deleted some smootisms. fixed framerate settings, added check for + * invalid input range + * + * Revision 1.33 1995/05/02 01:20:10 smoot + * *** empty log message *** + * + * Revision 1.31 1995/03/09 06:22:36 eyhung + * more robust input checking (whitespace at end of input file spec) + * + * Revision 1.30 1995/02/02 01:06:18 eyhung + * Added error checking for JMOVIE and stdin ; deleted smoot's "understand" + * param file ideas. + * + * Revision 1.29 1995/02/01 21:09:59 eyhung + * Finished infinite coding-on-the-fly + * + * Revision 1.28 1995/01/31 22:34:28 eyhung + * Added stdin as a parameter to INPUT_DIR for interactive encoding + * + * Revision 1.27 1995/01/27 21:58:07 eyhung + * Fixed a bug with reading JMOVIES in GetNthInputFileName + * + * Revision 1.26 1995/01/25 23:00:05 smoot + * Checks out Qtable entries + * + * Revision 1.25 1995/01/23 02:09:51 darryl + * removed "PICT_RATE" code + * + * Revision 1.24 1995/01/20 00:07:46 smoot + * requires unistd.c now + * + * Revision 1.23 1995/01/20 00:05:33 smoot + * Added gamma correction option + * + * Revision 1.22 1995/01/19 23:55:55 eyhung + * Fixed up smoot's "style" and made YUV_FORMAT default to EYUV + * + * Revision 1.21 1995/01/19 23:09:03 eyhung + * Changed copyrights + * + * Revision 1.20 1995/01/17 22:04:14 smoot + * Added `commands` to file name listing + * + * Revision 1.19 1995/01/17 06:28:01 eyhung + * StdinUsed added. + * + * Revision 1.18 1995/01/16 09:33:35 eyhung + * Fixed stupid commenting error. + * + * Revision 1.17 1995/01/16 06:07:53 eyhung + * Made it look a little nicer + * + * Revision 1.16 1995/01/13 23:57:25 smoot + * added Y format + * + * Revision 1.15 1995/01/08 06:20:39 eyhung + * *** empty log message *** + * + * Revision 1.14 1995/01/08 06:15:57 eyhung + * *** empty log message *** + * + * Revision 1.13 1995/01/08 05:50:32 eyhung + * Added YUV Format parameter + * + * Revision 1.12 1994/12/16 00:55:30 smoot + * Fixed INPU_FILES bug + * + * Revision 1.11 1994/12/12 23:54:36 smoot + * Fixed GOP-missing error message (GOP to GOP_SIZE) + * + * Revision 1.10 1994/12/07 00:40:36 smoot + * Added seperate P and B search ranges + * + * Revision 1.9 1994/11/18 23:19:22 smoot + * Added USER_DATA parameter + * + * Revision 1.8 1994/11/16 22:33:40 smoot + * Put in ifdef for rsh in param.c + * + * Revision 1.7 1994/11/16 22:25:05 smoot + * Corrected ASPECT_RATIO bug + * + * Revision 1.6 1994/11/14 22:39:26 smoot + * merged specifics and rate control + * + * Revision 1.5 1994/11/01 05:01:41 darryl + * with rate control changes added + * + * Revision 1.1 1994/09/27 00:16:28 darryl + * Initial revision + * + * Revision 1.4 1994/03/15 00:27:11 keving + * nothing + * + * Revision 1.3 1993/12/22 19:19:01 keving + * nothing + * + * Revision 1.2 1993/07/22 22:23:43 keving + * nothing + * + * Revision 1.1 1993/06/30 20:06:09 keving + * nothing + * + */ + + +/*==============* + * HEADER FILES * + *==============*/ + +#include "all.h" +#include "mtypes.h" +#include "mpeg.h" +#include "search.h" +#include "prototypes.h" +#include "parallel.h" +#include "param.h" +#include "readframe.h" +#include "fsize.h" +#include "frames.h" +#include "jpeg.h" +#include <string.h> +#include <ctype.h> +#include "rate.h" +#include "opts.h" + +/*===========* + * CONSTANTS * + *===========*/ + +#define INPUT_ENTRY_BLOCK_SIZE 128 + +#define FIRST_OPTION 0 +#define OPTION_GOP 0 +#define OPTION_PATTERN 1 +#define OPTION_PIXEL 2 +#define OPTION_PQSCALE 3 +#define OPTION_OUTPUT 4 +#define OPTION_RANGE 5 +#define OPTION_PSEARCH_ALG 6 +#define OPTION_IQSCALE 7 +#define OPTION_INPUT_DIR 8 +#define OPTION_INPUT_CONVERT 9 +#define OPTION_INPUT 10 +#define OPTION_BQSCALE 11 +#define OPTION_BASE_FORMAT 12 +#define OPTION_SPF 13 +#define OPTION_BSEARCH_ALG 14 +#define OPTION_REF_FRAME 15 +#define LAST_OPTION 15 + +/* put any non-required options after LAST_OPTION */ +#define OPTION_RESIZE 16 +#define OPTION_IO_CONVERT 17 +#define OPTION_SLAVE_CONVERT 18 +#define OPTION_IQTABLE 19 +#define OPTION_NIQTABLE 20 +#define OPTION_FRAME_RATE 21 +#define OPTION_ASPECT_RATIO 22 +#define OPTION_YUV_SIZE 23 +#define OPTION_SPECIFICS 24 +#define OPTION_DEFS_SPECIFICS 25 +#define OPTION_BUFFER_SIZE 26 +#define OPTION_BIT_RATE 27 +#define OPTION_USER_DATA 28 +#define OPTION_YUV_FORMAT 29 +#define OPTION_GAMMA 30 +#define OPTION_PARALLEL 31 + +#define NUM_OPTIONS 31 + +/*=======================* + * STRUCTURE DEFINITIONS * + *=======================*/ + +typedef struct InputFileEntryStruct { + char left[256]; + char right[256]; + boolean glob; /* if FALSE, left is complete name */ + int startID; + int endID; + int skip; + int numPadding; /* -1 if there is none */ + int numFiles; + boolean repeat; +} InputFileEntry; + + +/*==================* + * STATIC VARIABLES * + *==================*/ + +static InputFileEntry **inputFileEntries; +static int numInputFileEntries = 0; +static int maxInputFileEntries; + + +/*==================* + * GLOBAL VARIABLES * + *==================*/ + +extern char currentPath[MAXPATHLEN]; +extern char currentGOPPath[MAXPATHLEN]; +extern char currentFramePath[MAXPATHLEN]; +char outputFileName[256]; +int outputWidth, outputHeight; +int numInputFiles = 0; +char inputConversion[1024]; +char ioConversion[1024]; +char slaveConversion[1024]; +char yuvConversion[256]; +char specificsFile[256],specificsDefines[1024]=""; +boolean GammaCorrection=FALSE; +float GammaValue; +unsigned char userDataFileName[256]={0}; +boolean specificsOn = FALSE; +boolean optionSeen[NUM_OPTIONS+1]; +int numMachines; +char machineName[MAX_MACHINES][256]; +char userName[MAX_MACHINES][256]; +char executable[MAX_MACHINES][1024]; +char remoteParamFile[MAX_MACHINES][1024]; +boolean remote[MAX_MACHINES]; +boolean stdinUsed = FALSE; +int mult_seq_headers = 0; /* 0 for none, N for header/N GOPs */ + +/*===============================* + * INTERNAL PROCEDURE prototypes * + *===============================*/ +static void ReadInputFileNames _ANSI_ARGS_((FILE *fpointer, + const char *endInput)); +static void ReadMachineNames _ANSI_ARGS_((FILE *fpointer)); +static int GetAspectRatio _ANSI_ARGS_((char *p)); +static int GetFrameRate _ANSI_ARGS_((char *p)); + +/*=====================* + * EXPORTED PROCEDURES * + *=====================*/ + + +/*===========================================================================* + * + * ReadParamFile + * + * read the parameter file + * function is ENCODE_FRAMES, COMBINE_GOPS, or COMBINE_FRAMES, and + * will slightly modify the procedure's behavior as to what it + * is looking for in the parameter file + * + * RETURNS: TRUE if the parameter file was read correctly; FALSE if not + * + * SIDE EFFECTS: sets parameters accordingly, as well as machine info for + * parallel execution and input file names + * + *===========================================================================*/ +boolean +ReadParamFile(char *fileName, + int function) +{ + numInputFileEntries = 0; // for gmsh + FILE *fpointer; + char input[256]; + char *charPtr; + boolean yuvUsed = FALSE; + static const char *optionText[LAST_OPTION+1] = { "GOP_SIZE", "PATTERN", "PIXEL", "PQSCALE", + "OUTPUT", "RANGE", "PSEARCH_ALG", "IQSCALE", "INPUT_DIR", + "INPUT_CONVERT", "INPUT", "BQSCALE", "BASE_FILE_FORMAT", + "SLICES_PER_FRAME", "BSEARCH_ALG", "REFERENCE_FRAME"}; + register int index; + register int row, col; + + if ( (fpointer = fopen(fileName, "r")) == NULL ) { + fprintf(stderr, "Error: Cannot open parameter file: %s\n", fileName); + return FALSE; + } + + /* should set defaults */ + numInputFiles = 0; + numMachines = 0; + sprintf(currentPath, "."); + sprintf(currentGOPPath, "."); + sprintf(currentFramePath, "."); +#ifndef HPUX + SetRemoteShell((char*)"rsh"); +#else + SetRemoteShell("remsh"); +#endif + + switch(function) { + case ENCODE_FRAMES: + for ( index = FIRST_OPTION; index <= LAST_OPTION; index++ ) { + optionSeen[index] = FALSE; + } + optionSeen[OPTION_IO_CONVERT] = FALSE; + optionSeen[OPTION_SLAVE_CONVERT] = FALSE; + break; + case COMBINE_GOPS: + for ( index = FIRST_OPTION; index <= LAST_OPTION; index++ ) { + optionSeen[index] = TRUE; + } + + optionSeen[OPTION_OUTPUT] = FALSE; + break; + case COMBINE_FRAMES: + for ( index = FIRST_OPTION; index <= LAST_OPTION; index++ ) { + optionSeen[index] = TRUE; + } + + optionSeen[OPTION_GOP] = FALSE; + optionSeen[OPTION_OUTPUT] = FALSE; + break; + } + + for( index=LAST_OPTION+1; index<= NUM_OPTIONS; index++ ) { + optionSeen[index]=FALSE; + } + + while ( fgets(input, 256, fpointer) != NULL ) { + /* skip comments */ + if ( input[0] == '#' ) { + continue; + } + + { + int len = strlen(input); + if (input[len-1] == '\n') { + len--; + input[len] = '\0'; /* get rid of newline */ + /* Junk whitespace */ + while ((len >= 0) && ((input[len-1] == ' ') || (input[len-1] == '\t'))) { + input[--len] = '\0'; + } + } + } + + if (strlen(SkipSpacesTabs(input)) == 0) continue; + + switch(input[0]) { + case 'A': + if ( strncmp(input, "ASPECT_RATIO", 12) == 0 ) { + charPtr = SkipSpacesTabs(&input[12]); + aspectRatio = GetAspectRatio(charPtr); + optionSeen[OPTION_ASPECT_RATIO] = TRUE; + } + break; + + case 'B': + if ( strncmp(input, "BQSCALE", 7) == 0 ) { + charPtr = SkipSpacesTabs(&input[7]); + SetBQScale(atoi(charPtr)); + optionSeen[OPTION_BQSCALE] = TRUE; + } else if ( strncmp(input, "BASE_FILE_FORMAT", 16) == 0 ) { + charPtr = SkipSpacesTabs(&input[16]); + SetFileFormat(charPtr); + if ( (strncmp(charPtr,"YUV",3) == 0) || + (strcmp(charPtr,"Y") == 0) ) { + yuvUsed = TRUE; + } + optionSeen[OPTION_BASE_FORMAT] = TRUE; + } else if ( strncmp(input, "BSEARCH_ALG", 11) == 0 ) { + charPtr = SkipSpacesTabs(&input[11]); + SetBSearchAlg(charPtr); + optionSeen[OPTION_BSEARCH_ALG] = TRUE; + } else if ( strncmp(input, "BIT_RATE", 8) == 0 ) { + charPtr = SkipSpacesTabs(&input[8]); + setBitRate(charPtr); + optionSeen[OPTION_BIT_RATE] = TRUE; + } else if ( strncmp(input, "BUFFER_SIZE", 11) == 0 ) { + charPtr = SkipSpacesTabs(&input[11]); + setBufferSize(charPtr); + optionSeen[OPTION_BUFFER_SIZE] = TRUE; + } + break; + + case 'C': + if ( strncmp(input, "CDL_FILE", 8) == 0 ) { + charPtr = SkipSpacesTabs(&input[8]); + strcpy(specificsFile, charPtr); + specificsOn=TRUE; + optionSeen[OPTION_SPECIFICS] = TRUE; + } else if ( strncmp(input, "CDL_DEFINES", 11) == 0 ) { + charPtr = SkipSpacesTabs(&input[11]); + strcpy(specificsDefines, charPtr); + optionSeen[OPTION_DEFS_SPECIFICS] = TRUE; + } + break; + + case 'F': + if ( strncmp(input, "FRAME_INPUT_DIR", 15) == 0 ) { + charPtr = SkipSpacesTabs(&input[15]); + if ( strncmp(charPtr, "stdin", 5) == 0 || + strncmp(charPtr, "STDIN", 5) == 0 ) { + stdinUsed = TRUE; + numInputFiles = MAXINT; + numInputFileEntries = 1; + } + strcpy(currentFramePath, charPtr); + } else if ( strncmp(input, "FRAME_INPUT", 11) == 0 ) { + if ( function == COMBINE_FRAMES ) { + ReadInputFileNames(fpointer, "FRAME_END_INPUT"); + } + } else if ( strncmp(input, "FORCE_I_ALIGN", 13) == 0 ) { + forceIalign = TRUE; + } else if ( strncmp(input, "FORCE_ENCODE_LAST_FRAME", 23) == 0 ) { + forceEncodeLast = TRUE; + } else if ( strncmp(input, "FRAME_RATE", 10) == 0 ) { + charPtr = SkipSpacesTabs(&input[10]); + frameRate = GetFrameRate(charPtr); + frameRateRounded = (int) VidRateNum[frameRate]; + if ( (frameRate % 3) == 1) { + frameRateInteger = FALSE; + } + optionSeen[OPTION_FRAME_RATE] = TRUE; + } + break; + + case 'G': + if ( strncmp(input, "GOP_SIZE", 8) == 0 ) { + charPtr = SkipSpacesTabs(&input[8]); + SetGOPSize(atoi(charPtr)); + optionSeen[OPTION_GOP] = TRUE; + } else if ( strncmp(input, "GOP_INPUT_DIR", 13) == 0 ) { + charPtr = SkipSpacesTabs(&input[13]); + if ( strncmp(charPtr, "stdin", 5) == 0 || + strncmp(charPtr, "STDIN", 5) == 0 ) { + stdinUsed = TRUE; + numInputFiles = MAXINT; + numInputFileEntries = 1; + } + strcpy(currentGOPPath, charPtr); + } else if ( strncmp(input, "GOP_INPUT", 9) == 0 ) { + if ( function == COMBINE_GOPS ) { + ReadInputFileNames(fpointer, "GOP_END_INPUT"); + } + } else if ( strncmp(input, "GAMMA", 5) == 0) { + charPtr = SkipSpacesTabs(&input[5]); + GammaCorrection = TRUE; + sscanf(charPtr,"%f",&GammaValue); + optionSeen[OPTION_GAMMA] = TRUE; + } + break; + + case 'I': + if ( strncmp(input, "IQSCALE", 7) == 0 ) { + charPtr = SkipSpacesTabs(&input[7]); + SetIQScale(atoi(charPtr)); + optionSeen[OPTION_IQSCALE] = TRUE; + } else if ( strncmp(input, "INPUT_DIR", 9) == 0 ) { + charPtr = SkipSpacesTabs(&input[9]); + if ( strncmp(charPtr, "stdin", 5) == 0 || + strncmp(charPtr, "STDIN", 5) == 0 ) { + stdinUsed = TRUE; + numInputFiles = MAXINT; + numInputFileEntries = 1; + } + strcpy(currentPath, charPtr); + optionSeen[OPTION_INPUT_DIR] = TRUE; + } else if ( strncmp(input, "INPUT_CONVERT", 13) == 0 ) { + charPtr = SkipSpacesTabs(&input[13]); + strcpy(inputConversion, charPtr); + optionSeen[OPTION_INPUT_CONVERT] = TRUE; + } else if ( strcmp(input, "INPUT") == 0 ) { /* yes, strcmp */ + if ( function == ENCODE_FRAMES ) { + ReadInputFileNames(fpointer, "END_INPUT"); + optionSeen[OPTION_INPUT] = TRUE; + } + } else if ( strncmp(input, "IO_SERVER_CONVERT", 17) == 0 ) { + charPtr = SkipSpacesTabs(&input[17]); + strcpy(ioConversion, charPtr); + optionSeen[OPTION_IO_CONVERT] = TRUE; + } else if ( strncmp(input, "IQTABLE", 7) == 0 ) { + for ( row = 0; row < 8; row ++ ) { + fgets(input, 256, fpointer); + charPtr = input; + if (8!=sscanf(charPtr,"%d %d %d %d %d %d %d %d", + &qtable[row*8+0], &qtable[row*8+1], + &qtable[row*8+2], &qtable[row*8+3], + &qtable[row*8+4], &qtable[row*8+5], + &qtable[row*8+6], &qtable[row*8+7])) { + throw "Line of IQTABLE doesn't have 8 elements!"; + } + for ( col = 0; col < 8; col ++ ) { + if ((qtable[row*8+col]<1) || (qtable[row*8+col]>255)) { + fprintf(stderr, + "Warning: IQTable Element %1d,%1d (%d) corrected to 1-255.\n", + row+1, col+1, qtable[row*8+col]); + qtable[row*8+col] = (qtable[row*8+col]<1)?1:255; + }} + } + + if ( qtable[0] != 8 ) { + fprintf(stderr, "Warning: IQTable Element 1,1 reset to 8, since it must be 8.\n"); + qtable[0] = 8; + } + customQtable = qtable; + optionSeen[OPTION_IQTABLE] = TRUE; + } else if ( strncmp(input, "INPUT", 5) == 0 ) { /* handle spaces after input */ + log(10.0); + charPtr = SkipSpacesTabs(&input[5]); + if ( function == ENCODE_FRAMES && *charPtr==0) { + ReadInputFileNames(fpointer, "END_INPUT"); + optionSeen[OPTION_INPUT] = TRUE; + } + } + break; + + case 'N': + if ( strncmp(input, "NIQTABLE", 8) == 0 ) { + for ( row = 0; row < 8; row ++ ) { + fgets(input, 256, fpointer); + charPtr = input; + if (8!=sscanf(charPtr,"%d %d %d %d %d %d %d %d", + &niqtable[row*8+0], &niqtable[row*8+1], + &niqtable[row*8+2], &niqtable[row*8+3], + &niqtable[row*8+4], &niqtable[row*8+5], + &niqtable[row*8+6], &niqtable[row*8+7])) { + throw "Line of NIQTABLE doesn't have 8 elements!"; + } + for ( col = 0; col < 8; col++ ) { + if ((niqtable[row*8+col]<1) || (niqtable[row*8+col]>255)) { + fprintf(stderr, + "Warning: NIQTable Element %1d,%1d (%d) corrected to 1-255.\n", + row+1, col+1, niqtable[row*8+col]); + niqtable[row*8+col]=(niqtable[row*8+col]<1)?1:255; + }} + } + + customNIQtable = niqtable; + optionSeen[OPTION_NIQTABLE] = TRUE; + } + break; + + case 'O': + if ( strncmp(input, "OUTPUT", 6) == 0 ) { + charPtr = SkipSpacesTabs(&input[6]); + if ( whichGOP == -1 ) { + strcpy(outputFileName, charPtr); + } else { + sprintf(outputFileName, "%s.gop.%d", + charPtr, whichGOP); + } + + optionSeen[OPTION_OUTPUT] = TRUE; + } + break; + + case 'P': + if ( strncmp(input, "PATTERN", 7) == 0 ) { + charPtr = SkipSpacesTabs(&input[7]); + SetFramePattern(charPtr); + optionSeen[OPTION_PATTERN] = TRUE; + } else if ( strncmp(input, "PIXEL", 5) == 0 ) { + charPtr = SkipSpacesTabs(&input[5]); + SetPixelSearch(charPtr); + optionSeen[OPTION_PIXEL] = TRUE; + } else if ( strncmp(input, "PQSCALE", 7) == 0 ) { + charPtr = SkipSpacesTabs(&input[7]); + SetPQScale(atoi(charPtr)); + optionSeen[OPTION_PQSCALE] = TRUE; + } else if ( strncmp(input, "PSEARCH_ALG", 11) == 0 ) { + charPtr = SkipSpacesTabs(&input[11]); + SetPSearchAlg(charPtr); + optionSeen[OPTION_PSEARCH_ALG] = TRUE; + } else if ( strncmp(input, "PARALLEL_TEST_FRAMES", 20) == 0 ) { + SetParallelPerfect(FALSE); + charPtr = SkipSpacesTabs(&input[20]); + parallelTestFrames = atoi(charPtr); + } else if ( strncmp(input, "PARALLEL_TIME_CHUNKS", 20) == 0 ) { + SetParallelPerfect(FALSE); + charPtr = SkipSpacesTabs(&input[20]); + parallelTimeChunks = atoi(charPtr); + } else if ( strncmp(input, "PARALLEL_CHUNK_TAPER", 20) == 0 ) { + SetParallelPerfect(FALSE); + parallelTimeChunks = -1; + } else if ( strncmp(input, "PARALLEL_PERFECT", 16) == 0 ) { + SetParallelPerfect(TRUE); + } else if ( strncmp(input, "PARALLEL", 8) == 0 ) { + ReadMachineNames(fpointer); + optionSeen[OPTION_PARALLEL] = TRUE; + } + break; + + case 'R': + if ( strncmp(input, "RANGE", 5) == 0 ) { + int num_ranges=0,a,b; + charPtr = SkipSpacesTabs(&input[5]); + optionSeen[OPTION_RANGE] = TRUE; + num_ranges=sscanf(charPtr,"%d %d",&a,&b); + if (num_ranges==2) { + SetSearchRange(a,b); + } else if (sscanf(charPtr,"%d [%d]",&a,&b)==2) { + SetSearchRange(a,b); + } else SetSearchRange(a,a); + } else if ( strncmp(input, "REFERENCE_FRAME", 15) == 0 ) { + charPtr = SkipSpacesTabs(&input[15]); + SetReferenceFrameType(charPtr); + optionSeen[OPTION_REF_FRAME] = TRUE; + } else if ( strncmp(input, "RSH", 3) == 0 ) { + charPtr = SkipSpacesTabs(&input[3]); + SetRemoteShell(charPtr); + } else if ( strncmp(input, "RESIZE", 6) == 0 ) { + charPtr = SkipSpacesTabs(&input[6]); + sscanf(charPtr, "%dx%d", &outputWidth, &outputHeight); + outputWidth &= ~(DCTSIZE * 2 - 1); + outputHeight &= ~(DCTSIZE * 2 - 1); + optionSeen[OPTION_RESIZE] = TRUE; + } + break; + + case 'S': + if ( strncmp(input, "SLICES_PER_FRAME", 16) == 0 ) { + charPtr = SkipSpacesTabs(&input[16]); + SetSlicesPerFrame(atoi(charPtr)); + optionSeen[OPTION_SPF] = TRUE; + } else if ( strncmp(input, "SLAVE_CONVERT", 13) == 0 ) { + charPtr = SkipSpacesTabs(&input[13]); + strcpy(slaveConversion, charPtr); + optionSeen[OPTION_SLAVE_CONVERT] = TRUE; + } else if ( strncmp(input, "SPECIFICS_FILE", 14) == 0 ) { + charPtr = SkipSpacesTabs(&input[14]); + strcpy(specificsFile, charPtr); + specificsOn=TRUE; + optionSeen[OPTION_SPECIFICS] = TRUE; + } else if ( strncmp(input, "SPECIFICS_DEFINES", 16) == 0 ) { + charPtr = SkipSpacesTabs(&input[17]); + strcpy(specificsDefines, charPtr); + optionSeen[OPTION_DEFS_SPECIFICS] = TRUE; + } else if (strncmp(input, "SEQUENCE_SIZE", 13) == 0) { + charPtr = SkipSpacesTabs(&input[13]); + mult_seq_headers = atoi(charPtr); + } else if (strncmp(input, "SIZE", 4) == 0 ) { + charPtr = SkipSpacesTabs(&input[4]); + sscanf(charPtr, "%dx%d", &yuvWidth, &yuvHeight); + realWidth = yuvWidth; + realHeight = yuvHeight; + Fsize_Validate(&yuvWidth, &yuvHeight); + optionSeen[OPTION_YUV_SIZE] = TRUE; + } + break; + + case 'T': + if ( strncmp(input, "TUNE", 4) == 0) { + tuneingOn = TRUE; + charPtr = SkipSpacesTabs(&input[4]); + ParseTuneParam(charPtr); + } + break; + + case 'U': + if ( strncmp(input, "USER_DATA", 9) == 0 ) { + charPtr = SkipSpacesTabs(&input[9]); + strcpy((char*)userDataFileName, charPtr); + optionSeen[OPTION_USER_DATA] = TRUE; + } + break; + + case 'Y': + if (strncmp(input, "YUV_SIZE", 8) == 0 ) { + charPtr = SkipSpacesTabs(&input[8]); + sscanf(charPtr, "%dx%d", &yuvWidth, &yuvHeight); + realWidth = yuvWidth; + realHeight = yuvHeight; + Fsize_Validate(&yuvWidth, &yuvHeight); + optionSeen[OPTION_YUV_SIZE] = TRUE; + } + else if (strncmp(input, "Y_SIZE", 6) == 0 ) { + charPtr = SkipSpacesTabs(&input[6]); + sscanf(charPtr, "%dx%d", &yuvWidth, &yuvHeight); + realWidth = yuvWidth; + realHeight = yuvHeight; + Fsize_Validate(&yuvWidth, &yuvHeight); + optionSeen[OPTION_YUV_SIZE] = TRUE; + } + else if ( strncmp(input, "YUV_FORMAT", 10) == 0 ) { + charPtr = SkipSpacesTabs(&input[10]); + strcpy(yuvConversion, charPtr); + optionSeen[OPTION_YUV_FORMAT] = TRUE; + } + break; + } + } + + fclose(fpointer); + + for ( index = FIRST_OPTION; index <= LAST_OPTION; index++ ) { + if ( ! optionSeen[index] ) { + + /* INPUT unnecessary when stdin is used */ + if ((index == OPTION_INPUT) && stdinUsed) { + continue; + } + + throw "Missing option"; + } + } + + /* error checking */ + if ( yuvUsed ) { + + if (! optionSeen[OPTION_YUV_SIZE]) { + throw "YUV format used but YUV_SIZE not given"; + } + + if (! optionSeen[OPTION_YUV_FORMAT]) { + strcpy (yuvConversion, "EYUV"); + fprintf(stderr, "WARNING: YUV format not specified; defaulting to Berkeley YUV (EYUV)\n\n"); + } + + } + + if ( stdinUsed && optionSeen[OPTION_PARALLEL] ) { + throw "stdin reading for parallel execution not enabled yet"; + } + + + if ( optionSeen[OPTION_PARALLEL] && !optionSeen[OPTION_YUV_SIZE]) { + throw "Specify SIZE WxH for parallel encoding"; + } + + if ( optionSeen[OPTION_IO_CONVERT] != optionSeen[OPTION_SLAVE_CONVERT] ) { + throw "must have either both IO_SERVER_CONVERT and SLAVE_CONVERT or neither"; + } + + if ( optionSeen[OPTION_DEFS_SPECIFICS] && !optionSeen[OPTION_SPECIFICS]) { + throw "does not make sense to define Specifics file options, but no specifics file"; + } + + SetIOConvert(optionSeen[OPTION_IO_CONVERT]); + + SetResize(optionSeen[OPTION_RESIZE]); + + if ( function == ENCODE_FRAMES ) { + SetFCode(); + + if ( psearchAlg == PSEARCH_TWOLEVEL ) + SetPixelSearch((char*)"HALF"); + } + + return TRUE; +} + + +/*===========================================================================* + * + * GetNthInputFileName + * + * finds the nth input file name + * + * RETURNS: name is placed in already allocated fileName string + * + * SIDE EFFECTS: none + * + *===========================================================================*/ +void +GetNthInputFileName(char *fileName, + int n) +{ + static int lastN = 0, lastMapN = 0, lastSoFar = 0; + int mapN; + register int index; + int soFar; + int loop; + int numPadding; + char numBuffer[33]; + + if ( stdinUsed ) { + return; + } + + /* assumes n is within bounds 0...numInputFiles-1 */ + + if ( n >= lastN ) { + soFar = lastSoFar; + index = lastMapN; + } else { + soFar = 0; + index = 0; + } + + while ( soFar + inputFileEntries[index]->numFiles <= n ) { + soFar += inputFileEntries[index]->numFiles; + index++; + } + + mapN = index; + + index = inputFileEntries[mapN]->startID + + inputFileEntries[mapN]->skip*(n-soFar); + + numPadding = inputFileEntries[mapN]->numPadding; + + if ( numPadding != -1 ) { + sprintf(numBuffer, "%32d", index); + for ( loop = 32-numPadding; loop < 32; loop++ ) { + if ( numBuffer[loop] != ' ' ) { + break; + } else { + numBuffer[loop] = '0'; + } + } + + if (inputFileEntries[mapN]->repeat != TRUE) { + sprintf(fileName, "%s%s%s", + inputFileEntries[mapN]->left, + &numBuffer[32-numPadding], + inputFileEntries[mapN]->right); + } else { + sprintf(fileName, "%s", inputFileEntries[mapN]->left); + } + } else { + if (inputFileEntries[mapN]->repeat != TRUE) { + sprintf(fileName, "%s%d%s", + inputFileEntries[mapN]->left, + index, + inputFileEntries[mapN]->right); + } else { + sprintf(fileName, "%s", inputFileEntries[mapN]->left); + } + } + + lastN = n; + lastMapN = mapN; + lastSoFar = soFar; +} + + +/*=====================* + * INTERNAL PROCEDURES * + *=====================*/ + +/*===========================================================================* + * + * ReadMachineNames + * + * read a list of machine names for parallel execution + * + * RETURNS: nothing + * + * SIDE EFFECTS: machine info updated + * + *===========================================================================*/ +static void +ReadMachineNames(FILE *fpointer) +{ + char input[256]; + char *charPtr; + + while ( (fgets(input, 256, fpointer) != NULL) && + (strncmp(input, "END_PARALLEL", 12) != 0) ) { + if ( input[0] == '#' || input[0] == '\n') { + continue; + } + + if ( strncmp(input, "REMOTE", 6) == 0 ) { + charPtr = SkipSpacesTabs(&input[6]); + remote[numMachines] = TRUE; + + sscanf(charPtr, "%s %s %s %s", machineName[numMachines], + userName[numMachines], executable[numMachines], + remoteParamFile[numMachines]); + } else { + remote[numMachines] = FALSE; + + sscanf(input, "%s %s %s", machineName[numMachines], + userName[numMachines], executable[numMachines]); + } + + numMachines++; + } +} + + +/*===========================================================================* + * + * ReadInputFileNames + * + * read a list of input file names + * + * RETURNS: nothing + * + * SIDE EFFECTS: info stored for retrieval using GetNthInputFileName + * + *===========================================================================*/ +static void +ReadInputFileNames(FILE *fpointer, + const char *endInput) +{ + char input[256]; + char left[256], right[256]; + char *globPtr, *charPtr; + char leftNumText[256], rightNumText[256]; + char skipNumText[256]; + int leftNum, rightNum; + int skipNum; + boolean padding; + int numPadding = 0; + int length; + char full_path[MAXPATHLEN + 256]; + FILE *jmovie; + + inputFileEntries = (InputFileEntry **) malloc(INPUT_ENTRY_BLOCK_SIZE* + sizeof(InputFileEntry *)); + maxInputFileEntries = INPUT_ENTRY_BLOCK_SIZE; + + length = strlen(endInput); + + /* read input files up until endInput */ + while ( (fgets(input, 256, fpointer) != NULL) && + (strncmp(input, endInput, length) != 0) ) { + + /* if input is coming in via standard input, keep on looping till the + * endInput string is reached so that the program points to the right + * place on exit. + */ + if ( stdinUsed ) { + continue; + } + + /* ignore comments and newlines */ + if ( (input[0] == '#') || (input[0] == '\n') ) { + continue; + } + + if (input[0] == '`' ) { /* Recurse for commands */ + FILE *fp; + char cmd[300], *start, *end, tmp[300], cdcmd[110]; + + start = &input[1]; + end = &input[strlen(input)-1]; + + while (*end != '`') { + end--; + } + + end--; + + if (optionSeen[OPTION_INPUT_DIR] == TRUE) { + sprintf(cdcmd,"cd %s;",currentPath); + } else { + strcpy(cdcmd,""); + } + strncpy(tmp,start,end-start+1); + sprintf(cmd,"(%s %s)", cdcmd, tmp); + + fp = popen(cmd,"r"); + if (fp == NULL) { + fprintf(stderr,"Command failed! Could not open piped command:\n%s\n",cmd); + continue; + } + ReadInputFileNames(fp,"HOPE-THIS_ISNT_A_FILENAME.xyz5555"); + continue; + } + + + /* get rid of trailing whitespace including newline */ + while (isspace(input[strlen(input)-1])) { + input[strlen(input)-1] = '\0'; + } + + if ( numInputFileEntries == maxInputFileEntries ) { /* more space! */ + maxInputFileEntries += INPUT_ENTRY_BLOCK_SIZE; + inputFileEntries = (InputFileEntry **) realloc(inputFileEntries, + maxInputFileEntries* + sizeof(InputFileEntry *)); + } + + inputFileEntries[numInputFileEntries] = (InputFileEntry *) + malloc(sizeof(InputFileEntry)); + + if ( input[strlen(input)-1] == ']' ) { + inputFileEntries[numInputFileEntries]->glob = TRUE; + inputFileEntries[numInputFileEntries]->repeat = FALSE; + + /* star expand */ + + globPtr = input; + charPtr = left; + /* copy left of '*' */ + while ( (*globPtr != '\0') && (*globPtr != '*') ) { + *charPtr = *globPtr; + charPtr++; + globPtr++; + } + *charPtr = '\0'; + + if (*globPtr == '\0') { + fprintf(stderr, "WARNING: expanding non-star regular expression\n"); + inputFileEntries[numInputFileEntries]->repeat = TRUE; + globPtr = input; + charPtr = left; + /* recopy left of whitespace */ + while ( (*globPtr != '\0') && (*globPtr != '*') && + (*globPtr != ' ') && (*globPtr != '\t')) { + *charPtr = *globPtr; + charPtr++; + globPtr++; + } + *charPtr = '\0'; + *right = '\0'; + } else { + + globPtr++; + charPtr = right; + /* copy right of '*' */ + while ( (*globPtr != '\0') && (*globPtr != ' ') && + (*globPtr != '\t') ) { + *charPtr = *globPtr; + charPtr++; + globPtr++; + } + *charPtr = '\0'; + } + + globPtr = SkipSpacesTabs(globPtr); + + if ( *globPtr != '[' ) { + throw "Invalid input file expansion expression (no '[')"; + } + + globPtr++; + charPtr = leftNumText; + /* copy left number */ + while ( isdigit(*globPtr) ) { + *charPtr = *globPtr; + charPtr++; + globPtr++; + } + *charPtr = '\0'; + + if ( *globPtr != '-' ) { + throw "Invalid input file expansion expression (no '-')"; + } + + globPtr++; + charPtr = rightNumText; + /* copy right number */ + while ( isdigit(*globPtr) ) { + *charPtr = *globPtr; + charPtr++; + globPtr++; + } + *charPtr = '\0'; + if ( atoi(rightNumText) < atoi(leftNumText) ) { + throw "Beginning of input range is higher than end"; + } + + + if ( *globPtr != ']' ) { + if ( *globPtr != '+' ) { + throw "Invalid input file expansion expression (no ']')"; + } + + globPtr++; + charPtr = skipNumText; + /* copy skip number */ + while ( isdigit(*globPtr) ) { + *charPtr = *globPtr; + charPtr++; + globPtr++; + } + *charPtr = '\0'; + + if ( *globPtr != ']' ) { + throw "Invalid input file expansion expression (no ']')"; + } + + skipNum = atoi(skipNumText); + } else { + skipNum = 1; + } + + leftNum = atoi(leftNumText); + rightNum = atoi(rightNumText); + + if ( (leftNumText[0] == '0') && (leftNumText[1] != '\0') ) { + padding = TRUE; + numPadding = strlen(leftNumText); + } else { + padding = FALSE; + } + + inputFileEntries[numInputFileEntries]->startID = leftNum; + inputFileEntries[numInputFileEntries]->endID = rightNum; + inputFileEntries[numInputFileEntries]->skip = skipNum; + inputFileEntries[numInputFileEntries]->numFiles = (rightNum-leftNum+1)/skipNum; + strcpy(inputFileEntries[numInputFileEntries]->left, left); + strcpy(inputFileEntries[numInputFileEntries]->right, right); + if ( padding ) { + inputFileEntries[numInputFileEntries]->numPadding = numPadding; + } else { + inputFileEntries[numInputFileEntries]->numPadding = -1; + } + } else { + strcpy(inputFileEntries[numInputFileEntries]->left, input); + if (baseFormat == JMOVIE_FILE_TYPE) { + inputFileEntries[numInputFileEntries]->glob = TRUE; + full_path[0] = '\0'; + strcpy(full_path, currentPath); + + if (! stdinUsed) { + strcat(full_path, "/"); + strcat(full_path, input); + jmovie = fopen(input, "rb"); + + if (jmovie == NULL) { + perror (input); + } + + fseek (jmovie, (8*sizeof(char)), 0); + fseek (jmovie, (2*sizeof(int)), 1); + + if (fread (&(inputFileEntries[numInputFileEntries]->numFiles), + sizeof(int), 1, jmovie) != 1) { + throw "Error in reading number of frames in JMOVIE"; + } + fclose (jmovie); + } + + strcpy(inputFileEntries[numInputFileEntries]->right,".jpg"); + inputFileEntries[numInputFileEntries]->numPadding = -1; + inputFileEntries[numInputFileEntries]->startID = 1; + inputFileEntries[numInputFileEntries]->endID = (inputFileEntries[numInputFileEntries]->numFiles-1); + inputFileEntries[numInputFileEntries]->skip = 1; + if (! realQuiet) { + fprintf (stdout, "Encoding all %d frames from JMOVIE.\n", inputFileEntries[numInputFileEntries]->endID); + } + } else { + inputFileEntries[numInputFileEntries]->glob = FALSE; + inputFileEntries[numInputFileEntries]->numFiles = 1; + /* fixes a bug from version 1.3: */ + inputFileEntries[numInputFileEntries]->numPadding = 0; + /* fixes a bug from version 1.4 */ + strcpy(inputFileEntries[numInputFileEntries]->right,"\0"); + inputFileEntries[numInputFileEntries]->startID = 0; + inputFileEntries[numInputFileEntries]->endID = 0; + inputFileEntries[numInputFileEntries]->skip = 0; + } + } + + numInputFiles += inputFileEntries[numInputFileEntries]->numFiles; + numInputFileEntries++; + } +} + + +/*===========================================================================* + * + * SkipSpacesTabs + * + * skip all spaces and tabs + * + * RETURNS: point to next character not a space or tab + * + * SIDE EFFECTS: none + * + *===========================================================================*/ +char * +SkipSpacesTabs(char *start) +{ + while ( (*start == ' ') || (*start == '\t') ) { + start++; + } + + return start; +} + + +/*===========================================================================* + * + * GetFrameRate + * + * take a character string with the input frame rate + * and return the correct frame rate code for use in the Sequence header + * + * RETURNS: frame rate code as per MPEG-I spec + * + * SIDE EFFECTS: none + * + *===========================================================================*/ +static int +GetFrameRate(char *p) +{ + float rate; + int thouRate; + + sscanf(p, "%f", &rate); + thouRate = (int)(0.5+1000.0*rate); + + if ( thouRate == 23976 ) return 1; + else if ( thouRate == 24000 ) return 2; + else if ( thouRate == 25000 ) return 3; + else if ( thouRate == 29970 ) return 4; + else if ( thouRate == 30000 ) return 5; + else if ( thouRate == 50000 ) return 6; + else if ( thouRate == 59940 ) return 7; + else if ( thouRate == 60000 ) return 8; + else { + throw "INVALID FRAME RATE"; + } +} + + +/*===========================================================================* + * + * GetAspectRatio + * + * take a character string with the pixel aspect ratio + * and returns the correct aspect ratio code for use in the Sequence header + * + * RETURNS: aspect ratio code as per MPEG-I spec + * + * SIDE EFFECTS: none + * + *===========================================================================*/ +static int +GetAspectRatio(char *p) +{ + float ratio; + int ttRatio; + + sscanf(p, "%f", &ratio); + ttRatio = (int)(0.5+ratio*10000.0); + + if ( ttRatio == 10000 ) return 1; + else if ( ttRatio == 6735 ) return 2; + else if ( ttRatio == 7031 ) return 3; + else if ( ttRatio == 7615 ) return 4; + else if ( ttRatio == 8055 ) return 5; + else if ( ttRatio == 8437 ) return 6; + else if ( ttRatio == 8935 ) return 7; + else if ( ttRatio == 9157 ) return 8; + else if ( ttRatio == 9815 ) return 9; + else if ( ttRatio == 10255 ) return 10; + else if ( ttRatio == 10695 ) return 11; + else if ( ttRatio == 10950 ) return 12; + else if ( ttRatio == 11575 ) return 13; + else if ( ttRatio == 12015 ) return 14; + else { + throw "INVALID ASPECT RATIO"; + } +} + + + + + + +/**************************************************************** + * Jim Boucher's code + * + * + ****************************************************************/ +void +JM2JPEG() +{ + char full_path[MAXPATHLEN + 256]; + char inter_file[MAXPATHLEN +256]; + int ci; + + for(ci = 0; ci < numInputFileEntries; ci++) { + inter_file[0] = '\0'; + full_path[0] = '\0'; + strcpy(full_path, currentPath); + + if (! stdinUsed) { + strcat(full_path, "/"); + strcat(full_path, inputFileEntries[ci]->left); + strcpy(inter_file,full_path); + + if (! realQuiet) { + fprintf(stdout, "Extracting JPEG's in the JMOVIE from %s\n",full_path); + } + + JMovie2JPEG(full_path, + inter_file, + inputFileEntries[ci]->startID, inputFileEntries[ci]->endID); + } else { + throw "JMovie format not supported with stdin yet"; + } + + } +} diff --git a/contrib/mpeg_encode/param.new b/contrib/mpeg_encode/param.new new file mode 100644 index 0000000000000000000000000000000000000000..b2f63c130062226304a4e2771367e4657f9e4ab4 --- /dev/null +++ b/contrib/mpeg_encode/param.new @@ -0,0 +1,1141 @@ +/*===========================================================================* + * param.c * + * * + * Procedures to read in parameter file * + * * + * EXPORTED PROCEDURES: * + * ReadParamFile * + * GetNthInputFileName * + * * + *===========================================================================*/ + +/* + * Copyright (c) 1995 The Regents of the University of California. + * All rights reserved. + * + * Permission to use, copy, modify, and distribute this software and its + * documentation for any purpose, without fee, and without written agreement is + * hereby granted, provided that the above copyright notice and the following + * two paragraphs appear in all copies of this software. + * + * IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR + * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT + * OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF + * CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS + * ON AN "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO + * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. + */ + +/* + * $Header: /n/picasso/project/mm/mpeg/mpeg_dist/mpeg_encode/RCS/param.c,v 1.24 1995/01/20 00:07:46 smoot Exp darryl $ + * $Log: param.c,v $ + * Revision 1.24 1995/01/20 00:07:46 smoot + * requires unistd.c now + * + * Revision 1.23 1995/01/20 00:05:33 smoot + * Added gamma correction option + * + * Revision 1.22 1995/01/19 23:55:55 eyhung + * Fixed up smoot's "style" and made YUV_FORMAT default to EYUV + * + * Revision 1.21 1995/01/19 23:09:03 eyhung + * Changed copyrights + * + * Revision 1.20 1995/01/17 22:04:14 smoot + * Added `commands` to file name listing + * + * Revision 1.19 1995/01/17 06:28:01 eyhung + * StdinUsed added. + * + * Revision 1.18 1995/01/16 09:33:35 eyhung + * Fixed stupid commenting error. + * + * Revision 1.17 1995/01/16 06:07:53 eyhung + * Made it look a little nicer + * + * Revision 1.16 1995/01/13 23:57:25 smoot + * added Y format + * + * Revision 1.15 1995/01/08 06:20:39 eyhung + * *** empty log message *** + * + * Revision 1.14 1995/01/08 06:15:57 eyhung + * *** empty log message *** + * + * Revision 1.13 1995/01/08 05:50:32 eyhung + * Added YUV Format parameter + * + * Revision 1.12 1994/12/16 00:55:30 smoot + * Fixed INPU_FILES bug + * + * Revision 1.11 1994/12/12 23:54:36 smoot + * Fixed GOP-missing error message (GOP to GOP_SIZE) + * + * Revision 1.10 1994/12/07 00:40:36 smoot + * Added seperate P and B search ranges + * + * Revision 1.9 1994/11/18 23:19:22 smoot + * Added USER_DATA parameter + * + * Revision 1.8 1994/11/16 22:33:40 smoot + * Put in ifdef for rsh in param.c + * + * Revision 1.7 1994/11/16 22:25:05 smoot + * Corrected ASPECT_RATIO bug + * + * Revision 1.6 1994/11/14 22:39:26 smoot + * merged specifics and rate control + * + * Revision 1.5 1994/11/01 05:01:41 darryl + * with rate control changes added + * + * Revision 1.1 1994/09/27 00:16:28 darryl + * Initial revision + * + * Revision 1.4 1994/03/15 00:27:11 keving + * nothing + * + * Revision 1.3 1993/12/22 19:19:01 keving + * nothing + * + * Revision 1.2 1993/07/22 22:23:43 keving + * nothing + * + * Revision 1.1 1993/06/30 20:06:09 keving + * nothing + * + */ + + +/*==============* + * HEADER FILES * + *==============*/ + +#include "all.h" +#include "mtypes.h" +#include "mpeg.h" +#include "search.h" +#include "prototypes.h" +#include "parallel.h" +#include "param.h" +#include "readframe.h" +#include "fsize.h" +#include "frames.h" +#include "jpeg.h" +#include "strings.h" +#include <string.h> +#include <ctype.h> +#include "rate.h" +#include <unistd.h> + +/*===========* + * CONSTANTS * + *===========*/ + +#define INPUT_ENTRY_BLOCK_SIZE 128 + +#define FIRST_OPTION 0 +#define OPTION_GOP 0 +#define OPTION_PATTERN 1 +#define OPTION_PIXEL 2 +#define OPTION_PQSCALE 3 +#define OPTION_OUTPUT 4 +#define OPTION_RANGE 5 +#define OPTION_PSEARCH_ALG 6 +#define OPTION_IQSCALE 7 +#define OPTION_INPUT_DIR 8 +#define OPTION_INPUT_CONVERT 9 +#define OPTION_INPUT 10 +#define OPTION_BQSCALE 11 +#define OPTION_BASE_FORMAT 12 +#define OPTION_SPF 13 +#define OPTION_BSEARCH_ALG 14 +#define OPTION_REF_FRAME 15 +#define LAST_OPTION 15 + +/* put any non-required options after LAST_OPTION */ +#define OPTION_RESIZE 16 +#define OPTION_IO_CONVERT 17 +#define OPTION_SLAVE_CONVERT 18 +#define OPTION_IQTABLE 19 +#define OPTION_NIQTABLE 20 +#define OPTION_FRAME_RATE 21 +#define OPTION_ASPECT_RATIO 22 +#define OPTION_YUV_SIZE 23 +#define OPTION_SPECIFICS 24 +#define OPTION_DEFS_SPECIFICS 25 +#define OPTION_BUFFER_SIZE 26 +#define OPTION_BIT_RATE 27 +#define OPTION_USER_DATA 28 +#define OPTION_YUV_FORMAT 29 +#define OPTION_GAMMA 30 + +#define NUM_OPTIONS 30 + +/*=======================* + * STRUCTURE DEFINITIONS * + *=======================*/ + +typedef struct InputFileEntryStruct { + char left[256]; + char right[256]; + boolean glob; /* if FALSE, left is complete name */ + int startID; + int endID; + int skip; + int numPadding; /* -1 if there is none */ + int numFiles; +} InputFileEntry; + + +/*==================* + * STATIC VARIABLES * + *==================*/ + +static InputFileEntry **inputFileEntries; +static int numInputFileEntries = 0; +static int maxInputFileEntries; + + +/*==================* + * GLOBAL VARIABLES * + *==================*/ + +extern char currentPath[MAXPATHLEN]; +extern char currentGOPPath[MAXPATHLEN]; +extern char currentFramePath[MAXPATHLEN]; +char outputFileName[256]; +int outputWidth, outputHeight; +int numInputFiles = 0; +char inputConversion[1024]; +char ioConversion[1024]; +char slaveConversion[1024]; +char yuvConversion[256]; +char specificsFile[256],specificsDefines[1024]=""; +boolean GammaCorrection=FALSE; +float GammaValue; +unsigned char userDataFileName[256]={0}; +boolean specificsOn = FALSE; +boolean optionSeen[NUM_OPTIONS+1]; +int numMachines; +char machineName[MAX_MACHINES][256]; +char userName[MAX_MACHINES][256]; +char executable[MAX_MACHINES][1024]; +char remoteParamFile[MAX_MACHINES][1024]; +boolean remote[MAX_MACHINES]; +boolean stdinUsed = FALSE; + + +/*===============================* + * INTERNAL PROCEDURE prototypes * + *===============================*/ +static void ReadInputFileNames _ANSI_ARGS_((FILE *fpointer, + char *endInput)); +static char *SkipSpacesTabs _ANSI_ARGS_((char *start)); +static void ReadMachineNames _ANSI_ARGS_((FILE *fpointer)); +static int GetAspectRatio _ANSI_ARGS_((char *p)); +static int GetFrameRate _ANSI_ARGS_((char *p)); + + +/*=====================* + * EXPORTED PROCEDURES * + *=====================*/ + + +/*===========================================================================* + * + * ReadParamFile + * + * read the parameter file + * function is ENCODE_FRAMES, COMBINE_GOPS, or COMBINE_FRAMES, and + * will slightly modify the procedure's behavior as to what it + * is looking for in the parameter file + * + * RETURNS: TRUE if the parameter file was read correctly; FALSE if not + * + * SIDE EFFECTS: sets parameters accordingly, as well as machine info for + * parallel execution and input file names + * + *===========================================================================*/ +boolean +ReadParamFile(fileName, function) + char *fileName; + int function; +{ + FILE *fpointer; + char input[256]; + char *charPtr; + boolean yuvUsed = FALSE; + static char *optionText[LAST_OPTION+1] = { "GOP_SIZE", "PATTERN", "PIXEL", "PQSCALE", + "OUTPUT", "RANGE", "PSEARCH_ALG", "IQSCALE", "INPUT_DIR", + "INPUT_CONVERT", "INPUT", "BQSCALE", "BASE_FILE_FORMAT", + "SLICES_PER_FRAME", "BSEARCH_ALG", "REFERENCE_FRAME"}; + register int index; + register int row; + + if ( (fpointer = fopen(fileName, "r")) == NULL ) { + fprintf(stderr, "Error: Cannot open parameter file: %s\n", fileName); + return FALSE; + } + + /* should set defaults */ + numInputFiles = 0; + numMachines = 0; + sprintf(currentPath, "."); + sprintf(currentGOPPath, "."); + sprintf(currentFramePath, "."); +#ifndef HPUX + SetRemoteShell("rsh"); +#else + SetRemoteShell("remsh"); +#endif + + switch(function) { + case ENCODE_FRAMES: + for ( index = FIRST_OPTION; index <= LAST_OPTION; index++ ) { + optionSeen[index] = FALSE; + } + optionSeen[OPTION_IO_CONVERT] = FALSE; + optionSeen[OPTION_SLAVE_CONVERT] = FALSE; + break; + case COMBINE_GOPS: + for ( index = FIRST_OPTION; index <= LAST_OPTION; index++ ) { + optionSeen[index] = TRUE; + } + + optionSeen[OPTION_OUTPUT] = FALSE; + break; + case COMBINE_FRAMES: + for ( index = FIRST_OPTION; index <= LAST_OPTION; index++ ) { + optionSeen[index] = TRUE; + } + + optionSeen[OPTION_GOP] = FALSE; + optionSeen[OPTION_OUTPUT] = FALSE; + break; + } + + for(index=LAST_OPTION+1; index<= NUM_OPTIONS; index++) optionSeen[index]=FALSE; + + while ( fgets(input, 256, fpointer) != NULL ) { + /* skip comments */ + if ( input[0] == '#' ) { + continue; + } + + input[strlen(input)-1] = '\0'; /* get rid of newline */ + + switch(input[0]) { + case 'A': + if ( strncmp(input, "ASPECT_RATIO", 12) == 0 ) { + charPtr = SkipSpacesTabs(&input[12]); + aspectRatio = GetAspectRatio(charPtr); + optionSeen[OPTION_ASPECT_RATIO] = TRUE; + } + break; + + case 'B': + if ( strncmp(input, "BQSCALE", 7) == 0 ) { + charPtr = SkipSpacesTabs(&input[7]); + SetBQScale(atoi(charPtr)); + optionSeen[OPTION_BQSCALE] = TRUE; + } else if ( strncmp(input, "BASE_FILE_FORMAT", 16) == 0 ) { + charPtr = SkipSpacesTabs(&input[16]); + SetFileFormat(charPtr); + if ( (strcmp(charPtr,"YUV") == 0) || + (strcmp(charPtr,"Y") == 0) ) { + yuvUsed = TRUE; + } + optionSeen[OPTION_BASE_FORMAT] = TRUE; + } else if ( strncmp(input, "BSEARCH_ALG", 11) == 0 ) { + charPtr = SkipSpacesTabs(&input[11]); + SetBSearchAlg(charPtr); + optionSeen[OPTION_BSEARCH_ALG] = TRUE; + } else if ( strncmp(input, "BIT_RATE", 8) == 0 ) { + charPtr = SkipSpacesTabs(&input[8]); + setBitRate(charPtr); + optionSeen[OPTION_BIT_RATE] = TRUE; + } else if ( strncmp(input, "BUFFER_SIZE", 11) == 0 ) { + charPtr = SkipSpacesTabs(&input[11]); + setBufferSize(charPtr); + optionSeen[OPTION_BUFFER_SIZE] = TRUE; + } + break; + + case 'F': + if ( strncmp(input, "FRAME_INPUT_DIR", 15) == 0 ) { + charPtr = SkipSpacesTabs(&input[15]); + strcpy(currentFramePath, charPtr); + } else if ( strncmp(input, "FRAME_INPUT", 11) == 0 ) { + if ( function == COMBINE_FRAMES ) { + ReadInputFileNames(fpointer, "FRAME_END_INPUT"); + } + } else if ( strncmp(input, "FORCE_I_ALIGN", 13) == 0 ) { + forceIalign = TRUE; + } else if ( strncmp(input, "FORCE_ENCODE_LAST_FRAME", 23) == 0 ) { + forceEncodeLast = TRUE; + } else if ( strncmp(input, "FRAME_RATE", 10) == 0 ) { + charPtr = SkipSpacesTabs(&input[10]); + frameRate = GetFrameRate(charPtr); + optionSeen[OPTION_FRAME_RATE] = TRUE; + } + break; + + case 'G': + if ( strncmp(input, "GOP_SIZE", 8) == 0 ) { + charPtr = SkipSpacesTabs(&input[8]); + SetGOPSize(atoi(charPtr)); + optionSeen[OPTION_GOP] = TRUE; + } else if ( strncmp(input, "GOP_INPUT_DIR", 13) == 0 ) { + charPtr = SkipSpacesTabs(&input[13]); + strcpy(currentGOPPath, charPtr); + } else if ( strncmp(input, "GOP_INPUT", 9) == 0 ) { + if ( function == COMBINE_GOPS ) { + ReadInputFileNames(fpointer, "GOP_END_INPUT"); + } + } else if ( strncmp(input, "GAMMA", 5) == 0) { + charPtr = SkipSpacesTabs(&input[5]); + GammaCorrection=TRUE; + sscanf(charPtr,"%f",&GammaValue); + optionSeen[OPTION_GAMMA] = TRUE; + } + break; + + case 'I': + if ( strncmp(input, "IQSCALE", 7) == 0 ) { + charPtr = SkipSpacesTabs(&input[7]); + SetIQScale(atoi(charPtr)); + optionSeen[OPTION_IQSCALE] = TRUE; + } else if ( strncmp(input, "INPUT_DIR", 9) == 0 ) { + charPtr = SkipSpacesTabs(&input[9]); + strcpy(currentPath, charPtr); + optionSeen[OPTION_INPUT_DIR] = TRUE; + } else if ( strncmp(input, "INPUT_CONVERT", 13) == 0 ) { + charPtr = SkipSpacesTabs(&input[13]); + strcpy(inputConversion, charPtr); + optionSeen[OPTION_INPUT_CONVERT] = TRUE; + } else if ( strcmp(input, "INPUT") == 0 ) { /* yes, strcmp */ + if ( function == ENCODE_FRAMES ) { + ReadInputFileNames(fpointer, "END_INPUT"); + optionSeen[OPTION_INPUT] = TRUE; + } + } else if ( strncmp(input, "IO_SERVER_CONVERT", 17) == 0 ) { + charPtr = SkipSpacesTabs(&input[17]); + strcpy(ioConversion, charPtr); + optionSeen[OPTION_IO_CONVERT] = TRUE; + } else if ( strncmp(input, "IQTABLE", 7) == 0 ) { + for ( row = 0; row < 8; row ++ ) { + fgets(input, 256, fpointer); + charPtr = input; + sscanf(charPtr,"%d %d %d %d %d %d %d %d", + &qtable[row*8+0], + &qtable[row*8+1], + &qtable[row*8+2], + &qtable[row*8+3], + &qtable[row*8+4], + &qtable[row*8+5], + &qtable[row*8+6], + &qtable[row*8+7]); + } + + if ( qtable[0] != 8 ) { + fprintf(stdout, "Warning: [0][0] entry reset to 8, since it must be\n"); + qtable[0] = 8; + } + + customQtable = qtable; + optionSeen[OPTION_IQTABLE] = TRUE; + } + + break; + + case 'N': + if ( strncmp(input, "NIQTABLE", 8) == 0 ) { + for ( row = 0; row < 8; row ++ ) { + fgets(input, 256, fpointer); + charPtr = input; + sscanf(charPtr,"%d %d %d %d %d %d %d %d", + &niqtable[row*8+0], + &niqtable[row*8+1], + &niqtable[row*8+2], + &niqtable[row*8+3], + &niqtable[row*8+4], + &niqtable[row*8+5], + &niqtable[row*8+6], + &niqtable[row*8+7]); + } + + customNIQtable = niqtable; + optionSeen[OPTION_NIQTABLE] = TRUE; + } + + break; + + case 'O': + if ( strncmp(input, "OUTPUT", 6) == 0 ) { + charPtr = SkipSpacesTabs(&input[6]); + if ( whichGOP == -1 ) { + strcpy(outputFileName, charPtr); + } else { + sprintf(outputFileName, "%s.gop.%d", + charPtr, whichGOP); + } + + optionSeen[OPTION_OUTPUT] = TRUE; + } + + break; + + case 'P': + if ( strncmp(input, "PATTERN", 7) == 0 ) { + charPtr = SkipSpacesTabs(&input[7]); + SetFramePattern(charPtr); + optionSeen[OPTION_PATTERN] = TRUE; + } else if ( strncmp(input, "PIXEL", 5) == 0 ) { + charPtr = SkipSpacesTabs(&input[5]); + SetPixelSearch(charPtr); + optionSeen[OPTION_PIXEL] = TRUE; + } else if ( strncmp(input, "PQSCALE", 7) == 0 ) { + charPtr = SkipSpacesTabs(&input[7]); + SetPQScale(atoi(charPtr)); + optionSeen[OPTION_PQSCALE] = TRUE; + } else if ( strncmp(input, "PSEARCH_ALG", 11) == 0 ) { + charPtr = SkipSpacesTabs(&input[11]); + SetPSearchAlg(charPtr); + optionSeen[OPTION_PSEARCH_ALG] = TRUE; + } else if ( strncmp(input, "PARALLEL_TEST_FRAMES", 20) == 0 ) { + charPtr = SkipSpacesTabs(&input[20]); + parallelTestFrames = atoi(charPtr); + } else if ( strncmp(input, "PARALLEL_TIME_CHUNKS", 20) == 0 ) { + charPtr = SkipSpacesTabs(&input[20]); + parallelTimeChunks = atoi(charPtr); + } else if ( strncmp(input, "PARALLEL_CHUNK_TAPER", 20) == 0 ) { + parallelTimeChunks = -1; + } else if ( strncmp(input, "PARALLEL_PERFECT", 16) == 0 ) { + SetParallelPerfect(); + } else if ( strncmp(input, "PARALLEL", 8) == 0 ) { + ReadMachineNames(fpointer); + } + + break; + + case 'R': + if ( strncmp(input, "RANGE", 5) == 0 ) { + int num_ranges=0,a,b; + charPtr = SkipSpacesTabs(&input[5]); + optionSeen[OPTION_RANGE] = TRUE; + num_ranges=sscanf(charPtr,"%d %d",&a,&b); + if (num_ranges==2) { + SetSearchRange(a,b); + } else if (sscanf(charPtr,"%d [%d]",&a,&b)==2) { + SetSearchRange(a,b); + } else SetSearchRange(a,a); + } else if ( strncmp(input, "REFERENCE_FRAME", 15) == 0 ) { + charPtr = SkipSpacesTabs(&input[15]); + SetReferenceFrameType(charPtr); + optionSeen[OPTION_REF_FRAME] = TRUE; + } else if ( strncmp(input, "RSH", 3) == 0 ) { + charPtr = SkipSpacesTabs(&input[3]); + SetRemoteShell(charPtr); + } else if ( strncmp(input, "RESIZE", 6) == 0 ) { + charPtr = SkipSpacesTabs(&input[6]); + sscanf(charPtr, "%dx%d", &outputWidth, &outputHeight); + outputWidth &= ~(DCTSIZE * 2 - 1); + outputHeight &= ~(DCTSIZE * 2 - 1); + optionSeen[OPTION_RESIZE] = TRUE; + } + + break; + + case 'S': + if ( strncmp(input, "SLICES_PER_FRAME", 16) == 0 ) { + charPtr = SkipSpacesTabs(&input[16]); + SetSlicesPerFrame(atoi(charPtr)); + optionSeen[OPTION_SPF] = TRUE; + } else if ( strncmp(input, "SLAVE_CONVERT", 13) == 0 ) { + charPtr = SkipSpacesTabs(&input[13]); + strcpy(slaveConversion, charPtr); + optionSeen[OPTION_SLAVE_CONVERT] = TRUE; + charPtr = SkipSpacesTabs(&input[14]); + strcpy(specificsFile, charPtr); + specificsOn=TRUE; + optionSeen[OPTION_SPECIFICS] = TRUE; + } else if ( strncmp(input, "SPECIFICS_DEFINES", 16) == 0 ) { + charPtr = SkipSpacesTabs(&input[17]); + strcpy(specificsDefines, charPtr); + optionSeen[OPTION_DEFS_SPECIFICS] = TRUE; + } + + break; + + case 'U': + if ( strncmp(input, "USER_DATA", 9) == 0 ) { + charPtr = SkipSpacesTabs(&input[9]); + strcpy(userDataFileName, charPtr); + optionSeen[OPTION_USER_DATA] = TRUE; + } + + break; + + case 'Y': + if (strncmp(input, "YUV_SIZE", 8) == 0 ) { + charPtr = SkipSpacesTabs(&input[8]); + sscanf(charPtr, "%dx%d", &yuvWidth, &yuvHeight); + realWidth = yuvWidth; + realHeight = yuvHeight; + Fsize_Validate(&yuvWidth, &yuvHeight); + optionSeen[OPTION_YUV_SIZE] = TRUE; + } + else if (strncmp(input, "Y_SIZE", 6) == 0 ) { + charPtr = SkipSpacesTabs(&input[6]); + sscanf(charPtr, "%dx%d", &yuvWidth, &yuvHeight); + realWidth = yuvWidth; + realHeight = yuvHeight; + Fsize_Validate(&yuvWidth, &yuvHeight); + optionSeen[OPTION_YUV_SIZE] = TRUE; + } + else if ( strncmp(input, "YUV_FORMAT", 10) == 0 ) { + charPtr = SkipSpacesTabs(&input[10]); + strcpy(yuvConversion, charPtr); + optionSeen[OPTION_YUV_FORMAT] = TRUE; + } + + break; + + default: + break; + } + } + + fclose(fpointer); + + for ( index = FIRST_OPTION; index <= LAST_OPTION; index++ ) { + if ( ! optionSeen[index] ) { + fprintf(stderr, "ERROR: Missing option '%s'\n", optionText[index]); + exit(1); + } + } + + /* error checking */ + if ( yuvUsed ) { + + if (! optionSeen[OPTION_YUV_SIZE]) { + fprintf(stderr, "ERROR: YUV format used but YUV_SIZE not given\n"); + exit(1); + } + + if (! optionSeen[OPTION_YUV_FORMAT]) { + strcpy (yuvConversion, "EYUV"); + fprintf(stderr, "WARNING: YUV format not specified; defaulting to Berkeley YUV\n\n"); + } + + } + + if ( optionSeen[OPTION_IO_CONVERT] != optionSeen[OPTION_SLAVE_CONVERT] ) { + fprintf(stderr, "ERROR: must have either both IO_SERVER_CONVERT and SLAVE_CONVERT\n"); + fprintf(stderr, " or neither\n"); + exit(1); + } + + if ( optionSeen[OPTION_DEFS_SPECIFICS] && !optionSeen[OPTION_SPECIFICS]) { + fprintf(stderr, "ERROR: does not make sense to define Specifics file options, but no specifics file!\n"); + exit(1); + } + + SetIOConvert(optionSeen[OPTION_IO_CONVERT]); + + SetResize(optionSeen[OPTION_RESIZE]); + + if ( function == ENCODE_FRAMES ) { + SetFCode(); + + if ( psearchAlg == PSEARCH_TWOLEVEL ) + SetPixelSearch("HALF"); + } + + return TRUE; +} + + +/*===========================================================================* + * + * GetNthInputFileName + * + * finds the nth input file name + * + * RETURNS: name is placed in already allocated fileName string + * + * SIDE EFFECTS: none + * + *===========================================================================*/ +void +GetNthInputFileName(fileName, n) + char *fileName; + int n; +{ + static int lastN = 0, lastMapN = 0, lastSoFar = 0; + int mapN; + register int index; + int soFar; + int loop; + int numPadding; + char numBuffer[33]; + + /* assumes n is within bounds 0...numInputFiles-1 */ + + if ( n >= lastN ) { + soFar = lastSoFar; + index = lastMapN; + } else { + soFar = 0; + index = 0; + } + + while ( soFar + inputFileEntries[index]->numFiles <= n ) { + soFar += inputFileEntries[index]->numFiles; + index++; + } + + mapN = index; + + index = inputFileEntries[mapN]->startID + + inputFileEntries[mapN]->skip*(n-soFar); + + numPadding = inputFileEntries[mapN]->numPadding; + + if ( numPadding != -1 ) { + sprintf(numBuffer, "%32d", index); + for ( loop = 32-numPadding; loop < 32; loop++ ) { + if ( numBuffer[loop] != ' ' ) { + break; + } else { + numBuffer[loop] = '0'; + } + } + + sprintf(fileName, "%s%s%s", + inputFileEntries[mapN]->left, + &numBuffer[32-numPadding], + inputFileEntries[mapN]->right); + } else { + sprintf(fileName, "%s%d%s", + inputFileEntries[mapN]->left, + index, + inputFileEntries[mapN]->right); + } + + lastN = n; + lastMapN = mapN; + lastSoFar = soFar; +} + + +/*=====================* + * INTERNAL PROCEDURES * + *=====================*/ + +/*===========================================================================* + * + * ReadMachineNames + * + * read a list of machine names for parallel execution + * + * RETURNS: nothing + * + * SIDE EFFECTS: machine info updated + * + *===========================================================================*/ +static void +ReadMachineNames(fpointer) + FILE *fpointer; +{ + char input[256]; + char *charPtr; + + while ( (fgets(input, 256, fpointer) != NULL) && + (strncmp(input, "END_PARALLEL", 12) != 0) ) { + if ( input[0] == '#' ) { + continue; + } + + if ( strncmp(input, "REMOTE", 6) == 0 ) { + charPtr = SkipSpacesTabs(&input[6]); + remote[numMachines] = TRUE; + + sscanf(charPtr, "%s %s %s %s", machineName[numMachines], + userName[numMachines], executable[numMachines], + remoteParamFile[numMachines]); + } else { + remote[numMachines] = FALSE; + + sscanf(input, "%s %s %s", machineName[numMachines], + userName[numMachines], executable[numMachines]); + } + + numMachines++; + } +} + + +/*===========================================================================* + * + * ReadInputFileNames + * + * read a list of input file names + * + * RETURNS: nothing + * + * SIDE EFFECTS: info stored for retrieval using GetNthInputFileName + * + *===========================================================================*/ +static void +ReadInputFileNames(fpointer, endInput) + FILE *fpointer; + char *endInput; +{ + char input[256]; + char left[256], right[256]; + char *globPtr, *charPtr; + char leftNumText[256], rightNumText[256]; + char skipNumText[256]; + int leftNum, rightNum; + int skipNum; + boolean padding; + int numPadding = 0; + int length; + + inputFileEntries = (InputFileEntry **) malloc(INPUT_ENTRY_BLOCK_SIZE* + sizeof(InputFileEntry *)); + maxInputFileEntries = INPUT_ENTRY_BLOCK_SIZE; + + length = strlen(endInput); + + /* read input files up until endInput */ + while ( (fgets(input, 256, fpointer) != NULL) && + (strncmp(input, endInput, length) != 0) ) { + + if ( input[0] == '#' ) { + continue; + } + + if (input[0] == '`' ) { /* Recurse for commands */ + FILE *fp; + char cmd[300], *start, *end, tmp[300], templ[100], *temp, cdcmd[110]; + + start=&input[1]; + end=&input[strlen(input)-1]; + + while (*end != '`') { + end--; + } + + end--; + strncpy(tmp,start,end-start+1); + strcpy(templ,"/tmp/mpeg_enc_XXXXXX"); + temp = mktemp(templ); + + if (optionSeen[OPTION_INPUT_DIR] == TRUE) { + sprintf(cdcmd,"cd %s;",currentPath); + } else { + strcpy(cdcmd,""); + } + +#ifdef NO_UNISTD +sprintf(cmd,"(rm %s; %s %s > %s)", + temp, cdcmd, tmp, temp); +#else +unlink(temp); +sprintf(cmd,"(%s %s > %s)", cdcmd, tmp, temp); +#endif + if (! realQuiet) { + fprintf(stdout, "Executing %s\nto get file names.\n",cmd); + } + system(cmd); + fp=fopen(temp,"r"); + if (fp==NULL) { + fprintf(stderr,"Command failed! (could not open %s)\n",temp); + continue; + } + ReadInputFileNames(fp,"HOPE-THIS_ISNT_A_FILENAME.xyz5555"); +#ifdef NO_UNISTD +fprintf(cmd,"rm %s",temp); +system(cmd); +#else +unlink(temp); +#endif + continue; + } + + + input[strlen(input)-1] = '\0'; /* get rid of newline */ + + if ( numInputFileEntries == maxInputFileEntries ) { /* more space! */ + maxInputFileEntries += INPUT_ENTRY_BLOCK_SIZE; + inputFileEntries = (InputFileEntry **) realloc(inputFileEntries, + maxInputFileEntries* + sizeof(InputFileEntry *)); + } + + inputFileEntries[numInputFileEntries] = (InputFileEntry *) + malloc(sizeof(InputFileEntry)); + + if ( input[strlen(input)-1] == ']' ) { + inputFileEntries[numInputFileEntries]->glob = TRUE; + + /* star expand */ + + globPtr = input; + charPtr = left; + /* copy left of '*' */ + while ( (*globPtr != '\0') && (*globPtr != '*') ) { + *charPtr = *globPtr; + charPtr++; + globPtr++; + } + *charPtr = '\0'; + + globPtr++; + charPtr = right; + /* copy right of '*' */ + while ( (*globPtr != '\0') && (*globPtr != ' ') && + (*globPtr != '\t') ) { + *charPtr = *globPtr; + charPtr++; + globPtr++; + } + *charPtr = '\0'; + + globPtr = SkipSpacesTabs(globPtr); + + if ( *globPtr != '[' ) { + fprintf(stderr, "ERROR: Invalid input file expansion expression (no '[')\n"); + exit(1); + } + + globPtr++; + charPtr = leftNumText; + /* copy left number */ + while ( isdigit(*globPtr) ) { + *charPtr = *globPtr; + charPtr++; + globPtr++; + } + *charPtr = '\0'; + + if ( *globPtr != '-' ) { + fprintf(stderr, "ERROR: Invalid input file expansion expression (no '-')\n"); + exit(1); + } + + globPtr++; + charPtr = rightNumText; + /* copy right number */ + while ( isdigit(*globPtr) ) { + *charPtr = *globPtr; + charPtr++; + globPtr++; + } + *charPtr = '\0'; + + + if ( *globPtr != ']' ) { + if ( *globPtr != '+' ) { + fprintf(stderr, "ERROR: Invalid input file expansion expression (no ']')\n"); + exit(1); + } + + globPtr++; + charPtr = skipNumText; + /* copy skip number */ + while ( isdigit(*globPtr) ) { + *charPtr = *globPtr; + charPtr++; + globPtr++; + } + *charPtr = '\0'; + + if ( *globPtr != ']' ) { + fprintf(stderr, "ERROR: Invalid input file expansion expression (no ']')\n"); + exit(1); + } + + skipNum = atoi(skipNumText); + } else { + skipNum = 1; + } + + leftNum = atoi(leftNumText); + rightNum = atoi(rightNumText); + + if ( (leftNumText[0] == '0') && (leftNumText[1] != '\0') ) { + padding = TRUE; + numPadding = strlen(leftNumText); + } else { + padding = FALSE; + } + + inputFileEntries[numInputFileEntries]->startID = leftNum; + inputFileEntries[numInputFileEntries]->endID = rightNum; + inputFileEntries[numInputFileEntries]->skip = skipNum; + inputFileEntries[numInputFileEntries]->numFiles = (rightNum-leftNum+1)/skipNum; + strcpy(inputFileEntries[numInputFileEntries]->left, left); + strcpy(inputFileEntries[numInputFileEntries]->right, right); + if ( padding ) { + inputFileEntries[numInputFileEntries]->numPadding = numPadding; + } else { + inputFileEntries[numInputFileEntries]->numPadding = -1; + } + } else { + strcpy(inputFileEntries[numInputFileEntries]->left, input); + inputFileEntries[numInputFileEntries]->glob = FALSE; + inputFileEntries[numInputFileEntries]->numFiles = 1; + /* fixes a bug from version 1.3: */ + inputFileEntries[numInputFileEntries]->numPadding = 0; + /* fixes a bug from version 1.4 */ + strcpy(inputFileEntries[numInputFileEntries]->right,"\0"); + } + + numInputFiles += inputFileEntries[numInputFileEntries]->numFiles; + numInputFileEntries++; + } +} + + +/*===========================================================================* + * + * SkipSpacesTabs + * + * skip all spaces and tabs + * + * RETURNS: point to next character not a space or tab + * + * SIDE EFFECTS: none + * + *===========================================================================*/ +static char * +SkipSpacesTabs(start) + char *start; +{ + while ( (*start == ' ') || (*start == '\t') ) { + start++; + } + + return start; +} + + +/*===========================================================================* + * + * GetFrameRate + * + * take a character string with the input frame rate + * and return the correct frame rate code for use in the Sequence header + * + * RETURNS: frame rate code as per MPEG-I spec + * + * SIDE EFFECTS: none + * + *===========================================================================*/ +static int +GetFrameRate(p) + char *p; +{ + float rate; + int thouRate; + + sscanf(p, "%f", &rate); + thouRate = (int)(0.5+1000.0*rate); + + if ( thouRate == 23976 ) return 1; + else if ( thouRate == 24000 ) return 2; + else if ( thouRate == 25000 ) return 3; + else if ( thouRate == 29970 ) return 4; + else if ( thouRate == 30000 ) return 5; + else if ( thouRate == 50000 ) return 6; + else if ( thouRate == 59940 ) return 7; + else if ( thouRate == 60000 ) return 8; + else { + fprintf(stderr,"INVALID FRAME RATE: %s frames/sec\n", p); + exit(1); + } +} + + +/*===========================================================================* + * + * GetAspectRatio + * + * take a character string with the pixel aspect ratio + * and returns the correct aspect ratio code for use in the Sequence header + * + * RETURNS: aspect ratio code as per MPEG-I spec + * + * SIDE EFFECTS: none + * + *===========================================================================*/ +static int +GetAspectRatio(p) + char *p; +{ + float ratio; + int ttRatio; + + sscanf(p, "%f", &ratio); + ttRatio = (int)(0.5+ratio*10000.0); + + if ( ttRatio == 10000 ) return 1; + else if ( ttRatio == 6735 ) return 2; + else if ( ttRatio == 7031 ) return 3; + else if ( ttRatio == 7615 ) return 4; + else if ( ttRatio == 8055 ) return 5; + else if ( ttRatio == 8437 ) return 6; + else if ( ttRatio == 8935 ) return 7; + else if ( ttRatio == 9157 ) return 8; + else if ( ttRatio == 9815 ) return 9; + else if ( ttRatio == 10255 ) return 10; + else if ( ttRatio == 10695 ) return 11; + else if ( ttRatio == 10950 ) return 12; + else if ( ttRatio == 11575 ) return 13; + else if ( ttRatio == 12015 ) return 14; + else { + fprintf(stderr,"INVALID ASPECT RATIO: %s frames/sec\n", p); + exit(1); + } +} + + + + + + +/**************************************************************** +* Jim Boucher's code +* +* +****************************************************************/ +void +JM2JPEG() +{ + char full_path[MAXPATHLEN + 256]; + char inter_file[MAXPATHLEN +256]; +int ci; + + for(ci=0;ci<numInputFileEntries;ci++){ + inter_file[0] = '\0'; + full_path[0] = '\0'; + strcpy(full_path, currentPath); + strcat(full_path, "/"); + strcat(full_path, inputFileEntries[ci]->left); + strcpy(inter_file,full_path); + strcat(full_path, inputFileEntries[ci]->right); + fprintf(stderr, "%s\n",full_path); + + JMovie2JPEG(full_path, + inter_file, + inputFileEntries[ci]->startID,inputFileEntries[ci]->endID); +} +} diff --git a/contrib/mpeg_encode/pframe.cpp b/contrib/mpeg_encode/pframe.cpp new file mode 100644 index 0000000000000000000000000000000000000000..bd51ddc8bbd9db89eff591413e0c3139a1dd6108 --- /dev/null +++ b/contrib/mpeg_encode/pframe.cpp @@ -0,0 +1,1090 @@ +/*===========================================================================* + * pframe.c * + * * + * Procedures concerned with generation of P-frames * + * * + * EXPORTED PROCEDURES: * + * GenPFrame * + * ResetPFrameStats * + * ShowPFrameSummary * + * EstimateSecondsPerPFrame * + * ComputeHalfPixelData * + * SetPQScale * + * GetPQScale * + * * + * NOTE: when motion vectors are passed as arguments, they are passed as * + * twice their value. In other words, a motion vector of (3,4) will * + * be passed as (6,8). This allows half-pixel motion vectors to be * + * passed as integers. This is true throughout the program. * + * * + *===========================================================================*/ + +/* + * Copyright (c) 1995 The Regents of the University of California. + * All rights reserved. + * + * Permission to use, copy, modify, and distribute this software and its + * documentation for any purpose, without fee, and without written agreement is + * hereby granted, provided that the above copyright notice and the following + * two paragraphs appear in all copies of this software. + * + * IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR + * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT + * OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF + * CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS + * ON AN "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO + * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. + */ + +/* + * $Header: /n/picasso/project/mpeg/mpeg_dist/mpeg_encode/RCS/pframe.c,v 1.22 1995/08/07 21:51:23 smoot Exp $ + * $Log: pframe.c,v $ + * Revision 1.22 1995/08/07 21:51:23 smoot + * fixed LumMotionError call, simpler now with option type + * + * Revision 1.21 1995/06/21 22:23:16 smoot + * fixed specifics file bug + * generalized timeing stuff + * binary writes + * TUNEing stuff + * + * Revision 1.20 1995/04/14 23:07:41 smoot + * reorganized to ease rate control experimentation + * + * Revision 1.19 1995/02/24 23:49:27 smoot + * added specifications file format 2 + * + * Revision 1.18 1995/02/01 21:48:17 smoot + * cleanup + * + * Revision 1.17 1995/01/23 06:30:01 darryl + * fixed bug in "MMB Type "pattern" and Rate control + * + * Revision 1.15 1995/01/19 23:49:28 smoot + * moved rev_dct, make pattern changable by ComputeDiffDCTs + * + * Revision 1.14 1995/01/19 23:09:07 eyhung + * Changed copyrights + * + * Revision 1.13 1995/01/19 23:00:26 smoot + * Fixed 1st/last MB in slice color bug in P-frames + * + * Revision 1.12 1995/01/17 22:10:27 smoot + * Fixed B/P Qscale bug + * + * Revision 1.11 1995/01/16 08:14:41 eyhung + * added realQuiet + * + * Revision 1.10 1994/12/07 00:40:36 smoot + * Added seperate P and B search ranges + * + * Revision 1.9 1994/11/14 22:38:18 smoot + * merged specifics and rate control + * + * Revision 1.8 1994/11/01 05:01:09 darryl + * with rate control changes added + * + * Revision 2.1 1994/10/31 00:05:39 darryl + * version before, hopefully, final changes + * + * Revision 2.0 1994/10/24 02:38:26 darryl + * will be adding the experiment code + * + * Revision 1.1 1994/09/27 00:15:44 darryl + * Initial revision + * + * Revision 1.7 1994/03/15 00:27:11 keving + * nothing + * + * Revision 1.6 1993/12/22 19:19:01 keving + * nothing + * + * Revision 1.5 1993/07/22 22:23:43 keving + * nothing + * + * Revision 1.4 1993/06/30 20:06:09 keving + * nothing + * + * Revision 1.3 1993/06/03 21:08:08 keving + * nothing + * + * Revision 1.2 1993/03/02 23:03:42 keving + * nothing + * + * Revision 1.1 1993/02/19 19:14:12 keving + * nothing + * + */ + + +/*==============* + * HEADER FILES * + *==============*/ + +#include <assert.h> +#include <sys/param.h> +#include "all.h" +#include "mtypes.h" +#include "bitio.h" +#include "frames.h" +#include "prototypes.h" +#include "param.h" +#include "mheaders.h" +#include "fsize.h" +#include "postdct.h" +#include "mpeg.h" +#include "parallel.h" +#include "rate.h" +#include "opts.h" + +/*==================* + * STATIC VARIABLES * + *==================*/ + +static int32 zeroDiff; +static int numPIBlocks = 0; +static int numPPBlocks = 0; +static int numPSkipped = 0; +static int numPIBits = 0; +static int numPPBits = 0; +static int numFrames = 0; +static int numFrameBits = 0; +static int32 totalTime = 0; +static int qscaleP; +static float totalSNR = 0.0; +static float totalPSNR = 0.0; +extern Block **dct, **dctr, **dctb; +extern dct_data_type **dct_data; + +/*===============================* + * INTERNAL PROCEDURE prototypes * + *===============================*/ + +static boolean ZeroMotionBetter _ANSI_ARGS_((LumBlock currentBlock, + MpegFrame *prev, int by, int bx, + int my, int mx)); + +static boolean DoIntraCode _ANSI_ARGS_((LumBlock currentBlock, + MpegFrame *prev, int by, int bx, + int motionY, int motionX)); + +static boolean ZeroMotionSufficient _ANSI_ARGS_((LumBlock currentBlock, + MpegFrame *prev, + int by, int bx)); + +#ifdef BLEAH +static void ComputeAndPrintPframeMAD _ANSI_ARGS_((LumBlock currentBlock, + MpegFrame *prev, + int by, int bx, + int my, int mx, + int numBlock)); +#endif + + +/*=====================* + * EXPORTED PROCEDURES * + *=====================*/ + +/*===========================================================================* + * + * GenPFrame + * + * generate a P-frame from previous frame, adding the result to the + * given bit bucket + * + * RETURNS: frame appended to bb + * + * SIDE EFFECTS: none + * + *===========================================================================*/ +void +GenPFrame(BitBucket *bb, + MpegFrame *current, + MpegFrame *prev) +{ + extern int **pmvHistogram; + FlatBlock fba[6], fb[6]; + Block dec[6]; + int32 y_dc_pred, cr_dc_pred, cb_dc_pred; + int x, y; + int motionX = 0, motionY = 0; + int oldMotionX = 0, oldMotionY = 0; + int offsetX, offsetY; + int tempX, tempY; + int motionXrem, motionXquot; + int motionYrem, motionYquot; + int pattern; + int mbAddrInc = 1; + boolean useMotion; + int numIBlocks = 0; + int numPBlocks = 0; + int numSkipped = 0; + int numIBits = 0; + int numPBits = 0; + int totalBits; + int totalFrameBits; + int32 startTime, endTime; + int lastBlockX, lastBlockY; + int lastX, lastY; + int fy, fx; + LumBlock currentBlock; + register int ix, iy; + int mbAddress; + int slicePos; + register int index; + float snr[3], psnr[3]; + int QScale; + BlockMV *info; + int bitstreamMode, newQScale; + int rc_blockStart = 0; + boolean overflowChange = FALSE; + int overflowValue = 0; + + + if (collect_quant) {fprintf(collect_quant_fp, "# P\n");} + if (dct==NULL) AllocDctBlocks(); + numFrames++; + totalFrameBits = bb->cumulativeBits; + startTime = time_elapsed(); + + DBG_PRINT(("Generating pframe\n")); + + QScale = GetPQScale(); + /* bit allocation for rate control purposes */ + bitstreamMode = getRateMode(); + if (bitstreamMode == FIXED_RATE) { + targetRateControl(current); + } + + Mhead_GenPictureHeader(bb, P_FRAME, current->id, fCodeP); + /* Check for Qscale change */ + if (specificsOn) { + /* Set a Qscale for this frame? */ + newQScale = SpecLookup(current->id, 0, 0 /* junk */, &info /*junk*/, QScale); + if (newQScale != -1) { + QScale = newQScale; + } + /* Set for slice? */ + newQScale = SpecLookup(current->id, 1, 1, &info /*junk*/, QScale); + if (newQScale != -1) { + QScale = newQScale; + } + } + + DBG_PRINT(("Slice Header\n")); + Mhead_GenSliceHeader(bb, 1, QScale, NULL, 0); + + if ( referenceFrame == DECODED_FRAME ) { + Frame_AllocDecoded(current, TRUE); + } else if ( printSNR ) { + Frame_AllocDecoded(current, FALSE); + } + + /* don't do dct on blocks yet */ + Frame_AllocBlocks(current); + BlockifyFrame(current); + + /* for I-blocks */ + y_dc_pred = cr_dc_pred = cb_dc_pred = 128; + + totalBits = bb->cumulativeBits; + + if ( (! pixelFullSearch) && (! prev->halfComputed) ) { + ComputeHalfPixelData(prev); + } + + lastBlockX = Fsize_x>>3; + lastBlockY = Fsize_y>>3; + lastX = lastBlockX-2; + lastY = lastBlockY-2; + mbAddress = 0; + + /* First loop though finding motion/not and DCTing */ + for (y = 0; y < lastBlockY; y += 2) { + for (x = 0; x < lastBlockX; x += 2) { + /* compute currentBlock */ + BLOCK_TO_FRAME_COORD(y, x, fy, fx); + for ( iy = 0; iy < 16; iy++ ) { + for ( ix = 0; ix < 16; ix++ ) { + currentBlock[iy][ix] = (int16)current->orig_y[fy+iy][fx+ix]; + } + } + + /* See if we have a cached answer */ + if (specificsOn) { + (void) SpecLookup(current->id, 2, mbAddress, &info, QScale); + if (info != (BlockMV*)NULL) { + if (info->typ == TYP_SKIP) { + motionX = motionY = 0; + useMotion = TRUE; + goto no_search; + } else { /* assume P, since we're a P frame.... */ + motionX = info->fx; + motionY = info->fy; + useMotion = TRUE; + goto no_search; + }} + /* if unspecified, just look */ + } + + /* see if we should use motion vectors, and if so, what those + * vectors should be + */ + if ( ZeroMotionSufficient(currentBlock, prev, y, x) ) { + motionX = 0; + motionY = 0; + useMotion = TRUE; + } else { + useMotion = PMotionSearch(currentBlock, prev, y, x, + &motionY, &motionX); + if ( useMotion ) { + if ( ZeroMotionBetter(currentBlock, prev, y, x, motionY, + motionX) ) { + motionX = 0; + motionY = 0; + } + if (IntraPBAllowed) + useMotion = (! DoIntraCode(currentBlock, prev, y, x, + motionY, motionX)); + } + } + + no_search: + + dct_data[y][x].useMotion = useMotion; + if ( ! useMotion ) { + /* output I-block inside a P-frame */ + numIBlocks++; + + /* calculate forward dct's */ + if (collect_quant && (collect_quant_detailed & 1)) fprintf(collect_quant_fp, "l\n"); + mp_fwd_dct_block2(current->y_blocks[y][x], dct[y][x]); + mp_fwd_dct_block2(current->y_blocks[y][x+1], dct[y][x+1]); + mp_fwd_dct_block2(current->y_blocks[y+1][x], dct[y+1][x]); + mp_fwd_dct_block2(current->y_blocks[y+1][x+1], dct[y+1][x+1]); + if (collect_quant && (collect_quant_detailed & 1)) fprintf(collect_quant_fp, "c\n"); + mp_fwd_dct_block2(current->cb_blocks[y>>1][x>>1], dctb[y>>1][x>>1]); + mp_fwd_dct_block2(current->cr_blocks[y>>1][x>>1], dctr[y>>1][x>>1]); + + } else { + /* USE MOTION VECTORS */ + numPBlocks++; + + pattern = 63; + ComputeDiffDCTs(current, prev, y, x, motionY, motionX, + &pattern); + + assert(motionX+searchRangeP+1 >= 0); + assert(motionY+searchRangeP+1 >= 0); + +#ifdef BLEAH + if ( motionX+searchRangeP+1 > 2*searchRangeP+2 ) + { + fprintf(stdout, "motionX = %d, searchRangeP = %d\n", + motionX, searchRangeP); + } +#endif + + if ( computeMVHist ) { + assert(motionX+searchRangeP+1 <= 2*searchRangeP+2); + assert(motionY+searchRangeP+1 <= 2*searchRangeP+2); + pmvHistogram[motionX+searchRangeP+1][motionY+searchRangeP+1]++; + } + /* Save specs for next loops */ + dct_data[y][x].pattern = pattern; + dct_data[y][x].fmotionX = motionX; + dct_data[y][x].fmotionY = motionY; + + } + mbAddress++; + }} + + mbAddress = 0; + for (y = 0; y < lastBlockY; y += 2) { + for (x = 0; x < lastBlockX; x += 2) { + slicePos = (mbAddress % blocksPerSlice); + + if ( (slicePos == 0) && (mbAddress != 0) ) { + if (specificsOn) { + /* Make sure no slice Qscale change */ + newQScale = SpecLookup(current->id, 1, mbAddress/blocksPerSlice, + &info /*junk*/, QScale); + if (newQScale != -1) QScale = newQScale; + } + + Mhead_GenSliceEnder(bb); + Mhead_GenSliceHeader(bb, 1+(y>>1), QScale, NULL, 0); + + /* reset everything */ + oldMotionX = 0; oldMotionY = 0; + y_dc_pred = cr_dc_pred = cb_dc_pred = 128; + + mbAddrInc = 1+(x>>1); + } + + /* Determine if new Qscale needed for Rate Control purposes */ + if (bitstreamMode == FIXED_RATE) { + rc_blockStart = bb->cumulativeBits; + newQScale = needQScaleChange(qscaleP, + current->y_blocks[y][x], + current->y_blocks[y][x+1], + current->y_blocks[y+1][x], + current->y_blocks[y+1][x+1]); + if (newQScale > 0) { + QScale = newQScale; + } + } + + /* Check for Qscale change */ + if (specificsOn) { + newQScale = SpecLookup(current->id, 2, mbAddress, &info, QScale); + if (newQScale != -1) { + QScale = newQScale; + } + } + + if (! dct_data[y][x].useMotion) { + GEN_I_BLOCK(P_FRAME, current, bb, mbAddrInc, QScale); + mbAddrInc = 1; + + numIBits += (bb->cumulativeBits-totalBits); + totalBits = bb->cumulativeBits; + + /* reset because intra-coded */ + oldMotionX = 0; oldMotionY = 0; + + if ( decodeRefFrames ) { + /* need to decode block we just encoded */ + Mpost_UnQuantZigBlock(fb[0], dec[0], QScale, TRUE); + Mpost_UnQuantZigBlock(fb[1], dec[1], QScale, TRUE); + Mpost_UnQuantZigBlock(fb[2], dec[2], QScale, TRUE); + Mpost_UnQuantZigBlock(fb[3], dec[3], QScale, TRUE); + Mpost_UnQuantZigBlock(fb[4], dec[4], QScale, TRUE); + Mpost_UnQuantZigBlock(fb[5], dec[5], QScale, TRUE); + + /* now, reverse the DCT transform */ + for ( index = 0; index < 6; index++ ) { + mpeg_jrevdct((int16 *)dec[index]); + } + + /* now, unblockify */ + BlockToData(current->decoded_y, dec[0], y, x); + BlockToData(current->decoded_y, dec[1], y, x+1); + BlockToData(current->decoded_y, dec[2], y+1, x); + BlockToData(current->decoded_y, dec[3], y+1, x+1); + BlockToData(current->decoded_cb, dec[4], y>>1, x>>1); + BlockToData(current->decoded_cr, dec[5], y>>1, x>>1); + } + } else { + int fCode = fCodeP; + + /* reset because non-intra-coded */ + y_dc_pred = cr_dc_pred = cb_dc_pred = 128; + + pattern = dct_data[y][x].pattern; + motionX = dct_data[y][x].fmotionX; + motionY = dct_data[y][x].fmotionY; + +#ifdef BLEAH + ComputeAndPrintPframeMAD(currentBlock, prev, y, x, motionY, motionX, mbAddress); +#endif + + if ( pixelFullSearch ) { /* should be even */ + motionY /= 2; + motionX /= 2; + } + + /* transform the motion vector into the appropriate values */ + offsetX = motionX - oldMotionX; + offsetY = motionY - oldMotionY; +/* if ((offsetX+(8*x)) >= (Fsize_x-8)) log(10.0); */ + ENCODE_MOTION_VECTOR(offsetX, offsetY, motionXquot, + motionYquot, motionXrem, motionYrem, + FORW_F); + +#ifdef BLEAH + if ( (motionX != 0) || (motionY != 0) ) { + fprintf(stdout, "FRAME (y, x) %d, %d (block %d)\n", y, x, mbAddress); + fprintf(stdout, "motionX = %d, motionY = %d\n", motionX, motionY); + fprintf(stdout, " mxq, mxr = %d, %d myq, myr = %d, %d\n", + motionXquot, motionXrem, motionYquot, motionYrem); + } +#endif + + oldMotionX = motionX; + oldMotionY = motionY; + + if ( pixelFullSearch ) { /* reset for use with PMotionSearch */ + motionY *= 2; + motionX *= 2; + } + calc_blocks: + /* create flat blocks and update pattern if necessary */ + /* Note DoQuant references QScale, overflowChange, overflowValue, + pattern, and the calc_blocks label */ + DoQuant(0x20, dct[y][x], fba[0]); + DoQuant(0x10, dct[y][x+1], fba[1]); + DoQuant(0x08, dct[y+1][x], fba[2]); + DoQuant(0x04, dct[y+1][x+1], fba[3]); + DoQuant(0x02, dctb[y>>1][x>>1], fba[4]); + DoQuant(0x01, dctr[y>>1][x>>1], fba[5]); + + if ( decodeRefFrames) { + for ( index = 0; index < 6; index++ ) { + if ( pattern & (1 << (5-index))) { + Mpost_UnQuantZigBlock(fba[index], dec[index], QScale, FALSE); + mpeg_jrevdct((int16 *)dec[index]); + } else { + memset((char *)dec[index], 0, sizeof(Block)); + } + } + + /* now add the motion block */ + AddMotionBlock(dec[0], prev->decoded_y, y, x, motionY, motionX); + AddMotionBlock(dec[1], prev->decoded_y, y, x+1, motionY, motionX); + AddMotionBlock(dec[2], prev->decoded_y, y+1, x, motionY, motionX); + AddMotionBlock(dec[3], prev->decoded_y, y+1, x+1, motionY, motionX); + AddMotionBlock(dec[4], prev->decoded_cb, y>>1, x>>1, motionY/2, motionX/2); + AddMotionBlock(dec[5], prev->decoded_cr, y>>1, x>>1, motionY/2, motionX/2); + + /* now, unblockify */ + BlockToData(current->decoded_y, dec[0], y, x); + BlockToData(current->decoded_y, dec[1], y, x+1); + BlockToData(current->decoded_y, dec[2], y+1, x); + BlockToData(current->decoded_y, dec[3], y+1, x+1); + BlockToData(current->decoded_cb, dec[4], y>>1, x>>1); + BlockToData(current->decoded_cr, dec[5], y>>1, x>>1); + } + + if ( (motionX == 0) && (motionY == 0) ) { + if ( pattern == 0 ) { + /* can only skip if: + * 1) not the last block in frame + * 2) not the last block in slice + * 3) not the first block in slice + */ + + if ( ((y < lastY) || (x < lastX)) && + (slicePos+1 != blocksPerSlice) && + (slicePos != 0) ) { + mbAddrInc++; /* skipped macroblock */ + numSkipped++; + numPBlocks--; + } else { /* first/last macroblock */ + Mhead_GenMBHeader(bb, 2 /* pict_code_type */, mbAddrInc /* addr_incr */, + QScale /* q_scale */, + fCode /* forw_f_code */, 1 /* back_f_code */, + motionXrem /* horiz_forw_r */, motionYrem /* vert_forw_r */, + 0 /* horiz_back_r */, 0 /* vert_back_r */, + 1 /* motion_forw */, motionXquot /* m_horiz_forw */, + motionYquot /* m_vert_forw */, 0 /* motion_back */, + 0 /* m_horiz_back */, 0 /* m_vert_back */, + 0 /* mb_pattern */, 0 /* mb_intra */); + mbAddrInc = 1; + } + } else { + DBG_PRINT(("MB Header(%d,%d)\n", x, y)); + Mhead_GenMBHeader(bb, 2 /* pict_code_type */, mbAddrInc /* addr_incr */, + QScale /* q_scale */, + fCode /* forw_f_code */, 1 /* back_f_code */, + 0 /* horiz_forw_r */, 0 /* vert_forw_r */, + 0 /* horiz_back_r */, 0 /* vert_back_r */, + 0 /* motion_forw */, 0 /* m_horiz_forw */, + 0 /* m_vert_forw */, 0 /* motion_back */, + 0 /* m_horiz_back */, 0 /* m_vert_back */, + pattern /* mb_pattern */, 0 /* mb_intra */); + mbAddrInc = 1; + } + } else { + /* DBG_PRINT(("MB Header(%d,%d)\n", x, y)); */ + + Mhead_GenMBHeader(bb, 2 /* pict_code_type */, mbAddrInc /* addr_incr */, + QScale /* q_scale */, + fCode /* forw_f_code */, 1 /* back_f_code */, + motionXrem /* horiz_forw_r */, motionYrem /* vert_forw_r */, + 0 /* horiz_back_r */, 0 /* vert_back_r */, + 1 /* motion_forw */, motionXquot /* m_horiz_forw */, + motionYquot /* m_vert_forw */, 0 /* motion_back */, + 0 /* m_horiz_back */, 0 /* m_vert_back */, + pattern /* mb_pattern */, 0 /* mb_intra */); + mbAddrInc = 1; + } + + /* now output the difference */ + for ( tempX = 0; tempX < 6; tempX++ ) { + if ( GET_ITH_BIT(pattern, 5-tempX) ) { + Mpost_RLEHuffPBlock(fba[tempX], bb); + } + } + + numPBits += (bb->cumulativeBits-totalBits); + totalBits = bb->cumulativeBits; + } + + if (overflowChange) { + /* undo an overflow-caused Qscale change */ + overflowChange = FALSE; + QScale -= overflowValue; + overflowValue = 0; + } + + mbAddress++; + /* Rate Control */ + if (bitstreamMode == FIXED_RATE) { + incMacroBlockBits( bb->cumulativeBits- rc_blockStart); + rc_blockStart = bb->cumulativeBits; + MB_RateOut(TYPE_PFRAME); + } + } + } + + if ( printSNR ) { + BlockComputeSNR(current,snr,psnr); + totalSNR += snr[0]; + totalPSNR += psnr[0]; + } + +#ifdef BLEAHBLEAH + { + FILE *filePtr; + + filePtr = fopen("PFRAME.yuv", "wb"); + + for ( y = 0; y < Fsize_y; y++ ) + { + for ( x = 0; x < Fsize_x; x++ ) + fprintf(filePtr, "%d ", current->decoded_y[y][x]); + fprintf(filePtr, "\n"); + } + + fclose(filePtr); + } +#endif + + Mhead_GenSliceEnder(bb); + /* Rate Control */ + if (bitstreamMode == FIXED_RATE) { + updateRateControl(TYPE_PFRAME); + } + + /* UPDATE STATISTICS */ + endTime = time_elapsed(); + totalTime += (endTime-startTime); + + if ( ( ! childProcess) && showBitRatePerFrame ) { + /* ASSUMES 30 FRAMES PER SECOND */ + fprintf(bitRateFile, "%5d\t%8d\n", current->id, + 30*(bb->cumulativeBits-totalFrameBits)); + } + + if ( (! childProcess) && frameSummary && (! realQuiet) ) { + fprintf(stdout, "FRAME %d (P): I BLOCKS: %d; P BLOCKS: %d SKIPPED: %d (%ld seconds)\n", + current->id, numIBlocks, numPBlocks, numSkipped, (long)(endTime-startTime)/TIME_RATE); + if ( printSNR ) { + fprintf(stdout, "FRAME %d: SNR: %.1f\t%.1f\t%.1f\tPSNR: %.1f\t%.1f\t%.1f\n", + current->id, snr[0], snr[1], snr[2], + psnr[0], psnr[1], psnr[2]); + } + } + + numFrameBits += (bb->cumulativeBits-totalFrameBits); + numPIBlocks += numIBlocks; + numPPBlocks += numPBlocks; + numPSkipped += numSkipped; + numPIBits += numIBits; + numPPBits += numPBits; + + if ( (referenceFrame == DECODED_FRAME) && NonLocalRefFrame(current->id) ) { + if ( remoteIO ) { + SendDecodedFrame(current); + } else { + WriteDecodedFrame(current); + } + + NotifyDecodeServerReady(current->id); + } +} + + +/*===========================================================================* + * + * ResetPFrameStats + * + * reset the P-frame statistics + * + * RETURNS: nothing + * + * SIDE EFFECTS: none + * + *===========================================================================*/ +void + ResetPFrameStats() +{ + numPIBlocks = 0; + numPPBlocks = 0; + numPSkipped = 0; + numPIBits = 0; + numPPBits = 0; + numFrames = 0; + numFrameBits = 0; + totalTime = 0; +} + + +/*===========================================================================* + * + * SetPQScale + * + * set the P-frame Q-scale + * + * RETURNS: nothing + * + * SIDE EFFECTS: qscaleP + * + *===========================================================================*/ +void +SetPQScale(int qP) +{ + qscaleP = qP; +} + + +/*===========================================================================* + * + * GetPQScale + * + * return the P-frame Q-scale + * + * RETURNS: the P-frame Q-scale + * + * SIDE EFFECTS: none + * + *===========================================================================*/ +int + GetPQScale() +{ + return qscaleP; +} + + +/*===========================================================================* + * + * ShowPFrameSummary + * + * print a summary of information on encoding P-frames + * + * RETURNS: time taken for P-frames (in seconds) + * + * SIDE EFFECTS: none + * + *===========================================================================*/ +float +ShowPFrameSummary(int inputFrameBits, + int32 totalBits, + FILE *fpointer) +{ + if ( numFrames == 0 ) { + return 0.0; + } + + fprintf(fpointer, "-------------------------\n"); + fprintf(fpointer, "*****P FRAME SUMMARY*****\n"); + fprintf(fpointer, "-------------------------\n"); + + if ( numPIBlocks != 0 ) { + fprintf(fpointer, " I Blocks: %5d (%6d bits) (%5d bpb)\n", + numPIBlocks, numPIBits, numPIBits/numPIBlocks); + } else { + fprintf(fpointer, " I Blocks: %5d\n", 0); + } + + if ( numPPBlocks != 0 ) { + fprintf(fpointer, " P Blocks: %5d (%6d bits) (%5d bpb)\n", + numPPBlocks, numPPBits, numPPBits/numPPBlocks); + } else { + fprintf(fpointer, " P Blocks: %5d\n", 0); + } + + fprintf(fpointer, " Skipped: %5d\n", numPSkipped); + + fprintf(fpointer, " Frames: %5d (%6d bits) (%5d bpf) (%2.1f%% of total)\n", + numFrames, numFrameBits, numFrameBits/numFrames, + 100.0*(float)numFrameBits/(float)totalBits); + fprintf(fpointer, " Compression: %3d:1 (%9.4f bpp)\n", + numFrames*inputFrameBits/numFrameBits, + 24.0*(float)numFrameBits/(float)(numFrames*inputFrameBits)); + if ( printSNR ) + fprintf(fpointer, " Avg Y SNR/PSNR: %.1f %.1f\n", + totalSNR/(float)numFrames, totalPSNR/(float)numFrames); + if ( totalTime == 0 ) { + fprintf(fpointer, " Seconds: NONE\n"); + } else { + fprintf(fpointer, " Seconds: %9ld (%9.4f fps) (%9ld pps) (%9ld mps)\n", + (long)(totalTime/TIME_RATE), + (float)((float)(TIME_RATE*numFrames)/(float)totalTime), + (long)((float)TIME_RATE*(float)numFrames*(float)inputFrameBits/(24.0*(float)totalTime)), + (long)((float)TIME_RATE*(float)numFrames*(float)inputFrameBits/(256.0*24.0*(float)totalTime))); + } + + return (float)totalTime/(float)TIME_RATE; +} + + +/*===========================================================================* + * + * EstimateSecondsPerPFrame + * + * compute an estimate of the number of seconds required per P-frame + * + * RETURNS: the estimate, in seconds + * + * SIDE EFFECTS: none + * + *===========================================================================*/ +float + EstimateSecondsPerPFrame() +{ + if ( numFrames == 0 ) { + return 10.0; + } else { + return (float)totalTime/((float)TIME_RATE*(float)numFrames); + } +} + + +/*===========================================================================* + * + * ComputeHalfPixelData + * + * compute all half-pixel data required for half-pixel motion vector + * search (luminance only) + * + * RETURNS: frame->halfX, ->halfY, and ->halfBoth modified + * + * SIDE EFFECTS: none + * + *===========================================================================*/ +void +ComputeHalfPixelData(MpegFrame *frame) +{ + register int x, y; + + /* we add 1 before dividing by 2 because .5 is supposed to be rounded up + * (see MPEG-1, page D-31) + */ + + if ( frame->halfX == NULL ) { /* need to allocate memory */ + Frame_AllocHalf(frame); + } + + /* compute halfX */ + for ( y = 0; y < Fsize_y; y++ ) { + for ( x = 0; x < Fsize_x-1; x++ ) { + frame->halfX[y][x] = (frame->ref_y[y][x]+ + frame->ref_y[y][x+1]+1)>>1; + } + } + + /* compute halfY */ + for ( y = 0; y < Fsize_y-1; y++ ) { + for ( x = 0; x < Fsize_x; x++ ) { + frame->halfY[y][x] = (frame->ref_y[y][x]+ + frame->ref_y[y+1][x]+1)>>1; + } + } + + /* compute halfBoth */ + for ( y = 0; y < Fsize_y-1; y++ ) { + for ( x = 0; x < Fsize_x-1; x++ ) { + frame->halfBoth[y][x] = (frame->ref_y[y][x]+ + frame->ref_y[y][x+1]+ + frame->ref_y[y+1][x]+ + frame->ref_y[y+1][x+1]+2)>>2; + } + } + + frame->halfComputed = TRUE; +} + + +/*=====================* + * INTERNAL PROCEDURES * + *=====================*/ + +/*===========================================================================* + * + * USER-MODIFIABLE + * + * ZeroMotionBetter + * + * decide if (0,0) motion is better than the given motion vector + * + * RETURNS: TRUE if (0,0) is better, FALSE if (my,mx) is better + * + * SIDE EFFECTS: none + * + * PRECONDITIONS: The relevant block in 'current' is valid (it has not + * been dct'd). 'zeroDiff' has already been computed + * as the LumMotionError() with (0,0) motion + * + * NOTES: This procedure follows the algorithm described on + * page D-48 of the MPEG-1 specification + * + *===========================================================================*/ +static boolean +ZeroMotionBetter(LumBlock currentBlock, + MpegFrame *prev, + int by, + int bx, + int my, + int mx) +{ + int bestDiff; + int CompareMode; + + /* Junk needed to adapt for TUNEing */ + CompareMode = SearchCompareMode; + SearchCompareMode = DEFAULT_SEARCH; + bestDiff = LumMotionError(currentBlock, prev, by, bx, my, mx, 0x7fffffff); + SearchCompareMode = CompareMode; + + if ( zeroDiff < 256*3 ) { + if ( 2*bestDiff >= zeroDiff ) { + return TRUE; + } + } else { + if ( 11*bestDiff >= 10*zeroDiff ) { + return TRUE; + } + } + + return FALSE; +} + + +/*===========================================================================* + * + * USER-MODIFIABLE + * + * DoIntraCode + * + * decide if intra coding is necessary + * + * RETURNS: TRUE if intra-block coding is better; FALSE if not + * + * SIDE EFFECTS: none + * + * PRECONDITIONS: The relevant block in 'current' is valid (it has not + * been dct'd). + * + * NOTES: This procedure follows the algorithm described on + * page D-49 of the MPEG-1 specification + * + *===========================================================================*/ +static boolean +DoIntraCode(LumBlock currentBlock, + MpegFrame *prev, + int by, + int bx, + int motionY, + int motionX) +{ + int x, y; + int32 sum = 0, vard = 0, varc = 0, dif; + int32 currPixel, prevPixel; + LumBlock motionBlock; + + ComputeMotionLumBlock(prev, by, bx, motionY, motionX, motionBlock); + + for ( y = 0; y < 16; y++ ) { + for ( x = 0; x < 16; x++ ) { + currPixel = currentBlock[y][x]; + prevPixel = motionBlock[y][x]; + + sum += currPixel; + varc += currPixel*currPixel; + + dif = currPixel - prevPixel; + vard += dif*dif; + } + } + + vard >>= 8; /* divide by 256; assumes mean is close to zero */ + varc = (varc>>8) - (sum>>8)*(sum>>8); + + if ( vard <= 64 ) { + return FALSE; + } else if ( vard < varc ) { + return FALSE; + } else { + return TRUE; + } +} + + +/*===========================================================================* + * + * USER-MODIFIABLE + * + * ZeroMotionSufficient + * + * decide if zero motion is sufficient without DCT correction + * + * RETURNS: TRUE no DCT required; FALSE otherwise + * + * SIDE EFFECTS: none + * + * PRECONDITIONS: The relevant block in 'current' is raw YCC data + * + *===========================================================================*/ +static boolean +ZeroMotionSufficient(LumBlock currentBlock, + MpegFrame *prev, + int by, + int bx) +{ + LumBlock motionBlock; + register int fy, fx; + register int x, y; + + fy = by*DCTSIZE; + fx = bx*DCTSIZE; + for ( y = 0; y < 16; y++ ) { + for ( x = 0; x < 16; x++ ) { + motionBlock[y][x] = prev->ref_y[fy+y][fx+x]; + } + } + + zeroDiff = LumBlockMAD(currentBlock, motionBlock, 0x7fffffff); + + return (zeroDiff <= 256); +} + + +#ifdef UNUSED_PROCEDURES +static void +ComputeAndPrintPframeMAD(currentBlock, prev, by, bx, my, mbx, numBlock) + LumBlock currentBlock; + MpegFrame *prev; + int by; + int bx; + int my; + int mx; + int numBlock; +{ + LumBlock lumMotionBlock; + int32 mad; + + ComputeMotionLumBlock(prev, by, bx, my, mx, lumMotionBlock); + + mad = LumBlockMAD(currentBlock, lumMotionBlock, 0x7fffffff); + + if (! realQuiet) { + fprintf(stdout, "%d %d\n", numBlock, mad); + } +} +#endif diff --git a/contrib/mpeg_encode/postdct.cpp b/contrib/mpeg_encode/postdct.cpp new file mode 100644 index 0000000000000000000000000000000000000000..07152cbcd6025294d82a45465a97794d0f1eae7e --- /dev/null +++ b/contrib/mpeg_encode/postdct.cpp @@ -0,0 +1,619 @@ +/*===========================================================================* + * postdct.c * + * * + * Procedures concerned with MPEG post-DCT processing: * + * quantization and RLE Huffman encoding * + * * + * EXPORTED PROCEDURES: * + * Mpost_QuantZigBlock * + * Mpost_RLEHuffIBlock * + * Mpost_RLEHuffPBlock * + * Mpost_UnQuantZigBlock * + * * + *===========================================================================*/ + +/* + * Copyright (c) 1995 The Regents of the University of California. + * All rights reserved. + * + * Permission to use, copy, modify, and distribute this software and its + * documentation for any purpose, without fee, and without written agreement is + * hereby granted, provided that the above copyright notice and the following + * two paragraphs appear in all copies of this software. + * + * IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR + * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT + * OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF + * CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS + * ON AN "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO + * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. + */ + +/* + * $Header: /n/picasso/project/mm/mpeg/mpeg_dist/mpeg_encode/RCS/postdct.c,v 1.12 1995/06/21 18:26:39 smoot Exp $ + * $Log: postdct.c,v $ + * Revision 1.12 1995/06/21 18:26:39 smoot + * added length estimator for P-blocks + * + * Revision 1.11 1995/04/23 23:22:59 eyhung + * nothing changed + * + * Revision 1.10 1995/04/14 23:10:46 smoot + * Added overflow detection to MPOST_DCT so it will adjust Qscales (above) + * + * Revision 1.9 1995/02/15 23:15:32 smoot + * killed useless asserts + * + * Revision 1.8 1995/02/01 21:48:41 smoot + * assure out is set properly, short circuit 0 revquant + * + * Revision 1.7 1995/01/30 19:56:37 smoot + * Killed a <0 shift + * + * Revision 1.6 1995/01/25 23:07:33 smoot + * Better DBG_PRINTs, multiply/divide instead of shifts + * + * Revision 1.5 1995/01/19 23:09:10 eyhung + * Changed copyrights + * + * Revision 1.4 1995/01/16 08:17:08 eyhung + * added realQuiet + * + * Revision 1.3 1994/11/12 02:11:58 keving + * nothing + * + * Revision 1.2 1994/03/15 00:27:11 keving + * nothing + * + * Revision 1.2 1994/03/15 00:27:11 keving + * nothing + * + * Revision 1.1 1993/12/22 19:19:01 keving + * nothing + * + * Revision 1.11 1993/07/22 22:23:43 keving + * nothing + * + * Revision 1.10 1993/06/30 20:06:09 keving + * nothing + * + * Revision 1.9 1993/06/03 21:08:08 keving + * nothing + * + * Revision 1.8 1993/02/24 18:57:19 keving + * nothing + * + * Revision 1.7 1993/02/23 22:58:36 keving + * nothing + * + * Revision 1.6 1993/02/23 22:54:56 keving + * nothing + * + * Revision 1.5 1993/02/17 23:18:20 dwallach + * checkin prior to keving's joining the project + * + * Revision 1.4 1993/01/18 10:20:02 dwallach + * *** empty log message *** + * + * Revision 1.3 1993/01/18 10:17:29 dwallach + * RCS headers installed, code indented uniformly + * + * Revision 1.3 1993/01/18 10:17:29 dwallach + * RCS headers installed, code indented uniformly + * + */ + + +/*==============* + * HEADER FILES * + *==============*/ + +#include <assert.h> +#include "all.h" +#include "mtypes.h" +#include "bitio.h" +#include "huff.h" +#include "postdct.h" +#include "opts.h" + +/*==================* + * STATIC VARIABLES * + *==================*/ + +/* ZAG[i] is the natural-order position of the i'th element of zigzag order. */ +int ZAG[] = { + 0, 1, 8, 16, 9, 2, 3, 10, + 17, 24, 32, 25, 18, 11, 4, 5, + 12, 19, 26, 33, 40, 48, 41, 34, + 27, 20, 13, 6, 7, 14, 21, 28, + 35, 42, 49, 56, 57, 50, 43, 36, + 29, 22, 15, 23, 30, 37, 44, 51, + 58, 59, 52, 45, 38, 31, 39, 46, + 53, 60, 61, 54, 47, 55, 62, 63 +}; + +/* + * possible optimization: reorder the qtable in the correct zigzag order, to + * reduce the number of necessary lookups + * + * this table comes from the MPEG draft, p. D-16, Fig. 2-D.15. + */ +int32 qtable[] = { + 8, 16, 19, 22, 26, 27, 29, 34, + 16, 16, 22, 24, 27, 29, 34, 37, + 19, 22, 26, 27, 29, 34, 34, 38, + 22, 22, 26, 27, 29, 34, 37, 40, + 22, 26, 27, 29, 32, 35, 40, 48, + 26, 27, 29, 32, 35, 40, 48, 58, + 26, 27, 29, 34, 38, 46, 56, 69, + 27, 29, 35, 38, 46, 56, 69, 83 +}; + +int32 niqtable[] = { + 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16 +}; + +int32 *customQtable = NULL; +int32 *customNIQtable = NULL; + +/*==================* + * GLOBAL VARIABLES * + *==================*/ + +extern boolean realQuiet; + +/*=====================* + * EXPORTED PROCEDURES * + *=====================*/ + +/*===========================================================================* + * + * Mpost_UnQuantZigBlock + * + * unquantize and zig-zag (decode) a single block + * see section 2.4.4.1 of MPEG standard + * + * RETURNS: nothing + * + * SIDE EFFECTS: none + * + *===========================================================================*/ +void +Mpost_UnQuantZigBlock(FlatBlock in, + Block out, + int qscale, + boolean iblock) +{ + register int index; + int start; + int position; + register int qentry; + int level, coeff; + + if ( iblock ) { + /* qtable[0] must be 8 */ + out[0][0] = (int16)(in[0] * 8); + + /* don't need to do anything fancy here, because we saved orig + value, not encoded dc value */ + start = 1; + } else { + start = 0; + } + + for ( index = start; index < DCTSIZE_SQ; index++ ) { + position = ZAG[index]; + level = in[index]; + + if (level == 0) { + ((int16 *)out)[position] = 0; + continue; + } + + + if ( iblock ) { + qentry = qtable[position] * qscale; + coeff = (level*qentry)/8; + if ( (coeff & 1) == 0 ) { + if ( coeff < 0 ) { + coeff++; + } else if ( coeff > 0 ) { + coeff--; + } + } + } else { + qentry = niqtable[position] * qscale; + if ( level == 0 ) { + coeff = 0; + } else if ( level < 0 ) { + coeff = (((2*level)-1)*qentry) / 16; + if ( (coeff & 1) == 0 ) { + coeff++; + } + } else { + coeff = (((2*level)+1)*qentry) >> 4; + if ( (coeff & 1) == 0 ) { + coeff--; + } + } + + if ( coeff > 2047 ) { + coeff = 2047; + } else if ( coeff < -2048 ) { + coeff = -2048; + } + } + + ((int16 *)out)[position] = coeff; + } +} + + +/*===========================================================================* + * + * Mpost_QuantZigBlock + * + * quantize and zigzags a block + * + * RETURNS: MPOST_OVERFLOW if a generated value is outside |255| + * MPOST_ZERO if all coeffs are zero + * MPOST_NON_ZERO otherwisw + * + * SIDE EFFECTS: none + * + *===========================================================================*/ +int +Mpost_QuantZigBlock(Block in, + FlatBlock out, + register int qscale, + int iblock) +{ + register int i; + register int16 temp; + register int qentry; + register int position; + boolean nonZero = FALSE; + boolean overflow = FALSE; + + DBG_PRINT(("Mpost_QuantZigBlock...\n")); + if (iblock) { + /* + * the DC coefficient is handled specially -- it's not + * sensitive to qscale, but everything else is + */ + temp = ((int16 *) in)[ZAG[0]]; + qentry = qtable[ZAG[0]]; + + if (temp < 0) { + temp = -temp; + temp += (qentry >> 1); + temp /= qentry; + temp = -temp; + } else { + temp += (qentry >> 1); + temp /= qentry; + } + if ( temp != 0 ) { + nonZero = TRUE; + } + out[0] = temp; + + for (i = 1; i < DCTSIZE_SQ; i++) { + position = ZAG[i]; + temp = ((int16 *) in)[position]; + qentry = qtable[position] * qscale; + + /* see 1993 MPEG doc, section D.6.3.4 */ + if (temp < 0) { + temp = -temp; + temp = (temp << 3); /* temp > 0 */ + temp += (qentry >> 1); + temp /= qentry; + temp = -temp; + } else { + temp = (temp << 3); /* temp > 0 */ + temp += (qentry >> 1); + temp /= qentry; + } + + if ( temp != 0 ) { + nonZero = TRUE; + out[i] = temp; + if (temp < -255) { + temp = -255; + overflow = TRUE; + } else if (temp > 255) { + temp = 255; + overflow = TRUE; + } + } else out[i]=0; + } + } else { + for (i = 0; i < DCTSIZE_SQ; i++) { + position = ZAG[i]; + temp = ((int16 *) in)[position]; + + /* multiply by non-intra qtable */ + qentry = qscale * niqtable[position]; + + /* see 1993 MPEG doc, D.6.4.5 */ + temp *= 8; + temp /= qentry; /* truncation toward 0 -- correct */ + + if ( temp != 0 ) { + nonZero = TRUE; + out[i] = temp; + if (temp < -255) { + temp = -255; + overflow = TRUE; + } else if (temp > 255) { + temp = 255; + overflow = TRUE; + } + + } else out[i]=0; + } + } + + if (overflow) return MPOST_OVERFLOW; + if (nonZero) return MPOST_NON_ZERO; + return MPOST_ZERO; +} + + + +/*===========================================================================* + * + * Mpost_RLEHuffIBlock + * + * generate the huffman bits from an I-block + * + * RETURNS: nothing + * + * SIDE EFFECTS: none + * + *===========================================================================*/ +void +Mpost_RLEHuffIBlock(FlatBlock in, + BitBucket *out) +{ + register int i; + register int nzeros = 0; + register int16 cur; + register int16 acur; + register uint32 code; + register int nbits; + + /* + * yes, Virginia, we start at 1. The DC coefficient is handled + * specially, elsewhere. Not here. + */ + for (i = 1; i < DCTSIZE_SQ; i++) { + cur = in[i]; + acur = ABS(cur); + if (cur) { + if ( (nzeros < HUFF_MAXRUN) && (acur < huff_maxlevel[nzeros])) { + /* + * encode using the Huffman tables + */ + + DBG_PRINT(("rle_huff %02d.%02d: Run %02d, Level %4d\n", i, ZAG[i], nzeros, cur)); + code = (huff_table[nzeros])[acur]; + nbits = (huff_bits[nzeros])[acur]; + + if (cur < 0) { + code |= 1; /* the sign bit */ + } + Bitio_Write(out, code, nbits); + } else { + /* + * encode using the escape code + */ + DBG_PRINT(("Escape\n")); + Bitio_Write(out, 0x1, 6); /* ESCAPE */ + DBG_PRINT(("Run Length\n")); + Bitio_Write(out, nzeros, 6); /* Run-Length */ + + /* + * this shouldn't happen, but the other + * choice is to bomb out and dump core... + * Hmmm, seems to happen with small Qtable entries (1) -srs + */ + if (cur < -255) { + cur = -255; + } else if (cur > 255) { + cur = 255; + } + + DBG_PRINT(("Level\n")); + if (acur < 128) { + Bitio_Write(out, cur, 8); + } else { + if (cur < 0) { + Bitio_Write(out, 0x8001 + cur + 255, 16); + } else { + Bitio_Write(out, cur, 16); + } + } + } + nzeros = 0; + } else { + nzeros++; + } + } + DBG_PRINT(("End of block\n")); + Bitio_Write(out, 0x2, 2); /* end of block marker */ +} + + +/*===========================================================================* + * + * Mpost_RLEHuffPBlock + * + * generate the huffman bits from an P-block + * + * RETURNS: nothing + * + * SIDE EFFECTS: none + * + *===========================================================================*/ +void +Mpost_RLEHuffPBlock(FlatBlock in, + BitBucket *out) +{ + register int i; + register int nzeros = 0; + register int16 cur; + register int16 acur; + register uint32 code; + register int nbits; + boolean first_dct = TRUE; + + /* + * yes, Virginia, we start at 0. + */ + for (i = 0; i < DCTSIZE_SQ; i++) { + cur = in[i]; + acur = ABS(cur); + if (cur) { + if ((nzeros < HUFF_MAXRUN) && (acur < huff_maxlevel[nzeros])) { + /* + * encode using the Huffman tables + */ + + DBG_PRINT(("rle_huff %02d.%02d: Run %02d, Level %4d\n", i, ZAG[i], nzeros, cur)); + if ( first_dct && (nzeros == 0) && (acur == 1) ) { + /* actually, only needs = 0x2 */ + code = (cur == 1) ? 0x2 : 0x3; + nbits = 2; + } else { + code = (huff_table[nzeros])[acur]; + nbits = (huff_bits[nzeros])[acur]; + } + + assert(nbits); + + if (cur < 0) { + code |= 1; /* the sign bit */ + } + Bitio_Write(out, code, nbits); + first_dct = FALSE; + } else { + /* + * encode using the escape code + */ + DBG_PRINT(("Escape\n")); + Bitio_Write(out, 0x1, 6); /* ESCAPE */ + DBG_PRINT(("Run Length\n")); + Bitio_Write(out, nzeros, 6); /* Run-Length */ + + /* + * this shouldn't happen, but the other + * choice is to bomb out and dump core... + * Hmmm, seems to happen with small Qtable entries (1) -srs + */ + if (cur < -255) { + cur = -255; + } else if (cur > 255) { + cur = 255; + } + + DBG_PRINT(("Level\n")); + if (acur < 128) { + Bitio_Write(out, cur, 8); + } else { + if (cur < 0) { + Bitio_Write(out, 0x8001 + cur + 255, 16); + } else { + Bitio_Write(out, cur, 16); + } + } + + first_dct = FALSE; + } + nzeros = 0; + } else { + nzeros++; + } + } + + /* actually, should REALLY return FALSE and not use this! */ + + if ( first_dct ) { /* have to give a first_dct even if all 0's */ + throw "HUFF called with all-zero coefficients"; + } + + DBG_PRINT(("End of block\n")); + Bitio_Write(out, 0x2, 2); /* end of block marker */ +} + + +/*===========================================================================* + * + * CalcRLEHuffLength + * + * count the huffman bits for an P-block + * + * RETURNS: number of bits + * + * SIDE EFFECTS: none + * + *===========================================================================*/ +int +CalcRLEHuffLength(FlatBlock in) +{ + register int i; + register int nzeros = 0; + register int16 cur; + register int16 acur; + register int nbits; + register int countbits=0; + boolean first_dct = TRUE; + + for (i = 0; i < DCTSIZE_SQ; i++) { + cur = in[i]; + acur = ABS(cur); + if (cur) { + if ((nzeros < HUFF_MAXRUN) && (acur < huff_maxlevel[nzeros])) { + /* + * encode using the Huffman tables + */ + + if ( first_dct && (nzeros == 0) && (acur == 1) ) { + nbits = 2; + } else { + nbits = (huff_bits[nzeros])[acur]; + } + countbits += nbits; + first_dct = FALSE; + } else { + countbits += 12; /* ESCAPE + runlength */ + + if (acur < 128) { + countbits += 8; + } else { + countbits += 16; + } + + first_dct = FALSE; + } + nzeros = 0; + } else { + nzeros++; + } + } + + countbits += 2; /* end of block marker */ + return countbits; +} diff --git a/contrib/mpeg_encode/psearch.cpp b/contrib/mpeg_encode/psearch.cpp new file mode 100644 index 0000000000000000000000000000000000000000..bb96f67bab287347a05ac2c57a9c9f93ca1378b8 --- /dev/null +++ b/contrib/mpeg_encode/psearch.cpp @@ -0,0 +1,1010 @@ +/*===========================================================================* + * psearch.c * + * * + * Procedures concerned with the P-frame motion search * + * * + * EXPORTED PROCEDURES: * + * SetPixelSearch * + * SetPSearchAlg * + * SetSearchRange * + * MotionSearchPreComputation * + * PMotionSearch * + * PSearchName * + * PSubSampleSearch * + * PLogarithmicSearch * + * * + *===========================================================================*/ + +/* + * Copyright (c) 1995 The Regents of the University of California. + * All rights reserved. + * + * Permission to use, copy, modify, and distribute this software and its + * documentation for any purpose, without fee, and without written agreement is + * hereby granted, provided that the above copyright notice and the following + * two paragraphs appear in all copies of this software. + * + * IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR + * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT + * OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF + * CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS + * ON AN "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO + * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. + */ + +/* + * $Header: /u/smoot/md/mpeg_encode/RCS/psearch.c,v 1.9 1995/01/19 23:09:12 eyhung Exp $ + * $Log: psearch.c,v $ + * Revision 1.9 1995/01/19 23:09:12 eyhung + * Changed copyrights + * + * Revision 1.9 1995/01/19 23:09:12 eyhung + * Changed copyrights + * + * Revision 1.8 1994/12/07 00:40:36 smoot + * Added seperate P and B search ranges + * + * Revision 1.7 1994/11/12 02:09:45 eyhung + * full pixel bug + * fixed on lines 512 and 563 + * + * Revision 1.6 1994/03/15 00:27:11 keving + * nothing + * + * Revision 1.5 1993/12/22 19:19:01 keving + * nothing + * + * Revision 1.4 1993/07/22 22:23:43 keving + * nothing + * + * Revision 1.3 1993/06/30 20:06:09 keving + * nothing + * + * Revision 1.2 1993/06/03 21:08:08 keving + * nothing + * + * Revision 1.1 1993/03/02 18:27:05 keving + * nothing + * + */ + + +/*==============* + * HEADER FILES * + *==============*/ + +#include "all.h" +#include "mtypes.h" +#include "frames.h" +#include "search.h" +#include "prototypes.h" +#include "fsize.h" +#include "param.h" + + +/*==================* + * STATIC VARIABLES * + *==================*/ + +/* none */ + + +/*==================* + * GLOBAL VARIABLES * + *==================*/ + +int **pmvHistogram = NULL; /* histogram of P-frame motion vectors */ +int **bbmvHistogram = NULL; /* histogram of B-frame motion vectors */ +int **bfmvHistogram = NULL; /* histogram of B-frame motion vectors */ +int pixelFullSearch; +int searchRangeP,searchRangeB; +int psearchAlg; + + +/*===============================* + * INTERNAL PROCEDURE prototypes * + *===============================*/ + + +/*=====================* + * EXPORTED PROCEDURES * + *=====================*/ + +/*===========================================================================* + * + * PMotionSearch + * + * compute the best P-frame motion vector we can + * + * + * RETURNS: TRUE = motion vector valid + * FALSE = motion vector invalid; should code I-block + * + * PRECONDITIONS: The relevant block in 'current' is valid (it has not + * been dct'd). Thus, the data in 'current' can be + * accesed through y_blocks, cr_blocks, and cb_blocks. + * This is not the case for the blocks in 'prev.' + * Therefore, references into 'prev' should be done + * through the struct items ref_y, ref_cr, ref_cb + * + * POSTCONDITIONS: current, prev should be unchanged. + * Some computation could be saved by requiring + * the dct'd difference to be put into current's block + * elements here, depending on the search technique. + * However, it was decided that it mucks up the code + * organization a little, and the saving in computation + * would be relatively little (if any). + * + * NOTES: the search procedure need not check the (0,0) motion vector + * the calling procedure has a preference toward (0,0) and it + * will check it itself + * + * SIDE EFFECTS: none + * + *===========================================================================*/ +boolean +PMotionSearch(LumBlock currentBlock, + MpegFrame *prev, + int by, + int bx, + int *motionY, + int *motionX) +{ + /* CALL SEARCH PROCEDURE */ + + switch(psearchAlg) { + case PSEARCH_SUBSAMPLE: + PSubSampleSearch(currentBlock, prev, by, bx, motionY, motionX, searchRangeP); + break; + case PSEARCH_EXHAUSTIVE: + PLocalSearch(currentBlock, prev, by, bx, motionY, motionX, + 0x7fffffff, searchRangeP); + break; + case PSEARCH_LOGARITHMIC: + PLogarithmicSearch(currentBlock, prev, by, bx, motionY, motionX, searchRangeP); + break; + case PSEARCH_TWOLEVEL: + PTwoLevelSearch(currentBlock, prev, by, bx, motionY, motionX, + 0x7fffffff, searchRangeP); + break; + default: + throw "ILLEGAL PSEARCH ALG"; + } + + return TRUE; +} + + +/*===========================================================================* + * + * SetPixelSearch + * + * set the pixel search type (half or full) + * + * RETURNS: nothing + * + * SIDE EFFECTS: pixelFullSearch + * + *===========================================================================*/ +void +SetPixelSearch(char *searchType) +{ + if ( (strcmp(searchType, "FULL") == 0 ) || ( strcmp(searchType, "WHOLE") == 0 )) { + pixelFullSearch = TRUE; + } else if ( strcmp(searchType, "HALF") == 0 ) { + pixelFullSearch = FALSE; + } else { + throw "Invalid pixel search type"; + } +} + + +/*===========================================================================* + * + * SetPSearchAlg + * + * set the P-search algorithm + * + * RETURNS: nothing + * + * SIDE EFFECTS: psearchAlg + * + *===========================================================================*/ +void +SetPSearchAlg(char *alg) +{ + if ( strcmp(alg, "EXHAUSTIVE") == 0 ) { + psearchAlg = PSEARCH_EXHAUSTIVE; + } else if (strcmp(alg, "SUBSAMPLE") == 0 ) { + psearchAlg = PSEARCH_SUBSAMPLE; + } else if ( strcmp(alg, "LOGARITHMIC") == 0 ) { + psearchAlg = PSEARCH_LOGARITHMIC; + } else if ( strcmp(alg, "TWOLEVEL") == 0 ) { + psearchAlg = PSEARCH_TWOLEVEL; + } else { + throw "Invalid psearch algorithm"; + } +} + + +/*===========================================================================* + * + * PSearchName + * + * returns a string containing the name of the search algorithm + * + * RETURNS: pointer to the string + * + * SIDE EFFECTS: none + * + *===========================================================================*/ +char * +PSearchName() +{ + switch(psearchAlg) { + case PSEARCH_EXHAUSTIVE: + return (char*)"EXHAUSTIVE"; + case PSEARCH_SUBSAMPLE: + return (char*)"SUBSAMPLE"; + case PSEARCH_LOGARITHMIC: + return (char*)"LOGARITHMIC"; + case PSEARCH_TWOLEVEL: + return (char*)"TWOLEVEL"; + default: + throw "Unknown psearchname"; + break; + } +} + + +/*===========================================================================* + * + * SetSearchRange + * + * sets the range of the search to the given number of pixels + * + * RETURNS: nothing + * + * SIDE EFFECTS: searchRange*, fCode + * + *===========================================================================*/ +void +SetSearchRange(int pixelsP, int pixelsB) +{ + register int index; + + searchRangeP = 2*pixelsP; /* +/- 'pixels' pixels */ + searchRangeB = 2*pixelsB; + searchRangeB = 2*pixelsB; + + if ( computeMVHist ) { + int max_search; + max_search=(searchRangeP>searchRangeB) ? + ((searchRangeP>searchRangeB)?searchRangeP:searchRangeB) + : ((searchRangeB>searchRangeB)?searchRangeB:searchRangeB); + + pmvHistogram = (int **) malloc((2*searchRangeP+3)*sizeof(int *)); + bbmvHistogram = (int **) malloc((2*searchRangeB+3)*sizeof(int *)); + bfmvHistogram = (int **) malloc((2*searchRangeB+3)*sizeof(int *)); + for ( index = 0; index < 2*max_search+3; index++ ) { + pmvHistogram[index] = (int *) calloc(2*searchRangeP+3, sizeof(int)); + bbmvHistogram[index] = (int *) calloc(2*searchRangeB+3, sizeof(int)); + bfmvHistogram[index] = (int *) calloc(2*searchRangeB+3, sizeof(int)); + } + } +} + + +/*===========================================================================* + * + * USER-MODIFIABLE + * + * MotionSearchPreComputation + * + * do whatever you want here; this is called once per frame, directly + * after reading + * + * RETURNS: whatever + * + * SIDE EFFECTS: whatever + * + *===========================================================================*/ +void +MotionSearchPreComputation(MpegFrame *frame) +{ + /* do nothing */ +} + + +/*===========================================================================* + * + * PSubSampleSearch + * + * uses the subsampling algorithm to compute the P-frame vector + * + * RETURNS: motion vector + * + * SIDE EFFECTS: none + * + * REFERENCE: Liu and Zaccarin: New Fast Algorithms for the Estimation + * of Block Motion Vectors, IEEE Transactions on Circuits + * and Systems for Video Technology, Vol. 3, No. 2, 1993. + * + *===========================================================================*/ +int32 +PSubSampleSearch(LumBlock currentBlock, + MpegFrame *prev, + int by, + int bx, + int *motionY, + int *motionX, + int searchRange) +{ + register int mx, my; + int32 diff, bestBestDiff; + int stepSize; + register int x; + int bestMY[4], bestMX[4], bestDiff[4]; + int leftMY, leftMX; + int rightMY, rightMX; + + stepSize = (pixelFullSearch ? 2 : 1); + + COMPUTE_MOTION_BOUNDARY(by,bx,stepSize,leftMY,leftMX,rightMY,rightMX); + + if ( searchRange < rightMY ) { + rightMY = searchRange; + } + + if ( searchRange < rightMX ) { + rightMX = searchRange; + } + + for ( x = 0; x < 4; x++ ) { + bestMY[x] = 0; + bestMX[x] = 0; + bestDiff[x] = 0x7fffffff; + } + + /* do A pattern */ + for ( my = -searchRange; my < rightMY; my += 2*stepSize ) { + if ( my < leftMY ) { + continue; + } + + for ( mx = -searchRange; mx < rightMX; mx += 2*stepSize ) { + if ( mx < leftMX ) { + continue; + } + + diff = LumMotionErrorA(currentBlock, prev, by, bx, my, mx, bestDiff[0]); + + if ( diff < bestDiff[0] ) { + bestMY[0] = my; + bestMX[0] = mx; + bestDiff[0] = diff; + } + } + } + + /* do B pattern */ + for ( my = stepSize-searchRange; my < rightMY; my += 2*stepSize ) { + if ( my < leftMY ) { + continue; + } + + for ( mx = -searchRange; mx < rightMX; mx += 2*stepSize ) { + if ( mx < leftMX ) { + continue; + } + + diff = LumMotionErrorB(currentBlock, prev, by, bx, my, mx, bestDiff[1]); + + if ( diff < bestDiff[1] ) { + bestMY[1] = my; + bestMX[1] = mx; + bestDiff[1] = diff; + } + } + } + + /* do C pattern */ + for ( my = stepSize-searchRange; my < rightMY; my += 2*stepSize ) { + if ( my < leftMY ) { + continue; + } + + for ( mx = stepSize-searchRange; mx < rightMX; mx += 2*stepSize ) { + if ( mx < leftMX ) { + continue; + } + + diff = LumMotionErrorC(currentBlock, prev, by, bx, my, mx, bestDiff[2]); + + if ( diff < bestDiff[2] ) { + bestMY[2] = my; + bestMX[2] = mx; + bestDiff[2] = diff; + } + } + } + + /* do D pattern */ + for ( my = -searchRange; my < rightMY; my += 2*stepSize ) { + if ( my < leftMY ) { + continue; + } + + for ( mx = stepSize-searchRange; mx < rightMX; mx += 2*stepSize ) { + if ( mx < leftMX ) { + continue; + } + + diff = LumMotionErrorD(currentBlock, prev, by, bx, my, mx, bestDiff[3]); + + if ( diff < bestDiff[3] ) { + bestMY[3] = my; + bestMX[3] = mx; + bestDiff[3] = diff; + } + } + } + + /* first check old motion */ + if ( (*motionY >= leftMY) && (*motionY < rightMY) && + (*motionX >= leftMX) && (*motionX < rightMX) ) { + bestBestDiff = LumMotionError(currentBlock, prev, by, bx, *motionY, *motionX, 0x7fffffff); + } else { + bestBestDiff = 0x7fffffff; + } + + /* look at Error of 4 different motion vectors */ + for ( x = 0; x < 4; x++ ) { + bestDiff[x] = LumMotionError(currentBlock, prev, by, bx, + bestMY[x], bestMX[x], bestBestDiff); + + if ( bestDiff[x] < bestBestDiff ) { + bestBestDiff = bestDiff[x]; + *motionY = bestMY[x]; + *motionX = bestMX[x]; + } + } + + return bestBestDiff; +} + + +/*===========================================================================* + * + * PLogarithmicSearch + * + * uses logarithmic search to compute the P-frame vector + * + * RETURNS: motion vector + * + * SIDE EFFECTS: none + * + * REFERENCE: MPEG-I specification, pages 32-33 + * + *===========================================================================*/ +int32 +PLogarithmicSearch(LumBlock currentBlock, + MpegFrame *prev, + int by, + int bx, + int *motionY, + int *motionX, + int searchRange) +{ + register int mx, my; + int32 diff, bestDiff; + int stepSize; + int leftMY, leftMX; + int rightMY, rightMX; + int tempRightMY, tempRightMX; + int spacing; + int centerX, centerY; + int newCenterX, newCenterY; + + stepSize = (pixelFullSearch ? 2 : 1); + + COMPUTE_MOTION_BOUNDARY(by,bx,stepSize,leftMY,leftMX,rightMY,rightMX); + + bestDiff = 0x7fffffff; + + /* grid spacing */ + if ( stepSize == 2 ) { /* make sure spacing is even */ + spacing = (searchRange+1)/2; + if ( (spacing % 2) != 0 ) { + spacing--; + } + } else { + spacing = (searchRange+1)/2; + } + centerX = 0; + centerY = 0; + + while ( spacing >= stepSize ) { + newCenterY = centerY; + newCenterX = centerX; + + tempRightMY = rightMY; + if ( centerY+spacing+1 < tempRightMY ) { + tempRightMY = centerY+spacing+1; + } + tempRightMX = rightMX; + if ( centerX+spacing+1 < tempRightMX ) { + tempRightMX = centerX+spacing+1; + } + + for ( my = centerY-spacing; my < tempRightMY; my += spacing ) { + if ( my < leftMY ) { + continue; + } + + for ( mx = centerX-spacing; mx < tempRightMX; mx += spacing ) { + if ( mx < leftMX ) { + continue; + } + + diff = LumMotionError(currentBlock, prev, by, bx, my, mx, bestDiff); + + if ( diff < bestDiff ) { + newCenterY = my; + newCenterX = mx; + + bestDiff = diff; + } + } + } + + centerY = newCenterY; + centerX = newCenterX; + + if ( stepSize == 2 ) { /* make sure spacing is even */ + if ( spacing == 2 ) { + spacing = 0; + } else { + spacing = (spacing+1)/2; + if ( (spacing % 2) != 0 ) { + spacing--; + } + } + } else { + if ( spacing == 1 ) { + spacing = 0; + } else { + spacing = (spacing+1)/2; + } + } + } + + /* check old motion -- see if it's better */ + if ( (*motionY >= leftMY) && (*motionY < rightMY) && + (*motionX >= leftMX) && (*motionX < rightMX) ) { + diff = LumMotionError(currentBlock, prev, by, bx, *motionY, *motionX, bestDiff); + } else { + diff = 0x7fffffff; + } + + if ( bestDiff < diff ) { + *motionY = centerY; + *motionX = centerX; + } else { + bestDiff = diff; + } + + return bestDiff; +} + + +/*===========================================================================* + * + * PLocalSearch + * + * uses local exhaustive search to compute the P-frame vector + * + * RETURNS: motion vector + * + * SIDE EFFECTS: none + * + *===========================================================================*/ +int32 +PLocalSearch(LumBlock currentBlock, + MpegFrame *prev, + int by, + int bx, + int *motionY, + int *motionX, + int32 bestSoFar, + int searchRange) +{ + register int mx, my; + int32 diff, bestDiff; + int stepSize; + int leftMY, leftMX; + int rightMY, rightMX; + int distance; + int tempRightMY, tempRightMX; + + stepSize = (pixelFullSearch ? 2 : 1); + + COMPUTE_MOTION_BOUNDARY(by,bx,stepSize,leftMY,leftMX,rightMY,rightMX); + + /* try old motion vector first */ + if ( VALID_MOTION(*motionY, *motionX) ) { + bestDiff = LumMotionError(currentBlock, prev, by, bx, *motionY, *motionX, bestSoFar); + + if ( bestSoFar < bestDiff ) { + bestDiff = bestSoFar; + } + } else { + *motionY = 0; + *motionX = 0; + + bestDiff = bestSoFar; + } + + /* try a spiral pattern */ + for ( distance = stepSize; distance <= searchRange; + distance += stepSize ) { + tempRightMY = rightMY; + if ( distance < tempRightMY ) { + tempRightMY = distance; + } + tempRightMX = rightMX; + if ( distance < tempRightMX ) { + tempRightMX = distance; + } + + /* do top, bottom */ + for ( my = -distance; my < tempRightMY; + my += max(tempRightMY+distance-stepSize, stepSize) ) { + if ( my < leftMY ) { + continue; + } + + for ( mx = -distance; mx < tempRightMX; mx += stepSize ) { + if ( mx < leftMX ) { + continue; + } + + diff = LumMotionError(currentBlock, prev, by, bx, my, mx, bestDiff); + + if ( diff < bestDiff ) { + *motionY = my; + *motionX = mx; + bestDiff = diff; + } + } + } + + /* do left, right */ + for ( mx = -distance; mx < tempRightMX; + mx += max(tempRightMX+distance-stepSize, stepSize) ) { + if ( mx < leftMX ) { + continue; + } + + for ( my = -distance+stepSize; my < tempRightMY-stepSize; + my += stepSize ) { + if ( my < leftMY ) { + continue; + } + + diff = LumMotionError(currentBlock, prev, by, bx, my, mx, bestDiff); + + if ( diff < bestDiff ) { + *motionY = my; + *motionX = mx; + bestDiff = diff; + } + } + } + } + + return bestDiff; +} + + +/*===========================================================================* + * + * PTwoLevelSearch + * + * uses two-level search to compute the P-frame vector + * first does exhaustive full-pixel search, then looks at neighboring + * half-pixel motion vectors + * + * RETURNS: motion vector + * + * SIDE EFFECTS: none + * + *===========================================================================*/ +int32 +PTwoLevelSearch(LumBlock currentBlock, + MpegFrame *prev, + int by, + int bx, + int *motionY, + int *motionX, + int32 bestSoFar, + int searchRange) +{ + register int mx, my; + register int loopInc; + int32 diff, bestDiff; + int leftMY, leftMX; + int rightMY, rightMX; + int distance; + int tempRightMY, tempRightMX; + int xOffset, yOffset; + + /* exhaustive full-pixel search first */ + + COMPUTE_MOTION_BOUNDARY(by,bx,2,leftMY,leftMX,rightMY,rightMX); + + rightMY--; + rightMX--; + + /* convert vector into full-pixel vector */ + if ( *motionY > 0 ) { + if ( ((*motionY) % 2) == 1 ) { + (*motionY)--; + } + } else if ( ((-(*motionY)) % 2) == 1 ) { + (*motionY)++; + } + + if ( *motionX > 0 ) { + if ( ((*motionX) % 2) == 1 ) { + (*motionX)--; + } + } else if ( ((-(*motionX)) % 2) == 1 ) { + (*motionX)++; + } + + /* try old motion vector first */ + if ( VALID_MOTION(*motionY, *motionX) ) { + bestDiff = LumMotionError(currentBlock, prev, by, bx, *motionY, *motionX, bestSoFar); + + if ( bestSoFar < bestDiff ) { + bestDiff = bestSoFar; + } + } else { + *motionY = 0; + *motionX = 0; + + bestDiff = bestSoFar; + } + + rightMY++; + rightMX++; + + /* try a spiral pattern */ + for ( distance = 2; distance <= searchRange; distance += 2 ) { + tempRightMY = rightMY; + if ( distance < tempRightMY ) { + tempRightMY = distance; + } + tempRightMX = rightMX; + if ( distance < tempRightMX ) { + tempRightMX = distance; + } + + /* do top, bottom */ + loopInc = max(tempRightMY+distance-2, 2); + for ( my = -distance; my < tempRightMY; my += loopInc ) { + if ( my < leftMY ) { + continue; + } + + for ( mx = -distance; mx < tempRightMX; mx += 2 ) { + if ( mx < leftMX ) { + continue; + } + + diff = LumMotionError(currentBlock, prev, by, bx, my, mx, bestDiff); + + if ( diff < bestDiff ) { + *motionY = my; + *motionX = mx; + bestDiff = diff; + } + } + } + + /* do left, right */ + loopInc = max(tempRightMX+distance-2, 2); + for ( mx = -distance; mx < tempRightMX; mx += loopInc ) { + if ( mx < leftMX ) { + continue; + } + + for ( my = -distance+2; my < tempRightMY-2; my += 2 ) { + if ( my < leftMY ) { + continue; + } + + diff = LumMotionError(currentBlock, prev, by, bx, my, mx, bestDiff); + + if ( diff < bestDiff ) { + *motionY = my; + *motionX = mx; + bestDiff = diff; + } + } + } + } + + /* now look at neighboring half-pixels */ + my = *motionY; + mx = *motionX; + + rightMY--; + rightMX--; + + for ( yOffset = -1; yOffset <= 1; yOffset++ ) { + for ( xOffset = -1; xOffset <= 1; xOffset++ ) { + if ( (yOffset == 0) && (xOffset == 0) ) + continue; + + if ( VALID_MOTION(my+yOffset, mx+xOffset) && + ((diff = LumMotionError(currentBlock, prev, by, bx, + my+yOffset, mx+xOffset, bestDiff)) < bestDiff) ) { + *motionY = my+yOffset; + *motionX = mx+xOffset; + bestDiff = diff; + } + } + } + + return bestDiff; +} + + +void +ShowPMVHistogram(FILE *fpointer) +{ + register int x, y; + int *columnTotals; + int rowTotal; + + columnTotals = (int *) calloc(2*searchRangeP+3, sizeof(int)); + +#ifdef COMPLETE_DISPLAY + fprintf(fpointer, " "); + for ( y = 0; y < 2*searchRange+3; y++ ) { + fprintf(fpointer, "%3d ", y-searchRangeP-1); + } + fprintf(fpointer, "\n"); +#endif + + for ( x = 0; x < 2*searchRangeP+3; x++ ) { +#ifdef COMPLETE_DISPLAY + fprintf(fpointer, "%3d ", x-searchRangeP-1); +#endif + rowTotal = 0; + for ( y = 0; y < 2*searchRangeP+3; y++ ) { + fprintf(fpointer, "%3d ", pmvHistogram[x][y]); + rowTotal += pmvHistogram[x][y]; + columnTotals[y] += pmvHistogram[x][y]; + } +#ifdef COMPLETE_DISPLAY + fprintf(fpointer, "%4d\n", rowTotal); +#else + fprintf(fpointer, "\n"); +#endif + } + +#ifdef COMPLETE_DISPLAY + fprintf(fpointer, "Tot "); + for ( y = 0; y < 2*searchRangeP+3; y++ ) { + fprintf(fpointer, "%3d ", columnTotals[y]); + } +#endif + fprintf(fpointer, "\n"); +} + + +void +ShowBBMVHistogram(FILE *fpointer) +{ + register int x, y; + int *columnTotals; + int rowTotal; + + fprintf(fpointer, "B-frame Backwards:\n"); + + columnTotals = (int *) calloc(2*searchRangeB+3, sizeof(int)); + +#ifdef COMPLETE_DISPLAY + fprintf(fpointer, " "); + for ( y = 0; y < 2*searchRangeB+3; y++ ) { + fprintf(fpointer, "%3d ", y-searchRangeB-1); + } + fprintf(fpointer, "\n"); +#endif + + for ( x = 0; x < 2*searchRangeB+3; x++ ) { +#ifdef COMPLETE_DISPLAY + fprintf(fpointer, "%3d ", x-searchRangeB-1); +#endif + rowTotal = 0; + for ( y = 0; y < 2*searchRangeB+3; y++ ) { + fprintf(fpointer, "%3d ", bbmvHistogram[x][y]); + rowTotal += bbmvHistogram[x][y]; + columnTotals[y] += bbmvHistogram[x][y]; + } +#ifdef COMPLETE_DISPLAY + fprintf(fpointer, "%4d\n", rowTotal); +#else + fprintf(fpointer, "\n"); +#endif + } + +#ifdef COMPLETE_DISPLAY + fprintf(fpointer, "Tot "); + for ( y = 0; y < 2*searchRangeB+3; y++ ) { + fprintf(fpointer, "%3d ", columnTotals[y]); + } +#endif + fprintf(fpointer, "\n"); +} + + +void +ShowBFMVHistogram(FILE *fpointer) +{ + register int x, y; + int *columnTotals; + int rowTotal; + + fprintf(fpointer, "B-frame Forwards:\n"); + + columnTotals = (int *) calloc(2*searchRangeB+3, sizeof(int)); + +#ifdef COMPLETE_DISPLAY + fprintf(fpointer, " "); + for ( y = 0; y < 2*searchRangeB+3; y++ ) { + fprintf(fpointer, "%3d ", y-searchRangeB-1); + } + fprintf(fpointer, "\n"); +#endif + + for ( x = 0; x < 2*searchRangeB+3; x++ ) { +#ifdef COMPLETE_DISPLAY + fprintf(fpointer, "%3d ", x-searchRangeB-1); +#endif + rowTotal = 0; + for ( y = 0; y < 2*searchRangeB+3; y++ ) { + fprintf(fpointer, "%3d ", bfmvHistogram[x][y]); + rowTotal += bfmvHistogram[x][y]; + columnTotals[y] += bfmvHistogram[x][y]; + } +#ifdef COMPLETE_DISPLAY + fprintf(fpointer, "%4d\n", rowTotal); +#else + fprintf(fpointer, "\n"); +#endif + } + +#ifdef COMPLETE_DISPLAY + fprintf(fpointer, "Tot "); + for ( y = 0; y < 2*searchRangeB+3; y++ ) { + fprintf(fpointer, "%3d ", columnTotals[y]); + } +#endif + fprintf(fpointer, "\n"); +} + + +/*=====================* + * INTERNAL PROCEDURES * + *=====================*/ + + /* none */ + diff --git a/contrib/mpeg_encode/rate.cpp b/contrib/mpeg_encode/rate.cpp new file mode 100644 index 0000000000000000000000000000000000000000..27d9176d35aeb2118cdf76cd41b6f1adaeb365ee --- /dev/null +++ b/contrib/mpeg_encode/rate.cpp @@ -0,0 +1,947 @@ +/*============================================================================* + * rate.c * + * * + * Procedures concerned with rate control * + * * + * EXPORTED PROCEDURES: * + * initRatecontrol() * + * targetRateControl() * + * updateRateControl() * + * MB_RateOut() * + * needQScaleChange() * + * incNumBlocks() * + * incQuant() * + * incMacroBlockBits() * + * setPictureRate() * + * setBitRate() * + * getBitRate() * + * setBufferSize() * + * getBufferSize() * + * * + * NOTES: * + * Naming conventions follow those of MPEG-2 draft algorithm (chap. 10) * + *============================================================================*/ + + +/* + * Copyright (c) 1995 The Regents of the University of California. + * All rights reserved. + * + * Permission to use, copy, modify, and distribute this software and its + * documentation for any purpose, without fee, and without written agreement is + * hereby granted, provided that the above copyright notice and the following + * two paragraphs appear in all copies of this software. + * + * IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR + * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT + * OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF + * CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS + * ON AN "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO + * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. + */ + +/*==============* + * HEADER FILES * + *==============*/ + +#include <sys/times.h> +#include "all.h" +#include "mtypes.h" +#include "bitio.h" +#include "frames.h" +#include "prototypes.h" +#include "param.h" +#include "mheaders.h" +#include "fsize.h" +#include "postdct.h" +#include "mpeg.h" +#include "parallel.h" +#include "dct.h" +#include "rate.h" + + +/*==================* + * GLOBAL VARIABLES * + *==================*/ + +#define MAX_BIT_RATE 104857600 /* 18 digit number in units of 400 */ +#define MAX_BUFFER_SIZE 16760832 /* 10 digit number in units of 16k */ +#define DEFAULT_BUFFER_SIZE 327680 /* maximun for "constrained" bitstream */ +#define DEFAULT_VBV_FULLNESS 3 /* wait till 1/3 full */ +#define DEFAULT_PICT_RATE_CODE 5 /* code for 30 Frames/sec */ +#define DEFAULT_PICT_RATE 30 /* 30 frames per second */ +#define MAX_VBV_DELAY 32768 /* 16 digits */ + + +/* Variables from Parameter File */ + +static int RateControlMode = VARIABLE_RATE; +static int32 buffer_size = DEFAULT_BUFFER_SIZE; +static int32 bit_rate = -1; + + +/* Variables for the VBV buffer defined in MPEG specs */ +static int32 VBV_delay =0; /* delay in units of 1/90000 seconds */ +static int32 VBV_buffer = 0; /* fullness of the theoretical VBV buffer */ +static int32 bufferFillRate = 0; /* constant rate at which buffer filled */ +static int32 frameDelayIncrement = 0; /* number of "delay" units/Frame */ + +/* Global complexity measure variables */ +static int Xi, Xp, Xb; /* Global complexity measure */ + +static int Si, Sp, Sb; /* Total # bits for last pict of type (Overhead?) */ + +static float Qi, Qp, Qb; /* avg quantizaton for last picture of type */ + +/* Target bit allocations for each type of picture*/ +int Ti, Tp, Tb; + +int current_Tx; /* allocation for current frame */ + +/* Count of number of pictures of each type remaining */ +int GOP_X = 0; +int GOP_I = 0; +int GOP_P = 0; +int GOP_B = 0; + +int Nx = 0; +int Ni = 0; +int Np = 0; +int Nb = 0; + +/* Counters used while encoding frames */ + +int rc_numBlocks = 0; +int rc_totalQuant = 0; +int rc_bitsThisMB; +int rc_totalMBBits; +int rc_totalFrameBits; +int rc_totalOverheadBits = 0; + + +/* Want to print out Macroblock info every Nth MB */ +int RC_MB_SAMPLE_RATE = 0; + +static float Ki = .7; +static float Kp = 1; +static float Kb = 1.4; +static int rc_R; +static int rc_G; + +/* Rate Control variables */ + +/* Virtual buffers for each frame type */ +static int d0_i; /* Initial fullnesses */ +static int d0_p; +static int d0_b; + +static int lastFrameVirtBuf; /* fullness after last frame of this type */ +static int currentVirtBuf; /* fullness during current encoding*/ + +static int MB_cnt = -1; /* Number of MB's in picture */ + +static int rc_Q; /* reference quantization parameter */ + +static int reactionParameter; /* Reaction parameter */ + +/* Adaptive Quantization variables */ +static int act_j; /* spatial activity measure */ +static float N_act; /* Normalised spacial activity */ +static int avg_act; /* average activity value in last picture encoded */ +static int total_act_j; /* Sum of activity values in current frame */ + +static int var_sblk; /* sub-block activity */ +static int P_mean; /* Mean value of pixels in 8x8 sub-block */ + +static int mquant; /* Raw Quantization value */ +static int Qscale; /* Clipped, truncated quantization value */ + + + +/* Output-related variables */ +#ifdef RC_STATS_FILE +static FILE *RC_FILE; +#endif + +static char *Frame_header1 = (char*)" Fm # Bit GOP V "; +static char *Frame_header2 = (char*)" # type MBs Alloc left Ni Np Nb N_act buff Q_rc Qscale"; +static char *Frame_header3 = (char*)"---- - ---- ------ ------- -- -- -- ----- ------ ---- ----"; +static char *Frame_trailer1 = (char*)" avg virt % GOP % VBV"; +static char *Frame_trailer2 = (char*)" Sx Qx Xx act N_act buffer alloc left left buf delay"; +static char *Frame_trailer3 = (char*)"------ --.-- ------- --- --.-- ------- --- ------- --- ------- ------"; + +static char *MB_header1 = (char*)"MB# #bits Q mqt Dj Q_j actj N_act totbits b/MB %alloc %done"; +static char *MB_header2 = (char*)"--- ----- -- --- ------ --- ----- --.-- ------ ---- --- ---"; + +static char rc_buffer[101]; + +/* EXTERNAL Variables */ +extern char *framePattern; +extern int framePatternLen; + + +/*===============================* + * INTERNAL PROCEDURE prototypes * + *===============================*/ + +int initGOPRateControl _ANSI_ARGS_((void)); +int determineMBCount _ANSI_ARGS_((void)); +void checkBufferFullness _ANSI_ARGS_((int count)); +void checkSpatialActivity _ANSI_ARGS_((Block blk0, Block blk1, Block blk2, Block blk3)); +void incNumBlocks _ANSI_ARGS_((int num)); +void calculateVBVDelay _ANSI_ARGS_((int num)); +void updateVBVBuffer _ANSI_ARGS_((int frameBits)); +int BlockExperiments _ANSI_ARGS_((int16 *OrigBlock, int16 *NewBlock, int control)); + + +/*=====================* + * EXPORTED PROCEDURES * + *=====================*/ + +/*===========================================================================* + * + * initRateControl + * + * initialize the allocation parameters. + * + * RETURNS: nothing + * + * SIDE EFFECTS: many global variables + * + * NOTES: Get rid of the redundant pattern stuff!! + *===========================================================================*/ +int +initRateControl() +{ + int index; + int result; + + DBG_PRINT(("\tInitializing Allocation Data\n")); + +#ifdef RC_STATS_FILE + RC_FILE = fopen("RC_STATS_FILE", "w"); + if ( RC_FILE == NULL) { + DBG_PRINT(("\tOpen of RC file failed, using stderr\n")); + RC_FILE = stderr; + fprintf(RC_FILE, "\tOpen of RC file failed, using stderr\n"); + fflush(RC_FILE); + } +#endif + + /* Initialize Pattern info */ + GOP_X = framePatternLen; + for ( index = 0; index < framePatternLen; index++ ) { + switch( framePattern[index] ) { + case 'i': + GOP_I++; + break; + case 'p': + GOP_P++; + break; + case 'b': + GOP_B++; + break; + default: + printf("\n\tERROR rate.c - BAD PATTERN!\n"); + RateControlMode = VARIABLE_RATE; + return (0); + } + } + if (GOP_X != (GOP_I + GOP_P + GOP_B )) { + printf("\n\tERROR rate.c - Pattern Length Mismatch\n"); + RateControlMode = VARIABLE_RATE; + return (-1); + } + + /* Initializing GOP bit allocation */ + rc_R = 0; + rc_G = (bit_rate * GOP_X/frameRateRounded); + + /* Initialize the "global complexity measures" */ + Xi = (160 * bit_rate/115); + Xp = (60 * bit_rate/115); + Xb = (42 * bit_rate/115); + + /* Initialize MB counters */ + rc_totalMBBits= rc_bitsThisMB= rc_totalFrameBits=rc_totalOverheadBits = 0; + rc_numBlocks = rc_totalQuant = 0; + + /* init virtual buffers */ + reactionParameter = (2 * bit_rate / frameRateRounded); + d0_i = (10 * reactionParameter / 31); + d0_p = (Kp * d0_i); + d0_b = (Kb * d0_i); + + lastFrameVirtBuf = d0_i; /* start with I Frame */ + rc_Q = lastFrameVirtBuf * 31 / reactionParameter; + + /* init spatial activity measures */ + avg_act = 400; /* Suggested initial value */ + N_act = 1; + + mquant = rc_Q * N_act; + + frameDelayIncrement = (90000 / frameRateRounded); /* num of "delay" units per frame */ + bufferFillRate = bit_rate / frameRateRounded; /* VBV buf fills at constant rate */ + VBV_buffer = buffer_size; + DBG_PRINT(("\tVBV- delay: %d, fill rate: %d, delay/Frame: %d units, buffer size: %d\n", + VBV_delay, bufferFillRate, frameDelayIncrement, buffer_size)); + + result = initGOPRateControl(); + + return result; +} + +/*===========================================================================* + * + * initGOPRateControl + * + * (re)-initialize the RC for the a new Group of Pictures. + * New bit allocation, but carry over complexity measures. + * + * RETURNS: nothing + * + * SIDE EFFECTS: many global variables + * + *===========================================================================*/ +int + initGOPRateControl() +{ + DBG_PRINT(("\tInitializing new GOP\n")); + + Nx = GOP_X; + Ni = GOP_I; + Np = GOP_P; + Nb = GOP_B; + + rc_R += rc_G; + + DBG_PRINT(("\tbufsize: %d, bitrate: %d, pictrate: %d, GOP bits: %d\n", + buffer_size, bit_rate, frameRateRounded, rc_R)); + DBG_PRINT(("\tXi: %d, Xp: %d, Xb: %d Nx: %d, Ni: %d, Np: %d, Nb: %d\n", + Xi, Xp, Xb, Nx,Ni,Np,Nb)); + DBG_PRINT(("\td0_i: %d, d0_p: %d, d0_b: %d, avg_act: %d, rc_Q: %d, mquant: %d\n", + d0_i, d0_p, d0_b, avg_act, rc_Q, mquant)); + return 1; +} + + +/*===========================================================================* + * + * targetRateControl + * + * Determine the target allocation for given picture type, initiates + * variables for rate control process. + * + * RETURNS: nothing. + * + * SIDE EFFECTS: many global variables + * + *===========================================================================*/ +void +targetRateControl(MpegFrame *frame) +{ + float temp1, minimumBits; + float tempX, tempY, tempZ; + int result; + int frameType; + char *strPtr; + + minimumBits = (bit_rate / (8 * frameRateRounded)); + + /* Check if new GOP */ + if (Nx == 0) { + initGOPRateControl(); + } + + if (MB_cnt < 0) {MB_cnt = determineMBCount();} + + switch (frame->type) { + case TYPE_IFRAME: + frameType = 'I'; + + /* temp1 = ( rc_R / ( 1+ ((Np * Xp) / (Xi * Kp)) + ((Nb*Xb) / (Xi*Kb))))); */ + + tempX = ( (Np * Ki * Xp) / (Xi * Kp) ); + tempY = ( (Nb * Ki * Xb) / (Xi*Kb) ); + tempZ = Ni + tempX + tempY; + temp1 = (rc_R / tempZ); + result = (int) (temp1 > minimumBits ? temp1 : minimumBits); + current_Tx = Ti = result; + lastFrameVirtBuf = d0_i; + break; + + case TYPE_PFRAME: + frameType = 'P'; + tempX = ( (Ni * Kp * Xi) / (Ki * Xp) ); + tempY = ( (Nb * Kp * Xb) / (Kb * Xp) ); + tempZ = Np + tempX + tempY; + temp1 = (rc_R/ tempZ); + result = (int) (temp1 > minimumBits ? temp1 : minimumBits); + current_Tx = Tp = result; + lastFrameVirtBuf = d0_p; + break; + + case TYPE_BFRAME: + frameType = 'B'; + tempX = ( (Ni * Kb * Xi) / (Ki * Xb) ); + tempY = ( (Np * Kb * Xp) / (Kp * Xb) ); + tempZ = Nb + tempX + tempY; + temp1 = (rc_R/ tempZ); + result = (int) (temp1 > minimumBits ? temp1 : minimumBits); + current_Tx = Tb = result; + lastFrameVirtBuf = d0_b; + break; + + default: + frameType = 'X'; + } + + N_act = 1; + rc_Q = lastFrameVirtBuf * 31 / reactionParameter; + mquant = rc_Q * N_act; + Qscale = (mquant > 31 ? 31 : mquant); + Qscale = (Qscale < 1 ? 1 : Qscale); + + /* Print headers for Frame info */ + strPtr = Frame_header1; + DBG_PRINT(("%s\n",strPtr)); + strPtr = Frame_header2; + DBG_PRINT(("%s\n",strPtr)); + strPtr = Frame_header3; + DBG_PRINT(("%s\n",strPtr)); + + /* Print Frame info */ + sprintf(rc_buffer, "%4d %1c %4d %6d %7d %2d %2d %2d %2.2f %6d %4d %3d", + frame->id,frameType,MB_cnt,current_Tx,rc_R,Ni,Np,Nb, N_act, lastFrameVirtBuf, rc_Q, Qscale); + +#ifdef RC_STATS_FILE + fprintf(RC_FILE,"%s\n", rc_buffer); + fflush(RC_FILE); +#endif + DBG_PRINT(("%s\n",rc_buffer)); + + /* Print headers for Macroblock info */ + if (RC_MB_SAMPLE_RATE) { + strPtr = MB_header1; + DBG_PRINT(("%s\n",strPtr)); + strPtr = MB_header2; + DBG_PRINT(("%s\n",strPtr)); + } else { + return; + } + + return; +} + + + +/*===========================================================================* + * + * updateRateControl + * + * Update the statistics kept, after end of frame. Resets + * various global variables + * + * RETURNS: nothing + * + * SIDE EFFECTS: many global variables + * + *===========================================================================*/ +void +updateRateControl(int type) +{ + int totalBits, frameComplexity, pctAllocUsed, pctGOPUsed; + float avgQuant; + char *strPtr; + + totalBits = rc_totalFrameBits; + avgQuant = ((float) rc_totalQuant / (float) rc_numBlocks); + frameComplexity = totalBits * avgQuant; + pctAllocUsed = (totalBits *100 / current_Tx); + rc_R -= totalBits; + pctGOPUsed = (rc_R *100/ rc_G); + + avg_act = (total_act_j / MB_cnt); + + updateVBVBuffer(totalBits); + + switch (type) { + case TYPE_IFRAME: + Ti = current_Tx; + d0_i = currentVirtBuf; + Ni--; + Si = totalBits; + Qi = avgQuant; + Xi = frameComplexity; + break; + case TYPE_PFRAME: + Tp = current_Tx; + d0_p = currentVirtBuf; + Np--; + Sp = totalBits; + Qp = avgQuant; + Xp = frameComplexity; + break; + case TYPE_BFRAME: + Tb = current_Tx; + d0_b = currentVirtBuf; + Nb--; + Sb = totalBits; + Qb = avgQuant; + Xb = frameComplexity; + break; + } + + + /* Print Frame info */ + strPtr = Frame_trailer1; + DBG_PRINT(("%s\n",strPtr)); + strPtr = Frame_trailer2; + DBG_PRINT(("%s\n",strPtr)); + strPtr = Frame_trailer3; + DBG_PRINT(("%s\n",strPtr)); + + sprintf(rc_buffer, "%6d %2.2f %6d %3d %2.2f %7d %3d %7d %3d %6d %6d", + totalBits, avgQuant, frameComplexity, avg_act, N_act, currentVirtBuf, pctAllocUsed, rc_R, pctGOPUsed, VBV_buffer, VBV_delay); +#ifdef RC_STATS_FILE + fprintf(RC_FILE,"%s\n", rc_buffer); + fflush(RC_FILE); +#endif + DBG_PRINT(("%s\n",rc_buffer)); + + Nx--; + rc_totalMBBits= rc_bitsThisMB= rc_totalFrameBits=rc_totalOverheadBits = 0; + rc_numBlocks = rc_totalQuant = total_act_j = currentVirtBuf = 0; + + DBG_PRINT(("GOP now has %d bits remaining (%3d%%) for %d frames .. , Ni= %d, Np= %d, Nb= %d\n", rc_R, (rc_R*100/rc_G), (Ni+Np+Nb), Ni, Np, Nb)); + +} + + +/*===========================================================================* + * + * MB_RateOut + * + * Prints out sampling of MB rate control data. Every "nth" block + * stats are printed, with "n" controled by global RC_MB_SAMPLE_RATE + * (NB. "skipped" blocks do not go through this function and thus do not + * show up in the sample ) + * + * RETURNS: nothing + * + * SIDE EFFECTS: none + * + * NOTES: + * + *===========================================================================*/ +void +MB_RateOut(int type) +{ + int totalBits; + int pctUsed, pctDone; + int bitsThisMB; + int bitsPerMB; + + bitsThisMB = rc_bitsThisMB; + totalBits = rc_totalFrameBits; + bitsPerMB = (totalBits / rc_numBlocks); + pctDone = (rc_numBlocks * 100/ MB_cnt); + pctUsed = (totalBits *100/current_Tx); + + sprintf(rc_buffer, "%3d %5d %2d %3d %6d %3d %6d %2.2f %6d %4d %3d %3d\n", + (rc_numBlocks - 1), bitsThisMB, Qscale, mquant, currentVirtBuf, + rc_Q, act_j, N_act, totalBits, bitsPerMB, pctUsed, pctDone); +#ifdef RC_STATS_FILE + fprintf(RC_FILE, "%s", rc_buffer); + fflush(RC_FILE); +#endif + + if ( (RC_MB_SAMPLE_RATE) && ((rc_numBlocks -1) % RC_MB_SAMPLE_RATE)) { + DBG_PRINT(("%s\n", rc_buffer)); + } else { + return; + } +} + + + +/*===========================================================================* + * + * incNumBlocks() + * + * + * RETURNS: nothing + * + * SIDE EFFECTS: rc_numBlocks + * + * NOTES: + * + *===========================================================================*/ +void incNumBlocks(int num) +{ + rc_numBlocks += num; +} + + +/*===========================================================================* + * + * incMacroBlockBits() + * + * Increments the number of Macro Block bits and the total of Frame + * bits by the number passed. + * + * RETURNS: nothing + * + * SIDE EFFECTS: rc_totalMBBits + * + * NOTES: + * + *===========================================================================*/ +void incMacroBlockBits(int num) +{ + rc_bitsThisMB = num; + rc_totalMBBits += num; + rc_totalFrameBits += num; +} + + +/*===========================================================================* + * + * needQScaleChange(current Q scale, 4 luminance blocks) + * + * + * RETURNS: new Qscale + * + * SIDE EFFECTS: + * + *===========================================================================*/ +int needQScaleChange(int oldQScale, + Block blk0, + Block blk1, + Block blk2, + Block blk3) +{ + + /* One more MacroBlock seen */ + rc_numBlocks++; /* this notes each block num in MB */ + + checkBufferFullness(oldQScale); + + checkSpatialActivity(blk0, blk1, blk2, blk3); + + mquant = rc_Q * N_act; + Qscale = (mquant > 31 ? 31 : mquant); + Qscale = (Qscale < 1 ? 1 : Qscale); + rc_totalQuant += Qscale; + + if (oldQScale == Qscale) + return -1; + else + return Qscale; +} + + +/*===========================================================================* + * + * determineMBCount() + * + * Determines number of Macro Blocks in frame from the frame sizes + * passed. + * + * RETURNS: nothing + * + * SIDE EFFECTS: sets the count passed + * + *===========================================================================*/ +int + determineMBCount () +{ + int y,x; + + x = (Fsize_x +15)/16; + y = (Fsize_y +15)/16; + return (x * y); +} + + + +/*===========================================================================* + * + * void checkBufferFullness () + * + * Calculates the fullness of the virtual buffer for each + * frame type. Called before encoding each macro block. Along + * with the normalisec spatial activity measure (N_act), it + * determine the quantization factor for the next macroblock. + * + * RETURNS: nothing + * + * SIDE EFFECTS: the "currentVirtBuf" variable + * + * NOTES: + * + *===========================================================================*/ +void checkBufferFullness (int oldQScale) +{ + int temp; + + temp = lastFrameVirtBuf + rc_totalFrameBits; + temp -= (current_Tx * rc_numBlocks / MB_cnt); + currentVirtBuf = temp; + + rc_Q = (currentVirtBuf * 31 / reactionParameter); + return; +} + + +/*===========================================================================* + * + * void checkSpatialActivity() + * + * Calcualtes the spatial activity for the four luminance blocks of the + * macroblock. Along with the normalised reference quantization parameter + * (rc_Q) , it determines the quantization factor for the next macroblock. + * + * RETURNS: nothing + * + * SIDE EFFECTS: the Adaptive quantization variables- act_j, N_act. + * + * NOTES: + * + *===========================================================================*/ +void checkSpatialActivity(Block blk0, + Block blk1, + Block blk2, + Block blk3) +{ + int temp; + int16 *blkArray[4]; + int16 *curBlock; + int16 *blk_ptr; + int var[4]; + int i, j; + + + blkArray[0] = (int16 *) blk0; + blkArray[1] = (int16 *) blk1; + blkArray[2] = (int16 *) blk2; + blkArray[3] = (int16 *) blk3; + + + for (i =0; i < 4; i++) { /* Compute the activity in each block */ + curBlock = blkArray[i]; + blk_ptr = curBlock; + P_mean = 0; + /* Find the mean pixel value */ + for (j=0; j < DCTSIZE_SQ; j ++) { + P_mean += *(blk_ptr++); + /* P_mean += curBlock[j]; + if (curBlock[j] != *(blk_ptr++)) { + printf("\n\tARRAY ERROR: block %d\n", j); + } + */ + } + P_mean /= DCTSIZE_SQ; + + /* Now find the variance */ + curBlock = blkArray[i]; + blk_ptr = curBlock; + var[i] = 0; + for (j=0; j < DCTSIZE_SQ; j++) { +#ifdef notdef + if (curBlock[j] != *(blk_ptr++)) { + printf("\n\tARRAY ERROR: block %d\n", j); + } + temp = curBlock[j] - P_mean; +#endif + temp = *(blk_ptr++) - P_mean; + var[i] += (temp * temp); + } + var[i] /= DCTSIZE_SQ; + } + + /* Choose the minimum variance from the 4 blocks and use as the activity */ + var_sblk = var[0]; + for (i=1; i < 4; i++) { + var_sblk = (var_sblk < var[i] ? var_sblk : var[i]); + } + + + act_j = 1 + var_sblk; + total_act_j += act_j; + temp = (2 * act_j + avg_act); + N_act = ( (float) temp / (float) (act_j + 2*avg_act) ); + + return; +} + + + + +/*============================================================================* + * + * getRateMode () + * + * Returns the rate mode- interpreted as either Fixed or Variable + * + * RETURNS: integer + * + * SIDE EFFECTS: none + * + * + *==========================================================================*/ +int getRateMode() +{ + return RateControlMode; +} + + +/*===========================================================================* + * + * setBitRate () + * + * Checks the string parsed from the parameter file. Verifies + * number and sets global values. MPEG standard specifies that bit rate + * be rounded up to nearest 400 bits/sec. + * + * RETURNS: nothing + * + * SIDE EFFECTS: global variables + * + * NOTES: Should this be in the 400-bit units used in sequence header? + * + *===========================================================================*/ +void setBitRate (char * charPtr) +{ + int rate, rnd; + + rate = atoi(charPtr); + if (rate > 0) { + RateControlMode = FIXED_RATE; + } else { + printf("Parameter File Error: invalid BIT_RATE: \"%s\", defaults to Variable ratemode\n", + charPtr); + RateControlMode = VARIABLE_RATE; + bit_rate = -1; + } + rnd = (rate % 400); + rate += (rnd ? 400 -rnd : 0); /* round UP to nearest 400 bps */ + rate = (rate > MAX_BIT_RATE ? MAX_BIT_RATE : rate); + bit_rate = rate; + DBG_PRINT(("Bit rate is: %d\n", bit_rate)); +} + + + +/*===========================================================================* + * + * getBitRate () + * + * Returns the bit rate read from the parameter file. This is the + * real rate in bits per second, not in 400 bit units as is written to + * the sequence header. + * + * RETURNS: int (-1 if Variable mode operation) + * + * SIDE EFFECTS: none + * + *===========================================================================*/ +int getBitRate () +{ + return bit_rate; +} + + + + +/*===========================================================================* + * + * setBufferSize () + * + * Checks the string parsed from the parameter file. Verifies + * number and sets global values. + * + * RETURNS: nothing + * + * SIDE EFFECTS: buffer_size global variable. + * + * NOTES: The global is in bits, NOT the 16kb units used in sequence header + * + *===========================================================================*/ +void setBufferSize (char * charPtr) +{ + int size; + + size = atoi(charPtr); + size = (size > MAX_BUFFER_SIZE ? MAX_BUFFER_SIZE : size); + if (size > 0) { + size = (16*1024) * ((size + (16*1024 - 1)) / (16*1024)); + buffer_size = size; + } else { + buffer_size = DEFAULT_BUFFER_SIZE; + printf("Parameter File Error: invalid BUFFER_SIZE: \"%s\", defaults to : %d\n", + charPtr, buffer_size); + } + DBG_PRINT(("Buffer size is: %d\n", buffer_size)); +} + + +/*===========================================================================* + * + * getBufferSize () + * + * returns the buffer size read from the parameter file. Size is + * in bits- not in units of 16k as written to the sequence header. + * + * RETURNS: int (or -1 if invalid) + * + * SIDE EFFECTS: none + * + *===========================================================================*/ +int getBufferSize () +{ + return buffer_size; +} + + +/*===========================================================================* + * + * updateVBVBuffer () + * + * Update the VBV buffer after each frame. This theoretical + * buffer is being filled at constant rate, given by the bit rate. + * It is emptied as each frame is grabbed by the decoder. Exception + * is that the deocder will wait until the "delay" is over. + * + * RETURNS: nothing + * + * SIDE EFFECTS: VBV_buffer + * + * NOTES: + * + *===========================================================================*/ +void updateVBVBuffer (int frameBits) +{ + if (VBV_delay) { + VBV_delay -= frameDelayIncrement; + if (VBV_delay < 0) { + VBV_delay = 0; + } + + } else { + VBV_buffer -= frameBits; + } + VBV_buffer += bufferFillRate; + if (VBV_buffer < 0) { + fprintf(stderr, "\tWARNING - VBV buffer underflow (%d)\n", VBV_buffer); + } + if (VBV_buffer > buffer_size) { + fprintf(stderr, "WARNING - VBV buffer overflow (%d > %d)\n", + VBV_buffer, buffer_size); + } +} diff --git a/contrib/mpeg_encode/readframe.cpp b/contrib/mpeg_encode/readframe.cpp new file mode 100644 index 0000000000000000000000000000000000000000..de71b9967ffd9214510141314346ae4e7d20ceb5 --- /dev/null +++ b/contrib/mpeg_encode/readframe.cpp @@ -0,0 +1,1138 @@ +/*===========================================================================* + * readframe.c * + * * + * procedures to read in frames * + * * + * EXPORTED PROCEDURES: * + * ReadFrame * + * SetFileType * + * SetFileFormat * + * * + *===========================================================================*/ + +/* + * Copyright (c) 1995 The Regents of the University of California. + * All rights reserved. + * + * Permission to use, copy, modify, and distribute this software and its + * documentation for any purpose, without fee, and without written agreement is + * hereby granted, provided that the above copyright notice and the following + * two paragraphs appear in all copies of this software. + * + * IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR + * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT + * OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF + * CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS + * ON AN "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO + * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. + */ + +/* + * $Header: /n/picasso/project/mpeg/mpeg_dist/mpeg_encode/RCS/readframe.c,v 1.27 1995/08/14 22:31:40 smoot Exp $ + * $Log: readframe.c,v $ + * Revision 1.27 1995/08/14 22:31:40 smoot + * reads training info from PPms now (needed for piping reads) + * + * Revision 1.26 1995/08/07 21:48:36 smoot + * better error reporting, JPG == JPEG now + * + * Revision 1.25 1995/06/12 20:30:12 smoot + * added popen for OS2 + * + * Revision 1.24 1995/06/08 20:34:36 smoot + * added "b"'s to fopen calls to make MSDOS happy + * + * Revision 1.23 1995/05/03 10:16:01 smoot + * minor compile bug with static f + * + * Revision 1.22 1995/05/02 22:00:12 smoot + * added TUNEing, setting near-black values to black + * + * Revision 1.21 1995/03/27 21:00:01 eyhung + * fixed bug with some long jpeg names + * + * Revision 1.20 1995/02/02 01:05:54 eyhung + * Fixed aAdded error checking for stdin + * + * Revision 1.19 1995/02/01 05:01:12 eyhung + * Removed troubleshooting printf + * + * Revision 1.18 1995/01/31 21:08:16 eyhung + * Improved YUV_FORMAT strings with better algorithm + * + * Revision 1.17 1995/01/27 23:34:09 eyhung + * Removed temporary JPEG files created by JMOVIE input + * + * Revision 1.16 1995/01/27 21:57:43 eyhung + * Added case for reading original JMOVIES + * + * Revision 1.14 1995/01/24 23:47:51 eyhung + * Confusion with Abekas format fixed : all other YUV revisions are wrong + * + * Revision 1.13 1995/01/20 00:02:30 smoot + * added gamma correction + * + * Revision 1.12 1995/01/19 23:09:21 eyhung + * Changed copyrights + * + * Revision 1.11 1995/01/17 22:23:07 aswan + * AbekasYUV chrominance implementation fixed + * + * Revision 1.10 1995/01/17 21:26:25 smoot + * Tore our average on Abekus/Phillips reconstruct + * + * Revision 1.9 1995/01/17 08:22:34 eyhung + * Debugging of ReadAYUV + * + * Revision 1.8 1995/01/16 13:18:24 eyhung + * Interlaced YUV format (e.g. Abekas) support added (slightly buggy) + * + * Revision 1.7 1995/01/16 06:58:23 eyhung + * Added skeleton of ReadAYUV (for Abekas YUV files) + * + * Revision 1.6 1995/01/13 23:22:23 smoot + * Added ReadY, so we can make black&white movies (how artsy!) + * + * Revision 1.5 1994/12/16 00:20:40 smoot + * Now errors out on too small an input file + * + * Revision 1.4 1994/11/12 02:11:59 keving + * nothing + * + * Revision 1.3 1994/03/15 00:27:11 keving + * nothing + * + * Revision 1.2 1993/12/22 19:19:01 keving + * nothing + * + * Revision 1.1 1993/07/22 22:23:43 keving + * nothing + * + */ + + +/*==============* + * HEADER FILES * + *==============*/ + +#include "all.h" +#include <time.h> +#include <errno.h> +#include <ctype.h> +#include <string.h> +#include <unistd.h> +#include "mtypes.h" +#include "frames.h" +#include "prototypes.h" +#include "parallel.h" +#include "param.h" +#include "readframe.h" +#include "fsize.h" +#include "rgbtoycc.h" +#include "jpeg.h" +#include "opts.h" + +#define PPM_READ_STATE_MAGIC 0 +#define PPM_READ_STATE_WIDTH 1 +#define PPM_READ_STATE_HEIGHT 2 +#define PPM_READ_STATE_MAXVAL 3 +#define PPM_READ_STATE_DONE 4 + + +/*==================* + * STATIC VARIABLES * + *==================*/ + +static int fileType = BASE_FILE_TYPE; +struct YuvLine { + uint8 data[3072]; + uint8 y[1024]; + int8 cr[1024]; + int8 cb[1024]; +}; + + +/*==================* + * Portability * + *==================*/ +#ifdef __OS2__ + #define popen _popen +#endif + + +/*==================* + * Global VARIABLES * + *==================*/ + +extern boolean GammaCorrection; +extern float GammaValue; +extern int outputWidth,outputHeight; +boolean resizeFrame; +char *CurrFile; + +/*===============================* + * INTERNAL PROCEDURE prototypes * + *===============================*/ + +static char *ScanNextString _ANSI_ARGS_((char *inputLine, char *string)); +static void ReadPNM _ANSI_ARGS_((FILE * fp, MpegFrame * mf)); +static boolean ReadPPM _ANSI_ARGS_((MpegFrame *mf, FILE *fpointer)); +static void ReadEYUV _ANSI_ARGS_((MpegFrame * mf, FILE *fpointer, + int width, int height)); +static void ReadAYUV _ANSI_ARGS_((MpegFrame * mf, FILE *fpointer, + int width, int height)); +static void SeparateLine _ANSI_ARGS_((FILE *fpointer, struct YuvLine *lineptr, + int width)); +static void ReadY _ANSI_ARGS_((MpegFrame * mf, FILE *fpointer, + int width, int height)); +static void ReadSub4 _ANSI_ARGS_((MpegFrame * mf, FILE *fpointer, + int width, int height)); +static void DoGamma _ANSI_ARGS_((MpegFrame *mf, int width, int height)); + +static void DoKillDim _ANSI_ARGS_((MpegFrame *mf, int w, int h)); + +#define safe_fread(ptr,sz,len,fileptr) \ + if ((safe_read_count=fread(ptr,sz,len,fileptr))!=sz*len) { \ + throw "Input file too small! (%s)"; \ + } \ + +/*=====================* + * EXPORTED PROCEDURES * + *=====================*/ + + + +void SetResize( boolean set) +{ + resizeFrame = set; +} + + + +/*===========================================================================* + * + * ReadFrame + * + * reads the given frame, performing conversion as necessary + * if addPath = TRUE, then must add the current path before the + * file name + * + * RETURNS: frame modified + * + * SIDE EFFECTS: none + * + *===========================================================================*/ +void +ReadFrame(MpegFrame *frame, + char *fileName, + char *conversion, + boolean addPath) +{ + FILE *ifp; + char command[1024]; + char fullFileName[1024]; + MpegFrame tempFrame; + MpegFrame *framePtr; +#ifdef BLEAH + static int32 readDiskTime = 0; + int32 diskStartTime, diskEndTime; + +time(&diskStartTime); +#endif + + if ( resizeFrame ) { + tempFrame.inUse = FALSE; + tempFrame.ppm_data = NULL; + tempFrame.rgb_data = NULL; + tempFrame.orig_y = NULL; + tempFrame.y_blocks = NULL; + tempFrame.decoded_y = NULL; + tempFrame.halfX = NULL; + framePtr = &tempFrame; + } else { + framePtr = frame; + } + + if ( addPath ) { + sprintf(fullFileName, "%s/%s", currentPath, fileName); + } else { + sprintf(fullFileName, "%s", fileName); + } + + CurrFile = fullFileName; + +#ifdef BLEAH + if ( ! childProcess ) { + fprintf(stdout, "+++++READING Frame %d (type %d): %s\n", framePtr->id, + framePtr->type, fullFileName); + } +#endif + + if ( fileType == ANY_FILE_TYPE ) { + char *convertPtr, *commandPtr, *charPtr; + + if ( stdinUsed ) { + throw "cannot use stdin with INPUT_CONVERT"; + } + + /* replace every occurrence of '*' with fullFileName */ + convertPtr = conversion; + commandPtr = command; + while ( *convertPtr != '\0' ) { + while ( (*convertPtr != '\0') && (*convertPtr != '*') ) { + *commandPtr = *convertPtr; + commandPtr++; + convertPtr++; + } + + if ( *convertPtr == '*' ) { + /* copy fullFileName */ + charPtr = fullFileName; + while ( *charPtr != '\0' ) { + *commandPtr = *charPtr; + commandPtr++; + charPtr++; + } + + convertPtr++; /* go past '*' */ + } + } + *commandPtr = '\0'; + + if ( (ifp = popen(command, "r")) == NULL ) { + fprintf(stderr, "ERROR: Couldn't execute input conversion command:\n"); + fprintf(stderr, "\t%s\n", command); + fprintf(stderr, "errno = %d\n", errno); + if ( ioServer ) { + throw "IO SERVER: EXITING!"; + } else { + throw "SLAVE EXITING!"; + } + } + } else if (stdinUsed) { + ifp = stdin; + } else if ( (ifp = fopen(fullFileName, "rb")) == NULL ) { + throw "Couldn't open input file"; + } + + switch(baseFormat) { + case YUV_FILE_TYPE: + + /* Encoder YUV */ + if ((strncmp (yuvConversion, "EYUV", 4) == 0) || + (strncmp (yuvConversion, "UCB", 3) == 0) ) + { + ReadEYUV(framePtr, ifp, realWidth, realHeight); + } + + /* Abekas-type (interlaced) YUV */ + else { + ReadAYUV(framePtr, ifp, realWidth, realHeight); + } + + break; + case Y_FILE_TYPE: + ReadY(framePtr, ifp, realWidth, realHeight); + break; + case PPM_FILE_TYPE: + if ( ! ReadPPM(framePtr, ifp) ) { + throw "Error reading PPM input file!"; + } + PPMtoYUV(framePtr); + break; + case PNM_FILE_TYPE: + ReadPNM(ifp, framePtr); + PNMtoYUV(framePtr); + break; + case SUB4_FILE_TYPE: + ReadSub4(framePtr, ifp, yuvWidth, yuvHeight); + break; + case JPEG_FILE_TYPE: + case JMOVIE_FILE_TYPE: + ReadJPEG(framePtr, ifp); + break; + default: + break; + } + + if (! stdinUsed) { + if ( fileType == ANY_FILE_TYPE ) { + int errorcode; + if ( (errorcode = pclose(ifp)) != 0) { + fprintf(stderr, "WARNING: Pclose reported error (%d)\n", errorcode); + } + } else { + fclose(ifp); + } + } + + if ( baseFormat == JMOVIE_FILE_TYPE ) { + remove(fullFileName); + } + + if ( resizeFrame ) { + Frame_Resize(frame, &tempFrame, Fsize_x, Fsize_y, outputWidth, outputHeight); + } + +#ifdef BLEAH +time(&diskEndTime); + +readDiskTime += (diskEndTime-diskStartTime); + +fprintf(stdout, "cumulative disk read time: %d seconds\n", readDiskTime); +#endif + + if ( GammaCorrection ) { + DoGamma(frame, Fsize_x, Fsize_y); + } + + if ( kill_dim ) { + DoKillDim(frame, Fsize_x, Fsize_y); + } + + MotionSearchPreComputation(frame); +} + + +/*===========================================================================* + * + * SetFileType + * + * set the file type to be either a base type (no conversion), or + * any type (conversion required) + * + * RETURNS: nothing + * + * SIDE EFFECTS: fileType + * + *===========================================================================*/ +void +SetFileType(char *conversion) +{ + if ( strcmp(conversion, "*") == 0 ) { + fileType = BASE_FILE_TYPE; + } else { + fileType = ANY_FILE_TYPE; + } +} + + +/*===========================================================================* + * + * SetFileFormat + * + * set the file format (PPM, PNM, YUV, JPEG) + * + * RETURNS: nothing + * + * SIDE EFFECTS: baseFormat + * + *===========================================================================*/ +void +SetFileFormat(char *format) +{ + if ( strcmp(format, "PPM") == 0 ) { + baseFormat = PPM_FILE_TYPE; + } else if ( strcmp(format, "YUV") == 0 ) { + baseFormat = YUV_FILE_TYPE; + } else if ( strcmp(format, "Y") == 0 ) { + baseFormat = Y_FILE_TYPE; + } else if ( strcmp(format, "PNM") == 0 ) { + baseFormat = PNM_FILE_TYPE; + } else if (( strcmp(format, "JPEG") == 0 ) || ( strcmp(format, "JPG") == 0 )) { + baseFormat = JPEG_FILE_TYPE; + } else if ( strcmp(format, "JMOVIE") == 0 ) { + baseFormat = JMOVIE_FILE_TYPE; + } else if ( strcmp(format, "SUB4") == 0 ) { + baseFormat = SUB4_FILE_TYPE; + } else { + throw "Invalid file format"; + } +} + + +/*===========================================================================* + * + * ReadPNM + * + * read a PNM file + * + * RETURNS: mf modified + * + * SIDE EFFECTS: none + * + *===========================================================================*/ +static void +ReadPNM(FILE *fp, + MpegFrame *mf) +{ + int x, y; + xelval maxval; + int format; + + if (mf->rgb_data) { + pnm_freearray(mf->rgb_data, Fsize_y); + } + mf->rgb_data = pnm_readpnm(fp, &x, &y, &maxval, &format); + ERRCHK(mf, "pnm_readpnm"); + + if (format != PPM_FORMAT) { + if (maxval < 255) { + pnm_promoteformat(mf->rgb_data, x, y, maxval, format, 255, PPM_FORMAT); + maxval = 255; + } else { + pnm_promoteformat(mf->rgb_data, x, y, maxval, format, maxval, PPM_FORMAT); + } + } + if (maxval < 255) { + pnm_promoteformat(mf->rgb_data, x, y, maxval, format, 255, format); + maxval = 255; + } + /* + * if this is the first frame read, set the global frame size + */ + Fsize_Note(mf->id, x, y); + + mf->rgb_maxval = maxval; + mf->rgb_format = PPM_FORMAT; +} + + + +/*===========================================================================* + * + * ReadIOConvert + * + * do conversion; return a pointer to the appropriate file + * + * RETURNS: pointer to the appropriate file + * + * SIDE EFFECTS: none + * + *===========================================================================*/ +FILE * +ReadIOConvert(char *fileName) +{ + FILE *ifp; + char command[1024]; + char fullFileName[1024]; + char *convertPtr, *commandPtr, *charPtr; + + sprintf(fullFileName, "%s/%s", currentPath, fileName); + +#ifdef BLEAH + if ( ! childProcess ) { + fprintf(stdout, "+++++READING (IO CONVERT) Frame %d (type %d): %s\n", frame->id, + frame->type, fullFileName); } +#endif + + if ( strcmp(ioConversion, "*") == 0 ) { + char buff[1024]; + ifp = fopen(fullFileName, "rb"); + sprintf(buff,"fopen \"%s\"",fullFileName); + ERRCHK(ifp, buff); + return ifp; + } + + /* replace every occurrence of '*' with fullFileName */ + convertPtr = ioConversion; + commandPtr = command; + while ( *convertPtr != '\0' ) { + while ( (*convertPtr != '\0') && (*convertPtr != '*') ) { + *commandPtr = *convertPtr; + commandPtr++; + convertPtr++; + } + + if ( *convertPtr == '*' ) { + /* copy fullFileName */ + charPtr = fullFileName; + while ( *charPtr != '\0' ) { + *commandPtr = *charPtr; + commandPtr++; + charPtr++; + } + + convertPtr++; /* go past '*' */ + } + } + *commandPtr = '\0'; + + if ( (ifp = popen(command, "r")) == NULL ) { + fprintf(stderr, "ERROR: Couldn't execute input conversion command:\n"); + fprintf(stderr, "\t%s\n", command); + fprintf(stderr, "errno = %d\n", errno); + if ( ioServer ) { + throw "IO SERVER: EXITING!"; + } else { + throw "SLAVE EXITING!"; + } + } + + return ifp; +} + + + +/*===========================================================================* + * + * ReadPPM + * + * read a PPM file + * + * RETURNS: TRUE if successful; FALSE otherwise; mf modified + * + * SIDE EFFECTS: none + * + *===========================================================================*/ +static boolean +ReadPPM(MpegFrame *mf, + FILE *fpointer) +{ + char inputBuffer[71]; + char string[71]; + char *inputLine; + int height = 0, width = 0, maxVal=255; + uint8 junk[4096]; + register int y; + int state; + int safe_read_count; + + state = PPM_READ_STATE_MAGIC; + + while ( state != PPM_READ_STATE_DONE ) { + if ( fgets(inputBuffer, 71, fpointer) == NULL ) { + return FALSE; + } + + inputLine = inputBuffer; + + if ( inputLine[0] == '#' ) { + continue; + } + + if ( inputLine[strlen(inputLine)-1] != '\n' ) { + return FALSE; + } + + switch(state) { + case PPM_READ_STATE_MAGIC: + if ( (inputLine = ScanNextString(inputLine, string)) == NULL ) { + return FALSE; + } + + if ( strcmp(string, "P6") != 0 ) { + return FALSE; + } + state = PPM_READ_STATE_WIDTH; + /* no break */ + case PPM_READ_STATE_WIDTH: + if ( (inputLine = ScanNextString(inputLine, string)) == NULL ) { + if ( inputLine == inputBuffer ) { + return FALSE; + } else { + break; + } + } + + width = atoi(string); + + state = PPM_READ_STATE_HEIGHT; + + /* no break */ + case PPM_READ_STATE_HEIGHT: + if ( (inputLine = ScanNextString(inputLine, string)) == NULL ) { + if ( inputLine == inputBuffer ) { + return FALSE; + } else { + break; + } + } + + height = atoi(string); + + state = PPM_READ_STATE_MAXVAL; + + /* no break */ + case PPM_READ_STATE_MAXVAL: + if ( (inputLine = ScanNextString(inputLine, string)) == NULL ) { + if ( inputLine == inputBuffer ) { + return FALSE; + } else { + break; + } + } + + maxVal = atoi(string); + + state = PPM_READ_STATE_DONE; + break; + } /* end of switch */ + } + + Fsize_Note(mf->id, width, height); + + mf->rgb_maxval = maxVal; + + Frame_AllocPPM(mf); + + for ( y = 0; y < Fsize_y; y++ ) { + safe_fread(mf->ppm_data[y], sizeof(char), 3*Fsize_x, fpointer); + + /* read the leftover stuff on the right side */ + safe_fread(junk, sizeof(char), 3*(width-Fsize_x), fpointer); + } + + /* read the leftover stuff to prevent broken pipe */ + for ( y=Fsize_y; y<height; ++y ) { + safe_fread(junk, sizeof(char), 3*Fsize_x, fpointer); + } + return TRUE; +} + + +/*===========================================================================* + * + * ReadEYUV + * + * read a Encoder-YUV file (concatenated Y, U, and V) + * + * RETURNS: mf modified + * + * SIDE EFFECTS: none + * + *===========================================================================*/ +static void +ReadEYUV(MpegFrame *mf, + FILE *fpointer, + int width, + int height) +{ + register int y; + uint8 junk[4096]; + int safe_read_count; + + Fsize_Note(mf->id, width, height); + + Frame_AllocYCC(mf); + + for (y = 0; y < Fsize_y; y++) { /* Y */ + safe_fread(mf->orig_y[y], 1, Fsize_x, fpointer); + + /* read the leftover stuff on the right side */ + if ( width != Fsize_x ) { + safe_fread(junk, 1, width-Fsize_x, fpointer); + } + } + + /* read the leftover stuff on the bottom */ + for (y = Fsize_y; y < height; y++) { + safe_fread(junk, 1, width, fpointer); + } + + for (y = 0; y < (Fsize_y >> 1); y++) { /* U */ + safe_fread(mf->orig_cb[y], 1, Fsize_x >> 1, fpointer); + + /* read the leftover stuff on the right side */ + if ( width != Fsize_x ) { + safe_fread(junk, 1, (width-Fsize_x)>>1, fpointer); + } + } + + /* read the leftover stuff on the bottom */ + for (y = (Fsize_y >> 1); y < (height >> 1); y++) { + safe_fread(junk, 1, width>>1, fpointer); + } + + for (y = 0; y < (Fsize_y >> 1); y++) { /* V */ + safe_fread(mf->orig_cr[y], 1, Fsize_x >> 1, fpointer); + + /* read the leftover stuff on the right side */ + if ( width != Fsize_x ) { + safe_fread(junk, 1, (width-Fsize_x)>>1, fpointer); + } + } + + /* ignore leftover stuff on the bottom */ +} + +/*===========================================================================* + * + * ReadAYUV + * + * read an Abekas-YUV file + * + * RETURNS: mf modified + * + * SIDE EFFECTS: none + * + *===========================================================================*/ +static void +ReadAYUV(MpegFrame *mf, + FILE *fpointer, + int width, + int height) +{ + register int x, y; + struct YuvLine line1, line2; + uint8 junk[4096]; + int8 *cbptr, *crptr; + int safe_read_count; + + Fsize_Note(mf->id, width, height); + + Frame_AllocYCC(mf); + + for (y = 0; y < Fsize_y; y += 2) { + SeparateLine(fpointer, &line1, width); + SeparateLine(fpointer, &line2, width); + + /* Copy the Y values for each line to the frame */ + for (x = 0; x < Fsize_x; x++) { + mf->orig_y[y][x] = line1.y[x]; + mf->orig_y[y+1][x] = line2.y[x]; + } + + cbptr = (int8*)&(mf->orig_cb[y>>1][0]); + crptr = (int8*)&(mf->orig_cr[y>>1][0]); + + /* One U and one V for each two pixels horizontal as well */ + /* Toss the second line of Cr/Cb info, averaging was worse, + so just subsample */ + for (x = 0; x < (Fsize_x >> 1); x ++) { + cbptr[x] = line1.cb[x]; + crptr[x] = line1.cr[x]; + + } + } + + /* read the leftover stuff on the bottom */ + for (y = Fsize_y; y < height; y++) { + safe_fread(junk, 1, width<<1, fpointer); + } + +} + +/*===========================================================================* + * + * SeparateLine + * + * Separates one line of pixels into Y, U, and V components + * + * RETURNS: lineptr modified + * + * SIDE EFFECTS: none + * + *===========================================================================*/ +static void +SeparateLine(FILE *fpointer, + struct YuvLine *lineptr, + int width) +{ + uint8 junk[4096]; + int8 *crptr, *cbptr; + uint8 *yptr; + int num, length; + int safe_read_count; + + + /* Sets the deinterlacing pattern */ + + /* shorthand for UYVY */ + if (strncmp(yuvConversion, "ABEKAS", 6) == 0) { + strcpy(yuvConversion, "UYVY"); + + /* shorthand for YUYV */ + } else if (strncmp(yuvConversion, "PHILLIPS", 8) == 0) { + strcpy(yuvConversion, "YUYV"); + } + + length = strlen (yuvConversion); + + if ((length % 2) != 0) { + throw "YUV_FORMAT must represent two pixels, hence must be even in length"; + } + + /* each line in 4:2:2 chroma format takes 2X bytes to represent X pixels. + * each line in 4:4:4 chroma format takes 3X bytes to represent X pixels. + * Therefore, half of the length of the YUV_FORMAT represents 1 pixel. + */ + safe_fread(lineptr->data, 1, Fsize_x*(length>>1), fpointer); + + /* read the leftover stuff on the right side */ + if ( width != Fsize_x ) { + safe_fread(junk, 1, (width-Fsize_x)*(length>>1), fpointer); + } + + crptr = &(lineptr->cr[0]); + cbptr = &(lineptr->cb[0]); + yptr = &(lineptr->y[0]); + + for (num = 0; num < (Fsize_x*(length>>1)); num++) { + switch (yuvConversion[num % length]) { + case 'U': + case 'u': + *(cbptr++) = (lineptr->data[num]); + break; + case 'V': + case 'v': + *(crptr++) = (lineptr->data[num]); + break; + case 'Y': + case 'y': + *(yptr++) = (lineptr->data[num]); + break; + default: + throw "bad YUV_FORMAT"; + } + + } + +} + + +/*===========================================================================* + * + * ReadY + * + * read a Y file + * + * RETURNS: mf modified + * + * SIDE EFFECTS: none + * + *===========================================================================*/ +static void +ReadY(MpegFrame *mf, + FILE *fpointer, + int width, + int height) +{ + register int y; + uint8 junk[4096]; + int safe_read_count; + + Fsize_Note(mf->id, width, height); + + Frame_AllocYCC(mf); + + for (y = 0; y < Fsize_y; y++) { /* Y */ + safe_fread(mf->orig_y[y], 1, Fsize_x, fpointer); + + /* read the leftover stuff on the right side */ + if ( width != Fsize_x ) { + safe_fread(junk, 1, width-Fsize_x, fpointer); + } + } + + /* read the leftover stuff on the bottom */ + for (y = Fsize_y; y < height; y++) { + safe_fread(junk, 1, width, fpointer); + } + + for (y = 0 ; y < (Fsize_y >> 1); y++) { + memset(mf->orig_cb[y], 128, (Fsize_x>>1)); + memset(mf->orig_cr[y], 128, (Fsize_x>>1)); + } +} + + +/*===========================================================================* + * + * ReadSub4 + * + * read a YUV file (subsampled even further by 4:1 ratio) + * + * RETURNS: mf modified + * + * SIDE EFFECTS: none + * + *===========================================================================*/ +static void +ReadSub4(MpegFrame *mf, + FILE *fpointer, + int width, + int height) +{ + register int y; + register int x; + uint8 buffer[1024]; + int safe_read_count; + + Fsize_Note(mf->id, width, height); + + Frame_AllocYCC(mf); + + for (y = 0; y < (height>>1); y++) { /* Y */ + safe_fread(buffer, 1, width>>1, fpointer); + for ( x = 0; x < (width>>1); x++ ) { + mf->orig_y[2*y][2*x] = buffer[x]; + mf->orig_y[2*y][2*x+1] = buffer[x]; + mf->orig_y[2*y+1][2*x] = buffer[x]; + mf->orig_y[2*y+1][2*x+1] = buffer[x]; + } + } + + for (y = 0; y < (height >> 2); y++) { /* U */ + safe_fread(buffer, 1, width>>2, fpointer); + for ( x = 0; x < (width>>2); x++ ) { + mf->orig_cb[2*y][2*x] = buffer[x]; + mf->orig_cb[2*y][2*x+1] = buffer[x]; + mf->orig_cb[2*y+1][2*x] = buffer[x]; + mf->orig_cb[2*y+1][2*x+1] = buffer[x]; + } + } + + for (y = 0; y < (height >> 2); y++) { /* V */ + safe_fread(buffer, 1, width>>2, fpointer); + for ( x = 0; x < (width>>2); x++ ) { + mf->orig_cr[2*y][2*x] = buffer[x]; + mf->orig_cr[2*y][2*x+1] = buffer[x]; + mf->orig_cr[2*y+1][2*x] = buffer[x]; + mf->orig_cr[2*y+1][2*x+1] = buffer[x]; + } + } +} + + +/*=====================* + * INTERNAL PROCEDURES * + *=====================*/ + +/*===========================================================================* + * + * ScanNextString + * + * read a string from a input line, ignoring whitespace + * + * RETURNS: pointer to position in input line after string + * NULL if all whitespace + * puts string in 'string' + * + * SIDE EFFECTS: file stream munched a bit + * + *===========================================================================*/ +static char * +ScanNextString(char *inputLine, + char *string) +{ + /* skip whitespace */ + while ( isspace(*inputLine) && (*inputLine != '\n') ) { + inputLine++; + } + + if ( *inputLine == '\n' ) { + return NULL; + } + + while ( (! isspace(*inputLine)) && (*inputLine != '\n') ) { + *string = *inputLine; + string++; + inputLine++; + } + + *string = '\0'; + + return inputLine; +} + +/*===========================================================================* + * + * DoGamma + * + * Gamma Correct the Lum values + * + * RETURNS: nothing + * + * SIDE EFFECTS: Raises Y values to power gamma. + * + *===========================================================================*/ +static void +DoGamma(MpegFrame *mf, + int w, int h) +{ + static int GammaVal[256]; + static boolean init_done=FALSE; + int i,j; + + if (!init_done) { + for(i=0; i<256; i++) + GammaVal[i]=(unsigned char) (pow(((double) i)/255.0,GammaValue)*255.0+0.5); + init_done=TRUE; + } + + for (i=0; i< h; i++) { /* For each line */ + for (j=0; j<w; j++) { /* For each Y value */ + mf->orig_y[i][j] = GammaVal[mf->orig_y[i][j]]; + }} +} + + + + +/*===========================================================================* + * + * DoKillDim + * + * Applies an input filter to small Y values. + * + * RETURNS: nothing + * + * SIDE EFFECTS: Changes Y values: + * + * Output | / + | / + | / + | ! + | / + | ! + | / + | - + | / + | -- + | / + | -- + | / + ------------------------ + ^ kill_dim_break + ^kill_dim_end + kill_dim_slope gives the slope (y = kill_dim_slope * x +0) + from 0 to kill_dim_break + * + *===========================================================================*/ + +static void +DoKillDim(MpegFrame *mf, + int w, int h) +{ + static boolean init_done=FALSE; + static unsigned char mapper[256]; + register int i,j; + double slope, intercept; + + slope = (kill_dim_end - kill_dim_break*kill_dim_slope)*1.0 / + (kill_dim_end - kill_dim_break); + intercept = kill_dim_end * (1.0-slope); + + if (!init_done) { + for(i=0; i<256; i++) { + if (i >= kill_dim_end) { + mapper[i] = (char) i; + } else if (i >= kill_dim_break) { + mapper[i] = (char) (slope*i + intercept); + } else { /* i <= kill_dim_break */ + mapper[i] = (char) floor(i*kill_dim_slope + 0.49999); + } + } + init_done = TRUE; + } + + for (i=0; i < h; i++) { /* For each line */ + for (j=0; j < w; j++) { /* For each Y value */ + mf->orig_y[i][j] = mapper[mf->orig_y[i][j]]; + }} +} diff --git a/contrib/mpeg_encode/rgbtoycc.cpp b/contrib/mpeg_encode/rgbtoycc.cpp new file mode 100644 index 0000000000000000000000000000000000000000..62e61f707e1893890771f6323fb142551af2f379 --- /dev/null +++ b/contrib/mpeg_encode/rgbtoycc.cpp @@ -0,0 +1,348 @@ +/*===========================================================================* + * rgbtoycc.c * + * * + * Procedures to convert from RGB space to YUV space * + * * + * EXPORTED PROCEDURES: * + * PNMtoYUV * + * PPMtoYUV * + * * + *===========================================================================*/ + +/* + * Copyright (c) 1995 The Regents of the University of California. + * All rights reserved. + * + * Permission to use, copy, modify, and distribute this software and its + * documentation for any purpose, without fee, and without written agreement is + * hereby granted, provided that the above copyright notice and the following + * two paragraphs appear in all copies of this software. + * + * IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR + * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT + * OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF + * CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS + * ON AN "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO + * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. + */ + +/* + * $Header: /n/picasso/project/mpeg/mpeg_dist/mpeg_encode/RCS/rgbtoycc.c,v 1.5 1995/08/14 22:32:16 smoot Exp $ + * $Log: rgbtoycc.c,v $ + * Revision 1.5 1995/08/14 22:32:16 smoot + * added better error message + * + * Revision 1.4 1995/01/19 23:09:23 eyhung + * Changed copyrights + * + * Revision 1.3 1994/11/12 02:12:00 keving + * nothing + * + * Revision 1.2 1993/12/22 19:19:01 keving + * nothing + * + * Revision 1.2 1993/12/22 19:19:01 keving + * nothing + * + * Revision 1.1 1993/07/22 22:23:43 keving + * nothing + * + */ + + +/*==============* + * HEADER FILES * + *==============*/ + +#include "all.h" +#include "frame.h" +#include "fsize.h" +#include "rgbtoycc.h" + + +/*=====================* + * EXPORTED PROCEDURES * + *=====================*/ + + +/*===========================================================================* + * + * PNMtoYUV + * + * convert PNM data into YUV data + * + * RETURNS: nothing + * + * SIDE EFFECTS: none + * + *===========================================================================*/ +void +PNMtoYUV(MpegFrame *frame) +{ + register int x, y; + register uint8 *dy0, *dy1; + register uint8 *dcr, *dcb; + register xel *src0, *src1; + register int ydivisor, cdivisor; + static boolean first = TRUE; + static float mult299[1024], mult587[1024], mult114[1024]; + static float mult16874[1024], mult33126[1024], mult5[1024]; + static float mult41869[1024], mult08131[1024]; + + if ( first ) { + register int index; + register int maxValue; + + maxValue = frame->rgb_maxval; + + for ( index = 0; index <= maxValue; index++ ) { + mult299[index] = index*0.29900; + mult587[index] = index*0.58700; + mult114[index] = index*0.11400; + mult16874[index] = -0.16874*index; + mult33126[index] = -0.33126*index; + mult5[index] = index*0.50000; + mult41869[index] = -0.41869*index; + mult08131[index] = -0.08131*index; + } + + first = FALSE; + } + + Frame_AllocYCC(frame); + + /* + * okay. Now, convert everything into YCrCb space. (the specific + * numbers come from the JPEG source, jccolor.c) The conversion + * equations to be implemented are therefore + * + * Y = 0.29900 * R + 0.58700 * G + 0.11400 * B + * Cb = -0.16874 * R - 0.33126 * G + 0.50000 * B + * Cr = 0.50000 * R - 0.41869 * G - 0.08131 * B + */ + +/* ydivisor should be a FLOAT, shouldn't it?!?! */ + + ydivisor = (frame->rgb_maxval + 1) >> 8; /* for normalizing values + * 0-255, divide by 256 */ + cdivisor = (ydivisor << 2); /* because we're averaging 4 pixels */ + + for (y = 0; y < Fsize_y; y += 2) { + for (x = 0, src0 = frame->rgb_data[y], src1 = frame->rgb_data[y + 1], + dy0 = frame->orig_y[y], dy1 = frame->orig_y[y + 1], + dcr = frame->orig_cr[y >> 1], dcb = frame->orig_cb[y >> 1]; + x < Fsize_x; + x += 2, dy0 += 2, dy1 += 2, dcr++, + dcb++, src0 += 2, src1 += 2) { + + *dy0 = (mult299[PPM_GETR(*src0)] + + mult587[PPM_GETG(*src0)] + + mult114[PPM_GETB(*src0)]) / ydivisor; + + *dy1 = (mult299[PPM_GETR(*src1)] + + mult587[PPM_GETG(*src1)] + + mult114[PPM_GETB(*src1)]) / ydivisor; + + dy0[1] = (mult299[PPM_GETR(src0[1])] + + mult587[PPM_GETG(src0[1])] + + mult114[PPM_GETB(src0[1])]) / ydivisor; + + dy1[1] = (mult299[PPM_GETR(src1[1])] + + mult587[PPM_GETG(src1[1])] + + mult114[PPM_GETB(src1[1])]) / ydivisor; + + *dcb = ((mult16874[PPM_GETR(*src0)] + + mult33126[PPM_GETG(*src0)] + + mult5[PPM_GETB(*src0)] + + mult16874[PPM_GETR(*src1)] + + mult33126[PPM_GETG(*src1)] + + mult5[PPM_GETB(*src1)] + + mult16874[PPM_GETR(src0[1])] + + mult33126[PPM_GETG(src0[1])] + + mult5[PPM_GETB(src0[1])] + + mult16874[PPM_GETR(src1[1])] + + mult33126[PPM_GETG(src1[1])] + + mult5[PPM_GETB(src1[1])]) / cdivisor) + 128; + + *dcr = ((mult5[PPM_GETR(*src0)] + + mult41869[PPM_GETG(*src0)] + + mult08131[PPM_GETB(*src0)] + + mult5[PPM_GETR(*src1)] + + mult41869[PPM_GETG(*src1)] + + mult08131[PPM_GETB(*src1)] + + mult5[PPM_GETR(src0[1])] + + mult41869[PPM_GETG(src0[1])] + + mult08131[PPM_GETB(src0[1])] + + mult5[PPM_GETR(src1[1])] + + mult41869[PPM_GETG(src1[1])] + + mult08131[PPM_GETB(src1[1])]) / cdivisor) + 128; + + /* if your floating point is faster than your loads, you + * might consider this: + */ +#ifdef BLEAH + *dy0 = (PPM_GETR(*src0) * 0.29900 + + PPM_GETG(*src0) * 0.58700 + + PPM_GETB(*src0) * 0.11400) / ydivisor; + *dy1 = (PPM_GETR(*src1) * 0.29900 + + PPM_GETG(*src1) * 0.58700 + + PPM_GETB(*src1) * 0.11400) / ydivisor; + + dy0[1] = (PPM_GETR(src0[1]) * 0.29900 + + PPM_GETG(src0[1]) * 0.58700 + + PPM_GETB(src0[1]) * 0.11400) / ydivisor; + + dy1[1] = (PPM_GETR(src1[1]) * 0.29900 + + PPM_GETG(src1[1]) * 0.58700 + + PPM_GETB(src1[1]) * 0.11400) / ydivisor; + + *dcb = ((PPM_GETR(*src0) * -0.16874 + + PPM_GETG(*src0) * -0.33126 + + PPM_GETB(*src0) * 0.50000 + + PPM_GETR(*src1) * -0.16874 + + PPM_GETG(*src1) * -0. + + PPM_GETB(*src1) * 0.50000 + + PPM_GETR(src0[1]) * -0.16874 + + PPM_GETG(src0[1]) * -0.33126 + + PPM_GETB(src0[1]) * 0.50000 + + PPM_GETR(src1[1]) * -0.16874 + + PPM_GETG(src1[1]) * -0.33126 + + PPM_GETB(src1[1]) * 0.50000) / cdivisor) + 128; + + *dcr = ((PPM_GETR(*src0) * 0.50000 + + PPM_GETG(*src0) * -0.41869 + + PPM_GETB(*src0) * -0.08131 + + PPM_GETR(*src1) * 0.50000 + + PPM_GETG(*src1) * -0.41869 + + PPM_GETB(*src1) * -0.08131 + + PPM_GETR(src0[1]) * 0.50000 + + PPM_GETG(src0[1]) * -0.41869 + + PPM_GETB(src0[1]) * -0.08131 + + PPM_GETR(src1[1]) * 0.50000 + + PPM_GETG(src1[1]) * -0.41869 + + PPM_GETB(src1[1]) * -0.08131) / cdivisor) + 128; +#endif + + DBG_PRINT(("%3d,%3d: (%3d,%3d,%3d) --> (%3d,%3d,%3d)\n", x, y, PPM_GETR(*src0), PPM_GETG(*src0), PPM_GETB(*src0), *dy0, *dcb, *dcr)); + } + } +} + + + +/*===========================================================================* + * + * PPMtoYUV + * + * convert PPM data into YUV data + * same as PNMtoYUV, except extracts data from ppm_data, and + * assumes that ydivisor = 1 + * + * RETURNS: nothing + * + * SIDE EFFECTS: none + * + *===========================================================================*/ +void +PPMtoYUV(MpegFrame *frame) +{ + register int x, y; + register uint8 *dy0, *dy1; + register uint8 *dcr, *dcb; + register uint8 *src0, *src1; + register int cdivisor; + static boolean first = TRUE; + static float mult299[1024], mult587[1024], mult114[1024]; + static float mult16874[1024], mult33126[1024], mult5[1024]; + static float mult41869[1024], mult08131[1024]; + + if ( first ) { + register int index; + register int maxValue; + + maxValue = frame->rgb_maxval; + + for ( index = 0; index <= maxValue; index++ ) { + mult299[index] = index*0.29900; + mult587[index] = index*0.58700; + mult114[index] = index*0.11400; + mult16874[index] = -0.16874*index; + mult33126[index] = -0.33126*index; + mult5[index] = index*0.50000; + mult41869[index] = -0.41869*index; + mult08131[index] = -0.08131*index; + } + + first = FALSE; + } + + Frame_AllocYCC(frame); + + /* assume ydivisor = 1, so cdivisor = 4 */ + if ( frame->rgb_maxval != 255 ) { + throw "PPM max gray value != 255. Exiting.\n\tTry PNM type, not PPM"; + } + + cdivisor = 4; + + for (y = 0; y < Fsize_y; y += 2) { + src0 = frame->ppm_data[y]; + src1 = frame->ppm_data[y + 1]; + dy0 = frame->orig_y[y]; + dy1 = frame->orig_y[y + 1]; + dcr = frame->orig_cr[y >> 1]; + dcb = frame->orig_cb[y >> 1]; + + for ( x = 0; x < Fsize_x; x += 2, dy0 += 2, dy1 += 2, dcr++, + dcb++, src0 += 6, src1 += 6) { + *dy0 = (mult299[*src0] + + mult587[src0[1]] + + mult114[src0[2]]); + + *dy1 = (mult299[*src1] + + mult587[src1[1]] + + mult114[src1[2]]); + + dy0[1] = (mult299[src0[3]] + + mult587[src0[4]] + + mult114[src0[5]]); + + dy1[1] = (mult299[src1[3]] + + mult587[src1[4]] + + mult114[src1[5]]); + + *dcb = ((mult16874[*src0] + + mult33126[src0[1]] + + mult5[src0[2]] + + mult16874[*src1] + + mult33126[src1[1]] + + mult5[src1[2]] + + mult16874[src0[3]] + + mult33126[src0[4]] + + mult5[src0[5]] + + mult16874[src1[3]] + + mult33126[src1[4]] + + mult5[src1[5]]) / cdivisor) + 128; + + *dcr = ((mult5[*src0] + + mult41869[src0[1]] + + mult08131[src0[2]] + + mult5[*src1] + + mult41869[src1[1]] + + mult08131[src1[2]] + + mult5[src0[3]] + + mult41869[src0[4]] + + mult08131[src0[5]] + + mult5[src1[3]] + + mult41869[src1[4]] + + mult08131[src1[5]]) / cdivisor) + 128; + + DBG_PRINT(("%3d,%3d: (%3d,%3d,%3d) --> (%3d,%3d,%3d)\n", x, y, PPM_GETR(*src0), PPM_GETG(*src0), PPM_GETB(*src0), *dy0, *dcb, *dcr)); + } + } +} + diff --git a/contrib/mpeg_encode/specifics.cpp b/contrib/mpeg_encode/specifics.cpp new file mode 100644 index 0000000000000000000000000000000000000000..67dddc0fa03f5f3c5723bb676d764b26cdc8b9e6 --- /dev/null +++ b/contrib/mpeg_encode/specifics.cpp @@ -0,0 +1,681 @@ +/*===========================================================================* + * specifics.c * + * * + * basic procedures to deal with the specifics file * + * * + * EXPORTED PROCEDURES: * + * Specifics_Init * + * Spec_Lookup * + * SpecTypeLookup * + * * + *===========================================================================*/ + +/* + * Copyright (c) 1995 The Regents of the University of California. + * All rights reserved. + * + * Permission to use, copy, modify, and distribute this software and its + * documentation for any purpose, without fee, and without written agreement is + * hereby granted, provided that the above copyright notice and the following + * two paragraphs appear in all copies of this software. + * + * IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR + * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT + * OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF + * CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS + * ON AN "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO + * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. + */ + + +/*==============* + * HEADER FILES * + *==============*/ + +#include "all.h" +#include "mtypes.h" +#include "frames.h" +#include "frame.h" +#include "fsize.h" +#include "dct.h" +#include "specifics.h" +#include <stdio.h> +#include <string.h> +#include "prototypes.h" + +/*====================* + * System Information * + *====================*/ + +#define CPP_LOC "/lib/cpp" + +/*==================* + * GLOBAL VARIABLES * + *==================*/ + +extern boolean specificsOn; +extern char specificsFile[]; +extern char specificsDefines[]; +FrameSpecList *fsl; + +/*=====================* + * Internal procedures * + *=====================*/ + +void Parse_Specifics_File _ANSI_ARGS_((FILE *fp)); +void Parse_Specifics_File_v1 _ANSI_ARGS_((FILE *fp)); +void Parse_Specifics_File_v2 _ANSI_ARGS_((FILE *fp)); +FrameSpecList *MakeFslEntry _ANSI_ARGS_((void)); +void AddSlc _ANSI_ARGS_((FrameSpecList *c,int snum, int qs)); +Block_Specifics *AddBs _ANSI_ARGS_((FrameSpecList *c,int bnum, + boolean rel, int qs)); +FrameSpecList *MakeFslEntry _ANSI_ARGS_((void)); +#define my_upper(c) (((c>='a') && (c<='z')) ? (c-'a'+'A') : c) +#define CvtType(x) ReallyCvt(my_upper(x)) +#define ReallyCvt(x) (x=='I' ? 1 : (x=='P')?2: ((x=='B')?3:-1)) +#define SkipToSpace(lp) while ((*lp != ' ') && (*lp != '\n') && (*lp != '\0')) lp++ +#define EndString(lp) ((*lp == '\n') || (*lp == '\0')) + +/*============================================================= + * SPEC FILE FORMAT (version 1): + +Specs files are processed with the c preprecoessor, so use C style comments +and #defines if you wish. + +frames, blocks, and slices are numbered from 0. +(sorry) + +In order by frame number, slice number, block number +(if you skip slices it's fine). +Can have specifics for any frame, block, or slice. +Format: +version N + Specify the version of the specifics file format (this is 1) +frame N T M + Sets frame number N to type T and Qscale M + (type T is I,B,P,other, other means unspec. I recomend - ) +slice M Q + Sets slice M (in frame N as defined by a previous frame command) + to qscale Q +block M Q + Sets block M to qscale Q, in frame N previously specified. + +Unspecified frame types are set via the last I frame set, which is forced +to act as the first I of the GOP. +FORCE_ENCODE_LAST_FRAME overrides specifics on the final frame type. +Note that Qscale changes in skipped blocks will be lost! + +Version 2: +frames and slices are the same as above, but Q in blocks can be relative, i.e. ++N or -N. Clipping to 1..31 is done but sequences like +block 1 2 +block 2 -3 +block 3 +3 + +has undefined results (as present block 3 would be Qscale 2). + +In addition motion vectors can be specified: +block M Q skip + Says to skip the block (not really an MV, but....) +block M Q bi fx fy bx by + Sets block M to quality Q. It will be a bidirectional block. + fx/fy is the forward (like a P frame) vector, bx/y is the back +block M Q forw fx fy +block M Q back bx by + Single directional. + +All vectors are specified in HALF PIXEL fixed point units, i.e. +3.5 pixels is 7 +To specify a vector but not touch the q factor, set Q to 0 + +*=============================================================*/ + + +/*=============* + * Local State * + *=============*/ + +static char version = -1; + +/*================================================================ + * + * Specifics_Init + * + * Cpp's and reads in the specifics file. Creates fsl data structure. + * + * Returns: nothing + * + * Modifies: fsl, file specificsFile".cpp" + * + *================================================================ + */ +void Specifics_Init() +{ + char command[1100]; + FILE *specificsFP; + + sprintf(command, "/bin/rm -f %s.cpp", specificsFile); + system(command); + sprintf(command, "%s -P %s %s %s.cpp", + CPP_LOC, specificsDefines, specificsFile, specificsFile); + system(command); + strcat(specificsFile, ".cpp"); + if ((specificsFP = fopen(specificsFile, "r")) == NULL) { + throw "Cannot open specifics file"; + } + printf("Specifics file: %s\n", specificsFile); + Parse_Specifics_File(specificsFP); + sprintf(command, "/bin/rm -f %s.cpp", specificsFile); + system(command); + +} + + + + +/*================================================================ + * + * Parse_Specifics_File + * + * Read through the file passed in creating the fsl data structure + * There is a primary routine, and helpers for the specific versions. + * + * Returns: Nothing + * + * Modifies: fsl + * + *================================================================ + */ + void Parse_Specifics_File(FILE *fp) +{ + char line[1024], *lp; + int vers; + + while ((fgets(line, 1023, fp)) != NULL) { + lp = &line[0]; + while ((*lp == ' ') || (*lp == '\t')) lp++; + if (( *lp == '#' ) || (*lp=='\n')) { + continue; + } + + switch (my_upper(*lp)) { + case 'F': case 'S': case 'B': + throw "Must specify version at beginning of specifics file"; + break; + case 'V': + lp += 7; + if (1 != sscanf(lp, "%d", &vers)) { + fprintf(stderr," Improper version line in specs file: %s\n", line); + } else { + switch (vers) { + case 1: + version = vers; + Parse_Specifics_File_v1(fp); + break; + case 2: + version = vers; + Parse_Specifics_File_v2(fp); + break; + default: + fprintf(stderr, "Improper version line in specs file: %s\n", line); + fprintf(stderr, "\tSpecifics file will be IGNORED.\n"); + specificsOn = FALSE; + return; + break; + }} + break; + default: + fprintf(stderr, "Specifics file: What? *%s*\n", line); + break; + }} + +} + +/* Version 1 */ +void Parse_Specifics_File_v1(FILE *fp) +{ + char line[1024],*lp; + FrameSpecList *current, *newf; + char typ; + int fnum,snum, bnum, qs, newqs; + int num_scanned; + + fsl = MakeFslEntry(); + current = fsl; + + while ((fgets(line,1023, fp)) != NULL) { + lp = &line[0]; + while ((*lp == ' ') || (*lp == '\t')) lp++; + if (( *lp == '#' ) || (*lp=='\n')) { + continue; + } + + switch (my_upper(*lp)) { + case 'F': + lp += 6; + sscanf(lp, "%d %c %d", &fnum, &typ, &qs); + if (current->framenum != -1) { + newf=MakeFslEntry(); + current->next = newf; + current = newf; + } + current->framenum = fnum; + current->frametype = CvtType(typ); + if (qs <= 0) qs = -1; + current->qscale = qs; + break; + case 'S': + lp += 6; + sscanf(lp, "%d %d", &snum, &newqs); + if (qs == newqs) break; + qs = newqs; + AddSlc(current, snum, qs); + break; + case 'B': + lp += 6; + num_scanned = sscanf(lp, "%d %d", &bnum, &newqs); + if (qs == newqs) break; + qs = newqs; + AddBs(current, bnum, FALSE, qs); + break; + case 'V': + fprintf(stderr, "Cannot specify version twice! Taking first (%d)\n", version); + break; + default: + fprintf(stderr," What? *%s*\n", line); + break; + }} + +} + +/* Version 2 */ +void Parse_Specifics_File_v2(FILE *fp) +{ + char line[1024], *lp; + FrameSpecList *current, *newf; + char typ; + int fnum, snum, bnum, qs, newqs; + int num_scanned, fx=0, fy=0, sx=0, sy=0; + char kind[100]; + Block_Specifics *new_blk; + boolean relative; + + fsl = MakeFslEntry(); + current = fsl; + + while ((fgets(line,1023,fp))!=NULL) { + lp = &line[0]; + while ((*lp == ' ') || (*lp == '\t')) lp++; + if (( *lp == '#' ) || (*lp=='\n')) { + continue; + } + + switch (my_upper(*lp)) { + case 'F': + lp += 6; + sscanf(lp,"%d %c %d", &fnum, &typ, &qs); + newf = MakeFslEntry(); + if (current->framenum != -1) { + current->next = newf; + current = newf; + } + current->framenum = fnum; + current->frametype = CvtType(typ); + if (qs <= 0) qs = -1; + current->qscale = qs; + break; + case 'S': + lp += 6; + sscanf(lp,"%d %d", &snum, &newqs); + if (qs == newqs) break; + qs = newqs; + AddSlc(current, snum, qs); + break; + case 'B': + lp += 6; + num_scanned = 0; + bnum = atoi(lp); + SkipToSpace(lp); + while ((*lp != '-') && (*lp != '+') && + ((*lp < '0') || (*lp > '9'))) lp++; + relative = ((*lp == '-') || (*lp == '+')); + newqs = atoi(lp); + SkipToSpace(lp); + if (EndString(lp)) { + num_scanned = 2; + } else { + num_scanned = 2+sscanf(lp, "%s %d %d %d %d", kind, &fx, &fy, &sx, &sy); + } + + qs = newqs; + new_blk = AddBs(current, bnum, relative, qs); + if (num_scanned > 2) { + BlockMV *tmp; + tmp = (BlockMV *) malloc(sizeof(BlockMV)); + switch (num_scanned) { + case 7: + tmp->typ = TYP_BOTH; + tmp->fx = fx; + tmp->fy = fy; + tmp->bx = sx; + tmp->by = sy; + new_blk->mv = tmp; + break; + case 3: + tmp->typ = TYP_SKIP; + new_blk->mv = tmp; + break; + case 5: + if (my_upper(kind[0]) == 'B') { + tmp->typ = TYP_BACK; + tmp->bx = fx; + tmp->by = fy; + } else { + tmp->typ = TYP_FORW; + tmp->fx = fx; + tmp->fy = fy; + } + new_blk->mv = tmp; + break; + default: + fprintf(stderr, + "Bug in specifics file! Skipping short/long entry: %s\n",line); + break; + } + } else { + new_blk->mv = (BlockMV *) NULL; + } + + break; + case 'V': + fprintf(stderr, + "Cannot specify version twice! Taking first (%d).\n", + version); + break; + default: + printf("What? *%s*\n",line); + break; + }} + +} + + + + +/*================================================================= + * + * MakeFslEntry + * + * Makes a single entry in for the fsl linked list (makes a frame) + * + * Returns: the new entry + * + * Modifies: nothing + * + *================================================================= + */ +FrameSpecList *MakeFslEntry() +{ + FrameSpecList *fslp; + fslp = (FrameSpecList *) malloc(sizeof(FrameSpecList)); + fslp->framenum = -1; + fslp->slc = (Slice_Specifics *) NULL; + fslp->bs = (Block_Specifics *) NULL; + return fslp; +} + + + + + +/*================================================================ + * + * AddSlc + * + * Adds a slice to framespeclist c with values snum and qs + * + * Returns: nothing + * + * Modifies: fsl's structure + * + *================================================================ + */ +void AddSlc(FrameSpecList *c, + int snum, + int qs) +{ + Slice_Specifics *news; + static Slice_Specifics *last; + + news = (Slice_Specifics *) malloc(sizeof(Slice_Specifics)); + news->num = snum; + news->qscale = qs; + news->next = (Slice_Specifics *)NULL; + if (c->slc == (Slice_Specifics *)NULL) { + last = news; + c->slc = news; + } else { + last->next = news; + last = news; + } +} + + + + + +/*================================================================ + * + * AddBs + * + * Adds a sliceblock to framespeclist c with values bnum and qs + * + * Returns: pointer to the new block spec + * + * Modifies: fsl's structure + * + *================================================================ + */ +Block_Specifics *AddBs(FrameSpecList *c, + boolean rel, + int bnum, + int qs) +{ + Block_Specifics *news; + static Block_Specifics *last; + + news = (Block_Specifics *) malloc(sizeof(Block_Specifics)); + news->num = bnum; + if (qs == 0) rel = TRUE; + news->relative = rel; + news->qscale = qs; + news->next = (Block_Specifics *)NULL; + news->mv = (BlockMV *) NULL; + if (c->bs == (Block_Specifics *)NULL) { + last = news; + c->bs = news; + } else { + last->next = news; + last = news; + } + return news; +} + + + + + + +/*================================================================ + * + * SpecLookup + * + * Find out if there is any changes to be made for the qscale + * at entry fn.num (which is of type typ). Sets info to point to + * motion vector info (if any), else NULL. + * + * Returns: new qscale or -1 + * + * Modifies: *info (well, internal cache can change) + * + *================================================================ + */ + +int SpecLookup(int fn, int typ, int num, + BlockMV **info, + int start_qs) +{ + static FrameSpecList *last = (FrameSpecList *) NULL; + Slice_Specifics *sptr=(Slice_Specifics *) NULL; + Block_Specifics *bptr=(Block_Specifics *) NULL; + FrameSpecList *tmp; + boolean found_it; + static int leftovers = 0; /* Used in case of forced movement into 1..31 range */ + + *info = (BlockMV * )NULL; + if (last == (FrameSpecList *) NULL){ + /* No cache, try to find number fn */ + tmp = fsl; + found_it = FALSE; + while (tmp != (FrameSpecList *) NULL) { + if (tmp->framenum == fn) { + found_it = TRUE; + break; + } else tmp = tmp->next; + } + if (!found_it) return -1; + last=tmp; + } else { + if (last->framenum != fn) { /* cache miss! */ + /* first check if it is next */ + if ((last->next != (FrameSpecList *) NULL) && + (last->next->framenum == fn)) { + last = last->next; + } else { + /* if not next, check from the start. + (this allows people to put frames out of order,even + though the spec doesnt allow it.) */ + tmp = fsl; + found_it = FALSE; + while (tmp != (FrameSpecList *) NULL) { + if (tmp->framenum==fn) {found_it = TRUE; break;} + tmp = tmp->next; + } + if (!found_it) return -1; + last = tmp; + } + } + } + /* neither of these should ever be true, unless there is a bug above */ + if (last == (FrameSpecList *) NULL) { + fprintf(stderr, "PROGRAMMER ERROR: last is null!\n"); + return -1; + } + if (last->framenum!=fn) { + fprintf(stderr, "PROGRAMMER ERROR: last has wrong number!\n"); + return -1; /* no data on it */ + } + + switch(typ) { + case 0: /* Frame: num is ignored */ + leftovers = 0; +#ifdef BLEAH + printf("QSchange frame %d to %d\n", fn, last->qscale); +#endif + return last->qscale; + break; + + case 1: /* Slice */ + leftovers = 0; + /* So, any data on slices? */ + if (last->slc == (Slice_Specifics *) NULL) return -1; + for (sptr = last->slc; sptr != (Slice_Specifics *) NULL; sptr = sptr->next) { + if (sptr->num == num) { +#ifdef BLEAH + printf("QSchange Slice %d.%d to %d\n", fn, num, sptr->qscale); +#endif + if (sptr->qscale == 0) return -1; + return sptr->qscale; + } + } + break; + + case 2: /* block */ + /* So, any data on blocks? */ + if (last->bs == (Block_Specifics *) NULL) { + return -1; + } + for (bptr=last->bs; bptr != (Block_Specifics *) NULL; bptr=bptr->next) { + if (bptr->num == num) { + int new_one; +#ifdef BLEAH + printf("QSchange Block %d.%d to %d\n", fn, num, bptr->qscale); +#endif + *info = bptr->mv; + if (bptr->relative) { + if (bptr->qscale == 0) { + /* Do nothing! */ + new_one = start_qs; + } else { + new_one = start_qs + bptr->qscale + leftovers; + if (new_one < 1) { + leftovers = new_one - 1; + new_one = 1; + } else if (new_one > 31) { + leftovers = new_one - 31; + new_one = 31; + } else leftovers = 0; + }} + else { + new_one = bptr->qscale; + leftovers = 0; + } + return new_one; + } + } + break; + default: + fprintf(stderr, "PROGRAMMER ERROR: reached unreachable code in SpecLookup\n"); + break; + } + /* no luck */ + return -1; +} + + +/*================================================================ + * + * SpecTypeLookup + * + * Find out if there is any changes to be made for the type of frame + * at frame fn. + * + * Returns: new type or -1 (unspecified) + * + *================================================================ + */ +int SpecTypeLookup(int fn) +{ + FrameSpecList *tmp; + + /* try to find number fn */ + tmp = fsl; + do { + if (tmp->framenum == fn) break; + else tmp = tmp->next; + } while (tmp != (FrameSpecList *) NULL); + if (tmp == (FrameSpecList *) NULL) { +#ifdef BLEAH + printf("Frame %d type not specified\n", fn); +#endif + return -1; + } +#ifdef BLEAH + printf("Frame %d type set to %d\n", fn, tmp->frametype); +#endif + return tmp->frametype; +} diff --git a/contrib/mpeg_encode/subsample.cpp b/contrib/mpeg_encode/subsample.cpp new file mode 100644 index 0000000000000000000000000000000000000000..f968d0be11a19e5d8d3b478c97fce5a60cba1f2b --- /dev/null +++ b/contrib/mpeg_encode/subsample.cpp @@ -0,0 +1,780 @@ +/*===========================================================================* + * subsample.c * + * * + * Procedures concerned with subsampling * + * * + * EXPORTED PROCEDURES: * + * LumMotionErrorA * + * LumMotionErrorB * + * LumMotionErrorC * + * LumMotionErrorD * + * * + *===========================================================================*/ + +/* + * Copyright (c) 1995 The Regents of the University of California. + * All rights reserved. + * + * Permission to use, copy, modify, and distribute this software and its + * documentation for any purpose, without fee, and without written agreement is + * hereby granted, provided that the above copyright notice and the following + * two paragraphs appear in all copies of this software. + * + * IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR + * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT + * OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF + * CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS + * ON AN "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO + * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. + */ + +/* + * $Header: /n/charlie-brown/project/mm/mpeg/mpeg_dist/mpeg_encode/RCS/subsample.c,v 1.6 1995/01/19 23:09:28 eyhung Exp $ + * $Log: subsample.c,v $ + * Revision 1.6 1995/01/19 23:09:28 eyhung + * Changed copyrights + * + * Revision 1.5 1994/11/12 02:12:01 keving + * nothing + * + * Revision 1.4 1993/12/22 19:19:01 keving + * nothing + * + * Revision 1.4 1993/12/22 19:19:01 keving + * nothing + * + * Revision 1.3 1993/07/22 22:23:43 keving + * nothing + * + * Revision 1.2 1993/06/30 20:06:09 keving + * nothing + * + * Revision 1.1 1993/06/22 21:56:05 keving + * nothing + * + */ + + +/*==============* + * HEADER FILES * + *==============*/ + +#include "all.h" +#include "mtypes.h" +#include "frames.h" +#include "bitio.h" +#include "prototypes.h" + +#undef ABS +#define ABS(x) ((x < 0) ? (-x) : x) + + +/*=====================* + * EXPORTED PROCEDURES * + *=====================*/ + + +/*===========================================================================* + * + * LumMotionErrorA + * + * compute the motion error for the A subsampling pattern + * + * RETURNS: the error, or some number greater if it is worse + * + * SIDE EFFECTS: none + * + *===========================================================================*/ +int32 +LumMotionErrorA(LumBlock currentBlock, + MpegFrame *prevFrame, + int by, + int bx, + int my, + int mx, + int32 bestSoFar) +{ + register int32 diff = 0; /* max value of diff is 255*256 = 65280 */ + register int32 localDiff; + register uint8 *macross; + register uint8 **prev; + register int fy, fx; + boolean xHalf, yHalf; + + xHalf = (ABS(mx) % 2 == 1); + yHalf = (ABS(my) % 2 == 1); + + MOTION_TO_FRAME_COORD(by, bx, my/2, mx/2, fy, fx); + + if ( xHalf ) { + if ( mx < 0 ) { + fx--; + } + + if ( yHalf ) { + if ( my < 0 ) { + fy--; + } + + prev = prevFrame->halfBoth; + } else { + prev = prevFrame->halfX; + } + } else if ( yHalf ) { + if ( my < 0 ) { + fy--; + } + + prev = prevFrame->halfY; + } else { + prev = prevFrame->ref_y; + } + + macross = &(prev[fy][fx]); + + localDiff = macross[0]-currentBlock[0][0]; diff += ABS(localDiff); + localDiff = macross[2]-currentBlock[0][2]; diff += ABS(localDiff); + localDiff = macross[4]-currentBlock[0][4]; diff += ABS(localDiff); + localDiff = macross[6]-currentBlock[0][6]; diff += ABS(localDiff); + localDiff = macross[8]-currentBlock[0][8]; diff += ABS(localDiff); + localDiff = macross[10]-currentBlock[0][10]; diff += ABS(localDiff); + localDiff = macross[12]-currentBlock[0][12]; diff += ABS(localDiff); + localDiff = macross[14]-currentBlock[0][14]; diff += ABS(localDiff); + + if ( diff > bestSoFar ) { + return diff; + } + + macross = &(prev[fy+2][fx]); + + localDiff = macross[0]-currentBlock[2][0]; diff += ABS(localDiff); + localDiff = macross[2]-currentBlock[2][2]; diff += ABS(localDiff); + localDiff = macross[4]-currentBlock[2][4]; diff += ABS(localDiff); + localDiff = macross[6]-currentBlock[2][6]; diff += ABS(localDiff); + localDiff = macross[8]-currentBlock[2][8]; diff += ABS(localDiff); + localDiff = macross[10]-currentBlock[2][10]; diff += ABS(localDiff); + localDiff = macross[12]-currentBlock[2][12]; diff += ABS(localDiff); + localDiff = macross[14]-currentBlock[2][14]; diff += ABS(localDiff); + + if ( diff > bestSoFar ) { + return diff; + } + + macross = &(prev[fy+4][fx]); + + localDiff = macross[0]-currentBlock[4][0]; diff += ABS(localDiff); + localDiff = macross[2]-currentBlock[4][2]; diff += ABS(localDiff); + localDiff = macross[4]-currentBlock[4][4]; diff += ABS(localDiff); + localDiff = macross[6]-currentBlock[4][6]; diff += ABS(localDiff); + localDiff = macross[8]-currentBlock[4][8]; diff += ABS(localDiff); + localDiff = macross[10]-currentBlock[4][10]; diff += ABS(localDiff); + localDiff = macross[12]-currentBlock[4][12]; diff += ABS(localDiff); + localDiff = macross[14]-currentBlock[4][14]; diff += ABS(localDiff); + + if ( diff > bestSoFar ) { + return diff; + } + + macross = &(prev[fy+6][fx]); + + localDiff = macross[0]-currentBlock[6][0]; diff += ABS(localDiff); + localDiff = macross[2]-currentBlock[6][2]; diff += ABS(localDiff); + localDiff = macross[4]-currentBlock[6][4]; diff += ABS(localDiff); + localDiff = macross[6]-currentBlock[6][6]; diff += ABS(localDiff); + localDiff = macross[8]-currentBlock[6][8]; diff += ABS(localDiff); + localDiff = macross[10]-currentBlock[6][10]; diff += ABS(localDiff); + localDiff = macross[12]-currentBlock[6][12]; diff += ABS(localDiff); + localDiff = macross[14]-currentBlock[6][14]; diff += ABS(localDiff); + + if ( diff > bestSoFar ) { + return diff; + } + + macross = &(prev[fy+8][fx]); + + localDiff = macross[0]-currentBlock[8][0]; diff += ABS(localDiff); + localDiff = macross[2]-currentBlock[8][2]; diff += ABS(localDiff); + localDiff = macross[4]-currentBlock[8][4]; diff += ABS(localDiff); + localDiff = macross[6]-currentBlock[8][6]; diff += ABS(localDiff); + localDiff = macross[8]-currentBlock[8][8]; diff += ABS(localDiff); + localDiff = macross[10]-currentBlock[8][10]; diff += ABS(localDiff); + localDiff = macross[12]-currentBlock[8][12]; diff += ABS(localDiff); + localDiff = macross[14]-currentBlock[8][14]; diff += ABS(localDiff); + + if ( diff > bestSoFar ) { + return diff; + } + + macross = &(prev[fy+10][fx]); + + localDiff = macross[0]-currentBlock[10][0]; diff += ABS(localDiff); + localDiff = macross[2]-currentBlock[10][2]; diff += ABS(localDiff); + localDiff = macross[4]-currentBlock[10][4]; diff += ABS(localDiff); + localDiff = macross[6]-currentBlock[10][6]; diff += ABS(localDiff); + localDiff = macross[8]-currentBlock[10][8]; diff += ABS(localDiff); + localDiff = macross[10]-currentBlock[10][10]; diff += ABS(localDiff); + localDiff = macross[12]-currentBlock[10][12]; diff += ABS(localDiff); + localDiff = macross[14]-currentBlock[10][14]; diff += ABS(localDiff); + + if ( diff > bestSoFar ) { + return diff; + } + + macross = &(prev[fy+12][fx]); + + localDiff = macross[0]-currentBlock[12][0]; diff += ABS(localDiff); + localDiff = macross[2]-currentBlock[12][2]; diff += ABS(localDiff); + localDiff = macross[4]-currentBlock[12][4]; diff += ABS(localDiff); + localDiff = macross[6]-currentBlock[12][6]; diff += ABS(localDiff); + localDiff = macross[8]-currentBlock[12][8]; diff += ABS(localDiff); + localDiff = macross[10]-currentBlock[12][10]; diff += ABS(localDiff); + localDiff = macross[12]-currentBlock[12][12]; diff += ABS(localDiff); + localDiff = macross[14]-currentBlock[12][14]; diff += ABS(localDiff); + + if ( diff > bestSoFar ) { + return diff; + } + + macross = &(prev[fy+14][fx]); + + localDiff = macross[0]-currentBlock[14][0]; diff += ABS(localDiff); + localDiff = macross[2]-currentBlock[14][2]; diff += ABS(localDiff); + localDiff = macross[4]-currentBlock[14][4]; diff += ABS(localDiff); + localDiff = macross[6]-currentBlock[14][6]; diff += ABS(localDiff); + localDiff = macross[8]-currentBlock[14][8]; diff += ABS(localDiff); + localDiff = macross[10]-currentBlock[14][10]; diff += ABS(localDiff); + localDiff = macross[12]-currentBlock[14][12]; diff += ABS(localDiff); + localDiff = macross[14]-currentBlock[14][14]; diff += ABS(localDiff); + + return diff; +} + + +/*===========================================================================* + * + * LumMotionErrorB + * + * compute the motion error for the B subsampling pattern + * + * RETURNS: the error, or some number greater if it is worse + * + * SIDE EFFECTS: none + * + *===========================================================================*/ +int32 +LumMotionErrorB(LumBlock currentBlock, + MpegFrame *prevFrame, + int by, + int bx, + int my, + int mx, + int32 bestSoFar) +{ + register int32 diff = 0; /* max value of diff is 255*256 = 65280 */ + register int32 localDiff; + register uint8 *macross; + register uint8 **prev; + register int fy, fx; + boolean xHalf, yHalf; + + xHalf = (ABS(mx) % 2 == 1); + yHalf = (ABS(my) % 2 == 1); + + MOTION_TO_FRAME_COORD(by, bx, my/2, mx/2, fy, fx); + + if ( xHalf ) { + if ( mx < 0 ) { + fx--; + } + + if ( yHalf ) { + if ( my < 0 ) { + fy--; + } + + prev = prevFrame->halfBoth; + } else { + prev = prevFrame->halfX; + } + } else if ( yHalf ) { + if ( my < 0 ) { + fy--; + } + + prev = prevFrame->halfY; + } else { + prev = prevFrame->ref_y; + } + + macross = &(prev[fy+0][fx]); + + localDiff = macross[1]-currentBlock[0][1]; diff += ABS(localDiff); + localDiff = macross[3]-currentBlock[0][3]; diff += ABS(localDiff); + localDiff = macross[5]-currentBlock[0][5]; diff += ABS(localDiff); + localDiff = macross[7]-currentBlock[0][7]; diff += ABS(localDiff); + localDiff = macross[9]-currentBlock[0][9]; diff += ABS(localDiff); + localDiff = macross[11]-currentBlock[0][11]; diff += ABS(localDiff); + localDiff = macross[13]-currentBlock[0][13]; diff += ABS(localDiff); + localDiff = macross[15]-currentBlock[0][15]; diff += ABS(localDiff); + + if ( diff > bestSoFar ) { + return diff; + } + + macross = &(prev[fy+2][fx]); + + localDiff = macross[1]-currentBlock[2][1]; diff += ABS(localDiff); + localDiff = macross[3]-currentBlock[2][3]; diff += ABS(localDiff); + localDiff = macross[5]-currentBlock[2][5]; diff += ABS(localDiff); + localDiff = macross[7]-currentBlock[2][7]; diff += ABS(localDiff); + localDiff = macross[9]-currentBlock[2][9]; diff += ABS(localDiff); + localDiff = macross[11]-currentBlock[2][11]; diff += ABS(localDiff); + localDiff = macross[13]-currentBlock[2][13]; diff += ABS(localDiff); + localDiff = macross[15]-currentBlock[2][15]; diff += ABS(localDiff); + + if ( diff > bestSoFar ) { + return diff; + } + + macross = &(prev[fy+4][fx]); + + localDiff = macross[1]-currentBlock[4][1]; diff += ABS(localDiff); + localDiff = macross[3]-currentBlock[4][3]; diff += ABS(localDiff); + localDiff = macross[5]-currentBlock[4][5]; diff += ABS(localDiff); + localDiff = macross[7]-currentBlock[4][7]; diff += ABS(localDiff); + localDiff = macross[9]-currentBlock[4][9]; diff += ABS(localDiff); + localDiff = macross[11]-currentBlock[4][11]; diff += ABS(localDiff); + localDiff = macross[13]-currentBlock[4][13]; diff += ABS(localDiff); + localDiff = macross[15]-currentBlock[4][15]; diff += ABS(localDiff); + + if ( diff > bestSoFar ) { + return diff; + } + + macross = &(prev[fy+6][fx]); + + localDiff = macross[1]-currentBlock[6][1]; diff += ABS(localDiff); + localDiff = macross[3]-currentBlock[6][3]; diff += ABS(localDiff); + localDiff = macross[5]-currentBlock[6][5]; diff += ABS(localDiff); + localDiff = macross[7]-currentBlock[6][7]; diff += ABS(localDiff); + localDiff = macross[9]-currentBlock[6][9]; diff += ABS(localDiff); + localDiff = macross[11]-currentBlock[6][11]; diff += ABS(localDiff); + localDiff = macross[13]-currentBlock[6][13]; diff += ABS(localDiff); + localDiff = macross[15]-currentBlock[6][15]; diff += ABS(localDiff); + + if ( diff > bestSoFar ) { + return diff; + } + + macross = &(prev[fy+8][fx]); + + localDiff = macross[1]-currentBlock[8][1]; diff += ABS(localDiff); + localDiff = macross[3]-currentBlock[8][3]; diff += ABS(localDiff); + localDiff = macross[5]-currentBlock[8][5]; diff += ABS(localDiff); + localDiff = macross[7]-currentBlock[8][7]; diff += ABS(localDiff); + localDiff = macross[9]-currentBlock[8][9]; diff += ABS(localDiff); + localDiff = macross[11]-currentBlock[8][11]; diff += ABS(localDiff); + localDiff = macross[13]-currentBlock[8][13]; diff += ABS(localDiff); + localDiff = macross[15]-currentBlock[8][15]; diff += ABS(localDiff); + + if ( diff > bestSoFar ) { + return diff; + } + + macross = &(prev[fy+10][fx]); + + localDiff = macross[1]-currentBlock[10][1]; diff += ABS(localDiff); + localDiff = macross[3]-currentBlock[10][3]; diff += ABS(localDiff); + localDiff = macross[5]-currentBlock[10][5]; diff += ABS(localDiff); + localDiff = macross[7]-currentBlock[10][7]; diff += ABS(localDiff); + localDiff = macross[9]-currentBlock[10][9]; diff += ABS(localDiff); + localDiff = macross[11]-currentBlock[10][11]; diff += ABS(localDiff); + localDiff = macross[13]-currentBlock[10][13]; diff += ABS(localDiff); + localDiff = macross[15]-currentBlock[10][15]; diff += ABS(localDiff); + + if ( diff > bestSoFar ) { + return diff; + } + + macross = &(prev[fy+12][fx]); + + localDiff = macross[1]-currentBlock[12][1]; diff += ABS(localDiff); + localDiff = macross[3]-currentBlock[12][3]; diff += ABS(localDiff); + localDiff = macross[5]-currentBlock[12][5]; diff += ABS(localDiff); + localDiff = macross[7]-currentBlock[12][7]; diff += ABS(localDiff); + localDiff = macross[9]-currentBlock[12][9]; diff += ABS(localDiff); + localDiff = macross[11]-currentBlock[12][11]; diff += ABS(localDiff); + localDiff = macross[13]-currentBlock[12][13]; diff += ABS(localDiff); + localDiff = macross[15]-currentBlock[12][15]; diff += ABS(localDiff); + + if ( diff > bestSoFar ) { + return diff; + } + + macross = &(prev[fy+14][fx]); + + localDiff = macross[1]-currentBlock[14][1]; diff += ABS(localDiff); + localDiff = macross[3]-currentBlock[14][3]; diff += ABS(localDiff); + localDiff = macross[5]-currentBlock[14][5]; diff += ABS(localDiff); + localDiff = macross[7]-currentBlock[14][7]; diff += ABS(localDiff); + localDiff = macross[9]-currentBlock[14][9]; diff += ABS(localDiff); + localDiff = macross[11]-currentBlock[14][11]; diff += ABS(localDiff); + localDiff = macross[13]-currentBlock[14][13]; diff += ABS(localDiff); + localDiff = macross[15]-currentBlock[14][15]; diff += ABS(localDiff); + + return diff; +} + + +/*===========================================================================* + * + * LumMotionErrorC + * + * compute the motion error for the C subsampling pattern + * + * RETURNS: the error, or some number greater if it is worse + * + * SIDE EFFECTS: none + * + *===========================================================================*/ +int32 +LumMotionErrorC(LumBlock currentBlock, + MpegFrame *prevFrame, + int by, + int bx, + int my, + int mx, + int32 bestSoFar) +{ + register int32 diff = 0; /* max value of diff is 255*256 = 65280 */ + register int32 localDiff; + register uint8 *macross; + register uint8 **prev; + register int fy, fx; + boolean xHalf, yHalf; + + xHalf = (ABS(mx) % 2 == 1); + yHalf = (ABS(my) % 2 == 1); + + MOTION_TO_FRAME_COORD(by, bx, my/2, mx/2, fy, fx); + + if ( xHalf ) { + if ( mx < 0 ) { + fx--; + } + + if ( yHalf ) { + if ( my < 0 ) { + fy--; + } + + prev = prevFrame->halfBoth; + } else { + prev = prevFrame->halfX; + } + } else if ( yHalf ) { + if ( my < 0 ) { + fy--; + } + + prev = prevFrame->halfY; + } else { + prev = prevFrame->ref_y; + } + + macross = &(prev[fy+1][fx]); + + localDiff = macross[0]-currentBlock[1][0]; diff += ABS(localDiff); + localDiff = macross[2]-currentBlock[1][2]; diff += ABS(localDiff); + localDiff = macross[4]-currentBlock[1][4]; diff += ABS(localDiff); + localDiff = macross[6]-currentBlock[1][6]; diff += ABS(localDiff); + localDiff = macross[8]-currentBlock[1][8]; diff += ABS(localDiff); + localDiff = macross[10]-currentBlock[1][10]; diff += ABS(localDiff); + localDiff = macross[12]-currentBlock[1][12]; diff += ABS(localDiff); + localDiff = macross[14]-currentBlock[1][14]; diff += ABS(localDiff); + + if ( diff > bestSoFar ) { + return diff; + } + + macross = &(prev[fy+3][fx]); + + localDiff = macross[0]-currentBlock[3][0]; diff += ABS(localDiff); + localDiff = macross[2]-currentBlock[3][2]; diff += ABS(localDiff); + localDiff = macross[4]-currentBlock[3][4]; diff += ABS(localDiff); + localDiff = macross[6]-currentBlock[3][6]; diff += ABS(localDiff); + localDiff = macross[8]-currentBlock[3][8]; diff += ABS(localDiff); + localDiff = macross[10]-currentBlock[3][10]; diff += ABS(localDiff); + localDiff = macross[12]-currentBlock[3][12]; diff += ABS(localDiff); + localDiff = macross[14]-currentBlock[3][14]; diff += ABS(localDiff); + + if ( diff > bestSoFar ) { + return diff; + } + + macross = &(prev[fy+5][fx]); + + localDiff = macross[0]-currentBlock[5][0]; diff += ABS(localDiff); + localDiff = macross[2]-currentBlock[5][2]; diff += ABS(localDiff); + localDiff = macross[4]-currentBlock[5][4]; diff += ABS(localDiff); + localDiff = macross[6]-currentBlock[5][6]; diff += ABS(localDiff); + localDiff = macross[8]-currentBlock[5][8]; diff += ABS(localDiff); + localDiff = macross[10]-currentBlock[5][10]; diff += ABS(localDiff); + localDiff = macross[12]-currentBlock[5][12]; diff += ABS(localDiff); + localDiff = macross[14]-currentBlock[5][14]; diff += ABS(localDiff); + + if ( diff > bestSoFar ) { + return diff; + } + + macross = &(prev[fy+7][fx]); + + localDiff = macross[0]-currentBlock[7][0]; diff += ABS(localDiff); + localDiff = macross[2]-currentBlock[7][2]; diff += ABS(localDiff); + localDiff = macross[4]-currentBlock[7][4]; diff += ABS(localDiff); + localDiff = macross[6]-currentBlock[7][6]; diff += ABS(localDiff); + localDiff = macross[8]-currentBlock[7][8]; diff += ABS(localDiff); + localDiff = macross[10]-currentBlock[7][10]; diff += ABS(localDiff); + localDiff = macross[12]-currentBlock[7][12]; diff += ABS(localDiff); + localDiff = macross[14]-currentBlock[7][14]; diff += ABS(localDiff); + + if ( diff > bestSoFar ) { + return diff; + } + + macross = &(prev[fy+9][fx]); + + localDiff = macross[0]-currentBlock[9][0]; diff += ABS(localDiff); + localDiff = macross[2]-currentBlock[9][2]; diff += ABS(localDiff); + localDiff = macross[4]-currentBlock[9][4]; diff += ABS(localDiff); + localDiff = macross[6]-currentBlock[9][6]; diff += ABS(localDiff); + localDiff = macross[8]-currentBlock[9][8]; diff += ABS(localDiff); + localDiff = macross[10]-currentBlock[9][10]; diff += ABS(localDiff); + localDiff = macross[12]-currentBlock[9][12]; diff += ABS(localDiff); + localDiff = macross[14]-currentBlock[9][14]; diff += ABS(localDiff); + + if ( diff > bestSoFar ) { + return diff; + } + + macross = &(prev[fy+11][fx]); + + localDiff = macross[0]-currentBlock[11][0]; diff += ABS(localDiff); + localDiff = macross[2]-currentBlock[11][2]; diff += ABS(localDiff); + localDiff = macross[4]-currentBlock[11][4]; diff += ABS(localDiff); + localDiff = macross[6]-currentBlock[11][6]; diff += ABS(localDiff); + localDiff = macross[8]-currentBlock[11][8]; diff += ABS(localDiff); + localDiff = macross[10]-currentBlock[11][10]; diff += ABS(localDiff); + localDiff = macross[12]-currentBlock[11][12]; diff += ABS(localDiff); + localDiff = macross[14]-currentBlock[11][14]; diff += ABS(localDiff); + + if ( diff > bestSoFar ) { + return diff; + } + + macross = &(prev[fy+13][fx]); + + localDiff = macross[0]-currentBlock[13][0]; diff += ABS(localDiff); + localDiff = macross[2]-currentBlock[13][2]; diff += ABS(localDiff); + localDiff = macross[4]-currentBlock[13][4]; diff += ABS(localDiff); + localDiff = macross[6]-currentBlock[13][6]; diff += ABS(localDiff); + localDiff = macross[8]-currentBlock[13][8]; diff += ABS(localDiff); + localDiff = macross[10]-currentBlock[13][10]; diff += ABS(localDiff); + localDiff = macross[12]-currentBlock[13][12]; diff += ABS(localDiff); + localDiff = macross[14]-currentBlock[13][14]; diff += ABS(localDiff); + + if ( diff > bestSoFar ) { + return diff; + } + + macross = &(prev[fy+15][fx]); + + localDiff = macross[0]-currentBlock[15][0]; diff += ABS(localDiff); + localDiff = macross[2]-currentBlock[15][2]; diff += ABS(localDiff); + localDiff = macross[4]-currentBlock[15][4]; diff += ABS(localDiff); + localDiff = macross[6]-currentBlock[15][6]; diff += ABS(localDiff); + localDiff = macross[8]-currentBlock[15][8]; diff += ABS(localDiff); + localDiff = macross[10]-currentBlock[15][10]; diff += ABS(localDiff); + localDiff = macross[12]-currentBlock[15][12]; diff += ABS(localDiff); + localDiff = macross[14]-currentBlock[15][14]; diff += ABS(localDiff); + + return diff; +} + + +/*===========================================================================* + * + * LumMotionErrorD + * + * compute the motion error for the D subsampling pattern + * + * RETURNS: the error, or some number greater if it is worse + * + * SIDE EFFECTS: none + * + *===========================================================================*/ +int32 +LumMotionErrorD(LumBlock currentBlock, + MpegFrame *prevFrame, + int by, + int bx, + int my, + int mx, + int32 bestSoFar) +{ + register int32 diff = 0; /* max value of diff is 255*256 = 65280 */ + register int32 localDiff; + register uint8 *macross; + register uint8 **prev; + register int fy, fx; + boolean xHalf, yHalf; + + xHalf = (ABS(mx) % 2 == 1); + yHalf = (ABS(my) % 2 == 1); + + MOTION_TO_FRAME_COORD(by, bx, my/2, mx/2, fy, fx); + + if ( xHalf ) { + if ( mx < 0 ) { + fx--; + } + + if ( yHalf ) { + if ( my < 0 ) { + fy--; + } + prev = prevFrame->halfBoth; + } else { + prev = prevFrame->halfX; + } + } else if ( yHalf ) { + if ( my < 0 ) { + fy--; + } + prev = prevFrame->halfY; + } else { + prev = prevFrame->ref_y; + } + + macross = &(prev[fy+1][fx]); + + localDiff = macross[1]-currentBlock[1][1]; diff += ABS(localDiff); + localDiff = macross[3]-currentBlock[1][3]; diff += ABS(localDiff); + localDiff = macross[5]-currentBlock[1][5]; diff += ABS(localDiff); + localDiff = macross[7]-currentBlock[1][7]; diff += ABS(localDiff); + localDiff = macross[9]-currentBlock[1][9]; diff += ABS(localDiff); + localDiff = macross[11]-currentBlock[1][11]; diff += ABS(localDiff); + localDiff = macross[13]-currentBlock[1][13]; diff += ABS(localDiff); + localDiff = macross[15]-currentBlock[1][15]; diff += ABS(localDiff); + + if ( diff > bestSoFar ) { + return diff; + } + + macross = &(prev[fy+3][fx]); + + localDiff = macross[1]-currentBlock[3][1]; diff += ABS(localDiff); + localDiff = macross[3]-currentBlock[3][3]; diff += ABS(localDiff); + localDiff = macross[5]-currentBlock[3][5]; diff += ABS(localDiff); + localDiff = macross[7]-currentBlock[3][7]; diff += ABS(localDiff); + localDiff = macross[9]-currentBlock[3][9]; diff += ABS(localDiff); + localDiff = macross[11]-currentBlock[3][11]; diff += ABS(localDiff); + localDiff = macross[13]-currentBlock[3][13]; diff += ABS(localDiff); + localDiff = macross[15]-currentBlock[3][15]; diff += ABS(localDiff); + + if ( diff > bestSoFar ) { + return diff; + } + + macross = &(prev[fy+5][fx]); + + localDiff = macross[1]-currentBlock[5][1]; diff += ABS(localDiff); + localDiff = macross[3]-currentBlock[5][3]; diff += ABS(localDiff); + localDiff = macross[5]-currentBlock[5][5]; diff += ABS(localDiff); + localDiff = macross[7]-currentBlock[5][7]; diff += ABS(localDiff); + localDiff = macross[9]-currentBlock[5][9]; diff += ABS(localDiff); + localDiff = macross[11]-currentBlock[5][11]; diff += ABS(localDiff); + localDiff = macross[13]-currentBlock[5][13]; diff += ABS(localDiff); + localDiff = macross[15]-currentBlock[5][15]; diff += ABS(localDiff); + + if ( diff > bestSoFar ) { + return diff; + } + + macross = &(prev[fy+7][fx]); + + localDiff = macross[1]-currentBlock[7][1]; diff += ABS(localDiff); + localDiff = macross[3]-currentBlock[7][3]; diff += ABS(localDiff); + localDiff = macross[5]-currentBlock[7][5]; diff += ABS(localDiff); + localDiff = macross[7]-currentBlock[7][7]; diff += ABS(localDiff); + localDiff = macross[9]-currentBlock[7][9]; diff += ABS(localDiff); + localDiff = macross[11]-currentBlock[7][11]; diff += ABS(localDiff); + localDiff = macross[13]-currentBlock[7][13]; diff += ABS(localDiff); + localDiff = macross[15]-currentBlock[7][15]; diff += ABS(localDiff); + + if ( diff > bestSoFar ) { + return diff; + } + + macross = &(prev[fy+9][fx]); + + localDiff = macross[1]-currentBlock[9][1]; diff += ABS(localDiff); + localDiff = macross[3]-currentBlock[9][3]; diff += ABS(localDiff); + localDiff = macross[5]-currentBlock[9][5]; diff += ABS(localDiff); + localDiff = macross[7]-currentBlock[9][7]; diff += ABS(localDiff); + localDiff = macross[9]-currentBlock[9][9]; diff += ABS(localDiff); + localDiff = macross[11]-currentBlock[9][11]; diff += ABS(localDiff); + localDiff = macross[13]-currentBlock[9][13]; diff += ABS(localDiff); + localDiff = macross[15]-currentBlock[9][15]; diff += ABS(localDiff); + + if ( diff > bestSoFar ) { + return diff; + } + + macross = &(prev[fy+11][fx]); + + localDiff = macross[1]-currentBlock[11][1]; diff += ABS(localDiff); + localDiff = macross[3]-currentBlock[11][3]; diff += ABS(localDiff); + localDiff = macross[5]-currentBlock[11][5]; diff += ABS(localDiff); + localDiff = macross[7]-currentBlock[11][7]; diff += ABS(localDiff); + localDiff = macross[9]-currentBlock[11][9]; diff += ABS(localDiff); + localDiff = macross[11]-currentBlock[11][11]; diff += ABS(localDiff); + localDiff = macross[13]-currentBlock[11][13]; diff += ABS(localDiff); + localDiff = macross[15]-currentBlock[11][15]; diff += ABS(localDiff); + + if ( diff > bestSoFar ) { + return diff; + } + + macross = &(prev[fy+13][fx]); + + localDiff = macross[1]-currentBlock[13][1]; diff += ABS(localDiff); + localDiff = macross[3]-currentBlock[13][3]; diff += ABS(localDiff); + localDiff = macross[5]-currentBlock[13][5]; diff += ABS(localDiff); + localDiff = macross[7]-currentBlock[13][7]; diff += ABS(localDiff); + localDiff = macross[9]-currentBlock[13][9]; diff += ABS(localDiff); + localDiff = macross[11]-currentBlock[13][11]; diff += ABS(localDiff); + localDiff = macross[13]-currentBlock[13][13]; diff += ABS(localDiff); + localDiff = macross[15]-currentBlock[13][15]; diff += ABS(localDiff); + + if ( diff > bestSoFar ) { + return diff; + } + + macross = &(prev[fy+15][fx]); + + localDiff = macross[1]-currentBlock[15][1]; diff += ABS(localDiff); + localDiff = macross[3]-currentBlock[15][3]; diff += ABS(localDiff); + localDiff = macross[5]-currentBlock[15][5]; diff += ABS(localDiff); + localDiff = macross[7]-currentBlock[15][7]; diff += ABS(localDiff); + localDiff = macross[9]-currentBlock[15][9]; diff += ABS(localDiff); + localDiff = macross[11]-currentBlock[15][11]; diff += ABS(localDiff); + localDiff = macross[13]-currentBlock[15][13]; diff += ABS(localDiff); + localDiff = macross[15]-currentBlock[15][15]; diff += ABS(localDiff); + + return diff; +} diff --git a/demos/anim.script b/demos/anim.script index f09487f7ece9d11e43b9001b1d86b7cee7b9a9e4..5cd2944413b83ca92ecbe67b8acf79790c5aa99b 100644 --- a/demos/anim.script +++ b/demos/anim.script @@ -1,18 +1,21 @@ // This script creates an mpeg or gif animation by looping over all // the time steps and/or all the post-processing views -neww = GetValue("Width of animation? (enter 0 to keep current width)", 640); -newh = GetValue("Height of animation? (enter 0 to keep current height)", 640) ; -all = GetValue("Animate one view at a time or all views together? - -0: one at a time, 1: all together", 1) ; -method = GetValue("Animation encoder? - -0: mpeg_encode (MPEG1), 1: mencoder (MPEG4), 2: whirlgif (GIF89)", 0) ; MPEG_ENCODE = 0; MENCODER = 1; WHIRLGIF = 2; +ENCODER = GetValue("Which animation encoder do you want to use? + +0: mpeg_encode, 1: mencoder, 2: whirlgif", 0); +PATH = GetString("Where do you want to save the animation?", "/tmp"); +neww = GetValue("Width of animation? (enter 0 to keep current width)", 0); +newh = GetValue("Height of animation? (enter 0 to keep current height)", 0) ; +all = GetValue("Animate one view at a time, or all views together? + +0: one at a time, 1: all together", 1) ; + + oldw = General.GraphicsWidth; oldh = General.GraphicsHeight; @@ -36,11 +39,14 @@ If(all) EndFor For index In {1:NUM_FRAMES} Draw; - If(method == WHIRLGIF) - Print Sprintf("/tmp/tmp%03g.gif", index); + If(ENCODER == WHIRLGIF) + Print StrCat(PATH, Sprintf("/tmp%03g.gif", index)); EndIf - If(method == MPEG_ENCODE || method == MENCODER) - Print Sprintf("/tmp/tmp%03g.jpg", index); + If(ENCODER == MPEG_ENCODE) + Print StrCat(PATH, Sprintf("/tmp%03g.jpg", index)); + EndIf + If(ENCODER == MENCODER) + Print StrCat(PATH, Sprintf("/tmp%03g.png", index)); EndIf For i In {1:PostProcessing.NbViews} View[i-1].TimeStep++; @@ -62,19 +68,21 @@ If(!all) For j In {1:View[i-1].NbTimeStep} NUM_FRAMES++; Draw; - If(method == WHIRLGIF) + If(ENCODER == WHIRLGIF) Print Sprintf("/tmp/tmp%03g.gif", NUM_FRAMES); EndIf - If(method == MPEG_ENCODE || method == MENCODER) + If(ENCODER == MPEG_ENCODE) Print Sprintf("/tmp/tmp%03g.jpg", NUM_FRAMES); EndIf + If(ENCODER == MENCODER) + Print Sprintf("/tmp/tmp%03g.png", NUM_FRAMES); + EndIf View[i-1].TimeStep++; EndFor View[i-1].Visible = 0; EndFor EndIf -ENCODER = method; Include "encode.script"; General.GraphicsWidth = oldw; diff --git a/demos/encode.script b/demos/encode.script index 568db62cbf97d9f254e52e2cde4972372007d676..7211b894e79b28338960864edc65076cff4a58db 100644 --- a/demos/encode.script +++ b/demos/encode.script @@ -1,55 +1,62 @@ // This script encodes the image files // -// /tmp/tmp[001-NUM_FRAMES].{gif,jpg} +// PATH/tmp[001-NUM_FRAMES].{gif,jpg,png} // // into an mpeg or gif animation, using the encoder ENCODER // (set to WHIRLGIF, MENCODER or MPEG_ENCODE) If(ENCODER == WHIRLGIF) - // Call whirlgif - System "whirlgif -minimize -loop -o /tmp/animation.gif /tmp/tmp*.gif" ; + // call whirlgif + System StrCat(StrCat(StrCat(StrCat("whirlgif -minimize -loop -o ", PATH), + "/animation.gif "), PATH), "/tmp*.gif"); EndIf If(ENCODER == MENCODER) - // Call mencoder - System "mencoder 'mf:///tmp/tmp*.jpg' -mf fps=5 -o /tmp/animation.mpg -ovc lavc -lavcopts vcodec=mpeg4:vhq"; - // System "mencoder 'mf:///tmp/tmp*.jpg' -mf fps=5 -o /tmp/animation.mpg -ovc lavc -lavcopts vcodec=mpeg1video:vhq"; + // call mencoder + cmd = StrCat(StrCat(StrCat(StrCat("mencoder 'mf://", PATH), + "/tmp*.png' -mf type=png:fps=5 -o "), PATH), "/animation.mpg "); + System StrCat(cmd, "-ovc lavc -lavcopts vcodec=mpeg1video:vhq:mbd=2:trell"); + //System StrCat(cmd, "-ovc lavc -lavcopts vcodec=mpeg4:vhq:mbd=2:trell"); EndIf If(ENCODER == MPEG_ENCODE) // create the parameter file for mpeg_encode - System 'echo "PATTERN I" > /tmp/tmp.par' ; - System 'echo "BASE_FILE_FORMAT JPEG" >> /tmp/tmp.par' ; - System 'echo "GOP_SIZE 30" >> /tmp/tmp.par' ; - System 'echo "SLICES_PER_FRAME 1" >> /tmp/tmp.par' ; - System 'echo "PIXEL HALF" >> /tmp/tmp.par' ; - System 'echo "RANGE 10" >> /tmp/tmp.par' ; - System 'echo "PSEARCH_ALG TWOLEVEL" >> /tmp/tmp.par' ; - System 'echo "BSEARCH_ALG CROSS2" >> /tmp/tmp.par' ; - System 'echo "IQSCALE 1" >> /tmp/tmp.par' ; - System 'echo "PQSCALE 10" >> /tmp/tmp.par' ; - System 'echo "BQSCALE 25" >> /tmp/tmp.par' ; - System 'echo "REFERENCE_FRAME DECODED" >> /tmp/tmp.par' ; - System 'echo "OUTPUT /tmp/animation.mpg" >> /tmp/tmp.par' ; - System 'echo "INPUT_CONVERT *" >> /tmp/tmp.par' ; - System 'echo "INPUT_DIR /tmp" >> /tmp/tmp.par' ; - System 'echo "INPUT" >> /tmp/tmp.par' ; - System Sprintf('echo "tmp*.jpg [001-%03g]" >> /tmp/tmp.par', NUM_FRAMES) ; - System 'echo "END_INPUT" >> /tmp/tmp.par' ; - // Call mpeg_encode + par = StrCat(PATH, "/tmp.par"); + System StrCat('echo "PATTERN I" > ', par); + System StrCat('echo "BASE_FILE_FORMAT JPEG" >> ', par); + System StrCat('echo "GOP_SIZE 30" >> ', par); + System StrCat('echo "SLICES_PER_FRAME 1" >> ', par); + System StrCat('echo "PIXEL HALF" >> ', par); + System StrCat('echo "RANGE 10" >> ', par); + System StrCat('echo "PSEARCH_ALG TWOLEVEL" >> ', par); + System StrCat('echo "BSEARCH_ALG CROSS2" >> ', par); + System StrCat('echo "IQSCALE 1" >> ', par); + System StrCat('echo "PQSCALE 10" >> ', par); + System StrCat('echo "BQSCALE 25" >> ', par); + System StrCat('echo "REFERENCE_FRAME DECODED" >> ', par); + System StrCat(StrCat(StrCat('echo "OUTPUT ', PATH), '/animation.mpg" >> '), par); + System StrCat('echo "INPUT_CONVERT *" >> ', par); + System StrCat(StrCat(StrCat('echo "INPUT_DIR ', PATH), '" >> '), par); + System StrCat('echo "INPUT" >> ', par); + System StrCat(Sprintf('echo "tmp*.jpg [001-%03g]" >> ', NUM_FRAMES), par); + System StrCat('echo "END_INPUT" >> ', par); + // call mpeg_encode System "mpeg_encode /tmp/tmp.par" ; EndIf // Clean-up temp files? -cleanup = GetValue("Remove temporary files? +CLEANUP = GetValue(StrCat(StrCat("Remove temporary files? -(The final animation has been saved in /tmp/animation.{gif,mpg})", 1); +(The final animation has been saved in ", PATH), "/animation.{gif,mpg})"), 0); -If(cleanup) +If(CLEANUP) If(ENCODER == WHIRLGIF) - System "rm -f /tmp/tmp*.gif" ; + System StrCat(StrCat("rm -f ", PATH), "/tmp*.gif"); EndIf - If(ENCODER == MPEG_ENCODE || ENCODER == MENCODER) - System "rm -f /tmp/tmp*.jpg /tmp/tmp.par" ; + If(ENCODER == MPEG_ENCODE) + System StrCat(StrCat("rm -f ", PATH), "/tmp*.{jpg,par}"); + EndIf + If(ENCODER == MENCODER) + System StrCat(StrCat("rm -f ", PATH), "/tmp*.png"); EndIf EndIf diff --git a/demos/rotate.script b/demos/rotate.script index d911e3bafa1d9e5209adec8d82adfc3c4bbb9dae..a29cd9bb68f2099af5252c45f8ce79232095c4e4 100644 --- a/demos/rotate.script +++ b/demos/rotate.script @@ -1,6 +1,8 @@ // This script creates an mpeg or gif animation by applying // incremental rotations around the 3 coordinate axes +PATH = "/tmp"; + neww = GetValue("Width of animation? (enter 0 to keep current width)", 640); newh = GetValue("Height of animation? (enter 0 to keep current height)", 640); steps = GetValue("Number of steps", 360); @@ -36,9 +38,12 @@ For (1:steps) If(method == WHIRLGIF) Print Sprintf("/tmp/tmp%03g.gif", index); EndIf - If(method == MPEG_ENCODE || method == MENCODER) + If(method == MPEG_ENCODE) Print Sprintf("/tmp/tmp%03g.jpg", index); EndIf + If(method == MENCODER) + Print Sprintf("/tmp/tmp%03g.png", index); + EndIf EndFor NUM_FRAMES = index; diff --git a/doc/texinfo/gmsh.texi b/doc/texinfo/gmsh.texi index acfab898ce2693a0eb93f142590c83f0c2a3db74..d65901bb94309329bbb44018abcc0be61aebb117 100644 --- a/doc/texinfo/gmsh.texi +++ b/doc/texinfo/gmsh.texi @@ -1371,22 +1371,27 @@ Character expressions are defined as: StrRelative ( @var{char-expression} ) | StrCat ( @var{char-expression} , @var{char-expression} ) | Sprintf ( @var{char-expression} , @var{expression-list} ) | - Sprintf ( @var{char-expression} ) - Sprintf ( @var{char-option} ) + Sprintf ( @var{char-expression} ) | + Sprintf ( @var{char-option} ) | + GetEnv ( @var{char-expression} ) | + GetString ( @var{char-expression} , @var{char-expression} ) @end example @noindent The third and fourth cases in this definition permit to take the -prefix (e.g. to remove the extension) or the relative path of a string. The -fifth case permits to concatenate two character expressions, and the sixth -and seventh are equivalent to the @code{sprintf} C function (where -@var{char-expression} is a format string that can contain floating point -formatting characters: @code{%e}, @code{%g}, etc.). The last case permits to -use the value of a @var{char-option} as a @var{char-expression}. The -various @w{@var{char-option}s} are listed in @ref{Options}. +prefix (e.g. to remove the extension) or the relative path of a +string. The fifth case permits to concatenate two character expressions, +and the sixth and seventh are equivalent to the @code{sprintf} C +function (where @var{char-expression} is a format string that can +contain floating point formatting characters: @code{%e}, @code{%g}, +etc.). The eigth case permits to use the value of a @var{char-option} as +a @var{char-expression}. The ninth case gets the value of an environment +variable from the operating system. The last case in the definition +allows to ask the user for a value interactively. The various +@w{@var{char-option}s} are listed in @ref{Options}. Character expressions are mostly used to specify non-numeric options and input/output file names. See @ref{t8.geo}, for an interesting usage of -@w{@var{char-expression}s} in an animation script. +@w{@var{char-expression}s} in an animation script. @c ......................................................................... @c Color expressions