⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 timgfiltersharpen.cpp

📁 从FFMPEG转换而来的H264解码程序,VC下编译..
💻 CPP
📖 第 1 页 / 共 2 页
字号:
/*
 * Copyright (c) 2002-2006 Milan Cutka
 * algorithms based on VirtualDub and AviSynth filters by Donald A. Graft
 * asharp by Marc Fauconneau
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 */

#include "stdafx.h"
#include "TimgFilterSharpen.h"
#include "TsharpenSettings.h"
#include "IffdshowBase.h"
#include "T3x3blur.h"
#include "Tconfig.h"
#include "Tlibmplayer.h"
#include "postproc/swscale.h"
#include "simd.h"

//==================================== TimgFilterAsharp ====================================
TimgFilterAsharp::TimgFilterAsharp(IffdshowBase *Ideci,Tfilters *Iparent):TimgFilter(Ideci,Iparent)
{
 asharp_run=getAsharp();
 aline=NULL;
 oldAsharpT=INT_MAX;
}
void TimgFilterAsharp::done(void)
{
 if (aline) aligned_free(aline);aline=NULL;
}

bool TimgFilterAsharp::is(const TffPictBase &pict,const TfilterSettingsVideo *cfg0)
{
 const TsharpenSettings *cfg=(const TsharpenSettings*)cfg0;
 return super::is(pict,cfg) && cfg->asharpT;
}

HRESULT TimgFilterAsharp::process(TfilterQueue::iterator it,TffPict &pict,const TfilterSettingsVideo *cfg0)
{
 if (is(pict,cfg0))
  {
   const TsharpenSettings *cfg=(const TsharpenSettings*)cfg0;
   if (oldAsharpT!=cfg->asharpT || oldAsharpD!=cfg->asharpD || oldAsharpB!=cfg->asharpB || oldAsharpHQBF!=cfg->asharpHQBF)
    {
     oldAsharpT=cfg->asharpT;oldAsharpD=cfg->asharpD;oldAsharpB=cfg->asharpB;oldAsharpHQBF=cfg->asharpHQBF;
     //TODO: remove comparisons - it shouldn't be possible to enter too small/large parameter
     double t=oldAsharpT/100.0;
     asharpCfgT=(int)(t*(4<<7));
     asharpCfgT=limit(asharpCfgT,int(-(4<<7)),int(32*(4<<7))); // yes, negatives values are accepted

     double d=oldAsharpD/100.0;
     asharpCfgD=(int)(d*(4<<7));
     asharpCfgD=limit(asharpCfgD,0,int(16*(4<<7)));

     if (oldAsharpB==0)
      asharpCfgB=asharpCfgB2=256;
     else
      {
       double b=oldAsharpB/100.0;
       asharpCfgB=(int)(256-b*64);
       asharpCfgB=limit(asharpCfgB,0,256);
       asharpCfgB2=(int)(256-b*48);
       asharpCfgB2=limit(asharpCfgB2,0,256);
      }
    }

   init(pict,cfg->full,cfg->half);
   if (!aline) aline=(unsigned char*)aligned_malloc(pictRect.dx*2);
   unsigned char *dst;
   getCurNext(FF_CSPS_MASK_YUV_PLANAR,pict,cfg->full,COPYMODE_DEF,&dst,NULL,NULL,NULL);

   unsigned char *lastX2,*lastX1;
   if (oldAsharpHQBF)
    {
     lastX2=(unsigned char*)_alloca(dy1[0]);lastX1=(unsigned char*)_alloca(dy1[0]);
     for (unsigned int y=0;y<dy1[0];y++)
      {
       lastX2[y]=dst[y*stride2[0]+dx1[0]-2];
       lastX1[y]=dst[y*stride2[0]+dx1[0]-1];
      }
    }
   else
    lastX2=lastX1=NULL;

   asharp_run(dst,(int)stride2[0],dy1[0],dx1[0],asharpCfgT,asharpCfgD,asharpCfgB,asharpCfgB2,oldAsharpHQBF,aline);
   _mm_empty();

   if (oldAsharpHQBF)
    for (unsigned int y=0;y<dy1[0];y++)
     {
      dst[y*stride2[0]+dx1[0]-2]=lastX2[y];
      dst[y*stride2[0]+dx1[0]-1]=lastX1[y];
     }
  }
 return parent->deliverSample(++it,pict);
}

