home *** CD-ROM | disk | FTP | other *** search
/ Enigma Amiga Life 106 / EnigmaAmiga106CD.iso / indispensabili / grafica / amipeg_1.1 / src / video.c < prev    next >
C/C++ Source or Header  |  1997-12-06  |  60KB  |  2,234 lines

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