home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: Multimed / Multimed.zip / mpegplay.zip / VIDEO.C < prev    next >
C/C++ Source or Header  |  1994-02-13  |  113KB  |  4,051 lines

  1. /*
  2.  * Copyright (c) 1992 The Regents of the University of California.
  3.  * All rights reserved.  
  4.  *
  5.  * Permission to use, copy, modify, and distribute this software and its
  6.  * documentation for any purpose, without fee, and without written agreement is
  7.  * hereby granted, provided that the above copyright notice and the following
  8.  * two paragraphs appear in all copies of this software.
  9.  *
  10.  * IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR
  11.  * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
  12.  * OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF
  13.  * CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  14.  *
  15.  * THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,
  16.  * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
  17.  * AND FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
  18.  * ON AN "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO
  19.  * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
  20.  */
  21. /* This file contains C code that implements
  22.  * the video decoder model.
  23.  */
  24.  
  25. #include <stdio.h>
  26. #include <stdlib.h>
  27. #include <assert.h>
  28.  
  29. /* @@@ AK, System header vary on OS/2 */
  30. /* @@@ Make do with time.h with time() call */
  31. #if defined(OS2)
  32. #include <sys/types.h>
  33. #include <time.h>
  34. #elif defined(MIPS)
  35. #include <sys/types.h>
  36. #include <sys/system.h>
  37. #else
  38. #include <sys/time.h>
  39. #endif
  40.  
  41. #include "decoders.h"
  42. #include "video.h"
  43. #include "util.h"
  44. #include "proto.h"
  45.  
  46. /* Declarations of functions. */
  47. static void ReconIMBlock();
  48. static void ReconPMBlock();
  49. static void ReconBMBlock();
  50. static void ReconBiMBlock();
  51. static void ReconSkippedBlock();
  52. static void DoPictureDisplay();
  53. static int ParseSeqHead();
  54. static int ParseGOP();
  55. static int ParsePicture();
  56. static int ParseSlice();
  57. static int ParseMacroBlock();
  58. static void ProcessSkippedPFrameMBlocks();
  59. static void ProcessSkippedBFrameMBlocks();
  60.  
  61. extern int ditherType;
  62. char *ditherFlags;
  63.  
  64. /* Macro for returning 1 if num is positive, -1 if negative, 0 if 0. */
  65.  
  66. #define Sign(num) ((num > 0) ? 1 : ((num == 0) ? 0 : -1))
  67.  
  68. /* Declare global pointer to vid stream used for current decoding. */
  69.  
  70. VidStream *curVidStream = NULL;
  71.  
  72. /* Set up array for fast conversion from zig zag order to row/column
  73.    coordinates.
  74. */
  75.  
  76. int zigzag[64][2] = {
  77.   0, 0, 1, 0, 0, 1, 0, 2, 1, 1, 2, 0, 3, 0, 2, 1, 1, 2, 0, 3, 0, 4, 1, 3,
  78.   2, 2, 3, 1, 4, 0, 5, 0, 4, 1, 3, 2, 2, 3, 1, 4, 0, 5, 0, 6, 1, 5, 2, 4,
  79.   3, 3, 4, 2, 5, 1, 6, 0, 7, 0, 6, 1, 5, 2, 4, 3, 3, 4, 2, 5, 1, 6, 0, 7,
  80.   1, 7, 2, 6, 3, 5, 4, 4, 5, 3, 6, 2, 7, 1, 7, 2, 6, 3, 5, 4, 4, 5, 3, 6,
  81.   2, 7, 3, 7, 4, 6, 5, 5, 6, 4, 7, 3, 7, 4, 6, 5, 5, 6, 4, 7, 5, 7, 6, 6,
  82. 7, 5, 7, 6, 6, 7, 7, 7};
  83. /* Array mapping zigzag to array pointer offset. */
  84.  
  85. int zigzag_direct[64] = {
  86.   0, 1, 8, 16, 9, 2, 3, 10, 17, 24, 32, 25, 18, 11, 4, 5, 12,
  87.   19, 26, 33, 40, 48, 41, 34, 27, 20, 13, 6, 7, 14, 21, 28, 35,
  88.   42, 49, 56, 57, 50, 43, 36, 29, 22, 15, 23, 30, 37, 44, 51,
  89. 58, 59, 52, 45, 38, 31, 39, 46, 53, 60, 61, 54, 47, 55, 62, 63};
  90. /* Set up array for fast conversion from row/column coordinates to
  91.    zig zag order.
  92. */
  93.  
  94. int scan[8][8] = {
  95.   {0, 1, 5, 6, 14, 15, 27, 28},
  96.   {2, 4, 7, 13, 16, 26, 29, 42},
  97.   {3, 8, 12, 17, 25, 30, 41, 43},
  98.   {9, 11, 18, 24, 31, 40, 44, 53},
  99.   {10, 19, 23, 32, 39, 45, 52, 54},
  100.   {20, 22, 33, 38, 46, 51, 55, 60},
  101.   {21, 34, 37, 47, 50, 56, 59, 61},
  102. {35, 36, 48, 49, 57, 58, 62, 63}};
  103. /* Initialize P and B skip flags. */
  104.  
  105. static int No_P_Flag = 0;
  106. static int No_B_Flag = 0;
  107.  
  108. /* Max lum, chrom indices for illegal block checking. */
  109.  
  110. static int lmaxx;
  111. static int lmaxy;
  112. static int cmaxx;
  113. static int cmaxy;
  114.  
  115. /*
  116.  * We use a lookup table to make sure values stay in the 0..255 range.
  117.  * Since this is cropping (ie, x = (x < 0)?0:(x>255)?255:x; ), wee call this
  118.  * table the "crop table".
  119.  * MAX_NEG_CROP is the maximum neg/pos value we can handle.
  120.  */
  121.  
  122. #define MAX_NEG_CROP 384
  123. #define NUM_CROP_ENTRIES (256+2*MAX_NEG_CROP)
  124. #define assertCrop(x)    assert(((x) >= -MAX_NEG_CROP) && \
  125.                    ((x) <= 256+MAX_NEG_CROP))
  126. static unsigned char cropTbl[NUM_CROP_ENTRIES];
  127.  
  128. /*
  129.   The following accounts for time and size  spent in various parsing acitivites
  130.   if ANALYSIS has been defined.
  131. */
  132.  
  133. #ifdef ANALYSIS
  134.  
  135.  
  136. unsigned int bitCount = 0;
  137.  
  138. int showmb_flag = 0;
  139. int showEachFlag = 0;
  140.  
  141. typedef struct {
  142.   int frametype;
  143.   unsigned int totsize;
  144.   unsigned int number;
  145.   unsigned int i_mbsize;
  146.   unsigned int p_mbsize;
  147.   unsigned int b_mbsize;
  148.   unsigned int bi_mbsize;
  149.   unsigned int i_mbnum;
  150.   unsigned int p_mbnum;
  151.   unsigned int b_mbnum;
  152.   unsigned int bi_mbnum;
  153.   unsigned int i_mbcbp[64];
  154.   unsigned int p_mbcbp[64];
  155.   unsigned int b_mbcbp[64];
  156.   unsigned int bi_mbcbp[64];
  157.   unsigned int i_mbcoeff[64];
  158.   unsigned int p_mbcoeff[64];
  159.   unsigned int b_mbcoeff[64];
  160.   unsigned int bi_mbcoeff[64];
  161.   double tottime;
  162. } Statval;
  163.  
  164. Statval stat_a[4];
  165. unsigned int pictureSizeCount;
  166. unsigned int mbSizeCount;
  167. unsigned int *mbCBPPtr, *mbCoeffPtr, *mbSizePtr;
  168. unsigned int cacheHit[8][8];
  169. unsigned int cacheMiss[8][8];
  170.  
  171. static void
  172. init_stat_struct(astat)
  173.   Statval *astat;
  174. {
  175.   int j;
  176.  
  177.   astat->frametype = 0;
  178.   astat->totsize = 0;
  179.   astat->number = 0;
  180.   astat->i_mbsize = 0;
  181.   astat->p_mbsize = 0;
  182.   astat->b_mbsize = 0;
  183.   astat->bi_mbsize = 0;
  184.   astat->i_mbnum = 0;
  185.   astat->p_mbnum = 0;
  186.   astat->b_mbnum = 0;
  187.   astat->bi_mbnum = 0;
  188.  
  189.   for (j = 0; j < 64; j++) {
  190.  
  191.     astat->i_mbcbp[j] = 0;
  192.     astat->p_mbcbp[j] = 0;
  193.     astat->b_mbcbp[j] = 0;
  194.     astat->bi_mbcbp[j] = 0;
  195.     astat->i_mbcoeff[j] = 0;
  196.     astat->p_mbcoeff[j] = 0;
  197.     astat->b_mbcoeff[j] = 0;
  198.     astat->bi_mbcoeff[j] = 0;
  199.   }
  200.   astat->tottime = 0.0;
  201. }
  202.  
  203. void
  204. init_stats()
  205. {
  206.   int i, j;
  207.  
  208.   for (i = 0; i < 4; i++) {
  209.     init_stat_struct(&(stat_a[i]));
  210.     stat_a[i].frametype = i;
  211.   }
  212.  
  213.   for (i = 0; i < 8; i++) {
  214.     for (j = 0; j < 8; j++) {
  215.       cacheHit[i][j] = 0;
  216.       cacheMiss[i][j] = 0;
  217.     }
  218.   }
  219.  
  220.   bitCount = 0;
  221. }
  222.  
  223. static void
  224. PrintOneStat()
  225. {
  226.   int i;
  227.  
  228.   printf("\n");
  229.   switch (stat_a[0].frametype) {
  230.   case I_TYPE:
  231.     printf("I FRAME\n");
  232.     break;
  233.   case P_TYPE:
  234.     printf("P FRAME\n");
  235.     break;
  236.   case B_TYPE:
  237.     printf("B FRAME\n");
  238.     break;
  239.   }
  240.  
  241.   printf("Size: %d bytes + %d bits\n", stat_a[0].totsize / 8, stat_a[0].totsize % 8);
  242.   if (stat_a[0].i_mbnum > 0) {
  243.     printf("\tI Macro Block Stats:\n");
  244.     printf("\t%d I Macroblocks\n", stat_a[0].i_mbnum);
  245.     printf("\tAvg. Size: %d bytes + %d bits\n",
  246.        stat_a[0].i_mbsize / (8 * stat_a[0].i_mbnum),
  247.        (stat_a[0].i_mbsize * stat_a[0].i_mbnum) % 8);
  248.     printf("\t\tCoded Block Pattern Histogram:\n");
  249.     for (i = 0; i < 64; i += 8) {
  250.       printf("\t%.6d %.6d %.6d %.6d %.6d %.6d %.6d %.6d\n", stat_a[0].i_mbcbp[i],
  251.          stat_a[0].i_mbcbp[i + 1], stat_a[0].i_mbcbp[i + 2], stat_a[0].i_mbcbp[i + 3],
  252.          stat_a[0].i_mbcbp[i + 4], stat_a[0].i_mbcbp[i + 5], stat_a[0].i_mbcbp[i + 6],
  253.          stat_a[0].i_mbcbp[i + 7]);
  254.     }
  255.     printf("\n\t\tNumber of Coefficients/Block Histogram:\n");
  256.     for (i = 0; i < 64; i += 8) {
  257.       printf("\t%.6d %.6d %.6d %.6d %.6d %.6d %.6d %.6d\n", stat_a[0].i_mbcoeff[i],
  258.          stat_a[0].i_mbcoeff[i + 1], stat_a[0].i_mbcoeff[i + 2],
  259.          stat_a[0].i_mbcoeff[i + 3], stat_a[0].i_mbcoeff[i + 4],
  260.          stat_a[0].i_mbcoeff[i + 5], stat_a[0].i_mbcoeff[i + 6],
  261.          stat_a[0].i_mbcoeff[i + 7]);
  262.     }
  263.   }
  264.   if (stat_a[0].p_mbnum > 0) {
  265.     printf("\tP Macro Block Stats:\n");
  266.     printf("\t%d P Macroblocks\n", stat_a[0].p_mbnum);
  267.     printf("\tAvg. Size: %d bytes + %d bits\n",
  268.        stat_a[0].p_mbsize / (8 * stat_a[0].p_mbnum),
  269.        (stat_a[0].p_mbsize / stat_a[0].p_mbnum) % 8);
  270.     printf("\t\tCoded Block Pattern Histogram:\n");
  271.     for (i = 0; i < 64; i += 8) {
  272.       printf("\t%.6d %.6d %.6d %.6d %.6d %.6d %.6d %.6d\n", stat_a[0].p_mbcbp[i],
  273.          stat_a[0].p_mbcbp[i + 1], stat_a[0].p_mbcbp[i + 2], stat_a[0].p_mbcbp[i + 3],
  274.          stat_a[0].p_mbcbp[i + 4], stat_a[0].p_mbcbp[i + 5], stat_a[0].p_mbcbp[i + 6],
  275.          stat_a[0].p_mbcbp[i + 7]);
  276.     }
  277.     printf("\n\t\tNumber of Coefficients/Block Histogram:\n");
  278.     for (i = 0; i < 64; i += 8) {
  279.       printf("\t%.6d %.6d %.6d %.6d %.6d %.6d %.6d %.6d\n", stat_a[0].p_mbcoeff[i],
  280.          stat_a[0].p_mbcoeff[i + 1], stat_a[0].p_mbcoeff[i + 2],
  281.          stat_a[0].p_mbcoeff[i + 3], stat_a[0].p_mbcoeff[i + 4],
  282.          stat_a[0].p_mbcoeff[i + 5], stat_a[0].p_mbcoeff[i + 6],
  283.          stat_a[0].p_mbcoeff[i + 7]);
  284.     }
  285.   }
  286.   if (stat_a[0].b_mbnum > 0) {
  287.     printf("\tB Macro Block Stats:\n");
  288.     printf("\t%d B Macroblocks\n", stat_a[0].b_mbnum);
  289.     printf("\tAvg. Size: %d bytes + %d bits\n",
  290.        stat_a[0].b_mbsize / (8 * stat_a[0].b_mbnum),
  291.        (stat_a[0].b_mbsize / stat_a[0].b_mbnum) % 8);
  292.     printf("\t\tCoded Block Pattern Histogram:\n");
  293.     for (i = 0; i < 64; i += 8) {
  294.       printf("\t%.6d %.6d %.6d %.6d %.6d %.6d %.6d %.6d\n", stat_a[0].b_mbcbp[i],
  295.          stat_a[0].b_mbcbp[i + 1], stat_a[0].b_mbcbp[i + 2], stat_a[0].b_mbcbp[i + 3],
  296.          stat_a[0].b_mbcbp[i + 4], stat_a[0].b_mbcbp[i + 5], stat_a[0].b_mbcbp[i + 6],
  297.          stat_a[0].b_mbcbp[i + 7]);
  298.     }
  299.     printf("\n\t\tNumber of Coefficients/Block Histogram:\n");
  300.     for (i = 0; i < 64; i += 8) {
  301.       printf("\t%.6d %.6d %.6d %.6d %.6d %.6d %.6d %.6d\n", stat_a[0].b_mbcoeff[i],
  302.          stat_a[0].b_mbcoeff[i + 1], stat_a[0].b_mbcoeff[i + 2],
  303.          stat_a[0].b_mbcoeff[i + 3], stat_a[0].b_mbcoeff[i + 4],
  304.          stat_a[0].b_mbcoeff[i + 5], stat_a[0].b_mbcoeff[i + 6],
  305.          stat_a[0].b_mbcoeff[i + 7]);
  306.     }
  307.   }
  308.   if (stat_a[0].bi_mbnum > 0) {
  309.     printf("\tBi Macro Block Stats:\n");
  310.     printf("\t%d Bi Macroblocks\n", stat_a[0].bi_mbnum);
  311.     printf("\tAvg. Size: %d bytes + %d bits\n",
  312.        stat_a[0].bi_mbsize / (8 * stat_a[0].bi_mbnum),
  313.        (stat_a[0].bi_mbsize * stat_a[0].bi_mbnum) % 8);
  314.     printf("\t\tCoded Block Pattern Histogram:\n");
  315.     for (i = 0; i < 64; i += 8) {
  316.       printf("\t%.6d %.6d %.6d %.6d %.6d %.6d %.6d %.6d\n", stat_a[0].bi_mbcbp[i],
  317.          stat_a[0].bi_mbcbp[i + 1], stat_a[0].bi_mbcbp[i + 2], stat_a[0].bi_mbcbp[i + 3],
  318.          stat_a[0].bi_mbcbp[i + 4], stat_a[0].bi_mbcbp[i + 5], stat_a[0].bi_mbcbp[i + 6],
  319.          stat_a[0].bi_mbcbp[i + 7]);
  320.     }
  321.     printf("\n\t\tNumber of Coefficients/Block Histogram:\n");
  322.     for (i = 0; i < 64; i += 8) {
  323.       printf("\t%.6d %.6d %.6d %.6d %.6d %.6d %.6d %.6d\n", stat_a[0].bi_mbcoeff[i],
  324.          stat_a[0].bi_mbcoeff[i + 1], stat_a[0].bi_mbcoeff[i + 2],
  325.          stat_a[0].bi_mbcoeff[i + 3], stat_a[0].bi_mbcoeff[i + 4],
  326.          stat_a[0].bi_mbcoeff[i + 5], stat_a[0].bi_mbcoeff[i + 6],
  327.          stat_a[0].bi_mbcoeff[i + 7]);
  328.     }
  329.   }
  330.   printf("\nTime to Decode: %g secs.\n", stat_a[0].tottime);
  331.   printf("****************\n");
  332. }
  333.  
  334. void
  335. PrintAllStats()
  336. {
  337.   int i, j;
  338.   unsigned int supertot, supernum;
  339.   double supertime;
  340.  
  341.   printf("\n");
  342.   printf("General Info: \n");
  343.   printf("Width: %d\nHeight: %d\n", curVidStream->mb_width * 16, curVidStream->mb_height * 16);
  344.  
  345.   for (i = 1; i < 4; i++) {
  346.  
  347.     if (stat_a[i].number == 0)
  348.       continue;
  349.  
  350.     switch (i) {
  351.     case 1:
  352.       printf("I FRAMES\n");
  353.       break;
  354.     case 2:
  355.       printf("P FRAMES\n");
  356.       break;
  357.     case 3:
  358.       printf("B FRAMES\n");
  359.       break;
  360.     }
  361.  
  362.     printf("Number: %d\n", stat_a[i].number);
  363.     printf("Avg. Size: %d bytes + %d bits\n",
  364.        stat_a[i].totsize / (8 * stat_a[i].number), (stat_a[i].totsize / stat_a[i].number) % 8);
  365.     if (stat_a[i].i_mbnum > 0) {
  366.       printf("\tI Macro Block Stats:\n");
  367.       printf("\t%d I Macroblocks\n", stat_a[i].i_mbnum);
  368.       printf("\tAvg. Size: %d bytes + %d bits\n",
  369.          stat_a[i].i_mbsize / (8 * stat_a[i].i_mbnum),
  370.          (stat_a[i].i_mbsize / stat_a[i].i_mbnum) % 8);
  371.       printf("\t\tCoded Block Pattern Histogram:\n");
  372.       for (j = 0; j < 64; j += 8) {
  373.     printf("\t%.6d %.6d %.6d %.6d %.6d %.6d %.6d %.6d\n", stat_a[i].i_mbcbp[j],
  374.            stat_a[i].i_mbcbp[j + 1], stat_a[i].i_mbcbp[j + 2], stat_a[i].i_mbcbp[j + 3],
  375.            stat_a[i].i_mbcbp[j + 4], stat_a[i].i_mbcbp[j + 5], stat_a[i].i_mbcbp[j + 6],
  376.            stat_a[i].i_mbcbp[j + 7]);
  377.       }
  378.       printf("\n\t\tNumber of Coefficients/Block Histogram:\n");
  379.       for (j = 0; j < 64; j += 8) {
  380.     printf("\t%.6d %.6d %.6d %.6d %.6d %.6d %.6d %.6d\n", stat_a[i].i_mbcoeff[j],
  381.            stat_a[i].i_mbcoeff[j + 1], stat_a[i].i_mbcoeff[j + 2],
  382.            stat_a[i].i_mbcoeff[j + 3], stat_a[i].i_mbcoeff[j + 4],
  383.            stat_a[i].i_mbcoeff[j + 5], stat_a[i].i_mbcoeff[j + 6],
  384.            stat_a[i].i_mbcoeff[j + 7]);
  385.       }
  386.     }
  387.     if (stat_a[i].p_mbnum > 0) {
  388.       printf("\tP Macro Block Stats:\n");
  389.       printf("\t%d P Macroblocks\n", stat_a[i].p_mbnum);
  390.       printf("\tAvg. Size: %d bytes + %d bits\n",
  391.          stat_a[i].p_mbsize / (8 * stat_a[i].p_mbnum),
  392.          (stat_a[i].p_mbsize / stat_a[i].p_mbnum) % 8);
  393.       printf("\t\tCoded Block Pattern Histogram:\n");
  394.       for (j = 0; j < 64; j += 8) {
  395.     printf("\t%.6d %.6d %.6d %.6d %.6d %.6d %.6d %.6d\n", stat_a[i].p_mbcbp[j],
  396.            stat_a[i].p_mbcbp[j + 1], stat_a[i].p_mbcbp[j + 2], stat_a[i].p_mbcbp[j + 3],
  397.            stat_a[i].p_mbcbp[j + 4], stat_a[i].p_mbcbp[j + 5], stat_a[i].p_mbcbp[j + 6],
  398.            stat_a[i].p_mbcbp[j + 7]);
  399.       }
  400.       printf("\n\t\tNumber of Coefficients/Block Histogram:\n");
  401.       for (j = 0; j < 64; j += 8) {
  402.     printf("\t%.6d %.6d %.6d %.6d %.6d %.6d %.6d %.6d\n", stat_a[i].p_mbcoeff[j],
  403.            stat_a[i].p_mbcoeff[j + 1], stat_a[i].p_mbcoeff[j + 2],
  404.            stat_a[i].p_mbcoeff[j + 3], stat_a[i].p_mbcoeff[j + 4],
  405.            stat_a[i].p_mbcoeff[j + 5], stat_a[i].p_mbcoeff[j + 6],
  406.            stat_a[i].p_mbcoeff[j + 7]);
  407.       }
  408.     }
  409.     if (stat_a[i].b_mbnum > 0) {
  410.       printf("\tB Macro Block Stats:\n");
  411.       printf("\t%d B Macroblocks\n", stat_a[i].b_mbnum);
  412.       printf("\tAvg. Size: %d bytes + %d bits\n",
  413.          stat_a[i].b_mbsize / (8 * stat_a[i].b_mbnum),
  414.          (stat_a[i].b_mbsize * stat_a[i].b_mbnum) % 8);
  415.       printf("\t\tCoded Block Pattern Histogram:\n");
  416.       for (j = 0; j < 64; j += 8) {
  417.     printf("\t%.6d %.6d %.6d %.6d %.6d %.6d %.6d %.6d\n", stat_a[i].b_mbcbp[j],
  418.            stat_a[i].b_mbcbp[j + 1], stat_a[i].b_mbcbp[j + 2], stat_a[i].b_mbcbp[j + 3],
  419.            stat_a[i].b_mbcbp[j + 4], stat_a[i].b_mbcbp[j + 5], stat_a[i].b_mbcbp[j + 6],
  420.            stat_a[i].b_mbcbp[j + 7]);
  421.       }
  422.       printf("\n\t\tNumber of Coefficients/Block Histogram:\n");
  423.       for (j = 0; j < 64; j += 8) {
  424.     printf("\t%.6d %.6d %.6d %.6d %.6d %.6d %.6d %.6d\n", stat_a[i].b_mbcoeff[j],
  425.            stat_a[i].b_mbcoeff[j + 1], stat_a[i].b_mbcoeff[j + 2],
  426.            stat_a[i].b_mbcoeff[j + 3], stat_a[i].b_mbcoeff[j + 4],
  427.            stat_a[i].b_mbcoeff[j + 5], stat_a[i].b_mbcoeff[j + 6],
  428.            stat_a[i].b_mbcoeff[j + 7]);
  429.       }
  430.     }
  431.     if (stat_a[i].bi_mbnum > 0) {
  432.       printf("\tBi Macro Block Stats:\n");
  433.       printf("\t%d Bi Macroblocks\n", stat_a[i].bi_mbnum);
  434.       printf("\tAvg. Size: %d bytes + %d bits\n",
  435.          stat_a[i].bi_mbsize / (8 * stat_a[i].bi_mbnum),
  436.          (stat_a[i].bi_mbsize * stat_a[i].bi_mbnum) % 8);
  437.       printf("\t\tCoded Block Pattern Histogram:\n");
  438.       for (j = 0; j < 64; j += 8) {
  439.     printf("\t%.6d %.6d %.6d %.6d %.6d %.6d %.6d %.6d\n", stat_a[i].bi_mbcbp[j],
  440.            stat_a[i].bi_mbcbp[j + 1], stat_a[i].bi_mbcbp[j + 2], stat_a[i].bi_mbcbp[j + 3],
  441.            stat_a[i].bi_mbcbp[j + 4], stat_a[i].bi_mbcbp[j + 5], stat_a[i].bi_mbcbp[j + 6],
  442.            stat_a[i].bi_mbcbp[j + 7]);
  443.       }
  444.       printf("\n\t\tNumber of Coefficients/Block Histogram:\n");
  445.       for (j = 0; j < 64; j += 8) {
  446.     printf("\t%.6d %.6d %.6d %.6d %.6d %.6d %.6d %.6d\n", stat_a[i].bi_mbcoeff[j],
  447.            stat_a[i].bi_mbcoeff[j + 1], stat_a[i].bi_mbcoeff[j + 2],
  448.            stat_a[i].bi_mbcoeff[j + 3], stat_a[i].bi_mbcoeff[j + 4],
  449.            stat_a[i].bi_mbcoeff[j + 5], stat_a[i].bi_mbcoeff[j + 6],
  450.            stat_a[i].bi_mbcoeff[j + 7]);
  451.       }
  452.     }
  453.     printf("\nAvg. Time to Decode: %f secs.\n",
  454.        (stat_a[i].tottime / ((double) stat_a[i].number)));
  455.     printf("\n");
  456.     printf("*************************\n\n");
  457.   }
  458.  
  459.   supertot = stat_a[1].totsize + stat_a[2].totsize + stat_a[3].totsize;
  460.   supernum = stat_a[1].number + stat_a[2].number + stat_a[3].number;
  461.   supertime = stat_a[1].tottime + stat_a[2].tottime + stat_a[3].tottime;
  462.  
  463.   printf("Total Number of Frames: %d\n", supernum);
  464.   printf("Avg Frame Size: %d bytes %d bits\n",
  465.      supertot / (8 * supernum), (supertot / supernum) % 8);
  466.   printf("Total Time Decoding: %g secs.\n", supertime);
  467.   printf("Avg Decoding Time/Frame: %g secs.\n", supertime / ((double) supernum));
  468.   printf("Avg Decoding Frames/Sec: %g secs.\n", ((double) supernum) / supertime);
  469.   printf("\n");
  470.  
  471.   printf("Cache Hits/Miss\n");
  472.   for (i = 0; i < 8; i++) {
  473.     printf("%.6d/%.6d\t%.6d/%.6d\t%.6d/%.6d\t%.6d/%.6d\n",
  474.        cacheHit[i][0], cacheMiss[i][0], cacheHit[i][1], cacheMiss[i][1],
  475.        cacheHit[i][2], cacheMiss[i][2], cacheHit[i][3], cacheMiss[i][3]);
  476.     printf("%.6d/%.6d\t%.6d/%.6d\t%.6d/%.6d\t%.6d/%.6d\n",
  477.        cacheHit[i][4], cacheMiss[i][4], cacheHit[i][5], cacheMiss[i][5],
  478.        cacheHit[i][6], cacheMiss[i][6], cacheHit[i][7], cacheMiss[i][7]);
  479.   }
  480.  
  481. }
  482.  
  483. static void
  484. CollectStats()
  485. {
  486.   int i, j;
  487.  
  488.   i = stat_a[0].frametype;
  489.  
  490.   stat_a[i].totsize += stat_a[0].totsize;
  491.   stat_a[i].number += stat_a[0].number;
  492.   stat_a[i].i_mbsize += stat_a[0].i_mbsize;
  493.   stat_a[i].p_mbsize += stat_a[0].p_mbsize;
  494.   stat_a[i].b_mbsize += stat_a[0].b_mbsize;
  495.   stat_a[i].bi_mbsize += stat_a[0].bi_mbsize;
  496.   stat_a[i].i_mbnum += stat_a[0].i_mbnum;
  497.   stat_a[i].p_mbnum += stat_a[0].p_mbnum;
  498.   stat_a[i].b_mbnum += stat_a[0].b_mbnum;
  499.   stat_a[i].bi_mbnum += stat_a[0].bi_mbnum;
  500.  
  501.   for (j = 0; j < 64; j++) {
  502.  
  503.     stat_a[i].i_mbcbp[j] += stat_a[0].i_mbcbp[j];
  504.     stat_a[i].p_mbcbp[j] += stat_a[0].p_mbcbp[j];
  505.     stat_a[i].b_mbcbp[j] += stat_a[0].b_mbcbp[j];
  506.     stat_a[i].bi_mbcbp[j] += stat_a[0].bi_mbcbp[j];
  507.     stat_a[i].i_mbcoeff[j] += stat_a[0].i_mbcoeff[j];
  508.     stat_a[i].p_mbcoeff[j] += stat_a[0].p_mbcoeff[j];
  509.     stat_a[i].b_mbcoeff[j] += stat_a[0].b_mbcoeff[j];
  510.     stat_a[i].bi_mbcoeff[j] += stat_a[0].bi_mbcoeff[j];
  511.   }
  512.  
  513.   stat_a[i].tottime += stat_a[0].tottime;
  514.  
  515.   init_stat_struct(&(stat_a[0]));
  516. }
  517.  
  518. static unsigned int
  519. bitCountRead()
  520. {
  521.   return bitCount;
  522. }
  523.  
  524. static void
  525. StartTime()
  526. {
  527.   stat_a[0].tottime = ReadSysClock();
  528. }
  529.  
  530. static void
  531. EndTime()
  532. {
  533.   stat_a[0].tottime = ReadSysClock() - stat_a[0].tottime;
  534. }
  535. #endif
  536.  
  537. double realTimeStart;
  538. int totNumFrames = 0;
  539.  
  540. double
  541. ReadSysClock()
  542. {
  543. /* @@@ AK, Use crummy time() function, as no gettimeofday under OS/2 */
  544. #ifdef OS2
  545.   return (double) time(NULL);
  546. #else
  547.   struct timeval tv;
  548.   (void) gettimeofday(&tv, (struct timezone *)NULL);
  549.   return (tv.tv_sec + tv.tv_usec / 1000000.0);
  550. #endif
  551. }
  552.  
  553. void
  554. PrintTimeInfo()
  555. {
  556.   double spent;
  557.  
  558.   spent = ReadSysClock() - realTimeStart;
  559.  
  560.   if (!quietFlag) {
  561.     printf("\nReal Time Spent (After Initializations): %f secs.\n", spent);
  562.     printf("Avg. Frames/Sec: %f\n", ((double) totNumFrames) / spent);
  563.   }
  564. }
  565.  
  566.  
  567.  
  568. /*
  569.  *--------------------------------------------------------------
  570.  *
  571.  * NewVidStream --
  572.  *
  573.  *    Allocates and initializes a VidStream structure. Takes
  574.  *      as parameter requested size for buffer length.
  575.  *
  576.  * Results:
  577.  *    A pointer to the new VidStream structure.
  578.  *
  579.  * Side effects:
  580.  *      None.
  581.  *
  582.  *--------------------------------------------------------------
  583.  */
  584.  
  585. VidStream *
  586. NewVidStream(bufLength)
  587.   int bufLength;
  588. {
  589.   int i, j;
  590.   VidStream *new;
  591.   static unsigned char default_intra_matrix[64] = {
  592.     8, 16, 19, 22, 26, 27, 29, 34,
  593.     16, 16, 22, 24, 27, 29, 34, 37,
  594.     19, 22, 26, 27, 29, 34, 34, 38,
  595.     22, 22, 26, 27, 29, 34, 37, 40,
  596.     22, 26, 27, 29, 32, 35, 40, 48,
  597.     26, 27, 29, 32, 35, 40, 48, 58,
  598.     26, 27, 29, 34, 38, 46, 56, 69,
  599.   27, 29, 35, 38, 46, 56, 69, 83};
  600.  
  601.   /* Check for legal buffer length. */
  602.  
  603.   if (bufLength < 4)
  604.     return NULL;
  605.  
  606.   /* Make buffer length multiple of 4. */
  607.  
  608.   bufLength = (bufLength + 3) >> 2;
  609.  
  610.   /* Allocate memory for new structure. */
  611.  
  612.   new = (VidStream *) malloc(sizeof(VidStream));
  613.  
  614.   /* Initialize pointers to extension and user data. */
  615.  
  616.   new->group.ext_data = new->group.user_data =
  617.     new->picture.extra_info = new->picture.user_data =
  618.     new->picture.ext_data = new->slice.extra_info =
  619.     new->ext_data = new->user_data = NULL;
  620.  
  621.   /* Copy default intra matrix. */
  622.  
  623.   for (i = 0; i < 8; i++) {
  624.     for (j = 0; j < 8; j++) {
  625.       new->intra_quant_matrix[j][i] = default_intra_matrix[i * 8 + j];
  626.     }
  627.   }
  628.  
  629.   /* Initialize crop table. */
  630.  
  631.   for (i = (-MAX_NEG_CROP); i < NUM_CROP_ENTRIES - MAX_NEG_CROP; i++) {
  632.     if (i <= 0) {
  633.       cropTbl[i + MAX_NEG_CROP] = 0;
  634.     } else if (i >= 255) {
  635.       cropTbl[i + MAX_NEG_CROP] = 255;
  636.     } else {
  637.       cropTbl[i + MAX_NEG_CROP] = i;
  638.     }
  639.   }
  640.  
  641.   /* Initialize non intra quantization matrix. */
  642.  
  643.   for (i = 0; i < 8; i++) {
  644.     for (j = 0; j < 8; j++) {
  645.       new->non_intra_quant_matrix[j][i] = 16;
  646.     }
  647.   }
  648.  
  649.   /* Initialize pointers to image spaces. */
  650.  
  651.   new->current = new->past = new->future = NULL;
  652.   for (i = 0; i < RING_BUF_SIZE; i++) {
  653.     new->ring[i] = NULL;
  654.   }
  655.  
  656.   /* Create buffer. */
  657.  
  658.   new->buf_start = (unsigned int *) malloc(bufLength * 4);
  659.  
  660.   /*
  661.    * Set max_buf_length to one less than actual length to deal with messy
  662.    * data without proper seq. end codes.
  663.    */
  664.  
  665.   new->max_buf_length = bufLength - 1;
  666.  
  667.   /* Initialize bitstream i/o fields. */
  668.  
  669.   new->bit_offset = 0;
  670.   new->buf_length = 0;
  671.   new->buffer = new->buf_start;
  672.  
  673.  
  674.   /* Return structure. */
  675.  
  676.   return new;
  677. }
  678.  
  679.  
  680.  
  681. /*
  682.  *--------------------------------------------------------------
  683.  *
  684.  * DestroyVidStream --
  685.  *
  686.  *    Deallocates a VidStream structure.
  687.  *
  688.  * Results:
  689.  *      None.
  690.  *
  691.  * Side effects:
  692.  *    None.
  693.  *
  694.  *--------------------------------------------------------------
  695.  */
  696. void
  697. DestroyVidStream(astream)
  698.   VidStream *astream;
  699. {
  700.   int i;
  701.  
  702.   if (astream->ext_data != NULL)
  703.     free(astream->ext_data);
  704.  
  705.   if (astream->user_data != NULL)
  706.     free(astream->user_data);
  707.  
  708.   if (astream->group.ext_data != NULL)
  709.     free(astream->group.ext_data);
  710.  
  711.   if (astream->group.user_data != NULL)
  712.     free(astream->group.user_data);
  713.  
  714.   if (astream->picture.extra_info != NULL)
  715.     free(astream->picture.extra_info);
  716.  
  717.   if (astream->picture.ext_data != NULL)
  718.     free(astream->picture.ext_data);
  719.  
  720.   if (astream->picture.user_data != NULL)
  721.     free(astream->picture.user_data);
  722.  
  723.   if (astream->slice.extra_info != NULL)
  724.     free(astream->slice.extra_info);
  725.  
  726.   if (astream->buf_start != NULL)
  727.     free(astream->buf_start);
  728.  
  729.   for (i = 0; i < RING_BUF_SIZE; i++) {
  730.     if (astream->ring[i] != NULL) {
  731.       DestroyPictImage(astream->ring[i]);
  732.       astream->ring[i] = NULL;
  733.     }
  734.   }
  735.  
  736.   free((char *) astream);
  737. }
  738.  
  739.  
  740.  
  741.  
  742. /*
  743.  *--------------------------------------------------------------
  744.  *
  745.  * NewPictImage --
  746.  *
  747.  *    Allocates and initializes a PictImage structure.
  748.  *      The width and height of the image space are passed in
  749.  *      as parameters.
  750.  *
  751.  * Results:
  752.  *    A pointer to the new PictImage structure.
  753.  *
  754.  * Side effects:
  755.  *    None.
  756.  *
  757.  *--------------------------------------------------------------
  758.  */
  759.  
  760. PictImage *
  761. NewPictImage(width, height)
  762.   unsigned int width, height;
  763. {
  764.   PictImage *new;
  765.  
  766.   /* Allocate memory space for new structure. */
  767.  
  768.   new = (PictImage *) malloc(sizeof(PictImage));
  769.  
  770.  
  771.   /* Allocate memory for image spaces. */
  772.  
  773. #ifdef SH_MEM
  774.   new->ximage = NULL;
  775.  
  776.   if (shmemFlag) {
  777.     Visual *fc_visual;
  778.     int depth;
  779.     Visual *FindFullColorVisual();
  780.  
  781.     if (ditherType == Twox2_DITHER) {
  782.       new->ximage = XShmCreateImage(display, None, 8, ZPixmap, NULL,
  783.                     &(new->shminfo), width * 2, height * 2);
  784.     } else if (ditherType == FULL_COLOR_DITHER) {
  785.       fc_visual = FindFullColorVisual(display, &depth);
  786.       new->ximage = XShmCreateImage(display, fc_visual, depth, ZPixmap,
  787.                     NULL, &(new->shminfo), width, height);
  788.     } else if (ditherType == MONO_DITHER || ditherType == MONO_THRESHOLD) {
  789.       new->ximage = XShmCreateImage(display, None, 1, XYBitmap,
  790.                     NULL, &(new->shminfo), width, height);
  791.     } else {
  792.       new->ximage = XShmCreateImage(display, None, 8, ZPixmap, NULL,
  793.                     &(new->shminfo), width, height);
  794.     }
  795.  
  796.     /* If no go, then revert to normal Xlib calls. */
  797.  
  798.     if (new->ximage == NULL) {
  799.       shmemFlag = 0;
  800.       if (!quietFlag) {
  801.     fprintf(stderr, "Shared memory error, disabling.\n");
  802.     fprintf(stderr, "Ximage error.\n");
  803.       }
  804.       goto shmemerror;
  805.     }
  806.     /* Success here, continue. */
  807.  
  808.     new->shminfo.shmid = shmget(IPC_PRIVATE, (new->ximage->bytes_per_line *
  809.                           new->ximage->height),
  810.                 IPC_CREAT | 0777);
  811.  
  812.     if (new->shminfo.shmid < 0) {
  813.       XDestroyImage(new->ximage);
  814.       new->ximage = NULL;
  815.       shmemFlag = 0;
  816.       if (!quietFlag) {
  817.     fprintf(stderr, "Shared memory error, disabling.\n");
  818.     fprintf(stderr, "Seg. id. error.\n");
  819.       }
  820.       goto shmemerror;
  821.     }
  822.     new->shminfo.shmaddr = (char *) shmat(new->shminfo.shmid, 0, 0);
  823.     if (new->shminfo.shmaddr == ((char *) -1)) {
  824.       XDestroyImage(new->ximage);
  825.       new->ximage = NULL;
  826.       shmemFlag = 0;
  827.       if (!quietFlag) {
  828.     fprintf(stderr, "Shared memory error, disabling.\n");
  829.     fprintf(stderr, "Address error.\n");
  830.       }
  831.       goto shmemerror;
  832.     }
  833.     new->ximage->data = new->shminfo.shmaddr;
  834.     new->display = (unsigned char *) new->ximage->data;
  835.     new->shminfo.readOnly = False;
  836.  
  837.     XShmAttach(display, &(new->shminfo));
  838.     XSync(display, False);
  839.  
  840.     if (gXErrorFlag) {
  841.       /* Ultimate failure here. */
  842.       XDestroyImage(new->ximage);
  843.       new->ximage = NULL;
  844.       shmemFlag = 0;
  845.       if (!quietFlag) {
  846.     fprintf(stderr, "Shared memory error, disabling.\n");
  847.       }
  848.       gXErrorFlag = 0;
  849.       goto shmemerror;
  850.     } else {
  851.       shmctl(new->shminfo.shmid, IPC_RMID, 0);
  852.     }
  853.  
  854.     if (!quietFlag) {
  855.       fprintf(stderr, "Sharing memory.\n");
  856.     }
  857.   } else
  858. #endif
  859.   {
  860. shmemerror:
  861.  
  862.     if ((ditherType == Twox2_DITHER) || (ditherType == FULL_COLOR_DITHER)) {
  863.       new->display = (unsigned char *) malloc(width * height * 4);
  864.     } else {
  865.       new->display = (unsigned char *) malloc(width * height);
  866.     }
  867.   }
  868.  
  869.   new->luminance = (unsigned char *) malloc(width * height);
  870.   new->Cr = (unsigned char *) malloc(width * height / 4);
  871.   new->Cb = (unsigned char *) malloc(width * height / 4);
  872.  
  873.   /* Reset locked flag. */
  874.  
  875.   new->locked = 0;
  876.  
  877.   /* Return pointer to new structure. */
  878.  
  879.   return new;
  880. }
  881.  
  882.  
  883.  
  884. /*
  885.  *--------------------------------------------------------------
  886.  *
  887.  * DestroyPictImage --
  888.  *
  889.  *    Deallocates a PictImage structure.
  890.  *
  891.  * Results:
  892.  *      None.
  893.  *
  894.  * Side effects:
  895.  *    None.
  896.  *
  897.  *--------------------------------------------------------------
  898.  */
  899. void
  900. DestroyPictImage(apictimage)
  901.   PictImage *apictimage;
  902. {
  903.   if (apictimage->luminance != NULL) {
  904.     free(apictimage->luminance);
  905.   }
  906.   if (apictimage->Cr != NULL) {
  907.     free(apictimage->Cr);
  908.   }
  909.   if (apictimage->Cb != NULL) {
  910.     free(apictimage->Cb);
  911.   }
  912. #ifdef SH_MEM
  913.   if (apictimage->ximage != NULL) {
  914.     XShmDetach(display, &(apictimage->shminfo));
  915.     XDestroyImage(apictimage->ximage);
  916.     shmdt(apictimage->shminfo.shmaddr);
  917.     apictimage->ximage = NULL;
  918.     apictimage->display = NULL;
  919.   }
  920. #endif
  921.  
  922.   if (apictimage->display != NULL) {
  923.     free(apictimage->display);
  924.   }
  925.   free(apictimage);
  926. }
  927.  
  928.  
  929.  
  930. /*
  931.  *--------------------------------------------------------------
  932.  *
  933.  * mpegVidRsrc --
  934.  *
  935.  *      Parses bit stream until MB_QUANTUM number of
  936.  *      macroblocks have been decoded or current slice or
  937.  *      picture ends, whichever comes first. If the start
  938.  *      of a frame is encountered, the frame is time stamped
  939.  *      with the value passed in time_stamp. If the value
  940.  *      passed in buffer is not null, the video stream buffer
  941.  *      is set to buffer and the length of the buffer is
  942.  *      expected in value passed in through length. The current
  943.  *      video stream is set to vid_stream. If vid_stream
  944.  *      is passed as NULL, a new VidStream structure is created
  945.  *      and initialized and used as the current video stream.
  946.  *
  947.  * Results:
  948.  *      A pointer to the video stream structure used.
  949.  *
  950.  * Side effects:
  951.  *      Bit stream is irreversibly parsed. If a picture is completed,
  952.  *      a function is called to display the frame at the correct time.
  953.  *
  954.  *--------------------------------------------------------------
  955.  */
  956.  
  957. VidStream *
  958. mpegVidRsrc(time_stamp, vid_stream)
  959.   TimeStamp time_stamp;
  960.   VidStream *vid_stream;
  961. {
  962.   static int first = 1;
  963.   unsigned int data;
  964.   int i, status;
  965.  
  966.   /* If vid_stream is null, create new VidStream structure. */
  967.  
  968.   if (vid_stream == NULL) {
  969.     return NULL;
  970.   }
  971.   /*
  972.    * Set global curVidStream to vid_stream. Necessary because bit i/o use
  973.    * curVidStream and are not passed vid_stream. Also set global bitstream
  974.    * parameters.
  975.    */
  976.  
  977.   curVidStream = vid_stream;
  978.   bitOffset = curVidStream->bit_offset;
  979. #ifdef UTIL2
  980.   curBits = *curVidStream->buffer << bitOffset;
  981. #else
  982.   curBits = *curVidStream->buffer;
  983. #endif
  984.   bufLength = curVidStream->buf_length;
  985.   bitBuffer = curVidStream->buffer;
  986.  
  987.   /*
  988.    * If called for the first time, find start code, make sure it is a
  989.    * sequence start code.
  990.    */
  991.  
  992.   if (first) {
  993.     next_start_code();
  994.     show_bits32(data);
  995.     if (data != SEQ_START_CODE) {
  996.       fprintf(stderr, "This is not an MPEG stream.");
  997.       DestroyVidStream(curVidStream);
  998.       exit(1);
  999.     }
  1000.     first = 0;
  1001.   }
  1002.   /* Get next 32 bits (size of start codes). */
  1003.  
  1004.   show_bits32(data);
  1005.  
  1006.   /*
  1007.    * Process according to start code (or parse macroblock if not a start code
  1008.    * at all.
  1009.    */
  1010.  
  1011.   switch (data) {
  1012.  
  1013.   case SEQ_END_CODE:
  1014.  
  1015.     /* Display last frame. */
  1016.  
  1017.     if (vid_stream->future != NULL) {
  1018.       vid_stream->current = vid_stream->future;
  1019.       ExecuteDisplay(vid_stream);
  1020.     }
  1021.     
  1022.     /* Sequence done. Do the right thing. For right now, exit. */
  1023.  
  1024.     if (!quietFlag) {
  1025.       fprintf(stderr, "\nDone!\n");
  1026.     }
  1027.  
  1028. #ifdef ANALYSIS
  1029.     PrintAllStats();
  1030. #endif
  1031.     PrintTimeInfo();
  1032.  
  1033.     if (loopFlag)
  1034.       longjmp(env, 1);
  1035.  
  1036.     DestroyVidStream(curVidStream);
  1037.     exit(0);
  1038.     break;
  1039.  
  1040.   case SEQ_START_CODE:
  1041.  
  1042.     /* Sequence start code. Parse sequence header. */
  1043.  
  1044.     if (ParseSeqHead(vid_stream) != PARSE_OK)
  1045.       goto error;
  1046.  
  1047.     /*
  1048.      * Return after sequence start code so that application above can use
  1049.      * info in header.
  1050.      */
  1051.  
  1052.     goto done;
  1053.  
  1054.   case GOP_START_CODE:
  1055.  
  1056.     /* Group of Pictures start code. Parse gop header. */
  1057.  
  1058.     if (ParseGOP(vid_stream) != PARSE_OK)
  1059.       goto error;
  1060.  
  1061.  
  1062.   case PICTURE_START_CODE:
  1063.  
  1064.     /* Picture start code. Parse picture header and first slice header. */
  1065.  
  1066.     status = ParsePicture(vid_stream, time_stamp);
  1067.  
  1068.     if (status == SKIP_PICTURE) {
  1069.       next_start_code();
  1070.       fprintf(stderr, "Skipping picture...");
  1071.       while (!next_bits(32, PICTURE_START_CODE)) {
  1072.     if (next_bits(32, GOP_START_CODE))
  1073.       break;
  1074.     else if (next_bits(32, SEQ_END_CODE))
  1075.       break;
  1076.     flush_bits(24);
  1077.     next_start_code();
  1078.       }
  1079.       fprintf(stderr, "Done.\n");
  1080.       goto done;
  1081.     } else if (status != PARSE_OK)
  1082.       goto error;
  1083.  
  1084.  
  1085.     if (ParseSlice(vid_stream) != PARSE_OK)
  1086.       goto error;
  1087.     break;
  1088.  
  1089.   default:
  1090.  
  1091.     /* Check for slice start code. */
  1092.  
  1093.     if ((data >= SLICE_MIN_START_CODE) && (data <= SLICE_MAX_START_CODE)) {
  1094.  
  1095.       /* Slice start code. Parse slice header. */
  1096.  
  1097.       if (ParseSlice(vid_stream) != PARSE_OK)
  1098.     goto error;
  1099.     }
  1100.     break;
  1101.   }
  1102.  
  1103.   /* Parse next MB_QUANTUM macroblocks. */
  1104.  
  1105.   for (i = 0; i < MB_QUANTUM; i++) {
  1106.  
  1107.     /* Check to see if actually a startcode and not a macroblock. */
  1108.  
  1109.     if (!next_bits(23, 0x00000000)) {
  1110.  
  1111.       /* Not start code. Parse Macroblock. */
  1112.  
  1113.       if (ParseMacroBlock(vid_stream) != PARSE_OK)
  1114.     goto error;
  1115.  
  1116. #ifdef ANALYSIS
  1117.       if (showmb_flag) {
  1118.     DoDitherImage(vid_stream->current->luminance, vid_stream->current->Cr,
  1119.               vid_stream->current->Cb, vid_stream->current->display,
  1120.               vid_stream->mb_height * 16, vid_stream->mb_width * 16);
  1121.     ExecuteDisplay(vid_stream);
  1122.       }
  1123. #endif
  1124.  
  1125.     } else {
  1126.  
  1127.       /* Not macroblock, actually start code. Get start code. */
  1128.  
  1129.       next_start_code();
  1130.       show_bits32(data);
  1131.  
  1132.       /*
  1133.        * If start code is outside range of slice start codes, frame is
  1134.        * complete, display frame.
  1135.        */
  1136.  
  1137.       if ((data < SLICE_MIN_START_CODE) || (data > SLICE_MAX_START_CODE)) {
  1138.  
  1139. #ifdef ANALYSIS
  1140.     EndTime();
  1141.     stat_a[0].totsize += bitCountRead() - pictureSizeCount;
  1142.     if (showEachFlag) {
  1143.       PrintOneStat();
  1144.     };
  1145.  
  1146.     CollectStats();
  1147. #endif
  1148.  
  1149.     DoPictureDisplay(vid_stream);
  1150.       }
  1151.       break;
  1152.     }
  1153.   }
  1154.  
  1155.   /* Return pointer to video stream structure. */
  1156.  
  1157.   goto done;
  1158.  
  1159. error:
  1160.   fprintf(stderr, "Error!!!!\n");
  1161.   next_start_code();
  1162.   goto done;
  1163.  
  1164. done:
  1165.  
  1166.   /* Copy global bit i/o variables back into vid_stream. */
  1167.  
  1168.   vid_stream->buffer = bitBuffer;
  1169.   vid_stream->buf_length = bufLength;
  1170.   vid_stream->bit_offset = bitOffset;
  1171.  
  1172.   return vid_stream;
  1173.  
  1174. }
  1175.  
  1176.  
  1177.  
  1178. /*
  1179.  *--------------------------------------------------------------
  1180.  *
  1181.  * ParseSeqHead --
  1182.  *
  1183.  *      Assumes bit stream is at the begining of the sequence
  1184.  *      header start code. Parses off the sequence header.
  1185.  *
  1186.  * Results:
  1187.  *      Fills the vid_stream structure with values derived and
  1188.  *      decoded from the sequence header. Allocates the pict image
  1189.  *      structures based on the dimensions of the image space
  1190.  *      found in the sequence header.
  1191.  *
  1192.  * Side effects:
  1193.  *      Bit stream irreversibly parsed off.
  1194.  *
  1195.  *--------------------------------------------------------------
  1196.  */
  1197.  
  1198. static int
  1199. ParseSeqHead(vid_stream)
  1200.   VidStream *vid_stream;
  1201. {
  1202.  
  1203.   unsigned int data;
  1204.   int i;
  1205.  
  1206.   /* Flush off sequence start code. */
  1207.  
  1208.   flush_bits32;
  1209.  
  1210.   /* Get horizontal size of image space. */
  1211.  
  1212.   get_bits12(data);
  1213.   vid_stream->h_size = data;
  1214.  
  1215.   /* Get vertical size of image space. */
  1216.  
  1217.   get_bits12(data);
  1218.   vid_stream->v_size = data;
  1219.  
  1220.   /* Calculate macroblock width and height of image space. */
  1221.  
  1222.   vid_stream->mb_width = (vid_stream->h_size + 15) / 16;
  1223.   vid_stream->mb_height = (vid_stream->v_size + 15) / 16;
  1224.  
  1225.   /* If dither type is MBORDERED allocate ditherFlags. */
  1226.  
  1227.   if (ditherType == MBORDERED_DITHER) {
  1228.     ditherFlags = (char *) malloc(vid_stream->mb_width*vid_stream->mb_height);
  1229.   }
  1230.  
  1231.   /* Initialize lmaxx, lmaxy, cmaxx, cmaxy. */
  1232.  
  1233.   lmaxx = vid_stream->mb_width*16-1;
  1234.   lmaxy = vid_stream->mb_height*16-1;
  1235.   cmaxx = vid_stream->mb_width*8-1;
  1236.   cmaxy = vid_stream->mb_height*8-1;
  1237.  
  1238.   /*
  1239.    * Initialize ring buffer of pict images now that dimensions of image space
  1240.    * are known.
  1241.    */
  1242.  
  1243. #ifdef SH_MEM
  1244.   if (display != NULL) {
  1245.     InstallXErrorHandler();
  1246.   }
  1247. #endif
  1248.  
  1249.   if (vid_stream->ring[0] == NULL) {
  1250.     for (i = 0; i < RING_BUF_SIZE; i++) {
  1251.       vid_stream->ring[i] = NewPictImage(vid_stream->mb_width * 16,
  1252.                      vid_stream->mb_height * 16);
  1253.     }
  1254.   }
  1255. #ifdef SH_MEM
  1256.   if (display != NULL) {
  1257.     DeInstallXErrorHandler();
  1258.   }
  1259. #endif
  1260.  
  1261.   /* Parse of aspect ratio code. */
  1262.  
  1263.   get_bits4(data);
  1264.   vid_stream->aspect_ratio = (unsigned char) data;
  1265.  
  1266.   /* Parse off picture rate code. */
  1267.  
  1268.   get_bits4(data);
  1269.   vid_stream->picture_rate = (unsigned char) data;
  1270.  
  1271.   /* Parse off bit rate. */
  1272.  
  1273.   get_bits18(data);
  1274.   vid_stream->bit_rate = data;
  1275.  
  1276.   /* Flush marker bit. */
  1277.  
  1278.   flush_bits(1);
  1279.  
  1280.   /* Parse off vbv buffer size. */
  1281.  
  1282.   get_bits10(data);
  1283.   vid_stream->vbv_buffer_size = data;
  1284.  
  1285.   /* Parse off contrained parameter flag. */
  1286.  
  1287.   get_bits1(data);
  1288.   if (data) {
  1289.     vid_stream->const_param_flag = TRUE;
  1290.   } else
  1291.     vid_stream->const_param_flag = FALSE;
  1292.  
  1293.   /*
  1294.    * If intra_quant_matrix_flag set, parse off intra quant matrix values.
  1295.    */
  1296.  
  1297.   get_bits1(data);
  1298.   if (data) {
  1299.     for (i = 0; i < 64; i++) {
  1300.       get_bits8(data);
  1301.  
  1302.       vid_stream->intra_quant_matrix[zigzag[i][1]][zigzag[i][0]] =
  1303.     (unsigned char) data;
  1304.     }
  1305.   }
  1306.   /*
  1307.    * If non intra quant matrix flag set, parse off non intra quant matrix
  1308.    * values.
  1309.    */
  1310.  
  1311.   get_bits1(data);
  1312.   if (data) {
  1313.     for (i = 0; i < 64; i++) {
  1314.       get_bits8(data);
  1315.  
  1316.       vid_stream->non_intra_quant_matrix[zigzag[i][1]][zigzag[i][0]] =
  1317.     (unsigned char) data;
  1318.     }
  1319.   }
  1320.   /* Go to next start code. */
  1321.  
  1322.   next_start_code();
  1323.  
  1324.   /*
  1325.    * If next start code is extension start code, parse off extension data.
  1326.    */
  1327.  
  1328.   if (next_bits(32, EXT_START_CODE)) {
  1329.     flush_bits32;
  1330.     if (vid_stream->ext_data != NULL) {
  1331.       free(vid_stream->ext_data);
  1332.       vid_stream->ext_data = NULL;
  1333.     }
  1334.     vid_stream->ext_data = get_ext_data();
  1335.   }
  1336.   /* If next start code is user start code, parse off user data. */
  1337.  
  1338.   if (next_bits(32, USER_START_CODE)) {
  1339.     flush_bits32;
  1340.     if (vid_stream->user_data != NULL) {
  1341.       free(vid_stream->user_data);
  1342.       vid_stream->user_data = NULL;
  1343.     }
  1344.     vid_stream->user_data = get_ext_data();
  1345.   }
  1346.   return PARSE_OK;
  1347. }
  1348.  
  1349.  
  1350.  
  1351. /*
  1352.  *--------------------------------------------------------------
  1353.  *
  1354.  * ParseGOP --
  1355.  *
  1356.  *      Parses of group of pictures header from bit stream
  1357.  *      associated with vid_stream.
  1358.  *
  1359.  * Results:
  1360.  *      Values in gop header placed into video stream structure.
  1361.  *
  1362.  * Side effects:
  1363.  *      Bit stream irreversibly parsed.
  1364.  *
  1365.  *--------------------------------------------------------------
  1366.  */
  1367.  
  1368. static int
  1369. ParseGOP(vid_stream)
  1370.   VidStream *vid_stream;
  1371. {
  1372.   unsigned int data;
  1373.  
  1374.   /* Flush group of pictures start code. WWWWWWOOOOOOOSSSSSSHHHHH!!! */
  1375.  
  1376.   flush_bits32;
  1377.  
  1378.   /* Parse off drop frame flag. */
  1379.  
  1380.   get_bits1(data);
  1381.   if (data) {
  1382.     vid_stream->group.drop_flag = TRUE;
  1383.   } else
  1384.     vid_stream->group.drop_flag = FALSE;
  1385.  
  1386.   /* Parse off hour component of time code. */
  1387.  
  1388.   get_bits5(data);
  1389.   vid_stream->group.tc_hours = data;
  1390.  
  1391.   /* Parse off minute component of time code. */
  1392.  
  1393.   get_bits6(data);
  1394.   vid_stream->group.tc_minutes = data;
  1395.  
  1396.   /* Flush marker bit. */
  1397.  
  1398.   flush_bits(1);
  1399.  
  1400.   /* Parse off second component of time code. */
  1401.  
  1402.   get_bits6(data);
  1403.   vid_stream->group.tc_seconds = data;
  1404.  
  1405.   /* Parse off picture count component of time code. */
  1406.  
  1407.   get_bits6(data);
  1408.   vid_stream->group.tc_pictures = data;
  1409.  
  1410.   /* Parse off closed gop and broken link flags. */
  1411.  
  1412.   get_bits2(data);
  1413.   if (data > 1) {
  1414.     vid_stream->group.closed_gop = TRUE;
  1415.     if (data > 2) {
  1416.       vid_stream->group.broken_link = TRUE;
  1417.     } else
  1418.       vid_stream->group.broken_link = FALSE;
  1419.   } else {
  1420.     vid_stream->group.closed_gop = FALSE;
  1421.     if (data) {
  1422.       vid_stream->group.broken_link = TRUE;
  1423.     } else
  1424.       vid_stream->group.broken_link = FALSE;
  1425.   }
  1426.  
  1427.   /* Goto next start code. */
  1428.  
  1429.   next_start_code();
  1430.  
  1431.   /* If next start code is extension data, parse off extension data. */
  1432.  
  1433.   if (next_bits(32, EXT_START_CODE)) {
  1434.     flush_bits32;
  1435.     if (vid_stream->group.ext_data != NULL) {
  1436.       free(vid_stream->group.ext_data);
  1437.       vid_stream->group.ext_data = NULL;
  1438.     }
  1439.     vid_stream->group.ext_data = get_ext_data();
  1440.   }
  1441.   /* If next start code is user data, parse off user data. */
  1442.  
  1443.   if (next_bits(32, USER_START_CODE)) {
  1444.     flush_bits32;
  1445.     if (vid_stream->group.user_data != NULL) {
  1446.       free(vid_stream->group.user_data);
  1447.       vid_stream->group.user_data = NULL;
  1448.     }
  1449.     vid_stream->group.user_data = get_ext_data();
  1450.   }
  1451.   return PARSE_OK;
  1452. }
  1453.  
  1454.  
  1455.  
  1456. /*
  1457.  *--------------------------------------------------------------
  1458.  *
  1459.  * ParsePicture --
  1460.  *
  1461.  *      Parses picture header. Marks picture to be presented
  1462.  *      at particular time given a time stamp.
  1463.  *
  1464.  * Results:
  1465.  *      Values from picture header put into video stream structure.
  1466.  *
  1467.  * Side effects:
  1468.  *      Bit stream irreversibly parsed.
  1469.  *
  1470.  *--------------------------------------------------------------
  1471.  */
  1472.  
  1473. static int
  1474. ParsePicture(vid_stream, time_stamp)
  1475.   VidStream *vid_stream;
  1476.   TimeStamp time_stamp;
  1477. {
  1478.   unsigned int data;
  1479.   int i;
  1480.  
  1481.   /* Flush header start code. */
  1482.   flush_bits32;
  1483.  
  1484.   /* Parse off temporal reference. */
  1485.   get_bits10(data);
  1486.   vid_stream->picture.temp_ref = data;
  1487.  
  1488.   /* Parse of picture type. */
  1489.   get_bits3(data);
  1490.   vid_stream->picture.code_type = data;
  1491.  
  1492.   if ((vid_stream->picture.code_type == B_TYPE) &&
  1493.       (No_B_Flag ||
  1494.        (vid_stream->past == NULL) ||
  1495.        (vid_stream->future == NULL)))
  1496.     return SKIP_PICTURE;
  1497.  
  1498.   if ((vid_stream->picture.code_type == P_TYPE) &&
  1499.       (No_P_Flag || (vid_stream->future == NULL)))
  1500.     return SKIP_PICTURE;
  1501.  
  1502. #ifdef ANALYSIS
  1503.   StartTime();
  1504.   stat_a[0].frametype = vid_stream->picture.code_type;
  1505.   stat_a[0].number = 1;
  1506.   stat_a[0].totsize = 45;
  1507.   pictureSizeCount = bitCountRead();
  1508. #endif
  1509.  
  1510.   /* Parse off vbv buffer delay value. */
  1511.   get_bits16(data);
  1512.   vid_stream->picture.vbv_delay = data;
  1513.  
  1514.   /* If P or B type frame... */
  1515.  
  1516.   if ((vid_stream->picture.code_type == 2) || (vid_stream->picture.code_type == 3)) {
  1517.  
  1518.     /* Parse off forward vector full pixel flag. */
  1519.     get_bits1(data);
  1520.     if (data)
  1521.       vid_stream->picture.full_pel_forw_vector = TRUE;
  1522.     else
  1523.       vid_stream->picture.full_pel_forw_vector = FALSE;
  1524.  
  1525.     /* Parse of forw_r_code. */
  1526.     get_bits3(data);
  1527.  
  1528.     /* Decode forw_r_code into forw_r_size and forw_f. */
  1529.  
  1530.     vid_stream->picture.forw_r_size = data - 1;
  1531.     vid_stream->picture.forw_f = (1 << vid_stream->picture.forw_r_size);
  1532.   }
  1533.   /* If B type frame... */
  1534.  
  1535.   if (vid_stream->picture.code_type == 3) {
  1536.  
  1537.     /* Parse off back vector full pixel flag. */
  1538.     get_bits1(data);
  1539.     if (data)
  1540.       vid_stream->picture.full_pel_back_vector = TRUE;
  1541.     else
  1542.       vid_stream->picture.full_pel_back_vector = FALSE;
  1543.  
  1544.     /* Parse off back_r_code. */
  1545.     get_bits3(data);
  1546.  
  1547.     /* Decode back_r_code into back_r_size and back_f. */
  1548.  
  1549.     vid_stream->picture.back_r_size = data - 1;
  1550.     vid_stream->picture.back_f = (1 << vid_stream->picture.back_r_size);
  1551.   }
  1552.   /* Get extra bit picture info. */
  1553.  
  1554.   if (vid_stream->picture.extra_info != NULL) {
  1555.     free(vid_stream->picture.extra_info);
  1556.     vid_stream->picture.extra_info = NULL;
  1557.   }
  1558.   vid_stream->picture.extra_info = get_extra_bit_info();
  1559.  
  1560.   /* Goto next start code. */
  1561.   next_start_code();
  1562.  
  1563.   /* If start code is extension start code, parse off extension data. */
  1564.  
  1565.   if (next_bits(32, EXT_START_CODE)) {
  1566.     flush_bits32;
  1567.  
  1568.     if (vid_stream->picture.ext_data != NULL) {
  1569.       free(vid_stream->picture.ext_data);
  1570.       vid_stream->picture.ext_data = NULL;
  1571.     }
  1572.     vid_stream->picture.ext_data = get_ext_data();
  1573.   }
  1574.   /* If start code is user start code, parse off user data. */
  1575.  
  1576.   if (next_bits(32, USER_START_CODE)) {
  1577.     flush_bits32;
  1578.  
  1579.     if (vid_stream->picture.user_data != NULL) {
  1580.       free(vid_stream->picture.user_data);
  1581.       vid_stream->picture.user_data = NULL;
  1582.     }
  1583.     vid_stream->picture.user_data = get_ext_data();
  1584.   }
  1585.   /* Find a pict image structure in ring buffer not currently locked. */
  1586.  
  1587.   i = 0;
  1588.  
  1589.   while (vid_stream->ring[i]->locked != 0) {
  1590.     if (++i >= RING_BUF_SIZE) {
  1591.       perror("Fatal error. Ring buffer full.");
  1592.       exit(1);
  1593.     }
  1594.   }
  1595.  
  1596.   /* Set current pict image structure to the one just found in ring. */
  1597.  
  1598.   vid_stream->current = vid_stream->ring[i];
  1599.  
  1600.   /* Set time stamp. */
  1601.  
  1602.   vid_stream->current->show_time = time_stamp;
  1603.  
  1604.   /* Reset past macroblock address field. */
  1605.  
  1606.   vid_stream->mblock.past_mb_addr = -1;
  1607.  
  1608.   return PARSE_OK;
  1609. }
  1610.  
  1611.  
  1612.  
  1613. /*
  1614.  *--------------------------------------------------------------
  1615.  *
  1616.  * ParseSlice --
  1617.  *
  1618.  *      Parses off slice header.
  1619.  *
  1620.  * Results:
  1621.  *      Values found in slice header put into video stream structure.
  1622.  *
  1623.  * Side effects:
  1624.  *      Bit stream irreversibly parsed.
  1625.  *
  1626.  *--------------------------------------------------------------
  1627.  */
  1628.  
  1629. static int
  1630. ParseSlice(vid_stream)
  1631.   VidStream *vid_stream;
  1632. {
  1633.   unsigned int data;
  1634.  
  1635.   /* Flush slice start code. */
  1636.  
  1637.   flush_bits(24);
  1638.  
  1639.   /* Parse off slice vertical position. */
  1640.  
  1641.   get_bits8(data);
  1642.   vid_stream->slice.vert_pos = data;
  1643.  
  1644.   /* Parse off quantization scale. */
  1645.  
  1646.   get_bits5(data);
  1647.   vid_stream->slice.quant_scale = data;
  1648.  
  1649.   /* Parse off extra bit slice info. */
  1650.  
  1651.   if (vid_stream->slice.extra_info != NULL) {
  1652.     free(vid_stream->slice.extra_info);
  1653.     vid_stream->slice.extra_info = NULL;
  1654.   }
  1655.   vid_stream->slice.extra_info = get_extra_bit_info();
  1656.  
  1657.   /* Reset past intrablock address. */
  1658.  
  1659.   vid_stream->mblock.past_intra_addr = -2;
  1660.  
  1661.   /* Reset previous recon motion vectors. */
  1662.  
  1663.   vid_stream->mblock.recon_right_for_prev = 0;
  1664.   vid_stream->mblock.recon_down_for_prev = 0;
  1665.   vid_stream->mblock.recon_right_back_prev = 0;
  1666.   vid_stream->mblock.recon_down_back_prev = 0;
  1667.  
  1668.   /* Reset macroblock address. */
  1669.  
  1670.   vid_stream->mblock.mb_address = ((vid_stream->slice.vert_pos - 1) *
  1671.                    vid_stream->mb_width) - 1;
  1672.  
  1673.   /* Reset past dct dc y, cr, and cb values. */
  1674.  
  1675.   vid_stream->block.dct_dc_y_past = 1024;
  1676.   vid_stream->block.dct_dc_cr_past = 1024;
  1677.   vid_stream->block.dct_dc_cb_past = 1024;
  1678.  
  1679.   return PARSE_OK;
  1680. }
  1681.  
  1682.  
  1683.  
  1684. /*
  1685.  *--------------------------------------------------------------
  1686.  *
  1687.  * ParseMacroBlock --
  1688.  *
  1689.  *      Parseoff macroblock. Reconstructs DCT values. Applies
  1690.  *      inverse DCT, reconstructs motion vectors, calculates and
  1691.  *      set pixel values for macroblock in current pict image
  1692.  *      structure.
  1693.  *
  1694.  * Results:
  1695.  *      Here's where everything really happens. Welcome to the
  1696.  *      heart of darkness.
  1697.  *
  1698.  * Side effects:
  1699.  *      Bit stream irreversibly parsed off.
  1700.  *
  1701.  *--------------------------------------------------------------
  1702.  */
  1703.  
  1704. static int
  1705. ParseMacroBlock(vid_stream)
  1706.   VidStream *vid_stream;
  1707. {
  1708.   int addr_incr;
  1709.   unsigned int data;
  1710.   int mask, i, recon_right_for, recon_down_for, recon_right_back,
  1711.       recon_down_back;
  1712.   int zero_block_flag;
  1713.   BOOLEAN mb_quant, mb_motion_forw, mb_motion_back, mb_pattern;
  1714.   int no_dith_flag = 0;
  1715.  
  1716. #ifdef ANALYSIS
  1717.   mbSizeCount = bitCountRead();
  1718. #endif
  1719.  
  1720.   /*
  1721.    * Parse off macroblock address increment and add to macroblock address.
  1722.    */
  1723.   do {
  1724.     DecodeMBAddrInc(addr_incr);
  1725.     if (addr_incr == MB_ESCAPE) {
  1726.       vid_stream->mblock.mb_address += 33;
  1727.       addr_incr = MB_STUFFING;
  1728.     }
  1729.   } while (addr_incr == MB_STUFFING);
  1730.   vid_stream->mblock.mb_address += addr_incr;
  1731.  
  1732.   if (vid_stream->mblock.mb_address > (vid_stream->mb_height *
  1733.                        vid_stream->mb_width - 1))
  1734.     return SKIP_TO_START_CODE;
  1735.  
  1736.   /*
  1737.    * If macroblocks have been skipped, process skipped macroblocks.
  1738.    */
  1739.  
  1740.   if (vid_stream->mblock.mb_address - vid_stream->mblock.past_mb_addr > 1) {
  1741.     if (vid_stream->picture.code_type == P_TYPE)
  1742.       ProcessSkippedPFrameMBlocks(vid_stream);
  1743.     else if (vid_stream->picture.code_type == B_TYPE)
  1744.       ProcessSkippedBFrameMBlocks(vid_stream);
  1745.   }
  1746.   /* Set past macroblock address to current macroblock address. */
  1747.   vid_stream->mblock.past_mb_addr = vid_stream->mblock.mb_address;
  1748.  
  1749.   /* Based on picture type decode macroblock type. */
  1750.   switch (vid_stream->picture.code_type) {
  1751.   case I_TYPE:
  1752.     DecodeMBTypeI(mb_quant, mb_motion_forw, mb_motion_back, mb_pattern,
  1753.           vid_stream->mblock.mb_intra);
  1754.     break;
  1755.  
  1756.   case P_TYPE:
  1757.     DecodeMBTypeP(mb_quant, mb_motion_forw, mb_motion_back, mb_pattern,
  1758.           vid_stream->mblock.mb_intra);
  1759.     break;
  1760.  
  1761.   case B_TYPE:
  1762.     DecodeMBTypeB(mb_quant, mb_motion_forw, mb_motion_back, mb_pattern,
  1763.           vid_stream->mblock.mb_intra);
  1764.     break;
  1765.   }
  1766.  
  1767.   /* If quantization flag set, parse off new quantization scale. */
  1768.  
  1769.   if (mb_quant == TRUE) {
  1770.     get_bits5(data);
  1771.     vid_stream->slice.quant_scale = data;
  1772.   }
  1773.   /* If forward motion vectors exist... */
  1774.   if (mb_motion_forw == TRUE) {
  1775.  
  1776.     /* Parse off and decode horizontal forward motion vector. */
  1777.     DecodeMotionVectors(vid_stream->mblock.motion_h_forw_code);
  1778.  
  1779.     /* If horiz. forward r data exists, parse off. */
  1780.  
  1781.     if ((vid_stream->picture.forw_f != 1) &&
  1782.     (vid_stream->mblock.motion_h_forw_code != 0)) {
  1783.       get_bitsn(vid_stream->picture.forw_r_size, data);
  1784.       vid_stream->mblock.motion_h_forw_r = data;
  1785.     }
  1786.     /* Parse off and decode vertical forward motion vector. */
  1787.     DecodeMotionVectors(vid_stream->mblock.motion_v_forw_code);
  1788.  
  1789.     /* If vert. forw. r data exists, parse off. */
  1790.  
  1791.     if ((vid_stream->picture.forw_f != 1) &&
  1792.     (vid_stream->mblock.motion_v_forw_code != 0)) {
  1793.       get_bitsn(vid_stream->picture.forw_r_size, data);
  1794.       vid_stream->mblock.motion_v_forw_r = data;
  1795.     }
  1796.   }
  1797.   /* If back motion vectors exist... */
  1798.   if (mb_motion_back == TRUE) {
  1799.  
  1800.     /* Parse off and decode horiz. back motion vector. */
  1801.     DecodeMotionVectors(vid_stream->mblock.motion_h_back_code);
  1802.  
  1803.     /* If horiz. back r data exists, parse off. */
  1804.  
  1805.     if ((vid_stream->picture.back_f != 1) &&
  1806.     (vid_stream->mblock.motion_h_back_code != 0)) {
  1807.       get_bitsn(vid_stream->picture.back_r_size, data);
  1808.       vid_stream->mblock.motion_h_back_r = data;
  1809.     }
  1810.     /* Parse off and decode vert. back motion vector. */
  1811.     DecodeMotionVectors(vid_stream->mblock.motion_v_back_code);
  1812.  
  1813.     /* If vert. back r data exists, parse off. */
  1814.  
  1815.     if ((vid_stream->picture.back_f != 1) &&
  1816.     (vid_stream->mblock.motion_v_back_code != 0)) {
  1817.       get_bitsn(vid_stream->picture.back_r_size, data);
  1818.       vid_stream->mblock.motion_v_back_r = data;
  1819.     }
  1820.   }
  1821. #ifdef ANALYSIS
  1822.   if (vid_stream->mblock.mb_intra) {
  1823.     stat_a[0].i_mbnum++;
  1824.     mbCBPPtr = stat_a[0].i_mbcbp;
  1825.     mbCoeffPtr = stat_a[0].i_mbcoeff;
  1826.     mbSizePtr = &(stat_a[0].i_mbsize);
  1827.   } else if (mb_motion_back && mb_motion_forw) {
  1828.     stat_a[0].bi_mbnum++;
  1829.     mbCBPPtr = stat_a[0].bi_mbcbp;
  1830.     mbCoeffPtr = stat_a[0].bi_mbcoeff;
  1831.     mbSizePtr = &(stat_a[0].bi_mbsize);
  1832.   } else if (mb_motion_back) {
  1833.     stat_a[0].b_mbnum++;
  1834.     mbCBPPtr = stat_a[0].b_mbcbp;
  1835.     mbCoeffPtr = stat_a[0].b_mbcoeff;
  1836.     mbSizePtr = &(stat_a[0].b_mbsize);
  1837.   } else {
  1838.     stat_a[0].p_mbnum++;
  1839.     mbCBPPtr = stat_a[0].p_mbcbp;
  1840.     mbCoeffPtr = stat_a[0].p_mbcoeff;
  1841.     mbSizePtr = &(stat_a[0].p_mbsize);
  1842.   }
  1843. #endif
  1844.  
  1845.   /* If mblock pattern flag set, parse and decode CBP (code block pattern). */
  1846.   if (mb_pattern == TRUE) {
  1847.     DecodeCBP(vid_stream->mblock.cbp);
  1848.   }
  1849.   /* Otherwise, set CBP to zero. */
  1850.   else
  1851.     vid_stream->mblock.cbp = 0;
  1852.  
  1853.  
  1854. #ifdef ANALYSIS
  1855.   mbCBPPtr[vid_stream->mblock.cbp]++;
  1856. #endif
  1857.  
  1858.   /* Reconstruct motion vectors depending on picture type. */
  1859.   if (vid_stream->picture.code_type == P_TYPE) {
  1860.  
  1861.     /*
  1862.      * If no forw motion vectors, reset previous and current vectors to 0.
  1863.      */
  1864.  
  1865.     if (!mb_motion_forw) {
  1866.       recon_right_for = 0;
  1867.       recon_down_for = 0;
  1868.       vid_stream->mblock.recon_right_for_prev = 0;
  1869.       vid_stream->mblock.recon_down_for_prev = 0;
  1870.     }
  1871.     /*
  1872.      * Otherwise, compute new forw motion vectors. Reset previous vectors to
  1873.      * current vectors.
  1874.      */
  1875.  
  1876.     else {
  1877.       ComputeForwVector(&recon_right_for, &recon_down_for);
  1878.     }
  1879.   }
  1880.   if (vid_stream->picture.code_type == B_TYPE) {
  1881.  
  1882.     /* Reset prev. and current vectors to zero if mblock is intracoded. */
  1883.  
  1884.     if (vid_stream->mblock.mb_intra) {
  1885.       vid_stream->mblock.recon_right_for_prev = 0;
  1886.       vid_stream->mblock.recon_down_for_prev = 0;
  1887.       vid_stream->mblock.recon_right_back_prev = 0;
  1888.       vid_stream->mblock.recon_down_back_prev = 0;
  1889.     } else {
  1890.  
  1891.       /* If no forw vectors, current vectors equal prev. vectors. */
  1892.  
  1893.       if (!mb_motion_forw) {
  1894.     recon_right_for = vid_stream->mblock.recon_right_for_prev;
  1895.     recon_down_for = vid_stream->mblock.recon_down_for_prev;
  1896.       }
  1897.       /*
  1898.        * Otherwise compute forw. vectors. Reset prev vectors to new values.
  1899.        */
  1900.  
  1901.       else {
  1902.         ComputeForwVector(&recon_right_for, &recon_down_for);
  1903.       }
  1904.  
  1905.       /* If no back vectors, set back vectors to prev back vectors. */
  1906.  
  1907.       if (!mb_motion_back) {
  1908.     recon_right_back = vid_stream->mblock.recon_right_back_prev;
  1909.     recon_down_back = vid_stream->mblock.recon_down_back_prev;
  1910.       }
  1911.       /* Otherwise compute new vectors and reset prev. back vectors. */
  1912.  
  1913.       else {
  1914.     ComputeBackVector(&recon_right_back, &recon_down_back);
  1915.       }
  1916.  
  1917.       /*
  1918.        * Store vector existance flags in structure for possible skipped
  1919.        * macroblocks to follow.
  1920.        */
  1921.  
  1922.       vid_stream->mblock.bpict_past_forw = mb_motion_forw;
  1923.       vid_stream->mblock.bpict_past_back = mb_motion_back;
  1924.     }
  1925.   }
  1926.  
  1927.   /* For each possible block in macroblock. */
  1928.   if (ditherType == GRAY_DITHER ||
  1929.       ditherType == MONO_DITHER ||
  1930.       ditherType == MONO_THRESHOLD) {
  1931.     for (mask = 32, i = 0; i < 4; mask >>= 1, i++) {
  1932.  
  1933.       /* If block exists... */
  1934.       if ((vid_stream->mblock.mb_intra) || (vid_stream->mblock.cbp & mask)) {
  1935.     zero_block_flag = 0;
  1936.     ParseReconBlock(i);
  1937.       } else {
  1938.     zero_block_flag = 1;
  1939.       }
  1940.  
  1941.       /* If macroblock is intra coded... */
  1942.       if (vid_stream->mblock.mb_intra) {
  1943.     ReconIMBlock(vid_stream, i);
  1944.       } else if (mb_motion_forw && mb_motion_back) {
  1945.     ReconBiMBlock(vid_stream, i, recon_right_for, recon_down_for,
  1946.               recon_right_back, recon_down_back, zero_block_flag);
  1947.       } else if (mb_motion_forw || (vid_stream->picture.code_type == P_TYPE)) {
  1948.     ReconPMBlock(vid_stream, i, recon_right_for, recon_down_for,
  1949.              zero_block_flag);
  1950.       } else if (mb_motion_back) {
  1951.     ReconBMBlock(vid_stream, i, recon_right_back, recon_down_back,
  1952.              zero_block_flag);
  1953.       }
  1954.     }
  1955.     /* Kill the Chrominace blocks... */
  1956.     if ((vid_stream->mblock.mb_intra) || (vid_stream->mblock.cbp & 0x2)) {
  1957.         ParseAwayBlock(4);
  1958.     }
  1959.     if ((vid_stream->mblock.mb_intra) || (vid_stream->mblock.cbp & 0x1)) {
  1960.         ParseAwayBlock(5);
  1961.     }
  1962.   } else {
  1963.     if ((ditherType == MBORDERED_DITHER) &&
  1964.     (vid_stream->mblock.cbp == 0) &&
  1965.     (vid_stream->picture.code_type == 3) &&
  1966.     (!vid_stream->mblock.mb_intra) &&
  1967.     (!(mb_motion_forw && mb_motion_back))) {
  1968.       MBOrderedDitherDisplayCopy(vid_stream, vid_stream->mblock.mb_address, 
  1969.              mb_motion_forw, recon_right_for, recon_down_for, 
  1970.              mb_motion_back, recon_right_back, recon_down_back,
  1971.              vid_stream->past->display, vid_stream->future->display);
  1972.       ditherFlags[vid_stream->mblock.mb_address] = 0;
  1973.       no_dith_flag = 1;
  1974.     }
  1975.     else {
  1976.       for (mask = 32, i = 0; i < 6; mask >>= 1, i++) {
  1977.     
  1978.     /* If block exists... */
  1979.     if ((vid_stream->mblock.mb_intra) || (vid_stream->mblock.cbp & mask)) {
  1980.       zero_block_flag = 0;
  1981.       ParseReconBlock(i);
  1982.     } else {
  1983.       zero_block_flag = 1;
  1984.     }
  1985.     
  1986.     /* If macroblock is intra coded... */
  1987.     if (vid_stream->mblock.mb_intra) {
  1988.       ReconIMBlock(vid_stream, i);
  1989.     } else if (mb_motion_forw && mb_motion_back) {
  1990.       ReconBiMBlock(vid_stream, i, recon_right_for, recon_down_for,
  1991.             recon_right_back, recon_down_back, zero_block_flag);
  1992.     } else if (mb_motion_forw || (vid_stream->picture.code_type == P_TYPE)) {
  1993.       ReconPMBlock(vid_stream, i, recon_right_for, recon_down_for,
  1994.                zero_block_flag);
  1995.     } else if (mb_motion_back) {
  1996.       ReconBMBlock(vid_stream, i, recon_right_back, recon_down_back,
  1997.                zero_block_flag);
  1998.     }
  1999.       }
  2000.     }
  2001.   }
  2002.  
  2003.   if ((ditherType == MBORDERED_DITHER) && (!no_dith_flag)) {
  2004.     if ((vid_stream->picture.code_type == 2) &&
  2005.     (vid_stream->mblock.cbp == 0) &&
  2006.     (!vid_stream->mblock.mb_intra)) {
  2007.       MBOrderedDitherDisplayCopy(vid_stream, vid_stream->mblock.mb_address,
  2008.                  1, recon_right_for, recon_down_for,
  2009.                  0, 0, 0,
  2010.                  vid_stream->future->display,
  2011.                  (unsigned char *) NULL);
  2012.       ditherFlags[vid_stream->mblock.mb_address] = 0;
  2013.     }
  2014.     else {
  2015.       ditherFlags[vid_stream->mblock.mb_address] = 1;
  2016.     }
  2017.   }
  2018.  
  2019.  
  2020.   /* If D Type picture, flush marker bit. */
  2021.   if (vid_stream->picture.code_type == 4)
  2022.     flush_bits(1);
  2023.  
  2024.   /* If macroblock was intracoded, set macroblock past intra address. */
  2025.   if (vid_stream->mblock.mb_intra)
  2026.     vid_stream->mblock.past_intra_addr =
  2027.       vid_stream->mblock.mb_address;
  2028.  
  2029. #ifdef ANALYSIS
  2030.   *mbSizePtr += bitCountRead() - mbSizeCount;
  2031. #endif
  2032.   return PARSE_OK;
  2033. }
  2034.  
  2035.  
  2036.  
  2037. /*
  2038.  *--------------------------------------------------------------
  2039.  *
  2040.  * ReconIMBlock --
  2041.  *
  2042.  *    Reconstructs intra coded macroblock.
  2043.  *
  2044.  * Results:
  2045.  *    None.
  2046.  *
  2047.  * Side effects:
  2048.  *    None.
  2049.  *
  2050.  *--------------------------------------------------------------
  2051.  */
  2052.  
  2053. static void
  2054. ReconIMBlock(vid_stream, bnum)
  2055.   VidStream *vid_stream;
  2056.   int bnum;
  2057. {
  2058.   int mb_row, mb_col, row, col, row_size, rr;
  2059.   unsigned char *dest;
  2060.  
  2061.   /* Calculate macroblock row and column from address. */
  2062.  
  2063.   mb_row = vid_stream->mblock.mb_address / vid_stream->mb_width;
  2064.   mb_col = vid_stream->mblock.mb_address % vid_stream->mb_width;
  2065.  
  2066.  
  2067.   /* If block is luminance block... */
  2068.  
  2069.   if (bnum < 4) {
  2070.  
  2071.     /* Calculate row and col values for upper left pixel of block. */
  2072.  
  2073.     row = mb_row * 16;
  2074.     col = mb_col * 16;
  2075.     if (bnum > 1)
  2076.       row += 8;
  2077.     if (bnum % 2)
  2078.       col += 8;
  2079.  
  2080.     /* Set dest to luminance plane of current pict image. */
  2081.  
  2082.     dest = vid_stream->current->luminance;
  2083.  
  2084.     /* Establish row size. */
  2085.  
  2086.     row_size = vid_stream->mb_width * 16;
  2087.   }
  2088.   /* Otherwise if block is Cr block... */
  2089.  
  2090.   else if (bnum == 4) {
  2091.  
  2092.     /* Set dest to Cr plane of current pict image. */
  2093.  
  2094.     dest = vid_stream->current->Cr;
  2095.  
  2096.     /* Establish row size. */
  2097.  
  2098.     row_size = vid_stream->mb_width * 8;
  2099.  
  2100.     /* Calculate row,col for upper left pixel of block. */
  2101.  
  2102.     row = mb_row * 8;
  2103.     col = mb_col * 8;
  2104.   }
  2105.   /* Otherwise block is Cb block, and ... */
  2106.  
  2107.   else {
  2108.  
  2109.     /* Set dest to Cb plane of current pict image. */
  2110.  
  2111.     dest = vid_stream->current->Cb;
  2112.  
  2113.     /* Establish row size. */
  2114.  
  2115.     row_size = vid_stream->mb_width * 8;
  2116.  
  2117.     /* Calculate row,col for upper left pixel value of block. */
  2118.  
  2119.     row = mb_row * 8;
  2120.     col = mb_col * 8;
  2121.   }
  2122.  
  2123.   /*
  2124.    * For each pixel in block, set to cropped reconstructed value from inverse
  2125.    * dct.
  2126.    */
  2127.   {
  2128.     short *sp = &vid_stream->block.dct_recon[0][0];
  2129.     unsigned char *cm = cropTbl + MAX_NEG_CROP;
  2130.     dest += row * row_size + col;
  2131.     for (rr = 0; rr < 4; rr++, sp += 16, dest += row_size) {
  2132.       dest[0] = cm[sp[0]];
  2133.       assertCrop(sp[0]);
  2134.       dest[1] = cm[sp[1]];
  2135.       assertCrop(sp[1]);
  2136.       dest[2] = cm[sp[2]];
  2137.       assertCrop(sp[2]);
  2138.       dest[3] = cm[sp[3]];
  2139.       assertCrop(sp[3]);
  2140.       dest[4] = cm[sp[4]];
  2141.       assertCrop(sp[4]);
  2142.       dest[5] = cm[sp[5]];
  2143.       assertCrop(sp[5]);
  2144.       dest[6] = cm[sp[6]];
  2145.       assertCrop(sp[6]);
  2146.       dest[7] = cm[sp[7]];
  2147.       assertCrop(sp[7]);
  2148.  
  2149.       dest += row_size;
  2150.       dest[0] = cm[sp[8]];
  2151.       assertCrop(sp[8]);
  2152.       dest[1] = cm[sp[9]];
  2153.       assertCrop(sp[9]);
  2154.       dest[2] = cm[sp[10]];
  2155.       assertCrop(sp[10]);
  2156.       dest[3] = cm[sp[11]];
  2157.       assertCrop(sp[11]);
  2158.       dest[4] = cm[sp[12]];
  2159.       assertCrop(sp[12]);
  2160.       dest[5] = cm[sp[13]];
  2161.       assertCrop(sp[13]);
  2162.       dest[6] = cm[sp[14]];
  2163.       assertCrop(sp[14]);
  2164.       dest[7] = cm[sp[15]];
  2165.       assertCrop(sp[15]);
  2166.     }
  2167.   }
  2168. }
  2169.  
  2170.  
  2171.  
  2172. /*
  2173.  *--------------------------------------------------------------
  2174.  *
  2175.  * ReconPMBlock --
  2176.  *
  2177.  *    Reconstructs forward predicted macroblocks.
  2178.  *
  2179.  * Results:
  2180.  *      None.
  2181.  *
  2182.  * Side effects:
  2183.  *      None.
  2184.  *
  2185.  *--------------------------------------------------------------
  2186.  */
  2187.  
  2188. static void
  2189. ReconPMBlock(vid_stream, bnum, recon_right_for, recon_down_for, zflag)
  2190.   VidStream *vid_stream;
  2191.   int bnum, recon_right_for, recon_down_for, zflag;
  2192. {
  2193.   int mb_row, mb_col, row, col, row_size, rr;
  2194.   unsigned char *dest, *past;
  2195.   static int right_for, down_for, right_half_for, down_half_for;
  2196.   unsigned char *rindex1, *rindex2;
  2197.   unsigned char *index;
  2198.   short int *blockvals;
  2199.  
  2200. #ifdef LOOSE_MPEG
  2201.   int maxx, maxy;
  2202.   int illegalBlock = 0;
  2203.   int row_start, row_end, rfirst, rlast, col_start, col_end, cfirst, clast;
  2204. #endif
  2205.  
  2206.   /* Calculate macroblock row and column from address. */
  2207.  
  2208.   mb_row = vid_stream->mblock.mb_address / vid_stream->mb_width;
  2209.   mb_col = vid_stream->mblock.mb_address % vid_stream->mb_width;
  2210.  
  2211.   if (bnum < 4) {
  2212.  
  2213.     /* Calculate right_for, down_for motion vectors. */
  2214.  
  2215.     right_for = recon_right_for >> 1;
  2216.     down_for = recon_down_for >> 1;
  2217.     right_half_for = recon_right_for & 0x1;
  2218.     down_half_for = recon_down_for & 0x1;
  2219.  
  2220.     /* Set dest to luminance plane of current pict image. */
  2221.  
  2222.     dest = vid_stream->current->luminance;
  2223.  
  2224.     if (vid_stream->picture.code_type == B_TYPE) {
  2225.       if (vid_stream->past != NULL)
  2226.     past = vid_stream->past->luminance;
  2227.     } else {
  2228.  
  2229.       /* Set predicitive frame to current future frame. */
  2230.  
  2231.       if (vid_stream->future != NULL)
  2232.     past = vid_stream->future->luminance;
  2233.     }
  2234.  
  2235.     /* Establish row size. */
  2236.  
  2237.     row_size = vid_stream->mb_width << 4;
  2238.  
  2239.     /* Calculate row,col of upper left pixel in block. */
  2240.  
  2241.     row = mb_row << 4;
  2242.     col = mb_col << 4;
  2243.     if (bnum > 1)
  2244.       row += 8;
  2245.     if (bnum % 2)
  2246.       col += 8;
  2247.  
  2248. #ifdef LOOSE_MPEG
  2249.     /* Check for block illegality. */
  2250.  
  2251.     maxx = lmaxx; maxy = lmaxy;
  2252.  
  2253.     if (row + down_for + 7 > maxy) illegalBlock |= 0x4;
  2254.     else if (row + down_for < 0)  illegalBlock |= 0x1;
  2255.     
  2256.     if (col + right_for + 7 > maxx) illegalBlock |= 0x2;
  2257.     else if (col + right_for < 0) illegalBlock |= 0x8;
  2258.  
  2259. #endif
  2260.   }
  2261.   /* Otherwise, block is NOT luminance block, ... */
  2262.  
  2263.   else {
  2264.  
  2265.     /* Construct motion vectors. */
  2266.  
  2267.     recon_right_for /= 2;
  2268.     recon_down_for /= 2;
  2269.     right_for = recon_right_for >> 1;
  2270.     down_for = recon_down_for >> 1;
  2271.     right_half_for = recon_right_for & 0x1;
  2272.     down_half_for = recon_down_for & 0x1;
  2273.  
  2274.     /* Establish row size. */
  2275.  
  2276.     row_size = vid_stream->mb_width << 3;
  2277.  
  2278.     /* Calculate row,col of upper left pixel in block. */
  2279.  
  2280.     row = mb_row << 3;
  2281.     col = mb_col << 3;
  2282.  
  2283. #ifdef LOOSE_MPEG
  2284.     /* Check for block illegality. */
  2285.  
  2286.     maxx = cmaxx; maxy = cmaxy;
  2287.  
  2288.     if (row + down_for  + 7 > maxy) illegalBlock |= 0x4;
  2289.     else if (row + down_for < 0) illegalBlock |= 0x1;
  2290.  
  2291.     if (col + right_for  + 7 > maxx) illegalBlock  |= 0x2;
  2292.     else if (col + right_for < 0) illegalBlock |= 0x8;
  2293.  
  2294. #endif
  2295.  
  2296.     /* If block is Cr block... */
  2297.  
  2298.     if (bnum == 4) {
  2299.  
  2300.       /* Set dest to Cr plane of current pict image. */
  2301.  
  2302.       dest = vid_stream->current->Cr;
  2303.  
  2304.       if (vid_stream->picture.code_type == B_TYPE) {
  2305.  
  2306.     if (vid_stream->past != NULL)
  2307.       past = vid_stream->past->Cr;
  2308.       } else {
  2309.     if (vid_stream->future != NULL)
  2310.       past = vid_stream->future->Cr;
  2311.       }
  2312.     }
  2313.     /* Otherwise, block is Cb block... */
  2314.  
  2315.     else {
  2316.  
  2317.       /* Set dest to Cb plane of current pict image. */
  2318.  
  2319.       dest = vid_stream->current->Cb;
  2320.  
  2321.       if (vid_stream->picture.code_type == B_TYPE) {
  2322.     if (vid_stream->past != NULL)
  2323.       past = vid_stream->past->Cb;
  2324.       } else {
  2325.     if (vid_stream->future != NULL)
  2326.       past = vid_stream->future->Cb;
  2327.       }
  2328.     }
  2329.   }
  2330.  
  2331.   /* For each pixel in block... */
  2332.  
  2333. #ifdef LOOSE_MPEG
  2334.  
  2335.   if (illegalBlock) {
  2336.     if (illegalBlock & 0x1) {
  2337.       row_start = 0;
  2338.       row_end = row+down_for+8;
  2339.       rfirst = rlast = 8 - row_end;
  2340.     }
  2341.     else if (illegalBlock & 0x4) {
  2342.       row_start = row + down_for;
  2343.       row_end = maxy+1;
  2344.       rlast = row_end - row_start - 1;
  2345.       rfirst = 0;
  2346.     }
  2347.     else {
  2348.       row_start = row+down_for;
  2349.       row_end = row_start+8;
  2350.       rfirst = 0;
  2351.     }
  2352.  
  2353.     if (illegalBlock & 0x8) {
  2354.       col_start = 0;
  2355.       col_end = col + right_for + 8;
  2356.       cfirst = clast = 8 - col_end;
  2357.     }
  2358.     else if (illegalBlock & 0x2) {
  2359.       col_start = col + right_for;
  2360.       col_end = maxx + 1;
  2361.       clast = col_end - col_start - 1;
  2362.       cfirst = 0;
  2363.     }
  2364.     else {
  2365.       col_start = col + right_for;
  2366.       col_end = col_start + 8;
  2367.       cfirst = 0;
  2368.     }
  2369.  
  2370.     for (rr = row_start; rr < row_end; rr++) {
  2371.       rindex1 = past + (rr * row_size) + col_start;
  2372.       index = dest + ((row + rfirst) * row_size) + col + cfirst;
  2373.       for (cc = col_start; cc < col_end; cc++) {
  2374.     *index++ = *rindex1++;
  2375.       }
  2376.     }
  2377.  
  2378.     if (illegalBlock & 0x1) {
  2379.       for (rr = rlast -1; rr >=0; rr--) {
  2380.     index = dest + ((row + rr) * row_size) + col;
  2381.     rindex1 = dest + ((row + rlast) * row_size) + col;
  2382.     for (cc = 0; cc < 8; cc ++) {
  2383.       *index++ = *rindex1++;
  2384.     }
  2385.       }
  2386.     }
  2387.     else if (illegalBlock & 0x4) {
  2388.       for (rr = rlast+1; rr < 8; rr++) {
  2389.     index = dest + ((row + rr) * row_size) + col;
  2390.     rindex1 = dest + ((row + rlast) * row_size) + col;
  2391.     for (cc = 0; cc < 8; cc ++) {
  2392.       *index++ = *rindex1++;
  2393.     }
  2394.       }
  2395.     }
  2396.  
  2397.     if (illegalBlock & 0x2) {
  2398.       for (cc = clast+1; cc < 8; cc++) {
  2399.     index = dest + (row * row_size) + (col + cc);
  2400.     rindex1 = dest + (row * row_size) + (col + clast);
  2401.     for (rr = 0; rr < 8; rr++) {
  2402.       *index = *rindex1;
  2403.       index += row_size;
  2404.       rindex1 += row_size;
  2405.     }
  2406.       }
  2407.     }
  2408.     else if (illegalBlock & 0x8) {
  2409.       for (cc = clast-1; cc >= 0; cc--) {
  2410.     index = dest + (row * row_size) + (col + cc);
  2411.     rindex1 = dest + (row * row_size) + (col + clast);
  2412.     for (rr = 0; rr < 8; rr++) {
  2413.       *index = *rindex1;
  2414.       index += row_size;
  2415.       rindex1 += row_size;
  2416.     }
  2417.       }
  2418.     }
  2419.  
  2420.     if (!zflag) {
  2421.       for (rr = 0; rr < 8; rr++) {
  2422.     index = dest + (row*row_size) + col;
  2423.     blockvals = &(vid_stream->block.dct_recon[rr][0]);
  2424.     index[0] += blockvals[0];
  2425.     index[1] += blockvals[1];
  2426.     index[2] += blockvals[2];
  2427.     index[3] += blockvals[3];
  2428.     index[4] += blockvals[4];
  2429.     index[5] += blockvals[5];
  2430.     index[6] += blockvals[6];
  2431.     index[7] += blockvals[7];
  2432.       }
  2433.     }
  2434.   }
  2435.   else {
  2436.  
  2437. #endif
  2438.  
  2439.     index = dest + (row * row_size) + col;
  2440.     rindex1 = past + (row + down_for) * row_size + col + right_for;
  2441.     
  2442.     blockvals = &(vid_stream->block.dct_recon[0][0]);
  2443.     
  2444.     /*
  2445.      * Calculate predictive pixel value based on motion vectors and copy to
  2446.      * dest plane.
  2447.      */
  2448.     
  2449.     if ((!down_half_for) && (!right_half_for)) {
  2450.       unsigned char *cm = cropTbl + MAX_NEG_CROP;
  2451.       if (!zflag)
  2452.     for (rr = 0; rr < 4; rr++) {
  2453.       index[0] = cm[(int) rindex1[0] + (int) blockvals[0]];
  2454.       index[1] = cm[(int) rindex1[1] + (int) blockvals[1]];
  2455.       index[2] = cm[(int) rindex1[2] + (int) blockvals[2]];
  2456.       index[3] = cm[(int) rindex1[3] + (int) blockvals[3]];
  2457.       index[4] = cm[(int) rindex1[4] + (int) blockvals[4]];
  2458.       index[5] = cm[(int) rindex1[5] + (int) blockvals[5]];
  2459.       index[6] = cm[(int) rindex1[6] + (int) blockvals[6]];
  2460.       index[7] = cm[(int) rindex1[7] + (int) blockvals[7]];
  2461.       index += row_size;
  2462.       rindex1 += row_size;
  2463.       
  2464.       index[0] = cm[(int) rindex1[0] + (int) blockvals[8]];
  2465.       index[1] = cm[(int) rindex1[1] + (int) blockvals[9]];
  2466.       index[2] = cm[(int) rindex1[2] + (int) blockvals[10]];
  2467.       index[3] = cm[(int) rindex1[3] + (int) blockvals[11]];
  2468.       index[4] = cm[(int) rindex1[4] + (int) blockvals[12]];
  2469.       index[5] = cm[(int) rindex1[5] + (int) blockvals[13]];
  2470.       index[6] = cm[(int) rindex1[6] + (int) blockvals[14]];
  2471.       index[7] = cm[(int) rindex1[7] + (int) blockvals[15]];
  2472.       blockvals += 16;
  2473.       index += row_size;
  2474.       rindex1 += row_size;
  2475.     }
  2476.       else {
  2477.     if (right_for & 0x1) {
  2478.       /* No alignment, use bye copy */
  2479.       for (rr = 0; rr < 4; rr++) {
  2480.         index[0] = rindex1[0];
  2481.         index[1] = rindex1[1];
  2482.         index[2] = rindex1[2];
  2483.         index[3] = rindex1[3];
  2484.         index[4] = rindex1[4];
  2485.         index[5] = rindex1[5];
  2486.         index[6] = rindex1[6];
  2487.         index[7] = rindex1[7];
  2488.         index += row_size;
  2489.         rindex1 += row_size;
  2490.         
  2491.         index[0] = rindex1[0];
  2492.         index[1] = rindex1[1];
  2493.         index[2] = rindex1[2];
  2494.         index[3] = rindex1[3];
  2495.         index[4] = rindex1[4];
  2496.         index[5] = rindex1[5];
  2497.         index[6] = rindex1[6];
  2498.         index[7] = rindex1[7];
  2499.         index += row_size;
  2500.         rindex1 += row_size;
  2501.       }
  2502.     } else if (right_for & 0x2) {
  2503.       /* Half-word bit aligned, use 16 bit copy */
  2504.       short *src = (short *)rindex1;
  2505.       short *dest = (short *)index;
  2506.       row_size >>= 1;
  2507.       for (rr = 0; rr < 4; rr++) {
  2508.         dest[0] = src[0];
  2509.         dest[1] = src[1];
  2510.         dest[2] = src[2];
  2511.         dest[3] = src[3];
  2512.         dest += row_size;
  2513.         src += row_size;
  2514.         
  2515.         dest[0] = src[0];
  2516.         dest[1] = src[1];
  2517.         dest[2] = src[2];
  2518.         dest[3] = src[3];
  2519.         dest += row_size;
  2520.         src += row_size;
  2521.       }
  2522.     } else {
  2523.       /* Word aligned, use 32 bit copy */
  2524.       int *src = (int *)rindex1;
  2525.       int *dest = (int *)index;
  2526.       row_size >>= 2;
  2527.       for (rr = 0; rr < 4; rr++) {
  2528.         dest[0] = src[0];
  2529.         dest[1] = src[1];
  2530.         dest += row_size;
  2531.         src += row_size;
  2532.         
  2533.         dest[0] = src[0];
  2534.         dest[1] = src[1];
  2535.         dest += row_size;
  2536.         src += row_size;
  2537.       }
  2538.     }
  2539.       }
  2540.     } else {
  2541.       unsigned char *cm = cropTbl + MAX_NEG_CROP;
  2542.       rindex2 = rindex1 + right_half_for + (down_half_for * row_size);
  2543.       if (!zflag)
  2544.     for (rr = 0; rr < 4; rr++) {
  2545.       index[0] = cm[((int) (rindex1[0] + rindex2[0]) >> 1) + blockvals[0]];
  2546.       index[1] = cm[((int) (rindex1[1] + rindex2[1]) >> 1) + blockvals[1]];
  2547.       index[2] = cm[((int) (rindex1[2] + rindex2[2]) >> 1) + blockvals[2]];
  2548.       index[3] = cm[((int) (rindex1[3] + rindex2[3]) >> 1) + blockvals[3]];
  2549.       index[4] = cm[((int) (rindex1[4] + rindex2[4]) >> 1) + blockvals[4]];
  2550.       index[5] = cm[((int) (rindex1[5] + rindex2[5]) >> 1) + blockvals[5]];
  2551.       index[6] = cm[((int) (rindex1[6] + rindex2[6]) >> 1) + blockvals[6]];
  2552.       index[7] = cm[((int) (rindex1[7] + rindex2[7]) >> 1) + blockvals[7]];
  2553.       index += row_size;
  2554.       rindex1 += row_size;
  2555.       rindex2 += row_size;
  2556.       
  2557.       index[0] = cm[((int) (rindex1[0] + rindex2[0]) >> 1) + blockvals[8]];
  2558.       index[1] = cm[((int) (rindex1[1] + rindex2[1]) >> 1) + blockvals[9]];
  2559.       index[2] = cm[((int) (rindex1[2] + rindex2[2]) >> 1) + blockvals[10]];
  2560.       index[3] = cm[((int) (rindex1[3] + rindex2[3]) >> 1) + blockvals[11]];
  2561.       index[4] = cm[((int) (rindex1[4] + rindex2[4]) >> 1) + blockvals[12]];
  2562.       index[5] = cm[((int) (rindex1[5] + rindex2[5]) >> 1) + blockvals[13]];
  2563.       index[6] = cm[((int) (rindex1[6] + rindex2[6]) >> 1) + blockvals[14]];
  2564.       index[7] = cm[((int) (rindex1[7] + rindex2[7]) >> 1) + blockvals[15]];
  2565.       blockvals += 16;
  2566.       index += row_size;
  2567.       rindex1 += row_size;
  2568.       rindex2 += row_size;
  2569.     }
  2570.       else
  2571.     for (rr = 0; rr < 4; rr++) {
  2572.       index[0] = (int) (rindex1[0] + rindex2[0]) >> 1;
  2573.       index[1] = (int) (rindex1[1] + rindex2[1]) >> 1;
  2574.       index[2] = (int) (rindex1[2] + rindex2[2]) >> 1;
  2575.       index[3] = (int) (rindex1[3] + rindex2[3]) >> 1;
  2576.       index[4] = (int) (rindex1[4] + rindex2[4]) >> 1;
  2577.       index[5] = (int) (rindex1[5] + rindex2[5]) >> 1;
  2578.       index[6] = (int) (rindex1[6] + rindex2[6]) >> 1;
  2579.       index[7] = (int) (rindex1[7] + rindex2[7]) >> 1;
  2580.       index += row_size;
  2581.       rindex1 += row_size;
  2582.       rindex2 += row_size;
  2583.       
  2584.       index[0] = (int) (rindex1[0] + rindex2[0]) >> 1;
  2585.       index[1] = (int) (rindex1[1] + rindex2[1]) >> 1;
  2586.       index[2] = (int) (rindex1[2] + rindex2[2]) >> 1;
  2587.       index[3] = (int) (rindex1[3] + rindex2[3]) >> 1;
  2588.       index[4] = (int) (rindex1[4] + rindex2[4]) >> 1;
  2589.       index[5] = (int) (rindex1[5] + rindex2[5]) >> 1;
  2590.       index[6] = (int) (rindex1[6] + rindex2[6]) >> 1;
  2591.       index[7] = (int) (rindex1[7] + rindex2[7]) >> 1;
  2592.       index += row_size;
  2593.       rindex1 += row_size;
  2594.       rindex2 += row_size;
  2595.     }
  2596.     }
  2597.  
  2598. #ifdef LOOSE_MPEG
  2599.   }
  2600. #endif
  2601. }
  2602.  
  2603.  
  2604. /*
  2605.  *--------------------------------------------------------------
  2606.  *
  2607.  * ReconBMBlock --
  2608.  *
  2609.  *    Reconstructs back predicted macroblocks.
  2610.  *
  2611.  * Results:
  2612.  *      None.
  2613.  *
  2614.  * Side effects:
  2615.  *      None.
  2616.  *
  2617.  *--------------------------------------------------------------
  2618.  */
  2619.  
  2620. static void
  2621. ReconBMBlock(vid_stream, bnum, recon_right_back, recon_down_back, zflag)
  2622.   VidStream *vid_stream;
  2623.   int bnum, recon_right_back, recon_down_back, zflag;
  2624. {
  2625.   int mb_row, mb_col, row, col, row_size, rr;
  2626.   unsigned char *dest, *future;
  2627.   int right_back, down_back, right_half_back, down_half_back;
  2628.   unsigned char *rindex1, *rindex2;
  2629.   unsigned char *index;
  2630.   short int *blockvals;
  2631.  
  2632. #ifdef LOOSE_MPEG
  2633.   int illegalBlock = 0;
  2634.   int maxx, maxy;
  2635.   int row_start, row_end, rlast, rfirst, col_start, col_end, clast, cfirst;
  2636. #endif
  2637.  
  2638.   /* Calculate macroblock row and column from address. */
  2639.  
  2640.   mb_row = vid_stream->mblock.mb_address / vid_stream->mb_width;
  2641.   mb_col = vid_stream->mblock.mb_address % vid_stream->mb_width;
  2642.  
  2643.   /* If block is luminance block... */
  2644.  
  2645.   if (bnum < 4) {
  2646.  
  2647.     /* Calculate right_back, down_bakc motion vectors. */
  2648.  
  2649.     right_back = recon_right_back >> 1;
  2650.     down_back = recon_down_back >> 1;
  2651.     right_half_back = recon_right_back & 0x1;
  2652.     down_half_back = recon_down_back & 0x1;
  2653.  
  2654.     /* Set dest to luminance plane of current pict image. */
  2655.  
  2656.     dest = vid_stream->current->luminance;
  2657.  
  2658.     /*
  2659.      * If future frame exists, set future to luminance plane of future frame.
  2660.      */
  2661.  
  2662.     if (vid_stream->future != NULL)
  2663.       future = vid_stream->future->luminance;
  2664.  
  2665.     /* Establish row size. */
  2666.  
  2667.     row_size = vid_stream->mb_width << 4;
  2668.  
  2669.     /* Calculate row,col of upper left pixel in block. */
  2670.  
  2671.     row = mb_row << 4;
  2672.     col = mb_col << 4;
  2673.     if (bnum > 1)
  2674.       row += 8;
  2675.     if (bnum % 2)
  2676.       col += 8;
  2677.  
  2678. #ifdef LOOSE_MPEG
  2679.  
  2680.     /* Check for block illegality. */
  2681.  
  2682.     maxx = lmaxx; maxy = lmaxy;
  2683.  
  2684.     if (row + down_back + 7 > maxy) illegalBlock |= 0x4;
  2685.     else if (row + down_back < 0)  illegalBlock |= 0x1;
  2686.     
  2687.     if (col + right_back + 7 > maxx) illegalBlock |= 0x2;
  2688.     else if (col + right_back < 0) illegalBlock |= 0x8;
  2689.  
  2690. #endif
  2691.  
  2692.   }
  2693.   /* Otherwise, block is NOT luminance block, ... */
  2694.  
  2695.   else {
  2696.  
  2697.     /* Construct motion vectors. */
  2698.  
  2699.     recon_right_back /= 2;
  2700.     recon_down_back /= 2;
  2701.     right_back = recon_right_back >> 1;
  2702.     down_back = recon_down_back >> 1;
  2703.     right_half_back = recon_right_back & 0x1;
  2704.     down_half_back = recon_down_back & 0x1;
  2705.  
  2706.     /* Establish row size. */
  2707.  
  2708.     row_size = vid_stream->mb_width << 3;
  2709.  
  2710.     /* Calculate row,col of upper left pixel in block. */
  2711.  
  2712.     row = mb_row << 3;
  2713.     col = mb_col << 3;
  2714.  
  2715. #ifdef LOOSE_MPEG
  2716.  
  2717.     /* Check for block illegality. */
  2718.  
  2719.     maxx = cmaxx; maxy = cmaxy;
  2720.  
  2721.     if (row + down_back + 7 > maxy) illegalBlock |= 0x4;
  2722.     else if (row + down_back < 0) illegalBlock |= 0x1;
  2723.  
  2724.     if (col + right_back + 7 > maxx) illegalBlock  |= 0x2;
  2725.     else if (col + right_back < 0) illegalBlock |= 0x8;
  2726.  
  2727. #endif
  2728.  
  2729.     /* If block is Cr block... */
  2730.  
  2731.     if (bnum == 4) {
  2732.  
  2733.       /* Set dest to Cr plane of current pict image. */
  2734.  
  2735.       dest = vid_stream->current->Cr;
  2736.  
  2737.       /*
  2738.        * If future frame exists, set future to Cr plane of future image.
  2739.        */
  2740.  
  2741.       if (vid_stream->future != NULL)
  2742.     future = vid_stream->future->Cr;
  2743.     }
  2744.     /* Otherwise, block is Cb block... */
  2745.  
  2746.     else {
  2747.  
  2748.       /* Set dest to Cb plane of current pict image. */
  2749.  
  2750.       dest = vid_stream->current->Cb;
  2751.  
  2752.       /*
  2753.        * If future frame exists, set future to Cb plane of future frame.
  2754.        */
  2755.  
  2756.       if (vid_stream->future != NULL)
  2757.     future = vid_stream->future->Cb;
  2758.     }
  2759.   }
  2760.  
  2761.   /* For each pixel in block do... */
  2762.  
  2763. #ifdef LOOSE_MPEG
  2764.  
  2765.   if (illegalBlock) {
  2766.     if (illegalBlock & 0x1) {
  2767.       row_start = 0;
  2768.       row_end = row+down_back+8;
  2769.       rfirst = rlast = 8 - row_end;
  2770.     }
  2771.     else if (illegalBlock & 0x4) {
  2772.       row_start = row + down_back;
  2773.       row_end = maxy+1;
  2774.       rlast = row_end - row_start - 1;
  2775.       rfirst = 0;
  2776.     }
  2777.     else {
  2778.       row_start = row+down_back;
  2779.       row_end = row_start+8;
  2780.       rfirst = 0;
  2781.     }
  2782.  
  2783.     if (illegalBlock & 0x8) {
  2784.       col_start = 0;
  2785.       col_end = col + right_back + 8;
  2786.       cfirst = clast = 8 - col_end;
  2787.     }
  2788.     else if (illegalBlock & 0x2) {
  2789.       col_start = col + right_back;
  2790.       col_end = maxx + 1;
  2791.       clast = col_end - col_start - 1;
  2792.       cfirst = 0;
  2793.     }
  2794.     else {
  2795.       col_start = col + right_back;
  2796.       col_end = col_start + 8;
  2797.       cfirst = 0;
  2798.     }
  2799.  
  2800.     for (rr = row_start; rr < row_end; rr++) {
  2801.       rindex1 = future + (rr * row_size) + col_start;
  2802.       index = dest + ((row + rfirst) * row_size) + col + cfirst;
  2803.       for (cc = col_start; cc < col_end; cc++) {
  2804.     *index++ = *rindex1++;
  2805.       }
  2806.     }
  2807.  
  2808.     if (illegalBlock & 0x1) {
  2809.       for (rr = rlast -1; rr >=0; rr--) {
  2810.     index = dest + ((row + rr) * row_size) + col;
  2811.     rindex1 = dest + ((row + rlast) * row_size) + col;
  2812.     for (cc = 0; cc < 8; cc ++) {
  2813.       *index++ = *rindex1++;
  2814.     }
  2815.       }
  2816.     }
  2817.     else if (illegalBlock & 0x4) {
  2818.       for (rr = rlast+1; rr < 8; rr++) {
  2819.     index = dest + ((row + rr) * row_size) + col;
  2820.     rindex1 = dest + ((row + rlast) * row_size) + col;
  2821.     for (cc = 0; cc < 8; cc ++) {
  2822.       *index++ = *rindex1++;
  2823.     }
  2824.       }
  2825.     }
  2826.  
  2827.     if (illegalBlock & 0x2) {
  2828.       for (cc = clast+1; cc < 8; cc++) {
  2829.     index = dest + (row * row_size) + (col + cc);
  2830.     rindex1 = dest + (row * row_size) + (col + clast);
  2831.     for (rr = 0; rr < 8; rr++) {
  2832.       *index = *rindex1;
  2833.       index += row_size;
  2834.       rindex1 += row_size;
  2835.     }
  2836.       }
  2837.     }
  2838.     else if (illegalBlock & 0x8) {
  2839.       for (cc = clast-1; cc >= 0; cc--) {
  2840.     index = dest + (row * row_size) + (col + cc);
  2841.     rindex1 = dest + (row * row_size) + (col + clast);
  2842.     for (rr = 0; rr < 8; rr++) {
  2843.       *index = *rindex1;
  2844.       index += row_size;
  2845.       rindex1 += row_size;
  2846.     }
  2847.       }
  2848.     }
  2849.  
  2850.     if (!zflag) {
  2851.       for (rr = 0; rr < 8; rr++) {
  2852.     index = dest + (row*row_size) + col;
  2853.     blockvals = &(vid_stream->block.dct_recon[rr][0]);
  2854.     index[0] += blockvals[0];
  2855.     index[1] += blockvals[1];
  2856.     index[2] += blockvals[2];
  2857.     index[3] += blockvals[3];
  2858.     index[4] += blockvals[4];
  2859.     index[5] += blockvals[5];
  2860.     index[6] += blockvals[6];
  2861.     index[7] += blockvals[7];
  2862.       }
  2863.     }
  2864.   }
  2865.   else {
  2866.  
  2867. #endif
  2868.     
  2869.     index = dest + (row * row_size) + col;
  2870.     rindex1 = future + (row + down_back) * row_size + col + right_back;
  2871.  
  2872.     blockvals = &(vid_stream->block.dct_recon[0][0]);
  2873.  
  2874.     if ((!right_half_back) && (!down_half_back)) {
  2875.       unsigned char *cm = cropTbl + MAX_NEG_CROP;
  2876.       if (!zflag)
  2877.     for (rr = 0; rr < 4; rr++) {
  2878.       index[0] = cm[(int) rindex1[0] + (int) blockvals[0]];
  2879.       index[1] = cm[(int) rindex1[1] + (int) blockvals[1]];
  2880.       index[2] = cm[(int) rindex1[2] + (int) blockvals[2]];
  2881.       index[3] = cm[(int) rindex1[3] + (int) blockvals[3]];
  2882.       index[4] = cm[(int) rindex1[4] + (int) blockvals[4]];
  2883.       index[5] = cm[(int) rindex1[5] + (int) blockvals[5]];
  2884.       index[6] = cm[(int) rindex1[6] + (int) blockvals[6]];
  2885.       index[7] = cm[(int) rindex1[7] + (int) blockvals[7]];
  2886.       index += row_size;
  2887.       rindex1 += row_size;
  2888.       
  2889.       index[0] = cm[(int) rindex1[0] + (int) blockvals[8]];
  2890.       index[1] = cm[(int) rindex1[1] + (int) blockvals[9]];
  2891.       index[2] = cm[(int) rindex1[2] + (int) blockvals[10]];
  2892.       index[3] = cm[(int) rindex1[3] + (int) blockvals[11]];
  2893.       index[4] = cm[(int) rindex1[4] + (int) blockvals[12]];
  2894.       index[5] = cm[(int) rindex1[5] + (int) blockvals[13]];
  2895.       index[6] = cm[(int) rindex1[6] + (int) blockvals[14]];
  2896.       index[7] = cm[(int) rindex1[7] + (int) blockvals[15]];
  2897.       blockvals += 16;
  2898.       index += row_size;
  2899.       rindex1 += row_size;
  2900.     }
  2901.       else {
  2902.     if (right_back & 0x1) {
  2903.       /* No alignment, use bye copy */
  2904.       for (rr = 0; rr < 4; rr++) {
  2905.         index[0] = rindex1[0];
  2906.         index[1] = rindex1[1];
  2907.         index[2] = rindex1[2];
  2908.         index[3] = rindex1[3];
  2909.         index[4] = rindex1[4];
  2910.         index[5] = rindex1[5];
  2911.         index[6] = rindex1[6];
  2912.         index[7] = rindex1[7];
  2913.         index += row_size;
  2914.         rindex1 += row_size;
  2915.         
  2916.         index[0] = rindex1[0];
  2917.         index[1] = rindex1[1];
  2918.         index[2] = rindex1[2];
  2919.         index[3] = rindex1[3];
  2920.         index[4] = rindex1[4];
  2921.         index[5] = rindex1[5];
  2922.         index[6] = rindex1[6];
  2923.         index[7] = rindex1[7];
  2924.         index += row_size;
  2925.         rindex1 += row_size;
  2926.       }
  2927.     } else if (right_back & 0x2) {
  2928.       /* Half-word bit aligned, use 16 bit copy */
  2929.       short *src = (short *)rindex1;
  2930.       short *dest = (short *)index;
  2931.       row_size >>= 1;
  2932.       for (rr = 0; rr < 4; rr++) {
  2933.         dest[0] = src[0];
  2934.         dest[1] = src[1];
  2935.         dest[2] = src[2];
  2936.         dest[3] = src[3];
  2937.         dest += row_size;
  2938.         src += row_size;
  2939.         
  2940.         dest[0] = src[0];
  2941.         dest[1] = src[1];
  2942.         dest[2] = src[2];
  2943.         dest[3] = src[3];
  2944.         dest += row_size;
  2945.         src += row_size;
  2946.       }
  2947.     } else {
  2948.       /* Word aligned, use 32 bit copy */
  2949.       int *src = (int *)rindex1;
  2950.       int *dest = (int *)index;
  2951.       row_size >>= 2;
  2952.       for (rr = 0; rr < 4; rr++) {
  2953.         dest[0] = src[0];
  2954.         dest[1] = src[1];
  2955.         dest += row_size;
  2956.         src += row_size;
  2957.         
  2958.         dest[0] = src[0];
  2959.         dest[1] = src[1];
  2960.         dest += row_size;
  2961.         src += row_size;
  2962.       }
  2963.     }
  2964.       }
  2965.     } else {
  2966.       unsigned char *cm = cropTbl + MAX_NEG_CROP;
  2967.       rindex2 = rindex1 + right_half_back + (down_half_back * row_size);
  2968.       if (!zflag)
  2969.     for (rr = 0; rr < 4; rr++) {
  2970.       index[0] = cm[((int) (rindex1[0] + rindex2[0]) >> 1) + blockvals[0]];
  2971.       index[1] = cm[((int) (rindex1[1] + rindex2[1]) >> 1) + blockvals[1]];
  2972.       index[2] = cm[((int) (rindex1[2] + rindex2[2]) >> 1) + blockvals[2]];
  2973.       index[3] = cm[((int) (rindex1[3] + rindex2[3]) >> 1) + blockvals[3]];
  2974.       index[4] = cm[((int) (rindex1[4] + rindex2[4]) >> 1) + blockvals[4]];
  2975.       index[5] = cm[((int) (rindex1[5] + rindex2[5]) >> 1) + blockvals[5]];
  2976.       index[6] = cm[((int) (rindex1[6] + rindex2[6]) >> 1) + blockvals[6]];
  2977.       index[7] = cm[((int) (rindex1[7] + rindex2[7]) >> 1) + blockvals[7]];
  2978.       index += row_size;
  2979.       rindex1 += row_size;
  2980.       rindex2 += row_size;
  2981.       
  2982.       index[0] = cm[((int) (rindex1[0] + rindex2[0]) >> 1) + blockvals[8]];
  2983.       index[1] = cm[((int) (rindex1[1] + rindex2[1]) >> 1) + blockvals[9]];
  2984.       index[2] = cm[((int) (rindex1[2] + rindex2[2]) >> 1) + blockvals[10]];
  2985.       index[3] = cm[((int) (rindex1[3] + rindex2[3]) >> 1) + blockvals[11]];
  2986.       index[4] = cm[((int) (rindex1[4] + rindex2[4]) >> 1) + blockvals[12]];
  2987.       index[5] = cm[((int) (rindex1[5] + rindex2[5]) >> 1) + blockvals[13]];
  2988.       index[6] = cm[((int) (rindex1[6] + rindex2[6]) >> 1) + blockvals[14]];
  2989.       index[7] = cm[((int) (rindex1[7] + rindex2[7]) >> 1) + blockvals[15]];
  2990.       blockvals += 16;
  2991.       index += row_size;
  2992.       rindex1 += row_size;
  2993.       rindex2 += row_size;
  2994.     }
  2995.       else
  2996.     for (rr = 0; rr < 4; rr++) {
  2997.       index[0] = (int) (rindex1[0] + rindex2[0]) >> 1;
  2998.       index[1] = (int) (rindex1[1] + rindex2[1]) >> 1;
  2999.       index[2] = (int) (rindex1[2] + rindex2[2]) >> 1;
  3000.       index[3] = (int) (rindex1[3] + rindex2[3]) >> 1;
  3001.       index[4] = (int) (rindex1[4] + rindex2[4]) >> 1;
  3002.       index[5] = (int) (rindex1[5] + rindex2[5]) >> 1;
  3003.       index[6] = (int) (rindex1[6] + rindex2[6]) >> 1;
  3004.       index[7] = (int) (rindex1[7] + rindex2[7]) >> 1;
  3005.       index += row_size;
  3006.       rindex1 += row_size;
  3007.       rindex2 += row_size;
  3008.       
  3009.       index[0] = (int) (rindex1[0] + rindex2[0]) >> 1;
  3010.       index[1] = (int) (rindex1[1] + rindex2[1]) >> 1;
  3011.       index[2] = (int) (rindex1[2] + rindex2[2]) >> 1;
  3012.       index[3] = (int) (rindex1[3] + rindex2[3]) >> 1;
  3013.       index[4] = (int) (rindex1[4] + rindex2[4]) >> 1;
  3014.       index[5] = (int) (rindex1[5] + rindex2[5]) >> 1;
  3015.       index[6] = (int) (rindex1[6] + rindex2[6]) >> 1;
  3016.       index[7] = (int) (rindex1[7] + rindex2[7]) >> 1;
  3017.       index += row_size;
  3018.       rindex1 += row_size;
  3019.       rindex2 += row_size;
  3020.     }
  3021.     }
  3022.  
  3023. #ifdef LOOSE_MPEG
  3024.   }
  3025. #endif
  3026.  
  3027. }
  3028.  
  3029.  
  3030. /*
  3031.  *--------------------------------------------------------------
  3032.  *
  3033.  * ReconBiMBlock --
  3034.  *
  3035.  *    Reconstructs bidirectionally predicted macroblocks.
  3036.  *
  3037.  * Results:
  3038.  *      None.
  3039.  *
  3040.  * Side effects:
  3041.  *      None.
  3042.  *
  3043.  *--------------------------------------------------------------
  3044.  */
  3045.  
  3046. static void
  3047. ReconBiMBlock(vid_stream, bnum, recon_right_for, recon_down_for,
  3048.           recon_right_back, recon_down_back, zflag)
  3049.   VidStream *vid_stream;
  3050.   int bnum, recon_right_for, recon_down_for, recon_right_back, recon_down_back;
  3051.   int zflag;
  3052. {
  3053.   int mb_row, mb_col, row, col, row_size, rr;
  3054.   unsigned char *dest, *past, *future;
  3055.   int right_for, down_for, right_half_for, down_half_for;
  3056.   int right_back, down_back, right_half_back, down_half_back;
  3057.   unsigned char *index, *rindex1, *bindex1;
  3058.   short int *blockvals;
  3059.   int forw_row_start, back_row_start, forw_col_start, back_col_start;
  3060.  
  3061. #ifdef LOOSE_MPEG
  3062.   int illegal_forw = 0;
  3063.   int illegal_back = 0;
  3064. #endif
  3065.  
  3066.   /* Calculate macroblock row and column from address. */
  3067.  
  3068.   mb_row = vid_stream->mblock.mb_address / vid_stream->mb_width;
  3069.   mb_col = vid_stream->mblock.mb_address % vid_stream->mb_width;
  3070.  
  3071.   /* If block is luminance block... */
  3072.  
  3073.   if (bnum < 4) {
  3074.  
  3075.     /*
  3076.      * Calculate right_for, down_for, right_half_for, down_half_for,
  3077.      * right_back, down_bakc, right_half_back, and down_half_back, motion
  3078.      * vectors.
  3079.      */
  3080.  
  3081.     right_for = recon_right_for >> 1;
  3082.     down_for = recon_down_for >> 1;
  3083.     right_half_for = recon_right_for & 0x1;
  3084.     down_half_for = recon_down_for & 0x1;
  3085.  
  3086.     right_back = recon_right_back >> 1;
  3087.     down_back = recon_down_back >> 1;
  3088.     right_half_back = recon_right_back & 0x1;
  3089.     down_half_back = recon_down_back & 0x1;
  3090.  
  3091.     /* Set dest to luminance plane of current pict image. */
  3092.  
  3093.     dest = vid_stream->current->luminance;
  3094.  
  3095.     /* If past frame exists, set past to luminance plane of past frame. */
  3096.  
  3097.     if (vid_stream->past != NULL)
  3098.       past = vid_stream->past->luminance;
  3099.  
  3100.     /*
  3101.      * If future frame exists, set future to luminance plane of future frame.
  3102.      */
  3103.  
  3104.     if (vid_stream->future != NULL)
  3105.       future = vid_stream->future->luminance;
  3106.  
  3107.     /* Establish row size. */
  3108.  
  3109.     row_size = (vid_stream->mb_width << 4);
  3110.  
  3111.     /* Calculate row,col of upper left pixel in block. */
  3112.  
  3113.     row = (mb_row << 4);
  3114.     col = (mb_col << 4);
  3115.     if (bnum > 1)
  3116.       row += 8;
  3117.     if (bnum & 0x01)
  3118.       col += 8;
  3119.  
  3120.     forw_col_start = col + right_for;
  3121.     forw_row_start = row + down_for;
  3122.  
  3123.     back_col_start = col + right_back;
  3124.     back_row_start = row + down_back;
  3125.  
  3126. #ifdef LOOSE_MPEG
  3127.  
  3128.     /* Check for illegal pred. blocks. */
  3129.  
  3130.  
  3131.     if (forw_col_start+8 > lmaxx) illegal_forw = 1;
  3132.     else if (forw_col_start < 0) illegal_forw = 1;
  3133.  
  3134.     if (forw_row_start+8 > lmaxy) illegal_forw = 1;
  3135.     else if (forw_row_start < 0) illegal_forw = 1;
  3136.  
  3137.     if (back_col_start+8 > lmaxx) illegal_back = 1;
  3138.     else if (back_col_start < 0) illegal_back = 1;
  3139.  
  3140.     if (back_row_start+8 > lmaxy) illegal_back = 1;
  3141.     else if (back_row_start < 0) illegal_back = 1;
  3142.  
  3143. #endif
  3144.  
  3145.   }
  3146.   /* Otherwise, block is NOT luminance block, ... */
  3147.  
  3148.   else {
  3149.  
  3150.     /* Construct motion vectors. */
  3151.  
  3152.     recon_right_for /= 2;
  3153.     recon_down_for /= 2;
  3154.     right_for = recon_right_for >> 1;
  3155.     down_for = recon_down_for >> 1;
  3156.     right_half_for = recon_right_for & 0x1;
  3157.     down_half_for = recon_down_for & 0x1;
  3158.  
  3159.     recon_right_back /= 2;
  3160.     recon_down_back /= 2;
  3161.     right_back = recon_right_back >> 1;
  3162.     down_back = recon_down_back >> 1;
  3163.     right_half_back = recon_right_back & 0x1;
  3164.     down_half_back = recon_down_back & 0x1;
  3165.  
  3166.     /* Establish row size. */
  3167.  
  3168.     row_size = (vid_stream->mb_width << 3);
  3169.  
  3170.     /* Calculate row,col of upper left pixel in block. */
  3171.  
  3172.     row = (mb_row << 3);
  3173.     col = (mb_col << 3);
  3174.  
  3175.     forw_col_start = col + right_for;
  3176.     forw_row_start = row + down_for;
  3177.  
  3178.     back_col_start = col + right_back;
  3179.     back_row_start = row + down_back;
  3180.  
  3181. #ifdef LOOSE_MPEG
  3182.  
  3183.     /* Check for illegal pred. blocks. */
  3184.  
  3185.     if (forw_col_start+8 > cmaxx) illegal_forw = 1;
  3186.     else if (forw_col_start < 0) illegal_forw = 1;
  3187.  
  3188.     if (forw_row_start+8 > cmaxy) illegal_forw = 1;
  3189.     else if (forw_row_start < 0) illegal_forw = 1;
  3190.  
  3191.     if (back_col_start+8 > cmaxx) illegal_back = 1;
  3192.     else if (back_col_start < 0) illegal_back = 1;
  3193.     
  3194.     if (back_row_start+8 > cmaxy) illegal_back = 1;
  3195.     else if (back_row_start < 0) illegal_back = 1;
  3196.  
  3197. #endif
  3198.     
  3199.     /* If block is Cr block... */
  3200.  
  3201.     if (bnum == 4) {
  3202.  
  3203.       /* Set dest to Cr plane of current pict image. */
  3204.  
  3205.       dest = vid_stream->current->Cr;
  3206.  
  3207.       /* If past frame exists, set past to Cr plane of past image. */
  3208.  
  3209.       if (vid_stream->past != NULL)
  3210.     past = vid_stream->past->Cr;
  3211.  
  3212.       /*
  3213.        * If future frame exists, set future to Cr plane of future image.
  3214.        */
  3215.  
  3216.       if (vid_stream->future != NULL)
  3217.     future = vid_stream->future->Cr;
  3218.     }
  3219.     /* Otherwise, block is Cb block... */
  3220.  
  3221.     else {
  3222.  
  3223.       /* Set dest to Cb plane of current pict image. */
  3224.  
  3225.       dest = vid_stream->current->Cb;
  3226.  
  3227.       /* If past frame exists, set past to Cb plane of past frame. */
  3228.  
  3229.       if (vid_stream->past != NULL)
  3230.     past = vid_stream->past->Cb;
  3231.  
  3232.       /*
  3233.        * If future frame exists, set future to Cb plane of future frame.
  3234.        */
  3235.  
  3236.       if (vid_stream->future != NULL)
  3237.     future = vid_stream->future->Cb;
  3238.     }
  3239.   }
  3240.  
  3241.   /* For each pixel in block... */
  3242.  
  3243.   index = dest + (row * row_size) + col;
  3244.  
  3245. #ifdef LOOSE_MPEG
  3246.   if (illegal_forw) 
  3247.     rindex1 = future + back_row_start * row_size + back_col_start;
  3248.   else 
  3249. #endif
  3250.     rindex1 = past + forw_row_start  * row_size + forw_col_start;
  3251.  
  3252. #ifdef LOOSE_MPEG
  3253.   if (illegal_back) 
  3254.     bindex1 = past + forw_row_start * row_size + forw_col_start;
  3255.   else 
  3256. #endif
  3257.     bindex1 = future + back_row_start * row_size + back_col_start;
  3258.  
  3259.   blockvals = (short int *) &(vid_stream->block.dct_recon[0][0]);
  3260.  
  3261.   {
  3262.   unsigned char *cm = cropTbl + MAX_NEG_CROP;
  3263.   if (!zflag)
  3264.     for (rr = 0; rr < 4; rr++) {
  3265.       index[0] = cm[((int) (rindex1[0] + bindex1[0]) >> 1) + blockvals[0]];
  3266.       index[1] = cm[((int) (rindex1[1] + bindex1[1]) >> 1) + blockvals[1]];
  3267.       index[2] = cm[((int) (rindex1[2] + bindex1[2]) >> 1) + blockvals[2]];
  3268.       index[3] = cm[((int) (rindex1[3] + bindex1[3]) >> 1) + blockvals[3]];
  3269.       index[4] = cm[((int) (rindex1[4] + bindex1[4]) >> 1) + blockvals[4]];
  3270.       index[5] = cm[((int) (rindex1[5] + bindex1[5]) >> 1) + blockvals[5]];
  3271.       index[6] = cm[((int) (rindex1[6] + bindex1[6]) >> 1) + blockvals[6]];
  3272.       index[7] = cm[((int) (rindex1[7] + bindex1[7]) >> 1) + blockvals[7]];
  3273.       index += row_size;
  3274.       rindex1 += row_size;
  3275.       bindex1 += row_size;
  3276.  
  3277.       index[0] = cm[((int) (rindex1[0] + bindex1[0]) >> 1) + blockvals[8]];
  3278.       index[1] = cm[((int) (rindex1[1] + bindex1[1]) >> 1) + blockvals[9]];
  3279.       index[2] = cm[((int) (rindex1[2] + bindex1[2]) >> 1) + blockvals[10]];
  3280.       index[3] = cm[((int) (rindex1[3] + bindex1[3]) >> 1) + blockvals[11]];
  3281.       index[4] = cm[((int) (rindex1[4] + bindex1[4]) >> 1) + blockvals[12]];
  3282.       index[5] = cm[((int) (rindex1[5] + bindex1[5]) >> 1) + blockvals[13]];
  3283.       index[6] = cm[((int) (rindex1[6] + bindex1[6]) >> 1) + blockvals[14]];
  3284.       index[7] = cm[((int) (rindex1[7] + bindex1[7]) >> 1) + blockvals[15]];
  3285.       blockvals += 16;
  3286.       index += row_size;
  3287.       rindex1 += row_size;
  3288.       bindex1 += row_size;
  3289.     }
  3290.  
  3291.   else
  3292.     for (rr = 0; rr < 4; rr++) {
  3293.       index[0] = (int) (rindex1[0] + bindex1[0]) >> 1;
  3294.       index[1] = (int) (rindex1[1] + bindex1[1]) >> 1;
  3295.       index[2] = (int) (rindex1[2] + bindex1[2]) >> 1;
  3296.       index[3] = (int) (rindex1[3] + bindex1[3]) >> 1;
  3297.       index[4] = (int) (rindex1[4] + bindex1[4]) >> 1;
  3298.       index[5] = (int) (rindex1[5] + bindex1[5]) >> 1;
  3299.       index[6] = (int) (rindex1[6] + bindex1[6]) >> 1;
  3300.       index[7] = (int) (rindex1[7] + bindex1[7]) >> 1;
  3301.       index += row_size;
  3302.       rindex1 += row_size;
  3303.       bindex1 += row_size;
  3304.  
  3305.       index[0] = (int) (rindex1[0] + bindex1[0]) >> 1;
  3306.       index[1] = (int) (rindex1[1] + bindex1[1]) >> 1;
  3307.       index[2] = (int) (rindex1[2] + bindex1[2]) >> 1;
  3308.       index[3] = (int) (rindex1[3] + bindex1[3]) >> 1;
  3309.       index[4] = (int) (rindex1[4] + bindex1[4]) >> 1;
  3310.       index[5] = (int) (rindex1[5] + bindex1[5]) >> 1;
  3311.       index[6] = (int) (rindex1[6] + bindex1[6]) >> 1;
  3312.       index[7] = (int) (rindex1[7] + bindex1[7]) >> 1;
  3313.       index += row_size;
  3314.       rindex1 += row_size;
  3315.       bindex1 += row_size;
  3316.     }
  3317.   }
  3318. }
  3319.  
  3320. /*
  3321.  *--------------------------------------------------------------
  3322.  *
  3323.  * ProcessSkippedPFrameMBlocks --
  3324.  *
  3325.  *    Processes skipped macroblocks in P frames.
  3326.  *
  3327.  * Results:
  3328.  *    Calculates pixel values for luminance, Cr, and Cb planes
  3329.  *      in current pict image for skipped macroblocks.
  3330.  *
  3331.  * Side effects:
  3332.  *    Pixel values in pict image changed.
  3333.  *
  3334.  *--------------------------------------------------------------
  3335.  */
  3336.  
  3337. static void
  3338. ProcessSkippedPFrameMBlocks(vid_stream)
  3339.   VidStream *vid_stream;
  3340. {
  3341.   int row_size, half_row, mb_row, mb_col, row, col, rr;
  3342.   int addr, row_incr, half_row_incr, crow, ccol;
  3343.   int *dest, *src, *dest1, *src1;
  3344.  
  3345.   /* Calculate row sizes for luminance and Cr/Cb macroblock areas. */
  3346.  
  3347.   row_size = vid_stream->mb_width << 4;
  3348.   half_row = (row_size >> 1);
  3349.   row_incr = row_size >> 2;
  3350.   half_row_incr = half_row >> 2;
  3351.  
  3352.   /* For each skipped macroblock, do... */
  3353.  
  3354.   for (addr = vid_stream->mblock.past_mb_addr + 1;
  3355.        addr < vid_stream->mblock.mb_address; addr++) {
  3356.  
  3357.     /* Calculate macroblock row and col. */
  3358.  
  3359.     mb_row = addr / vid_stream->mb_width;
  3360.     mb_col = addr % vid_stream->mb_width;
  3361.  
  3362.     /* Calculate upper left pixel row,col for luminance plane. */
  3363.  
  3364.     row = mb_row << 4;
  3365.     col = mb_col << 4;
  3366.  
  3367.  
  3368.     /* For each row in macroblock luminance plane... */
  3369.  
  3370.     dest = (int *)(vid_stream->current->luminance + (row * row_size) + col);
  3371.     src = (int *)(vid_stream->future->luminance + (row * row_size) + col);
  3372.  
  3373.     for (rr = 0; rr < 8; rr++) {
  3374.  
  3375.       /* Copy pixel values from last I or P picture. */
  3376.  
  3377.       dest[0] = src[0];
  3378.       dest[1] = src[1];
  3379.       dest[2] = src[2];
  3380.       dest[3] = src[3];
  3381.       dest += row_incr;
  3382.       src += row_incr;
  3383.  
  3384.       dest[0] = src[0];
  3385.       dest[1] = src[1];
  3386.       dest[2] = src[2];
  3387.       dest[3] = src[3];
  3388.       dest += row_incr;
  3389.       src += row_incr;
  3390.     }
  3391.  
  3392.     /*
  3393.      * Divide row,col to get upper left pixel of macroblock in Cr and Cb
  3394.      * planes.
  3395.      */
  3396.  
  3397.     crow = row >> 1;
  3398.     ccol = col >> 1;
  3399.  
  3400.     /* For each row in Cr, and Cb planes... */
  3401.  
  3402.     dest = (int *)(vid_stream->current->Cr + (crow * half_row) + ccol);
  3403.     src = (int *)(vid_stream->future->Cr + (crow * half_row) + ccol);
  3404.     dest1 = (int *)(vid_stream->current->Cb + (crow * half_row) + ccol);
  3405.     src1 = (int *)(vid_stream->future->Cb + (crow * half_row) + ccol);
  3406.  
  3407.     for (rr = 0; rr < 4; rr++) {
  3408.  
  3409.       /* Copy pixel values from last I or P picture. */
  3410.  
  3411.       dest[0] = src[0];
  3412.       dest[1] = src[1];
  3413.  
  3414.       dest1[0] = src1[0];
  3415.       dest1[1] = src1[1];
  3416.  
  3417.       dest += half_row_incr;
  3418.       src += half_row_incr;
  3419.       dest1 += half_row_incr;
  3420.       src1 += half_row_incr;
  3421.  
  3422.       dest[0] = src[0];
  3423.       dest[1] = src[1];
  3424.  
  3425.       dest1[0] = src1[0];
  3426.       dest1[1] = src1[1];
  3427.  
  3428.       dest += half_row_incr;
  3429.       src += half_row_incr;
  3430.       dest1 += half_row_incr;
  3431.       src1 += half_row_incr;
  3432.     }
  3433.  
  3434.     if (ditherType == MBORDERED_DITHER) {
  3435.       MBOrderedDitherDisplayCopy(vid_stream, addr,
  3436.                  1, 0, 0, 0, 0, 0,
  3437.                  vid_stream->future->display,
  3438.                  (unsigned char *) NULL);
  3439.       ditherFlags[addr] = 0;
  3440.     }
  3441.   }
  3442.  
  3443.   vid_stream->mblock.recon_right_for_prev = 0;
  3444.   vid_stream->mblock.recon_down_for_prev = 0;
  3445. }
  3446.  
  3447.  
  3448.  
  3449.  
  3450. /*
  3451.  *--------------------------------------------------------------
  3452.  *
  3453.  * ProcessSkippedBFrameMBlocks --
  3454.  *
  3455.  *    Processes skipped macroblocks in B frames.
  3456.  *
  3457.  * Results:
  3458.  *    Calculates pixel values for luminance, Cr, and Cb planes
  3459.  *      in current pict image for skipped macroblocks.
  3460.  *
  3461.  * Side effects:
  3462.  *    Pixel values in pict image changed.
  3463.  *
  3464.  *--------------------------------------------------------------
  3465.  */
  3466.  
  3467. static void
  3468. ProcessSkippedBFrameMBlocks(vid_stream)
  3469.   VidStream *vid_stream;
  3470. {
  3471.   int row_size, half_row, mb_row, mb_col, row, col, rr;
  3472.   int right_half_for, down_half_for, c_right_half_for, c_down_half_for;
  3473.   int right_half_back, down_half_back, c_right_half_back, c_down_half_back;
  3474.   int addr, right_for, down_for;
  3475.   int recon_right_for, recon_down_for;
  3476.   int recon_right_back, recon_down_back;
  3477.   int right_back, down_back;
  3478.   int c_right_for, c_down_for;
  3479.   int c_right_back, c_down_back;
  3480.   unsigned char forw_lum[256];
  3481.   unsigned char forw_cr[64], forw_cb[64];
  3482.   unsigned char back_lum[256], back_cr[64], back_cb[64];
  3483.   int row_incr, half_row_incr;
  3484.   int ccol, crow;
  3485.  
  3486.   /* Calculate row sizes for luminance and Cr/Cb macroblock areas. */
  3487.  
  3488.   row_size = vid_stream->mb_width << 4;
  3489.   half_row = (row_size >> 1);
  3490.   row_incr = row_size >> 2;
  3491.   half_row_incr =  half_row >> 2;
  3492.  
  3493.   /* Establish motion vector codes based on full pixel flag. */
  3494.  
  3495.   if (vid_stream->picture.full_pel_forw_vector) {
  3496.     recon_right_for = vid_stream->mblock.recon_right_for_prev << 1;
  3497.     recon_down_for = vid_stream->mblock.recon_down_for_prev << 1;
  3498.   } else {
  3499.     recon_right_for = vid_stream->mblock.recon_right_for_prev;
  3500.     recon_down_for = vid_stream->mblock.recon_down_for_prev;
  3501.   }
  3502.  
  3503.   if (vid_stream->picture.full_pel_back_vector) {
  3504.     recon_right_back = vid_stream->mblock.recon_right_back_prev << 1;
  3505.     recon_down_back = vid_stream->mblock.recon_down_back_prev << 1;
  3506.   } else {
  3507.     recon_right_back = vid_stream->mblock.recon_right_back_prev;
  3508.     recon_down_back = vid_stream->mblock.recon_down_back_prev;
  3509.   }
  3510.  
  3511.  
  3512.   /* If only one motion vector, do display copy, else do full
  3513.      calculation. 
  3514.   */
  3515.  
  3516.   if (ditherType == MBORDERED_DITHER) {
  3517.     if (vid_stream->mblock.bpict_past_forw &&
  3518.     !vid_stream->mblock.bpict_past_back) {
  3519.       for (addr = vid_stream->mblock.past_mb_addr+1;
  3520.        addr < vid_stream->mblock.mb_address; addr++) {
  3521.     
  3522.     MBOrderedDitherDisplayCopy(vid_stream, addr,
  3523.                    1, recon_right_for, recon_down_for,
  3524.                  0, 0, 0, vid_stream->past->display,
  3525.                    vid_stream->future->display);
  3526.     ditherFlags[addr] = 0;
  3527.       }
  3528.       return;
  3529.     }
  3530.     if (vid_stream->mblock.bpict_past_back && 
  3531.     !vid_stream->mblock.bpict_past_forw) {
  3532.       for (addr = vid_stream->mblock.past_mb_addr+1;
  3533.        addr < vid_stream->mblock.mb_address; addr++) {
  3534.     
  3535.     MBOrderedDitherDisplayCopy(vid_stream, addr,
  3536.                    0, 0, 0,
  3537.                    1, recon_right_back, recon_down_back,
  3538.                    vid_stream->past->display, vid_stream->future->display);
  3539.     ditherFlags[addr] = 0;
  3540.       }
  3541.       return;
  3542.     }
  3543.   }
  3544.  
  3545.   /* Calculate motion vectors. */
  3546.   
  3547.   if (vid_stream->mblock.bpict_past_forw) {
  3548.     right_for = recon_right_for >> 1;
  3549.     down_for = recon_down_for >> 1;
  3550.     right_half_for = recon_right_for & 0x1;
  3551.     down_half_for = recon_down_for & 0x1;
  3552.     
  3553.     recon_right_for /= 2;
  3554.     recon_down_for /= 2;
  3555.     c_right_for = recon_right_for >> 1;
  3556.     c_down_for = recon_down_for >> 1;
  3557.     c_right_half_for = recon_right_for & 0x1;
  3558.     c_down_half_for = recon_down_for & 0x1;
  3559.     
  3560.   }
  3561.   if (vid_stream->mblock.bpict_past_back) {
  3562.     right_back = recon_right_back >> 1;
  3563.     down_back = recon_down_back >> 1;
  3564.     right_half_back = recon_right_back & 0x1;
  3565.     down_half_back = recon_down_back & 0x1;
  3566.     
  3567.     recon_right_back /= 2;
  3568.     recon_down_back /= 2;
  3569.     c_right_back = recon_right_back >> 1;
  3570.     c_down_back = recon_down_back >> 1;
  3571.     c_right_half_back = recon_right_back & 0x1;
  3572.     c_down_half_back = recon_down_back & 0x1;
  3573.     
  3574.   }
  3575.   /* For each skipped macroblock, do... */
  3576.   
  3577.   for (addr = vid_stream->mblock.past_mb_addr + 1;
  3578.        addr < vid_stream->mblock.mb_address; addr++) {
  3579.     
  3580.     /* Calculate macroblock row and col. */
  3581.     
  3582.     mb_row = addr / vid_stream->mb_width;
  3583.     mb_col = addr % vid_stream->mb_width;
  3584.     
  3585.     /* Calculate upper left pixel row,col for luminance plane. */
  3586.     
  3587.     row = mb_row << 4;
  3588.     col = mb_col << 4;
  3589.     crow = row / 2;
  3590.     ccol = col / 2;
  3591.     
  3592.     /* If forward predicted, calculate prediction values. */
  3593.     
  3594.     if (vid_stream->mblock.bpict_past_forw) {
  3595.       
  3596.       ReconSkippedBlock(vid_stream->past->luminance, forw_lum,
  3597.             row, col, row_size, right_for, down_for,
  3598.             right_half_for, down_half_for, 16);
  3599.       ReconSkippedBlock(vid_stream->past->Cr, forw_cr, crow,
  3600.             ccol, half_row,
  3601.             c_right_for, c_down_for, c_right_half_for, c_down_half_for, 8);
  3602.       ReconSkippedBlock(vid_stream->past->Cb, forw_cb, crow,
  3603.             ccol, half_row,
  3604.             c_right_for, c_down_for, c_right_half_for, c_down_half_for, 8);
  3605.     }
  3606.     /* If back predicted, calculate prediction values. */
  3607.     
  3608.     if (vid_stream->mblock.bpict_past_back) {
  3609.       ReconSkippedBlock(vid_stream->future->luminance, back_lum,
  3610.             row, col, row_size, right_back, down_back,
  3611.             right_half_back, down_half_back, 16);
  3612.       ReconSkippedBlock(vid_stream->future->Cr, back_cr, crow,
  3613.             ccol, half_row,
  3614.             c_right_back, c_down_back,
  3615.             c_right_half_back, c_down_half_back, 8);
  3616.       ReconSkippedBlock(vid_stream->future->Cb, back_cb, crow,
  3617.             ccol, half_row,
  3618.             c_right_back, c_down_back,
  3619.             c_right_half_back, c_down_half_back, 8);
  3620.     }
  3621.     if (vid_stream->mblock.bpict_past_forw &&
  3622.     !vid_stream->mblock.bpict_past_back) {
  3623.       
  3624.       int *dest, *dest1;
  3625.       int *src, *src1;
  3626.       dest = (int *)(vid_stream->current->luminance + (row * row_size) + col);
  3627.       src = (int *)forw_lum;
  3628.       
  3629.       for (rr = 0; rr < 16; rr++) {
  3630.     
  3631.     /* memcpy(dest, forw_lum+(rr<<4), 16);  */
  3632.     dest[0] = src[0];
  3633.     dest[1] = src[1];
  3634.     dest[2] = src[2];
  3635.     dest[3] = src[3];
  3636.     dest += row_incr;
  3637.     src += 4;
  3638.       }
  3639.       
  3640.       dest = (int *)(vid_stream->current->Cr + (crow * half_row) + ccol);
  3641.       dest1 = (int *)(vid_stream->current->Cb + (crow * half_row) + ccol);
  3642.       src = (int *)forw_cr;
  3643.       src1 = (int *)forw_cb;
  3644.       
  3645.       for (rr = 0; rr < 8; rr++) {
  3646.     /*
  3647.      * memcpy(dest, forw_cr+(rr<<3), 8); memcpy(dest1, forw_cb+(rr<<3),
  3648.      * 8);
  3649.      */
  3650.     
  3651.     dest[0] = src[0];
  3652.     dest[1] = src[1];
  3653.     
  3654.     dest1[0] = src1[0];
  3655.     dest1[1] = src1[1];
  3656.     
  3657.     dest += half_row_incr;
  3658.     dest1 += half_row_incr;
  3659.     src += 2;
  3660.     src1 += 2;
  3661.       }
  3662.     } else if (vid_stream->mblock.bpict_past_back &&
  3663.            !vid_stream->mblock.bpict_past_forw) {
  3664.       
  3665.       int *src, *src1;
  3666.       int *dest, *dest1;
  3667.       dest = (int *)(vid_stream->current->luminance + (row * row_size) + col);
  3668.       src = (int *)back_lum;
  3669.       
  3670.       for (rr = 0; rr < 16; rr++) {
  3671.     dest[0] = src[0];
  3672.     dest[1] = src[1];
  3673.     dest[2] = src[2];
  3674.     dest[3] = src[3];
  3675.     dest += row_incr;
  3676.     src += 4;
  3677.       }
  3678.       
  3679.       
  3680.       dest = (int *)(vid_stream->current->Cr + (crow * half_row) + ccol);
  3681.       dest1 = (int *)(vid_stream->current->Cb + (crow * half_row) + ccol);
  3682.       src = (int *)back_cr;
  3683.       src1 = (int *)back_cb;
  3684.       
  3685.       for (rr = 0; rr < 8; rr++) {
  3686.     /*
  3687.      * memcpy(dest, back_cr+(rr<<3), 8); memcpy(dest1, back_cb+(rr<<3),
  3688.      * 8);
  3689.      */
  3690.     
  3691.     dest[0] = src[0];
  3692.     dest[1] = src[1];
  3693.     
  3694.     dest1[0] = src1[0];
  3695.     dest1[1] = src1[1];
  3696.     
  3697.     dest += half_row_incr;
  3698.     dest1 += half_row_incr;
  3699.     src += 2;
  3700.     src1 += 2;
  3701.       }
  3702.     } else {
  3703.       
  3704.       unsigned char *src1, *src2, *src1a, *src2a;
  3705.       unsigned char *dest, *dest1;
  3706.       dest = vid_stream->current->luminance + (row * row_size) + col;
  3707.       src1 = forw_lum;
  3708.       src2 = back_lum;
  3709.       
  3710.       for (rr = 0; rr < 16; rr++) {
  3711.     dest[0] = (int) (src1[0] + src2[0]) >> 1;
  3712.     dest[1] = (int) (src1[1] + src2[1]) >> 1;
  3713.     dest[2] = (int) (src1[2] + src2[2]) >> 1;
  3714.     dest[3] = (int) (src1[3] + src2[3]) >> 1;
  3715.     dest[4] = (int) (src1[4] + src2[4]) >> 1;
  3716.     dest[5] = (int) (src1[5] + src2[5]) >> 1;
  3717.     dest[6] = (int) (src1[6] + src2[6]) >> 1;
  3718.     dest[7] = (int) (src1[7] + src2[7]) >> 1;
  3719.     dest[8] = (int) (src1[8] + src2[8]) >> 1;
  3720.     dest[9] = (int) (src1[9] + src2[9]) >> 1;
  3721.     dest[10] = (int) (src1[10] + src2[10]) >> 1;
  3722.     dest[11] = (int) (src1[11] + src2[11]) >> 1;
  3723.     dest[12] = (int) (src1[12] + src2[12]) >> 1;
  3724.     dest[13] = (int) (src1[13] + src2[13]) >> 1;
  3725.     dest[14] = (int) (src1[14] + src2[14]) >> 1;
  3726.     dest[15] = (int) (src1[15] + src2[15]) >> 1;
  3727.     dest += row_size;
  3728.     src1 += 16;
  3729.     src2 += 16;
  3730.       }
  3731.       
  3732.       
  3733.       dest = vid_stream->current->Cr + (crow * half_row) + ccol;
  3734.       dest1 = vid_stream->current->Cb + (crow * half_row) + ccol;
  3735.       src1 = forw_cr;
  3736.       src2 = back_cr;
  3737.       src1a = forw_cb;
  3738.       src2a = back_cb;
  3739.       
  3740.       for (rr = 0; rr < 8; rr++) {
  3741.     dest[0] = (int) (src1[0] + src2[0]) >> 1;
  3742.     dest[1] = (int) (src1[1] + src2[1]) >> 1;
  3743.     dest[2] = (int) (src1[2] + src2[2]) >> 1;
  3744.     dest[3] = (int) (src1[3] + src2[3]) >> 1;
  3745.     dest[4] = (int) (src1[4] + src2[4]) >> 1;
  3746.     dest[5] = (int) (src1[5] + src2[5]) >> 1;
  3747.     dest[6] = (int) (src1[6] + src2[6]) >> 1;
  3748.     dest[7] = (int) (src1[7] + src2[7]) >> 1;
  3749.     dest += half_row;
  3750.     src1 += 8;
  3751.     src2 += 8;
  3752.     
  3753.     dest1[0] = (int) (src1a[0] + src2a[0]) >> 1;
  3754.     dest1[1] = (int) (src1a[1] + src2a[1]) >> 1;
  3755.     dest1[2] = (int) (src1a[2] + src2a[2]) >> 1;
  3756.     dest1[3] = (int) (src1a[3] + src2a[3]) >> 1;
  3757.     dest1[4] = (int) (src1a[4] + src2a[4]) >> 1;
  3758.     dest1[5] = (int) (src1a[5] + src2a[5]) >> 1;
  3759.     dest1[6] = (int) (src1a[6] + src2a[6]) >> 1;
  3760.     dest1[7] = (int) (src1a[7] + src2a[7]) >> 1;
  3761.     dest1 += half_row;
  3762.     src1a += 8;
  3763.     src2a += 8;
  3764.       }
  3765.     }
  3766.     
  3767.     if (ditherType == MBORDERED_DITHER) {
  3768.       ditherFlags[addr] = 1;
  3769.     }
  3770.   }
  3771. }
  3772.  
  3773.  
  3774.  
  3775.  
  3776. /*
  3777.  *--------------------------------------------------------------
  3778.  *
  3779.  * ReconSkippedBlock --
  3780.  *
  3781.  *    Reconstructs predictive block for skipped macroblocks
  3782.  *      in B Frames.
  3783.  *
  3784.  * Results:
  3785.  *    No return values.
  3786.  *
  3787.  * Side effects:
  3788.  *    None.
  3789.  *
  3790.  *--------------------------------------------------------------
  3791.  */
  3792.  
  3793. static void
  3794. ReconSkippedBlock(source, dest, row, col, row_size,
  3795.           right, down, right_half, down_half, width)
  3796.   unsigned char *source;
  3797.   unsigned char *dest;
  3798.   int row, col, row_size, right, down, right_half, down_half, width;
  3799. {
  3800.   int rr;
  3801.   unsigned char *source2;
  3802.  
  3803.   source += ((row + down) * row_size) + col + right;
  3804.  
  3805.   if (width == 16) {
  3806.     if ((!right_half) && (!down_half)) {
  3807.     if (right & 0x1) {
  3808.       /* No alignment, use bye copy */
  3809.       for (rr = 0; rr < 16; rr++) {
  3810.         dest[0] = source[0];
  3811.         dest[1] = source[1];
  3812.         dest[2] = source[2];
  3813.         dest[3] = source[3];
  3814.         dest[4] = source[4];
  3815.         dest[5] = source[5];
  3816.         dest[6] = source[6];
  3817.         dest[7] = source[7];
  3818.         dest[8] = source[8];
  3819.         dest[9] = source[9];
  3820.         dest[10] = source[10];
  3821.         dest[11] = source[11];
  3822.         dest[12] = source[12];
  3823.         dest[13] = source[13];
  3824.         dest[14] = source[14];
  3825.         dest[15] = source[15];
  3826.         dest += 16;
  3827.         source += row_size;
  3828.       }
  3829.     } else if (right & 0x2) {
  3830.       /* Half-word bit aligned, use 16 bit copy */
  3831.       short *src = (short *)source;
  3832.       short *d = (short *)dest;
  3833.       row_size >>= 1;
  3834.       for (rr = 0; rr < 16; rr++) {
  3835.         d[0] = src[0];
  3836.         d[1] = src[1];
  3837.         d[2] = src[2];
  3838.         d[3] = src[3];
  3839.         d[4] = src[4];
  3840.         d[5] = src[5];
  3841.         d[6] = src[6];
  3842.         d[7] = src[7];
  3843.         d += 8;
  3844.         src += row_size;
  3845.       }
  3846.     } else {
  3847.       /* Word aligned, use 32 bit copy */
  3848.       int *src = (int *)source;
  3849.       int *d = (int *)dest;
  3850.       row_size >>= 2;
  3851.       for (rr = 0; rr < 16; rr++) {
  3852.         d[0] = src[0];
  3853.         d[1] = src[1];
  3854.         d[2] = src[2];
  3855.         d[3] = src[3];
  3856.         d += 4;
  3857.         src += row_size;
  3858.       }
  3859.     }
  3860.     } else {
  3861.       source2 = source + right_half + (row_size * down_half);
  3862.       for (rr = 0; rr < width; rr++) {
  3863.     dest[0] = (int) (source[0] + source2[0]) >> 1;
  3864.     dest[1] = (int) (source[1] + source2[1]) >> 1;
  3865.     dest[2] = (int) (source[2] + source2[2]) >> 1;
  3866.     dest[3] = (int) (source[3] + source2[3]) >> 1;
  3867.     dest[4] = (int) (source[4] + source2[4]) >> 1;
  3868.     dest[5] = (int) (source[5] + source2[5]) >> 1;
  3869.     dest[6] = (int) (source[6] + source2[6]) >> 1;
  3870.     dest[7] = (int) (source[7] + source2[7]) >> 1;
  3871.     dest[8] = (int) (source[8] + source2[8]) >> 1;
  3872.     dest[9] = (int) (source[9] + source2[9]) >> 1;
  3873.     dest[10] = (int) (source[10] + source2[10]) >> 1;
  3874.     dest[11] = (int) (source[11] + source2[11]) >> 1;
  3875.     dest[12] = (int) (source[12] + source2[12]) >> 1;
  3876.     dest[13] = (int) (source[13] + source2[13]) >> 1;
  3877.     dest[14] = (int) (source[14] + source2[14]) >> 1;
  3878.     dest[15] = (int) (source[15] + source2[15]) >> 1;
  3879.     dest += width;
  3880.     source += row_size;
  3881.     source2 += row_size;
  3882.       }
  3883.     }
  3884.   } else {            /* (width == 8) */
  3885.     assert(width == 8);
  3886.     if ((!right_half) && (!down_half)) {
  3887.       if (right & 0x1) {
  3888.     for (rr = 0; rr < width; rr++) {
  3889.       dest[0] = source[0];
  3890.       dest[1] = source[1];
  3891.       dest[2] = source[2];
  3892.       dest[3] = source[3];
  3893.       dest[4] = source[4];
  3894.       dest[5] = source[5];
  3895.       dest[6] = source[6];
  3896.       dest[7] = source[7];
  3897.       dest += 8;
  3898.       source += row_size;
  3899.     }
  3900.       } else if (right & 0x02) {
  3901.     short *d = (short *)dest;
  3902.     short *src = (short *)source;
  3903.     row_size >>= 1;
  3904.     for (rr = 0; rr < width; rr++) {
  3905.       d[0] = src[0];
  3906.       d[1] = src[1];
  3907.       d[2] = src[2];
  3908.       d[3] = src[3];
  3909.       d += 4;
  3910.       src += row_size;
  3911.     }
  3912.       } else {
  3913.     int *d = (int *)dest;
  3914.     int *src = (int *)source;
  3915.     row_size >>= 2;
  3916.     for (rr = 0; rr < width; rr++) {
  3917.       d[0] = src[0];
  3918.       d[1] = src[1];
  3919.       d += 2;
  3920.       src += row_size;
  3921.     }
  3922.       }
  3923.     } else {
  3924.       source2 = source + right_half + (row_size * down_half);
  3925.       for (rr = 0; rr < width; rr++) {
  3926.     dest[0] = (int) (source[0] + source2[0]) >> 1;
  3927.     dest[1] = (int) (source[1] + source2[1]) >> 1;
  3928.     dest[2] = (int) (source[2] + source2[2]) >> 1;
  3929.     dest[3] = (int) (source[3] + source2[3]) >> 1;
  3930.     dest[4] = (int) (source[4] + source2[4]) >> 1;
  3931.     dest[5] = (int) (source[5] + source2[5]) >> 1;
  3932.     dest[6] = (int) (source[6] + source2[6]) >> 1;
  3933.     dest[7] = (int) (source[7] + source2[7]) >> 1;
  3934.     dest += width;
  3935.     source += row_size;
  3936.     source2 += row_size;
  3937.       }
  3938.     }
  3939.   }
  3940. }
  3941.  
  3942.  
  3943.  
  3944. /*
  3945.  *--------------------------------------------------------------
  3946.  *
  3947.  * DoPictureDisplay --
  3948.  *
  3949.  *    Converts image from Lum, Cr, Cb to colormap space. Puts
  3950.  *      image in lum plane. Updates past and future frame
  3951.  *      pointers. Dithers image. Sends to display mechanism.
  3952.  *
  3953.  * Results:
  3954.  *    Pict image structure locked if displaying or if frame
  3955.  *      is needed as past or future reference.
  3956.  *
  3957.  * Side effects:
  3958.  *    Lum plane pummelled.
  3959.  *
  3960.  *--------------------------------------------------------------
  3961.  */
  3962.  
  3963. static void
  3964. DoPictureDisplay(vid_stream)
  3965.   VidStream *vid_stream;
  3966. {
  3967.  
  3968.   /* Convert to colormap space and dither. */
  3969.  
  3970.   DoDitherImage(vid_stream->current->luminance, vid_stream->current->Cr,
  3971.         vid_stream->current->Cb, vid_stream->current->display,
  3972.         vid_stream->mb_height * 16, vid_stream->mb_width * 16);
  3973.  
  3974.   /* Update past and future references if needed. */
  3975.  
  3976.   if ((vid_stream->picture.code_type == I_TYPE) || (vid_stream->picture.code_type == P_TYPE)) {
  3977.     if (vid_stream->future == NULL) {
  3978.       vid_stream->future = vid_stream->current;
  3979.       vid_stream->future->locked |= FUTURE_LOCK;
  3980.     } else {
  3981.       if (vid_stream->past != NULL) {
  3982.     vid_stream->past->locked &= ~PAST_LOCK;
  3983.       }
  3984.       vid_stream->past = vid_stream->future;
  3985.       vid_stream->past->locked &= ~FUTURE_LOCK;
  3986.       vid_stream->past->locked |= PAST_LOCK;
  3987.       vid_stream->future = vid_stream->current;
  3988.       vid_stream->future->locked |= FUTURE_LOCK;
  3989.       vid_stream->current = vid_stream->past;
  3990.       ExecuteDisplay(vid_stream);
  3991.     }
  3992.   } else
  3993.     ExecuteDisplay(vid_stream);
  3994.  
  3995. }
  3996.  
  3997.  
  3998.  
  3999. /*
  4000.  *--------------------------------------------------------------
  4001.  *
  4002.  * ToggleBFlag --
  4003.  *
  4004.  *    Called to set no b frame processing flag.
  4005.  *
  4006.  * Results:
  4007.  *      No_B_Flag flag is toggled from present value to opposite value.
  4008.  *
  4009.  * Side effects:
  4010.  *      None.
  4011.  *
  4012.  *--------------------------------------------------------------
  4013.  */
  4014.  
  4015. void
  4016. ToggleBFlag()
  4017. {
  4018.   if (No_B_Flag) {
  4019.     No_B_Flag = 0;
  4020.   } else
  4021.     No_B_Flag = 1;
  4022. }
  4023.  
  4024.  
  4025.  
  4026.  
  4027. /*
  4028.  *--------------------------------------------------------------
  4029.  *
  4030.  * TogglePFlag --
  4031.  *
  4032.  *    Called to set no p frame processing flag.
  4033.  *
  4034.  * Results:
  4035.  *      No_P_Flag flag is toggled from present value to opposite value.
  4036.  *
  4037.  * Side effects:
  4038.  *      None.
  4039.  *
  4040.  *--------------------------------------------------------------
  4041.  */
  4042.  
  4043. void
  4044. TogglePFlag()
  4045. {
  4046.   if (No_P_Flag) {
  4047.     No_P_Flag = 0;
  4048.   } else
  4049.     No_P_Flag = 1;
  4050. }
  4051.