Recongob.c
上传用户:zhongxx05
上传日期:2007-06-06
资源大小:33641k
文件大小:48k
- /* ***** BEGIN LICENSE BLOCK *****
- * Version: RCSL 1.0/RPSL 1.0
- *
- * Portions Copyright (c) 1995-2002 RealNetworks, Inc. All Rights Reserved.
- *
- * The contents of this file, and the files included with this file, are
- * subject to the current version of the RealNetworks Public Source License
- * Version 1.0 (the "RPSL") available at
- * http://www.helixcommunity.org/content/rpsl unless you have licensed
- * the file under the RealNetworks Community Source License Version 1.0
- * (the "RCSL") available at http://www.helixcommunity.org/content/rcsl,
- * in which case the RCSL will apply. You may also obtain the license terms
- * directly from RealNetworks. You may not use this file except in
- * compliance with the RPSL or, if you have a valid RCSL with RealNetworks
- * applicable to this file, the RCSL. Please see the applicable RPSL or
- * RCSL for the rights, obligations and limitations governing use of the
- * contents of the file.
- *
- * This file is part of the Helix DNA Technology. RealNetworks is the
- * developer of the Original Code and owns the copyrights in the portions
- * it created.
- *
- * This file, and the files included with this file, is distributed and made
- * available on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
- * EXPRESS OR IMPLIED, AND REALNETWORKS HEREBY DISCLAIMS ALL SUCH WARRANTIES,
- * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, FITNESS
- * FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
- *
- * Technology Compatibility Kit Test Suite(s) Location:
- * http://www.helixcommunity.org/content/tck
- *
- * Contributor(s):
- *
- * ***** END LICENSE BLOCK ***** */
- #include "hxtypes.h"
- #ifdef _MACINTOSH
- #include <string.h> // for memset
- #endif
- //#include <string.h>
- //#include <stdio.h>
- #include <stdlib.h>
- #include "dllindex.h"
- #include "h261defs.h"
- #include "h261func.h"
- #include "h263plus.h"
- extern S16 Recon [QUANT_MAX - QUANT_MIN + 1] [N_SYM_INDICES];
- //#define DISPLAY_DIFFERENCE // Display quantized pred. error (don't use prev. frame)
- #ifdef TESTING
- #define CHECKSYM(a) a // Check symbol types to verify decoder state tables
- #else
- #define CHECKSYM(a) // Don't check symbol types
- #endif
- #define GRAY (128)
- #ifdef DO_H263_PLUS
- extern void PredBframePlus( MACROBLOCK_DESCR * mb, // Macroblock to be predicted
- PICTURE * prevPic, // Prev. picture (forward pred)
- PICTURE * nextPic, // Next P-picture (backward pred)
- PICTURE * Bpic // Output picture where pred is placed
- );
- #endif
- // Declarations of local functions
- static void reconBframe( MACROBLOCK_DESCR * mb, PICTURE * Bpic );
- static void gray_mb( MACROBLOCK_DESCR * mb, PICTURE * pic );
- static void fill_mb( MACROBLOCK_DESCR * mb, PICTURE * pic, PIXEL value );
- #ifdef DO_H263_PLUS
- static void idct32x32( MACROBLOCK_DESCR * mb, // Macroblock to be reconstructed
- PICTURE * tempPic, // Store 16-bit IDCT values here
- int intra // INTER block if zero, otherwise INTRA
- );
- static void filtAddClip32x32( MACROBLOCK_DESCR * mb,// Macroblock to be reconstructed
- PICTURE * pic, // Input: motion-comp prediction w/ filtered
- // intra borders; output: reconstr. picture
- PICTURE * tempPic // 16-bit IDCT values
- );
- static void filtAddClip( PIXEL x[], int xdim, // Output pixels
- S16 idct_out[], int idim, // Input IDCT values
- int hSize, int vSize // Input block size for IDCT values
- );
- #endif
- // ReconGob - Reconstruct one GOB of a picture
- // state->i > 0 indicates that we are reentering after previous timeout
- extern int ReconGob( GOB_DESCR * gob, MACROBLOCK_DESCR mb[],
- PICTURE * prev_pic, PICTURE * pic, PICTURE * Bpic,
- int advancedPred, int PBframe, int PBframeCap, int reducedResUpdate,
- int advancedIntraMode, H261DecState *state, int maxComp )
- #define CLEAN NO
- {
- int mbnum, i, col, dummy[4], reconBflag;
- int intra;
- PICTURE *tempPic;
- CHECKSYM( char msg[120]; ) /* Flawfinder: ignore */
- if (PBframe && PBframeCap) {
- reconBflag = 1; // Reconstruct B frame
- } else {
- reconBflag = 0; // Don't do B frame
- }
- tempPic = Bpic; // Use as work array in Reduced-res. Update mode
- if (state->i > 0) {
- // We timed out last time: restore state
- i = state->i;
- mbnum = state->mbnum;
- col = state->col;
- } else {
- // Reset state
- i = 0;
- mbnum = gob->first_col + gob->first_row * gob->mb_offset;
- col = gob->first_col; // Used to check when we reach end of line
- }
- #ifndef DISPLAY_DIFFERENCE // Do proper reconstruction
- if (pic->y.nhor == prev_pic->y.nhor && pic->y.nvert == prev_pic->y.nvert) {
- // Size of prev_pic is OK; use it if specified
- while (i < gob->num_mb) {
- //printf("recon_gob: mbnum = %d type = %dn", mbnum, mb[mbnum].mtype);
- switch (mb[mbnum].mtype) {
- case MTYPE_SKIP:
- mb[mbnum].mv_x = 0;
- mb[mbnum].mv_y = 0;
- if (reducedResUpdate) {
- MotionComp32x32( &mb[mbnum], prev_pic, pic);
- if (advancedPred) {
- Overlap32x32( &mb[mbnum], prev_pic, pic,
- gob->mb_width, gob->mb_offset, dummy );
- }
- } else {
- MotionComp( &mb[mbnum], prev_pic, pic);
- if (advancedPred) {
- OverlapMC( &mb[mbnum], PBframe, prev_pic, pic,
- gob->mb_width, gob->mb_offset, dummy );
- }
- if (reconBflag) { // Repeat prev. picture in B frame
- MotionComp( &mb[mbnum], prev_pic, Bpic );
- }
- }
- break;
-
- case MTYPE263_INTER:
- case MTYPE263_INTER_Q:
- case MTYPE263_INTER4V:
- if (reducedResUpdate) {
- MotionComp32x32( &mb[mbnum], prev_pic, pic);
- if (advancedPred) {
- Overlap32x32( &mb[mbnum], prev_pic, pic,
- gob->mb_width, gob->mb_offset, dummy );
- state->actComp += 4; // Increment computation measure
- }
- intra = NO;
- ReconReducedResMb( &mb[mbnum], pic, intra, tempPic );
- state->actComp += 4; // Increment computation measure
- } else {
- MotionComp263( &mb[mbnum], prev_pic, pic);
- if (advancedPred) {
- OverlapMC( &mb[mbnum], PBframe, prev_pic, pic,
- gob->mb_width, gob->mb_offset, dummy );
- ++state->actComp; // Increment computation measure
- }
- ReconInter( &mb[mbnum], pic, CLEAN);
- ++state->actComp; // Increment computation measure
- if (reconBflag) { // Reconstruct B frame
- if(PBframe == H263PLUS_IMPROVED_PBFRAME_MODE) {
- PredBframePlus( &mb[mbnum], prev_pic, pic, Bpic );
- } else {
- PredBframe( &mb[mbnum], prev_pic, pic, Bpic );
- }
- reconBframe( &mb[mbnum], Bpic );
- ++state->actComp; // Increment computation measure
- }
- }
- break;
- case MTYPE263_INTRA:
- case MTYPE263_INTRA_Q:
- if (reducedResUpdate) {
- Fill32x32( &mb[mbnum], pic, 0 );
- intra = YES;
- ReconReducedResMb( &mb[mbnum], pic, intra, tempPic );
- state->actComp += 4; // Increment computation measure
- } else {
- if(advancedIntraMode)
- ReconAdvancedIntra( &mb[mbnum], pic, CLEAN );
- else
- ReconIntra( &mb[mbnum], pic, CLEAN );
- ++state->actComp; // Increment computation measure
- if (reconBflag) { // Reconstruct B frame
- if(PBframe==H263PLUS_IMPROVED_PBFRAME_MODE) {
- PredBframePlus( &mb[mbnum], prev_pic, pic, Bpic );
- } else {
- PredBframe( &mb[mbnum], prev_pic, pic, Bpic );
- }
- reconBframe( &mb[mbnum], Bpic );
- ++state->actComp; // Increment computation measure
- }
- }
- break;
-
- case MTYPE_INTER:
- case MTYPE_INTER_MQUANT:
- mb[mbnum].mv_x = 0;
- mb[mbnum].mv_y = 0;
- MotionComp( &mb[mbnum], prev_pic, pic);
- ReconInter( &mb[mbnum], pic, CLEAN);
- ++state->actComp; // Increment computation measure
- break;
- case MTYPE_MCFILT_CBP:
- case MTYPE_MCFILT_MQUANT:
- LoopFilter( &mb[mbnum], prev_pic, pic);
- ReconInter( &mb[mbnum], pic, CLEAN);
- state->actComp += 2; // Increment computation measure
- break;
- case MTYPE_MCFILT_NOCBP:
- LoopFilter( &mb[mbnum], prev_pic, pic);
- ++state->actComp; // Increment computation measure
- break;
- case MTYPE_INTRA:
- case MTYPE_INTRA_MQUANT:
- //printf("Calling ReconIntra, mbnum = %d n", mbnum);
- ReconIntra( &mb[mbnum], pic, CLEAN );
- ++state->actComp; // Increment computation measure
- break;
- case MTYPE_MC_CBP:
- case MTYPE_MC_MQUANT:
- MotionComp( &mb[mbnum], prev_pic, pic);
- ReconInter( &mb[mbnum], pic, CLEAN);
- ++state->actComp; // Increment computation measure
- break;
- case MTYPE_MC_NOCBP:
- MotionComp( &mb[mbnum], prev_pic, pic);
- break;
- default:
- CHECKSYM( sprintf( msg, "PROGRAM ERROR: MTYPE = %d in recon_gob", mb[mbnum].mtype); /* Flawfinder: ignore */
- H261ErrMsg( msg );
- state->i = 0; // Indicate that we finished without timing out
- return( H261_ERROR ); )
- break;
- }
- i++, mbnum++;
- col++;
- if (col == gob->mb_width) { // Start on next row of macroblocks
- mbnum += gob->mb_offset - gob->mb_width;
- col = 0;
- }
- if (maxComp > 0 && state->actComp >= maxComp) {
- // We have timed out: save state and return
- state->i = i;
- state->mbnum= mbnum;
- state->col = col;
- return OK;
- }
- }
- state->i = 0; // Indicate that we finished without timing out
- return (OK);
- } else
- #endif
- { // Don't use prev_pic, i.e., reconstruct difference image
- while (i < gob->num_mb) {
- switch (mb[mbnum].mtype) {
- case MTYPE_SKIP:
- case MTYPE_MCFILT_NOCBP:
- case MTYPE_MC_NOCBP:
- if (reducedResUpdate) {
- Fill32x32( &mb[mbnum], pic, GRAY);
- } else {
- gray_mb( &mb[mbnum], pic);
- if (reconBflag) { // Reconstruct B frame
- gray_mb( &mb[mbnum], Bpic );
- }
- }
- break;
- case MTYPE263_INTER:
- case MTYPE263_INTER_Q:
- case MTYPE263_INTER4V:
- case MTYPE_INTER:
- case MTYPE_INTER_MQUANT:
- case MTYPE_MCFILT_CBP:
- case MTYPE_MCFILT_MQUANT:
- case MTYPE_MC_CBP:
- case MTYPE_MC_MQUANT:
- if (reducedResUpdate) {
- Fill32x32( &mb[mbnum], pic, GRAY);
- intra = NO;
- ReconReducedResMb( &mb[mbnum], pic, intra, tempPic );
- state->actComp += 4; // Increment computation measure
- } else {
- gray_mb( &mb[mbnum], pic);
- ReconInter( &mb[mbnum], pic, CLEAN);
- ++state->actComp; // Increment computation measure
- if (reconBflag) { // Reconstruct B frame
- gray_mb( &mb[mbnum], Bpic );
- reconBframe( &mb[mbnum], Bpic );
- }
- }
- break;
- case MTYPE263_INTRA:
- case MTYPE263_INTRA_Q:
- case MTYPE_INTRA:
- case MTYPE_INTRA_MQUANT:
- if (reducedResUpdate) {
- Fill32x32( &mb[mbnum], pic, 0 );
- intra = YES;
- ReconReducedResMb( &mb[mbnum], pic, intra, tempPic );
- state->actComp += 4; // Increment computation measure
- } else {
- if(advancedIntraMode)
- ReconAdvancedIntra( &mb[mbnum], pic, CLEAN );
- else
- ReconIntra( &mb[mbnum], pic, CLEAN );
- ++state->actComp; // Increment computation measure
- if (reconBflag) { // Reconstruct B frame
- gray_mb( &mb[mbnum], Bpic );
- reconBframe( &mb[mbnum], Bpic );
- }
- }
- break;
- default:
- CHECKSYM( sprintf( msg, "PROGRAM ERROR: MTYPE = %d in recon_gob", mb[mbnum].mtype); /* Flawfinder: ignore */
- H261ErrMsg( msg );
- state->i = 0; // Indicate that we finished without timing out
- return( H261_ERROR ); )
- break;
- }
- i++, mbnum++;
- col++;
- if (col == gob->mb_width) { // Start on next row of macroblocks
- mbnum += gob->mb_offset - gob->mb_width;
- col = 0;
- }
- if (maxComp > 0 && state->actComp >= maxComp) {
- // We have timed out: save state and return
- state->i = i;
- state->mbnum= mbnum;
- state->col = col;
- return H261_ERROR;
- }
- }
- state->i = 0; // Indicate that we finished without timing out
- return (H261_ERROR);
- }
- }
- // Reconstruct GOB by repeating previous picture
- extern int ConcealGob( GOB_DESCR * gob, MACROBLOCK_DESCR mb[], int reducedResUpdate,
- PICTURE * prev_pic, PICTURE * pic )
- {
- int mbnum, i, col;
- i = 0;
- mbnum = gob->first_col + gob->first_row * gob->mb_offset;
- col = gob->first_col; // Used to check when we reach end of line
- if (pic->y.nhor == prev_pic->y.nhor && pic->y.nvert == prev_pic->y.nvert) {
- // Size of prev_pic is OK; use it for new picture
- while (i < gob->num_mb) {
- mb[mbnum].mv_x = 0;
- mb[mbnum].mv_y = 0;
- if (reducedResUpdate) {
- MotionComp32x32( &mb[mbnum], prev_pic, pic);
- } else {
- MotionComp( &mb[mbnum], prev_pic, pic);
- }
- i++, mbnum++;
- col++;
- if (col == gob->mb_width) { // Start on next row of macroblocks
- mbnum += gob->mb_offset - gob->mb_width;
- col = 0;
- }
- }
- return (OK);
- } else { // Paint gray
- while (i < gob->num_mb) {
- if (reducedResUpdate) {
- Fill32x32( &mb[mbnum], pic, GRAY);
- } else {
- gray_mb( &mb[mbnum], pic);
- }
- i++, mbnum++;
- col++;
- if (col == gob->mb_width) { // Start on next row of macroblocks
- mbnum += gob->mb_offset - gob->mb_width;
- col = 0;
- }
- }
- return (H261_ERROR);
- }
- }
- // ReconIntra
- extern void ReconIntra( MACROBLOCK_DESCR * mb, PICTURE * pic, int clean)
- {
- int row, col, offset;
- PIXEL * pixel0;
- S16 * recon_tab;
- recon_tab = Recon[mb->quant - QUANT_MIN];
- col = 16 * mb->x;
- row = 16 * mb->y;
- /*{
- int isym;
- printf("ReconIntra: x = %d y = %dn", col, row);
- printf("nsym = %d %d %d %d %d %d n", mb->block[0].nsym,
- mb->block[1].nsym, mb->block[2].nsym, mb->block[3].nsym,
- mb->block[4].nsym, mb->block[5].nsym);
- printf("Symbol number to print: ");
- scanf("%d", &isym);
- while (isym > 0) {
- printf("Luma 1: ");
- printsym( *(mb->block[0].sym + isym - 1) ); printf("n");
- printf("Luma 2: ");
- printsym( *(mb->block[1].sym + isym - 1) ); printf("n");
- printf("Luma 3: ");
- printsym( *(mb->block[2].sym + isym - 1) ); printf("n");
- printf("Luma 4: ");
- printsym( *(mb->block[3].sym + isym - 1) ); printf("n");
- printf("Symbol number to print: ");
- scanf("%d", &isym);
- }
- }*/
- pixel0 = pic->y.ptr + col + row * pic->y.hoffset;
- //printf("Luma block 1 n");
- Idct2( mb->block[0].sym, mb->block[0].nsym, pixel0,
- pic->y.hoffset, recon_tab, clean);
- //printf("Luma block 2 n");
- Idct2( mb->block[1].sym, mb->block[1].nsym, pixel0 + 8,
- pic->y.hoffset, recon_tab, clean);
- //printf("Luma block 3 n");
- Idct2( mb->block[2].sym, mb->block[2].nsym, pixel0 + 8 * pic->y.hoffset,
- pic->y.hoffset, recon_tab, clean);
- //printf("Luma block 4 n");
- Idct2( mb->block[3].sym, mb->block[3].nsym, pixel0 + 8 + 8 * pic->y.hoffset,
- pic->y.hoffset, recon_tab, clean);
- if (pic->color) {
- // Assuming same offset for Cr and Cb
- col = 8 * mb->x;
- row = 8 * mb->y;
- offset = col + row * pic->cb.hoffset;
- pixel0 = pic->cb.ptr + offset;
- //printf("CB block n");
- Idct2( mb->block[4].sym, mb->block[4].nsym, pixel0,
- pic->cb.hoffset, recon_tab, clean);
- pixel0 = pic->cr.ptr + offset;
- //printf("CR block n");
- Idct2( mb->block[5].sym, mb->block[5].nsym, pixel0,
- pic->cr.hoffset, recon_tab, clean);
- }
- return;
- }
- #ifdef DO_H263_PLUS
- #define MAX_MACROBLKS_PER_ROW (88) /* Up to 16CIF (1408 pixels/line) */
- #define UPPER_LUMA_BLOCK_CACHE_LENGTH (2 * MAX_MACROBLKS_PER_ROW)
- #define UPPER_CHROMA_BLOCK_CACHE_LENGTH (MAX_MACROBLKS_PER_ROW)
- // Storage for the first rows of the lower 8x8 blocks of the intra macroblocks in the previous GOB.
- // Refer to these for appropriate predictions. For right now we make this static
- // data, but should really allocate it on the heap only if advanced intra is being
- // used?
- static S8 upperLumaBlockCache[UPPER_LUMA_BLOCK_CACHE_LENGTH][8]; // allocated for CIF video!
- static S8 upperCrBlockCache[UPPER_CHROMA_BLOCK_CACHE_LENGTH][8]; // allocated for CIF video!
- static S8 upperCbBlockCache[UPPER_CHROMA_BLOCK_CACHE_LENGTH][8]; // allocated for CIF video!
- // Storage for the first columns of the 8x8 blocks of the most recent intra macroblock.
- // Refer to these for appropriate predictions.
- static S8 leftLumaBlockCache[4][8];
- static S8 leftCrBlockCache[1][8];
- static S8 leftCbBlockCache[1][8];
- static U8 upperDCLumaBlockCache[UPPER_LUMA_BLOCK_CACHE_LENGTH][1];
- static U8 upperDCCrBlockCache[UPPER_CHROMA_BLOCK_CACHE_LENGTH][1];
- static U8 upperDCCbBlockCache[UPPER_CHROMA_BLOCK_CACHE_LENGTH][1];
- static U8 leftDCLumaBlockCache[4][1];
- static U8 leftDCCrBlockCache[1];
- static U8 leftDCCbBlockCache[1];
- static void InitializeLeftCache(int qp)
- {
- int i;
- for(i=0; i<4; i++) {
- //leftDCLumaBlockCache[i][0] = ( U8 )128; // MPEG4 style boundary conditions
- leftDCLumaBlockCache[i][0] = ( U8 )(512/qp); // H.263+ style boundary conditions
- memset(&leftLumaBlockCache[i][1], 0, 7);
- }
- leftDCCrBlockCache[0] = ( U8 )(512/qp); // H.263+ style boundary conditions
- memset(&leftCrBlockCache[0][1], 0, 7);
-
- leftDCCbBlockCache[0] = ( U8 )(512/qp); // H.263+ style boundary conditions
- memset(&leftCbBlockCache[0][1], 0, 7);
- }
- static void InitializeUpperCache(int qp, int i)
- {
- //upperDCLumaBlockCache[2*i][0] = ( U8 )128; // MPEG4 style boundary conditions
- upperDCLumaBlockCache[2*i][0] = ( U8 )(512/qp); // H.263+ style boundary conditions
- memset(&upperLumaBlockCache[2*i][1], 0, 7);
- //upperDCLumaBlockCache[2*i+1][0] = ( U8 )128; // MPEG4 style boundary conditions
- upperDCLumaBlockCache[2*i+1][0] = ( U8 )(512/qp); // H.263+ style boundary conditions
- memset(&upperLumaBlockCache[2*i+1][1], 0, 7);
-
- //upperDCCrBlockCache[i][0] = ( U8 )128; // MPEG4 style boundary conditions
- upperDCCrBlockCache[i][0] = ( U8 )(512/qp); // H.263+ style boundary conditions
- memset(&upperCrBlockCache[i][1], 0, 7);
-
- //upperDCCbBlockCache[i][0] = ( U8 )128; // MPEG4 style boundary conditions
- upperDCCbBlockCache[i][0] = ( U8 )(512/qp); // H.263+ style boundary conditions
- memset(&upperCbBlockCache[i][1], 0, 7);
- }
- #define INTRA(mb) (((mb).mtype >= MTYPE263_INTRA_MIN && (mb).mtype <= MTYPE263_INTRA_MAX) ? 1:0)
- extern void ReconAdvancedIntra( MACROBLOCK_DESCR * mb, PICTURE * pic, int clean)
- {
- int row, col, offset;
- PIXEL * pixel0;
- S16 * recon_tab;
- int predtype = mb->intra_mode;
- int fixedDC = mb->quant<8;
- int numhor=pic->y.nhor>>4; // number of mb per row
- // Ensure that we are not scribbling outside the allocated cache
- if (mb->x >= MAX_MACROBLKS_PER_ROW) return;
- // Reinitialize predictors if we're on a new row or if one of our abutting macroblocks
- // isn't intra
- if(mb->x == 0 || !INTRA(mb[-1])) {
- InitializeLeftCache(fixedDC ? 4 : mb->quant);
- }
- if(mb->y == 0 || !INTRA(mb[-numhor])) {
- InitializeUpperCache(fixedDC ? 4 : mb->quant, mb->x);
- }
- recon_tab = Recon[mb->quant - QUANT_MIN];
- col = 16 * mb->x;
- row = 16 * mb->y;
- /*{
- int isym;
- printf("ReconAdvancedIntra: x = %d y = %dn", col, row);
- printf("nsym = %d %d %d %d %d %d n", mb->block[0].nsym,
- mb->block[1].nsym, mb->block[2].nsym, mb->block[3].nsym,
- mb->block[4].nsym, mb->block[5].nsym);
- printf("Symbol number to print: ");
- scanf("%d", &isym);
- while (isym > 0) {
- printf("Luma 1: ");
- printsym( *(mb->block[0].sym + isym - 1) ); printf("n");
- printf("Luma 2: ");
- printsym( *(mb->block[1].sym + isym - 1) ); printf("n");
- printf("Luma 3: ");
- printsym( *(mb->block[2].sym + isym - 1) ); printf("n");
- printf("Luma 4: ");
- printsym( *(mb->block[3].sym + isym - 1) ); printf("n");
- printf("Symbol number to print: ");
- scanf("%d", &isym);
- }
- }*/
- pixel0 = pic->y.ptr + col + row * pic->y.hoffset;
- //printf("Luma block 1 n");
- Idct2AdvancedIntra( mb->block[0].sym, mb->block[0].nsym, pixel0,
- pic->y.hoffset, recon_tab,
- upperDCLumaBlockCache[2*mb->x][0], upperLumaBlockCache[2*mb->x], // DC and AC pred for row
- upperDCLumaBlockCache[2*mb->x],upperLumaBlockCache[2*mb->x], // DC and AC store for row
- leftDCLumaBlockCache[1][0], leftLumaBlockCache[1], // DC and AC pred for column
- leftDCLumaBlockCache[0], leftLumaBlockCache[0], // DC and AC store for column
- predtype, fixedDC,
- mb->x==0, mb->y==0); // can be on left or upper boundary
-
- //printf("Luma block 2 n");
- Idct2AdvancedIntra( mb->block[1].sym, mb->block[1].nsym, pixel0 + 8,
- pic->y.hoffset, recon_tab,
- upperDCLumaBlockCache[2*mb->x+1][0], upperLumaBlockCache[2*mb->x+1], // DC and AC pred for row
- upperDCLumaBlockCache[2*mb->x+1],upperLumaBlockCache[2*mb->x+1], // DC and AC store for row
- leftDCLumaBlockCache[0][0], leftLumaBlockCache[0], // DC and AC pred for column
- leftDCLumaBlockCache[1], leftLumaBlockCache[1], // DC and AC store for column
- predtype, fixedDC,
- FALSE, mb->y==0); // can only be on upper boudary
- //printf("Luma block 3 n");
- Idct2AdvancedIntra( mb->block[2].sym, mb->block[2].nsym, pixel0 + 8 * pic->y.hoffset,
- pic->y.hoffset, recon_tab,
- upperDCLumaBlockCache[2*mb->x][0], upperLumaBlockCache[2*mb->x], // DC and AC pred for row
- upperDCLumaBlockCache[2*mb->x],upperLumaBlockCache[2*mb->x], // DC and AC store for row
- leftDCLumaBlockCache[3][0], leftLumaBlockCache[3], // DC and AC pred for column
- leftDCLumaBlockCache[2], leftLumaBlockCache[2], // DC and AC store for column
- predtype, fixedDC,
- mb->x==0, FALSE); // can only be on left boundary
- //printf("Luma block 4 n");
- Idct2AdvancedIntra( mb->block[3].sym, mb->block[3].nsym, pixel0 + 8 + 8 * pic->y.hoffset,
- pic->y.hoffset, recon_tab,
- upperDCLumaBlockCache[2*mb->x+1][0], upperLumaBlockCache[2*mb->x+1], // DC and AC pred for row
- upperDCLumaBlockCache[2*mb->x+1],upperLumaBlockCache[2*mb->x+1], // DC and AC store for row
- leftDCLumaBlockCache[2][0], leftLumaBlockCache[2], // DC and AC pred for column
- leftDCLumaBlockCache[3], leftLumaBlockCache[3], // DC and AC store for column
- predtype, fixedDC,
- FALSE, FALSE); // can't be on left or upper boundary
-
- if (pic->color) {
- // Assuming same offset for Cr and Cb
- col = 8 * mb->x;
- row = 8 * mb->y;
- offset = col + row * pic->cb.hoffset;
- pixel0 = pic->cb.ptr + offset;
- //printf("CB block n");
- Idct2AdvancedIntra( mb->block[4].sym, mb->block[4].nsym, pixel0,
- pic->cb.hoffset, recon_tab,
- upperDCCbBlockCache[mb->x][0], upperCbBlockCache[mb->x], // DC and AC pred for row
- upperDCCbBlockCache[mb->x],upperCbBlockCache[mb->x], // DC and AC store for row
- leftDCCbBlockCache[0], leftCbBlockCache[0], // DC and AC pred for column
- leftDCCbBlockCache, leftCbBlockCache[0], // DC and AC store for column
- predtype, fixedDC,
- mb->x==0, mb->y==0); // what boundaries are we on?
-
- pixel0 = pic->cr.ptr + offset;
- //printf("CR block n");
- Idct2AdvancedIntra( mb->block[5].sym, mb->block[5].nsym, pixel0,
- pic->cr.hoffset, recon_tab,
- upperDCCrBlockCache[mb->x][0], upperCrBlockCache[mb->x], // DC and AC pred for row
- upperDCCrBlockCache[mb->x],upperCrBlockCache[mb->x], // DC and AC store for row
- leftDCCrBlockCache[0], leftCrBlockCache[0], // DC and AC pred for column
- leftDCCrBlockCache, leftCrBlockCache[0], // DC and AC store for column
- predtype, fixedDC,
- mb->x==0, mb->y==0); // what boundaries are we on?
- }
- return;
- }
- #endif
- // ReconInter
- extern void ReconInter( MACROBLOCK_DESCR * mb, PICTURE * pic, int clean )
- {
- int row, col, offset ;
- PIXEL * pixel0;
- S16 * recon_tab;
- recon_tab = Recon[mb->quant - QUANT_MIN];
- col = 16 * mb->x;
- row = 16 * mb->y;
- /* {
- int isym;
- printf("ReconInter: x = %d y = %dn", col, row);
- printf("nsym = %d %d %d %d %d %d n", mb->block[0].nsym,
- mb->block[1].nsym, mb->block[2].nsym, mb->block[3].nsym,
- mb->block[4].nsym, mb->block[5].nsym);
- printf("Symbol number to print: ");
- scanf("%d", &isym);
- while (isym > 0) {
- printf("Luma 1: ");
- printsym( *(mb->block[0].sym + isym - 1) ); printf("n");
- printf("Luma 2: ");
- printsym( *(mb->block[1].sym + isym - 1) ); printf("n");
- printf("Luma 3: ");
- printsym( *(mb->block[2].sym + isym - 1) ); printf("n");
- printf("Luma 4: ");
- printsym( *(mb->block[3].sym + isym - 1) ); printf("n");
- printf("Symbol number to print: ");
- scanf("%d", &isym);
- }
- }
- */
- pixel0 = pic->y.ptr + col + row * pic->y.hoffset;
- // #define DB_DUMP_MACROBLOCK
- #ifdef DB_DUMP_MACROBLOCK
- {
- static char foo[256]; /* Flawfinder: ignore */
- static char dump=0;
- int dbi,dbj;
- if(dump) {
- SafeSprintf(foo, 256, "Reference Block (from ReconInter) (%d, %d)n", mb->x, mb->y);
- OutputDebugString(foo);
- for(dbi=0;dbi<16;dbi++)
- {
- foo[0] = ' ';
- for(dbj=0;dbj<16;dbj++)
- {
- SafeSprintf(foo+strlen(foo), 256-strlen(foo), "%d ", pixel0[dbi*pic->y.hoffset + dbj]);
- }
- SafeStrCat(foo, "n", 256);
- OutputDebugString(foo);
- }
- }
- }
- #endif
- if (mb->block[0].nsym > 0) {
- //printf("Luma block 1 n");
- Idct2Sum( mb->block[0].sym, mb->block[0].nsym, pixel0,
- pic->y.hoffset, recon_tab, clean);
- }
- if (mb->block[1].nsym > 0) {
- //printf("Luma block 2 n");
- Idct2Sum( mb->block[1].sym, mb->block[1].nsym, pixel0 + 8,
- pic->y.hoffset, recon_tab, clean);
- }
- if (mb->block[2].nsym > 0) {
- //printf("Luma block 3 n");
- Idct2Sum( mb->block[2].sym, mb->block[2].nsym, pixel0 + 8 * pic->y.hoffset,
- pic->y.hoffset, recon_tab, clean);
- }
- if (mb->block[3].nsym > 0) {
- //printf("Luma block 4 n");
- Idct2Sum( mb->block[3].sym, mb->block[3].nsym, pixel0 + 8 + 8 * pic->y.hoffset,
- pic->y.hoffset, recon_tab, clean);
- }
- if (pic->color && (mb->block[4].nsym > 0 || mb->block[5].nsym > 0)) {
- // Assuming same offset for Cr and Cb
- col = 8 * mb->x;
- row = 8 * mb->y;
- offset = col + row * pic->cb.hoffset;
- if (mb->block[4].nsym > 0) {
- pixel0 = pic->cb.ptr + offset;
- //printf("CB block n");
- Idct2Sum( mb->block[4].sym, mb->block[4].nsym, pixel0,
- pic->cb.hoffset, recon_tab, clean);
- }
- if (mb->block[5].nsym > 0) {
- pixel0 = pic->cr.ptr + offset;
- //printf("CR block n");
- Idct2Sum( mb->block[5].sym, mb->block[5].nsym, pixel0,
- pic->cr.hoffset, recon_tab, clean);
- }
- }
- //#define DB_DUMP_MACROBLOCK
- #ifdef DB_DUMP_MACROBLOCK
- {
- static char foo[256]; /* Flawfinder: ignore */
- static char dump=0;
- int dbi,dbj;
- if(dump) {
- pixel0 = pic->y.ptr + col + row * pic->y.hoffset;
- SafeSprintf(foo, 256, "Reconstructed Macroblock (%d, %d)n", mb->x, mb->y);
- OutputDebugString(foo);
- for(dbi=0;dbi<16;dbi++)
- {
- foo[0] = ' ';
- for(dbj=0;dbj<16;dbj++)
- {
- SafeSprintf(foo+strlen(foo), 256-strlen(foo), "%d ", pixel0[dbi*pic->y.hoffset + dbj]);
- }
- SafeStrCat(foo, "n", 256);
- OutputDebugString(foo);
- }
- }
- }
- #endif
- return;
- }
- // reconBframe - Reconstruct B-frame prediction error and add to prediction
- static void reconBframe( MACROBLOCK_DESCR * mb, PICTURE * Bpic )
- {
- int i;
- U8 saveQuant, saveCbp;
- SYMBOL *saveSym[6];
- int saveNsym[6];
- if (BFRAME_HAS_CBP(mb)) {
- // Set quant, cbp, and block[] to hold values for B-frame
- saveQuant = mb->quant;
- mb->quant = mb->Bquant;
- saveCbp = mb->cbp;
- mb->cbp = mb->cbpB;
- for (i = 0; i < 6; ++i) {
- saveSym[i] = mb->block[i].sym;
- mb->block[i].sym = mb->Bblock[i].sym;
- saveNsym[i] = mb->block[i].nsym;
- mb->block[i].nsym = mb->Bblock[i].nsym;
- }
- // Do reconstruction
- ReconInter( mb, Bpic, CLEAN );
- // Restore parameters (if needed for statistics)
- mb->quant = saveQuant;
- mb->cbp = saveCbp;
- for (i = 0; i < 6; ++i) {
- mb->block[i].sym = saveSym[i];
- mb->block[i].nsym = saveNsym[i];
- }
- }
- }
- // gray_mb - fill macroblock with gray (value 128); assumes that pic is word-aligned
- static void gray_mb( MACROBLOCK_DESCR * mb, PICTURE * pic )
- {
- fill_mb( mb, pic, GRAY );
- }
- // fill_mb - fill macroblock with constant color; assumes that pic is word-aligned
- static void fill_mb( MACROBLOCK_DESCR * mb, PICTURE * pic, PIXEL value )
- {
- int row, col, i;
- union { // Write words to speed up routine
- PIXEL * pix;
- U32 * word;
- } pixel;
- U32 * dest;
- U32 dValue;
- dValue = value | (value << 8) | (value << 16) | (value << 24);
- col = 16 * mb->x;
- row = 16 * mb->y;
- #ifdef DO_H263_PLUS
- if (col >= pic->y.nhor || row >= pic->y.nvert)
- return; // Inactive part of Macroblock
- #endif
- pixel.pix = pic->y.ptr + col + row * pic->y.hoffset;
- for (i = 0; i < 16; i++) {
- for (dest = pixel.word; dest < pixel.word + 16/4; dest++) {
- *dest = dValue;
- }
- pixel.pix += pic->y.hoffset;
- }
- if (pic->color) {
- col = 8 * mb->x;
- row = 8 * mb->y;
- pixel.pix = pic->cb.ptr + col + row * pic->cb.hoffset;
- for (i = 0; i < 8; i++) {
- for (dest = pixel.word; dest < pixel.word + 8/4; dest++) {
- *dest = dValue;
- }
- pixel.pix += pic->cb.hoffset;
- }
- pixel.pix = pic->cr.ptr + col + row * pic->cr.hoffset;
- for (i = 0; i < 8; i++) {
- for (dest = pixel.word; dest < pixel.word + 8/4; dest++) {
- *dest = dValue;
- }
- pixel.pix += pic->cr.hoffset;
- }
- }
- return;
- }
- #ifdef DO_H263_PLUS
- /////////////////////////////////////////////////////////////////////////////////////////
- //////////// Functions for reconstruction in Reduced-resolution Update mode /////////////
- /////////////////////////////////////////////////////////////////////////////////////////
- // ReducedResMvComponent - Translate Reduced-res. motion vector component to representation
- // with one fractional bit. The input value is "rounded" half a pixel towards zero, e.g.,
- // input values: -2 -1 0 1 2 are
- // translated to: -1.5 -0.5 0 0.5 1.5,
- extern S8 ReducedResMvComponent( S8 x )
- {
- if (x > 0) {
- x = 2 * x - 1;
- } else if (x < 0) {
- x = 2 * x + 1;
- }
- return x;
- }
- // MotionComp32x32 - perform motion compensation for Reduced-res. Update mode
- extern void MotionComp32x32( MACROBLOCK_DESCR * mb, // Describes block to be motion-compensated
- PICTURE * prevPic, // Describes previous picture used to form MC
- PICTURE * pic // Output picture where MC block is placed
- )
- {
- int blk;
- // Save MTYPE and x/y position
- int saveType = mb->mtype;
- int saveX = mb->x;
- int saveY = mb->y;
- int saveMvX = mb->mv_x;
- int saveMvY = mb->mv_y;
- mb->mtype = MTYPE263_INTER;
- if (saveType != MTYPE263_INTER4V) {
- // Use same motion vector for all four quadrants
- for (blk = 0; blk < 4; ++blk) {
- mb->blkMvX[blk] = mb->mv_x;
- mb->blkMvY[blk] = mb->mv_y;
- }
- }
- // Upper Left 16x16
- mb->x = 2 * saveX;
- mb->y = 2 * saveY;
- mb->mv_x = ReducedResMvComponent( mb->blkMvX[UPPER_LEFT_BLK] );
- mb->mv_y = ReducedResMvComponent( mb->blkMvY[UPPER_LEFT_BLK] );
- MotionComp263( mb, prevPic, pic);
- // Upper Right 16x16
- mb->x = 2 * saveX + 1;
- if (16 * mb->x < pic->y.nhor) {
- mb->mv_x = ReducedResMvComponent( mb->blkMvX[UPPER_RIGHT_BLK] );
- mb->mv_y = ReducedResMvComponent( mb->blkMvY[UPPER_RIGHT_BLK] );
- MotionComp263( mb, prevPic, pic);
- }
- mb->y = 2 * saveY + 1;
- if (16 * mb->y < pic->y.nvert) {
- // Lower Left 16x16
- mb->x = 2 * saveX;
- mb->mv_x = ReducedResMvComponent( mb->blkMvX[LOWER_LEFT_BLK] );
- mb->mv_y = ReducedResMvComponent( mb->blkMvY[LOWER_LEFT_BLK] );
- MotionComp263( mb, prevPic, pic);
- // Lower Right 16x16
- mb->x = 2 * saveX + 1;
- if (16 * mb->x < pic->y.nhor) {
- mb->mv_x = ReducedResMvComponent( mb->blkMvX[LOWER_RIGHT_BLK] );
- mb->mv_y = ReducedResMvComponent( mb->blkMvY[LOWER_RIGHT_BLK] );
- MotionComp263( mb, prevPic, pic);
- }
- }
- // Restore MTYPE, x/y position, and motion vector
- mb->mtype = saveType;
- mb->x = saveX;
- mb->y = saveY;
- mb->mv_x = saveMvX;
- mb->mv_y = saveMvY;
- }
- // Overlap32x32 - Do overlapped motion comp. for luma (Reduced-res. Update mode)
- extern void Overlap32x32( MACROBLOCK_DESCR * mb, // Describes block to be motion-compensated
- PICTURE * prevPic, // Describes previous picture used to form MC
- PICTURE * pic, // Output picture where MC block is placed
- int mbWidth, // Macroblocks per row
- int mbOffset, // Row offset; (mb-mbOffset) is neighbor on top
- int overlap[4] // Returns YES or NO to indicate whether overlap
- // was done in each 8x8 subblock
- )
- {
- // Placeholder -- not yet implemented
- overlap[UPPER_LEFT_BLK] = NO;
- overlap[UPPER_RIGHT_BLK] = NO;
- overlap[LOWER_LEFT_BLK] = NO;
- overlap[LOWER_RIGHT_BLK] = NO;
- }
- // Fill32x32 - Fill Reduced-res. MB (32x32 block) with constant color
- extern void Fill32x32( MACROBLOCK_DESCR * mb, PICTURE * pic, PIXEL value )
- {
- // Get MB coordinates
- int saveX = mb->x;
- int saveY = mb->y;
- // Fill Upper Left 16x16
- mb->x = 2 * saveX;
- mb->y = 2 * saveY;
- fill_mb( mb, pic, value);
- // Fill Upper Right 16x16
- mb->x = 2 * saveX + 1;
- if (16 * mb->x < pic->y.nhor) {
- fill_mb( mb, pic, value);
- }
- mb->y = 2 * saveY + 1;
- if (16 * mb->y < pic->y.nvert) {
- // Fill Lower Left 16x16
- mb->x = 2 * saveX;
- fill_mb( mb, pic, value);
- // Fill Lower Right 16x16
- mb->x = 2 * saveX + 1;
- if (16 * mb->x < pic->y.nhor) {
- fill_mb( mb, pic, value);
- }
- }
- // Restore MB coordinates
- mb->x = saveX;
- mb->y = saveY;
- }
- // ReconReducedResMb - Reconstruct macroblock in Reduced-resolution Update mode
- extern void ReconReducedResMb( MACROBLOCK_DESCR * mb, // Macroblock to be reconstructed
- PICTURE * pic, // Input: motioncomp. prediction;
- // output: reconstr. picture
- int intra, // INTER block if zero, otherwise INTRA
- PICTURE * tempPic// Use for temporary storage
- )
- {
- // Perform IDCT of prediction error; use "first half" of tempPic for temporary storage
- idct32x32( mb, tempPic, intra );
- // Interpolate prediction error, add to motioncomp. prediction and clip to [0,255]
- filtAddClip32x32( mb, pic, tempPic );
- }
- // idct32x32 - Perform IDCT for 32x32 macroblock (Reduced-res. update mode)
- static void idct32x32( MACROBLOCK_DESCR * mb, // Macroblock to be reconstructed
- PICTURE * tempPic, // Store 16-bit IDCT values here
- int intra // INTER block if zero, otherwise INTRA
- )
- {
- int row, col, yHoffset, cHoffset, chromaPixels;
- S16 * pIdct;
- S16 * recon_tab;
- recon_tab = Recon[mb->quant - QUANT_MIN];
- // Reconstruct luminance
- // The PIXEL y[V][H] array is used as S16[V/2][H/2], i.e., only upper half is used
- col = 16 * mb->x;
- row = 16 * mb->y;
- yHoffset = tempPic->y.hoffset >> 1;
- pIdct = (S16 *)tempPic->y.ptr;
- pIdct += col + row * yHoffset;
- Idct2_s16( intra, mb->block[0].sym, mb->block[0].nsym,
- pIdct + 0 + 0 * yHoffset,
- yHoffset, recon_tab );
- if (2 * col + 16 < tempPic->y.nhor) {
- Idct2_s16( intra, mb->block[1].sym, mb->block[1].nsym,
- pIdct + 8 + 0 * yHoffset,
- yHoffset, recon_tab );
- }
- if (2 * row + 16 < tempPic->y.nvert) {
- Idct2_s16( intra, mb->block[2].sym, mb->block[2].nsym,
- pIdct + 0 + 8 * yHoffset,
- yHoffset, recon_tab );
- if (2 * col + 16 < tempPic->y.nhor) {
- Idct2_s16( intra, mb->block[3].sym, mb->block[3].nsym,
- pIdct + 8 + 8 * yHoffset,
- yHoffset, recon_tab );
- }
- }
- // Reconstruct chrominance
- // Ensure that we have memory for picture sizes that are
- // not multiples of 32, i.e., odd number of macroblocks. In that case, we will
- // throw away 4 chroma pixels on the right and/or bottom after the IDCT.
- // This routine assumes that the two VxH chroma arrays can be treated as one block of
- // memory starting at tempPic->cb.ptr and of size (V+8)/16 * (H+8)/16 * 256 bytes.
- // The current memory allocation done in initializePicture fulfills this as long
- // as each chroma array is at least 16x16 (2x2 macroblocks).
- if (tempPic->color) {
- col = 8 * mb->x;
- row = 8 * mb->y;
- chromaPixels = 8 * ((tempPic->cb.nhor + 8) >> 4);
- cHoffset = 2 * chromaPixels;
- pIdct = (S16 *)tempPic->cb.ptr;
- pIdct += col + row * cHoffset;
- //printf("CB block n");
- Idct2_s16( intra, mb->block[4].sym, mb->block[4].nsym, pIdct,
- cHoffset, recon_tab );
- // CR array is placed "to the right" of CB array
- //printf("CR block n");
- Idct2_s16( intra, mb->block[5].sym, mb->block[5].nsym, pIdct + chromaPixels,
- cHoffset, recon_tab );
- }
- }
- // filtAddClip32x32 - Interpolate, add & clip 32x32 macroblock (Reduced-res. update mode)
- static void filtAddClip32x32( MACROBLOCK_DESCR * mb,// Macroblock to be reconstructed
- PICTURE * pic, // Input: motion-comp prediction w/ filtered
- // intra borders; output: reconstr. picture
- PICTURE * tempPic // 16-bit IDCT values
- )
- {
- int row, col, offset, yHoffset, cHoffset, chromaPixels;
- int hSize, vSize;
- PIXEL * pixel0;
- S16 * pIdct;
- yHoffset = pic->y.hoffset >> 1;
- col = 16 * mb->x;
- row = 16 * mb->y;
- hSize = vSize = 16;
- if (2 * col + 16 >= pic->y.nhor)
- hSize = 8;
- if (2 * row + 16 >= pic->y.nvert)
- vSize = 8;
- // Interpolate, add, and clip
- pixel0 = pic->y.ptr + 2 * col + 2 * row * pic->y.hoffset;
- pIdct = (S16 *)tempPic->y.ptr;
- pIdct += col + row * yHoffset;
- filtAddClip( pixel0, pic->y.hoffset, pIdct, yHoffset, 8, 8 );
- if (hSize == 16)
- filtAddClip( pixel0 + 16, pic->y.hoffset, pIdct + 8, yHoffset, 8, 8 );
- if (vSize == 16) {
- pixel0 += 16 * pic->y.hoffset;
- pIdct += 8 * yHoffset;
- filtAddClip( pixel0, pic->y.hoffset, pIdct, yHoffset, 8, 8 );
- if (hSize == 16)
- filtAddClip( pixel0 + 16, pic->y.hoffset, pIdct + 8, yHoffset, 8, 8 );
- }
- if (pic->color) {
- chromaPixels = 8 * ((pic->cb.nhor + 8) >> 4);
- cHoffset = 2 * chromaPixels;
- offset = col + row * pic->cb.hoffset;
- pixel0 = pic->cb.ptr + offset;
- pIdct = (S16 *)tempPic->cb.ptr;
- pIdct += (col >> 1) + (row >> 1) * cHoffset;
- filtAddClip( pixel0, pic->cb.hoffset, pIdct,
- cHoffset, hSize>>1, vSize>>1 );
- pixel0 = pic->cr.ptr + offset;
- filtAddClip( pixel0, pic->cr.hoffset, pIdct + chromaPixels,
- cHoffset, hSize>>1, vSize>>1 );
- }
- }
- #define PIXEL_MIN 0
- #define PIXEL_MAX 255
- #define CLIPMARGIN 300
- #define CLIPMIN (PIXEL_MIN - CLIPMARGIN)
- #define CLIPMAX (PIXEL_MAX + CLIPMARGIN)
- extern PIXEL clip[(CLIPMAX-CLIPMIN+1)];
- // filtAddClip - interpolate IDCT output (typically 8x8), add to prediction (typ. 16x16),
- // and clip. Interpolation is only done within the block.
- static void filtAddClip( PIXEL x[], int xdim, // Output pixels
- S16 idct_out[], int idim, // Input IDCT values
- int hSize, int vSize // Input block size for IDCT values
- )
- {
- int i, j, e;
- // Handle top border
- e = idct_out[0];
- x[0] = clip[ -CLIPMIN + e + x[0] ];
- for (j = 1; j < hSize; ++j) {
- e = (3 * idct_out[j-1] + 1 * idct_out[j] + 2) >> 2;
- x[2*j-1] = clip[ -CLIPMIN + e + x[2*j-1] ];
- e = (1 * idct_out[j-1] + 3 * idct_out[j] + 2) >> 2;
- x[2*j] = clip[ -CLIPMIN + e + x[2*j] ];
- }
- e = idct_out[hSize-1];
- x[2*hSize-1] = clip[ -CLIPMIN + e + x[2*hSize-1] ];
- x += 2 * xdim;
- idct_out += idim;
- // Process 2*vSize-2 rows
- for (i = 1; i < vSize; ++i) {
- e = (3 * idct_out[-idim] + 1 * idct_out[0] + 2) >> 2;
- x[-xdim] = clip[ -CLIPMIN + e + x[-xdim] ];
- e = (1 * idct_out[-idim] + 3 * idct_out[0] + 2) >> 2;
- x[0] = clip[ -CLIPMIN + e + x[0] ];
- for (j = 1; j < hSize; ++j) {
- e = (9 * idct_out[j-1-idim] + 3 * idct_out[j-idim]
- + 3 * idct_out[j-1] + 1 * idct_out[j] + 8) >> 4;
- x[2*j-1 - xdim] = clip[ -CLIPMIN + e + x[2*j-1 - xdim] ];
- e = (3 * idct_out[j-1-idim] + 9 * idct_out[j-idim]
- + 1 * idct_out[j-1] + 3 * idct_out[j] + 8) >> 4;
- x[2*j - xdim] = clip[ -CLIPMIN + e + x[2*j - xdim] ];
- e = (3 * idct_out[j-1-idim] + 1 * idct_out[j-idim]
- + 9 * idct_out[j-1] + 3 * idct_out[j] + 8) >> 4;
- x[2*j-1] = clip[ -CLIPMIN + e + x[2*j-1] ];
- e = (1 * idct_out[j-1-idim] + 3 * idct_out[j-idim]
- + 3 * idct_out[j-1] + 9 * idct_out[j] + 8) >> 4;
- x[2*j] = clip[ -CLIPMIN + e + x[2*j] ];
- }
- e = (3 * idct_out[hSize-1-idim] + 1 * idct_out[hSize-1] + 2) >> 2;
- x[2*hSize-1-xdim] = clip[ -CLIPMIN + e + x[2*hSize-1-xdim] ];
- e = (1 * idct_out[hSize-1-idim] + 3 * idct_out[hSize-1] + 2) >> 2;
- x[2*hSize-1] = clip[ -CLIPMIN + e + x[2*hSize-1] ];
- x += 2 * xdim;
- idct_out += idim;
- }
- // Handle bottom border
- x -= xdim;
- idct_out -= idim;
- e = idct_out[0];
- x[0] = clip[ -CLIPMIN + e + x[0] ];
- for (j = 1; j < hSize; ++j) {
- e = (3 * idct_out[j-1] + 1 * idct_out[j] + 2) >> 2;
- x[2*j-1] = clip[ -CLIPMIN + e + x[2*j-1] ];
- e = (1 * idct_out[j-1] + 3 * idct_out[j] + 2) >> 2;
- x[2*j] = clip[ -CLIPMIN + e + x[2*j] ];
- }
- e = idct_out[hSize-1];
- x[2*hSize-1] = clip[ -CLIPMIN + e + x[2*hSize-1] ];
- }
- #endif