Initial community commit

This commit is contained in:
Jef
2024-09-24 14:54:57 +02:00
parent 537bcbc862
commit 20d28e80a5
16810 changed files with 4640254 additions and 2 deletions
@@ -0,0 +1,76 @@
/****************************************************************************
*
* Module Title : DeInterlace.c
*
* Description : De-Interlace routines.
*
***************************************************************************/
/****************************************************************************
* Header Files
****************************************************************************/
#include <memory.h>
#include "type_aliases.h"
/****************************************************************************
*
* ROUTINE : CFastDeInterlace
*
* INPUTS : UINT8 *SrcPtr : Pointer to input image.
* UINT8 *DstPtr : Pointer to output image.
* INT32 Width : Image width.
* INT32 Height : Image height.
* INT32 Stride : Image stride.
*
* OUTPUTS : None.
*
* RETURNS : void
*
* FUNCTION : Applies a 3-tap filter vertically to remove interlacing
* artifacts.
*
* SPECIAL NOTES : This function use a three tap filter [1, 2, 1] to blur
* veritically in an interlaced frame. This function assumes:
* 1) SrcPtr & DstPtr buffers have the same geometry.
* 2) SrcPtr != DstPtr.
*
****************************************************************************/
void CFastDeInterlace
(
UINT8 *SrcPtr,
UINT8 *DstPtr,
INT32 Width,
INT32 Height,
INT32 Stride
)
{
INT32 i, j;
UINT32 x0, x1, x2;
UINT8 *PrevSrcPtr, *NextSrcPtr;
UINT8 *CurrentSrcPtr = SrcPtr;
UINT8 *CurrentDstPtr = DstPtr;
// Always copy the first line
memcpy ( CurrentDstPtr, CurrentSrcPtr, Width );
for ( i=1; i<Height-1; i++ )
{
PrevSrcPtr = CurrentSrcPtr;
CurrentSrcPtr += Stride;
NextSrcPtr = CurrentSrcPtr + Stride;
CurrentDstPtr += Stride;
for ( j=0; j<Width; j++ )
{
x0 = PrevSrcPtr[j];
x1 = (CurrentSrcPtr[j]<<1);
x2 = NextSrcPtr[j];
CurrentDstPtr[j] = (UINT8)( (x0 + x1 + x2 + 2)>>2 );
}
}
// Copy the last line
CurrentSrcPtr += Stride;
CurrentDstPtr += Stride;
memcpy ( CurrentDstPtr, CurrentSrcPtr, Width );
}
@@ -0,0 +1,303 @@
/****************************************************************************
*
* Module Title : borders.c
*
* Description :
*
****************************************************************************/
#define STRICT /* Strict type checking */
/****************************************************************************
* Header Files
****************************************************************************/
#include "postp.h"
#ifdef MAPCA
#include "eti/mm.h"
#include "eti_loopdir.h"
#endif
#ifdef MAPCA
void CopyYLeftRightBorder
(
UINT8 *restrict SrcPtr1,
UINT8 *restrict SrcPtr2,
UINT8 *restrict DestPtr1,
UINT8 *restrict DestPtr2,
UINT32 PlaneHeight,
UINT32 PlaneStride
)
{
n64 *restrict DstPtr64_1 = (n64* restrict)DestPtr1;
n64 *restrict DstPtr64_2 = (n64* restrict)DestPtr2;
n32 PlaneStride64 = (PlaneStride>>3);
n32 Left, Right;
n64 Left64, Right64;
int i;
loop_directives ( ELD_SWP_IVDEP );
for ( i=0; i<PlaneHeight; i++ )
{
Left = SrcPtr1[0];
Right = SrcPtr2[0];
Left64 = hmpv_bcopyrev_64_32 ( Left, 0, 0 );
Right64 = hmpv_bcopyrev_64_32 ( Right, 0, 0 );
DstPtr64_1[0] = Left64;
DstPtr64_2[0] = Right64;
DstPtr64_1[1] = Left64;
DstPtr64_2[1] = Right64;
DstPtr64_1[2] = Left64;
DstPtr64_2[2] = Right64;
DstPtr64_1[3] = Left64;
DstPtr64_2[3] = Right64;
SrcPtr1 += PlaneStride;
SrcPtr2 += PlaneStride;
DstPtr64_1 += PlaneStride64;
DstPtr64_2 += PlaneStride64;
}
}
void CopyUVLeftRightBorder
(
UINT8 *restrict SrcPtr1,
UINT8 *restrict SrcPtr2,
UINT8 *restrict DestPtr1,
UINT8 *restrict DestPtr2,
UINT32 PlaneHeight,
UINT32 PlaneStride
)
{
n64 *restrict DstPtr64_1 = (n64* restrict)DestPtr1;
n64 *restrict DstPtr64_2 = (n64* restrict)DestPtr2;
n32 PlaneStride64 = (PlaneStride>>3);
n32 Left, Right;
n64 Left64, Right64;
int i;
loop_directives ( ELD_SWP_IVDEP );
for ( i=0; i<PlaneHeight; i++ )
{
Left = SrcPtr1[0];
Right = SrcPtr2[0];
Left64 = hmpv_bcopyrev_64_32 ( Left, 0, 0 );
Right64 = hmpv_bcopyrev_64_32 ( Right, 0, 0 );
DstPtr64_1[0] = Left64;
DstPtr64_2[0] = Right64;
DstPtr64_1[1] = Left64;
DstPtr64_2[1] = Right64;
SrcPtr1 += PlaneStride;
SrcPtr2 += PlaneStride;
DstPtr64_1 += PlaneStride64;
DstPtr64_2 += PlaneStride64;
}
}
#endif
/****************************************************************************
*
* ROUTINE : UpdateUMVBorder
*
* INPUTS : POSTPROC_INSTANCE *pbi : Pointer to post-processor instance.
* UINT8 *DestReconPtr : Pointer to reconstructed image.
*
* OUTPUTS : None.
*
* RETURNS : void
*
* FUNCTION : Copies pixel values in first/last rows/columns of the
* image into the UMV border in the specified reconstructed
* image.
*
* SPECIAL NOTES : None.
*
****************************************************************************/
void UpdateUMVBorder ( POSTPROC_INSTANCE *pbi, UINT8 *DestReconPtr )
{
INT32 i;
INT32 PlaneHeight;
UINT8 *SrcPtr1, *SrcPtr2;
UINT8 *DestPtr1, *DestPtr2;
UINT32 Border = pbi->MVBorder;
INT32 PlaneStride = pbi->YStride;
/***********/
/* Y Plane */
/***********/
PlaneStride = pbi->YStride;
PlaneHeight = pbi->VFragments * 8;
// copy the left and right most columns out
SrcPtr1 = DestReconPtr + pbi->ReconYDataOffset;
SrcPtr2 = SrcPtr1 + 8 * pbi->HFragments - 1;
DestPtr1= SrcPtr1 - Border;
DestPtr2= SrcPtr2 + 1;
#ifdef MAPCA
CopyYLeftRightBorder ( SrcPtr1, SrcPtr2, DestPtr1,DestPtr2, PlaneHeight, PlaneStride );
#else
for ( i=0; i<PlaneHeight; i++ )
{
memset ( DestPtr1, SrcPtr1[0], Border );
memset ( DestPtr2, SrcPtr2[0], Border );
SrcPtr1 += PlaneStride;
SrcPtr2 += PlaneStride;
DestPtr1 += PlaneStride;
DestPtr2 += PlaneStride;
}
#endif
// Now copy the top and bottom source lines into each line of the respective borders
SrcPtr1 = DestReconPtr + Border * PlaneStride;
SrcPtr2 = SrcPtr1 + (pbi->VFragments * 8 * PlaneStride)- PlaneStride;
DestPtr1= DestReconPtr;
DestPtr2= SrcPtr2 + PlaneStride;
for ( i=0; i<(INT32)Border; i++ )
{
memcpy ( DestPtr1, SrcPtr1, PlaneStride );
memcpy ( DestPtr2, SrcPtr2, PlaneStride );
DestPtr1 += PlaneStride;
DestPtr2 += PlaneStride;
}
PlaneStride = pbi->UVStride;
PlaneHeight = pbi->VFragments * 4;
/***********/
/* U Plane */
/***********/
// copy the left and right most columns out
SrcPtr1 = DestReconPtr + pbi->ReconUDataOffset;
SrcPtr2 = SrcPtr1 + 4 * pbi->HFragments - 1;
DestPtr1= SrcPtr1 - Border/2;
DestPtr2= SrcPtr2 + 1;
#ifdef MAPCA
CopyUVLeftRightBorder ( SrcPtr1, SrcPtr2, DestPtr1,DestPtr2, PlaneHeight, PlaneStride );
#else
for ( i=0; i<PlaneHeight; i++ )
{
memset ( DestPtr1, SrcPtr1[0], Border/2 );
memset ( DestPtr2, SrcPtr2[0], Border/2 );
SrcPtr1 += PlaneStride;
SrcPtr2 += PlaneStride;
DestPtr1 += PlaneStride;
DestPtr2 += PlaneStride;
}
#endif
// Now copy the top and bottom source lines into each line of the respective borders
SrcPtr1 = DestReconPtr + pbi->ReconUDataOffset - Border/2;
SrcPtr2 = SrcPtr1 + (pbi->VFragments * 4 * PlaneStride)- PlaneStride;
DestPtr1= SrcPtr1 - Border/2*PlaneStride;
DestPtr2= SrcPtr2 + PlaneStride;
for ( i=0; i<(INT32)(Border/2); i++ )
{
memcpy ( DestPtr1, SrcPtr1, PlaneStride );
memcpy ( DestPtr2, SrcPtr2, PlaneStride );
DestPtr1 += PlaneStride;
DestPtr2 += PlaneStride;
}
/***********/
/* V Plane */
/***********/
// copy the left and right most columns out
SrcPtr1 = DestReconPtr + pbi->ReconVDataOffset;
SrcPtr2 = SrcPtr1 + 4 * pbi->HFragments - 1;
DestPtr1= SrcPtr1 - Border/2;
DestPtr2= SrcPtr2 + 1;
#ifdef MAPCA
CopyUVLeftRightBorder ( SrcPtr1, SrcPtr2, DestPtr1,DestPtr2, PlaneHeight, PlaneStride );
#else
for ( i=0; i<PlaneHeight; i++ )
{
memset ( DestPtr1, SrcPtr1[0], Border/2 );
memset ( DestPtr2, SrcPtr2[0], Border/2 );
SrcPtr1 += PlaneStride;
SrcPtr2 += PlaneStride;
DestPtr1 += PlaneStride;
DestPtr2 += PlaneStride;
}
#endif
// Now copy the top and bottom source lines into each line of the respective borders
SrcPtr1 = DestReconPtr + pbi->ReconVDataOffset - Border/2;
SrcPtr2 = SrcPtr1 + (pbi->VFragments * 4 * PlaneStride)- PlaneStride;
DestPtr1= SrcPtr1 - Border/2*PlaneStride;
DestPtr2= SrcPtr2 + PlaneStride;
for ( i=0; i<(INT32)(Border/2); i++ )
{
memcpy ( DestPtr1, SrcPtr1, PlaneStride );
memcpy ( DestPtr2, SrcPtr2, PlaneStride );
DestPtr1 += PlaneStride;
DestPtr2 += PlaneStride;
}
}
/****************************************************************************
*
* ROUTINE : CopyFrame
*
* INPUTS : POSTPROC_INSTANCE *pbi : Pointer to post-processor instance.
* YUV_BUFFER_CONFIG *b : Pointer to source image.
* UINT8 *DestReconPtr : Pointer to destination image.
*
* OUTPUTS : None.
*
* RETURNS : void
*
* FUNCTION : Copies the source image into the destination image and
* updates the destination's UMV borders.
*
* SPECIAL NOTES : None.
*
****************************************************************************/
void CopyFrame ( POSTPROC_INSTANCE *pbi, YUV_BUFFER_CONFIG *b, UINT8 *DestReconPtr )
{
int row;
unsigned char *source, *dest;
source = (unsigned char *) b->YBuffer;
dest = DestReconPtr + pbi->ReconYDataOffset;
for ( row=0; row<b->YHeight; row++ )
{
memcpy ( dest, source, b->YWidth );
source += b->YStride;
dest += pbi->YStride;
}
source = (unsigned char *) b->UBuffer;
dest = DestReconPtr + pbi->ReconUDataOffset;
for ( row=0; row<b->UVHeight; row++ )
{
memcpy ( dest, source, b->UVWidth );
source += b->UVStride;
dest += pbi->UVStride;
}
source = (unsigned char *) b->VBuffer;
dest = DestReconPtr + pbi->ReconVDataOffset;
for ( row=0; row<b->UVHeight; row++ )
{
memcpy ( dest, source, b->UVWidth );
source += b->UVStride;
dest += pbi->UVStride;
}
UpdateUMVBorder ( pbi, DestReconPtr );
}
@@ -0,0 +1,75 @@
/****************************************************************************
*
* Module Title : clamp.c
*
* Description : Image pixel value clamping routines.
*
***************************************************************************/
/****************************************************************************
* Header Files
****************************************************************************/
#include "postp.h"
/****************************************************************************
*
* ROUTINE : ClampLevels_C
*
* INPUTS : POSTPROC_INSTANCE *pbi : Pointer to post-processor instance.
* INT32 BlackClamp, : Number of levels to clamp up from 0.
* INT32 WhiteClamp, : Number of levels to clamp down from 255.
* UINT8 *Src, : Pointer to input image to be clamped.
* UINT8 *Dst : Pointer to clamped image.
*
* OUTPUTS : None.
*
* RETURNS : void
*
* FUNCTION : Clamps the pixel values in the input image at each
* end of the 8-bit range.
*
* SPECIAL NOTES : BlackClamp/WhiteClamp are the number.of levels to
* clamp at either end of the range. In particular, it
* should be noted that WhiteClamp is _not_ the level
* to clamp to at the high end of the range.
*
****************************************************************************/
void ClampLevels_C
(
POSTPROC_INSTANCE *pbi,
INT32 BlackClamp,
INT32 WhiteClamp,
UINT8 *Src,
UINT8 *Dst
)
{
int i;
int row,col;
unsigned char clamped[256];
int width = pbi->HFragments*8;
int height = pbi->VFragments*8;
UINT8 *SrcPtr = Src + pbi->ReconYDataOffset;
UINT8 *DestPtr = Dst + pbi->ReconYDataOffset;
UINT32 LineLength = pbi->YStride;
// set up clamping table so we can avoid ifs while clamping
for ( i=0; i<256; i++ )
{
clamped[i] = i;
if ( i<BlackClamp )
clamped[i] = BlackClamp;
if ( i>(255-WhiteClamp) )
clamped[i] = 255-WhiteClamp;
}
// clamping is for Y only!
for ( row=0 ; row<height; row++ )
{
for ( col=0; col<width; col++ )
SrcPtr[col] = clamped[DestPtr[col]];
SrcPtr += LineLength;
DestPtr += LineLength;
}
}
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,92 @@
/****************************************************************************
*
* Module Title : SystemDependant.c
*
* Description : Miscellaneous system dependant functions
*
****************************************************************************/
/*******************************************3********************************
* Header Files
****************************************************************************/
#include "postp.h"
/****************************************************************************
* Imports
****************************************************************************/
extern void GetProcessorFlags ( INT32 *MmxEnabled, INT32 *XmmEnabled, INT32 *WmtEnabled );
extern void FilteringVert_12_C ( UINT32 QValue,UINT8 *Src, INT32 Pitch);
extern void FilteringHoriz_12_C ( UINT32 QValue, UINT8 *Src, INT32 Pitch );
extern void FilteringVert_8_C ( UINT32 QValue, UINT8 *Src, INT32 Pitch );
extern void FilteringHoriz_8_C ( UINT32 QValue, UINT8 *Src, INT32 Pitch );
extern void HorizontalLine_1_2_Scale_C ( const unsigned char *source, unsigned int sourceWidth, unsigned char *dest, unsigned int destWidth );
extern void HorizontalLine_3_5_Scale_C ( const unsigned char *source, unsigned int sourceWidth, unsigned char *dest, unsigned int destWidth );
extern void HorizontalLine_4_5_Scale_C ( const unsigned char *source, unsigned int sourceWidth, unsigned char *dest, unsigned int destWidth );
extern void VerticalBand_4_5_Scale_C ( unsigned char *dest, unsigned int destPitch, unsigned int destWidth );
extern void LastVerticalBand_4_5_Scale_C ( unsigned char *dest, unsigned int destPitch, unsigned int destWidth );
extern void VerticalBand_3_5_Scale_C ( unsigned char *dest, unsigned int destPitch, unsigned int destWidth );
extern void LastVerticalBand_3_5_Scale_C ( unsigned char *dest, unsigned int destPitch, unsigned int destWidth );
extern void VerticalBand_1_2_Scale_C ( unsigned char *dest, unsigned int destPitch, unsigned int destWidth );
extern void LastVerticalBand_1_2_Scale_C ( unsigned char *dest, unsigned int destPitch, unsigned int destWidth );
extern void FilterHoriz_Simple_C ( POSTPROC_INSTANCE *pbi, UINT8 *PixelPtr, INT32 LineLength, INT32 *BoundingValuePtr );
extern void FilterVert_Simple_C ( POSTPROC_INSTANCE *pbi, UINT8 *PixelPtr, INT32 LineLength, INT32 *BoundingValuePtr );
extern void FilterHoriz_Generic ( POSTPROC_INSTANCE *pbi, UINT8 *PixelPtr, INT32 LineLength, INT32 *BoundingValuePtr );
extern void FilterVert_Generic ( POSTPROC_INSTANCE *pbi, UINT8 *PixelPtr, INT32 LineLength, INT32 *BoundingValuePtr );
extern INT32 *SetupBoundingValueArray_Generic ( POSTPROC_INSTANCE *pbi, INT32 FLimit );
extern INT32 *SetupDeblockValueArray_Generic ( POSTPROC_INSTANCE *pbi, INT32 FLimit );
extern void DeringBlockWeak_C ( POSTPROC_INSTANCE *pbi, const UINT8 *SrcPtr, UINT8 *DstPtr, const INT32 Pitch, UINT32 FragQIndex, UINT32 *QuantScale );
extern void DeringBlockStrong_C ( POSTPROC_INSTANCE *pbi, const UINT8 *SrcPtr, UINT8 *DstPtr, const INT32 Pitch, UINT32 FragQIndex, UINT32 *QuantScale );
extern void DeblockLoopFilteredBand_C ( POSTPROC_INSTANCE *pbi, UINT8 *SrcPtr, UINT8 *DesPtr, UINT32 PlaneLineStep, UINT32 FragsAcross, UINT32 StartFrag, UINT32 *QuantScale );
extern void DeblockNonFilteredBand_C ( POSTPROC_INSTANCE *pbi, UINT8 *SrcPtr, UINT8 *DesPtr, UINT32 PlaneLineStep, UINT32 FragsAcross, UINT32 StartFrag, UINT32 *QuantScale );
extern void DeblockNonFilteredBandNewFilter_C ( POSTPROC_INSTANCE *pbi, UINT8 *SrcPtr, UINT8 *DesPtr, UINT32 PlaneLineStep, UINT32 FragsAcross, UINT32 StartFrag, UINT32 *QuantScale );
extern void ClampLevels_C( POSTPROC_INSTANCE *pbi,INT32 BlackClamp,INT32 WhiteClamp,UINT8 *Src,UINT8 *Dst);
extern void CFastDeInterlace(UINT8 * SrcPtr,UINT8 * DstPtr,INT32 Width,INT32 Height,INT32 Stride);
extern void PlaneAddNoise_C( UINT8 *Start, UINT32 Width, UINT32 Height, INT32 Pitch, int q);
/****************************************************************************
*
* ROUTINE : PostProcMachineSpecificConfig
*
* INPUTS : UINT32 version : Codec version number (UNUSED)
*
* OUTPUTS : None.
*
* RETURNS : void
*
* FUNCTION : Sets post-processing function pointers to vanilla
* C implementations.
*
* SPECIAL NOTES : None.
*
****************************************************************************/
void PostProcMachineSpecificConfig ( UINT32 Version )
{
FilterHoriz = FilterHoriz_Generic;
FilterVert = FilterVert_Generic;
SetupBoundingValueArray = SetupBoundingValueArray_Generic;
SetupDeblockValueArray = SetupDeblockValueArray_Generic;
DeringBlockWeak = DeringBlockWeak_C;
DeringBlockStrong = DeringBlockStrong_C;
DeblockLoopFilteredBand = DeblockLoopFilteredBand_C;
DeblockNonFilteredBand = DeblockNonFilteredBand_C;
DeblockNonFilteredBandNewFilter = DeblockNonFilteredBandNewFilter_C;
FilterHoriz_Simple = FilterHoriz_Simple_C;
FilterVert_Simple = FilterVert_Simple_C;
HorizontalLine_1_2_Scale = HorizontalLine_1_2_Scale_C;
VerticalBand_1_2_Scale = VerticalBand_1_2_Scale_C;
LastVerticalBand_1_2_Scale = LastVerticalBand_1_2_Scale_C;
HorizontalLine_3_5_Scale = HorizontalLine_3_5_Scale_C;
VerticalBand_3_5_Scale = VerticalBand_3_5_Scale_C;
LastVerticalBand_3_5_Scale = LastVerticalBand_3_5_Scale_C;
HorizontalLine_4_5_Scale = HorizontalLine_4_5_Scale_C;
VerticalBand_4_5_Scale = VerticalBand_4_5_Scale_C;
LastVerticalBand_4_5_Scale = LastVerticalBand_4_5_Scale_C;
FilteringHoriz_8 = FilteringHoriz_8_C;
FilteringVert_8 = FilteringVert_8_C;
FilteringHoriz_12 = FilteringHoriz_12_C;
FilteringVert_12 = FilteringVert_12_C;
FastDeInterlace = CFastDeInterlace;
ClampLevels = ClampLevels_C;
PlaneAddNoise = PlaneAddNoise_C;
}
@@ -0,0 +1,976 @@
/****************************************************************************
*
* Module Title : loopfilter.c
*
* Description : Loop filter functions.
*
****************************************************************************/
#define STRICT /* Strict type checking */
/****************************************************************************
* Header Files
****************************************************************************/
#include "postp.h"
/****************************************************************************
* Macros
****************************************************************************/
#define Mod8(x) ( (x) & 7 )
/****************************************************************************
* Exports
****************************************************************************/
UINT32 LoopFilterLimitValuesV1[Q_TABLE_SIZE] =
{
30, 25, 20, 20, 15, 15, 14, 14,
13, 13, 12, 12, 11, 11, 10, 10,
9, 9, 8, 8, 7, 7, 7, 7,
6, 6, 6, 6, 5, 5, 5, 5,
4, 4, 4, 4, 3, 3, 3, 3,
2, 2, 2, 2, 2, 2, 2, 2,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0
};
UINT32 *LoopFilterLimitValuesV2;
UINT32 LoopFilterLimitValuesVp4[Q_TABLE_SIZE] =
{
30, 25, 20, 20, 15, 15, 14, 14,
13, 13, 12, 12, 11, 11, 10, 10,
9, 9, 8, 8, 7, 7, 7, 7,
6, 6, 6, 6, 5, 5, 5, 5,
4, 4, 4, 4, 3, 3, 3, 3,
2, 2, 2, 2, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2,
1, 1, 1, 1, 1, 1, 1, 1
};
UINT32 LoopFilterLimitValuesVp5[Q_TABLE_SIZE] =
{
14, 14, 13, 13, 12, 12, 10, 10,
10, 10, 8, 8, 8, 8, 8, 8,
8, 8, 8, 8, 8, 8, 8, 8,
8, 8, 8, 8, 8, 8, 8, 8,
8, 8, 8, 8, 7, 7, 7, 7,
7, 7, 6, 6, 6, 6, 6, 6,
5, 5, 5, 5, 4, 4, 4, 4,
4, 4, 4, 3, 3, 3, 3, 2
};
UINT32 LoopFilterLimitValuesVp6[Q_TABLE_SIZE] =
{
14, 14, 13, 13, 12, 12, 10, 10,
10, 10, 8, 8, 8, 8, 8, 8,
8, 8, 8, 8, 8, 8, 8, 8,
8, 8, 8, 8, 8, 8, 8, 8,
8, 8, 8, 8, 7, 7, 7, 7,
7, 7, 6, 6, 6, 6, 6, 6,
5, 5, 5, 5, 4, 4, 4, 4,
4, 4, 4, 3, 3, 3, 3, 2
};
/****************************************************************************
*
* ROUTINE : SetupBoundingValueArray_Generic
*
* INPUTS : POSTPROC_INSTANCE *ppi : Pointer to post-processor instance.
* INT32 FLimit : Value to use as limit.
*
* OUTPUTS : None.
*
* RETURNS : INT32: Pointer to LUT position 0 (cast to UINT32)
*
* FUNCTION : Set up the bounding value array.
*
* SPECIAL NOTES : None.
*
****************************************************************************/
INT32 *SetupBoundingValueArray_Generic ( POSTPROC_INSTANCE *ppi, INT32 FLimit )
{
INT32 i;
INT32 *BoundingValuePtr;
BoundingValuePtr = &ppi->FiltBoundingValue[256];
// Set up the bounding value array
memset ( ppi->FiltBoundingValue, 0, (512*sizeof(*ppi->FiltBoundingValue)) );
for ( i=0; i<FLimit; i++ )
{
BoundingValuePtr[-i-FLimit] = (-FLimit+i);
BoundingValuePtr[-i] = -i;
BoundingValuePtr[i] = i;
BoundingValuePtr[i+FLimit] = FLimit-i;
}
return BoundingValuePtr;
}
/****************************************************************************
*
* ROUTINE : SetupLoopFilter
*
* INPUTS : POSTPROC_INSTANCE *ppi : Pointer to post-processor instance.
*
* OUTPUTS : None.
*
* RETURNS : void
*
* FUNCTION : Initializes LUTs and function pointer for loop filter.
*
* SPECIAL NOTES : None.
*
****************************************************************************/
void SetupLoopFilter ( POSTPROC_INSTANCE *ppi )
{
INT32 FLimit;
FLimit = LoopFilterLimitValuesV2[ppi->FrameQIndex];
if ( ppi->Vp3VersionNo >= 2 )
ppi->BoundingValuePtr = SetupBoundingValueArray_Generic(ppi, FLimit);
else
ppi->BoundingValuePtr = SetupBoundingValueArray ( ppi, FLimit );
}
/****************************************************************************
*
* ROUTINE : FilterHoriz_Generic
*
* INPUTS : POSTPROC_INSTANCE *ppi : Pointer to post-processor instance.
* UINT8 *PixelPtr : Pointer to Pointer to input data.
* INT32 LineLength : Stride of input data.
* INT32 *BoundingValuePtr : Pointer to array of bounding values.
*
* OUTPUTS : None.
*
* RETURNS : void
*
* FUNCTION : Applies the 4-tap loop-filter across vertical edge,
* i.e. filter is applied horizontally.
*
* SPECIAL NOTES : 4-Tap filter used is (1, -3, 3, -1).
*
****************************************************************************/
void FilterHoriz_Generic
(
POSTPROC_INSTANCE *ppi,
UINT8 *PixelPtr,
INT32 LineLength,
INT32 *BoundingValuePtr
)
{
INT32 j;
INT32 FiltVal;
UINT8 *LimitTable = &LimitVal_VP31[VAL_RANGE];
(void)ppi;
for ( j=0; j<8; j++ )
{
FiltVal = PixelPtr[0] - (PixelPtr[1]*3) + (PixelPtr[2]*3) - PixelPtr[3];
FiltVal = BoundingValuePtr[(FiltVal + 4) >> 3];
PixelPtr[1] = LimitTable[(INT32)PixelPtr[1] + FiltVal];
PixelPtr[2] = LimitTable[(INT32)PixelPtr[2] - FiltVal];
PixelPtr += LineLength;
}
}
/****************************************************************************
*
* ROUTINE : FilterVert_Generic
*
* INPUTS : POSTPROC_INSTANCE *ppi : Pointer to post-processor instance.
* UINT8 *PixelPtr : Pointer to Pointer to input data.
* INT32 LineLength : Stride of input data.
* INT32 *BoundingValuePtr : Pointer to array of bounding values.
*
* OUTPUTS : None.
*
* RETURNS : void
*
* FUNCTION : Applies the 4-tap loop-filter across horizontal edge,
* i.e. filter is applied vertically.
*
* SPECIAL NOTES : 4-Tap filter used is (1, -3, 3, -1).
*
****************************************************************************/
void FilterVert_Generic
(
POSTPROC_INSTANCE *ppi,
UINT8 *PixelPtr,
INT32 LineLength,
INT32 *BoundingValuePtr
)
{
INT32 j;
INT32 FiltVal;
UINT8 * LimitTable = &LimitVal_VP31[VAL_RANGE];
(void)ppi;
for ( j=0; j<8; j++ )
{
FiltVal = (INT32)PixelPtr[-(2 * LineLength)]
- ((INT32)PixelPtr[- LineLength] * 3)
+ ((INT32)PixelPtr[0] * 3)
- (INT32)PixelPtr[LineLength];
FiltVal = BoundingValuePtr[(FiltVal + 4) >> 3];
PixelPtr[-LineLength] = LimitTable[(INT32)PixelPtr[-LineLength] + FiltVal];
PixelPtr[0] = LimitTable[(INT32)PixelPtr[0] - FiltVal];
PixelPtr++;
}
}
/****************************************************************************
*
* ROUTINE : Bound
*
* INPUTS : UINT32 FLimit : Limit to use in computing bounding value.
* INT32 FiltVal : Value to have bounds applied to.
*
* OUTPUTS : None.
*
* RETURNS : INT32:
*
* FUNCTION : Computes a bounded Filtval based on specified Flimit.
*
* SPECIAL NOTES : None.
*
****************************************************************************/
#if defined (_WIN32_WCE)
INT32 Bound ( UINT32 FLimit, INT32 FiltVal )
#else
INLINE INT32 Bound ( UINT32 FLimit, INT32 FiltVal )
#endif
{
INT32 Clamp;
INT32 FiltSign;
INT32 NewSign;
Clamp = 2 * FLimit;
// Next 3 lines are fast way to find abs...
FiltSign = (FiltVal >> 31); // Sign extension makes FiltSign all 0's or all 1's
FiltVal ^= FiltSign; // FiltVal is then 1's complement of value if -ve
FiltVal -= FiltSign; // Filtval = abs Filtval
FiltVal *= (FiltVal < Clamp); // clamp filter value to 2 times limit
FiltVal -= FLimit; // subtract limit value
// Next 3 lines are fast way to find abs...
NewSign = (FiltVal >> 31); // Sign extension makes NewSign all 0's or all 1's
FiltVal ^= NewSign; // FiltVal is then 1's complement of value if -ve
FiltVal -= NewSign; // FiltVal = abs FiltVal
FiltVal = FLimit - FiltVal; // flimit - abs (filtVal - flimit)
FiltVal += FiltSign; // convert back to signed value
FiltVal ^= FiltSign;
return FiltVal;
}
/****************************************************************************
*
* ROUTINE : FilteringHoriz_8_C
*
* INPUTS : UINT32 QValue : Current quatizer level.
* UINT8 *Src : Pointer to data to be filtered.
* INT32 Pitch : Pitch of input data.
*
* OUTPUTS : None.
*
* RETURNS : void
*
* FUNCTION : Applies horizontal filter across vertical edge inside
* block with Q-dependent limits.
*
* SPECIAL NOTES : 4-Tap filter used is (1, -3, 3, -1).
*
****************************************************************************/
void FilteringHoriz_8_C ( UINT32 QValue, UINT8 *Src, INT32 Pitch )
{
INT32 j;
INT32 FiltVal;
UINT32 FLimit;
UINT8 *LimitTable = &LimitVal_VP31[VAL_RANGE];
FLimit = LoopFilterLimitValuesV2[QValue];
for ( j=0; j<8; j++ )
{
// Apply 4-tap filter with rounding...
FiltVal = ( Src[-2] -
(Src[-1] * 3) +
(Src[ 0] * 3) -
Src[ 1] + 4 ) >> 3;
FiltVal = Bound ( FLimit, FiltVal );
Src[-1] = LimitTable[(INT32)Src[-1] + FiltVal];
Src[ 0] = LimitTable[(INT32)Src[ 0] - FiltVal];
Src += Pitch;
}
}
/****************************************************************************
*
* ROUTINE : FilteringVert_8_C
*
* INPUTS : UINT32 QValue : Current quatizer level.
* UINT8 *Src : Pointer to data to be filtered.
* INT32 Pitch : Pitch of input data.
*
* OUTPUTS : None.
*
* RETURNS : void
*
* FUNCTION : Applies vertical filter across horizontal edge inside
* block with Q-dependent limits.
*
* SPECIAL NOTES : 4-Tap filter used is (1, -3, 3, -1).
*
****************************************************************************/
void FilteringVert_8_C ( UINT32 QValue, UINT8 *Src, INT32 Pitch )
{
INT32 j;
INT32 FiltVal;
UINT32 FLimit;
UINT8 *LimitTable = &LimitVal_VP31[VAL_RANGE];
FLimit = LoopFilterLimitValuesV2[QValue];
for ( j=0; j<8; j++ )
{
// Apply 4-tap filter with rounding...
FiltVal = ( (INT32)Src[-(2 * Pitch)] -
((INT32)Src[-Pitch] * 3) +
((INT32)Src[0] * 3 ) -
(INT32)Src[Pitch] + 4 ) >> 3;
FiltVal = Bound( FLimit, FiltVal);
Src[-Pitch] = LimitTable[(INT32)Src[-Pitch] + FiltVal];
Src[ 0] = LimitTable[(INT32)Src[ 0] - FiltVal];
Src++;
}
}
/****************************************************************************
*
* ROUTINE : FilteringHoriz_12_C
*
* INPUTS : UINT32 QValue : Current quatizer level.
* UINT8 *Src : Pointer to data to be filtered.
* INT32 Pitch : Pitch of input data.
*
* OUTPUTS : None.
*
* RETURNS : void
*
* FUNCTION : Applies vertical filter across horizontal edge inside
* block with Q-dependent limits.
*
* SPECIAL NOTES : 4-Tap filter used is (1, -3, 3, -1).
*
****************************************************************************/
void FilteringHoriz_12_C ( UINT32 QValue, UINT8 *Src, INT32 Pitch )
{
INT32 j;
INT32 FiltVal;
UINT32 FLimit;
UINT8 *LimitTable = &LimitVal_VP31[VAL_RANGE];
FLimit = LoopFilterLimitValuesV2[QValue];
for ( j=0; j<12; j++ )
{
// Apply 4-tap filter with rounding...
FiltVal = ( Src[-2] -
(Src[-1] * 3) +
(Src[ 0] * 3) -
Src[1] + 4) >> 3;
FiltVal = Bound ( FLimit, FiltVal );
Src[-1] = LimitTable[(INT32)Src[-1] + FiltVal];
Src[ 0] = LimitTable[(INT32)Src[ 0] - FiltVal];
Src += Pitch;
}
}
/****************************************************************************
*
* ROUTINE : FilteringVert_12_C
*
* INPUTS : UINT32 QValue : Current quatizer level.
* UINT8 *Src : Pointer to data to be filtered.
* INT32 Pitch : Pitch of input data.
*
* OUTPUTS : None.
*
* RETURNS : void
*
* FUNCTION : Applies vertical filter across horizontal edge inside
* block with Q-dependent limits.
*
* SPECIAL NOTES : 4-Tap filter used is (1, -3, 3, -1).
*
****************************************************************************/
void FilteringVert_12_C ( UINT32 QValue, UINT8 *Src, INT32 Pitch )
{
INT32 j;
INT32 FiltVal;
UINT32 FLimit;
UINT8 *LimitTable = &LimitVal_VP31[VAL_RANGE];
FLimit = LoopFilterLimitValuesV2[QValue];
for ( j=0; j<12; j++ )
{
FiltVal = ( (INT32)Src[- (2 * Pitch)] -
((INT32)Src[- Pitch] * 3) +
((INT32)Src[0] * 3) -
(INT32)Src[Pitch] + 4 ) >> 3;
FiltVal = Bound ( FLimit, FiltVal );
Src[-Pitch] = LimitTable[(INT32)Src[-Pitch] + FiltVal];
Src[ 0] = LimitTable[(INT32)Src[ 0] - FiltVal];
Src++;
}
}
/****************************************************************************
*
* ROUTINE : ApplyReconLoopFilter
*
* INPUTS : POSTPROC_INSTANCE *ppi : Pointer to post-processor instance.
* INT32 FrameQIndex : Q index for the frame.
* UINT8 *LastFrameRecon : Pointer to last frame reconstruction buffer.
* UINT8 *PostProcessBuffer : Pointer to last post-processing buffer.
* UINT8 *FragInfo : Pointer to list of coded blocks.
* UINT32 FragInfoElementSize : Size of each element.
* UINT32 FragInfoCodedMask : Mask to get at whether fragment is coded.
*
* OUTPUTS : None.
*
* RETURNS : void
*
* FUNCTION : Applies a loop filter to the edge pixels of coded blocks.
*
* SPECIAL NOTES : None.
*
****************************************************************************/
void ApplyReconLoopFilter
(
POSTPROC_INSTANCE *ppi,
INT32 FrameQIndex,
UINT8 *LastFrameRecon,
UINT8 *PostProcessBuffer,
UINT8 *FragInfo,
UINT32 FragInfoElementSize,
UINT32 FragInfoCodedMask
)
{
int j, m, n;
UINT32 nextRow;
UINT8 *rowStart;
INT32 *BoundingValuePtr;
INT32 i = 0;
INT32 FLimit = 0;
int FromFragment = 0;
INT32 LineLength = 0;
INT32 LineFragments = 0;
int FragsAcross = ppi->HFragments;
int FragsDown = ppi->VFragments;
// variables passed in per frame
ppi->FrameQIndex = FrameQIndex;
ppi->LastFrameRecon = LastFrameRecon;
ppi->PostProcessBuffer = PostProcessBuffer;
ppi->FragInfo = FragInfo;
ppi->FragInfoElementSize = FragInfoElementSize;
ppi->FragInfoCodedMask = FragInfoCodedMask;
FLimit = LoopFilterLimitValuesV1[ppi->FrameQIndex];
if ( FLimit == 0 )
return;
BoundingValuePtr = SetupBoundingValueArray ( ppi, FLimit );
for ( j=0; j<3; j++ )
{
switch ( j )
{
case 0: // Y
FromFragment = 0;
FragsAcross = ppi->HFragments;
FragsDown = ppi->VFragments;
LineLength = ppi->YStride;
LineFragments = ppi->HFragments;
rowStart = ppi->LastFrameRecon + ppi->ReconYDataOffset;
break;
case 1: // U
FromFragment = ppi->YPlaneFragments;
FragsAcross = ppi->HFragments >> 1;
FragsDown = ppi->VFragments >> 1;
LineLength = ppi->UVStride;
LineFragments = ppi->HFragments / 2;
rowStart = ppi->LastFrameRecon + ppi->ReconUDataOffset;
break;
case 2: // V
FromFragment = ppi->YPlaneFragments + ppi->UVPlaneFragments;
FragsAcross = ppi->HFragments >> 1;
FragsDown = ppi->VFragments >> 1;
LineLength = ppi->UVStride;
LineFragments = ppi->HFragments / 2;
rowStart = ppi->LastFrameRecon + ppi->ReconVDataOffset;
break;
}
nextRow = 8*LineLength;
i = FromFragment;
n = 0;
/*************/
/* First Row */
/*************/
/* First column */
// only do 2 prediction if fragment coded and on non intra or if all fragments are intra
if ( blockCoded ( i ) )
{
// Filter right hand border only if the block to the right is not coded
if ( !blockCoded ( i + 1 ) )
FilterHoriz ( ppi, rowStart+8*n+6, LineLength, BoundingValuePtr );
// Bottom done if next row set
if ( !blockCoded (i + LineFragments) )
FilterVert ( ppi, rowStart+8*n+nextRow, LineLength, BoundingValuePtr );
}
i++;
/* Middle columns */
for ( n=1; n<FragsAcross-1; n++, i++ )
{
if ( blockCoded( i ))
{
// Filter Left edge always
FilterHoriz ( ppi, rowStart+8*n-2, LineLength, BoundingValuePtr );
// Filter right hand border only if the block to the right is not coded
if ( !blockCoded( i + 1 ) )
FilterHoriz ( ppi, rowStart+8*n+6, LineLength, BoundingValuePtr );
// Bottom done if next row set
if( !blockCoded( i + LineFragments) )
FilterVert(ppi, rowStart + 8*n + nextRow, LineLength, BoundingValuePtr);
}
}
// Last Column
if ( blockCoded( i ) )
{
// Filter Left edge always
FilterHoriz ( ppi, rowStart+8*n-2, LineLength, BoundingValuePtr );
// Bottom done if next row set
if( !blockCoded (i + LineFragments) )
FilterVert(ppi, rowStart + 8*n + nextRow, LineLength, BoundingValuePtr);
}
i++;
rowStart += nextRow;
n = 0;
/***************/
/* Middle Rows */
/***************/
for ( m=1; m<FragsDown-1; m++ )
{
/* First column */
n=0;
// only do 2 prediction if fragment coded and on non intra or if all fragments are intra
if( blockCoded( i ) )
{
// TopRow is always done
FilterVert ( ppi, rowStart+8*n, LineLength, BoundingValuePtr );
// Filter right hand border only if the block to the right is not coded
if ( !blockCoded ( i + 1 ) )
FilterHoriz ( ppi, rowStart+8*n+6, LineLength, BoundingValuePtr );
// Bottom done if next row set
if ( !blockCoded (i + LineFragments) )
FilterVert ( ppi, rowStart + 8*n + nextRow, LineLength, BoundingValuePtr );
}
i++;
/* Middle columns */
for ( n=1; n<FragsAcross-1; n++, i++ )
{
if ( blockCoded ( i ) )
{
// Filter Left edge always
FilterHoriz ( ppi, rowStart+8*n-2, LineLength, BoundingValuePtr );
// TopRow is always done
FilterVert ( ppi, rowStart+8*n, LineLength, BoundingValuePtr );
// Filter right hand border only if the block to the right is not coded
if ( !blockCoded ( i + 1 ) )
FilterHoriz ( ppi, rowStart + 8*n + 6 , LineLength, BoundingValuePtr );
// Bottom done if next row set
if ( !blockCoded (i + LineFragments) )
FilterVert ( ppi, rowStart+8*n+nextRow, LineLength, BoundingValuePtr );
}
}
/* Last Column */
if ( blockCoded ( i ) )
{
// Filter Left edge always
FilterHoriz ( ppi, rowStart+8*n-2, LineLength, BoundingValuePtr );
// TopRow is always done
FilterVert ( ppi, rowStart+8*n, LineLength, BoundingValuePtr );
// Bottom done if next row set
if ( !blockCoded (i + LineFragments) )
FilterVert ( ppi, rowStart + 8*n + nextRow, LineLength, BoundingValuePtr );
}
i++;
rowStart += nextRow;
}
}
//***********/
// Last Row */
//***********/
/* First Column */
n = 0;
// only do 2 prediction if fragment coded and on non intra or if all fragments are intra
if ( blockCoded ( i ) )
{
// TopRow is always done
FilterVert ( ppi, rowStart+8*n, LineLength, BoundingValuePtr );
// Filter right hand border only if the block to the right is not coded
if ( !blockCoded ( i + 1 ) )
FilterHoriz ( ppi, rowStart+8*n+6, LineLength, BoundingValuePtr );
}
i++;
/* middle columns */
for ( n=1; n<FragsAcross-1; n++, i++ )
{
if ( blockCoded ( i ) )
{
// Filter Left edge always
FilterHoriz ( ppi, rowStart+8*n-2, LineLength, BoundingValuePtr );
// TopRow is always done
FilterVert ( ppi, rowStart+8*n, LineLength, BoundingValuePtr );
// Filter right hand border only if the block to the right is not coded
if ( !blockCoded( i + 1 ) )
FilterHoriz ( ppi, rowStart+8*n+6, LineLength, BoundingValuePtr );
}
}
/* Last Column */
if ( blockCoded ( i ) )
{
// Filter Left edge always
FilterHoriz ( ppi, rowStart+8*n-2, LineLength, BoundingValuePtr );
// TopRow is always done
FilterVert ( ppi, rowStart+8*n, LineLength, BoundingValuePtr );
}
}
/****************************************************************************
*
* ROUTINE : LoopFilter
*
* INPUTS : POSTPROC_INSTANCE *ppi : Pointer to post-processor instance.
* INT32 FrameQIndex : Q index for the frame.
* UINT8 *LastFrameRecon : Pointer to last frame reconstruction buffer.
* UINT8 *PostProcessBuffer : Pointer to last post-processing buffer.
* UINT8 *FragInfo : Pointer to list of coded blocks.
* UINT32 FragInfoElementSize : Size of each element.
* UINT32 FragInfoCodedMask : Mask to get at whether fragment is coded.
*
* OUTPUTS : None.
*
* RETURNS : void
*
* FUNCTION : Applies a loop filter to the edge pixels of coded blocks.
*
* SPECIAL NOTES : None.
*
****************************************************************************/
void LoopFilter
(
POSTPROC_INSTANCE *ppi,
INT32 FrameQIndex,
UINT8 *LastFrameRecon,
UINT8 *PostProcessBuffer,
UINT8 *FragInfo,
UINT32 FragInfoElementSize,
UINT32 FragInfoCodedMask
)
{
int j, m, n;
UINT32 nextRow;
UINT8 *rowStart;
INT32 *BoundingValuePtr;
INT32 i = 0;
INT32 FLimit = 0;
int FromFragment = 0;
INT32 LineLength = 0;
INT32 LineFragments = 0;
int FragsDown = ppi->VFragments;
int FragsAcross = ppi->HFragments;
// variables passed in per frame
ppi->FrameQIndex = FrameQIndex;
ppi->LastFrameRecon = LastFrameRecon;
ppi->PostProcessBuffer = PostProcessBuffer;
ppi->FragInfo = FragInfo;
ppi->FragInfoElementSize = FragInfoElementSize;
ppi->FragInfoCodedMask = FragInfoCodedMask;
FLimit = LoopFilterLimitValuesV1[ppi->FrameQIndex];
if ( FLimit == 0 )
return;
BoundingValuePtr = SetupBoundingValueArray ( ppi, FLimit );
for ( j=0; j<3; j++ )
{
switch ( j )
{
case 0: // Y
FromFragment = 0;
FragsAcross = ppi->HFragments;
FragsDown = ppi->VFragments;
LineLength = ppi->YStride;
LineFragments = ppi->HFragments;
rowStart = ppi->LastFrameRecon + ppi->ReconYDataOffset;
break;
case 1: // U
FromFragment = ppi->YPlaneFragments;
FragsAcross = ppi->HFragments >> 1;
FragsDown = ppi->VFragments >> 1;
LineLength = ppi->UVStride;
LineFragments = ppi->HFragments / 2;
rowStart = ppi->LastFrameRecon + ppi->ReconUDataOffset;
break;
case 2: // V
FromFragment = ppi->YPlaneFragments + ppi->UVPlaneFragments;
FragsAcross = ppi->HFragments >> 1;
FragsDown = ppi->VFragments >> 1;
LineLength = ppi->UVStride;
LineFragments = ppi->HFragments / 2;
rowStart = ppi->LastFrameRecon + ppi->ReconVDataOffset;
break;
}
nextRow = 8*LineLength;
i = FromFragment;
n = 0;
//************/
// First Row */
//************/
/* First Column */
// only do 2 prediction if fragment coded and on non intra or if all fragments are intra
if ( blockCoded ( i ) )
{
// Filter right hand border only if the block to the right is not coded
if ( !blockCoded ( i + 1 ) )
FilterHoriz ( ppi, rowStart+8*n+6, LineLength, BoundingValuePtr );
// Bottom done if next row set
if( !blockCoded (i + LineFragments) )
FilterVert ( ppi, rowStart+8*n+nextRow, LineLength, BoundingValuePtr );
}
i++;
/* Middle columns */
for ( n=1; n<FragsAcross-1; n++, i++ )
{
if ( blockCoded ( i ) )
{
// Filter Left edge always
FilterHoriz ( ppi, rowStart+8*n-2, LineLength, BoundingValuePtr );
// Filter right hand border only if the block to the right is not coded
if ( !blockCoded ( i + 1 ) )
FilterHoriz(ppi, rowStart + 8*n +6 , LineLength, BoundingValuePtr);
// Bottom done if next row set
if( !blockCoded (i + LineFragments) )
FilterVert ( ppi, rowStart+8*n+nextRow, LineLength, BoundingValuePtr );
}
}
/* Last Column */
if ( blockCoded ( i ) )
{
// Filter Left edge always
FilterHoriz ( ppi, rowStart+8*n-2, LineLength, BoundingValuePtr );
// Bottom done if next row set
if( !blockCoded (i + LineFragments) )
FilterVert ( ppi, rowStart+8*n+nextRow, LineLength, BoundingValuePtr );
}
i++;
rowStart += nextRow;
n = 0;
//**************/
// Middle Rows */
//**************/
for ( m=1; m<FragsDown-1; m++ )
{
/* First column */
n = 0;
// only do 2 prediction if fragment coded and on non intra or if all fragments are intra
if ( blockCoded ( i ) )
{
// TopRow is always done
FilterVert ( ppi, rowStart+8*n, LineLength, BoundingValuePtr );
// Filter right hand border only if the block to the right is not coded
if ( !blockCoded ( i + 1 ) )
FilterHoriz ( ppi, rowStart+8*n+6, LineLength, BoundingValuePtr );
// Bottom done if next row set
if( !blockCoded (i + LineFragments) )
FilterVert(ppi, rowStart + 8*n + nextRow, LineLength, BoundingValuePtr);
}
i++;
/* Middle columns */
for ( n=1; n<FragsAcross-1; n++, i++ )
{
if ( blockCoded ( i ) )
{
// Filter Left edge always
FilterHoriz ( ppi, rowStart+8*n-2, LineLength, BoundingValuePtr );
// TopRow is always done
FilterVert ( ppi, rowStart+8*n, LineLength, BoundingValuePtr );
// Filter right hand border only if the block to the right is not coded
if ( !blockCoded ( i + 1 ) )
FilterHoriz ( ppi, rowStart+8*n+6, LineLength, BoundingValuePtr );
// Bottom done if next row set
if( !blockCoded (i + LineFragments) )
FilterVert ( ppi, rowStart+8*n+nextRow, LineLength, BoundingValuePtr );
}
}
/* Last Column */
if ( blockCoded ( i ) )
{
// Filter Left edge always
FilterHoriz ( ppi, rowStart+8*n-2, LineLength, BoundingValuePtr );
// TopRow is always done
FilterVert ( ppi, rowStart+8*n, LineLength, BoundingValuePtr );
// Bottom done if next row set
if( !blockCoded (i + LineFragments) )
FilterVert ( ppi, rowStart+8*n+nextRow, LineLength, BoundingValuePtr );
}
i++;
rowStart += nextRow;
}
//***********/
// Last Row */
//***********/
/* First column */
n = 0;
// only do 2 prediction if fragment coded and on non intra or if all fragments are intra
if ( blockCoded ( i ) )
{
// TopRow is always done
FilterVert ( ppi, rowStart+8*n, LineLength, BoundingValuePtr );
// Filter right hand border only if the block to the right is not coded
if ( !blockCoded ( i + 1 ) )
FilterHoriz ( ppi, rowStart+8*n+6, LineLength, BoundingValuePtr );
}
i++;
/* Middle columns */
for ( n=1; n<FragsAcross-1; n++, i++ )
{
if ( blockCoded ( i ) )
{
// Filter Left edge always
FilterHoriz ( ppi, rowStart+8*n-2, LineLength, BoundingValuePtr );
// TopRow is always done
FilterVert ( ppi, rowStart+8*n, LineLength, BoundingValuePtr );
// Filter right hand border only if the block to the right is not coded
if ( !blockCoded ( i + 1 ) )
FilterHoriz ( ppi, rowStart+8*n+6, LineLength, BoundingValuePtr );
}
}
/* Last Column */
if ( blockCoded ( i ) )
{
// Filter Left edge always
FilterHoriz ( ppi, rowStart+8*n-2, LineLength, BoundingValuePtr );
// TopRow is always done
FilterVert ( ppi, rowStart+8*n, LineLength, BoundingValuePtr );
}
i++;
}
}
@@ -0,0 +1,796 @@
/***************************************************************************
*
* Module Title : PostProc.c
*
* Description : Post Processing
*
***************************************************************************/
#define STRICT /* Strict type checking */
/****************************************************************************
* Header Files
****************************************************************************/
#include "postp.h"
#include "duck_mem.h"
#include "stdlib.h"
#include <math.h>
#include <stddef.h>
/****************************************************************************
* Macros
****************************************************************************/
#define Clamp255(x) (unsigned char) ( (x) < 0 ? 0 : ( (x) <= 255 ? (x) : 255 ) )
// TODO: benski> need better checks for other compilers
#if defined(_M_AMD64) || defined(__LP64__)
#define ROUNDUP32(X) ( ( ( (uintptr_t) X ) + 31 )&( 0xFFFFFFFFFFFFFFE0 ) )
#else //#elif //defined(_M_IX86)
#define ROUNDUP32(X) ( ( ( (unsigned long) X ) + 31 )&( 0xFFFFFFE0 ) )
#endif
/****************************************************************************
* Imports
****************************************************************************/
extern void SimpleDeblockFrame(POSTPROC_INSTANCE *ppi, UINT8* SrcBuffer, UINT8* DestBuffer);
extern void UpdateUMVBorder( POSTPROC_INSTANCE *ppi, UINT8 * DestReconPtr);
extern void PostProcMachineSpecificConfig(UINT32 );
extern void DeringFrame(POSTPROC_INSTANCE *ppi, UINT8 *Src, UINT8 *Dst);
extern void DeringFrameInterlaced(POSTPROC_INSTANCE *ppi, UINT8 *Src, UINT8 *Dst);
extern void DeblockFrame(POSTPROC_INSTANCE *ppi, UINT8 *SourceBuffer, UINT8 *DestinationBuffer);
extern void DeblockFrameUsing7TapFilter(POSTPROC_INSTANCE *ppi, UINT8 *SourceBuffer, UINT8 *DestinationBuffer);
extern void DeblockFrameInterlaced(POSTPROC_INSTANCE *ppi, UINT8 *SourceBuffer, UINT8 *DestinationBuffer);
extern UINT32 DeringModifierV1[ Q_TABLE_SIZE ];
extern UINT32 DeringModifierV2[ Q_TABLE_SIZE ];
extern UINT32 *DCQuantScaleV2;
extern UINT32 *DCQuantScaleUV;
extern UINT32 *DCQuantScaleV1;
extern UINT32 LoopFilterLimitValuesVp4[Q_TABLE_SIZE];
extern UINT32 LoopFilterLimitValuesVp5[Q_TABLE_SIZE];
extern UINT32 LoopFilterLimitValuesVp6[Q_TABLE_SIZE];
extern UINT32 DeblockLimitValuesVp4[Q_TABLE_SIZE];
extern UINT32 DeblockLimitValuesVp5[Q_TABLE_SIZE];
extern UINT32 DeblockLimitValuesVp6[Q_TABLE_SIZE];
extern UINT32 *LoopFilterLimitValuesV2;
extern UINT32 *DeblockLimitValuesV2;
/****************************************************************************
* Exports
****************************************************************************/
UINT8 LimitVal_VP31[VAL_RANGE * 3];
void (*FilteringVert_12)(UINT32 QValue,UINT8 * Src, INT32 Pitch);
void (*FilteringHoriz_12)(UINT32 QValue,UINT8 * Src, INT32 Pitch);
void (*FilteringVert_8)(UINT32 QValue,UINT8 * Src, INT32 Pitch);
void (*FilteringHoriz_8)(UINT32 QValue,UINT8 * Src, INT32 Pitch);
void (*VerticalBand_4_5_Scale)(unsigned char * dest,unsigned int destPitch,unsigned int destWidth);
void (*LastVerticalBand_4_5_Scale)(unsigned char * dest,unsigned int destPitch,unsigned int destWidth);
void (*VerticalBand_3_5_Scale)(unsigned char * dest,unsigned int destPitch,unsigned int destWidth);
void (*LastVerticalBand_3_5_Scale)(unsigned char * dest,unsigned int destPitch,unsigned int destWidth);
void (*HorizontalLine_1_2_Scale)(const unsigned char * source,unsigned int sourceWidth,unsigned char * dest,unsigned int destWidth);
void (*HorizontalLine_3_5_Scale)(const unsigned char * source,unsigned int sourceWidth,unsigned char * dest,unsigned int destWidth);
void (*HorizontalLine_4_5_Scale)(const unsigned char * source,unsigned int sourceWidth,unsigned char * dest,unsigned int destWidth);
void (*VerticalBand_1_2_Scale)(unsigned char * dest,unsigned int destPitch,unsigned int destWidth);
void (*LastVerticalBand_1_2_Scale)(unsigned char * dest,unsigned int destPitch,unsigned int destWidth);
void (*FilterHoriz_Simple)(xPB_INST ppi, UINT8 * PixelPtr, INT32 LineLength, INT32*);
void (*FilterVert_Simple)(xPB_INST ppi, UINT8 * PixelPtr, INT32 LineLength, INT32*);
void (*DeringBlockWeak)(xPB_INST, const UINT8 *, UINT8 *, INT32, UINT32, UINT32 *);
void (*DeringBlockStrong)(xPB_INST, const UINT8 *, UINT8 *, INT32, UINT32, UINT32 *);
void (*DeblockLoopFilteredBand)(xPB_INST, UINT8 *, UINT8 *, UINT32, UINT32, UINT32, UINT32 *);
void (*DeblockNonFilteredBand)(xPB_INST, UINT8 *, UINT8 *, UINT32, UINT32, UINT32, UINT32 *);
void (*DeblockNonFilteredBandNewFilter)(xPB_INST, UINT8 *, UINT8 *, UINT32, UINT32, UINT32, UINT32 *);
INT32*(*SetupBoundingValueArray)(xPB_INST ppi, INT32 FLimit);
INT32*(*SetupDeblockValueArray)(xPB_INST ppi, INT32 FLimit);
void (*FilterHoriz)(xPB_INST ppi, UINT8 * PixelPtr, INT32 LineLength, INT32*);
void (*FilterVert)(xPB_INST ppi, UINT8 * PixelPtr, INT32 LineLength, INT32*);
void (*ClampLevels)( POSTPROC_INSTANCE *ppi,INT32 BlackClamp, INT32 WhiteClamp, UINT8 *Src, UINT8 *Dst);
void (*FastDeInterlace)(UINT8 *SrcPtr, UINT8 *DstPtr, INT32 Width, INT32 Height, INT32 Stride);
void (*PlaneAddNoise)( UINT8 *Start, UINT32 Width, UINT32 Height, INT32 Pitch, int q);
/****************************************************************************
*
* ROUTINE : InitPostProcessing
*
* INPUTS : UINT32 *DCQuantScaleV2p :
* UINT32 *DCQuantScaleUVp :
* UINT32 *DCQuantScaleV1p :
* UINT32 Version : Codec version number.
*
* OUTPUTS : None.
*
* RETURNS : void
*
* FUNCTION : Initialise pointers to version specific data tables &
* set-up LUTs.
*
* SPECIAL NOTES : None
*
****************************************************************************/
void InitPostProcessing
(
UINT32 *DCQuantScaleV2p,
UINT32 *DCQuantScaleUVp,
UINT32 *DCQuantScaleV1p,
UINT32 Version
)
{
int i;
for ( i=0; i<VAL_RANGE*3; i++ )
{
int x = i - VAL_RANGE;
LimitVal_VP31[i] = Clamp255 ( x );
}
DCQuantScaleV2 = DCQuantScaleV2p;
DCQuantScaleUV = DCQuantScaleUVp;
DCQuantScaleV1 = DCQuantScaleV1p;
for ( i=0 ; i<Q_TABLE_SIZE; i++ )
DeringModifierV1[i] = DCQuantScaleV1[i];
if ( Version >= 6 )
{
LoopFilterLimitValuesV2 = LoopFilterLimitValuesVp6;
DeblockLimitValuesV2 = DeblockLimitValuesVp6;
}
else if ( Version >= 5 )
{
LoopFilterLimitValuesV2 = LoopFilterLimitValuesVp5;
DeblockLimitValuesV2 = DeblockLimitValuesVp5;
}
else
{
LoopFilterLimitValuesV2 = LoopFilterLimitValuesVp4;
DeblockLimitValuesV2 = DeblockLimitValuesVp4;
}
PostProcMachineSpecificConfig ( Version );
}
/****************************************************************************
*
* ROUTINE : DeInitPostProcessing
*
* INPUTS : None.
*
* OUTPUTS : None.
*
* RETURNS : void
*
* FUNCTION : De-initializes post-processing module.
*
* SPECIAL NOTES : Currently this function does nothing.
*
****************************************************************************/
void DeInitPostProcessing ( void )
{
return;
}
/****************************************************************************
*
* ROUTINE : DeletePostProcBuffers
*
* INPUTS : POSTPROC_INSTANCE *ppi : Pointer to post-processor instance.
*
* OUTPUTS : None.
*
* RETURNS : void
*
* FUNCTION : De-allocates buffers used by the post-processing module.
*
* SPECIAL NOTES : None.
*
****************************************************************************/
void DeletePostProcBuffers ( POSTPROC_INSTANCE *ppi )
{
if ( ppi->IntermediateBufferAlloc )
duck_free ( ppi->IntermediateBufferAlloc );
ppi->IntermediateBufferAlloc = 0;
ppi->IntermediateBuffer = 0;
if ( ppi->IntermediateBufferAlloc )
duck_free ( ppi->IntermediateBufferAlloc );
ppi->IntermediateBufferAlloc = 0;
ppi->IntermediateBuffer = 0;
if ( ppi->FiltBoundingValueAlloc )
duck_free ( ppi->FiltBoundingValueAlloc );
ppi->FiltBoundingValueAlloc = 0;
ppi->FiltBoundingValue = 0;
if ( ppi->DeblockBoundingValueAlloc )
duck_free ( ppi->DeblockBoundingValueAlloc );
ppi->DeblockBoundingValueAlloc = 0;
ppi->DeblockBoundingValue = 0;
if ( ppi->FragQIndexAlloc )
duck_free ( ppi->FragQIndexAlloc );
ppi->FragQIndexAlloc = 0;
ppi->FragQIndex = 0;
if ( ppi->FragmentVariancesAlloc )
duck_free ( ppi->FragmentVariancesAlloc );
ppi->FragmentVariancesAlloc = 0;
ppi->FragmentVariances = 0;
if ( ppi->FragDeblockingFlagAlloc )
duck_free ( ppi->FragDeblockingFlagAlloc );
ppi->FragDeblockingFlagAlloc = 0;
ppi->FragDeblockingFlag = 0;
}
/****************************************************************************
*
* ROUTINE : AllocatePostProcBuffers
*
* INPUTS : POSTPROC_INSTANCE *ppi : Pointer to post-processor instance.
*
* OUTPUTS : None.
*
* RETURNS : INT32: TRUE: Success, FALSE Failure (Chenge to BOOL!!)
*
* FUNCTION : Allocates buffers used by the post-processing module.
*
* SPECIAL NOTES : Uses ROUNDUP32 to align allocated buffers to improve
* cache performance.
*
****************************************************************************/
INT32 AllocatePostProcBuffers ( POSTPROC_INSTANCE *ppi )
{
DeletePostProcBuffers ( ppi );
ppi->IntermediateBufferAlloc = (UINT8*)duck_malloc ( 32 + ppi->YStride *
(ppi->Configuration.VideoFrameHeight + ppi->MVBorder*2) * 3/2 * sizeof(UINT8), DMEM_GENERAL);
if ( !ppi->IntermediateBufferAlloc ) { DeletePostProcBuffers ( ppi ); return FALSE; };
ppi->IntermediateBuffer = (UINT8 *)ROUNDUP32 ( ppi->IntermediateBufferAlloc );
ppi->FiltBoundingValueAlloc = (INT32 *)duck_malloc(32+512*sizeof(INT32), DMEM_GENERAL);
if ( !ppi->FiltBoundingValueAlloc ) { DeletePostProcBuffers ( ppi ); return FALSE; };
ppi->FiltBoundingValue = (INT32 *)ROUNDUP32 ( ppi->FiltBoundingValueAlloc );
ppi->DeblockBoundingValueAlloc = (INT32 *)duck_malloc(32+512*sizeof(INT32), DMEM_GENERAL);
if ( !ppi->DeblockBoundingValueAlloc ) { DeletePostProcBuffers ( ppi ); return FALSE; };
ppi->DeblockBoundingValue = (INT32 *)ROUNDUP32 ( ppi->DeblockBoundingValueAlloc );
ppi->FragQIndexAlloc = (INT32 *)duck_malloc(32+ppi->UnitFragments*sizeof(INT32), DMEM_GENERAL);
if ( !ppi->FragQIndexAlloc ) { DeletePostProcBuffers ( ppi ); return FALSE; };
ppi->FragQIndex = (INT32 *)ROUNDUP32 ( ppi->FragQIndexAlloc );
ppi->FragmentVariancesAlloc = (INT32 *)duck_malloc(32+ppi->UnitFragments*sizeof(INT32), DMEM_GENERAL);
if ( !ppi->FragmentVariancesAlloc ) { DeletePostProcBuffers ( ppi ); return FALSE; };
ppi->FragmentVariances = (INT32 *)ROUNDUP32 ( ppi->FragmentVariancesAlloc );
ppi->FragDeblockingFlagAlloc = (UINT8 *)duck_malloc(32+ppi->UnitFragments*sizeof(UINT8), DMEM_GENERAL);
if ( !ppi->FragDeblockingFlagAlloc ){ DeletePostProcBuffers ( ppi ); return FALSE; };
ppi->FragDeblockingFlag = (UINT8 *)ROUNDUP32 ( ppi->FragDeblockingFlagAlloc );
return TRUE;
}
/****************************************************************************
*
* ROUTINE : ChangePostProcConfiguration
*
* INPUTS : POSTPROC_INSTANCE *ppi : Pointer to post-processor instance.
* CONFIG_TYPE *ConfigurationInit : Pointer to
*
* OUTPUTS : None.
*
* RETURNS : void
*
* FUNCTION : Initialize post-processor to with the setting passed in.
*
* SPECIAL NOTES : None.
*
****************************************************************************/
void ChangePostProcConfiguration ( POSTPROC_INSTANCE *ppi, CONFIG_TYPE *ConfigurationInit )
{
memcpy ((void *)&ppi->Configuration, (void *)ConfigurationInit, sizeof(CONFIG_TYPE) );
ppi->HFragments = (ppi->Configuration.VideoFrameWidth >> 3);
ppi->VFragments = (ppi->Configuration.VideoFrameHeight>> 3);
ppi->YStride = ppi->Configuration.YStride;
ppi->UVStride = ppi->Configuration.UVStride;
ppi->YPlaneFragments = ppi->HFragments * ppi->VFragments;
ppi->UVPlaneFragments = ppi->YPlaneFragments / 4;
ppi->UnitFragments = ppi->YPlaneFragments + 2 * ppi->UVPlaneFragments;
ppi->MVBorder = (ppi->YStride - 8*ppi->HFragments)/2;
ppi->ReconYDataOffset = ppi->MVBorder * ppi->YStride + ppi->MVBorder;
ppi->ReconYDataOffset = ppi->MVBorder * ppi->YStride + ppi->MVBorder;
ppi->ReconUDataOffset =
(ppi->YStride * (ppi->Configuration.VideoFrameHeight + ppi->MVBorder*2))
+ ppi->MVBorder / 2 * ppi->UVStride + ppi->MVBorder/2;
ppi->ReconVDataOffset =
(ppi->YStride * (ppi->Configuration.VideoFrameHeight + ppi->MVBorder*2))
+ (ppi->UVStride * (ppi->Configuration.VideoFrameHeight/2 + ppi->MVBorder))
+ ppi->MVBorder/2 * ppi->UVStride +ppi->MVBorder/2;
AllocatePostProcBuffers ( ppi );
}
/****************************************************************************
*
* ROUTINE : CreatePostProcInstance
*
* INPUTS : CONFIG_TYPE *ConfigurationInit : Pointer to configuration.
*
* OUTPUTS : None.
*
* RETURNS : POSTPROC_INSTANCE *: Pointer to allocated & configured
* post-processor instance.
*
* FUNCTION : Allocates space for and initializes a post-processor
* instance.
*
* SPECIAL NOTES : None.
*
****************************************************************************/
POSTPROC_INSTANCE *CreatePostProcInstance ( CONFIG_TYPE *ConfigurationInit )
{
POSTPROC_INSTANCE *ppi;
int postproc_size = sizeof ( POSTPROC_INSTANCE );
ppi = (POSTPROC_INSTANCE *) duck_malloc ( postproc_size, DMEM_GENERAL );
if ( !ppi )
return 0;
// initialize whole structure to 0
memset ( (unsigned char *)ppi, 0, postproc_size );
ChangePostProcConfiguration ( ppi, ConfigurationInit );
ppi->AddNoiseMode = 1;
return ppi;
}
/****************************************************************************
*
* ROUTINE : DeletePostProcInstance
*
* INPUTS : POSTPROC_INSTANCE **ppi : Pointer-to-pointer to post-processor instance.
*
* OUTPUTS : POSTPROC_INSTANCE **ppi : Pointer-to-pointer to post-processor instance.
*
* RETURNS : void.
*
* FUNCTION : Deletes post-processor instance & de-allocates memory.
*
* SPECIAL NOTES : Pointer to post-processor instance is set to NULL
* on exit.
*
****************************************************************************/
void DeletePostProcInstance ( POSTPROC_INSTANCE **ppi )
{
if ( *ppi )
{
// Delete any other dynamically allocaed temporary buffers
DeletePostProcBuffers ( *ppi );
duck_free ( *ppi );
*ppi = 0;
}
}
/****************************************************************************
*
* ROUTINE : SetPPInterlacedMode
*
* INPUTS : POSTPROC_INSTANCE *ppi : Pointer to post-processor instance.
* int Interlaced : 0=Non-interlaced, 1=Interlaced.
*
* OUTPUTS : None.
*
* RETURNS : void.
*
* FUNCTION : Set post-processor's Interlaced Mode to specified value.
*
* SPECIAL NOTES : None.
*
****************************************************************************/
void SetPPInterlacedMode ( POSTPROC_INSTANCE *ppi, int Interlaced )
{
ppi->Configuration.Interlaced = Interlaced;
}
/****************************************************************************
*
* ROUTINE : SetDeInterlaceMode
*
* INPUTS : POSTPROC_INSTANCE *ppi : Pointer to post-processor instance.
* int DeInterlaceMode : Mode to use for de-interlacing.
*
* OUTPUTS : None.
*
* RETURNS : void.
*
* FUNCTION : Set post-processor's De-Interlace Mode to specified value.
*
* SPECIAL NOTES : None.
*
****************************************************************************/
void SetDeInterlaceMode ( POSTPROC_INSTANCE *ppi, int DeInterlaceMode )
{
ppi->DeInterlaceMode = DeInterlaceMode;
}
/****************************************************************************
*
* ROUTINE : SetDeInterlaceMode
*
* INPUTS : POSTPROC_INSTANCE *ppi : Pointer to post-processor instance.
* int DeInterlaceMode : Mode to use for de-interlacing.
*
* OUTPUTS : None.
*
* RETURNS : void.
*
* FUNCTION : Set post-processor's De-Interlace Mode to specified value.
*
* SPECIAL NOTES : None.
*
****************************************************************************/
void SetAddNoiseMode(POSTPROC_INSTANCE *ppi, int AddNoiseMode)
{
ppi->AddNoiseMode = AddNoiseMode;
}
/****************************************************************************
*
* ROUTINE : UpdateFragQIndex
*
* INPUTS : POSTPROC_INSTANCE *ppi : Pointer to post-processor instance.
*
* OUTPUTS : None.
*
* RETURNS : void.
*
* FUNCTION : Update the QIndex for each updated block.
*
* SPECIAL NOTES : None.
*
****************************************************************************/
void UpdateFragQIndex ( POSTPROC_INSTANCE *ppi )
{
UINT32 i;
UINT32 ThisFrameQIndex;
// Mark coded blocks with Q-index
ThisFrameQIndex = ppi->FrameQIndex;
for ( i=0; i<ppi->UnitFragments; i++ )
if ( blockCoded ( i ) )
ppi->FragQIndex[i] = ThisFrameQIndex;
}
/****************************************************************************
*
* ROUTINE : Gaussian
*
* INPUTS : sigma ( standard deviation), mu ( mean) and x (value)
*
* OUTPUTS : None.
*
* RETURNS : void.
*
* FUNCTION : generate height of gaussian distribution curve with
* deviation sigma and mean mu at position x
*
* SPECIAL NOTES : None.
*
****************************************************************************/
double gaussian(double sigma, double mu, double x)
{
return 1 / ( sigma * sqrt(2.0*3.14159265)) *
(exp(-(x-mu)*(x-mu)/(2*sigma*sigma)));
}
/****************************************************************************
*
* ROUTINE : PlaneAddNoise_C
*
* INPUTS : UINT8 *Start starting address of buffer to add gaussian
* noise to
* UINT32 Width width of plane
* UINT32 Height height of plane
* INT32 Pitch distance between subsequent lines of frame
* INT32 q quantizer used to determine amount of noise
* to add
*
* OUTPUTS : None.
*
* RETURNS : void.
*
* FUNCTION : adds gaussian noise to a plane of pixels
*
* SPECIAL NOTES : None.
*
****************************************************************************/
void PlaneAddNoise_C( UINT8 *Start, UINT32 Width, UINT32 Height, INT32 Pitch, int q)
{
unsigned int i,j;
INT32 Pitch4 = Pitch * 4;
const int noiseAmount = 2;
const int noiseAdder = 2 * noiseAmount + 1;
unsigned char blackclamp[16];
unsigned char whiteclamp[16];
unsigned char bothclamp[16];
char CharDist[300];
char Rand[2048];
double sigma;
sigma = 1 + .8*(63-q) / 63.0;
// set up a lookup table of 256 entries that matches
// a gaussian distribution with sigma determined by q.
//
{
double i,sum=0;
int next,j;
next=0;
for(i=-32;i<32;i++)
{
int a = (int) (.5+256*gaussian(sigma,0,i));
if(a)
{
for(j=0;j<a;j++)
{
CharDist[next+j]=(char) i;
}
next = next+j;
}
}
for(next=next;next<256;next++)
CharDist[next] = 0;
}
// generate a line of 2048 characters following our gaussian distribution
for(i=0;i<2048;i++)
{
Rand[i]=CharDist[rand() & 0xff];
}
for(i=0;i<16;i++)
{
blackclamp[i]=-CharDist[0];
whiteclamp[i]=-CharDist[0];
bothclamp[i]=-2*CharDist[0];
}
for(i=0;i<Height;i++)
{
UINT8* Pos = Start + i *Pitch;
INT8* Ref = (INT8 *) (Rand + (rand() & 0xff)); /* cast required on strict OSX-CW8 */
for(j=0;j<Width;j++)
{
if(Pos[j] < -CharDist[0])
Pos[j] = -CharDist[0];
if(Pos[j] > 255-CharDist[0])
Pos[j] = 255-CharDist[0];
Pos[j]+=Ref[j];
}
}
}
/****************************************************************************
*
* ROUTINE : PostProcess
*
* INPUTS : POSTPROC_INSTANCE *ppi : Pointer to post-processor instance.
* INT32 Vp3VersionNo : Encoder version used to code frame.
* INT32 FrameType : Encoding method: Keyframe or non-Keyframe.
* INT32 PostProcessingLevel : Level of post-processing to perform.
* INT32 FrameQIndex : Q-index used to code frame.
* UINT8 *LastFrameRecon : Pointer to last frame reconstruction buffer.
* UINT8 *PostProcessBuffer : Pointer to last post-processing buffer.
* UINT8 *FragInfo : Pointer to list of coded blocks.
* UINT32 FragInfoElementSize : Size of each element.
* UINT32 FragInfoCodedMask : Mask to get at whether fragment is coded.
*
* OUTPUTS : None.
*
* RETURNS : void.
*
* FUNCTION : Applies de-blocking and de-ringing filters to the frame.
*
* SPECIAL NOTES : None.
*
****************************************************************************/
void PostProcess
(
POSTPROC_INSTANCE *ppi,
INT32 Vp3VersionNo,
INT32 FrameType,
INT32 PostProcessingLevel,
INT32 FrameQIndex,
UINT8 *LastFrameRecon,
UINT8 *PostProcessBuffer,
UINT8 *FragInfo,
UINT32 FragInfoElementSize,
UINT32 FragInfoCodedMask
)
{
int ReconUVPlaneSize;
// variables passed in per frame
ppi->Vp3VersionNo = Vp3VersionNo;
ppi->FrameType = FrameType;
ppi->PostProcessingLevel = PostProcessingLevel;
ppi->FrameQIndex = FrameQIndex;
ppi->LastFrameRecon = LastFrameRecon;
ppi->PostProcessBuffer = PostProcessBuffer;
ppi->FragInfo = FragInfo;
ppi->FragInfoElementSize = FragInfoElementSize;
ppi->FragInfoCodedMask = FragInfoCodedMask;
switch ( ppi->PostProcessingLevel )
{
case 8:
// On a slow machine, use a simpler and faster deblocking filter
UpdateFragQIndex ( ppi );
if(ppi->Vp3VersionNo < 2)
{
DeblockFrame ( ppi, ppi->LastFrameRecon, ppi->PostProcessBuffer );
}
else
{
if ( ppi->Configuration.Interlaced && ppi->DeInterlaceMode )
{
SimpleDeblockFrame ( ppi, ppi->LastFrameRecon, ppi->IntermediateBuffer );
ReconUVPlaneSize = ppi->VFragments*2*ppi->YStride;
memcpy ( ppi->PostProcessBuffer+ppi->ReconUDataOffset, ppi->IntermediateBuffer+ppi->ReconUDataOffset, ReconUVPlaneSize );
memcpy ( ppi->PostProcessBuffer+ppi->ReconVDataOffset, ppi->IntermediateBuffer+ppi->ReconVDataOffset, ReconUVPlaneSize );
FastDeInterlace ( ppi->IntermediateBuffer+ppi->ReconYDataOffset,
ppi->PostProcessBuffer+ppi->ReconYDataOffset,
ppi->HFragments*8, ppi->VFragments*8, ppi->YStride );
}
else
SimpleDeblockFrame ( ppi, ppi->LastFrameRecon, ppi->PostProcessBuffer );
}
break;
case 6:
case 5:
if ( ppi->Vp3VersionNo < 5 )
{
UpdateFragQIndex ( ppi );
}
else
{
if ( ppi->Configuration.Interlaced )
{
if ( !ppi->DeInterlaceMode )
{
DeblockFrameInterlaced ( ppi, ppi->LastFrameRecon, ppi->PostProcessBuffer );
UpdateUMVBorder ( ppi, ppi->PostProcessBuffer );
DeringFrameInterlaced ( ppi, ppi->PostProcessBuffer, ppi->PostProcessBuffer );
}
else
{
DeblockFrameInterlaced ( ppi, ppi->LastFrameRecon, ppi->IntermediateBuffer );
UpdateUMVBorder ( ppi, ppi->IntermediateBuffer );
DeringFrameInterlaced ( ppi, ppi->IntermediateBuffer, ppi->IntermediateBuffer );
ReconUVPlaneSize = ppi->VFragments*2*ppi->YStride;
memcpy ( ppi->PostProcessBuffer+ppi->ReconUDataOffset, ppi->IntermediateBuffer+ppi->ReconUDataOffset, ReconUVPlaneSize );
memcpy ( ppi->PostProcessBuffer+ppi->ReconVDataOffset, ppi->IntermediateBuffer+ppi->ReconVDataOffset, ReconUVPlaneSize );
FastDeInterlace ( ppi->IntermediateBuffer+ppi->ReconYDataOffset,
ppi->PostProcessBuffer+ppi->ReconYDataOffset,
ppi->HFragments*8, ppi->VFragments*8, ppi->YStride);
}
break;
}
}
DeblockFrame ( ppi, ppi->LastFrameRecon, ppi->PostProcessBuffer );
UpdateUMVBorder ( ppi, ppi->PostProcessBuffer );
DeringFrame ( ppi, ppi->PostProcessBuffer, ppi->PostProcessBuffer );
if(ppi->AddNoiseMode&&PlaneAddNoise!=0)
PlaneAddNoise(ppi->PostProcessBuffer + ppi->ReconYDataOffset,ppi->HFragments*8, ppi->VFragments*8,ppi->YStride,FrameQIndex);
break;
case 7:
if ( ppi->Vp3VersionNo >= 5 )
{
if ( ppi->Configuration.Interlaced )
{
if ( !ppi->DeInterlaceMode )
DeblockFrameInterlaced ( ppi, ppi->LastFrameRecon, ppi->PostProcessBuffer );
else
{
DeblockFrameInterlaced ( ppi, ppi->LastFrameRecon, ppi->IntermediateBuffer );
ReconUVPlaneSize = ppi->VFragments*2*ppi->YStride;
memcpy ( ppi->PostProcessBuffer+ppi->ReconUDataOffset, ppi->IntermediateBuffer+ppi->ReconUDataOffset, ReconUVPlaneSize );
memcpy ( ppi->PostProcessBuffer+ppi->ReconVDataOffset, ppi->IntermediateBuffer+ppi->ReconVDataOffset, ReconUVPlaneSize );
FastDeInterlace ( ppi->IntermediateBuffer+ppi->ReconYDataOffset,
ppi->PostProcessBuffer+ppi->ReconYDataOffset,
ppi->HFragments*8, ppi->VFragments*8, ppi->YStride );
}
break;
}
}
else
{
UpdateFragQIndex ( ppi );
}
DeblockFrame ( ppi, ppi->LastFrameRecon, ppi->PostProcessBuffer );
UpdateUMVBorder ( ppi, ppi->PostProcessBuffer );
DeringFrame ( ppi, ppi->PostProcessBuffer, ppi->PostProcessBuffer );
break;
case 4:
if ( ppi->Vp3VersionNo >= 5 )
{
if ( ppi->Configuration.Interlaced )
{
if ( !ppi->DeInterlaceMode )
DeblockFrameInterlaced ( ppi, ppi->LastFrameRecon, ppi->PostProcessBuffer );
else
{
DeblockFrameInterlaced ( ppi, ppi->LastFrameRecon, ppi->IntermediateBuffer );
ReconUVPlaneSize = ppi->VFragments*2*ppi->YStride;
memcpy ( ppi->PostProcessBuffer+ppi->ReconUDataOffset, ppi->IntermediateBuffer+ppi->ReconUDataOffset, ReconUVPlaneSize );
memcpy ( ppi->PostProcessBuffer+ppi->ReconVDataOffset, ppi->IntermediateBuffer+ppi->ReconVDataOffset, ReconUVPlaneSize );
FastDeInterlace ( ppi->IntermediateBuffer+ppi->ReconYDataOffset,
ppi->PostProcessBuffer+ppi->ReconYDataOffset,
ppi->HFragments*8, ppi->VFragments*8, ppi->YStride );
}
break;
}
}
else
{
UpdateFragQIndex ( ppi );
}
DeblockFrame ( ppi, ppi->LastFrameRecon, ppi->PostProcessBuffer );
//PlaneAddNoise(ppi->PostProcessBuffer + ppi->ReconYDataOffset,ppi->HFragments*8, ppi->VFragments*8,ppi->YStride,FrameQIndex);
break;
case 1:
UpdateFragQIndex ( ppi );
break;
case 0:
if ( ppi->Configuration.Interlaced && ppi->DeInterlaceMode )
{
ReconUVPlaneSize = ppi->VFragments*2*ppi->YStride;
memcpy ( ppi->PostProcessBuffer+ppi->ReconUDataOffset, ppi->LastFrameRecon+ppi->ReconUDataOffset, ReconUVPlaneSize );
memcpy ( ppi->PostProcessBuffer+ppi->ReconVDataOffset, ppi->LastFrameRecon+ppi->ReconVDataOffset, ReconUVPlaneSize );
FastDeInterlace ( ppi->LastFrameRecon+ppi->ReconYDataOffset,
ppi->PostProcessBuffer+ppi->ReconYDataOffset,
ppi->HFragments*8, ppi->VFragments*8, ppi->YStride );
}
break;
default:
DeblockFrame ( ppi, ppi->LastFrameRecon, ppi->PostProcessBuffer );
UpdateUMVBorder ( ppi, ppi->PostProcessBuffer );
DeringFrame ( ppi, ppi->PostProcessBuffer, ppi->PostProcessBuffer );
break;
}
}
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,392 @@
/****************************************************************************
*
* Module Title : simpledeblock.c
*
* Description : Simple deblocking filter.
*
***************************************************************************/
#define STRICT /* Strict type checking */
/****************************************************************************
* Header Files
****************************************************************************/
#include "postp.h"
/****************************************************************************
* Macros
****************************************************************************/
#if ( defined(_MSC_VER) || defined(MAPCA) )
#define abs(x) ( (x>0) ? (x) : (-(x)) )
#endif
/****************************************************************************
* Imports
****************************************************************************/
extern UINT32 *DeblockLimitValuesV2;
/****************************************************************************
* Module Statics
****************************************************************************/
static const UINT32 DeblockLimitValuesV1[Q_TABLE_SIZE] =
{
30, 25, 20, 20, 15, 15, 14, 14,
13, 13, 12, 12, 11, 11, 10, 10,
9, 9, 8, 8, 7, 7, 7, 7,
6, 6, 6, 6, 5, 5, 5, 5,
4, 4, 4, 4, 3, 3, 3, 3,
2, 2, 2, 2, 2, 2, 2, 2,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0
};
/****************************************************************************
*
* ROUTINE : FilterHoriz_Simple2_C
*
* INPUTS : POSTPROC_INSTANCE *ppi : Pointer to post-processing instance (NOT USED).
* UINT8 *PixelPtr : Pointer to four pixels that straddle the edge.
* INT32 LineLength : Stride of the image being filtered.
* INT32 *BoundingValuePtr : Pointer to array of bounding values.
*
* OUTPUTS : None.
*
* RETURNS : void
*
* FUNCTION : Applies a loop filter to the vertical edge by applying
* the filter horizontally to each of the 8-rows of the
* block edge.
*
* SPECIAL NOTES : None.
*
****************************************************************************/
void FilterHoriz_Simple2_C
(
POSTPROC_INSTANCE *ppi,
UINT8 *PixelPtr,
INT32 LineLength,
INT32 *BoundingValuePtr
)
{
INT32 j;
INT32 x,y,z;
INT32 FiltVal;
UINT8 *LimitTable = &LimitVal_VP31[VAL_RANGE];
(void) ppi;
for ( j=0; j<8; j++ )
{
y = PixelPtr[2]-PixelPtr[1];
if ( !y ) continue;
x = PixelPtr[1]-PixelPtr[0];
z = PixelPtr[3]-PixelPtr[2];
FiltVal = 2 * y + z - x;
FiltVal = BoundingValuePtr[(FiltVal + 4) >> 3];
PixelPtr[1] = LimitTable[(INT32)PixelPtr[1] + FiltVal];
PixelPtr[2] = LimitTable[(INT32)PixelPtr[2] - FiltVal];
FiltVal >>= 1;
FiltVal *= ((x|z)==0);
PixelPtr[0] = LimitTable[(INT32)PixelPtr[0] + FiltVal];
PixelPtr[3] = LimitTable[(INT32)PixelPtr[3] - FiltVal];
PixelPtr += LineLength;
}
}
/****************************************************************************
*
* ROUTINE : FilterVert_Simple2_C
*
* INPUTS : POSTPROC_INSTANCE *ppi : Pointer to post-processing instance (NOT USED).
* UINT8 *PixelPtr : Pointer to four pixels that straddle the edge.
* INT32 LineLength : Stride of the image being filtered.
* INT32 *BoundingValuePtr : Pointer to array of bounding values.
*
* OUTPUTS : None.
*
* RETURNS : void
*
* FUNCTION : Applies a loop filter to the horizontal edge by applying
* the filter vertically to each of the 8-columns of the
* block edge.
*
* SPECIAL NOTES : None.
*
****************************************************************************/
void FilterVert_Simple2_C
(
POSTPROC_INSTANCE *ppi,
UINT8 *PixelPtr,
INT32 LineLength,
INT32 *BoundingValuePtr
)
{
INT32 j;
INT32 FiltVal;
UINT8 *LimitTable = &LimitVal_VP31[VAL_RANGE];
(void) ppi;
for ( j=0; j<8; j++ )
{
INT32 UseHighVariance;
FiltVal = ( ((INT32)PixelPtr[0]*3) - ((INT32)PixelPtr[-LineLength]*3) );
UseHighVariance = abs ( PixelPtr[-(2*LineLength)] - PixelPtr[-LineLength] ) > 1 ||
abs ( PixelPtr[0] - PixelPtr[LineLength]) > 1;
if ( UseHighVariance )
FiltVal += ((INT32)PixelPtr[-(2*LineLength)]) - ((INT32)PixelPtr[LineLength]);
FiltVal = BoundingValuePtr[(FiltVal + 4) >> 3];
PixelPtr[-LineLength] = LimitTable[(INT32)PixelPtr[-LineLength] + FiltVal];
PixelPtr[ 0] = LimitTable[(INT32)PixelPtr[ 0] - FiltVal];
if ( !UseHighVariance )
{
FiltVal >>=1;
PixelPtr[-2*LineLength] = LimitTable[(INT32)PixelPtr[-2*LineLength] + FiltVal];
PixelPtr[ LineLength] = LimitTable[(INT32)PixelPtr[ LineLength] - FiltVal];
}
PixelPtr++;
}
}
/****************************************************************************
*
* ROUTINE : FilterHoriz_Simple_C
*
* INPUTS : POSTPROC_INSTANCE *ppi : Pointer to post-processing instance (NOT USED).
* UINT8 *PixelPtr : Pointer to four pixels that straddle the edge.
* INT32 LineLength : Stride of the image being filtered.
* INT32 *BoundingValuePtr : Pointer to array of bounding values.
*
* OUTPUTS : None.
*
* RETURNS : void
*
* FUNCTION : Applies a loop filter to the vertical edge by applying
* the filter horizontally to each of the 8-rows of the
* block edge.
*
* SPECIAL NOTES : None.
*
****************************************************************************/
void FilterHoriz_Simple_C
(
POSTPROC_INSTANCE *ppi,
UINT8 *PixelPtr,
INT32 LineLength,
INT32 *BoundingValuePtr
)
{
INT32 j;
INT32 FiltVal;
UINT8 *LimitTable = &LimitVal_VP31[VAL_RANGE];
(void) ppi;
for ( j=0; j<8; j++ )
{
INT32 UseHighVariance;
FiltVal = (PixelPtr[2]*3) - (PixelPtr[1]*3);
UseHighVariance = abs(PixelPtr[0] - PixelPtr[1]) > 1 ||
abs(PixelPtr[2] - PixelPtr[3]) > 1;
if ( UseHighVariance )
FiltVal += PixelPtr[0] - PixelPtr[3];
FiltVal = BoundingValuePtr[(FiltVal + 4) >> 3];
PixelPtr[1] = LimitTable[(INT32)PixelPtr[1] + FiltVal];
PixelPtr[2] = LimitTable[(INT32)PixelPtr[2] - FiltVal];
if ( !UseHighVariance )
{
FiltVal >>= 1;
PixelPtr[0] = LimitTable[(INT32)PixelPtr[0] + FiltVal];
PixelPtr[3] = LimitTable[(INT32)PixelPtr[3] - FiltVal];
}
PixelPtr += LineLength;
}
}
/****************************************************************************
*
* ROUTINE : FilterVert_Simple_C
*
* INPUTS : POSTPROC_INSTANCE *ppi : Pointer to post-processing instance (NOT USED).
* UINT8 *PixelPtr : Pointer to four pixels that straddle the edge.
* INT32 LineLength : Stride of the image being filtered.
* INT32 *BoundingValuePtr : Pointer to array of bounding values.
*
* OUTPUTS : None.
*
* RETURNS : void
*
* FUNCTION : Applies a loop filter to the horizontal edge by applying
* the filter vertically to each of the 8-columns of the
* block edge.
*
* SPECIAL NOTES : None.
*
****************************************************************************/
void FilterVert_Simple_C
(
POSTPROC_INSTANCE *ppi,
UINT8 *PixelPtr,
INT32 LineLength,
INT32 *BoundingValuePtr
)
{
INT32 j;
INT32 FiltVal;
UINT8 *LimitTable = &LimitVal_VP31[VAL_RANGE];
(void) ppi;
for ( j=0; j<8; j++ )
{
INT32 UseHighVariance;
FiltVal = ( ((INT32)PixelPtr[0]*3) - ((INT32)PixelPtr[-LineLength]*3) );
UseHighVariance = abs(PixelPtr[-(2*LineLength)] - PixelPtr[-LineLength]) > 1 ||
abs(PixelPtr[0] - PixelPtr[LineLength]) > 1;
if ( UseHighVariance )
FiltVal += ((INT32)PixelPtr[-(2*LineLength)]) - ((INT32)PixelPtr[LineLength]);
FiltVal = BoundingValuePtr[(FiltVal + 4) >> 3];
PixelPtr[-LineLength] = LimitTable[(INT32)PixelPtr[-LineLength] + FiltVal];
PixelPtr[ 0] = LimitTable[(INT32)PixelPtr[ 0] - FiltVal];
if ( !UseHighVariance )
{
FiltVal >>=1;
PixelPtr[-2*LineLength] = LimitTable[(INT32)PixelPtr[-2*LineLength] + FiltVal];
PixelPtr[ LineLength] = LimitTable[(INT32)PixelPtr[ LineLength] - FiltVal];
}
PixelPtr++;
}
}
/****************************************************************************
*
* ROUTINE : SimpleDeblockFrame
*
* INPUTS : POSTPROC_INSTANCE *ppi : Pointer to post-processing instance.
* UINT8 *SrcBuffer : Pointer to image to be deblocked.
* UINT8 *DestBuffer : Pointer to image to hold deblocked image.
*
* OUTPUTS : None.
*
* RETURNS : void
*
* FUNCTION : Simple deblocker.
*
* SPECIAL NOTES : None.
*
****************************************************************************/
void SimpleDeblockFrame ( POSTPROC_INSTANCE *ppi, UINT8 *SrcBuffer, UINT8 *DestBuffer )
{
INT32 j, m, n;
INT32 RowStart;
INT32 NextRow;
INT32 FLimit;
INT32 QIndex;
INT32 *BoundingValuePtr;
INT32 LineLength = 0;
INT32 FragsAcross = ppi->HFragments;
INT32 FragsDown = ppi->VFragments;
QIndex = ppi->FrameQIndex;
// Encoder version specific clause
if ( ppi->Vp3VersionNo >= 2 )
FLimit = DeblockLimitValuesV2[QIndex];
else
FLimit = DeblockLimitValuesV1[QIndex];
BoundingValuePtr = SetupDeblockValueArray ( ppi, FLimit );
for ( j=0; j<3; j++ )
{
switch ( j )
{
case 0: // Y
FragsAcross = ppi->HFragments;
FragsDown = ppi->VFragments;
LineLength = ppi->YStride;
RowStart = ppi->ReconYDataOffset;
break;
case 1: // U
FragsAcross = ppi->HFragments >> 1;
FragsDown = ppi->VFragments >> 1;
LineLength = ppi->UVStride;
RowStart = ppi->ReconUDataOffset;
break;
case 2: // V
FragsAcross = ppi->HFragments >> 1;
FragsDown = ppi->VFragments >> 1;
LineLength = ppi->UVStride;
RowStart = ppi->ReconVDataOffset;
break;
}
NextRow = LineLength * 8;
/*************/
/* First Row */
/*************/
memcpy ( &DestBuffer[RowStart], &SrcBuffer[RowStart], 8*LineLength );
/* First Column -- Skip */
/* Remaining Columns */
for ( n=1; n<FragsAcross; n++ ) // Filter Left edge always
FilterHoriz_Simple ( ppi, &DestBuffer[RowStart+n*8-2], LineLength, BoundingValuePtr );
RowStart += NextRow;
//**************/
// Middle Rows */
//**************/
for ( m=1; m<FragsDown; m++ )
{
n = 0;
memcpy ( &DestBuffer[RowStart], &SrcBuffer[RowStart], 8*LineLength );
/* First column */
FilterVert_Simple ( ppi, &DestBuffer[RowStart+n*8], LineLength, BoundingValuePtr );
/* Middle columns */
for ( n=1; n<FragsAcross; n++ )
{
// Filter Left edge always
FilterHoriz_Simple ( ppi, &DestBuffer[RowStart+n*8-2], LineLength, BoundingValuePtr );
// TopRow is always done
FilterVert_Simple ( ppi, &DestBuffer[RowStart+n*8], LineLength, BoundingValuePtr );
}
RowStart += NextRow;
}
}
}