//==================================== TimgFilterMplayerSharp ====================================
TimgFilterMplayerSharp::TimgFilterMplayerSharp(IffdshowBase *Ideci,Tfilters *Iparent):TimgFilter(Ideci,Iparent)
{
 libmplayer=NULL;swsc=NULL;swsf=NULL;oldmplayersharpenluma=oldmplayersharpenchroma=-1;
}
TimgFilterMplayerSharp::~TimgFilterMplayerSharp()
{
 if (libmplayer) libmplayer->Release();
}
void TimgFilterMplayerSharp::done(void)
{
 if (swsf) libmplayer->sws_freeFilter(swsf);swsf=NULL;
 if (swsc) libmplayer->sws_freeContext(swsc);swsc=NULL;
}

bool TimgFilterMplayerSharp::is(const TffPictBase &pict,const TfilterSettingsVideo *cfg0)
{
 const TsharpenSettings *cfg=(const TsharpenSettings*)cfg0;
 return super::is(pict,cfg) && (cfg->mplayerLuma || cfg->mplayerChroma);
}

HRESULT TimgFilterMplayerSharp::process(TfilterQueue::iterator it,TffPict &pict,const TfilterSettingsVideo *cfg0)
{
 if (is(pict,cfg0))
  {
   const TsharpenSettings *cfg=(const TsharpenSettings*)cfg0;
   init(pict,cfg->full,cfg->half);
   bool cspChanged=false;
   const unsigned char *src[4];
   cspChanged|=getCur(SWS_IN_CSPS,pict,cfg->full,src);
   unsigned char *dst[4];
   cspChanged|=getNext(SWS_OUT_CSPS,pict,cfg->full,dst);
   if (cspChanged) done();

   if (!swsc || oldmplayersharpenluma!=cfg->mplayerLuma || oldmplayersharpenchroma!=cfg->mplayerChroma)
    {
     oldmplayersharpenluma=cfg->mplayerLuma;oldmplayersharpenchroma=cfg->mplayerChroma;
     if (!libmplayer) deci->getPostproc(&libmplayer);
     done();
     swsf=libmplayer->sws_getDefaultFilter(0,0,oldmplayersharpenluma/100.0f,oldmplayersharpenchroma/100.0f,0,0,0);
     SwsParams params;Tlibmplayer::swsInitParams(&params,0);
     swsc=libmplayer->sws_getContext(dx1[0],dy1[0],csp_ffdshow2mplayer(csp1),dx1[0],dy1[0],csp_ffdshow2mplayer(csp2),&params,swsf,NULL);
    }

   if (swsc)
    libmplayer->sws_scale_ordered(swsc,src,stride1,0,dy1[0],dst,stride2);
  }
 return parent->deliverSample(++it,pict);
}

//==================================== TimgFilterUnsharp ====================================
TimgFilterUnsharp::TimgFilterUnsharp(IffdshowBase *Ideci,Tfilters *Iparent):TimgFilter(Ideci,Iparent)
{
 Ysum=NULL;
#ifdef __SSE2__
 if (Tconfig::cpu_flags&FF_CPU_SSE2)
  unsharpFc=&TimgFilterUnsharp::unsharp<Tsse2>;
 else
#endif
  unsharpFc=&TimgFilterUnsharp::unsharp<Tmmx>;
}
void TimgFilterUnsharp::done(void)
{
 if (Ysum) aligned_free(Ysum);Ysum=NULL;
}

bool TimgFilterUnsharp::is(const TffPictBase &pict,const TfilterSettingsVideo *cfg0)
{
 const TsharpenSettings *cfg=(const TsharpenSettings*)cfg0;
 return super::is(pict,cfg) && cfg->unsharpStrength;
}

