📄 loopfilter.c.new
字号:
/*!
*************************************************************************************
* \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 + -