timgfilterbitmap.cpp
来自「从FFMPEG转换而来的H264解码程序,VC下编译..」· C++ 代码 · 共 280 行
CPP
280 行
/*
* Copyright (c) 2004-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 "TimgFilterBitmap.h"
#include "TbitmapSettings.h"
#include "simd.h"
#include "Tconfig.h"
template<class _mm> void TimgFilterBitmap::blend(const TcspInfo &cspInfo,const unsigned int dx[3],const unsigned int dy[3],unsigned char *dst[3],const stride_t dststride[3],const unsigned char *src[3],const stride_t srcstride[3],int strength,int invstrength)
{
typename _mm::__m strength64=_mm::set1_pi16(short(strength/2)),invstrength64=_mm::set1_pi16(short(invstrength/2)),m0=_mm::setzero_si64(),m128=_mm::set1_pi16(64);
for (unsigned int i=0;i<cspInfo.numPlanes;i++)
for (unsigned int y=0;y<dy[i];y++,dst[i]+=dststride[i],src[i]+=srcstride[i])
{
int x=0,cnt=dx[i];
const int cnt3=cnt-_mm::size/2+1;
for (;x<cnt3;x+=_mm::size/2)
{
typename _mm::__m dst8=_mm::unpacklo_pi8(_mm::load2(dst[i]+x),m0);
typename _mm::__m src8=_mm::unpacklo_pi8(_mm::load2(src[i]+x),m0);
dst8=_mm::mullo_pi16(dst8,invstrength64);
src8=_mm::mullo_pi16(src8,strength64);
dst8=_mm::add_pi16(dst8,src8);
dst8=_mm::add_pi16(dst8,m128);
dst8=_mm::srai_pi16(dst8,7);
_mm::store2(dst[i]+x,_mm::packs_pu16(dst8,m0));
}
for (;x<cnt;x++)
dst[i][x]=uint8_t((invstrength*dst[i][x]+strength*src[i][x]+128)/256);
}
_mm::empty();
}
template<class _mm> void TimgFilterBitmap::darken(const TcspInfo &cspInfo,const unsigned int dx[3],const unsigned int dy[3],unsigned char *dst[3],const stride_t dststride[3],const unsigned char *src[3],const stride_t srcstride[3],int strength,int invstrength)
{
typename _mm::__m strength64=_mm::set1_pi16(short(strength/2)),invstrength64=_mm::set1_pi16(short(invstrength/2)),m0=_mm::setzero_si64(),m128=_mm::set1_pi16(64);
if (cspInfo.numPlanes==3)
for (unsigned int i=1;i<3;i++)
for (unsigned int y=0;y<dy[i];y++,dst[i]+=dststride[i],src[i]+=srcstride[i])
for (unsigned int x=0;x<dx[i];x++)
if (src[0][(x<<cspInfo.shiftX[i])+(y<<cspInfo.shiftY[i])*srcstride[0]]<dst[0][(x<<cspInfo.shiftX[i])+(y<<cspInfo.shiftY[i])*dststride[0]])
dst[i][x]=uint8_t((invstrength*dst[i][x]+strength*src[i][x]+128)/256);
for (unsigned int y=0;y<dy[0];y++,dst[0]+=dststride[0],src[0]+=srcstride[0])
{
int x=0,cnt=dx[0];
const int cnt3=cnt-_mm::size/2+1;
for (;x<cnt3;x+=_mm::size/2)
{
typename _mm::__m dst8=_mm::unpacklo_pi8(_mm::load2(dst[0]+x),m0);
typename _mm::__m src8=_mm::unpacklo_pi8(_mm::load2(src[0]+x),m0);
typename _mm::__m mask=_mm::cmpgt_pi16(dst8,src8);
_mm::store2(dst[0]+x,_mm::packs_pu16(_mm::or_si64(_mm::and_si64(mask,_mm::srai_pi16(_mm::add_pi16(_mm::add_pi16(_mm::mullo_pi16(invstrength64,dst8),_mm::mullo_pi16(strength64,src8)),m128),7)),_mm::andnot_si64(mask,dst8)),m0));
}
for (;x<cnt;x++)
if (src[0][x]<dst[0][x])
dst[0][x]=uint8_t((invstrength*dst[0][x]+strength*src[0][x]+128)/256);
}
_mm::empty();
}
template<class _mm> void TimgFilterBitmap::lighten(const TcspInfo &cspInfo,const unsigned int dx[3],const unsigned int dy[3],unsigned char *dst[3],const stride_t dststride[3],const unsigned char *src[3],const stride_t srcstride[3],int strength,int invstrength)
{
typename _mm::__m strength64=_mm::set1_pi16(short(strength/2)),invstrength64=_mm::set1_pi16(short(invstrength/2)),m0=_mm::setzero_si64(),m128=_mm::set1_pi16(64);
if (cspInfo.numPlanes==3)
for (unsigned int i=1;i<3;i++)
for (unsigned int y=0;y<dy[i];y++,dst[i]+=dststride[i],src[i]+=srcstride[i])
for (unsigned int x=0;x<dx[i];x++)
if (src[0][(x<<cspInfo.shiftX[i])+(y<<cspInfo.shiftY[i])*srcstride[0]]>dst[0][(x<<cspInfo.shiftX[i])+(y<<cspInfo.shiftY[i])*dststride[0]])
dst[i][x]=uint8_t((invstrength*dst[i][x]+strength*src[i][x]+128)/256);
for (unsigned int y=0;y<dy[0];y++,dst[0]+=dststride[0],src[0]+=srcstride[0])
{
int x=0,cnt=dx[0];
const int cnt3=cnt-_mm::size/2+1;
for (;x<cnt3;x+=_mm::size/2)
{
typename _mm::__m dst8=_mm::unpacklo_pi8(_mm::load2(dst[0]+x),m0);
typename _mm::__m src8=_mm::unpacklo_pi8(_mm::load2(src[0]+x),m0);
typename _mm::__m mask=_mm::cmpgt_pi16(src8,dst8);
_mm::store2(dst[0]+x,_mm::packs_pu16(_mm::or_si64(_mm::and_si64(mask,_mm::srai_pi16(_mm::add_pi16(_mm::add_pi16(_mm::mullo_pi16(invstrength64,dst8),_mm::mullo_pi16(strength64,src8)),m128),7)),_mm::andnot_si64(mask,dst8)),m0));
}
for (;x<cnt;x++)
if (src[0][x]>dst[0][x])
dst[0][x]=uint8_t((invstrength*dst[0][x]+strength*src[0][x]+128)/256);
}
_mm::empty();
}
template<class _mm> void TimgFilterBitmap::add(const TcspInfo &cspInfo,const unsigned int dx[3],const unsigned int dy[3],unsigned char *dst[3],const stride_t dststride[3],const unsigned char *src[3],const stride_t srcstride[3],int strength,int invstrength)
{
typename _mm::__m strength64=_mm::set1_pi16(short(strength/2)),invstrength64=_mm::set1_pi16(short(127*invstrength/2)),m0=_mm::setzero_si64(),m127=_mm::set1_pi16(127);
if (cspInfo.numPlanes==3)
for (unsigned int i=1;i<3;i++)
for (unsigned int y=0;y<dy[i];y++,dst[i]+=dststride[i],src[i]+=srcstride[i])
{
int x=0,cnt=dx[i];
const int cnt3=cnt-_mm::size/2+1;
for (;x<cnt3;x+=_mm::size/2)
{
typename _mm::__m dst8=_mm::unpacklo_pi8(_mm::load2(dst[i]+x),m0);
typename _mm::__m src8=_mm::unpacklo_pi8(_mm::load2(src[i]+x),m0);
src8=_mm::mullo_pi16(strength64,src8);
src8=_mm::add_pi16(invstrength64,src8);
src8=_mm::srai_pi16(src8,7);
dst8=_mm::add_pi16(dst8,src8);
dst8=_mm::sub_pi16(dst8,m127);
_mm::store2(dst[i]+x,_mm::packs_pu16(dst8,m0));
}
for (;x<cnt;x++)
dst[i][x]=uint8_t(dst[i][x]+(((127*invstrength)+(strength*src[i][x]))>>8)-127);
}
for (unsigned int y=0;y<dy[0];y++,dst[0]+=dststride[0],src[0]+=srcstride[0])
{
int x=0,cnt=dx[0];
const int cnt3=cnt-_mm::size/2+1;
for (;x<cnt3;x+=_mm::size/2)
{
typename _mm::__m dst8=_mm::unpacklo_pi8(_mm::load2(dst[0]+x),m0);
typename _mm::__m src8=_mm::unpacklo_pi8(_mm::load2(src[0]+x),m0);
typename _mm::__m Y=_mm::add_pi16(dst8,_mm::srai_pi16(_mm::mullo_pi16(strength64,src8),7));
_mm::store2(dst[0]+x,_mm::packs_pu16(Y,m0));
}
for (;x<cnt;x++)
{
int Y=dst[0][x]+((strength*src[0][x])>>8);
if (Y>255) Y=255;
dst[0][x]=uint8_t(Y);
}
}
_mm::empty();
}
template<class _mm> void TimgFilterBitmap::softlight(const TcspInfo &cspInfo,const unsigned int dx[3],const unsigned int dy[3],unsigned char *dst[3],const stride_t dststride[3],const unsigned char *src[3],const stride_t srcstride[3],int strength,int invstrength)
{
typename _mm::__m strength64=_mm::set1_pi16((short)strength/2),invstrength64=_mm::set1_pi16((short)invstrength/2),m0=_mm::setzero_si64(),m128=_mm::set1_pi16(128);
for (unsigned int i=0;i<3;i++)
for (unsigned int y=0;y<dy[i];y++,dst[i]+=dststride[i],src[i]+=srcstride[i])
{
int x=0,cnt=dx[i];
const int cnt3=cnt-_mm::size/2+1;
for (;x<cnt3;x+=_mm::size/2)
{
typename _mm::__m dst8=_mm::unpacklo_pi8(_mm::load2(dst[0]+x),m0);
typename _mm::__m src8=_mm::unpacklo_pi8(_mm::load2(src[0]+x),m0);
typename _mm::__m Y=_mm::unpacklo_pi8(_mm::packs_pu16(_mm::sub_pi16(_mm::add_pi16(src8,dst8),m128),m0),m0);
dst8=_mm::add_pi16(_mm::mullo_pi16(Y,strength64), _mm::mullo_pi16(dst8,invstrength64));
dst8=_mm::srai_pi16(dst8,7);
_mm::store2(dst[0]+x,_mm::packs_pu16(dst8,m0));
}
for (;x<cnt;x++)
{
int Y=limit_uint8(dst[i][x]+src[i][x]-127);
dst[i][x]=limit_uint8((Y*strength+invstrength*dst[i][x])>>8);
}
}
_mm::empty();
}
template<class _mm> void TimgFilterBitmap::exclusion(const TcspInfo &cspInfo,const unsigned int dx[3],const unsigned int dy[3],unsigned char *dst[3],const stride_t dststride[3],const unsigned char *src[3],const stride_t srcstride[3],int strength,int invstrength)
{
typename _mm::__m strength64=_mm::set1_pi16(short(strength/2)),invstrength64=_mm::set1_pi16(short(invstrength/2)),m0=_mm::setzero_si64(),m255=_mm::set1_pi16(255);
for (unsigned int i=0;i<3;i++)
for (unsigned int y=0;y<dy[i];y++,dst[i]+=dststride[i],src[i]+=srcstride[i])
{
int x=0,cnt=dx[i];
const int cnt3=cnt-_mm::size/2+1;
for (;x<cnt3;x+=_mm::size/2)
{
typename _mm::__m dst8=_mm::unpacklo_pi8(_mm::load2(dst[i]+x),m0);
typename _mm::__m src8=_mm::unpacklo_pi8(_mm::load2(src[i]+x),m0);
typename _mm::__m Y=_mm::add_pi16(_mm::srli_pi16(_mm::mullo_pi16(_mm::xor_si64(dst8,m255),src8),1) , _mm::srli_pi16(_mm::mullo_pi16(_mm::xor_si64(src8,m255),dst8),1));
Y=_mm::srai_pi16(Y,7);
Y=_mm::srai_pi16(_mm::add_pi16(_mm::mullo_pi16(Y,strength64),_mm::mullo_pi16(invstrength64,dst8)),7);
_mm::store2(dst[i]+x,_mm::packs_pu16(Y,m0));
}
for (;x<cnt;x++)
{
int Y=((int)(dst[i][x]^0xff)*src[i][x] + (int)(src[i][x]^0xff)*dst[i][x])>>8;
Y=((Y*strength) + (invstrength*dst[i][x]))>>8;
dst[i][x]=limit_uint8(Y);
}
}
_mm::empty();
}
template<class _mm> TimgFilterBitmap::Tblendplane TimgFilterBitmap::getBlend(int mode)
{
switch (mode)
{
case TbitmapSettings::MODE_BLEND:
default:return blend<_mm>;
case TbitmapSettings::MODE_DARKEN:return darken<_mm>;
case TbitmapSettings::MODE_LIGHTEN:return lighten<_mm>;
case TbitmapSettings::MODE_ADD:return add<_mm>;
case TbitmapSettings::MODE_SOFTLIGHT:return softlight<_mm>;
case TbitmapSettings::MODE_EXCLUSION:return exclusion<_mm>;
}
}
void TimgFilterBitmap::TrenderedSubtitleLineBitmap::print(unsigned int dx[3],unsigned char *dstLn[3],const stride_t stride[3],const unsigned char *bmp[3],const unsigned char *msk[3]) const
{
blend(pict->cspInfo,dx,dy,dstLn,stride,bmp,bmpmskstride,cfg->strength,255-cfg->strength);
}
TimgFilterBitmap::TimgFilterBitmap(IffdshowBase *Ideci,Tfilters *Iparent):TimgFilter(Ideci,Iparent),l(&w),ls(&l)
{
bitmap=NULL;
oldflnm[0]='\0';
oldmode=-1;
}
TimgFilterBitmap::~TimgFilterBitmap()
{
if (bitmap) delete bitmap;
}
bool TimgFilterBitmap::is(const TffPictBase &pict,const TfilterSettingsVideo *cfg0)
{
const TbitmapSettings *cfg=(const TbitmapSettings*)cfg0;
return super::is(pict,cfg) && cfg->strength && cfg->flnm[0];
}
HRESULT TimgFilterBitmap::process(TfilterQueue::iterator it,TffPict &pict,const TfilterSettingsVideo *cfg0)
{
if (is(pict,cfg0))
{
const TbitmapSettings *cfg=(const TbitmapSettings*)cfg0;
init(pict,cfg->full,cfg->half);
unsigned char *dst[4];
bool cspChanged=getCurNext(FF_CSPS_MASK_YUV_PLANAR,pict,cfg->full,COPYMODE_DEF,dst);
if (!bitmap || cspChanged || stricmp(oldflnm,cfg->flnm)!=0)
{
strcpy(oldflnm,cfg->flnm);
if (bitmap) delete bitmap;
bitmap=new TffPict(csp2,cfg->flnm,bitmapbuf,deci);
for (int i=0;i<3;i++)
{
w.dx[i]=bitmap->rectFull.dx>>bitmap->cspInfo.shiftX[i];
w.dy[i]=bitmap->rectFull.dy>>bitmap->cspInfo.shiftY[i];
w.bmp[i]=bitmap->data[i];
w.bmpmskstride[i]=bitmap->stride[i];
}
w.dxCharY=w.dx[0];w.dyCharY=w.dy[0];
}
if (bitmap->rectFull.dx!=0)
{
if (oldmode!=cfg->mode)
#ifdef __SSE2__
if (Tconfig::cpu_flags&FF_CPU_SSE2)
w.blend=getBlend<Tsse2>(oldmode=cfg->mode);
else
#endif
w.blend=getBlend<Tmmx>(oldmode=cfg->mode);
TrenderedSubtitleLines::TprintPrefs prefs(deci);
prefs.dst=dst;
prefs.stride=stride2;
prefs.shiftX=pict.cspInfo.shiftX;prefs.shiftY=pict.cspInfo.shiftY;
prefs.dx=dx2[0];prefs.dy=dy2[0];
prefs.xpos=cfg->posx;prefs.ypos=cfg->posy;if (cfg->posmode==1) {prefs.xpos*=-1;prefs.ypos*=-1;}
prefs.align=cfg->align;
prefs.linespacing=100;
w.pict=&pict;
w.cfg=cfg;
ls.print(prefs);
}
}
return parent->deliverSample(++it,pict);
}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?