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 + -
显示快捷键?