timgfiltertimesmooth.cpp
来自「从FFMPEG转换而来的H264解码程序,VC下编译..」· C++ 代码 · 共 232 行
CPP
232 行
/*
* Copyright (c) 2002-2006 Milan Cutka
*
* 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 "TimgFilterTimesmooth.h"
#include "TblurSettings.h"
#define SCALE(i) (0x0000000100010001LL * (0x10000 / (i)))
#define SCALE2(i) SCALE((i)+0),SCALE((i)+1),SCALE((i)+2),SCALE((i)+3),SCALE((i)+4),\
SCALE((i)+5),SCALE((i)+6),SCALE((i)+7),SCALE((i)+8),SCALE((i)+9)
const int64_t TimgFilterTimesmooth::scaletab[]=
{
0,
0x00007fff7fff7fffLL, // special case for 1
0x00007fff7fff7fffLL, // special case for 2
SCALE(3),
SCALE(4),
SCALE(5),
SCALE(6),
SCALE(7),
SCALE(8),
SCALE(9),
SCALE2(10),
SCALE2(20),
SCALE2(30),
SCALE2(40),
SCALE2(50),
SCALE2(60),
SCALE2(70),
SCALE2(80),
SCALE2(90),
SCALE2(100),
SCALE2(110),
SCALE2(120),
};
TimgFilterTimesmooth::TimgFilterTimesmooth(IffdshowBase *Ideci,Tfilters *Iparent):TimgFilter(Ideci,Iparent)
{
oldStrength=-1;
framecount=0;isFirstFrame=true;
accumY=accumU=accumV=NULL;
tempU[0]=tempU[1]=tempU[2]=tempV[0]=tempV[1]=tempV[2]=NULL;
framecount=0;isFirstFrame=true;
UVcount=-3;
}
void TimgFilterTimesmooth::done(void)
{
if (accumY) aligned_free(accumY);accumY=NULL;
if (accumU) aligned_free(accumU);accumU=NULL;
if (accumV) aligned_free(accumV);accumV=NULL;
if (tempU[0]) aligned_free(tempU[0]);tempU[0]=NULL;
if (tempU[1]) aligned_free(tempU[1]);tempU[1]=NULL;
if (tempU[2]) aligned_free(tempU[2]);tempU[2]=NULL;
if (tempV[0]) aligned_free(tempV[0]);tempV[0]=NULL;
if (tempV[1]) aligned_free(tempV[1]);tempV[1]=NULL;
if (tempV[2]) aligned_free(tempV[2]);tempV[2]=NULL;
}
void TimgFilterTimesmooth::onSizeChange(void)
{
done();
UVcount=-3;
}
bool TimgFilterTimesmooth::is(const TffPictBase &pict,const TfilterSettingsVideo *cfg0)
{
const TblurSettings *cfg=(const TblurSettings*)cfg0;
return super::is(pict,cfg) && cfg->isTempSmooth && cfg->tempSmooth;
}
HRESULT TimgFilterTimesmooth::process(TfilterQueue::iterator it,TffPict &pict,const TfilterSettingsVideo *cfg0)
{
if (is(pict,cfg0))
{
const TblurSettings *cfg=(const TblurSettings*)cfg0;
init(pict,cfg->full,cfg->half);
const unsigned char *srcY,*srcU,*srcV;
getCur(FF_CSPS_MASK_YUV_PLANAR,pict,cfg->full,&srcY,&srcU,&srcV,NULL);
unsigned char *dstY=NULL,*dstU=NULL,*dstV=NULL;
if (!isFirstFrame || !cfg->tempSmoothColor)
getNext(csp1,pict,cfg->full,&dstY,&dstU,&dstV,NULL);
if (cfg->tempSmooth!=oldStrength)
{
oldStrength=cfg->tempSmooth;
for (int i=0;i<=510;i++)
{
int sqerr=((i-255)*(i-255))>>oldStrength;
if (sqerr>16) sqerr=16;
sqerr=16-sqerr;
square_table[i]=sqerr;
}
}
if (!accumY)
{
accumY=(unsigned char*)aligned_malloc(dx1[0]*dy1[0]*KERNEL);
memset(accumY,0,dx1[0]*dy1[0]*KERNEL);
}
smooth(srcY,stride1[0],dstY,stride2[0],accumY,dx1[0],dy1[0]);
if (cfg->tempSmoothColor)
{
if (!accumU)
{
accumU=(unsigned char*)aligned_malloc(dx1[1]*dy1[1]*KERNEL);
memset(accumU,128,dx1[1]*dy1[1]*KERNEL);
}
smooth(srcU,stride1[1],dstU,stride2[1],accumU,dx1[1],dy1[1]);
if (!accumV)
{
accumV=(unsigned char*)aligned_malloc(dx1[2]*dy1[2]*KERNEL);
memset(accumV,128,dx1[2]*dy1[2]*KERNEL);
}
smooth(srcV,stride1[2],dstV,stride2[1],accumV,dx1[2],dy1[2]);
}
else
{
if (!tempU[0])
{
tempU[0]=(unsigned char*)aligned_malloc(dx1[1]*dy1[1]);
tempU[1]=(unsigned char*)aligned_malloc(dx1[1]*dy1[1]);
tempU[2]=(unsigned char*)aligned_malloc(dx1[1]*dy1[1]);
tempV[0]=(unsigned char*)aligned_malloc(dx1[2]*dy1[2]);
tempV[1]=(unsigned char*)aligned_malloc(dx1[2]*dy1[2]);
tempV[2]=(unsigned char*)aligned_malloc(dx1[2]*dy1[2]);
}
TffPict::copy(tempU[uint32_t(UVcount)%3],dx1[1],srcU,stride1[1],dx1[1],dy1[1]);//dst=tempU[UVcount%3];for (y=0;y<dyUV;y++) memcpy(dst+dxUV*y,srcU+stride1[1]*y,dxUV);
TffPict::copy(tempV[uint32_t(UVcount)%3],dx1[2],srcV,stride1[2],dx1[2],dy1[2]);//dst=tempV[UVcount%3];for (y=0;y<dyUV;y++) memcpy(dst+dxUV*y,srcV+stride1[2]*y,dxUV);
if (UVcount>=0)
{
TffPict::copy(dstU,stride2[1],tempU[uint32_t(UVcount-2)%3],dx1[1],dx1[1],dy1[1]);
TffPict::copy(dstV,stride2[2],tempV[uint32_t(UVcount-2)%3],dx1[1],dx1[2],dy1[2]);
}
else
{
TffPict::copy(dstU,stride2[1],srcU,stride1[1],dx1[1],dy1[1]);
TffPict::copy(dstU,stride2[2],srcU,stride1[2],dx1[2],dy1[2]);
}
UVcount++;
}
isFirstFrame=false;
if (++framecount>=KERNEL) framecount=0;
}
return parent->deliverSample(++it,pict);
}
void TimgFilterTimesmooth::smooth(const unsigned char *src,stride_t srcStride,unsigned char *dst,stride_t dstStride,unsigned char *Iaccum,unsigned int dx,unsigned int dy)
{
int offset1=framecount;
int offset2=((framecount+KERNEL-(KERNEL/2))%KERNEL);
if (isFirstFrame)
{
unsigned char *accum=Iaccum;
/*
int w=dx,x;
int y=dy;
const unsigned char *srcdst=src;
do
{
x=w;
do
{
accum[0]=accum[1]=accum[2]=accum[3]=accum[4]=accum[5]=accum[6]=*srcdst++;
} while(--x);
srcdst+=stride-dx;
} while(--y);
*/
//accum[0]=accum[1]=accum[2]=accum[3]=accum[4]=accum[5]=accum[6]=src[stride*(dy-1)+(dx-1)];
int w=dx,x;
int y=dy;
do
{
x=w;
do
{
accum[0] = accum[1] = accum[2] = accum[3] = *src++;
accum += KERNEL;
} while(--x);
src+=srcStride-dx;
} while(--y);
return;
}
unsigned int w=dx,x;
unsigned int y=dy;
unsigned char *accum=Iaccum;
do
{
x=w;
do
{
const unsigned char center=accum[offset2];
const int *crtab=square_table+255-center;
accum[offset1]=*src;src++;
int raccum=0;
int count=0;
for(int i=0;i<KERNEL;i++)
{
const int c=*accum++;
const int sqerr=crtab[c];
raccum+=sqerr*c;
count+=sqerr;
}
int divisor=((long*)scaletab)[2*count+1];
raccum=(raccum*divisor)>>16;
*dst=(unsigned char)raccum;dst++;
} while(--x);
src+=srcStride-dx;dst+=dstStride-dx;
} while(--y);
}
void TimgFilterTimesmooth::onSeek(void)
{
done();
UVcount=-3;
}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?