loopFilter.c
上传用户:sun1608
上传日期:2007-02-02
资源大小:6116k
文件大小:12k
源码类别:

流媒体/Mpeg4/MP4

开发平台:

Visual C++

  1. /*
  2. ***********************************************************************
  3. * COPYRIGHT AND WARRANTY INFORMATION
  4. *
  5. * Copyright 2001, International Telecommunications Union, Geneva
  6. *
  7. * DISCLAIMER OF WARRANTY
  8. *
  9. * These software programs are available to the user without any
  10. * license fee or royalty on an "as is" basis. The ITU disclaims
  11. * any and all warranties, whether express, implied, or
  12. * statutory, including any implied warranties of merchantability
  13. * or of fitness for a particular purpose.  In no event shall the
  14. * contributor or the ITU be liable for any incidental, punitive, or
  15. * consequential damages of any kind whatsoever arising from the
  16. * use of these programs.
  17. *
  18. * This disclaimer of warranty extends to the user of these programs
  19. * and user's customers, employees, agents, transferees, successors,
  20. * and assigns.
  21. *
  22. * The ITU does not represent or warrant that the programs furnished
  23. * hereunder are free of infringement of any third-party patents.
  24. * Commercial implementations of ITU-T Recommendations, including
  25. * shareware, may be subject to royalty fees to patent holders.
  26. * Information regarding the ITU-T patent policy is available from
  27. * the ITU Web site at http://www.itu.int.
  28. *
  29. * THIS IS NOT A GRANT OF PATENT RIGHTS - SEE THE ITU-T PATENT POLICY.
  30. ************************************************************************
  31. */
  32. /*!
  33.  *************************************************************************************
  34.  * file loopFilter.c
  35.  *
  36.  * brief
  37.  *    Filter to reduce blocking artifacts on a macroblock level.
  38.  *    The filter strengh is QP dependent.
  39.  *
  40.  * author
  41.  *    Contributors:
  42.  *    - Peter List      Peter.List@t-systems.de:  Original code                             (13.8.2001)
  43.  *    - Jani Lainema    Jani.Lainema@nokia.com:   Some bug fixing, removal of recusiveness  (16.8.2001)
  44.  *************************************************************************************
  45.  */
  46. #include <stdlib.h>
  47. #include <string.h>
  48. #include "global.h"
  49. #define  Clip( Min, Max, Val) (((Val)<(Min))? (Min):(((Val)>(Max))? (Max):(Val)))
  50. int ALPHA_TABLE[32]  = {128,128,128,128,128,128,128,128,128,128,122, 96, 75, 59, 47, 37,
  51.                          29, 23, 18, 15, 13, 11,  9,  8,  7,  6,  5,  4,  3,  3,  2,  2 } ;
  52. int  BETA_TABLE[32]  = {  0,  0,  0,  0,  0,  0,  0,  0,  3,  3,  3,  4,  4,  4,  6,  6,
  53.                           6,  7,  8,  8,  9,  9, 10, 10, 11, 11, 12, 12, 13, 13, 14, 14  } ;
  54. byte CLIP_TBL[3][32] = {{0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0},
  55.                         {0,0,0,0,0,0,0,0, 0,0,0,1,1,1,1,1, 1,1,1,1,1,2,2,2, 2,3,3,3,3,4,5,5},
  56.                         {0,0,0,0,0,0,0,0, 0,1,1,1,1,1,1,1, 1,2,2,2,2,3,3,3, 4,4,5,5,5,7,8,9}} ;
  57. byte MASK_L[2][16]   = {{3,0,1,2,  7,4,5,6,  11,8,9,10,  15,12,13,14}, {12,13,14,15,  0,1,2,3, 4,5,6,7, 8,9,10,11}} ;
  58. byte MASK_C[2][ 4]   = {{1,0,3,2}, {2,3,0,1}} ;
  59. /*!
  60.  *****************************************************************************************
  61.  * brief
  62.  *    Filters one edge of 4 (luma) or 2 (chroma) pel
  63.  *****************************************************************************************
  64.  */
  65. void EdgeLoop( byte* ptrOut, int* ptrIn, Macroblock *MbP, Macroblock *MbQ, int VecDif, int dir, int CbpMaskP, int CbpMaskQ, int widthOut, int widthIn, int luma )
  66. {
  67.   int      StrengthP, StrengthQ ;
  68.   int      alpha, beta  ;
  69.   int      pel, ap, aq;
  70.   int      incIn, incIn2, incIn3, incIn4 ;
  71.   int      incOut, incOut2, incOut3 ;
  72.   int      C0, Cq, Cp, c0, n, delta, strong, dif ;
  73.   int      lastPel = luma ? 4 : 2;
  74.   StrengthQ = ((MbQ->intraOrInter != INTER_MB) || (img->types == SP_IMG))? 2: ((MbQ->cbp_blk & CbpMaskQ) != 0)? 1:0 ;  // if not INTRA: has this
  75.   StrengthP = ((MbP->intraOrInter != INTER_MB) || (img->types == SP_IMG))? 2: ((MbP->cbp_blk & CbpMaskP) != 0)? 1:0 ;       // 4x4 block coeffs?
  76.   if( StrengthP || StrengthQ || VecDif )
  77.   {
  78.     alpha   = ALPHA_TABLE[ MbQ->qp ] ;
  79.     beta    = BETA_TABLE [ MbQ->qp ] ;
  80.     Cq      = CLIP_TBL[ StrengthQ ][ MbQ->qp ] ;
  81.     Cp      = CLIP_TBL[ StrengthP ][ MbQ->qp ] ;
  82.     C0      = Cq + Cp ;
  83.     incIn   = dir ?  widthIn : 1 ;                     // vertical filtering increment to next pixel is 1 else width
  84.     incIn2  = incIn<<1 ;
  85.     incIn3  = incIn + incIn2 ;
  86.     incIn4  = incIn<<2 ;
  87.     incOut  = dir ?  widthOut : 1 ;                    // vertical filtering increment to next pixel is 1 else width
  88.     incOut2 = incOut<<1 ;
  89.     incOut3 = incOut + incOut2 ;
  90.     strong  = (MbP != MbQ ) && ((StrengthQ == 2) || (StrengthP == 2)) ; // stronger filtering possible if Macroblock
  91.                                                                                 // boundary and one of MB's is Intra
  92.     for( pel=0 ; pel<lastPel ; pel++ )
  93.     {
  94.       delta = abs( ptrIn[0] - ptrIn[-incIn] ) ;
  95.       n     = min( 3, 4-(delta*alpha >> 7) ) ;
  96.       for( aq=1 ; aq<n ; aq++ )
  97.         if( abs(ptrIn[     0] - ptrIn[     aq*incIn]) > beta)
  98.           break ;
  99.       for( ap=1 ; ap<n  ; ap++ )
  100.         if( abs(ptrIn[-incIn] - ptrIn[(-1-ap)*incIn]) > beta)
  101.           break ;
  102.       if( strong & (ap+aq == 6) & (delta < MbQ->qp>>2) & (delta >= 2) )                   // INTRA strong filtering
  103.       {
  104.         ptrOut[ -incOut]   = (25*( ptrIn[-incIn3] +  ptrIn[  incIn]) + 26*( ptrIn[-incIn2] + ptrIn[-incIn ] +  ptrIn[      0 ]) + 64) >> 7 ;
  105.         ptrOut[-incOut2]   = (25*( ptrIn[-incIn4] +  ptrIn[      0]) + 26*( ptrIn[-incIn3] + ptrIn[-incIn2] + ptrOut[ -incOut]) + 64) >> 7 ;
  106.         ptrOut[       0]   = (25*( ptrIn[-incIn2] +  ptrIn[ incIn2]) + 26*( ptrIn[ -incIn] + ptrIn[      0] +  ptrIn[  incIn ]) + 64) >> 7 ;
  107.         ptrOut[  incOut]   = (25*( ptrIn[-incIn ] +  ptrIn[ incIn3]) + 26*(ptrOut[      0] + ptrIn[ incIn ] +  ptrIn[  incIn2]) + 64) >> 7 ;
  108.         if( luma )                                                                  // For luma do two more pixels
  109.         {
  110.           ptrOut[-incOut3] = (25*( ptrIn[-incIn3] + ptrOut[-incOut]) + 26*( ptrIn[-incIn4] + ptrIn[-incIn3] + ptrOut[-incOut2]) + 64) >> 7 ;
  111.           ptrOut[ incOut2] = (25*(ptrOut[      0] +  ptrIn[ incIn2]) + 26*(ptrOut[ incOut] + ptrIn[ incIn2] +  ptrIn[  incIn3]) + 64) >> 7 ;
  112.         }
  113.       }
  114.       else
  115.       {
  116.         if( (ap > 1) && (aq > 1) )                                                             // normal filtering
  117.         {
  118.           c0                 = (C0 + ap + aq) >> 1 ;
  119.           dif                = Clip( -c0,  c0, (((ptrIn[0] - ptrIn[-incIn]) << 2) + (ptrIn[-incIn2] - ptrIn[incIn]) + 4) >> 3 ) ;
  120.           ptrOut[-incOut ]   = Clip(   0, 255, ptrIn[-incIn] + dif ) ;
  121.           ptrOut[      0 ]   = Clip(   0, 255, ptrIn[    0 ] - dif ) ;
  122.           if( ap == 3)
  123.           {
  124.             dif              = Clip( -Cp,  Cp, (ptrIn[-incIn3] + ptrIn[-incIn] - (ptrIn[-incIn2]<<1)) >> 1 ) ;
  125.             ptrOut[-incOut2] = ptrIn[-incIn2] + dif;
  126.           }
  127.           if( aq == 3)
  128.           {
  129.             dif              = Clip( -Cq,  Cq, (ptrIn[ incIn2] + ptrIn[     0] - (ptrIn[  incIn]<<1)) >> 1 ) ;
  130.             ptrOut[  incOut] = ptrIn[  incIn] + dif;
  131.           }
  132.         }
  133.       }
  134.       ptrOut += dir?  1:widthOut ;      // Increment to next set of pixel
  135.       ptrIn  += dir?  1:widthIn  ;
  136.     }
  137.   }
  138. }
  139. /*!
  140.  *****************************************************************************************
  141.  * brief
  142.  *    returns VecDiff for different Frame types
  143.  *****************************************************************************************
  144.  */
  145. int GetVecDif( ImageParameters *img, int dir, int blk_y, int blk_x )
  146. {
  147.   if( img->type == B_IMG )
  148.   {
  149.     if( img->imod != B_Direct )
  150.       return ( abs( tmp_fwMV[0][blk_y][blk_x+4] - tmp_fwMV[0][blk_y-dir][blk_x+4-!dir]) >= 4) |
  151.              ( abs( tmp_fwMV[1][blk_y][blk_x+4] - tmp_fwMV[1][blk_y-dir][blk_x+4-!dir]) >= 4) |
  152.              ( abs( tmp_bwMV[0][blk_y][blk_x+4] - tmp_bwMV[0][blk_y-dir][blk_x+4-!dir]) >= 4) |
  153.              ( abs( tmp_bwMV[1][blk_y][blk_x+4] - tmp_bwMV[1][blk_y-dir][blk_x+4-!dir]) >= 4)  ;
  154.     else
  155.       return ( abs(     dfMV[0][blk_y][blk_x+4] -     dfMV[0][blk_y-dir][blk_x+4-!dir]) >= 4) |
  156.              ( abs(     dfMV[1][blk_y][blk_x+4] -     dfMV[1][blk_y-dir][blk_x+4-!dir]) >= 4) |
  157.              ( abs(     dbMV[0][blk_y][blk_x+4] -     dbMV[0][blk_y-dir][blk_x+4-!dir]) >= 4) |
  158.              ( abs(     dbMV[1][blk_y][blk_x+4] -     dbMV[1][blk_y-dir][blk_x+4-!dir]) >= 4)  ;
  159.   }
  160.   else
  161.     return   ( abs(   tmp_mv[0][blk_y][blk_x+4] -   tmp_mv[0][blk_y-dir][blk_x+4-!dir]) >= 4 ) |
  162.              ( abs(   tmp_mv[1][blk_y][blk_x+4] -   tmp_mv[1][blk_y-dir][blk_x+4-!dir]) >= 4 ) |
  163.              (         refFrArr[blk_y][blk_x  ]!=    refFrArr[blk_y-dir][blk_x  -!dir]);
  164. }
  165. /*!
  166.  *****************************************************************************************
  167.  * brief
  168.  *    The main MB-filtering function
  169.  *****************************************************************************************
  170.  */
  171. void DeblockMb(ImageParameters *img, byte **imgY, byte ***imgUV)
  172. {
  173.   int           ofs_x, ofs_y ;
  174.   int           blk_x, blk_y ;
  175.   int           x, y, EdgeX, EdgeY ;
  176.   int           VecDif ;                                    // TRUE if x or ydifference to neighboring mv is >= 4
  177.   int           dir ;                                                         // horizontal or vertical filtering
  178.   int           CbpMaskQ ;
  179.   Macroblock    *MbP, *MbQ ;                                        // the current (MbQ) and neighboring (MbP) mb
  180.   int           bufferY[20*20],  bufferU[12*12], bufferV[12*12];
  181.   int xFirst =  img->block_x? -4:0;
  182.   int yFirst =  img->block_y? -4:0;
  183.   for( dir=0 ; dir<2 ; dir++ )                                           // vertical edges, than horicontal edges
  184.   {
  185.     for( y = yFirst ; y < 16 ; y++ )                        // Copy the original data to be filtered into buffers
  186.       for( x = xFirst ; x < 16 ; x++ )
  187.         bufferY[20*y+x+84] = imgY[img->pix_y+y][img->pix_x+x];
  188.     if (imgUV!=NULL)
  189.       for( y = yFirst ; y < 8 ; y++ )
  190.         for( x = xFirst ; x < 8 ; x++ )
  191.         {
  192.           bufferU[12*y+x+52] = imgUV[0][img->pix_c_y+y][img->pix_c_x+x];
  193.           bufferV[12*y+x+52] = imgUV[1][img->pix_c_y+y][img->pix_c_x+x];
  194.         }
  195.     EdgeX = ( dir || img->block_x)? 0:1 ;
  196.     EdgeY = (!dir || img->block_y)? 0:1 ;
  197.     for( ofs_y=EdgeY ; ofs_y<4 ; ofs_y++ )             // go  vertically through 4x4 blocks
  198.       for( ofs_x=EdgeX ; ofs_x<4 ; ofs_x++ )          // go horicontally through 4x4 blocks
  199.       {
  200.         blk_y    = img->block_y + ofs_y ;                                                 // absolute 4x4 address
  201.         blk_x    = img->block_x + ofs_x ;
  202.         MbQ      = MbP = &img->mb_data[ img->current_mb_nr ] ;                                      // current Mb
  203.         MbP     -= ( !ofs_x && !dir)? 1 : ((!ofs_y && dir)? (img->width>>4) : 0) ;              // neighboring Mb
  204.         VecDif   = GetVecDif( img, dir, blk_y, blk_x ) ;                 // Get Vecdiff for different frame types
  205.         CbpMaskQ = (ofs_y<<2) + ofs_x ;
  206.         EdgeLoop( imgY[blk_y<<2] + (blk_x<<2), bufferY + ((20*ofs_y+ofs_x)<<2) + 84, MbP, MbQ, VecDif, dir, 1<<MASK_L[dir][CbpMaskQ], 1<<CbpMaskQ, img->width, 20, 1 ) ;
  207.         if (imgUV!=NULL)
  208.         {
  209.           if( (!dir && !(ofs_x & 1)) || (dir && !(ofs_y & 1)) )                      // do the same for chrominance
  210.           {
  211.             CbpMaskQ = (ofs_y & 0xfe) + (ofs_x>>1) ;
  212.             EdgeLoop( imgUV[0][blk_y<<1] + ((blk_x)<<1), bufferU + ((12*ofs_y+ofs_x)<<1) + 52, MbP, MbQ, VecDif, dir, 0x010000<<MASK_C[dir][CbpMaskQ], 0x010000<<CbpMaskQ, img->width_cr, 12, 0 ) ;
  213.             EdgeLoop( imgUV[1][blk_y<<1] + ((blk_x)<<1), bufferV + ((12*ofs_y+ofs_x)<<1) + 52, MbP, MbQ, VecDif, dir, 0x100000<<MASK_C[dir][CbpMaskQ], 0x100000<<CbpMaskQ, img->width_cr, 12, 0 ) ;
  214.           }
  215.         }
  216.       }
  217.   }
  218. }