erc_do_i.c
上传用户:hjq518
上传日期:2021-12-09
资源大小:5084k
文件大小:18k
源码类别:

Audio

开发平台:

Visual C++

  1. /*!
  2.  *************************************************************************************
  3.  * file
  4.  *      erc_do_i.c
  5.  *
  6.  * brief
  7.  *      Intra (I) frame error concealment algorithms for decoder
  8.  *
  9.  *  author
  10.  *      - Ari Hourunranta              <ari.hourunranta@nokia.com>
  11.  *      - Viktor Varsa                 <viktor.varsa@nokia.com>
  12.  *      - Ye-Kui Wang                  <wyk@ieee.org>
  13.  *
  14.  *************************************************************************************
  15.  */
  16. #include "global.h"
  17. #include "erc_do.h"
  18. static void concealBlocks( int lastColumn, int lastRow, int comp, frame *recfr, int picSizeX, int *condition );
  19. static void pixMeanInterpolateBlock( imgpel *src[], imgpel *block, int blockSize, int frameWidth );
  20. /*!
  21.  ************************************************************************
  22.  * brief
  23.  *      The main function for Intra frame concealment.
  24.  *      Calls "concealBlocks" for each color component (Y,U,V) separately
  25.  * return
  26.  *      0, if the concealment was not successful and simple concealment should be used
  27.  *      1, otherwise (even if none of the blocks were concealed)
  28.  * param recfr
  29.  *      Reconstructed frame buffer
  30.  * param picSizeX
  31.  *      Width of the frame in pixels
  32.  * param picSizeY
  33.  *      Height of the frame in pixels
  34.  * param errorVar
  35.  *      Variables for error concealment
  36.  ************************************************************************
  37.  */
  38. int ercConcealIntraFrame( frame *recfr, int picSizeX, int picSizeY, ercVariables_t *errorVar )
  39. {
  40.   int lastColumn = 0, lastRow = 0;
  41.   // if concealment is on
  42.   if ( errorVar && errorVar->concealment )
  43.   {
  44.     // if there are segments to be concealed
  45.     if ( errorVar->nOfCorruptedSegments )
  46.     {
  47.       // Y
  48.       lastRow = (int) (picSizeY>>3);
  49.       lastColumn = (int) (picSizeX>>3);
  50.       concealBlocks( lastColumn, lastRow, 0, recfr, picSizeX, errorVar->yCondition );
  51.       // U (dimensions halved compared to Y)
  52.       lastRow = (int) (picSizeY>>4);
  53.       lastColumn = (int) (picSizeX>>4);
  54.       concealBlocks( lastColumn, lastRow, 1, recfr, picSizeX, errorVar->uCondition );
  55.       // V ( dimensions equal to U )
  56.       concealBlocks( lastColumn, lastRow, 2, recfr, picSizeX, errorVar->vCondition );
  57.     }
  58.     return 1;
  59.   }
  60.   else
  61.     return 0;
  62. }
  63. /*!
  64.  ************************************************************************
  65.  * brief
  66.  *      Conceals the MB at position (row, column) using pixels from predBlocks[]
  67.  *      using pixMeanInterpolateBlock()
  68.  * param currFrame
  69.  *      current frame
  70.  * param row
  71.  *      y coordinate in blocks
  72.  * param column
  73.  *      x coordinate in blocks
  74.  * param predBlocks[]
  75.  *      list of neighboring source blocks (numbering 0 to 7, 1 means: use the neighbor)
  76.  * param frameWidth
  77.  *      width of frame in pixels
  78.  * param mbWidthInBlocks
  79.  *      2 for Y, 1 for U/V components
  80.  ************************************************************************
  81.  */
  82. void ercPixConcealIMB(imgpel *currFrame, int row, int column, int predBlocks[], int frameWidth, int mbWidthInBlocks)
  83. {
  84.    imgpel *src[8]={NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL};
  85.    imgpel *currBlock = NULL;
  86.    // collect the reliable neighboring blocks
  87.    if (predBlocks[0])
  88.       src[0] = currFrame + (row-mbWidthInBlocks)*frameWidth*8 + (column+mbWidthInBlocks)*8;
  89.    if (predBlocks[1])
  90.       src[1] = currFrame + (row-mbWidthInBlocks)*frameWidth*8 + (column-mbWidthInBlocks)*8;
  91.    if (predBlocks[2])
  92.       src[2] = currFrame + (row+mbWidthInBlocks)*frameWidth*8 + (column-mbWidthInBlocks)*8;
  93.    if (predBlocks[3])
  94.       src[3] = currFrame + (row+mbWidthInBlocks)*frameWidth*8 + (column+mbWidthInBlocks)*8;
  95.    if (predBlocks[4])
  96.       src[4] = currFrame + (row-mbWidthInBlocks)*frameWidth*8 + column*8;
  97.    if (predBlocks[5])
  98.       src[5] = currFrame + row*frameWidth*8 + (column-mbWidthInBlocks)*8;
  99.    if (predBlocks[6])
  100.       src[6] = currFrame + (row+mbWidthInBlocks)*frameWidth*8 + column*8;
  101.    if (predBlocks[7])
  102.       src[7] = currFrame + row*frameWidth*8 + (column+mbWidthInBlocks)*8;
  103.    currBlock = currFrame + row*frameWidth*8 + column*8;
  104.    pixMeanInterpolateBlock( src, currBlock, mbWidthInBlocks*8, frameWidth );
  105. }
  106. /*!
  107.  ************************************************************************
  108.  * brief
  109.  *      This function checks the neighbors of a Macroblock for usability in
  110.  *      concealment. First the OK macroblocks are marked, and if there is not
  111.  *      enough of them, then the CONCEALED ones as well.
  112.  *      A "1" in the the output array means reliable, a "0" non reliable MB.
  113.  *      The block order in "predBlocks":
  114.  *              1 4 0
  115.  *              5 x 7
  116.  *              2 6 3
  117.  *      i.e., corners first.
  118.  * return
  119.  *      Number of useable neighbor macroblocks for concealment.
  120.  * param predBlocks[]
  121.  *      Array for indicating the valid neighbor blocks
  122.  * param currRow
  123.  *      Current block row in the frame
  124.  * param currColumn
  125.  *      Current block column in the frame
  126.  * param condition
  127.  *      The block condition (ok, lost) table
  128.  * param maxRow
  129.  *      Number of block rows in the frame
  130.  * param maxColumn
  131.  *      Number of block columns in the frame
  132.  * param step
  133.  *      Number of blocks belonging to a MB, when counting
  134.  *      in vertical/horizontal direction. (Y:2 U,V:1)
  135.  * param fNoCornerNeigh
  136.  *      No corner neighbors are considered
  137.  ************************************************************************
  138.  */
  139. int ercCollect8PredBlocks( int predBlocks[], int currRow, int currColumn, int *condition,
  140.                            int maxRow, int maxColumn, int step, byte fNoCornerNeigh )
  141. {
  142.   int srcCounter  = 0;
  143.   int srcCountMin = (fNoCornerNeigh ? 2 : 4);
  144.   int threshold   = ERC_BLOCK_OK;
  145.   memset( predBlocks, 0, 8*sizeof(int) );
  146.   // collect the reliable neighboring blocks
  147.   do
  148.   {
  149.     srcCounter = 0;
  150.     // top
  151.     if (currRow > 0 && condition[ (currRow-1)*maxColumn + currColumn ] >= threshold )
  152.     {                           //ERC_BLOCK_OK (3) or ERC_BLOCK_CONCEALED (2)
  153.       predBlocks[4] = condition[ (currRow-1)*maxColumn + currColumn ];
  154.       srcCounter++;
  155.     }
  156.     // bottom
  157.     if ( currRow < (maxRow-step) && condition[ (currRow+step)*maxColumn + currColumn ] >= threshold )
  158.     {
  159.       predBlocks[6] = condition[ (currRow+step)*maxColumn + currColumn ];
  160.       srcCounter++;
  161.     }
  162.     if ( currColumn > 0 )
  163.     {
  164.       // left
  165.       if ( condition[ currRow*maxColumn + currColumn - 1 ] >= threshold )
  166.       {
  167.         predBlocks[5] = condition[ currRow*maxColumn + currColumn - 1 ];
  168.         srcCounter++;
  169.       }
  170.       if ( !fNoCornerNeigh )
  171.       {
  172.         // top-left
  173.         if ( currRow > 0 && condition[ (currRow-1)*maxColumn + currColumn - 1 ] >= threshold )
  174.         {
  175.           predBlocks[1] = condition[ (currRow-1)*maxColumn + currColumn - 1 ];
  176.           srcCounter++;
  177.         }
  178.         // bottom-left
  179.         if ( currRow < (maxRow-step) && condition[ (currRow+step)*maxColumn + currColumn - 1 ] >= threshold )
  180.         {
  181.           predBlocks[2] = condition[ (currRow+step)*maxColumn + currColumn - 1 ];
  182.           srcCounter++;
  183.         }
  184.       }
  185.     }
  186.     if ( currColumn < (maxColumn-step) )
  187.     {
  188.       // right
  189.       if ( condition[ currRow*maxColumn+currColumn + step ] >= threshold )
  190.       {
  191.         predBlocks[7] = condition[ currRow*maxColumn+currColumn + step ];
  192.         srcCounter++;
  193.       }
  194.       if ( !fNoCornerNeigh )
  195.       {
  196.         // top-right
  197.         if ( currRow > 0 && condition[ (currRow-1)*maxColumn + currColumn + step ] >= threshold )
  198.         {
  199.           predBlocks[0] = condition[ (currRow-1)*maxColumn + currColumn + step ];
  200.           srcCounter++;
  201.         }
  202.         // bottom-right
  203.         if ( currRow < (maxRow-step) && condition[ (currRow+step)*maxColumn + currColumn + step ] >= threshold )
  204.         {
  205.           predBlocks[3] = condition[ (currRow+step)*maxColumn + currColumn + step ];
  206.           srcCounter++;
  207.         }
  208.       }
  209.     }
  210.     // prepare for the next round
  211.     threshold--;
  212.     if (threshold < ERC_BLOCK_CONCEALED)
  213.       break;
  214.   } while ( srcCounter < srcCountMin);
  215.   return srcCounter;
  216. }
  217. /*!
  218.  ************************************************************************
  219.  * brief
  220.  *      collects prediction blocks only from the current column
  221.  * return
  222.  *      Number of usable neighbour Macroblocks for concealment.
  223.  * param predBlocks[]
  224.  *      Array for indicating the valid neighbor blocks
  225.  * param currRow
  226.  *      Current block row in the frame
  227.  * param currColumn
  228.  *      Current block column in the frame
  229.  * param condition
  230.  *      The block condition (ok, lost) table
  231.  * param maxRow
  232.  *      Number of block rows in the frame
  233.  * param maxColumn
  234.  *      Number of block columns in the frame
  235.  * param step
  236.  *      Number of blocks belonging to a MB, when counting
  237.  *      in vertical/horizontal direction. (Y:2 U,V:1)
  238.  ************************************************************************
  239.  */
  240. int ercCollectColumnBlocks( int predBlocks[], int currRow, int currColumn, int *condition, int maxRow, int maxColumn, int step )
  241. {
  242.   int srcCounter = 0, threshold = ERC_BLOCK_CORRUPTED;
  243.   memset( predBlocks, 0, 8*sizeof(int) );
  244.   // in this case, row > 0 and row < 17
  245.   if ( condition[ (currRow-1)*maxColumn + currColumn ] > threshold )
  246.   {
  247.     predBlocks[4] = 1;
  248.     srcCounter++;
  249.   }
  250.   if ( condition[ (currRow+step)*maxColumn + currColumn ] > threshold )
  251.   {
  252.     predBlocks[6] = 1;
  253.     srcCounter++;
  254.   }
  255.   return srcCounter;
  256. }
  257. /*!
  258.  ************************************************************************
  259.  * brief
  260.  *      Core for the Intra blocks concealment.
  261.  *      It is called for each color component (Y,U,V) separately
  262.  *      Finds the corrupted blocks and calls pixel interpolation functions
  263.  *      to correct them, one block at a time.
  264.  *      Scanning is done vertically and each corrupted column is corrected
  265.  *      bi-directionally, i.e., first block, last block, first block+1, last block -1 ...
  266.  * param lastColumn
  267.  *      Number of block columns in the frame
  268.  * param lastRow
  269.  *      Number of block rows in the frame
  270.  * param comp
  271.  *      color component
  272.  * param recfr
  273.  *      Reconstructed frame buffer
  274.  * param picSizeX
  275.  *      Width of the frame in pixels
  276.  * param condition
  277.  *      The block condition (ok, lost) table
  278.  ************************************************************************
  279.  */
  280. static void concealBlocks( int lastColumn, int lastRow, int comp, frame *recfr, int picSizeX, int *condition )
  281. {
  282.   int row, column, srcCounter = 0,  thr = ERC_BLOCK_CORRUPTED,
  283.       lastCorruptedRow = -1, firstCorruptedRow = -1, currRow = 0,
  284.       areaHeight = 0, i = 0, smoothColumn = 0;
  285.   int predBlocks[8], step = 1;
  286.   // in the Y component do the concealment MB-wise (not block-wise):
  287.   // this is useful if only whole MBs can be damaged or lost
  288.   if ( comp == 0 )
  289.     step = 2;
  290.   else
  291.     step = 1;
  292.   for ( column = 0; column < lastColumn; column += step )
  293.   {
  294.     for ( row = 0; row < lastRow; row += step )
  295.     {
  296.       if ( condition[row*lastColumn+column] <= thr )
  297.       {
  298.         firstCorruptedRow = row;
  299.         // find the last row which has corrupted blocks (in same continuous area)
  300.         for ( lastCorruptedRow = row+step; lastCorruptedRow < lastRow; lastCorruptedRow += step )
  301.         {
  302.           // check blocks in the current column
  303.           if ( condition[ lastCorruptedRow*lastColumn + column ] > thr )
  304.           {
  305.             // current one is already OK, so the last was the previous one
  306.             lastCorruptedRow -= step;
  307.             break;
  308.           }
  309.         }
  310.         if ( lastCorruptedRow >= lastRow )
  311.         {
  312.           // correct only from above
  313.           lastCorruptedRow = lastRow-step;
  314.           for ( currRow = firstCorruptedRow; currRow < lastRow; currRow += step )
  315.           {
  316.             srcCounter = ercCollect8PredBlocks( predBlocks, currRow, column, condition, lastRow, lastColumn, step, 1 );
  317.             switch( comp )
  318.             {
  319.             case 0 :
  320.               ercPixConcealIMB( recfr->yptr, currRow, column, predBlocks, picSizeX, 2 );
  321.               break;
  322.             case 1 :
  323.               ercPixConcealIMB( recfr->uptr, currRow, column, predBlocks, (picSizeX>>1), 1 );
  324.               break;
  325.             case 2 :
  326.               ercPixConcealIMB( recfr->vptr, currRow, column, predBlocks, (picSizeX>>1), 1 );
  327.               break;
  328.             }
  329.             if ( comp == 0 )
  330.             {
  331.               condition[ currRow*lastColumn+column] = ERC_BLOCK_CONCEALED;
  332.               condition[ currRow*lastColumn+column + 1] = ERC_BLOCK_CONCEALED;
  333.               condition[ currRow*lastColumn+column + lastColumn] = ERC_BLOCK_CONCEALED;
  334.               condition[ currRow*lastColumn+column + lastColumn + 1] = ERC_BLOCK_CONCEALED;
  335.             }
  336.             else
  337.             {
  338.               condition[ currRow*lastColumn+column] = ERC_BLOCK_CONCEALED;
  339.             }
  340.           }
  341.           row = lastRow;
  342.         }
  343.         else if ( firstCorruptedRow == 0 )
  344.         {
  345.           // correct only from below
  346.           for ( currRow = lastCorruptedRow; currRow >= 0; currRow -= step )
  347.           {
  348.             srcCounter = ercCollect8PredBlocks( predBlocks, currRow, column, condition, lastRow, lastColumn, step, 1 );
  349.             switch( comp )
  350.             {
  351.             case 0 :
  352.               ercPixConcealIMB( recfr->yptr, currRow, column, predBlocks, picSizeX, 2 );
  353.               break;
  354.             case 1 :
  355.               ercPixConcealIMB( recfr->uptr, currRow, column, predBlocks, (picSizeX>>1), 1 );
  356.               break;
  357.             case 2 :
  358.               ercPixConcealIMB( recfr->vptr, currRow, column, predBlocks, (picSizeX>>1), 1 );
  359.               break;
  360.             }
  361.             if ( comp == 0 )
  362.             {
  363.               condition[ currRow*lastColumn+column] = ERC_BLOCK_CONCEALED;
  364.               condition[ currRow*lastColumn+column + 1] = ERC_BLOCK_CONCEALED;
  365.               condition[ currRow*lastColumn+column + lastColumn] = ERC_BLOCK_CONCEALED;
  366.               condition[ currRow*lastColumn+column + lastColumn + 1] = ERC_BLOCK_CONCEALED;
  367.             }
  368.             else
  369.             {
  370.               condition[ currRow*lastColumn+column] = ERC_BLOCK_CONCEALED;
  371.             }
  372.           }
  373.           row = lastCorruptedRow+step;
  374.         }
  375.         else
  376.         {
  377.           // correct bi-directionally
  378.           row = lastCorruptedRow+step;
  379.           areaHeight = lastCorruptedRow-firstCorruptedRow+step;
  380.           // Conceal the corrupted area switching between the up and the bottom rows
  381.           for ( i = 0; i < areaHeight; i += step )
  382.           {
  383.             if ( i % 2 )
  384.             {
  385.               currRow = lastCorruptedRow;
  386.               lastCorruptedRow -= step;
  387.             }
  388.             else
  389.             {
  390.               currRow = firstCorruptedRow;
  391.               firstCorruptedRow += step;
  392.             }
  393.             if (smoothColumn > 0)
  394.             {
  395.               srcCounter = ercCollectColumnBlocks( predBlocks, currRow, column, condition, lastRow, lastColumn, step );
  396.             }
  397.             else
  398.             {
  399.               srcCounter = ercCollect8PredBlocks( predBlocks, currRow, column, condition, lastRow, lastColumn, step, 1 );
  400.             }
  401.             switch( comp )
  402.             {
  403.             case 0 :
  404.               ercPixConcealIMB( recfr->yptr, currRow, column, predBlocks, picSizeX, 2 );
  405.               break;
  406.             case 1 :
  407.               ercPixConcealIMB( recfr->uptr, currRow, column, predBlocks, (picSizeX>>1), 1 );
  408.               break;
  409.             case 2 :
  410.               ercPixConcealIMB( recfr->vptr, currRow, column, predBlocks, (picSizeX>>1), 1 );
  411.               break;
  412.             }
  413.             if ( comp == 0 )
  414.             {
  415.               condition[ currRow*lastColumn+column] = ERC_BLOCK_CONCEALED;
  416.               condition[ currRow*lastColumn+column + 1] = ERC_BLOCK_CONCEALED;
  417.               condition[ currRow*lastColumn+column + lastColumn] = ERC_BLOCK_CONCEALED;
  418.               condition[ currRow*lastColumn+column + lastColumn + 1] = ERC_BLOCK_CONCEALED;
  419.             }
  420.             else
  421.             {
  422.               condition[ currRow*lastColumn+column ] = ERC_BLOCK_CONCEALED;
  423.             }
  424.           }
  425.         }
  426.         lastCorruptedRow = -1;
  427.         firstCorruptedRow = -1;
  428.       }
  429.     }
  430.   }
  431. }
  432. /*!
  433.  ************************************************************************
  434.  * brief
  435.  *      Does the actual pixel based interpolation for block[]
  436.  *      using weighted average
  437.  * param src[]
  438.  *      pointers to neighboring source blocks
  439.  * param block
  440.  *      destination block
  441.  * param blockSize
  442.  *      16 for Y, 8 for U/V components
  443.  * param frameWidth
  444.  *      Width of the frame in pixels
  445.  ************************************************************************
  446.  */
  447. static void pixMeanInterpolateBlock( imgpel *src[], imgpel *block, int blockSize, int frameWidth )
  448. {
  449.   int row, column, k, tmp, srcCounter = 0, weight = 0, bmax = blockSize - 1;
  450.   k = 0;
  451.   for ( row = 0; row < blockSize; row++ )
  452.   {
  453.     for ( column = 0; column < blockSize; column++ )
  454.     {
  455.       tmp = 0;
  456.       srcCounter = 0;
  457.       // above
  458.       if ( src[4] != NULL )
  459.       {
  460.         weight = blockSize-row;
  461.         tmp += weight * (*(src[4]+bmax*frameWidth+column));
  462.         srcCounter += weight;
  463.       }
  464.       // left
  465.       if ( src[5] != NULL )
  466.       {
  467.         weight = blockSize-column;
  468.         tmp += weight * (*(src[5]+row*frameWidth+bmax));
  469.         srcCounter += weight;
  470.       }
  471.       // below
  472.       if ( src[6] != NULL )
  473.       {
  474.         weight = row+1;
  475.         tmp += weight * (*(src[6]+column));
  476.         srcCounter += weight;
  477.       }
  478.       // right
  479.       if ( src[7] != NULL )
  480.       {
  481.         weight = column+1;
  482.         tmp += weight * (*(src[7]+row*frameWidth));
  483.         srcCounter += weight;
  484.       }
  485.       if ( srcCounter > 0 )
  486.         block[ k + column ] = (byte)(tmp/srcCounter);
  487.       else
  488.         block[ k + column ] = blockSize == 8 ? img->dc_pred_value_comp[1] : img->dc_pred_value_comp[0];
  489.     }
  490.     k += frameWidth;
  491.   }
  492. }