home *** CD-ROM | disk | FTP | other *** search
/ Amiga MA Magazine 1998 #6 / amigamamagazinepolishissue1998.iso / opus / v5 / amipeg / source / video.c < prev    next >
C/C++ Source or Header  |  1977-12-31  |  58KB  |  2,188 lines

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