configfile.c
上传用户:hjq518
上传日期:2021-12-09
资源大小:5084k
文件大小:48k
源码类别:

Audio

开发平台:

Visual C++

  1. /*!
  2.  ***********************************************************************
  3.  * file
  4.  *    configfile.c
  5.  * brief
  6.  *    Configuration handling.
  7.  * author
  8.  *  Main contributors (see contributors.h for copyright, address and affiliation details)
  9.  *    - Stephan Wenger           <stewe@cs.tu-berlin.de>
  10.  * note
  11.  *    In the future this module should hide the Parameters and offer only
  12.  *    Functions for their access.  Modules which make frequent use of some parameters
  13.  *    (e.g. picture size in macroblocks) are free to buffer them on local variables.
  14.  *    This will not only avoid global variable and make the code more readable, but also
  15.  *    speed it up.  It will also greatly facilitate future enhancements such as the
  16.  *    handling of different picture sizes in the same sequence.                         n
  17.  *                                                                                      n
  18.  *    For now, everything is just copied to the inp_par structure (gulp)
  19.  *
  20.  **************************************************************************************
  21.  * par Configuration File Format
  22.  **************************************************************************************
  23.  * Format is line oriented, maximum of one parameter per line                           n
  24.  *                                                                                      n
  25.  * Lines have the following format:                                                     n
  26.  * <ParameterName> = <ParameterValue> # Comments \n                                    n
  27.  * Whitespace is space and \t
  28.  * par
  29.  * <ParameterName> are the predefined names for Parameters and are case sensitive.
  30.  *   See configfile.h for the definition of those names and their mapping to
  31.  *   configinput->values.
  32.  * par
  33.  * <ParameterValue> are either integers [0..9]* or strings.
  34.  *   Integers must fit into the wordlengths, signed values are generally assumed.
  35.  *   Strings containing no whitespace characters can be used directly.  Strings containing
  36.  *   whitespace characters are to be inclosed in double quotes ("string with whitespace")
  37.  *   The double quote character is forbidden (may want to implement something smarter here).
  38.  * par
  39.  * Any Parameters whose ParameterName is undefined lead to the termination of the program
  40.  * with an error message.
  41.  *
  42.  * par Known bug/Shortcoming:
  43.  *    zero-length strings (i.e. to signal an non-existing file
  44.  *    have to be coded as "".
  45.  *
  46.  * par Rules for using command files
  47.  *                                                                                      n
  48.  * All Parameters are initially taken from DEFAULTCONFIGFILENAME, defined in configfile.h.
  49.  * If an -f <config> parameter is present in the command line then this file is used to
  50.  * update the defaults of DEFAULTCONFIGFILENAME.  There can be more than one -f parameters
  51.  * present.  If -p <ParameterName = ParameterValue> parameters are present then these
  52.  * override the default and the additional config file's settings, and are themselves
  53.  * overridden by future -p parameters.  There must be whitespace between -f and -p commands
  54.  * and their respective parameters
  55.  ***********************************************************************
  56.  */
  57. #define INCLUDED_BY_CONFIGFILE_C
  58. #include <sys/stat.h>
  59. #include "global.h"
  60. #include "configfile.h"
  61. #include "fmo.h"
  62. #include "conformance.h"
  63. char *GetConfigFileContent (char *Filename);
  64. static void ParseContent (char *buf, int bufsize);
  65. static int ParameterNameToMapIndex (char *s);
  66. static int InitEncoderParams(void);
  67. static int TestEncoderParams(int bitdepth_qp_scale[3]);
  68. static int DisplayEncoderParams(void);
  69. static void PatchInp (void);
  70. static int mb_width_cr[4] = {0,8, 8,16};
  71. static int mb_height_cr[4]= {0,8,16,16};
  72. #define MAX_ITEMS_TO_PARSE  10000
  73. /*!
  74.  ***********************************************************************
  75.  * brief
  76.  *   print help message and exit
  77.  ***********************************************************************
  78.  */
  79. void JMHelpExit (void)
  80. {
  81.   fprintf( stderr, "n   lencod [-h] [-d defenc.cfg] {[-f curenc1.cfg]...[-f curencN.cfg]}"
  82.     " {[-p EncParam1=EncValue1]..[-p EncParamM=EncValueM]}nn"
  83.     "## Parametersnn"
  84.     "## Optionsn"
  85.     "   -h :  prints function usagen"
  86.     "   -d :  use <defenc.cfg> as default file for parameter initializations.n"
  87.     "         If not used then file defaults to encoder.cfg in local directory.n"
  88.     "   -f :  read <curencM.cfg> for reseting selected encoder parameters.n"
  89.     "         Multiple files could be used that set different parametersn"
  90.     "   -p :  Set parameter <EncParamM> to <EncValueM>.n"
  91.     "         See default encoder.cfg file for description of all parameters.nn"
  92.     "## Supported video file formatsn"
  93.     "   RAW:  .yuv -> YUV 4:2:0nn"
  94.     "## Examples of usage:n"
  95.     "   lencodn"
  96.     "   lencod  -hn"
  97.     "   lencod  -d default.cfgn"
  98.     "   lencod  -f curenc1.cfgn"
  99.     "   lencod  -f curenc1.cfg -p InputFile="e:\data\container_qcif_30.yuv" -p SourceWidth=176 -p SourceHeight=144n"
  100.     "   lencod  -f curenc1.cfg -p FramesToBeEncoded=30 -p QPISlice=28 -p QPPSlice=28 -p QPBSlice=30n");
  101.   exit(-1);
  102. }
  103. /*!
  104.  ************************************************************************
  105.  * brief
  106.  *    Reads Input File Size 
  107.  *
  108.  ************************************************************************
  109.  */
  110. int64 getVideoFileSize(void)
  111. {
  112.    int64 fsize;   
  113.    lseek(p_in, 0, SEEK_END); 
  114.    fsize = tell((int) p_in); 
  115.    lseek(p_in, 0, SEEK_SET); 
  116.    return fsize;
  117. }
  118. /*!
  119.  ************************************************************************
  120.  * brief
  121.  *    Updates the number of frames to encode based on the file size
  122.  *
  123.  ************************************************************************
  124.  */
  125. static void getNumberOfFrames (void)
  126. {
  127.   int64 fsize = getVideoFileSize();
  128.   int64 isize = (int64) params->output.size;
  129.   int maxBitDepth = imax(params->output.bit_depth[0], params->output.bit_depth[1]);
  130.   isize <<= (maxBitDepth > 8)? 1: 0;
  131.   params->no_frames = (int) (((fsize - params->infile_header)/ isize) - params->start_frame - 1) / (1 + params->jumpd) + 1;
  132. }
  133. /*!
  134.  ************************************************************************
  135.  * brief
  136.  *    Updates images max values
  137.  *
  138.  ************************************************************************
  139.  */
  140. static void updateMaxValue(FrameFormat *format)
  141. {
  142.   format->max_value[0] = (1 << format->bit_depth[0]) - 1;
  143.   format->max_value_sq[0] = format->max_value[0] * format->max_value[0];
  144.   format->max_value[1] = (1 << format->bit_depth[1]) - 1;
  145.   format->max_value_sq[1] = format->max_value[1] * format->max_value[1];
  146.   format->max_value[2] = (1 << format->bit_depth[2]) - 1;
  147.   format->max_value_sq[2] = format->max_value[2] * format->max_value[2];
  148. }
  149. /*!
  150.  ************************************************************************
  151.  * brief
  152.  *    Update output format parameters (resolution & bit-depth) given input
  153.  *
  154.  ************************************************************************
  155.  */
  156. static void updateOutFormat(InputParameters *params)
  157. {
  158.   params->output.yuv_format = params->yuv_format;
  159.   params->source.yuv_format = params->yuv_format;
  160.   if (params->src_resize == 0)
  161.   {
  162.     params->output.width = params->source.width;
  163.     params->output.height = params->source.height;
  164.   }
  165.   if (params->yuv_format == YUV400) // reset bitdepth of chroma for 400 content
  166.   {
  167.     params->source.bit_depth[1] = 8;
  168.     params->output.bit_depth[1] = 8;
  169.     params->source.width_cr  = 0;
  170.     params->source.height_cr = 0;
  171.     params->output.width_cr  = 0;
  172.     params->output.height_cr = 0;
  173.   }
  174.   else
  175.   {
  176.     params->source.width_cr  = (params->source.width  * mb_width_cr [params->yuv_format]) >> 4;
  177.     params->source.height_cr = (params->source.height * mb_height_cr[params->yuv_format]) >> 4;
  178.     params->output.width_cr  = (params->output.width  * mb_width_cr [params->yuv_format]) >> 4;
  179.     params->output.height_cr = (params->output.height * mb_height_cr[params->yuv_format]) >> 4;
  180.   }
  181.   // source size
  182.   params->source.size_cmp[0] = params->source.width    * params->source.height;
  183.   params->source.size_cmp[1] = params->source.width_cr * params->source.height_cr;
  184.   params->source.size_cmp[2] = params->source.size_cmp[1];
  185.   params->source.size        = params->source.size_cmp[0] + params->source.size_cmp[1] + params->source.size_cmp[2];
  186.   params->source.mb_width    = params->source.width  / MB_BLOCK_SIZE;
  187.   params->source.mb_height   = params->source.height / MB_BLOCK_SIZE;
  188.   // output size (excluding padding)
  189.   params->output.size_cmp[0] = params->output.width * params->source.height;
  190.   params->output.size_cmp[1] = params->output.width_cr * params->source.height_cr;
  191.   params->output.size_cmp[2] = params->output.size_cmp[1];
  192.   params->output.size        = params->output.size_cmp[0] + params->output.size_cmp[1] + params->output.size_cmp[2];
  193.   params->output.mb_width    = params->output.width  / MB_BLOCK_SIZE;
  194.   params->output.mb_height   = params->output.height / MB_BLOCK_SIZE;
  195.   // both chroma components have the same bitdepth
  196.   params->source.bit_depth[2] = params->source.bit_depth[1];
  197.   params->output.bit_depth[2] = params->output.bit_depth[1];
  198.   
  199.   // if no bitdepth rescale ensure bitdepth is same
  200.   if (params->src_BitDepthRescale == 0) 
  201.   {    
  202.     params->output.bit_depth[0] = params->source.bit_depth[0];
  203.     params->output.bit_depth[1] = params->source.bit_depth[1];
  204.     params->output.bit_depth[2] = params->source.bit_depth[2];
  205.   }
  206.   
  207.   updateMaxValue(&params->source);
  208.   updateMaxValue(&params->output);
  209. }
  210. /*!
  211.  ***********************************************************************
  212.  * brief
  213.  *    Parse the command line parameters and read the config files.
  214.  * param ac
  215.  *    number of command line parameters
  216.  * param av
  217.  *    command line parameters
  218.  ***********************************************************************
  219.  */
  220. void Configure (int ac, char *av[])
  221. {
  222.   char *content = NULL;
  223.   int CLcount, ContentLen, NumberParams;
  224.   char *filename=DEFAULTCONFIGFILENAME;
  225.   memset (&configinput, 0, sizeof (InputParameters));
  226.   //Set default parameters.
  227.   printf ("Setting Default Parameters...n");
  228.   InitEncoderParams();
  229.   // Process default config file
  230.   CLcount = 1;
  231.   if (ac==2)
  232.   {
  233.     if (0 == strncmp (av[1], "-h", 2))
  234.     {
  235.       JMHelpExit();
  236.     }
  237.   }
  238.   if (ac>=3)
  239.   {
  240.     if (0 == strncmp (av[1], "-d", 2))
  241.     {
  242.       filename=av[2];
  243.       CLcount = 3;
  244.     }
  245.     if (0 == strncmp (av[1], "-h", 2))
  246.     {
  247.       JMHelpExit();
  248.     }
  249.   }
  250.   printf ("Parsing Configfile %s", filename);
  251.   content = GetConfigFileContent (filename);
  252.   if (NULL==content)
  253.     error (errortext, 300);
  254.   ParseContent (content, strlen(content));
  255.   printf ("n");
  256.   free (content);
  257.   // Parse the command line
  258.   while (CLcount < ac)
  259.   {
  260.     if (0 == strncmp (av[CLcount], "-h", 2))
  261.     {
  262.       JMHelpExit();
  263.     }
  264.     if (0 == strncmp (av[CLcount], "-f", 2))  // A file parameter?
  265.     {
  266.       content = GetConfigFileContent (av[CLcount+1]);
  267.       if (NULL==content)
  268.         error (errortext, 300);
  269.       printf ("Parsing Configfile %s", av[CLcount+1]);
  270.       ParseContent (content, strlen (content));
  271.       printf ("n");
  272.       free (content);
  273.       CLcount += 2;
  274.     } 
  275.     else
  276.     {
  277.       if (0 == strncmp (av[CLcount], "-p", 2))  // A config change?
  278.       {
  279.         // Collect all data until next parameter (starting with -<x> (x is any character)),
  280.         // put it into content, and parse content.
  281.         CLcount++;
  282.         ContentLen = 0;
  283.         NumberParams = CLcount;
  284.         // determine the necessary size for content
  285.         while (NumberParams < ac && av[NumberParams][0] != '-')
  286.           ContentLen += strlen (av[NumberParams++]);        // Space for all the strings
  287.         ContentLen += 1000;                     // Additional 1000 bytes for spaces and s
  288.         if ((content = malloc (ContentLen))==NULL) no_mem_exit("Configure: content");;
  289.         content[0] = '';
  290.         // concatenate all parameters identified before
  291.         while (CLcount < NumberParams)
  292.         {
  293.           char *source = &av[CLcount][0];
  294.           char *destin = &content[strlen (content)];
  295.           while (*source != '')
  296.           {
  297.             if (*source == '=')  // The Parser expects whitespace before and after '='
  298.             {
  299.               *destin++=' '; *destin++='='; *destin++=' ';  // Hence make sure we add it
  300.             } else
  301.               *destin++=*source;
  302.             source++;
  303.           }
  304.           *destin = '';
  305.           CLcount++;
  306.         }
  307.         printf ("Parsing command line string '%s'", content);
  308.         ParseContent (content, strlen(content));
  309.         free (content);
  310.         printf ("n");
  311.       }
  312.       else
  313.       {
  314.         snprintf (errortext, ET_SIZE, "Error in command line, ac %d, around string '%s', missing -f or -p parameters?", CLcount, av[CLcount]);
  315.         error (errortext, 300);
  316.       }
  317.     }
  318.   }
  319.   printf ("n");
  320.   PatchInp();
  321.   if (params->DisplayEncParams)
  322.     DisplayEncoderParams();
  323. }
  324. /*!
  325.  ***********************************************************************
  326.  * brief
  327.  *    allocates memory buf, opens file Filename in f, reads contents into
  328.  *    buf and returns buf
  329.  * param Filename
  330.  *    name of config file
  331.  * return
  332.  *    if successfull, content of config file
  333.  *    NULL in case of error. Error message will be set in errortext
  334.  ***********************************************************************
  335.  */
  336. char *GetConfigFileContent (char *Filename)
  337. {
  338.   long FileSize;
  339.   FILE *f;
  340.   char *buf;
  341.   if (NULL == (f = fopen (Filename, "r")))
  342.   {
  343.       snprintf (errortext, ET_SIZE, "Cannot open configuration file %s.", Filename);
  344.       return NULL;
  345.   }
  346.   if (0 != fseek (f, 0, SEEK_END))
  347.   {
  348.     snprintf (errortext, ET_SIZE, "Cannot fseek in configuration file %s.", Filename);
  349.     return NULL;
  350.   }
  351.   FileSize = ftell (f);
  352.   if (FileSize < 0 || FileSize > 100000)
  353.   {
  354.     snprintf (errortext, ET_SIZE, "Unreasonable Filesize %ld reported by ftell for configuration file %s.", FileSize, Filename);
  355.     return NULL;
  356.   }
  357.   if (0 != fseek (f, 0, SEEK_SET))
  358.   {
  359.     snprintf (errortext, ET_SIZE, "Cannot fseek in configuration file %s.", Filename);
  360.     return NULL;
  361.   }
  362.   if ((buf = malloc (FileSize + 1))==NULL) no_mem_exit("GetConfigFileContent: buf");
  363.   // Note that ftell() gives us the file size as the file system sees it.  The actual file size,
  364.   // as reported by fread() below will be often smaller due to CR/LF to CR conversion and/or
  365.   // control characters after the dos EOF marker in the file.
  366.   FileSize = fread (buf, 1, FileSize, f);
  367.   buf[FileSize] = '';
  368.   fclose (f);
  369.   return buf;
  370. }
  371. /*!
  372.  ***********************************************************************
  373.  * brief
  374.  *    Parses the character array buf and writes global variable input, which is defined in
  375.  *    configfile.h.  This hack will continue to be necessary to facilitate the addition of
  376.  *    new parameters through the Map[] mechanism (Need compiler-generated addresses in map[]).
  377.  * param buf
  378.  *    buffer to be parsed
  379.  * param bufsize
  380.  *    buffer size of buffer
  381.  ***********************************************************************
  382.  */
  383. void ParseContent (char *buf, int bufsize)
  384. {
  385.   char *items[MAX_ITEMS_TO_PARSE];
  386.   int MapIdx;
  387.   int item = 0;
  388.   int InString = 0, InItem = 0;
  389.   char *p = buf;
  390.   char *bufend = &buf[bufsize];
  391.   int IntContent;
  392.   double DoubleContent;
  393.   int i;
  394. // Stage one: Generate an argc/argv-type list in items[], without comments and whitespace.
  395. // This is context insensitive and could be done most easily with lex(1).
  396.   while (p < bufend)
  397.   {
  398.     switch (*p)
  399.     {
  400.       case 13:
  401.         p++;
  402.         break;
  403.       case '#':                 // Found comment
  404.         *p = '';              // Replace '#' with '' in case of comment immediately following integer or string
  405.         while (*p != 'n' && p < bufend)  // Skip till EOL or EOF, whichever comes first
  406.           p++;
  407.         InString = 0;
  408.         InItem = 0;
  409.         break;
  410.       case 'n':
  411.         InItem = 0;
  412.         InString = 0;
  413.         *p++='';
  414.         break;
  415.       case ' ':
  416.       case 't':              // Skip whitespace, leave state unchanged
  417.         if (InString)
  418.           p++;
  419.         else
  420.         {                     // Terminate non-strings once whitespace is found
  421.           *p++ = '';
  422.           InItem = 0;
  423.         }
  424.         break;
  425.       case '"':               // Begin/End of String
  426.         *p++ = '';
  427.         if (!InString)
  428.         {
  429.           items[item++] = p;
  430.           InItem = ~InItem;
  431.         }
  432.         else
  433.           InItem = 0;
  434.         InString = ~InString; // Toggle
  435.         break;
  436.       default:
  437.         if (!InItem)
  438.         {
  439.           items[item++] = p;
  440.           InItem = ~InItem;
  441.         }
  442.         p++;
  443.     }
  444.   }
  445.   item--;
  446.   for (i=0; i<item; i+= 3)
  447.   {
  448.     if (0 > (MapIdx = ParameterNameToMapIndex (items[i])))
  449.     {
  450.       //snprintf (errortext, ET_SIZE, " Parsing error in config file: Parameter Name '%s' not recognized.", items[i]);
  451.       //error (errortext, 300);
  452.       printf ("ntParsing error in config file: Parameter Name '%s' not recognized.", items[i]);
  453.       continue;
  454.     }
  455.     if (strcasecmp ("=", items[i+1]))
  456.     {
  457.       snprintf (errortext, ET_SIZE, " Parsing error in config file: '=' expected as the second token in each line.");
  458.       error (errortext, 300);
  459.     }
  460.     // Now interpret the Value, context sensitive...
  461.     switch (Map[MapIdx].Type)
  462.     {
  463.       case 0:           // Numerical
  464.         if (1 != sscanf (items[i+2], "%d", &IntContent))
  465.         {
  466.           snprintf (errortext, ET_SIZE, " Parsing error: Expected numerical value for Parameter of %s, found '%s'.", items[i], items[i+2]);
  467.           error (errortext, 300);
  468.         }
  469.         * (int *) (Map[MapIdx].Place) = IntContent;
  470.         printf (".");
  471.         break;
  472.       case 1:
  473.         strncpy ((char *) Map[MapIdx].Place, items [i+2], FILE_NAME_SIZE);
  474.         printf (".");
  475.         break;
  476.       case 2:           // Numerical double
  477.         if (1 != sscanf (items[i+2], "%lf", &DoubleContent))
  478.         {
  479.           snprintf (errortext, ET_SIZE, " Parsing error: Expected numerical value for Parameter of %s, found '%s'.", items[i], items[i+2]);
  480.           error (errortext, 300);
  481.         }
  482.         * (double *) (Map[MapIdx].Place) = DoubleContent;
  483.         printf (".");
  484.         break;
  485.       default:
  486.         error ("Unknown value type in the map definition of configfile.h",-1);
  487.     }
  488.   }
  489.   memcpy (params, &configinput, sizeof (InputParameters));
  490. }
  491. /*!
  492.  ***********************************************************************
  493.  * brief
  494.  *    Returns the index number from Map[] for a given parameter name.
  495.  * param s
  496.  *    parameter name string
  497.  * return
  498.  *    the index number if the string is a valid parameter name,         n
  499.  *    -1 for error
  500.  ***********************************************************************
  501.  */
  502. static int ParameterNameToMapIndex (char *s)
  503. {
  504.   int i = 0;
  505.   while (Map[i].TokenName != NULL)
  506.     if (0==strcasecmp (Map[i].TokenName, s))
  507.       return i;
  508.     else
  509.       i++;
  510.   return -1;
  511. }
  512. /*!
  513.  ***********************************************************************
  514.  * brief
  515.  *    Sets initial values for encoding parameters.
  516.  * return
  517.  *    -1 for error
  518.  ***********************************************************************
  519.  */
  520. static int InitEncoderParams(void)
  521. {
  522.   int i = 0;
  523.   while (Map[i].TokenName != NULL)
  524.   {
  525.     if (Map[i].Type == 0)
  526.         * (int *) (Map[i].Place) = (int) Map[i].Default;
  527.     else if (Map[i].Type == 2)
  528.     * (double *) (Map[i].Place) = Map[i].Default;
  529.       i++;
  530.   }
  531.   return -1;
  532. }
  533. /*!
  534.  ***********************************************************************
  535.  * brief
  536.  *    Validates encoding parameters.
  537.  * return
  538.  *    -1 for error
  539.  ***********************************************************************
  540.  */
  541. static int TestEncoderParams(int bitdepth_qp_scale[3])
  542. {
  543.   int i = 0;
  544.   while (Map[i].TokenName != NULL)
  545.   {
  546.     if (Map[i].param_limits == 1)
  547.     {
  548.       if (Map[i].Type == 0)
  549.       {
  550.         if ( * (int *) (Map[i].Place) < (int) Map[i].min_limit || * (int *) (Map[i].Place) > (int) Map[i].max_limit )
  551.         {
  552.           snprintf(errortext, ET_SIZE, "Error in input parameter %s. Check configuration file. Value should be in [%d, %d] range.", Map[i].TokenName, (int) Map[i].min_limit,(int)Map[i].max_limit );
  553.           error (errortext, 400);
  554.         }
  555.       }
  556.       else if (Map[i].Type == 2)
  557.       {
  558.         if ( * (double *) (Map[i].Place) < Map[i].min_limit || * (double *) (Map[i].Place) > Map[i].max_limit )
  559.         {
  560.           snprintf(errortext, ET_SIZE, "Error in input parameter %s. Check configuration file. Value should be in [%.2f, %.2f] range.", Map[i].TokenName,Map[i].min_limit ,Map[i].max_limit );
  561.           error (errortext, 400);
  562.         }
  563.       }
  564.     }
  565.     else if (Map[i].param_limits == 2)
  566.     {
  567.       if (Map[i].Type == 0)
  568.       {
  569.         if ( * (int *) (Map[i].Place) < (int) Map[i].min_limit )
  570.         {
  571.           snprintf(errortext, ET_SIZE, "Error in input parameter %s. Check configuration file. Value should not be smaller than %d.", Map[i].TokenName, (int) Map[i].min_limit);
  572.           error (errortext, 400);
  573.         }
  574.       }
  575.       else if (Map[i].Type == 2)
  576.       {
  577.         if ( * (double *) (Map[i].Place) < Map[i].min_limit )
  578.         {
  579.           snprintf(errortext, ET_SIZE, "Error in input parameter %s. Check configuration file. Value should not be smaller than %2.f.", Map[i].TokenName,Map[i].min_limit);
  580.           error (errortext, 400);
  581.         }
  582.       }
  583.     }
  584.     else if (Map[i].param_limits == 3) // Only used for QPs
  585.     {
  586.       
  587.       if (Map[i].Type == 0)
  588.       {
  589.         int cur_qp = * (int *) (Map[i].Place);
  590.         int min_qp = (int) (Map[i].min_limit - bitdepth_qp_scale[0]);
  591.         int max_qp = (int) Map[i].max_limit;
  592.         if (( cur_qp < min_qp ) || ( cur_qp > max_qp ))
  593.         {
  594.           snprintf(errortext, ET_SIZE, "Error in input parameter %s. Check configuration file. Value should be in [%d, %d] range.", Map[i].TokenName, min_qp, max_qp );
  595.           error (errortext, 400);
  596.         }
  597.       }
  598.     }
  599.     i++;
  600.   }
  601.   return -1;
  602. }
  603. /*!
  604.  ***********************************************************************
  605.  * brief
  606.  *    Outputs encoding parameters.
  607.  * return
  608.  *    -1 for error
  609.  ***********************************************************************
  610.  */
  611. static int DisplayEncoderParams(void)
  612. {
  613.   int i = 0;
  614.   printf("******************************************************n");
  615.   printf("*               Encoder Parameters                   *n");
  616.   printf("******************************************************n");
  617.   while (Map[i].TokenName != NULL)
  618.   {
  619.     if (Map[i].Type == 0)
  620.       printf("Parameter %s = %dn",Map[i].TokenName,* (int *) (Map[i].Place));
  621.     else if (Map[i].Type == 1)
  622.       printf("Parameter %s = ""%s""n",Map[i].TokenName,(char *)  (Map[i].Place));
  623.     else if (Map[i].Type == 2)
  624.       printf("Parameter %s = %.2fn",Map[i].TokenName,* (double *) (Map[i].Place));
  625.       i++;
  626.   }
  627.   printf("******************************************************n");
  628.   return -1;
  629. }
  630. /*!
  631.  ************************************************************************
  632.  * brief
  633.  *    calculate Ceil(Log2(uiVal))
  634.  ************************************************************************
  635.  */
  636. unsigned CeilLog2( unsigned uiVal)
  637. {
  638.   unsigned uiTmp = uiVal-1;
  639.   unsigned uiRet = 0;
  640.   while( uiTmp != 0 )
  641.   {
  642.     uiTmp >>= 1;
  643.     uiRet++;
  644.   }
  645.   return uiRet;
  646. }
  647. /*!
  648.  ************************************************************************
  649.  * brief
  650.  *    read the slice group configuration file. Returns without action
  651.  *    if type is not 0, 2 or 6
  652.  ************************************************************************
  653.  */
  654. void read_slice_group_info()
  655. {
  656.   FILE * sgfile=NULL;
  657.   int i;
  658.   int ret;
  659.   if ((params->slice_group_map_type != 0) && (params->slice_group_map_type != 2) && (params->slice_group_map_type != 6))
  660.   {
  661.     // nothing to do
  662.     return;
  663.   }
  664.   // do we have a file name (not only NULL character)
  665.   if (strlen (params->SliceGroupConfigFileName) <= 1)
  666.     error ("No slice group config file name specified", 500);
  667.     
  668.   // open file
  669.   sgfile = fopen(params->SliceGroupConfigFileName,"r");
  670.   if ( NULL==sgfile )
  671.   {
  672.     snprintf(errortext, ET_SIZE, "Error opening slice group file %s", params->SliceGroupConfigFileName);
  673.     error (errortext, 500);
  674.   }
  675.   switch (params->slice_group_map_type)
  676.   {
  677.   case 0:
  678.     params->run_length_minus1=(int *)malloc(sizeof(int)*(params->num_slice_groups_minus1+1));
  679.     if ( NULL==params->run_length_minus1 )
  680.     {
  681.       fclose(sgfile);
  682.       no_mem_exit("PatchInp: params->run_length_minus1");
  683.     }
  684.     // each line contains one 'run_length_minus1' value
  685.     for(i=0;i<=params->num_slice_groups_minus1;i++)
  686.     {
  687.       ret = fscanf(sgfile,"%d",(params->run_length_minus1+i));
  688.       fscanf(sgfile,"%*[^n]");
  689.       if ( 1!=ret )
  690.       {
  691.         fclose(sgfile);
  692.         snprintf(errortext, ET_SIZE, "Error while reading slice group config file (line %d)", i+1);
  693.         error (errortext, 500);
  694.       }
  695.     }
  696.     break;
  697.   case 2:
  698.     params->top_left=(int *)malloc(sizeof(int)*params->num_slice_groups_minus1);
  699.     params->bottom_right=(int *)malloc(sizeof(int)*params->num_slice_groups_minus1);
  700.     if (NULL==params->top_left)
  701.     {
  702.       fclose(sgfile);
  703.       no_mem_exit("PatchInp: params->top_left");
  704.     }
  705.     if (NULL==params->bottom_right)
  706.     {
  707.       fclose(sgfile);
  708.       no_mem_exit("PatchInp: params->bottom_right");
  709.     }
  710.     // every two lines contain 'top_left' and 'bottom_right' value
  711.     for(i=0;i<params->num_slice_groups_minus1;i++)
  712.     {
  713.       ret = fscanf(sgfile,"%d",(params->top_left+i));
  714.       fscanf(sgfile,"%*[^n]");
  715.       if ( 1!=ret )
  716.       {
  717.         fclose(sgfile);
  718.         snprintf(errortext, ET_SIZE, "Error while reading slice group config file (line %d)", 2*i +1);
  719.         error (errortext, 500);
  720.       }
  721.       ret = fscanf(sgfile,"%d",(params->bottom_right+i));
  722.       fscanf(sgfile,"%*[^n]");
  723.       if ( 1!=ret )
  724.       {
  725.         fclose(sgfile);
  726.         snprintf(errortext, ET_SIZE, "Error while reading slice group config file (line %d)", 2*i + 2);
  727.         error (errortext, 500);
  728.       }
  729.     }
  730.     break;
  731.   case 6:
  732.     {
  733.       int tmp;
  734.       int frame_mb_only;
  735.       int mb_width, mb_height, mapunit_height;
  736.       frame_mb_only = !(params->PicInterlace || params->MbInterlace);
  737.       mb_width  = (params->output.width + img->auto_crop_right)>>4;
  738.       mb_height = (params->output.height + img->auto_crop_bottom)>>4;
  739.       mapunit_height = mb_height / (2-frame_mb_only);
  740.       params->slice_group_id=(byte * ) malloc(sizeof(byte)*mapunit_height*mb_width);
  741.       if (NULL==params->slice_group_id)
  742.       {
  743.         fclose(sgfile);
  744.         no_mem_exit("PatchInp: params->slice_group_id");
  745.       }
  746.       // each line contains slice_group_id for one Macroblock
  747.       for (i=0;i<mapunit_height*mb_width;i++)
  748.       {
  749.         ret = fscanf(sgfile,"%d", &tmp);
  750.         params->slice_group_id[i]= (byte) tmp;
  751.         if ( 1!=ret )
  752.         {
  753.           fclose(sgfile);
  754.           snprintf(errortext, ET_SIZE, "Error while reading slice group config file (line %d)", i + 1);
  755.           error (errortext, 500);
  756.         }
  757.         if ( *(params->slice_group_id+i) > params->num_slice_groups_minus1 )
  758.         {
  759.           fclose(sgfile);
  760.           snprintf(errortext, ET_SIZE, "Error while reading slice group config file: slice_group_id not allowed (line %d)", i + 1);
  761.           error (errortext, 500);
  762.         }
  763.         fscanf(sgfile,"%*[^n]");
  764.       }
  765.     }
  766.     break;
  767.   default:
  768.     // we should not get here
  769.     error ("Wrong slice group type while reading config file", 500);
  770.     break;
  771.   }
  772.   // close file again
  773.   fclose(sgfile);
  774. }
  775. /*!
  776.  ***********************************************************************
  777.  * brief
  778.  *    Checks the input parameters for consistency.
  779.  ***********************************************************************
  780.  */
  781. static void PatchInp (void)
  782. {
  783.   int i,j;
  784.   int storedBplus1;
  785.   int bitdepth_qp_scale[3];
  786.   if (params->src_BitDepthRescale)
  787.   {
  788.     bitdepth_qp_scale [0] = 6*(params->output.bit_depth[0] - 8);
  789.     bitdepth_qp_scale [1] = 6*(params->output.bit_depth[1] - 8);
  790.     bitdepth_qp_scale [2] = 6*(params->output.bit_depth[2] - 8);
  791.   }
  792.   else
  793.   {
  794.     bitdepth_qp_scale [0] = 6*(params->source.bit_depth[0] - 8);
  795.     bitdepth_qp_scale [1] = 6*(params->source.bit_depth[1] - 8);
  796.     bitdepth_qp_scale [2] = 6*(params->source.bit_depth[2] - 8);
  797.   }
  798.   TestEncoderParams(bitdepth_qp_scale);
  799.   if (params->FrameRate == 0.0)
  800.     params->FrameRate = INIT_FRAME_RATE;
  801.   // Set block sizes
  802.   // Skip/Direct16x16
  803.   params->part_size[0][0] = 4;
  804.   params->part_size[0][1] = 4;
  805.   // 16x16
  806.   params->part_size[1][0] = 4;
  807.   params->part_size[1][1] = 4;
  808.   // 16x8
  809.   params->part_size[2][0] = 4;
  810.   params->part_size[2][1] = 2;
  811.   // 8x16
  812.   params->part_size[3][0] = 2;
  813.   params->part_size[3][1] = 4;
  814.   // 8x8
  815.   params->part_size[4][0] = 2;
  816.   params->part_size[4][1] = 2;
  817.   // 8x4
  818.   params->part_size[5][0] = 2;
  819.   params->part_size[5][1] = 1;
  820.   // 4x8
  821.   params->part_size[6][0] = 1;
  822.   params->part_size[6][1] = 2;
  823.   // 4x4
  824.   params->part_size[7][0] = 1;
  825.   params->part_size[7][1] = 1;
  826.   for (j = 0; j<8;j++)
  827.   {
  828.     for (i = 0; i<2; i++)
  829.     {
  830.       params->blc_size[j][i] = params->part_size[j][i] * BLOCK_SIZE;
  831.     }
  832.   }
  833.   if (params->idr_period && params->intra_delay && params->idr_period <= params->intra_delay)
  834.   {
  835.     snprintf(errortext, ET_SIZE, " IntraDelay cannot be larger than or equal to IDRPeriod.");
  836.     error (errortext, 500);
  837.   }
  838.   if (params->idr_period && params->intra_delay && params->EnableIDRGOP == 0)
  839.   {
  840.     snprintf(errortext, ET_SIZE, " IntraDelay can only be used with only 1 IDR or with EnableIDRGOP=1.");
  841.     error (errortext, 500);
  842.   }
  843.   if (params->idr_period && params->intra_delay && params->adaptive_idr_period)
  844.   {
  845.     snprintf(errortext, ET_SIZE, " IntraDelay can not be used with AdaptiveIDRPeriod.");
  846.     error (errortext, 500);
  847.   }
  848.   storedBplus1 = (params->BRefPictures ) ? params->successive_Bframe + 1: 1;
  849.   
  850.   if (params->Log2MaxFNumMinus4 == -1)
  851.   {    
  852.     log2_max_frame_num_minus4 = iClip3(0,12, (int) (CeilLog2(params->no_frames * storedBplus1) - 4));    
  853.   }
  854.   else  
  855.     log2_max_frame_num_minus4 = params->Log2MaxFNumMinus4;
  856.   max_frame_num = 1 << (log2_max_frame_num_minus4 + 4);
  857.   if (log2_max_frame_num_minus4 == 0 && params->num_ref_frames == 16)
  858.   {
  859.     snprintf(errortext, ET_SIZE, " NumberReferenceFrames=%d and Log2MaxFNumMinus4=%d may lead to an invalid value of frame_num.", params->num_ref_frames, params-> Log2MaxFNumMinus4);
  860.     error (errortext, 500);
  861.   }
  862.   // set proper log2_max_pic_order_cnt_lsb_minus4.
  863.   if (params->Log2MaxPOCLsbMinus4 == - 1)
  864.     log2_max_pic_order_cnt_lsb_minus4 = iClip3(0,12, (int) (CeilLog2( 2*params->no_frames * (params->jumpd + 1)) - 4));
  865.   else
  866.     log2_max_pic_order_cnt_lsb_minus4 = params->Log2MaxPOCLsbMinus4;
  867.   max_pic_order_cnt_lsb = 1 << (log2_max_pic_order_cnt_lsb_minus4 + 4);
  868.   if (((1<<(log2_max_pic_order_cnt_lsb_minus4 + 3)) < params->jumpd * 4) && params->Log2MaxPOCLsbMinus4 != -1)
  869.     error("log2_max_pic_order_cnt_lsb_minus4 might not be sufficient for encoding. Increase value.",400);
  870.   // B picture consistency check
  871.   if(params->successive_Bframe > params->jumpd)
  872.   {
  873.     snprintf(errortext, ET_SIZE, "Number of B-frames %d can not exceed the number of frames skipped", params->successive_Bframe);
  874.     error (errortext, 400);
  875.   }
  876.   // Direct Mode consistency check
  877.   if(params->successive_Bframe && params->direct_spatial_mv_pred_flag != DIR_SPATIAL && params->direct_spatial_mv_pred_flag != DIR_TEMPORAL)
  878.   {
  879.     snprintf(errortext, ET_SIZE, "Unsupported direct mode=%d, use TEMPORAL=0 or SPATIAL=1", params->direct_spatial_mv_pred_flag);
  880.     error (errortext, 400);
  881.   }
  882.   if (params->PicInterlace>0 || params->MbInterlace>0)
  883.   {
  884.     if (params->directInferenceFlag==0)
  885.       printf("nWarning: DirectInferenceFlag set to 1 due to interlace coding.");
  886.     params->directInferenceFlag = 1;
  887.   }
  888.   // Open Files
  889.   if ((p_in=open(params->infile, OPENFLAGS_READ))==-1)
  890.   {
  891.     snprintf(errortext, ET_SIZE, "Input file %s does not exist",params->infile);
  892.     error (errortext, 500);
  893.   }
  894.   updateOutFormat(params);
  895.   if (params->no_frames == -1)
  896.   {
  897.     getNumberOfFrames();
  898.   }
  899.   if (params->no_frames < 1)
  900.   {      
  901.     snprintf(errortext, ET_SIZE, "Not enough frames to encode (%d)", params->no_frames);
  902.     error (errortext, 500);
  903.   }
  904.   if (strlen (params->ReconFile) > 0 && (p_dec=open(params->ReconFile, OPENFLAGS_WRITE, OPEN_PERMISSIONS))==-1)
  905.   {
  906.     snprintf(errortext, ET_SIZE, "Error open file %s", params->ReconFile);
  907.     error (errortext, 500);
  908.   }
  909. #if TRACE
  910.   if (strlen (params->TraceFile) > 0 && (p_trace=fopen(params->TraceFile,"w"))==NULL)
  911.   {
  912.     snprintf(errortext, ET_SIZE, "Error open file %s", params->TraceFile);
  913.     error (errortext, 500);
  914.   }
  915. #endif
  916.   if (params->output.width % 16 != 0)
  917.   {
  918.     img->auto_crop_right = 16 - (params->output.width % 16);
  919.   }
  920.   else
  921.   {
  922.     img->auto_crop_right=0;
  923.   }
  924.   if (params->PicInterlace || params->MbInterlace)
  925.   {
  926.     if ((params->output.height & 0x01) != 0)
  927.     {
  928.       error ("even number of lines required for interlaced coding", 500);
  929.     }
  930.     
  931.     if (params->output.height % 32 != 0)
  932.     {
  933.       img->auto_crop_bottom = 32-(params->output.height % 32);
  934.     }
  935.     else
  936.     {
  937.       img->auto_crop_bottom=0;
  938.     }
  939.   }
  940.   else
  941.   {
  942.     if (params->output.height % 16 != 0)
  943.     {
  944.       img->auto_crop_bottom = 16-(params->output.height % 16);
  945.     }
  946.     else
  947.     {
  948.       img->auto_crop_bottom=0;
  949.     }
  950.   }
  951.   if (img->auto_crop_bottom || img->auto_crop_right)
  952.   {
  953.     fprintf (stderr, "Warning: Automatic cropping activated: Coded frame Size: %dx%dn", 
  954.       params->output.width + img->auto_crop_right, params->output.height + img->auto_crop_bottom);
  955.   }
  956.   if ((params->slice_mode==1)&&(params->MbInterlace!=0))
  957.   {
  958.     if ((params->slice_argument%2)!=0)
  959.     {
  960.       fprintf ( stderr, "Warning: slice border within macroblock pair. ");
  961.       if (params->slice_argument > 1)
  962.       {
  963.         params->slice_argument--;
  964.       }
  965.       else
  966.       {
  967.         params->slice_argument++;
  968.       }
  969.       fprintf ( stderr, "Using %d MBs per slice.n", params->slice_argument);
  970.     }
  971.   }
  972.   // read the slice group configuration file. Only for types 0, 2 or 6
  973.   if ( 0 != params->num_slice_groups_minus1 )
  974.   {
  975.     read_slice_group_info();
  976.   }
  977.   if (params->WPMCPrecision && (params->RDPictureDecision != 1 || params->GenerateMultiplePPS != 1) )
  978.   {
  979.     snprintf(errortext, ET_SIZE, "WPMCPrecision requires both RDPictureDecision=1 and GenerateMultiplePPS=1.n");
  980.     error (errortext, 400);
  981.   }
  982.   if (params->WPMCPrecision && params->WPMCPrecFullRef && params->num_ref_frames < 16 )
  983.   {
  984.     params->num_ref_frames++;
  985.     if ( params->P_List0_refs )
  986.       params->P_List0_refs++;
  987.     else
  988.       params->P_List0_refs = params->num_ref_frames;
  989.     if ( params->B_List0_refs )
  990.       params->B_List0_refs++;
  991.     else
  992.       params->B_List0_refs = params->num_ref_frames;
  993.     if ( params->B_List1_refs )
  994.       params->B_List1_refs++;
  995.     else
  996.       params->B_List1_refs = params->num_ref_frames;
  997.   }
  998.   else if ( params->WPMCPrecision && params->WPMCPrecFullRef )
  999.   {
  1000.     snprintf(errortext, ET_SIZE, "WPMCPrecFullRef requires NumberReferenceFrames < 16.n");
  1001.     error (errortext, 400);
  1002.   }
  1003.   if (params->ReferenceReorder && params->MbInterlace )
  1004.   {
  1005.     snprintf(errortext, ET_SIZE, "ReferenceReorder not supported with MBAFFn");
  1006.     error (errortext, 400);
  1007.   }
  1008.   if (params->PocMemoryManagement && params->MbInterlace )
  1009.   {
  1010.     snprintf(errortext, ET_SIZE, "PocMemoryManagement not supported with MBAFFn");
  1011.     error (errortext, 400);
  1012.   }
  1013.   if ((!params->rdopt)&&(params->MbInterlace))
  1014.   {
  1015.     snprintf(errortext, ET_SIZE, "MB AFF is not compatible with non-rd-optimized coding.");
  1016.     error (errortext, 500);
  1017.   }
  1018.   // check RDoptimization mode and profile. FMD does not support Frex Profiles.
  1019.   if (params->rdopt==2 && ( params->ProfileIDC>=FREXT_HP || params->ProfileIDC==FREXT_CAVLC444 ))
  1020.   {
  1021.     snprintf(errortext, ET_SIZE, "Fast Mode Decision methods not supported in FREX Profiles");
  1022.     error (errortext, 500);
  1023.   }
  1024.   if ( (params->MEErrorMetric[Q_PEL] == ERROR_SATD && params->MEErrorMetric[H_PEL] == ERROR_SAD && params->MEErrorMetric[F_PEL] == ERROR_SAD)
  1025.     && params->SearchMode > FAST_FULL_SEARCH && params->SearchMode < EPZS)
  1026.   {
  1027.     snprintf(errortext, ET_SIZE, "MEDistortionQPel=2, MEDistortionHPel=0, MEDistortionFPel=0 is not allowed when SearchMode is set to 1 or 2.");
  1028.     error (errortext, 500);
  1029.   }
  1030.   // Tian Dong: May 31, 2002
  1031.   // The number of frames in one sub-seq in enhanced layer should not exceed
  1032.   // the number of reference frame number.
  1033.   if ( params->NumFramesInELSubSeq > params->num_ref_frames || params->NumFramesInELSubSeq < 0 )
  1034.   {
  1035.     snprintf(errortext, ET_SIZE, "NumFramesInELSubSeq (%d) is out of range [0,%d).", params->NumFramesInELSubSeq, params->num_ref_frames);
  1036.     error (errortext, 500);
  1037.   }
  1038.   // Tian Dong: Enhanced GOP is not supported in bitstream mode. September, 2002
  1039.   if ( params->NumFramesInELSubSeq > 0 && params->of_mode == PAR_OF_ANNEXB )
  1040.   {
  1041.     snprintf(errortext, ET_SIZE, "Enhanced GOP is not supported in bitstream mode and RTP mode yet.");
  1042.     error (errortext, 500);
  1043.   }
  1044.   // Tian Dong (Sept 2002)
  1045.   // The AFF is not compatible with spare picture for the time being.
  1046.   if ((params->PicInterlace || params->MbInterlace) && params->SparePictureOption == TRUE)
  1047.   {
  1048.     snprintf(errortext, ET_SIZE, "AFF is not compatible with spare picture.");
  1049.     error (errortext, 500);
  1050.   }
  1051.   // Only the RTP mode is compatible with spare picture for the time being.
  1052.   if (params->of_mode != PAR_OF_RTP && params->SparePictureOption == TRUE)
  1053.   {
  1054.     snprintf(errortext, ET_SIZE, "Only RTP output mode is compatible with spare picture features.");
  1055.     error (errortext, 500);
  1056.   }
  1057.   if( (params->WeightedPrediction > 0 || params->WeightedBiprediction > 0) && (params->MbInterlace))
  1058.   {
  1059.     snprintf(errortext, ET_SIZE, "Weighted prediction coding is not supported for MB AFF currently.");
  1060.     error (errortext, 500);
  1061.   }
  1062.   if ( params->NumFramesInELSubSeq > 0 && params->WeightedPrediction > 0)
  1063.   {
  1064.     snprintf(errortext, ET_SIZE, "Enhanced GOP is not supported in weighted prediction coding mode yet.");
  1065.     error (errortext, 500);
  1066.   }
  1067.   //! the number of slice groups is forced to be 1 for slice group type 3-5
  1068.   if(params->num_slice_groups_minus1 > 0)
  1069.   {
  1070.     if( (params->slice_group_map_type >= 3) && (params->slice_group_map_type<=5) )
  1071.       params->num_slice_groups_minus1 = 1;
  1072.   }
  1073.   // Rate control
  1074.   if(params->RCEnable)
  1075.   {
  1076.     if (params->basicunit == 0)
  1077.       params->basicunit = (params->output.height + img->auto_crop_bottom)*(params->output.width + img->auto_crop_right)/256;
  1078.     if ( ((params->output.height + img->auto_crop_bottom)*(params->output.width + img->auto_crop_right)/256) % params->basicunit != 0)
  1079.     {
  1080.       snprintf(errortext, ET_SIZE, "Frame size in macroblocks must be a multiple of BasicUnit.");
  1081.       error (errortext, 500);
  1082.     }
  1083.     if ( params->RCUpdateMode == RC_MODE_1 && 
  1084.       !( (params->intra_period == 1 || params->idr_period == 1 || params->BRefPictures == 2 ) && !params->successive_Bframe ) )
  1085.     {
  1086.       snprintf(errortext, ET_SIZE, "Use RCUpdateMode = 1 only for all intra or all B-slice coding.");
  1087.       error (errortext, 500);
  1088.     }
  1089.     if ( params->BRefPictures == 2 && params->intra_period == 0 && params->RCUpdateMode != RC_MODE_1 )
  1090.     {
  1091.       snprintf(errortext, ET_SIZE, "Use RCUpdateMode = 1 for all B-slice coding.");
  1092.       error (errortext, 500);
  1093.     }
  1094.     if ( params->HierarchicalCoding && params->RCUpdateMode != RC_MODE_2 && params->RCUpdateMode != RC_MODE_3 )
  1095.     {
  1096.       snprintf(errortext, ET_SIZE, "Use RCUpdateMode = 2 or 3 for hierarchical B-picture coding.");
  1097.       error (errortext, 500);
  1098.     }
  1099.     if ( (params->RCUpdateMode != RC_MODE_1) && (params->intra_period == 1) )
  1100.     {
  1101.       snprintf(errortext, ET_SIZE, "Use RCUpdateMode = 1 for all intra coding.");
  1102.       error (errortext, 500);
  1103.     }
  1104.   }
  1105.   if ((params->successive_Bframe)&&(params->BRefPictures)&&(params->idr_period)&&(params->pic_order_cnt_type!=0))
  1106.   {
  1107.     error("Stored B pictures combined with IDR pictures only supported in Picture Order Count type 0n",-1000);
  1108.   }
  1109.   if( !params->direct_spatial_mv_pred_flag && params->num_ref_frames<2 && params->successive_Bframe >0)
  1110.     error("temporal direct needs at least 2 ref framesn",-1000);
  1111.   if (params->rdopt == 0)
  1112.   {
  1113.     if ((params->DisableSubpelME && params->MEErrorMetric[F_PEL] != params->ModeDecisionMetric))
  1114.     {
  1115.       snprintf(errortext, ET_SIZE, "nLast refinement level (FPel) distortion not the same as Mode decision distortion.nPlease update MEDistortionFPel (%d) and/or  MDDistortion(%d).", params->MEErrorMetric[F_PEL], params->ModeDecisionMetric);
  1116.       error (errortext, 500);
  1117.     }
  1118.     else if (params->MEErrorMetric[Q_PEL] != params->ModeDecisionMetric)
  1119.     {
  1120.       snprintf(errortext, ET_SIZE, "nLast refinement level (QPel) distortion not the same as Mode decision distortion.nPlease update MEDistortionQPel (%d) and/or  MDDistortion(%d).", params->MEErrorMetric[Q_PEL], params->ModeDecisionMetric);
  1121.       error (errortext, 500);
  1122.     }
  1123.   }
  1124.   // frext
  1125.   if(params->Transform8x8Mode && params->sp_periodicity /*SP-frames*/)
  1126.   {
  1127.     snprintf(errortext, ET_SIZE, "nThe new 8x8 mode is not implemented for sp-frames.");
  1128.     error (errortext, 500);
  1129.   }
  1130.   if(params->Transform8x8Mode && ( params->ProfileIDC<FREXT_HP && params->ProfileIDC!=FREXT_CAVLC444 ))
  1131.   {
  1132.     snprintf(errortext, ET_SIZE, "nTransform8x8Mode may be used only with ProfileIDC %d to %d.", FREXT_HP, FREXT_Hi444);
  1133.     error (errortext, 500);
  1134.   }
  1135.   if (params->DisableIntra4x4 == 1 && params->DisableIntra16x16 == 1 && params->EnableIPCM == 0 && params->Transform8x8Mode == 0)
  1136.   {
  1137.     snprintf(errortext, ET_SIZE, "nAt least one intra prediction mode needs to be enabled.");
  1138.     error (errortext, 500);
  1139.   }
  1140.   if(params->ScalingMatrixPresentFlag && ( params->ProfileIDC<FREXT_HP && params->ProfileIDC!=FREXT_CAVLC444 ))
  1141.   {
  1142.     snprintf(errortext, ET_SIZE, "nScalingMatrixPresentFlag may be used only with ProfileIDC %d to %d.", FREXT_HP, FREXT_Hi444);
  1143.     error (errortext, 500);
  1144.   }
  1145.   if(params->yuv_format==YUV422 && ( params->ProfileIDC < FREXT_Hi422 && params->ProfileIDC!=FREXT_CAVLC444 ))
  1146.   {
  1147.     snprintf(errortext, ET_SIZE, "nFRExt Profile(YUV Format) Error!nYUV422 can be used only with ProfileIDC %d or %dn",FREXT_Hi422, FREXT_Hi444);
  1148.     error (errortext, 500);
  1149.   }
  1150.   if(params->yuv_format==YUV444 && ( params->ProfileIDC < FREXT_Hi444 && params->ProfileIDC!=FREXT_CAVLC444 ))
  1151.   {
  1152.     snprintf(errortext, ET_SIZE, "nFRExt Profile(YUV Format) Error!nYUV444 can be used only with ProfileIDC %d.n",FREXT_Hi444);
  1153.     error (errortext, 500);
  1154.   }
  1155.   if (params->successive_Bframe && ((params->BiPredMotionEstimation) && (params->search_range < params->BiPredMESearchRange)))
  1156.   {
  1157.     snprintf(errortext, ET_SIZE, "nBiPredMESearchRange must be smaller or equal SearchRange.");
  1158.     error (errortext, 500);
  1159.   }
  1160.   // check consistency
  1161.   if ( params->ChromaMEEnable && !(params->ChromaMCBuffer) ) 
  1162.   {
  1163.     snprintf(errortext, ET_SIZE, "nChromaMCBuffer must be set to 1 if ChromaMEEnable is set.");
  1164.     error (errortext, 500);
  1165.   }
  1166.   if ( params->ChromaMEEnable && params->yuv_format ==  YUV400) 
  1167.   {
  1168.     fprintf(stderr, "Warning: ChromaMEEnable cannot be used with YUV400 color format, disabling ChromaMEEnable.n");
  1169.     params->ChromaMEEnable = 0;
  1170.   }
  1171.   if ( (params->ChromaMCBuffer == 0) && (( params->yuv_format ==  YUV444) && (!params->separate_colour_plane_flag)) )
  1172.   {
  1173.     fprintf(stderr, "Warning: Enabling ChromaMCBuffer for YUV444 combined color coding.n");
  1174.     params->ChromaMCBuffer = 1;
  1175.   }
  1176.   if (params->EnableOpenGOP)
  1177.     params->ReferenceReorder = 1;
  1178.   if (params->SearchMode != EPZS)
  1179.     params->EPZSSubPelGrid = 0;
  1180.   params->EPZSGrid = params->EPZSSubPelGrid << 1;
  1181.   if (params->redundant_pic_flag)
  1182.   {
  1183.     if (params->PicInterlace || params->MbInterlace)
  1184.     {
  1185.       snprintf(errortext, ET_SIZE, "Redundant pictures cannot be used with interlaced tools.");
  1186.       error (errortext, 500);
  1187.     }
  1188.     if (params->RDPictureDecision)
  1189.     {
  1190.       snprintf(errortext, ET_SIZE, "Redundant pictures cannot be used with RDPictureDecision.");
  1191.       error (errortext, 500);
  1192.     }
  1193.     if (params->successive_Bframe)
  1194.     {
  1195.       snprintf(errortext, ET_SIZE, "Redundant pictures cannot be used with B frames.");
  1196.       error (errortext, 500);
  1197.     }
  1198.     if (params->PrimaryGOPLength < (1 << params->NumRedundantHierarchy))
  1199.     {
  1200.       snprintf(errortext, ET_SIZE, "PrimaryGOPLength must be equal or greater than 2^NumRedundantHierarchy.");
  1201.       error (errortext, 500);
  1202.     }
  1203.     if (params->num_ref_frames < params->PrimaryGOPLength)
  1204.     {
  1205.       snprintf(errortext, ET_SIZE, "NumberReferenceFrames must be greater than or equal to PrimaryGOPLength.");
  1206.       error (errortext, 500);
  1207.     }
  1208.   }
  1209.   if (params->num_ref_frames == 1 && params->successive_Bframe)
  1210.   {
  1211.     fprintf( stderr, "nWarning: B slices used but only one reference allocated within reference buffer.n");
  1212.     fprintf( stderr, "         Performance may be considerably compromised! n");
  1213.     fprintf( stderr, "         2 or more references recommended for use with B slices.n");
  1214.   }
  1215.   if ((params->HierarchicalCoding || params->BRefPictures) && params->successive_Bframe)
  1216.   {
  1217.     fprintf( stderr, "nWarning: Hierarchical coding or Referenced B slices used.n");
  1218.     fprintf( stderr, "         Make sure that you have allocated enough referencesn");
  1219.     fprintf( stderr, "         in reference buffer to achieve best performance.n");
  1220.   }
  1221.   if (params->FastMDEnable == 0)
  1222.   {
  1223.     params->FastIntraMD = 0;
  1224.     params->FastIntra16x16 = 0;
  1225.     params->FastIntra4x4 = 0;
  1226.     params->FastIntra8x8 = 0;
  1227.     params->FastIntraChroma = 0;
  1228.   }
  1229.   if (params->UseRDOQuant == 1)
  1230.   {
  1231.     if (params->rdopt == 0)
  1232.     {
  1233.       snprintf(errortext, ET_SIZE, "RDO Quantization not supported with low complexity RDO.");
  1234.       error (errortext, 500);
  1235.     }
  1236.     if (params->MbInterlace != 0)
  1237.     {
  1238.       printf("RDO Quantization currently not supported with MBAFF. Option disabled.n");
  1239.       params->UseRDOQuant = 0;
  1240.       params->RDOQ_QP_Num = 1;
  1241.       params->RDOQ_CP_MV = 0;
  1242.       params->RDOQ_CP_Mode = 0;
  1243.     }
  1244.     else
  1245.     {
  1246.       params->AdaptiveRounding = 0;
  1247.       printf("AdaptiveRounding is disabled when RDO Quantization is usedn");
  1248.       if (params->RDOQ_QP_Num < 2)
  1249.       {
  1250.         params->RDOQ_CP_MV = 0;
  1251.         params->RDOQ_CP_Mode = 0;
  1252.       }
  1253.     }
  1254.   }
  1255.   else
  1256.   {
  1257.     params->RDOQ_QP_Num = 1;
  1258.     params->RDOQ_CP_MV = 0;
  1259.     params->RDOQ_CP_Mode = 0;
  1260.   }
  1261.   ProfileCheck();
  1262.   LevelCheck();
  1263. }
  1264. void PatchInputNoFrames(void)
  1265. {
  1266.   // Tian Dong: May 31, 2002
  1267.   // If the frames are grouped into two layers, "FramesToBeEncoded" in the config file
  1268.   // will give the number of frames which are in the base layer. Here we let params->no_frames
  1269.   // be the total frame numbers.
  1270.   params->no_frames = 1 + (params->no_frames - 1) * (params->NumFramesInELSubSeq + 1);
  1271. }