Recongob.c
上传用户:dangjiwu
上传日期:2013-07-19
资源大小:42019k
文件大小:49k
源码类别:

Symbian

开发平台:

Visual C++

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