⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 loopfilter.c.new

📁 h.264标准和jm
💻 NEW
📖 第 1 页 / 共 2 页
字号:

/*!
 *************************************************************************************
 * \file loopFilter.c
 *
 * \brief
 *    Filter to reduce blocking artifacts on a macroblock level.
 *    The filter strengh is QP dependent.
 *
 * \author
 *    Contributors:
 *    - Peter List       Peter.List@t-systems.de:  Original code                                 (13-Aug-2001)
 *    - Jani Lainema     Jani.Lainema@nokia.com:   Some bug fixing, removal of recusiveness      (16-Aug-2001)
 *    - Peter List       Peter.List@t-systems.de:  inplace filtering and various simplifications (10-Jan-2002)
 *    - Anthony Joch     anthony@ubvideo.com:      Simplified switching between filters and 
 *                                                 non-recursive default filter.                 (08-Jul-2002)
 *    - Cristina Gomila  cristina.gomila@thomson.net: Simplification of the chroma deblocking
 *                                                    from JVT-E089                              (21-Nov-2002)
 *************************************************************************************
 */
#include <stdlib.h>
#include <string.h>
#include "global.h"
#include "image.h"
#include "mb_access.h"

extern const byte QP_SCALE_CR[52] ;

/*********************************************************************************************************/

// NOTE: to change the tables below for instance when the QP doubling is changed from 6 to 8 values 
//       send an e-mail to Peter.List@t-systems.com to get a little programm that calculates them automatically 

byte ALPHA_TABLE[52]  = {0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,4,4,5,6,  7,8,9,10,12,13,15,17,  20,22,25,28,32,36,40,45,  50,56,63,71,80,90,101,113,  127,144,162,182,203,226,255,255} ;
byte  BETA_TABLE[52]  = {0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,2,2,2,3,  3,3,3, 4, 4, 4, 6, 6,   7, 7, 8, 8, 9, 9,10,10,  11,11,12,12,13,13, 14, 14,   15, 15, 16, 16, 17, 17, 18, 18} ;
byte CLIP_TAB[52][5]  =
{
  { 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, 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, 0},{ 0, 0, 0, 0, 0},{ 0, 0, 0, 0, 0},{ 0, 0, 0, 0, 0},
  { 0, 0, 0, 0, 0},{ 0, 0, 0, 1, 1},{ 0, 0, 0, 1, 1},{ 0, 0, 0, 1, 1},{ 0, 0, 0, 1, 1},{ 0, 0, 1, 1, 1},{ 0, 0, 1, 1, 1},{ 0, 1, 1, 1, 1},
  { 0, 1, 1, 1, 1},{ 0, 1, 1, 1, 1},{ 0, 1, 1, 1, 1},{ 0, 1, 1, 2, 2},{ 0, 1, 1, 2, 2},{ 0, 1, 1, 2, 2},{ 0, 1, 1, 2, 2},{ 0, 1, 2, 3, 3},
  { 0, 1, 2, 3, 3},{ 0, 2, 2, 3, 3},{ 0, 2, 2, 4, 4},{ 0, 2, 3, 4, 4},{ 0, 2, 3, 4, 4},{ 0, 3, 3, 5, 5},{ 0, 3, 4, 6, 6},{ 0, 3, 4, 6, 6},
  { 0, 4, 5, 7, 7},{ 0, 4, 5, 8, 8},{ 0, 4, 6, 9, 9},{ 0, 5, 7,10,10},{ 0, 6, 8,11,11},{ 0, 6, 8,13,13},{ 0, 7,10,14,14},{ 0, 8,11,16,16},
  { 0, 9,12,18,18},{ 0,10,13,20,20},{ 0,11,15,23,23},{ 0,13,17,25,25}
} ;



void GetStrength(byte Strength[16],struct img_par *img,Macroblock* MbP[16],Macroblock* MbQ[16],int dir,int edge,int mb_y,int mb_x, int mvlimit);
void EdgeLoop(byte* SrcPtr,byte Strength[16], int QP[16], int AlphaC0Offset, int BetaOffset, int dir,int width,int yuv);
void DeblockMb(ImageParameters *img, byte **imgY, byte ***imgUV, int mbaddr) ;

/*!
 *****************************************************************************************
 * \brief
 *    Filter all macroblocks in order of increasing macroblock address.
 *****************************************************************************************
 */
void DeblockFrame(ImageParameters *img, byte **imgY, byte ***imgUV)
{
  unsigned i;

  for (i=0; i<img->PicSizeInMbs; i++)
    DeblockMb( img, imgY, imgUV, i ) ;
} 


/*!
 *****************************************************************************************
 * \brief
 *    Deblocking filter for one macroblock.
 *****************************************************************************************
 */

void DeblockMb(ImageParameters *img, byte **imgY, byte ***imgUV, int mb_addr)
{
  int           EdgeCondition;
  int           edge; //,dir;
  byte          Strength[16],*SrcY, *SrcU, *SrcV ;
  Macroblock    *MbQ[16], *MbP[16], *MbP_temp; 
  int           QPC[16],QP[16];
  int           mb_x, mb_y;
  
  int           filterLeftMbEdgeFlag;
  int           filterTopMbEdgeFlag;
  int           fieldModeMbFlag;
  int           mvlimit=4;
  int			      horizontal;  //replaced dir
  int           i;
  int           qPp,qPq;
  
  get_mb_block_pos(mb_addr, &mb_x, &mb_y);
  
  filterLeftMbEdgeFlag  = (mb_x != 0);
  filterTopMbEdgeFlag   = (mb_y != 0);
  
  SrcY = imgY    [mb_y<<4] + (mb_x<<4) ;                     // pointers to source
  SrcU = imgUV[0][mb_y<<3] + (mb_x<<3) ;
  SrcV = imgUV[1][mb_y<<3] + (mb_x<<3) ;
  
  for (i=0; i<16; i++)
  {
    MbQ[i] = ( img->mb_data[mb_addr].mb_field ? 
               &img->mb_data[(mb_addr & ~1) + (i%2)] : 
               &img->mb_data[mb_addr]) ;                            // current Mb
  }
  
  fieldModeMbFlag = img->field_pic_flag || (img->MbaffFrameFlag && MbQ[0]->mb_field);

  if (fieldModeMbFlag)
    mvlimit = 2;
  
  // return, if filter is disabled
  if (img->mb_data[mb_addr].LFDisableIdc==1) return;
  
  if (img->mb_data[mb_addr].LFDisableIdc==2)
  {
    // don't filter at slice boundaries
    filterLeftMbEdgeFlag = img->mb_data[mb_addr].mbAvailA;
    filterTopMbEdgeFlag  = img->mb_data[mb_addr].mbAvailB;
  }

  for( horizontal=0 ; horizontal<2 ; horizontal++ )         // vertical edges, then horizontal edges
  {
    // cannot filter beyond picture boundaries (or slice boundaries if LFDisableIdc == 2)
    EdgeCondition = (horizontal && filterTopMbEdgeFlag) || (!horizontal && filterLeftMbEdgeFlag); 

    for( edge=0 ; edge<4 ; edge++ )                        // first 4 vertical strips of 16 pel
    {                                                      // then  4 horizontal
      if( edge || EdgeCondition )
      {
        // [*]Getting Remote MB data: MbPa & MbPb ---------------------------------------------------------------------------------
        // Figure out what macroblock(s) are on the other side of this edge */

        if (img->MbaffFrameFlag) 
        {
          if(edge) 
          { // interior edge 
            for (i=0; i<16; i++) 
              MbP[i] = MbQ[i];                   //interior edge means all blocks are within curMB
          }
          else if (!horizontal) 
          { // left MB edge 
            if(img->mb_data[mb_addr].mb_field)  
            {                                                    // current is field
              if( img->mb_data[mb_addr-2].mb_field )                            //   remote is field
              {
                for (i=0; i<16; i++) 
                  MbP[i] = &img->mb_data[mb_addr - 2];
              }
              else                                               //   remote is frame
              {
                for (i=0; i<8; i++) 
                {
                  MbP[i]   = &img->mb_data[(mb_addr & ~1) - 2];  // to apply to top half
                  MbP[i+8] = &img->mb_data[(mb_addr & ~1) - 1];  // to apply to bottom half
                }
              }
            }
            else 
            {                                                    // current is frame
              if(img->mb_data[mb_addr-2].mb_field) 
              {                                                  //   remote is field
                for (i=0; i<16; i+=2) 
                {
                  MbP[i]   = &img->mb_data[(mb_addr & ~1) - 2];    // to apply to top field lines
                  MbP[i+1] = &img->mb_data[(mb_addr & ~1) - 1];	   // to apply to bot field lines
                }
              } 
              else 
              {                                                  // remote is frame
                for (i=0; i<16; i++) 
                  MbP[i] = &img->mb_data[mb_addr - 2];
              }
            }
          }
          else 
          { // top MB edge 
            if(img->mb_data[mb_addr].mb_field) 
            {                                                                  // current is field
              if( img->mb_data[mb_addr - (img->PicWidthInMbs << 1) ].mb_field )               //   remote is field
              {
                for (i=0; i<16; i++)
                  MbP[i] = &img->mb_data[mb_addr - (img->PicWidthInMbs << 1)];                         
              }
              else                                                             //   remote is frame
              {
                for (i=0; i<16; i++) 
                  MbP[i] = &img->mb_data[(mb_addr | 1) - (img->PicWidthInMbs << 1)];
              }
            }
            else 
            {                                                                 // current is frame
              if(mb_addr & 1) 
              {                                                               // remote is topMB in same MB pair
                for (i=0; i<16; i++) 
                  MbP[i] = &img->mb_data[mb_addr - 1];
              }
              else 
              {
                if( img->mb_data[mb_addr - (img->PicWidthInMbs << 1) ].mb_field )
                {        // remote is field
                  for (i=0; i<16; i++) 
                    MbP[i] = &img->mb_data[(mb_addr & ~1) - (img->PicWidthInMbs << 1)]; // to apply to top field lines
                } 
                else
                {                                                                                                          // remote is frame
                  for (i=0; i<16; i++) 
                    MbP[i] = &img->mb_data[(mb_addr | 1) - (img->PicWidthInMbs << 1)];
                }
              }
            }
          }
        } //End of MBAFF = 1
        else 
        {
          // MbP = Left or Upper Mb 
          MbP_temp = (edge)? &img->mb_data[mb_addr] : ((horizontal)? &img->mb_data[mb_addr - img->PicWidthInMbs]  : &img->mb_data[mb_addr-1] ) ;       
          for (i=0; i<16; i++) 
            MbP[i] = MbP_temp;
          
        } //End of MBAFF = 0
        
        // GJS: The rest of this needs work
        
        // As in Draft, if MB is I_PCM, MB->qp should be 0 or corresponding value of 0 for chroma
        // This is set in decode_ipcm_mb() and here affect the values of QP and QPC (QP_SCALE_CR[])
        
        // [*] PARAMETER SETUP: AVERAGE QP & Bs (Boundary Strength) ------------------------------------------------------
        // Average QP of the two blocks
        //QP is for chroma flag = 0 (yuv)
        
        for(i=0; i<16; i++)
        {
          qPp    = ((MbP[i]->mb_type == IPCM) ? 0 : MbP[i]->qp);   // IPCM = 14 at defines.h
          qPq    = ((MbQ[i]->mb_type == IPCM) ? 0 : MbQ[i]->qp);
          QP[i]  = ( qPp + qPq + 1) >> 1;                          // Average QP of the two blocks
        }
        
        //Need work for GetStrength(): MbP --> MbP[i] 
        GetStrength( Strength, img, MbP, MbQ, horizontal, edge, mb_y<<2, mb_x<<2, mvlimit); // Strength for 4 blks in 1 stripe
 
        //Need more work done below
        
        if( *((int*)Strength) )                      // only if one of the 4 Strength bytes is != 0
        {
          EdgeLoop( SrcY + (edge<<2)* ((horizontal)? img->width:1 ), Strength, QP, MbQ[0]->LFAlphaC0Offset, MbQ[0]->LFBetaOffset, horizontal, img->width, 0) ; 
          
          if( (imgUV != NULL) && !(edge & 1) )
          {
            //8.7.2.2 (chroma flag = 1)
            for(i=0; i<16; i++) 
            {
              qPq = MbQ[i]->mb_type==IPCM ? QP_SCALE_CR[0] : QP_SCALE_CR[MbQ[i]->qp];
              qPp = MbP[i]->mb_type==IPCM ? QP_SCALE_CR[0] : QP_SCALE_CR[MbP[i]->qp];
              QPC[i] = (qPp + qPq + 1) >> 1;								
            }
            
            EdgeLoop( SrcU +  (edge<<1) * ((horizontal)? img->width_cr:1 ), Strength, QPC, MbQ[0]->LFAlphaC0Offset, MbQ[0]->LFBetaOffset, horizontal, img->width_cr, 1 ) ; 
            EdgeLoop( SrcV +  (edge<<1) * ((horizontal)? img->width_cr:1 ), Strength, QPC, MbQ[0]->LFAlphaC0Offset, MbQ[0]->LFBetaOffset, horizontal, img->width_cr, 1 ) ; 
          }
        }
        
        // In the strangest case, filter again for the top edge of the bottom field 
        if(img->MbaffFrameFlag && !edge && horizontal && !MbQ[0]->mb_field && !(mb_addr & 1) && 
          img->mb_data[mb_addr - (img->PicWidthInMbs << 1)].mb_field)
        {
          for(i=0; i<16; i++) 
          {
            MbP[i] = &img->mb_data[(mb_addr | 1) - (img->PicWidthInMbs << 1)]; // to apply to bot field lines
            
            // In the second pass, we don't need to compute Average QP of the two blocks again.
          }
          
          GetStrength(Strength,img,MbP,MbQ,horizontal,edge,mb_y<<2,mb_x<<2, mvlimit); // Strength for 4 blks in 1 stripe
          
          if( *((int*)Strength) )                      // only if one of the 4 Strength bytes is != 0
          {
            EdgeLoop( SrcY + (edge<<2)* ((horizontal)? img->width:1 ), Strength, QP, MbQ[0]->LFAlphaC0Offset, MbQ[0]->LFBetaOffset, horizontal, img->width, 0) ; 

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -