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 aAdded 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