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