timgfilternoise.cpp
来自「从FFMPEG转换而来的H264解码程序,VC下编译..」· C++ 代码 · 共 797 行 · 第 1/2 页
CPP
797 行
{
noiseMul=_mm::subs_pi16(noiseMul,m128);
noiseMul=_mm::slli_pi16(noiseMul,3);
}
noiseMul=_mm::srai_pi16(_mm::mullo_pi16(noiseMul,noise),8);
}
if (!avih)
_mm::storeU(noiseMask+x,noiseMul=_mm::srai_pi16(_mm::mullo_pi16(noiseMul,noiseStrength64),8));
_mm::store2(dst+x,_mm::packs_pu16(_mm::add_pi16(noiseMul,src8),m0));
}
for (;x<(int)dx;x++)
{
int mm1;
if (!avih)
{
typename _mm::integer2_t val;
_mm::store2(&val,noisenext64=_mm::add_pi16(_mm::madd_pi16(noisenext64,Tnoise<_mm>::noiseConst()),Tnoise<_mm>::noiseConst()));
mm1=(char)val;
}
else
mm1=(char)noiseMask[x];
int mm0,mm7=src[x];
if (uniform)
mm0=mm1;
else
{
mm0=mm7;
if (chroma)
mm0-=128;
mm0=(mm0*mm1)>>8;
}
if (!avih)
noiseMask[x]=(short)(mm0=(mm0*noiseStrength)>>8);
dst[x]=limit_uint8(mm0+mm7);
}
}
if (!avih)
Tnoise<_mm>::noisenext()=noisenext64;
}
template<class _mm,bool chroma,bool avih> void TimgFilterNoise::generateAddNoise(const unsigned char *src,stride_t srcStride,unsigned char *dst,stride_t dstStride,unsigned int dx,unsigned int dy,int noiseStrength,int uniformNoise,short *noiseMask,stride_t noiseMaskStride,int noiseCount)
{
if (_mm::align && (intptr_t(src)&15 || intptr_t(dst)&15 || srcStride&15 || dstStride&15))
{
generateAddNoise<Tmmx,chroma,avih>(src,srcStride,dst,dstStride,dx,dy,noiseStrength,uniformNoise,noiseMask,noiseMaskStride,noiseCount);
return;
}
typename _mm::__m m0=_mm::setzero_si64();
if (!avih && noiseCount&1)
{
for (const unsigned char *srcEnd=src+srcStride*dy;src!=srcEnd;src+=srcStride,dst+=dstStride,noiseMask+=noiseMaskStride)
{
int x=0;
for (;x<int(dx-_mm::size/2+1);x+=_mm::size/2)
_mm::store2(dst+x,_mm::packs_pu16(_mm::add_pi16(_mm::unpacklo_pi8(_mm::load2(src+x),m0),*(typename _mm::__m*)(noiseMask+x)),m0));
for (;x<(int)dx;x++)
dst[x]=limit_uint8(src[x]+noiseMask[x]);
}
return;
}
if (!uniformNoise)
addNoise<_mm,chroma,avih,false>(src,srcStride,dst,dstStride,dx,dy,noiseMask,noiseMaskStride,noiseStrength);
else
addNoise<_mm,chroma,avih,true >(src,srcStride,dst,dstStride,dx,dy,noiseMask,noiseMaskStride,noiseStrength);
}
void TimgFilterNoise::genAVIHnoise(int plane,int strength)
{
short *dst1=noiseMask[plane],*dst2=dst1+noiseMaskStride[plane]*dy1[plane];
for (unsigned int i=0,j=0;i<noiseMaskStride[plane]*dy1[plane];i++,j++)
{
dst1[i]=dst2[i]=short((((rand()&255)-128)*strength)/256+(oldPattern?patt[j%4]*strength/12:0));
if (!(rand()%6)) j--;
}
}
template<class _mm> void TimgFilterNoise::processLuma(const TnoiseSettings *cfg,const unsigned char *srcY,unsigned char *dstY)
{
switch (cfg->method)
{
case TnoiseSettings::NOISE_FF:
{
noiseCount[0]++;
if (noiseAvihStrength) noiseCount[0]=0;
generateAddNoise<_mm,false,false>(srcY,stride1[0],dstY,stride2[0],dx1[0],dy1[0],cfg->strength,cfg->uniform,noiseMask[0],noiseMaskStride[0],noiseCount[0]);
noiseAvihStrength=0;
break;
}
case TnoiseSettings::NOISE_AVIH:
{
if (cfg->strength!=noiseAvihStrength)
genAVIHnoise(0,noiseAvihStrength=cfg->strength);
generateAddNoise<_mm,false,true>(srcY,stride1[0],dstY,stride2[0],dx1[0],dy1[0],0,cfg->uniform,noiseMask[0]+((rand()%(dx1[0]*dy1[0]))&~15),noiseMaskStride[0],0);
break;
}
}
_mm::empty();
}
template<class _mm> void TimgFilterNoise::processChroma(const TnoiseSettings *cfg,const unsigned char *srcU,const unsigned char *srcV,unsigned char *dstU,unsigned char *dstV)
{
switch (cfg->method)
{
case TnoiseSettings::NOISE_FF:
{
noiseCount[1]++;noiseCount[2]++;
if (noiseAvihStrengthChroma) noiseCount[1]=noiseCount[2]=0;
generateAddNoise<_mm,true,false>(srcU,stride1[1],dstU,stride2[1],dx1[1],dy1[1],cfg->strengthChroma,cfg->uniform,noiseMask[1],noiseMaskStride[1],noiseCount[1]);
generateAddNoise<_mm,true,false>(srcV,stride1[2],dstV,stride2[2],dx1[2],dy1[2],cfg->strengthChroma,cfg->uniform,noiseMask[2],noiseMaskStride[2],noiseCount[2]);
noiseAvihStrengthChroma=0;
break;
}
case TnoiseSettings::NOISE_AVIH:
{
if (cfg->strengthChroma!=noiseAvihStrengthChroma)
{
noiseAvihStrengthChroma=cfg->strengthChroma;
genAVIHnoise(1,noiseAvihStrengthChroma);
genAVIHnoise(2,noiseAvihStrengthChroma);
}
generateAddNoise<_mm,true,true>(srcU,stride1[1],dstU,stride2[1],dx1[1],dy1[1],0,cfg->uniform,noiseMask[1]+rand()%(noiseMaskStride[1]*dy1[1]),noiseMaskStride[1],0);
generateAddNoise<_mm,true,true>(srcV,stride1[2],dstV,stride2[2],dx1[2],dy1[2],0,cfg->uniform,noiseMask[2]+rand()%(noiseMaskStride[2]*dy1[2]),noiseMaskStride[2],0);
break;
}
}
_mm::empty();
}
bool TimgFilterNoise::is(const TffPictBase &pict,const TfilterSettingsVideo *cfg0)
{
const TnoiseSettings *cfg=(const TnoiseSettings*)cfg0;
return super::is(pict,cfg) && (cfg->strength || cfg->strengthChroma);
}
HRESULT TimgFilterNoise::process(TfilterQueue::iterator it,TffPict &pict,const TfilterSettingsVideo *cfg0)
{
if (is(pict,cfg0))
{
const TnoiseSettings *cfg=(const TnoiseSettings*)cfg0;
init(pict,cfg->full,cfg->half);
if (oldPattern!=cfg->pattern)
{
oldPattern=cfg->pattern;
noiseAvihStrength=noiseAvihStrengthChroma=-1;
}
int csp=0;
if (cfg->strength)
{
const unsigned char *srcY;
getCur(FF_CSPS_MASK_YUV_PLANAR,pict,cfg->full,&srcY,NULL,NULL,NULL);
unsigned char *dstY;
getCurNext(csp=csp1,pict,cfg->full,COPYMODE_NO,&dstY,NULL,NULL,NULL);
if (!noiseMask[0])
{
noiseMaskStride[0]=(dx1[0]/16+2)*16;
noiseMask[0]=(short*)aligned_calloc(noiseMaskStride[0]*dy1[0]*2,2);
}
(this->*processLumaFc)(cfg,srcY,dstY);
}
if (cfg->strengthChroma)
{
const unsigned char *srcU,*srcV;
getCur(csp?csp:FF_CSPS_MASK_YUV_PLANAR,pict,cfg->full,NULL,&srcU,&srcV,NULL);
unsigned char *dstU,*dstV;
getCurNext(csp1,pict,cfg->full,COPYMODE_NO,NULL,&dstU,&dstV,NULL);
if (oldcsp!=csp1)
{
oldcsp=csp1;
doneChroma();
}
if (!noiseMask[1])
{
noiseMaskStride[1]=(dx1[1]/16+2)*16;
noiseMask[1]=(short*)aligned_calloc(noiseMaskStride[1]*dy1[2]*2,2);
}
if (!noiseMask[2])
{
noiseMaskStride[2]=(dx1[2]/16+2)*16;
noiseMask[2]=(short*)aligned_calloc(noiseMaskStride[2]*dy1[2]*2,2);
}
(this->*processChromaFc)(cfg,srcU,srcV,dstU,dstV);
}
}
_mm_empty();
return parent->deliverSample(++it,pict);
}
#pragma warning(pop)
//======================================== TimgFilterFlicker ========================================
TimgFilterFlicker::TimgFilterFlicker(IffdshowBase *Ideci,Tfilters *Iparent):TimgFilter(Ideci,Iparent)
{
luma=NULL;lumaSettings.lumGain=lumaSettings.lumGainDef;lumaSettings.is=lumaSettings.show=1;lumaSettings.gammaCorrection=lumaSettings.gammaCorrectionDef;lumaT=0;
}
TimgFilterFlicker::~TimgFilterFlicker()
{
if (luma) delete luma;
}
void TimgFilterFlicker::done(void)
{
if (luma) luma->done();
}
bool TimgFilterFlicker::is(const TffPictBase &pict,const TfilterSettingsVideo *cfg0)
{
const TnoiseSettings *cfg=(const TnoiseSettings*)cfg0;
return super::is(pict,cfg0) && cfg->flickerA;
}
HRESULT TimgFilterFlicker::process(TfilterQueue::iterator it,TffPict &pict,const TfilterSettingsVideo *cfg0)
{
if (is(pict,cfg0))
{
const TnoiseSettings *cfg=(const TnoiseSettings*)cfg0;
lumaSettings.full=cfg->full;lumaSettings.half=cfg->half;
lumaSettings.lumOffset=int(cfg->flickerA*sin(lumaT/(2*M_PI)));
lumaT+=rand()%cfg->flickerF;
if (!luma) luma=new TimgFilterLuma(deci,parent);
return luma->process(it,pict,&lumaSettings);
}
else
return parent->deliverSample(++it,pict);
}
//========================================= TimgFilterShake =========================================
TimgFilterShake::TimgFilterShake(IffdshowBase *Ideci,Tfilters *Iparent):TimgFilter(Ideci,Iparent)
{
offset=NULL;offsetSettings.is=offsetSettings.show=1;offsetTX=offsetTY=0;
}
TimgFilterShake::~TimgFilterShake()
{
if (offset) delete offset;
}
void TimgFilterShake::done(void)
{
if (offset) offset->done();
}
bool TimgFilterShake::is(const TffPictBase &pict,const TfilterSettingsVideo *cfg0)
{
const TnoiseSettings *cfg=(const TnoiseSettings*)cfg0;
return super::is(pict,cfg0) && cfg->shakeA;
}
HRESULT TimgFilterShake::process(TfilterQueue::iterator it,TffPict &pict,const TfilterSettingsVideo *cfg0)
{
if (is(pict,cfg0))
{
const TnoiseSettings *cfg=(const TnoiseSettings*)cfg0;
offsetSettings.full=cfg->full;offsetSettings.half=cfg->half;
int offsetX=int((cfg->shakeA+1)*sin(offsetTX/(2*M_PI)));
int offsetY=int((cfg->shakeA+1)*sin(offsetTY/(2*M_PI)));
offsetSettings.Y_X=offsetSettings.U_X=offsetSettings.V_X=offsetX;
offsetSettings.Y_Y=offsetSettings.U_Y=offsetSettings.V_Y=offsetY;
if ((rand()%cfg->shakeF)>cfg->shakeF/2)
{
offsetTX+=(rand()%cfg->shakeF)-cfg->shakeF/2;
offsetTY+=(rand()%cfg->shakeF)-cfg->shakeF/2;
}
else
offsetTX=offsetTY=0;
if (!offset) offset=new TimgFilterOffset(deci,parent);
return offset->process(it,pict,&offsetSettings);
}
else
return parent->deliverSample(++it,pict);
}
//======================================= TimgFilterFilmLines =======================================
TimgFilterFilmLines::TimgFilterFilmLines(IffdshowBase *Ideci,Tfilters *Iparent):TimgFilter(Ideci,Iparent)
{
linesT=0;
}
void TimgFilterFilmLines::done(void)
{
lines.clear();
}
bool TimgFilterFilmLines::is(const TffPictBase &pict,const TfilterSettingsVideo *cfg0)
{
const TnoiseSettings *cfg=(const TnoiseSettings*)cfg0;
return super::is(pict,cfg0) && cfg->linesF;
}
HRESULT TimgFilterFilmLines::process(TfilterQueue::iterator it,TffPict &pict,const TfilterSettingsVideo *cfg0)
{
if (is(pict,cfg0))
{
const TnoiseSettings *cfg=(const TnoiseSettings*)cfg0;
int linesF=101-cfg->linesF;
if (rand()%linesF>linesF-linesT)
{
lines.push_back(Tline(cfg));
linesT=0;
}
else
linesT++;
if (!lines.empty())
{
init(pict,cfg->full,cfg->half);
unsigned char *dst;
getCurNext(FF_CSPS_MASK_YUV_PLANAR,pict,cfg->full,COPYMODE_DEF,&dst,NULL,NULL,NULL);
int maxtransp=std::min(3*cfg->linesTransparency/2,250);
for (Tlines::iterator l=lines.begin();l!=lines.end();)
{
if (l->firsttime)
{
l->setDx(dx2[0]);
l->firsttime=false;
}
unsigned char *p=dst;
int x=l->x>>16;
for (unsigned int y=0;y<dy2[0];y++,p+=stride2[0])
{
p[x]=uint8_t(((255-l->strength)*p[x]+l->strength*l->color)/256);
l->strength=limit(l->strength+rand()%5-2,0,maxtransp);
}
if (l->update()) l=lines.erase(l);else l++;
}
}
}
return parent->deliverSample(++it,pict);
}
void TimgFilterFilmLines::onSeek(void)
{
done();
}
void TimgFilterFilmLines::onSizeChange(void)
{
done();
}
TimgFilterFilmLines::Tline::Tline(const TnoiseSettings *cfg):firsttime(true)
{
life=rand()%cfg->linesA+1;
if (rand()%256>cfg->linesC)
color=(unsigned char)(20+rand()%30);
else
color=(unsigned char)(210-rand()%50);
strength=rand()%cfg->linesTransparency;
}
void TimgFilterFilmLines::Tline::setDx(unsigned int Idx)
{
dx=Idx;
x=(rand()%dx)<<16;
diffx=rand()%4096-2048;
}
bool TimgFilterFilmLines::Tline::update(void)
{
if (!--life) return true;
x+=diffx;
if (!isIn(x>>16,0,int(dx-1))) return true;
return false;
}
//==================================== TimgFilterFilmSchratches =====================================
TimgFilterScratches::TimgFilterScratches(IffdshowBase *Ideci,Tfilters *Iparent):TimgFilter(Ideci,Iparent)
{
scratchesT=0;
}
bool TimgFilterScratches::is(const TffPictBase &pict,const TfilterSettingsVideo *cfg0)
{
const TnoiseSettings *cfg=(const TnoiseSettings*)cfg0;
return super::is(pict,cfg0) && cfg->scratchesF;
}
HRESULT TimgFilterScratches::process(TfilterQueue::iterator it,TffPict &pict,const TfilterSettingsVideo *cfg0)
{
if (is(pict,cfg0))
{
const TnoiseSettings *cfg=(const TnoiseSettings*)cfg0;
int scratchesF=101-cfg->scratchesF;
if (rand()%scratchesF>scratchesF-scratchesT-2)
{
unsigned char *dst=NULL;
init(pict,cfg->full,cfg->half);
getCurNext(FF_CSPS_MASK_YUV_PLANAR,pict,cfg->full,COPYMODE_DEF,&dst,NULL,NULL,NULL);
unsigned int numscratches=1+((rand()%100)/scratchesF)/30;
int maxtransp=std::min(3*cfg->scratchesTransparency/2,250);
for (unsigned int s=0;s<numscratches;s++)
{
int sx=(rand()%(dx2[0]-10)+5)<<16,sy=(rand()%(dy2[0]-10)+5)<<16;
unsigned int length=rand()%30+2*cfg->scratchesA;
unsigned char color;
if (rand()%256>cfg->scratchesC)
color=(unsigned char)(10+rand()%30);
else
color=(unsigned char)(210-rand()%30);
int strength=rand()%20;
int rx=rand()%400,ry=rand()%400;
for (unsigned int i=1;i<length;i++)
{
unsigned char *p=dst+(sx>>16)+(sy>>16)*stride2[0];
*p=uint8_t(((255-strength)**p+strength*color)/256);
sx+=int((1<<15)*sin(rx+rand()%(length-i)/(M_PI*2)));
sy+=int((1<<15)*cos(ry+rand()%(length-i)/(M_PI*2)));
if (!isIn(sx,0,int(dx2[0]-1)<<16) || !isIn(sy,0,int(dy2[0]-1)<<16))
break;
strength=limit(strength+rand()%16-7,0,maxtransp);
}
}
scratchesT=0;
}
else
scratchesT++;
}
return parent->deliverSample(++it,pict);
}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?