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

📄 timgfilterdeinterlace.cpp

📁 从FFMPEG转换而来的H264解码程序,VC下编译..
💻 CPP
字号:
/*
 * Copyright (c) 2002-2006 Milan Cutka
 * motion compensated frame rate doubling by Tom Barry
 *
 * 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 "TimgFilterDeinterlace.h"
#include "TdeinterlaceSettings.h"
#include "IffdshowBase.h"
#include "IffdshowDecVideo.h"
#include "Tlibmplayer.h"
#include "Tconfig.h"
#include "simd.h"

//============================================= TimgFilterDeinterlace =============================================
TimgFilterDeinterlace::TimgFilterDeinterlace(IffdshowBase *Ideci,Tfilters *Iparent):TimgFilter(Ideci,Iparent)
{
}
HRESULT TimgFilterDeinterlace::process(TfilterQueue::iterator it,TffPict &pict,const TfilterSettingsVideo *cfg0)
{
 const TdeinterlaceSettings *cfg=(const TdeinterlaceSettings*)cfg0;
 if (cfg->swapfields)
  if (pict.fieldtype&FIELD_TYPE::INT_TFF)
   pict.fieldtype=(pict.fieldtype&~FIELD_TYPE::INT_TFF)|FIELD_TYPE::INT_BFF;
  else if (pict.fieldtype&FIELD_TYPE::INT_BFF)
   pict.fieldtype=(pict.fieldtype&~FIELD_TYPE::INT_BFF)|FIELD_TYPE::INT_TFF;

 if (pict.rectClip != pict.rectFull)
  parent->dirtyBorder=1;

 return parent->deliverSample(++it,pict);
}

//===================================== TimgFilterFramerateDoubler ====================================
TimgFilterFramerateDoubler::TimgFilterFramerateDoubler(IffdshowBase *Ideci,Tfilters *Iparent):
 TimgFilter(Ideci,Iparent),
 old(NULL)
{
 if (Tconfig::cpu_flags&FF_CPU_MMXEXT)
  {
   interpolateMotion=Tinterpolate<Tmmxext>::interpolateMotion;
   pictInterpolate=Tinterpolate<Tmmxext>::pictInterpolate;
  }
 else
  {
   interpolateMotion=Tinterpolate<Tmmx>::interpolateMotion;
   pictInterpolate=Tinterpolate<Tmmx>::pictInterpolate;
  }
#ifdef __SSE2__
 if (Tconfig::cpu_flags&FF_CPU_SSE2)
  pictInterpolate=Tinterpolate<Tsse2>::pictInterpolate;
#endif
}
void TimgFilterFramerateDoubler::done(void)
{
 if (old) delete old;old=NULL;
}

template<class Tsimd> void TimgFilterFramerateDoubler::Tinterpolate<Tsimd>::pictInterpolate(unsigned char *dst,stride_t dstStride,const unsigned char *src1,stride_t src1stride,const unsigned char *src2,stride_t src2stride,unsigned int dx,unsigned int dy)
{
 if (Tsimd::align && (intptr_t(src1)&15 || intptr_t(src2)&15 || intptr_t(dst)&15 || src1stride&15 || src2stride&15 || dstStride&15))
  {
   Tinterpolate<typename Tsimd::T64>::pictInterpolate(dst,dstStride,src1,src1stride,src2,src2stride,dx,dy);
   return;
  }
 for (unsigned int y=0;y<dy;y++,src1+=src1stride,src2+=src2stride,dst+=dstStride)
  {
   int x;
   for (x=0;x<int(dx-Tsimd::size*2+1);x+=Tsimd::size*2)
    {
     typename Tsimd::__m dest1,dest2;
     movq(dest1,src1+x);movq(dest2,src1+x+Tsimd::size);
     Tsimd::pavgb(dest1,src2+x);Tsimd::pavgb(dest2,src2+x+Tsimd::size);
     movq(dst+x,dest1);movq(dst+x+Tsimd::size,dest2);
    }
   for (;x<int(dx);x++)
    dst[x]=uint8_t((src1[x]+src2[x]+1)/2);
  }
}

template<class Tsimd> inline void TimgFilterFramerateDoubler::Tinterpolate<Tsimd>::bestInterp(__m64 &mm5,__m64 &mm6,const __m64 *paddr1,const __m64 *paddr2)
{
 __m64 m0=_mm_setzero_si64();
 __m64 mm0=*paddr1; // our 4 pixels
 __m64 mm1=*paddr2; // our pixel2 value

 __m64 mm2=mm0;     // another copy of our pixel1 value

 Tsimd::pminub(mm0,mm1);// mm0=_mm_min_pu8(mm0,mm1); // minimum value of the 2
 Tsimd::pmaxub(mm1,mm2);// mm1=_mm_max_pu8(mm1,mm2); // maximum value of the 2
 mm2=_mm_subs_pu8(mm1,mm0);// the diff
 Tsimd::pavgb(mm0,mm1);// mm0=_mm_avg_pu8(mm0,mm1); // just keep avg
 __m64 mm3=_mm_subs_pu8(mm2,mm5); // nonzero where old weights lower, else 0
 mm3=_mm_cmpeq_pi8(mm3,m0); // now ff where new better, else 00
 mm0=_mm_and_si64(mm0,mm3); // keep only better new avg pixels
 mm2=_mm_and_si64(mm2,mm3); // and weights
 mm3=_mm_cmpeq_pi8(mm3,m0); // here ff where old better, else 00
 mm5=_mm_and_si64(mm5,mm3); // keep only better old weights
 mm6=_mm_and_si64(mm6,mm3); // keep only better old avg pixels
 mm5=_mm_or_si64(mm5,mm2);  // merge new & old weights
 mm6=_mm_or_si64(mm6,mm0);  // merge new & old avg pixels
}

template<class Tsimd> void TimgFilterFramerateDoubler::Tinterpolate<Tsimd>::interpolateMotion(
 stride_t src_pit, stride_t dst_pit, stride_t prev_pit,
 unsigned int rowsize, const BYTE* srcp, BYTE* dstp, const BYTE* _pPrev,
 int FldHeight, // go H expand lines into even output lines
 int Search_Effort,int thresh)
{
 const BYTE* pPrev = _pPrev;
 const BYTE* pSrc = srcp;
 BYTE* pDest = dstp;
 int ct = ((rowsize-10) >> 3);

 memcpy(pDest, pSrc, rowsize);           // copy first line
 memcpy(pDest+dst_pit*(FldHeight-1), pSrc+src_pit*(FldHeight-1), rowsize);  // and last

 pDest += dst_pit;

 const __m64 thresh64=_mm_set1_pi8((char)thresh);
 if (Search_Effort>=9)
  for (int y=1;y<=FldHeight-2;y++,pSrc+=src_pit,pPrev+=prev_pit,pDest+=dst_pit)
   {
    *(__m64*)(pDest+0)=*(__m64*)(pSrc+0);
    *(__m64*)(pDest+rowsize-8)=*(__m64*)(pSrc+src_pit+rowsize-8);
    for (unsigned int x=8;x<rowsize-10;x+=8)
     {
      __m64 mm5=thresh64;
      __m64 mm6=*(__m64*)(pSrc+x+src_pit);
      bestInterp(mm5,mm6,(const __m64*)(pSrc+x          -1),(const __m64*)(pPrev+x+2*prev_pit+1));
      bestInterp(mm5,mm6,(const __m64*)(pSrc+x          +1),(const __m64*)(pPrev+x+2*prev_pit-1));
      bestInterp(mm5,mm6,(const __m64*)(pSrc+x+2*src_pit-1),(const __m64*)(pPrev+x+  prev_pit+1));
      bestInterp(mm5,mm6,(const __m64*)(pSrc+x+2*src_pit+1),(const __m64*)(pPrev+x+  prev_pit-1));
      bestInterp(mm5,mm6,(const __m64*)(pSrc+x+2*src_pit  ),(const __m64*)(pPrev+x+  prev_pit  ));
      bestInterp(mm5,mm6,(const __m64*)(pSrc+x            ),(const __m64*)(pPrev+x+2*prev_pit  ));
      bestInterp(mm5,mm6,(const __m64*)(pSrc+x+src_pit  -1),(const __m64*)(pPrev+x+  prev_pit+1));
      bestInterp(mm5,mm6,(const __m64*)(pSrc+x+src_pit  +1),(const __m64*)(pPrev+x+  prev_pit-1));
      bestInterp(mm5,mm6,(const __m64*)(pSrc+x+src_pit    ),(const __m64*)(pPrev+x+  prev_pit  ));
      Tsimd::movntq(pDest+x,mm6);
     }
   }
 else if (Search_Effort>=3)
  for (int y=1;y<=FldHeight-2;y++,pSrc+=src_pit,pPrev+=prev_pit,pDest+=dst_pit)
   {
    *(__m64*)(pDest+0)=*(__m64*)(pSrc+0);
    *(__m64*)(pDest+rowsize-8)=*(__m64*)(pSrc+src_pit+rowsize-8);
    for (unsigned int x=8;x<rowsize-10;x+=8)
     {
      __m64 mm5=thresh64;
      __m64 mm6=*(__m64*)(pSrc+x+src_pit);
      bestInterp(mm5,mm6,(const __m64*)(pSrc+x+src_pit-1),(const __m64*)(pPrev+x+prev_pit+1));
      bestInterp(mm5,mm6,(const __m64*)(pSrc+x+src_pit+1),(const __m64*)(pPrev+x+prev_pit-1));
      bestInterp(mm5,mm6,(const __m64*)(pSrc+x+src_pit  ),(const __m64*)(pPrev+x+prev_pit  ));
      Tsimd::movntq(pDest+x,mm6);
     }
   }
 else
  for (int y=1;y<=FldHeight-2;y++,pSrc+=src_pit,pPrev+=prev_pit,pDest+=dst_pit)
   {
    *(__m64*)(pDest+0)=*(__m64*)(pSrc+0);
    *(__m64*)(pDest+rowsize-8)=*(__m64*)(pSrc+src_pit+rowsize-8);
    for (unsigned int x=8;x<rowsize-10;x+=8)
     {
      __m64 mm5=thresh64;
      __m64 mm6=*(__m64*)(pSrc+x+src_pit);
      bestInterp(mm5,mm6,(const __m64*)(pSrc+x+src_pit),(const __m64*)(pPrev+x+prev_pit));
      Tsimd::movntq(pDest+x,mm6);
     }
   }
}
HRESULT TimgFilterFramerateDoubler::process(TfilterQueue::iterator it,TffPict &pict,const TfilterSettingsVideo *cfg0)
{
 const TdeinterlaceSettings *cfg=(const TdeinterlaceSettings*)cfg0;
 init(pict,true,cfg->half);
 const unsigned char *src[4];
 bool cspChanged=getCur(FF_CSPS_MASK_YUV_PLANAR,pict,true,src);
 if (cspChanged) done();
 if (old)
  {
   TffPict p1=pict;
   p1.setRO(true);
   //interpolate image
   unsigned char *dst[4];
   getNext(csp1,p1,true,dst);
   for (unsigned int i=0;i<pict.cspInfo.numPlanes;i++)
    if (cfg->frameRateDoublerSE==0)
     pictInterpolate(dst[i],stride2[i],old->data[i],old->stride[i],src[i],stride1[i],dx1[i],dy1[i]);
    else
     interpolateMotion(stride1[i],stride2[i],old->stride[i],pict.cspInfo.Bpp*(dx1[i]),src[i],dst[i],old->data[i],dy1[i],cfg->frameRateDoublerSE,cfg->frameRateDoublerThreshold);
   _mm_empty();
   TfilterQueue::iterator it1=it;
   REFERENCE_TIME dur=(pict.rtStop-pict.rtStart)/2;
   p1.rtStop=pict.rtStart+dur;
   HRESULT hr=parent->deliverSample(++it1,p1);
   if (FAILED(hr)) return hr;
   pict.rtStart+=dur;
  }
 else
  old=new TffPict;
 old->copyFrom(pict,oldbuf);

 if (pict.rectClip != pict.rectFull)
  parent->dirtyBorder=1;

 return parent->deliverSample(++it,pict);
}

void TimgFilterFramerateDoubler::onSeek(void)
{
 if (old) delete old;old=NULL;
}

//========================================= TimgFilterMplayerDeinterlace ==========================================
TimgFilterMplayerDeinterlace::TimgFilterMplayerDeinterlace(IffdshowBase *Ideci,Tfilters *Iparent):TimgFilter(Ideci,Iparent)
{
 libmplayer=NULL;
 pp_ctx=NULL;Tlibmplayer::pp_mode_defaults(pp_mode);
}
TimgFilterMplayerDeinterlace::~TimgFilterMplayerDeinterlace()
{
 if (libmplayer) libmplayer->Release();
}
void TimgFilterMplayerDeinterlace::done(void)
{
 if (pp_ctx) libmplayer->pp_free_context(pp_ctx);pp_ctx=NULL;
}
HRESULT TimgFilterMplayerDeinterlace::process(TfilterQueue::iterator it,TffPict &pict,const TfilterSettingsVideo *cfg0)
{
 const TdeinterlaceSettings *cfg=(const TdeinterlaceSettings*)cfg0;
 init(pict,cfg->full,cfg->half);
 bool cspChanged=false;
 const unsigned char *tempPict1[4];
 cspChanged|=getCur(FF_CSPS_MASK_YUV_PLANAR,pict,cfg->full,tempPict1);
 unsigned char *tempPict2[4];
 cspChanged|=getNext(csp1,pict,cfg->full,tempPict2);
 if (cspChanged) done();

 if (!pp_ctx)
  {
   if (!libmplayer) deci->getPostproc(&libmplayer);
   pp_ctx=libmplayer->pp_get_context(dx1[0],dy1[0],Tlibmplayer::ppCpuCaps(csp1));
  }
 const TdeinterlaceSettings::TmethodProps &methodProps=TdeinterlaceSettings::getMethod(cfg->cfgId);
 pp_mode.lumMode=pp_mode.chromMode=methodProps.id;
 libmplayer->pp_postprocess(tempPict1,stride1,
                            tempPict2,stride2,
                            dx1[0],dy1[0],
                            NULL,0,
                            &pp_mode,pp_ctx,pict.frametype&FRAME_TYPE::typemask);
 pict.fieldtype=FIELD_TYPE::PROGRESSIVE_FRAME;

 if (pict.rectClip != pict.rectFull)
  parent->dirtyBorder=1;

 return parent->deliverSample(++it,pict);
}

⌨️ 快捷键说明

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