timgfilterlevels.cpp

来自「从FFMPEG转换而来的H264解码程序,VC下编译..」· C++ 代码 · 共 173 行

CPP
173
字号
/*
 * Copyright (c) 2002-2006 Milan Cutka
 * Levels table calculation from Avisynth v1.0 beta. Copyright 2000 Ben Rudiak-Gould
 * Ylevels by Did閑
 *
 * 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 "TimgFilterLevels.h"
#include "IffdshowBase.h"
#include "ffdebug.h"

TimgFilterLevels::TimgFilterLevels(IffdshowBase *Ideci,Tfilters *Iparent):TimgFilter(Ideci,Iparent)
{
 oldSettings.inMin=-1;
 resetHistory();
}

bool TimgFilterLevels::is(const TffPictBase &pict,const TfilterSettingsVideo *cfg0)
{
 const TlevelsSettings *cfg=(const TlevelsSettings*)cfg0;
 return super::is(pict,cfg) && (cfg->mode==5 || cfg->inAuto || cfg->inMin!=0 || cfg->inMax!=255 || cfg->outMin!=0 || cfg->outMax!=255 || cfg->gamma!=100);
}

HRESULT TimgFilterLevels::process(TfilterQueue::iterator it,TffPict &pict,const TfilterSettingsVideo *cfg0)
{
 const TlevelsSettings *cfg=(const TlevelsSettings*)cfg0;
 const unsigned char *srcY=NULL;
 if (cfg->inAuto || (deci->getParam2(IDFF_buildHistogram) && deci->getCfgDlgHwnd()))
  {
   if (cfg->inAuto)
    {
     init(pict,cfg->full,cfg->half);
     getCur(supportedcsps,pict,cfg->full,&srcY,NULL,NULL,NULL);
    }
   CAutoLock lock(&csHistogram);
   pict.histogram(histogram,cfg->full,cfg->half);
  }
 if (cfg->inAuto)
  {
   int newInMin,newInMax;
   unsigned int l=pictRect.dx*pictRect.dy/7000;
   for (newInMin=0;newInMin<250 && histogram[newInMin]<l;newInMin++)
    ;
   for (newInMax=255;newInMax>newInMin+1 && histogram[newInMax]<l;newInMax--)
    ;
   int diff=newInMax-newInMin;
   if (diff<40)
    {
     newInMin=limit(newInMin-20,0,254);
     newInMax=limit(newInMax+20,1,255);
    }
   inMinSum-=inMins[minMaxPos];inMins[minMaxPos]=newInMin;inMinSum+=newInMin;
   inMaxSum-=inMaxs[minMaxPos];inMaxs[minMaxPos]=newInMax;inMaxSum+=newInMax;
   minMaxPos++;if (minMaxPos==HISTORY) minMaxPos=0;
   inMin=inMinSum/HISTORY;inMax=inMaxSum/HISTORY;
   //DPRINTF("min:%i max:%i\n",inMin,inMax);
  }
 else
  {
   inMin=cfg->inMin;
   inMax=cfg->inMax;
  }
 if (cfg->is && (cfg->mode==5 || cfg->inAuto || inMin!=0 || inMax!=255 || cfg->outMin!=0 || cfg->outMax!=255 || cfg->gamma!=100 || cfg->posterize!=255))
  {
   bool equal=cfg->equal(oldSettings);
   if (cfg->inAuto || !equal)
    {
     oldSettings=*cfg;
     int divisor;
     oldSettings.calcMap(map,&divisor,inMin,inMax);
     if (!equal)
      {
       if (cfg->inAuto)
        divisor=cfg->inMax-cfg->inMin+(cfg->inMax==cfg->inMin);
       for (int x=0;x<256;x++)
        mapchroma[x]=limit(((x-128)*(oldSettings.outMax-oldSettings.outMin)+(divisor>>1))/divisor+128,16,240);
      }
    }
   if (!srcY)
    {
     init(pict,cfg->full,cfg->half);
     getCur(supportedcsps,pict,cfg->full,&srcY,NULL,NULL,NULL);
    }
   unsigned char *dstY;
   getCurNext(csp1,pict,cfg->full,COPYMODE_NO,&dstY,NULL,NULL,NULL);
   if (csp_isYUVplanar(csp1))
    {
     for (unsigned int y=0;y<dy1[0];y++)
      {
       const unsigned char *src;unsigned char *dst,*dstEnd;
       for (src=srcY+stride1[0]*y,dst=dstY+stride2[0]*y,dstEnd=dst+dx1[0];dst<dstEnd-3;src+=4,dst+=4)
        *(unsigned int*)dst=(map[src[3]]<<24)|(map[src[2]]<<16)|(map[src[1]]<<8)|map[src[0]];
       for (;dst!=dstEnd;src++,dst++)
        *dst=uint8_t(map[*src]);
      }
     if (!oldSettings.onlyLuma)
      {
       const unsigned char *srcU,*srcV;
       getCur(csp1,pict,cfg->full,NULL,&srcU,&srcV,NULL);
       unsigned char *dstU,*dstV;
       getCurNext(csp1,pict,cfg->full,COPYMODE_NO,NULL,&dstU,&dstV,NULL);
       for (unsigned int y=0;y<dy1[1];y++)
        {
         const unsigned char *srcu,*srcv;unsigned char *dstu,*dstv,*dstuEnd;
         for (srcu=srcU+stride1[1]*y,srcv=srcV+stride1[2]*y,dstu=dstU+stride2[1]*y,dstv=dstV+stride2[2]*y,dstuEnd=dstu+dx1[1];dstu<dstuEnd-3;srcu+=4,srcv+=4,dstu+=4,dstv+=4)
          {
           *(unsigned int*)dstu=(mapchroma[srcu[3]]<<24)|(mapchroma[srcu[2]]<<16)|(mapchroma[srcu[1]]<<8)|mapchroma[srcu[0]];
           *(unsigned int*)dstv=(mapchroma[srcv[3]]<<24)|(mapchroma[srcv[2]]<<16)|(mapchroma[srcv[1]]<<8)|mapchroma[srcv[0]];
          }
         for (;dstu!=dstuEnd;srcu++,srcv++,dstu++,dstv++)
          {
           *dstu=uint8_t(mapchroma[*srcu]);
           *dstv=uint8_t(mapchroma[*srcv]);
          }
        }
      }
    }
   else if (csp_isYUVpacked(csp1))
    {
     int lumaoffset=pict.cspInfo.packedLumaOffset,chromaoffset=pict.cspInfo.packedChromaOffset;
     if      (lumaoffset==0 && chromaoffset==1 && oldSettings.onlyLuma==0) processPacked<0,1,0>(srcY,dstY);
     else if (lumaoffset==0 && chromaoffset==1 && oldSettings.onlyLuma==1) processPacked<0,1,1>(srcY,dstY);
     else if (lumaoffset==1 && chromaoffset==0 && oldSettings.onlyLuma==0) processPacked<1,0,0>(srcY,dstY);
     else if (lumaoffset==1 && chromaoffset==0 && oldSettings.onlyLuma==1) processPacked<1,0,1>(srcY,dstY);
    }
  }
 return parent->deliverSample(++it,pict);
}

void TimgFilterLevels::resetHistory(void)
{
 inMin=0;memsetd(inMins,inMin,sizeof(inMins));inMinSum=inMin;
 inMax=255;memsetd(inMaxs,inMax,sizeof(inMaxs));inMaxSum=inMax*HISTORY;
 minMaxPos=0;
}
void TimgFilterLevels::onSeek(void)
{
 resetHistory();
}

STDMETHODIMP TimgFilterLevels::getHistogram(unsigned int dst[256])
{
 CAutoLock lock(&csHistogram);
 memcpy(dst,histogram,sizeof(histogram));
 return S_OK;
}
STDMETHODIMP TimgFilterLevels::getInAuto(int *min,int *max)
{
 *min=inMin;
 *max=inMax;
 return S_OK;
}

HRESULT TimgFilterLevels::queryInterface(const IID &iid,void **ptr) const
{
 if (iid==IID_IimgFilterLevels) {*ptr=(IimgFilterLevels*)this;return S_OK;}
 else return E_NOINTERFACE;
}

⌨️ 快捷键说明

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