home *** CD-ROM | disk | FTP | other *** search
/ Magazyn Amiga Shareware Floppies / ma57.dms / ma57.adf / aMiPEG05 / source.lha / video.c < prev    next >
C/C++ Source or Header  |  1996-01-23  |  57KB  |  2,109 lines

  1. /*
  2.  *  This file contains C code that implements the video decoder model.
  3.  */
  4.  
  5. #include "video.h"
  6. #include "proto.h"
  7. #include "decoders.h"
  8. #include "util.h"
  9.  
  10. #include <time.h>
  11.  
  12. #define MYRECON
  13.  
  14. /* Declarations of functions. */
  15. //static void init_stat_struct(Statval *);
  16. //static void PrintOneStat(void);
  17. //static void CollectStats(void);
  18. //static unsigned int bitCountRead(void);
  19. //static void StartTime(void);
  20. //static void EndTime(void);
  21. static int ParseSeqHead(VidStream *);
  22. static int ParseGOP(VidStream *);
  23. static int ParsePicture(VidStream *, TimeStamp);
  24. static int ParseSlice(VidStream *);
  25. static int ParseMacroBlock(VidStream *);
  26. static void DoPictureDisplay(VidStream *);
  27.  
  28. #ifndef MYRECON
  29. static void ReconIMBlock(VidStream *, int);
  30. static void ReconPMBlock(VidStream *, int, int, int, int);
  31. static void ReconBMBlock(VidStream *, int, int, int, int);
  32. static void ReconBiMBlock(VidStream *, int, int, int, int, int, int);
  33. #endif
  34.  
  35. static void ProcessSkippedPFrameMBlocks(VidStream *);
  36. static void ProcessSkippedBFrameMBlocks(VidStream *);
  37. static void ReconSkippedBlock16(unsigned char *, unsigned char *, int, int, int, int, int, int, int);
  38. static void ReconSkippedBlock8(unsigned char *, unsigned char *, int, int, int, int, int, int, int);
  39.  
  40. extern int ditherType;
  41.  
  42. /* Macro for returning 1 if num is positive, -1 if negative, 0 if 0. */
  43. //#define Sign(num) ((num > 0) ? 1 : ((num == 0) ? 0 : -1))
  44.  
  45. /* Declare global pointer to vid stream used for current decoding. */
  46.  
  47. VidStream *curVidStream = NULL;
  48.  
  49. /* Array mapping zigzag to array pointer offset. */
  50. int zigzag_direct[64] = {
  51.   0, 1, 8, 16, 9, 2, 3, 10, 17, 24, 32, 25, 18, 11, 4, 5, 12,
  52.   19, 26, 33, 40, 48, 41, 34, 27, 20, 13, 6, 7, 14, 21, 28, 35,
  53.   42, 49, 56, 57, 50, 43, 36, 29, 22, 15, 23, 30, 37, 44, 51,
  54.   58, 59, 52, 45, 38, 31, 39, 46, 53, 60, 61, 54, 47, 55, 62, 63};
  55.  
  56. /* Initialize P and B skip flags. */
  57.  
  58. static int No_P_Flag = 0;
  59. static int No_B_Flag = 0;
  60.  
  61. /* Max lum, chrom indices for illegal block checking. */
  62.  
  63. static int lmaxx, lmaxy, cmaxx, cmaxy;
  64.  
  65.  
  66. /*
  67.   The following accounts for time and size  spent in various parsing acitivites
  68.   if ANALYSIS has been defined.
  69. */
  70. #ifdef ANALYSIS
  71. #include "analysis.h"
  72. #endif
  73.  
  74. double realTimeStart;
  75. int totNumFrames = 0;
  76.  
  77. double ReadSysClock(void)
  78. {
  79.     unsigned int clock[2];
  80.  
  81.     (void) timer(clock);
  82.     return clock[0] + clock[1] / 1000000.0;
  83. }
  84.  
  85. void PrintTimeInfo(void)
  86. {
  87.     if (!quietFlag) {
  88.         double spent = ReadSysClock() - realTimeStart;
  89.  
  90.         printf("\nReal Time Spent (After Initializations): %f secs.\n", spent);
  91.         printf("Avg. Frames/Sec: %f\n", ((double) totNumFrames) / spent);
  92.  
  93.         printf("Frame size: %i*%i pixels\n", curVidStream->h_size, curVidStream->v_size);
  94.         if(modeid != 0xffffffff)
  95.             printf("ModeID of CyberGraphX screen: 0x%X\n", modeid);
  96.     }
  97. }
  98.  
  99.  
  100.  
  101. /*
  102.  *--------------------------------------------------------------
  103.  *
  104.  * NewVidStream --
  105.  *
  106.  *    Allocates and initializes a VidStream structure. Takes
  107.  *      as parameter requested size for buffer length.
  108.  *
  109.  * Results:
  110.  *    A pointer to the new VidStream structure.
  111.  *
  112.  * Side effects:
  113.  *      None.
  114.  *
  115.  *--------------------------------------------------------------
  116.  */
  117.  
  118. VidStream * NewVidStream(int bufLength)
  119. {
  120.   int i,j;
  121.   short *intra_quant_matrix, *intra_quant_matrix0, *intra_quant_matrix1;
  122.   VidStream *new;
  123.   static unsigned char default_intra_matrix[64] = {
  124.     8, 16, 19, 22, 26, 27, 29, 34,
  125.     16, 16, 22, 24, 27, 29, 34, 37,
  126.     19, 22, 26, 27, 29, 34, 34, 38,
  127.     22, 22, 26, 27, 29, 34, 37, 40,
  128.     22, 26, 27, 29, 32, 35, 40, 48,
  129.     26, 27, 29, 32, 35, 40, 48, 58,
  130.     26, 27, 29, 34, 38, 46, 56, 69,
  131.     27, 29, 35, 38, 46, 56, 69, 83};
  132.  
  133.   /* Check for legal buffer length. */
  134.  
  135.   if (bufLength < 4) return NULL;
  136.  
  137.   /* Make buffer length multiple of 4. */
  138.  
  139.   bufLength = (bufLength + 3) >> 2;
  140.  
  141.   /* Allocate memory for new structure. */
  142.  
  143.   new = (VidStream *) malloc(sizeof(VidStream));
  144.  
  145.   /* Initialize pointers to extension and user data. */
  146.  
  147.   new->group.ext_data = new->group.user_data =
  148.     new->picture.extra_info = new->picture.user_data =
  149.     new->picture.ext_data = new->slice.extra_info =
  150.     new->ext_data = new->user_data = NULL;
  151.  
  152.   /* Create default intra matrix and qscale multiplication tables. */
  153.  
  154.   new->intra_quant_matrix_ptr[0] = (short*) malloc(32 * 8*8 * sizeof(short));
  155.   clear64words(intra_quant_matrix = new->intra_quant_matrix_ptr[0]);
  156.   for(j=1; j<32; j++) new->intra_quant_matrix_ptr[j] = (intra_quant_matrix+=64);
  157.  
  158.   intra_quant_matrix0 = intra_quant_matrix = new->intra_quant_matrix_ptr[1];
  159.  
  160.   for(i=0; i<64; i++)
  161.     *intra_quant_matrix++ = default_intra_matrix[zigzag_direct[i]];
  162.  
  163.   for(j=2; j<32; j++)
  164.   {
  165.     intra_quant_matrix1 = new->intra_quant_matrix_ptr[1];
  166.     for(i=0; i<64; i++) *intra_quant_matrix++ = (*intra_quant_matrix0++) + (*intra_quant_matrix1++);
  167.   }
  168.  
  169.   /* Initialize non intra quantization matrix. */
  170.  
  171.   new->non_intra_default = TRUE;
  172.   new->non_intra_quant_matrix_ptr[0] = NULL;
  173.  
  174.   /* Initialize pointers to image spaces. */
  175.  
  176.   new->current = new->past = new->future = NULL;
  177.   for (i = 0; i < RING_BUF_SIZE; i++) new->ring[i] = NULL;
  178.  
  179.   /* Create buffer. */
  180.  
  181.   new->buf_start = (unsigned int *) malloc(bufLength * 4);
  182.  
  183.   /*
  184.    * Set max_buf_length to one less than actual length to deal with messy
  185.    * data without proper seq. end codes.
  186.    */
  187.  
  188.   new->max_buf_length = bufLength - 1;
  189.  
  190.   /* Initialize bitstream i/o fields. */
  191.  
  192.   new->bit_offset = 0;
  193.   new->buf_length = 0;
  194.   new->buffer = new->buf_start;
  195.  
  196.   /* display stuff */
  197.  
  198.   new->display_is_initialized = FALSE;
  199.  
  200.   /* Return structure. */
  201.  
  202.   return new;
  203. }
  204.  
  205.  
  206.  
  207. /*
  208.  *--------------------------------------------------------------
  209.  *
  210.  * DestroyVidStream --
  211.  *
  212.  *    Deallocates a VidStream structure.
  213.  *
  214.  * Results:
  215.  *      None.
  216.  *
  217.  * Side effects:
  218.  *    None.
  219.  *
  220.  *--------------------------------------------------------------
  221.  */
  222. void DestroyVidStream(VidStream *astream)
  223. {
  224.   int i;
  225.  
  226.   if (astream->ext_data) free(astream->ext_data);
  227.  
  228.   if (astream->user_data) free(astream->user_data);
  229.  
  230.   if (astream->group.ext_data) free(astream->group.ext_data);
  231.  
  232.   if (astream->group.user_data) free(astream->group.user_data);
  233.  
  234.   if (astream->picture.extra_info) free(astream->picture.extra_info);
  235.  
  236.   if (astream->picture.ext_data) free(astream->picture.ext_data);
  237.  
  238.   if (astream->picture.user_data) free(astream->picture.user_data);
  239.  
  240.   if (astream->slice.extra_info) free(astream->slice.extra_info);
  241.  
  242.   if (astream->buf_start) free(astream->buf_start);
  243.  
  244.   for (i = 0; i < RING_BUF_SIZE; i++) {
  245.     if (astream->ring[i]) {
  246.       DestroyPictImage(astream->ring[i]);
  247.       astream->ring[i] = NULL;
  248.     }
  249.   }
  250.  
  251.   if (!astream->non_intra_default) free(astream->non_intra_quant_matrix_ptr[0]);
  252.  
  253.   if (astream->intra_quant_matrix_ptr[0]) free(astream->intra_quant_matrix_ptr[0]);
  254.  
  255.   free((char *) astream);
  256. }
  257.  
  258.  
  259.  
  260.  
  261. /*
  262.  *--------------------------------------------------------------
  263.  *
  264.  * NewPictImage --
  265.  *
  266.  *    Allocates and initializes a PictImage structure.
  267.  *      The width and height of the image space are passed in
  268.  *      as parameters.
  269.  *
  270.  * Results:
  271.  *    A pointer to the new PictImage structure.
  272.  *
  273.  * Side effects:
  274.  *    None.
  275.  *
  276.  *--------------------------------------------------------------
  277.  */
  278.  
  279. PictImage * NewPictImage(unsigned int width, unsigned int height)
  280. {
  281.   extern int lores, ham6;
  282.   PictImage *new;
  283.   int size = (short)width * (short)height;
  284.  
  285.   /* Allocate memory space for new structure. */
  286.  
  287.   new = (PictImage *) malloc(sizeof(PictImage));
  288.  
  289.   /* Allocate memory for image spaces. */
  290.   if (ditherType == FULL_COLOR_DITHER) {
  291.     new->display = (unsigned char *) malloc(ham6 ? size : (lores ? (size << 1) : (size << 2)));
  292.   } else if (ditherType == CYBERGFX_DITHER) {
  293.         new->display = (unsigned char *) malloc(size * 4);    /* one byte for each of R, G and B  and A :)*/
  294.     } else {
  295.     new->display = (unsigned char *) malloc(size);
  296.   }
  297.  
  298.   new->luminance = (unsigned char *) malloc(size);
  299.   new->Cr = (unsigned char *) malloc(size >> 2);
  300.   new->Cb = (unsigned char *) malloc(size >> 2);
  301.  
  302.   /* Reset locked flag. */
  303.  
  304.   new->locked = 0;
  305.  
  306.   /* Return pointer to new structure. */
  307.  
  308.   return new;
  309. }
  310.  
  311.  
  312.  
  313. /*
  314.  *--------------------------------------------------------------
  315.  *
  316.  * DestroyPictImage --
  317.  *
  318.  *    Deallocates a PictImage structure.
  319.  *
  320.  * Results:
  321.  *      None.
  322.  *
  323.  * Side effects:
  324.  *    None.
  325.  *
  326.  *--------------------------------------------------------------
  327.  */
  328. void DestroyPictImage(PictImage *apictimage)
  329. {
  330.   if (apictimage->luminance) free(apictimage->luminance);
  331.   if (apictimage->Cr) free(apictimage->Cr);
  332.   if (apictimage->Cb) free(apictimage->Cb);
  333.   if (apictimage->display) free(apictimage->display);
  334.   free(apictimage);
  335. }
  336.  
  337. /*
  338.  *--------------------------------------------------------------
  339.  *
  340.  * mpegInitVidRsrc --
  341.  *
  342.  *      reset first to 1
  343.  *
  344.  * gonna check this thingy out !!!!
  345.  *
  346.  *--------------------------------------------------------------
  347.  */
  348. static int first = 1;
  349.  
  350. void mpegInitVidRsrc(void)
  351. {
  352.     first = 1;
  353. }
  354.  
  355.  
  356. /*
  357.  *--------------------------------------------------------------
  358.  *
  359.  * mpegVidRsrc --
  360.  *
  361.  *      Parses bit stream until MB_QUANTUM number of
  362.  *      macroblocks have been decoded or current slice or
  363.  *      picture ends, whichever comes first. If the start
  364.  *      of a frame is encountered, the frame is time stamped
  365.  *      with the value passed in time_stamp. If the value
  366.  *      passed in buffer is not null, the video stream buffer
  367.  *      is set to buffer and the length of the buffer is
  368.  *      expected in value passed in through length. The current
  369.  *      video stream is set to vid_stream. If vid_stream
  370.  *      is passed as NULL, a new VidStream structure is created
  371.  *      and initialized and used as the current video stream.
  372.  *
  373.  * Results:
  374.  *      A Boolean value is returned - 0 is end of picture or error
  375.  *
  376.  * Side effects:
  377.  *      Bit stream is irreversibly parsed. If a picture is completed,
  378.  *      a function is called to display the frame at the correct time.
  379.  *
  380.  *--------------------------------------------------------------
  381.  */
  382.  
  383. int mpegVidRsrc(TimeStamp time_stamp, VidStream *vid_stream)
  384. {
  385.   unsigned int data;
  386.   int i, status;
  387.  
  388.   /* If vid_stream is null, create new VidStream structure.  MR: ????? */
  389.  
  390.     if(!handle_window())
  391.         return 0;
  392.  
  393.   if (vid_stream == NULL) return 0;
  394.  
  395.   /*
  396.    * Set global curVidStream to vid_stream. Necessary because bit i/o use
  397.    * curVidStream and are not passed vid_stream. Also set global bitstream
  398.    * parameters.
  399.    */
  400.  
  401.   curVidStream = vid_stream;
  402.   bitOffset = curVidStream->bit_offset;
  403.   bufLength = curVidStream->buf_length;
  404.   bitBuffer = curVidStream->buffer;
  405.  
  406.   /*
  407.    * If called for the first time, find start code, make sure it is a
  408.    * sequence start code.
  409.    */
  410.  
  411.   if (first) {
  412.     next_start_code();
  413.     if (show_bits32(data) != SEQ_START_CODE) {
  414.       fprintf(stderr, "This is not an MPEG stream.\n");
  415.       DestroyVidStream(curVidStream);
  416.       exit(1);
  417.     }
  418.     first = 0;
  419.   }
  420.  
  421.   /*
  422.    * Process according to start code (or parse macroblock if not a start code
  423.    * at all.
  424.    */
  425.  
  426.   switch (show_bits32(data)) {
  427.  
  428.   case SEQ_END_CODE:
  429.  
  430.     /* Display last frame. */
  431.  
  432.     if (vid_stream->future != NULL) {
  433.       vid_stream->current = vid_stream->future;
  434.       ExecuteDisplay(vid_stream);
  435.     }
  436.     
  437.     /* Sequence done. Do the right thing. return False. */
  438.  
  439.     if (!quietFlag) {
  440.       fprintf(stderr, "\nDone!\n");
  441.     }
  442.  
  443. #ifdef ANALYSIS
  444.     PrintAllStats();
  445. #endif
  446.     PrintTimeInfo();
  447.  
  448.     if (loopFlag) longjmp(env, 1);
  449.  
  450.     DestroyVidStream(curVidStream);
  451.     return 0;
  452.     break;
  453.  
  454.   case SEQ_START_CODE:
  455.  
  456.     /* Sequence start code. Parse sequence header. */
  457.  
  458.     if (ParseSeqHead(vid_stream) != PARSE_OK) goto error;
  459.  
  460.     /*
  461.      * Return after sequence start code so that application above can use
  462.      * info in header.
  463.      */
  464.  
  465.     goto done;
  466.  
  467.   case GOP_START_CODE:
  468.  
  469.     /* Group of Pictures start code. Parse gop header. */
  470.  
  471.     if (ParseGOP(vid_stream) != PARSE_OK) goto error;
  472.  
  473.  
  474.   case PICTURE_START_CODE:
  475.  
  476.     /* Picture start code. Parse picture header and first slice header. */
  477.  
  478.     status = ParsePicture(vid_stream, time_stamp);
  479.  
  480.     if (status == SKIP_PICTURE) {
  481.       next_start_code();
  482.       fprintf(stderr, "Skipping picture...");
  483.       while ((show_bits32(data)) != PICTURE_START_CODE) {
  484.     if (data == GOP_START_CODE || data == SEQ_END_CODE)
  485.       break;
  486.     flush_bits(24);
  487.     next_start_code();
  488.       }
  489.       fprintf(stderr, "Done.\n");
  490.       goto done;
  491.     } else if (status != PARSE_OK) goto error;
  492.  
  493.  
  494.     if (ParseSlice(vid_stream) != PARSE_OK) goto error;
  495.     break;
  496.  
  497.   case USER_START_CODE:    // there has been one stream with an error in a GOP header
  498.     flush_bits32;
  499.     if (vid_stream->group.user_data) {
  500.       free(vid_stream->group.user_data);
  501.       vid_stream->group.user_data = NULL;
  502.     }
  503.     vid_stream->group.user_data = get_ext_data();
  504.     break;
  505.   case EXT_START_CODE:
  506.     flush_bits32;
  507.     if (vid_stream->group.ext_data) {
  508.       free(vid_stream->group.ext_data);
  509.       vid_stream->group.ext_data = NULL;
  510.     }
  511.     vid_stream->group.ext_data = get_ext_data();
  512.     break;
  513.  
  514.   default:
  515.     /* Check for slice start code. */
  516.  
  517.     if ((data >= SLICE_MIN_START_CODE) && (data <= SLICE_MAX_START_CODE))
  518.       if (ParseSlice(vid_stream) != PARSE_OK)    /* Slice start code. Parse slice header. */
  519.     goto error;
  520.  
  521.     break;
  522.   }
  523.  
  524.   /* Parse next MB_QUANTUM macroblocks. */
  525.  
  526.   for (i = 0; i < MB_QUANTUM; i++) {
  527.  
  528.     /* Check to see if actually a startcode and not a macroblock. */
  529.  
  530.     if ((show_bitsn(23,data)) != 0x00000000) {
  531.  
  532.       /* Not start code. Parse Macroblock. */
  533.  
  534.       if (ParseMacroBlock(vid_stream) != PARSE_OK)
  535.     goto error;
  536.  
  537. #ifdef ANALYSIS
  538.       if (showmb_flag) {
  539.     DoDitherImage(vid_stream->current->luminance, vid_stream->current->Cr,
  540.               vid_stream->current->Cb, vid_stream->current->display,
  541.               vid_stream->mb_height * 16, vid_stream->mb_width * 16);
  542.     ExecuteDisplay(vid_stream);
  543.       }
  544. #endif
  545.  
  546.     } else {
  547.  
  548.       /* Not macroblock, actually start code. Get start code. */
  549.  
  550.       next_start_code();
  551.       show_bits32(data);
  552.  
  553.       /*
  554.        * If start code is outside range of slice start codes, frame is
  555.        * complete, display frame.
  556.        */
  557.  
  558.       if ((data < SLICE_MIN_START_CODE) || (data > SLICE_MAX_START_CODE)) {
  559.  
  560. #ifdef ANALYSIS
  561.     EndTime();
  562.     stat_a[0].totsize += bitCountRead() - pictureSizeCount;
  563.     if (showEachFlag)
  564.       PrintOneStat();
  565.  
  566.     CollectStats();
  567. #endif
  568.  
  569.     DoPictureDisplay(vid_stream);
  570.       }
  571.       break;
  572.     }
  573.   }
  574.  
  575.   /* Return pointer to video stream structure. */
  576.  
  577.   goto done;
  578.  
  579. error:
  580.   fprintf(stderr, "Error!!!!\n");
  581.   next_start_code();
  582.   goto done;
  583.  
  584. done:
  585.  
  586.   /* Copy global bit i/o variables back into vid_stream. */
  587.  
  588.   vid_stream->buffer = bitBuffer;
  589.   vid_stream->buf_length = bufLength;
  590.   vid_stream->bit_offset = bitOffset;
  591.  
  592.   return 1;
  593. }
  594.  
  595.  
  596. /*
  597.  *--------------------------------------------------------------
  598.  *
  599.  * ParseSeqHead --
  600.  *
  601.  *      Assumes bit stream is at the begining of the sequence
  602.  *      header start code. Parses off the sequence header.
  603.  *
  604.  * Results:
  605.  *      Fills the vid_stream structure with values derived and
  606.  *      decoded from the sequence header. Allocates the pict image
  607.  *      structures based on the dimensions of the image space
  608.  *      found in the sequence header.
  609.  *
  610.  * Side effects:
  611.  *      Bit stream irreversibly parsed off.
  612.  *
  613.  *--------------------------------------------------------------
  614.  */
  615.  
  616. static int ParseSeqHead(VidStream *vid_stream)
  617. {
  618.   unsigned int data;
  619.   int i;
  620.  
  621.   /* Flush off sequence start code. */
  622.  
  623.   flush_bits32;
  624.  
  625.   /* Get horizontal size of image space. */
  626.  
  627.   get_bits12(vid_stream->h_size);
  628.  
  629.   /* Get vertical size of image space. */
  630.  
  631.   get_bits12(vid_stream->v_size);
  632.  
  633.   /* Calculate macroblock width and height of image space. */
  634.  
  635.   vid_stream->mb_width = (vid_stream->h_size + 15) >> 4;
  636.   vid_stream->mb_height = (vid_stream->v_size + 15) >> 4;
  637.  
  638.   /* Initialize lmaxx, lmaxy, cmaxx, cmaxy. */
  639.  
  640.   lmaxx = (vid_stream->mb_width<<4)-1;
  641.   lmaxy = (vid_stream->mb_height<<4)-1;
  642.   cmaxx = (vid_stream->mb_width<<3)-1;
  643.   cmaxy = (vid_stream->mb_height<<3)-1;
  644.  
  645.   /*
  646.    * Initialize ring buffer of pict images now that dimensions of image space
  647.    * are known.
  648.    */
  649.  
  650.   if (vid_stream->ring[0] == NULL) {
  651.     for (i = 0; i < RING_BUF_SIZE; i++)
  652.       vid_stream->ring[i] = NewPictImage(vid_stream->mb_width << 4, vid_stream->mb_height << 4);
  653.   }
  654.  
  655.   /* Parse of aspect ratio code. */
  656.  
  657.   get_bits4(vid_stream->aspect_ratio);
  658.  
  659.   /* Parse off picture rate code. */
  660.  
  661.   get_bits4(vid_stream->picture_rate);
  662.  
  663.   /* Parse off bit rate. */
  664.  
  665.   get_bits18(vid_stream->bit_rate);
  666.  
  667.   /* Flush marker bit. */
  668.  
  669.   flush_bits(1);
  670.  
  671.   /* Parse off vbv buffer size. */
  672.  
  673.   get_bits10(vid_stream->vbv_buffer_size);
  674.  
  675.   /* Parse off contrained parameter flag. */
  676.  
  677.   get_bits1(vid_stream->const_param_flag);
  678.  
  679.   /*
  680.    * If intra_quant_matrix_flag set, parse off intra quant matrix values.
  681.    */
  682.  
  683.   if (get_bits1(data))
  684.     new_matrix(vid_stream->intra_quant_matrix_ptr[1]);
  685.  
  686.   /*
  687.    * If non intra quant matrix flag set, parse off non intra quant matrix
  688.    * values.
  689.    */
  690.  
  691.   if (get_bits1(data))
  692.   {
  693.     if(vid_stream->non_intra_default)
  694.     {
  695.     unsigned short *intra_quant_matrix;
  696.  
  697.     vid_stream->non_intra_quant_matrix_ptr[0] = (short*) malloc(32 * 8*8 * sizeof(short));
  698.     clear64words(intra_quant_matrix = vid_stream->non_intra_quant_matrix_ptr[0]);
  699.     for(i=1; i<32; i++) vid_stream->non_intra_quant_matrix_ptr[i] = (intra_quant_matrix+=64);
  700.  
  701.     vid_stream->non_intra_default = FALSE;
  702.     }
  703.  
  704.     new_matrix(vid_stream->non_intra_quant_matrix_ptr[1]);
  705.   }
  706.  
  707.   /* Go to next start code. */
  708.  
  709.   next_start_code();
  710.  
  711.   /* If next start code is extension start code, parse off extension data. */
  712.  
  713.   if ((show_bits32(data)) == EXT_START_CODE) {
  714.     flush_bits32;
  715.     if (vid_stream->ext_data) {
  716.       free(vid_stream->ext_data);
  717.       vid_stream->ext_data = NULL;
  718.     }
  719.     vid_stream->ext_data = get_ext_data();
  720.     show_bits32(data);
  721.   }
  722.  
  723.   /* If next start code is user start code, parse off user data. */
  724.  
  725.   if (data == USER_START_CODE) {
  726.     flush_bits32;
  727.     if (vid_stream->user_data) {
  728.       free(vid_stream->user_data);
  729.       vid_stream->user_data = NULL;
  730.     }
  731.     vid_stream->user_data = get_ext_data();
  732.   }
  733.  
  734.   return PARSE_OK;
  735. }
  736.  
  737.  
  738.  
  739. /*
  740.  *--------------------------------------------------------------
  741.  *
  742.  * ParseGOP --
  743.  *
  744.  *      Parses of group of pictures header from bit stream
  745.  *      associated with vid_stream.
  746.  *
  747.  * Results:
  748.  *      Values in gop header placed into video stream structure.
  749.  *
  750.  * Side effects:
  751.  *      Bit stream irreversibly parsed.
  752.  *
  753.  *--------------------------------------------------------------
  754.  */
  755.  
  756. static int ParseGOP(VidStream *vid_stream)
  757. {
  758.   unsigned int data;
  759.  
  760.   /* Flush group of pictures start code. WWWWWWOOOOOOOSSSSSSHHHHH!!! */
  761.  
  762.   flush_bits32;
  763.  
  764.   /* Parse off drop frame flag. */
  765.  
  766.   get_bits1(vid_stream->group.drop_flag);
  767.  
  768.   /* Parse off hour component of time code. */
  769.  
  770.   get_bits5(vid_stream->group.tc_hours);
  771.  
  772.   /* Parse off minute component of time code. */
  773.  
  774.   get_bits6(vid_stream->group.tc_minutes);
  775.  
  776.   /* Flush marker bit. */
  777.  
  778.   flush_bits(1);
  779.  
  780.   /* Parse off second component of time code. */
  781.  
  782.   get_bits6(vid_stream->group.tc_seconds);
  783.  
  784.   /* Parse off picture count component of time code. */
  785.  
  786.   get_bits6(vid_stream->group.tc_pictures);
  787.  
  788.   /* Parse off closed gop and broken link flags. */
  789.  
  790.   get_bits1(vid_stream->group.closed_gop);
  791.   get_bits1(vid_stream->group.broken_link);
  792.  
  793.   /* Goto next start code. */
  794.   next_start_code();
  795.  
  796.   /* If next start code is extension data, parse off extension data. */
  797.  
  798.   if ((show_bits32(data)) == EXT_START_CODE) {
  799.     flush_bits32;
  800.     if (vid_stream->group.ext_data) {
  801.       free(vid_stream->group.ext_data);
  802.       vid_stream->group.ext_data = NULL;
  803.     }
  804.     vid_stream->group.ext_data = get_ext_data();
  805.     show_bits32(data);
  806.   }
  807.  
  808.   /* If next start code is user data, parse off user data. */
  809.  
  810.   if (data == USER_START_CODE) {
  811.     flush_bits32;
  812.     if (vid_stream->group.user_data) {
  813.       free(vid_stream->group.user_data);
  814.       vid_stream->group.user_data = NULL;
  815.     }
  816.     vid_stream->group.user_data = get_ext_data();
  817.   }
  818.  
  819.   return PARSE_OK;
  820. }
  821.  
  822.  
  823.  
  824. /*
  825.  *--------------------------------------------------------------
  826.  *
  827.  * ParsePicture --
  828.  *
  829.  *      Parses picture header. Marks picture to be presented
  830.  *      at particular time given a time stamp.
  831.  *
  832.  * Results:
  833.  *      Values from picture header put into video stream structure.
  834.  *
  835.  * Side effects:
  836.  *      Bit stream irreversibly parsed.
  837.  *
  838.  *--------------------------------------------------------------
  839.  */
  840.  
  841. static int ParsePicture(VidStream *vid_stream, TimeStamp time_stamp)
  842. {
  843.   unsigned int data;
  844.   int i;
  845.  
  846.   /* Flush header start code. */
  847.   flush_bits32;
  848.  
  849.   /* Parse off temporal reference. */
  850.   get_bits10(vid_stream->picture.temp_ref);
  851.  
  852.   /* Parse of picture type. */
  853.   get_bits3(vid_stream->picture.code_type);
  854.  
  855.   if ((vid_stream->picture.code_type == B_TYPE) &&
  856.       (No_B_Flag ||
  857.        (vid_stream->past == NULL) ||
  858.        (vid_stream->future == NULL)))
  859.     return SKIP_PICTURE;
  860.  
  861.   if ((vid_stream->picture.code_type == P_TYPE) &&
  862.       (No_P_Flag || (vid_stream->future == NULL)))
  863.     return SKIP_PICTURE;
  864.  
  865. #ifdef ANALYSIS
  866.   StartTime();
  867.   stat_a[0].frametype = vid_stream->picture.code_type;
  868.   stat_a[0].number = 1;
  869.   stat_a[0].totsize = 45;
  870.   pictureSizeCount = bitCountRead();
  871. #endif
  872.  
  873.   /* Parse off vbv buffer delay value. */
  874.  
  875.   get_bits16(vid_stream->picture.vbv_delay);
  876.  
  877.   /* If P or B type frame... */
  878.  
  879.   if ((vid_stream->picture.code_type == 2) || (vid_stream->picture.code_type == 3)) {
  880.  
  881.     /* Parse off forward vector full pixel flag. */
  882.     get_bits1(vid_stream->picture.full_pel_forw_vector);
  883.  
  884.     /* Parse of and decode forw_r_code into forw_r_size and forw_f. */
  885.  
  886.     get_bits3(vid_stream->picture.forw_r_size) - 1;
  887.     vid_stream->picture.forw_f = (1 << vid_stream->picture.forw_r_size);
  888.   }
  889.  
  890.   /* If B type frame... */
  891.  
  892.   if (vid_stream->picture.code_type == 3) {
  893.  
  894.     /* Parse off back vector full pixel flag. */
  895.     get_bits1(vid_stream->picture.full_pel_back_vector);
  896.  
  897.     /* Parse off and decode back_r_code into back_r_size and back_f. */
  898.  
  899.     get_bits3(vid_stream->picture.back_r_size) - 1;
  900.     vid_stream->picture.back_f = (1 << vid_stream->picture.back_r_size);
  901.   }
  902.  
  903.   /* Get extra bit picture info. */
  904.  
  905.   if (vid_stream->picture.extra_info) {
  906.     free(vid_stream->picture.extra_info);
  907.     vid_stream->picture.extra_info = NULL;
  908.   }
  909.   vid_stream->picture.extra_info = get_extra_bit_info();
  910.  
  911.   /* Goto next start code. */
  912.  
  913.   next_start_code();
  914.  
  915.   /* If start code is extension start code, parse off extension data. */
  916.  
  917.   if ((show_bits32(data)) == EXT_START_CODE) {
  918.     flush_bits32;
  919.     if (vid_stream->picture.ext_data) {
  920.       free(vid_stream->picture.ext_data);
  921.       vid_stream->picture.ext_data = NULL;
  922.     }
  923.     vid_stream->picture.ext_data = get_ext_data();
  924.     show_bits32(data);
  925.   }
  926.  
  927.   /* If start code is user start code, parse off user data. */
  928.  
  929.   if (data == USER_START_CODE) {
  930.     flush_bits32;
  931.     if (vid_stream->picture.user_data) {
  932.       free(vid_stream->picture.user_data);
  933.       vid_stream->picture.user_data = NULL;
  934.     }
  935.     vid_stream->picture.user_data = get_ext_data();
  936.   }
  937.  
  938.   /* Find a pict image structure in ring buffer not currently locked. */
  939.   i = 0;
  940.   while (vid_stream->ring[i]->locked != 0) {
  941.     if (++i >= RING_BUF_SIZE) {
  942.       perror("Fatal error. Ring buffer full.");
  943.       exit(1);
  944.     }
  945.   }
  946.  
  947.   /* Set current pict image structure to the one just found in ring. */
  948.  
  949.   vid_stream->current = vid_stream->ring[i];
  950.  
  951.   /* Set time stamp. */
  952.  
  953.   vid_stream->current->show_time = time_stamp;
  954.  
  955.   /* Reset past macroblock address field. */
  956.  
  957.   vid_stream->mblock.past_mb_addr = -1;
  958.  
  959.   return PARSE_OK;
  960. }
  961.  
  962.  
  963.  
  964. /*
  965.  *--------------------------------------------------------------
  966.  *
  967.  * ParseSlice --
  968.  *
  969.  *      Parses off slice header.
  970.  *
  971.  * Results:
  972.  *      Values found in slice header put into video stream structure.
  973.  *
  974.  * Side effects:
  975.  *      Bit stream irreversibly parsed.
  976.  *
  977.  *--------------------------------------------------------------
  978.  */
  979.  
  980. static int ParseSlice(VidStream *vid_stream)
  981. {
  982.   /* Flush slice start code. */
  983.  
  984.   flush_bits(24);
  985.  
  986.   /* Parse off slice vertical position. */
  987.  
  988.   get_bits8(vid_stream->slice.vert_pos);
  989.  
  990.   /* Parse off quantization scale. */
  991.  
  992.   get_bits5(vid_stream->slice.quant_scale);
  993.  
  994.   /* Parse off extra bit slice info. */
  995.  
  996.   if (vid_stream->slice.extra_info) {
  997.     free(vid_stream->slice.extra_info);
  998.     vid_stream->slice.extra_info = NULL;
  999.   }
  1000.   vid_stream->slice.extra_info = get_extra_bit_info();
  1001.  
  1002.   /* Reset past intrablock address. */
  1003.  
  1004.   vid_stream->mblock.past_intra_addr = -2;
  1005.  
  1006.   /* Reset previous recon motion vectors. */
  1007.  
  1008.   vid_stream->mblock.recon_right_for_prev = 0;
  1009.   vid_stream->mblock.recon_down_for_prev = 0;
  1010.   vid_stream->mblock.recon_right_back_prev = 0;
  1011.   vid_stream->mblock.recon_down_back_prev = 0;
  1012.  
  1013.   /* Reset macroblock address. */
  1014.  
  1015.   vid_stream->mblock.mb_address = ((short)(vid_stream->slice.vert_pos - 1) * (short)vid_stream->mb_width) - 1;
  1016.  
  1017.   /* Reset past dct dc y, cr, and cb values. */
  1018.  
  1019.   vid_stream->block.dct_dc_y_past = 1024;
  1020.   vid_stream->block.dct_dc_cr_past = 1024;
  1021.   vid_stream->block.dct_dc_cb_past = 1024;
  1022.  
  1023.   return PARSE_OK;
  1024. }
  1025.  
  1026.  
  1027.  
  1028. /*
  1029.  *--------------------------------------------------------------
  1030.  *
  1031.  * ParseMacroBlock --
  1032.  *
  1033.  *      Parseoff macroblock. Reconstructs DCT values. Applies
  1034.  *      inverse DCT, reconstructs motion vectors, calculates and
  1035.  *      set pixel values for macroblock in current pict image
  1036.  *      structure.
  1037.  *
  1038.  * Results:
  1039.  *      Here's where everything really happens. Welcome to the
  1040.  *      heart of darkness.
  1041.  *
  1042.  * Side effects:
  1043.  *      Bit stream irreversibly parsed off.
  1044.  *
  1045.  *--------------------------------------------------------------
  1046.  */
  1047.  
  1048. static int ParseMacroBlock(VidStream *vid_stream)
  1049. {
  1050.     int addr_incr, mask, i;
  1051.     int recon_right_for, recon_down_for, recon_right_back, recon_down_back, zero_block_flag;
  1052.     int mb_data;
  1053.  
  1054. #ifdef ANALYSIS
  1055.     mbSizeCount = bitCountRead();
  1056. #endif
  1057.  
  1058.     /*
  1059.      * Parse off macroblock address increment and add to macroblock address.
  1060.      */
  1061.     do {
  1062.         DecodeMBAddrInc(addr_incr);
  1063.         if (addr_incr == MB_ESCAPE) {
  1064.             vid_stream->mblock.mb_address += 33;
  1065.             addr_incr = MB_STUFFING;
  1066.         }
  1067.     } while (addr_incr == MB_STUFFING);
  1068.     vid_stream->mblock.mb_address += addr_incr;
  1069.  
  1070.     if (vid_stream->mblock.mb_address > ((short)vid_stream->mb_height * (short)vid_stream->mb_width - 1))
  1071.         return SKIP_TO_START_CODE;
  1072.  
  1073.     /*
  1074.      * If macroblocks have been skipped, process skipped macroblocks.
  1075.      */
  1076.  
  1077.     if (vid_stream->mblock.mb_address - vid_stream->mblock.past_mb_addr > 1) {
  1078.         if (vid_stream->picture.code_type == P_TYPE)
  1079.             ProcessSkippedPFrameMBlocks(vid_stream);
  1080.         else if (vid_stream->picture.code_type == B_TYPE)
  1081.             ProcessSkippedBFrameMBlocks(vid_stream);
  1082.     }
  1083.  
  1084.     /* Set past macroblock address to current macroblock address. */
  1085.     vid_stream->mblock.past_mb_addr = vid_stream->mblock.mb_address;
  1086.  
  1087.     /* Based on picture type decode macroblock type. */
  1088.     switch (vid_stream->picture.code_type) {
  1089.         case I_TYPE:
  1090.             DecodeMBTypeI(mb_data, vid_stream->mblock.mb_intra);
  1091.             break;
  1092.         case P_TYPE:
  1093.             DecodeMBTypeP(mb_data, vid_stream->mblock.mb_intra);
  1094.             break;
  1095.         case B_TYPE:
  1096.             DecodeMBTypeB(mb_data, vid_stream->mblock.mb_intra);
  1097.             break;
  1098.     }
  1099.  
  1100.     /* If quantization flag set, parse off new quantization scale. */
  1101.     if (mb_data&MB_quant) {
  1102.         get_bits5(vid_stream->slice.quant_scale);
  1103.     }
  1104.  
  1105.   /* If forward motion vectors exist... */
  1106.   if (mb_data&MB_motion_forw) {
  1107.  
  1108.     /* Parse off and decode horizontal forward motion vector. */
  1109.     DecodeMotionVectors(vid_stream->mblock.motion_h_forw_code);
  1110.  
  1111.     /* If horiz. forward r data exists, parse off. */
  1112.  
  1113.     if ((vid_stream->picture.forw_f != 1) && (vid_stream->mblock.motion_h_forw_code != 0)) {
  1114.       get_bitsn(vid_stream->picture.forw_r_size, vid_stream->mblock.motion_h_forw_r);
  1115.     }
  1116.     /* Parse off and decode vertical forward motion vector. */
  1117.     DecodeMotionVectors(vid_stream->mblock.motion_v_forw_code);
  1118.  
  1119.     /* If vert. forw. r data exists, parse off. */
  1120.  
  1121.     if ((vid_stream->picture.forw_f != 1) && (vid_stream->mblock.motion_v_forw_code != 0)) {
  1122.       get_bitsn(vid_stream->picture.forw_r_size, vid_stream->mblock.motion_v_forw_r);
  1123.     }
  1124.   }
  1125.   /* If back motion vectors exist... */
  1126.   if (mb_data&MB_motion_back) {
  1127.  
  1128.     /* Parse off and decode horiz. back motion vector. */
  1129.     DecodeMotionVectors(vid_stream->mblock.motion_h_back_code);
  1130.  
  1131.     /* If horiz. back r data exists, parse off. */
  1132.  
  1133.     if ((vid_stream->picture.back_f != 1) && (vid_stream->mblock.motion_h_back_code != 0)) {
  1134.       get_bitsn(vid_stream->picture.back_r_size, vid_stream->mblock.motion_h_back_r);
  1135.     }
  1136.     /* Parse off and decode vert. back motion vector. */
  1137.     DecodeMotionVectors(vid_stream->mblock.motion_v_back_code);
  1138.  
  1139.     /* If vert. back r data exists, parse off. */
  1140.  
  1141.     if ((vid_stream->picture.back_f != 1) && (vid_stream->mblock.motion_v_back_code != 0)) {
  1142.       get_bitsn(vid_stream->picture.back_r_size, vid_stream->mblock.motion_v_back_r);
  1143.     }
  1144.   }
  1145. #ifdef ANALYSIS
  1146.     if (vid_stream->mblock.mb_intra) {
  1147.         stat_a[0].i_mbnum++;
  1148.         mbCBPPtr = stat_a[0].i_mbcbp;
  1149.         mbCoeffPtr = stat_a[0].i_mbcoeff;
  1150.         mbSizePtr = &(stat_a[0].i_mbsize);
  1151.     } else if ((mb_data&(MB_motion_back | MB_motion_forw)) == (MB_motion_back | MB_motion_forw)) {
  1152.         stat_a[0].bi_mbnum++;
  1153.         mbCBPPtr = stat_a[0].bi_mbcbp;
  1154.         mbCoeffPtr = stat_a[0].bi_mbcoeff;
  1155.         mbSizePtr = &(stat_a[0].bi_mbsize);
  1156.     } else if (mb_data&MB_motion_back) {
  1157.         stat_a[0].b_mbnum++;
  1158.         mbCBPPtr = stat_a[0].b_mbcbp;
  1159.         mbCoeffPtr = stat_a[0].b_mbcoeff;
  1160.         mbSizePtr = &(stat_a[0].b_mbsize);
  1161.     } else {
  1162.         stat_a[0].p_mbnum++;
  1163.         mbCBPPtr = stat_a[0].p_mbcbp;
  1164.         mbCoeffPtr = stat_a[0].p_mbcoeff;
  1165.         mbSizePtr = &(stat_a[0].p_mbsize);
  1166.     }
  1167. #endif
  1168.  
  1169.     /* If mblock pattern flag set, parse and decode CBP (code block pattern). */
  1170.     if (mb_data&MB_pattern) {
  1171.         DecodeCBP(vid_stream->mblock.cbp);
  1172.     } else /* Otherwise, set CBP to zero. */
  1173.         vid_stream->mblock.cbp = 0;
  1174.  
  1175. #ifdef ANALYSIS
  1176.     mbCBPPtr[vid_stream->mblock.cbp]++;
  1177. #endif
  1178.  
  1179.   /* Reconstruct motion vectors depending on picture type. */
  1180.   if (vid_stream->picture.code_type == P_TYPE) {
  1181.  
  1182.     /*
  1183.      * If no forw motion vectors, reset previous and current vectors to 0.
  1184.      */
  1185.  
  1186.     if (!(mb_data&MB_motion_forw)) {
  1187.       recon_right_for = 0;
  1188.       recon_down_for = 0;
  1189.       vid_stream->mblock.recon_right_for_prev = 0;
  1190.       vid_stream->mblock.recon_down_for_prev = 0;
  1191.     }
  1192.     /*
  1193.      * Otherwise, compute new forw motion vectors. Reset previous vectors to
  1194.      * current vectors.
  1195.      */
  1196.  
  1197.     else {
  1198.       ComputeForwVector(&recon_right_for, &recon_down_for);
  1199.     }
  1200.   }
  1201.   if (vid_stream->picture.code_type == B_TYPE) {
  1202.  
  1203.     /* Reset prev. and current vectors to zero if mblock is intracoded. */
  1204.  
  1205.     if (vid_stream->mblock.mb_intra) {
  1206.       vid_stream->mblock.recon_right_for_prev = 0;
  1207.       vid_stream->mblock.recon_down_for_prev = 0;
  1208.       vid_stream->mblock.recon_right_back_prev = 0;
  1209.       vid_stream->mblock.recon_down_back_prev = 0;
  1210.     } else {
  1211.  
  1212.       /* If no forw vectors, current vectors equal prev. vectors. */
  1213.  
  1214.       if (!(mb_data&MB_motion_forw)) {
  1215.     recon_right_for = vid_stream->mblock.recon_right_for_prev;
  1216.     recon_down_for = vid_stream->mblock.recon_down_for_prev;
  1217.       }
  1218.       /*
  1219.        * Otherwise compute forw. vectors. Reset prev vectors to new values.
  1220.        */
  1221.  
  1222.       else {
  1223.         ComputeForwVector(&recon_right_for, &recon_down_for);
  1224.       }
  1225.  
  1226.       /* If no back vectors, set back vectors to prev back vectors. */
  1227.  
  1228.       if (!(mb_data&MB_motion_back)) {
  1229.     recon_right_back = vid_stream->mblock.recon_right_back_prev;
  1230.     recon_down_back = vid_stream->mblock.recon_down_back_prev;
  1231.       }
  1232.       /* Otherwise compute new vectors and reset prev. back vectors. */
  1233.  
  1234.       else {
  1235.     ComputeBackVector(&recon_right_back, &recon_down_back);
  1236.       }
  1237.  
  1238.       /*
  1239.        * Store vector existance flags in structure for possible skipped
  1240.        * macroblocks to follow.
  1241.        */
  1242.  
  1243.       if(mb_data<0)
  1244.     vid_stream->mblock.bpict_past_forw = vid_stream->mblock.bpict_past_back = -1;
  1245.       else {
  1246.     vid_stream->mblock.bpict_past_forw = mb_data&MB_motion_forw;
  1247.     vid_stream->mblock.bpict_past_back = mb_data&MB_motion_back;
  1248.       }
  1249.  
  1250.     }
  1251.   }
  1252.  
  1253.   /* For each possible block in macroblock. */
  1254.   if (ditherType == GRAY_DITHER || ditherType == CYBERGFXGRAY_DITHER) {
  1255.     for (mask = 32, i = 0; i < 4; mask >>= 1, i++) {
  1256.  
  1257.       /* If block exists... */
  1258.       if ((vid_stream->mblock.mb_intra) || (vid_stream->mblock.cbp & mask)) {
  1259.     zero_block_flag = 0;
  1260.     ParseReconBlock(i);
  1261.       } else
  1262.     zero_block_flag = 1;
  1263.  
  1264.       /* If macroblock is intra coded... */
  1265.       if (vid_stream->mblock.mb_intra) {
  1266.     ReconIMBlock(vid_stream, i);
  1267.       } else if ((mb_data&(MB_motion_forw | MB_motion_back)) == (MB_motion_forw | MB_motion_back)) {
  1268.     ReconBiMBlock(vid_stream, i, recon_right_for, recon_down_for,
  1269.               recon_right_back, recon_down_back, zero_block_flag);
  1270.       } else if ((mb_data&MB_motion_forw) || (vid_stream->picture.code_type == P_TYPE)) {
  1271.     ReconPMBlock(vid_stream, i, recon_right_for, recon_down_for,
  1272.              zero_block_flag);
  1273.       } else if (mb_data&MB_motion_back) {
  1274.     ReconBMBlock(vid_stream, i, recon_right_back, recon_down_back,
  1275.              zero_block_flag);
  1276.       }
  1277.     }
  1278.     /* Kill the Chrominace blocks... */
  1279.     if ((vid_stream->mblock.mb_intra) || (vid_stream->mblock.cbp & 0x2)) ParseAwayBlock(4);
  1280.     if ((vid_stream->mblock.mb_intra) || (vid_stream->mblock.cbp & 0x1)) ParseAwayBlock(5);
  1281.   } else {
  1282.       for (mask = 32, i = 0; i < 6; mask >>= 1, i++) {
  1283.     
  1284.     /* If block exists... */
  1285.     if ((vid_stream->mblock.mb_intra) || (vid_stream->mblock.cbp & mask)) {
  1286.       zero_block_flag = 0;
  1287.       ParseReconBlock(i);
  1288.     } else
  1289.       zero_block_flag = 1;
  1290.     
  1291.     /* If macroblock is intra coded... */
  1292.     if (vid_stream->mblock.mb_intra) {
  1293.       ReconIMBlock(vid_stream, i);
  1294.     } else if ((mb_data&(MB_motion_forw | MB_motion_back)) == (MB_motion_forw | MB_motion_back)) {
  1295.       ReconBiMBlock(vid_stream, i, recon_right_for, recon_down_for,
  1296.             recon_right_back, recon_down_back, zero_block_flag);
  1297.     } else if ((mb_data&MB_motion_forw) || (vid_stream->picture.code_type == P_TYPE)) {
  1298.       ReconPMBlock(vid_stream, i, recon_right_for, recon_down_for,
  1299.                zero_block_flag);
  1300.     } else if (mb_data&MB_motion_back) {
  1301.       ReconBMBlock(vid_stream, i, recon_right_back, recon_down_back,
  1302.                zero_block_flag);
  1303.     }
  1304.       }
  1305.   }
  1306.  
  1307.   /* If D Type picture, flush marker bit. */
  1308.   if (vid_stream->picture.code_type == 4) flush_bits(1);
  1309.  
  1310.   /* If macroblock was intracoded, set macroblock past intra address. */
  1311.   if (vid_stream->mblock.mb_intra) vid_stream->mblock.past_intra_addr = vid_stream->mblock.mb_address;
  1312.  
  1313. #ifdef ANALYSIS
  1314.   *mbSizePtr += bitCountRead() - mbSizeCount;
  1315. #endif
  1316.  
  1317.   return PARSE_OK;
  1318. }
  1319.  
  1320. #ifndef MYRECON
  1321.  
  1322. /*MR
  1323.  *--------------------------------------------------------------
  1324.  *
  1325.  * ReconIMBlock --
  1326.  *
  1327.  *    Reconstructs intra coded macroblock.
  1328.  *
  1329.  * Results:
  1330.  *    None.
  1331.  *
  1332.  * Side effects:
  1333.  *    None.
  1334.  *
  1335.  *--------------------------------------------------------------
  1336.  */
  1337.  
  1338. static void ReconIMBlock(VidStream *vid_stream, int bnum)
  1339. {
  1340.   int row, col, row_size;
  1341.   unsigned char *dest;
  1342.  
  1343.   row_size = vid_stream->mb_width;
  1344.   /* Calculate macroblock row and column from address. */
  1345.   row = vid_stream->mblock.mb_address / row_size;
  1346.   col = vid_stream->mblock.mb_address % row_size;
  1347.  
  1348.   /* If block is luminance block... */
  1349.  
  1350.   if (bnum < 4) {
  1351.  
  1352.     /* Calculate row and col values for upper left pixel of block. */
  1353.     row <<= 4;
  1354.     col <<= 4;
  1355.     if (bnum > 1) row += 8;
  1356.     if (bnum & 1) col += 8;
  1357.  
  1358.     /* Set dest to luminance plane of current pict image. */
  1359.     dest = vid_stream->current->luminance;
  1360.  
  1361.     /* Establish row size. */
  1362.     row_size *= 16;
  1363.   }
  1364.   /* Otherwise if block is Cr block... */
  1365.  
  1366.   else if (bnum == 4) {
  1367.  
  1368.     /* Set dest to Cr plane of current pict image. */
  1369.     dest = vid_stream->current->Cr;
  1370.  
  1371.     /* Establish row size. */
  1372.     row_size <<= 3;
  1373.  
  1374.     /* Calculate row,col for upper left pixel of block. */
  1375.     row <<= 3;
  1376.     col <<= 3;
  1377.   }
  1378.   /* Otherwise block is Cb block, and ... */
  1379.  
  1380.   else {
  1381.  
  1382.     /* Set dest to Cb plane of current pict image. */
  1383.     dest = vid_stream->current->Cb;
  1384.  
  1385.     /* Establish row size. */
  1386.     row_size <<= 3;
  1387.  
  1388.     /* Calculate row,col for upper left pixel value of block. */
  1389.     row <<= 3;
  1390.     col <<= 3;
  1391.   }
  1392.  
  1393.   /*
  1394.    * For each pixel in block, set to cropped reconstructed value from inverse dct.
  1395.    */
  1396.   IM_reconstruct(dest + row * row_size + col, &vid_stream->block.dct_recon[0][0], row_size);
  1397. }
  1398.  
  1399.  
  1400. /* MR
  1401.  *--------------------------------------------------------------
  1402.  *
  1403.  * ReconPMBlock --
  1404.  *
  1405.  *    Reconstructs forward predicted macroblocks.
  1406.  *
  1407.  * Results:
  1408.  *      None.
  1409.  *
  1410.  * Side effects:
  1411.  *      None.
  1412.  *
  1413.  *--------------------------------------------------------------
  1414.  */
  1415. static void ReconPMBlock(VidStream *vid_stream, int bnum, int recon_right_for, int recon_down_for, int zflag)
  1416. {
  1417.   int row, col, row_size;
  1418.   unsigned char *dest, *past, *rindex2;
  1419.   int right_half_for, down_half_for;
  1420.  
  1421.   row_size = vid_stream->mb_width;
  1422.   /* Calculate macroblock row and column from address. */
  1423.   row = vid_stream->mblock.mb_address / row_size;
  1424.   col = vid_stream->mblock.mb_address % row_size;
  1425.  
  1426.   if (bnum < 4) {
  1427.     /* Calculate right_for, down_for motion vectors. */
  1428.  
  1429.     right_half_for = recon_right_for & 0x1;
  1430.     down_half_for = recon_down_for & 0x1;
  1431.     recon_right_for >>= 1;
  1432.     recon_down_for >>= 1;
  1433.  
  1434.     /* Set dest to luminance plane of current pict image. */
  1435.     dest = vid_stream->current->luminance;
  1436.  
  1437.     if (vid_stream->picture.code_type == B_TYPE) {
  1438.       if (vid_stream->past) past = vid_stream->past->luminance;
  1439.     } else {
  1440.       /* Set predicitive frame to current future frame. */
  1441.       if (vid_stream->future) past = vid_stream->future->luminance;
  1442.     }
  1443.  
  1444.     /* Establish row size. */
  1445.     row_size <<= 4;
  1446.  
  1447.     /* Calculate row,col of upper left pixel in block. */
  1448.     row <<= 4;
  1449.     col <<= 4;
  1450.     if (bnum > 1) row += 8;
  1451.     if (bnum & 1) col += 8;
  1452.  
  1453.   }
  1454.   /* Otherwise, block is NOT luminance block, ... */
  1455.   else {
  1456.     /* Construct motion vectors. */
  1457.     right_half_for = (recon_right_for & 0x2)>>1;
  1458.     down_half_for = recon_down_for & 0x2;
  1459.     recon_right_for >>= 2;
  1460.     recon_down_for >>= 2;
  1461.  
  1462.     /* Establish row size. */
  1463.     row_size <<= 3;
  1464.  
  1465.     /* Calculate row,col of upper left pixel in block. */
  1466.     row <<= 3;
  1467.     col <<= 3;
  1468.  
  1469.     /* If block is Cr block... */
  1470.  
  1471.     if (bnum == 4) {
  1472.       /* Set dest to Cr plane of current pict image. */
  1473.       dest = vid_stream->current->Cr;
  1474.  
  1475.       if (vid_stream->picture.code_type == B_TYPE) {
  1476.     if (vid_stream->past) past = vid_stream->past->Cr;
  1477.       } else {
  1478.     if (vid_stream->future) past = vid_stream->future->Cr;
  1479.       }
  1480.     }
  1481.     /* Otherwise, block is Cb block... */
  1482.     else {
  1483.       /* Set dest to Cb plane of current pict image. */
  1484.       dest = vid_stream->current->Cb;
  1485.  
  1486.       if (vid_stream->picture.code_type == B_TYPE) {
  1487.     if (vid_stream->past) past = vid_stream->past->Cb;
  1488.       } else {
  1489.     if (vid_stream->future) past = vid_stream->future->Cb;
  1490.       }
  1491.     }
  1492.   }
  1493.  
  1494.   /* For each pixel in block... */
  1495.     dest += ((short)row * (short)row_size) + col;
  1496.     past += (short)(row + recon_down_for) * (short)row_size + col + recon_right_for;
  1497.  
  1498.     /*
  1499.      * Calculate predictive pixel value based on motion vectors and copy to
  1500.      * dest plane.
  1501.      */
  1502.  
  1503.     if ((!down_half_for) && (!right_half_for)) {
  1504.       if (!zflag)
  1505.     BMcm_reconstruct(dest, past, &(vid_stream->block.dct_recon[0][0]), row_size);
  1506.       else
  1507.     BM_reconstruct(dest, past, row_size);
  1508.     } else {
  1509.       rindex2 = past + right_half_for + (down_half_for?row_size:0);
  1510.       if (!zflag)
  1511.     BIMcm_reconstruct(dest, past, rindex2, &(vid_stream->block.dct_recon[0][0]), row_size);
  1512.       else
  1513.     BIM_reconstruct(dest, past, rindex2, row_size);
  1514.     }
  1515.  
  1516. }
  1517.  
  1518.  
  1519. /* MR
  1520.  *--------------------------------------------------------------
  1521.  *
  1522.  * ReconBMBlock --
  1523.  *
  1524.  *    Reconstructs back predicted macroblocks.
  1525.  *
  1526.  * Results:
  1527.  *      None.
  1528.  *
  1529.  * Side effects:
  1530.  *      None.
  1531.  *
  1532.  *--------------------------------------------------------------
  1533.  */
  1534.  
  1535. static void ReconBMBlock(VidStream *vid_stream, int bnum, int recon_right_back, int recon_down_back, int zflag)
  1536. {
  1537.   int row, col, row_size;
  1538.   unsigned char *dest, *future, *rindex2;
  1539.   int right_half_back, down_half_back;
  1540.  
  1541.   row_size = vid_stream->mb_width;
  1542.   /* Calculate macroblock row and column from address. */
  1543.   row = vid_stream->mblock.mb_address / row_size;
  1544.   col = vid_stream->mblock.mb_address % row_size;
  1545.  
  1546.   /* If block is luminance block... */
  1547.  
  1548.   if (bnum < 4) {
  1549.     /* Calculate right_back, down_back motion vectors. */
  1550.     right_half_back = recon_right_back & 0x1;
  1551.     down_half_back = recon_down_back & 0x1;
  1552.     recon_right_back >>= 1;
  1553.     recon_down_back >>= 1;
  1554.  
  1555.     /* Set dest to luminance plane of current pict image. */
  1556.     dest = vid_stream->current->luminance;
  1557.  
  1558.     /* If future frame exists, set future to luminance plane of future frame. */
  1559.     if (vid_stream->future) future = vid_stream->future->luminance;
  1560.  
  1561.     /* Establish row size. */
  1562.     row_size <<= 4;
  1563.  
  1564.     /* Calculate row,col of upper left pixel in block. */
  1565.     row <<= 4;
  1566.     col <<= 4;
  1567.     if (bnum > 1) row += 8;
  1568.     if (bnum & 1) col += 8;
  1569.  
  1570.   }
  1571.   /* Otherwise, block is NOT luminance block, ... */
  1572.   else {
  1573.     /* Construct motion vectors. */
  1574.     right_half_back = (recon_right_back & 0x2)>>1;    /* used as integer down there */
  1575.     down_half_back = recon_down_back & 0x2;
  1576.     recon_right_back >>= 2;
  1577.     recon_down_back >>= 2;
  1578.  
  1579.     /* Establish row size. */
  1580.     row_size <<= 3;
  1581.  
  1582.     /* Calculate row,col of upper left pixel in block. */
  1583.     row <<= 3;
  1584.     col <<= 3;
  1585.  
  1586.     /* If block is Cr block... */
  1587.  
  1588.     if (bnum == 4) {
  1589.       /* Set dest to Cr plane of current pict image. */
  1590.       dest = vid_stream->current->Cr;
  1591.  
  1592.       /* If future frame exists, set future to Cr plane of future image. */
  1593.       if (vid_stream->future) future = vid_stream->future->Cr;
  1594.     }
  1595.     /* Otherwise, block is Cb block... */
  1596.     else {
  1597.       /* Set dest to Cb plane of current pict image. */
  1598.       dest = vid_stream->current->Cb;
  1599.  
  1600.       /* If future frame exists, set future to Cb plane of future frame. */
  1601.       if (vid_stream->future) future = vid_stream->future->Cb;
  1602.     }
  1603.   }
  1604.  
  1605.   /* For each pixel in block do... */
  1606.     dest += ((short)row * (short)row_size) + col;
  1607.     future += (short)(row + recon_down_back) * (short)row_size + col + recon_right_back;
  1608.  
  1609.     if ((!right_half_back) && (!down_half_back)) {
  1610.       if (!zflag)
  1611.     BMcm_reconstruct(dest, future, &(vid_stream->block.dct_recon[0][0]), row_size);
  1612.       else
  1613.     BM_reconstruct(dest, future, row_size);
  1614.     } else {
  1615.       rindex2 = future + right_half_back + (down_half_back?row_size:0);
  1616.       if (!zflag)
  1617.     BIMcm_reconstruct(dest, future, rindex2, &(vid_stream->block.dct_recon[0][0]), row_size);
  1618.       else
  1619.     BIM_reconstruct(dest, future, rindex2, row_size);
  1620.     }
  1621. }
  1622.  
  1623.  
  1624. /* MR
  1625.  *--------------------------------------------------------------
  1626.  *
  1627.  * ReconBiMBlock --
  1628.  *
  1629.  *    Reconstructs bidirectionally predicted macroblocks.
  1630.  *
  1631.  * Results:
  1632.  *      None.
  1633.  *
  1634.  * Side effects:
  1635.  *      None.
  1636.  *
  1637.  *--------------------------------------------------------------
  1638.  */
  1639.  
  1640. static void ReconBiMBlock(VidStream *vid_stream, int bnum,
  1641.               int forw_col_start, int forw_row_start,
  1642.               int back_col_start, int back_row_start,
  1643.               int zflag)
  1644. {
  1645.   int row, col, row_size;
  1646.   unsigned char *dest, *past, *future;
  1647.  
  1648.   row_size = vid_stream->mb_width;
  1649.   /* Calculate macroblock row and column from address. */
  1650.   row = vid_stream->mblock.mb_address / row_size;
  1651.   col = vid_stream->mblock.mb_address % row_size;
  1652.  
  1653.   /* If block is luminance block... */
  1654.  
  1655.   if (bnum < 4) {
  1656.     /* Set dest to luminance plane of current pict image. */
  1657.     dest = vid_stream->current->luminance;
  1658.  
  1659.     /* If past frame exists, set past to luminance plane of past frame. */
  1660.     if (vid_stream->past) past = vid_stream->past->luminance;
  1661.  
  1662.     /*If future frame exists, set future to luminance plane of future frame. */
  1663.     if (vid_stream->future) future = vid_stream->future->luminance;
  1664.  
  1665.     /* Establish row size. */
  1666.     row_size <<= 4;
  1667.  
  1668.     /* Calculate row,col of upper left pixel in block. */
  1669.     row <<= 4;
  1670.     col <<= 4;
  1671.     if (bnum > 1) row += 8;
  1672.     if (bnum & 1) col += 8;
  1673.  
  1674.     forw_col_start = (forw_col_start>>1) + col;
  1675.     forw_row_start = (forw_row_start>>1) + row;
  1676.     back_col_start = (back_col_start>>1) + col;
  1677.     back_row_start = (back_row_start>>1) + row;
  1678.  
  1679.   }
  1680.   /* Otherwise, block is NOT luminance block, ... */
  1681.  
  1682.   else {
  1683.     /* Establish row size. */
  1684.     row_size <<= 3;
  1685.  
  1686.     /* Calculate row,col of upper left pixel in block. */
  1687.     row <<= 3;
  1688.     col <<= 3;
  1689.  
  1690.     forw_col_start = (forw_col_start>>2) + col;
  1691.     forw_row_start = (forw_row_start>>2) + row;
  1692.     back_col_start = (back_col_start>>2) + col;
  1693.     back_row_start = (back_row_start>>2) + row;
  1694.  
  1695.     /* If block is Cr block... */
  1696.  
  1697.     if (bnum == 4) {
  1698.       /* Set dest to Cr plane of current pict image. */
  1699.       dest = vid_stream->current->Cr;
  1700.  
  1701.       /* If past frame exists, set past to Cr plane of past image. */
  1702.       if (vid_stream->past) past = vid_stream->past->Cr;
  1703.  
  1704.       /* If future frame exists, set future to Cr plane of future image. */
  1705.       if (vid_stream->future) future = vid_stream->future->Cr;
  1706.     }
  1707.     /* Otherwise, block is Cb block... */
  1708.  
  1709.     else {
  1710.       /* Set dest to Cb plane of current pict image. */
  1711.       dest = vid_stream->current->Cb;
  1712.  
  1713.       /* If past frame exists, set past to Cb plane of past frame. */
  1714.       if (vid_stream->past) past = vid_stream->past->Cb;
  1715.  
  1716.       /* If future frame exists, set future to Cb plane of future frame. */
  1717.       if (vid_stream->future) future = vid_stream->future->Cb;
  1718.     }
  1719.   }
  1720.  
  1721.   dest += (short)row * (short)row_size + col;
  1722.   past += (short)forw_row_start  * (short)row_size + forw_col_start;
  1723.   future += (short)back_row_start * (short)row_size + back_col_start;
  1724.  
  1725.   if (!zflag)
  1726.     BIMcm_reconstruct(dest, past, future, &(vid_stream->block.dct_recon[0][0]), row_size);
  1727.   else
  1728.     BIM_reconstruct(dest, past, future, row_size);
  1729. }
  1730. #endif
  1731.  
  1732.  
  1733. /* MR
  1734.  *--------------------------------------------------------------
  1735.  *
  1736.  * ProcessSkippedPFrameMBlocks --
  1737.  *
  1738.  *    Processes skipped macroblocks in P frames.
  1739.  *
  1740.  * Results:
  1741.  *    Calculates pixel values for luminance, Cr, and Cb planes
  1742.  *      in current pict image for skipped macroblocks.
  1743.  *
  1744.  * Side effects:
  1745.  *    Pixel values in pict image changed.
  1746.  *
  1747.  *--------------------------------------------------------------
  1748.  */
  1749.  
  1750. static void ProcessSkippedPFrameMBlocks(VidStream *vid_stream)
  1751. {
  1752.   int row_size, row, col, addr, off;
  1753.  
  1754.   /* Calculate row sizes for luminance and Cr/Cb macroblock areas. */
  1755.  
  1756.   row_size = vid_stream->mb_width << 4;
  1757.  
  1758.   /* For each skipped macroblock, do... */
  1759.  
  1760.   addr = vid_stream->mblock.past_mb_addr + 1;
  1761.   row = (addr / vid_stream->mb_width)<<4;
  1762.   col = (addr % vid_stream->mb_width)<<4;
  1763.  
  1764.   for (; addr < vid_stream->mblock.mb_address; addr++, col+=16) {
  1765.  
  1766.     /* Calculate macroblock row and col. */
  1767.     if(col>=row_size) col=0, row+=16;
  1768.  
  1769.     /* For each row in macroblock luminance plane... */
  1770.  
  1771.     off = ((short)row * (short)row_size);
  1772.     PMB1_reconstruct(vid_stream->current->luminance + off + col,
  1773.              vid_stream->future->luminance + off + col,
  1774.              row_size >> 2);
  1775.  
  1776.     /* For each row in Cr, and Cb planes... */
  1777.  
  1778.     off >>= 2;
  1779.     off += (col>>1);
  1780.     PMB2_reconstruct(vid_stream->current->Cr + off,
  1781.              vid_stream->current->Cb + off,
  1782.              vid_stream->future->Cr + off,
  1783.              vid_stream->future->Cb + off,
  1784.              row_size >> 3);
  1785.   }
  1786.  
  1787.   vid_stream->mblock.recon_right_for_prev = 0;
  1788.   vid_stream->mblock.recon_down_for_prev = 0;
  1789. }
  1790.  
  1791.  
  1792.  
  1793.  
  1794. /* MR
  1795.  *--------------------------------------------------------------
  1796.  *
  1797.  * ProcessSkippedBFrameMBlocks --
  1798.  *
  1799.  *    Processes skipped macroblocks in B frames.
  1800.  *
  1801.  * Results:
  1802.  *    Calculates pixel values for luminance, Cr, and Cb planes
  1803.  *      in current pict image for skipped macroblocks.
  1804.  *
  1805.  * Side effects:
  1806.  *    Pixel values in pict image changed.
  1807.  *
  1808.  *--------------------------------------------------------------
  1809.  */
  1810.  
  1811. static void ProcessSkippedBFrameMBlocks(VidStream *vid_stream)
  1812. {
  1813.   int row_size, half_row, row, col, ccol, crow;
  1814.   int right_half_for, down_half_for, c_right_half_for, c_down_half_for;
  1815.   int right_half_back, down_half_back, c_right_half_back, c_down_half_back;
  1816.   int addr;
  1817.   int recon_right_for, recon_down_for, recon_right_back, recon_down_back;
  1818.   int c_right_for, c_down_for, c_right_back, c_down_back;
  1819.   unsigned char forw_lum[256];
  1820.   unsigned char forw_cr[64], forw_cb[64];
  1821.   unsigned char back_lum[256], back_cr[64], back_cb[64];
  1822.   int row_incr, half_row_incr;
  1823.   int h;
  1824.   char *lum;
  1825.  
  1826.   /* Calculate row sizes for luminance and Cr/Cb macroblock areas. */
  1827.  
  1828.   row_size = vid_stream->mb_width << 4;
  1829.   half_row = row_size >> 1;
  1830.   row_incr = row_size >> 2;
  1831.   half_row_incr =  half_row >> 2;
  1832.  
  1833.   /* Establish motion vector codes based on full pixel flag. */
  1834.  
  1835.   recon_right_for = vid_stream->mblock.recon_right_for_prev;
  1836.   recon_down_for = vid_stream->mblock.recon_down_for_prev;
  1837.   if (vid_stream->picture.full_pel_forw_vector) {
  1838.     recon_right_for <<= 1;
  1839.     recon_down_for <<= 1;
  1840.   }
  1841.  
  1842.   recon_right_back = vid_stream->mblock.recon_right_back_prev;
  1843.   recon_down_back = vid_stream->mblock.recon_down_back_prev;
  1844.   if (vid_stream->picture.full_pel_back_vector) {
  1845.     recon_right_back <<= 1;
  1846.     recon_down_back <<= 1;
  1847.   }
  1848.  
  1849.  
  1850.   /* If only one motion vector, do display copy, else do full
  1851.      calculation. 
  1852.   */
  1853.   /* Calculate motion vectors. */
  1854.   
  1855.   if (vid_stream->mblock.bpict_past_forw) {
  1856.     right_half_for = recon_right_for & 0x1;
  1857.     down_half_for = recon_down_for & 0x1;
  1858.     recon_right_for >>= 1;
  1859.     recon_down_for >>= 1;
  1860.     c_right_for = recon_right_for >> 1;
  1861.     c_down_for = recon_down_for >> 1;
  1862.     c_right_half_for = recon_right_for & 0x1;
  1863.     c_down_half_for = recon_down_for & 0x1;
  1864.     
  1865.   }
  1866.   if (vid_stream->mblock.bpict_past_back) {
  1867.     right_half_back = recon_right_back & 0x1;
  1868.     down_half_back = recon_down_back & 0x1;    
  1869.     recon_right_back >>= 1;
  1870.     recon_down_back >>= 1;
  1871.     c_right_back = recon_right_back >> 1;
  1872.     c_down_back = recon_down_back >> 1;
  1873.     c_right_half_back = recon_right_back & 0x1;
  1874.     c_down_half_back = recon_down_back & 0x1;
  1875.     
  1876.   }
  1877.   /* For each skipped macroblock, do... */
  1878.   addr = vid_stream->mblock.past_mb_addr + 1;
  1879.   row = (addr / vid_stream->mb_width)<<4;
  1880.   col = (addr % vid_stream->mb_width)<<4;
  1881.  
  1882.   for (; addr < vid_stream->mblock.mb_address; addr++, col+=16) {
  1883.     
  1884.     /* Calculate macroblock row and col. */
  1885.     if(col>=row_size) col=0, row+=16;
  1886.  
  1887.     /* Calculate upper left pixel row,col for luminance plane. */
  1888.     crow = row >> 1;
  1889.     ccol = col >> 1;
  1890.     
  1891.     /* If forward predicted, calculate prediction values. */
  1892.     
  1893.     if (vid_stream->mblock.bpict_past_forw) {
  1894.       
  1895.       ReconSkippedBlock16(vid_stream->past->luminance, forw_lum,
  1896.               row, col, row_size, recon_right_for, recon_down_for,
  1897.               right_half_for, down_half_for);
  1898.       ReconSkippedBlock8(vid_stream->past->Cr, forw_cr, crow, ccol, half_row,
  1899.              c_right_for, c_down_for, c_right_half_for, c_down_half_for);
  1900.       ReconSkippedBlock8(vid_stream->past->Cb, forw_cb, crow, ccol, half_row,
  1901.              c_right_for, c_down_for, c_right_half_for, c_down_half_for);
  1902.     }
  1903.     /* If back predicted, calculate prediction values. */
  1904.     
  1905.     if (vid_stream->mblock.bpict_past_back) {
  1906.       ReconSkippedBlock16(vid_stream->future->luminance, back_lum,
  1907.               row, col, row_size, recon_right_back, recon_down_back,
  1908.               right_half_back, down_half_back);
  1909.       ReconSkippedBlock8(vid_stream->future->Cr, back_cr, crow, ccol, half_row,
  1910.              c_right_back, c_down_back,
  1911.              c_right_half_back, c_down_half_back);
  1912.       ReconSkippedBlock8(vid_stream->future->Cb, back_cb, crow, ccol, half_row,
  1913.              c_right_back, c_down_back,
  1914.              c_right_half_back, c_down_half_back);
  1915.     }
  1916.  
  1917.     h = ((short)crow * (short)half_row) + ccol;
  1918.     lum = (vid_stream->current->luminance + ((short)row * (short)row_size) + col);
  1919.  
  1920.     if (vid_stream->mblock.bpict_past_forw && !vid_stream->mblock.bpict_past_back) {
  1921.  
  1922.       PSB1_reconstruct(lum, forw_lum, row_incr);
  1923.  
  1924.       PSB2_reconstruct(vid_stream->current->Cr + h, vid_stream->current->Cb + h,
  1925.                forw_cr, forw_cb, half_row_incr);
  1926.  
  1927.     } else if (vid_stream->mblock.bpict_past_back && !vid_stream->mblock.bpict_past_forw) {
  1928.  
  1929.       PSB1_reconstruct(lum, back_lum, row_incr);
  1930.  
  1931.       PSB2_reconstruct(vid_stream->current->Cr + h, vid_stream->current->Cb + h,
  1932.                back_cr, back_cb, half_row_incr);
  1933.     } else {
  1934.       PSB3_reconstruct(lum, forw_lum, back_lum, row_size);
  1935.  
  1936.       PSB4_reconstruct(vid_stream->current->Cr + h, vid_stream->current->Cb + h,
  1937.                forw_cr, back_cr, forw_cb, back_cb, half_row);
  1938.     }    
  1939.   }
  1940. }
  1941.  
  1942.  
  1943.  
  1944. /* MR
  1945.  *--------------------------------------------------------------
  1946.  *
  1947.  * ReconSkippedBlock -- width 16
  1948.  *
  1949.  *    Reconstructs predictive block for skipped macroblocks
  1950.  *      in B Frames.
  1951.  *
  1952.  * Results:
  1953.  *    No return values.
  1954.  *
  1955.  * Side effects:
  1956.  *    None.
  1957.  *
  1958.  *--------------------------------------------------------------
  1959.  */
  1960.  
  1961. static
  1962. void ReconSkippedBlock16(unsigned char *source, unsigned char *dest, int row, int col, int row_size,
  1963.              int right, int down, int right_half, int down_half)
  1964. {
  1965.   source += ((short)(row + down) * (short)row_size) + col + right;
  1966.  
  1967.   if ((!right_half) && (!down_half))
  1968.     RSB1_reconstruct(dest, source, row_size);
  1969.   else 
  1970.     RSB2_reconstruct(dest, source, source + right_half + ((short)row_size * (short)down_half), row_size);
  1971. }
  1972.  
  1973. /* MR
  1974.  *--------------------------------------------------------------
  1975.  *
  1976.  * ReconSkippedBlock -- width 8
  1977.  *
  1978.  *    Reconstructs predictive block for skipped macroblocks
  1979.  *      in B Frames.
  1980.  *
  1981.  * Results:
  1982.  *    No return values.
  1983.  *
  1984.  * Side effects:
  1985.  *    None.
  1986.  *
  1987.  *--------------------------------------------------------------
  1988.  */
  1989.  
  1990. static
  1991. void ReconSkippedBlock8(unsigned char *source, unsigned char *dest, int row, int col, int row_size,
  1992.             int right, int down, int right_half, int down_half)
  1993. {
  1994.   source += ((short)(row + down) * (short)row_size) + col + right;
  1995.  
  1996.   if ((!right_half) && (!down_half))
  1997.     RSB3_reconstruct(dest, source, row_size);
  1998.   else 
  1999.     RSB4_reconstruct(dest, source, source + right_half + ((short)row_size * (short)down_half), row_size);
  2000. }
  2001.  
  2002.  
  2003. /*
  2004.  *--------------------------------------------------------------
  2005.  *
  2006.  * DoPictureDisplay --
  2007.  *
  2008.  *    Converts image from Lum, Cr, Cb to colormap space. Puts
  2009.  *      image in lum plane. Updates past and future frame
  2010.  *      pointers. Dithers image. Sends to display mechanism.
  2011.  *
  2012.  * Results:
  2013.  *    Pict image structure locked if displaying or if frame
  2014.  *      is needed as past or future reference.
  2015.  *
  2016.  * Side effects:
  2017.  *    Lum plane pummelled.
  2018.  *
  2019.  *--------------------------------------------------------------
  2020.  */
  2021.  
  2022. static void DoPictureDisplay(VidStream *vid_stream)
  2023. {
  2024.  
  2025.   /* init display, if needed */
  2026.  
  2027.  
  2028.   if(!vid_stream->display_is_initialized)
  2029.   {
  2030.     ResizeDisplay(vid_stream->h_size, vid_stream->v_size);
  2031.     vid_stream->display_is_initialized = TRUE;
  2032.   }
  2033.   /* Convert to colormap space and dither. */
  2034.  
  2035.     if(ditherType == CYBERGFXGRAY_DITHER)
  2036.         vid_stream->current->display = vid_stream->current->luminance;
  2037.     else
  2038.       DoDitherImage(vid_stream->current->luminance, vid_stream->current->Cr,
  2039.         vid_stream->current->Cb, vid_stream->current->display,
  2040.         vid_stream->mb_height <<4, vid_stream->mb_width <<4);
  2041.  
  2042.   /* Update past and future references if needed. */
  2043.  
  2044.   if ((vid_stream->picture.code_type == I_TYPE) || (vid_stream->picture.code_type == P_TYPE)) {
  2045.     if (vid_stream->future == NULL) {
  2046.       vid_stream->future = vid_stream->current;
  2047.       vid_stream->future->locked |= FUTURE_LOCK;
  2048.     } else {
  2049.       if (vid_stream->past != NULL) {
  2050.     vid_stream->past->locked &= ~PAST_LOCK;
  2051.       }
  2052.       vid_stream->past = vid_stream->future;
  2053.       vid_stream->past->locked &= ~FUTURE_LOCK;
  2054.       vid_stream->past->locked |= PAST_LOCK;
  2055.       vid_stream->future = vid_stream->current;
  2056.       vid_stream->future->locked |= FUTURE_LOCK;
  2057.       vid_stream->current = vid_stream->past;
  2058.       ExecuteDisplay(vid_stream);
  2059.     }
  2060.   } else
  2061.     ExecuteDisplay(vid_stream);
  2062.  
  2063. }
  2064.  
  2065.  
  2066.  
  2067. /*
  2068.  *--------------------------------------------------------------
  2069.  *
  2070.  * ToggleBFlag --
  2071.  *
  2072.  *    Called to set no b frame processing flag.
  2073.  *
  2074.  * Results:
  2075.  *      No_B_Flag flag is toggled from present value to opposite value.
  2076.  *
  2077.  * Side effects:
  2078.  *      None.
  2079.  *
  2080.  *--------------------------------------------------------------
  2081.  */
  2082.  
  2083. void ToggleBFlag(void)
  2084. {
  2085.   No_B_Flag ^= 0xffff;
  2086. }
  2087.  
  2088.  
  2089. /*
  2090.  *--------------------------------------------------------------
  2091.  *
  2092.  * TogglePFlag --
  2093.  *
  2094.  *    Called to set no p frame processing flag.
  2095.  *
  2096.  * Results:
  2097.  *      No_P_Flag flag is toggled from present value to opposite value.
  2098.  *
  2099.  * Side effects:
  2100.  *      None.
  2101.  *
  2102.  *--------------------------------------------------------------
  2103.  */
  2104.  
  2105. void TogglePFlag(void)
  2106. {
  2107.   No_P_Flag ^= 0xffff;
  2108. }
  2109.