Recongob.c
上传用户:zhongxx05
上传日期:2007-06-06
资源大小:33641k
文件大小:48k
源码类别:

Symbian

开发平台:

C/C++

  1. /* ***** BEGIN LICENSE BLOCK ***** 
  2.  * Version: RCSL 1.0/RPSL 1.0 
  3.  *  
  4.  * Portions Copyright (c) 1995-2002 RealNetworks, Inc. All Rights Reserved. 
  5.  *      
  6.  * The contents of this file, and the files included with this file, are 
  7.  * subject to the current version of the RealNetworks Public Source License 
  8.  * Version 1.0 (the "RPSL") available at 
  9.  * http://www.helixcommunity.org/content/rpsl unless you have licensed 
  10.  * the file under the RealNetworks Community Source License Version 1.0 
  11.  * (the "RCSL") available at http://www.helixcommunity.org/content/rcsl, 
  12.  * in which case the RCSL will apply. You may also obtain the license terms 
  13.  * directly from RealNetworks.  You may not use this file except in 
  14.  * compliance with the RPSL or, if you have a valid RCSL with RealNetworks 
  15.  * applicable to this file, the RCSL.  Please see the applicable RPSL or 
  16.  * RCSL for the rights, obligations and limitations governing use of the 
  17.  * contents of the file.  
  18.  *  
  19.  * This file is part of the Helix DNA Technology. RealNetworks is the 
  20.  * developer of the Original Code and owns the copyrights in the portions 
  21.  * it created. 
  22.  *  
  23.  * This file, and the files included with this file, is distributed and made 
  24.  * available on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER 
  25.  * EXPRESS OR IMPLIED, AND REALNETWORKS HEREBY DISCLAIMS ALL SUCH WARRANTIES, 
  26.  * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, FITNESS 
  27.  * FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. 
  28.  * 
  29.  * Technology Compatibility Kit Test Suite(s) Location: 
  30.  *    http://www.helixcommunity.org/content/tck 
  31.  * 
  32.  * Contributor(s): 
  33.  *  
  34.  * ***** END LICENSE BLOCK ***** */ 
  35. #include "hxtypes.h"
  36. #ifdef _MACINTOSH
  37. #include <string.h> // for memset
  38. #endif
  39. //#include <string.h>
  40. //#include <stdio.h>
  41. #include <stdlib.h>
  42. #include "dllindex.h"
  43. #include "h261defs.h"
  44. #include "h261func.h"
  45. #include "h263plus.h"
  46. extern S16 Recon [QUANT_MAX - QUANT_MIN + 1] [N_SYM_INDICES];
  47. //#define DISPLAY_DIFFERENCE  // Display quantized pred. error (don't use prev. frame)
  48. #ifdef TESTING
  49. #define CHECKSYM(a)     a   // Check symbol types to verify decoder state tables
  50. #else
  51. #define CHECKSYM(a)         // Don't check symbol types
  52. #endif
  53. #define GRAY    (128)
  54. #ifdef DO_H263_PLUS
  55. extern void PredBframePlus( MACROBLOCK_DESCR * mb,  // Macroblock to be predicted
  56.                         PICTURE * prevPic,      // Prev. picture (forward pred)
  57.                         PICTURE * nextPic,      // Next P-picture (backward pred)
  58.                         PICTURE * Bpic          // Output picture where pred is placed
  59.                         );
  60. #endif
  61. // Declarations of local functions
  62. static void reconBframe( MACROBLOCK_DESCR * mb, PICTURE * Bpic );
  63. static void gray_mb( MACROBLOCK_DESCR * mb, PICTURE * pic );
  64. static void fill_mb( MACROBLOCK_DESCR * mb, PICTURE * pic, PIXEL value );
  65. #ifdef DO_H263_PLUS
  66. static void idct32x32( MACROBLOCK_DESCR * mb,   // Macroblock to be reconstructed
  67.                        PICTURE * tempPic,       // Store 16-bit IDCT values here
  68.                        int intra                // INTER block if zero, otherwise INTRA
  69.                        );
  70. static void filtAddClip32x32( MACROBLOCK_DESCR * mb,// Macroblock to be reconstructed
  71.                               PICTURE * pic,    // Input: motion-comp prediction w/ filtered
  72.                                                 // intra borders; output: reconstr. picture
  73.                               PICTURE * tempPic // 16-bit IDCT values
  74.                               );
  75. static void filtAddClip( PIXEL x[], int xdim,       // Output pixels
  76.                          S16 idct_out[], int idim,  // Input IDCT values
  77.                          int hSize, int vSize       // Input block size for IDCT values
  78.                         );
  79. #endif
  80. // ReconGob - Reconstruct one GOB of a picture
  81. // state->i > 0 indicates that we are reentering after previous timeout
  82. extern int ReconGob( GOB_DESCR * gob, MACROBLOCK_DESCR mb[],
  83.                      PICTURE * prev_pic, PICTURE * pic, PICTURE * Bpic, 
  84.                      int advancedPred, int PBframe, int PBframeCap, int reducedResUpdate,
  85.                      int advancedIntraMode, H261DecState *state, int maxComp )
  86. #define CLEAN NO
  87. {
  88.     int mbnum, i, col, dummy[4], reconBflag;
  89.     int intra;
  90.     PICTURE *tempPic;
  91.     CHECKSYM( char msg[120]; ) /* Flawfinder: ignore */
  92.     if (PBframe && PBframeCap) {
  93.         reconBflag = 1; // Reconstruct B frame
  94.     } else {
  95.         reconBflag = 0; // Don't do B frame
  96.     }
  97.     tempPic = Bpic; // Use as work array in Reduced-res. Update mode
  98.     if (state->i > 0) {
  99.         // We timed out last time: restore state
  100.         i     = state->i;
  101.         mbnum = state->mbnum;
  102.         col   = state->col;
  103.     } else {
  104.         // Reset state
  105.         i = 0;
  106.         mbnum = gob->first_col + gob->first_row * gob->mb_offset;
  107.         col = gob->first_col;   // Used to check when we reach end of line
  108.     }
  109. #ifndef DISPLAY_DIFFERENCE  // Do proper reconstruction
  110.     if (pic->y.nhor == prev_pic->y.nhor  &&  pic->y.nvert == prev_pic->y.nvert) {
  111.         // Size of prev_pic is OK; use it if specified
  112.         while (i < gob->num_mb) {
  113.             //printf("recon_gob:  mbnum = %d   type = %dn", mbnum, mb[mbnum].mtype);
  114.             switch (mb[mbnum].mtype) {
  115.             case MTYPE_SKIP:
  116.                 mb[mbnum].mv_x = 0;
  117.                 mb[mbnum].mv_y = 0;
  118.                 if (reducedResUpdate) {
  119.                     MotionComp32x32( &mb[mbnum], prev_pic, pic);
  120.                     if (advancedPred) {
  121.                         Overlap32x32( &mb[mbnum], prev_pic, pic,
  122.                                 gob->mb_width, gob->mb_offset, dummy );
  123.                     }
  124.                 } else {
  125.                     MotionComp( &mb[mbnum], prev_pic, pic);
  126.                     if (advancedPred) {
  127.                         OverlapMC( &mb[mbnum], PBframe, prev_pic, pic,
  128.                                 gob->mb_width, gob->mb_offset, dummy );
  129.                     }
  130.                     if (reconBflag) {   // Repeat prev. picture in B frame
  131.                         MotionComp( &mb[mbnum], prev_pic, Bpic );
  132.                     }
  133.                 }
  134.                 break;
  135.             
  136.             case MTYPE263_INTER:
  137.             case MTYPE263_INTER_Q:
  138.             case MTYPE263_INTER4V:
  139.                 if (reducedResUpdate) {
  140.                     MotionComp32x32( &mb[mbnum], prev_pic, pic);
  141.                     if (advancedPred) {
  142.                         Overlap32x32( &mb[mbnum], prev_pic, pic,
  143.                                 gob->mb_width, gob->mb_offset, dummy );
  144.                         state->actComp += 4;   // Increment computation measure
  145.                     }
  146.                     intra = NO;
  147.                     ReconReducedResMb( &mb[mbnum], pic, intra, tempPic );
  148.                     state->actComp += 4;   // Increment computation measure
  149.                 } else {
  150.                     MotionComp263( &mb[mbnum], prev_pic, pic);
  151.                     if (advancedPred) {
  152.                         OverlapMC( &mb[mbnum], PBframe, prev_pic, pic,
  153.                                 gob->mb_width, gob->mb_offset, dummy );
  154.                         ++state->actComp;   // Increment computation measure
  155.                     }
  156.                     ReconInter( &mb[mbnum], pic, CLEAN);
  157.                     ++state->actComp;   // Increment computation measure
  158.                     if (reconBflag) {   // Reconstruct B frame
  159.     if(PBframe == H263PLUS_IMPROVED_PBFRAME_MODE) {
  160.     PredBframePlus( &mb[mbnum], prev_pic, pic, Bpic );
  161.     } else {
  162.     PredBframe( &mb[mbnum], prev_pic, pic, Bpic );
  163.     }
  164.                         reconBframe( &mb[mbnum], Bpic );
  165.                         ++state->actComp;   // Increment computation measure
  166.                     }
  167.                 }
  168.                 break;
  169.             case MTYPE263_INTRA:
  170.             case MTYPE263_INTRA_Q:
  171.                 if (reducedResUpdate) {
  172.                     Fill32x32( &mb[mbnum], pic, 0 );
  173.                     intra = YES;
  174.                     ReconReducedResMb( &mb[mbnum], pic, intra, tempPic );
  175.                     state->actComp += 4;   // Increment computation measure
  176.                 } else {
  177.                     if(advancedIntraMode)
  178.                         ReconAdvancedIntra( &mb[mbnum], pic, CLEAN );
  179.                     else
  180.                         ReconIntra( &mb[mbnum], pic, CLEAN );
  181.                     ++state->actComp;   // Increment computation measure
  182.                     if (reconBflag) {   // Reconstruct B frame
  183.                         if(PBframe==H263PLUS_IMPROVED_PBFRAME_MODE) {
  184.     PredBframePlus( &mb[mbnum], prev_pic, pic, Bpic );
  185.     } else {
  186.                             PredBframe( &mb[mbnum], prev_pic, pic, Bpic );
  187.                         }
  188.                         reconBframe( &mb[mbnum], Bpic );
  189.                         ++state->actComp;   // Increment computation measure
  190.                     }
  191.                 }
  192.                 break;
  193.             
  194.             case MTYPE_INTER:
  195.             case MTYPE_INTER_MQUANT:
  196.                 mb[mbnum].mv_x = 0;
  197.                 mb[mbnum].mv_y = 0;
  198.                 MotionComp( &mb[mbnum], prev_pic, pic);
  199.                 ReconInter( &mb[mbnum], pic, CLEAN);
  200.                 ++state->actComp;   // Increment computation measure
  201.                 break;
  202.             case MTYPE_MCFILT_CBP:
  203.             case MTYPE_MCFILT_MQUANT:
  204.                 LoopFilter( &mb[mbnum], prev_pic, pic);
  205.                 ReconInter( &mb[mbnum], pic, CLEAN);
  206.                 state->actComp += 2;    // Increment computation measure
  207.                 break;
  208.             case MTYPE_MCFILT_NOCBP:
  209.                 LoopFilter( &mb[mbnum], prev_pic, pic);
  210.                 ++state->actComp;   // Increment computation measure
  211.                 break;
  212.             case MTYPE_INTRA:
  213.             case MTYPE_INTRA_MQUANT:
  214.                 //printf("Calling ReconIntra, mbnum = %d n", mbnum);
  215.                 ReconIntra( &mb[mbnum], pic, CLEAN );
  216.                 ++state->actComp;   // Increment computation measure
  217.                 break;
  218.             case MTYPE_MC_CBP:
  219.             case MTYPE_MC_MQUANT:
  220.                 MotionComp( &mb[mbnum], prev_pic, pic);
  221.                 ReconInter( &mb[mbnum], pic, CLEAN);
  222.                 ++state->actComp;   // Increment computation measure
  223.                 break;
  224.             case MTYPE_MC_NOCBP:
  225.                 MotionComp( &mb[mbnum], prev_pic, pic);
  226.                 break;
  227.             default:
  228.                 CHECKSYM( sprintf( msg, "PROGRAM ERROR: MTYPE = %d in recon_gob", mb[mbnum].mtype); /* Flawfinder: ignore */
  229.                     H261ErrMsg( msg );
  230.                     state->i = 0;   // Indicate that we finished without timing out
  231.                     return( H261_ERROR ); )
  232.                 break;
  233.             }
  234.             i++, mbnum++;
  235.             col++;
  236.             if (col == gob->mb_width) { // Start on next row of macroblocks
  237.                 mbnum += gob->mb_offset - gob->mb_width;
  238.                 col = 0;
  239.             }
  240.             if (maxComp > 0  &&  state->actComp >= maxComp) {
  241.                 // We have timed out: save state and return
  242.                 state->i    = i;
  243.                 state->mbnum= mbnum;
  244.                 state->col  = col;
  245.                 return OK;
  246.             }
  247.         }
  248.         state->i = 0;   // Indicate that we finished without timing out
  249.         return (OK);
  250.     } else
  251. #endif
  252.     {   // Don't use prev_pic, i.e., reconstruct difference image
  253.         while (i < gob->num_mb) {
  254.             switch (mb[mbnum].mtype) {
  255.             case MTYPE_SKIP:
  256.             case MTYPE_MCFILT_NOCBP:
  257.             case MTYPE_MC_NOCBP:
  258.                 if (reducedResUpdate) {
  259.                     Fill32x32( &mb[mbnum], pic, GRAY);
  260.                 } else {
  261.                     gray_mb( &mb[mbnum], pic);
  262.                     if (reconBflag) {   // Reconstruct B frame
  263.                         gray_mb( &mb[mbnum], Bpic );
  264.                     }
  265.                 }
  266.                 break;
  267.             case MTYPE263_INTER:
  268.             case MTYPE263_INTER_Q:
  269.             case MTYPE263_INTER4V:
  270.             case MTYPE_INTER:
  271.             case MTYPE_INTER_MQUANT:
  272.             case MTYPE_MCFILT_CBP:
  273.             case MTYPE_MCFILT_MQUANT:
  274.             case MTYPE_MC_CBP:
  275.             case MTYPE_MC_MQUANT:
  276.                 if (reducedResUpdate) {
  277.                     Fill32x32( &mb[mbnum], pic, GRAY);
  278.                     intra = NO;
  279.                     ReconReducedResMb( &mb[mbnum], pic, intra, tempPic );
  280.                     state->actComp += 4;   // Increment computation measure
  281.                 } else {
  282.                     gray_mb( &mb[mbnum], pic);
  283.                     ReconInter( &mb[mbnum], pic, CLEAN);
  284.                     ++state->actComp;   // Increment computation measure
  285.                     if (reconBflag) {   // Reconstruct B frame
  286.                         gray_mb( &mb[mbnum], Bpic );
  287.                         reconBframe( &mb[mbnum], Bpic );
  288.                     }
  289.                 }
  290.                 break;
  291.             case MTYPE263_INTRA:
  292.             case MTYPE263_INTRA_Q:
  293.             case MTYPE_INTRA:
  294.             case MTYPE_INTRA_MQUANT:
  295.                 if (reducedResUpdate) {
  296.                     Fill32x32( &mb[mbnum], pic, 0 );
  297.                     intra = YES;
  298.                     ReconReducedResMb( &mb[mbnum], pic, intra, tempPic );
  299.                     state->actComp += 4;   // Increment computation measure
  300.                 } else {
  301.                     if(advancedIntraMode)
  302.                         ReconAdvancedIntra( &mb[mbnum], pic, CLEAN );
  303.                     else
  304.                         ReconIntra( &mb[mbnum], pic, CLEAN );
  305.                     ++state->actComp;   // Increment computation measure
  306.                     if (reconBflag) {   // Reconstruct B frame
  307.                         gray_mb( &mb[mbnum], Bpic );
  308.                         reconBframe( &mb[mbnum], Bpic );
  309.                     }
  310.                 }
  311.                 break;
  312.             default:
  313.                 CHECKSYM( sprintf( msg, "PROGRAM ERROR: MTYPE = %d in recon_gob", mb[mbnum].mtype); /* Flawfinder: ignore */
  314.                     H261ErrMsg( msg );
  315.                     state->i = 0;   // Indicate that we finished without timing out
  316.                     return( H261_ERROR ); )
  317.                 break;
  318.             }
  319.             i++, mbnum++;
  320.             col++;
  321.             if (col == gob->mb_width) { // Start on next row of macroblocks
  322.                 mbnum += gob->mb_offset - gob->mb_width;
  323.                 col = 0;
  324.             }
  325.             if (maxComp > 0  &&  state->actComp >= maxComp) {
  326.                 // We have timed out: save state and return
  327.                 state->i    = i;
  328.                 state->mbnum= mbnum;
  329.                 state->col  = col;
  330.                 return H261_ERROR;
  331.             }
  332.         }
  333.         state->i = 0;   // Indicate that we finished without timing out
  334.         return (H261_ERROR);
  335.     }
  336. }
  337. // Reconstruct GOB by repeating previous picture
  338. extern int ConcealGob( GOB_DESCR * gob, MACROBLOCK_DESCR mb[], int reducedResUpdate,
  339.                        PICTURE * prev_pic, PICTURE * pic )
  340. {
  341.     int mbnum, i, col;
  342.     i = 0;
  343.     mbnum = gob->first_col + gob->first_row * gob->mb_offset;
  344.     col = gob->first_col;   // Used to check when we reach end of line
  345.     if (pic->y.nhor == prev_pic->y.nhor  &&  pic->y.nvert == prev_pic->y.nvert) {
  346.         // Size of prev_pic is OK; use it for new picture
  347.         while (i < gob->num_mb) {
  348.             mb[mbnum].mv_x = 0;
  349.             mb[mbnum].mv_y = 0;
  350.             if (reducedResUpdate) {
  351.                 MotionComp32x32( &mb[mbnum], prev_pic, pic);
  352.             } else {
  353.                 MotionComp( &mb[mbnum], prev_pic, pic);
  354.             }
  355.             i++, mbnum++;
  356.             col++;
  357.             if (col == gob->mb_width) { // Start on next row of macroblocks
  358.                 mbnum += gob->mb_offset - gob->mb_width;
  359.                 col = 0;
  360.             }
  361.         }
  362.         return (OK);
  363.     } else {    // Paint gray
  364.         while (i < gob->num_mb) {
  365.             if (reducedResUpdate) {
  366.                 Fill32x32( &mb[mbnum], pic, GRAY);
  367.             } else {
  368.                 gray_mb( &mb[mbnum], pic);
  369.             }
  370.             i++, mbnum++;
  371.             col++;
  372.             if (col == gob->mb_width) { // Start on next row of macroblocks
  373.                 mbnum += gob->mb_offset - gob->mb_width;
  374.                 col = 0;
  375.             }
  376.         }
  377.         return (H261_ERROR);
  378.     }
  379. }
  380. // ReconIntra
  381. extern void ReconIntra( MACROBLOCK_DESCR * mb, PICTURE * pic, int clean)
  382. {
  383.     int     row, col, offset;
  384.     PIXEL   * pixel0;
  385.     S16   * recon_tab;
  386.     recon_tab = Recon[mb->quant - QUANT_MIN];
  387.     col = 16 * mb->x;
  388.     row = 16 * mb->y;
  389.     /*{
  390.         int isym;
  391.         printf("ReconIntra: x = %d  y = %dn", col, row);
  392.         printf("nsym = %d %d %d %d %d %d n", mb->block[0].nsym,
  393.                 mb->block[1].nsym, mb->block[2].nsym, mb->block[3].nsym,
  394.                 mb->block[4].nsym, mb->block[5].nsym);
  395.         printf("Symbol number to print: ");
  396.         scanf("%d", &isym);
  397.         while (isym > 0) {
  398.             printf("Luma 1: ");
  399.             printsym( *(mb->block[0].sym + isym - 1) ); printf("n");
  400.             printf("Luma 2: ");
  401.             printsym( *(mb->block[1].sym + isym - 1) ); printf("n");
  402.             printf("Luma 3: ");
  403.             printsym( *(mb->block[2].sym + isym - 1) ); printf("n");
  404.             printf("Luma 4: ");
  405.             printsym( *(mb->block[3].sym + isym - 1) ); printf("n");
  406.             printf("Symbol number to print: ");
  407.             scanf("%d", &isym);
  408.         }
  409.     }*/
  410.     pixel0 = pic->y.ptr + col + row * pic->y.hoffset;
  411.     //printf("Luma block 1 n");
  412.     Idct2( mb->block[0].sym, mb->block[0].nsym, pixel0,
  413.             pic->y.hoffset, recon_tab, clean);
  414.     //printf("Luma block 2 n");
  415.     Idct2( mb->block[1].sym, mb->block[1].nsym, pixel0 + 8,
  416.             pic->y.hoffset, recon_tab, clean);
  417.     //printf("Luma block 3 n");
  418.     Idct2( mb->block[2].sym, mb->block[2].nsym, pixel0 + 8 * pic->y.hoffset,
  419.             pic->y.hoffset, recon_tab, clean);
  420.     //printf("Luma block 4 n");
  421.     Idct2( mb->block[3].sym, mb->block[3].nsym, pixel0 + 8 + 8 * pic->y.hoffset,
  422.             pic->y.hoffset, recon_tab, clean);
  423.     if (pic->color) {
  424.         // Assuming same offset for Cr and Cb
  425.         col = 8 * mb->x;
  426.         row = 8 * mb->y;
  427.         offset = col + row * pic->cb.hoffset;
  428.         pixel0 = pic->cb.ptr + offset;
  429.         //printf("CB block n");
  430.         Idct2( mb->block[4].sym, mb->block[4].nsym, pixel0,
  431.             pic->cb.hoffset, recon_tab, clean);
  432.         pixel0 = pic->cr.ptr + offset;
  433.         //printf("CR block n");
  434.         Idct2( mb->block[5].sym, mb->block[5].nsym, pixel0,
  435.             pic->cr.hoffset, recon_tab, clean);
  436.     }
  437.     return;
  438. }
  439. #ifdef DO_H263_PLUS
  440. #define MAX_MACROBLKS_PER_ROW           (88)    /* Up to 16CIF (1408 pixels/line) */
  441. #define UPPER_LUMA_BLOCK_CACHE_LENGTH   (2 * MAX_MACROBLKS_PER_ROW)
  442. #define UPPER_CHROMA_BLOCK_CACHE_LENGTH (MAX_MACROBLKS_PER_ROW)
  443. // Storage for the first rows of the lower 8x8 blocks of the intra macroblocks in the previous GOB.
  444. // Refer to these for appropriate predictions.  For right now we make this static
  445. // data, but should really allocate it on the heap only if advanced intra is being
  446. // used?
  447. static S8 upperLumaBlockCache[UPPER_LUMA_BLOCK_CACHE_LENGTH][8]; // allocated for CIF video!
  448. static S8 upperCrBlockCache[UPPER_CHROMA_BLOCK_CACHE_LENGTH][8];   // allocated for CIF video!
  449. static S8 upperCbBlockCache[UPPER_CHROMA_BLOCK_CACHE_LENGTH][8];   // allocated for CIF video!
  450. // Storage for the first columns of the 8x8 blocks of the most recent intra macroblock.
  451. // Refer to these for appropriate predictions.
  452. static S8 leftLumaBlockCache[4][8];
  453. static S8 leftCrBlockCache[1][8];
  454. static S8 leftCbBlockCache[1][8];
  455. static U8 upperDCLumaBlockCache[UPPER_LUMA_BLOCK_CACHE_LENGTH][1];
  456. static U8 upperDCCrBlockCache[UPPER_CHROMA_BLOCK_CACHE_LENGTH][1];
  457. static U8 upperDCCbBlockCache[UPPER_CHROMA_BLOCK_CACHE_LENGTH][1];
  458. static U8 leftDCLumaBlockCache[4][1];
  459. static U8 leftDCCrBlockCache[1];
  460. static U8 leftDCCbBlockCache[1];
  461. static void InitializeLeftCache(int qp)
  462. {
  463.     int i;
  464.     for(i=0; i<4; i++) {
  465.         //leftDCLumaBlockCache[i][0] = ( U8 )128; // MPEG4 style boundary conditions
  466.         leftDCLumaBlockCache[i][0] = ( U8 )(512/qp); // H.263+ style boundary conditions
  467.         memset(&leftLumaBlockCache[i][1], 0, 7);
  468.     }
  469.     leftDCCrBlockCache[0] = ( U8 )(512/qp); // H.263+ style boundary conditions
  470.     memset(&leftCrBlockCache[0][1], 0, 7);
  471.     
  472.     leftDCCbBlockCache[0] = ( U8 )(512/qp); // H.263+ style boundary conditions
  473.     memset(&leftCbBlockCache[0][1], 0, 7);
  474. }
  475. static void InitializeUpperCache(int qp, int i)
  476. {
  477.         //upperDCLumaBlockCache[2*i][0] = ( U8 )128; // MPEG4 style boundary conditions
  478.         upperDCLumaBlockCache[2*i][0] = ( U8 )(512/qp); // H.263+ style boundary conditions
  479.         memset(&upperLumaBlockCache[2*i][1], 0, 7);
  480.         //upperDCLumaBlockCache[2*i+1][0] = ( U8 )128; // MPEG4 style boundary conditions
  481.         upperDCLumaBlockCache[2*i+1][0] = ( U8 )(512/qp); // H.263+ style boundary conditions
  482.         memset(&upperLumaBlockCache[2*i+1][1], 0, 7);
  483.         
  484.         //upperDCCrBlockCache[i][0] = ( U8 )128; // MPEG4 style boundary conditions
  485.         upperDCCrBlockCache[i][0] = ( U8 )(512/qp); // H.263+ style boundary conditions
  486.         memset(&upperCrBlockCache[i][1], 0, 7);
  487.         
  488.         //upperDCCbBlockCache[i][0] = ( U8 )128; // MPEG4 style boundary conditions
  489.         upperDCCbBlockCache[i][0] = ( U8 )(512/qp); // H.263+ style boundary conditions
  490.         memset(&upperCbBlockCache[i][1], 0, 7);
  491. }
  492. #define INTRA(mb)   (((mb).mtype >= MTYPE263_INTRA_MIN && (mb).mtype <= MTYPE263_INTRA_MAX) ? 1:0)
  493. extern void ReconAdvancedIntra( MACROBLOCK_DESCR * mb, PICTURE * pic, int clean)
  494. {
  495.     int     row, col, offset;
  496.     PIXEL   * pixel0;
  497.     S16   * recon_tab;
  498.     int   predtype = mb->intra_mode;
  499.     int   fixedDC = mb->quant<8;
  500.     int   numhor=pic->y.nhor>>4; // number of mb per row
  501.     // Ensure that we are not scribbling outside the allocated cache
  502.     if (mb->x >= MAX_MACROBLKS_PER_ROW) return;
  503.     // Reinitialize predictors if we're on a new row or if one of our abutting macroblocks
  504.     // isn't intra
  505.     if(mb->x == 0 || !INTRA(mb[-1])) {
  506.         InitializeLeftCache(fixedDC ? 4 : mb->quant);
  507.     }
  508.     if(mb->y == 0 || !INTRA(mb[-numhor])) {
  509.         InitializeUpperCache(fixedDC ? 4 : mb->quant, mb->x);
  510.     }
  511.     recon_tab = Recon[mb->quant - QUANT_MIN];
  512.     col = 16 * mb->x;
  513.     row = 16 * mb->y;
  514.     /*{
  515.         int isym;
  516.         printf("ReconAdvancedIntra: x = %d  y = %dn", col, row);
  517.         printf("nsym = %d %d %d %d %d %d n", mb->block[0].nsym,
  518.                 mb->block[1].nsym, mb->block[2].nsym, mb->block[3].nsym,
  519.                 mb->block[4].nsym, mb->block[5].nsym);
  520.         printf("Symbol number to print: ");
  521.         scanf("%d", &isym);
  522.         while (isym > 0) {
  523.             printf("Luma 1: ");
  524.             printsym( *(mb->block[0].sym + isym - 1) ); printf("n");
  525.             printf("Luma 2: ");
  526.             printsym( *(mb->block[1].sym + isym - 1) ); printf("n");
  527.             printf("Luma 3: ");
  528.             printsym( *(mb->block[2].sym + isym - 1) ); printf("n");
  529.             printf("Luma 4: ");
  530.             printsym( *(mb->block[3].sym + isym - 1) ); printf("n");
  531.             printf("Symbol number to print: ");
  532.             scanf("%d", &isym);
  533.         }
  534.     }*/
  535.     pixel0 = pic->y.ptr + col + row * pic->y.hoffset;
  536.     //printf("Luma block 1 n");
  537.     Idct2AdvancedIntra( mb->block[0].sym, mb->block[0].nsym, pixel0,
  538.             pic->y.hoffset, recon_tab,
  539.             upperDCLumaBlockCache[2*mb->x][0], upperLumaBlockCache[2*mb->x], // DC and AC pred for row  
  540.             upperDCLumaBlockCache[2*mb->x],upperLumaBlockCache[2*mb->x],  // DC and AC store for row
  541.             leftDCLumaBlockCache[1][0], leftLumaBlockCache[1],  // DC and AC pred for column
  542.             leftDCLumaBlockCache[0], leftLumaBlockCache[0],  // DC and AC store for column
  543.             predtype, fixedDC,
  544.             mb->x==0, mb->y==0); // can be on left or upper boundary
  545.        
  546.     //printf("Luma block 2 n");
  547.     Idct2AdvancedIntra( mb->block[1].sym, mb->block[1].nsym, pixel0 + 8,
  548.             pic->y.hoffset, recon_tab, 
  549.             upperDCLumaBlockCache[2*mb->x+1][0], upperLumaBlockCache[2*mb->x+1], // DC and AC pred for row  
  550.             upperDCLumaBlockCache[2*mb->x+1],upperLumaBlockCache[2*mb->x+1],  // DC and AC store for row
  551.             leftDCLumaBlockCache[0][0], leftLumaBlockCache[0],  // DC and AC pred for column
  552.             leftDCLumaBlockCache[1], leftLumaBlockCache[1],  // DC and AC store for column
  553.             predtype, fixedDC,
  554.             FALSE, mb->y==0); // can only be on upper boudary
  555.     //printf("Luma block 3 n");
  556.     Idct2AdvancedIntra( mb->block[2].sym, mb->block[2].nsym, pixel0 + 8 * pic->y.hoffset,
  557.             pic->y.hoffset, recon_tab,
  558.             upperDCLumaBlockCache[2*mb->x][0], upperLumaBlockCache[2*mb->x], // DC and AC pred for row  
  559.             upperDCLumaBlockCache[2*mb->x],upperLumaBlockCache[2*mb->x],  // DC and AC store for row
  560.             leftDCLumaBlockCache[3][0], leftLumaBlockCache[3],  // DC and AC pred for column
  561.             leftDCLumaBlockCache[2], leftLumaBlockCache[2],  // DC and AC store for column
  562.             predtype, fixedDC,
  563.             mb->x==0, FALSE); // can only be on left boundary
  564.     //printf("Luma block 4 n");
  565.     Idct2AdvancedIntra( mb->block[3].sym, mb->block[3].nsym, pixel0 + 8 + 8 * pic->y.hoffset,
  566.             pic->y.hoffset, recon_tab,
  567.             upperDCLumaBlockCache[2*mb->x+1][0], upperLumaBlockCache[2*mb->x+1], // DC and AC pred for row  
  568.             upperDCLumaBlockCache[2*mb->x+1],upperLumaBlockCache[2*mb->x+1],  // DC and AC store for row
  569.             leftDCLumaBlockCache[2][0], leftLumaBlockCache[2],  // DC and AC pred for column
  570.             leftDCLumaBlockCache[3], leftLumaBlockCache[3],  // DC and AC store for column
  571.             predtype, fixedDC,
  572.             FALSE, FALSE); // can't be on left or upper boundary
  573.     
  574.     if (pic->color) {
  575.         // Assuming same offset for Cr and Cb
  576.         col = 8 * mb->x;
  577.         row = 8 * mb->y;
  578.         offset = col + row * pic->cb.hoffset;
  579.         pixel0 = pic->cb.ptr + offset;
  580.         //printf("CB block n");
  581.         Idct2AdvancedIntra( mb->block[4].sym, mb->block[4].nsym, pixel0,
  582.             pic->cb.hoffset, recon_tab,
  583.             upperDCCbBlockCache[mb->x][0], upperCbBlockCache[mb->x], // DC and AC pred for row  
  584.             upperDCCbBlockCache[mb->x],upperCbBlockCache[mb->x],  // DC and AC store for row
  585.             leftDCCbBlockCache[0], leftCbBlockCache[0],  // DC and AC pred for column
  586.             leftDCCbBlockCache, leftCbBlockCache[0],  // DC and AC store for column
  587.             predtype, fixedDC,
  588.             mb->x==0, mb->y==0);  // what boundaries are we on?
  589.  
  590.         pixel0 = pic->cr.ptr + offset;
  591.         //printf("CR block n");
  592.         Idct2AdvancedIntra( mb->block[5].sym, mb->block[5].nsym, pixel0,
  593.             pic->cr.hoffset, recon_tab,
  594.             upperDCCrBlockCache[mb->x][0], upperCrBlockCache[mb->x], // DC and AC pred for row  
  595.             upperDCCrBlockCache[mb->x],upperCrBlockCache[mb->x],  // DC and AC store for row
  596.             leftDCCrBlockCache[0], leftCrBlockCache[0],  // DC and AC pred for column
  597.             leftDCCrBlockCache, leftCrBlockCache[0],  // DC and AC store for column
  598.             predtype, fixedDC,
  599.             mb->x==0, mb->y==0); // what boundaries are we on?
  600.     }
  601.     return;
  602. }
  603. #endif
  604. // ReconInter
  605. extern void ReconInter( MACROBLOCK_DESCR * mb, PICTURE * pic, int clean )
  606. {
  607.     int     row, col, offset ;
  608.     PIXEL   * pixel0;
  609.     S16   * recon_tab;
  610.     recon_tab = Recon[mb->quant - QUANT_MIN];
  611.     col = 16 * mb->x;
  612.     row = 16 * mb->y;
  613. /*    {
  614.         int isym;
  615.         printf("ReconInter: x = %d  y = %dn", col, row);
  616.         printf("nsym = %d %d %d %d %d %d n", mb->block[0].nsym,
  617.                 mb->block[1].nsym, mb->block[2].nsym, mb->block[3].nsym,
  618.                 mb->block[4].nsym, mb->block[5].nsym);
  619.         printf("Symbol number to print: ");
  620.         scanf("%d", &isym);
  621.         while (isym > 0) {
  622.             printf("Luma 1: ");
  623.             printsym( *(mb->block[0].sym + isym - 1) ); printf("n");
  624.             printf("Luma 2: ");
  625.             printsym( *(mb->block[1].sym + isym - 1) ); printf("n");
  626.             printf("Luma 3: ");
  627.             printsym( *(mb->block[2].sym + isym - 1) ); printf("n");
  628.             printf("Luma 4: ");
  629.             printsym( *(mb->block[3].sym + isym - 1) ); printf("n");
  630.             printf("Symbol number to print: ");
  631.             scanf("%d", &isym);
  632.     }
  633.     }
  634.  */
  635.     pixel0 = pic->y.ptr + col + row * pic->y.hoffset;
  636. //    #define DB_DUMP_MACROBLOCK
  637. #ifdef DB_DUMP_MACROBLOCK
  638.     {
  639.                 static char foo[256]; /* Flawfinder: ignore */
  640.                 static char dump=0;
  641.                 int dbi,dbj;
  642.                 if(dump) {
  643.                 SafeSprintf(foo, 256, "Reference Block (from ReconInter) (%d, %d)n", mb->x, mb->y);
  644.                 OutputDebugString(foo);
  645.                 for(dbi=0;dbi<16;dbi++) 
  646.                 {
  647.                     foo[0] = '';
  648.                     for(dbj=0;dbj<16;dbj++)
  649.                     {
  650.                         SafeSprintf(foo+strlen(foo), 256-strlen(foo), "%d ", pixel0[dbi*pic->y.hoffset + dbj]);
  651.                     }
  652.                     SafeStrCat(foo, "n", 256);
  653.                     OutputDebugString(foo);
  654.                 }
  655.                 }
  656.     }
  657. #endif
  658.     if (mb->block[0].nsym > 0) {
  659.         //printf("Luma block 1 n");
  660.         Idct2Sum( mb->block[0].sym, mb->block[0].nsym, pixel0,
  661.             pic->y.hoffset, recon_tab, clean);
  662.     }
  663.     if (mb->block[1].nsym > 0) {
  664.         //printf("Luma block 2 n");
  665.         Idct2Sum( mb->block[1].sym, mb->block[1].nsym, pixel0 + 8,
  666.             pic->y.hoffset, recon_tab, clean);
  667.     }
  668.     if (mb->block[2].nsym > 0) {
  669.         //printf("Luma block 3 n");
  670.         Idct2Sum( mb->block[2].sym, mb->block[2].nsym, pixel0 + 8 * pic->y.hoffset,
  671.             pic->y.hoffset, recon_tab, clean);
  672.     }
  673.     if (mb->block[3].nsym > 0) {
  674.         //printf("Luma block 4 n");
  675.         Idct2Sum( mb->block[3].sym, mb->block[3].nsym, pixel0 + 8 + 8 * pic->y.hoffset,
  676.             pic->y.hoffset, recon_tab, clean);
  677.     }
  678.     if (pic->color  &&  (mb->block[4].nsym > 0  ||  mb->block[5].nsym > 0)) {
  679.         // Assuming same offset for Cr and Cb
  680.         col = 8 * mb->x;
  681.         row = 8 * mb->y;
  682.         offset = col + row * pic->cb.hoffset;
  683.         if (mb->block[4].nsym > 0) {
  684.             pixel0 = pic->cb.ptr + offset;
  685.             //printf("CB block n");
  686.             Idct2Sum( mb->block[4].sym, mb->block[4].nsym, pixel0,
  687.                         pic->cb.hoffset, recon_tab, clean);
  688.         }
  689.         if (mb->block[5].nsym > 0) {
  690.             pixel0 = pic->cr.ptr + offset;
  691.             //printf("CR block n");
  692.             Idct2Sum( mb->block[5].sym, mb->block[5].nsym, pixel0,
  693.                         pic->cr.hoffset, recon_tab, clean);
  694.         }
  695.     }
  696. //#define DB_DUMP_MACROBLOCK
  697. #ifdef DB_DUMP_MACROBLOCK
  698.     {
  699.                 static char foo[256]; /* Flawfinder: ignore */
  700.                 static char dump=0;
  701.                 int dbi,dbj;
  702.                 if(dump) {
  703.                 pixel0 = pic->y.ptr + col + row * pic->y.hoffset;
  704.                 SafeSprintf(foo, 256, "Reconstructed Macroblock (%d, %d)n", mb->x, mb->y);
  705.                 OutputDebugString(foo);
  706.                 for(dbi=0;dbi<16;dbi++) 
  707.                 {
  708.                     foo[0] = '';
  709.                     for(dbj=0;dbj<16;dbj++)
  710.                     {
  711.                         SafeSprintf(foo+strlen(foo), 256-strlen(foo), "%d ", pixel0[dbi*pic->y.hoffset + dbj]);
  712.                     }
  713.                     SafeStrCat(foo, "n", 256);
  714.                     OutputDebugString(foo);
  715.                 }
  716.                 }
  717.     }
  718. #endif
  719.     return;
  720. }
  721. //  reconBframe - Reconstruct B-frame prediction error and add to prediction
  722. static void reconBframe( MACROBLOCK_DESCR * mb, PICTURE * Bpic )
  723. {
  724.     int         i;
  725.     U8          saveQuant, saveCbp;
  726.     SYMBOL      *saveSym[6];
  727.     int         saveNsym[6];
  728.     if (BFRAME_HAS_CBP(mb)) {
  729.         // Set quant, cbp, and block[] to hold values for B-frame
  730.         saveQuant = mb->quant;
  731.         mb->quant = mb->Bquant;
  732.         saveCbp = mb->cbp;
  733.         mb->cbp = mb->cbpB;
  734.         for (i = 0; i < 6; ++i) {
  735.             saveSym[i] = mb->block[i].sym;
  736.             mb->block[i].sym = mb->Bblock[i].sym;
  737.             saveNsym[i] = mb->block[i].nsym;
  738.             mb->block[i].nsym = mb->Bblock[i].nsym;
  739.         }
  740.         // Do reconstruction
  741.         ReconInter( mb, Bpic, CLEAN );
  742.         // Restore parameters (if needed for statistics)
  743.         mb->quant = saveQuant;
  744.         mb->cbp = saveCbp;
  745.         for (i = 0; i < 6; ++i) {
  746.             mb->block[i].sym = saveSym[i];
  747.             mb->block[i].nsym = saveNsym[i];
  748.         }
  749.     }
  750. }
  751. //  gray_mb - fill macroblock with gray (value 128); assumes that pic is word-aligned
  752. static void gray_mb( MACROBLOCK_DESCR * mb, PICTURE * pic )
  753. {
  754.     fill_mb( mb, pic, GRAY );
  755. }
  756. //  fill_mb - fill macroblock with constant color; assumes that pic is word-aligned
  757. static void fill_mb( MACROBLOCK_DESCR * mb, PICTURE * pic, PIXEL value )
  758. {
  759.     int     row, col, i;
  760.     union {     // Write words to speed up routine
  761.         PIXEL   * pix;
  762.         U32     * word;
  763.     } pixel;
  764.     U32     * dest;
  765.     U32     dValue;
  766.     dValue = value | (value << 8) | (value << 16) | (value << 24);
  767.     col = 16 * mb->x;
  768.     row = 16 * mb->y;
  769. #ifdef DO_H263_PLUS
  770.     if (col >= pic->y.nhor  ||  row >= pic->y.nvert)
  771.         return; // Inactive part of Macroblock
  772. #endif
  773.     pixel.pix = pic->y.ptr + col + row * pic->y.hoffset;
  774.     for (i = 0; i < 16; i++) {
  775.         for (dest = pixel.word; dest < pixel.word + 16/4; dest++) {
  776.             *dest = dValue;
  777.         }
  778.         pixel.pix += pic->y.hoffset;
  779.     }
  780.     if (pic->color) {
  781.         col = 8 * mb->x;
  782.         row = 8 * mb->y;
  783.         pixel.pix = pic->cb.ptr + col + row * pic->cb.hoffset;
  784.         for (i = 0; i < 8; i++) {
  785.             for (dest = pixel.word; dest < pixel.word + 8/4; dest++) {
  786.                 *dest = dValue;
  787.             }
  788.             pixel.pix += pic->cb.hoffset;
  789.         }
  790.         pixel.pix = pic->cr.ptr + col + row * pic->cr.hoffset;
  791.         for (i = 0; i < 8; i++) {
  792.             for (dest = pixel.word; dest < pixel.word + 8/4; dest++) {
  793.                 *dest = dValue;
  794.             }
  795.             pixel.pix += pic->cr.hoffset;
  796.         }
  797.     }
  798.     return;
  799. }
  800. #ifdef DO_H263_PLUS
  801. /////////////////////////////////////////////////////////////////////////////////////////
  802. //////////// Functions for reconstruction in Reduced-resolution Update mode /////////////
  803. /////////////////////////////////////////////////////////////////////////////////////////
  804. // ReducedResMvComponent - Translate Reduced-res. motion vector component to representation
  805. //  with one fractional bit. The input value is "rounded" half a pixel towards zero, e.g.,
  806. //  input values:   -2   -1   0    1    2  are
  807. //  translated to: -1.5 -0.5  0   0.5  1.5,
  808. extern S8 ReducedResMvComponent( S8 x )
  809. {
  810.     if (x > 0) {
  811.         x = 2 * x - 1;
  812.     } else if (x < 0) {
  813.         x = 2 * x + 1;
  814.     }
  815.     return x;
  816. }
  817. // MotionComp32x32 - perform motion compensation for Reduced-res. Update mode
  818. extern void MotionComp32x32( MACROBLOCK_DESCR * mb, // Describes block to be motion-compensated
  819.                             PICTURE * prevPic,  // Describes previous picture used to form MC
  820.                             PICTURE * pic       // Output picture where MC block is placed
  821.                             )
  822. {
  823.     int blk;
  824.     // Save MTYPE and x/y position
  825.     int saveType = mb->mtype;
  826.     int saveX = mb->x;
  827.     int saveY = mb->y;
  828.     int saveMvX = mb->mv_x;
  829.     int saveMvY = mb->mv_y;
  830.     mb->mtype = MTYPE263_INTER;
  831.     if (saveType != MTYPE263_INTER4V) {
  832.         // Use same motion vector for all four quadrants
  833.         for (blk = 0; blk < 4; ++blk) {
  834.             mb->blkMvX[blk] = mb->mv_x;
  835.             mb->blkMvY[blk] = mb->mv_y;
  836.         }
  837.     }
  838.     // Upper Left 16x16
  839.     mb->x = 2 * saveX;
  840.     mb->y = 2 * saveY;
  841.     mb->mv_x = ReducedResMvComponent( mb->blkMvX[UPPER_LEFT_BLK] );
  842.     mb->mv_y = ReducedResMvComponent( mb->blkMvY[UPPER_LEFT_BLK] );
  843.     MotionComp263( mb, prevPic, pic);
  844.     // Upper Right 16x16
  845.     mb->x = 2 * saveX + 1;
  846.     if (16 * mb->x < pic->y.nhor) {
  847.         mb->mv_x = ReducedResMvComponent( mb->blkMvX[UPPER_RIGHT_BLK] );
  848.         mb->mv_y = ReducedResMvComponent( mb->blkMvY[UPPER_RIGHT_BLK] );
  849.         MotionComp263( mb, prevPic, pic);
  850.     }
  851.     mb->y = 2 * saveY + 1;
  852.     if (16 * mb->y < pic->y.nvert) {
  853.         // Lower Left 16x16
  854.         mb->x = 2 * saveX;
  855.         mb->mv_x = ReducedResMvComponent( mb->blkMvX[LOWER_LEFT_BLK] );
  856.         mb->mv_y = ReducedResMvComponent( mb->blkMvY[LOWER_LEFT_BLK] );
  857.         MotionComp263( mb, prevPic, pic);
  858.         // Lower Right 16x16
  859.         mb->x = 2 * saveX + 1;
  860.         if (16 * mb->x < pic->y.nhor) {
  861.             mb->mv_x = ReducedResMvComponent( mb->blkMvX[LOWER_RIGHT_BLK] );
  862.             mb->mv_y = ReducedResMvComponent( mb->blkMvY[LOWER_RIGHT_BLK] );
  863.             MotionComp263( mb, prevPic, pic);
  864.         }
  865.     }
  866.     // Restore MTYPE, x/y position, and motion vector
  867.     mb->mtype = saveType;
  868.     mb->x = saveX;
  869.     mb->y = saveY;
  870.     mb->mv_x = saveMvX;
  871.     mb->mv_y = saveMvY;
  872. }
  873. // Overlap32x32 - Do overlapped motion comp. for luma (Reduced-res. Update mode)
  874. extern void Overlap32x32( MACROBLOCK_DESCR * mb,   // Describes block to be motion-compensated
  875.                         PICTURE * prevPic,  // Describes previous picture used to form MC
  876.                         PICTURE * pic,      // Output picture where MC block is placed
  877.                         int     mbWidth,    // Macroblocks per row
  878.                         int     mbOffset,   // Row offset; (mb-mbOffset) is neighbor on top
  879.                         int     overlap[4]  // Returns YES or NO to indicate whether overlap
  880.                                             // was done in each 8x8 subblock
  881.                         )
  882. {
  883.     // Placeholder -- not yet implemented
  884.     overlap[UPPER_LEFT_BLK] = NO;
  885.     overlap[UPPER_RIGHT_BLK] = NO;
  886.     overlap[LOWER_LEFT_BLK] = NO;
  887.     overlap[LOWER_RIGHT_BLK] = NO;
  888. }
  889. // Fill32x32 - Fill Reduced-res. MB (32x32 block) with constant color
  890. extern void Fill32x32( MACROBLOCK_DESCR * mb, PICTURE * pic, PIXEL value )
  891. {
  892.     // Get MB coordinates
  893.     int saveX = mb->x;
  894.     int saveY = mb->y;
  895.     // Fill Upper Left 16x16
  896.     mb->x = 2 * saveX;
  897.     mb->y = 2 * saveY;
  898.     fill_mb( mb, pic, value);
  899.     // Fill Upper Right 16x16
  900.     mb->x = 2 * saveX + 1;
  901.     if (16 * mb->x < pic->y.nhor) {
  902.         fill_mb( mb, pic, value);
  903.     }
  904.     mb->y = 2 * saveY + 1;
  905.     if (16 * mb->y < pic->y.nvert) {
  906.         // Fill Lower Left 16x16
  907.         mb->x = 2 * saveX;
  908.         fill_mb( mb, pic, value);
  909.         // Fill Lower Right 16x16
  910.         mb->x = 2 * saveX + 1;
  911.         if (16 * mb->x < pic->y.nhor) {
  912.             fill_mb( mb, pic, value);
  913.         }
  914.     }
  915.     // Restore MB coordinates
  916.     mb->x = saveX;
  917.     mb->y = saveY;
  918. }
  919. // ReconReducedResMb - Reconstruct macroblock in Reduced-resolution Update mode
  920. extern void ReconReducedResMb( MACROBLOCK_DESCR * mb,   // Macroblock to be reconstructed
  921.                                PICTURE * pic,   // Input: motioncomp. prediction;
  922.                                                 // output: reconstr. picture
  923.                                int intra,       // INTER block if zero, otherwise INTRA
  924.                                PICTURE * tempPic// Use for temporary storage
  925.                                )
  926. {
  927.     // Perform IDCT of prediction error; use "first half" of tempPic for temporary storage
  928.     idct32x32( mb, tempPic, intra );
  929.     // Interpolate prediction error, add to motioncomp. prediction and clip to [0,255]
  930.     filtAddClip32x32( mb, pic, tempPic );
  931. }
  932. // idct32x32 - Perform IDCT for 32x32 macroblock (Reduced-res. update mode)
  933. static void idct32x32( MACROBLOCK_DESCR * mb,   // Macroblock to be reconstructed
  934.                        PICTURE * tempPic,       // Store 16-bit IDCT values here
  935.                        int intra                // INTER block if zero, otherwise INTRA
  936.                        )
  937. {
  938.     int     row, col, yHoffset, cHoffset, chromaPixels;
  939.     S16     * pIdct;
  940.     S16     * recon_tab;
  941.     recon_tab = Recon[mb->quant - QUANT_MIN];
  942.     // Reconstruct luminance
  943.     // The PIXEL y[V][H] array is used as S16[V/2][H/2], i.e., only upper half is used
  944.     col = 16 * mb->x;
  945.     row = 16 * mb->y;
  946.     yHoffset = tempPic->y.hoffset >> 1;
  947.     pIdct = (S16 *)tempPic->y.ptr;
  948.     pIdct += col + row * yHoffset;
  949.     Idct2_s16( intra, mb->block[0].sym, mb->block[0].nsym, 
  950.                pIdct + 0 + 0 * yHoffset,
  951.                yHoffset, recon_tab );
  952.     if (2 * col + 16 < tempPic->y.nhor) {
  953.         Idct2_s16( intra, mb->block[1].sym, mb->block[1].nsym, 
  954.                    pIdct + 8 + 0 * yHoffset,
  955.                    yHoffset, recon_tab );
  956.     }
  957.     if (2 * row + 16  <  tempPic->y.nvert) {
  958.         Idct2_s16( intra, mb->block[2].sym, mb->block[2].nsym, 
  959.                    pIdct + 0 + 8 * yHoffset,
  960.                    yHoffset, recon_tab );
  961.         if (2 * col + 16 < tempPic->y.nhor) {
  962.             Idct2_s16( intra, mb->block[3].sym, mb->block[3].nsym, 
  963.                        pIdct + 8 + 8 * yHoffset,
  964.                        yHoffset, recon_tab );
  965.         }
  966.     }
  967.     // Reconstruct chrominance
  968.     //  Ensure that we have memory for picture sizes that are
  969.     //  not multiples of 32, i.e., odd number of macroblocks.  In that case, we will
  970.     //  throw away 4 chroma pixels on the right and/or bottom after the IDCT.
  971.     //  This routine assumes that the two VxH chroma arrays can be treated as one block of
  972.     //  memory starting at tempPic->cb.ptr and of size (V+8)/16 * (H+8)/16 * 256 bytes.
  973.     //  The current memory allocation done in initializePicture fulfills this as long
  974.     //  as each chroma array is at least 16x16 (2x2 macroblocks).
  975.     if (tempPic->color) {
  976.         col = 8 * mb->x;
  977.         row = 8 * mb->y;
  978.         chromaPixels = 8 * ((tempPic->cb.nhor + 8) >> 4);
  979.         cHoffset =  2 * chromaPixels;
  980.         pIdct = (S16 *)tempPic->cb.ptr;
  981.         pIdct += col + row * cHoffset;
  982.         //printf("CB block n");
  983.         Idct2_s16( intra, mb->block[4].sym, mb->block[4].nsym, pIdct,
  984.                         cHoffset, recon_tab );
  985.         // CR array is placed "to the right" of CB array
  986.         //printf("CR block n");
  987.         Idct2_s16( intra, mb->block[5].sym, mb->block[5].nsym, pIdct + chromaPixels,
  988.                         cHoffset, recon_tab );
  989.     }
  990. }
  991. // filtAddClip32x32 - Interpolate, add & clip 32x32 macroblock (Reduced-res. update mode)
  992. static void filtAddClip32x32( MACROBLOCK_DESCR * mb,// Macroblock to be reconstructed
  993.                               PICTURE * pic,    // Input: motion-comp prediction w/ filtered
  994.                                                 // intra borders; output: reconstr. picture
  995.                               PICTURE * tempPic // 16-bit IDCT values
  996.                               )
  997. {
  998.     int     row, col, offset, yHoffset, cHoffset, chromaPixels;
  999.     int     hSize, vSize;
  1000.     PIXEL   * pixel0;
  1001.     S16     * pIdct;
  1002.     yHoffset = pic->y.hoffset >> 1;
  1003.     col = 16 * mb->x;
  1004.     row = 16 * mb->y;
  1005.     hSize = vSize = 16;
  1006.     if (2 * col + 16 >= pic->y.nhor)
  1007.         hSize = 8;
  1008.     if (2 * row + 16 >= pic->y.nvert)
  1009.         vSize = 8;
  1010.     // Interpolate, add, and clip
  1011.     pixel0 = pic->y.ptr + 2 * col + 2 * row * pic->y.hoffset;
  1012.     pIdct = (S16 *)tempPic->y.ptr;
  1013.     pIdct += col + row * yHoffset;
  1014.     filtAddClip( pixel0, pic->y.hoffset, pIdct, yHoffset, 8, 8 );
  1015.     if (hSize == 16)
  1016.         filtAddClip( pixel0 + 16, pic->y.hoffset, pIdct + 8, yHoffset, 8, 8 );
  1017.     if (vSize == 16) {
  1018.         pixel0 += 16 * pic->y.hoffset;
  1019.         pIdct += 8 * yHoffset;
  1020.         filtAddClip( pixel0, pic->y.hoffset, pIdct, yHoffset, 8, 8 );
  1021.         if (hSize == 16)
  1022.             filtAddClip( pixel0 + 16, pic->y.hoffset, pIdct + 8, yHoffset, 8, 8 );
  1023.     }
  1024.     if (pic->color) {
  1025.         chromaPixels = 8 * ((pic->cb.nhor + 8) >> 4);
  1026.         cHoffset =  2 * chromaPixels;
  1027.         offset = col + row * pic->cb.hoffset;
  1028.         pixel0 = pic->cb.ptr + offset;
  1029.         pIdct = (S16 *)tempPic->cb.ptr;
  1030.         pIdct += (col >> 1) + (row >> 1) * cHoffset;
  1031.         filtAddClip( pixel0, pic->cb.hoffset, pIdct,
  1032.                     cHoffset, hSize>>1, vSize>>1 );
  1033.         pixel0 = pic->cr.ptr + offset;
  1034.         filtAddClip( pixel0, pic->cr.hoffset, pIdct + chromaPixels,
  1035.                     cHoffset, hSize>>1, vSize>>1 );
  1036.     }
  1037. }
  1038. #define PIXEL_MIN       0
  1039. #define PIXEL_MAX       255
  1040. #define CLIPMARGIN      300
  1041. #define CLIPMIN         (PIXEL_MIN - CLIPMARGIN)
  1042. #define CLIPMAX         (PIXEL_MAX + CLIPMARGIN)
  1043. extern PIXEL   clip[(CLIPMAX-CLIPMIN+1)];
  1044. // filtAddClip - interpolate IDCT output (typically 8x8), add to prediction (typ. 16x16),
  1045. //  and clip.  Interpolation is only done within the block.
  1046. static void filtAddClip( PIXEL x[], int xdim,       // Output pixels
  1047.                          S16 idct_out[], int idim,  // Input IDCT values
  1048.                          int hSize, int vSize       // Input block size for IDCT values
  1049.                         )
  1050. {
  1051.     int     i, j, e;
  1052.     // Handle top border
  1053.     e = idct_out[0];
  1054.     x[0] = clip[ -CLIPMIN + e + x[0] ];
  1055.     for (j = 1; j < hSize; ++j) {
  1056.         e = (3 * idct_out[j-1] + 1 * idct_out[j] + 2) >> 2;
  1057.         x[2*j-1] = clip[ -CLIPMIN + e + x[2*j-1] ];
  1058.         e = (1 * idct_out[j-1] + 3 * idct_out[j] + 2) >> 2;
  1059.         x[2*j]   = clip[ -CLIPMIN + e + x[2*j] ];
  1060.     }
  1061.     e = idct_out[hSize-1];
  1062.     x[2*hSize-1] = clip[ -CLIPMIN + e + x[2*hSize-1] ];
  1063.     x += 2 * xdim;
  1064.     idct_out += idim;
  1065.     // Process 2*vSize-2 rows
  1066.     for (i = 1; i < vSize; ++i) {
  1067.         e = (3 * idct_out[-idim] + 1 * idct_out[0] + 2) >> 2;
  1068.         x[-xdim] = clip[ -CLIPMIN + e + x[-xdim] ];
  1069.         e = (1 * idct_out[-idim] + 3 * idct_out[0] + 2) >> 2;
  1070.         x[0]     = clip[ -CLIPMIN + e + x[0] ];
  1071.         for (j = 1; j < hSize; ++j) {
  1072.             e = (9 * idct_out[j-1-idim] + 3 * idct_out[j-idim]
  1073.                + 3 * idct_out[j-1]      + 1 * idct_out[j] + 8) >> 4;
  1074.             x[2*j-1 - xdim] = clip[ -CLIPMIN + e + x[2*j-1 - xdim] ];
  1075.             e = (3 * idct_out[j-1-idim] + 9 * idct_out[j-idim]
  1076.                + 1 * idct_out[j-1]      + 3 * idct_out[j] + 8) >> 4;
  1077.             x[2*j - xdim]   = clip[ -CLIPMIN + e + x[2*j - xdim] ];
  1078.             e = (3 * idct_out[j-1-idim] + 1 * idct_out[j-idim]
  1079.                + 9 * idct_out[j-1]      + 3 * idct_out[j] + 8) >> 4;
  1080.             x[2*j-1]        = clip[ -CLIPMIN + e + x[2*j-1] ];
  1081.             e = (1 * idct_out[j-1-idim] + 3 * idct_out[j-idim]
  1082.                + 3 * idct_out[j-1]      + 9 * idct_out[j] + 8) >> 4;
  1083.             x[2*j]          = clip[ -CLIPMIN + e + x[2*j] ];
  1084.         }
  1085.         e = (3 * idct_out[hSize-1-idim] + 1 * idct_out[hSize-1] + 2) >> 2;
  1086.         x[2*hSize-1-xdim] = clip[ -CLIPMIN + e + x[2*hSize-1-xdim] ];
  1087.         e = (1 * idct_out[hSize-1-idim] + 3 * idct_out[hSize-1] + 2) >> 2;
  1088.         x[2*hSize-1]      = clip[ -CLIPMIN + e + x[2*hSize-1] ];
  1089.         x += 2 * xdim;
  1090.         idct_out += idim;
  1091.     }
  1092.     // Handle bottom border
  1093.     x -= xdim;
  1094.     idct_out -= idim;
  1095.     e = idct_out[0];
  1096.     x[0] = clip[ -CLIPMIN + e + x[0] ];
  1097.     for (j = 1; j < hSize; ++j) {
  1098.         e = (3 * idct_out[j-1] + 1 * idct_out[j] + 2) >> 2;
  1099.         x[2*j-1] = clip[ -CLIPMIN + e + x[2*j-1] ];
  1100.         e = (1 * idct_out[j-1] + 3 * idct_out[j] + 2) >> 2;
  1101.         x[2*j]   = clip[ -CLIPMIN + e + x[2*j] ];
  1102.     }
  1103.     e = idct_out[hSize-1];
  1104.     x[2*hSize-1] = clip[ -CLIPMIN + e + x[2*hSize-1] ];
  1105. }
  1106. #endif