📄 pp.c
字号:
/********************************************************************
* *
* THIS FILE IS PART OF THE OggTheora SOFTWARE CODEC SOURCE CODE. *
* USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS *
* GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE *
* IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING. *
* *
* THE Theora SOURCE CODE IS COPYRIGHT (C) 2002-2003 *
* by the Xiph.Org Foundation http://www.xiph.org/ *
* *
********************************************************************
function:
********************************************************************/
#include <stdlib.h>
#include <string.h>
#include "codec_internal.h"
#include "pp.h"
#include "dsp.h"
#include <mmintrin.h>
#define MAX(a, b) ((a>b)?a:b)
#define MIN(a, b) ((a<b)?a:b)
#define PP_QUALITY_THRESH 49
const ogg_int32_t SharpenModifier[ Q_TABLE_SIZE ] =
{ -12, -11, -10, -10, -9, -9, -9, -9,
-6, -6, -6, -6, -6, -6, -6, -6,
-4, -4, -4, -4, -4, -4, -4, -4,
-2, -2, -2, -2, -2, -2, -2, -2,
-2, -2, -2, -2, -2, -2, -2, -2,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0
};
static const ogg_uint32_t DcQuantScaleV1[ Q_TABLE_SIZE ] = {
22, 20, 19, 18, 17, 17, 16, 16,
15, 15, 14, 14, 13, 13, 12, 12,
11, 11, 10, 10, 9, 9, 9, 8,
8, 8, 7, 7, 7, 6, 6, 6,
6, 5, 5, 5, 5, 4, 4, 4,
4, 4, 3, 3, 3, 3, 3, 3,
3, 2, 2, 2, 2, 2, 2, 2,
2, 1, 1, 1, 1, 1, 1, 1
};
static const ogg_uint32_t * const DeringModifierV1=DcQuantScaleV1;
static void PClearFrameInfo(PP_INSTANCE * ppi){
int i;
if(ppi->ScanPixelIndexTable) _ogg_free(ppi->ScanPixelIndexTable);
ppi->ScanPixelIndexTable=0;
if(ppi->ScanDisplayFragments) _ogg_free(ppi->ScanDisplayFragments);
ppi->ScanDisplayFragments=0;
for(i = 0 ; i < MAX_PREV_FRAMES ; i ++)
if(ppi->PrevFragments[i]){
_ogg_free(ppi->PrevFragments[i]);
ppi->PrevFragments[i]=0;
}
if(ppi->FragScores) _ogg_free(ppi->FragScores);
ppi->FragScores=0;
if(ppi->SameGreyDirPixels) _ogg_free(ppi->SameGreyDirPixels);
ppi->SameGreyDirPixels=0;
if(ppi->FragDiffPixels) _ogg_free(ppi->FragDiffPixels);
ppi->FragDiffPixels=0;
if(ppi->BarBlockMap) _ogg_free(ppi->BarBlockMap);
ppi->BarBlockMap=0;
if(ppi->TmpCodedMap) _ogg_free(ppi->TmpCodedMap);
ppi->TmpCodedMap=0;
if(ppi->RowChangedPixels) _ogg_free(ppi->RowChangedPixels);
ppi->RowChangedPixels=0;
if(ppi->PixelScores) _ogg_free(ppi->PixelScores);
ppi->PixelScores=0;
if(ppi->PixelChangedMap) _ogg_free(ppi->PixelChangedMap);
ppi->PixelChangedMap=0;
if(ppi->ChLocals) _ogg_free(ppi->ChLocals);
ppi->ChLocals=0;
if(ppi->yuv_differences) _ogg_free(ppi->yuv_differences);
ppi->yuv_differences=0;
}
void PInitFrameInfo(PP_INSTANCE * ppi){
int i;
PClearFrameInfo(ppi);
ppi->ScanPixelIndexTable =
_ogg_malloc(ppi->ScanFrameFragments*sizeof(*ppi->ScanPixelIndexTable));
ppi->ScanDisplayFragments =
_ogg_malloc(ppi->ScanFrameFragments*sizeof(*ppi->ScanDisplayFragments));
for(i = 0 ; i < MAX_PREV_FRAMES ; i ++)
ppi->PrevFragments[i] =
_ogg_malloc(ppi->ScanFrameFragments*sizeof(*ppi->PrevFragments));
ppi->FragScores =
_ogg_malloc(ppi->ScanFrameFragments*sizeof(*ppi->FragScores));
ppi->SameGreyDirPixels =
_ogg_malloc(ppi->ScanFrameFragments*sizeof(*ppi->SameGreyDirPixels));
ppi->FragDiffPixels =
_ogg_malloc(ppi->ScanFrameFragments*sizeof(*ppi->FragScores));
ppi->BarBlockMap=
_ogg_malloc(3 * ppi->ScanHFragments*sizeof(*ppi->BarBlockMap));
ppi->TmpCodedMap =
_ogg_malloc(ppi->ScanHFragments*sizeof(*ppi->TmpCodedMap));
ppi->RowChangedPixels =
_ogg_malloc(3 * ppi->ScanConfig.VideoFrameHeight*
sizeof(*ppi->RowChangedPixels));
ppi->PixelScores =
_ogg_malloc(ppi->ScanConfig.VideoFrameWidth*
sizeof(*ppi->PixelScores) * PSCORE_CB_ROWS);
ppi->PixelChangedMap =
_ogg_malloc(ppi->ScanConfig.VideoFrameWidth*
sizeof(*ppi->PixelChangedMap) * PMAP_CB_ROWS);
ppi->ChLocals =
_ogg_malloc(ppi->ScanConfig.VideoFrameWidth*
sizeof(*ppi->ChLocals) * CHLOCALS_CB_ROWS);
ppi->yuv_differences =
_ogg_malloc(ppi->ScanConfig.VideoFrameWidth*
sizeof(*ppi->yuv_differences) * YDIFF_CB_ROWS);
}
void ClearPPInstance(PP_INSTANCE *ppi){
PClearFrameInfo(ppi);
}
void InitPPInstance(PP_INSTANCE *ppi){
memset(ppi,0,sizeof(*ppi));
/* Initializations */
ppi->PrevFrameLimit = 3; /* Must not exceed MAX_PREV_FRAMES (Note
that this number includes the current
frame so "1 = no effect") */
/* Scan control variables. */
ppi->HFragPixels = 8;
ppi->VFragPixels = 8;
ppi->SRFGreyThresh = 4;
ppi->SRFColThresh = 5;
ppi->NoiseSupLevel = 3;
ppi->SgcLevelThresh = 3;
ppi->SuvcLevelThresh = 4;
/* Variables controlling S.A.D. breakouts. */
ppi->GrpLowSadThresh = 10;
ppi->GrpHighSadThresh = 64;
ppi->PrimaryBlockThreshold = 5;
ppi->SgcThresh = 16; /* (Default values for 8x8 blocks). */
ppi->UVBlockThreshCorrection = 1.25;
ppi->UVSgcCorrection = 1.5;
ppi->MaxLineSearchLen = MAX_SEARCH_LINE_LEN;
}
void DeringBlockStrong(unsigned char *SrcPtr,
unsigned char *DstPtr,
ogg_int32_t Pitch,
ogg_uint32_t FragQIndex,
const ogg_uint32_t *QuantScale){
ogg_int16_t UDMod[72];
ogg_int16_t LRMod[72];
unsigned int j,k,l;
const unsigned char * Src;
unsigned int QValue = QuantScale[FragQIndex];
unsigned char p;
unsigned char pl;
unsigned char pr;
unsigned char pu;
unsigned char pd;
int al;
int ar;
int au;
int ad;
int atot;
int B;
int newVal;
const unsigned char *curRow = SrcPtr - 1; /* avoid negative array indexes */
unsigned char *dstRow = DstPtr;
const unsigned char *lastRow = SrcPtr-Pitch;
const unsigned char *nextRow = SrcPtr+Pitch;
unsigned int rowOffset = 0;
unsigned int round = (1<<6);
int High;
int Low;
int TmpMod;
int Sharpen = SharpenModifier[FragQIndex];
High = 3 * QValue;
if(High>32)High=32;
Low = 0;
/* Initialize the Mod Data */
Src = SrcPtr-Pitch;
for(k=0;k<9;k++){
for(j=0;j<8;j++){
TmpMod = 32 + QValue - (abs(Src[j+Pitch]-Src[j]));
if(TmpMod< -64)
TmpMod = Sharpen;
else if(TmpMod<Low)
TmpMod = Low;
else if(TmpMod>High)
TmpMod = High;
UDMod[k*8+j] = (ogg_int16_t)TmpMod;
}
Src +=Pitch;
}
Src = SrcPtr-1;
for(k=0;k<8;k++){
for(j=0;j<9;j++){
TmpMod = 32 + QValue - (abs(Src[j+1]-Src[j]));
if(TmpMod< -64 )
TmpMod = Sharpen;
else if(TmpMod<0)
TmpMod = Low;
else if(TmpMod>High)
TmpMod = High;
LRMod[k*9+j] = (ogg_int16_t)TmpMod;
}
Src+=Pitch;
}
for(k=0;k<8;k++){
/* In the case that this function called with same buffer for
source and destination, To keep the c and the mmx version to have
consistant results, intermediate buffer is used to store the
eight pixel value before writing them to destination
(i.e. Overwriting souce for the speical case) */
for(l=0;l<8;l++){
atot = 128;
B = round;
p = curRow[ rowOffset +l +1];
pl = curRow[ rowOffset +l];
al = LRMod[k*9+l];
atot -= al;
B += al * pl;
pu = lastRow[ rowOffset +l];
au = UDMod[k*8+l];
atot -= au;
B += au * pu;
pd = nextRow[ rowOffset +l];
ad = UDMod[(k+1)*8+l];
atot -= ad;
B += ad * pd;
pr = curRow[ rowOffset +l+2];
ar = LRMod[k*9+l+1];
atot -= ar;
B += ar * pr;
newVal = ( atot * p + B) >> 7;
dstRow[ rowOffset +l]= clamp255( newVal );
}
rowOffset += Pitch;
}
}
void DeringBlockWeak(unsigned char *SrcPtr,
unsigned char *DstPtr,
ogg_int32_t Pitch,
ogg_uint32_t FragQIndex,
const ogg_uint32_t *QuantScale){
ogg_int16_t UDMod[72];
ogg_int16_t LRMod[72];
unsigned int j,k;
const unsigned char * Src;
unsigned int QValue = QuantScale[FragQIndex];
unsigned char p;
unsigned char pl;
unsigned char pr;
unsigned char pu;
unsigned char pd;
int al;
int ar;
int au;
int ad;
int atot;
int B;
int newVal;
const unsigned char *curRow = SrcPtr-1;
unsigned char *dstRow = DstPtr;
const unsigned char *lastRow = SrcPtr-Pitch;
const unsigned char *nextRow = SrcPtr+Pitch;
unsigned int rowOffset = 0;
unsigned int round = (1<<6);
int High;
int Low;
int TmpMod;
int Sharpen = SharpenModifier[FragQIndex];
High = 3 * QValue;
if(High>24)
High=24;
Low = 0 ;
/* Initialize the Mod Data */
Src=SrcPtr-Pitch;
for(k=0;k<9;k++) {
for(j=0;j<8;j++) {
TmpMod = 32 + QValue - 2*(abs(Src[j+Pitch]-Src[j]));
if(TmpMod< -64)
TmpMod = Sharpen;
else if(TmpMod<Low)
TmpMod = Low;
else if(TmpMod>High)
TmpMod = High;
UDMod[k*8+j] = (ogg_int16_t)TmpMod;
}
Src +=Pitch;
}
Src = SrcPtr-1;
for(k=0;k<8;k++){
for(j=0;j<9;j++){
TmpMod = 32 + QValue - 2*(abs(Src[j+1]-Src[j]));
if(TmpMod< -64 )
TmpMod = Sharpen;
else if(TmpMod<Low)
TmpMod = Low;
else if(TmpMod>High)
TmpMod = High;
LRMod[k*9+j] = (ogg_int16_t)TmpMod;
}
Src+=Pitch;
}
for(k=0;k<8;k++) {
for(j=0;j<8;j++){
atot = 128;
B = round;
p = curRow[ rowOffset +j+1];
pl = curRow[ rowOffset +j];
al = LRMod[k*9+j];
atot -= al;
B += al * pl;
pu = lastRow[ rowOffset +j];
au = UDMod[k*8+j];
atot -= au;
B += au * pu;
pd = nextRow[ rowOffset +j];
ad = UDMod[(k+1)*8+j];
atot -= ad;
B += ad * pd;
pr = curRow[ rowOffset +j+2];
ar = LRMod[k*9+j+1];
atot -= ar;
B += ar * pr;
newVal = ( atot * p + B) >> 7;
dstRow[ rowOffset +j] = clamp255( newVal );
}
rowOffset += Pitch;
}
}
static void DeringFrame(PB_INSTANCE *pbi,
unsigned char *Src, unsigned char *Dst){
ogg_uint32_t col,row;
unsigned char *SrcPtr;
unsigned char *DestPtr;
ogg_uint32_t BlocksAcross,BlocksDown;
const ogg_uint32_t *QuantScale;
ogg_uint32_t Block;
ogg_uint32_t LineLength;
ogg_int32_t Thresh1,Thresh2,Thresh3,Thresh4;
Thresh1 = 384;
Thresh2 = 4 * Thresh1;
Thresh3 = 5 * Thresh2/4;
Thresh4 = 5 * Thresh2/2;
QuantScale = DeringModifierV1;
BlocksAcross = pbi->HFragments;
BlocksDown = pbi->VFragments;
SrcPtr = Src + pbi->ReconYDataOffset;
DestPtr = Dst + pbi->ReconYDataOffset;
LineLength = pbi->YStride;
Block = 0;
for ( row = 0 ; row < BlocksDown; row ++){
for (col = 0; col < BlocksAcross; col ++){
ogg_uint32_t Quality = pbi->FragQIndex[Block];
ogg_int32_t Variance = pbi->FragmentVariances[Block];
if( pbi->PostProcessingLevel >5 && Variance > Thresh3 ){
dsp_funcs.DeringBlockStrong(SrcPtr + 8 * col, DestPtr + 8 * col,
LineLength,Quality,QuantScale);
if( (col > 0 &&
pbi->FragmentVariances[Block-1] > Thresh4 ) ||
(col + 1 < BlocksAcross &&
pbi->FragmentVariances[Block+1] > Thresh4 ) ||
(row + 1 < BlocksDown &&
pbi->FragmentVariances[Block+BlocksAcross] > Thresh4) ||
(row > 0 &&
pbi->FragmentVariances[Block-BlocksAcross] > Thresh4) ){
dsp_funcs.DeringBlockStrong(SrcPtr + 8 * col, DestPtr + 8 * col,
LineLength,Quality,QuantScale);
dsp_funcs.DeringBlockStrong(SrcPtr + 8 * col, DestPtr + 8 * col,
LineLength,Quality,QuantScale);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -