home *** CD-ROM | disk | FTP | other *** search
/ MPEG Toolkit / MPEG Toolkit.iso / win / mpg2w11b / mpeg2enc / mpeg2enc.c < prev    next >
Encoding:
C/C++ Source or Header  |  1997-01-01  |  25.7 KB  |  914 lines

  1. #include <windows.h>
  2. #include <commdlg.h>
  3. #include <assert.h>
  4. #include <setjmp.h>
  5. #include <io.h>
  6. #include "resource.h"
  7. #define APPNAME            "Mpeg2Encode" /* The name of this application */
  8. #define BASEWINDOWTITLE    "MPEG2 Software Simulation" /* The title bar text */
  9. #define MAXFILENAME        256           /* maximum length of file pathname      */
  10. #define MAXCUSTFILTER      40            /* maximum size of custom filter buffer */
  11.  
  12. // MS Windows related variables
  13. LRESULT CALLBACK WndProc(HWND   hWnd,       // window handle
  14.                          UINT   message,    // type of message
  15.                          WPARAM uParam,     // additional information
  16.                          LPARAM lParam);    // additional information
  17. static HINSTANCE   hInst;          // current instance
  18. static HWND        ghWnd   =NULL;  // handle to main window
  19. static char        szFileName[MAXFILENAME]="";
  20. static unsigned short gusState;
  21. static jmp_buf     env;
  22. extern int         __argc;
  23. extern char      **__argv;
  24. #define argc       __argc
  25. #define argv       __argv
  26.  
  27. #define   START     0
  28. #define        READY        1
  29. #define   PLAYING   2
  30. #define   PAUSED    3
  31. #define   FINISH    4
  32. #define        STOP        5
  33.  
  34. #include <stdio.h>
  35. #include <stdlib.h>
  36.  
  37. #define GLOBAL /* used by global.h */
  38. #include "config.h"
  39. #include "global.h"
  40.  
  41. /* private prototypes */
  42. static void init _ANSI_ARGS_((void));
  43. static void readparmfile _ANSI_ARGS_((char *fname));
  44. static void readquantmat _ANSI_ARGS_((void));
  45.  
  46.  
  47. // MS Windows related functions
  48. /////////////////////////////////////////////////////////////////////////////
  49. //
  50. // yield function to simulate multitasking on MS Windows
  51. //
  52. void myYield(void)
  53. {
  54.     MSG        msg;
  55.  
  56.   if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
  57.   {
  58.     TranslateMessage(&msg);// Translates virtual key codes
  59.     DispatchMessage(&msg); // Dispatches message to window
  60.     }
  61.   if (gusState==PAUSED)
  62.      longjmp(env,error);
  63. }
  64.  
  65. //
  66. // initializations
  67. //
  68. static BOOL InitApplication(HINSTANCE hInstance)
  69. {
  70.    WNDCLASS  wc;
  71.  
  72.    // Fill in window class structure with parameters that describe the
  73.    // main window.
  74.  
  75.    wc.style         = CS_OWNDC | CS_HREDRAW | CS_VREDRAW;// Class style(s).
  76.    wc.lpfnWndProc   = (WNDPROC)WndProc;           // Window Procedure
  77.    wc.cbClsExtra    = 0;                          // No per-class extra data.
  78.    wc.cbWndExtra    = 0;                          // No per-window extra data.
  79.    wc.hInstance     = hInstance;                  // Owner of this class
  80.    wc.hIcon         = LoadIcon (hInstance, APPNAME); // Icon name from .RC
  81.    wc.hCursor       = LoadCursor(NULL, IDC_ARROW);// Cursor
  82.    wc.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);   // Default color
  83.    wc.lpszMenuName  = APPNAME;                    // Menu name from .RC
  84.    wc.lpszClassName = APPNAME;                    // Name to register as
  85.  
  86.    // Register the window class and return success/failure code.
  87.    return (RegisterClass(&wc));
  88. }
  89.  
  90. static BOOL InitInstance(HINSTANCE hInstance,int       nCmdShow)
  91. {
  92.  
  93.     // Save the instance handle in static variable, which will be used in
  94.     // many subsequence calls from this application to Windows.
  95.  
  96.     hInst = hInstance; // Store instance handle in our global variable
  97.  
  98.     // Create a main window for this application instance.
  99.  
  100.     ghWnd = CreateWindow(APPNAME,            // See RegisterClass() call.
  101.                          BASEWINDOWTITLE,    // Text for window title bar.
  102.                          WS_OVERLAPPEDWINDOW &
  103.                          ~WS_THICKFRAME &
  104.                          ~WS_MAXIMIZEBOX,    // Window style.
  105.                          CW_USEDEFAULT,
  106.                          0,
  107.                          CW_USEDEFAULT,
  108.                          0,                  // Use default positioning
  109.                          NULL,               // Overlapped windows have no parent.
  110.                          NULL,               // Use the window class menu.
  111.                          hInstance,          // This instance owns this window.
  112.                          NULL                // We don't use any data in our WM_CREATE
  113.         );
  114.  
  115.     // If window could not be created, return "failure"
  116.     if (!ghWnd)
  117.        return (FALSE);
  118.  
  119.     // Make the window visible; update its client area; and return "success"
  120.     ShowWindow(ghWnd, nCmdShow); // Show the window
  121.     UpdateWindow(ghWnd);         // Sends WM_PAINT message
  122.  
  123.     return (TRUE);              // We succeeded...
  124.  
  125. }
  126.  
  127. //
  128. // prompts the user for the efile name
  129. //
  130. static BOOL AskUserFileName(char szFileName[],char szFileTitle[], char szFilterSpec[], BOOL bSave)
  131. {
  132.    /* new variables for common dialogs */
  133.    static char         szInitialDirectory[MAXFILENAME]="";
  134.           OPENFILENAME ofn;
  135.  
  136.    memset(&ofn,0,sizeof(ofn));
  137.  
  138.    /* fill in non-variant fields of OPENFILENAME struct. */
  139.    ofn.lStructSize       = sizeof(OPENFILENAME);
  140.    ofn.hwndOwner         = ghWnd;
  141.    ofn.lpstrFilter       = szFilterSpec;
  142.    ofn.lpstrCustomFilter = NULL;
  143.    ofn.nMaxCustFilter    = 0;
  144.    ofn.nFilterIndex      = 0;
  145.    ofn.lpstrFile         = szFileName;
  146.    ofn.nMaxFile          = MAXFILENAME;
  147.    if (!szInitialDirectory[0])
  148.       GetModuleFileName(hInst, szInitialDirectory, MAXFILENAME);
  149.  
  150.    // strip the file name
  151.    *(LPSTR)strrchr(szInitialDirectory,'\\')=0;
  152.  
  153.    ofn.lpstrInitialDir     = szInitialDirectory;
  154.    ofn.lpstrFileTitle      = szFileTitle;
  155.    ofn.nMaxFileTitle       = MAXFILENAME;
  156.    ofn.lpstrTitle          = NULL;
  157.    ofn.lpstrDefExt         = "MPG";
  158.    ofn.Flags               = 0;
  159.  
  160.    if (bSave)
  161.    {
  162.       if (!GetSaveFileName ((LPOPENFILENAME)&ofn))
  163.          return FALSE;
  164.    }
  165.    else if (!GetOpenFileName ((LPOPENFILENAME)&ofn))
  166.       return FALSE;
  167.  
  168.    // save the current directory
  169.    lstrcpy(szInitialDirectory,szFileName);
  170.    return TRUE;
  171. }
  172.  
  173.  
  174. /*********************************************************************************
  175.  *
  176.  * About box
  177.  *
  178. *********************************************************************************
  179. */
  180.  
  181. BOOL CALLBACK About(HWND   hDlg,         // window handle of the dialog box
  182.                     UINT   message,      // type of message
  183.                     WPARAM uParam,       // message-specific information
  184.                     LPARAM lParam)
  185. {
  186.    switch (message)
  187.    {
  188.       case WM_COMMAND:                     // message: received a command
  189.          if (LOWORD(uParam) == IDOK || LOWORD(uParam) == IDCANCEL)
  190.          {
  191.             EndDialog(hDlg, TRUE);        // Exit the dialog
  192.             return (TRUE);
  193.          }
  194.          break;
  195.    }
  196.    return (FALSE); // Didn't process the message
  197.  
  198.    lParam; // This will prevent 'unused formal parameter' warnings
  199. }
  200.  
  201. //
  202. // Main window procedure
  203. //
  204. LRESULT CALLBACK WndProc(HWND   hWnd,       // window handle
  205.                          UINT   message,    // type of message
  206.                          WPARAM uParam,     // additional information
  207.                          LPARAM lParam)     // additional information
  208. {
  209.    switch (message)
  210.    {
  211.      case WM_CLOSE:
  212.       if (gusState==PLAYING)
  213.          gusState = PAUSED;
  214.         myYield();
  215.       return (DefWindowProc(hWnd, message, uParam, lParam));
  216.         break;
  217.  
  218.  
  219.      case WM_DESTROY:  // message: window being destroyed
  220.       if (gusState==PLAYING)
  221.          gusState = PAUSED;
  222.         myYield();
  223.       PostQuitMessage(0);
  224.       break;
  225.  
  226.      case WM_COMMAND:  // message: command from application menu
  227.       {
  228.         int wmId, wmEvent;
  229.  
  230.         wmId    = LOWORD(uParam);
  231.         wmEvent = HIWORD(uParam);
  232.  
  233.         switch (wmId)
  234.         {
  235.            case IDM_FILE_OPEN_PARAMS:
  236.            {
  237.               static char szFilterSpec[]="Encoder Parameter File\0*.PAR\0\All Files\0\*.*\0\0";
  238.               char szWindowTitle[80];
  239.               char szFileTitle[MAXFILENAME];
  240.  
  241.               szFileName[0]=0;
  242.               if (!AskUserFileName (szFileName,szFileTitle,szFilterSpec,0))
  243.                  return FALSE;
  244.  
  245.               lstrcpy(szWindowTitle, BASEWINDOWTITLE);
  246.               lstrcat(szWindowTitle, " - ");
  247.               lstrcat(szWindowTitle, szFileTitle);
  248.               SetWindowText(hWnd, szFileTitle);
  249.  
  250.               // enable play menu
  251.               EnableMenuItem(GetMenu(hWnd), IDM_RUN, MF_ENABLED);
  252.  
  253.               gusState = READY;
  254.               break;
  255.            }
  256.  
  257.            case IDM_RUN:
  258.            {
  259.               static char szFilterSpec[]="MPEG2 Video Files\0*.M2V\0MPEG1 Video Files\0*.M1V\0MPEG Files\0*.MPG\0All Files (*.*)\0*.*\0";
  260.               char  szWindowTitle[256];
  261.               char  szOldWindowTitle[256];
  262.               char  szTargetName[MAXFILENAME];
  263.               char  szFileTitle [MAXFILENAME];
  264.               char *argv[]={NULL,szFileName,szTargetName};
  265.               int e;
  266.  
  267.               szTargetName[0]=0;
  268.               if (!AskUserFileName (szTargetName,szFileTitle,szFilterSpec,1))
  269.                  return FALSE;
  270.  
  271.               GetWindowText(hWnd, szOldWindowTitle, 256);
  272.               lstrcpy(szWindowTitle, szOldWindowTitle);
  273.               lstrcat(szWindowTitle, " - ");
  274.               lstrcat(szWindowTitle, szTargetName);
  275.               SetWindowText(hWnd, szWindowTitle);
  276.  
  277.               // disable play menu while playing
  278.               EnableMenuItem(GetMenu(hWnd), IDM_STOP, MF_ENABLED);
  279.               EnableMenuItem(GetMenu(hWnd), IDM_RUN, MF_GRAYED | MF_DISABLED);
  280.               EnableMenuItem(GetMenu(hWnd), IDM_FILE_OPEN_PARAMS, MF_GRAYED | MF_DISABLED);
  281.  
  282.               // play the movie. It returns after the playing ended
  283.               gusState = PLAYING;
  284.               e=setjmp(env);
  285.               if (!e)
  286.                  main(3,argv);
  287.               gusState = STOP;
  288.  
  289.               // disable stop menu
  290.               EnableMenuItem(GetMenu(hWnd), IDM_STOP, MF_GRAYED | MF_DISABLED);
  291.               EnableMenuItem(GetMenu(hWnd), IDM_RUN, MF_ENABLED);
  292.               EnableMenuItem(GetMenu(hWnd), IDM_FILE_OPEN_PARAMS, MF_ENABLED);
  293.               SetWindowText(hWnd, szOldWindowTitle);
  294.               break;
  295.            }
  296.            case IDM_STOP:
  297.               if (gusState==PLAYING)
  298.                  gusState=PAUSED;
  299.               // force a task switch to allow the decoder to see the stop command
  300.               myYield();
  301.               break;
  302.  
  303.            case IDM_EXIT:
  304.               if (gusState==PLAYING)
  305.                  gusState=PAUSED;
  306.               // force a task switch to allow the decoder to see the stop command
  307.               myYield();
  308.               SendMessage(hWnd, WM_CLOSE, 0, 0l);
  309.               break;
  310.  
  311.            case IDM_ABOUT:
  312.            {
  313.               FARPROC lpProcAbout;  // pointer to the "About" function
  314.  
  315.               lpProcAbout = MakeProcInstance((FARPROC)About, hInst);
  316.               DialogBox(hInst,                 // current instance
  317.                         "AboutBox",            // dlg resource to use
  318.                         hWnd,                  // parent handle
  319.                         (DLGPROC)lpProcAbout); // About() instance address
  320.  
  321.               FreeProcInstance(lpProcAbout);
  322.               break;
  323.            }
  324.  
  325.         }
  326.         break;
  327.       }
  328.  
  329.      default:          // Passes it on if unproccessed
  330.         return (DefWindowProc(hWnd, message, uParam, lParam));
  331.    }
  332.    return (0);
  333. }
  334.  
  335. //
  336. // program entry point
  337. //
  338. int APIENTRY WinMain(HINSTANCE   hInstance,
  339.                      HINSTANCE   hPrevInstance,
  340.                      LPSTR       lpCmdLine,
  341.                      int         nCmdShow)
  342. {
  343.     MSG msg;
  344.  
  345.     if (!hPrevInstance)
  346.        // Other instances of app running?
  347.         if (!InitApplication(hInstance))
  348.            // Initialize shared things
  349.            return (FALSE);     // Exits if unable to initialize
  350.  
  351.     /* Perform initializations that apply to a specific instance */
  352.     if (!InitInstance(hInstance, nCmdShow))
  353.        return (FALSE);
  354.  
  355.     gusState = STOP;
  356.  
  357.     /* Acquire and dispatch messages until a WM_QUIT message is received. */
  358.     while (GetMessage(&msg, // message structure
  359.                       NULL,   // handle of window receiving the message
  360.                       0,      // lowest message to examine
  361.                       0))     // highest message to examine
  362.     {
  363.         TranslateMessage(&msg);// Translates virtual key codes
  364.         DispatchMessage(&msg); // Dispatches message to window
  365.     }
  366.  
  367.     return (msg.wParam); // Returns the value from PostQuitMessage
  368.  
  369.     lpCmdLine; // This will prevent 'unused formal parameter' warnings
  370. }
  371.  
  372. void Output(char *pFormatInfo, ...)
  373. {
  374.     va_list    marker;
  375.     char    szPrintBuffer[512];
  376.  
  377.     va_start(marker, pFormatInfo);
  378.  
  379.     wvsprintf(szPrintBuffer, pFormatInfo, marker);
  380.  
  381.     OutputDebugString(szPrintBuffer);
  382.     myYield();
  383. }
  384.  
  385. void message(char *pFormatInfo, ...)
  386. {
  387.     va_list    marker;
  388.     char    szPrintBuffer[512];
  389.  
  390.     va_start(marker, pFormatInfo);
  391.  
  392.     wvsprintf(szPrintBuffer, pFormatInfo, marker);
  393.  
  394.     {
  395.        HDC  hDC;
  396.  
  397.        hDC=GetDC(ghWnd);
  398.        TextOut(hDC,10,10,szPrintBuffer,strlen(szPrintBuffer));
  399.        ReleaseDC(ghWnd,hDC);
  400.     }
  401.     myYield();
  402. }
  403.  
  404. int main(argc,argv)
  405. int argc;
  406. char *argv[];
  407. {
  408.   if (argc!=3)
  409.   {
  410.     printf("\n%s, %s\n",version,author);
  411.     printf("Usage: mpeg2encode in.par out.m2v\n");
  412.     exit(0);
  413.   }
  414.  
  415.   /* read parameter file */
  416.   readparmfile(argv[1]);
  417.  
  418.   /* read quantization matrices */
  419.   readquantmat();
  420.  
  421.   /* open output file */
  422.   if (!(outfile=fopen(argv[2],"wb")))
  423.   {
  424.     sprintf(errortext,"Couldn't create output file %s",argv[1]);
  425.     error(errortext);
  426.   }
  427.  
  428.   init();
  429.   putseq();
  430.  
  431.   fclose(outfile);
  432.   fclose(statfile);
  433.  
  434.   return 0;
  435. }
  436.  
  437. static void init()
  438. {
  439.   int i, size;
  440.   static int block_count_tab[3] = {6,8,12};
  441.  
  442.   initbits();
  443.   init_fdct();
  444.   init_idct();
  445.  
  446.   /* Non-linear qscale not yet implemented */
  447.   q_scale_type=0;
  448.  
  449.   /* round picture dimensions to nearest multiple of 16 or 32 */
  450.   mb_width = (horizontal_size+15)/16;
  451.   mb_height = prog_seq ? (vertical_size+15)/16 : 2*((vertical_size+31)/32);
  452.   mb_height2 = fieldpic ? mb_height>>1 : mb_height; /* for field pictures */
  453.   width = 16*mb_width;
  454.   height = 16*mb_height;
  455.  
  456.   chrom_width = (chroma_format==CHROMA444) ? width : width>>1;
  457.   chrom_height = (chroma_format!=CHROMA420) ? height : height>>1;
  458.  
  459.   height2 = fieldpic ? height>>1 : height;
  460.   width2 = fieldpic ? width<<1 : width;
  461.   chrom_width2 = fieldpic ? chrom_width<<1 : chrom_width;
  462.  
  463.   block_count = block_count_tab[chroma_format-1];
  464.  
  465.   /* clip table */
  466.   if (!(clp = (unsigned char *)malloc(1024)))
  467.     error("malloc failed\n");
  468.   clp+= 384;
  469.   for (i=-384; i<640; i++)
  470.     clp[i] = (i<0) ? 0 : ((i>255) ? 255 : i);
  471.  
  472.   for (i=0; i<3; i++)
  473.   {
  474.     size = (i==0) ? width*height : chrom_width*chrom_height;
  475.  
  476.     if (!(newrefframe[i] = (unsigned char *)malloc(size)))
  477.       error("malloc failed\n");
  478.     if (!(oldrefframe[i] = (unsigned char *)malloc(size)))
  479.       error("malloc failed\n");
  480.     if (!(auxframe[i] = (unsigned char *)malloc(size)))
  481.       error("malloc failed\n");
  482.     if (!(neworgframe[i] = (unsigned char *)malloc(size)))
  483.       error("malloc failed\n");
  484.     if (!(oldorgframe[i] = (unsigned char *)malloc(size)))
  485.       error("malloc failed\n");
  486.     if (!(auxorgframe[i] = (unsigned char *)malloc(size)))
  487.       error("malloc failed\n");
  488.     if (!(predframe[i] = (unsigned char *)malloc(size)))
  489.       error("malloc failed\n");
  490.   }
  491.  
  492.   mbinfo = (struct mbinfo *)malloc(mb_width*mb_height2*sizeof(struct mbinfo));
  493.  
  494.   if (!mbinfo)
  495.     error("malloc failed\n");
  496.  
  497.   blocks =
  498.     (short (*)[64])malloc(mb_width*mb_height2*block_count*sizeof(short [64]));
  499.  
  500.   if (!blocks)
  501.     error("malloc failed\n");
  502.  
  503.   /* open statistics output file */
  504.   if (statname[0]=='-')
  505.     statfile = stdout;
  506.   else if (!(statfile = fopen(statname,"w")))
  507.   {
  508.     sprintf(errortext,"Couldn't create statistics output file %s",statname);
  509.     error(errortext);
  510.   }
  511. }
  512.  
  513. void error(text)
  514. char *text;
  515. {
  516.   fprintf(stderr,text);
  517.   putc('\n',stderr);
  518.   exit(1);
  519. }
  520.  
  521. static void readparmfile(fname)
  522. char *fname;
  523. {
  524.   int i;
  525.   int h,m,s,f;
  526.   FILE *fd;
  527.   char line[256];
  528.   static double ratetab[8]=
  529.     {24000.0/1001.0,24.0,25.0,30000.0/1001.0,30.0,50.0,60000.0/1001.0,60.0};
  530.   extern int r,Xi,Xb,Xp,d0i,d0p,d0b; /* rate control */
  531.   extern double avg_act; /* rate control */
  532.  
  533.   if (!(fd = fopen(fname,"r")))
  534.   {
  535.     sprintf(errortext,"Couldn't open parameter file %s",fname);
  536.     error(errortext);
  537.   }
  538.  
  539.   fgets(id_string,254,fd);
  540.   fgets(line,254,fd); sscanf(line,"%s",tplorg);
  541.   fgets(line,254,fd); sscanf(line,"%s",tplref);
  542.   fgets(line,254,fd); sscanf(line,"%s",iqname);
  543.   fgets(line,254,fd); sscanf(line,"%s",niqname);
  544.   fgets(line,254,fd); sscanf(line,"%s",statname);
  545.   fgets(line,254,fd); sscanf(line,"%d",&inputtype);
  546.   fgets(line,254,fd); sscanf(line,"%d",&nframes);
  547.   fgets(line,254,fd); sscanf(line,"%d",&frame0);
  548.   fgets(line,254,fd); sscanf(line,"%d:%d:%d:%d",&h,&m,&s,&f);
  549.   fgets(line,254,fd); sscanf(line,"%d",&N);
  550.   fgets(line,254,fd); sscanf(line,"%d",&M);
  551.   fgets(line,254,fd); sscanf(line,"%d",&mpeg1);
  552.   fgets(line,254,fd); sscanf(line,"%d",&fieldpic);
  553.   fgets(line,254,fd); sscanf(line,"%d",&horizontal_size);
  554.   fgets(line,254,fd); sscanf(line,"%d",&vertical_size);
  555.   fgets(line,254,fd); sscanf(line,"%d",&aspectratio);
  556.   fgets(line,254,fd); sscanf(line,"%d",&frame_rate_code);
  557.   fgets(line,254,fd); sscanf(line,"%lf",&bit_rate);
  558.   fgets(line,254,fd); sscanf(line,"%d",&vbv_buffer_size);
  559.   fgets(line,254,fd); sscanf(line,"%d",&low_delay);
  560.   fgets(line,254,fd); sscanf(line,"%d",&constrparms);
  561.   fgets(line,254,fd); sscanf(line,"%d",&profile);
  562.   fgets(line,254,fd); sscanf(line,"%d",&level);
  563.   fgets(line,254,fd); sscanf(line,"%d",&prog_seq);
  564.   fgets(line,254,fd); sscanf(line,"%d",&chroma_format);
  565.   fgets(line,254,fd); sscanf(line,"%d",&video_format);
  566.   fgets(line,254,fd); sscanf(line,"%d",&color_primaries);
  567.   fgets(line,254,fd); sscanf(line,"%d",&transfer_characteristics);
  568.   fgets(line,254,fd); sscanf(line,"%d",&matrix_coefficients);
  569.   fgets(line,254,fd); sscanf(line,"%d",&display_horizontal_size);
  570.   fgets(line,254,fd); sscanf(line,"%d",&display_vertical_size);
  571.   fgets(line,254,fd); sscanf(line,"%d",&dc_prec);
  572.   fgets(line,254,fd); sscanf(line,"%d",&topfirst);
  573.   fgets(line,254,fd); sscanf(line,"%d %d %d",
  574.     frame_pred_dct_tab,frame_pred_dct_tab+1,frame_pred_dct_tab+2);
  575.  
  576.   fgets(line,254,fd); sscanf(line,"%d %d %d",
  577.     conceal_tab,conceal_tab+1,conceal_tab+2);
  578.  
  579.   fgets(line,254,fd); sscanf(line,"%d %d %d",
  580.     qscale_tab,qscale_tab+1,qscale_tab+2);
  581.  
  582.   fgets(line,254,fd); sscanf(line,"%d %d %d",
  583.     intravlc_tab,intravlc_tab+1,intravlc_tab+2);
  584.   fgets(line,254,fd); sscanf(line,"%d %d %d",
  585.     altscan_tab,altscan_tab+1,altscan_tab+2);
  586.   fgets(line,254,fd); sscanf(line,"%d",&repeatfirst);
  587.   fgets(line,254,fd); sscanf(line,"%d",&prog_frame);
  588. /* intra slice interval refresh period */
  589.   fgets(line,254,fd); sscanf(line,"%d",&P);
  590.   fgets(line,254,fd); sscanf(line,"%d",&r);
  591.   fgets(line,254,fd); sscanf(line,"%lf",&avg_act);
  592.   fgets(line,254,fd); sscanf(line,"%d",&Xi);
  593.   fgets(line,254,fd); sscanf(line,"%d",&Xp);
  594.   fgets(line,254,fd); sscanf(line,"%d",&Xb);
  595.   fgets(line,254,fd); sscanf(line,"%d",&d0i);
  596.   fgets(line,254,fd); sscanf(line,"%d",&d0p);
  597.   fgets(line,254,fd); sscanf(line,"%d",&d0b);
  598.  
  599.   if (N<1)
  600.     error("N must be positive");
  601.   if (M<1)
  602.     error("M must be positive");
  603.   if (N%M != 0)
  604.     error("N must be an integer multiple of M");
  605.  
  606.   motion_data = (struct motion_data *)malloc(M*sizeof(struct motion_data));
  607.   if (!motion_data)
  608.     error("Couldn't allocate motion_data\n");
  609.  
  610.   for (i=0; i<M; i++)
  611.   {
  612.     fgets(line,254,fd);
  613.     sscanf(line,"%d %d %d %d",
  614.       &motion_data[i].forw_hor_f_code, &motion_data[i].forw_vert_f_code,
  615.       &motion_data[i].sxf, &motion_data[i].syf);
  616.  
  617.     if (i!=0)
  618.     {
  619.       fgets(line,254,fd);
  620.       sscanf(line,"%d %d %d %d",
  621.         &motion_data[i].back_hor_f_code, &motion_data[i].back_vert_f_code,
  622.         &motion_data[i].sxb, &motion_data[i].syb);
  623.     }
  624.   }
  625.  
  626.   fclose(fd);
  627.  
  628.   /* make flags boolean (x!=0 -> x=1) */
  629.   mpeg1 = !!mpeg1;
  630.   fieldpic = !!fieldpic;
  631.   low_delay = !!low_delay;
  632.   constrparms = !!constrparms;
  633.   prog_seq = !!prog_seq;
  634.   topfirst = !!topfirst;
  635.  
  636.   for (i=0; i<3; i++)
  637.   {
  638.     frame_pred_dct_tab[i] = !!frame_pred_dct_tab[i];
  639.     conceal_tab[i] = !!conceal_tab[i];
  640.     qscale_tab[i] = !!qscale_tab[i];
  641.     intravlc_tab[i] = !!intravlc_tab[i];
  642.     altscan_tab[i] = !!altscan_tab[i];
  643.   }
  644.   repeatfirst = !!repeatfirst;
  645.   prog_frame = !!prog_frame;
  646.  
  647.   /* make sure MPEG specific parameters are valid */
  648.   range_checks();
  649.  
  650.   frame_rate = ratetab[frame_rate_code-1];
  651.  
  652.   /* timecode -> frame number */
  653.   tc0 = h;
  654.   tc0 = 60*tc0 + m;
  655.   tc0 = 60*tc0 + s;
  656.   tc0 = (int)(frame_rate+0.5)*tc0 + f;
  657.  
  658.   if (!mpeg1)
  659.   {
  660.     profile_and_level_checks();
  661.   }
  662.   else
  663.   {
  664.     /* MPEG-1 */
  665.     if (constrparms)
  666.     {
  667.       if (horizontal_size>768
  668.           || vertical_size>576
  669.           || ((horizontal_size+15)/16)*((vertical_size+15)/16)>396
  670.           || ((horizontal_size+15)/16)*((vertical_size+15)/16)*frame_rate>396*25.0
  671.           || frame_rate>30.0)
  672.       {
  673.         if (!quiet)
  674.           fprintf(stderr,"Warning: setting constrained_parameters_flag = 0\n");
  675.         constrparms = 0;
  676.       }
  677.     }
  678.  
  679.     if (constrparms)
  680.     {
  681.       for (i=0; i<M; i++)
  682.       {
  683.         if (motion_data[i].forw_hor_f_code>4)
  684.         {
  685.           if (!quiet)
  686.             fprintf(stderr,"Warning: setting constrained_parameters_flag = 0\n");
  687.           constrparms = 0;
  688.           break;
  689.         }
  690.  
  691.         if (motion_data[i].forw_vert_f_code>4)
  692.         {
  693.           if (!quiet)
  694.             fprintf(stderr,"Warning: setting constrained_parameters_flag = 0\n");
  695.           constrparms = 0;
  696.           break;
  697.         }
  698.  
  699.         if (i!=0)
  700.         {
  701.           if (motion_data[i].back_hor_f_code>4)
  702.           {
  703.             if (!quiet)
  704.               fprintf(stderr,"Warning: setting constrained_parameters_flag = 0\n");
  705.             constrparms = 0;
  706.             break;
  707.           }
  708.  
  709.           if (motion_data[i].back_vert_f_code>4)
  710.           {
  711.             if (!quiet)
  712.               fprintf(stderr,"Warning: setting constrained_parameters_flag = 0\n");
  713.             constrparms = 0;
  714.             break;
  715.           }
  716.         }
  717.       }
  718.     }
  719.   }
  720.  
  721.   /* relational checks */
  722.  
  723.   if (mpeg1)
  724.   {
  725.     if (!prog_seq)
  726.     {
  727.       if (!quiet)
  728.         fprintf(stderr,"Warning: setting progressive_sequence = 1\n");
  729.       prog_seq = 1;
  730.     }
  731.  
  732.     if (chroma_format!=CHROMA420)
  733.     {
  734.       if (!quiet)
  735.         fprintf(stderr,"Warning: setting chroma_format = 1 (4:2:0)\n");
  736.       chroma_format = CHROMA420;
  737.     }
  738.  
  739.     if (dc_prec!=0)
  740.     {
  741.       if (!quiet)
  742.         fprintf(stderr,"Warning: setting intra_dc_precision = 0\n");
  743.       dc_prec = 0;
  744.     }
  745.  
  746.     for (i=0; i<3; i++)
  747.       if (intravlc_tab[i])
  748.       {
  749.         if (!quiet)
  750.           fprintf(stderr,"Warning: setting intravlc_tab[%d] = 0\n",i);
  751.         intravlc_tab[i] = 0;
  752.       }
  753.     for (i=0; i<3; i++)
  754.       if (altscan_tab[i])
  755.       {
  756.         if (!quiet)
  757.           fprintf(stderr,"Warning: setting altscan_tab[%d] = 0\n",i);
  758.         altscan_tab[i] = 0;
  759.       }
  760.   }
  761.  
  762.   if (!mpeg1 && constrparms)
  763.   {
  764.     if (!quiet)
  765.       fprintf(stderr,"Warning: setting constrained_parameters_flag = 0\n");
  766.     constrparms = 0;
  767.   }
  768.  
  769.   if (prog_seq && !prog_frame)
  770.   {
  771.     if (!quiet)
  772.       fprintf(stderr,"Warning: setting progressive_frame = 1\n");
  773.     prog_frame = 1;
  774.   }
  775.  
  776.   if (prog_frame && fieldpic)
  777.   {
  778.     if (!quiet)
  779.       fprintf(stderr,"Warning: setting field_pictures = 0\n");
  780.     fieldpic = 0;
  781.   }
  782.  
  783.   if (!prog_frame && repeatfirst)
  784.   {
  785.     if (!quiet)
  786.       fprintf(stderr,"Warning: setting repeat_first_field = 0\n");
  787.     repeatfirst = 0;
  788.   }
  789.  
  790.   if (prog_frame)
  791.   {
  792.     for (i=0; i<3; i++)
  793.       if (!frame_pred_dct_tab[i])
  794.       {
  795.         if (!quiet)
  796.           fprintf(stderr,"Warning: setting frame_pred_frame_dct[%d] = 1\n",i);
  797.         frame_pred_dct_tab[i] = 1;
  798.       }
  799.   }
  800.  
  801.   if (prog_seq && !repeatfirst && topfirst)
  802.   {
  803.     if (!quiet)
  804.       fprintf(stderr,"Warning: setting top_field_first = 0\n");
  805.     topfirst = 0;
  806.   }
  807.  
  808.   /* search windows */
  809.   for (i=0; i<M; i++)
  810.   {
  811.     if (motion_data[i].sxf > (4<<motion_data[i].forw_hor_f_code)-1)
  812.     {
  813.       if (!quiet)
  814.         fprintf(stderr,
  815.           "Warning: reducing forward horizontal search width to %d\n",
  816.           (4<<motion_data[i].forw_hor_f_code)-1);
  817.       motion_data[i].sxf = (4<<motion_data[i].forw_hor_f_code)-1;
  818.     }
  819.  
  820.     if (motion_data[i].syf > (4<<motion_data[i].forw_vert_f_code)-1)
  821.     {
  822.       if (!quiet)
  823.         fprintf(stderr,
  824.           "Warning: reducing forward vertical search width to %d\n",
  825.           (4<<motion_data[i].forw_vert_f_code)-1);
  826.       motion_data[i].syf = (4<<motion_data[i].forw_vert_f_code)-1;
  827.     }
  828.  
  829.     if (i!=0)
  830.     {
  831.       if (motion_data[i].sxb > (4<<motion_data[i].back_hor_f_code)-1)
  832.       {
  833.         if (!quiet)
  834.           fprintf(stderr,
  835.             "Warning: reducing backward horizontal search width to %d\n",
  836.             (4<<motion_data[i].back_hor_f_code)-1);
  837.         motion_data[i].sxb = (4<<motion_data[i].back_hor_f_code)-1;
  838.       }
  839.  
  840.       if (motion_data[i].syb > (4<<motion_data[i].back_vert_f_code)-1)
  841.       {
  842.         if (!quiet)
  843.           fprintf(stderr,
  844.             "Warning: reducing backward vertical search width to %d\n",
  845.             (4<<motion_data[i].back_vert_f_code)-1);
  846.         motion_data[i].syb = (4<<motion_data[i].back_vert_f_code)-1;
  847.       }
  848.     }
  849.   }
  850.  
  851. }
  852.  
  853. static void readquantmat()
  854. {
  855.   int i,v;
  856.   FILE *fd;
  857.  
  858.   if (iqname[0]=='-')
  859.   {
  860.     /* use default intra matrix */
  861.     load_iquant = 0;
  862.     for (i=0; i<64; i++)
  863.       intra_q[i] = default_intra_quantizer_matrix[i];
  864.   }
  865.   else
  866.   {
  867.     /* read customized intra matrix */
  868.     load_iquant = 1;
  869.     if (!(fd = fopen(iqname,"r")))
  870.     {
  871.       sprintf(errortext,"Couldn't open quant matrix file %s",iqname);
  872.       error(errortext);
  873.     }
  874.  
  875.     for (i=0; i<64; i++)
  876.     {
  877.       fscanf(fd,"%d",&v);
  878.       if (v<1 || v>255)
  879.         error("invalid value in quant matrix");
  880.       intra_q[i] = v;
  881.     }
  882.  
  883.     fclose(fd);
  884.   }
  885.  
  886.   if (niqname[0]=='-')
  887.   {
  888.     /* use default non-intra matrix */
  889.     load_niquant = 0;
  890.     for (i=0; i<64; i++)
  891.       inter_q[i] = 16;
  892.   }
  893.   else
  894.   {
  895.     /* read customized non-intra matrix */
  896.     load_niquant = 1;
  897.     if (!(fd = fopen(niqname,"r")))
  898.     {
  899.       sprintf(errortext,"Couldn't open quant matrix file %s",niqname);
  900.       error(errortext);
  901.     }
  902.  
  903.     for (i=0; i<64; i++)
  904.     {
  905.       fscanf(fd,"%d",&v);
  906.       if (v<1 || v>255)
  907.         error("invalid value in quant matrix");
  908.       inter_q[i] = v;
  909.     }
  910.  
  911.     fclose(fd);
  912.   }
  913. }
  914.