template<class _mm> void TimgFilterUnsharp::unsharp(const TsharpenSettings *cfg,const unsigned char *src,unsigned char *dst,unsigned short *sum)
{
 static const int C_SCALE=32;
 typename _mm::__m div9_64=_mm::set1_pi16(7281),m0=_mm::setzero_si64();
 //typename _mm::__m T64=_mm::set1_pi16((short)cfg->unsharpThreshold);
 typename _mm::__m C64=_mm::set1_pi16(short(cfg->unsharpStrength+C_SCALE)); //strength=0..250
 src+=stride1[0];dst+=stride2[0];sum+=minStride;
 for (const unsigned char *srcEnd=src+(dy1[0]-2)*stride1[0];src!=srcEnd;src+=stride1[0],sum+=minStride,dst+=stride2[0])
  {
   for (unsigned int x=0;x<dx1[0]-1;x+=_mm::size/2)
    {
     typename _mm::__m mm0=_mm::unpacklo_pi8(_mm::load2(src+stride1[0]+x  ),m0);
     typename _mm::__m mm1=_mm::unpacklo_pi8(_mm::load2(src+stride1[0]+x+1),m0);
     typename _mm::__m mm2=_mm::unpacklo_pi8(_mm::load2(src+stride1[0]+x+2),m0);
     _mm::storeU(sum+minStride+1+x,_mm::add_pi16(mm0,_mm::add_pi16(mm1,mm2)));
    }
   for (unsigned int x=0;x<dx1[0]-1;x+=_mm::size/2)
    {
     typename _mm::__m y_sum=_mm::mulhi_pi16(_mm::add_pi16(_mm::add_pi16(*(typename _mm::__m*)(sum+x),*(typename _mm::__m*)(sum+minStride+x)),*(typename _mm::__m*)(sum-minStride+x)),div9_64);
     typename _mm::__m diff=_mm::sub_pi16(_mm::unpacklo_pi8(_mm::load2(src+x),m0),y_sum);
     diff=_mm::adds_pi16(_mm::srai_pi16(_mm::mullo_pi16(diff,C64),5),y_sum);
     _mm::store2(dst+x,_mm::packs_pu16(diff,m0));
    }
  }
 _mm::empty();
}

HRESULT TimgFilterUnsharp::process(TfilterQueue::iterator it,TffPict &pict,const TfilterSettingsVideo *cfg0)
{
 if (is(pict,cfg0))
  {
   const TsharpenSettings *cfg=(const TsharpenSettings*)cfg0;
   init(pict,cfg->full,cfg->half);
   if (!Ysum)
    {
     minStride=(pictRect.dx/16+2)*16;
     Ysum=(unsigned short*)aligned_malloc(minStride*pictRect.dy*2);
    }

   const unsigned char *src_;
   unsigned char *dst_;
   getCur(FF_CSPS_MASK_YUV_PLANAR,pict,cfg->full,&src_,NULL,NULL,NULL);
   getNext(csp1,pict,cfg->full,&dst_,NULL,NULL,NULL);
   const unsigned char *src=src_;
   unsigned char *dst=dst_;

   unsigned short *sum=Ysum;
   for (unsigned int x=1;x<dx1[0]-1;x++)
    {
     sum[x          ]=(unsigned short)(src[x-1           ]+src[x           ]+src[x+1           ]);
     sum[x+minStride]=(unsigned short)(src[x-1+stride1[0]]+src[x+stride1[0]]+src[x+1+stride1[0]]);
    }
   (this->*unsharpFc)(cfg,src,dst,sum);
   const unsigned char *srcL=src_+stride1[0],*srcR=srcL+dx1[0]-1;unsigned char *dstL=dst_+stride2[0],*dstR=dstL+dx1[0]-1;
   for (unsigned int y=1;y<dy1[0]-1;srcL+=stride1[0],srcR+=stride1[0],dstL+=stride2[0],dstR+=stride2[0],y++)
    {
     *dstL=*srcL;
     *dstR=*srcR;
    }
   memcpy(dst_,src_,dx1[0]);
   memcpy(dst_+stride2[0]*(dy1[0]-2),src_+stride1[0]*(dy1[0]-2),dx1[0]);
   memcpy(dst_+stride2[0]*(dy1[0]-1),src_+stride1[0]*(dy1[0]-1),dx1[0]);
  }
 return parent->deliverSample(++it,pict);
}

//==================================== TimgFilterXsharp =====================================
TimgFilterXsharp::TimgFilterXsharp(IffdshowBase *Ideci,Tfilters *Iparent):TimgFilter(Ideci,Iparent)
{
 Ymin=Ymax=NULL;
#ifdef __SSE2__
 if (Tconfig::cpu_flags&FF_CPU_SSE2)
  xsharpenFc=&TimgFilterXsharp::xsharpen<Tsse2>;
 else
#endif
 if (Tconfig::cpu_flags&FF_CPU_MMXEXT)
  xsharpenFc=&TimgFilterXsharp::xsharpen<Tmmxext>;
 else
  xsharpenFc=&TimgFilterXsharp::xsharpen<Tmmx>;
}
void TimgFilterXsharp::done(void)
{
 if (Ymin) aligned_free(Ymin);Ymin=NULL;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -