erc_do_i.c
资源名称:chapter15.rar [点击查看]
上传用户:hjq518
上传日期:2021-12-09
资源大小:5084k
文件大小:18k
源码类别:
Audio
开发平台:
Visual C++
- /*!
- *************************************************************************************
- * file
- * erc_do_i.c
- *
- * brief
- * Intra (I) frame error concealment algorithms for decoder
- *
- * author
- * - Ari Hourunranta <ari.hourunranta@nokia.com>
- * - Viktor Varsa <viktor.varsa@nokia.com>
- * - Ye-Kui Wang <wyk@ieee.org>
- *
- *************************************************************************************
- */
- #include "global.h"
- #include "erc_do.h"
- static void concealBlocks( int lastColumn, int lastRow, int comp, frame *recfr, int picSizeX, int *condition );
- static void pixMeanInterpolateBlock( imgpel *src[], imgpel *block, int blockSize, int frameWidth );
- /*!
- ************************************************************************
- * brief
- * The main function for Intra frame concealment.
- * Calls "concealBlocks" for each color component (Y,U,V) separately
- * return
- * 0, if the concealment was not successful and simple concealment should be used
- * 1, otherwise (even if none of the blocks were concealed)
- * param recfr
- * Reconstructed frame buffer
- * param picSizeX
- * Width of the frame in pixels
- * param picSizeY
- * Height of the frame in pixels
- * param errorVar
- * Variables for error concealment
- ************************************************************************
- */
- int ercConcealIntraFrame( frame *recfr, int picSizeX, int picSizeY, ercVariables_t *errorVar )
- {
- int lastColumn = 0, lastRow = 0;
- // if concealment is on
- if ( errorVar && errorVar->concealment )
- {
- // if there are segments to be concealed
- if ( errorVar->nOfCorruptedSegments )
- {
- // Y
- lastRow = (int) (picSizeY>>3);
- lastColumn = (int) (picSizeX>>3);
- concealBlocks( lastColumn, lastRow, 0, recfr, picSizeX, errorVar->yCondition );
- // U (dimensions halved compared to Y)
- lastRow = (int) (picSizeY>>4);
- lastColumn = (int) (picSizeX>>4);
- concealBlocks( lastColumn, lastRow, 1, recfr, picSizeX, errorVar->uCondition );
- // V ( dimensions equal to U )
- concealBlocks( lastColumn, lastRow, 2, recfr, picSizeX, errorVar->vCondition );
- }
- return 1;
- }
- else
- return 0;
- }
- /*!
- ************************************************************************
- * brief
- * Conceals the MB at position (row, column) using pixels from predBlocks[]
- * using pixMeanInterpolateBlock()
- * param currFrame
- * current frame
- * param row
- * y coordinate in blocks
- * param column
- * x coordinate in blocks
- * param predBlocks[]
- * list of neighboring source blocks (numbering 0 to 7, 1 means: use the neighbor)
- * param frameWidth
- * width of frame in pixels
- * param mbWidthInBlocks
- * 2 for Y, 1 for U/V components
- ************************************************************************
- */
- void ercPixConcealIMB(imgpel *currFrame, int row, int column, int predBlocks[], int frameWidth, int mbWidthInBlocks)
- {
- imgpel *src[8]={NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL};
- imgpel *currBlock = NULL;
- // collect the reliable neighboring blocks
- if (predBlocks[0])
- src[0] = currFrame + (row-mbWidthInBlocks)*frameWidth*8 + (column+mbWidthInBlocks)*8;
- if (predBlocks[1])
- src[1] = currFrame + (row-mbWidthInBlocks)*frameWidth*8 + (column-mbWidthInBlocks)*8;
- if (predBlocks[2])
- src[2] = currFrame + (row+mbWidthInBlocks)*frameWidth*8 + (column-mbWidthInBlocks)*8;
- if (predBlocks[3])
- src[3] = currFrame + (row+mbWidthInBlocks)*frameWidth*8 + (column+mbWidthInBlocks)*8;
- if (predBlocks[4])
- src[4] = currFrame + (row-mbWidthInBlocks)*frameWidth*8 + column*8;
- if (predBlocks[5])
- src[5] = currFrame + row*frameWidth*8 + (column-mbWidthInBlocks)*8;
- if (predBlocks[6])
- src[6] = currFrame + (row+mbWidthInBlocks)*frameWidth*8 + column*8;
- if (predBlocks[7])
- src[7] = currFrame + row*frameWidth*8 + (column+mbWidthInBlocks)*8;
- currBlock = currFrame + row*frameWidth*8 + column*8;
- pixMeanInterpolateBlock( src, currBlock, mbWidthInBlocks*8, frameWidth );
- }
- /*!
- ************************************************************************
- * brief
- * This function checks the neighbors of a Macroblock for usability in
- * concealment. First the OK macroblocks are marked, and if there is not
- * enough of them, then the CONCEALED ones as well.
- * A "1" in the the output array means reliable, a "0" non reliable MB.
- * The block order in "predBlocks":
- * 1 4 0
- * 5 x 7
- * 2 6 3
- * i.e., corners first.
- * return
- * Number of useable neighbor macroblocks for concealment.
- * param predBlocks[]
- * Array for indicating the valid neighbor blocks
- * param currRow
- * Current block row in the frame
- * param currColumn
- * Current block column in the frame
- * param condition
- * The block condition (ok, lost) table
- * param maxRow
- * Number of block rows in the frame
- * param maxColumn
- * Number of block columns in the frame
- * param step
- * Number of blocks belonging to a MB, when counting
- * in vertical/horizontal direction. (Y:2 U,V:1)
- * param fNoCornerNeigh
- * No corner neighbors are considered
- ************************************************************************
- */
- int ercCollect8PredBlocks( int predBlocks[], int currRow, int currColumn, int *condition,
- int maxRow, int maxColumn, int step, byte fNoCornerNeigh )
- {
- int srcCounter = 0;
- int srcCountMin = (fNoCornerNeigh ? 2 : 4);
- int threshold = ERC_BLOCK_OK;
- memset( predBlocks, 0, 8*sizeof(int) );
- // collect the reliable neighboring blocks
- do
- {
- srcCounter = 0;
- // top
- if (currRow > 0 && condition[ (currRow-1)*maxColumn + currColumn ] >= threshold )
- { //ERC_BLOCK_OK (3) or ERC_BLOCK_CONCEALED (2)
- predBlocks[4] = condition[ (currRow-1)*maxColumn + currColumn ];
- srcCounter++;
- }
- // bottom
- if ( currRow < (maxRow-step) && condition[ (currRow+step)*maxColumn + currColumn ] >= threshold )
- {
- predBlocks[6] = condition[ (currRow+step)*maxColumn + currColumn ];
- srcCounter++;
- }
- if ( currColumn > 0 )
- {
- // left
- if ( condition[ currRow*maxColumn + currColumn - 1 ] >= threshold )
- {
- predBlocks[5] = condition[ currRow*maxColumn + currColumn - 1 ];
- srcCounter++;
- }
- if ( !fNoCornerNeigh )
- {
- // top-left
- if ( currRow > 0 && condition[ (currRow-1)*maxColumn + currColumn - 1 ] >= threshold )
- {
- predBlocks[1] = condition[ (currRow-1)*maxColumn + currColumn - 1 ];
- srcCounter++;
- }
- // bottom-left
- if ( currRow < (maxRow-step) && condition[ (currRow+step)*maxColumn + currColumn - 1 ] >= threshold )
- {
- predBlocks[2] = condition[ (currRow+step)*maxColumn + currColumn - 1 ];
- srcCounter++;
- }
- }
- }
- if ( currColumn < (maxColumn-step) )
- {
- // right
- if ( condition[ currRow*maxColumn+currColumn + step ] >= threshold )
- {
- predBlocks[7] = condition[ currRow*maxColumn+currColumn + step ];
- srcCounter++;
- }
- if ( !fNoCornerNeigh )
- {
- // top-right
- if ( currRow > 0 && condition[ (currRow-1)*maxColumn + currColumn + step ] >= threshold )
- {
- predBlocks[0] = condition[ (currRow-1)*maxColumn + currColumn + step ];
- srcCounter++;
- }
- // bottom-right
- if ( currRow < (maxRow-step) && condition[ (currRow+step)*maxColumn + currColumn + step ] >= threshold )
- {
- predBlocks[3] = condition[ (currRow+step)*maxColumn + currColumn + step ];
- srcCounter++;
- }
- }
- }
- // prepare for the next round
- threshold--;
- if (threshold < ERC_BLOCK_CONCEALED)
- break;
- } while ( srcCounter < srcCountMin);
- return srcCounter;
- }
- /*!
- ************************************************************************
- * brief
- * collects prediction blocks only from the current column
- * return
- * Number of usable neighbour Macroblocks for concealment.
- * param predBlocks[]
- * Array for indicating the valid neighbor blocks
- * param currRow
- * Current block row in the frame
- * param currColumn
- * Current block column in the frame
- * param condition
- * The block condition (ok, lost) table
- * param maxRow
- * Number of block rows in the frame
- * param maxColumn
- * Number of block columns in the frame
- * param step
- * Number of blocks belonging to a MB, when counting
- * in vertical/horizontal direction. (Y:2 U,V:1)
- ************************************************************************
- */
- int ercCollectColumnBlocks( int predBlocks[], int currRow, int currColumn, int *condition, int maxRow, int maxColumn, int step )
- {
- int srcCounter = 0, threshold = ERC_BLOCK_CORRUPTED;
- memset( predBlocks, 0, 8*sizeof(int) );
- // in this case, row > 0 and row < 17
- if ( condition[ (currRow-1)*maxColumn + currColumn ] > threshold )
- {
- predBlocks[4] = 1;
- srcCounter++;
- }
- if ( condition[ (currRow+step)*maxColumn + currColumn ] > threshold )
- {
- predBlocks[6] = 1;
- srcCounter++;
- }
- return srcCounter;
- }
- /*!
- ************************************************************************
- * brief
- * Core for the Intra blocks concealment.
- * It is called for each color component (Y,U,V) separately
- * Finds the corrupted blocks and calls pixel interpolation functions
- * to correct them, one block at a time.
- * Scanning is done vertically and each corrupted column is corrected
- * bi-directionally, i.e., first block, last block, first block+1, last block -1 ...
- * param lastColumn
- * Number of block columns in the frame
- * param lastRow
- * Number of block rows in the frame
- * param comp
- * color component
- * param recfr
- * Reconstructed frame buffer
- * param picSizeX
- * Width of the frame in pixels
- * param condition
- * The block condition (ok, lost) table
- ************************************************************************
- */
- static void concealBlocks( int lastColumn, int lastRow, int comp, frame *recfr, int picSizeX, int *condition )
- {
- int row, column, srcCounter = 0, thr = ERC_BLOCK_CORRUPTED,
- lastCorruptedRow = -1, firstCorruptedRow = -1, currRow = 0,
- areaHeight = 0, i = 0, smoothColumn = 0;
- int predBlocks[8], step = 1;
- // in the Y component do the concealment MB-wise (not block-wise):
- // this is useful if only whole MBs can be damaged or lost
- if ( comp == 0 )
- step = 2;
- else
- step = 1;
- for ( column = 0; column < lastColumn; column += step )
- {
- for ( row = 0; row < lastRow; row += step )
- {
- if ( condition[row*lastColumn+column] <= thr )
- {
- firstCorruptedRow = row;
- // find the last row which has corrupted blocks (in same continuous area)
- for ( lastCorruptedRow = row+step; lastCorruptedRow < lastRow; lastCorruptedRow += step )
- {
- // check blocks in the current column
- if ( condition[ lastCorruptedRow*lastColumn + column ] > thr )
- {
- // current one is already OK, so the last was the previous one
- lastCorruptedRow -= step;
- break;
- }
- }
- if ( lastCorruptedRow >= lastRow )
- {
- // correct only from above
- lastCorruptedRow = lastRow-step;
- for ( currRow = firstCorruptedRow; currRow < lastRow; currRow += step )
- {
- srcCounter = ercCollect8PredBlocks( predBlocks, currRow, column, condition, lastRow, lastColumn, step, 1 );
- switch( comp )
- {
- case 0 :
- ercPixConcealIMB( recfr->yptr, currRow, column, predBlocks, picSizeX, 2 );
- break;
- case 1 :
- ercPixConcealIMB( recfr->uptr, currRow, column, predBlocks, (picSizeX>>1), 1 );
- break;
- case 2 :
- ercPixConcealIMB( recfr->vptr, currRow, column, predBlocks, (picSizeX>>1), 1 );
- break;
- }
- if ( comp == 0 )
- {
- condition[ currRow*lastColumn+column] = ERC_BLOCK_CONCEALED;
- condition[ currRow*lastColumn+column + 1] = ERC_BLOCK_CONCEALED;
- condition[ currRow*lastColumn+column + lastColumn] = ERC_BLOCK_CONCEALED;
- condition[ currRow*lastColumn+column + lastColumn + 1] = ERC_BLOCK_CONCEALED;
- }
- else
- {
- condition[ currRow*lastColumn+column] = ERC_BLOCK_CONCEALED;
- }
- }
- row = lastRow;
- }
- else if ( firstCorruptedRow == 0 )
- {
- // correct only from below
- for ( currRow = lastCorruptedRow; currRow >= 0; currRow -= step )
- {
- srcCounter = ercCollect8PredBlocks( predBlocks, currRow, column, condition, lastRow, lastColumn, step, 1 );
- switch( comp )
- {
- case 0 :
- ercPixConcealIMB( recfr->yptr, currRow, column, predBlocks, picSizeX, 2 );
- break;
- case 1 :
- ercPixConcealIMB( recfr->uptr, currRow, column, predBlocks, (picSizeX>>1), 1 );
- break;
- case 2 :
- ercPixConcealIMB( recfr->vptr, currRow, column, predBlocks, (picSizeX>>1), 1 );
- break;
- }
- if ( comp == 0 )
- {
- condition[ currRow*lastColumn+column] = ERC_BLOCK_CONCEALED;
- condition[ currRow*lastColumn+column + 1] = ERC_BLOCK_CONCEALED;
- condition[ currRow*lastColumn+column + lastColumn] = ERC_BLOCK_CONCEALED;
- condition[ currRow*lastColumn+column + lastColumn + 1] = ERC_BLOCK_CONCEALED;
- }
- else
- {
- condition[ currRow*lastColumn+column] = ERC_BLOCK_CONCEALED;
- }
- }
- row = lastCorruptedRow+step;
- }
- else
- {
- // correct bi-directionally
- row = lastCorruptedRow+step;
- areaHeight = lastCorruptedRow-firstCorruptedRow+step;
- // Conceal the corrupted area switching between the up and the bottom rows
- for ( i = 0; i < areaHeight; i += step )
- {
- if ( i % 2 )
- {
- currRow = lastCorruptedRow;
- lastCorruptedRow -= step;
- }
- else
- {
- currRow = firstCorruptedRow;
- firstCorruptedRow += step;
- }
- if (smoothColumn > 0)
- {
- srcCounter = ercCollectColumnBlocks( predBlocks, currRow, column, condition, lastRow, lastColumn, step );
- }
- else
- {
- srcCounter = ercCollect8PredBlocks( predBlocks, currRow, column, condition, lastRow, lastColumn, step, 1 );
- }
- switch( comp )
- {
- case 0 :
- ercPixConcealIMB( recfr->yptr, currRow, column, predBlocks, picSizeX, 2 );
- break;
- case 1 :
- ercPixConcealIMB( recfr->uptr, currRow, column, predBlocks, (picSizeX>>1), 1 );
- break;
- case 2 :
- ercPixConcealIMB( recfr->vptr, currRow, column, predBlocks, (picSizeX>>1), 1 );
- break;
- }
- if ( comp == 0 )
- {
- condition[ currRow*lastColumn+column] = ERC_BLOCK_CONCEALED;
- condition[ currRow*lastColumn+column + 1] = ERC_BLOCK_CONCEALED;
- condition[ currRow*lastColumn+column + lastColumn] = ERC_BLOCK_CONCEALED;
- condition[ currRow*lastColumn+column + lastColumn + 1] = ERC_BLOCK_CONCEALED;
- }
- else
- {
- condition[ currRow*lastColumn+column ] = ERC_BLOCK_CONCEALED;
- }
- }
- }
- lastCorruptedRow = -1;
- firstCorruptedRow = -1;
- }
- }
- }
- }
- /*!
- ************************************************************************
- * brief
- * Does the actual pixel based interpolation for block[]
- * using weighted average
- * param src[]
- * pointers to neighboring source blocks
- * param block
- * destination block
- * param blockSize
- * 16 for Y, 8 for U/V components
- * param frameWidth
- * Width of the frame in pixels
- ************************************************************************
- */
- static void pixMeanInterpolateBlock( imgpel *src[], imgpel *block, int blockSize, int frameWidth )
- {
- int row, column, k, tmp, srcCounter = 0, weight = 0, bmax = blockSize - 1;
- k = 0;
- for ( row = 0; row < blockSize; row++ )
- {
- for ( column = 0; column < blockSize; column++ )
- {
- tmp = 0;
- srcCounter = 0;
- // above
- if ( src[4] != NULL )
- {
- weight = blockSize-row;
- tmp += weight * (*(src[4]+bmax*frameWidth+column));
- srcCounter += weight;
- }
- // left
- if ( src[5] != NULL )
- {
- weight = blockSize-column;
- tmp += weight * (*(src[5]+row*frameWidth+bmax));
- srcCounter += weight;
- }
- // below
- if ( src[6] != NULL )
- {
- weight = row+1;
- tmp += weight * (*(src[6]+column));
- srcCounter += weight;
- }
- // right
- if ( src[7] != NULL )
- {
- weight = column+1;
- tmp += weight * (*(src[7]+row*frameWidth));
- srcCounter += weight;
- }
- if ( srcCounter > 0 )
- block[ k + column ] = (byte)(tmp/srcCounter);
- else
- block[ k + column ] = blockSize == 8 ? img->dc_pred_value_comp[1] : img->dc_pred_value_comp[0];
- }
- k += frameWidth;
- }
- }